1 //===--- SemaOpenMP.cpp - Semantic Analysis for OpenMP 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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// \file 9 /// This file implements semantic analysis for OpenMP directives and 10 /// clauses. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/Sema/SemaOpenMP.h" 15 16 #include "TreeTransform.h" 17 #include "clang/AST/ASTContext.h" 18 #include "clang/AST/ASTMutationListener.h" 19 #include "clang/AST/CXXInheritance.h" 20 #include "clang/AST/Decl.h" 21 #include "clang/AST/DeclCXX.h" 22 #include "clang/AST/DeclOpenMP.h" 23 #include "clang/AST/DynamicRecursiveASTVisitor.h" 24 #include "clang/AST/OpenMPClause.h" 25 #include "clang/AST/StmtCXX.h" 26 #include "clang/AST/StmtOpenMP.h" 27 #include "clang/AST/StmtVisitor.h" 28 #include "clang/Basic/DiagnosticSema.h" 29 #include "clang/Basic/OpenMPKinds.h" 30 #include "clang/Basic/PartialDiagnostic.h" 31 #include "clang/Basic/TargetInfo.h" 32 #include "clang/Sema/EnterExpressionEvaluationContext.h" 33 #include "clang/Sema/Initialization.h" 34 #include "clang/Sema/Lookup.h" 35 #include "clang/Sema/ParsedAttr.h" 36 #include "clang/Sema/Scope.h" 37 #include "clang/Sema/ScopeInfo.h" 38 #include "clang/Sema/Sema.h" 39 #include "llvm/ADT/IndexedMap.h" 40 #include "llvm/ADT/PointerEmbeddedInt.h" 41 #include "llvm/ADT/STLExtras.h" 42 #include "llvm/ADT/Sequence.h" 43 #include "llvm/ADT/SetVector.h" 44 #include "llvm/ADT/SmallSet.h" 45 #include "llvm/ADT/StringExtras.h" 46 #include "llvm/Frontend/OpenMP/OMPAssume.h" 47 #include "llvm/Frontend/OpenMP/OMPConstants.h" 48 #include "llvm/IR/Assumptions.h" 49 #include <optional> 50 51 using namespace clang; 52 using namespace llvm::omp; 53 54 //===----------------------------------------------------------------------===// 55 // Stack of data-sharing attributes for variables 56 //===----------------------------------------------------------------------===// 57 58 static const Expr *checkMapClauseExpressionBase( 59 Sema &SemaRef, Expr *E, 60 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents, 61 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose); 62 63 namespace { 64 /// Default data sharing attributes, which can be applied to directive. 65 enum DefaultDataSharingAttributes { 66 DSA_unspecified = 0, /// Data sharing attribute not specified. 67 DSA_none = 1 << 0, /// Default data sharing attribute 'none'. 68 DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'. 69 DSA_private = 1 << 2, /// Default data sharing attribute 'private'. 70 DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'. 71 }; 72 73 /// Stack for tracking declarations used in OpenMP directives and 74 /// clauses and their data-sharing attributes. 75 class DSAStackTy { 76 public: 77 struct DSAVarData { 78 OpenMPDirectiveKind DKind = OMPD_unknown; 79 OpenMPClauseKind CKind = OMPC_unknown; 80 unsigned Modifier = 0; 81 const Expr *RefExpr = nullptr; 82 DeclRefExpr *PrivateCopy = nullptr; 83 SourceLocation ImplicitDSALoc; 84 bool AppliedToPointee = false; 85 DSAVarData() = default; 86 DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, 87 const Expr *RefExpr, DeclRefExpr *PrivateCopy, 88 SourceLocation ImplicitDSALoc, unsigned Modifier, 89 bool AppliedToPointee) 90 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr), 91 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc), 92 AppliedToPointee(AppliedToPointee) {} 93 }; 94 using OperatorOffsetTy = 95 llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>; 96 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>; 97 /// Kind of the declaration used in the uses_allocators clauses. 98 enum class UsesAllocatorsDeclKind { 99 /// Predefined allocator 100 PredefinedAllocator, 101 /// User-defined allocator 102 UserDefinedAllocator, 103 /// The declaration that represent allocator trait 104 AllocatorTrait, 105 }; 106 107 private: 108 struct DSAInfo { 109 OpenMPClauseKind Attributes = OMPC_unknown; 110 unsigned Modifier = 0; 111 /// Pointer to a reference expression and a flag which shows that the 112 /// variable is marked as lastprivate(true) or not (false). 113 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr; 114 DeclRefExpr *PrivateCopy = nullptr; 115 /// true if the attribute is applied to the pointee, not the variable 116 /// itself. 117 bool AppliedToPointee = false; 118 }; 119 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>; 120 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>; 121 using LCDeclInfo = std::pair<unsigned, VarDecl *>; 122 using LoopControlVariablesMapTy = 123 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>; 124 /// Struct that associates a component with the clause kind where they are 125 /// found. 126 struct MappedExprComponentTy { 127 OMPClauseMappableExprCommon::MappableExprComponentLists Components; 128 OpenMPClauseKind Kind = OMPC_unknown; 129 }; 130 using MappedExprComponentsTy = 131 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>; 132 using CriticalsWithHintsTy = 133 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>; 134 struct ReductionData { 135 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>; 136 SourceRange ReductionRange; 137 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp; 138 ReductionData() = default; 139 void set(BinaryOperatorKind BO, SourceRange RR) { 140 ReductionRange = RR; 141 ReductionOp = BO; 142 } 143 void set(const Expr *RefExpr, SourceRange RR) { 144 ReductionRange = RR; 145 ReductionOp = RefExpr; 146 } 147 }; 148 using DeclReductionMapTy = 149 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>; 150 struct DefaultmapInfo { 151 OpenMPDefaultmapClauseModifier ImplicitBehavior = 152 OMPC_DEFAULTMAP_MODIFIER_unknown; 153 SourceLocation SLoc; 154 DefaultmapInfo() = default; 155 DefaultmapInfo(OpenMPDefaultmapClauseModifier M, SourceLocation Loc) 156 : ImplicitBehavior(M), SLoc(Loc) {} 157 }; 158 159 struct SharingMapTy { 160 DeclSAMapTy SharingMap; 161 DeclReductionMapTy ReductionMap; 162 UsedRefMapTy AlignedMap; 163 UsedRefMapTy NontemporalMap; 164 MappedExprComponentsTy MappedExprComponents; 165 LoopControlVariablesMapTy LCVMap; 166 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified; 167 SourceLocation DefaultAttrLoc; 168 DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown + 1]; 169 OpenMPDirectiveKind Directive = OMPD_unknown; 170 DeclarationNameInfo DirectiveName; 171 Scope *CurScope = nullptr; 172 DeclContext *Context = nullptr; 173 SourceLocation ConstructLoc; 174 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to 175 /// get the data (loop counters etc.) about enclosing loop-based construct. 176 /// This data is required during codegen. 177 DoacrossClauseMapTy DoacrossDepends; 178 /// First argument (Expr *) contains optional argument of the 179 /// 'ordered' clause, the second one is true if the regions has 'ordered' 180 /// clause, false otherwise. 181 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion; 182 bool RegionHasOrderConcurrent = false; 183 unsigned AssociatedLoops = 1; 184 bool HasMutipleLoops = false; 185 const Decl *PossiblyLoopCounter = nullptr; 186 bool NowaitRegion = false; 187 bool UntiedRegion = false; 188 bool CancelRegion = false; 189 bool LoopStart = false; 190 bool BodyComplete = false; 191 SourceLocation PrevScanLocation; 192 SourceLocation PrevOrderedLocation; 193 SourceLocation InnerTeamsRegionLoc; 194 /// Reference to the taskgroup task_reduction reference expression. 195 Expr *TaskgroupReductionRef = nullptr; 196 llvm::DenseSet<QualType> MappedClassesQualTypes; 197 SmallVector<Expr *, 4> InnerUsedAllocators; 198 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates; 199 /// List of globals marked as declare target link in this target region 200 /// (isOpenMPTargetExecutionDirective(Directive) == true). 201 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls; 202 /// List of decls used in inclusive/exclusive clauses of the scan directive. 203 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective; 204 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind> 205 UsesAllocatorsDecls; 206 /// Data is required on creating capture fields for implicit 207 /// default first|private clause. 208 struct ImplicitDefaultFDInfoTy { 209 /// Field decl. 210 const FieldDecl *FD = nullptr; 211 /// Nesting stack level 212 size_t StackLevel = 0; 213 /// Capture variable decl. 214 VarDecl *VD = nullptr; 215 ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel, 216 VarDecl *VD) 217 : FD(FD), StackLevel(StackLevel), VD(VD) {} 218 }; 219 /// List of captured fields 220 llvm::SmallVector<ImplicitDefaultFDInfoTy, 8> 221 ImplicitDefaultFirstprivateFDs; 222 Expr *DeclareMapperVar = nullptr; 223 SmallVector<VarDecl *, 16> IteratorVarDecls; 224 SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name, 225 Scope *CurScope, SourceLocation Loc) 226 : Directive(DKind), DirectiveName(Name), CurScope(CurScope), 227 ConstructLoc(Loc) {} 228 SharingMapTy() = default; 229 }; 230 231 using StackTy = SmallVector<SharingMapTy, 4>; 232 233 /// Stack of used declaration and their data-sharing attributes. 234 DeclSAMapTy Threadprivates; 235 const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr; 236 SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack; 237 /// true, if check for DSA must be from parent directive, false, if 238 /// from current directive. 239 OpenMPClauseKind ClauseKindMode = OMPC_unknown; 240 Sema &SemaRef; 241 bool ForceCapturing = false; 242 /// true if all the variables in the target executable directives must be 243 /// captured by reference. 244 bool ForceCaptureByReferenceInTargetExecutable = false; 245 CriticalsWithHintsTy Criticals; 246 unsigned IgnoredStackElements = 0; 247 248 /// Iterators over the stack iterate in order from innermost to outermost 249 /// directive. 250 using const_iterator = StackTy::const_reverse_iterator; 251 const_iterator begin() const { 252 return Stack.empty() ? const_iterator() 253 : Stack.back().first.rbegin() + IgnoredStackElements; 254 } 255 const_iterator end() const { 256 return Stack.empty() ? const_iterator() : Stack.back().first.rend(); 257 } 258 using iterator = StackTy::reverse_iterator; 259 iterator begin() { 260 return Stack.empty() ? iterator() 261 : Stack.back().first.rbegin() + IgnoredStackElements; 262 } 263 iterator end() { 264 return Stack.empty() ? iterator() : Stack.back().first.rend(); 265 } 266 267 // Convenience operations to get at the elements of the stack. 268 269 bool isStackEmpty() const { 270 return Stack.empty() || 271 Stack.back().second != CurrentNonCapturingFunctionScope || 272 Stack.back().first.size() <= IgnoredStackElements; 273 } 274 size_t getStackSize() const { 275 return isStackEmpty() ? 0 276 : Stack.back().first.size() - IgnoredStackElements; 277 } 278 279 SharingMapTy *getTopOfStackOrNull() { 280 size_t Size = getStackSize(); 281 if (Size == 0) 282 return nullptr; 283 return &Stack.back().first[Size - 1]; 284 } 285 const SharingMapTy *getTopOfStackOrNull() const { 286 return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull(); 287 } 288 SharingMapTy &getTopOfStack() { 289 assert(!isStackEmpty() && "no current directive"); 290 return *getTopOfStackOrNull(); 291 } 292 const SharingMapTy &getTopOfStack() const { 293 return const_cast<DSAStackTy &>(*this).getTopOfStack(); 294 } 295 296 SharingMapTy *getSecondOnStackOrNull() { 297 size_t Size = getStackSize(); 298 if (Size <= 1) 299 return nullptr; 300 return &Stack.back().first[Size - 2]; 301 } 302 const SharingMapTy *getSecondOnStackOrNull() const { 303 return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull(); 304 } 305 306 /// Get the stack element at a certain level (previously returned by 307 /// \c getNestingLevel). 308 /// 309 /// Note that nesting levels count from outermost to innermost, and this is 310 /// the reverse of our iteration order where new inner levels are pushed at 311 /// the front of the stack. 312 SharingMapTy &getStackElemAtLevel(unsigned Level) { 313 assert(Level < getStackSize() && "no such stack element"); 314 return Stack.back().first[Level]; 315 } 316 const SharingMapTy &getStackElemAtLevel(unsigned Level) const { 317 return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level); 318 } 319 320 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const; 321 322 /// Checks if the variable is a local for OpenMP region. 323 bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const; 324 325 /// Vector of previously declared requires directives 326 SmallVector<const OMPRequiresDecl *, 2> RequiresDecls; 327 /// omp_allocator_handle_t type. 328 QualType OMPAllocatorHandleT; 329 /// omp_depend_t type. 330 QualType OMPDependT; 331 /// omp_event_handle_t type. 332 QualType OMPEventHandleT; 333 /// omp_alloctrait_t type. 334 QualType OMPAlloctraitT; 335 /// Expression for the predefined allocators. 336 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = { 337 nullptr}; 338 /// Vector of previously encountered target directives 339 SmallVector<SourceLocation, 2> TargetLocations; 340 SourceLocation AtomicLocation; 341 /// Vector of declare variant construct traits. 342 SmallVector<llvm::omp::TraitProperty, 8> ConstructTraits; 343 344 public: 345 explicit DSAStackTy(Sema &S) : SemaRef(S) {} 346 347 /// Sets omp_allocator_handle_t type. 348 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; } 349 /// Gets omp_allocator_handle_t type. 350 QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; } 351 /// Sets omp_alloctrait_t type. 352 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; } 353 /// Gets omp_alloctrait_t type. 354 QualType getOMPAlloctraitT() const { return OMPAlloctraitT; } 355 /// Sets the given default allocator. 356 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, 357 Expr *Allocator) { 358 OMPPredefinedAllocators[AllocatorKind] = Allocator; 359 } 360 /// Returns the specified default allocator. 361 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const { 362 return OMPPredefinedAllocators[AllocatorKind]; 363 } 364 /// Sets omp_depend_t type. 365 void setOMPDependT(QualType Ty) { OMPDependT = Ty; } 366 /// Gets omp_depend_t type. 367 QualType getOMPDependT() const { return OMPDependT; } 368 369 /// Sets omp_event_handle_t type. 370 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; } 371 /// Gets omp_event_handle_t type. 372 QualType getOMPEventHandleT() const { return OMPEventHandleT; } 373 374 bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; } 375 OpenMPClauseKind getClauseParsingMode() const { 376 assert(isClauseParsingMode() && "Must be in clause parsing mode."); 377 return ClauseKindMode; 378 } 379 void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; } 380 381 bool isBodyComplete() const { 382 const SharingMapTy *Top = getTopOfStackOrNull(); 383 return Top && Top->BodyComplete; 384 } 385 void setBodyComplete() { getTopOfStack().BodyComplete = true; } 386 387 bool isForceVarCapturing() const { return ForceCapturing; } 388 void setForceVarCapturing(bool V) { ForceCapturing = V; } 389 390 void setForceCaptureByReferenceInTargetExecutable(bool V) { 391 ForceCaptureByReferenceInTargetExecutable = V; 392 } 393 bool isForceCaptureByReferenceInTargetExecutable() const { 394 return ForceCaptureByReferenceInTargetExecutable; 395 } 396 397 void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName, 398 Scope *CurScope, SourceLocation Loc) { 399 assert(!IgnoredStackElements && 400 "cannot change stack while ignoring elements"); 401 if (Stack.empty() || 402 Stack.back().second != CurrentNonCapturingFunctionScope) 403 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope); 404 Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc); 405 Stack.back().first.back().DefaultAttrLoc = Loc; 406 } 407 408 void pop() { 409 assert(!IgnoredStackElements && 410 "cannot change stack while ignoring elements"); 411 assert(!Stack.back().first.empty() && 412 "Data-sharing attributes stack is empty!"); 413 Stack.back().first.pop_back(); 414 } 415 416 /// RAII object to temporarily leave the scope of a directive when we want to 417 /// logically operate in its parent. 418 class ParentDirectiveScope { 419 DSAStackTy &Self; 420 bool Active; 421 422 public: 423 ParentDirectiveScope(DSAStackTy &Self, bool Activate) 424 : Self(Self), Active(false) { 425 if (Activate) 426 enable(); 427 } 428 ~ParentDirectiveScope() { disable(); } 429 void disable() { 430 if (Active) { 431 --Self.IgnoredStackElements; 432 Active = false; 433 } 434 } 435 void enable() { 436 if (!Active) { 437 ++Self.IgnoredStackElements; 438 Active = true; 439 } 440 } 441 }; 442 443 /// Marks that we're started loop parsing. 444 void loopInit() { 445 assert(isOpenMPLoopDirective(getCurrentDirective()) && 446 "Expected loop-based directive."); 447 getTopOfStack().LoopStart = true; 448 } 449 /// Start capturing of the variables in the loop context. 450 void loopStart() { 451 assert(isOpenMPLoopDirective(getCurrentDirective()) && 452 "Expected loop-based directive."); 453 getTopOfStack().LoopStart = false; 454 } 455 /// true, if variables are captured, false otherwise. 456 bool isLoopStarted() const { 457 assert(isOpenMPLoopDirective(getCurrentDirective()) && 458 "Expected loop-based directive."); 459 return !getTopOfStack().LoopStart; 460 } 461 /// Marks (or clears) declaration as possibly loop counter. 462 void resetPossibleLoopCounter(const Decl *D = nullptr) { 463 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D; 464 } 465 /// Gets the possible loop counter decl. 466 const Decl *getPossiblyLoopCounter() const { 467 return getTopOfStack().PossiblyLoopCounter; 468 } 469 /// Start new OpenMP region stack in new non-capturing function. 470 void pushFunction() { 471 assert(!IgnoredStackElements && 472 "cannot change stack while ignoring elements"); 473 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction(); 474 assert(!isa<CapturingScopeInfo>(CurFnScope)); 475 CurrentNonCapturingFunctionScope = CurFnScope; 476 } 477 /// Pop region stack for non-capturing function. 478 void popFunction(const FunctionScopeInfo *OldFSI) { 479 assert(!IgnoredStackElements && 480 "cannot change stack while ignoring elements"); 481 if (!Stack.empty() && Stack.back().second == OldFSI) { 482 assert(Stack.back().first.empty()); 483 Stack.pop_back(); 484 } 485 CurrentNonCapturingFunctionScope = nullptr; 486 for (const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) { 487 if (!isa<CapturingScopeInfo>(FSI)) { 488 CurrentNonCapturingFunctionScope = FSI; 489 break; 490 } 491 } 492 } 493 494 void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) { 495 Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint); 496 } 497 const std::pair<const OMPCriticalDirective *, llvm::APSInt> 498 getCriticalWithHint(const DeclarationNameInfo &Name) const { 499 auto I = Criticals.find(Name.getAsString()); 500 if (I != Criticals.end()) 501 return I->second; 502 return std::make_pair(nullptr, llvm::APSInt()); 503 } 504 /// If 'aligned' declaration for given variable \a D was not seen yet, 505 /// add it and return NULL; otherwise return previous occurrence's expression 506 /// for diagnostics. 507 const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE); 508 /// If 'nontemporal' declaration for given variable \a D was not seen yet, 509 /// add it and return NULL; otherwise return previous occurrence's expression 510 /// for diagnostics. 511 const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE); 512 513 /// Register specified variable as loop control variable. 514 void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture); 515 /// Check if the specified variable is a loop control variable for 516 /// current region. 517 /// \return The index of the loop control variable in the list of associated 518 /// for-loops (from outer to inner). 519 const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const; 520 /// Check if the specified variable is a loop control variable for 521 /// parent region. 522 /// \return The index of the loop control variable in the list of associated 523 /// for-loops (from outer to inner). 524 const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const; 525 /// Check if the specified variable is a loop control variable for 526 /// current region. 527 /// \return The index of the loop control variable in the list of associated 528 /// for-loops (from outer to inner). 529 const LCDeclInfo isLoopControlVariable(const ValueDecl *D, 530 unsigned Level) const; 531 /// Get the loop control variable for the I-th loop (or nullptr) in 532 /// parent directive. 533 const ValueDecl *getParentLoopControlVariable(unsigned I) const; 534 535 /// Marks the specified decl \p D as used in scan directive. 536 void markDeclAsUsedInScanDirective(ValueDecl *D) { 537 if (SharingMapTy *Stack = getSecondOnStackOrNull()) 538 Stack->UsedInScanDirective.insert(D); 539 } 540 541 /// Checks if the specified declaration was used in the inner scan directive. 542 bool isUsedInScanDirective(ValueDecl *D) const { 543 if (const SharingMapTy *Stack = getTopOfStackOrNull()) 544 return Stack->UsedInScanDirective.contains(D); 545 return false; 546 } 547 548 /// Adds explicit data sharing attribute to the specified declaration. 549 void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A, 550 DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0, 551 bool AppliedToPointee = false); 552 553 /// Adds additional information for the reduction items with the reduction id 554 /// represented as an operator. 555 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR, 556 BinaryOperatorKind BOK); 557 /// Adds additional information for the reduction items with the reduction id 558 /// represented as reduction identifier. 559 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR, 560 const Expr *ReductionRef); 561 /// Returns the location and reduction operation from the innermost parent 562 /// region for the given \p D. 563 const DSAVarData 564 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR, 565 BinaryOperatorKind &BOK, 566 Expr *&TaskgroupDescriptor) const; 567 /// Returns the location and reduction operation from the innermost parent 568 /// region for the given \p D. 569 const DSAVarData 570 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR, 571 const Expr *&ReductionRef, 572 Expr *&TaskgroupDescriptor) const; 573 /// Return reduction reference expression for the current taskgroup or 574 /// parallel/worksharing directives with task reductions. 575 Expr *getTaskgroupReductionRef() const { 576 assert((getTopOfStack().Directive == OMPD_taskgroup || 577 ((isOpenMPParallelDirective(getTopOfStack().Directive) || 578 isOpenMPWorksharingDirective(getTopOfStack().Directive)) && 579 !isOpenMPSimdDirective(getTopOfStack().Directive))) && 580 "taskgroup reference expression requested for non taskgroup or " 581 "parallel/worksharing directive."); 582 return getTopOfStack().TaskgroupReductionRef; 583 } 584 /// Checks if the given \p VD declaration is actually a taskgroup reduction 585 /// descriptor variable at the \p Level of OpenMP regions. 586 bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const { 587 return getStackElemAtLevel(Level).TaskgroupReductionRef && 588 cast<DeclRefExpr>(getStackElemAtLevel(Level).TaskgroupReductionRef) 589 ->getDecl() == VD; 590 } 591 592 /// Returns data sharing attributes from top of the stack for the 593 /// specified declaration. 594 const DSAVarData getTopDSA(ValueDecl *D, bool FromParent); 595 /// Returns data-sharing attributes for the specified declaration. 596 const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const; 597 /// Returns data-sharing attributes for the specified declaration. 598 const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const; 599 /// Checks if the specified variables has data-sharing attributes which 600 /// match specified \a CPred predicate in any directive which matches \a DPred 601 /// predicate. 602 const DSAVarData 603 hasDSA(ValueDecl *D, 604 const llvm::function_ref<bool(OpenMPClauseKind, bool, 605 DefaultDataSharingAttributes)> 606 CPred, 607 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred, 608 bool FromParent) const; 609 /// Checks if the specified variables has data-sharing attributes which 610 /// match specified \a CPred predicate in any innermost directive which 611 /// matches \a DPred predicate. 612 const DSAVarData 613 hasInnermostDSA(ValueDecl *D, 614 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred, 615 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred, 616 bool FromParent) const; 617 /// Checks if the specified variables has explicit data-sharing 618 /// attributes which match specified \a CPred predicate at the specified 619 /// OpenMP region. 620 bool 621 hasExplicitDSA(const ValueDecl *D, 622 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred, 623 unsigned Level, bool NotLastprivate = false) const; 624 625 /// Returns true if the directive at level \Level matches in the 626 /// specified \a DPred predicate. 627 bool hasExplicitDirective( 628 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred, 629 unsigned Level) const; 630 631 /// Finds a directive which matches specified \a DPred predicate. 632 bool hasDirective( 633 const llvm::function_ref<bool( 634 OpenMPDirectiveKind, const DeclarationNameInfo &, SourceLocation)> 635 DPred, 636 bool FromParent) const; 637 638 /// Returns currently analyzed directive. 639 OpenMPDirectiveKind getCurrentDirective() const { 640 const SharingMapTy *Top = getTopOfStackOrNull(); 641 return Top ? Top->Directive : OMPD_unknown; 642 } 643 /// Returns directive kind at specified level. 644 OpenMPDirectiveKind getDirective(unsigned Level) const { 645 assert(!isStackEmpty() && "No directive at specified level."); 646 return getStackElemAtLevel(Level).Directive; 647 } 648 /// Returns the capture region at the specified level. 649 OpenMPDirectiveKind getCaptureRegion(unsigned Level, 650 unsigned OpenMPCaptureLevel) const { 651 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 652 getOpenMPCaptureRegions(CaptureRegions, getDirective(Level)); 653 return CaptureRegions[OpenMPCaptureLevel]; 654 } 655 /// Returns parent directive. 656 OpenMPDirectiveKind getParentDirective() const { 657 const SharingMapTy *Parent = getSecondOnStackOrNull(); 658 return Parent ? Parent->Directive : OMPD_unknown; 659 } 660 661 /// Add requires decl to internal vector 662 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); } 663 664 /// Checks if the defined 'requires' directive has specified type of clause. 665 template <typename ClauseType> bool hasRequiresDeclWithClause() const { 666 return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) { 667 return llvm::any_of(D->clauselists(), [](const OMPClause *C) { 668 return isa<ClauseType>(C); 669 }); 670 }); 671 } 672 673 /// Checks for a duplicate clause amongst previously declared requires 674 /// directives 675 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const { 676 bool IsDuplicate = false; 677 for (OMPClause *CNew : ClauseList) { 678 for (const OMPRequiresDecl *D : RequiresDecls) { 679 for (const OMPClause *CPrev : D->clauselists()) { 680 if (CNew->getClauseKind() == CPrev->getClauseKind()) { 681 SemaRef.Diag(CNew->getBeginLoc(), 682 diag::err_omp_requires_clause_redeclaration) 683 << getOpenMPClauseName(CNew->getClauseKind()); 684 SemaRef.Diag(CPrev->getBeginLoc(), 685 diag::note_omp_requires_previous_clause) 686 << getOpenMPClauseName(CPrev->getClauseKind()); 687 IsDuplicate = true; 688 } 689 } 690 } 691 } 692 return IsDuplicate; 693 } 694 695 /// Add location of previously encountered target to internal vector 696 void addTargetDirLocation(SourceLocation LocStart) { 697 TargetLocations.push_back(LocStart); 698 } 699 700 /// Add location for the first encountered atomic directive. 701 void addAtomicDirectiveLoc(SourceLocation Loc) { 702 if (AtomicLocation.isInvalid()) 703 AtomicLocation = Loc; 704 } 705 706 /// Returns the location of the first encountered atomic directive in the 707 /// module. 708 SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; } 709 710 // Return previously encountered target region locations. 711 ArrayRef<SourceLocation> getEncounteredTargetLocs() const { 712 return TargetLocations; 713 } 714 715 /// Set default data sharing attribute to none. 716 void setDefaultDSANone(SourceLocation Loc) { 717 getTopOfStack().DefaultAttr = DSA_none; 718 getTopOfStack().DefaultAttrLoc = Loc; 719 } 720 /// Set default data sharing attribute to shared. 721 void setDefaultDSAShared(SourceLocation Loc) { 722 getTopOfStack().DefaultAttr = DSA_shared; 723 getTopOfStack().DefaultAttrLoc = Loc; 724 } 725 /// Set default data sharing attribute to private. 726 void setDefaultDSAPrivate(SourceLocation Loc) { 727 getTopOfStack().DefaultAttr = DSA_private; 728 getTopOfStack().DefaultAttrLoc = Loc; 729 } 730 /// Set default data sharing attribute to firstprivate. 731 void setDefaultDSAFirstPrivate(SourceLocation Loc) { 732 getTopOfStack().DefaultAttr = DSA_firstprivate; 733 getTopOfStack().DefaultAttrLoc = Loc; 734 } 735 /// Set default data mapping attribute to Modifier:Kind 736 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M, 737 OpenMPDefaultmapClauseKind Kind, SourceLocation Loc) { 738 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind]; 739 DMI.ImplicitBehavior = M; 740 DMI.SLoc = Loc; 741 } 742 /// Check whether the implicit-behavior has been set in defaultmap 743 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) { 744 if (VariableCategory == OMPC_DEFAULTMAP_unknown) 745 return getTopOfStack() 746 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate] 747 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown || 748 getTopOfStack() 749 .DefaultmapMap[OMPC_DEFAULTMAP_scalar] 750 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown || 751 getTopOfStack() 752 .DefaultmapMap[OMPC_DEFAULTMAP_pointer] 753 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown; 754 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior != 755 OMPC_DEFAULTMAP_MODIFIER_unknown; 756 } 757 758 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() { 759 return ConstructTraits; 760 } 761 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits, 762 bool ScopeEntry) { 763 if (ScopeEntry) 764 ConstructTraits.append(Traits.begin(), Traits.end()); 765 else 766 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) { 767 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val(); 768 assert(Top == Trait && "Something left a trait on the stack!"); 769 (void)Trait; 770 (void)Top; 771 } 772 } 773 774 DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const { 775 return getStackSize() <= Level ? DSA_unspecified 776 : getStackElemAtLevel(Level).DefaultAttr; 777 } 778 DefaultDataSharingAttributes getDefaultDSA() const { 779 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr; 780 } 781 SourceLocation getDefaultDSALocation() const { 782 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc; 783 } 784 OpenMPDefaultmapClauseModifier 785 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const { 786 return isStackEmpty() 787 ? OMPC_DEFAULTMAP_MODIFIER_unknown 788 : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior; 789 } 790 OpenMPDefaultmapClauseModifier 791 getDefaultmapModifierAtLevel(unsigned Level, 792 OpenMPDefaultmapClauseKind Kind) const { 793 return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior; 794 } 795 bool isDefaultmapCapturedByRef(unsigned Level, 796 OpenMPDefaultmapClauseKind Kind) const { 797 OpenMPDefaultmapClauseModifier M = 798 getDefaultmapModifierAtLevel(Level, Kind); 799 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) { 800 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) || 801 (M == OMPC_DEFAULTMAP_MODIFIER_to) || 802 (M == OMPC_DEFAULTMAP_MODIFIER_from) || 803 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom) || 804 (M == OMPC_DEFAULTMAP_MODIFIER_present); 805 } 806 return true; 807 } 808 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M, 809 OpenMPDefaultmapClauseKind Kind) { 810 switch (Kind) { 811 case OMPC_DEFAULTMAP_scalar: 812 case OMPC_DEFAULTMAP_pointer: 813 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) || 814 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) || 815 (M == OMPC_DEFAULTMAP_MODIFIER_default); 816 case OMPC_DEFAULTMAP_aggregate: 817 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate; 818 default: 819 break; 820 } 821 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum"); 822 } 823 bool mustBeFirstprivateAtLevel(unsigned Level, 824 OpenMPDefaultmapClauseKind Kind) const { 825 OpenMPDefaultmapClauseModifier M = 826 getDefaultmapModifierAtLevel(Level, Kind); 827 return mustBeFirstprivateBase(M, Kind); 828 } 829 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const { 830 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind); 831 return mustBeFirstprivateBase(M, Kind); 832 } 833 834 /// Checks if the specified variable is a threadprivate. 835 bool isThreadPrivate(VarDecl *D) { 836 const DSAVarData DVar = getTopDSA(D, false); 837 return isOpenMPThreadPrivate(DVar.CKind); 838 } 839 840 /// Marks current region as ordered (it has an 'ordered' clause). 841 void setOrderedRegion(bool IsOrdered, const Expr *Param, 842 OMPOrderedClause *Clause) { 843 if (IsOrdered) 844 getTopOfStack().OrderedRegion.emplace(Param, Clause); 845 else 846 getTopOfStack().OrderedRegion.reset(); 847 } 848 /// Returns true, if region is ordered (has associated 'ordered' clause), 849 /// false - otherwise. 850 bool isOrderedRegion() const { 851 if (const SharingMapTy *Top = getTopOfStackOrNull()) 852 return Top->OrderedRegion.has_value(); 853 return false; 854 } 855 /// Returns optional parameter for the ordered region. 856 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const { 857 if (const SharingMapTy *Top = getTopOfStackOrNull()) 858 if (Top->OrderedRegion) 859 return *Top->OrderedRegion; 860 return std::make_pair(nullptr, nullptr); 861 } 862 /// Returns true, if parent region is ordered (has associated 863 /// 'ordered' clause), false - otherwise. 864 bool isParentOrderedRegion() const { 865 if (const SharingMapTy *Parent = getSecondOnStackOrNull()) 866 return Parent->OrderedRegion.has_value(); 867 return false; 868 } 869 /// Returns optional parameter for the ordered region. 870 std::pair<const Expr *, OMPOrderedClause *> 871 getParentOrderedRegionParam() const { 872 if (const SharingMapTy *Parent = getSecondOnStackOrNull()) 873 if (Parent->OrderedRegion) 874 return *Parent->OrderedRegion; 875 return std::make_pair(nullptr, nullptr); 876 } 877 /// Marks current region as having an 'order' clause. 878 void setRegionHasOrderConcurrent(bool HasOrderConcurrent) { 879 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent; 880 } 881 /// Returns true, if parent region is order (has associated 882 /// 'order' clause), false - otherwise. 883 bool isParentOrderConcurrent() const { 884 if (const SharingMapTy *Parent = getSecondOnStackOrNull()) 885 return Parent->RegionHasOrderConcurrent; 886 return false; 887 } 888 /// Marks current region as nowait (it has a 'nowait' clause). 889 void setNowaitRegion(bool IsNowait = true) { 890 getTopOfStack().NowaitRegion = IsNowait; 891 } 892 /// Returns true, if parent region is nowait (has associated 893 /// 'nowait' clause), false - otherwise. 894 bool isParentNowaitRegion() const { 895 if (const SharingMapTy *Parent = getSecondOnStackOrNull()) 896 return Parent->NowaitRegion; 897 return false; 898 } 899 /// Marks current region as untied (it has a 'untied' clause). 900 void setUntiedRegion(bool IsUntied = true) { 901 getTopOfStack().UntiedRegion = IsUntied; 902 } 903 /// Return true if current region is untied. 904 bool isUntiedRegion() const { 905 const SharingMapTy *Top = getTopOfStackOrNull(); 906 return Top ? Top->UntiedRegion : false; 907 } 908 /// Marks parent region as cancel region. 909 void setParentCancelRegion(bool Cancel = true) { 910 if (SharingMapTy *Parent = getSecondOnStackOrNull()) 911 Parent->CancelRegion |= Cancel; 912 } 913 /// Return true if current region has inner cancel construct. 914 bool isCancelRegion() const { 915 const SharingMapTy *Top = getTopOfStackOrNull(); 916 return Top ? Top->CancelRegion : false; 917 } 918 919 /// Mark that parent region already has scan directive. 920 void setParentHasScanDirective(SourceLocation Loc) { 921 if (SharingMapTy *Parent = getSecondOnStackOrNull()) 922 Parent->PrevScanLocation = Loc; 923 } 924 /// Return true if current region has inner cancel construct. 925 bool doesParentHasScanDirective() const { 926 const SharingMapTy *Top = getSecondOnStackOrNull(); 927 return Top ? Top->PrevScanLocation.isValid() : false; 928 } 929 /// Return true if current region has inner cancel construct. 930 SourceLocation getParentScanDirectiveLoc() const { 931 const SharingMapTy *Top = getSecondOnStackOrNull(); 932 return Top ? Top->PrevScanLocation : SourceLocation(); 933 } 934 /// Mark that parent region already has ordered directive. 935 void setParentHasOrderedDirective(SourceLocation Loc) { 936 if (SharingMapTy *Parent = getSecondOnStackOrNull()) 937 Parent->PrevOrderedLocation = Loc; 938 } 939 /// Return true if current region has inner ordered construct. 940 bool doesParentHasOrderedDirective() const { 941 const SharingMapTy *Top = getSecondOnStackOrNull(); 942 return Top ? Top->PrevOrderedLocation.isValid() : false; 943 } 944 /// Returns the location of the previously specified ordered directive. 945 SourceLocation getParentOrderedDirectiveLoc() const { 946 const SharingMapTy *Top = getSecondOnStackOrNull(); 947 return Top ? Top->PrevOrderedLocation : SourceLocation(); 948 } 949 950 /// Set collapse value for the region. 951 void setAssociatedLoops(unsigned Val) { 952 getTopOfStack().AssociatedLoops = Val; 953 if (Val > 1) 954 getTopOfStack().HasMutipleLoops = true; 955 } 956 /// Return collapse value for region. 957 unsigned getAssociatedLoops() const { 958 const SharingMapTy *Top = getTopOfStackOrNull(); 959 return Top ? Top->AssociatedLoops : 0; 960 } 961 /// Returns true if the construct is associated with multiple loops. 962 bool hasMutipleLoops() const { 963 const SharingMapTy *Top = getTopOfStackOrNull(); 964 return Top ? Top->HasMutipleLoops : false; 965 } 966 967 /// Marks current target region as one with closely nested teams 968 /// region. 969 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) { 970 if (SharingMapTy *Parent = getSecondOnStackOrNull()) 971 Parent->InnerTeamsRegionLoc = TeamsRegionLoc; 972 } 973 /// Returns true, if current region has closely nested teams region. 974 bool hasInnerTeamsRegion() const { 975 return getInnerTeamsRegionLoc().isValid(); 976 } 977 /// Returns location of the nested teams region (if any). 978 SourceLocation getInnerTeamsRegionLoc() const { 979 const SharingMapTy *Top = getTopOfStackOrNull(); 980 return Top ? Top->InnerTeamsRegionLoc : SourceLocation(); 981 } 982 983 Scope *getCurScope() const { 984 const SharingMapTy *Top = getTopOfStackOrNull(); 985 return Top ? Top->CurScope : nullptr; 986 } 987 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; } 988 SourceLocation getConstructLoc() const { 989 const SharingMapTy *Top = getTopOfStackOrNull(); 990 return Top ? Top->ConstructLoc : SourceLocation(); 991 } 992 993 /// Do the check specified in \a Check to all component lists and return true 994 /// if any issue is found. 995 bool checkMappableExprComponentListsForDecl( 996 const ValueDecl *VD, bool CurrentRegionOnly, 997 const llvm::function_ref< 998 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef, 999 OpenMPClauseKind)> 1000 Check) const { 1001 if (isStackEmpty()) 1002 return false; 1003 auto SI = begin(); 1004 auto SE = end(); 1005 1006 if (SI == SE) 1007 return false; 1008 1009 if (CurrentRegionOnly) 1010 SE = std::next(SI); 1011 else 1012 std::advance(SI, 1); 1013 1014 for (; SI != SE; ++SI) { 1015 auto MI = SI->MappedExprComponents.find(VD); 1016 if (MI != SI->MappedExprComponents.end()) 1017 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L : 1018 MI->second.Components) 1019 if (Check(L, MI->second.Kind)) 1020 return true; 1021 } 1022 return false; 1023 } 1024 1025 /// Do the check specified in \a Check to all component lists at a given level 1026 /// and return true if any issue is found. 1027 bool checkMappableExprComponentListsForDeclAtLevel( 1028 const ValueDecl *VD, unsigned Level, 1029 const llvm::function_ref< 1030 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef, 1031 OpenMPClauseKind)> 1032 Check) const { 1033 if (getStackSize() <= Level) 1034 return false; 1035 1036 const SharingMapTy &StackElem = getStackElemAtLevel(Level); 1037 auto MI = StackElem.MappedExprComponents.find(VD); 1038 if (MI != StackElem.MappedExprComponents.end()) 1039 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L : 1040 MI->second.Components) 1041 if (Check(L, MI->second.Kind)) 1042 return true; 1043 return false; 1044 } 1045 1046 /// Create a new mappable expression component list associated with a given 1047 /// declaration and initialize it with the provided list of components. 1048 void addMappableExpressionComponents( 1049 const ValueDecl *VD, 1050 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 1051 OpenMPClauseKind WhereFoundClauseKind) { 1052 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD]; 1053 // Create new entry and append the new components there. 1054 MEC.Components.resize(MEC.Components.size() + 1); 1055 MEC.Components.back().append(Components.begin(), Components.end()); 1056 MEC.Kind = WhereFoundClauseKind; 1057 } 1058 1059 unsigned getNestingLevel() const { 1060 assert(!isStackEmpty()); 1061 return getStackSize() - 1; 1062 } 1063 void addDoacrossDependClause(OMPClause *C, const OperatorOffsetTy &OpsOffs) { 1064 SharingMapTy *Parent = getSecondOnStackOrNull(); 1065 assert(Parent && isOpenMPWorksharingDirective(Parent->Directive)); 1066 Parent->DoacrossDepends.try_emplace(C, OpsOffs); 1067 } 1068 llvm::iterator_range<DoacrossClauseMapTy::const_iterator> 1069 getDoacrossDependClauses() const { 1070 const SharingMapTy &StackElem = getTopOfStack(); 1071 if (isOpenMPWorksharingDirective(StackElem.Directive)) { 1072 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends; 1073 return llvm::make_range(Ref.begin(), Ref.end()); 1074 } 1075 return llvm::make_range(StackElem.DoacrossDepends.end(), 1076 StackElem.DoacrossDepends.end()); 1077 } 1078 1079 // Store types of classes which have been explicitly mapped 1080 void addMappedClassesQualTypes(QualType QT) { 1081 SharingMapTy &StackElem = getTopOfStack(); 1082 StackElem.MappedClassesQualTypes.insert(QT); 1083 } 1084 1085 // Return set of mapped classes types 1086 bool isClassPreviouslyMapped(QualType QT) const { 1087 const SharingMapTy &StackElem = getTopOfStack(); 1088 return StackElem.MappedClassesQualTypes.contains(QT); 1089 } 1090 1091 /// Adds global declare target to the parent target region. 1092 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) { 1093 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( 1094 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link && 1095 "Expected declare target link global."); 1096 for (auto &Elem : *this) { 1097 if (isOpenMPTargetExecutionDirective(Elem.Directive)) { 1098 Elem.DeclareTargetLinkVarDecls.push_back(E); 1099 return; 1100 } 1101 } 1102 } 1103 1104 /// Returns the list of globals with declare target link if current directive 1105 /// is target. 1106 ArrayRef<DeclRefExpr *> getLinkGlobals() const { 1107 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) && 1108 "Expected target executable directive."); 1109 return getTopOfStack().DeclareTargetLinkVarDecls; 1110 } 1111 1112 /// Adds list of allocators expressions. 1113 void addInnerAllocatorExpr(Expr *E) { 1114 getTopOfStack().InnerUsedAllocators.push_back(E); 1115 } 1116 /// Return list of used allocators. 1117 ArrayRef<Expr *> getInnerAllocators() const { 1118 return getTopOfStack().InnerUsedAllocators; 1119 } 1120 /// Marks the declaration as implicitly firstprivate nin the task-based 1121 /// regions. 1122 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) { 1123 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(D); 1124 } 1125 /// Checks if the decl is implicitly firstprivate in the task-based region. 1126 bool isImplicitTaskFirstprivate(Decl *D) const { 1127 return getTopOfStack().ImplicitTaskFirstprivates.contains(D); 1128 } 1129 1130 /// Marks decl as used in uses_allocators clause as the allocator. 1131 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) { 1132 getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind); 1133 } 1134 /// Checks if specified decl is used in uses allocator clause as the 1135 /// allocator. 1136 std::optional<UsesAllocatorsDeclKind> 1137 isUsesAllocatorsDecl(unsigned Level, const Decl *D) const { 1138 const SharingMapTy &StackElem = getTopOfStack(); 1139 auto I = StackElem.UsesAllocatorsDecls.find(D); 1140 if (I == StackElem.UsesAllocatorsDecls.end()) 1141 return std::nullopt; 1142 return I->getSecond(); 1143 } 1144 std::optional<UsesAllocatorsDeclKind> 1145 isUsesAllocatorsDecl(const Decl *D) const { 1146 const SharingMapTy &StackElem = getTopOfStack(); 1147 auto I = StackElem.UsesAllocatorsDecls.find(D); 1148 if (I == StackElem.UsesAllocatorsDecls.end()) 1149 return std::nullopt; 1150 return I->getSecond(); 1151 } 1152 1153 void addDeclareMapperVarRef(Expr *Ref) { 1154 SharingMapTy &StackElem = getTopOfStack(); 1155 StackElem.DeclareMapperVar = Ref; 1156 } 1157 const Expr *getDeclareMapperVarRef() const { 1158 const SharingMapTy *Top = getTopOfStackOrNull(); 1159 return Top ? Top->DeclareMapperVar : nullptr; 1160 } 1161 1162 /// Add a new iterator variable. 1163 void addIteratorVarDecl(VarDecl *VD) { 1164 SharingMapTy &StackElem = getTopOfStack(); 1165 StackElem.IteratorVarDecls.push_back(VD->getCanonicalDecl()); 1166 } 1167 /// Check if variable declaration is an iterator VarDecl. 1168 bool isIteratorVarDecl(const VarDecl *VD) const { 1169 const SharingMapTy *Top = getTopOfStackOrNull(); 1170 if (!Top) 1171 return false; 1172 1173 return llvm::is_contained(Top->IteratorVarDecls, VD->getCanonicalDecl()); 1174 } 1175 /// get captured field from ImplicitDefaultFirstprivateFDs 1176 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const { 1177 const_iterator I = begin(); 1178 const_iterator EndI = end(); 1179 size_t StackLevel = getStackSize(); 1180 for (; I != EndI; ++I) { 1181 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private) 1182 break; 1183 StackLevel--; 1184 } 1185 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI)); 1186 if (I == EndI) 1187 return nullptr; 1188 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs) 1189 if (IFD.FD == FD && IFD.StackLevel == StackLevel) 1190 return IFD.VD; 1191 return nullptr; 1192 } 1193 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs 1194 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const { 1195 const_iterator I = begin(); 1196 const_iterator EndI = end(); 1197 for (; I != EndI; ++I) 1198 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private) 1199 break; 1200 if (I == EndI) 1201 return false; 1202 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs) 1203 if (IFD.VD == VD) 1204 return true; 1205 return false; 1206 } 1207 /// Store capture FD info in ImplicitDefaultFirstprivateFDs 1208 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) { 1209 iterator I = begin(); 1210 const_iterator EndI = end(); 1211 size_t StackLevel = getStackSize(); 1212 for (; I != EndI; ++I) { 1213 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) { 1214 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD); 1215 break; 1216 } 1217 StackLevel--; 1218 } 1219 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI)); 1220 } 1221 }; 1222 1223 bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) { 1224 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind); 1225 } 1226 1227 bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) { 1228 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) || 1229 DKind == OMPD_unknown; 1230 } 1231 1232 } // namespace 1233 1234 static const Expr *getExprAsWritten(const Expr *E) { 1235 if (const auto *FE = dyn_cast<FullExpr>(E)) 1236 E = FE->getSubExpr(); 1237 1238 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) 1239 E = MTE->getSubExpr(); 1240 1241 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E)) 1242 E = Binder->getSubExpr(); 1243 1244 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) 1245 E = ICE->getSubExprAsWritten(); 1246 return E->IgnoreParens(); 1247 } 1248 1249 static Expr *getExprAsWritten(Expr *E) { 1250 return const_cast<Expr *>(getExprAsWritten(const_cast<const Expr *>(E))); 1251 } 1252 1253 static const ValueDecl *getCanonicalDecl(const ValueDecl *D) { 1254 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(D)) 1255 if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit()))) 1256 D = ME->getMemberDecl(); 1257 1258 D = cast<ValueDecl>(D->getCanonicalDecl()); 1259 return D; 1260 } 1261 1262 static ValueDecl *getCanonicalDecl(ValueDecl *D) { 1263 return const_cast<ValueDecl *>( 1264 getCanonicalDecl(const_cast<const ValueDecl *>(D))); 1265 } 1266 1267 DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter, 1268 ValueDecl *D) const { 1269 D = getCanonicalDecl(D); 1270 auto *VD = dyn_cast<VarDecl>(D); 1271 const auto *FD = dyn_cast<FieldDecl>(D); 1272 DSAVarData DVar; 1273 if (Iter == end()) { 1274 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 1275 // in a region but not in construct] 1276 // File-scope or namespace-scope variables referenced in called routines 1277 // in the region are shared unless they appear in a threadprivate 1278 // directive. 1279 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD)) 1280 DVar.CKind = OMPC_shared; 1281 1282 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced 1283 // in a region but not in construct] 1284 // Variables with static storage duration that are declared in called 1285 // routines in the region are shared. 1286 if (VD && VD->hasGlobalStorage()) 1287 DVar.CKind = OMPC_shared; 1288 1289 // Non-static data members are shared by default. 1290 if (FD) 1291 DVar.CKind = OMPC_shared; 1292 1293 return DVar; 1294 } 1295 1296 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 1297 // in a Construct, C/C++, predetermined, p.1] 1298 // Variables with automatic storage duration that are declared in a scope 1299 // inside the construct are private. 1300 if (VD && isOpenMPLocal(VD, Iter) && VD->isLocalVarDecl() && 1301 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) { 1302 DVar.CKind = OMPC_private; 1303 return DVar; 1304 } 1305 1306 DVar.DKind = Iter->Directive; 1307 // Explicitly specified attributes and local variables with predetermined 1308 // attributes. 1309 if (Iter->SharingMap.count(D)) { 1310 const DSAInfo &Data = Iter->SharingMap.lookup(D); 1311 DVar.RefExpr = Data.RefExpr.getPointer(); 1312 DVar.PrivateCopy = Data.PrivateCopy; 1313 DVar.CKind = Data.Attributes; 1314 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc; 1315 DVar.Modifier = Data.Modifier; 1316 DVar.AppliedToPointee = Data.AppliedToPointee; 1317 return DVar; 1318 } 1319 1320 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 1321 // in a Construct, C/C++, implicitly determined, p.1] 1322 // In a parallel or task construct, the data-sharing attributes of these 1323 // variables are determined by the default clause, if present. 1324 switch (Iter->DefaultAttr) { 1325 case DSA_shared: 1326 DVar.CKind = OMPC_shared; 1327 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc; 1328 return DVar; 1329 case DSA_none: 1330 return DVar; 1331 case DSA_firstprivate: 1332 if (VD && VD->getStorageDuration() == SD_Static && 1333 VD->getDeclContext()->isFileContext()) { 1334 DVar.CKind = OMPC_unknown; 1335 } else { 1336 DVar.CKind = OMPC_firstprivate; 1337 } 1338 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc; 1339 return DVar; 1340 case DSA_private: 1341 // each variable with static storage duration that is declared 1342 // in a namespace or global scope and referenced in the construct, 1343 // and that does not have a predetermined data-sharing attribute 1344 if (VD && VD->getStorageDuration() == SD_Static && 1345 VD->getDeclContext()->isFileContext()) { 1346 DVar.CKind = OMPC_unknown; 1347 } else { 1348 DVar.CKind = OMPC_private; 1349 } 1350 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc; 1351 return DVar; 1352 case DSA_unspecified: 1353 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 1354 // in a Construct, implicitly determined, p.2] 1355 // In a parallel construct, if no default clause is present, these 1356 // variables are shared. 1357 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc; 1358 if ((isOpenMPParallelDirective(DVar.DKind) && 1359 !isOpenMPTaskLoopDirective(DVar.DKind)) || 1360 isOpenMPTeamsDirective(DVar.DKind)) { 1361 DVar.CKind = OMPC_shared; 1362 return DVar; 1363 } 1364 1365 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 1366 // in a Construct, implicitly determined, p.4] 1367 // In a task construct, if no default clause is present, a variable that in 1368 // the enclosing context is determined to be shared by all implicit tasks 1369 // bound to the current team is shared. 1370 if (isOpenMPTaskingDirective(DVar.DKind)) { 1371 DSAVarData DVarTemp; 1372 const_iterator I = Iter, E = end(); 1373 do { 1374 ++I; 1375 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables 1376 // Referenced in a Construct, implicitly determined, p.6] 1377 // In a task construct, if no default clause is present, a variable 1378 // whose data-sharing attribute is not determined by the rules above is 1379 // firstprivate. 1380 DVarTemp = getDSA(I, D); 1381 if (DVarTemp.CKind != OMPC_shared) { 1382 DVar.RefExpr = nullptr; 1383 DVar.CKind = OMPC_firstprivate; 1384 return DVar; 1385 } 1386 } while (I != E && !isImplicitTaskingRegion(I->Directive)); 1387 DVar.CKind = 1388 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared; 1389 return DVar; 1390 } 1391 } 1392 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 1393 // in a Construct, implicitly determined, p.3] 1394 // For constructs other than task, if no default clause is present, these 1395 // variables inherit their data-sharing attributes from the enclosing 1396 // context. 1397 return getDSA(++Iter, D); 1398 } 1399 1400 const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D, 1401 const Expr *NewDE) { 1402 assert(!isStackEmpty() && "Data sharing attributes stack is empty"); 1403 D = getCanonicalDecl(D); 1404 SharingMapTy &StackElem = getTopOfStack(); 1405 auto [It, Inserted] = StackElem.AlignedMap.try_emplace(D, NewDE); 1406 if (Inserted) { 1407 assert(NewDE && "Unexpected nullptr expr to be added into aligned map"); 1408 return nullptr; 1409 } 1410 assert(It->second && "Unexpected nullptr expr in the aligned map"); 1411 return It->second; 1412 } 1413 1414 const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D, 1415 const Expr *NewDE) { 1416 assert(!isStackEmpty() && "Data sharing attributes stack is empty"); 1417 D = getCanonicalDecl(D); 1418 SharingMapTy &StackElem = getTopOfStack(); 1419 auto [It, Inserted] = StackElem.NontemporalMap.try_emplace(D, NewDE); 1420 if (Inserted) { 1421 assert(NewDE && "Unexpected nullptr expr to be added into aligned map"); 1422 return nullptr; 1423 } 1424 assert(It->second && "Unexpected nullptr expr in the aligned map"); 1425 return It->second; 1426 } 1427 1428 void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) { 1429 assert(!isStackEmpty() && "Data-sharing attributes stack is empty"); 1430 D = getCanonicalDecl(D); 1431 SharingMapTy &StackElem = getTopOfStack(); 1432 StackElem.LCVMap.try_emplace( 1433 D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture)); 1434 } 1435 1436 const DSAStackTy::LCDeclInfo 1437 DSAStackTy::isLoopControlVariable(const ValueDecl *D) const { 1438 assert(!isStackEmpty() && "Data-sharing attributes stack is empty"); 1439 D = getCanonicalDecl(D); 1440 const SharingMapTy &StackElem = getTopOfStack(); 1441 auto It = StackElem.LCVMap.find(D); 1442 if (It != StackElem.LCVMap.end()) 1443 return It->second; 1444 return {0, nullptr}; 1445 } 1446 1447 const DSAStackTy::LCDeclInfo 1448 DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const { 1449 assert(!isStackEmpty() && "Data-sharing attributes stack is empty"); 1450 D = getCanonicalDecl(D); 1451 for (unsigned I = Level + 1; I > 0; --I) { 1452 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1); 1453 auto It = StackElem.LCVMap.find(D); 1454 if (It != StackElem.LCVMap.end()) 1455 return It->second; 1456 } 1457 return {0, nullptr}; 1458 } 1459 1460 const DSAStackTy::LCDeclInfo 1461 DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const { 1462 const SharingMapTy *Parent = getSecondOnStackOrNull(); 1463 assert(Parent && "Data-sharing attributes stack is empty"); 1464 D = getCanonicalDecl(D); 1465 auto It = Parent->LCVMap.find(D); 1466 if (It != Parent->LCVMap.end()) 1467 return It->second; 1468 return {0, nullptr}; 1469 } 1470 1471 const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const { 1472 const SharingMapTy *Parent = getSecondOnStackOrNull(); 1473 assert(Parent && "Data-sharing attributes stack is empty"); 1474 if (Parent->LCVMap.size() < I) 1475 return nullptr; 1476 for (const auto &Pair : Parent->LCVMap) 1477 if (Pair.second.first == I) 1478 return Pair.first; 1479 return nullptr; 1480 } 1481 1482 void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A, 1483 DeclRefExpr *PrivateCopy, unsigned Modifier, 1484 bool AppliedToPointee) { 1485 D = getCanonicalDecl(D); 1486 if (A == OMPC_threadprivate) { 1487 DSAInfo &Data = Threadprivates[D]; 1488 Data.Attributes = A; 1489 Data.RefExpr.setPointer(E); 1490 Data.PrivateCopy = nullptr; 1491 Data.Modifier = Modifier; 1492 } else { 1493 DSAInfo &Data = getTopOfStack().SharingMap[D]; 1494 assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) || 1495 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) || 1496 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) || 1497 (isLoopControlVariable(D).first && A == OMPC_private)); 1498 Data.Modifier = Modifier; 1499 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) { 1500 Data.RefExpr.setInt(/*IntVal=*/true); 1501 return; 1502 } 1503 const bool IsLastprivate = 1504 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate; 1505 Data.Attributes = A; 1506 Data.RefExpr.setPointerAndInt(E, IsLastprivate); 1507 Data.PrivateCopy = PrivateCopy; 1508 Data.AppliedToPointee = AppliedToPointee; 1509 if (PrivateCopy) { 1510 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()]; 1511 Data.Modifier = Modifier; 1512 Data.Attributes = A; 1513 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate); 1514 Data.PrivateCopy = nullptr; 1515 Data.AppliedToPointee = AppliedToPointee; 1516 } 1517 } 1518 } 1519 1520 /// Build a variable declaration for OpenMP loop iteration variable. 1521 static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type, 1522 StringRef Name, const AttrVec *Attrs = nullptr, 1523 DeclRefExpr *OrigRef = nullptr) { 1524 DeclContext *DC = SemaRef.CurContext; 1525 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name); 1526 TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc); 1527 auto *Decl = 1528 VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None); 1529 if (Attrs) { 1530 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end()); 1531 I != E; ++I) 1532 Decl->addAttr(*I); 1533 } 1534 Decl->setImplicit(); 1535 if (OrigRef) { 1536 Decl->addAttr( 1537 OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef)); 1538 } 1539 return Decl; 1540 } 1541 1542 static DeclRefExpr *buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty, 1543 SourceLocation Loc, 1544 bool RefersToCapture = false) { 1545 D->setReferenced(); 1546 D->markUsed(S.Context); 1547 return DeclRefExpr::Create(S.getASTContext(), NestedNameSpecifierLoc(), 1548 SourceLocation(), D, RefersToCapture, Loc, Ty, 1549 VK_LValue); 1550 } 1551 1552 void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR, 1553 BinaryOperatorKind BOK) { 1554 D = getCanonicalDecl(D); 1555 assert(!isStackEmpty() && "Data-sharing attributes stack is empty"); 1556 assert( 1557 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction && 1558 "Additional reduction info may be specified only for reduction items."); 1559 ReductionData &ReductionData = getTopOfStack().ReductionMap[D]; 1560 assert(ReductionData.ReductionRange.isInvalid() && 1561 (getTopOfStack().Directive == OMPD_taskgroup || 1562 ((isOpenMPParallelDirective(getTopOfStack().Directive) || 1563 isOpenMPWorksharingDirective(getTopOfStack().Directive)) && 1564 !isOpenMPSimdDirective(getTopOfStack().Directive))) && 1565 "Additional reduction info may be specified only once for reduction " 1566 "items."); 1567 ReductionData.set(BOK, SR); 1568 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef; 1569 if (!TaskgroupReductionRef) { 1570 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(), 1571 SemaRef.Context.VoidPtrTy, ".task_red."); 1572 TaskgroupReductionRef = 1573 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin()); 1574 } 1575 } 1576 1577 void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR, 1578 const Expr *ReductionRef) { 1579 D = getCanonicalDecl(D); 1580 assert(!isStackEmpty() && "Data-sharing attributes stack is empty"); 1581 assert( 1582 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction && 1583 "Additional reduction info may be specified only for reduction items."); 1584 ReductionData &ReductionData = getTopOfStack().ReductionMap[D]; 1585 assert(ReductionData.ReductionRange.isInvalid() && 1586 (getTopOfStack().Directive == OMPD_taskgroup || 1587 ((isOpenMPParallelDirective(getTopOfStack().Directive) || 1588 isOpenMPWorksharingDirective(getTopOfStack().Directive)) && 1589 !isOpenMPSimdDirective(getTopOfStack().Directive))) && 1590 "Additional reduction info may be specified only once for reduction " 1591 "items."); 1592 ReductionData.set(ReductionRef, SR); 1593 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef; 1594 if (!TaskgroupReductionRef) { 1595 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(), 1596 SemaRef.Context.VoidPtrTy, ".task_red."); 1597 TaskgroupReductionRef = 1598 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin()); 1599 } 1600 } 1601 1602 const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData( 1603 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK, 1604 Expr *&TaskgroupDescriptor) const { 1605 D = getCanonicalDecl(D); 1606 assert(!isStackEmpty() && "Data-sharing attributes stack is empty."); 1607 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) { 1608 const DSAInfo &Data = I->SharingMap.lookup(D); 1609 if (Data.Attributes != OMPC_reduction || 1610 Data.Modifier != OMPC_REDUCTION_task) 1611 continue; 1612 const ReductionData &ReductionData = I->ReductionMap.lookup(D); 1613 if (!ReductionData.ReductionOp || 1614 isa<const Expr *>(ReductionData.ReductionOp)) 1615 return DSAVarData(); 1616 SR = ReductionData.ReductionRange; 1617 BOK = cast<ReductionData::BOKPtrType>(ReductionData.ReductionOp); 1618 assert(I->TaskgroupReductionRef && "taskgroup reduction reference " 1619 "expression for the descriptor is not " 1620 "set."); 1621 TaskgroupDescriptor = I->TaskgroupReductionRef; 1622 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(), 1623 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task, 1624 /*AppliedToPointee=*/false); 1625 } 1626 return DSAVarData(); 1627 } 1628 1629 const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData( 1630 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef, 1631 Expr *&TaskgroupDescriptor) const { 1632 D = getCanonicalDecl(D); 1633 assert(!isStackEmpty() && "Data-sharing attributes stack is empty."); 1634 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) { 1635 const DSAInfo &Data = I->SharingMap.lookup(D); 1636 if (Data.Attributes != OMPC_reduction || 1637 Data.Modifier != OMPC_REDUCTION_task) 1638 continue; 1639 const ReductionData &ReductionData = I->ReductionMap.lookup(D); 1640 if (!ReductionData.ReductionOp || 1641 !isa<const Expr *>(ReductionData.ReductionOp)) 1642 return DSAVarData(); 1643 SR = ReductionData.ReductionRange; 1644 ReductionRef = cast<const Expr *>(ReductionData.ReductionOp); 1645 assert(I->TaskgroupReductionRef && "taskgroup reduction reference " 1646 "expression for the descriptor is not " 1647 "set."); 1648 TaskgroupDescriptor = I->TaskgroupReductionRef; 1649 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(), 1650 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task, 1651 /*AppliedToPointee=*/false); 1652 } 1653 return DSAVarData(); 1654 } 1655 1656 bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const { 1657 D = D->getCanonicalDecl(); 1658 for (const_iterator E = end(); I != E; ++I) { 1659 if (isImplicitOrExplicitTaskingRegion(I->Directive) || 1660 isOpenMPTargetExecutionDirective(I->Directive)) { 1661 if (I->CurScope) { 1662 Scope *TopScope = I->CurScope->getParent(); 1663 Scope *CurScope = getCurScope(); 1664 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D)) 1665 CurScope = CurScope->getParent(); 1666 return CurScope != TopScope; 1667 } 1668 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent()) 1669 if (I->Context == DC) 1670 return true; 1671 return false; 1672 } 1673 } 1674 return false; 1675 } 1676 1677 static bool isConstNotMutableType(Sema &SemaRef, QualType Type, 1678 bool AcceptIfMutable = true, 1679 bool *IsClassType = nullptr) { 1680 ASTContext &Context = SemaRef.getASTContext(); 1681 Type = Type.getNonReferenceType().getCanonicalType(); 1682 bool IsConstant = Type.isConstant(Context); 1683 Type = Context.getBaseElementType(Type); 1684 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus 1685 ? Type->getAsCXXRecordDecl() 1686 : nullptr; 1687 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD)) 1688 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate()) 1689 RD = CTD->getTemplatedDecl(); 1690 if (IsClassType) 1691 *IsClassType = RD; 1692 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD && 1693 RD->hasDefinition() && RD->hasMutableFields()); 1694 } 1695 1696 static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D, 1697 QualType Type, OpenMPClauseKind CKind, 1698 SourceLocation ELoc, 1699 bool AcceptIfMutable = true, 1700 bool ListItemNotVar = false) { 1701 ASTContext &Context = SemaRef.getASTContext(); 1702 bool IsClassType; 1703 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, &IsClassType)) { 1704 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item 1705 : IsClassType ? diag::err_omp_const_not_mutable_variable 1706 : diag::err_omp_const_variable; 1707 SemaRef.Diag(ELoc, Diag) << getOpenMPClauseName(CKind); 1708 if (!ListItemNotVar && D) { 1709 const VarDecl *VD = dyn_cast<VarDecl>(D); 1710 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) == 1711 VarDecl::DeclarationOnly; 1712 SemaRef.Diag(D->getLocation(), 1713 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 1714 << D; 1715 } 1716 return true; 1717 } 1718 return false; 1719 } 1720 1721 const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, 1722 bool FromParent) { 1723 D = getCanonicalDecl(D); 1724 DSAVarData DVar; 1725 1726 auto *VD = dyn_cast<VarDecl>(D); 1727 auto TI = Threadprivates.find(D); 1728 if (TI != Threadprivates.end()) { 1729 DVar.RefExpr = TI->getSecond().RefExpr.getPointer(); 1730 DVar.CKind = OMPC_threadprivate; 1731 DVar.Modifier = TI->getSecond().Modifier; 1732 return DVar; 1733 } 1734 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) { 1735 DVar.RefExpr = buildDeclRefExpr( 1736 SemaRef, VD, D->getType().getNonReferenceType(), 1737 VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation()); 1738 DVar.CKind = OMPC_threadprivate; 1739 addDSA(D, DVar.RefExpr, OMPC_threadprivate); 1740 return DVar; 1741 } 1742 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 1743 // in a Construct, C/C++, predetermined, p.1] 1744 // Variables appearing in threadprivate directives are threadprivate. 1745 if ((VD && VD->getTLSKind() != VarDecl::TLS_None && 1746 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() && 1747 SemaRef.getLangOpts().OpenMPUseTLS && 1748 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) || 1749 (VD && VD->getStorageClass() == SC_Register && 1750 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) { 1751 DVar.RefExpr = buildDeclRefExpr( 1752 SemaRef, VD, D->getType().getNonReferenceType(), D->getLocation()); 1753 DVar.CKind = OMPC_threadprivate; 1754 addDSA(D, DVar.RefExpr, OMPC_threadprivate); 1755 return DVar; 1756 } 1757 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD && 1758 VD->isLocalVarDeclOrParm() && !isStackEmpty() && 1759 !isLoopControlVariable(D).first) { 1760 const_iterator IterTarget = 1761 std::find_if(begin(), end(), [](const SharingMapTy &Data) { 1762 return isOpenMPTargetExecutionDirective(Data.Directive); 1763 }); 1764 if (IterTarget != end()) { 1765 const_iterator ParentIterTarget = IterTarget + 1; 1766 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) { 1767 if (isOpenMPLocal(VD, Iter)) { 1768 DVar.RefExpr = 1769 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(), 1770 D->getLocation()); 1771 DVar.CKind = OMPC_threadprivate; 1772 return DVar; 1773 } 1774 } 1775 if (!isClauseParsingMode() || IterTarget != begin()) { 1776 auto DSAIter = IterTarget->SharingMap.find(D); 1777 if (DSAIter != IterTarget->SharingMap.end() && 1778 isOpenMPPrivate(DSAIter->getSecond().Attributes)) { 1779 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer(); 1780 DVar.CKind = OMPC_threadprivate; 1781 return DVar; 1782 } 1783 const_iterator End = end(); 1784 if (!SemaRef.OpenMP().isOpenMPCapturedByRef( 1785 D, std::distance(ParentIterTarget, End), 1786 /*OpenMPCaptureLevel=*/0)) { 1787 DVar.RefExpr = 1788 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(), 1789 IterTarget->ConstructLoc); 1790 DVar.CKind = OMPC_threadprivate; 1791 return DVar; 1792 } 1793 } 1794 } 1795 } 1796 1797 if (isStackEmpty()) 1798 // Not in OpenMP execution region and top scope was already checked. 1799 return DVar; 1800 1801 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 1802 // in a Construct, C/C++, predetermined, p.4] 1803 // Static data members are shared. 1804 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 1805 // in a Construct, C/C++, predetermined, p.7] 1806 // Variables with static storage duration that are declared in a scope 1807 // inside the construct are shared. 1808 if (VD && VD->isStaticDataMember()) { 1809 // Check for explicitly specified attributes. 1810 const_iterator I = begin(); 1811 const_iterator EndI = end(); 1812 if (FromParent && I != EndI) 1813 ++I; 1814 if (I != EndI) { 1815 auto It = I->SharingMap.find(D); 1816 if (It != I->SharingMap.end()) { 1817 const DSAInfo &Data = It->getSecond(); 1818 DVar.RefExpr = Data.RefExpr.getPointer(); 1819 DVar.PrivateCopy = Data.PrivateCopy; 1820 DVar.CKind = Data.Attributes; 1821 DVar.ImplicitDSALoc = I->DefaultAttrLoc; 1822 DVar.DKind = I->Directive; 1823 DVar.Modifier = Data.Modifier; 1824 DVar.AppliedToPointee = Data.AppliedToPointee; 1825 return DVar; 1826 } 1827 } 1828 1829 DVar.CKind = OMPC_shared; 1830 return DVar; 1831 } 1832 1833 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; }; 1834 // The predetermined shared attribute for const-qualified types having no 1835 // mutable members was removed after OpenMP 3.1. 1836 if (SemaRef.LangOpts.OpenMP <= 31) { 1837 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 1838 // in a Construct, C/C++, predetermined, p.6] 1839 // Variables with const qualified type having no mutable member are 1840 // shared. 1841 if (isConstNotMutableType(SemaRef, D->getType())) { 1842 // Variables with const-qualified type having no mutable member may be 1843 // listed in a firstprivate clause, even if they are static data members. 1844 DSAVarData DVarTemp = hasInnermostDSA( 1845 D, 1846 [](OpenMPClauseKind C, bool) { 1847 return C == OMPC_firstprivate || C == OMPC_shared; 1848 }, 1849 MatchesAlways, FromParent); 1850 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr) 1851 return DVarTemp; 1852 1853 DVar.CKind = OMPC_shared; 1854 return DVar; 1855 } 1856 } 1857 1858 // Explicitly specified attributes and local variables with predetermined 1859 // attributes. 1860 const_iterator I = begin(); 1861 const_iterator EndI = end(); 1862 if (FromParent && I != EndI) 1863 ++I; 1864 if (I == EndI) 1865 return DVar; 1866 auto It = I->SharingMap.find(D); 1867 if (It != I->SharingMap.end()) { 1868 const DSAInfo &Data = It->getSecond(); 1869 DVar.RefExpr = Data.RefExpr.getPointer(); 1870 DVar.PrivateCopy = Data.PrivateCopy; 1871 DVar.CKind = Data.Attributes; 1872 DVar.ImplicitDSALoc = I->DefaultAttrLoc; 1873 DVar.DKind = I->Directive; 1874 DVar.Modifier = Data.Modifier; 1875 DVar.AppliedToPointee = Data.AppliedToPointee; 1876 } 1877 1878 return DVar; 1879 } 1880 1881 const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D, 1882 bool FromParent) const { 1883 if (isStackEmpty()) { 1884 const_iterator I; 1885 return getDSA(I, D); 1886 } 1887 D = getCanonicalDecl(D); 1888 const_iterator StartI = begin(); 1889 const_iterator EndI = end(); 1890 if (FromParent && StartI != EndI) 1891 ++StartI; 1892 return getDSA(StartI, D); 1893 } 1894 1895 const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D, 1896 unsigned Level) const { 1897 if (getStackSize() <= Level) 1898 return DSAVarData(); 1899 D = getCanonicalDecl(D); 1900 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level); 1901 return getDSA(StartI, D); 1902 } 1903 1904 const DSAStackTy::DSAVarData 1905 DSAStackTy::hasDSA(ValueDecl *D, 1906 const llvm::function_ref<bool(OpenMPClauseKind, bool, 1907 DefaultDataSharingAttributes)> 1908 CPred, 1909 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred, 1910 bool FromParent) const { 1911 if (isStackEmpty()) 1912 return {}; 1913 D = getCanonicalDecl(D); 1914 const_iterator I = begin(); 1915 const_iterator EndI = end(); 1916 if (FromParent && I != EndI) 1917 ++I; 1918 for (; I != EndI; ++I) { 1919 if (!DPred(I->Directive) && 1920 !isImplicitOrExplicitTaskingRegion(I->Directive)) 1921 continue; 1922 const_iterator NewI = I; 1923 DSAVarData DVar = getDSA(NewI, D); 1924 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr)) 1925 return DVar; 1926 } 1927 return {}; 1928 } 1929 1930 const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA( 1931 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred, 1932 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred, 1933 bool FromParent) const { 1934 if (isStackEmpty()) 1935 return {}; 1936 D = getCanonicalDecl(D); 1937 const_iterator StartI = begin(); 1938 const_iterator EndI = end(); 1939 if (FromParent && StartI != EndI) 1940 ++StartI; 1941 if (StartI == EndI || !DPred(StartI->Directive)) 1942 return {}; 1943 const_iterator NewI = StartI; 1944 DSAVarData DVar = getDSA(NewI, D); 1945 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee)) 1946 ? DVar 1947 : DSAVarData(); 1948 } 1949 1950 bool DSAStackTy::hasExplicitDSA( 1951 const ValueDecl *D, 1952 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred, 1953 unsigned Level, bool NotLastprivate) const { 1954 if (getStackSize() <= Level) 1955 return false; 1956 D = getCanonicalDecl(D); 1957 const SharingMapTy &StackElem = getStackElemAtLevel(Level); 1958 auto I = StackElem.SharingMap.find(D); 1959 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() && 1960 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) && 1961 (!NotLastprivate || !I->getSecond().RefExpr.getInt())) 1962 return true; 1963 // Check predetermined rules for the loop control variables. 1964 auto LI = StackElem.LCVMap.find(D); 1965 if (LI != StackElem.LCVMap.end()) 1966 return CPred(OMPC_private, /*AppliedToPointee=*/false); 1967 return false; 1968 } 1969 1970 bool DSAStackTy::hasExplicitDirective( 1971 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred, 1972 unsigned Level) const { 1973 if (getStackSize() <= Level) 1974 return false; 1975 const SharingMapTy &StackElem = getStackElemAtLevel(Level); 1976 return DPred(StackElem.Directive); 1977 } 1978 1979 bool DSAStackTy::hasDirective( 1980 const llvm::function_ref<bool(OpenMPDirectiveKind, 1981 const DeclarationNameInfo &, SourceLocation)> 1982 DPred, 1983 bool FromParent) const { 1984 // We look only in the enclosing region. 1985 size_t Skip = FromParent ? 2 : 1; 1986 for (const_iterator I = begin() + std::min(Skip, getStackSize()), E = end(); 1987 I != E; ++I) { 1988 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc)) 1989 return true; 1990 } 1991 return false; 1992 } 1993 1994 void SemaOpenMP::InitDataSharingAttributesStack() { 1995 VarDataSharingAttributesStack = new DSAStackTy(SemaRef); 1996 } 1997 1998 #define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack) 1999 2000 void SemaOpenMP::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); } 2001 2002 void SemaOpenMP::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) { 2003 DSAStack->popFunction(OldFSI); 2004 } 2005 2006 static bool isOpenMPDeviceDelayedContext(Sema &S) { 2007 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsTargetDevice && 2008 "Expected OpenMP device compilation."); 2009 return !S.OpenMP().isInOpenMPTargetExecutionDirective(); 2010 } 2011 2012 namespace { 2013 /// Status of the function emission on the host/device. 2014 enum class FunctionEmissionStatus { 2015 Emitted, 2016 Discarded, 2017 Unknown, 2018 }; 2019 } // anonymous namespace 2020 2021 SemaBase::SemaDiagnosticBuilder 2022 SemaOpenMP::diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID, 2023 const FunctionDecl *FD) { 2024 assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice && 2025 "Expected OpenMP device compilation."); 2026 2027 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop; 2028 if (FD) { 2029 Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(FD); 2030 switch (FES) { 2031 case Sema::FunctionEmissionStatus::Emitted: 2032 Kind = SemaDiagnosticBuilder::K_Immediate; 2033 break; 2034 case Sema::FunctionEmissionStatus::Unknown: 2035 // TODO: We should always delay diagnostics here in case a target 2036 // region is in a function we do not emit. However, as the 2037 // current diagnostics are associated with the function containing 2038 // the target region and we do not emit that one, we would miss out 2039 // on diagnostics for the target region itself. We need to anchor 2040 // the diagnostics with the new generated function *or* ensure we 2041 // emit diagnostics associated with the surrounding function. 2042 Kind = isOpenMPDeviceDelayedContext(SemaRef) 2043 ? SemaDiagnosticBuilder::K_Deferred 2044 : SemaDiagnosticBuilder::K_Immediate; 2045 break; 2046 case Sema::FunctionEmissionStatus::TemplateDiscarded: 2047 case Sema::FunctionEmissionStatus::OMPDiscarded: 2048 Kind = SemaDiagnosticBuilder::K_Nop; 2049 break; 2050 case Sema::FunctionEmissionStatus::CUDADiscarded: 2051 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation"); 2052 break; 2053 } 2054 } 2055 2056 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef); 2057 } 2058 2059 SemaBase::SemaDiagnosticBuilder 2060 SemaOpenMP::diagIfOpenMPHostCode(SourceLocation Loc, unsigned DiagID, 2061 const FunctionDecl *FD) { 2062 assert(getLangOpts().OpenMP && !getLangOpts().OpenMPIsTargetDevice && 2063 "Expected OpenMP host compilation."); 2064 2065 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop; 2066 if (FD) { 2067 Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(FD); 2068 switch (FES) { 2069 case Sema::FunctionEmissionStatus::Emitted: 2070 Kind = SemaDiagnosticBuilder::K_Immediate; 2071 break; 2072 case Sema::FunctionEmissionStatus::Unknown: 2073 Kind = SemaDiagnosticBuilder::K_Deferred; 2074 break; 2075 case Sema::FunctionEmissionStatus::TemplateDiscarded: 2076 case Sema::FunctionEmissionStatus::OMPDiscarded: 2077 case Sema::FunctionEmissionStatus::CUDADiscarded: 2078 Kind = SemaDiagnosticBuilder::K_Nop; 2079 break; 2080 } 2081 } 2082 2083 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef); 2084 } 2085 2086 static OpenMPDefaultmapClauseKind 2087 getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD) { 2088 if (LO.OpenMP <= 45) { 2089 if (VD->getType().getNonReferenceType()->isScalarType()) 2090 return OMPC_DEFAULTMAP_scalar; 2091 return OMPC_DEFAULTMAP_aggregate; 2092 } 2093 if (VD->getType().getNonReferenceType()->isAnyPointerType()) 2094 return OMPC_DEFAULTMAP_pointer; 2095 if (VD->getType().getNonReferenceType()->isScalarType()) 2096 return OMPC_DEFAULTMAP_scalar; 2097 return OMPC_DEFAULTMAP_aggregate; 2098 } 2099 2100 bool SemaOpenMP::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, 2101 unsigned OpenMPCaptureLevel) const { 2102 assert(getLangOpts().OpenMP && "OpenMP is not allowed"); 2103 2104 ASTContext &Ctx = getASTContext(); 2105 bool IsByRef = true; 2106 2107 // Find the directive that is associated with the provided scope. 2108 D = cast<ValueDecl>(D->getCanonicalDecl()); 2109 QualType Ty = D->getType(); 2110 2111 bool IsVariableUsedInMapClause = false; 2112 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) { 2113 // This table summarizes how a given variable should be passed to the device 2114 // given its type and the clauses where it appears. This table is based on 2115 // the description in OpenMP 4.5 [2.10.4, target Construct] and 2116 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses]. 2117 // 2118 // ========================================================================= 2119 // | type | defaultmap | pvt | first | is_device_ptr | map | res. | 2120 // | |(tofrom:scalar)| | pvt | |has_dv_adr| | 2121 // ========================================================================= 2122 // | scl | | | | - | | bycopy| 2123 // | scl | | - | x | - | - | bycopy| 2124 // | scl | | x | - | - | - | null | 2125 // | scl | x | | | - | | byref | 2126 // | scl | x | - | x | - | - | bycopy| 2127 // | scl | x | x | - | - | - | null | 2128 // | scl | | - | - | - | x | byref | 2129 // | scl | x | - | - | - | x | byref | 2130 // 2131 // | agg | n.a. | | | - | | byref | 2132 // | agg | n.a. | - | x | - | - | byref | 2133 // | agg | n.a. | x | - | - | - | null | 2134 // | agg | n.a. | - | - | - | x | byref | 2135 // | agg | n.a. | - | - | - | x[] | byref | 2136 // 2137 // | ptr | n.a. | | | - | | bycopy| 2138 // | ptr | n.a. | - | x | - | - | bycopy| 2139 // | ptr | n.a. | x | - | - | - | null | 2140 // | ptr | n.a. | - | - | - | x | byref | 2141 // | ptr | n.a. | - | - | - | x[] | bycopy| 2142 // | ptr | n.a. | - | - | x | | bycopy| 2143 // | ptr | n.a. | - | - | x | x | bycopy| 2144 // | ptr | n.a. | - | - | x | x[] | bycopy| 2145 // ========================================================================= 2146 // Legend: 2147 // scl - scalar 2148 // ptr - pointer 2149 // agg - aggregate 2150 // x - applies 2151 // - - invalid in this combination 2152 // [] - mapped with an array section 2153 // byref - should be mapped by reference 2154 // byval - should be mapped by value 2155 // null - initialize a local variable to null on the device 2156 // 2157 // Observations: 2158 // - All scalar declarations that show up in a map clause have to be passed 2159 // by reference, because they may have been mapped in the enclosing data 2160 // environment. 2161 // - If the scalar value does not fit the size of uintptr, it has to be 2162 // passed by reference, regardless the result in the table above. 2163 // - For pointers mapped by value that have either an implicit map or an 2164 // array section, the runtime library may pass the NULL value to the 2165 // device instead of the value passed to it by the compiler. 2166 2167 if (Ty->isReferenceType()) 2168 Ty = Ty->castAs<ReferenceType>()->getPointeeType(); 2169 2170 // Locate map clauses and see if the variable being captured is referred to 2171 // in any of those clauses. Here we only care about variables, not fields, 2172 // because fields are part of aggregates. 2173 bool IsVariableAssociatedWithSection = false; 2174 2175 DSAStack->checkMappableExprComponentListsForDeclAtLevel( 2176 D, Level, 2177 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection, 2178 D](OMPClauseMappableExprCommon::MappableExprComponentListRef 2179 MapExprComponents, 2180 OpenMPClauseKind WhereFoundClauseKind) { 2181 // Both map and has_device_addr clauses information influences how a 2182 // variable is captured. E.g. is_device_ptr does not require changing 2183 // the default behavior. 2184 if (WhereFoundClauseKind != OMPC_map && 2185 WhereFoundClauseKind != OMPC_has_device_addr) 2186 return false; 2187 2188 auto EI = MapExprComponents.rbegin(); 2189 auto EE = MapExprComponents.rend(); 2190 2191 assert(EI != EE && "Invalid map expression!"); 2192 2193 if (isa<DeclRefExpr>(EI->getAssociatedExpression())) 2194 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D; 2195 2196 ++EI; 2197 if (EI == EE) 2198 return false; 2199 auto Last = std::prev(EE); 2200 const auto *UO = 2201 dyn_cast<UnaryOperator>(Last->getAssociatedExpression()); 2202 if ((UO && UO->getOpcode() == UO_Deref) || 2203 isa<ArraySubscriptExpr>(Last->getAssociatedExpression()) || 2204 isa<ArraySectionExpr>(Last->getAssociatedExpression()) || 2205 isa<MemberExpr>(EI->getAssociatedExpression()) || 2206 isa<OMPArrayShapingExpr>(Last->getAssociatedExpression())) { 2207 IsVariableAssociatedWithSection = true; 2208 // There is nothing more we need to know about this variable. 2209 return true; 2210 } 2211 2212 // Keep looking for more map info. 2213 return false; 2214 }); 2215 2216 if (IsVariableUsedInMapClause) { 2217 // If variable is identified in a map clause it is always captured by 2218 // reference except if it is a pointer that is dereferenced somehow. 2219 IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection); 2220 } else { 2221 // By default, all the data that has a scalar type is mapped by copy 2222 // (except for reduction variables). 2223 // Defaultmap scalar is mutual exclusive to defaultmap pointer 2224 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() && 2225 !Ty->isAnyPointerType()) || 2226 !Ty->isScalarType() || 2227 DSAStack->isDefaultmapCapturedByRef( 2228 Level, getVariableCategoryFromDecl(getLangOpts(), D)) || 2229 DSAStack->hasExplicitDSA( 2230 D, 2231 [](OpenMPClauseKind K, bool AppliedToPointee) { 2232 return K == OMPC_reduction && !AppliedToPointee; 2233 }, 2234 Level); 2235 } 2236 } 2237 2238 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) { 2239 IsByRef = 2240 ((IsVariableUsedInMapClause && 2241 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) == 2242 OMPD_target) || 2243 !(DSAStack->hasExplicitDSA( 2244 D, 2245 [](OpenMPClauseKind K, bool AppliedToPointee) -> bool { 2246 return K == OMPC_firstprivate || 2247 (K == OMPC_reduction && AppliedToPointee); 2248 }, 2249 Level, /*NotLastprivate=*/true) || 2250 DSAStack->isUsesAllocatorsDecl(Level, D))) && 2251 // If the variable is artificial and must be captured by value - try to 2252 // capture by value. 2253 !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() && 2254 !cast<OMPCapturedExprDecl>(D)->getInit()->isGLValue()) && 2255 // If the variable is implicitly firstprivate and scalar - capture by 2256 // copy 2257 !((DSAStack->getDefaultDSA() == DSA_firstprivate || 2258 DSAStack->getDefaultDSA() == DSA_private) && 2259 !DSAStack->hasExplicitDSA( 2260 D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; }, 2261 Level) && 2262 !DSAStack->isLoopControlVariable(D, Level).first); 2263 } 2264 2265 // When passing data by copy, we need to make sure it fits the uintptr size 2266 // and alignment, because the runtime library only deals with uintptr types. 2267 // If it does not fit the uintptr size, we need to pass the data by reference 2268 // instead. 2269 if (!IsByRef && (Ctx.getTypeSizeInChars(Ty) > 2270 Ctx.getTypeSizeInChars(Ctx.getUIntPtrType()) || 2271 Ctx.getAlignOfGlobalVarInChars(Ty, dyn_cast<VarDecl>(D)) > 2272 Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) { 2273 IsByRef = true; 2274 } 2275 2276 return IsByRef; 2277 } 2278 2279 unsigned SemaOpenMP::getOpenMPNestingLevel() const { 2280 assert(getLangOpts().OpenMP); 2281 return DSAStack->getNestingLevel(); 2282 } 2283 2284 bool SemaOpenMP::isInOpenMPTaskUntiedContext() const { 2285 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) && 2286 DSAStack->isUntiedRegion(); 2287 } 2288 2289 bool SemaOpenMP::isInOpenMPTargetExecutionDirective() const { 2290 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) && 2291 !DSAStack->isClauseParsingMode()) || 2292 DSAStack->hasDirective( 2293 [](OpenMPDirectiveKind K, const DeclarationNameInfo &, 2294 SourceLocation) -> bool { 2295 return isOpenMPTargetExecutionDirective(K); 2296 }, 2297 false); 2298 } 2299 2300 bool SemaOpenMP::isOpenMPRebuildMemberExpr(ValueDecl *D) { 2301 // Only rebuild for Field. 2302 if (!dyn_cast<FieldDecl>(D)) 2303 return false; 2304 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA( 2305 D, 2306 [](OpenMPClauseKind C, bool AppliedToPointee, 2307 DefaultDataSharingAttributes DefaultAttr) { 2308 return isOpenMPPrivate(C) && !AppliedToPointee && 2309 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private); 2310 }, 2311 [](OpenMPDirectiveKind) { return true; }, 2312 DSAStack->isClauseParsingMode()); 2313 if (DVarPrivate.CKind != OMPC_unknown) 2314 return true; 2315 return false; 2316 } 2317 2318 static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id, 2319 Expr *CaptureExpr, bool WithInit, 2320 DeclContext *CurContext, 2321 bool AsExpression); 2322 2323 VarDecl *SemaOpenMP::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo, 2324 unsigned StopAt) { 2325 assert(getLangOpts().OpenMP && "OpenMP is not allowed"); 2326 D = getCanonicalDecl(D); 2327 2328 auto *VD = dyn_cast<VarDecl>(D); 2329 // Do not capture constexpr variables. 2330 if (VD && VD->isConstexpr()) 2331 return nullptr; 2332 2333 // If we want to determine whether the variable should be captured from the 2334 // perspective of the current capturing scope, and we've already left all the 2335 // capturing scopes of the top directive on the stack, check from the 2336 // perspective of its parent directive (if any) instead. 2337 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII( 2338 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete()); 2339 2340 // If we are attempting to capture a global variable in a directive with 2341 // 'target' we return true so that this global is also mapped to the device. 2342 // 2343 if (VD && !VD->hasLocalStorage() && 2344 (SemaRef.getCurCapturedRegion() || SemaRef.getCurBlock() || 2345 SemaRef.getCurLambda())) { 2346 if (isInOpenMPTargetExecutionDirective()) { 2347 DSAStackTy::DSAVarData DVarTop = 2348 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode()); 2349 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr) 2350 return VD; 2351 // If the declaration is enclosed in a 'declare target' directive, 2352 // then it should not be captured. 2353 // 2354 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) 2355 return nullptr; 2356 CapturedRegionScopeInfo *CSI = nullptr; 2357 for (FunctionScopeInfo *FSI : llvm::drop_begin( 2358 llvm::reverse(SemaRef.FunctionScopes), 2359 CheckScopeInfo ? (SemaRef.FunctionScopes.size() - (StopAt + 1)) 2360 : 0)) { 2361 if (!isa<CapturingScopeInfo>(FSI)) 2362 return nullptr; 2363 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI)) 2364 if (RSI->CapRegionKind == CR_OpenMP) { 2365 CSI = RSI; 2366 break; 2367 } 2368 } 2369 assert(CSI && "Failed to find CapturedRegionScopeInfo"); 2370 SmallVector<OpenMPDirectiveKind, 4> Regions; 2371 getOpenMPCaptureRegions(Regions, 2372 DSAStack->getDirective(CSI->OpenMPLevel)); 2373 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task) 2374 return VD; 2375 } 2376 if (isInOpenMPDeclareTargetContext()) { 2377 // Try to mark variable as declare target if it is used in capturing 2378 // regions. 2379 if (getLangOpts().OpenMP <= 45 && 2380 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) 2381 checkDeclIsAllowedInOpenMPTarget(nullptr, VD); 2382 return nullptr; 2383 } 2384 } 2385 2386 if (CheckScopeInfo) { 2387 bool OpenMPFound = false; 2388 for (unsigned I = StopAt + 1; I > 0; --I) { 2389 FunctionScopeInfo *FSI = SemaRef.FunctionScopes[I - 1]; 2390 if (!isa<CapturingScopeInfo>(FSI)) 2391 return nullptr; 2392 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI)) 2393 if (RSI->CapRegionKind == CR_OpenMP) { 2394 OpenMPFound = true; 2395 break; 2396 } 2397 } 2398 if (!OpenMPFound) 2399 return nullptr; 2400 } 2401 2402 if (DSAStack->getCurrentDirective() != OMPD_unknown && 2403 (!DSAStack->isClauseParsingMode() || 2404 DSAStack->getParentDirective() != OMPD_unknown)) { 2405 auto &&Info = DSAStack->isLoopControlVariable(D); 2406 if (Info.first || 2407 (VD && VD->hasLocalStorage() && 2408 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) || 2409 (VD && DSAStack->isForceVarCapturing())) 2410 return VD ? VD : Info.second; 2411 DSAStackTy::DSAVarData DVarTop = 2412 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode()); 2413 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) && 2414 (!VD || VD->hasLocalStorage() || !DVarTop.AppliedToPointee)) 2415 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl()); 2416 // Threadprivate variables must not be captured. 2417 if (isOpenMPThreadPrivate(DVarTop.CKind)) 2418 return nullptr; 2419 // The variable is not private or it is the variable in the directive with 2420 // default(none) clause and not used in any clause. 2421 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA( 2422 D, 2423 [](OpenMPClauseKind C, bool AppliedToPointee, bool) { 2424 return isOpenMPPrivate(C) && !AppliedToPointee; 2425 }, 2426 [](OpenMPDirectiveKind) { return true; }, 2427 DSAStack->isClauseParsingMode()); 2428 // Global shared must not be captured. 2429 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown && 2430 ((DSAStack->getDefaultDSA() != DSA_none && 2431 DSAStack->getDefaultDSA() != DSA_private && 2432 DSAStack->getDefaultDSA() != DSA_firstprivate) || 2433 DVarTop.CKind == OMPC_shared)) 2434 return nullptr; 2435 auto *FD = dyn_cast<FieldDecl>(D); 2436 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD && 2437 !DVarPrivate.PrivateCopy) { 2438 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA( 2439 D, 2440 [](OpenMPClauseKind C, bool AppliedToPointee, 2441 DefaultDataSharingAttributes DefaultAttr) { 2442 return isOpenMPPrivate(C) && !AppliedToPointee && 2443 (DefaultAttr == DSA_firstprivate || 2444 DefaultAttr == DSA_private); 2445 }, 2446 [](OpenMPDirectiveKind) { return true; }, 2447 DSAStack->isClauseParsingMode()); 2448 if (DVarPrivate.CKind == OMPC_unknown) 2449 return nullptr; 2450 2451 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD); 2452 if (VD) 2453 return VD; 2454 if (SemaRef.getCurrentThisType().isNull()) 2455 return nullptr; 2456 Expr *ThisExpr = SemaRef.BuildCXXThisExpr(SourceLocation(), 2457 SemaRef.getCurrentThisType(), 2458 /*IsImplicit=*/true); 2459 const CXXScopeSpec CS = CXXScopeSpec(); 2460 Expr *ME = SemaRef.BuildMemberExpr( 2461 ThisExpr, /*IsArrow=*/true, SourceLocation(), 2462 NestedNameSpecifierLoc(), SourceLocation(), FD, 2463 DeclAccessPair::make(FD, FD->getAccess()), 2464 /*HadMultipleCandidates=*/false, DeclarationNameInfo(), FD->getType(), 2465 VK_LValue, OK_Ordinary); 2466 OMPCapturedExprDecl *CD = buildCaptureDecl( 2467 SemaRef, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private, 2468 SemaRef.CurContext->getParent(), /*AsExpression=*/false); 2469 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr( 2470 SemaRef, CD, CD->getType().getNonReferenceType(), SourceLocation()); 2471 VD = cast<VarDecl>(VDPrivateRefExpr->getDecl()); 2472 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD); 2473 return VD; 2474 } 2475 if (DVarPrivate.CKind != OMPC_unknown || 2476 (VD && (DSAStack->getDefaultDSA() == DSA_none || 2477 DSAStack->getDefaultDSA() == DSA_private || 2478 DSAStack->getDefaultDSA() == DSA_firstprivate))) 2479 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl()); 2480 } 2481 return nullptr; 2482 } 2483 2484 void SemaOpenMP::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex, 2485 unsigned Level) const { 2486 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level)); 2487 } 2488 2489 void SemaOpenMP::startOpenMPLoop() { 2490 assert(getLangOpts().OpenMP && "OpenMP must be enabled."); 2491 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) 2492 DSAStack->loopInit(); 2493 } 2494 2495 void SemaOpenMP::startOpenMPCXXRangeFor() { 2496 assert(getLangOpts().OpenMP && "OpenMP must be enabled."); 2497 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) { 2498 DSAStack->resetPossibleLoopCounter(); 2499 DSAStack->loopStart(); 2500 } 2501 } 2502 2503 OpenMPClauseKind SemaOpenMP::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, 2504 unsigned CapLevel) const { 2505 assert(getLangOpts().OpenMP && "OpenMP is not allowed"); 2506 if (DSAStack->getCurrentDirective() != OMPD_unknown && 2507 (!DSAStack->isClauseParsingMode() || 2508 DSAStack->getParentDirective() != OMPD_unknown)) { 2509 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA( 2510 D, 2511 [](OpenMPClauseKind C, bool AppliedToPointee, 2512 DefaultDataSharingAttributes DefaultAttr) { 2513 return isOpenMPPrivate(C) && !AppliedToPointee && 2514 DefaultAttr == DSA_private; 2515 }, 2516 [](OpenMPDirectiveKind) { return true; }, 2517 DSAStack->isClauseParsingMode()); 2518 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) && 2519 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) && 2520 !DSAStack->isLoopControlVariable(D).first) 2521 return OMPC_private; 2522 } 2523 if (DSAStack->hasExplicitDirective(isOpenMPTaskingDirective, Level)) { 2524 bool IsTriviallyCopyable = 2525 D->getType().getNonReferenceType().isTriviallyCopyableType( 2526 getASTContext()) && 2527 !D->getType() 2528 .getNonReferenceType() 2529 .getCanonicalType() 2530 ->getAsCXXRecordDecl(); 2531 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level); 2532 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 2533 getOpenMPCaptureRegions(CaptureRegions, DKind); 2534 if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) && 2535 (IsTriviallyCopyable || 2536 !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) { 2537 if (DSAStack->hasExplicitDSA( 2538 D, 2539 [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; }, 2540 Level, /*NotLastprivate=*/true)) 2541 return OMPC_firstprivate; 2542 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level); 2543 if (DVar.CKind != OMPC_shared && 2544 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) { 2545 DSAStack->addImplicitTaskFirstprivate(Level, D); 2546 return OMPC_firstprivate; 2547 } 2548 } 2549 } 2550 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) && 2551 !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) { 2552 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) { 2553 DSAStack->resetPossibleLoopCounter(D); 2554 DSAStack->loopStart(); 2555 return OMPC_private; 2556 } 2557 if ((DSAStack->getPossiblyLoopCounter() == D->getCanonicalDecl() || 2558 DSAStack->isLoopControlVariable(D).first) && 2559 !DSAStack->hasExplicitDSA( 2560 D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; }, 2561 Level) && 2562 !isOpenMPSimdDirective(DSAStack->getCurrentDirective())) 2563 return OMPC_private; 2564 } 2565 if (const auto *VD = dyn_cast<VarDecl>(D)) { 2566 if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) && 2567 DSAStack->isForceVarCapturing() && 2568 !DSAStack->hasExplicitDSA( 2569 D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; }, 2570 Level)) 2571 return OMPC_private; 2572 } 2573 // User-defined allocators are private since they must be defined in the 2574 // context of target region. 2575 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) && 2576 DSAStack->isUsesAllocatorsDecl(Level, D).value_or( 2577 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) == 2578 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator) 2579 return OMPC_private; 2580 return (DSAStack->hasExplicitDSA( 2581 D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; }, 2582 Level) || 2583 (DSAStack->isClauseParsingMode() && 2584 DSAStack->getClauseParsingMode() == OMPC_private) || 2585 // Consider taskgroup reduction descriptor variable a private 2586 // to avoid possible capture in the region. 2587 (DSAStack->hasExplicitDirective( 2588 [](OpenMPDirectiveKind K) { 2589 return K == OMPD_taskgroup || 2590 ((isOpenMPParallelDirective(K) || 2591 isOpenMPWorksharingDirective(K)) && 2592 !isOpenMPSimdDirective(K)); 2593 }, 2594 Level) && 2595 DSAStack->isTaskgroupReductionRef(D, Level))) 2596 ? OMPC_private 2597 : OMPC_unknown; 2598 } 2599 2600 void SemaOpenMP::setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D, 2601 unsigned Level) { 2602 assert(getLangOpts().OpenMP && "OpenMP is not allowed"); 2603 D = getCanonicalDecl(D); 2604 OpenMPClauseKind OMPC = OMPC_unknown; 2605 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) { 2606 const unsigned NewLevel = I - 1; 2607 if (DSAStack->hasExplicitDSA( 2608 D, 2609 [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) { 2610 if (isOpenMPPrivate(K) && !AppliedToPointee) { 2611 OMPC = K; 2612 return true; 2613 } 2614 return false; 2615 }, 2616 NewLevel)) 2617 break; 2618 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel( 2619 D, NewLevel, 2620 [](OMPClauseMappableExprCommon::MappableExprComponentListRef, 2621 OpenMPClauseKind) { return true; })) { 2622 OMPC = OMPC_map; 2623 break; 2624 } 2625 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, 2626 NewLevel)) { 2627 OMPC = OMPC_map; 2628 if (DSAStack->mustBeFirstprivateAtLevel( 2629 NewLevel, getVariableCategoryFromDecl(getLangOpts(), D))) 2630 OMPC = OMPC_firstprivate; 2631 break; 2632 } 2633 } 2634 if (OMPC != OMPC_unknown) 2635 FD->addAttr( 2636 OMPCaptureKindAttr::CreateImplicit(getASTContext(), unsigned(OMPC))); 2637 } 2638 2639 bool SemaOpenMP::isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level, 2640 unsigned CaptureLevel) const { 2641 assert(getLangOpts().OpenMP && "OpenMP is not allowed"); 2642 // Return true if the current level is no longer enclosed in a target region. 2643 2644 SmallVector<OpenMPDirectiveKind, 4> Regions; 2645 getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level)); 2646 const auto *VD = dyn_cast<VarDecl>(D); 2647 return VD && !VD->hasLocalStorage() && 2648 DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, 2649 Level) && 2650 Regions[CaptureLevel] != OMPD_task; 2651 } 2652 2653 bool SemaOpenMP::isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level, 2654 unsigned CaptureLevel) const { 2655 assert(getLangOpts().OpenMP && "OpenMP is not allowed"); 2656 // Return true if the current level is no longer enclosed in a target region. 2657 2658 if (const auto *VD = dyn_cast<VarDecl>(D)) { 2659 if (!VD->hasLocalStorage()) { 2660 if (isInOpenMPTargetExecutionDirective()) 2661 return true; 2662 DSAStackTy::DSAVarData TopDVar = 2663 DSAStack->getTopDSA(D, /*FromParent=*/false); 2664 unsigned NumLevels = 2665 getOpenMPCaptureLevels(DSAStack->getDirective(Level)); 2666 if (Level == 0) 2667 // non-file scope static variable with default(firstprivate) 2668 // should be global captured. 2669 return (NumLevels == CaptureLevel + 1 && 2670 (TopDVar.CKind != OMPC_shared || 2671 DSAStack->getDefaultDSA() == DSA_firstprivate)); 2672 do { 2673 --Level; 2674 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level); 2675 if (DVar.CKind != OMPC_shared) 2676 return true; 2677 } while (Level > 0); 2678 } 2679 } 2680 return true; 2681 } 2682 2683 void SemaOpenMP::DestroyDataSharingAttributesStack() { delete DSAStack; } 2684 2685 void SemaOpenMP::ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, 2686 OMPTraitInfo &TI) { 2687 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI)); 2688 } 2689 2690 void SemaOpenMP::ActOnOpenMPEndDeclareVariant() { 2691 assert(isInOpenMPDeclareVariantScope() && 2692 "Not in OpenMP declare variant scope!"); 2693 2694 OMPDeclareVariantScopes.pop_back(); 2695 } 2696 2697 void SemaOpenMP::finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, 2698 const FunctionDecl *Callee, 2699 SourceLocation Loc) { 2700 assert(getLangOpts().OpenMP && "Expected OpenMP compilation mode."); 2701 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 2702 OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl()); 2703 // Ignore host functions during device analysis. 2704 if (getLangOpts().OpenMPIsTargetDevice && 2705 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)) 2706 return; 2707 // Ignore nohost functions during host analysis. 2708 if (!getLangOpts().OpenMPIsTargetDevice && DevTy && 2709 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) 2710 return; 2711 const FunctionDecl *FD = Callee->getMostRecentDecl(); 2712 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD); 2713 if (getLangOpts().OpenMPIsTargetDevice && DevTy && 2714 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) { 2715 // Diagnose host function called during device codegen. 2716 StringRef HostDevTy = 2717 getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host); 2718 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0; 2719 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD), 2720 diag::note_omp_marked_device_type_here) 2721 << HostDevTy; 2722 return; 2723 } 2724 if (!getLangOpts().OpenMPIsTargetDevice && 2725 !getLangOpts().OpenMPOffloadMandatory && DevTy && 2726 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) { 2727 // In OpenMP 5.2 or later, if the function has a host variant then allow 2728 // that to be called instead 2729 auto &&HasHostAttr = [](const FunctionDecl *Callee) { 2730 for (OMPDeclareVariantAttr *A : 2731 Callee->specific_attrs<OMPDeclareVariantAttr>()) { 2732 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef()); 2733 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl()); 2734 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 2735 OMPDeclareTargetDeclAttr::getDeviceType( 2736 VariantFD->getMostRecentDecl()); 2737 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host) 2738 return true; 2739 } 2740 return false; 2741 }; 2742 if (getLangOpts().OpenMP >= 52 && 2743 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee)) 2744 return; 2745 // Diagnose nohost function called during host codegen. 2746 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName( 2747 OMPC_device_type, OMPC_DEVICE_TYPE_nohost); 2748 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1; 2749 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD), 2750 diag::note_omp_marked_device_type_here) 2751 << NoHostDevTy; 2752 } 2753 } 2754 2755 void SemaOpenMP::StartOpenMPDSABlock(OpenMPDirectiveKind DKind, 2756 const DeclarationNameInfo &DirName, 2757 Scope *CurScope, SourceLocation Loc) { 2758 DSAStack->push(DKind, DirName, CurScope, Loc); 2759 SemaRef.PushExpressionEvaluationContext( 2760 Sema::ExpressionEvaluationContext::PotentiallyEvaluated); 2761 } 2762 2763 void SemaOpenMP::StartOpenMPClause(OpenMPClauseKind K) { 2764 DSAStack->setClauseParsingMode(K); 2765 } 2766 2767 void SemaOpenMP::EndOpenMPClause() { 2768 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown); 2769 SemaRef.CleanupVarDeclMarking(); 2770 } 2771 2772 static std::pair<ValueDecl *, bool> 2773 getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc, 2774 SourceRange &ERange, bool AllowArraySection = false, 2775 StringRef DiagType = ""); 2776 2777 /// Check consistency of the reduction clauses. 2778 static void checkReductionClauses(Sema &S, DSAStackTy *Stack, 2779 ArrayRef<OMPClause *> Clauses) { 2780 bool InscanFound = false; 2781 SourceLocation InscanLoc; 2782 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions. 2783 // A reduction clause without the inscan reduction-modifier may not appear on 2784 // a construct on which a reduction clause with the inscan reduction-modifier 2785 // appears. 2786 for (OMPClause *C : Clauses) { 2787 if (C->getClauseKind() != OMPC_reduction) 2788 continue; 2789 auto *RC = cast<OMPReductionClause>(C); 2790 if (RC->getModifier() == OMPC_REDUCTION_inscan) { 2791 InscanFound = true; 2792 InscanLoc = RC->getModifierLoc(); 2793 continue; 2794 } 2795 if (RC->getModifier() == OMPC_REDUCTION_task) { 2796 // OpenMP 5.0, 2.19.5.4 reduction Clause. 2797 // A reduction clause with the task reduction-modifier may only appear on 2798 // a parallel construct, a worksharing construct or a combined or 2799 // composite construct for which any of the aforementioned constructs is a 2800 // constituent construct and simd or loop are not constituent constructs. 2801 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective(); 2802 if (!(isOpenMPParallelDirective(CurDir) || 2803 isOpenMPWorksharingDirective(CurDir)) || 2804 isOpenMPSimdDirective(CurDir)) 2805 S.Diag(RC->getModifierLoc(), 2806 diag::err_omp_reduction_task_not_parallel_or_worksharing); 2807 continue; 2808 } 2809 } 2810 if (InscanFound) { 2811 for (OMPClause *C : Clauses) { 2812 if (C->getClauseKind() != OMPC_reduction) 2813 continue; 2814 auto *RC = cast<OMPReductionClause>(C); 2815 if (RC->getModifier() != OMPC_REDUCTION_inscan) { 2816 S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown 2817 ? RC->getBeginLoc() 2818 : RC->getModifierLoc(), 2819 diag::err_omp_inscan_reduction_expected); 2820 S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction); 2821 continue; 2822 } 2823 for (Expr *Ref : RC->varlist()) { 2824 assert(Ref && "NULL expr in OpenMP nontemporal clause."); 2825 SourceLocation ELoc; 2826 SourceRange ERange; 2827 Expr *SimpleRefExpr = Ref; 2828 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange, 2829 /*AllowArraySection=*/true); 2830 ValueDecl *D = Res.first; 2831 if (!D) 2832 continue; 2833 if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) { 2834 S.Diag(Ref->getExprLoc(), 2835 diag::err_omp_reduction_not_inclusive_exclusive) 2836 << Ref->getSourceRange(); 2837 } 2838 } 2839 } 2840 } 2841 } 2842 2843 static void checkAllocateClauses(Sema &S, DSAStackTy *Stack, 2844 ArrayRef<OMPClause *> Clauses); 2845 static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr, 2846 bool WithInit); 2847 2848 static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack, 2849 const ValueDecl *D, 2850 const DSAStackTy::DSAVarData &DVar, 2851 bool IsLoopIterVar = false); 2852 2853 void SemaOpenMP::EndOpenMPDSABlock(Stmt *CurDirective) { 2854 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1] 2855 // A variable of class type (or array thereof) that appears in a lastprivate 2856 // clause requires an accessible, unambiguous default constructor for the 2857 // class type, unless the list item is also specified in a firstprivate 2858 // clause. 2859 2860 auto FinalizeLastprivate = [&](OMPLastprivateClause *Clause) { 2861 SmallVector<Expr *, 8> PrivateCopies; 2862 for (Expr *DE : Clause->varlist()) { 2863 if (DE->isValueDependent() || DE->isTypeDependent()) { 2864 PrivateCopies.push_back(nullptr); 2865 continue; 2866 } 2867 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens()); 2868 auto *VD = cast<VarDecl>(DRE->getDecl()); 2869 QualType Type = VD->getType().getNonReferenceType(); 2870 const DSAStackTy::DSAVarData DVar = 2871 DSAStack->getTopDSA(VD, /*FromParent=*/false); 2872 if (DVar.CKind != OMPC_lastprivate) { 2873 // The variable is also a firstprivate, so initialization sequence 2874 // for private copy is generated already. 2875 PrivateCopies.push_back(nullptr); 2876 continue; 2877 } 2878 // Generate helper private variable and initialize it with the 2879 // default value. The address of the original variable is replaced 2880 // by the address of the new private variable in CodeGen. This new 2881 // variable is not added to IdResolver, so the code in the OpenMP 2882 // region uses original variable for proper diagnostics. 2883 VarDecl *VDPrivate = buildVarDecl( 2884 SemaRef, DE->getExprLoc(), Type.getUnqualifiedType(), VD->getName(), 2885 VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE); 2886 SemaRef.ActOnUninitializedDecl(VDPrivate); 2887 if (VDPrivate->isInvalidDecl()) { 2888 PrivateCopies.push_back(nullptr); 2889 continue; 2890 } 2891 PrivateCopies.push_back(buildDeclRefExpr( 2892 SemaRef, VDPrivate, DE->getType(), DE->getExprLoc())); 2893 } 2894 Clause->setPrivateCopies(PrivateCopies); 2895 }; 2896 2897 auto FinalizeNontemporal = [&](OMPNontemporalClause *Clause) { 2898 // Finalize nontemporal clause by handling private copies, if any. 2899 SmallVector<Expr *, 8> PrivateRefs; 2900 for (Expr *RefExpr : Clause->varlist()) { 2901 assert(RefExpr && "NULL expr in OpenMP nontemporal clause."); 2902 SourceLocation ELoc; 2903 SourceRange ERange; 2904 Expr *SimpleRefExpr = RefExpr; 2905 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); 2906 if (Res.second) 2907 // It will be analyzed later. 2908 PrivateRefs.push_back(RefExpr); 2909 ValueDecl *D = Res.first; 2910 if (!D) 2911 continue; 2912 2913 const DSAStackTy::DSAVarData DVar = 2914 DSAStack->getTopDSA(D, /*FromParent=*/false); 2915 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy 2916 : SimpleRefExpr); 2917 } 2918 Clause->setPrivateRefs(PrivateRefs); 2919 }; 2920 2921 auto FinalizeAllocators = [&](OMPUsesAllocatorsClause *Clause) { 2922 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) { 2923 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I); 2924 auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts()); 2925 if (!DRE) 2926 continue; 2927 ValueDecl *VD = DRE->getDecl(); 2928 if (!VD || !isa<VarDecl>(VD)) 2929 continue; 2930 DSAStackTy::DSAVarData DVar = 2931 DSAStack->getTopDSA(VD, /*FromParent=*/false); 2932 // OpenMP [2.12.5, target Construct] 2933 // Memory allocators that appear in a uses_allocators clause cannot 2934 // appear in other data-sharing attribute clauses or data-mapping 2935 // attribute clauses in the same construct. 2936 Expr *MapExpr = nullptr; 2937 if (DVar.RefExpr || 2938 DSAStack->checkMappableExprComponentListsForDecl( 2939 VD, /*CurrentRegionOnly=*/true, 2940 [VD, &MapExpr]( 2941 OMPClauseMappableExprCommon::MappableExprComponentListRef 2942 MapExprComponents, 2943 OpenMPClauseKind C) { 2944 auto MI = MapExprComponents.rbegin(); 2945 auto ME = MapExprComponents.rend(); 2946 if (MI != ME && 2947 MI->getAssociatedDeclaration()->getCanonicalDecl() == 2948 VD->getCanonicalDecl()) { 2949 MapExpr = MI->getAssociatedExpression(); 2950 return true; 2951 } 2952 return false; 2953 })) { 2954 Diag(D.Allocator->getExprLoc(), diag::err_omp_allocator_used_in_clauses) 2955 << D.Allocator->getSourceRange(); 2956 if (DVar.RefExpr) 2957 reportOriginalDsa(SemaRef, DSAStack, VD, DVar); 2958 else 2959 Diag(MapExpr->getExprLoc(), diag::note_used_here) 2960 << MapExpr->getSourceRange(); 2961 } 2962 } 2963 }; 2964 2965 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) { 2966 for (OMPClause *C : D->clauses()) { 2967 if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) { 2968 FinalizeLastprivate(Clause); 2969 } else if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) { 2970 FinalizeNontemporal(Clause); 2971 } else if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) { 2972 FinalizeAllocators(Clause); 2973 } 2974 } 2975 // Check allocate clauses. 2976 if (!SemaRef.CurContext->isDependentContext()) 2977 checkAllocateClauses(SemaRef, DSAStack, D->clauses()); 2978 checkReductionClauses(SemaRef, DSAStack, D->clauses()); 2979 } 2980 2981 DSAStack->pop(); 2982 SemaRef.DiscardCleanupsInEvaluationContext(); 2983 SemaRef.PopExpressionEvaluationContext(); 2984 } 2985 2986 static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, 2987 Expr *NumIterations, Sema &SemaRef, 2988 Scope *S, DSAStackTy *Stack); 2989 2990 static bool finishLinearClauses(Sema &SemaRef, ArrayRef<OMPClause *> Clauses, 2991 OMPLoopBasedDirective::HelperExprs &B, 2992 DSAStackTy *Stack) { 2993 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 2994 "loop exprs were not built"); 2995 2996 if (SemaRef.CurContext->isDependentContext()) 2997 return false; 2998 2999 // Finalize the clauses that need pre-built expressions for CodeGen. 3000 for (OMPClause *C : Clauses) { 3001 auto *LC = dyn_cast<OMPLinearClause>(C); 3002 if (!LC) 3003 continue; 3004 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef), 3005 B.NumIterations, SemaRef, 3006 SemaRef.getCurScope(), Stack)) 3007 return true; 3008 } 3009 3010 return false; 3011 } 3012 3013 namespace { 3014 3015 class VarDeclFilterCCC final : public CorrectionCandidateCallback { 3016 private: 3017 Sema &SemaRef; 3018 3019 public: 3020 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {} 3021 bool ValidateCandidate(const TypoCorrection &Candidate) override { 3022 NamedDecl *ND = Candidate.getCorrectionDecl(); 3023 if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) { 3024 return VD->hasGlobalStorage() && 3025 SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(), 3026 SemaRef.getCurScope()); 3027 } 3028 return false; 3029 } 3030 3031 std::unique_ptr<CorrectionCandidateCallback> clone() override { 3032 return std::make_unique<VarDeclFilterCCC>(*this); 3033 } 3034 }; 3035 3036 class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback { 3037 private: 3038 Sema &SemaRef; 3039 3040 public: 3041 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {} 3042 bool ValidateCandidate(const TypoCorrection &Candidate) override { 3043 NamedDecl *ND = Candidate.getCorrectionDecl(); 3044 if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) || 3045 isa<FunctionDecl>(ND))) { 3046 return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(), 3047 SemaRef.getCurScope()); 3048 } 3049 return false; 3050 } 3051 3052 std::unique_ptr<CorrectionCandidateCallback> clone() override { 3053 return std::make_unique<VarOrFuncDeclFilterCCC>(*this); 3054 } 3055 }; 3056 3057 } // namespace 3058 3059 ExprResult SemaOpenMP::ActOnOpenMPIdExpression(Scope *CurScope, 3060 CXXScopeSpec &ScopeSpec, 3061 const DeclarationNameInfo &Id, 3062 OpenMPDirectiveKind Kind) { 3063 ASTContext &Context = getASTContext(); 3064 LookupResult Lookup(SemaRef, Id, Sema::LookupOrdinaryName); 3065 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec, 3066 /*ObjectType=*/QualType(), 3067 /*AllowBuiltinCreation=*/true); 3068 3069 if (Lookup.isAmbiguous()) 3070 return ExprError(); 3071 3072 VarDecl *VD; 3073 if (!Lookup.isSingleResult()) { 3074 VarDeclFilterCCC CCC(SemaRef); 3075 if (TypoCorrection Corrected = 3076 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr, 3077 CCC, Sema::CTK_ErrorRecovery)) { 3078 SemaRef.diagnoseTypo( 3079 Corrected, 3080 SemaRef.PDiag(Lookup.empty() ? diag::err_undeclared_var_use_suggest 3081 : diag::err_omp_expected_var_arg_suggest) 3082 << Id.getName()); 3083 VD = Corrected.getCorrectionDeclAs<VarDecl>(); 3084 } else { 3085 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use 3086 : diag::err_omp_expected_var_arg) 3087 << Id.getName(); 3088 return ExprError(); 3089 } 3090 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) { 3091 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName(); 3092 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at); 3093 return ExprError(); 3094 } 3095 Lookup.suppressDiagnostics(); 3096 3097 // OpenMP [2.9.2, Syntax, C/C++] 3098 // Variables must be file-scope, namespace-scope, or static block-scope. 3099 if (Kind == OMPD_threadprivate && !VD->hasGlobalStorage()) { 3100 Diag(Id.getLoc(), diag::err_omp_global_var_arg) 3101 << getOpenMPDirectiveName(Kind) << !VD->isStaticLocal(); 3102 bool IsDecl = 3103 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; 3104 Diag(VD->getLocation(), 3105 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 3106 << VD; 3107 return ExprError(); 3108 } 3109 3110 VarDecl *CanonicalVD = VD->getCanonicalDecl(); 3111 NamedDecl *ND = CanonicalVD; 3112 // OpenMP [2.9.2, Restrictions, C/C++, p.2] 3113 // A threadprivate directive for file-scope variables must appear outside 3114 // any definition or declaration. 3115 if (CanonicalVD->getDeclContext()->isTranslationUnit() && 3116 !SemaRef.getCurLexicalContext()->isTranslationUnit()) { 3117 Diag(Id.getLoc(), diag::err_omp_var_scope) 3118 << getOpenMPDirectiveName(Kind) << VD; 3119 bool IsDecl = 3120 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; 3121 Diag(VD->getLocation(), 3122 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 3123 << VD; 3124 return ExprError(); 3125 } 3126 // OpenMP [2.9.2, Restrictions, C/C++, p.3] 3127 // A threadprivate directive for static class member variables must appear 3128 // in the class definition, in the same scope in which the member 3129 // variables are declared. 3130 if (CanonicalVD->isStaticDataMember() && 3131 !CanonicalVD->getDeclContext()->Equals(SemaRef.getCurLexicalContext())) { 3132 Diag(Id.getLoc(), diag::err_omp_var_scope) 3133 << getOpenMPDirectiveName(Kind) << VD; 3134 bool IsDecl = 3135 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; 3136 Diag(VD->getLocation(), 3137 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 3138 << VD; 3139 return ExprError(); 3140 } 3141 // OpenMP [2.9.2, Restrictions, C/C++, p.4] 3142 // A threadprivate directive for namespace-scope variables must appear 3143 // outside any definition or declaration other than the namespace 3144 // definition itself. 3145 if (CanonicalVD->getDeclContext()->isNamespace() && 3146 (!SemaRef.getCurLexicalContext()->isFileContext() || 3147 !SemaRef.getCurLexicalContext()->Encloses( 3148 CanonicalVD->getDeclContext()))) { 3149 Diag(Id.getLoc(), diag::err_omp_var_scope) 3150 << getOpenMPDirectiveName(Kind) << VD; 3151 bool IsDecl = 3152 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; 3153 Diag(VD->getLocation(), 3154 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 3155 << VD; 3156 return ExprError(); 3157 } 3158 // OpenMP [2.9.2, Restrictions, C/C++, p.6] 3159 // A threadprivate directive for static block-scope variables must appear 3160 // in the scope of the variable and not in a nested scope. 3161 if (CanonicalVD->isLocalVarDecl() && CurScope && 3162 !SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(), CurScope)) { 3163 Diag(Id.getLoc(), diag::err_omp_var_scope) 3164 << getOpenMPDirectiveName(Kind) << VD; 3165 bool IsDecl = 3166 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; 3167 Diag(VD->getLocation(), 3168 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 3169 << VD; 3170 return ExprError(); 3171 } 3172 3173 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6] 3174 // A threadprivate directive must lexically precede all references to any 3175 // of the variables in its list. 3176 if (Kind == OMPD_threadprivate && VD->isUsed() && 3177 !DSAStack->isThreadPrivate(VD)) { 3178 Diag(Id.getLoc(), diag::err_omp_var_used) 3179 << getOpenMPDirectiveName(Kind) << VD; 3180 return ExprError(); 3181 } 3182 3183 QualType ExprType = VD->getType().getNonReferenceType(); 3184 return DeclRefExpr::Create(Context, NestedNameSpecifierLoc(), 3185 SourceLocation(), VD, 3186 /*RefersToEnclosingVariableOrCapture=*/false, 3187 Id.getLoc(), ExprType, VK_LValue); 3188 } 3189 3190 SemaOpenMP::DeclGroupPtrTy 3191 SemaOpenMP::ActOnOpenMPThreadprivateDirective(SourceLocation Loc, 3192 ArrayRef<Expr *> VarList) { 3193 if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) { 3194 SemaRef.CurContext->addDecl(D); 3195 return DeclGroupPtrTy::make(DeclGroupRef(D)); 3196 } 3197 return nullptr; 3198 } 3199 3200 namespace { 3201 class LocalVarRefChecker final 3202 : public ConstStmtVisitor<LocalVarRefChecker, bool> { 3203 Sema &SemaRef; 3204 3205 public: 3206 bool VisitDeclRefExpr(const DeclRefExpr *E) { 3207 if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) { 3208 if (VD->hasLocalStorage()) { 3209 SemaRef.Diag(E->getBeginLoc(), 3210 diag::err_omp_local_var_in_threadprivate_init) 3211 << E->getSourceRange(); 3212 SemaRef.Diag(VD->getLocation(), diag::note_defined_here) 3213 << VD << VD->getSourceRange(); 3214 return true; 3215 } 3216 } 3217 return false; 3218 } 3219 bool VisitStmt(const Stmt *S) { 3220 for (const Stmt *Child : S->children()) { 3221 if (Child && Visit(Child)) 3222 return true; 3223 } 3224 return false; 3225 } 3226 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {} 3227 }; 3228 } // namespace 3229 3230 OMPThreadPrivateDecl * 3231 SemaOpenMP::CheckOMPThreadPrivateDecl(SourceLocation Loc, 3232 ArrayRef<Expr *> VarList) { 3233 ASTContext &Context = getASTContext(); 3234 SmallVector<Expr *, 8> Vars; 3235 for (Expr *RefExpr : VarList) { 3236 auto *DE = cast<DeclRefExpr>(RefExpr); 3237 auto *VD = cast<VarDecl>(DE->getDecl()); 3238 SourceLocation ILoc = DE->getExprLoc(); 3239 3240 // Mark variable as used. 3241 VD->setReferenced(); 3242 VD->markUsed(Context); 3243 3244 QualType QType = VD->getType(); 3245 if (QType->isDependentType() || QType->isInstantiationDependentType()) { 3246 // It will be analyzed later. 3247 Vars.push_back(DE); 3248 continue; 3249 } 3250 3251 // OpenMP [2.9.2, Restrictions, C/C++, p.10] 3252 // A threadprivate variable must not have an incomplete type. 3253 if (SemaRef.RequireCompleteType( 3254 ILoc, VD->getType(), diag::err_omp_threadprivate_incomplete_type)) { 3255 continue; 3256 } 3257 3258 // OpenMP [2.9.2, Restrictions, C/C++, p.10] 3259 // A threadprivate variable must not have a reference type. 3260 if (VD->getType()->isReferenceType()) { 3261 Diag(ILoc, diag::err_omp_ref_type_arg) 3262 << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType(); 3263 bool IsDecl = 3264 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; 3265 Diag(VD->getLocation(), 3266 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 3267 << VD; 3268 continue; 3269 } 3270 3271 // Check if this is a TLS variable. If TLS is not being supported, produce 3272 // the corresponding diagnostic. 3273 if ((VD->getTLSKind() != VarDecl::TLS_None && 3274 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() && 3275 getLangOpts().OpenMPUseTLS && 3276 getASTContext().getTargetInfo().isTLSSupported())) || 3277 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() && 3278 !VD->isLocalVarDecl())) { 3279 Diag(ILoc, diag::err_omp_var_thread_local) 3280 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1); 3281 bool IsDecl = 3282 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; 3283 Diag(VD->getLocation(), 3284 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 3285 << VD; 3286 continue; 3287 } 3288 3289 // Check if initial value of threadprivate variable reference variable with 3290 // local storage (it is not supported by runtime). 3291 if (const Expr *Init = VD->getAnyInitializer()) { 3292 LocalVarRefChecker Checker(SemaRef); 3293 if (Checker.Visit(Init)) 3294 continue; 3295 } 3296 3297 Vars.push_back(RefExpr); 3298 DSAStack->addDSA(VD, DE, OMPC_threadprivate); 3299 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit( 3300 Context, SourceRange(Loc, Loc))); 3301 if (ASTMutationListener *ML = Context.getASTMutationListener()) 3302 ML->DeclarationMarkedOpenMPThreadPrivate(VD); 3303 } 3304 OMPThreadPrivateDecl *D = nullptr; 3305 if (!Vars.empty()) { 3306 D = OMPThreadPrivateDecl::Create(Context, SemaRef.getCurLexicalContext(), 3307 Loc, Vars); 3308 D->setAccess(AS_public); 3309 } 3310 return D; 3311 } 3312 3313 static OMPAllocateDeclAttr::AllocatorTypeTy 3314 getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) { 3315 if (!Allocator) 3316 return OMPAllocateDeclAttr::OMPNullMemAlloc; 3317 if (Allocator->isTypeDependent() || Allocator->isValueDependent() || 3318 Allocator->isInstantiationDependent() || 3319 Allocator->containsUnexpandedParameterPack()) 3320 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; 3321 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; 3322 llvm::FoldingSetNodeID AEId; 3323 const Expr *AE = Allocator->IgnoreParenImpCasts(); 3324 AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true); 3325 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) { 3326 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I); 3327 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind); 3328 llvm::FoldingSetNodeID DAEId; 3329 DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(), 3330 /*Canonical=*/true); 3331 if (AEId == DAEId) { 3332 AllocatorKindRes = AllocatorKind; 3333 break; 3334 } 3335 } 3336 return AllocatorKindRes; 3337 } 3338 3339 static bool checkPreviousOMPAllocateAttribute( 3340 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD, 3341 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) { 3342 if (!VD->hasAttr<OMPAllocateDeclAttr>()) 3343 return false; 3344 const auto *A = VD->getAttr<OMPAllocateDeclAttr>(); 3345 Expr *PrevAllocator = A->getAllocator(); 3346 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind = 3347 getAllocatorKind(S, Stack, PrevAllocator); 3348 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind; 3349 if (AllocatorsMatch && 3350 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc && 3351 Allocator && PrevAllocator) { 3352 const Expr *AE = Allocator->IgnoreParenImpCasts(); 3353 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts(); 3354 llvm::FoldingSetNodeID AEId, PAEId; 3355 AE->Profile(AEId, S.Context, /*Canonical=*/true); 3356 PAE->Profile(PAEId, S.Context, /*Canonical=*/true); 3357 AllocatorsMatch = AEId == PAEId; 3358 } 3359 if (!AllocatorsMatch) { 3360 SmallString<256> AllocatorBuffer; 3361 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer); 3362 if (Allocator) 3363 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy()); 3364 SmallString<256> PrevAllocatorBuffer; 3365 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer); 3366 if (PrevAllocator) 3367 PrevAllocator->printPretty(PrevAllocatorStream, nullptr, 3368 S.getPrintingPolicy()); 3369 3370 SourceLocation AllocatorLoc = 3371 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc(); 3372 SourceRange AllocatorRange = 3373 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange(); 3374 SourceLocation PrevAllocatorLoc = 3375 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation(); 3376 SourceRange PrevAllocatorRange = 3377 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange(); 3378 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator) 3379 << (Allocator ? 1 : 0) << AllocatorStream.str() 3380 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str() 3381 << AllocatorRange; 3382 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator) 3383 << PrevAllocatorRange; 3384 return true; 3385 } 3386 return false; 3387 } 3388 3389 static void 3390 applyOMPAllocateAttribute(Sema &S, VarDecl *VD, 3391 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, 3392 Expr *Allocator, Expr *Alignment, SourceRange SR) { 3393 if (VD->hasAttr<OMPAllocateDeclAttr>()) 3394 return; 3395 if (Alignment && 3396 (Alignment->isTypeDependent() || Alignment->isValueDependent() || 3397 Alignment->isInstantiationDependent() || 3398 Alignment->containsUnexpandedParameterPack())) 3399 // Apply later when we have a usable value. 3400 return; 3401 if (Allocator && 3402 (Allocator->isTypeDependent() || Allocator->isValueDependent() || 3403 Allocator->isInstantiationDependent() || 3404 Allocator->containsUnexpandedParameterPack())) 3405 return; 3406 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind, 3407 Allocator, Alignment, SR); 3408 VD->addAttr(A); 3409 if (ASTMutationListener *ML = S.Context.getASTMutationListener()) 3410 ML->DeclarationMarkedOpenMPAllocate(VD, A); 3411 } 3412 3413 SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPAllocateDirective( 3414 SourceLocation Loc, ArrayRef<Expr *> VarList, ArrayRef<OMPClause *> Clauses, 3415 DeclContext *Owner) { 3416 assert(Clauses.size() <= 2 && "Expected at most two clauses."); 3417 Expr *Alignment = nullptr; 3418 Expr *Allocator = nullptr; 3419 if (Clauses.empty()) { 3420 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions. 3421 // allocate directives that appear in a target region must specify an 3422 // allocator clause unless a requires directive with the dynamic_allocators 3423 // clause is present in the same compilation unit. 3424 if (getLangOpts().OpenMPIsTargetDevice && 3425 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>()) 3426 SemaRef.targetDiag(Loc, diag::err_expected_allocator_clause); 3427 } else { 3428 for (const OMPClause *C : Clauses) 3429 if (const auto *AC = dyn_cast<OMPAllocatorClause>(C)) 3430 Allocator = AC->getAllocator(); 3431 else if (const auto *AC = dyn_cast<OMPAlignClause>(C)) 3432 Alignment = AC->getAlignment(); 3433 else 3434 llvm_unreachable("Unexpected clause on allocate directive"); 3435 } 3436 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind = 3437 getAllocatorKind(SemaRef, DSAStack, Allocator); 3438 SmallVector<Expr *, 8> Vars; 3439 for (Expr *RefExpr : VarList) { 3440 auto *DE = cast<DeclRefExpr>(RefExpr); 3441 auto *VD = cast<VarDecl>(DE->getDecl()); 3442 3443 // Check if this is a TLS variable or global register. 3444 if (VD->getTLSKind() != VarDecl::TLS_None || 3445 VD->hasAttr<OMPThreadPrivateDeclAttr>() || 3446 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() && 3447 !VD->isLocalVarDecl())) 3448 continue; 3449 3450 // If the used several times in the allocate directive, the same allocator 3451 // must be used. 3452 if (checkPreviousOMPAllocateAttribute(SemaRef, DSAStack, RefExpr, VD, 3453 AllocatorKind, Allocator)) 3454 continue; 3455 3456 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++ 3457 // If a list item has a static storage type, the allocator expression in the 3458 // allocator clause must be a constant expression that evaluates to one of 3459 // the predefined memory allocator values. 3460 if (Allocator && VD->hasGlobalStorage()) { 3461 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) { 3462 Diag(Allocator->getExprLoc(), 3463 diag::err_omp_expected_predefined_allocator) 3464 << Allocator->getSourceRange(); 3465 bool IsDecl = VD->isThisDeclarationADefinition(getASTContext()) == 3466 VarDecl::DeclarationOnly; 3467 Diag(VD->getLocation(), 3468 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 3469 << VD; 3470 continue; 3471 } 3472 } 3473 3474 Vars.push_back(RefExpr); 3475 applyOMPAllocateAttribute(SemaRef, VD, AllocatorKind, Allocator, Alignment, 3476 DE->getSourceRange()); 3477 } 3478 if (Vars.empty()) 3479 return nullptr; 3480 if (!Owner) 3481 Owner = SemaRef.getCurLexicalContext(); 3482 auto *D = OMPAllocateDecl::Create(getASTContext(), Owner, Loc, Vars, Clauses); 3483 D->setAccess(AS_public); 3484 Owner->addDecl(D); 3485 return DeclGroupPtrTy::make(DeclGroupRef(D)); 3486 } 3487 3488 SemaOpenMP::DeclGroupPtrTy 3489 SemaOpenMP::ActOnOpenMPRequiresDirective(SourceLocation Loc, 3490 ArrayRef<OMPClause *> ClauseList) { 3491 OMPRequiresDecl *D = nullptr; 3492 if (!SemaRef.CurContext->isFileContext()) { 3493 Diag(Loc, diag::err_omp_invalid_scope) << "requires"; 3494 } else { 3495 D = CheckOMPRequiresDecl(Loc, ClauseList); 3496 if (D) { 3497 SemaRef.CurContext->addDecl(D); 3498 DSAStack->addRequiresDecl(D); 3499 } 3500 } 3501 return DeclGroupPtrTy::make(DeclGroupRef(D)); 3502 } 3503 3504 void SemaOpenMP::ActOnOpenMPAssumesDirective(SourceLocation Loc, 3505 OpenMPDirectiveKind DKind, 3506 ArrayRef<std::string> Assumptions, 3507 bool SkippedClauses) { 3508 if (!SkippedClauses && Assumptions.empty()) 3509 Diag(Loc, diag::err_omp_no_clause_for_directive) 3510 << llvm::omp::getAllAssumeClauseOptions() 3511 << llvm::omp::getOpenMPDirectiveName(DKind); 3512 3513 auto *AA = 3514 OMPAssumeAttr::Create(getASTContext(), llvm::join(Assumptions, ","), Loc); 3515 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) { 3516 OMPAssumeScoped.push_back(AA); 3517 return; 3518 } 3519 3520 // Global assumes without assumption clauses are ignored. 3521 if (Assumptions.empty()) 3522 return; 3523 3524 assert(DKind == llvm::omp::Directive::OMPD_assumes && 3525 "Unexpected omp assumption directive!"); 3526 OMPAssumeGlobal.push_back(AA); 3527 3528 // The OMPAssumeGlobal scope above will take care of new declarations but 3529 // we also want to apply the assumption to existing ones, e.g., to 3530 // declarations in included headers. To this end, we traverse all existing 3531 // declaration contexts and annotate function declarations here. 3532 SmallVector<DeclContext *, 8> DeclContexts; 3533 auto *Ctx = SemaRef.CurContext; 3534 while (Ctx->getLexicalParent()) 3535 Ctx = Ctx->getLexicalParent(); 3536 DeclContexts.push_back(Ctx); 3537 while (!DeclContexts.empty()) { 3538 DeclContext *DC = DeclContexts.pop_back_val(); 3539 for (auto *SubDC : DC->decls()) { 3540 if (SubDC->isInvalidDecl()) 3541 continue; 3542 if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) { 3543 DeclContexts.push_back(CTD->getTemplatedDecl()); 3544 llvm::append_range(DeclContexts, CTD->specializations()); 3545 continue; 3546 } 3547 if (auto *DC = dyn_cast<DeclContext>(SubDC)) 3548 DeclContexts.push_back(DC); 3549 if (auto *F = dyn_cast<FunctionDecl>(SubDC)) { 3550 F->addAttr(AA); 3551 continue; 3552 } 3553 } 3554 } 3555 } 3556 3557 void SemaOpenMP::ActOnOpenMPEndAssumesDirective() { 3558 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!"); 3559 OMPAssumeScoped.pop_back(); 3560 } 3561 3562 StmtResult SemaOpenMP::ActOnOpenMPAssumeDirective(ArrayRef<OMPClause *> Clauses, 3563 Stmt *AStmt, 3564 SourceLocation StartLoc, 3565 SourceLocation EndLoc) { 3566 if (!AStmt) 3567 return StmtError(); 3568 3569 return OMPAssumeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses, 3570 AStmt); 3571 } 3572 3573 OMPRequiresDecl * 3574 SemaOpenMP::CheckOMPRequiresDecl(SourceLocation Loc, 3575 ArrayRef<OMPClause *> ClauseList) { 3576 /// For target specific clauses, the requires directive cannot be 3577 /// specified after the handling of any of the target regions in the 3578 /// current compilation unit. 3579 ArrayRef<SourceLocation> TargetLocations = 3580 DSAStack->getEncounteredTargetLocs(); 3581 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc(); 3582 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) { 3583 for (const OMPClause *CNew : ClauseList) { 3584 // Check if any of the requires clauses affect target regions. 3585 if (isa<OMPUnifiedSharedMemoryClause>(CNew) || 3586 isa<OMPUnifiedAddressClause>(CNew) || 3587 isa<OMPReverseOffloadClause>(CNew) || 3588 isa<OMPDynamicAllocatorsClause>(CNew)) { 3589 Diag(Loc, diag::err_omp_directive_before_requires) 3590 << "target" << getOpenMPClauseName(CNew->getClauseKind()); 3591 for (SourceLocation TargetLoc : TargetLocations) { 3592 Diag(TargetLoc, diag::note_omp_requires_encountered_directive) 3593 << "target"; 3594 } 3595 } else if (!AtomicLoc.isInvalid() && 3596 isa<OMPAtomicDefaultMemOrderClause>(CNew)) { 3597 Diag(Loc, diag::err_omp_directive_before_requires) 3598 << "atomic" << getOpenMPClauseName(CNew->getClauseKind()); 3599 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive) 3600 << "atomic"; 3601 } 3602 } 3603 } 3604 3605 if (!DSAStack->hasDuplicateRequiresClause(ClauseList)) 3606 return OMPRequiresDecl::Create( 3607 getASTContext(), SemaRef.getCurLexicalContext(), Loc, ClauseList); 3608 return nullptr; 3609 } 3610 3611 static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack, 3612 const ValueDecl *D, 3613 const DSAStackTy::DSAVarData &DVar, 3614 bool IsLoopIterVar) { 3615 if (DVar.RefExpr) { 3616 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa) 3617 << getOpenMPClauseName(DVar.CKind); 3618 return; 3619 } 3620 enum { 3621 PDSA_StaticMemberShared, 3622 PDSA_StaticLocalVarShared, 3623 PDSA_LoopIterVarPrivate, 3624 PDSA_LoopIterVarLinear, 3625 PDSA_LoopIterVarLastprivate, 3626 PDSA_ConstVarShared, 3627 PDSA_GlobalVarShared, 3628 PDSA_TaskVarFirstprivate, 3629 PDSA_LocalVarPrivate, 3630 PDSA_Implicit 3631 } Reason = PDSA_Implicit; 3632 bool ReportHint = false; 3633 auto ReportLoc = D->getLocation(); 3634 auto *VD = dyn_cast<VarDecl>(D); 3635 if (IsLoopIterVar) { 3636 if (DVar.CKind == OMPC_private) 3637 Reason = PDSA_LoopIterVarPrivate; 3638 else if (DVar.CKind == OMPC_lastprivate) 3639 Reason = PDSA_LoopIterVarLastprivate; 3640 else 3641 Reason = PDSA_LoopIterVarLinear; 3642 } else if (isOpenMPTaskingDirective(DVar.DKind) && 3643 DVar.CKind == OMPC_firstprivate) { 3644 Reason = PDSA_TaskVarFirstprivate; 3645 ReportLoc = DVar.ImplicitDSALoc; 3646 } else if (VD && VD->isStaticLocal()) 3647 Reason = PDSA_StaticLocalVarShared; 3648 else if (VD && VD->isStaticDataMember()) 3649 Reason = PDSA_StaticMemberShared; 3650 else if (VD && VD->isFileVarDecl()) 3651 Reason = PDSA_GlobalVarShared; 3652 else if (D->getType().isConstant(SemaRef.getASTContext())) 3653 Reason = PDSA_ConstVarShared; 3654 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) { 3655 ReportHint = true; 3656 Reason = PDSA_LocalVarPrivate; 3657 } 3658 if (Reason != PDSA_Implicit) { 3659 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa) 3660 << Reason << ReportHint 3661 << getOpenMPDirectiveName(Stack->getCurrentDirective()); 3662 } else if (DVar.ImplicitDSALoc.isValid()) { 3663 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa) 3664 << getOpenMPClauseName(DVar.CKind); 3665 } 3666 } 3667 3668 static OpenMPMapClauseKind 3669 getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M, 3670 bool IsAggregateOrDeclareTarget) { 3671 OpenMPMapClauseKind Kind = OMPC_MAP_unknown; 3672 switch (M) { 3673 case OMPC_DEFAULTMAP_MODIFIER_alloc: 3674 Kind = OMPC_MAP_alloc; 3675 break; 3676 case OMPC_DEFAULTMAP_MODIFIER_to: 3677 Kind = OMPC_MAP_to; 3678 break; 3679 case OMPC_DEFAULTMAP_MODIFIER_from: 3680 Kind = OMPC_MAP_from; 3681 break; 3682 case OMPC_DEFAULTMAP_MODIFIER_tofrom: 3683 Kind = OMPC_MAP_tofrom; 3684 break; 3685 case OMPC_DEFAULTMAP_MODIFIER_present: 3686 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description] 3687 // If implicit-behavior is present, each variable referenced in the 3688 // construct in the category specified by variable-category is treated as if 3689 // it had been listed in a map clause with the map-type of alloc and 3690 // map-type-modifier of present. 3691 Kind = OMPC_MAP_alloc; 3692 break; 3693 case OMPC_DEFAULTMAP_MODIFIER_firstprivate: 3694 case OMPC_DEFAULTMAP_MODIFIER_last: 3695 llvm_unreachable("Unexpected defaultmap implicit behavior"); 3696 case OMPC_DEFAULTMAP_MODIFIER_none: 3697 case OMPC_DEFAULTMAP_MODIFIER_default: 3698 case OMPC_DEFAULTMAP_MODIFIER_unknown: 3699 // IsAggregateOrDeclareTarget could be true if: 3700 // 1. the implicit behavior for aggregate is tofrom 3701 // 2. it's a declare target link 3702 if (IsAggregateOrDeclareTarget) { 3703 Kind = OMPC_MAP_tofrom; 3704 break; 3705 } 3706 llvm_unreachable("Unexpected defaultmap implicit behavior"); 3707 } 3708 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known"); 3709 return Kind; 3710 } 3711 3712 namespace { 3713 struct VariableImplicitInfo { 3714 static const unsigned MapKindNum = OMPC_MAP_unknown; 3715 static const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1; 3716 3717 llvm::SetVector<Expr *> Privates; 3718 llvm::SetVector<Expr *> Firstprivates; 3719 llvm::SetVector<Expr *> Mappings[DefaultmapKindNum][MapKindNum]; 3720 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers> 3721 MapModifiers[DefaultmapKindNum]; 3722 }; 3723 3724 class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> { 3725 DSAStackTy *Stack; 3726 Sema &SemaRef; 3727 OpenMPDirectiveKind DKind = OMPD_unknown; 3728 bool ErrorFound = false; 3729 bool TryCaptureCXXThisMembers = false; 3730 CapturedStmt *CS = nullptr; 3731 3732 VariableImplicitInfo ImpInfo; 3733 SemaOpenMP::VarsWithInheritedDSAType VarsWithInheritedDSA; 3734 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations; 3735 3736 void VisitSubCaptures(OMPExecutableDirective *S) { 3737 // Check implicitly captured variables. 3738 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt()) 3739 return; 3740 if (S->getDirectiveKind() == OMPD_atomic || 3741 S->getDirectiveKind() == OMPD_critical || 3742 S->getDirectiveKind() == OMPD_section || 3743 S->getDirectiveKind() == OMPD_master || 3744 S->getDirectiveKind() == OMPD_masked || 3745 S->getDirectiveKind() == OMPD_scope || 3746 S->getDirectiveKind() == OMPD_assume || 3747 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) { 3748 Visit(S->getAssociatedStmt()); 3749 return; 3750 } 3751 visitSubCaptures(S->getInnermostCapturedStmt()); 3752 // Try to capture inner this->member references to generate correct mappings 3753 // and diagnostics. 3754 if (TryCaptureCXXThisMembers || 3755 (isOpenMPTargetExecutionDirective(DKind) && 3756 llvm::any_of(S->getInnermostCapturedStmt()->captures(), 3757 [](const CapturedStmt::Capture &C) { 3758 return C.capturesThis(); 3759 }))) { 3760 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers; 3761 TryCaptureCXXThisMembers = true; 3762 Visit(S->getInnermostCapturedStmt()->getCapturedStmt()); 3763 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers; 3764 } 3765 // In tasks firstprivates are not captured anymore, need to analyze them 3766 // explicitly. 3767 if (isOpenMPTaskingDirective(S->getDirectiveKind()) && 3768 !isOpenMPTaskLoopDirective(S->getDirectiveKind())) { 3769 for (OMPClause *C : S->clauses()) 3770 if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) { 3771 for (Expr *Ref : FC->varlist()) 3772 Visit(Ref); 3773 } 3774 } 3775 } 3776 3777 public: 3778 void VisitDeclRefExpr(DeclRefExpr *E) { 3779 if (TryCaptureCXXThisMembers || E->isTypeDependent() || 3780 E->isValueDependent() || E->containsUnexpandedParameterPack() || 3781 E->isInstantiationDependent() || 3782 E->isNonOdrUse() == clang::NOUR_Unevaluated) 3783 return; 3784 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) { 3785 // Check the datasharing rules for the expressions in the clauses. 3786 if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) && 3787 !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr && 3788 !Stack->isImplicitDefaultFirstprivateFD(VD))) { 3789 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD)) 3790 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) { 3791 Visit(CED->getInit()); 3792 return; 3793 } 3794 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD)) 3795 // Do not analyze internal variables and do not enclose them into 3796 // implicit clauses. 3797 if (!Stack->isImplicitDefaultFirstprivateFD(VD)) 3798 return; 3799 VD = VD->getCanonicalDecl(); 3800 // Skip internally declared variables. 3801 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) && 3802 !Stack->isImplicitDefaultFirstprivateFD(VD) && 3803 !Stack->isImplicitTaskFirstprivate(VD)) 3804 return; 3805 // Skip allocators in uses_allocators clauses. 3806 if (Stack->isUsesAllocatorsDecl(VD)) 3807 return; 3808 3809 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false); 3810 // Check if the variable has explicit DSA set and stop analysis if it so. 3811 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second) 3812 return; 3813 3814 // Skip internally declared static variables. 3815 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 3816 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 3817 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) && 3818 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() || 3819 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) && 3820 !Stack->isImplicitDefaultFirstprivateFD(VD) && 3821 !Stack->isImplicitTaskFirstprivate(VD)) 3822 return; 3823 3824 SourceLocation ELoc = E->getExprLoc(); 3825 // The default(none) clause requires that each variable that is referenced 3826 // in the construct, and does not have a predetermined data-sharing 3827 // attribute, must have its data-sharing attribute explicitly determined 3828 // by being listed in a data-sharing attribute clause. 3829 if (DVar.CKind == OMPC_unknown && 3830 (Stack->getDefaultDSA() == DSA_none || 3831 Stack->getDefaultDSA() == DSA_private || 3832 Stack->getDefaultDSA() == DSA_firstprivate) && 3833 isImplicitOrExplicitTaskingRegion(DKind) && 3834 VarsWithInheritedDSA.count(VD) == 0) { 3835 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none; 3836 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate || 3837 Stack->getDefaultDSA() == DSA_private)) { 3838 DSAStackTy::DSAVarData DVar = 3839 Stack->getImplicitDSA(VD, /*FromParent=*/false); 3840 InheritedDSA = DVar.CKind == OMPC_unknown; 3841 } 3842 if (InheritedDSA) 3843 VarsWithInheritedDSA[VD] = E; 3844 if (Stack->getDefaultDSA() == DSA_none) 3845 return; 3846 } 3847 3848 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description] 3849 // If implicit-behavior is none, each variable referenced in the 3850 // construct that does not have a predetermined data-sharing attribute 3851 // and does not appear in a to or link clause on a declare target 3852 // directive must be listed in a data-mapping attribute clause, a 3853 // data-sharing attribute clause (including a data-sharing attribute 3854 // clause on a combined construct where target. is one of the 3855 // constituent constructs), or an is_device_ptr clause. 3856 OpenMPDefaultmapClauseKind ClauseKind = 3857 getVariableCategoryFromDecl(SemaRef.getLangOpts(), VD); 3858 if (SemaRef.getLangOpts().OpenMP >= 50) { 3859 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) == 3860 OMPC_DEFAULTMAP_MODIFIER_none; 3861 if (DVar.CKind == OMPC_unknown && IsModifierNone && 3862 VarsWithInheritedDSA.count(VD) == 0 && !Res) { 3863 // Only check for data-mapping attribute and is_device_ptr here 3864 // since we have already make sure that the declaration does not 3865 // have a data-sharing attribute above 3866 if (!Stack->checkMappableExprComponentListsForDecl( 3867 VD, /*CurrentRegionOnly=*/true, 3868 [VD](OMPClauseMappableExprCommon::MappableExprComponentListRef 3869 MapExprComponents, 3870 OpenMPClauseKind) { 3871 auto MI = MapExprComponents.rbegin(); 3872 auto ME = MapExprComponents.rend(); 3873 return MI != ME && MI->getAssociatedDeclaration() == VD; 3874 })) { 3875 VarsWithInheritedDSA[VD] = E; 3876 return; 3877 } 3878 } 3879 } 3880 if (SemaRef.getLangOpts().OpenMP > 50) { 3881 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) == 3882 OMPC_DEFAULTMAP_MODIFIER_present; 3883 if (IsModifierPresent) { 3884 if (!llvm::is_contained(ImpInfo.MapModifiers[ClauseKind], 3885 OMPC_MAP_MODIFIER_present)) { 3886 ImpInfo.MapModifiers[ClauseKind].push_back( 3887 OMPC_MAP_MODIFIER_present); 3888 } 3889 } 3890 } 3891 3892 if (isOpenMPTargetExecutionDirective(DKind) && 3893 !Stack->isLoopControlVariable(VD).first) { 3894 if (!Stack->checkMappableExprComponentListsForDecl( 3895 VD, /*CurrentRegionOnly=*/true, 3896 [this](OMPClauseMappableExprCommon::MappableExprComponentListRef 3897 StackComponents, 3898 OpenMPClauseKind) { 3899 if (SemaRef.LangOpts.OpenMP >= 50) 3900 return !StackComponents.empty(); 3901 // Variable is used if it has been marked as an array, array 3902 // section, array shaping or the variable itself. 3903 return StackComponents.size() == 1 || 3904 llvm::all_of( 3905 llvm::drop_begin(llvm::reverse(StackComponents)), 3906 [](const OMPClauseMappableExprCommon:: 3907 MappableComponent &MC) { 3908 return MC.getAssociatedDeclaration() == 3909 nullptr && 3910 (isa<ArraySectionExpr>( 3911 MC.getAssociatedExpression()) || 3912 isa<OMPArrayShapingExpr>( 3913 MC.getAssociatedExpression()) || 3914 isa<ArraySubscriptExpr>( 3915 MC.getAssociatedExpression())); 3916 }); 3917 })) { 3918 bool IsFirstprivate = false; 3919 // By default lambdas are captured as firstprivates. 3920 if (const auto *RD = 3921 VD->getType().getNonReferenceType()->getAsCXXRecordDecl()) 3922 IsFirstprivate = RD->isLambda(); 3923 IsFirstprivate = 3924 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res); 3925 if (IsFirstprivate) { 3926 ImpInfo.Firstprivates.insert(E); 3927 } else { 3928 OpenMPDefaultmapClauseModifier M = 3929 Stack->getDefaultmapModifier(ClauseKind); 3930 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier( 3931 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res); 3932 ImpInfo.Mappings[ClauseKind][Kind].insert(E); 3933 } 3934 return; 3935 } 3936 } 3937 3938 // OpenMP [2.9.3.6, Restrictions, p.2] 3939 // A list item that appears in a reduction clause of the innermost 3940 // enclosing worksharing or parallel construct may not be accessed in an 3941 // explicit task. 3942 DVar = Stack->hasInnermostDSA( 3943 VD, 3944 [](OpenMPClauseKind C, bool AppliedToPointee) { 3945 return C == OMPC_reduction && !AppliedToPointee; 3946 }, 3947 [](OpenMPDirectiveKind K) { 3948 return isOpenMPParallelDirective(K) || 3949 isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K); 3950 }, 3951 /*FromParent=*/true); 3952 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) { 3953 ErrorFound = true; 3954 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task); 3955 reportOriginalDsa(SemaRef, Stack, VD, DVar); 3956 return; 3957 } 3958 3959 // Define implicit data-sharing attributes for task. 3960 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false); 3961 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) || 3962 (((Stack->getDefaultDSA() == DSA_firstprivate && 3963 DVar.CKind == OMPC_firstprivate) || 3964 (Stack->getDefaultDSA() == DSA_private && 3965 DVar.CKind == OMPC_private)) && 3966 !DVar.RefExpr)) && 3967 !Stack->isLoopControlVariable(VD).first) { 3968 if (Stack->getDefaultDSA() == DSA_private) 3969 ImpInfo.Privates.insert(E); 3970 else 3971 ImpInfo.Firstprivates.insert(E); 3972 return; 3973 } 3974 3975 // Store implicitly used globals with declare target link for parent 3976 // target. 3977 if (!isOpenMPTargetExecutionDirective(DKind) && Res && 3978 *Res == OMPDeclareTargetDeclAttr::MT_Link) { 3979 Stack->addToParentTargetRegionLinkGlobals(E); 3980 return; 3981 } 3982 } 3983 } 3984 void VisitMemberExpr(MemberExpr *E) { 3985 if (E->isTypeDependent() || E->isValueDependent() || 3986 E->containsUnexpandedParameterPack() || E->isInstantiationDependent()) 3987 return; 3988 auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl()); 3989 if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) { 3990 if (!FD) 3991 return; 3992 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false); 3993 // Check if the variable has explicit DSA set and stop analysis if it 3994 // so. 3995 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second) 3996 return; 3997 3998 if (isOpenMPTargetExecutionDirective(DKind) && 3999 !Stack->isLoopControlVariable(FD).first && 4000 !Stack->checkMappableExprComponentListsForDecl( 4001 FD, /*CurrentRegionOnly=*/true, 4002 [](OMPClauseMappableExprCommon::MappableExprComponentListRef 4003 StackComponents, 4004 OpenMPClauseKind) { 4005 return isa<CXXThisExpr>( 4006 cast<MemberExpr>( 4007 StackComponents.back().getAssociatedExpression()) 4008 ->getBase() 4009 ->IgnoreParens()); 4010 })) { 4011 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3] 4012 // A bit-field cannot appear in a map clause. 4013 // 4014 if (FD->isBitField()) 4015 return; 4016 4017 // Check to see if the member expression is referencing a class that 4018 // has already been explicitly mapped 4019 if (Stack->isClassPreviouslyMapped(TE->getType())) 4020 return; 4021 4022 OpenMPDefaultmapClauseModifier Modifier = 4023 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate); 4024 OpenMPDefaultmapClauseKind ClauseKind = 4025 getVariableCategoryFromDecl(SemaRef.getLangOpts(), FD); 4026 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier( 4027 Modifier, /*IsAggregateOrDeclareTarget=*/true); 4028 ImpInfo.Mappings[ClauseKind][Kind].insert(E); 4029 return; 4030 } 4031 4032 SourceLocation ELoc = E->getExprLoc(); 4033 // OpenMP [2.9.3.6, Restrictions, p.2] 4034 // A list item that appears in a reduction clause of the innermost 4035 // enclosing worksharing or parallel construct may not be accessed in 4036 // an explicit task. 4037 DVar = Stack->hasInnermostDSA( 4038 FD, 4039 [](OpenMPClauseKind C, bool AppliedToPointee) { 4040 return C == OMPC_reduction && !AppliedToPointee; 4041 }, 4042 [](OpenMPDirectiveKind K) { 4043 return isOpenMPParallelDirective(K) || 4044 isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K); 4045 }, 4046 /*FromParent=*/true); 4047 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) { 4048 ErrorFound = true; 4049 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task); 4050 reportOriginalDsa(SemaRef, Stack, FD, DVar); 4051 return; 4052 } 4053 4054 // Define implicit data-sharing attributes for task. 4055 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false); 4056 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared && 4057 !Stack->isLoopControlVariable(FD).first) { 4058 // Check if there is a captured expression for the current field in the 4059 // region. Do not mark it as firstprivate unless there is no captured 4060 // expression. 4061 // TODO: try to make it firstprivate. 4062 if (DVar.CKind != OMPC_unknown) 4063 ImpInfo.Firstprivates.insert(E); 4064 } 4065 return; 4066 } 4067 if (isOpenMPTargetExecutionDirective(DKind)) { 4068 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents; 4069 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map, 4070 DKind, /*NoDiagnose=*/true)) 4071 return; 4072 const auto *VD = cast<ValueDecl>( 4073 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl()); 4074 if (!Stack->checkMappableExprComponentListsForDecl( 4075 VD, /*CurrentRegionOnly=*/true, 4076 [&CurComponents]( 4077 OMPClauseMappableExprCommon::MappableExprComponentListRef 4078 StackComponents, 4079 OpenMPClauseKind) { 4080 auto CCI = CurComponents.rbegin(); 4081 auto CCE = CurComponents.rend(); 4082 for (const auto &SC : llvm::reverse(StackComponents)) { 4083 // Do both expressions have the same kind? 4084 if (CCI->getAssociatedExpression()->getStmtClass() != 4085 SC.getAssociatedExpression()->getStmtClass()) 4086 if (!((isa<ArraySectionExpr>( 4087 SC.getAssociatedExpression()) || 4088 isa<OMPArrayShapingExpr>( 4089 SC.getAssociatedExpression())) && 4090 isa<ArraySubscriptExpr>( 4091 CCI->getAssociatedExpression()))) 4092 return false; 4093 4094 const Decl *CCD = CCI->getAssociatedDeclaration(); 4095 const Decl *SCD = SC.getAssociatedDeclaration(); 4096 CCD = CCD ? CCD->getCanonicalDecl() : nullptr; 4097 SCD = SCD ? SCD->getCanonicalDecl() : nullptr; 4098 if (SCD != CCD) 4099 return false; 4100 std::advance(CCI, 1); 4101 if (CCI == CCE) 4102 break; 4103 } 4104 return true; 4105 })) { 4106 Visit(E->getBase()); 4107 } 4108 } else if (!TryCaptureCXXThisMembers) { 4109 Visit(E->getBase()); 4110 } 4111 } 4112 void VisitOMPExecutableDirective(OMPExecutableDirective *S) { 4113 for (OMPClause *C : S->clauses()) { 4114 // Skip analysis of arguments of private clauses for task|target 4115 // directives. 4116 if (isa_and_nonnull<OMPPrivateClause>(C)) 4117 continue; 4118 // Skip analysis of arguments of implicitly defined firstprivate clause 4119 // for task|target directives. 4120 // Skip analysis of arguments of implicitly defined map clause for target 4121 // directives. 4122 if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) && 4123 C->isImplicit() && !isOpenMPTaskingDirective(DKind))) { 4124 for (Stmt *CC : C->children()) { 4125 if (CC) 4126 Visit(CC); 4127 } 4128 } 4129 } 4130 // Check implicitly captured variables. 4131 VisitSubCaptures(S); 4132 } 4133 4134 void VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective *S) { 4135 // Loop transformation directives do not introduce data sharing 4136 VisitStmt(S); 4137 } 4138 4139 void VisitCallExpr(CallExpr *S) { 4140 for (Stmt *C : S->arguments()) { 4141 if (C) { 4142 // Check implicitly captured variables in the task-based directives to 4143 // check if they must be firstprivatized. 4144 Visit(C); 4145 } 4146 } 4147 if (Expr *Callee = S->getCallee()) { 4148 auto *CI = Callee->IgnoreParenImpCasts(); 4149 if (auto *CE = dyn_cast<MemberExpr>(CI)) 4150 Visit(CE->getBase()); 4151 else if (auto *CE = dyn_cast<DeclRefExpr>(CI)) 4152 Visit(CE); 4153 } 4154 } 4155 void VisitStmt(Stmt *S) { 4156 for (Stmt *C : S->children()) { 4157 if (C) { 4158 // Check implicitly captured variables in the task-based directives to 4159 // check if they must be firstprivatized. 4160 Visit(C); 4161 } 4162 } 4163 } 4164 4165 void visitSubCaptures(CapturedStmt *S) { 4166 for (const CapturedStmt::Capture &Cap : S->captures()) { 4167 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy()) 4168 continue; 4169 VarDecl *VD = Cap.getCapturedVar(); 4170 // Do not try to map the variable if it or its sub-component was mapped 4171 // already. 4172 if (isOpenMPTargetExecutionDirective(DKind) && 4173 Stack->checkMappableExprComponentListsForDecl( 4174 VD, /*CurrentRegionOnly=*/true, 4175 [](OMPClauseMappableExprCommon::MappableExprComponentListRef, 4176 OpenMPClauseKind) { return true; })) 4177 continue; 4178 DeclRefExpr *DRE = buildDeclRefExpr( 4179 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context), 4180 Cap.getLocation(), /*RefersToCapture=*/true); 4181 Visit(DRE); 4182 } 4183 } 4184 bool isErrorFound() const { return ErrorFound; } 4185 const VariableImplicitInfo &getImplicitInfo() const { return ImpInfo; } 4186 const SemaOpenMP::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const { 4187 return VarsWithInheritedDSA; 4188 } 4189 4190 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS) 4191 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) { 4192 DKind = S->getCurrentDirective(); 4193 // Process declare target link variables for the target directives. 4194 if (isOpenMPTargetExecutionDirective(DKind)) { 4195 for (DeclRefExpr *E : Stack->getLinkGlobals()) 4196 Visit(E); 4197 } 4198 } 4199 }; 4200 } // namespace 4201 4202 static void handleDeclareVariantConstructTrait(DSAStackTy *Stack, 4203 OpenMPDirectiveKind DKind, 4204 bool ScopeEntry) { 4205 SmallVector<llvm::omp::TraitProperty, 8> Traits; 4206 if (isOpenMPTargetExecutionDirective(DKind)) 4207 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target); 4208 if (isOpenMPTeamsDirective(DKind)) 4209 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams); 4210 if (isOpenMPParallelDirective(DKind)) 4211 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel); 4212 if (isOpenMPWorksharingDirective(DKind)) 4213 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for); 4214 if (isOpenMPSimdDirective(DKind)) 4215 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd); 4216 Stack->handleConstructTrait(Traits, ScopeEntry); 4217 } 4218 4219 static SmallVector<SemaOpenMP::CapturedParamNameType> 4220 getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing) { 4221 ASTContext &Context = SemaRef.getASTContext(); 4222 QualType KmpInt32Ty = 4223 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst(); 4224 QualType KmpInt32PtrTy = 4225 Context.getPointerType(KmpInt32Ty).withConst().withRestrict(); 4226 SmallVector<SemaOpenMP::CapturedParamNameType> Params{ 4227 std::make_pair(".global_tid.", KmpInt32PtrTy), 4228 std::make_pair(".bound_tid.", KmpInt32PtrTy), 4229 }; 4230 if (LoopBoundSharing) { 4231 QualType KmpSizeTy = Context.getSizeType().withConst(); 4232 Params.push_back(std::make_pair(".previous.lb.", KmpSizeTy)); 4233 Params.push_back(std::make_pair(".previous.ub.", KmpSizeTy)); 4234 } 4235 4236 // __context with shared vars 4237 Params.push_back(std::make_pair(StringRef(), QualType())); 4238 return Params; 4239 } 4240 4241 static SmallVector<SemaOpenMP::CapturedParamNameType> 4242 getTeamsRegionParams(Sema &SemaRef) { 4243 return getParallelRegionParams(SemaRef, /*LoopBoundSharing=*/false); 4244 } 4245 4246 static SmallVector<SemaOpenMP::CapturedParamNameType> 4247 getTaskRegionParams(Sema &SemaRef) { 4248 ASTContext &Context = SemaRef.getASTContext(); 4249 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst(); 4250 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict(); 4251 QualType KmpInt32PtrTy = 4252 Context.getPointerType(KmpInt32Ty).withConst().withRestrict(); 4253 QualType Args[] = {VoidPtrTy}; 4254 FunctionProtoType::ExtProtoInfo EPI; 4255 EPI.Variadic = true; 4256 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI); 4257 SmallVector<SemaOpenMP::CapturedParamNameType> Params{ 4258 std::make_pair(".global_tid.", KmpInt32Ty), 4259 std::make_pair(".part_id.", KmpInt32PtrTy), 4260 std::make_pair(".privates.", VoidPtrTy), 4261 std::make_pair( 4262 ".copy_fn.", 4263 Context.getPointerType(CopyFnType).withConst().withRestrict()), 4264 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()), 4265 std::make_pair(StringRef(), QualType()) // __context with shared vars 4266 }; 4267 return Params; 4268 } 4269 4270 static SmallVector<SemaOpenMP::CapturedParamNameType> 4271 getTargetRegionParams(Sema &SemaRef) { 4272 ASTContext &Context = SemaRef.getASTContext(); 4273 SmallVector<SemaOpenMP::CapturedParamNameType> Params; 4274 if (SemaRef.getLangOpts().OpenMPIsTargetDevice) { 4275 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict(); 4276 Params.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy)); 4277 } 4278 // __context with shared vars 4279 Params.push_back(std::make_pair(StringRef(), QualType())); 4280 return Params; 4281 } 4282 4283 static SmallVector<SemaOpenMP::CapturedParamNameType> 4284 getUnknownRegionParams(Sema &SemaRef) { 4285 SmallVector<SemaOpenMP::CapturedParamNameType> Params{ 4286 std::make_pair(StringRef(), QualType()) // __context with shared vars 4287 }; 4288 return Params; 4289 } 4290 4291 static SmallVector<SemaOpenMP::CapturedParamNameType> 4292 getTaskloopRegionParams(Sema &SemaRef) { 4293 ASTContext &Context = SemaRef.getASTContext(); 4294 QualType KmpInt32Ty = 4295 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst(); 4296 QualType KmpUInt64Ty = 4297 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0).withConst(); 4298 QualType KmpInt64Ty = 4299 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1).withConst(); 4300 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict(); 4301 QualType KmpInt32PtrTy = 4302 Context.getPointerType(KmpInt32Ty).withConst().withRestrict(); 4303 QualType Args[] = {VoidPtrTy}; 4304 FunctionProtoType::ExtProtoInfo EPI; 4305 EPI.Variadic = true; 4306 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI); 4307 SmallVector<SemaOpenMP::CapturedParamNameType> Params{ 4308 std::make_pair(".global_tid.", KmpInt32Ty), 4309 std::make_pair(".part_id.", KmpInt32PtrTy), 4310 std::make_pair(".privates.", VoidPtrTy), 4311 std::make_pair( 4312 ".copy_fn.", 4313 Context.getPointerType(CopyFnType).withConst().withRestrict()), 4314 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()), 4315 std::make_pair(".lb.", KmpUInt64Ty), 4316 std::make_pair(".ub.", KmpUInt64Ty), 4317 std::make_pair(".st.", KmpInt64Ty), 4318 std::make_pair(".liter.", KmpInt32Ty), 4319 std::make_pair(".reductions.", VoidPtrTy), 4320 std::make_pair(StringRef(), QualType()) // __context with shared vars 4321 }; 4322 return Params; 4323 } 4324 4325 static void processCapturedRegions(Sema &SemaRef, OpenMPDirectiveKind DKind, 4326 Scope *CurScope, SourceLocation Loc) { 4327 SmallVector<OpenMPDirectiveKind> Regions; 4328 getOpenMPCaptureRegions(Regions, DKind); 4329 4330 bool LoopBoundSharing = isOpenMPLoopBoundSharingDirective(DKind); 4331 4332 auto MarkAsInlined = [&](CapturedRegionScopeInfo *CSI) { 4333 CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit( 4334 SemaRef.getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline)); 4335 }; 4336 4337 for (auto [Level, RKind] : llvm::enumerate(Regions)) { 4338 switch (RKind) { 4339 // All region kinds that can be returned from `getOpenMPCaptureRegions` 4340 // are listed here. 4341 case OMPD_parallel: 4342 SemaRef.ActOnCapturedRegionStart( 4343 Loc, CurScope, CR_OpenMP, 4344 getParallelRegionParams(SemaRef, LoopBoundSharing), Level); 4345 break; 4346 case OMPD_teams: 4347 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, 4348 getTeamsRegionParams(SemaRef), Level); 4349 break; 4350 case OMPD_task: 4351 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, 4352 getTaskRegionParams(SemaRef), Level); 4353 // Mark this captured region as inlined, because we don't use outlined 4354 // function directly. 4355 MarkAsInlined(SemaRef.getCurCapturedRegion()); 4356 break; 4357 case OMPD_taskloop: 4358 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, 4359 getTaskloopRegionParams(SemaRef), Level); 4360 // Mark this captured region as inlined, because we don't use outlined 4361 // function directly. 4362 MarkAsInlined(SemaRef.getCurCapturedRegion()); 4363 break; 4364 case OMPD_target: 4365 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, 4366 getTargetRegionParams(SemaRef), Level); 4367 break; 4368 case OMPD_unknown: 4369 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, 4370 getUnknownRegionParams(SemaRef)); 4371 break; 4372 case OMPD_metadirective: 4373 case OMPD_nothing: 4374 default: 4375 llvm_unreachable("Unexpected capture region"); 4376 } 4377 } 4378 } 4379 4380 void SemaOpenMP::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, 4381 Scope *CurScope) { 4382 switch (DKind) { 4383 case OMPD_atomic: 4384 case OMPD_critical: 4385 case OMPD_masked: 4386 case OMPD_master: 4387 case OMPD_section: 4388 case OMPD_tile: 4389 case OMPD_unroll: 4390 case OMPD_reverse: 4391 case OMPD_interchange: 4392 case OMPD_assume: 4393 break; 4394 default: 4395 processCapturedRegions(SemaRef, DKind, CurScope, 4396 DSAStack->getConstructLoc()); 4397 break; 4398 } 4399 4400 DSAStack->setContext(SemaRef.CurContext); 4401 handleDeclareVariantConstructTrait(DSAStack, DKind, /*ScopeEntry=*/true); 4402 } 4403 4404 int SemaOpenMP::getNumberOfConstructScopes(unsigned Level) const { 4405 return getOpenMPCaptureLevels(DSAStack->getDirective(Level)); 4406 } 4407 4408 int SemaOpenMP::getOpenMPCaptureLevels(OpenMPDirectiveKind DKind) { 4409 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 4410 getOpenMPCaptureRegions(CaptureRegions, DKind); 4411 return CaptureRegions.size(); 4412 } 4413 4414 static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id, 4415 Expr *CaptureExpr, bool WithInit, 4416 DeclContext *CurContext, 4417 bool AsExpression) { 4418 assert(CaptureExpr); 4419 ASTContext &C = S.getASTContext(); 4420 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts(); 4421 QualType Ty = Init->getType(); 4422 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) { 4423 if (S.getLangOpts().CPlusPlus) { 4424 Ty = C.getLValueReferenceType(Ty); 4425 } else { 4426 Ty = C.getPointerType(Ty); 4427 ExprResult Res = 4428 S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init); 4429 if (!Res.isUsable()) 4430 return nullptr; 4431 Init = Res.get(); 4432 } 4433 WithInit = true; 4434 } 4435 auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty, 4436 CaptureExpr->getBeginLoc()); 4437 if (!WithInit) 4438 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C)); 4439 CurContext->addHiddenDecl(CED); 4440 Sema::TentativeAnalysisScope Trap(S); 4441 S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false); 4442 return CED; 4443 } 4444 4445 static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr, 4446 bool WithInit) { 4447 OMPCapturedExprDecl *CD; 4448 if (VarDecl *VD = S.OpenMP().isOpenMPCapturedDecl(D)) 4449 CD = cast<OMPCapturedExprDecl>(VD); 4450 else 4451 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit, 4452 S.CurContext, 4453 /*AsExpression=*/false); 4454 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(), 4455 CaptureExpr->getExprLoc()); 4456 } 4457 4458 static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref, 4459 StringRef Name) { 4460 CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get(); 4461 if (!Ref) { 4462 OMPCapturedExprDecl *CD = buildCaptureDecl( 4463 S, &S.getASTContext().Idents.get(Name), CaptureExpr, 4464 /*WithInit=*/true, S.CurContext, /*AsExpression=*/true); 4465 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(), 4466 CaptureExpr->getExprLoc()); 4467 } 4468 ExprResult Res = Ref; 4469 if (!S.getLangOpts().CPlusPlus && 4470 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() && 4471 Ref->getType()->isPointerType()) { 4472 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref); 4473 if (!Res.isUsable()) 4474 return ExprError(); 4475 } 4476 return S.DefaultLvalueConversion(Res.get()); 4477 } 4478 4479 namespace { 4480 // OpenMP directives parsed in this section are represented as a 4481 // CapturedStatement with an associated statement. If a syntax error 4482 // is detected during the parsing of the associated statement, the 4483 // compiler must abort processing and close the CapturedStatement. 4484 // 4485 // Combined directives such as 'target parallel' have more than one 4486 // nested CapturedStatements. This RAII ensures that we unwind out 4487 // of all the nested CapturedStatements when an error is found. 4488 class CaptureRegionUnwinderRAII { 4489 private: 4490 Sema &S; 4491 bool &ErrorFound; 4492 OpenMPDirectiveKind DKind = OMPD_unknown; 4493 4494 public: 4495 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound, 4496 OpenMPDirectiveKind DKind) 4497 : S(S), ErrorFound(ErrorFound), DKind(DKind) {} 4498 ~CaptureRegionUnwinderRAII() { 4499 if (ErrorFound) { 4500 int ThisCaptureLevel = S.OpenMP().getOpenMPCaptureLevels(DKind); 4501 while (--ThisCaptureLevel >= 0) 4502 S.ActOnCapturedRegionError(); 4503 } 4504 } 4505 }; 4506 } // namespace 4507 4508 void SemaOpenMP::tryCaptureOpenMPLambdas(ValueDecl *V) { 4509 // Capture variables captured by reference in lambdas for target-based 4510 // directives. 4511 if (!SemaRef.CurContext->isDependentContext() && 4512 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) || 4513 isOpenMPTargetDataManagementDirective( 4514 DSAStack->getCurrentDirective()))) { 4515 QualType Type = V->getType(); 4516 if (const auto *RD = Type.getCanonicalType() 4517 .getNonReferenceType() 4518 ->getAsCXXRecordDecl()) { 4519 bool SavedForceCaptureByReferenceInTargetExecutable = 4520 DSAStack->isForceCaptureByReferenceInTargetExecutable(); 4521 DSAStack->setForceCaptureByReferenceInTargetExecutable( 4522 /*V=*/true); 4523 if (RD->isLambda()) { 4524 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures; 4525 FieldDecl *ThisCapture; 4526 RD->getCaptureFields(Captures, ThisCapture); 4527 for (const LambdaCapture &LC : RD->captures()) { 4528 if (LC.getCaptureKind() == LCK_ByRef) { 4529 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar()); 4530 DeclContext *VDC = VD->getDeclContext(); 4531 if (!VDC->Encloses(SemaRef.CurContext)) 4532 continue; 4533 SemaRef.MarkVariableReferenced(LC.getLocation(), VD); 4534 } else if (LC.getCaptureKind() == LCK_This) { 4535 QualType ThisTy = SemaRef.getCurrentThisType(); 4536 if (!ThisTy.isNull() && getASTContext().typesAreCompatible( 4537 ThisTy, ThisCapture->getType())) 4538 SemaRef.CheckCXXThisCapture(LC.getLocation()); 4539 } 4540 } 4541 } 4542 DSAStack->setForceCaptureByReferenceInTargetExecutable( 4543 SavedForceCaptureByReferenceInTargetExecutable); 4544 } 4545 } 4546 } 4547 4548 static bool checkOrderedOrderSpecified(Sema &S, 4549 const ArrayRef<OMPClause *> Clauses) { 4550 const OMPOrderedClause *Ordered = nullptr; 4551 const OMPOrderClause *Order = nullptr; 4552 4553 for (const OMPClause *Clause : Clauses) { 4554 if (Clause->getClauseKind() == OMPC_ordered) 4555 Ordered = cast<OMPOrderedClause>(Clause); 4556 else if (Clause->getClauseKind() == OMPC_order) { 4557 Order = cast<OMPOrderClause>(Clause); 4558 if (Order->getKind() != OMPC_ORDER_concurrent) 4559 Order = nullptr; 4560 } 4561 if (Ordered && Order) 4562 break; 4563 } 4564 4565 if (Ordered && Order) { 4566 S.Diag(Order->getKindKwLoc(), 4567 diag::err_omp_simple_clause_incompatible_with_ordered) 4568 << getOpenMPClauseName(OMPC_order) 4569 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent) 4570 << SourceRange(Order->getBeginLoc(), Order->getEndLoc()); 4571 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param) 4572 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc()); 4573 return true; 4574 } 4575 return false; 4576 } 4577 4578 StmtResult SemaOpenMP::ActOnOpenMPRegionEnd(StmtResult S, 4579 ArrayRef<OMPClause *> Clauses) { 4580 handleDeclareVariantConstructTrait(DSAStack, DSAStack->getCurrentDirective(), 4581 /*ScopeEntry=*/false); 4582 if (!isOpenMPCapturingDirective(DSAStack->getCurrentDirective())) 4583 return S; 4584 4585 bool ErrorFound = false; 4586 CaptureRegionUnwinderRAII CaptureRegionUnwinder( 4587 SemaRef, ErrorFound, DSAStack->getCurrentDirective()); 4588 if (!S.isUsable()) { 4589 ErrorFound = true; 4590 return StmtError(); 4591 } 4592 4593 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 4594 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective()); 4595 OMPOrderedClause *OC = nullptr; 4596 OMPScheduleClause *SC = nullptr; 4597 SmallVector<const OMPLinearClause *, 4> LCs; 4598 SmallVector<const OMPClauseWithPreInit *, 4> PICs; 4599 // This is required for proper codegen. 4600 for (OMPClause *Clause : Clauses) { 4601 if (!getLangOpts().OpenMPSimd && 4602 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) || 4603 DSAStack->getCurrentDirective() == OMPD_target) && 4604 Clause->getClauseKind() == OMPC_in_reduction) { 4605 // Capture taskgroup task_reduction descriptors inside the tasking regions 4606 // with the corresponding in_reduction items. 4607 auto *IRC = cast<OMPInReductionClause>(Clause); 4608 for (Expr *E : IRC->taskgroup_descriptors()) 4609 if (E) 4610 SemaRef.MarkDeclarationsReferencedInExpr(E); 4611 } 4612 if (isOpenMPPrivate(Clause->getClauseKind()) || 4613 Clause->getClauseKind() == OMPC_copyprivate || 4614 (getLangOpts().OpenMPUseTLS && 4615 getASTContext().getTargetInfo().isTLSSupported() && 4616 Clause->getClauseKind() == OMPC_copyin)) { 4617 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin); 4618 // Mark all variables in private list clauses as used in inner region. 4619 for (Stmt *VarRef : Clause->children()) { 4620 if (auto *E = cast_or_null<Expr>(VarRef)) { 4621 SemaRef.MarkDeclarationsReferencedInExpr(E); 4622 } 4623 } 4624 DSAStack->setForceVarCapturing(/*V=*/false); 4625 } else if (CaptureRegions.size() > 1 || 4626 CaptureRegions.back() != OMPD_unknown) { 4627 if (auto *C = OMPClauseWithPreInit::get(Clause)) 4628 PICs.push_back(C); 4629 if (auto *C = OMPClauseWithPostUpdate::get(Clause)) { 4630 if (Expr *E = C->getPostUpdateExpr()) 4631 SemaRef.MarkDeclarationsReferencedInExpr(E); 4632 } 4633 } 4634 if (Clause->getClauseKind() == OMPC_schedule) 4635 SC = cast<OMPScheduleClause>(Clause); 4636 else if (Clause->getClauseKind() == OMPC_ordered) 4637 OC = cast<OMPOrderedClause>(Clause); 4638 else if (Clause->getClauseKind() == OMPC_linear) 4639 LCs.push_back(cast<OMPLinearClause>(Clause)); 4640 } 4641 // Capture allocator expressions if used. 4642 for (Expr *E : DSAStack->getInnerAllocators()) 4643 SemaRef.MarkDeclarationsReferencedInExpr(E); 4644 // OpenMP, 2.7.1 Loop Construct, Restrictions 4645 // The nonmonotonic modifier cannot be specified if an ordered clause is 4646 // specified. 4647 if (SC && 4648 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic || 4649 SC->getSecondScheduleModifier() == 4650 OMPC_SCHEDULE_MODIFIER_nonmonotonic) && 4651 OC) { 4652 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic 4653 ? SC->getFirstScheduleModifierLoc() 4654 : SC->getSecondScheduleModifierLoc(), 4655 diag::err_omp_simple_clause_incompatible_with_ordered) 4656 << getOpenMPClauseName(OMPC_schedule) 4657 << getOpenMPSimpleClauseTypeName(OMPC_schedule, 4658 OMPC_SCHEDULE_MODIFIER_nonmonotonic) 4659 << SourceRange(OC->getBeginLoc(), OC->getEndLoc()); 4660 ErrorFound = true; 4661 } 4662 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions. 4663 // If an order(concurrent) clause is present, an ordered clause may not appear 4664 // on the same directive. 4665 if (checkOrderedOrderSpecified(SemaRef, Clauses)) 4666 ErrorFound = true; 4667 if (!LCs.empty() && OC && OC->getNumForLoops()) { 4668 for (const OMPLinearClause *C : LCs) { 4669 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered) 4670 << SourceRange(OC->getBeginLoc(), OC->getEndLoc()); 4671 } 4672 ErrorFound = true; 4673 } 4674 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) && 4675 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC && 4676 OC->getNumForLoops()) { 4677 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd) 4678 << getOpenMPDirectiveName(DSAStack->getCurrentDirective()); 4679 ErrorFound = true; 4680 } 4681 if (ErrorFound) { 4682 return StmtError(); 4683 } 4684 StmtResult SR = S; 4685 unsigned CompletedRegions = 0; 4686 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) { 4687 // Mark all variables in private list clauses as used in inner region. 4688 // Required for proper codegen of combined directives. 4689 // TODO: add processing for other clauses. 4690 if (ThisCaptureRegion != OMPD_unknown) { 4691 for (const clang::OMPClauseWithPreInit *C : PICs) { 4692 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion(); 4693 // Find the particular capture region for the clause if the 4694 // directive is a combined one with multiple capture regions. 4695 // If the directive is not a combined one, the capture region 4696 // associated with the clause is OMPD_unknown and is generated 4697 // only once. 4698 if (CaptureRegion == ThisCaptureRegion || 4699 CaptureRegion == OMPD_unknown) { 4700 if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) { 4701 for (Decl *D : DS->decls()) 4702 SemaRef.MarkVariableReferenced(D->getLocation(), 4703 cast<VarDecl>(D)); 4704 } 4705 } 4706 } 4707 } 4708 if (ThisCaptureRegion == OMPD_target) { 4709 // Capture allocator traits in the target region. They are used implicitly 4710 // and, thus, are not captured by default. 4711 for (OMPClause *C : Clauses) { 4712 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) { 4713 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End; 4714 ++I) { 4715 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I); 4716 if (Expr *E = D.AllocatorTraits) 4717 SemaRef.MarkDeclarationsReferencedInExpr(E); 4718 } 4719 continue; 4720 } 4721 } 4722 } 4723 if (ThisCaptureRegion == OMPD_parallel) { 4724 // Capture temp arrays for inscan reductions and locals in aligned 4725 // clauses. 4726 for (OMPClause *C : Clauses) { 4727 if (auto *RC = dyn_cast<OMPReductionClause>(C)) { 4728 if (RC->getModifier() != OMPC_REDUCTION_inscan) 4729 continue; 4730 for (Expr *E : RC->copy_array_temps()) 4731 if (E) 4732 SemaRef.MarkDeclarationsReferencedInExpr(E); 4733 } 4734 if (auto *AC = dyn_cast<OMPAlignedClause>(C)) { 4735 for (Expr *E : AC->varlist()) 4736 SemaRef.MarkDeclarationsReferencedInExpr(E); 4737 } 4738 } 4739 } 4740 if (++CompletedRegions == CaptureRegions.size()) 4741 DSAStack->setBodyComplete(); 4742 SR = SemaRef.ActOnCapturedRegionEnd(SR.get()); 4743 } 4744 return SR; 4745 } 4746 4747 static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion, 4748 OpenMPDirectiveKind CancelRegion, 4749 SourceLocation StartLoc) { 4750 // CancelRegion is only needed for cancel and cancellation_point. 4751 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point) 4752 return false; 4753 4754 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for || 4755 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup) 4756 return false; 4757 4758 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region) 4759 << getOpenMPDirectiveName(CancelRegion); 4760 return true; 4761 } 4762 4763 static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack, 4764 OpenMPDirectiveKind CurrentRegion, 4765 const DeclarationNameInfo &CurrentName, 4766 OpenMPDirectiveKind CancelRegion, 4767 OpenMPBindClauseKind BindKind, 4768 SourceLocation StartLoc) { 4769 if (!Stack->getCurScope()) 4770 return false; 4771 4772 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective(); 4773 OpenMPDirectiveKind OffendingRegion = ParentRegion; 4774 bool NestingProhibited = false; 4775 bool CloseNesting = true; 4776 bool OrphanSeen = false; 4777 enum { 4778 NoRecommend, 4779 ShouldBeInParallelRegion, 4780 ShouldBeInOrderedRegion, 4781 ShouldBeInTargetRegion, 4782 ShouldBeInTeamsRegion, 4783 ShouldBeInLoopSimdRegion, 4784 } Recommend = NoRecommend; 4785 4786 SmallVector<OpenMPDirectiveKind, 4> LeafOrComposite; 4787 ArrayRef<OpenMPDirectiveKind> ParentLOC = 4788 getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite); 4789 OpenMPDirectiveKind EnclosingConstruct = ParentLOC.back(); 4790 4791 if (SemaRef.LangOpts.OpenMP >= 51 && Stack->isParentOrderConcurrent() && 4792 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_loop && 4793 CurrentRegion != OMPD_parallel && 4794 !isOpenMPCombinedParallelADirective(CurrentRegion)) { 4795 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order) 4796 << getOpenMPDirectiveName(CurrentRegion); 4797 return true; 4798 } 4799 if (isOpenMPSimdDirective(ParentRegion) && 4800 ((SemaRef.LangOpts.OpenMP <= 45 && CurrentRegion != OMPD_ordered) || 4801 (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion != OMPD_ordered && 4802 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic && 4803 CurrentRegion != OMPD_scan))) { 4804 // OpenMP [2.16, Nesting of Regions] 4805 // OpenMP constructs may not be nested inside a simd region. 4806 // OpenMP [2.8.1,simd Construct, Restrictions] 4807 // An ordered construct with the simd clause is the only OpenMP 4808 // construct that can appear in the simd region. 4809 // Allowing a SIMD construct nested in another SIMD construct is an 4810 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning 4811 // message. 4812 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions] 4813 // The only OpenMP constructs that can be encountered during execution of 4814 // a simd region are the atomic construct, the loop construct, the simd 4815 // construct and the ordered construct with the simd clause. 4816 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd) 4817 ? diag::err_omp_prohibited_region_simd 4818 : diag::warn_omp_nesting_simd) 4819 << (SemaRef.LangOpts.OpenMP >= 50 ? 1 : 0); 4820 return CurrentRegion != OMPD_simd; 4821 } 4822 if (EnclosingConstruct == OMPD_atomic) { 4823 // OpenMP [2.16, Nesting of Regions] 4824 // OpenMP constructs may not be nested inside an atomic region. 4825 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic); 4826 return true; 4827 } 4828 if (CurrentRegion == OMPD_section) { 4829 // OpenMP [2.7.2, sections Construct, Restrictions] 4830 // Orphaned section directives are prohibited. That is, the section 4831 // directives must appear within the sections construct and must not be 4832 // encountered elsewhere in the sections region. 4833 if (EnclosingConstruct != OMPD_sections) { 4834 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive) 4835 << (ParentRegion != OMPD_unknown) 4836 << getOpenMPDirectiveName(ParentRegion); 4837 return true; 4838 } 4839 return false; 4840 } 4841 // Allow some constructs (except teams and cancellation constructs) to be 4842 // orphaned (they could be used in functions, called from OpenMP regions 4843 // with the required preconditions). 4844 if (ParentRegion == OMPD_unknown && 4845 !isOpenMPNestingTeamsDirective(CurrentRegion) && 4846 CurrentRegion != OMPD_cancellation_point && 4847 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan) 4848 return false; 4849 // Checks needed for mapping "loop" construct. Please check mapLoopConstruct 4850 // for a detailed explanation 4851 if (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion == OMPD_loop && 4852 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) && 4853 (isOpenMPWorksharingDirective(ParentRegion) || 4854 EnclosingConstruct == OMPD_loop)) { 4855 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4; 4856 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region) 4857 << true << getOpenMPDirectiveName(ParentRegion) << ErrorMsgNumber 4858 << getOpenMPDirectiveName(CurrentRegion); 4859 return true; 4860 } 4861 if (CurrentRegion == OMPD_cancellation_point || 4862 CurrentRegion == OMPD_cancel) { 4863 // OpenMP [2.16, Nesting of Regions] 4864 // A cancellation point construct for which construct-type-clause is 4865 // taskgroup must be nested inside a task construct. A cancellation 4866 // point construct for which construct-type-clause is not taskgroup must 4867 // be closely nested inside an OpenMP construct that matches the type 4868 // specified in construct-type-clause. 4869 // A cancel construct for which construct-type-clause is taskgroup must be 4870 // nested inside a task construct. A cancel construct for which 4871 // construct-type-clause is not taskgroup must be closely nested inside an 4872 // OpenMP construct that matches the type specified in 4873 // construct-type-clause. 4874 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(ParentRegion); 4875 if (CancelRegion == OMPD_taskgroup) { 4876 NestingProhibited = EnclosingConstruct != OMPD_task && 4877 (SemaRef.getLangOpts().OpenMP < 50 || 4878 EnclosingConstruct != OMPD_taskloop); 4879 } else if (CancelRegion == OMPD_sections) { 4880 NestingProhibited = EnclosingConstruct != OMPD_section && 4881 EnclosingConstruct != OMPD_sections; 4882 } else { 4883 NestingProhibited = CancelRegion != Leafs.back(); 4884 } 4885 OrphanSeen = ParentRegion == OMPD_unknown; 4886 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) { 4887 // OpenMP 5.1 [2.22, Nesting of Regions] 4888 // A masked region may not be closely nested inside a worksharing, loop, 4889 // atomic, task, or taskloop region. 4890 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) || 4891 isOpenMPGenericLoopDirective(ParentRegion) || 4892 isOpenMPTaskingDirective(ParentRegion); 4893 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) { 4894 // OpenMP [2.16, Nesting of Regions] 4895 // A critical region may not be nested (closely or otherwise) inside a 4896 // critical region with the same name. Note that this restriction is not 4897 // sufficient to prevent deadlock. 4898 SourceLocation PreviousCriticalLoc; 4899 bool DeadLock = Stack->hasDirective( 4900 [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K, 4901 const DeclarationNameInfo &DNI, 4902 SourceLocation Loc) { 4903 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) { 4904 PreviousCriticalLoc = Loc; 4905 return true; 4906 } 4907 return false; 4908 }, 4909 false /* skip top directive */); 4910 if (DeadLock) { 4911 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name) 4912 << CurrentName.getName(); 4913 if (PreviousCriticalLoc.isValid()) 4914 SemaRef.Diag(PreviousCriticalLoc, 4915 diag::note_omp_previous_critical_region); 4916 return true; 4917 } 4918 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) { 4919 // OpenMP 5.1 [2.22, Nesting of Regions] 4920 // A scope region may not be closely nested inside a worksharing, loop, 4921 // task, taskloop, critical, ordered, atomic, or masked region. 4922 // OpenMP 5.1 [2.22, Nesting of Regions] 4923 // A barrier region may not be closely nested inside a worksharing, loop, 4924 // task, taskloop, critical, ordered, atomic, or masked region. 4925 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) || 4926 isOpenMPGenericLoopDirective(ParentRegion) || 4927 isOpenMPTaskingDirective(ParentRegion) || 4928 llvm::is_contained({OMPD_masked, OMPD_master, 4929 OMPD_critical, OMPD_ordered}, 4930 EnclosingConstruct); 4931 } else if (isOpenMPWorksharingDirective(CurrentRegion) && 4932 !isOpenMPParallelDirective(CurrentRegion) && 4933 !isOpenMPTeamsDirective(CurrentRegion)) { 4934 // OpenMP 5.1 [2.22, Nesting of Regions] 4935 // A loop region that binds to a parallel region or a worksharing region 4936 // may not be closely nested inside a worksharing, loop, task, taskloop, 4937 // critical, ordered, atomic, or masked region. 4938 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) || 4939 isOpenMPGenericLoopDirective(ParentRegion) || 4940 isOpenMPTaskingDirective(ParentRegion) || 4941 llvm::is_contained({OMPD_masked, OMPD_master, 4942 OMPD_critical, OMPD_ordered}, 4943 EnclosingConstruct); 4944 Recommend = ShouldBeInParallelRegion; 4945 } else if (CurrentRegion == OMPD_ordered) { 4946 // OpenMP [2.16, Nesting of Regions] 4947 // An ordered region may not be closely nested inside a critical, 4948 // atomic, or explicit task region. 4949 // An ordered region must be closely nested inside a loop region (or 4950 // parallel loop region) with an ordered clause. 4951 // OpenMP [2.8.1,simd Construct, Restrictions] 4952 // An ordered construct with the simd clause is the only OpenMP construct 4953 // that can appear in the simd region. 4954 NestingProhibited = EnclosingConstruct == OMPD_critical || 4955 isOpenMPTaskingDirective(ParentRegion) || 4956 !(isOpenMPSimdDirective(ParentRegion) || 4957 Stack->isParentOrderedRegion()); 4958 Recommend = ShouldBeInOrderedRegion; 4959 } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) { 4960 // OpenMP [2.16, Nesting of Regions] 4961 // If specified, a teams construct must be contained within a target 4962 // construct. 4963 NestingProhibited = 4964 (SemaRef.LangOpts.OpenMP <= 45 && EnclosingConstruct != OMPD_target) || 4965 (SemaRef.LangOpts.OpenMP >= 50 && EnclosingConstruct != OMPD_unknown && 4966 EnclosingConstruct != OMPD_target); 4967 OrphanSeen = ParentRegion == OMPD_unknown; 4968 Recommend = ShouldBeInTargetRegion; 4969 } else if (CurrentRegion == OMPD_scan) { 4970 if (SemaRef.LangOpts.OpenMP >= 50) { 4971 // OpenMP spec 5.0 and 5.1 require scan to be directly enclosed by for, 4972 // simd, or for simd. This has to take into account combined directives. 4973 // In 5.2 this seems to be implied by the fact that the specified 4974 // separated constructs are do, for, and simd. 4975 NestingProhibited = !llvm::is_contained( 4976 {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct); 4977 } else { 4978 NestingProhibited = true; 4979 } 4980 OrphanSeen = ParentRegion == OMPD_unknown; 4981 Recommend = ShouldBeInLoopSimdRegion; 4982 } 4983 if (!NestingProhibited && !isOpenMPTargetExecutionDirective(CurrentRegion) && 4984 !isOpenMPTargetDataManagementDirective(CurrentRegion) && 4985 EnclosingConstruct == OMPD_teams) { 4986 // OpenMP [5.1, 2.22, Nesting of Regions] 4987 // distribute, distribute simd, distribute parallel worksharing-loop, 4988 // distribute parallel worksharing-loop SIMD, loop, parallel regions, 4989 // including any parallel regions arising from combined constructs, 4990 // omp_get_num_teams() regions, and omp_get_team_num() regions are the 4991 // only OpenMP regions that may be strictly nested inside the teams 4992 // region. 4993 // 4994 // As an extension, we permit atomic within teams as well. 4995 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) && 4996 !isOpenMPDistributeDirective(CurrentRegion) && 4997 CurrentRegion != OMPD_loop && 4998 !(SemaRef.getLangOpts().OpenMPExtensions && 4999 CurrentRegion == OMPD_atomic); 5000 Recommend = ShouldBeInParallelRegion; 5001 } 5002 if (!NestingProhibited && CurrentRegion == OMPD_loop) { 5003 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions] 5004 // If the bind clause is present on the loop construct and binding is 5005 // teams then the corresponding loop region must be strictly nested inside 5006 // a teams region. 5007 NestingProhibited = 5008 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams; 5009 Recommend = ShouldBeInTeamsRegion; 5010 } 5011 if (!NestingProhibited && isOpenMPNestingDistributeDirective(CurrentRegion)) { 5012 // OpenMP 4.5 [2.17 Nesting of Regions] 5013 // The region associated with the distribute construct must be strictly 5014 // nested inside a teams region 5015 NestingProhibited = EnclosingConstruct != OMPD_teams; 5016 Recommend = ShouldBeInTeamsRegion; 5017 } 5018 if (!NestingProhibited && 5019 (isOpenMPTargetExecutionDirective(CurrentRegion) || 5020 isOpenMPTargetDataManagementDirective(CurrentRegion))) { 5021 // OpenMP 4.5 [2.17 Nesting of Regions] 5022 // If a target, target update, target data, target enter data, or 5023 // target exit data construct is encountered during execution of a 5024 // target region, the behavior is unspecified. 5025 NestingProhibited = Stack->hasDirective( 5026 [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &, 5027 SourceLocation) { 5028 if (isOpenMPTargetExecutionDirective(K)) { 5029 OffendingRegion = K; 5030 return true; 5031 } 5032 return false; 5033 }, 5034 false /* don't skip top directive */); 5035 CloseNesting = false; 5036 } 5037 if (NestingProhibited) { 5038 if (OrphanSeen) { 5039 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive) 5040 << getOpenMPDirectiveName(CurrentRegion) << Recommend; 5041 } else { 5042 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region) 5043 << CloseNesting << getOpenMPDirectiveName(OffendingRegion) 5044 << Recommend << getOpenMPDirectiveName(CurrentRegion); 5045 } 5046 return true; 5047 } 5048 return false; 5049 } 5050 5051 struct Kind2Unsigned { 5052 using argument_type = OpenMPDirectiveKind; 5053 unsigned operator()(argument_type DK) { return unsigned(DK); } 5054 }; 5055 static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind, 5056 ArrayRef<OMPClause *> Clauses, 5057 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) { 5058 bool ErrorFound = false; 5059 unsigned NamedModifiersNumber = 0; 5060 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers; 5061 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1); 5062 SmallVector<SourceLocation, 4> NameModifierLoc; 5063 for (const OMPClause *C : Clauses) { 5064 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) { 5065 // At most one if clause without a directive-name-modifier can appear on 5066 // the directive. 5067 OpenMPDirectiveKind CurNM = IC->getNameModifier(); 5068 if (FoundNameModifiers[CurNM]) { 5069 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause) 5070 << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if) 5071 << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM); 5072 ErrorFound = true; 5073 } else if (CurNM != OMPD_unknown) { 5074 NameModifierLoc.push_back(IC->getNameModifierLoc()); 5075 ++NamedModifiersNumber; 5076 } 5077 FoundNameModifiers[CurNM] = IC; 5078 if (CurNM == OMPD_unknown) 5079 continue; 5080 // Check if the specified name modifier is allowed for the current 5081 // directive. 5082 // At most one if clause with the particular directive-name-modifier can 5083 // appear on the directive. 5084 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) { 5085 S.Diag(IC->getNameModifierLoc(), 5086 diag::err_omp_wrong_if_directive_name_modifier) 5087 << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind); 5088 ErrorFound = true; 5089 } 5090 } 5091 } 5092 // If any if clause on the directive includes a directive-name-modifier then 5093 // all if clauses on the directive must include a directive-name-modifier. 5094 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) { 5095 if (NamedModifiersNumber == AllowedNameModifiers.size()) { 5096 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(), 5097 diag::err_omp_no_more_if_clause); 5098 } else { 5099 std::string Values; 5100 std::string Sep(", "); 5101 unsigned AllowedCnt = 0; 5102 unsigned TotalAllowedNum = 5103 AllowedNameModifiers.size() - NamedModifiersNumber; 5104 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End; 5105 ++Cnt) { 5106 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt]; 5107 if (!FoundNameModifiers[NM]) { 5108 Values += "'"; 5109 Values += getOpenMPDirectiveName(NM); 5110 Values += "'"; 5111 if (AllowedCnt + 2 == TotalAllowedNum) 5112 Values += " or "; 5113 else if (AllowedCnt + 1 != TotalAllowedNum) 5114 Values += Sep; 5115 ++AllowedCnt; 5116 } 5117 } 5118 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(), 5119 diag::err_omp_unnamed_if_clause) 5120 << (TotalAllowedNum > 1) << Values; 5121 } 5122 for (SourceLocation Loc : NameModifierLoc) { 5123 S.Diag(Loc, diag::note_omp_previous_named_if_clause); 5124 } 5125 ErrorFound = true; 5126 } 5127 return ErrorFound; 5128 } 5129 5130 static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr, 5131 SourceLocation &ELoc, 5132 SourceRange &ERange, 5133 bool AllowArraySection, 5134 StringRef DiagType) { 5135 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() || 5136 RefExpr->containsUnexpandedParameterPack()) 5137 return std::make_pair(nullptr, true); 5138 5139 // OpenMP [3.1, C/C++] 5140 // A list item is a variable name. 5141 // OpenMP [2.9.3.3, Restrictions, p.1] 5142 // A variable that is part of another variable (as an array or 5143 // structure element) cannot appear in a private clause. 5144 RefExpr = RefExpr->IgnoreParens(); 5145 enum { 5146 NoArrayExpr = -1, 5147 ArraySubscript = 0, 5148 OMPArraySection = 1 5149 } IsArrayExpr = NoArrayExpr; 5150 if (AllowArraySection) { 5151 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) { 5152 Expr *Base = ASE->getBase()->IgnoreParenImpCasts(); 5153 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 5154 Base = TempASE->getBase()->IgnoreParenImpCasts(); 5155 RefExpr = Base; 5156 IsArrayExpr = ArraySubscript; 5157 } else if (auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) { 5158 Expr *Base = OASE->getBase()->IgnoreParenImpCasts(); 5159 while (auto *TempOASE = dyn_cast<ArraySectionExpr>(Base)) 5160 Base = TempOASE->getBase()->IgnoreParenImpCasts(); 5161 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 5162 Base = TempASE->getBase()->IgnoreParenImpCasts(); 5163 RefExpr = Base; 5164 IsArrayExpr = OMPArraySection; 5165 } 5166 } 5167 ELoc = RefExpr->getExprLoc(); 5168 ERange = RefExpr->getSourceRange(); 5169 RefExpr = RefExpr->IgnoreParenImpCasts(); 5170 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr); 5171 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr); 5172 if ((!DE || !isa<VarDecl>(DE->getDecl())) && 5173 (S.getCurrentThisType().isNull() || !ME || 5174 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) || 5175 !isa<FieldDecl>(ME->getMemberDecl()))) { 5176 if (IsArrayExpr != NoArrayExpr) { 5177 S.Diag(ELoc, diag::err_omp_expected_base_var_name) 5178 << IsArrayExpr << ERange; 5179 } else if (!DiagType.empty()) { 5180 unsigned DiagSelect = S.getLangOpts().CPlusPlus 5181 ? (S.getCurrentThisType().isNull() ? 1 : 2) 5182 : 0; 5183 S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type) 5184 << DiagSelect << DiagType << ERange; 5185 } else { 5186 S.Diag(ELoc, 5187 AllowArraySection 5188 ? diag::err_omp_expected_var_name_member_expr_or_array_item 5189 : diag::err_omp_expected_var_name_member_expr) 5190 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange; 5191 } 5192 return std::make_pair(nullptr, false); 5193 } 5194 return std::make_pair( 5195 getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false); 5196 } 5197 5198 namespace { 5199 /// Checks if the allocator is used in uses_allocators clause to be allowed in 5200 /// target regions. 5201 class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> { 5202 DSAStackTy *S = nullptr; 5203 5204 public: 5205 bool VisitDeclRefExpr(const DeclRefExpr *E) { 5206 return S->isUsesAllocatorsDecl(E->getDecl()) 5207 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) == 5208 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait; 5209 } 5210 bool VisitStmt(const Stmt *S) { 5211 for (const Stmt *Child : S->children()) { 5212 if (Child && Visit(Child)) 5213 return true; 5214 } 5215 return false; 5216 } 5217 explicit AllocatorChecker(DSAStackTy *S) : S(S) {} 5218 }; 5219 } // namespace 5220 5221 static void checkAllocateClauses(Sema &S, DSAStackTy *Stack, 5222 ArrayRef<OMPClause *> Clauses) { 5223 assert(!S.CurContext->isDependentContext() && 5224 "Expected non-dependent context."); 5225 auto AllocateRange = 5226 llvm::make_filter_range(Clauses, OMPAllocateClause::classof); 5227 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy; 5228 auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) { 5229 return isOpenMPPrivate(C->getClauseKind()); 5230 }); 5231 for (OMPClause *Cl : PrivateRange) { 5232 MutableArrayRef<Expr *>::iterator I, It, Et; 5233 if (Cl->getClauseKind() == OMPC_private) { 5234 auto *PC = cast<OMPPrivateClause>(Cl); 5235 I = PC->private_copies().begin(); 5236 It = PC->varlist_begin(); 5237 Et = PC->varlist_end(); 5238 } else if (Cl->getClauseKind() == OMPC_firstprivate) { 5239 auto *PC = cast<OMPFirstprivateClause>(Cl); 5240 I = PC->private_copies().begin(); 5241 It = PC->varlist_begin(); 5242 Et = PC->varlist_end(); 5243 } else if (Cl->getClauseKind() == OMPC_lastprivate) { 5244 auto *PC = cast<OMPLastprivateClause>(Cl); 5245 I = PC->private_copies().begin(); 5246 It = PC->varlist_begin(); 5247 Et = PC->varlist_end(); 5248 } else if (Cl->getClauseKind() == OMPC_linear) { 5249 auto *PC = cast<OMPLinearClause>(Cl); 5250 I = PC->privates().begin(); 5251 It = PC->varlist_begin(); 5252 Et = PC->varlist_end(); 5253 } else if (Cl->getClauseKind() == OMPC_reduction) { 5254 auto *PC = cast<OMPReductionClause>(Cl); 5255 I = PC->privates().begin(); 5256 It = PC->varlist_begin(); 5257 Et = PC->varlist_end(); 5258 } else if (Cl->getClauseKind() == OMPC_task_reduction) { 5259 auto *PC = cast<OMPTaskReductionClause>(Cl); 5260 I = PC->privates().begin(); 5261 It = PC->varlist_begin(); 5262 Et = PC->varlist_end(); 5263 } else if (Cl->getClauseKind() == OMPC_in_reduction) { 5264 auto *PC = cast<OMPInReductionClause>(Cl); 5265 I = PC->privates().begin(); 5266 It = PC->varlist_begin(); 5267 Et = PC->varlist_end(); 5268 } else { 5269 llvm_unreachable("Expected private clause."); 5270 } 5271 for (Expr *E : llvm::make_range(It, Et)) { 5272 if (!*I) { 5273 ++I; 5274 continue; 5275 } 5276 SourceLocation ELoc; 5277 SourceRange ERange; 5278 Expr *SimpleRefExpr = E; 5279 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange, 5280 /*AllowArraySection=*/true); 5281 DeclToCopy.try_emplace(Res.first, 5282 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl())); 5283 ++I; 5284 } 5285 } 5286 for (OMPClause *C : AllocateRange) { 5287 auto *AC = cast<OMPAllocateClause>(C); 5288 if (S.getLangOpts().OpenMP >= 50 && 5289 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() && 5290 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) && 5291 AC->getAllocator()) { 5292 Expr *Allocator = AC->getAllocator(); 5293 // OpenMP, 2.12.5 target Construct 5294 // Memory allocators that do not appear in a uses_allocators clause cannot 5295 // appear as an allocator in an allocate clause or be used in the target 5296 // region unless a requires directive with the dynamic_allocators clause 5297 // is present in the same compilation unit. 5298 AllocatorChecker Checker(Stack); 5299 if (Checker.Visit(Allocator)) 5300 S.Diag(Allocator->getExprLoc(), 5301 diag::err_omp_allocator_not_in_uses_allocators) 5302 << Allocator->getSourceRange(); 5303 } 5304 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind = 5305 getAllocatorKind(S, Stack, AC->getAllocator()); 5306 // OpenMP, 2.11.4 allocate Clause, Restrictions. 5307 // For task, taskloop or target directives, allocation requests to memory 5308 // allocators with the trait access set to thread result in unspecified 5309 // behavior. 5310 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc && 5311 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) || 5312 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) { 5313 S.Diag(AC->getAllocator()->getExprLoc(), 5314 diag::warn_omp_allocate_thread_on_task_target_directive) 5315 << getOpenMPDirectiveName(Stack->getCurrentDirective()); 5316 } 5317 for (Expr *E : AC->varlist()) { 5318 SourceLocation ELoc; 5319 SourceRange ERange; 5320 Expr *SimpleRefExpr = E; 5321 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange); 5322 ValueDecl *VD = Res.first; 5323 if (!VD) 5324 continue; 5325 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false); 5326 if (!isOpenMPPrivate(Data.CKind)) { 5327 S.Diag(E->getExprLoc(), 5328 diag::err_omp_expected_private_copy_for_allocate); 5329 continue; 5330 } 5331 VarDecl *PrivateVD = DeclToCopy[VD]; 5332 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD, 5333 AllocatorKind, AC->getAllocator())) 5334 continue; 5335 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(), 5336 AC->getAlignment(), E->getSourceRange()); 5337 } 5338 } 5339 } 5340 5341 namespace { 5342 /// Rewrite statements and expressions for Sema \p Actions CurContext. 5343 /// 5344 /// Used to wrap already parsed statements/expressions into a new CapturedStmt 5345 /// context. DeclRefExpr used inside the new context are changed to refer to the 5346 /// captured variable instead. 5347 class CaptureVars : public TreeTransform<CaptureVars> { 5348 using BaseTransform = TreeTransform<CaptureVars>; 5349 5350 public: 5351 CaptureVars(Sema &Actions) : BaseTransform(Actions) {} 5352 5353 bool AlwaysRebuild() { return true; } 5354 }; 5355 } // namespace 5356 5357 static VarDecl *precomputeExpr(Sema &Actions, 5358 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E, 5359 StringRef Name) { 5360 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E)); 5361 VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr, 5362 dyn_cast<DeclRefExpr>(E->IgnoreImplicit())); 5363 auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess( 5364 Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {}))); 5365 Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false); 5366 BodyStmts.push_back(NewDeclStmt); 5367 return NewVar; 5368 } 5369 5370 /// Create a closure that computes the number of iterations of a loop. 5371 /// 5372 /// \param Actions The Sema object. 5373 /// \param LogicalTy Type for the logical iteration number. 5374 /// \param Rel Comparison operator of the loop condition. 5375 /// \param StartExpr Value of the loop counter at the first iteration. 5376 /// \param StopExpr Expression the loop counter is compared against in the loop 5377 /// condition. \param StepExpr Amount of increment after each iteration. 5378 /// 5379 /// \return Closure (CapturedStmt) of the distance calculation. 5380 static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy, 5381 BinaryOperator::Opcode Rel, 5382 Expr *StartExpr, Expr *StopExpr, 5383 Expr *StepExpr) { 5384 ASTContext &Ctx = Actions.getASTContext(); 5385 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy); 5386 5387 // Captured regions currently don't support return values, we use an 5388 // out-parameter instead. All inputs are implicit captures. 5389 // TODO: Instead of capturing each DeclRefExpr occurring in 5390 // StartExpr/StopExpr/Step, these could also be passed as a value capture. 5391 QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy); 5392 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy}, 5393 {StringRef(), QualType()}}; 5394 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params); 5395 5396 Stmt *Body; 5397 { 5398 Sema::CompoundScopeRAII CompoundScope(Actions); 5399 CapturedDecl *CS = cast<CapturedDecl>(Actions.CurContext); 5400 5401 // Get the LValue expression for the result. 5402 ImplicitParamDecl *DistParam = CS->getParam(0); 5403 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr( 5404 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr); 5405 5406 SmallVector<Stmt *, 4> BodyStmts; 5407 5408 // Capture all referenced variable references. 5409 // TODO: Instead of computing NewStart/NewStop/NewStep inside the 5410 // CapturedStmt, we could compute them before and capture the result, to be 5411 // used jointly with the LoopVar function. 5412 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start"); 5413 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop"); 5414 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step"); 5415 auto BuildVarRef = [&](VarDecl *VD) { 5416 return buildDeclRefExpr(Actions, VD, VD->getType(), {}); 5417 }; 5418 5419 IntegerLiteral *Zero = IntegerLiteral::Create( 5420 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {}); 5421 IntegerLiteral *One = IntegerLiteral::Create( 5422 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {}); 5423 Expr *Dist; 5424 if (Rel == BO_NE) { 5425 // When using a != comparison, the increment can be +1 or -1. This can be 5426 // dynamic at runtime, so we need to check for the direction. 5427 Expr *IsNegStep = AssertSuccess( 5428 Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero)); 5429 5430 // Positive increment. 5431 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp( 5432 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart))); 5433 ForwardRange = AssertSuccess( 5434 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange)); 5435 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp( 5436 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep))); 5437 5438 // Negative increment. 5439 Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp( 5440 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop))); 5441 BackwardRange = AssertSuccess( 5442 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange)); 5443 Expr *NegIncAmount = AssertSuccess( 5444 Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep))); 5445 Expr *BackwardDist = AssertSuccess( 5446 Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount)); 5447 5448 // Use the appropriate case. 5449 Dist = AssertSuccess(Actions.ActOnConditionalOp( 5450 {}, {}, IsNegStep, BackwardDist, ForwardDist)); 5451 } else { 5452 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) && 5453 "Expected one of these relational operators"); 5454 5455 // We can derive the direction from any other comparison operator. It is 5456 // non well-formed OpenMP if Step increments/decrements in the other 5457 // directions. Whether at least the first iteration passes the loop 5458 // condition. 5459 Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp( 5460 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop))); 5461 5462 // Compute the range between first and last counter value. 5463 Expr *Range; 5464 if (Rel == BO_GE || Rel == BO_GT) 5465 Range = AssertSuccess(Actions.BuildBinOp( 5466 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop))); 5467 else 5468 Range = AssertSuccess(Actions.BuildBinOp( 5469 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart))); 5470 5471 // Ensure unsigned range space. 5472 Range = 5473 AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range)); 5474 5475 if (Rel == BO_LE || Rel == BO_GE) { 5476 // Add one to the range if the relational operator is inclusive. 5477 Range = 5478 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One)); 5479 } 5480 5481 // Divide by the absolute step amount. If the range is not a multiple of 5482 // the step size, rounding-up the effective upper bound ensures that the 5483 // last iteration is included. 5484 // Note that the rounding-up may cause an overflow in a temporary that 5485 // could be avoided, but would have occurred in a C-style for-loop as 5486 // well. 5487 Expr *Divisor = BuildVarRef(NewStep); 5488 if (Rel == BO_GE || Rel == BO_GT) 5489 Divisor = 5490 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor)); 5491 Expr *DivisorMinusOne = 5492 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One)); 5493 Expr *RangeRoundUp = AssertSuccess( 5494 Actions.BuildBinOp(nullptr, {}, BO_Add, Range, DivisorMinusOne)); 5495 Dist = AssertSuccess( 5496 Actions.BuildBinOp(nullptr, {}, BO_Div, RangeRoundUp, Divisor)); 5497 5498 // If there is not at least one iteration, the range contains garbage. Fix 5499 // to zero in this case. 5500 Dist = AssertSuccess( 5501 Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero)); 5502 } 5503 5504 // Assign the result to the out-parameter. 5505 Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp( 5506 Actions.getCurScope(), {}, BO_Assign, DistRef, Dist)); 5507 BodyStmts.push_back(ResultAssign); 5508 5509 Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false)); 5510 } 5511 5512 return cast<CapturedStmt>( 5513 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body))); 5514 } 5515 5516 /// Create a closure that computes the loop variable from the logical iteration 5517 /// number. 5518 /// 5519 /// \param Actions The Sema object. 5520 /// \param LoopVarTy Type for the loop variable used for result value. 5521 /// \param LogicalTy Type for the logical iteration number. 5522 /// \param StartExpr Value of the loop counter at the first iteration. 5523 /// \param Step Amount of increment after each iteration. 5524 /// \param Deref Whether the loop variable is a dereference of the loop 5525 /// counter variable. 5526 /// 5527 /// \return Closure (CapturedStmt) of the loop value calculation. 5528 static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy, 5529 QualType LogicalTy, 5530 DeclRefExpr *StartExpr, Expr *Step, 5531 bool Deref) { 5532 ASTContext &Ctx = Actions.getASTContext(); 5533 5534 // Pass the result as an out-parameter. Passing as return value would require 5535 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to 5536 // invoke a copy constructor. 5537 QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy); 5538 SemaOpenMP::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy}, 5539 {"Logical", LogicalTy}, 5540 {StringRef(), QualType()}}; 5541 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params); 5542 5543 // Capture the initial iterator which represents the LoopVar value at the 5544 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update 5545 // it in every iteration, capture it by value before it is modified. 5546 VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl()); 5547 bool Invalid = Actions.tryCaptureVariable(StartVar, {}, 5548 Sema::TryCapture_ExplicitByVal, {}); 5549 (void)Invalid; 5550 assert(!Invalid && "Expecting capture-by-value to work."); 5551 5552 Expr *Body; 5553 { 5554 Sema::CompoundScopeRAII CompoundScope(Actions); 5555 auto *CS = cast<CapturedDecl>(Actions.CurContext); 5556 5557 ImplicitParamDecl *TargetParam = CS->getParam(0); 5558 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr( 5559 TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr); 5560 ImplicitParamDecl *IndvarParam = CS->getParam(1); 5561 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr( 5562 IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr); 5563 5564 // Capture the Start expression. 5565 CaptureVars Recap(Actions); 5566 Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr)); 5567 Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step)); 5568 5569 Expr *Skip = AssertSuccess( 5570 Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef)); 5571 // TODO: Explicitly cast to the iterator's difference_type instead of 5572 // relying on implicit conversion. 5573 Expr *Advanced = 5574 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip)); 5575 5576 if (Deref) { 5577 // For range-based for-loops convert the loop counter value to a concrete 5578 // loop variable value by dereferencing the iterator. 5579 Advanced = 5580 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced)); 5581 } 5582 5583 // Assign the result to the output parameter. 5584 Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {}, 5585 BO_Assign, TargetRef, Advanced)); 5586 } 5587 return cast<CapturedStmt>( 5588 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body))); 5589 } 5590 5591 StmtResult SemaOpenMP::ActOnOpenMPCanonicalLoop(Stmt *AStmt) { 5592 ASTContext &Ctx = getASTContext(); 5593 5594 // Extract the common elements of ForStmt and CXXForRangeStmt: 5595 // Loop variable, repeat condition, increment 5596 Expr *Cond, *Inc; 5597 VarDecl *LIVDecl, *LUVDecl; 5598 if (auto *For = dyn_cast<ForStmt>(AStmt)) { 5599 Stmt *Init = For->getInit(); 5600 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) { 5601 // For statement declares loop variable. 5602 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl()); 5603 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) { 5604 // For statement reuses variable. 5605 assert(LCAssign->getOpcode() == BO_Assign && 5606 "init part must be a loop variable assignment"); 5607 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS()); 5608 LIVDecl = cast<VarDecl>(CounterRef->getDecl()); 5609 } else 5610 llvm_unreachable("Cannot determine loop variable"); 5611 LUVDecl = LIVDecl; 5612 5613 Cond = For->getCond(); 5614 Inc = For->getInc(); 5615 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) { 5616 DeclStmt *BeginStmt = RangeFor->getBeginStmt(); 5617 LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl()); 5618 LUVDecl = RangeFor->getLoopVariable(); 5619 5620 Cond = RangeFor->getCond(); 5621 Inc = RangeFor->getInc(); 5622 } else 5623 llvm_unreachable("unhandled kind of loop"); 5624 5625 QualType CounterTy = LIVDecl->getType(); 5626 QualType LVTy = LUVDecl->getType(); 5627 5628 // Analyze the loop condition. 5629 Expr *LHS, *RHS; 5630 BinaryOperator::Opcode CondRel; 5631 Cond = Cond->IgnoreImplicit(); 5632 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) { 5633 LHS = CondBinExpr->getLHS(); 5634 RHS = CondBinExpr->getRHS(); 5635 CondRel = CondBinExpr->getOpcode(); 5636 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) { 5637 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands"); 5638 LHS = CondCXXOp->getArg(0); 5639 RHS = CondCXXOp->getArg(1); 5640 switch (CondCXXOp->getOperator()) { 5641 case OO_ExclaimEqual: 5642 CondRel = BO_NE; 5643 break; 5644 case OO_Less: 5645 CondRel = BO_LT; 5646 break; 5647 case OO_LessEqual: 5648 CondRel = BO_LE; 5649 break; 5650 case OO_Greater: 5651 CondRel = BO_GT; 5652 break; 5653 case OO_GreaterEqual: 5654 CondRel = BO_GE; 5655 break; 5656 default: 5657 llvm_unreachable("unexpected iterator operator"); 5658 } 5659 } else 5660 llvm_unreachable("unexpected loop condition"); 5661 5662 // Normalize such that the loop counter is on the LHS. 5663 if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) || 5664 cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) { 5665 std::swap(LHS, RHS); 5666 CondRel = BinaryOperator::reverseComparisonOp(CondRel); 5667 } 5668 auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit()); 5669 5670 // Decide the bit width for the logical iteration counter. By default use the 5671 // unsigned ptrdiff_t integer size (for iterators and pointers). 5672 // TODO: For iterators, use iterator::difference_type, 5673 // std::iterator_traits<>::difference_type or decltype(it - end). 5674 QualType LogicalTy = Ctx.getUnsignedPointerDiffType(); 5675 if (CounterTy->isIntegerType()) { 5676 unsigned BitWidth = Ctx.getIntWidth(CounterTy); 5677 LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false); 5678 } 5679 5680 // Analyze the loop increment. 5681 Expr *Step; 5682 if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) { 5683 int Direction; 5684 switch (IncUn->getOpcode()) { 5685 case UO_PreInc: 5686 case UO_PostInc: 5687 Direction = 1; 5688 break; 5689 case UO_PreDec: 5690 case UO_PostDec: 5691 Direction = -1; 5692 break; 5693 default: 5694 llvm_unreachable("unhandled unary increment operator"); 5695 } 5696 Step = IntegerLiteral::Create( 5697 Ctx, 5698 llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction, /*isSigned=*/true), 5699 LogicalTy, {}); 5700 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) { 5701 if (IncBin->getOpcode() == BO_AddAssign) { 5702 Step = IncBin->getRHS(); 5703 } else if (IncBin->getOpcode() == BO_SubAssign) { 5704 Step = AssertSuccess( 5705 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS())); 5706 } else 5707 llvm_unreachable("unhandled binary increment operator"); 5708 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) { 5709 switch (CondCXXOp->getOperator()) { 5710 case OO_PlusPlus: 5711 Step = IntegerLiteral::Create( 5712 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {}); 5713 break; 5714 case OO_MinusMinus: 5715 Step = IntegerLiteral::Create( 5716 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {}); 5717 break; 5718 case OO_PlusEqual: 5719 Step = CondCXXOp->getArg(1); 5720 break; 5721 case OO_MinusEqual: 5722 Step = AssertSuccess( 5723 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1))); 5724 break; 5725 default: 5726 llvm_unreachable("unhandled overloaded increment operator"); 5727 } 5728 } else 5729 llvm_unreachable("unknown increment expression"); 5730 5731 CapturedStmt *DistanceFunc = 5732 buildDistanceFunc(SemaRef, LogicalTy, CondRel, LHS, RHS, Step); 5733 CapturedStmt *LoopVarFunc = buildLoopVarFunc( 5734 SemaRef, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt)); 5735 DeclRefExpr *LVRef = 5736 SemaRef.BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue, {}, 5737 nullptr, nullptr, {}, nullptr); 5738 return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc, 5739 LoopVarFunc, LVRef); 5740 } 5741 5742 StmtResult SemaOpenMP::ActOnOpenMPLoopnest(Stmt *AStmt) { 5743 // Handle a literal loop. 5744 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt)) 5745 return ActOnOpenMPCanonicalLoop(AStmt); 5746 5747 // If not a literal loop, it must be the result of a loop transformation. 5748 OMPExecutableDirective *LoopTransform = cast<OMPExecutableDirective>(AStmt); 5749 assert( 5750 isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) && 5751 "Loop transformation directive expected"); 5752 return LoopTransform; 5753 } 5754 5755 static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, 5756 CXXScopeSpec &MapperIdScopeSpec, 5757 const DeclarationNameInfo &MapperId, 5758 QualType Type, 5759 Expr *UnresolvedMapper); 5760 5761 /// Perform DFS through the structure/class data members trying to find 5762 /// member(s) with user-defined 'default' mapper and generate implicit map 5763 /// clauses for such members with the found 'default' mapper. 5764 static void 5765 processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack, 5766 SmallVectorImpl<OMPClause *> &Clauses) { 5767 // Check for the default mapper for data members. 5768 if (S.getLangOpts().OpenMP < 50) 5769 return; 5770 SmallVector<OMPClause *, 4> ImplicitMaps; 5771 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) { 5772 auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]); 5773 if (!C) 5774 continue; 5775 SmallVector<Expr *, 4> SubExprs; 5776 auto *MI = C->mapperlist_begin(); 5777 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End; 5778 ++I, ++MI) { 5779 // Expression is mapped using mapper - skip it. 5780 if (*MI) 5781 continue; 5782 Expr *E = *I; 5783 // Expression is dependent - skip it, build the mapper when it gets 5784 // instantiated. 5785 if (E->isTypeDependent() || E->isValueDependent() || 5786 E->containsUnexpandedParameterPack()) 5787 continue; 5788 // Array section - need to check for the mapping of the array section 5789 // element. 5790 QualType CanonType = E->getType().getCanonicalType(); 5791 if (CanonType->isSpecificBuiltinType(BuiltinType::ArraySection)) { 5792 const auto *OASE = cast<ArraySectionExpr>(E->IgnoreParenImpCasts()); 5793 QualType BaseType = 5794 ArraySectionExpr::getBaseOriginalType(OASE->getBase()); 5795 QualType ElemType; 5796 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe()) 5797 ElemType = ATy->getElementType(); 5798 else 5799 ElemType = BaseType->getPointeeType(); 5800 CanonType = ElemType; 5801 } 5802 5803 // DFS over data members in structures/classes. 5804 SmallVector<std::pair<QualType, FieldDecl *>, 4> Types( 5805 1, {CanonType, nullptr}); 5806 llvm::DenseMap<const Type *, Expr *> Visited; 5807 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain( 5808 1, {nullptr, 1}); 5809 while (!Types.empty()) { 5810 QualType BaseType; 5811 FieldDecl *CurFD; 5812 std::tie(BaseType, CurFD) = Types.pop_back_val(); 5813 while (ParentChain.back().second == 0) 5814 ParentChain.pop_back(); 5815 --ParentChain.back().second; 5816 if (BaseType.isNull()) 5817 continue; 5818 // Only structs/classes are allowed to have mappers. 5819 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl(); 5820 if (!RD) 5821 continue; 5822 auto It = Visited.find(BaseType.getTypePtr()); 5823 if (It == Visited.end()) { 5824 // Try to find the associated user-defined mapper. 5825 CXXScopeSpec MapperIdScopeSpec; 5826 DeclarationNameInfo DefaultMapperId; 5827 DefaultMapperId.setName(S.Context.DeclarationNames.getIdentifier( 5828 &S.Context.Idents.get("default"))); 5829 DefaultMapperId.setLoc(E->getExprLoc()); 5830 ExprResult ER = buildUserDefinedMapperRef( 5831 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId, 5832 BaseType, /*UnresolvedMapper=*/nullptr); 5833 if (ER.isInvalid()) 5834 continue; 5835 It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first; 5836 } 5837 // Found default mapper. 5838 if (It->second) { 5839 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType, 5840 VK_LValue, OK_Ordinary, E); 5841 OE->setIsUnique(/*V=*/true); 5842 Expr *BaseExpr = OE; 5843 for (const auto &P : ParentChain) { 5844 if (P.first) { 5845 BaseExpr = S.BuildMemberExpr( 5846 BaseExpr, /*IsArrow=*/false, E->getExprLoc(), 5847 NestedNameSpecifierLoc(), SourceLocation(), P.first, 5848 DeclAccessPair::make(P.first, P.first->getAccess()), 5849 /*HadMultipleCandidates=*/false, DeclarationNameInfo(), 5850 P.first->getType(), VK_LValue, OK_Ordinary); 5851 BaseExpr = S.DefaultLvalueConversion(BaseExpr).get(); 5852 } 5853 } 5854 if (CurFD) 5855 BaseExpr = S.BuildMemberExpr( 5856 BaseExpr, /*IsArrow=*/false, E->getExprLoc(), 5857 NestedNameSpecifierLoc(), SourceLocation(), CurFD, 5858 DeclAccessPair::make(CurFD, CurFD->getAccess()), 5859 /*HadMultipleCandidates=*/false, DeclarationNameInfo(), 5860 CurFD->getType(), VK_LValue, OK_Ordinary); 5861 SubExprs.push_back(BaseExpr); 5862 continue; 5863 } 5864 // Check for the "default" mapper for data members. 5865 bool FirstIter = true; 5866 for (FieldDecl *FD : RD->fields()) { 5867 if (!FD) 5868 continue; 5869 QualType FieldTy = FD->getType(); 5870 if (FieldTy.isNull() || 5871 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType())) 5872 continue; 5873 if (FirstIter) { 5874 FirstIter = false; 5875 ParentChain.emplace_back(CurFD, 1); 5876 } else { 5877 ++ParentChain.back().second; 5878 } 5879 Types.emplace_back(FieldTy, FD); 5880 } 5881 } 5882 } 5883 if (SubExprs.empty()) 5884 continue; 5885 CXXScopeSpec MapperIdScopeSpec; 5886 DeclarationNameInfo MapperId; 5887 if (OMPClause *NewClause = S.OpenMP().ActOnOpenMPMapClause( 5888 nullptr, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(), 5889 MapperIdScopeSpec, MapperId, C->getMapType(), 5890 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), 5891 SubExprs, OMPVarListLocTy())) 5892 Clauses.push_back(NewClause); 5893 } 5894 } 5895 5896 namespace { 5897 /// A 'teams loop' with a nested 'loop bind(parallel)' or generic function 5898 /// call in the associated loop-nest cannot be a 'parallel for'. 5899 class TeamsLoopChecker final : public ConstStmtVisitor<TeamsLoopChecker> { 5900 Sema &SemaRef; 5901 5902 public: 5903 bool teamsLoopCanBeParallelFor() const { return TeamsLoopCanBeParallelFor; } 5904 5905 // Is there a nested OpenMP loop bind(parallel) 5906 void VisitOMPExecutableDirective(const OMPExecutableDirective *D) { 5907 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) { 5908 if (const auto *C = D->getSingleClause<OMPBindClause>()) 5909 if (C->getBindKind() == OMPC_BIND_parallel) { 5910 TeamsLoopCanBeParallelFor = false; 5911 // No need to continue visiting any more 5912 return; 5913 } 5914 } 5915 for (const Stmt *Child : D->children()) 5916 if (Child) 5917 Visit(Child); 5918 } 5919 5920 void VisitCallExpr(const CallExpr *C) { 5921 // Function calls inhibit parallel loop translation of 'target teams loop' 5922 // unless the assume-no-nested-parallelism flag has been specified. 5923 // OpenMP API runtime library calls do not inhibit parallel loop 5924 // translation, regardless of the assume-no-nested-parallelism. 5925 bool IsOpenMPAPI = false; 5926 auto *FD = dyn_cast_or_null<FunctionDecl>(C->getCalleeDecl()); 5927 if (FD) { 5928 std::string Name = FD->getNameInfo().getAsString(); 5929 IsOpenMPAPI = Name.find("omp_") == 0; 5930 } 5931 TeamsLoopCanBeParallelFor = 5932 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism; 5933 if (!TeamsLoopCanBeParallelFor) 5934 return; 5935 5936 for (const Stmt *Child : C->children()) 5937 if (Child) 5938 Visit(Child); 5939 } 5940 5941 void VisitCapturedStmt(const CapturedStmt *S) { 5942 if (!S) 5943 return; 5944 Visit(S->getCapturedDecl()->getBody()); 5945 } 5946 5947 void VisitStmt(const Stmt *S) { 5948 if (!S) 5949 return; 5950 for (const Stmt *Child : S->children()) 5951 if (Child) 5952 Visit(Child); 5953 } 5954 explicit TeamsLoopChecker(Sema &SemaRef) 5955 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(true) {} 5956 5957 private: 5958 bool TeamsLoopCanBeParallelFor; 5959 }; 5960 } // namespace 5961 5962 static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) { 5963 TeamsLoopChecker Checker(SemaRef); 5964 Checker.Visit(AStmt); 5965 return Checker.teamsLoopCanBeParallelFor(); 5966 } 5967 5968 StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective( 5969 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, 5970 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses, 5971 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { 5972 assert(isOpenMPExecutableDirective(Kind) && "Unexpected directive category"); 5973 5974 StmtResult Res = StmtError(); 5975 OpenMPBindClauseKind BindKind = OMPC_BIND_unknown; 5976 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit; 5977 5978 if (const OMPBindClause *BC = 5979 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses)) 5980 BindKind = BC->getBindKind(); 5981 5982 if (Kind == OMPD_loop && BindKind == OMPC_BIND_unknown) { 5983 const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective(); 5984 5985 // Setting the enclosing teams or parallel construct for the loop 5986 // directive without bind clause. 5987 // [5.0:129:25-28] If the bind clause is not present on the construct and 5988 // the loop construct is closely nested inside a teams or parallel 5989 // construct, the binding region is the corresponding teams or parallel 5990 // region. If none of those conditions hold, the binding region is not 5991 // defined. 5992 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown 5993 ArrayRef<OpenMPDirectiveKind> ParentLeafs = 5994 getLeafConstructsOrSelf(ParentDirective); 5995 5996 if (ParentDirective == OMPD_unknown) { 5997 Diag(DSAStack->getDefaultDSALocation(), 5998 diag::err_omp_bind_required_on_loop); 5999 } else if (ParentLeafs.back() == OMPD_parallel) { 6000 BindKind = OMPC_BIND_parallel; 6001 } else if (ParentLeafs.back() == OMPD_teams) { 6002 BindKind = OMPC_BIND_teams; 6003 } 6004 6005 assert(BindKind != OMPC_BIND_unknown && "Expecting BindKind"); 6006 6007 OMPClause *C = 6008 ActOnOpenMPBindClause(BindKind, SourceLocation(), SourceLocation(), 6009 SourceLocation(), SourceLocation()); 6010 ClausesWithImplicit.push_back(C); 6011 } 6012 6013 // Diagnose "loop bind(teams)" with "reduction". 6014 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) { 6015 for (OMPClause *C : Clauses) { 6016 if (C->getClauseKind() == OMPC_reduction) 6017 Diag(DSAStack->getDefaultDSALocation(), 6018 diag::err_omp_loop_reduction_clause); 6019 } 6020 } 6021 6022 // First check CancelRegion which is then used in checkNestingOfRegions. 6023 if (checkCancelRegion(SemaRef, Kind, CancelRegion, StartLoc) || 6024 checkNestingOfRegions(SemaRef, DSAStack, Kind, DirName, CancelRegion, 6025 BindKind, StartLoc)) { 6026 return StmtError(); 6027 } 6028 6029 // Report affected OpenMP target offloading behavior when in HIP lang-mode. 6030 if (getLangOpts().HIP && (isOpenMPTargetExecutionDirective(Kind) || 6031 isOpenMPTargetDataManagementDirective(Kind))) 6032 Diag(StartLoc, diag::warn_hip_omp_target_directives); 6033 6034 VarsWithInheritedDSAType VarsWithInheritedDSA; 6035 bool ErrorFound = false; 6036 ClausesWithImplicit.append(Clauses.begin(), Clauses.end()); 6037 6038 if (AStmt && !SemaRef.CurContext->isDependentContext() && 6039 isOpenMPCapturingDirective(Kind)) { 6040 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 6041 6042 // Check default data sharing attributes for referenced variables. 6043 DSAAttrChecker DSAChecker(DSAStack, SemaRef, cast<CapturedStmt>(AStmt)); 6044 int ThisCaptureLevel = getOpenMPCaptureLevels(Kind); 6045 Stmt *S = AStmt; 6046 while (--ThisCaptureLevel >= 0) 6047 S = cast<CapturedStmt>(S)->getCapturedStmt(); 6048 DSAChecker.Visit(S); 6049 if (!isOpenMPTargetDataManagementDirective(Kind) && 6050 !isOpenMPTaskingDirective(Kind)) { 6051 // Visit subcaptures to generate implicit clauses for captured vars. 6052 auto *CS = cast<CapturedStmt>(AStmt); 6053 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 6054 getOpenMPCaptureRegions(CaptureRegions, Kind); 6055 // Ignore outer tasking regions for target directives. 6056 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task) 6057 CS = cast<CapturedStmt>(CS->getCapturedStmt()); 6058 DSAChecker.visitSubCaptures(CS); 6059 } 6060 if (DSAChecker.isErrorFound()) 6061 return StmtError(); 6062 // Generate list of implicitly defined firstprivate variables. 6063 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA(); 6064 VariableImplicitInfo ImpInfo = DSAChecker.getImplicitInfo(); 6065 6066 SmallVector<SourceLocation, NumberOfOMPMapClauseModifiers> 6067 ImplicitMapModifiersLoc[VariableImplicitInfo::DefaultmapKindNum]; 6068 // Get the original location of present modifier from Defaultmap clause. 6069 SourceLocation PresentModifierLocs[VariableImplicitInfo::DefaultmapKindNum]; 6070 for (OMPClause *C : Clauses) { 6071 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C)) 6072 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present) 6073 PresentModifierLocs[DMC->getDefaultmapKind()] = 6074 DMC->getDefaultmapModifierLoc(); 6075 } 6076 6077 for (OpenMPDefaultmapClauseKind K : 6078 llvm::enum_seq_inclusive<OpenMPDefaultmapClauseKind>( 6079 OpenMPDefaultmapClauseKind(), OMPC_DEFAULTMAP_unknown)) { 6080 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[K]), 6081 ImpInfo.MapModifiers[K].size(), PresentModifierLocs[K]); 6082 } 6083 // Mark taskgroup task_reduction descriptors as implicitly firstprivate. 6084 for (OMPClause *C : Clauses) { 6085 if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) { 6086 for (Expr *E : IRC->taskgroup_descriptors()) 6087 if (E) 6088 ImpInfo.Firstprivates.insert(E); 6089 } 6090 // OpenMP 5.0, 2.10.1 task Construct 6091 // [detach clause]... The event-handle will be considered as if it was 6092 // specified on a firstprivate clause. 6093 if (auto *DC = dyn_cast<OMPDetachClause>(C)) 6094 ImpInfo.Firstprivates.insert(DC->getEventHandler()); 6095 } 6096 if (!ImpInfo.Firstprivates.empty()) { 6097 if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause( 6098 ImpInfo.Firstprivates.getArrayRef(), SourceLocation(), 6099 SourceLocation(), SourceLocation())) { 6100 ClausesWithImplicit.push_back(Implicit); 6101 ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() != 6102 ImpInfo.Firstprivates.size(); 6103 } else { 6104 ErrorFound = true; 6105 } 6106 } 6107 if (!ImpInfo.Privates.empty()) { 6108 if (OMPClause *Implicit = ActOnOpenMPPrivateClause( 6109 ImpInfo.Privates.getArrayRef(), SourceLocation(), 6110 SourceLocation(), SourceLocation())) { 6111 ClausesWithImplicit.push_back(Implicit); 6112 ErrorFound = cast<OMPPrivateClause>(Implicit)->varlist_size() != 6113 ImpInfo.Privates.size(); 6114 } else { 6115 ErrorFound = true; 6116 } 6117 } 6118 // OpenMP 5.0 [2.19.7] 6119 // If a list item appears in a reduction, lastprivate or linear 6120 // clause on a combined target construct then it is treated as 6121 // if it also appears in a map clause with a map-type of tofrom 6122 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target && 6123 isOpenMPTargetExecutionDirective(Kind)) { 6124 SmallVector<Expr *, 4> ImplicitExprs; 6125 for (OMPClause *C : Clauses) { 6126 if (auto *RC = dyn_cast<OMPReductionClause>(C)) 6127 for (Expr *E : RC->varlist()) 6128 if (!isa<DeclRefExpr>(E->IgnoreParenImpCasts())) 6129 ImplicitExprs.emplace_back(E); 6130 } 6131 if (!ImplicitExprs.empty()) { 6132 ArrayRef<Expr *> Exprs = ImplicitExprs; 6133 CXXScopeSpec MapperIdScopeSpec; 6134 DeclarationNameInfo MapperId; 6135 if (OMPClause *Implicit = ActOnOpenMPMapClause( 6136 nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(), 6137 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom, 6138 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), 6139 Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true)) 6140 ClausesWithImplicit.emplace_back(Implicit); 6141 } 6142 } 6143 for (unsigned I = 0; I < VariableImplicitInfo::DefaultmapKindNum; ++I) { 6144 int ClauseKindCnt = -1; 6145 for (unsigned J = 0; J < VariableImplicitInfo::MapKindNum; ++J) { 6146 ArrayRef<Expr *> ImplicitMap = ImpInfo.Mappings[I][J].getArrayRef(); 6147 ++ClauseKindCnt; 6148 if (ImplicitMap.empty()) 6149 continue; 6150 CXXScopeSpec MapperIdScopeSpec; 6151 DeclarationNameInfo MapperId; 6152 auto K = static_cast<OpenMPMapClauseKind>(ClauseKindCnt); 6153 if (OMPClause *Implicit = ActOnOpenMPMapClause( 6154 nullptr, ImpInfo.MapModifiers[I], ImplicitMapModifiersLoc[I], 6155 MapperIdScopeSpec, MapperId, K, /*IsMapTypeImplicit=*/true, 6156 SourceLocation(), SourceLocation(), ImplicitMap, 6157 OMPVarListLocTy())) { 6158 ClausesWithImplicit.emplace_back(Implicit); 6159 ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() != 6160 ImplicitMap.size(); 6161 } else { 6162 ErrorFound = true; 6163 } 6164 } 6165 } 6166 // Build expressions for implicit maps of data members with 'default' 6167 // mappers. 6168 if (getLangOpts().OpenMP >= 50) 6169 processImplicitMapsWithDefaultMappers(SemaRef, DSAStack, 6170 ClausesWithImplicit); 6171 } 6172 6173 switch (Kind) { 6174 case OMPD_parallel: 6175 Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc, 6176 EndLoc); 6177 break; 6178 case OMPD_simd: 6179 Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc, 6180 VarsWithInheritedDSA); 6181 break; 6182 case OMPD_tile: 6183 Res = 6184 ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc); 6185 break; 6186 case OMPD_unroll: 6187 Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc, 6188 EndLoc); 6189 break; 6190 case OMPD_reverse: 6191 assert(ClausesWithImplicit.empty() && 6192 "reverse directive does not support any clauses"); 6193 Res = ActOnOpenMPReverseDirective(AStmt, StartLoc, EndLoc); 6194 break; 6195 case OMPD_interchange: 6196 Res = ActOnOpenMPInterchangeDirective(ClausesWithImplicit, AStmt, StartLoc, 6197 EndLoc); 6198 break; 6199 case OMPD_for: 6200 Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc, 6201 VarsWithInheritedDSA); 6202 break; 6203 case OMPD_for_simd: 6204 Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc, 6205 EndLoc, VarsWithInheritedDSA); 6206 break; 6207 case OMPD_sections: 6208 Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc, 6209 EndLoc); 6210 break; 6211 case OMPD_section: 6212 assert(ClausesWithImplicit.empty() && 6213 "No clauses are allowed for 'omp section' directive"); 6214 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc); 6215 break; 6216 case OMPD_single: 6217 Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc, 6218 EndLoc); 6219 break; 6220 case OMPD_master: 6221 assert(ClausesWithImplicit.empty() && 6222 "No clauses are allowed for 'omp master' directive"); 6223 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc); 6224 break; 6225 case OMPD_masked: 6226 Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc, 6227 EndLoc); 6228 break; 6229 case OMPD_critical: 6230 Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt, 6231 StartLoc, EndLoc); 6232 break; 6233 case OMPD_parallel_for: 6234 Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc, 6235 EndLoc, VarsWithInheritedDSA); 6236 break; 6237 case OMPD_parallel_for_simd: 6238 Res = ActOnOpenMPParallelForSimdDirective( 6239 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6240 break; 6241 case OMPD_scope: 6242 Res = 6243 ActOnOpenMPScopeDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc); 6244 break; 6245 case OMPD_parallel_master: 6246 Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt, 6247 StartLoc, EndLoc); 6248 break; 6249 case OMPD_parallel_masked: 6250 Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt, 6251 StartLoc, EndLoc); 6252 break; 6253 case OMPD_parallel_sections: 6254 Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt, 6255 StartLoc, EndLoc); 6256 break; 6257 case OMPD_task: 6258 Res = 6259 ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc); 6260 break; 6261 case OMPD_taskyield: 6262 assert(ClausesWithImplicit.empty() && 6263 "No clauses are allowed for 'omp taskyield' directive"); 6264 assert(AStmt == nullptr && 6265 "No associated statement allowed for 'omp taskyield' directive"); 6266 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc); 6267 break; 6268 case OMPD_error: 6269 assert(AStmt == nullptr && 6270 "No associated statement allowed for 'omp error' directive"); 6271 Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc); 6272 break; 6273 case OMPD_barrier: 6274 assert(ClausesWithImplicit.empty() && 6275 "No clauses are allowed for 'omp barrier' directive"); 6276 assert(AStmt == nullptr && 6277 "No associated statement allowed for 'omp barrier' directive"); 6278 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc); 6279 break; 6280 case OMPD_taskwait: 6281 assert(AStmt == nullptr && 6282 "No associated statement allowed for 'omp taskwait' directive"); 6283 Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc); 6284 break; 6285 case OMPD_taskgroup: 6286 Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc, 6287 EndLoc); 6288 break; 6289 case OMPD_flush: 6290 assert(AStmt == nullptr && 6291 "No associated statement allowed for 'omp flush' directive"); 6292 Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc); 6293 break; 6294 case OMPD_depobj: 6295 assert(AStmt == nullptr && 6296 "No associated statement allowed for 'omp depobj' directive"); 6297 Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc); 6298 break; 6299 case OMPD_scan: 6300 assert(AStmt == nullptr && 6301 "No associated statement allowed for 'omp scan' directive"); 6302 Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc); 6303 break; 6304 case OMPD_ordered: 6305 Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc, 6306 EndLoc); 6307 break; 6308 case OMPD_atomic: 6309 Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc, 6310 EndLoc); 6311 break; 6312 case OMPD_teams: 6313 Res = 6314 ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc); 6315 break; 6316 case OMPD_target: 6317 Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc, 6318 EndLoc); 6319 break; 6320 case OMPD_target_parallel: 6321 Res = ActOnOpenMPTargetParallelDirective(ClausesWithImplicit, AStmt, 6322 StartLoc, EndLoc); 6323 break; 6324 case OMPD_target_parallel_for: 6325 Res = ActOnOpenMPTargetParallelForDirective( 6326 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6327 break; 6328 case OMPD_cancellation_point: 6329 assert(ClausesWithImplicit.empty() && 6330 "No clauses are allowed for 'omp cancellation point' directive"); 6331 assert(AStmt == nullptr && "No associated statement allowed for 'omp " 6332 "cancellation point' directive"); 6333 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion); 6334 break; 6335 case OMPD_cancel: 6336 assert(AStmt == nullptr && 6337 "No associated statement allowed for 'omp cancel' directive"); 6338 Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc, 6339 CancelRegion); 6340 break; 6341 case OMPD_target_data: 6342 Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc, 6343 EndLoc); 6344 break; 6345 case OMPD_target_enter_data: 6346 Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc, 6347 EndLoc, AStmt); 6348 break; 6349 case OMPD_target_exit_data: 6350 Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc, 6351 EndLoc, AStmt); 6352 break; 6353 case OMPD_taskloop: 6354 Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc, 6355 EndLoc, VarsWithInheritedDSA); 6356 break; 6357 case OMPD_taskloop_simd: 6358 Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc, 6359 EndLoc, VarsWithInheritedDSA); 6360 break; 6361 case OMPD_master_taskloop: 6362 Res = ActOnOpenMPMasterTaskLoopDirective( 6363 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6364 break; 6365 case OMPD_masked_taskloop: 6366 Res = ActOnOpenMPMaskedTaskLoopDirective( 6367 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6368 break; 6369 case OMPD_master_taskloop_simd: 6370 Res = ActOnOpenMPMasterTaskLoopSimdDirective( 6371 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6372 break; 6373 case OMPD_masked_taskloop_simd: 6374 Res = ActOnOpenMPMaskedTaskLoopSimdDirective( 6375 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6376 break; 6377 case OMPD_parallel_master_taskloop: 6378 Res = ActOnOpenMPParallelMasterTaskLoopDirective( 6379 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6380 break; 6381 case OMPD_parallel_masked_taskloop: 6382 Res = ActOnOpenMPParallelMaskedTaskLoopDirective( 6383 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6384 break; 6385 case OMPD_parallel_master_taskloop_simd: 6386 Res = ActOnOpenMPParallelMasterTaskLoopSimdDirective( 6387 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6388 break; 6389 case OMPD_parallel_masked_taskloop_simd: 6390 Res = ActOnOpenMPParallelMaskedTaskLoopSimdDirective( 6391 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6392 break; 6393 case OMPD_distribute: 6394 Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc, 6395 EndLoc, VarsWithInheritedDSA); 6396 break; 6397 case OMPD_target_update: 6398 Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc, 6399 EndLoc, AStmt); 6400 break; 6401 case OMPD_distribute_parallel_for: 6402 Res = ActOnOpenMPDistributeParallelForDirective( 6403 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6404 break; 6405 case OMPD_distribute_parallel_for_simd: 6406 Res = ActOnOpenMPDistributeParallelForSimdDirective( 6407 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6408 break; 6409 case OMPD_distribute_simd: 6410 Res = ActOnOpenMPDistributeSimdDirective( 6411 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6412 break; 6413 case OMPD_target_parallel_for_simd: 6414 Res = ActOnOpenMPTargetParallelForSimdDirective( 6415 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6416 break; 6417 case OMPD_target_simd: 6418 Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc, 6419 EndLoc, VarsWithInheritedDSA); 6420 break; 6421 case OMPD_teams_distribute: 6422 Res = ActOnOpenMPTeamsDistributeDirective( 6423 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6424 break; 6425 case OMPD_teams_distribute_simd: 6426 Res = ActOnOpenMPTeamsDistributeSimdDirective( 6427 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6428 break; 6429 case OMPD_teams_distribute_parallel_for_simd: 6430 Res = ActOnOpenMPTeamsDistributeParallelForSimdDirective( 6431 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6432 break; 6433 case OMPD_teams_distribute_parallel_for: 6434 Res = ActOnOpenMPTeamsDistributeParallelForDirective( 6435 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6436 break; 6437 case OMPD_target_teams: 6438 Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, 6439 EndLoc); 6440 break; 6441 case OMPD_target_teams_distribute: 6442 Res = ActOnOpenMPTargetTeamsDistributeDirective( 6443 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6444 break; 6445 case OMPD_target_teams_distribute_parallel_for: 6446 Res = ActOnOpenMPTargetTeamsDistributeParallelForDirective( 6447 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6448 break; 6449 case OMPD_target_teams_distribute_parallel_for_simd: 6450 Res = ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective( 6451 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6452 break; 6453 case OMPD_target_teams_distribute_simd: 6454 Res = ActOnOpenMPTargetTeamsDistributeSimdDirective( 6455 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6456 break; 6457 case OMPD_interop: 6458 assert(AStmt == nullptr && 6459 "No associated statement allowed for 'omp interop' directive"); 6460 Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc); 6461 break; 6462 case OMPD_dispatch: 6463 Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc, 6464 EndLoc); 6465 break; 6466 case OMPD_loop: 6467 Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc, 6468 EndLoc, VarsWithInheritedDSA); 6469 break; 6470 case OMPD_teams_loop: 6471 Res = ActOnOpenMPTeamsGenericLoopDirective( 6472 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6473 break; 6474 case OMPD_target_teams_loop: 6475 Res = ActOnOpenMPTargetTeamsGenericLoopDirective( 6476 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6477 break; 6478 case OMPD_parallel_loop: 6479 Res = ActOnOpenMPParallelGenericLoopDirective( 6480 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6481 break; 6482 case OMPD_target_parallel_loop: 6483 Res = ActOnOpenMPTargetParallelGenericLoopDirective( 6484 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6485 break; 6486 case OMPD_declare_target: 6487 case OMPD_end_declare_target: 6488 case OMPD_threadprivate: 6489 case OMPD_allocate: 6490 case OMPD_declare_reduction: 6491 case OMPD_declare_mapper: 6492 case OMPD_declare_simd: 6493 case OMPD_requires: 6494 case OMPD_declare_variant: 6495 case OMPD_begin_declare_variant: 6496 case OMPD_end_declare_variant: 6497 llvm_unreachable("OpenMP Directive is not allowed"); 6498 case OMPD_unknown: 6499 default: 6500 llvm_unreachable("Unknown OpenMP directive"); 6501 } 6502 6503 ErrorFound = Res.isInvalid() || ErrorFound; 6504 6505 // Check variables in the clauses if default(none) or 6506 // default(firstprivate) was specified. 6507 if (DSAStack->getDefaultDSA() == DSA_none || 6508 DSAStack->getDefaultDSA() == DSA_private || 6509 DSAStack->getDefaultDSA() == DSA_firstprivate) { 6510 DSAAttrChecker DSAChecker(DSAStack, SemaRef, nullptr); 6511 for (OMPClause *C : Clauses) { 6512 switch (C->getClauseKind()) { 6513 case OMPC_num_threads: 6514 case OMPC_dist_schedule: 6515 // Do not analyze if no parent teams directive. 6516 if (isOpenMPTeamsDirective(Kind)) 6517 break; 6518 continue; 6519 case OMPC_if: 6520 if (isOpenMPTeamsDirective(Kind) && 6521 cast<OMPIfClause>(C)->getNameModifier() != OMPD_target) 6522 break; 6523 if (isOpenMPParallelDirective(Kind) && 6524 isOpenMPTaskLoopDirective(Kind) && 6525 cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel) 6526 break; 6527 continue; 6528 case OMPC_schedule: 6529 case OMPC_detach: 6530 break; 6531 case OMPC_grainsize: 6532 case OMPC_num_tasks: 6533 case OMPC_final: 6534 case OMPC_priority: 6535 case OMPC_novariants: 6536 case OMPC_nocontext: 6537 // Do not analyze if no parent parallel directive. 6538 if (isOpenMPParallelDirective(Kind)) 6539 break; 6540 continue; 6541 case OMPC_ordered: 6542 case OMPC_device: 6543 case OMPC_num_teams: 6544 case OMPC_thread_limit: 6545 case OMPC_hint: 6546 case OMPC_collapse: 6547 case OMPC_safelen: 6548 case OMPC_simdlen: 6549 case OMPC_sizes: 6550 case OMPC_default: 6551 case OMPC_proc_bind: 6552 case OMPC_private: 6553 case OMPC_firstprivate: 6554 case OMPC_lastprivate: 6555 case OMPC_shared: 6556 case OMPC_reduction: 6557 case OMPC_task_reduction: 6558 case OMPC_in_reduction: 6559 case OMPC_linear: 6560 case OMPC_aligned: 6561 case OMPC_copyin: 6562 case OMPC_copyprivate: 6563 case OMPC_nowait: 6564 case OMPC_untied: 6565 case OMPC_mergeable: 6566 case OMPC_allocate: 6567 case OMPC_read: 6568 case OMPC_write: 6569 case OMPC_update: 6570 case OMPC_capture: 6571 case OMPC_compare: 6572 case OMPC_seq_cst: 6573 case OMPC_acq_rel: 6574 case OMPC_acquire: 6575 case OMPC_release: 6576 case OMPC_relaxed: 6577 case OMPC_depend: 6578 case OMPC_threads: 6579 case OMPC_simd: 6580 case OMPC_map: 6581 case OMPC_nogroup: 6582 case OMPC_defaultmap: 6583 case OMPC_to: 6584 case OMPC_from: 6585 case OMPC_use_device_ptr: 6586 case OMPC_use_device_addr: 6587 case OMPC_is_device_ptr: 6588 case OMPC_has_device_addr: 6589 case OMPC_nontemporal: 6590 case OMPC_order: 6591 case OMPC_destroy: 6592 case OMPC_inclusive: 6593 case OMPC_exclusive: 6594 case OMPC_uses_allocators: 6595 case OMPC_affinity: 6596 case OMPC_bind: 6597 case OMPC_filter: 6598 continue; 6599 case OMPC_allocator: 6600 case OMPC_flush: 6601 case OMPC_depobj: 6602 case OMPC_threadprivate: 6603 case OMPC_uniform: 6604 case OMPC_unknown: 6605 case OMPC_unified_address: 6606 case OMPC_unified_shared_memory: 6607 case OMPC_reverse_offload: 6608 case OMPC_dynamic_allocators: 6609 case OMPC_atomic_default_mem_order: 6610 case OMPC_device_type: 6611 case OMPC_match: 6612 case OMPC_when: 6613 case OMPC_at: 6614 case OMPC_severity: 6615 case OMPC_message: 6616 default: 6617 llvm_unreachable("Unexpected clause"); 6618 } 6619 for (Stmt *CC : C->children()) { 6620 if (CC) 6621 DSAChecker.Visit(CC); 6622 } 6623 } 6624 for (const auto &P : DSAChecker.getVarsWithInheritedDSA()) 6625 VarsWithInheritedDSA[P.getFirst()] = P.getSecond(); 6626 } 6627 for (const auto &P : VarsWithInheritedDSA) { 6628 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst())) 6629 continue; 6630 ErrorFound = true; 6631 if (DSAStack->getDefaultDSA() == DSA_none || 6632 DSAStack->getDefaultDSA() == DSA_private || 6633 DSAStack->getDefaultDSA() == DSA_firstprivate) { 6634 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable) 6635 << P.first << P.second->getSourceRange(); 6636 Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none); 6637 } else if (getLangOpts().OpenMP >= 50) { 6638 Diag(P.second->getExprLoc(), 6639 diag::err_omp_defaultmap_no_attr_for_variable) 6640 << P.first << P.second->getSourceRange(); 6641 Diag(DSAStack->getDefaultDSALocation(), 6642 diag::note_omp_defaultmap_attr_none); 6643 } 6644 } 6645 6646 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers; 6647 for (OpenMPDirectiveKind D : getLeafConstructsOrSelf(Kind)) { 6648 if (isAllowedClauseForDirective(D, OMPC_if, getLangOpts().OpenMP)) 6649 AllowedNameModifiers.push_back(D); 6650 } 6651 if (!AllowedNameModifiers.empty()) 6652 ErrorFound = checkIfClauses(SemaRef, Kind, Clauses, AllowedNameModifiers) || 6653 ErrorFound; 6654 6655 if (ErrorFound) 6656 return StmtError(); 6657 6658 if (!SemaRef.CurContext->isDependentContext() && 6659 isOpenMPTargetExecutionDirective(Kind) && 6660 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() || 6661 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() || 6662 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() || 6663 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) { 6664 // Register target to DSA Stack. 6665 DSAStack->addTargetDirLocation(StartLoc); 6666 } 6667 6668 return Res; 6669 } 6670 6671 SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareSimdDirective( 6672 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen, 6673 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds, 6674 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears, 6675 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) { 6676 assert(Aligneds.size() == Alignments.size()); 6677 assert(Linears.size() == LinModifiers.size()); 6678 assert(Linears.size() == Steps.size()); 6679 if (!DG || DG.get().isNull()) 6680 return DeclGroupPtrTy(); 6681 6682 const int SimdId = 0; 6683 if (!DG.get().isSingleDecl()) { 6684 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant) 6685 << SimdId; 6686 return DG; 6687 } 6688 Decl *ADecl = DG.get().getSingleDecl(); 6689 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl)) 6690 ADecl = FTD->getTemplatedDecl(); 6691 6692 auto *FD = dyn_cast<FunctionDecl>(ADecl); 6693 if (!FD) { 6694 Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId; 6695 return DeclGroupPtrTy(); 6696 } 6697 6698 // OpenMP [2.8.2, declare simd construct, Description] 6699 // The parameter of the simdlen clause must be a constant positive integer 6700 // expression. 6701 ExprResult SL; 6702 if (Simdlen) 6703 SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen); 6704 // OpenMP [2.8.2, declare simd construct, Description] 6705 // The special this pointer can be used as if was one of the arguments to the 6706 // function in any of the linear, aligned, or uniform clauses. 6707 // The uniform clause declares one or more arguments to have an invariant 6708 // value for all concurrent invocations of the function in the execution of a 6709 // single SIMD loop. 6710 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs; 6711 const Expr *UniformedLinearThis = nullptr; 6712 for (const Expr *E : Uniforms) { 6713 E = E->IgnoreParenImpCasts(); 6714 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) 6715 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) 6716 if (FD->getNumParams() > PVD->getFunctionScopeIndex() && 6717 FD->getParamDecl(PVD->getFunctionScopeIndex()) 6718 ->getCanonicalDecl() == PVD->getCanonicalDecl()) { 6719 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E); 6720 continue; 6721 } 6722 if (isa<CXXThisExpr>(E)) { 6723 UniformedLinearThis = E; 6724 continue; 6725 } 6726 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) 6727 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0); 6728 } 6729 // OpenMP [2.8.2, declare simd construct, Description] 6730 // The aligned clause declares that the object to which each list item points 6731 // is aligned to the number of bytes expressed in the optional parameter of 6732 // the aligned clause. 6733 // The special this pointer can be used as if was one of the arguments to the 6734 // function in any of the linear, aligned, or uniform clauses. 6735 // The type of list items appearing in the aligned clause must be array, 6736 // pointer, reference to array, or reference to pointer. 6737 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs; 6738 const Expr *AlignedThis = nullptr; 6739 for (const Expr *E : Aligneds) { 6740 E = E->IgnoreParenImpCasts(); 6741 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) 6742 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) { 6743 const VarDecl *CanonPVD = PVD->getCanonicalDecl(); 6744 if (FD->getNumParams() > PVD->getFunctionScopeIndex() && 6745 FD->getParamDecl(PVD->getFunctionScopeIndex()) 6746 ->getCanonicalDecl() == CanonPVD) { 6747 // OpenMP [2.8.1, simd construct, Restrictions] 6748 // A list-item cannot appear in more than one aligned clause. 6749 if (AlignedArgs.count(CanonPVD) > 0) { 6750 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice) 6751 << 1 << getOpenMPClauseName(OMPC_aligned) 6752 << E->getSourceRange(); 6753 Diag(AlignedArgs[CanonPVD]->getExprLoc(), 6754 diag::note_omp_explicit_dsa) 6755 << getOpenMPClauseName(OMPC_aligned); 6756 continue; 6757 } 6758 AlignedArgs[CanonPVD] = E; 6759 QualType QTy = PVD->getType() 6760 .getNonReferenceType() 6761 .getUnqualifiedType() 6762 .getCanonicalType(); 6763 const Type *Ty = QTy.getTypePtrOrNull(); 6764 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) { 6765 Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr) 6766 << QTy << getLangOpts().CPlusPlus << E->getSourceRange(); 6767 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD; 6768 } 6769 continue; 6770 } 6771 } 6772 if (isa<CXXThisExpr>(E)) { 6773 if (AlignedThis) { 6774 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice) 6775 << 2 << getOpenMPClauseName(OMPC_aligned) << E->getSourceRange(); 6776 Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa) 6777 << getOpenMPClauseName(OMPC_aligned); 6778 } 6779 AlignedThis = E; 6780 continue; 6781 } 6782 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) 6783 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0); 6784 } 6785 // The optional parameter of the aligned clause, alignment, must be a constant 6786 // positive integer expression. If no optional parameter is specified, 6787 // implementation-defined default alignments for SIMD instructions on the 6788 // target platforms are assumed. 6789 SmallVector<const Expr *, 4> NewAligns; 6790 for (Expr *E : Alignments) { 6791 ExprResult Align; 6792 if (E) 6793 Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned); 6794 NewAligns.push_back(Align.get()); 6795 } 6796 // OpenMP [2.8.2, declare simd construct, Description] 6797 // The linear clause declares one or more list items to be private to a SIMD 6798 // lane and to have a linear relationship with respect to the iteration space 6799 // of a loop. 6800 // The special this pointer can be used as if was one of the arguments to the 6801 // function in any of the linear, aligned, or uniform clauses. 6802 // When a linear-step expression is specified in a linear clause it must be 6803 // either a constant integer expression or an integer-typed parameter that is 6804 // specified in a uniform clause on the directive. 6805 llvm::DenseMap<const Decl *, const Expr *> LinearArgs; 6806 const bool IsUniformedThis = UniformedLinearThis != nullptr; 6807 auto MI = LinModifiers.begin(); 6808 for (const Expr *E : Linears) { 6809 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI); 6810 ++MI; 6811 E = E->IgnoreParenImpCasts(); 6812 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) 6813 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) { 6814 const VarDecl *CanonPVD = PVD->getCanonicalDecl(); 6815 if (FD->getNumParams() > PVD->getFunctionScopeIndex() && 6816 FD->getParamDecl(PVD->getFunctionScopeIndex()) 6817 ->getCanonicalDecl() == CanonPVD) { 6818 // OpenMP [2.15.3.7, linear Clause, Restrictions] 6819 // A list-item cannot appear in more than one linear clause. 6820 if (LinearArgs.count(CanonPVD) > 0) { 6821 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa) 6822 << getOpenMPClauseName(OMPC_linear) 6823 << getOpenMPClauseName(OMPC_linear) << E->getSourceRange(); 6824 Diag(LinearArgs[CanonPVD]->getExprLoc(), 6825 diag::note_omp_explicit_dsa) 6826 << getOpenMPClauseName(OMPC_linear); 6827 continue; 6828 } 6829 // Each argument can appear in at most one uniform or linear clause. 6830 if (UniformedArgs.count(CanonPVD) > 0) { 6831 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa) 6832 << getOpenMPClauseName(OMPC_linear) 6833 << getOpenMPClauseName(OMPC_uniform) << E->getSourceRange(); 6834 Diag(UniformedArgs[CanonPVD]->getExprLoc(), 6835 diag::note_omp_explicit_dsa) 6836 << getOpenMPClauseName(OMPC_uniform); 6837 continue; 6838 } 6839 LinearArgs[CanonPVD] = E; 6840 if (E->isValueDependent() || E->isTypeDependent() || 6841 E->isInstantiationDependent() || 6842 E->containsUnexpandedParameterPack()) 6843 continue; 6844 (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind, 6845 PVD->getOriginalType(), 6846 /*IsDeclareSimd=*/true); 6847 continue; 6848 } 6849 } 6850 if (isa<CXXThisExpr>(E)) { 6851 if (UniformedLinearThis) { 6852 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa) 6853 << getOpenMPClauseName(OMPC_linear) 6854 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform : OMPC_linear) 6855 << E->getSourceRange(); 6856 Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa) 6857 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform 6858 : OMPC_linear); 6859 continue; 6860 } 6861 UniformedLinearThis = E; 6862 if (E->isValueDependent() || E->isTypeDependent() || 6863 E->isInstantiationDependent() || E->containsUnexpandedParameterPack()) 6864 continue; 6865 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind, 6866 E->getType(), /*IsDeclareSimd=*/true); 6867 continue; 6868 } 6869 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) 6870 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0); 6871 } 6872 Expr *Step = nullptr; 6873 Expr *NewStep = nullptr; 6874 SmallVector<Expr *, 4> NewSteps; 6875 for (Expr *E : Steps) { 6876 // Skip the same step expression, it was checked already. 6877 if (Step == E || !E) { 6878 NewSteps.push_back(E ? NewStep : nullptr); 6879 continue; 6880 } 6881 Step = E; 6882 if (const auto *DRE = dyn_cast<DeclRefExpr>(Step)) 6883 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) { 6884 const VarDecl *CanonPVD = PVD->getCanonicalDecl(); 6885 if (UniformedArgs.count(CanonPVD) == 0) { 6886 Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param) 6887 << Step->getSourceRange(); 6888 } else if (E->isValueDependent() || E->isTypeDependent() || 6889 E->isInstantiationDependent() || 6890 E->containsUnexpandedParameterPack() || 6891 CanonPVD->getType()->hasIntegerRepresentation()) { 6892 NewSteps.push_back(Step); 6893 } else { 6894 Diag(Step->getExprLoc(), diag::err_omp_expected_int_param) 6895 << Step->getSourceRange(); 6896 } 6897 continue; 6898 } 6899 NewStep = Step; 6900 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() && 6901 !Step->isInstantiationDependent() && 6902 !Step->containsUnexpandedParameterPack()) { 6903 NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step) 6904 .get(); 6905 if (NewStep) 6906 NewStep = SemaRef 6907 .VerifyIntegerConstantExpression( 6908 NewStep, /*FIXME*/ Sema::AllowFold) 6909 .get(); 6910 } 6911 NewSteps.push_back(NewStep); 6912 } 6913 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit( 6914 getASTContext(), BS, SL.get(), const_cast<Expr **>(Uniforms.data()), 6915 Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(), 6916 const_cast<Expr **>(NewAligns.data()), NewAligns.size(), 6917 const_cast<Expr **>(Linears.data()), Linears.size(), 6918 const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(), 6919 NewSteps.data(), NewSteps.size(), SR); 6920 ADecl->addAttr(NewAttr); 6921 return DG; 6922 } 6923 6924 StmtResult SemaOpenMP::ActOnOpenMPInformationalDirective( 6925 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, 6926 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 6927 SourceLocation EndLoc) { 6928 assert(isOpenMPInformationalDirective(Kind) && 6929 "Unexpected directive category"); 6930 6931 StmtResult Res = StmtError(); 6932 6933 switch (Kind) { 6934 case OMPD_assume: 6935 Res = ActOnOpenMPAssumeDirective(Clauses, AStmt, StartLoc, EndLoc); 6936 break; 6937 default: 6938 llvm_unreachable("Unknown OpenMP directive"); 6939 } 6940 6941 return Res; 6942 } 6943 6944 static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto, 6945 QualType NewType) { 6946 assert(NewType->isFunctionProtoType() && 6947 "Expected function type with prototype."); 6948 assert(FD->getType()->isFunctionNoProtoType() && 6949 "Expected function with type with no prototype."); 6950 assert(FDWithProto->getType()->isFunctionProtoType() && 6951 "Expected function with prototype."); 6952 // Synthesize parameters with the same types. 6953 FD->setType(NewType); 6954 SmallVector<ParmVarDecl *, 16> Params; 6955 for (const ParmVarDecl *P : FDWithProto->parameters()) { 6956 auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(), 6957 SourceLocation(), nullptr, P->getType(), 6958 /*TInfo=*/nullptr, SC_None, nullptr); 6959 Param->setScopeInfo(0, Params.size()); 6960 Param->setImplicit(); 6961 Params.push_back(Param); 6962 } 6963 6964 FD->setParams(Params); 6965 } 6966 6967 void SemaOpenMP::ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D) { 6968 if (D->isInvalidDecl()) 6969 return; 6970 FunctionDecl *FD = nullptr; 6971 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D)) 6972 FD = UTemplDecl->getTemplatedDecl(); 6973 else 6974 FD = cast<FunctionDecl>(D); 6975 assert(FD && "Expected a function declaration!"); 6976 6977 // If we are instantiating templates we do *not* apply scoped assumptions but 6978 // only global ones. We apply scoped assumption to the template definition 6979 // though. 6980 if (!SemaRef.inTemplateInstantiation()) { 6981 for (OMPAssumeAttr *AA : OMPAssumeScoped) 6982 FD->addAttr(AA); 6983 } 6984 for (OMPAssumeAttr *AA : OMPAssumeGlobal) 6985 FD->addAttr(AA); 6986 } 6987 6988 SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI) 6989 : TI(&TI), NameSuffix(TI.getMangledName()) {} 6990 6991 void SemaOpenMP::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope( 6992 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists, 6993 SmallVectorImpl<FunctionDecl *> &Bases) { 6994 if (!D.getIdentifier()) 6995 return; 6996 6997 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back(); 6998 6999 // Template specialization is an extension, check if we do it. 7000 bool IsTemplated = !TemplateParamLists.empty(); 7001 if (IsTemplated && 7002 !DVScope.TI->isExtensionActive( 7003 llvm::omp::TraitProperty::implementation_extension_allow_templates)) 7004 return; 7005 7006 const IdentifierInfo *BaseII = D.getIdentifier(); 7007 LookupResult Lookup(SemaRef, DeclarationName(BaseII), D.getIdentifierLoc(), 7008 Sema::LookupOrdinaryName); 7009 SemaRef.LookupParsedName(Lookup, S, &D.getCXXScopeSpec(), 7010 /*ObjectType=*/QualType()); 7011 7012 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D); 7013 QualType FType = TInfo->getType(); 7014 7015 bool IsConstexpr = 7016 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr; 7017 bool IsConsteval = 7018 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Consteval; 7019 7020 for (auto *Candidate : Lookup) { 7021 auto *CandidateDecl = Candidate->getUnderlyingDecl(); 7022 FunctionDecl *UDecl = nullptr; 7023 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) { 7024 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl); 7025 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size()) 7026 UDecl = FTD->getTemplatedDecl(); 7027 } else if (!IsTemplated) 7028 UDecl = dyn_cast<FunctionDecl>(CandidateDecl); 7029 if (!UDecl) 7030 continue; 7031 7032 // Don't specialize constexpr/consteval functions with 7033 // non-constexpr/consteval functions. 7034 if (UDecl->isConstexpr() && !IsConstexpr) 7035 continue; 7036 if (UDecl->isConsteval() && !IsConsteval) 7037 continue; 7038 7039 QualType UDeclTy = UDecl->getType(); 7040 if (!UDeclTy->isDependentType()) { 7041 QualType NewType = getASTContext().mergeFunctionTypes( 7042 FType, UDeclTy, /*OfBlockPointer=*/false, 7043 /*Unqualified=*/false, /*AllowCXX=*/true); 7044 if (NewType.isNull()) 7045 continue; 7046 } 7047 7048 // Found a base! 7049 Bases.push_back(UDecl); 7050 } 7051 7052 bool UseImplicitBase = !DVScope.TI->isExtensionActive( 7053 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base); 7054 // If no base was found we create a declaration that we use as base. 7055 if (Bases.empty() && UseImplicitBase) { 7056 D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration); 7057 Decl *BaseD = SemaRef.HandleDeclarator(S, D, TemplateParamLists); 7058 BaseD->setImplicit(true); 7059 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD)) 7060 Bases.push_back(BaseTemplD->getTemplatedDecl()); 7061 else 7062 Bases.push_back(cast<FunctionDecl>(BaseD)); 7063 } 7064 7065 std::string MangledName; 7066 MangledName += D.getIdentifier()->getName(); 7067 MangledName += getOpenMPVariantManglingSeparatorStr(); 7068 MangledName += DVScope.NameSuffix; 7069 IdentifierInfo &VariantII = getASTContext().Idents.get(MangledName); 7070 7071 VariantII.setMangledOpenMPVariantName(true); 7072 D.SetIdentifier(&VariantII, D.getBeginLoc()); 7073 } 7074 7075 void SemaOpenMP::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope( 7076 Decl *D, SmallVectorImpl<FunctionDecl *> &Bases) { 7077 // Do not mark function as is used to prevent its emission if this is the 7078 // only place where it is used. 7079 EnterExpressionEvaluationContext Unevaluated( 7080 SemaRef, Sema::ExpressionEvaluationContext::Unevaluated); 7081 7082 FunctionDecl *FD = nullptr; 7083 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D)) 7084 FD = UTemplDecl->getTemplatedDecl(); 7085 else 7086 FD = cast<FunctionDecl>(D); 7087 auto *VariantFuncRef = DeclRefExpr::Create( 7088 getASTContext(), NestedNameSpecifierLoc(), SourceLocation(), FD, 7089 /*RefersToEnclosingVariableOrCapture=*/false, 7090 /*NameLoc=*/FD->getLocation(), FD->getType(), ExprValueKind::VK_PRValue); 7091 7092 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back(); 7093 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit( 7094 getASTContext(), VariantFuncRef, DVScope.TI, 7095 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0, 7096 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0, 7097 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0); 7098 for (FunctionDecl *BaseFD : Bases) 7099 BaseFD->addAttr(OMPDeclareVariantA); 7100 } 7101 7102 ExprResult SemaOpenMP::ActOnOpenMPCall(ExprResult Call, Scope *Scope, 7103 SourceLocation LParenLoc, 7104 MultiExprArg ArgExprs, 7105 SourceLocation RParenLoc, 7106 Expr *ExecConfig) { 7107 // The common case is a regular call we do not want to specialize at all. Try 7108 // to make that case fast by bailing early. 7109 CallExpr *CE = dyn_cast<CallExpr>(Call.get()); 7110 if (!CE) 7111 return Call; 7112 7113 FunctionDecl *CalleeFnDecl = CE->getDirectCallee(); 7114 if (!CalleeFnDecl) 7115 return Call; 7116 7117 if (getLangOpts().OpenMP >= 51 && CalleeFnDecl->getIdentifier() && 7118 CalleeFnDecl->getName().starts_with_insensitive("omp_")) { 7119 // checking for any calls inside an Order region 7120 if (Scope && Scope->isOpenMPOrderClauseScope()) 7121 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api); 7122 } 7123 7124 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>()) 7125 return Call; 7126 7127 ASTContext &Context = getASTContext(); 7128 std::function<void(StringRef)> DiagUnknownTrait = [this, 7129 CE](StringRef ISATrait) { 7130 // TODO Track the selector locations in a way that is accessible here to 7131 // improve the diagnostic location. 7132 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait) 7133 << ISATrait; 7134 }; 7135 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait), 7136 SemaRef.getCurFunctionDecl(), 7137 DSAStack->getConstructTraits()); 7138 7139 QualType CalleeFnType = CalleeFnDecl->getType(); 7140 7141 SmallVector<Expr *, 4> Exprs; 7142 SmallVector<VariantMatchInfo, 4> VMIs; 7143 while (CalleeFnDecl) { 7144 for (OMPDeclareVariantAttr *A : 7145 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) { 7146 Expr *VariantRef = A->getVariantFuncRef(); 7147 7148 VariantMatchInfo VMI; 7149 OMPTraitInfo &TI = A->getTraitInfo(); 7150 TI.getAsVariantMatchInfo(Context, VMI); 7151 if (!isVariantApplicableInContext(VMI, OMPCtx, 7152 /*DeviceSetOnly=*/false)) 7153 continue; 7154 7155 VMIs.push_back(VMI); 7156 Exprs.push_back(VariantRef); 7157 } 7158 7159 CalleeFnDecl = CalleeFnDecl->getPreviousDecl(); 7160 } 7161 7162 ExprResult NewCall; 7163 do { 7164 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx); 7165 if (BestIdx < 0) 7166 return Call; 7167 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]); 7168 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl(); 7169 7170 { 7171 // Try to build a (member) call expression for the current best applicable 7172 // variant expression. We allow this to fail in which case we continue 7173 // with the next best variant expression. The fail case is part of the 7174 // implementation defined behavior in the OpenMP standard when it talks 7175 // about what differences in the function prototypes: "Any differences 7176 // that the specific OpenMP context requires in the prototype of the 7177 // variant from the base function prototype are implementation defined." 7178 // This wording is there to allow the specialized variant to have a 7179 // different type than the base function. This is intended and OK but if 7180 // we cannot create a call the difference is not in the "implementation 7181 // defined range" we allow. 7182 Sema::TentativeAnalysisScope Trap(SemaRef); 7183 7184 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) { 7185 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE); 7186 BestExpr = MemberExpr::CreateImplicit( 7187 Context, MemberCall->getImplicitObjectArgument(), 7188 /*IsArrow=*/false, SpecializedMethod, Context.BoundMemberTy, 7189 MemberCall->getValueKind(), MemberCall->getObjectKind()); 7190 } 7191 NewCall = SemaRef.BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs, 7192 RParenLoc, ExecConfig); 7193 if (NewCall.isUsable()) { 7194 if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) { 7195 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee(); 7196 QualType NewType = getASTContext().mergeFunctionTypes( 7197 CalleeFnType, NewCalleeFnDecl->getType(), 7198 /*OfBlockPointer=*/false, 7199 /*Unqualified=*/false, /*AllowCXX=*/true); 7200 if (!NewType.isNull()) 7201 break; 7202 // Don't use the call if the function type was not compatible. 7203 NewCall = nullptr; 7204 } 7205 } 7206 } 7207 7208 VMIs.erase(VMIs.begin() + BestIdx); 7209 Exprs.erase(Exprs.begin() + BestIdx); 7210 } while (!VMIs.empty()); 7211 7212 if (!NewCall.isUsable()) 7213 return Call; 7214 return PseudoObjectExpr::Create(getASTContext(), CE, {NewCall.get()}, 0); 7215 } 7216 7217 std::optional<std::pair<FunctionDecl *, Expr *>> 7218 SemaOpenMP::checkOpenMPDeclareVariantFunction(SemaOpenMP::DeclGroupPtrTy DG, 7219 Expr *VariantRef, 7220 OMPTraitInfo &TI, 7221 unsigned NumAppendArgs, 7222 SourceRange SR) { 7223 ASTContext &Context = getASTContext(); 7224 if (!DG || DG.get().isNull()) 7225 return std::nullopt; 7226 7227 const int VariantId = 1; 7228 // Must be applied only to single decl. 7229 if (!DG.get().isSingleDecl()) { 7230 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant) 7231 << VariantId << SR; 7232 return std::nullopt; 7233 } 7234 Decl *ADecl = DG.get().getSingleDecl(); 7235 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl)) 7236 ADecl = FTD->getTemplatedDecl(); 7237 7238 // Decl must be a function. 7239 auto *FD = dyn_cast<FunctionDecl>(ADecl); 7240 if (!FD) { 7241 Diag(ADecl->getLocation(), diag::err_omp_function_expected) 7242 << VariantId << SR; 7243 return std::nullopt; 7244 } 7245 7246 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) { 7247 // The 'target' attribute needs to be separately checked because it does 7248 // not always signify a multiversion function declaration. 7249 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>(); 7250 }; 7251 // OpenMP is not compatible with multiversion function attributes. 7252 if (HasMultiVersionAttributes(FD)) { 7253 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes) 7254 << SR; 7255 return std::nullopt; 7256 } 7257 7258 // Allow #pragma omp declare variant only if the function is not used. 7259 if (FD->isUsed(false)) 7260 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used) 7261 << FD->getLocation(); 7262 7263 // Check if the function was emitted already. 7264 const FunctionDecl *Definition; 7265 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) && 7266 (getLangOpts().EmitAllDecls || Context.DeclMustBeEmitted(Definition))) 7267 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted) 7268 << FD->getLocation(); 7269 7270 // The VariantRef must point to function. 7271 if (!VariantRef) { 7272 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId; 7273 return std::nullopt; 7274 } 7275 7276 auto ShouldDelayChecks = [](Expr *&E, bool) { 7277 return E && (E->isTypeDependent() || E->isValueDependent() || 7278 E->containsUnexpandedParameterPack() || 7279 E->isInstantiationDependent()); 7280 }; 7281 // Do not check templates, wait until instantiation. 7282 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) || 7283 TI.anyScoreOrCondition(ShouldDelayChecks)) 7284 return std::make_pair(FD, VariantRef); 7285 7286 // Deal with non-constant score and user condition expressions. 7287 auto HandleNonConstantScoresAndConditions = [this](Expr *&E, 7288 bool IsScore) -> bool { 7289 if (!E || E->isIntegerConstantExpr(getASTContext())) 7290 return false; 7291 7292 if (IsScore) { 7293 // We warn on non-constant scores and pretend they were not present. 7294 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant) 7295 << E; 7296 E = nullptr; 7297 } else { 7298 // We could replace a non-constant user condition with "false" but we 7299 // will soon need to handle these anyway for the dynamic version of 7300 // OpenMP context selectors. 7301 Diag(E->getExprLoc(), 7302 diag::err_omp_declare_variant_user_condition_not_constant) 7303 << E; 7304 } 7305 return true; 7306 }; 7307 if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions)) 7308 return std::nullopt; 7309 7310 QualType AdjustedFnType = FD->getType(); 7311 if (NumAppendArgs) { 7312 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>(); 7313 if (!PTy) { 7314 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required) 7315 << SR; 7316 return std::nullopt; 7317 } 7318 // Adjust the function type to account for an extra omp_interop_t for each 7319 // specified in the append_args clause. 7320 const TypeDecl *TD = nullptr; 7321 LookupResult Result(SemaRef, &Context.Idents.get("omp_interop_t"), 7322 SR.getBegin(), Sema::LookupOrdinaryName); 7323 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) { 7324 NamedDecl *ND = Result.getFoundDecl(); 7325 TD = dyn_cast_or_null<TypeDecl>(ND); 7326 } 7327 if (!TD) { 7328 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR; 7329 return std::nullopt; 7330 } 7331 QualType InteropType = Context.getTypeDeclType(TD); 7332 if (PTy->isVariadic()) { 7333 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR; 7334 return std::nullopt; 7335 } 7336 llvm::SmallVector<QualType, 8> Params; 7337 Params.append(PTy->param_type_begin(), PTy->param_type_end()); 7338 Params.insert(Params.end(), NumAppendArgs, InteropType); 7339 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params, 7340 PTy->getExtProtoInfo()); 7341 } 7342 7343 // Convert VariantRef expression to the type of the original function to 7344 // resolve possible conflicts. 7345 ExprResult VariantRefCast = VariantRef; 7346 if (getLangOpts().CPlusPlus) { 7347 QualType FnPtrType; 7348 auto *Method = dyn_cast<CXXMethodDecl>(FD); 7349 if (Method && !Method->isStatic()) { 7350 const Type *ClassType = 7351 Context.getTypeDeclType(Method->getParent()).getTypePtr(); 7352 FnPtrType = Context.getMemberPointerType(AdjustedFnType, ClassType); 7353 ExprResult ER; 7354 { 7355 // Build addr_of unary op to correctly handle type checks for member 7356 // functions. 7357 Sema::TentativeAnalysisScope Trap(SemaRef); 7358 ER = SemaRef.CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf, 7359 VariantRef); 7360 } 7361 if (!ER.isUsable()) { 7362 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected) 7363 << VariantId << VariantRef->getSourceRange(); 7364 return std::nullopt; 7365 } 7366 VariantRef = ER.get(); 7367 } else { 7368 FnPtrType = Context.getPointerType(AdjustedFnType); 7369 } 7370 QualType VarianPtrType = Context.getPointerType(VariantRef->getType()); 7371 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) { 7372 ImplicitConversionSequence ICS = SemaRef.TryImplicitConversion( 7373 VariantRef, FnPtrType.getUnqualifiedType(), 7374 /*SuppressUserConversions=*/false, Sema::AllowedExplicit::None, 7375 /*InOverloadResolution=*/false, 7376 /*CStyle=*/false, 7377 /*AllowObjCWritebackConversion=*/false); 7378 if (ICS.isFailure()) { 7379 Diag(VariantRef->getExprLoc(), 7380 diag::err_omp_declare_variant_incompat_types) 7381 << VariantRef->getType() 7382 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType()) 7383 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange(); 7384 return std::nullopt; 7385 } 7386 VariantRefCast = SemaRef.PerformImplicitConversion( 7387 VariantRef, FnPtrType.getUnqualifiedType(), 7388 AssignmentAction::Converting); 7389 if (!VariantRefCast.isUsable()) 7390 return std::nullopt; 7391 } 7392 // Drop previously built artificial addr_of unary op for member functions. 7393 if (Method && !Method->isStatic()) { 7394 Expr *PossibleAddrOfVariantRef = VariantRefCast.get(); 7395 if (auto *UO = dyn_cast<UnaryOperator>( 7396 PossibleAddrOfVariantRef->IgnoreImplicit())) 7397 VariantRefCast = UO->getSubExpr(); 7398 } 7399 } 7400 7401 ExprResult ER = SemaRef.CheckPlaceholderExpr(VariantRefCast.get()); 7402 if (!ER.isUsable() || 7403 !ER.get()->IgnoreParenImpCasts()->getType()->isFunctionType()) { 7404 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected) 7405 << VariantId << VariantRef->getSourceRange(); 7406 return std::nullopt; 7407 } 7408 7409 // The VariantRef must point to function. 7410 auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts()); 7411 if (!DRE) { 7412 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected) 7413 << VariantId << VariantRef->getSourceRange(); 7414 return std::nullopt; 7415 } 7416 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl()); 7417 if (!NewFD) { 7418 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected) 7419 << VariantId << VariantRef->getSourceRange(); 7420 return std::nullopt; 7421 } 7422 7423 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) { 7424 Diag(VariantRef->getExprLoc(), 7425 diag::err_omp_declare_variant_same_base_function) 7426 << VariantRef->getSourceRange(); 7427 return std::nullopt; 7428 } 7429 7430 // Check if function types are compatible in C. 7431 if (!getLangOpts().CPlusPlus) { 7432 QualType NewType = 7433 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType()); 7434 if (NewType.isNull()) { 7435 Diag(VariantRef->getExprLoc(), 7436 diag::err_omp_declare_variant_incompat_types) 7437 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0) 7438 << VariantRef->getSourceRange(); 7439 return std::nullopt; 7440 } 7441 if (NewType->isFunctionProtoType()) { 7442 if (FD->getType()->isFunctionNoProtoType()) 7443 setPrototype(SemaRef, FD, NewFD, NewType); 7444 else if (NewFD->getType()->isFunctionNoProtoType()) 7445 setPrototype(SemaRef, NewFD, FD, NewType); 7446 } 7447 } 7448 7449 // Check if variant function is not marked with declare variant directive. 7450 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) { 7451 Diag(VariantRef->getExprLoc(), 7452 diag::warn_omp_declare_variant_marked_as_declare_variant) 7453 << VariantRef->getSourceRange(); 7454 SourceRange SR = 7455 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange(); 7456 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR; 7457 return std::nullopt; 7458 } 7459 7460 enum DoesntSupport { 7461 VirtFuncs = 1, 7462 Constructors = 3, 7463 Destructors = 4, 7464 DeletedFuncs = 5, 7465 DefaultedFuncs = 6, 7466 ConstexprFuncs = 7, 7467 ConstevalFuncs = 8, 7468 }; 7469 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) { 7470 if (CXXFD->isVirtual()) { 7471 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support) 7472 << VirtFuncs; 7473 return std::nullopt; 7474 } 7475 7476 if (isa<CXXConstructorDecl>(FD)) { 7477 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support) 7478 << Constructors; 7479 return std::nullopt; 7480 } 7481 7482 if (isa<CXXDestructorDecl>(FD)) { 7483 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support) 7484 << Destructors; 7485 return std::nullopt; 7486 } 7487 } 7488 7489 if (FD->isDeleted()) { 7490 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support) 7491 << DeletedFuncs; 7492 return std::nullopt; 7493 } 7494 7495 if (FD->isDefaulted()) { 7496 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support) 7497 << DefaultedFuncs; 7498 return std::nullopt; 7499 } 7500 7501 if (FD->isConstexpr()) { 7502 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support) 7503 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs); 7504 return std::nullopt; 7505 } 7506 7507 // Check general compatibility. 7508 if (SemaRef.areMultiversionVariantFunctionsCompatible( 7509 FD, NewFD, PartialDiagnostic::NullDiagnostic(), 7510 PartialDiagnosticAt(SourceLocation(), 7511 PartialDiagnostic::NullDiagnostic()), 7512 PartialDiagnosticAt( 7513 VariantRef->getExprLoc(), 7514 SemaRef.PDiag(diag::err_omp_declare_variant_doesnt_support)), 7515 PartialDiagnosticAt(VariantRef->getExprLoc(), 7516 SemaRef.PDiag(diag::err_omp_declare_variant_diff) 7517 << FD->getLocation()), 7518 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false, 7519 /*CLinkageMayDiffer=*/true)) 7520 return std::nullopt; 7521 return std::make_pair(FD, cast<Expr>(DRE)); 7522 } 7523 7524 void SemaOpenMP::ActOnOpenMPDeclareVariantDirective( 7525 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, 7526 ArrayRef<Expr *> AdjustArgsNothing, 7527 ArrayRef<Expr *> AdjustArgsNeedDevicePtr, 7528 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc, 7529 SourceLocation AppendArgsLoc, SourceRange SR) { 7530 7531 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions] 7532 // An adjust_args clause or append_args clause can only be specified if the 7533 // dispatch selector of the construct selector set appears in the match 7534 // clause. 7535 7536 SmallVector<Expr *, 8> AllAdjustArgs; 7537 llvm::append_range(AllAdjustArgs, AdjustArgsNothing); 7538 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr); 7539 7540 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) { 7541 VariantMatchInfo VMI; 7542 TI.getAsVariantMatchInfo(getASTContext(), VMI); 7543 if (!llvm::is_contained( 7544 VMI.ConstructTraits, 7545 llvm::omp::TraitProperty::construct_dispatch_dispatch)) { 7546 if (!AllAdjustArgs.empty()) 7547 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct) 7548 << getOpenMPClauseName(OMPC_adjust_args); 7549 if (!AppendArgs.empty()) 7550 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct) 7551 << getOpenMPClauseName(OMPC_append_args); 7552 return; 7553 } 7554 } 7555 7556 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions] 7557 // Each argument can only appear in a single adjust_args clause for each 7558 // declare variant directive. 7559 llvm::SmallPtrSet<const VarDecl *, 4> AdjustVars; 7560 7561 for (Expr *E : AllAdjustArgs) { 7562 E = E->IgnoreParenImpCasts(); 7563 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) { 7564 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) { 7565 const VarDecl *CanonPVD = PVD->getCanonicalDecl(); 7566 if (FD->getNumParams() > PVD->getFunctionScopeIndex() && 7567 FD->getParamDecl(PVD->getFunctionScopeIndex()) 7568 ->getCanonicalDecl() == CanonPVD) { 7569 // It's a parameter of the function, check duplicates. 7570 if (!AdjustVars.insert(CanonPVD).second) { 7571 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses) 7572 << PVD; 7573 return; 7574 } 7575 continue; 7576 } 7577 } 7578 } 7579 // Anything that is not a function parameter is an error. 7580 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0; 7581 return; 7582 } 7583 7584 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit( 7585 getASTContext(), VariantRef, &TI, 7586 const_cast<Expr **>(AdjustArgsNothing.data()), AdjustArgsNothing.size(), 7587 const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()), 7588 AdjustArgsNeedDevicePtr.size(), 7589 const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR); 7590 FD->addAttr(NewAttr); 7591 } 7592 7593 static CapturedStmt * 7594 setBranchProtectedScope(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt) { 7595 auto *CS = dyn_cast<CapturedStmt>(AStmt); 7596 assert(CS && "Captured statement expected"); 7597 // 1.2.2 OpenMP Language Terminology 7598 // Structured block - An executable statement with a single entry at the 7599 // top and a single exit at the bottom. 7600 // The point of exit cannot be a branch out of the structured block. 7601 // longjmp() and throw() must not violate the entry/exit criteria. 7602 CS->getCapturedDecl()->setNothrow(); 7603 7604 for (int ThisCaptureLevel = SemaRef.OpenMP().getOpenMPCaptureLevels(DKind); 7605 ThisCaptureLevel > 1; --ThisCaptureLevel) { 7606 CS = cast<CapturedStmt>(CS->getCapturedStmt()); 7607 // 1.2.2 OpenMP Language Terminology 7608 // Structured block - An executable statement with a single entry at the 7609 // top and a single exit at the bottom. 7610 // The point of exit cannot be a branch out of the structured block. 7611 // longjmp() and throw() must not violate the entry/exit criteria. 7612 CS->getCapturedDecl()->setNothrow(); 7613 } 7614 SemaRef.setFunctionHasBranchProtectedScope(); 7615 return CS; 7616 } 7617 7618 StmtResult 7619 SemaOpenMP::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses, 7620 Stmt *AStmt, SourceLocation StartLoc, 7621 SourceLocation EndLoc) { 7622 if (!AStmt) 7623 return StmtError(); 7624 7625 setBranchProtectedScope(SemaRef, OMPD_parallel, AStmt); 7626 7627 return OMPParallelDirective::Create( 7628 getASTContext(), StartLoc, EndLoc, Clauses, AStmt, 7629 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion()); 7630 } 7631 7632 namespace { 7633 /// Iteration space of a single for loop. 7634 struct LoopIterationSpace final { 7635 /// True if the condition operator is the strict compare operator (<, > or 7636 /// !=). 7637 bool IsStrictCompare = false; 7638 /// Condition of the loop. 7639 Expr *PreCond = nullptr; 7640 /// This expression calculates the number of iterations in the loop. 7641 /// It is always possible to calculate it before starting the loop. 7642 Expr *NumIterations = nullptr; 7643 /// The loop counter variable. 7644 Expr *CounterVar = nullptr; 7645 /// Private loop counter variable. 7646 Expr *PrivateCounterVar = nullptr; 7647 /// This is initializer for the initial value of #CounterVar. 7648 Expr *CounterInit = nullptr; 7649 /// This is step for the #CounterVar used to generate its update: 7650 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration. 7651 Expr *CounterStep = nullptr; 7652 /// Should step be subtracted? 7653 bool Subtract = false; 7654 /// Source range of the loop init. 7655 SourceRange InitSrcRange; 7656 /// Source range of the loop condition. 7657 SourceRange CondSrcRange; 7658 /// Source range of the loop increment. 7659 SourceRange IncSrcRange; 7660 /// Minimum value that can have the loop control variable. Used to support 7661 /// non-rectangular loops. Applied only for LCV with the non-iterator types, 7662 /// since only such variables can be used in non-loop invariant expressions. 7663 Expr *MinValue = nullptr; 7664 /// Maximum value that can have the loop control variable. Used to support 7665 /// non-rectangular loops. Applied only for LCV with the non-iterator type, 7666 /// since only such variables can be used in non-loop invariant expressions. 7667 Expr *MaxValue = nullptr; 7668 /// true, if the lower bound depends on the outer loop control var. 7669 bool IsNonRectangularLB = false; 7670 /// true, if the upper bound depends on the outer loop control var. 7671 bool IsNonRectangularUB = false; 7672 /// Index of the loop this loop depends on and forms non-rectangular loop 7673 /// nest. 7674 unsigned LoopDependentIdx = 0; 7675 /// Final condition for the non-rectangular loop nest support. It is used to 7676 /// check that the number of iterations for this particular counter must be 7677 /// finished. 7678 Expr *FinalCondition = nullptr; 7679 }; 7680 7681 /// Scan an AST subtree, checking that no decls in the CollapsedLoopVarDecls 7682 /// set are referenced. Used for verifying loop nest structure before 7683 /// performing a loop collapse operation. 7684 class ForSubExprChecker : public DynamicRecursiveASTVisitor { 7685 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls; 7686 VarDecl *ForbiddenVar = nullptr; 7687 SourceRange ErrLoc; 7688 7689 public: 7690 explicit ForSubExprChecker( 7691 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls) 7692 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) { 7693 // We want to visit implicit code, i.e. synthetic initialisation statements 7694 // created during range-for lowering. 7695 ShouldVisitImplicitCode = true; 7696 } 7697 7698 bool VisitDeclRefExpr(DeclRefExpr *E) override { 7699 ValueDecl *VD = E->getDecl(); 7700 if (!isa<VarDecl, BindingDecl>(VD)) 7701 return true; 7702 VarDecl *V = VD->getPotentiallyDecomposedVarDecl(); 7703 if (V->getType()->isReferenceType()) { 7704 VarDecl *VD = V->getDefinition(); 7705 if (VD->hasInit()) { 7706 Expr *I = VD->getInit(); 7707 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(I); 7708 if (!DRE) 7709 return true; 7710 V = DRE->getDecl()->getPotentiallyDecomposedVarDecl(); 7711 } 7712 } 7713 Decl *Canon = V->getCanonicalDecl(); 7714 if (CollapsedLoopVarDecls.contains(Canon)) { 7715 ForbiddenVar = V; 7716 ErrLoc = E->getSourceRange(); 7717 return false; 7718 } 7719 7720 return true; 7721 } 7722 7723 VarDecl *getForbiddenVar() const { return ForbiddenVar; } 7724 SourceRange getErrRange() const { return ErrLoc; } 7725 }; 7726 7727 /// Helper class for checking canonical form of the OpenMP loops and 7728 /// extracting iteration space of each loop in the loop nest, that will be used 7729 /// for IR generation. 7730 class OpenMPIterationSpaceChecker { 7731 /// Reference to Sema. 7732 Sema &SemaRef; 7733 /// Does the loop associated directive support non-rectangular loops? 7734 bool SupportsNonRectangular; 7735 /// Data-sharing stack. 7736 DSAStackTy &Stack; 7737 /// A location for diagnostics (when there is no some better location). 7738 SourceLocation DefaultLoc; 7739 /// A location for diagnostics (when increment is not compatible). 7740 SourceLocation ConditionLoc; 7741 /// The set of variables declared within the (to be collapsed) loop nest. 7742 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls; 7743 /// A source location for referring to loop init later. 7744 SourceRange InitSrcRange; 7745 /// A source location for referring to condition later. 7746 SourceRange ConditionSrcRange; 7747 /// A source location for referring to increment later. 7748 SourceRange IncrementSrcRange; 7749 /// Loop variable. 7750 ValueDecl *LCDecl = nullptr; 7751 /// Reference to loop variable. 7752 Expr *LCRef = nullptr; 7753 /// Lower bound (initializer for the var). 7754 Expr *LB = nullptr; 7755 /// Upper bound. 7756 Expr *UB = nullptr; 7757 /// Loop step (increment). 7758 Expr *Step = nullptr; 7759 /// This flag is true when condition is one of: 7760 /// Var < UB 7761 /// Var <= UB 7762 /// UB > Var 7763 /// UB >= Var 7764 /// This will have no value when the condition is != 7765 std::optional<bool> TestIsLessOp; 7766 /// This flag is true when condition is strict ( < or > ). 7767 bool TestIsStrictOp = false; 7768 /// This flag is true when step is subtracted on each iteration. 7769 bool SubtractStep = false; 7770 /// The outer loop counter this loop depends on (if any). 7771 const ValueDecl *DepDecl = nullptr; 7772 /// Contains number of loop (starts from 1) on which loop counter init 7773 /// expression of this loop depends on. 7774 std::optional<unsigned> InitDependOnLC; 7775 /// Contains number of loop (starts from 1) on which loop counter condition 7776 /// expression of this loop depends on. 7777 std::optional<unsigned> CondDependOnLC; 7778 /// Checks if the provide statement depends on the loop counter. 7779 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S, 7780 bool IsInitializer); 7781 /// Original condition required for checking of the exit condition for 7782 /// non-rectangular loop. 7783 Expr *Condition = nullptr; 7784 7785 public: 7786 OpenMPIterationSpaceChecker( 7787 Sema &SemaRef, bool SupportsNonRectangular, DSAStackTy &Stack, 7788 SourceLocation DefaultLoc, 7789 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls) 7790 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular), 7791 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc), 7792 CollapsedLoopVarDecls(CollapsedLoopDecls) {} 7793 /// Check init-expr for canonical loop form and save loop counter 7794 /// variable - #Var and its initialization value - #LB. 7795 bool checkAndSetInit(Stmt *S, bool EmitDiags = true); 7796 /// Check test-expr for canonical form, save upper-bound (#UB), flags 7797 /// for less/greater and for strict/non-strict comparison. 7798 bool checkAndSetCond(Expr *S); 7799 /// Check incr-expr for canonical loop form and return true if it 7800 /// does not conform, otherwise save loop step (#Step). 7801 bool checkAndSetInc(Expr *S); 7802 /// Return the loop counter variable. 7803 ValueDecl *getLoopDecl() const { return LCDecl; } 7804 /// Return the reference expression to loop counter variable. 7805 Expr *getLoopDeclRefExpr() const { return LCRef; } 7806 /// Source range of the loop init. 7807 SourceRange getInitSrcRange() const { return InitSrcRange; } 7808 /// Source range of the loop condition. 7809 SourceRange getConditionSrcRange() const { return ConditionSrcRange; } 7810 /// Source range of the loop increment. 7811 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; } 7812 /// True if the step should be subtracted. 7813 bool shouldSubtractStep() const { return SubtractStep; } 7814 /// True, if the compare operator is strict (<, > or !=). 7815 bool isStrictTestOp() const { return TestIsStrictOp; } 7816 /// Build the expression to calculate the number of iterations. 7817 Expr *buildNumIterations( 7818 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType, 7819 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const; 7820 /// Build the precondition expression for the loops. 7821 Expr * 7822 buildPreCond(Scope *S, Expr *Cond, 7823 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const; 7824 /// Build reference expression to the counter be used for codegen. 7825 DeclRefExpr * 7826 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, 7827 DSAStackTy &DSA) const; 7828 /// Build reference expression to the private counter be used for 7829 /// codegen. 7830 Expr *buildPrivateCounterVar() const; 7831 /// Build initialization of the counter be used for codegen. 7832 Expr *buildCounterInit() const; 7833 /// Build step of the counter be used for codegen. 7834 Expr *buildCounterStep() const; 7835 /// Build loop data with counter value for depend clauses in ordered 7836 /// directives. 7837 Expr * 7838 buildOrderedLoopData(Scope *S, Expr *Counter, 7839 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, 7840 SourceLocation Loc, Expr *Inc = nullptr, 7841 OverloadedOperatorKind OOK = OO_Amp); 7842 /// Builds the minimum value for the loop counter. 7843 std::pair<Expr *, Expr *> buildMinMaxValues( 7844 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const; 7845 /// Builds final condition for the non-rectangular loops. 7846 Expr *buildFinalCondition(Scope *S) const; 7847 /// Return true if any expression is dependent. 7848 bool dependent() const; 7849 /// Returns true if the initializer forms non-rectangular loop. 7850 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); } 7851 /// Returns true if the condition forms non-rectangular loop. 7852 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); } 7853 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise. 7854 unsigned getLoopDependentIdx() const { 7855 return InitDependOnLC.value_or(CondDependOnLC.value_or(0)); 7856 } 7857 7858 private: 7859 /// Check the right-hand side of an assignment in the increment 7860 /// expression. 7861 bool checkAndSetIncRHS(Expr *RHS); 7862 /// Helper to set loop counter variable and its initializer. 7863 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB, 7864 bool EmitDiags); 7865 /// Helper to set upper bound. 7866 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp, 7867 SourceRange SR, SourceLocation SL); 7868 /// Helper to set loop increment. 7869 bool setStep(Expr *NewStep, bool Subtract); 7870 }; 7871 7872 bool OpenMPIterationSpaceChecker::dependent() const { 7873 if (!LCDecl) { 7874 assert(!LB && !UB && !Step); 7875 return false; 7876 } 7877 return LCDecl->getType()->isDependentType() || 7878 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) || 7879 (Step && Step->isValueDependent()); 7880 } 7881 7882 bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl, 7883 Expr *NewLCRefExpr, 7884 Expr *NewLB, bool EmitDiags) { 7885 // State consistency checking to ensure correct usage. 7886 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr && 7887 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp); 7888 if (!NewLCDecl || !NewLB || NewLB->containsErrors()) 7889 return true; 7890 LCDecl = getCanonicalDecl(NewLCDecl); 7891 LCRef = NewLCRefExpr; 7892 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB)) 7893 if (const CXXConstructorDecl *Ctor = CE->getConstructor()) 7894 if ((Ctor->isCopyOrMoveConstructor() || 7895 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) && 7896 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr) 7897 NewLB = CE->getArg(0)->IgnoreParenImpCasts(); 7898 LB = NewLB; 7899 if (EmitDiags) 7900 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true); 7901 return false; 7902 } 7903 7904 bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp, 7905 bool StrictOp, SourceRange SR, 7906 SourceLocation SL) { 7907 // State consistency checking to ensure correct usage. 7908 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr && 7909 Step == nullptr && !TestIsLessOp && !TestIsStrictOp); 7910 if (!NewUB || NewUB->containsErrors()) 7911 return true; 7912 UB = NewUB; 7913 if (LessOp) 7914 TestIsLessOp = LessOp; 7915 TestIsStrictOp = StrictOp; 7916 ConditionSrcRange = SR; 7917 ConditionLoc = SL; 7918 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false); 7919 return false; 7920 } 7921 7922 bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) { 7923 // State consistency checking to ensure correct usage. 7924 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr); 7925 if (!NewStep || NewStep->containsErrors()) 7926 return true; 7927 if (!NewStep->isValueDependent()) { 7928 // Check that the step is integer expression. 7929 SourceLocation StepLoc = NewStep->getBeginLoc(); 7930 ExprResult Val = SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion( 7931 StepLoc, getExprAsWritten(NewStep)); 7932 if (Val.isInvalid()) 7933 return true; 7934 NewStep = Val.get(); 7935 7936 // OpenMP [2.6, Canonical Loop Form, Restrictions] 7937 // If test-expr is of form var relational-op b and relational-op is < or 7938 // <= then incr-expr must cause var to increase on each iteration of the 7939 // loop. If test-expr is of form var relational-op b and relational-op is 7940 // > or >= then incr-expr must cause var to decrease on each iteration of 7941 // the loop. 7942 // If test-expr is of form b relational-op var and relational-op is < or 7943 // <= then incr-expr must cause var to decrease on each iteration of the 7944 // loop. If test-expr is of form b relational-op var and relational-op is 7945 // > or >= then incr-expr must cause var to increase on each iteration of 7946 // the loop. 7947 std::optional<llvm::APSInt> Result = 7948 NewStep->getIntegerConstantExpr(SemaRef.Context); 7949 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation(); 7950 bool IsConstNeg = 7951 Result && Result->isSigned() && (Subtract != Result->isNegative()); 7952 bool IsConstPos = 7953 Result && Result->isSigned() && (Subtract == Result->isNegative()); 7954 bool IsConstZero = Result && !Result->getBoolValue(); 7955 7956 // != with increment is treated as <; != with decrement is treated as > 7957 if (!TestIsLessOp) 7958 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract); 7959 if (UB && (IsConstZero || 7960 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract)) 7961 : (IsConstPos || (IsUnsigned && !Subtract))))) { 7962 SemaRef.Diag(NewStep->getExprLoc(), 7963 diag::err_omp_loop_incr_not_compatible) 7964 << LCDecl << *TestIsLessOp << NewStep->getSourceRange(); 7965 SemaRef.Diag(ConditionLoc, 7966 diag::note_omp_loop_cond_requires_compatible_incr) 7967 << *TestIsLessOp << ConditionSrcRange; 7968 return true; 7969 } 7970 if (*TestIsLessOp == Subtract) { 7971 NewStep = 7972 SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep) 7973 .get(); 7974 Subtract = !Subtract; 7975 } 7976 } 7977 7978 Step = NewStep; 7979 SubtractStep = Subtract; 7980 return false; 7981 } 7982 7983 namespace { 7984 /// Checker for the non-rectangular loops. Checks if the initializer or 7985 /// condition expression references loop counter variable. 7986 class LoopCounterRefChecker final 7987 : public ConstStmtVisitor<LoopCounterRefChecker, bool> { 7988 Sema &SemaRef; 7989 DSAStackTy &Stack; 7990 const ValueDecl *CurLCDecl = nullptr; 7991 const ValueDecl *DepDecl = nullptr; 7992 const ValueDecl *PrevDepDecl = nullptr; 7993 bool IsInitializer = true; 7994 bool SupportsNonRectangular; 7995 unsigned BaseLoopId = 0; 7996 bool checkDecl(const Expr *E, const ValueDecl *VD) { 7997 if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) { 7998 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter) 7999 << (IsInitializer ? 0 : 1); 8000 return false; 8001 } 8002 const auto &&Data = Stack.isLoopControlVariable(VD); 8003 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions. 8004 // The type of the loop iterator on which we depend may not have a random 8005 // access iterator type. 8006 if (Data.first && VD->getType()->isRecordType()) { 8007 SmallString<128> Name; 8008 llvm::raw_svector_ostream OS(Name); 8009 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(), 8010 /*Qualified=*/true); 8011 SemaRef.Diag(E->getExprLoc(), 8012 diag::err_omp_wrong_dependency_iterator_type) 8013 << OS.str(); 8014 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD; 8015 return false; 8016 } 8017 if (Data.first && !SupportsNonRectangular) { 8018 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency); 8019 return false; 8020 } 8021 if (Data.first && 8022 (DepDecl || (PrevDepDecl && 8023 getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) { 8024 if (!DepDecl && PrevDepDecl) 8025 DepDecl = PrevDepDecl; 8026 SmallString<128> Name; 8027 llvm::raw_svector_ostream OS(Name); 8028 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(), 8029 /*Qualified=*/true); 8030 SemaRef.Diag(E->getExprLoc(), 8031 diag::err_omp_invariant_or_linear_dependency) 8032 << OS.str(); 8033 return false; 8034 } 8035 if (Data.first) { 8036 DepDecl = VD; 8037 BaseLoopId = Data.first; 8038 } 8039 return Data.first; 8040 } 8041 8042 public: 8043 bool VisitDeclRefExpr(const DeclRefExpr *E) { 8044 const ValueDecl *VD = E->getDecl(); 8045 if (isa<VarDecl>(VD)) 8046 return checkDecl(E, VD); 8047 return false; 8048 } 8049 bool VisitMemberExpr(const MemberExpr *E) { 8050 if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) { 8051 const ValueDecl *VD = E->getMemberDecl(); 8052 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD)) 8053 return checkDecl(E, VD); 8054 } 8055 return false; 8056 } 8057 bool VisitStmt(const Stmt *S) { 8058 bool Res = false; 8059 for (const Stmt *Child : S->children()) 8060 Res = (Child && Visit(Child)) || Res; 8061 return Res; 8062 } 8063 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack, 8064 const ValueDecl *CurLCDecl, bool IsInitializer, 8065 const ValueDecl *PrevDepDecl = nullptr, 8066 bool SupportsNonRectangular = true) 8067 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl), 8068 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer), 8069 SupportsNonRectangular(SupportsNonRectangular) {} 8070 unsigned getBaseLoopId() const { 8071 assert(CurLCDecl && "Expected loop dependency."); 8072 return BaseLoopId; 8073 } 8074 const ValueDecl *getDepDecl() const { 8075 assert(CurLCDecl && "Expected loop dependency."); 8076 return DepDecl; 8077 } 8078 }; 8079 } // namespace 8080 8081 std::optional<unsigned> 8082 OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S, 8083 bool IsInitializer) { 8084 // Check for the non-rectangular loops. 8085 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer, 8086 DepDecl, SupportsNonRectangular); 8087 if (LoopStmtChecker.Visit(S)) { 8088 DepDecl = LoopStmtChecker.getDepDecl(); 8089 return LoopStmtChecker.getBaseLoopId(); 8090 } 8091 return std::nullopt; 8092 } 8093 8094 bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) { 8095 // Check init-expr for canonical loop form and save loop counter 8096 // variable - #Var and its initialization value - #LB. 8097 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following: 8098 // var = lb 8099 // integer-type var = lb 8100 // random-access-iterator-type var = lb 8101 // pointer-type var = lb 8102 // 8103 if (!S) { 8104 if (EmitDiags) { 8105 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init); 8106 } 8107 return true; 8108 } 8109 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S)) 8110 if (!ExprTemp->cleanupsHaveSideEffects()) 8111 S = ExprTemp->getSubExpr(); 8112 8113 if (!CollapsedLoopVarDecls.empty()) { 8114 ForSubExprChecker FSEC{CollapsedLoopVarDecls}; 8115 if (!FSEC.TraverseStmt(S)) { 8116 SourceRange Range = FSEC.getErrRange(); 8117 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var) 8118 << Range.getEnd() << 0 << FSEC.getForbiddenVar(); 8119 return true; 8120 } 8121 } 8122 8123 InitSrcRange = S->getSourceRange(); 8124 if (Expr *E = dyn_cast<Expr>(S)) 8125 S = E->IgnoreParens(); 8126 if (auto *BO = dyn_cast<BinaryOperator>(S)) { 8127 if (BO->getOpcode() == BO_Assign) { 8128 Expr *LHS = BO->getLHS()->IgnoreParens(); 8129 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) { 8130 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl())) 8131 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit()))) 8132 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(), 8133 EmitDiags); 8134 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags); 8135 } 8136 if (auto *ME = dyn_cast<MemberExpr>(LHS)) { 8137 if (ME->isArrow() && 8138 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) 8139 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(), 8140 EmitDiags); 8141 } 8142 } 8143 } else if (auto *DS = dyn_cast<DeclStmt>(S)) { 8144 if (DS->isSingleDecl()) { 8145 if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) { 8146 if (Var->hasInit() && !Var->getType()->isReferenceType()) { 8147 // Accept non-canonical init form here but emit ext. warning. 8148 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags) 8149 SemaRef.Diag(S->getBeginLoc(), 8150 diag::ext_omp_loop_not_canonical_init) 8151 << S->getSourceRange(); 8152 return setLCDeclAndLB( 8153 Var, 8154 buildDeclRefExpr(SemaRef, Var, 8155 Var->getType().getNonReferenceType(), 8156 DS->getBeginLoc()), 8157 Var->getInit(), EmitDiags); 8158 } 8159 } 8160 } 8161 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) { 8162 if (CE->getOperator() == OO_Equal) { 8163 Expr *LHS = CE->getArg(0); 8164 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) { 8165 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl())) 8166 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit()))) 8167 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(), 8168 EmitDiags); 8169 return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags); 8170 } 8171 if (auto *ME = dyn_cast<MemberExpr>(LHS)) { 8172 if (ME->isArrow() && 8173 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) 8174 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(), 8175 EmitDiags); 8176 } 8177 } 8178 } 8179 8180 if (dependent() || SemaRef.CurContext->isDependentContext()) 8181 return false; 8182 if (EmitDiags) { 8183 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init) 8184 << S->getSourceRange(); 8185 } 8186 return true; 8187 } 8188 8189 /// Ignore parenthesizes, implicit casts, copy constructor and return the 8190 /// variable (which may be the loop variable) if possible. 8191 static const ValueDecl *getInitLCDecl(const Expr *E) { 8192 if (!E) 8193 return nullptr; 8194 E = getExprAsWritten(E); 8195 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E)) 8196 if (const CXXConstructorDecl *Ctor = CE->getConstructor()) 8197 if ((Ctor->isCopyOrMoveConstructor() || 8198 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) && 8199 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr) 8200 E = CE->getArg(0)->IgnoreParenImpCasts(); 8201 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) { 8202 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) 8203 return getCanonicalDecl(VD); 8204 } 8205 if (const auto *ME = dyn_cast_or_null<MemberExpr>(E)) 8206 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) 8207 return getCanonicalDecl(ME->getMemberDecl()); 8208 return nullptr; 8209 } 8210 8211 bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) { 8212 // Check test-expr for canonical form, save upper-bound UB, flags for 8213 // less/greater and for strict/non-strict comparison. 8214 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following: 8215 // var relational-op b 8216 // b relational-op var 8217 // 8218 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50; 8219 if (!S) { 8220 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond) 8221 << (IneqCondIsCanonical ? 1 : 0) << LCDecl; 8222 return true; 8223 } 8224 Condition = S; 8225 S = getExprAsWritten(S); 8226 8227 if (!CollapsedLoopVarDecls.empty()) { 8228 ForSubExprChecker FSEC{CollapsedLoopVarDecls}; 8229 if (!FSEC.TraverseStmt(S)) { 8230 SourceRange Range = FSEC.getErrRange(); 8231 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var) 8232 << Range.getEnd() << 1 << FSEC.getForbiddenVar(); 8233 return true; 8234 } 8235 } 8236 8237 SourceLocation CondLoc = S->getBeginLoc(); 8238 auto &&CheckAndSetCond = 8239 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS, 8240 const Expr *RHS, SourceRange SR, 8241 SourceLocation OpLoc) -> std::optional<bool> { 8242 if (BinaryOperator::isRelationalOp(Opcode)) { 8243 if (getInitLCDecl(LHS) == LCDecl) 8244 return setUB(const_cast<Expr *>(RHS), 8245 (Opcode == BO_LT || Opcode == BO_LE), 8246 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc); 8247 if (getInitLCDecl(RHS) == LCDecl) 8248 return setUB(const_cast<Expr *>(LHS), 8249 (Opcode == BO_GT || Opcode == BO_GE), 8250 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc); 8251 } else if (IneqCondIsCanonical && Opcode == BO_NE) { 8252 return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS), 8253 /*LessOp=*/std::nullopt, 8254 /*StrictOp=*/true, SR, OpLoc); 8255 } 8256 return std::nullopt; 8257 }; 8258 std::optional<bool> Res; 8259 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) { 8260 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm(); 8261 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(), 8262 RBO->getOperatorLoc()); 8263 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) { 8264 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(), 8265 BO->getSourceRange(), BO->getOperatorLoc()); 8266 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) { 8267 if (CE->getNumArgs() == 2) { 8268 Res = CheckAndSetCond( 8269 BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0), 8270 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc()); 8271 } 8272 } 8273 if (Res) 8274 return *Res; 8275 if (dependent() || SemaRef.CurContext->isDependentContext()) 8276 return false; 8277 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond) 8278 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl; 8279 return true; 8280 } 8281 8282 bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) { 8283 // RHS of canonical loop form increment can be: 8284 // var + incr 8285 // incr + var 8286 // var - incr 8287 // 8288 RHS = RHS->IgnoreParenImpCasts(); 8289 if (auto *BO = dyn_cast<BinaryOperator>(RHS)) { 8290 if (BO->isAdditiveOp()) { 8291 bool IsAdd = BO->getOpcode() == BO_Add; 8292 if (getInitLCDecl(BO->getLHS()) == LCDecl) 8293 return setStep(BO->getRHS(), !IsAdd); 8294 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl) 8295 return setStep(BO->getLHS(), /*Subtract=*/false); 8296 } 8297 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) { 8298 bool IsAdd = CE->getOperator() == OO_Plus; 8299 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) { 8300 if (getInitLCDecl(CE->getArg(0)) == LCDecl) 8301 return setStep(CE->getArg(1), !IsAdd); 8302 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl) 8303 return setStep(CE->getArg(0), /*Subtract=*/false); 8304 } 8305 } 8306 if (dependent() || SemaRef.CurContext->isDependentContext()) 8307 return false; 8308 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr) 8309 << RHS->getSourceRange() << LCDecl; 8310 return true; 8311 } 8312 8313 bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) { 8314 // Check incr-expr for canonical loop form and return true if it 8315 // does not conform. 8316 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following: 8317 // ++var 8318 // var++ 8319 // --var 8320 // var-- 8321 // var += incr 8322 // var -= incr 8323 // var = var + incr 8324 // var = incr + var 8325 // var = var - incr 8326 // 8327 if (!S) { 8328 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl; 8329 return true; 8330 } 8331 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S)) 8332 if (!ExprTemp->cleanupsHaveSideEffects()) 8333 S = ExprTemp->getSubExpr(); 8334 8335 if (!CollapsedLoopVarDecls.empty()) { 8336 ForSubExprChecker FSEC{CollapsedLoopVarDecls}; 8337 if (!FSEC.TraverseStmt(S)) { 8338 SourceRange Range = FSEC.getErrRange(); 8339 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var) 8340 << Range.getEnd() << 2 << FSEC.getForbiddenVar(); 8341 return true; 8342 } 8343 } 8344 8345 IncrementSrcRange = S->getSourceRange(); 8346 S = S->IgnoreParens(); 8347 if (auto *UO = dyn_cast<UnaryOperator>(S)) { 8348 if (UO->isIncrementDecrementOp() && 8349 getInitLCDecl(UO->getSubExpr()) == LCDecl) 8350 return setStep(SemaRef 8351 .ActOnIntegerConstant(UO->getBeginLoc(), 8352 (UO->isDecrementOp() ? -1 : 1)) 8353 .get(), 8354 /*Subtract=*/false); 8355 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) { 8356 switch (BO->getOpcode()) { 8357 case BO_AddAssign: 8358 case BO_SubAssign: 8359 if (getInitLCDecl(BO->getLHS()) == LCDecl) 8360 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign); 8361 break; 8362 case BO_Assign: 8363 if (getInitLCDecl(BO->getLHS()) == LCDecl) 8364 return checkAndSetIncRHS(BO->getRHS()); 8365 break; 8366 default: 8367 break; 8368 } 8369 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) { 8370 switch (CE->getOperator()) { 8371 case OO_PlusPlus: 8372 case OO_MinusMinus: 8373 if (getInitLCDecl(CE->getArg(0)) == LCDecl) 8374 return setStep(SemaRef 8375 .ActOnIntegerConstant( 8376 CE->getBeginLoc(), 8377 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1)) 8378 .get(), 8379 /*Subtract=*/false); 8380 break; 8381 case OO_PlusEqual: 8382 case OO_MinusEqual: 8383 if (getInitLCDecl(CE->getArg(0)) == LCDecl) 8384 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual); 8385 break; 8386 case OO_Equal: 8387 if (getInitLCDecl(CE->getArg(0)) == LCDecl) 8388 return checkAndSetIncRHS(CE->getArg(1)); 8389 break; 8390 default: 8391 break; 8392 } 8393 } 8394 if (dependent() || SemaRef.CurContext->isDependentContext()) 8395 return false; 8396 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr) 8397 << S->getSourceRange() << LCDecl; 8398 return true; 8399 } 8400 8401 static ExprResult 8402 tryBuildCapture(Sema &SemaRef, Expr *Capture, 8403 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, 8404 StringRef Name = ".capture_expr.") { 8405 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors()) 8406 return Capture; 8407 if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects)) 8408 return SemaRef.PerformImplicitConversion(Capture->IgnoreImpCasts(), 8409 Capture->getType(), 8410 AssignmentAction::Converting, 8411 /*AllowExplicit=*/true); 8412 auto I = Captures.find(Capture); 8413 if (I != Captures.end()) 8414 return buildCapture(SemaRef, Capture, I->second, Name); 8415 DeclRefExpr *Ref = nullptr; 8416 ExprResult Res = buildCapture(SemaRef, Capture, Ref, Name); 8417 Captures[Capture] = Ref; 8418 return Res; 8419 } 8420 8421 /// Calculate number of iterations, transforming to unsigned, if number of 8422 /// iterations may be larger than the original type. 8423 static Expr * 8424 calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc, 8425 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy, 8426 bool TestIsStrictOp, bool RoundToStep, 8427 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) { 8428 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step"); 8429 if (!NewStep.isUsable()) 8430 return nullptr; 8431 llvm::APSInt LRes, SRes; 8432 bool IsLowerConst = false, IsStepConst = false; 8433 if (std::optional<llvm::APSInt> Res = 8434 Lower->getIntegerConstantExpr(SemaRef.Context)) { 8435 LRes = *Res; 8436 IsLowerConst = true; 8437 } 8438 if (std::optional<llvm::APSInt> Res = 8439 Step->getIntegerConstantExpr(SemaRef.Context)) { 8440 SRes = *Res; 8441 IsStepConst = true; 8442 } 8443 bool NoNeedToConvert = IsLowerConst && !RoundToStep && 8444 ((!TestIsStrictOp && LRes.isNonNegative()) || 8445 (TestIsStrictOp && LRes.isStrictlyPositive())); 8446 bool NeedToReorganize = false; 8447 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow. 8448 if (!NoNeedToConvert && IsLowerConst && 8449 (TestIsStrictOp || (RoundToStep && IsStepConst))) { 8450 NoNeedToConvert = true; 8451 if (RoundToStep) { 8452 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth() 8453 ? LRes.getBitWidth() 8454 : SRes.getBitWidth(); 8455 LRes = LRes.extend(BW + 1); 8456 LRes.setIsSigned(true); 8457 SRes = SRes.extend(BW + 1); 8458 SRes.setIsSigned(true); 8459 LRes -= SRes; 8460 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes; 8461 LRes = LRes.trunc(BW); 8462 } 8463 if (TestIsStrictOp) { 8464 unsigned BW = LRes.getBitWidth(); 8465 LRes = LRes.extend(BW + 1); 8466 LRes.setIsSigned(true); 8467 ++LRes; 8468 NoNeedToConvert = 8469 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes; 8470 // truncate to the original bitwidth. 8471 LRes = LRes.trunc(BW); 8472 } 8473 NeedToReorganize = NoNeedToConvert; 8474 } 8475 llvm::APSInt URes; 8476 bool IsUpperConst = false; 8477 if (std::optional<llvm::APSInt> Res = 8478 Upper->getIntegerConstantExpr(SemaRef.Context)) { 8479 URes = *Res; 8480 IsUpperConst = true; 8481 } 8482 if (NoNeedToConvert && IsLowerConst && IsUpperConst && 8483 (!RoundToStep || IsStepConst)) { 8484 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth() 8485 : URes.getBitWidth(); 8486 LRes = LRes.extend(BW + 1); 8487 LRes.setIsSigned(true); 8488 URes = URes.extend(BW + 1); 8489 URes.setIsSigned(true); 8490 URes -= LRes; 8491 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes; 8492 NeedToReorganize = NoNeedToConvert; 8493 } 8494 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant 8495 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to 8496 // unsigned. 8497 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) && 8498 !LCTy->isDependentType() && LCTy->isIntegerType()) { 8499 QualType LowerTy = Lower->getType(); 8500 QualType UpperTy = Upper->getType(); 8501 uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy); 8502 uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy); 8503 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) || 8504 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) { 8505 QualType CastType = SemaRef.Context.getIntTypeForBitwidth( 8506 LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0); 8507 Upper = 8508 SemaRef 8509 .PerformImplicitConversion( 8510 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(), 8511 CastType, AssignmentAction::Converting) 8512 .get(); 8513 Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(); 8514 NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get()); 8515 } 8516 } 8517 if (!Lower || !Upper || NewStep.isInvalid()) 8518 return nullptr; 8519 8520 ExprResult Diff; 8521 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+ 8522 // 1]). 8523 if (NeedToReorganize) { 8524 Diff = Lower; 8525 8526 if (RoundToStep) { 8527 // Lower - Step 8528 Diff = 8529 SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get()); 8530 if (!Diff.isUsable()) 8531 return nullptr; 8532 } 8533 8534 // Lower - Step [+ 1] 8535 if (TestIsStrictOp) 8536 Diff = SemaRef.BuildBinOp( 8537 S, DefaultLoc, BO_Add, Diff.get(), 8538 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get()); 8539 if (!Diff.isUsable()) 8540 return nullptr; 8541 8542 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get()); 8543 if (!Diff.isUsable()) 8544 return nullptr; 8545 8546 // Upper - (Lower - Step [+ 1]). 8547 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get()); 8548 if (!Diff.isUsable()) 8549 return nullptr; 8550 } else { 8551 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower); 8552 8553 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) { 8554 // BuildBinOp already emitted error, this one is to point user to upper 8555 // and lower bound, and to tell what is passed to 'operator-'. 8556 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx) 8557 << Upper->getSourceRange() << Lower->getSourceRange(); 8558 return nullptr; 8559 } 8560 8561 if (!Diff.isUsable()) 8562 return nullptr; 8563 8564 // Upper - Lower [- 1] 8565 if (TestIsStrictOp) 8566 Diff = SemaRef.BuildBinOp( 8567 S, DefaultLoc, BO_Sub, Diff.get(), 8568 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get()); 8569 if (!Diff.isUsable()) 8570 return nullptr; 8571 8572 if (RoundToStep) { 8573 // Upper - Lower [- 1] + Step 8574 Diff = 8575 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get()); 8576 if (!Diff.isUsable()) 8577 return nullptr; 8578 } 8579 } 8580 8581 // Parentheses (for dumping/debugging purposes only). 8582 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get()); 8583 if (!Diff.isUsable()) 8584 return nullptr; 8585 8586 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step 8587 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get()); 8588 if (!Diff.isUsable()) 8589 return nullptr; 8590 8591 return Diff.get(); 8592 } 8593 8594 /// Build the expression to calculate the number of iterations. 8595 Expr *OpenMPIterationSpaceChecker::buildNumIterations( 8596 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType, 8597 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const { 8598 QualType VarType = LCDecl->getType().getNonReferenceType(); 8599 if (!VarType->isIntegerType() && !VarType->isPointerType() && 8600 !SemaRef.getLangOpts().CPlusPlus) 8601 return nullptr; 8602 Expr *LBVal = LB; 8603 Expr *UBVal = UB; 8604 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) : 8605 // max(LB(MinVal), LB(MaxVal))) 8606 if (InitDependOnLC) { 8607 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1]; 8608 if (!IS.MinValue || !IS.MaxValue) 8609 return nullptr; 8610 // OuterVar = Min 8611 ExprResult MinValue = 8612 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue); 8613 if (!MinValue.isUsable()) 8614 return nullptr; 8615 8616 ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, 8617 IS.CounterVar, MinValue.get()); 8618 if (!LBMinVal.isUsable()) 8619 return nullptr; 8620 // OuterVar = Min, LBVal 8621 LBMinVal = 8622 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal); 8623 if (!LBMinVal.isUsable()) 8624 return nullptr; 8625 // (OuterVar = Min, LBVal) 8626 LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get()); 8627 if (!LBMinVal.isUsable()) 8628 return nullptr; 8629 8630 // OuterVar = Max 8631 ExprResult MaxValue = 8632 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue); 8633 if (!MaxValue.isUsable()) 8634 return nullptr; 8635 8636 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, 8637 IS.CounterVar, MaxValue.get()); 8638 if (!LBMaxVal.isUsable()) 8639 return nullptr; 8640 // OuterVar = Max, LBVal 8641 LBMaxVal = 8642 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal); 8643 if (!LBMaxVal.isUsable()) 8644 return nullptr; 8645 // (OuterVar = Max, LBVal) 8646 LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get()); 8647 if (!LBMaxVal.isUsable()) 8648 return nullptr; 8649 8650 Expr *LBMin = 8651 tryBuildCapture(SemaRef, LBMinVal.get(), Captures, ".lb_min").get(); 8652 Expr *LBMax = 8653 tryBuildCapture(SemaRef, LBMaxVal.get(), Captures, ".lb_max").get(); 8654 if (!LBMin || !LBMax) 8655 return nullptr; 8656 // LB(MinVal) < LB(MaxVal) 8657 ExprResult MinLessMaxRes = 8658 SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax); 8659 if (!MinLessMaxRes.isUsable()) 8660 return nullptr; 8661 Expr *MinLessMax = 8662 tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures, ".min_less_max") 8663 .get(); 8664 if (!MinLessMax) 8665 return nullptr; 8666 if (*TestIsLessOp) { 8667 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal), 8668 // LB(MaxVal)) 8669 ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc, 8670 MinLessMax, LBMin, LBMax); 8671 if (!MinLB.isUsable()) 8672 return nullptr; 8673 LBVal = MinLB.get(); 8674 } else { 8675 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal), 8676 // LB(MaxVal)) 8677 ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc, 8678 MinLessMax, LBMax, LBMin); 8679 if (!MaxLB.isUsable()) 8680 return nullptr; 8681 LBVal = MaxLB.get(); 8682 } 8683 // OuterVar = LB 8684 LBMinVal = 8685 SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal); 8686 if (!LBMinVal.isUsable()) 8687 return nullptr; 8688 LBVal = LBMinVal.get(); 8689 } 8690 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) : 8691 // min(UB(MinVal), UB(MaxVal)) 8692 if (CondDependOnLC) { 8693 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1]; 8694 if (!IS.MinValue || !IS.MaxValue) 8695 return nullptr; 8696 // OuterVar = Min 8697 ExprResult MinValue = 8698 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue); 8699 if (!MinValue.isUsable()) 8700 return nullptr; 8701 8702 ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, 8703 IS.CounterVar, MinValue.get()); 8704 if (!UBMinVal.isUsable()) 8705 return nullptr; 8706 // OuterVar = Min, UBVal 8707 UBMinVal = 8708 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal); 8709 if (!UBMinVal.isUsable()) 8710 return nullptr; 8711 // (OuterVar = Min, UBVal) 8712 UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get()); 8713 if (!UBMinVal.isUsable()) 8714 return nullptr; 8715 8716 // OuterVar = Max 8717 ExprResult MaxValue = 8718 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue); 8719 if (!MaxValue.isUsable()) 8720 return nullptr; 8721 8722 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, 8723 IS.CounterVar, MaxValue.get()); 8724 if (!UBMaxVal.isUsable()) 8725 return nullptr; 8726 // OuterVar = Max, UBVal 8727 UBMaxVal = 8728 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal); 8729 if (!UBMaxVal.isUsable()) 8730 return nullptr; 8731 // (OuterVar = Max, UBVal) 8732 UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get()); 8733 if (!UBMaxVal.isUsable()) 8734 return nullptr; 8735 8736 Expr *UBMin = 8737 tryBuildCapture(SemaRef, UBMinVal.get(), Captures, ".ub_min").get(); 8738 Expr *UBMax = 8739 tryBuildCapture(SemaRef, UBMaxVal.get(), Captures, ".ub_max").get(); 8740 if (!UBMin || !UBMax) 8741 return nullptr; 8742 // UB(MinVal) > UB(MaxVal) 8743 ExprResult MinGreaterMaxRes = 8744 SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax); 8745 if (!MinGreaterMaxRes.isUsable()) 8746 return nullptr; 8747 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.get(), 8748 Captures, ".min_greater_max") 8749 .get(); 8750 if (!MinGreaterMax) 8751 return nullptr; 8752 if (*TestIsLessOp) { 8753 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal), 8754 // UB(MaxVal)) 8755 ExprResult MaxUB = SemaRef.ActOnConditionalOp( 8756 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax); 8757 if (!MaxUB.isUsable()) 8758 return nullptr; 8759 UBVal = MaxUB.get(); 8760 } else { 8761 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal), 8762 // UB(MaxVal)) 8763 ExprResult MinUB = SemaRef.ActOnConditionalOp( 8764 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin); 8765 if (!MinUB.isUsable()) 8766 return nullptr; 8767 UBVal = MinUB.get(); 8768 } 8769 } 8770 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal; 8771 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal; 8772 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures, ".upper").get(); 8773 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures, ".lower").get(); 8774 if (!Upper || !Lower) 8775 return nullptr; 8776 8777 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper, 8778 Step, VarType, TestIsStrictOp, 8779 /*RoundToStep=*/true, Captures); 8780 if (!Diff.isUsable()) 8781 return nullptr; 8782 8783 // OpenMP runtime requires 32-bit or 64-bit loop variables. 8784 QualType Type = Diff.get()->getType(); 8785 ASTContext &C = SemaRef.Context; 8786 bool UseVarType = VarType->hasIntegerRepresentation() && 8787 C.getTypeSize(Type) > C.getTypeSize(VarType); 8788 if (!Type->isIntegerType() || UseVarType) { 8789 unsigned NewSize = 8790 UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type); 8791 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation() 8792 : Type->hasSignedIntegerRepresentation(); 8793 Type = C.getIntTypeForBitwidth(NewSize, IsSigned); 8794 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) { 8795 Diff = SemaRef.PerformImplicitConversion(Diff.get(), Type, 8796 AssignmentAction::Converting, 8797 /*AllowExplicit=*/true); 8798 if (!Diff.isUsable()) 8799 return nullptr; 8800 } 8801 } 8802 if (LimitedType) { 8803 unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32; 8804 if (NewSize != C.getTypeSize(Type)) { 8805 if (NewSize < C.getTypeSize(Type)) { 8806 assert(NewSize == 64 && "incorrect loop var size"); 8807 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var) 8808 << InitSrcRange << ConditionSrcRange; 8809 } 8810 QualType NewType = C.getIntTypeForBitwidth( 8811 NewSize, Type->hasSignedIntegerRepresentation() || 8812 C.getTypeSize(Type) < NewSize); 8813 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) { 8814 Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType, 8815 AssignmentAction::Converting, 8816 /*AllowExplicit=*/true); 8817 if (!Diff.isUsable()) 8818 return nullptr; 8819 } 8820 } 8821 } 8822 8823 return Diff.get(); 8824 } 8825 8826 std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues( 8827 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const { 8828 // Do not build for iterators, they cannot be used in non-rectangular loop 8829 // nests. 8830 if (LCDecl->getType()->isRecordType()) 8831 return std::make_pair(nullptr, nullptr); 8832 // If we subtract, the min is in the condition, otherwise the min is in the 8833 // init value. 8834 Expr *MinExpr = nullptr; 8835 Expr *MaxExpr = nullptr; 8836 Expr *LBExpr = *TestIsLessOp ? LB : UB; 8837 Expr *UBExpr = *TestIsLessOp ? UB : LB; 8838 bool LBNonRect = 8839 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value(); 8840 bool UBNonRect = 8841 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value(); 8842 Expr *Lower = 8843 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get(); 8844 Expr *Upper = 8845 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get(); 8846 if (!Upper || !Lower) 8847 return std::make_pair(nullptr, nullptr); 8848 8849 if (*TestIsLessOp) 8850 MinExpr = Lower; 8851 else 8852 MaxExpr = Upper; 8853 8854 // Build minimum/maximum value based on number of iterations. 8855 QualType VarType = LCDecl->getType().getNonReferenceType(); 8856 8857 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper, 8858 Step, VarType, TestIsStrictOp, 8859 /*RoundToStep=*/false, Captures); 8860 if (!Diff.isUsable()) 8861 return std::make_pair(nullptr, nullptr); 8862 8863 // ((Upper - Lower [- 1]) / Step) * Step 8864 // Parentheses (for dumping/debugging purposes only). 8865 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get()); 8866 if (!Diff.isUsable()) 8867 return std::make_pair(nullptr, nullptr); 8868 8869 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step"); 8870 if (!NewStep.isUsable()) 8871 return std::make_pair(nullptr, nullptr); 8872 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get()); 8873 if (!Diff.isUsable()) 8874 return std::make_pair(nullptr, nullptr); 8875 8876 // Parentheses (for dumping/debugging purposes only). 8877 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get()); 8878 if (!Diff.isUsable()) 8879 return std::make_pair(nullptr, nullptr); 8880 8881 // Convert to the ptrdiff_t, if original type is pointer. 8882 if (VarType->isAnyPointerType() && 8883 !SemaRef.Context.hasSameType( 8884 Diff.get()->getType(), 8885 SemaRef.Context.getUnsignedPointerDiffType())) { 8886 Diff = SemaRef.PerformImplicitConversion( 8887 Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(), 8888 AssignmentAction::Converting, /*AllowExplicit=*/true); 8889 } 8890 if (!Diff.isUsable()) 8891 return std::make_pair(nullptr, nullptr); 8892 8893 if (*TestIsLessOp) { 8894 // MinExpr = Lower; 8895 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step) 8896 Diff = SemaRef.BuildBinOp( 8897 S, DefaultLoc, BO_Add, 8898 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(), 8899 Diff.get()); 8900 if (!Diff.isUsable()) 8901 return std::make_pair(nullptr, nullptr); 8902 } else { 8903 // MaxExpr = Upper; 8904 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step) 8905 Diff = SemaRef.BuildBinOp( 8906 S, DefaultLoc, BO_Sub, 8907 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(), 8908 Diff.get()); 8909 if (!Diff.isUsable()) 8910 return std::make_pair(nullptr, nullptr); 8911 } 8912 8913 // Convert to the original type. 8914 if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType)) 8915 Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType, 8916 AssignmentAction::Converting, 8917 /*AllowExplicit=*/true); 8918 if (!Diff.isUsable()) 8919 return std::make_pair(nullptr, nullptr); 8920 8921 Sema::TentativeAnalysisScope Trap(SemaRef); 8922 Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false); 8923 if (!Diff.isUsable()) 8924 return std::make_pair(nullptr, nullptr); 8925 8926 if (*TestIsLessOp) 8927 MaxExpr = Diff.get(); 8928 else 8929 MinExpr = Diff.get(); 8930 8931 return std::make_pair(MinExpr, MaxExpr); 8932 } 8933 8934 Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const { 8935 if (InitDependOnLC || CondDependOnLC) 8936 return Condition; 8937 return nullptr; 8938 } 8939 8940 Expr *OpenMPIterationSpaceChecker::buildPreCond( 8941 Scope *S, Expr *Cond, 8942 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const { 8943 // Do not build a precondition when the condition/initialization is dependent 8944 // to prevent pessimistic early loop exit. 8945 // TODO: this can be improved by calculating min/max values but not sure that 8946 // it will be very effective. 8947 if (CondDependOnLC || InitDependOnLC) 8948 return SemaRef 8949 .PerformImplicitConversion( 8950 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(), 8951 SemaRef.Context.BoolTy, /*Action=*/AssignmentAction::Casting, 8952 /*AllowExplicit=*/true) 8953 .get(); 8954 8955 // Try to build LB <op> UB, where <op> is <, >, <=, or >=. 8956 Sema::TentativeAnalysisScope Trap(SemaRef); 8957 8958 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures); 8959 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures); 8960 if (!NewLB.isUsable() || !NewUB.isUsable()) 8961 return nullptr; 8962 8963 ExprResult CondExpr = 8964 SemaRef.BuildBinOp(S, DefaultLoc, 8965 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE) 8966 : (TestIsStrictOp ? BO_GT : BO_GE), 8967 NewLB.get(), NewUB.get()); 8968 if (CondExpr.isUsable()) { 8969 if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(), 8970 SemaRef.Context.BoolTy)) 8971 CondExpr = SemaRef.PerformImplicitConversion( 8972 CondExpr.get(), SemaRef.Context.BoolTy, 8973 /*Action=*/AssignmentAction::Casting, 8974 /*AllowExplicit=*/true); 8975 } 8976 8977 // Otherwise use original loop condition and evaluate it in runtime. 8978 return CondExpr.isUsable() ? CondExpr.get() : Cond; 8979 } 8980 8981 /// Build reference expression to the counter be used for codegen. 8982 DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar( 8983 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, 8984 DSAStackTy &DSA) const { 8985 auto *VD = dyn_cast<VarDecl>(LCDecl); 8986 if (!VD) { 8987 VD = SemaRef.OpenMP().isOpenMPCapturedDecl(LCDecl); 8988 DeclRefExpr *Ref = buildDeclRefExpr( 8989 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc); 8990 const DSAStackTy::DSAVarData Data = 8991 DSA.getTopDSA(LCDecl, /*FromParent=*/false); 8992 // If the loop control decl is explicitly marked as private, do not mark it 8993 // as captured again. 8994 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr) 8995 Captures.insert(std::make_pair(LCRef, Ref)); 8996 return Ref; 8997 } 8998 return cast<DeclRefExpr>(LCRef); 8999 } 9000 9001 Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const { 9002 if (LCDecl && !LCDecl->isInvalidDecl()) { 9003 QualType Type = LCDecl->getType().getNonReferenceType(); 9004 VarDecl *PrivateVar = buildVarDecl( 9005 SemaRef, DefaultLoc, Type, LCDecl->getName(), 9006 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr, 9007 isa<VarDecl>(LCDecl) 9008 ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc) 9009 : nullptr); 9010 if (PrivateVar->isInvalidDecl()) 9011 return nullptr; 9012 return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc); 9013 } 9014 return nullptr; 9015 } 9016 9017 /// Build initialization of the counter to be used for codegen. 9018 Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; } 9019 9020 /// Build step of the counter be used for codegen. 9021 Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; } 9022 9023 Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData( 9024 Scope *S, Expr *Counter, 9025 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc, 9026 Expr *Inc, OverloadedOperatorKind OOK) { 9027 Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get(); 9028 if (!Cnt) 9029 return nullptr; 9030 if (Inc) { 9031 assert((OOK == OO_Plus || OOK == OO_Minus) && 9032 "Expected only + or - operations for depend clauses."); 9033 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub; 9034 Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get(); 9035 if (!Cnt) 9036 return nullptr; 9037 } 9038 QualType VarType = LCDecl->getType().getNonReferenceType(); 9039 if (!VarType->isIntegerType() && !VarType->isPointerType() && 9040 !SemaRef.getLangOpts().CPlusPlus) 9041 return nullptr; 9042 // Upper - Lower 9043 Expr *Upper = 9044 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get(); 9045 Expr *Lower = 9046 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt; 9047 if (!Upper || !Lower) 9048 return nullptr; 9049 9050 ExprResult Diff = calculateNumIters( 9051 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType, 9052 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures); 9053 if (!Diff.isUsable()) 9054 return nullptr; 9055 9056 return Diff.get(); 9057 } 9058 } // namespace 9059 9060 void SemaOpenMP::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, 9061 Stmt *Init) { 9062 assert(getLangOpts().OpenMP && "OpenMP is not active."); 9063 assert(Init && "Expected loop in canonical form."); 9064 unsigned AssociatedLoops = DSAStack->getAssociatedLoops(); 9065 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); 9066 if (AssociatedLoops == 0 || !isOpenMPLoopDirective(DKind)) 9067 return; 9068 9069 DSAStack->loopStart(); 9070 llvm::SmallPtrSet<const Decl *, 1> EmptyDeclSet; 9071 OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true, 9072 *DSAStack, ForLoc, EmptyDeclSet); 9073 if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) { 9074 if (ValueDecl *D = ISC.getLoopDecl()) { 9075 auto *VD = dyn_cast<VarDecl>(D); 9076 DeclRefExpr *PrivateRef = nullptr; 9077 if (!VD) { 9078 if (VarDecl *Private = isOpenMPCapturedDecl(D)) { 9079 VD = Private; 9080 } else { 9081 PrivateRef = buildCapture(SemaRef, D, ISC.getLoopDeclRefExpr(), 9082 /*WithInit=*/false); 9083 VD = cast<VarDecl>(PrivateRef->getDecl()); 9084 } 9085 } 9086 DSAStack->addLoopControlVariable(D, VD); 9087 const Decl *LD = DSAStack->getPossiblyLoopCounter(); 9088 if (LD != D->getCanonicalDecl()) { 9089 DSAStack->resetPossibleLoopCounter(); 9090 if (auto *Var = dyn_cast_or_null<VarDecl>(LD)) 9091 SemaRef.MarkDeclarationsReferencedInExpr(buildDeclRefExpr( 9092 SemaRef, const_cast<VarDecl *>(Var), 9093 Var->getType().getNonLValueExprType(getASTContext()), ForLoc, 9094 /*RefersToCapture=*/true)); 9095 } 9096 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables 9097 // Referenced in a Construct, C/C++]. The loop iteration variable in the 9098 // associated for-loop of a simd construct with just one associated 9099 // for-loop may be listed in a linear clause with a constant-linear-step 9100 // that is the increment of the associated for-loop. The loop iteration 9101 // variable(s) in the associated for-loop(s) of a for or parallel for 9102 // construct may be listed in a private or lastprivate clause. 9103 DSAStackTy::DSAVarData DVar = 9104 DSAStack->getTopDSA(D, /*FromParent=*/false); 9105 // If LoopVarRefExpr is nullptr it means the corresponding loop variable 9106 // is declared in the loop and it is predetermined as a private. 9107 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr(); 9108 OpenMPClauseKind PredeterminedCKind = 9109 isOpenMPSimdDirective(DKind) 9110 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear) 9111 : OMPC_private; 9112 auto IsOpenMPTaskloopDirective = [](OpenMPDirectiveKind DK) { 9113 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop; 9114 }; 9115 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown && 9116 DVar.CKind != PredeterminedCKind && DVar.RefExpr && 9117 (getLangOpts().OpenMP <= 45 || 9118 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) || 9119 ((isOpenMPWorksharingDirective(DKind) || 9120 IsOpenMPTaskloopDirective(DKind) || 9121 isOpenMPDistributeDirective(DKind)) && 9122 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown && 9123 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) && 9124 (DVar.CKind != OMPC_private || DVar.RefExpr)) { 9125 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa) 9126 << getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind) 9127 << getOpenMPClauseName(PredeterminedCKind); 9128 if (DVar.RefExpr == nullptr) 9129 DVar.CKind = PredeterminedCKind; 9130 reportOriginalDsa(SemaRef, DSAStack, D, DVar, /*IsLoopIterVar=*/true); 9131 } else if (LoopDeclRefExpr) { 9132 // Make the loop iteration variable private (for worksharing 9133 // constructs), linear (for simd directives with the only one 9134 // associated loop) or lastprivate (for simd directives with several 9135 // collapsed or ordered loops). 9136 if (DVar.CKind == OMPC_unknown) 9137 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef); 9138 } 9139 } 9140 } 9141 DSAStack->setAssociatedLoops(AssociatedLoops - 1); 9142 } 9143 9144 namespace { 9145 // Utility for OpenMP doacross clause kind 9146 class OMPDoacrossKind { 9147 public: 9148 bool isSource(const OMPDoacrossClause *C) { 9149 return C->getDependenceType() == OMPC_DOACROSS_source || 9150 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration; 9151 } 9152 bool isSink(const OMPDoacrossClause *C) { 9153 return C->getDependenceType() == OMPC_DOACROSS_sink; 9154 } 9155 bool isSinkIter(const OMPDoacrossClause *C) { 9156 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration; 9157 } 9158 }; 9159 } // namespace 9160 /// Called on a for stmt to check and extract its iteration space 9161 /// for further processing (such as collapsing). 9162 static bool checkOpenMPIterationSpace( 9163 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA, 9164 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount, 9165 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr, 9166 Expr *OrderedLoopCountExpr, 9167 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA, 9168 llvm::MutableArrayRef<LoopIterationSpace> ResultIterSpaces, 9169 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, 9170 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls) { 9171 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind); 9172 // OpenMP [2.9.1, Canonical Loop Form] 9173 // for (init-expr; test-expr; incr-expr) structured-block 9174 // for (range-decl: range-expr) structured-block 9175 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S)) 9176 S = CanonLoop->getLoopStmt(); 9177 auto *For = dyn_cast_or_null<ForStmt>(S); 9178 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S); 9179 // Ranged for is supported only in OpenMP 5.0. 9180 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) { 9181 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for) 9182 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr) 9183 << getOpenMPDirectiveName(DKind) << TotalNestedLoopCount 9184 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount; 9185 if (TotalNestedLoopCount > 1) { 9186 if (CollapseLoopCountExpr && OrderedLoopCountExpr) 9187 SemaRef.Diag(DSA.getConstructLoc(), 9188 diag::note_omp_collapse_ordered_expr) 9189 << 2 << CollapseLoopCountExpr->getSourceRange() 9190 << OrderedLoopCountExpr->getSourceRange(); 9191 else if (CollapseLoopCountExpr) 9192 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(), 9193 diag::note_omp_collapse_ordered_expr) 9194 << 0 << CollapseLoopCountExpr->getSourceRange(); 9195 else if (OrderedLoopCountExpr) 9196 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(), 9197 diag::note_omp_collapse_ordered_expr) 9198 << 1 << OrderedLoopCountExpr->getSourceRange(); 9199 } 9200 return true; 9201 } 9202 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) && 9203 "No loop body."); 9204 // Postpone analysis in dependent contexts for ranged for loops. 9205 if (CXXFor && SemaRef.CurContext->isDependentContext()) 9206 return false; 9207 9208 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA, 9209 For ? For->getForLoc() : CXXFor->getForLoc(), 9210 CollapsedLoopVarDecls); 9211 9212 // Check init. 9213 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt(); 9214 if (ISC.checkAndSetInit(Init)) 9215 return true; 9216 9217 bool HasErrors = false; 9218 9219 // Check loop variable's type. 9220 if (ValueDecl *LCDecl = ISC.getLoopDecl()) { 9221 // OpenMP [2.6, Canonical Loop Form] 9222 // Var is one of the following: 9223 // A variable of signed or unsigned integer type. 9224 // For C++, a variable of a random access iterator type. 9225 // For C, a variable of a pointer type. 9226 QualType VarType = LCDecl->getType().getNonReferenceType(); 9227 if (!VarType->isDependentType() && !VarType->isIntegerType() && 9228 !VarType->isPointerType() && 9229 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) { 9230 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type) 9231 << SemaRef.getLangOpts().CPlusPlus; 9232 HasErrors = true; 9233 } 9234 9235 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in 9236 // a Construct 9237 // The loop iteration variable(s) in the associated for-loop(s) of a for or 9238 // parallel for construct is (are) private. 9239 // The loop iteration variable in the associated for-loop of a simd 9240 // construct with just one associated for-loop is linear with a 9241 // constant-linear-step that is the increment of the associated for-loop. 9242 // Exclude loop var from the list of variables with implicitly defined data 9243 // sharing attributes. 9244 VarsWithImplicitDSA.erase(LCDecl); 9245 9246 assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars"); 9247 9248 // Check test-expr. 9249 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond()); 9250 9251 // Check incr-expr. 9252 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc()); 9253 } 9254 9255 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors) 9256 return HasErrors; 9257 9258 // Build the loop's iteration space representation. 9259 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond( 9260 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures); 9261 ResultIterSpaces[CurrentNestedLoopCount].NumIterations = 9262 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces, 9263 (isOpenMPWorksharingDirective(DKind) || 9264 isOpenMPGenericLoopDirective(DKind) || 9265 isOpenMPTaskLoopDirective(DKind) || 9266 isOpenMPDistributeDirective(DKind) || 9267 isOpenMPLoopTransformationDirective(DKind)), 9268 Captures); 9269 ResultIterSpaces[CurrentNestedLoopCount].CounterVar = 9270 ISC.buildCounterVar(Captures, DSA); 9271 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar = 9272 ISC.buildPrivateCounterVar(); 9273 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit(); 9274 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep(); 9275 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange(); 9276 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange = 9277 ISC.getConditionSrcRange(); 9278 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange = 9279 ISC.getIncrementSrcRange(); 9280 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep(); 9281 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare = 9282 ISC.isStrictTestOp(); 9283 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue, 9284 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) = 9285 ISC.buildMinMaxValues(DSA.getCurScope(), Captures); 9286 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition = 9287 ISC.buildFinalCondition(DSA.getCurScope()); 9288 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB = 9289 ISC.doesInitDependOnLC(); 9290 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB = 9291 ISC.doesCondDependOnLC(); 9292 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx = 9293 ISC.getLoopDependentIdx(); 9294 9295 HasErrors |= 9296 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr || 9297 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr || 9298 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr || 9299 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr || 9300 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr || 9301 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr); 9302 if (!HasErrors && DSA.isOrderedRegion()) { 9303 if (DSA.getOrderedRegionParam().second->getNumForLoops()) { 9304 if (CurrentNestedLoopCount < 9305 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) { 9306 DSA.getOrderedRegionParam().second->setLoopNumIterations( 9307 CurrentNestedLoopCount, 9308 ResultIterSpaces[CurrentNestedLoopCount].NumIterations); 9309 DSA.getOrderedRegionParam().second->setLoopCounter( 9310 CurrentNestedLoopCount, 9311 ResultIterSpaces[CurrentNestedLoopCount].CounterVar); 9312 } 9313 } 9314 for (auto &Pair : DSA.getDoacrossDependClauses()) { 9315 auto *DependC = dyn_cast<OMPDependClause>(Pair.first); 9316 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first); 9317 unsigned NumLoops = 9318 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops(); 9319 if (CurrentNestedLoopCount >= NumLoops) { 9320 // Erroneous case - clause has some problems. 9321 continue; 9322 } 9323 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink && 9324 Pair.second.size() <= CurrentNestedLoopCount) { 9325 // Erroneous case - clause has some problems. 9326 DependC->setLoopData(CurrentNestedLoopCount, nullptr); 9327 continue; 9328 } 9329 OMPDoacrossKind ODK; 9330 if (DoacrossC && ODK.isSink(DoacrossC) && 9331 Pair.second.size() <= CurrentNestedLoopCount) { 9332 // Erroneous case - clause has some problems. 9333 DoacrossC->setLoopData(CurrentNestedLoopCount, nullptr); 9334 continue; 9335 } 9336 Expr *CntValue; 9337 SourceLocation DepLoc = 9338 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc(); 9339 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) || 9340 (DoacrossC && ODK.isSource(DoacrossC))) 9341 CntValue = ISC.buildOrderedLoopData( 9342 DSA.getCurScope(), 9343 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures, 9344 DepLoc); 9345 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) { 9346 Expr *Cnt = SemaRef 9347 .DefaultLvalueConversion( 9348 ResultIterSpaces[CurrentNestedLoopCount].CounterVar) 9349 .get(); 9350 if (!Cnt) 9351 continue; 9352 // build CounterVar - 1 9353 Expr *Inc = 9354 SemaRef.ActOnIntegerConstant(DoacrossC->getColonLoc(), /*Val=*/1) 9355 .get(); 9356 CntValue = ISC.buildOrderedLoopData( 9357 DSA.getCurScope(), 9358 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures, 9359 DepLoc, Inc, clang::OO_Minus); 9360 } else 9361 CntValue = ISC.buildOrderedLoopData( 9362 DSA.getCurScope(), 9363 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures, 9364 DepLoc, Pair.second[CurrentNestedLoopCount].first, 9365 Pair.second[CurrentNestedLoopCount].second); 9366 if (DependC) 9367 DependC->setLoopData(CurrentNestedLoopCount, CntValue); 9368 else 9369 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue); 9370 } 9371 } 9372 9373 return HasErrors; 9374 } 9375 9376 /// Build 'VarRef = Start. 9377 static ExprResult 9378 buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef, 9379 ExprResult Start, bool IsNonRectangularLB, 9380 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) { 9381 // Build 'VarRef = Start. 9382 ExprResult NewStart = IsNonRectangularLB 9383 ? Start.get() 9384 : tryBuildCapture(SemaRef, Start.get(), Captures); 9385 if (!NewStart.isUsable()) 9386 return ExprError(); 9387 if (!SemaRef.Context.hasSameType(NewStart.get()->getType(), 9388 VarRef.get()->getType())) { 9389 NewStart = SemaRef.PerformImplicitConversion( 9390 NewStart.get(), VarRef.get()->getType(), AssignmentAction::Converting, 9391 /*AllowExplicit=*/true); 9392 if (!NewStart.isUsable()) 9393 return ExprError(); 9394 } 9395 9396 ExprResult Init = 9397 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get()); 9398 return Init; 9399 } 9400 9401 /// Build 'VarRef = Start + Iter * Step'. 9402 static ExprResult buildCounterUpdate( 9403 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef, 9404 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract, 9405 bool IsNonRectangularLB, 9406 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) { 9407 // Add parentheses (for debugging purposes only). 9408 Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get()); 9409 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() || 9410 !Step.isUsable()) 9411 return ExprError(); 9412 9413 ExprResult NewStep = Step; 9414 if (Captures) 9415 NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures); 9416 if (NewStep.isInvalid()) 9417 return ExprError(); 9418 ExprResult Update = 9419 SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get()); 9420 if (!Update.isUsable()) 9421 return ExprError(); 9422 9423 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or 9424 // 'VarRef = Start (+|-) Iter * Step'. 9425 if (!Start.isUsable()) 9426 return ExprError(); 9427 ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get()); 9428 if (!NewStart.isUsable()) 9429 return ExprError(); 9430 if (Captures && !IsNonRectangularLB) 9431 NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures); 9432 if (NewStart.isInvalid()) 9433 return ExprError(); 9434 9435 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'. 9436 ExprResult SavedUpdate = Update; 9437 ExprResult UpdateVal; 9438 if (VarRef.get()->getType()->isOverloadableType() || 9439 NewStart.get()->getType()->isOverloadableType() || 9440 Update.get()->getType()->isOverloadableType()) { 9441 Sema::TentativeAnalysisScope Trap(SemaRef); 9442 9443 Update = 9444 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get()); 9445 if (Update.isUsable()) { 9446 UpdateVal = 9447 SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign, 9448 VarRef.get(), SavedUpdate.get()); 9449 if (UpdateVal.isUsable()) { 9450 Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(), 9451 UpdateVal.get()); 9452 } 9453 } 9454 } 9455 9456 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'. 9457 if (!Update.isUsable() || !UpdateVal.isUsable()) { 9458 Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add, 9459 NewStart.get(), SavedUpdate.get()); 9460 if (!Update.isUsable()) 9461 return ExprError(); 9462 9463 if (!SemaRef.Context.hasSameType(Update.get()->getType(), 9464 VarRef.get()->getType())) { 9465 Update = SemaRef.PerformImplicitConversion( 9466 Update.get(), VarRef.get()->getType(), AssignmentAction::Converting, 9467 /*AllowExplicit=*/true); 9468 if (!Update.isUsable()) 9469 return ExprError(); 9470 } 9471 9472 Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get()); 9473 } 9474 return Update; 9475 } 9476 9477 /// Convert integer expression \a E to make it have at least \a Bits 9478 /// bits. 9479 static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) { 9480 if (E == nullptr) 9481 return ExprError(); 9482 ASTContext &C = SemaRef.Context; 9483 QualType OldType = E->getType(); 9484 unsigned HasBits = C.getTypeSize(OldType); 9485 if (HasBits >= Bits) 9486 return ExprResult(E); 9487 // OK to convert to signed, because new type has more bits than old. 9488 QualType NewType = C.getIntTypeForBitwidth(Bits, /*Signed=*/true); 9489 return SemaRef.PerformImplicitConversion( 9490 E, NewType, AssignmentAction::Converting, /*AllowExplicit=*/true); 9491 } 9492 9493 /// Check if the given expression \a E is a constant integer that fits 9494 /// into \a Bits bits. 9495 static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) { 9496 if (E == nullptr) 9497 return false; 9498 if (std::optional<llvm::APSInt> Result = 9499 E->getIntegerConstantExpr(SemaRef.Context)) 9500 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits); 9501 return false; 9502 } 9503 9504 /// Build preinits statement for the given declarations. 9505 static Stmt *buildPreInits(ASTContext &Context, 9506 MutableArrayRef<Decl *> PreInits) { 9507 if (!PreInits.empty()) { 9508 return new (Context) DeclStmt( 9509 DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()), 9510 SourceLocation(), SourceLocation()); 9511 } 9512 return nullptr; 9513 } 9514 9515 /// Append the \p Item or the content of a CompoundStmt to the list \p 9516 /// TargetList. 9517 /// 9518 /// A CompoundStmt is used as container in case multiple statements need to be 9519 /// stored in lieu of using an explicit list. Flattening is necessary because 9520 /// contained DeclStmts need to be visible after the execution of the list. Used 9521 /// for OpenMP pre-init declarations/statements. 9522 static void appendFlattenedStmtList(SmallVectorImpl<Stmt *> &TargetList, 9523 Stmt *Item) { 9524 // nullptr represents an empty list. 9525 if (!Item) 9526 return; 9527 9528 if (auto *CS = dyn_cast<CompoundStmt>(Item)) 9529 llvm::append_range(TargetList, CS->body()); 9530 else 9531 TargetList.push_back(Item); 9532 } 9533 9534 /// Build preinits statement for the given declarations. 9535 static Stmt * 9536 buildPreInits(ASTContext &Context, 9537 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) { 9538 if (!Captures.empty()) { 9539 SmallVector<Decl *, 16> PreInits; 9540 for (const auto &Pair : Captures) 9541 PreInits.push_back(Pair.second->getDecl()); 9542 return buildPreInits(Context, PreInits); 9543 } 9544 return nullptr; 9545 } 9546 9547 /// Build pre-init statement for the given statements. 9548 static Stmt *buildPreInits(ASTContext &Context, ArrayRef<Stmt *> PreInits) { 9549 if (PreInits.empty()) 9550 return nullptr; 9551 9552 SmallVector<Stmt *> Stmts; 9553 for (Stmt *S : PreInits) 9554 appendFlattenedStmtList(Stmts, S); 9555 return CompoundStmt::Create(Context, PreInits, FPOptionsOverride(), {}, {}); 9556 } 9557 9558 /// Build postupdate expression for the given list of postupdates expressions. 9559 static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) { 9560 Expr *PostUpdate = nullptr; 9561 if (!PostUpdates.empty()) { 9562 for (Expr *E : PostUpdates) { 9563 Expr *ConvE = S.BuildCStyleCastExpr( 9564 E->getExprLoc(), 9565 S.Context.getTrivialTypeSourceInfo(S.Context.VoidTy), 9566 E->getExprLoc(), E) 9567 .get(); 9568 PostUpdate = PostUpdate 9569 ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma, 9570 PostUpdate, ConvE) 9571 .get() 9572 : ConvE; 9573 } 9574 } 9575 return PostUpdate; 9576 } 9577 9578 /// Look for variables declared in the body parts of a for-loop nest. Used 9579 /// for verifying loop nest structure before performing a loop collapse 9580 /// operation. 9581 class ForVarDeclFinder : public DynamicRecursiveASTVisitor { 9582 int NestingDepth = 0; 9583 llvm::SmallPtrSetImpl<const Decl *> &VarDecls; 9584 9585 public: 9586 explicit ForVarDeclFinder(llvm::SmallPtrSetImpl<const Decl *> &VD) 9587 : VarDecls(VD) {} 9588 9589 bool VisitForStmt(ForStmt *F) override { 9590 ++NestingDepth; 9591 TraverseStmt(F->getBody()); 9592 --NestingDepth; 9593 return false; 9594 } 9595 9596 bool VisitCXXForRangeStmt(CXXForRangeStmt *RF) override { 9597 ++NestingDepth; 9598 TraverseStmt(RF->getBody()); 9599 --NestingDepth; 9600 return false; 9601 } 9602 9603 bool VisitVarDecl(VarDecl *D) override { 9604 Decl *C = D->getCanonicalDecl(); 9605 if (NestingDepth > 0) 9606 VarDecls.insert(C); 9607 return true; 9608 } 9609 }; 9610 9611 /// Called on a for stmt to check itself and nested loops (if any). 9612 /// \return Returns 0 if one of the collapsed stmts is not canonical for loop, 9613 /// number of collapsed loops otherwise. 9614 static unsigned 9615 checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, 9616 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef, 9617 DSAStackTy &DSA, 9618 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA, 9619 OMPLoopBasedDirective::HelperExprs &Built) { 9620 unsigned NestedLoopCount = 1; 9621 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) && 9622 !isOpenMPLoopTransformationDirective(DKind); 9623 llvm::SmallPtrSet<const Decl *, 4> CollapsedLoopVarDecls; 9624 9625 if (CollapseLoopCountExpr) { 9626 // Found 'collapse' clause - calculate collapse number. 9627 Expr::EvalResult Result; 9628 if (!CollapseLoopCountExpr->isValueDependent() && 9629 CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) { 9630 NestedLoopCount = Result.Val.getInt().getLimitedValue(); 9631 9632 ForVarDeclFinder FVDF{CollapsedLoopVarDecls}; 9633 FVDF.TraverseStmt(AStmt); 9634 } else { 9635 Built.clear(/*Size=*/1); 9636 return 1; 9637 } 9638 } 9639 unsigned OrderedLoopCount = 1; 9640 if (OrderedLoopCountExpr) { 9641 // Found 'ordered' clause - calculate collapse number. 9642 Expr::EvalResult EVResult; 9643 if (!OrderedLoopCountExpr->isValueDependent() && 9644 OrderedLoopCountExpr->EvaluateAsInt(EVResult, 9645 SemaRef.getASTContext())) { 9646 llvm::APSInt Result = EVResult.Val.getInt(); 9647 if (Result.getLimitedValue() < NestedLoopCount) { 9648 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(), 9649 diag::err_omp_wrong_ordered_loop_count) 9650 << OrderedLoopCountExpr->getSourceRange(); 9651 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(), 9652 diag::note_collapse_loop_count) 9653 << CollapseLoopCountExpr->getSourceRange(); 9654 } 9655 OrderedLoopCount = Result.getLimitedValue(); 9656 } else { 9657 Built.clear(/*Size=*/1); 9658 return 1; 9659 } 9660 } 9661 // This is helper routine for loop directives (e.g., 'for', 'simd', 9662 // 'for simd', etc.). 9663 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 9664 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount); 9665 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops); 9666 if (!OMPLoopBasedDirective::doForAllLoops( 9667 AStmt->IgnoreContainers(!isOpenMPLoopTransformationDirective(DKind)), 9668 SupportsNonPerfectlyNested, NumLoops, 9669 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount, 9670 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA, 9671 &IterSpaces, &Captures, 9672 &CollapsedLoopVarDecls](unsigned Cnt, Stmt *CurStmt) { 9673 if (checkOpenMPIterationSpace( 9674 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount, 9675 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr, 9676 VarsWithImplicitDSA, IterSpaces, Captures, 9677 CollapsedLoopVarDecls)) 9678 return true; 9679 if (Cnt > 0 && Cnt >= NestedLoopCount && 9680 IterSpaces[Cnt].CounterVar) { 9681 // Handle initialization of captured loop iterator variables. 9682 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar); 9683 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) { 9684 Captures[DRE] = DRE; 9685 } 9686 } 9687 return false; 9688 }, 9689 [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) { 9690 Stmt *DependentPreInits = Transform->getPreInits(); 9691 if (!DependentPreInits) 9692 return; 9693 9694 // Search for pre-init declared variables that need to be captured 9695 // to be referenceable inside the directive. 9696 SmallVector<Stmt *> Constituents; 9697 appendFlattenedStmtList(Constituents, DependentPreInits); 9698 for (Stmt *S : Constituents) { 9699 if (auto *DC = dyn_cast<DeclStmt>(S)) { 9700 for (Decl *C : DC->decls()) { 9701 auto *D = cast<VarDecl>(C); 9702 DeclRefExpr *Ref = buildDeclRefExpr( 9703 SemaRef, D, D->getType().getNonReferenceType(), 9704 Transform->getBeginLoc()); 9705 Captures[Ref] = Ref; 9706 } 9707 } 9708 } 9709 })) 9710 return 0; 9711 9712 Built.clear(/*size=*/NestedLoopCount); 9713 9714 if (SemaRef.CurContext->isDependentContext()) 9715 return NestedLoopCount; 9716 9717 // An example of what is generated for the following code: 9718 // 9719 // #pragma omp simd collapse(2) ordered(2) 9720 // for (i = 0; i < NI; ++i) 9721 // for (k = 0; k < NK; ++k) 9722 // for (j = J0; j < NJ; j+=2) { 9723 // <loop body> 9724 // } 9725 // 9726 // We generate the code below. 9727 // Note: the loop body may be outlined in CodeGen. 9728 // Note: some counters may be C++ classes, operator- is used to find number of 9729 // iterations and operator+= to calculate counter value. 9730 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32 9731 // or i64 is currently supported). 9732 // 9733 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2)) 9734 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) { 9735 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2); 9736 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2; 9737 // // similar updates for vars in clauses (e.g. 'linear') 9738 // <loop body (using local i and j)> 9739 // } 9740 // i = NI; // assign final values of counters 9741 // j = NJ; 9742 // 9743 9744 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are 9745 // the iteration counts of the collapsed for loops. 9746 // Precondition tests if there is at least one iteration (all conditions are 9747 // true). 9748 auto PreCond = ExprResult(IterSpaces[0].PreCond); 9749 Expr *N0 = IterSpaces[0].NumIterations; 9750 ExprResult LastIteration32 = widenIterationCount( 9751 /*Bits=*/32, 9752 SemaRef 9753 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(), 9754 AssignmentAction::Converting, 9755 /*AllowExplicit=*/true) 9756 .get(), 9757 SemaRef); 9758 ExprResult LastIteration64 = widenIterationCount( 9759 /*Bits=*/64, 9760 SemaRef 9761 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(), 9762 AssignmentAction::Converting, 9763 /*AllowExplicit=*/true) 9764 .get(), 9765 SemaRef); 9766 9767 if (!LastIteration32.isUsable() || !LastIteration64.isUsable()) 9768 return NestedLoopCount; 9769 9770 ASTContext &C = SemaRef.Context; 9771 bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32; 9772 9773 Scope *CurScope = DSA.getCurScope(); 9774 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) { 9775 if (PreCond.isUsable()) { 9776 PreCond = 9777 SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd, 9778 PreCond.get(), IterSpaces[Cnt].PreCond); 9779 } 9780 Expr *N = IterSpaces[Cnt].NumIterations; 9781 SourceLocation Loc = N->getExprLoc(); 9782 AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32; 9783 if (LastIteration32.isUsable()) 9784 LastIteration32 = SemaRef.BuildBinOp( 9785 CurScope, Loc, BO_Mul, LastIteration32.get(), 9786 SemaRef 9787 .PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(), 9788 AssignmentAction::Converting, 9789 /*AllowExplicit=*/true) 9790 .get()); 9791 if (LastIteration64.isUsable()) 9792 LastIteration64 = SemaRef.BuildBinOp( 9793 CurScope, Loc, BO_Mul, LastIteration64.get(), 9794 SemaRef 9795 .PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(), 9796 AssignmentAction::Converting, 9797 /*AllowExplicit=*/true) 9798 .get()); 9799 } 9800 9801 // Choose either the 32-bit or 64-bit version. 9802 ExprResult LastIteration = LastIteration64; 9803 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse || 9804 (LastIteration32.isUsable() && 9805 C.getTypeSize(LastIteration32.get()->getType()) == 32 && 9806 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 || 9807 fitsInto( 9808 /*Bits=*/32, 9809 LastIteration32.get()->getType()->hasSignedIntegerRepresentation(), 9810 LastIteration64.get(), SemaRef)))) 9811 LastIteration = LastIteration32; 9812 QualType VType = LastIteration.get()->getType(); 9813 QualType RealVType = VType; 9814 QualType StrideVType = VType; 9815 if (isOpenMPTaskLoopDirective(DKind)) { 9816 VType = 9817 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 9818 StrideVType = 9819 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 9820 } 9821 9822 if (!LastIteration.isUsable()) 9823 return 0; 9824 9825 // Save the number of iterations. 9826 ExprResult NumIterations = LastIteration; 9827 { 9828 LastIteration = SemaRef.BuildBinOp( 9829 CurScope, LastIteration.get()->getExprLoc(), BO_Sub, 9830 LastIteration.get(), 9831 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get()); 9832 if (!LastIteration.isUsable()) 9833 return 0; 9834 } 9835 9836 // Calculate the last iteration number beforehand instead of doing this on 9837 // each iteration. Do not do this if the number of iterations may be kfold-ed. 9838 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context); 9839 ExprResult CalcLastIteration; 9840 if (!IsConstant) { 9841 ExprResult SaveRef = 9842 tryBuildCapture(SemaRef, LastIteration.get(), Captures); 9843 LastIteration = SaveRef; 9844 9845 // Prepare SaveRef + 1. 9846 NumIterations = SemaRef.BuildBinOp( 9847 CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(), 9848 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get()); 9849 if (!NumIterations.isUsable()) 9850 return 0; 9851 } 9852 9853 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin(); 9854 9855 // Build variables passed into runtime, necessary for worksharing directives. 9856 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB; 9857 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) || 9858 isOpenMPDistributeDirective(DKind) || 9859 isOpenMPGenericLoopDirective(DKind) || 9860 isOpenMPLoopTransformationDirective(DKind)) { 9861 // Lower bound variable, initialized with zero. 9862 VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb"); 9863 LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc); 9864 SemaRef.AddInitializerToDecl(LBDecl, 9865 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(), 9866 /*DirectInit=*/false); 9867 9868 // Upper bound variable, initialized with last iteration number. 9869 VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub"); 9870 UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc); 9871 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(), 9872 /*DirectInit=*/false); 9873 9874 // A 32-bit variable-flag where runtime returns 1 for the last iteration. 9875 // This will be used to implement clause 'lastprivate'. 9876 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true); 9877 VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last"); 9878 IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc); 9879 SemaRef.AddInitializerToDecl(ILDecl, 9880 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(), 9881 /*DirectInit=*/false); 9882 9883 // Stride variable returned by runtime (we initialize it to 1 by default). 9884 VarDecl *STDecl = 9885 buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride"); 9886 ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc); 9887 SemaRef.AddInitializerToDecl(STDecl, 9888 SemaRef.ActOnIntegerConstant(InitLoc, 1).get(), 9889 /*DirectInit=*/false); 9890 9891 // Build expression: UB = min(UB, LastIteration) 9892 // It is necessary for CodeGen of directives with static scheduling. 9893 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT, 9894 UB.get(), LastIteration.get()); 9895 ExprResult CondOp = SemaRef.ActOnConditionalOp( 9896 LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(), 9897 LastIteration.get(), UB.get()); 9898 EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(), 9899 CondOp.get()); 9900 EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue=*/false); 9901 9902 // If we have a combined directive that combines 'distribute', 'for' or 9903 // 'simd' we need to be able to access the bounds of the schedule of the 9904 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained 9905 // by scheduling 'distribute' have to be passed to the schedule of 'for'. 9906 if (isOpenMPLoopBoundSharingDirective(DKind)) { 9907 // Lower bound variable, initialized with zero. 9908 VarDecl *CombLBDecl = 9909 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb"); 9910 CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc); 9911 SemaRef.AddInitializerToDecl( 9912 CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(), 9913 /*DirectInit=*/false); 9914 9915 // Upper bound variable, initialized with last iteration number. 9916 VarDecl *CombUBDecl = 9917 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub"); 9918 CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc); 9919 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(), 9920 /*DirectInit=*/false); 9921 9922 ExprResult CombIsUBGreater = SemaRef.BuildBinOp( 9923 CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get()); 9924 ExprResult CombCondOp = 9925 SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(), 9926 LastIteration.get(), CombUB.get()); 9927 CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(), 9928 CombCondOp.get()); 9929 CombEUB = 9930 SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue=*/false); 9931 9932 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl(); 9933 // We expect to have at least 2 more parameters than the 'parallel' 9934 // directive does - the lower and upper bounds of the previous schedule. 9935 assert(CD->getNumParams() >= 4 && 9936 "Unexpected number of parameters in loop combined directive"); 9937 9938 // Set the proper type for the bounds given what we learned from the 9939 // enclosed loops. 9940 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2); 9941 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3); 9942 9943 // Previous lower and upper bounds are obtained from the region 9944 // parameters. 9945 PrevLB = 9946 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc); 9947 PrevUB = 9948 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc); 9949 } 9950 } 9951 9952 // Build the iteration variable and its initialization before loop. 9953 ExprResult IV; 9954 ExprResult Init, CombInit; 9955 { 9956 VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv"); 9957 IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc); 9958 Expr *RHS = (isOpenMPWorksharingDirective(DKind) || 9959 isOpenMPGenericLoopDirective(DKind) || 9960 isOpenMPTaskLoopDirective(DKind) || 9961 isOpenMPDistributeDirective(DKind) || 9962 isOpenMPLoopTransformationDirective(DKind)) 9963 ? LB.get() 9964 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get(); 9965 Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS); 9966 Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue=*/false); 9967 9968 if (isOpenMPLoopBoundSharingDirective(DKind)) { 9969 Expr *CombRHS = 9970 (isOpenMPWorksharingDirective(DKind) || 9971 isOpenMPGenericLoopDirective(DKind) || 9972 isOpenMPTaskLoopDirective(DKind) || 9973 isOpenMPDistributeDirective(DKind)) 9974 ? CombLB.get() 9975 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get(); 9976 CombInit = 9977 SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS); 9978 CombInit = 9979 SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue=*/false); 9980 } 9981 } 9982 9983 bool UseStrictCompare = 9984 RealVType->hasUnsignedIntegerRepresentation() && 9985 llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) { 9986 return LIS.IsStrictCompare; 9987 }); 9988 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for 9989 // unsigned IV)) for worksharing loops. 9990 SourceLocation CondLoc = AStmt->getBeginLoc(); 9991 Expr *BoundUB = UB.get(); 9992 if (UseStrictCompare) { 9993 BoundUB = 9994 SemaRef 9995 .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB, 9996 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get()) 9997 .get(); 9998 BoundUB = 9999 SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue=*/false).get(); 10000 } 10001 ExprResult Cond = 10002 (isOpenMPWorksharingDirective(DKind) || 10003 isOpenMPGenericLoopDirective(DKind) || 10004 isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind) || 10005 isOpenMPLoopTransformationDirective(DKind)) 10006 ? SemaRef.BuildBinOp(CurScope, CondLoc, 10007 UseStrictCompare ? BO_LT : BO_LE, IV.get(), 10008 BoundUB) 10009 : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(), 10010 NumIterations.get()); 10011 ExprResult CombDistCond; 10012 if (isOpenMPLoopBoundSharingDirective(DKind)) { 10013 CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(), 10014 NumIterations.get()); 10015 } 10016 10017 ExprResult CombCond; 10018 if (isOpenMPLoopBoundSharingDirective(DKind)) { 10019 Expr *BoundCombUB = CombUB.get(); 10020 if (UseStrictCompare) { 10021 BoundCombUB = 10022 SemaRef 10023 .BuildBinOp( 10024 CurScope, CondLoc, BO_Add, BoundCombUB, 10025 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get()) 10026 .get(); 10027 BoundCombUB = 10028 SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue=*/false) 10029 .get(); 10030 } 10031 CombCond = 10032 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, 10033 IV.get(), BoundCombUB); 10034 } 10035 // Loop increment (IV = IV + 1) 10036 SourceLocation IncLoc = AStmt->getBeginLoc(); 10037 ExprResult Inc = 10038 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(), 10039 SemaRef.ActOnIntegerConstant(IncLoc, 1).get()); 10040 if (!Inc.isUsable()) 10041 return 0; 10042 Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get()); 10043 Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue=*/false); 10044 if (!Inc.isUsable()) 10045 return 0; 10046 10047 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST). 10048 // Used for directives with static scheduling. 10049 // In combined construct, add combined version that use CombLB and CombUB 10050 // base variables for the update 10051 ExprResult NextLB, NextUB, CombNextLB, CombNextUB; 10052 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) || 10053 isOpenMPGenericLoopDirective(DKind) || 10054 isOpenMPDistributeDirective(DKind) || 10055 isOpenMPLoopTransformationDirective(DKind)) { 10056 // LB + ST 10057 NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get()); 10058 if (!NextLB.isUsable()) 10059 return 0; 10060 // LB = LB + ST 10061 NextLB = 10062 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get()); 10063 NextLB = 10064 SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue=*/false); 10065 if (!NextLB.isUsable()) 10066 return 0; 10067 // UB + ST 10068 NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get()); 10069 if (!NextUB.isUsable()) 10070 return 0; 10071 // UB = UB + ST 10072 NextUB = 10073 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get()); 10074 NextUB = 10075 SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue=*/false); 10076 if (!NextUB.isUsable()) 10077 return 0; 10078 if (isOpenMPLoopBoundSharingDirective(DKind)) { 10079 CombNextLB = 10080 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get()); 10081 if (!NextLB.isUsable()) 10082 return 0; 10083 // LB = LB + ST 10084 CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(), 10085 CombNextLB.get()); 10086 CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(), 10087 /*DiscardedValue=*/false); 10088 if (!CombNextLB.isUsable()) 10089 return 0; 10090 // UB + ST 10091 CombNextUB = 10092 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get()); 10093 if (!CombNextUB.isUsable()) 10094 return 0; 10095 // UB = UB + ST 10096 CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(), 10097 CombNextUB.get()); 10098 CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(), 10099 /*DiscardedValue=*/false); 10100 if (!CombNextUB.isUsable()) 10101 return 0; 10102 } 10103 } 10104 10105 // Create increment expression for distribute loop when combined in a same 10106 // directive with for as IV = IV + ST; ensure upper bound expression based 10107 // on PrevUB instead of NumIterations - used to implement 'for' when found 10108 // in combination with 'distribute', like in 'distribute parallel for' 10109 SourceLocation DistIncLoc = AStmt->getBeginLoc(); 10110 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond; 10111 if (isOpenMPLoopBoundSharingDirective(DKind)) { 10112 DistCond = SemaRef.BuildBinOp( 10113 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB); 10114 assert(DistCond.isUsable() && "distribute cond expr was not built"); 10115 10116 DistInc = 10117 SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get()); 10118 assert(DistInc.isUsable() && "distribute inc expr was not built"); 10119 DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(), 10120 DistInc.get()); 10121 DistInc = 10122 SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue=*/false); 10123 assert(DistInc.isUsable() && "distribute inc expr was not built"); 10124 10125 // Build expression: UB = min(UB, prevUB) for #for in composite or combined 10126 // construct 10127 ExprResult NewPrevUB = PrevUB; 10128 SourceLocation DistEUBLoc = AStmt->getBeginLoc(); 10129 if (!SemaRef.Context.hasSameType(UB.get()->getType(), 10130 PrevUB.get()->getType())) { 10131 NewPrevUB = SemaRef.BuildCStyleCastExpr( 10132 DistEUBLoc, 10133 SemaRef.Context.getTrivialTypeSourceInfo(UB.get()->getType()), 10134 DistEUBLoc, NewPrevUB.get()); 10135 if (!NewPrevUB.isUsable()) 10136 return 0; 10137 } 10138 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT, 10139 UB.get(), NewPrevUB.get()); 10140 ExprResult CondOp = SemaRef.ActOnConditionalOp( 10141 DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get()); 10142 PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(), 10143 CondOp.get()); 10144 PrevEUB = 10145 SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue=*/false); 10146 10147 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in 10148 // parallel for is in combination with a distribute directive with 10149 // schedule(static, 1) 10150 Expr *BoundPrevUB = PrevUB.get(); 10151 if (UseStrictCompare) { 10152 BoundPrevUB = 10153 SemaRef 10154 .BuildBinOp( 10155 CurScope, CondLoc, BO_Add, BoundPrevUB, 10156 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get()) 10157 .get(); 10158 BoundPrevUB = 10159 SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue=*/false) 10160 .get(); 10161 } 10162 ParForInDistCond = 10163 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, 10164 IV.get(), BoundPrevUB); 10165 } 10166 10167 // Build updates and final values of the loop counters. 10168 bool HasErrors = false; 10169 Built.Counters.resize(NestedLoopCount); 10170 Built.Inits.resize(NestedLoopCount); 10171 Built.Updates.resize(NestedLoopCount); 10172 Built.Finals.resize(NestedLoopCount); 10173 Built.DependentCounters.resize(NestedLoopCount); 10174 Built.DependentInits.resize(NestedLoopCount); 10175 Built.FinalsConditions.resize(NestedLoopCount); 10176 { 10177 // We implement the following algorithm for obtaining the 10178 // original loop iteration variable values based on the 10179 // value of the collapsed loop iteration variable IV. 10180 // 10181 // Let n+1 be the number of collapsed loops in the nest. 10182 // Iteration variables (I0, I1, .... In) 10183 // Iteration counts (N0, N1, ... Nn) 10184 // 10185 // Acc = IV; 10186 // 10187 // To compute Ik for loop k, 0 <= k <= n, generate: 10188 // Prod = N(k+1) * N(k+2) * ... * Nn; 10189 // Ik = Acc / Prod; 10190 // Acc -= Ik * Prod; 10191 // 10192 ExprResult Acc = IV; 10193 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) { 10194 LoopIterationSpace &IS = IterSpaces[Cnt]; 10195 SourceLocation UpdLoc = IS.IncSrcRange.getBegin(); 10196 ExprResult Iter; 10197 10198 // Compute prod 10199 ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(); 10200 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K) 10201 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(), 10202 IterSpaces[K].NumIterations); 10203 10204 // Iter = Acc / Prod 10205 // If there is at least one more inner loop to avoid 10206 // multiplication by 1. 10207 if (Cnt + 1 < NestedLoopCount) 10208 Iter = 10209 SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get()); 10210 else 10211 Iter = Acc; 10212 if (!Iter.isUsable()) { 10213 HasErrors = true; 10214 break; 10215 } 10216 10217 // Update Acc: 10218 // Acc -= Iter * Prod 10219 // Check if there is at least one more inner loop to avoid 10220 // multiplication by 1. 10221 if (Cnt + 1 < NestedLoopCount) 10222 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(), 10223 Prod.get()); 10224 else 10225 Prod = Iter; 10226 Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get()); 10227 10228 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step 10229 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl()); 10230 DeclRefExpr *CounterVar = buildDeclRefExpr( 10231 SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(), 10232 /*RefersToCapture=*/true); 10233 ExprResult Init = 10234 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar, 10235 IS.CounterInit, IS.IsNonRectangularLB, Captures); 10236 if (!Init.isUsable()) { 10237 HasErrors = true; 10238 break; 10239 } 10240 ExprResult Update = buildCounterUpdate( 10241 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter, 10242 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures); 10243 if (!Update.isUsable()) { 10244 HasErrors = true; 10245 break; 10246 } 10247 10248 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step 10249 ExprResult Final = 10250 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar, 10251 IS.CounterInit, IS.NumIterations, IS.CounterStep, 10252 IS.Subtract, IS.IsNonRectangularLB, &Captures); 10253 if (!Final.isUsable()) { 10254 HasErrors = true; 10255 break; 10256 } 10257 10258 if (!Update.isUsable() || !Final.isUsable()) { 10259 HasErrors = true; 10260 break; 10261 } 10262 // Save results 10263 Built.Counters[Cnt] = IS.CounterVar; 10264 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar; 10265 Built.Inits[Cnt] = Init.get(); 10266 Built.Updates[Cnt] = Update.get(); 10267 Built.Finals[Cnt] = Final.get(); 10268 Built.DependentCounters[Cnt] = nullptr; 10269 Built.DependentInits[Cnt] = nullptr; 10270 Built.FinalsConditions[Cnt] = nullptr; 10271 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) { 10272 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1]; 10273 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1]; 10274 Built.FinalsConditions[Cnt] = IS.FinalCondition; 10275 } 10276 } 10277 } 10278 10279 if (HasErrors) 10280 return 0; 10281 10282 // Save results 10283 Built.IterationVarRef = IV.get(); 10284 Built.LastIteration = LastIteration.get(); 10285 Built.NumIterations = NumIterations.get(); 10286 Built.CalcLastIteration = SemaRef 10287 .ActOnFinishFullExpr(CalcLastIteration.get(), 10288 /*DiscardedValue=*/false) 10289 .get(); 10290 Built.PreCond = PreCond.get(); 10291 Built.PreInits = buildPreInits(C, Captures); 10292 Built.Cond = Cond.get(); 10293 Built.Init = Init.get(); 10294 Built.Inc = Inc.get(); 10295 Built.LB = LB.get(); 10296 Built.UB = UB.get(); 10297 Built.IL = IL.get(); 10298 Built.ST = ST.get(); 10299 Built.EUB = EUB.get(); 10300 Built.NLB = NextLB.get(); 10301 Built.NUB = NextUB.get(); 10302 Built.PrevLB = PrevLB.get(); 10303 Built.PrevUB = PrevUB.get(); 10304 Built.DistInc = DistInc.get(); 10305 Built.PrevEUB = PrevEUB.get(); 10306 Built.DistCombinedFields.LB = CombLB.get(); 10307 Built.DistCombinedFields.UB = CombUB.get(); 10308 Built.DistCombinedFields.EUB = CombEUB.get(); 10309 Built.DistCombinedFields.Init = CombInit.get(); 10310 Built.DistCombinedFields.Cond = CombCond.get(); 10311 Built.DistCombinedFields.NLB = CombNextLB.get(); 10312 Built.DistCombinedFields.NUB = CombNextUB.get(); 10313 Built.DistCombinedFields.DistCond = CombDistCond.get(); 10314 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get(); 10315 10316 return NestedLoopCount; 10317 } 10318 10319 static Expr *getCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) { 10320 auto CollapseClauses = 10321 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses); 10322 if (CollapseClauses.begin() != CollapseClauses.end()) 10323 return (*CollapseClauses.begin())->getNumForLoops(); 10324 return nullptr; 10325 } 10326 10327 static Expr *getOrderedNumberExpr(ArrayRef<OMPClause *> Clauses) { 10328 auto OrderedClauses = 10329 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses); 10330 if (OrderedClauses.begin() != OrderedClauses.end()) 10331 return (*OrderedClauses.begin())->getNumForLoops(); 10332 return nullptr; 10333 } 10334 10335 static bool checkSimdlenSafelenSpecified(Sema &S, 10336 const ArrayRef<OMPClause *> Clauses) { 10337 const OMPSafelenClause *Safelen = nullptr; 10338 const OMPSimdlenClause *Simdlen = nullptr; 10339 10340 for (const OMPClause *Clause : Clauses) { 10341 if (Clause->getClauseKind() == OMPC_safelen) 10342 Safelen = cast<OMPSafelenClause>(Clause); 10343 else if (Clause->getClauseKind() == OMPC_simdlen) 10344 Simdlen = cast<OMPSimdlenClause>(Clause); 10345 if (Safelen && Simdlen) 10346 break; 10347 } 10348 10349 if (Simdlen && Safelen) { 10350 const Expr *SimdlenLength = Simdlen->getSimdlen(); 10351 const Expr *SafelenLength = Safelen->getSafelen(); 10352 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() || 10353 SimdlenLength->isInstantiationDependent() || 10354 SimdlenLength->containsUnexpandedParameterPack()) 10355 return false; 10356 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() || 10357 SafelenLength->isInstantiationDependent() || 10358 SafelenLength->containsUnexpandedParameterPack()) 10359 return false; 10360 Expr::EvalResult SimdlenResult, SafelenResult; 10361 SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context); 10362 SafelenLength->EvaluateAsInt(SafelenResult, S.Context); 10363 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt(); 10364 llvm::APSInt SafelenRes = SafelenResult.Val.getInt(); 10365 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions] 10366 // If both simdlen and safelen clauses are specified, the value of the 10367 // simdlen parameter must be less than or equal to the value of the safelen 10368 // parameter. 10369 if (SimdlenRes > SafelenRes) { 10370 S.Diag(SimdlenLength->getExprLoc(), 10371 diag::err_omp_wrong_simdlen_safelen_values) 10372 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange(); 10373 return true; 10374 } 10375 } 10376 return false; 10377 } 10378 10379 StmtResult SemaOpenMP::ActOnOpenMPSimdDirective( 10380 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 10381 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 10382 if (!AStmt) 10383 return StmtError(); 10384 10385 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_simd, AStmt); 10386 10387 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 10388 OMPLoopBasedDirective::HelperExprs B; 10389 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 10390 // define the nested loops number. 10391 unsigned NestedLoopCount = checkOpenMPLoop( 10392 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses), 10393 CS, SemaRef, *DSAStack, VarsWithImplicitDSA, B); 10394 if (NestedLoopCount == 0) 10395 return StmtError(); 10396 10397 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 10398 return StmtError(); 10399 10400 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 10401 return StmtError(); 10402 10403 auto *SimdDirective = OMPSimdDirective::Create( 10404 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 10405 return SimdDirective; 10406 } 10407 10408 StmtResult SemaOpenMP::ActOnOpenMPForDirective( 10409 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 10410 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 10411 if (!AStmt) 10412 return StmtError(); 10413 10414 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 10415 OMPLoopBasedDirective::HelperExprs B; 10416 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 10417 // define the nested loops number. 10418 unsigned NestedLoopCount = checkOpenMPLoop( 10419 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses), 10420 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B); 10421 if (NestedLoopCount == 0) 10422 return StmtError(); 10423 10424 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 10425 return StmtError(); 10426 10427 auto *ForDirective = OMPForDirective::Create( 10428 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B, 10429 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion()); 10430 return ForDirective; 10431 } 10432 10433 StmtResult SemaOpenMP::ActOnOpenMPForSimdDirective( 10434 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 10435 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 10436 if (!AStmt) 10437 return StmtError(); 10438 10439 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_for_simd, AStmt); 10440 10441 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 10442 OMPLoopBasedDirective::HelperExprs B; 10443 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 10444 // define the nested loops number. 10445 unsigned NestedLoopCount = 10446 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses), 10447 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack, 10448 VarsWithImplicitDSA, B); 10449 if (NestedLoopCount == 0) 10450 return StmtError(); 10451 10452 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 10453 return StmtError(); 10454 10455 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 10456 return StmtError(); 10457 10458 return OMPForSimdDirective::Create(getASTContext(), StartLoc, EndLoc, 10459 NestedLoopCount, Clauses, AStmt, B); 10460 } 10461 10462 static bool checkSectionsDirective(Sema &SemaRef, OpenMPDirectiveKind DKind, 10463 Stmt *AStmt, DSAStackTy *Stack) { 10464 if (!AStmt) 10465 return true; 10466 10467 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 10468 auto BaseStmt = AStmt; 10469 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt)) 10470 BaseStmt = CS->getCapturedStmt(); 10471 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) { 10472 auto S = C->children(); 10473 if (S.begin() == S.end()) 10474 return true; 10475 // All associated statements must be '#pragma omp section' except for 10476 // the first one. 10477 for (Stmt *SectionStmt : llvm::drop_begin(S)) { 10478 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) { 10479 if (SectionStmt) 10480 SemaRef.Diag(SectionStmt->getBeginLoc(), 10481 diag::err_omp_sections_substmt_not_section) 10482 << getOpenMPDirectiveName(DKind); 10483 return true; 10484 } 10485 cast<OMPSectionDirective>(SectionStmt) 10486 ->setHasCancel(Stack->isCancelRegion()); 10487 } 10488 } else { 10489 SemaRef.Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt) 10490 << getOpenMPDirectiveName(DKind); 10491 return true; 10492 } 10493 return false; 10494 } 10495 10496 StmtResult 10497 SemaOpenMP::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses, 10498 Stmt *AStmt, SourceLocation StartLoc, 10499 SourceLocation EndLoc) { 10500 if (checkSectionsDirective(SemaRef, OMPD_sections, AStmt, DSAStack)) 10501 return StmtError(); 10502 10503 SemaRef.setFunctionHasBranchProtectedScope(); 10504 10505 return OMPSectionsDirective::Create( 10506 getASTContext(), StartLoc, EndLoc, Clauses, AStmt, 10507 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion()); 10508 } 10509 10510 StmtResult SemaOpenMP::ActOnOpenMPSectionDirective(Stmt *AStmt, 10511 SourceLocation StartLoc, 10512 SourceLocation EndLoc) { 10513 if (!AStmt) 10514 return StmtError(); 10515 10516 SemaRef.setFunctionHasBranchProtectedScope(); 10517 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion()); 10518 10519 return OMPSectionDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt, 10520 DSAStack->isCancelRegion()); 10521 } 10522 10523 static Expr *getDirectCallExpr(Expr *E) { 10524 E = E->IgnoreParenCasts()->IgnoreImplicit(); 10525 if (auto *CE = dyn_cast<CallExpr>(E)) 10526 if (CE->getDirectCallee()) 10527 return E; 10528 return nullptr; 10529 } 10530 10531 StmtResult 10532 SemaOpenMP::ActOnOpenMPDispatchDirective(ArrayRef<OMPClause *> Clauses, 10533 Stmt *AStmt, SourceLocation StartLoc, 10534 SourceLocation EndLoc) { 10535 if (!AStmt) 10536 return StmtError(); 10537 10538 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt(); 10539 10540 // 5.1 OpenMP 10541 // expression-stmt : an expression statement with one of the following forms: 10542 // expression = target-call ( [expression-list] ); 10543 // target-call ( [expression-list] ); 10544 10545 SourceLocation TargetCallLoc; 10546 10547 if (!SemaRef.CurContext->isDependentContext()) { 10548 Expr *TargetCall = nullptr; 10549 10550 auto *E = dyn_cast<Expr>(S); 10551 if (!E) { 10552 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call); 10553 return StmtError(); 10554 } 10555 10556 E = E->IgnoreParenCasts()->IgnoreImplicit(); 10557 10558 if (auto *BO = dyn_cast<BinaryOperator>(E)) { 10559 if (BO->getOpcode() == BO_Assign) 10560 TargetCall = getDirectCallExpr(BO->getRHS()); 10561 } else { 10562 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E)) 10563 if (COCE->getOperator() == OO_Equal) 10564 TargetCall = getDirectCallExpr(COCE->getArg(1)); 10565 if (!TargetCall) 10566 TargetCall = getDirectCallExpr(E); 10567 } 10568 if (!TargetCall) { 10569 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call); 10570 return StmtError(); 10571 } 10572 TargetCallLoc = TargetCall->getExprLoc(); 10573 } 10574 10575 SemaRef.setFunctionHasBranchProtectedScope(); 10576 10577 return OMPDispatchDirective::Create(getASTContext(), StartLoc, EndLoc, 10578 Clauses, AStmt, TargetCallLoc); 10579 } 10580 10581 static bool checkGenericLoopLastprivate(Sema &S, ArrayRef<OMPClause *> Clauses, 10582 OpenMPDirectiveKind K, 10583 DSAStackTy *Stack) { 10584 bool ErrorFound = false; 10585 for (OMPClause *C : Clauses) { 10586 if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) { 10587 for (Expr *RefExpr : LPC->varlist()) { 10588 SourceLocation ELoc; 10589 SourceRange ERange; 10590 Expr *SimpleRefExpr = RefExpr; 10591 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange); 10592 if (ValueDecl *D = Res.first) { 10593 auto &&Info = Stack->isLoopControlVariable(D); 10594 if (!Info.first) { 10595 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration) 10596 << getOpenMPDirectiveName(K); 10597 ErrorFound = true; 10598 } 10599 } 10600 } 10601 } 10602 } 10603 return ErrorFound; 10604 } 10605 10606 StmtResult SemaOpenMP::ActOnOpenMPGenericLoopDirective( 10607 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 10608 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 10609 if (!AStmt) 10610 return StmtError(); 10611 10612 // OpenMP 5.1 [2.11.7, loop construct, Restrictions] 10613 // A list item may not appear in a lastprivate clause unless it is the 10614 // loop iteration variable of a loop that is associated with the construct. 10615 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_loop, DSAStack)) 10616 return StmtError(); 10617 10618 setBranchProtectedScope(SemaRef, OMPD_loop, AStmt); 10619 10620 OMPLoopDirective::HelperExprs B; 10621 // In presence of clause 'collapse', it will define the nested loops number. 10622 unsigned NestedLoopCount = checkOpenMPLoop( 10623 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses), 10624 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B); 10625 if (NestedLoopCount == 0) 10626 return StmtError(); 10627 10628 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 10629 "omp loop exprs were not built"); 10630 10631 return OMPGenericLoopDirective::Create(getASTContext(), StartLoc, EndLoc, 10632 NestedLoopCount, Clauses, AStmt, B); 10633 } 10634 10635 StmtResult SemaOpenMP::ActOnOpenMPTeamsGenericLoopDirective( 10636 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 10637 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 10638 if (!AStmt) 10639 return StmtError(); 10640 10641 // OpenMP 5.1 [2.11.7, loop construct, Restrictions] 10642 // A list item may not appear in a lastprivate clause unless it is the 10643 // loop iteration variable of a loop that is associated with the construct. 10644 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_teams_loop, DSAStack)) 10645 return StmtError(); 10646 10647 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_teams_loop, AStmt); 10648 10649 OMPLoopDirective::HelperExprs B; 10650 // In presence of clause 'collapse', it will define the nested loops number. 10651 unsigned NestedLoopCount = 10652 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses), 10653 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack, 10654 VarsWithImplicitDSA, B); 10655 if (NestedLoopCount == 0) 10656 return StmtError(); 10657 10658 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 10659 "omp loop exprs were not built"); 10660 10661 DSAStack->setParentTeamsRegionLoc(StartLoc); 10662 10663 return OMPTeamsGenericLoopDirective::Create( 10664 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 10665 } 10666 10667 StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsGenericLoopDirective( 10668 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 10669 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 10670 if (!AStmt) 10671 return StmtError(); 10672 10673 // OpenMP 5.1 [2.11.7, loop construct, Restrictions] 10674 // A list item may not appear in a lastprivate clause unless it is the 10675 // loop iteration variable of a loop that is associated with the construct. 10676 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_teams_loop, 10677 DSAStack)) 10678 return StmtError(); 10679 10680 CapturedStmt *CS = 10681 setBranchProtectedScope(SemaRef, OMPD_target_teams_loop, AStmt); 10682 10683 OMPLoopDirective::HelperExprs B; 10684 // In presence of clause 'collapse', it will define the nested loops number. 10685 unsigned NestedLoopCount = 10686 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses), 10687 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack, 10688 VarsWithImplicitDSA, B); 10689 if (NestedLoopCount == 0) 10690 return StmtError(); 10691 10692 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 10693 "omp loop exprs were not built"); 10694 10695 return OMPTargetTeamsGenericLoopDirective::Create( 10696 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B, 10697 teamsLoopCanBeParallelFor(AStmt, SemaRef)); 10698 } 10699 10700 StmtResult SemaOpenMP::ActOnOpenMPParallelGenericLoopDirective( 10701 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 10702 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 10703 if (!AStmt) 10704 return StmtError(); 10705 10706 // OpenMP 5.1 [2.11.7, loop construct, Restrictions] 10707 // A list item may not appear in a lastprivate clause unless it is the 10708 // loop iteration variable of a loop that is associated with the construct. 10709 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_parallel_loop, 10710 DSAStack)) 10711 return StmtError(); 10712 10713 CapturedStmt *CS = 10714 setBranchProtectedScope(SemaRef, OMPD_parallel_loop, AStmt); 10715 10716 OMPLoopDirective::HelperExprs B; 10717 // In presence of clause 'collapse', it will define the nested loops number. 10718 unsigned NestedLoopCount = 10719 checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses), 10720 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack, 10721 VarsWithImplicitDSA, B); 10722 if (NestedLoopCount == 0) 10723 return StmtError(); 10724 10725 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 10726 "omp loop exprs were not built"); 10727 10728 return OMPParallelGenericLoopDirective::Create( 10729 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 10730 } 10731 10732 StmtResult SemaOpenMP::ActOnOpenMPTargetParallelGenericLoopDirective( 10733 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 10734 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 10735 if (!AStmt) 10736 return StmtError(); 10737 10738 // OpenMP 5.1 [2.11.7, loop construct, Restrictions] 10739 // A list item may not appear in a lastprivate clause unless it is the 10740 // loop iteration variable of a loop that is associated with the construct. 10741 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_parallel_loop, 10742 DSAStack)) 10743 return StmtError(); 10744 10745 CapturedStmt *CS = 10746 setBranchProtectedScope(SemaRef, OMPD_target_parallel_loop, AStmt); 10747 10748 OMPLoopDirective::HelperExprs B; 10749 // In presence of clause 'collapse', it will define the nested loops number. 10750 unsigned NestedLoopCount = 10751 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses), 10752 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack, 10753 VarsWithImplicitDSA, B); 10754 if (NestedLoopCount == 0) 10755 return StmtError(); 10756 10757 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 10758 "omp loop exprs were not built"); 10759 10760 return OMPTargetParallelGenericLoopDirective::Create( 10761 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 10762 } 10763 10764 StmtResult SemaOpenMP::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses, 10765 Stmt *AStmt, 10766 SourceLocation StartLoc, 10767 SourceLocation EndLoc) { 10768 if (!AStmt) 10769 return StmtError(); 10770 10771 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 10772 10773 SemaRef.setFunctionHasBranchProtectedScope(); 10774 10775 // OpenMP [2.7.3, single Construct, Restrictions] 10776 // The copyprivate clause must not be used with the nowait clause. 10777 const OMPClause *Nowait = nullptr; 10778 const OMPClause *Copyprivate = nullptr; 10779 for (const OMPClause *Clause : Clauses) { 10780 if (Clause->getClauseKind() == OMPC_nowait) 10781 Nowait = Clause; 10782 else if (Clause->getClauseKind() == OMPC_copyprivate) 10783 Copyprivate = Clause; 10784 if (Copyprivate && Nowait) { 10785 Diag(Copyprivate->getBeginLoc(), 10786 diag::err_omp_single_copyprivate_with_nowait); 10787 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here); 10788 return StmtError(); 10789 } 10790 } 10791 10792 return OMPSingleDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses, 10793 AStmt); 10794 } 10795 10796 StmtResult SemaOpenMP::ActOnOpenMPMasterDirective(Stmt *AStmt, 10797 SourceLocation StartLoc, 10798 SourceLocation EndLoc) { 10799 if (!AStmt) 10800 return StmtError(); 10801 10802 SemaRef.setFunctionHasBranchProtectedScope(); 10803 10804 return OMPMasterDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt); 10805 } 10806 10807 StmtResult SemaOpenMP::ActOnOpenMPMaskedDirective(ArrayRef<OMPClause *> Clauses, 10808 Stmt *AStmt, 10809 SourceLocation StartLoc, 10810 SourceLocation EndLoc) { 10811 if (!AStmt) 10812 return StmtError(); 10813 10814 SemaRef.setFunctionHasBranchProtectedScope(); 10815 10816 return OMPMaskedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses, 10817 AStmt); 10818 } 10819 10820 StmtResult SemaOpenMP::ActOnOpenMPCriticalDirective( 10821 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses, 10822 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { 10823 if (!AStmt) 10824 return StmtError(); 10825 10826 bool ErrorFound = false; 10827 llvm::APSInt Hint; 10828 SourceLocation HintLoc; 10829 bool DependentHint = false; 10830 for (const OMPClause *C : Clauses) { 10831 if (C->getClauseKind() == OMPC_hint) { 10832 if (!DirName.getName()) { 10833 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name); 10834 ErrorFound = true; 10835 } 10836 Expr *E = cast<OMPHintClause>(C)->getHint(); 10837 if (E->isTypeDependent() || E->isValueDependent() || 10838 E->isInstantiationDependent()) { 10839 DependentHint = true; 10840 } else { 10841 Hint = E->EvaluateKnownConstInt(getASTContext()); 10842 HintLoc = C->getBeginLoc(); 10843 } 10844 } 10845 } 10846 if (ErrorFound) 10847 return StmtError(); 10848 const auto Pair = DSAStack->getCriticalWithHint(DirName); 10849 if (Pair.first && DirName.getName() && !DependentHint) { 10850 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) { 10851 Diag(StartLoc, diag::err_omp_critical_with_hint); 10852 if (HintLoc.isValid()) 10853 Diag(HintLoc, diag::note_omp_critical_hint_here) 10854 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false); 10855 else 10856 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0; 10857 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) { 10858 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here) 10859 << 1 10860 << toString(C->getHint()->EvaluateKnownConstInt(getASTContext()), 10861 /*Radix=*/10, /*Signed=*/false); 10862 } else { 10863 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1; 10864 } 10865 } 10866 } 10867 10868 SemaRef.setFunctionHasBranchProtectedScope(); 10869 10870 auto *Dir = OMPCriticalDirective::Create(getASTContext(), DirName, StartLoc, 10871 EndLoc, Clauses, AStmt); 10872 if (!Pair.first && DirName.getName() && !DependentHint) 10873 DSAStack->addCriticalWithHint(Dir, Hint); 10874 return Dir; 10875 } 10876 10877 StmtResult SemaOpenMP::ActOnOpenMPParallelForDirective( 10878 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 10879 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 10880 if (!AStmt) 10881 return StmtError(); 10882 10883 setBranchProtectedScope(SemaRef, OMPD_parallel_for, AStmt); 10884 10885 OMPLoopBasedDirective::HelperExprs B; 10886 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 10887 // define the nested loops number. 10888 unsigned NestedLoopCount = 10889 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses), 10890 getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack, 10891 VarsWithImplicitDSA, B); 10892 if (NestedLoopCount == 0) 10893 return StmtError(); 10894 10895 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 10896 return StmtError(); 10897 10898 return OMPParallelForDirective::Create( 10899 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B, 10900 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion()); 10901 } 10902 10903 StmtResult SemaOpenMP::ActOnOpenMPParallelForSimdDirective( 10904 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 10905 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 10906 if (!AStmt) 10907 return StmtError(); 10908 10909 CapturedStmt *CS = 10910 setBranchProtectedScope(SemaRef, OMPD_parallel_for_simd, AStmt); 10911 10912 OMPLoopBasedDirective::HelperExprs B; 10913 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 10914 // define the nested loops number. 10915 unsigned NestedLoopCount = 10916 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses), 10917 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack, 10918 VarsWithImplicitDSA, B); 10919 if (NestedLoopCount == 0) 10920 return StmtError(); 10921 10922 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 10923 return StmtError(); 10924 10925 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 10926 return StmtError(); 10927 10928 return OMPParallelForSimdDirective::Create( 10929 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 10930 } 10931 10932 StmtResult SemaOpenMP::ActOnOpenMPParallelMasterDirective( 10933 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 10934 SourceLocation EndLoc) { 10935 if (!AStmt) 10936 return StmtError(); 10937 10938 setBranchProtectedScope(SemaRef, OMPD_parallel_master, AStmt); 10939 10940 return OMPParallelMasterDirective::Create( 10941 getASTContext(), StartLoc, EndLoc, Clauses, AStmt, 10942 DSAStack->getTaskgroupReductionRef()); 10943 } 10944 10945 StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedDirective( 10946 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 10947 SourceLocation EndLoc) { 10948 if (!AStmt) 10949 return StmtError(); 10950 10951 setBranchProtectedScope(SemaRef, OMPD_parallel_masked, AStmt); 10952 10953 return OMPParallelMaskedDirective::Create( 10954 getASTContext(), StartLoc, EndLoc, Clauses, AStmt, 10955 DSAStack->getTaskgroupReductionRef()); 10956 } 10957 10958 StmtResult SemaOpenMP::ActOnOpenMPParallelSectionsDirective( 10959 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 10960 SourceLocation EndLoc) { 10961 if (checkSectionsDirective(SemaRef, OMPD_parallel_sections, AStmt, DSAStack)) 10962 return StmtError(); 10963 10964 SemaRef.setFunctionHasBranchProtectedScope(); 10965 10966 return OMPParallelSectionsDirective::Create( 10967 getASTContext(), StartLoc, EndLoc, Clauses, AStmt, 10968 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion()); 10969 } 10970 10971 /// Find and diagnose mutually exclusive clause kinds. 10972 static bool checkMutuallyExclusiveClauses( 10973 Sema &S, ArrayRef<OMPClause *> Clauses, 10974 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) { 10975 const OMPClause *PrevClause = nullptr; 10976 bool ErrorFound = false; 10977 for (const OMPClause *C : Clauses) { 10978 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) { 10979 if (!PrevClause) { 10980 PrevClause = C; 10981 } else if (PrevClause->getClauseKind() != C->getClauseKind()) { 10982 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive) 10983 << getOpenMPClauseName(C->getClauseKind()) 10984 << getOpenMPClauseName(PrevClause->getClauseKind()); 10985 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause) 10986 << getOpenMPClauseName(PrevClause->getClauseKind()); 10987 ErrorFound = true; 10988 } 10989 } 10990 } 10991 return ErrorFound; 10992 } 10993 10994 StmtResult SemaOpenMP::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses, 10995 Stmt *AStmt, 10996 SourceLocation StartLoc, 10997 SourceLocation EndLoc) { 10998 if (!AStmt) 10999 return StmtError(); 11000 11001 // OpenMP 5.0, 2.10.1 task Construct 11002 // If a detach clause appears on the directive, then a mergeable clause cannot 11003 // appear on the same directive. 11004 if (checkMutuallyExclusiveClauses(SemaRef, Clauses, 11005 {OMPC_detach, OMPC_mergeable})) 11006 return StmtError(); 11007 11008 setBranchProtectedScope(SemaRef, OMPD_task, AStmt); 11009 11010 return OMPTaskDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses, 11011 AStmt, DSAStack->isCancelRegion()); 11012 } 11013 11014 StmtResult SemaOpenMP::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc, 11015 SourceLocation EndLoc) { 11016 return OMPTaskyieldDirective::Create(getASTContext(), StartLoc, EndLoc); 11017 } 11018 11019 StmtResult SemaOpenMP::ActOnOpenMPBarrierDirective(SourceLocation StartLoc, 11020 SourceLocation EndLoc) { 11021 return OMPBarrierDirective::Create(getASTContext(), StartLoc, EndLoc); 11022 } 11023 11024 StmtResult SemaOpenMP::ActOnOpenMPErrorDirective(ArrayRef<OMPClause *> Clauses, 11025 SourceLocation StartLoc, 11026 SourceLocation EndLoc, 11027 bool InExContext) { 11028 const OMPAtClause *AtC = 11029 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses); 11030 11031 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) { 11032 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier); 11033 return StmtError(); 11034 } 11035 11036 const OMPSeverityClause *SeverityC = 11037 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses); 11038 const OMPMessageClause *MessageC = 11039 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses); 11040 Expr *ME = MessageC ? MessageC->getMessageString() : nullptr; 11041 11042 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) { 11043 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning) 11044 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded) 11045 << (ME ? cast<StringLiteral>(ME)->getString() : "WARNING"); 11046 else 11047 Diag(StartLoc, diag::err_diagnose_if_succeeded) 11048 << (ME ? cast<StringLiteral>(ME)->getString() : "ERROR"); 11049 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning) 11050 return StmtError(); 11051 } 11052 return OMPErrorDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses); 11053 } 11054 11055 StmtResult 11056 SemaOpenMP::ActOnOpenMPTaskwaitDirective(ArrayRef<OMPClause *> Clauses, 11057 SourceLocation StartLoc, 11058 SourceLocation EndLoc) { 11059 const OMPNowaitClause *NowaitC = 11060 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses); 11061 bool HasDependC = 11062 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses) 11063 .empty(); 11064 if (NowaitC && !HasDependC) { 11065 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend); 11066 return StmtError(); 11067 } 11068 11069 return OMPTaskwaitDirective::Create(getASTContext(), StartLoc, EndLoc, 11070 Clauses); 11071 } 11072 11073 StmtResult 11074 SemaOpenMP::ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause *> Clauses, 11075 Stmt *AStmt, SourceLocation StartLoc, 11076 SourceLocation EndLoc) { 11077 if (!AStmt) 11078 return StmtError(); 11079 11080 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 11081 11082 SemaRef.setFunctionHasBranchProtectedScope(); 11083 11084 return OMPTaskgroupDirective::Create(getASTContext(), StartLoc, EndLoc, 11085 Clauses, AStmt, 11086 DSAStack->getTaskgroupReductionRef()); 11087 } 11088 11089 StmtResult SemaOpenMP::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses, 11090 SourceLocation StartLoc, 11091 SourceLocation EndLoc) { 11092 OMPFlushClause *FC = nullptr; 11093 OMPClause *OrderClause = nullptr; 11094 for (OMPClause *C : Clauses) { 11095 if (C->getClauseKind() == OMPC_flush) 11096 FC = cast<OMPFlushClause>(C); 11097 else 11098 OrderClause = C; 11099 } 11100 OpenMPClauseKind MemOrderKind = OMPC_unknown; 11101 SourceLocation MemOrderLoc; 11102 for (const OMPClause *C : Clauses) { 11103 if (C->getClauseKind() == OMPC_acq_rel || 11104 C->getClauseKind() == OMPC_acquire || 11105 C->getClauseKind() == OMPC_release || 11106 C->getClauseKind() == OMPC_seq_cst /*OpenMP 5.1*/) { 11107 if (MemOrderKind != OMPC_unknown) { 11108 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses) 11109 << getOpenMPDirectiveName(OMPD_flush) << 1 11110 << SourceRange(C->getBeginLoc(), C->getEndLoc()); 11111 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause) 11112 << getOpenMPClauseName(MemOrderKind); 11113 } else { 11114 MemOrderKind = C->getClauseKind(); 11115 MemOrderLoc = C->getBeginLoc(); 11116 } 11117 } 11118 } 11119 if (FC && OrderClause) { 11120 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list) 11121 << getOpenMPClauseName(OrderClause->getClauseKind()); 11122 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here) 11123 << getOpenMPClauseName(OrderClause->getClauseKind()); 11124 return StmtError(); 11125 } 11126 return OMPFlushDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses); 11127 } 11128 11129 StmtResult SemaOpenMP::ActOnOpenMPDepobjDirective(ArrayRef<OMPClause *> Clauses, 11130 SourceLocation StartLoc, 11131 SourceLocation EndLoc) { 11132 if (Clauses.empty()) { 11133 Diag(StartLoc, diag::err_omp_depobj_expected); 11134 return StmtError(); 11135 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) { 11136 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected); 11137 return StmtError(); 11138 } 11139 // Only depobj expression and another single clause is allowed. 11140 if (Clauses.size() > 2) { 11141 Diag(Clauses[2]->getBeginLoc(), 11142 diag::err_omp_depobj_single_clause_expected); 11143 return StmtError(); 11144 } else if (Clauses.size() < 1) { 11145 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected); 11146 return StmtError(); 11147 } 11148 return OMPDepobjDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses); 11149 } 11150 11151 StmtResult SemaOpenMP::ActOnOpenMPScanDirective(ArrayRef<OMPClause *> Clauses, 11152 SourceLocation StartLoc, 11153 SourceLocation EndLoc) { 11154 // Check that exactly one clause is specified. 11155 if (Clauses.size() != 1) { 11156 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(), 11157 diag::err_omp_scan_single_clause_expected); 11158 return StmtError(); 11159 } 11160 // Check that scan directive is used in the scope of the OpenMP loop body. 11161 if (Scope *S = DSAStack->getCurScope()) { 11162 Scope *ParentS = S->getParent(); 11163 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() || 11164 !ParentS->getBreakParent()->isOpenMPLoopScope()) 11165 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive) 11166 << getOpenMPDirectiveName(OMPD_scan) << 5); 11167 } 11168 // Check that only one instance of scan directives is used in the same outer 11169 // region. 11170 if (DSAStack->doesParentHasScanDirective()) { 11171 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan"; 11172 Diag(DSAStack->getParentScanDirectiveLoc(), 11173 diag::note_omp_previous_directive) 11174 << "scan"; 11175 return StmtError(); 11176 } 11177 DSAStack->setParentHasScanDirective(StartLoc); 11178 return OMPScanDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses); 11179 } 11180 11181 StmtResult 11182 SemaOpenMP::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses, 11183 Stmt *AStmt, SourceLocation StartLoc, 11184 SourceLocation EndLoc) { 11185 const OMPClause *DependFound = nullptr; 11186 const OMPClause *DependSourceClause = nullptr; 11187 const OMPClause *DependSinkClause = nullptr; 11188 const OMPClause *DoacrossFound = nullptr; 11189 const OMPClause *DoacrossSourceClause = nullptr; 11190 const OMPClause *DoacrossSinkClause = nullptr; 11191 bool ErrorFound = false; 11192 const OMPThreadsClause *TC = nullptr; 11193 const OMPSIMDClause *SC = nullptr; 11194 for (const OMPClause *C : Clauses) { 11195 auto DOC = dyn_cast<OMPDoacrossClause>(C); 11196 auto DC = dyn_cast<OMPDependClause>(C); 11197 if (DC || DOC) { 11198 DependFound = DC ? C : nullptr; 11199 DoacrossFound = DOC ? C : nullptr; 11200 OMPDoacrossKind ODK; 11201 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) || 11202 (DOC && (ODK.isSource(DOC)))) { 11203 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) { 11204 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause) 11205 << getOpenMPDirectiveName(OMPD_ordered) 11206 << getOpenMPClauseName(DC ? OMPC_depend : OMPC_doacross) << 2; 11207 ErrorFound = true; 11208 } else { 11209 if (DC) 11210 DependSourceClause = C; 11211 else 11212 DoacrossSourceClause = C; 11213 } 11214 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) { 11215 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed) 11216 << (DC ? "depend" : "doacross") << 0; 11217 ErrorFound = true; 11218 } 11219 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) || 11220 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) { 11221 if (DependSourceClause || DoacrossSourceClause) { 11222 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed) 11223 << (DC ? "depend" : "doacross") << 1; 11224 ErrorFound = true; 11225 } 11226 if (DC) 11227 DependSinkClause = C; 11228 else 11229 DoacrossSinkClause = C; 11230 } 11231 } else if (C->getClauseKind() == OMPC_threads) { 11232 TC = cast<OMPThreadsClause>(C); 11233 } else if (C->getClauseKind() == OMPC_simd) { 11234 SC = cast<OMPSIMDClause>(C); 11235 } 11236 } 11237 if (!ErrorFound && !SC && 11238 isOpenMPSimdDirective(DSAStack->getParentDirective())) { 11239 // OpenMP [2.8.1,simd Construct, Restrictions] 11240 // An ordered construct with the simd clause is the only OpenMP construct 11241 // that can appear in the simd region. 11242 Diag(StartLoc, diag::err_omp_prohibited_region_simd) 11243 << (getLangOpts().OpenMP >= 50 ? 1 : 0); 11244 ErrorFound = true; 11245 } else if ((DependFound || DoacrossFound) && (TC || SC)) { 11246 SourceLocation Loc = 11247 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc(); 11248 Diag(Loc, diag::err_omp_depend_clause_thread_simd) 11249 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross) 11250 << getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind()); 11251 ErrorFound = true; 11252 } else if ((DependFound || DoacrossFound) && 11253 !DSAStack->getParentOrderedRegionParam().first) { 11254 SourceLocation Loc = 11255 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc(); 11256 Diag(Loc, diag::err_omp_ordered_directive_without_param) 11257 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross); 11258 ErrorFound = true; 11259 } else if (TC || Clauses.empty()) { 11260 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) { 11261 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc; 11262 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param) 11263 << (TC != nullptr); 11264 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1; 11265 ErrorFound = true; 11266 } 11267 } 11268 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound) 11269 return StmtError(); 11270 11271 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions. 11272 // During execution of an iteration of a worksharing-loop or a loop nest 11273 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread 11274 // must not execute more than one ordered region corresponding to an ordered 11275 // construct without a depend clause. 11276 if (!DependFound && !DoacrossFound) { 11277 if (DSAStack->doesParentHasOrderedDirective()) { 11278 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered"; 11279 Diag(DSAStack->getParentOrderedDirectiveLoc(), 11280 diag::note_omp_previous_directive) 11281 << "ordered"; 11282 return StmtError(); 11283 } 11284 DSAStack->setParentHasOrderedDirective(StartLoc); 11285 } 11286 11287 if (AStmt) { 11288 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 11289 11290 SemaRef.setFunctionHasBranchProtectedScope(); 11291 } 11292 11293 return OMPOrderedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses, 11294 AStmt); 11295 } 11296 11297 namespace { 11298 /// Helper class for checking expression in 'omp atomic [update]' 11299 /// construct. 11300 class OpenMPAtomicUpdateChecker { 11301 /// Error results for atomic update expressions. 11302 enum ExprAnalysisErrorCode { 11303 /// A statement is not an expression statement. 11304 NotAnExpression, 11305 /// Expression is not builtin binary or unary operation. 11306 NotABinaryOrUnaryExpression, 11307 /// Unary operation is not post-/pre- increment/decrement operation. 11308 NotAnUnaryIncDecExpression, 11309 /// An expression is not of scalar type. 11310 NotAScalarType, 11311 /// A binary operation is not an assignment operation. 11312 NotAnAssignmentOp, 11313 /// RHS part of the binary operation is not a binary expression. 11314 NotABinaryExpression, 11315 /// RHS part is not additive/multiplicative/shift/bitwise binary 11316 /// expression. 11317 NotABinaryOperator, 11318 /// RHS binary operation does not have reference to the updated LHS 11319 /// part. 11320 NotAnUpdateExpression, 11321 /// An expression contains semantical error not related to 11322 /// 'omp atomic [update]' 11323 NotAValidExpression, 11324 /// No errors is found. 11325 NoError 11326 }; 11327 /// Reference to Sema. 11328 Sema &SemaRef; 11329 /// A location for note diagnostics (when error is found). 11330 SourceLocation NoteLoc; 11331 /// 'x' lvalue part of the source atomic expression. 11332 Expr *X; 11333 /// 'expr' rvalue part of the source atomic expression. 11334 Expr *E; 11335 /// Helper expression of the form 11336 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or 11337 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'. 11338 Expr *UpdateExpr; 11339 /// Is 'x' a LHS in a RHS part of full update expression. It is 11340 /// important for non-associative operations. 11341 bool IsXLHSInRHSPart; 11342 BinaryOperatorKind Op; 11343 SourceLocation OpLoc; 11344 /// true if the source expression is a postfix unary operation, false 11345 /// if it is a prefix unary operation. 11346 bool IsPostfixUpdate; 11347 11348 public: 11349 OpenMPAtomicUpdateChecker(Sema &SemaRef) 11350 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr), 11351 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {} 11352 /// Check specified statement that it is suitable for 'atomic update' 11353 /// constructs and extract 'x', 'expr' and Operation from the original 11354 /// expression. If DiagId and NoteId == 0, then only check is performed 11355 /// without error notification. 11356 /// \param DiagId Diagnostic which should be emitted if error is found. 11357 /// \param NoteId Diagnostic note for the main error message. 11358 /// \return true if statement is not an update expression, false otherwise. 11359 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0); 11360 /// Return the 'x' lvalue part of the source atomic expression. 11361 Expr *getX() const { return X; } 11362 /// Return the 'expr' rvalue part of the source atomic expression. 11363 Expr *getExpr() const { return E; } 11364 /// Return the update expression used in calculation of the updated 11365 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or 11366 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'. 11367 Expr *getUpdateExpr() const { return UpdateExpr; } 11368 /// Return true if 'x' is LHS in RHS part of full update expression, 11369 /// false otherwise. 11370 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; } 11371 11372 /// true if the source expression is a postfix unary operation, false 11373 /// if it is a prefix unary operation. 11374 bool isPostfixUpdate() const { return IsPostfixUpdate; } 11375 11376 private: 11377 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0, 11378 unsigned NoteId = 0); 11379 }; 11380 11381 bool OpenMPAtomicUpdateChecker::checkBinaryOperation( 11382 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) { 11383 ExprAnalysisErrorCode ErrorFound = NoError; 11384 SourceLocation ErrorLoc, NoteLoc; 11385 SourceRange ErrorRange, NoteRange; 11386 // Allowed constructs are: 11387 // x = x binop expr; 11388 // x = expr binop x; 11389 if (AtomicBinOp->getOpcode() == BO_Assign) { 11390 X = AtomicBinOp->getLHS(); 11391 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>( 11392 AtomicBinOp->getRHS()->IgnoreParenImpCasts())) { 11393 if (AtomicInnerBinOp->isMultiplicativeOp() || 11394 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() || 11395 AtomicInnerBinOp->isBitwiseOp()) { 11396 Op = AtomicInnerBinOp->getOpcode(); 11397 OpLoc = AtomicInnerBinOp->getOperatorLoc(); 11398 Expr *LHS = AtomicInnerBinOp->getLHS(); 11399 Expr *RHS = AtomicInnerBinOp->getRHS(); 11400 llvm::FoldingSetNodeID XId, LHSId, RHSId; 11401 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(), 11402 /*Canonical=*/true); 11403 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(), 11404 /*Canonical=*/true); 11405 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(), 11406 /*Canonical=*/true); 11407 if (XId == LHSId) { 11408 E = RHS; 11409 IsXLHSInRHSPart = true; 11410 } else if (XId == RHSId) { 11411 E = LHS; 11412 IsXLHSInRHSPart = false; 11413 } else { 11414 ErrorLoc = AtomicInnerBinOp->getExprLoc(); 11415 ErrorRange = AtomicInnerBinOp->getSourceRange(); 11416 NoteLoc = X->getExprLoc(); 11417 NoteRange = X->getSourceRange(); 11418 ErrorFound = NotAnUpdateExpression; 11419 } 11420 } else { 11421 ErrorLoc = AtomicInnerBinOp->getExprLoc(); 11422 ErrorRange = AtomicInnerBinOp->getSourceRange(); 11423 NoteLoc = AtomicInnerBinOp->getOperatorLoc(); 11424 NoteRange = SourceRange(NoteLoc, NoteLoc); 11425 ErrorFound = NotABinaryOperator; 11426 } 11427 } else { 11428 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc(); 11429 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange(); 11430 ErrorFound = NotABinaryExpression; 11431 } 11432 } else { 11433 ErrorLoc = AtomicBinOp->getExprLoc(); 11434 ErrorRange = AtomicBinOp->getSourceRange(); 11435 NoteLoc = AtomicBinOp->getOperatorLoc(); 11436 NoteRange = SourceRange(NoteLoc, NoteLoc); 11437 ErrorFound = NotAnAssignmentOp; 11438 } 11439 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) { 11440 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange; 11441 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange; 11442 return true; 11443 } 11444 if (SemaRef.CurContext->isDependentContext()) 11445 E = X = UpdateExpr = nullptr; 11446 return ErrorFound != NoError; 11447 } 11448 11449 bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId, 11450 unsigned NoteId) { 11451 ExprAnalysisErrorCode ErrorFound = NoError; 11452 SourceLocation ErrorLoc, NoteLoc; 11453 SourceRange ErrorRange, NoteRange; 11454 // Allowed constructs are: 11455 // x++; 11456 // x--; 11457 // ++x; 11458 // --x; 11459 // x binop= expr; 11460 // x = x binop expr; 11461 // x = expr binop x; 11462 if (auto *AtomicBody = dyn_cast<Expr>(S)) { 11463 AtomicBody = AtomicBody->IgnoreParenImpCasts(); 11464 if (AtomicBody->getType()->isScalarType() || 11465 AtomicBody->isInstantiationDependent()) { 11466 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>( 11467 AtomicBody->IgnoreParenImpCasts())) { 11468 // Check for Compound Assignment Operation 11469 Op = BinaryOperator::getOpForCompoundAssignment( 11470 AtomicCompAssignOp->getOpcode()); 11471 OpLoc = AtomicCompAssignOp->getOperatorLoc(); 11472 E = AtomicCompAssignOp->getRHS(); 11473 X = AtomicCompAssignOp->getLHS()->IgnoreParens(); 11474 IsXLHSInRHSPart = true; 11475 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>( 11476 AtomicBody->IgnoreParenImpCasts())) { 11477 // Check for Binary Operation 11478 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId)) 11479 return true; 11480 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>( 11481 AtomicBody->IgnoreParenImpCasts())) { 11482 // Check for Unary Operation 11483 if (AtomicUnaryOp->isIncrementDecrementOp()) { 11484 IsPostfixUpdate = AtomicUnaryOp->isPostfix(); 11485 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub; 11486 OpLoc = AtomicUnaryOp->getOperatorLoc(); 11487 X = AtomicUnaryOp->getSubExpr()->IgnoreParens(); 11488 E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get(); 11489 IsXLHSInRHSPart = true; 11490 } else { 11491 ErrorFound = NotAnUnaryIncDecExpression; 11492 ErrorLoc = AtomicUnaryOp->getExprLoc(); 11493 ErrorRange = AtomicUnaryOp->getSourceRange(); 11494 NoteLoc = AtomicUnaryOp->getOperatorLoc(); 11495 NoteRange = SourceRange(NoteLoc, NoteLoc); 11496 } 11497 } else if (!AtomicBody->isInstantiationDependent()) { 11498 ErrorFound = NotABinaryOrUnaryExpression; 11499 NoteLoc = ErrorLoc = AtomicBody->getExprLoc(); 11500 NoteRange = ErrorRange = AtomicBody->getSourceRange(); 11501 } else if (AtomicBody->containsErrors()) { 11502 ErrorFound = NotAValidExpression; 11503 NoteLoc = ErrorLoc = AtomicBody->getExprLoc(); 11504 NoteRange = ErrorRange = AtomicBody->getSourceRange(); 11505 } 11506 } else { 11507 ErrorFound = NotAScalarType; 11508 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc(); 11509 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc); 11510 } 11511 } else { 11512 ErrorFound = NotAnExpression; 11513 NoteLoc = ErrorLoc = S->getBeginLoc(); 11514 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc); 11515 } 11516 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) { 11517 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange; 11518 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange; 11519 return true; 11520 } 11521 if (SemaRef.CurContext->isDependentContext()) 11522 E = X = UpdateExpr = nullptr; 11523 if (ErrorFound == NoError && E && X) { 11524 // Build an update expression of form 'OpaqueValueExpr(x) binop 11525 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop 11526 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression. 11527 auto *OVEX = new (SemaRef.getASTContext()) 11528 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue); 11529 auto *OVEExpr = new (SemaRef.getASTContext()) 11530 OpaqueValueExpr(E->getExprLoc(), E->getType(), VK_PRValue); 11531 ExprResult Update = 11532 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr, 11533 IsXLHSInRHSPart ? OVEExpr : OVEX); 11534 if (Update.isInvalid()) 11535 return true; 11536 Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(), 11537 AssignmentAction::Casting); 11538 if (Update.isInvalid()) 11539 return true; 11540 UpdateExpr = Update.get(); 11541 } 11542 return ErrorFound != NoError; 11543 } 11544 11545 /// Get the node id of the fixed point of an expression \a S. 11546 llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) { 11547 llvm::FoldingSetNodeID Id; 11548 S->IgnoreParenImpCasts()->Profile(Id, Context, true); 11549 return Id; 11550 } 11551 11552 /// Check if two expressions are same. 11553 bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS, 11554 const Expr *RHS) { 11555 return getNodeId(Context, LHS) == getNodeId(Context, RHS); 11556 } 11557 11558 class OpenMPAtomicCompareChecker { 11559 public: 11560 /// All kinds of errors that can occur in `atomic compare` 11561 enum ErrorTy { 11562 /// Empty compound statement. 11563 NoStmt = 0, 11564 /// More than one statement in a compound statement. 11565 MoreThanOneStmt, 11566 /// Not an assignment binary operator. 11567 NotAnAssignment, 11568 /// Not a conditional operator. 11569 NotCondOp, 11570 /// Wrong false expr. According to the spec, 'x' should be at the false 11571 /// expression of a conditional expression. 11572 WrongFalseExpr, 11573 /// The condition of a conditional expression is not a binary operator. 11574 NotABinaryOp, 11575 /// Invalid binary operator (not <, >, or ==). 11576 InvalidBinaryOp, 11577 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x). 11578 InvalidComparison, 11579 /// X is not a lvalue. 11580 XNotLValue, 11581 /// Not a scalar. 11582 NotScalar, 11583 /// Not an integer. 11584 NotInteger, 11585 /// 'else' statement is not expected. 11586 UnexpectedElse, 11587 /// Not an equality operator. 11588 NotEQ, 11589 /// Invalid assignment (not v == x). 11590 InvalidAssignment, 11591 /// Not if statement 11592 NotIfStmt, 11593 /// More than two statements in a compound statement. 11594 MoreThanTwoStmts, 11595 /// Not a compound statement. 11596 NotCompoundStmt, 11597 /// No else statement. 11598 NoElse, 11599 /// Not 'if (r)'. 11600 InvalidCondition, 11601 /// No error. 11602 NoError, 11603 }; 11604 11605 struct ErrorInfoTy { 11606 ErrorTy Error; 11607 SourceLocation ErrorLoc; 11608 SourceRange ErrorRange; 11609 SourceLocation NoteLoc; 11610 SourceRange NoteRange; 11611 }; 11612 11613 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {} 11614 11615 /// Check if statement \a S is valid for <tt>atomic compare</tt>. 11616 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo); 11617 11618 Expr *getX() const { return X; } 11619 Expr *getE() const { return E; } 11620 Expr *getD() const { return D; } 11621 Expr *getCond() const { return C; } 11622 bool isXBinopExpr() const { return IsXBinopExpr; } 11623 11624 protected: 11625 /// Reference to ASTContext 11626 ASTContext &ContextRef; 11627 /// 'x' lvalue part of the source atomic expression. 11628 Expr *X = nullptr; 11629 /// 'expr' or 'e' rvalue part of the source atomic expression. 11630 Expr *E = nullptr; 11631 /// 'd' rvalue part of the source atomic expression. 11632 Expr *D = nullptr; 11633 /// 'cond' part of the source atomic expression. It is in one of the following 11634 /// forms: 11635 /// expr ordop x 11636 /// x ordop expr 11637 /// x == e 11638 /// e == x 11639 Expr *C = nullptr; 11640 /// True if the cond expr is in the form of 'x ordop expr'. 11641 bool IsXBinopExpr = true; 11642 11643 /// Check if it is a valid conditional update statement (cond-update-stmt). 11644 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo); 11645 11646 /// Check if it is a valid conditional expression statement (cond-expr-stmt). 11647 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo); 11648 11649 /// Check if all captured values have right type. 11650 bool checkType(ErrorInfoTy &ErrorInfo) const; 11651 11652 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo, 11653 bool ShouldBeLValue, bool ShouldBeInteger = false) { 11654 if (E->isInstantiationDependent()) 11655 return true; 11656 11657 if (ShouldBeLValue && !E->isLValue()) { 11658 ErrorInfo.Error = ErrorTy::XNotLValue; 11659 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc(); 11660 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange(); 11661 return false; 11662 } 11663 11664 QualType QTy = E->getType(); 11665 if (!QTy->isScalarType()) { 11666 ErrorInfo.Error = ErrorTy::NotScalar; 11667 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc(); 11668 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange(); 11669 return false; 11670 } 11671 if (ShouldBeInteger && !QTy->isIntegerType()) { 11672 ErrorInfo.Error = ErrorTy::NotInteger; 11673 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc(); 11674 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange(); 11675 return false; 11676 } 11677 11678 return true; 11679 } 11680 }; 11681 11682 bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S, 11683 ErrorInfoTy &ErrorInfo) { 11684 auto *Then = S->getThen(); 11685 if (auto *CS = dyn_cast<CompoundStmt>(Then)) { 11686 if (CS->body_empty()) { 11687 ErrorInfo.Error = ErrorTy::NoStmt; 11688 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc(); 11689 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange(); 11690 return false; 11691 } 11692 if (CS->size() > 1) { 11693 ErrorInfo.Error = ErrorTy::MoreThanOneStmt; 11694 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc(); 11695 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange(); 11696 return false; 11697 } 11698 Then = CS->body_front(); 11699 } 11700 11701 auto *BO = dyn_cast<BinaryOperator>(Then); 11702 if (!BO) { 11703 ErrorInfo.Error = ErrorTy::NotAnAssignment; 11704 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc(); 11705 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange(); 11706 return false; 11707 } 11708 if (BO->getOpcode() != BO_Assign) { 11709 ErrorInfo.Error = ErrorTy::NotAnAssignment; 11710 ErrorInfo.ErrorLoc = BO->getExprLoc(); 11711 ErrorInfo.NoteLoc = BO->getOperatorLoc(); 11712 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange(); 11713 return false; 11714 } 11715 11716 X = BO->getLHS(); 11717 11718 auto *Cond = dyn_cast<BinaryOperator>(S->getCond()); 11719 if (!Cond) { 11720 ErrorInfo.Error = ErrorTy::NotABinaryOp; 11721 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc(); 11722 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange(); 11723 return false; 11724 } 11725 11726 switch (Cond->getOpcode()) { 11727 case BO_EQ: { 11728 C = Cond; 11729 D = BO->getRHS(); 11730 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) { 11731 E = Cond->getRHS(); 11732 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) { 11733 E = Cond->getLHS(); 11734 } else { 11735 ErrorInfo.Error = ErrorTy::InvalidComparison; 11736 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc(); 11737 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange(); 11738 return false; 11739 } 11740 break; 11741 } 11742 case BO_LT: 11743 case BO_GT: { 11744 E = BO->getRHS(); 11745 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) && 11746 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) { 11747 C = Cond; 11748 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) && 11749 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) { 11750 C = Cond; 11751 IsXBinopExpr = false; 11752 } else { 11753 ErrorInfo.Error = ErrorTy::InvalidComparison; 11754 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc(); 11755 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange(); 11756 return false; 11757 } 11758 break; 11759 } 11760 default: 11761 ErrorInfo.Error = ErrorTy::InvalidBinaryOp; 11762 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc(); 11763 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange(); 11764 return false; 11765 } 11766 11767 if (S->getElse()) { 11768 ErrorInfo.Error = ErrorTy::UnexpectedElse; 11769 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc(); 11770 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange(); 11771 return false; 11772 } 11773 11774 return true; 11775 } 11776 11777 bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S, 11778 ErrorInfoTy &ErrorInfo) { 11779 auto *BO = dyn_cast<BinaryOperator>(S); 11780 if (!BO) { 11781 ErrorInfo.Error = ErrorTy::NotAnAssignment; 11782 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc(); 11783 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange(); 11784 return false; 11785 } 11786 if (BO->getOpcode() != BO_Assign) { 11787 ErrorInfo.Error = ErrorTy::NotAnAssignment; 11788 ErrorInfo.ErrorLoc = BO->getExprLoc(); 11789 ErrorInfo.NoteLoc = BO->getOperatorLoc(); 11790 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange(); 11791 return false; 11792 } 11793 11794 X = BO->getLHS(); 11795 11796 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts()); 11797 if (!CO) { 11798 ErrorInfo.Error = ErrorTy::NotCondOp; 11799 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc(); 11800 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange(); 11801 return false; 11802 } 11803 11804 if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) { 11805 ErrorInfo.Error = ErrorTy::WrongFalseExpr; 11806 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc(); 11807 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = 11808 CO->getFalseExpr()->getSourceRange(); 11809 return false; 11810 } 11811 11812 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond()); 11813 if (!Cond) { 11814 ErrorInfo.Error = ErrorTy::NotABinaryOp; 11815 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc(); 11816 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = 11817 CO->getCond()->getSourceRange(); 11818 return false; 11819 } 11820 11821 switch (Cond->getOpcode()) { 11822 case BO_EQ: { 11823 C = Cond; 11824 D = CO->getTrueExpr(); 11825 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) { 11826 E = Cond->getRHS(); 11827 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) { 11828 E = Cond->getLHS(); 11829 } else { 11830 ErrorInfo.Error = ErrorTy::InvalidComparison; 11831 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc(); 11832 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange(); 11833 return false; 11834 } 11835 break; 11836 } 11837 case BO_LT: 11838 case BO_GT: { 11839 E = CO->getTrueExpr(); 11840 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) && 11841 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) { 11842 C = Cond; 11843 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) && 11844 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) { 11845 C = Cond; 11846 IsXBinopExpr = false; 11847 } else { 11848 ErrorInfo.Error = ErrorTy::InvalidComparison; 11849 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc(); 11850 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange(); 11851 return false; 11852 } 11853 break; 11854 } 11855 default: 11856 ErrorInfo.Error = ErrorTy::InvalidBinaryOp; 11857 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc(); 11858 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange(); 11859 return false; 11860 } 11861 11862 return true; 11863 } 11864 11865 bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const { 11866 // 'x' and 'e' cannot be nullptr 11867 assert(X && E && "X and E cannot be nullptr"); 11868 11869 if (!CheckValue(X, ErrorInfo, true)) 11870 return false; 11871 11872 if (!CheckValue(E, ErrorInfo, false)) 11873 return false; 11874 11875 if (D && !CheckValue(D, ErrorInfo, false)) 11876 return false; 11877 11878 return true; 11879 } 11880 11881 bool OpenMPAtomicCompareChecker::checkStmt( 11882 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) { 11883 auto *CS = dyn_cast<CompoundStmt>(S); 11884 if (CS) { 11885 if (CS->body_empty()) { 11886 ErrorInfo.Error = ErrorTy::NoStmt; 11887 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc(); 11888 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange(); 11889 return false; 11890 } 11891 11892 if (CS->size() != 1) { 11893 ErrorInfo.Error = ErrorTy::MoreThanOneStmt; 11894 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc(); 11895 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange(); 11896 return false; 11897 } 11898 S = CS->body_front(); 11899 } 11900 11901 auto Res = false; 11902 11903 if (auto *IS = dyn_cast<IfStmt>(S)) { 11904 // Check if the statement is in one of the following forms 11905 // (cond-update-stmt): 11906 // if (expr ordop x) { x = expr; } 11907 // if (x ordop expr) { x = expr; } 11908 // if (x == e) { x = d; } 11909 Res = checkCondUpdateStmt(IS, ErrorInfo); 11910 } else { 11911 // Check if the statement is in one of the following forms (cond-expr-stmt): 11912 // x = expr ordop x ? expr : x; 11913 // x = x ordop expr ? expr : x; 11914 // x = x == e ? d : x; 11915 Res = checkCondExprStmt(S, ErrorInfo); 11916 } 11917 11918 if (!Res) 11919 return false; 11920 11921 return checkType(ErrorInfo); 11922 } 11923 11924 class OpenMPAtomicCompareCaptureChecker final 11925 : public OpenMPAtomicCompareChecker { 11926 public: 11927 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {} 11928 11929 Expr *getV() const { return V; } 11930 Expr *getR() const { return R; } 11931 bool isFailOnly() const { return IsFailOnly; } 11932 bool isPostfixUpdate() const { return IsPostfixUpdate; } 11933 11934 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>. 11935 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo); 11936 11937 private: 11938 bool checkType(ErrorInfoTy &ErrorInfo); 11939 11940 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th 11941 // form of 'conditional-update-capture-atomic' structured block on the v5.2 11942 // spec p.p. 82: 11943 // (1) { v = x; cond-update-stmt } 11944 // (2) { cond-update-stmt v = x; } 11945 // (3) if(x == e) { x = d; } else { v = x; } 11946 // (4) { r = x == e; if(r) { x = d; } } 11947 // (5) { r = x == e; if(r) { x = d; } else { v = x; } } 11948 11949 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3) 11950 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo); 11951 11952 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }', 11953 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5) 11954 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo); 11955 11956 /// 'v' lvalue part of the source atomic expression. 11957 Expr *V = nullptr; 11958 /// 'r' lvalue part of the source atomic expression. 11959 Expr *R = nullptr; 11960 /// If 'v' is only updated when the comparison fails. 11961 bool IsFailOnly = false; 11962 /// If original value of 'x' must be stored in 'v', not an updated one. 11963 bool IsPostfixUpdate = false; 11964 }; 11965 11966 bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) { 11967 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo)) 11968 return false; 11969 11970 if (V && !CheckValue(V, ErrorInfo, true)) 11971 return false; 11972 11973 if (R && !CheckValue(R, ErrorInfo, true, true)) 11974 return false; 11975 11976 return true; 11977 } 11978 11979 bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S, 11980 ErrorInfoTy &ErrorInfo) { 11981 IsFailOnly = true; 11982 11983 auto *Then = S->getThen(); 11984 if (auto *CS = dyn_cast<CompoundStmt>(Then)) { 11985 if (CS->body_empty()) { 11986 ErrorInfo.Error = ErrorTy::NoStmt; 11987 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc(); 11988 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange(); 11989 return false; 11990 } 11991 if (CS->size() > 1) { 11992 ErrorInfo.Error = ErrorTy::MoreThanOneStmt; 11993 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc(); 11994 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange(); 11995 return false; 11996 } 11997 Then = CS->body_front(); 11998 } 11999 12000 auto *BO = dyn_cast<BinaryOperator>(Then); 12001 if (!BO) { 12002 ErrorInfo.Error = ErrorTy::NotAnAssignment; 12003 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc(); 12004 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange(); 12005 return false; 12006 } 12007 if (BO->getOpcode() != BO_Assign) { 12008 ErrorInfo.Error = ErrorTy::NotAnAssignment; 12009 ErrorInfo.ErrorLoc = BO->getExprLoc(); 12010 ErrorInfo.NoteLoc = BO->getOperatorLoc(); 12011 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange(); 12012 return false; 12013 } 12014 12015 X = BO->getLHS(); 12016 D = BO->getRHS(); 12017 12018 auto *Cond = dyn_cast<BinaryOperator>(S->getCond()); 12019 if (!Cond) { 12020 ErrorInfo.Error = ErrorTy::NotABinaryOp; 12021 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc(); 12022 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange(); 12023 return false; 12024 } 12025 if (Cond->getOpcode() != BO_EQ) { 12026 ErrorInfo.Error = ErrorTy::NotEQ; 12027 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc(); 12028 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange(); 12029 return false; 12030 } 12031 12032 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) { 12033 E = Cond->getRHS(); 12034 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) { 12035 E = Cond->getLHS(); 12036 } else { 12037 ErrorInfo.Error = ErrorTy::InvalidComparison; 12038 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc(); 12039 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange(); 12040 return false; 12041 } 12042 12043 C = Cond; 12044 12045 if (!S->getElse()) { 12046 ErrorInfo.Error = ErrorTy::NoElse; 12047 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc(); 12048 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange(); 12049 return false; 12050 } 12051 12052 auto *Else = S->getElse(); 12053 if (auto *CS = dyn_cast<CompoundStmt>(Else)) { 12054 if (CS->body_empty()) { 12055 ErrorInfo.Error = ErrorTy::NoStmt; 12056 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc(); 12057 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange(); 12058 return false; 12059 } 12060 if (CS->size() > 1) { 12061 ErrorInfo.Error = ErrorTy::MoreThanOneStmt; 12062 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc(); 12063 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange(); 12064 return false; 12065 } 12066 Else = CS->body_front(); 12067 } 12068 12069 auto *ElseBO = dyn_cast<BinaryOperator>(Else); 12070 if (!ElseBO) { 12071 ErrorInfo.Error = ErrorTy::NotAnAssignment; 12072 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc(); 12073 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange(); 12074 return false; 12075 } 12076 if (ElseBO->getOpcode() != BO_Assign) { 12077 ErrorInfo.Error = ErrorTy::NotAnAssignment; 12078 ErrorInfo.ErrorLoc = ElseBO->getExprLoc(); 12079 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc(); 12080 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange(); 12081 return false; 12082 } 12083 12084 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) { 12085 ErrorInfo.Error = ErrorTy::InvalidAssignment; 12086 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc(); 12087 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = 12088 ElseBO->getRHS()->getSourceRange(); 12089 return false; 12090 } 12091 12092 V = ElseBO->getLHS(); 12093 12094 return checkType(ErrorInfo); 12095 } 12096 12097 bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S, 12098 ErrorInfoTy &ErrorInfo) { 12099 // We don't check here as they should be already done before call this 12100 // function. 12101 auto *CS = cast<CompoundStmt>(S); 12102 assert(CS->size() == 2 && "CompoundStmt size is not expected"); 12103 auto *S1 = cast<BinaryOperator>(CS->body_front()); 12104 auto *S2 = cast<IfStmt>(CS->body_back()); 12105 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator"); 12106 12107 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) { 12108 ErrorInfo.Error = ErrorTy::InvalidCondition; 12109 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc(); 12110 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange(); 12111 return false; 12112 } 12113 12114 R = S1->getLHS(); 12115 12116 auto *Then = S2->getThen(); 12117 if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) { 12118 if (ThenCS->body_empty()) { 12119 ErrorInfo.Error = ErrorTy::NoStmt; 12120 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc(); 12121 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange(); 12122 return false; 12123 } 12124 if (ThenCS->size() > 1) { 12125 ErrorInfo.Error = ErrorTy::MoreThanOneStmt; 12126 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc(); 12127 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange(); 12128 return false; 12129 } 12130 Then = ThenCS->body_front(); 12131 } 12132 12133 auto *ThenBO = dyn_cast<BinaryOperator>(Then); 12134 if (!ThenBO) { 12135 ErrorInfo.Error = ErrorTy::NotAnAssignment; 12136 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc(); 12137 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange(); 12138 return false; 12139 } 12140 if (ThenBO->getOpcode() != BO_Assign) { 12141 ErrorInfo.Error = ErrorTy::NotAnAssignment; 12142 ErrorInfo.ErrorLoc = ThenBO->getExprLoc(); 12143 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc(); 12144 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange(); 12145 return false; 12146 } 12147 12148 X = ThenBO->getLHS(); 12149 D = ThenBO->getRHS(); 12150 12151 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts()); 12152 if (BO->getOpcode() != BO_EQ) { 12153 ErrorInfo.Error = ErrorTy::NotEQ; 12154 ErrorInfo.ErrorLoc = BO->getExprLoc(); 12155 ErrorInfo.NoteLoc = BO->getOperatorLoc(); 12156 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange(); 12157 return false; 12158 } 12159 12160 C = BO; 12161 12162 if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) { 12163 E = BO->getRHS(); 12164 } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) { 12165 E = BO->getLHS(); 12166 } else { 12167 ErrorInfo.Error = ErrorTy::InvalidComparison; 12168 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc(); 12169 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange(); 12170 return false; 12171 } 12172 12173 if (S2->getElse()) { 12174 IsFailOnly = true; 12175 12176 auto *Else = S2->getElse(); 12177 if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) { 12178 if (ElseCS->body_empty()) { 12179 ErrorInfo.Error = ErrorTy::NoStmt; 12180 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc(); 12181 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange(); 12182 return false; 12183 } 12184 if (ElseCS->size() > 1) { 12185 ErrorInfo.Error = ErrorTy::MoreThanOneStmt; 12186 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc(); 12187 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange(); 12188 return false; 12189 } 12190 Else = ElseCS->body_front(); 12191 } 12192 12193 auto *ElseBO = dyn_cast<BinaryOperator>(Else); 12194 if (!ElseBO) { 12195 ErrorInfo.Error = ErrorTy::NotAnAssignment; 12196 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc(); 12197 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange(); 12198 return false; 12199 } 12200 if (ElseBO->getOpcode() != BO_Assign) { 12201 ErrorInfo.Error = ErrorTy::NotAnAssignment; 12202 ErrorInfo.ErrorLoc = ElseBO->getExprLoc(); 12203 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc(); 12204 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange(); 12205 return false; 12206 } 12207 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) { 12208 ErrorInfo.Error = ErrorTy::InvalidAssignment; 12209 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc(); 12210 ErrorInfo.NoteLoc = X->getExprLoc(); 12211 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange(); 12212 ErrorInfo.NoteRange = X->getSourceRange(); 12213 return false; 12214 } 12215 12216 V = ElseBO->getLHS(); 12217 } 12218 12219 return checkType(ErrorInfo); 12220 } 12221 12222 bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S, 12223 ErrorInfoTy &ErrorInfo) { 12224 // if(x == e) { x = d; } else { v = x; } 12225 if (auto *IS = dyn_cast<IfStmt>(S)) 12226 return checkForm3(IS, ErrorInfo); 12227 12228 auto *CS = dyn_cast<CompoundStmt>(S); 12229 if (!CS) { 12230 ErrorInfo.Error = ErrorTy::NotCompoundStmt; 12231 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc(); 12232 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange(); 12233 return false; 12234 } 12235 if (CS->body_empty()) { 12236 ErrorInfo.Error = ErrorTy::NoStmt; 12237 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc(); 12238 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange(); 12239 return false; 12240 } 12241 12242 // { if(x == e) { x = d; } else { v = x; } } 12243 if (CS->size() == 1) { 12244 auto *IS = dyn_cast<IfStmt>(CS->body_front()); 12245 if (!IS) { 12246 ErrorInfo.Error = ErrorTy::NotIfStmt; 12247 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc(); 12248 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = 12249 CS->body_front()->getSourceRange(); 12250 return false; 12251 } 12252 12253 return checkForm3(IS, ErrorInfo); 12254 } else if (CS->size() == 2) { 12255 auto *S1 = CS->body_front(); 12256 auto *S2 = CS->body_back(); 12257 12258 Stmt *UpdateStmt = nullptr; 12259 Stmt *CondUpdateStmt = nullptr; 12260 Stmt *CondExprStmt = nullptr; 12261 12262 if (auto *BO = dyn_cast<BinaryOperator>(S1)) { 12263 // It could be one of the following cases: 12264 // { v = x; cond-update-stmt } 12265 // { v = x; cond-expr-stmt } 12266 // { cond-expr-stmt; v = x; } 12267 // form 45 12268 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) || 12269 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) { 12270 // check if form 45 12271 if (isa<IfStmt>(S2)) 12272 return checkForm45(CS, ErrorInfo); 12273 // { cond-expr-stmt; v = x; } 12274 CondExprStmt = S1; 12275 UpdateStmt = S2; 12276 } else { 12277 IsPostfixUpdate = true; 12278 UpdateStmt = S1; 12279 if (isa<IfStmt>(S2)) { 12280 // { v = x; cond-update-stmt } 12281 CondUpdateStmt = S2; 12282 } else { 12283 // { v = x; cond-expr-stmt } 12284 CondExprStmt = S2; 12285 } 12286 } 12287 } else { 12288 // { cond-update-stmt v = x; } 12289 UpdateStmt = S2; 12290 CondUpdateStmt = S1; 12291 } 12292 12293 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) { 12294 auto *IS = dyn_cast<IfStmt>(CUS); 12295 if (!IS) { 12296 ErrorInfo.Error = ErrorTy::NotIfStmt; 12297 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc(); 12298 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange(); 12299 return false; 12300 } 12301 12302 return checkCondUpdateStmt(IS, ErrorInfo); 12303 }; 12304 12305 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt. 12306 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) { 12307 auto *BO = dyn_cast<BinaryOperator>(US); 12308 if (!BO) { 12309 ErrorInfo.Error = ErrorTy::NotAnAssignment; 12310 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc(); 12311 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange(); 12312 return false; 12313 } 12314 if (BO->getOpcode() != BO_Assign) { 12315 ErrorInfo.Error = ErrorTy::NotAnAssignment; 12316 ErrorInfo.ErrorLoc = BO->getExprLoc(); 12317 ErrorInfo.NoteLoc = BO->getOperatorLoc(); 12318 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange(); 12319 return false; 12320 } 12321 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) { 12322 ErrorInfo.Error = ErrorTy::InvalidAssignment; 12323 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc(); 12324 ErrorInfo.NoteLoc = this->X->getExprLoc(); 12325 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange(); 12326 ErrorInfo.NoteRange = this->X->getSourceRange(); 12327 return false; 12328 } 12329 12330 this->V = BO->getLHS(); 12331 12332 return true; 12333 }; 12334 12335 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt)) 12336 return false; 12337 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo)) 12338 return false; 12339 if (!CheckUpdateStmt(UpdateStmt)) 12340 return false; 12341 } else { 12342 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts; 12343 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc(); 12344 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange(); 12345 return false; 12346 } 12347 12348 return checkType(ErrorInfo); 12349 } 12350 } // namespace 12351 12352 StmtResult SemaOpenMP::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, 12353 Stmt *AStmt, 12354 SourceLocation StartLoc, 12355 SourceLocation EndLoc) { 12356 ASTContext &Context = getASTContext(); 12357 // Register location of the first atomic directive. 12358 DSAStack->addAtomicDirectiveLoc(StartLoc); 12359 if (!AStmt) 12360 return StmtError(); 12361 12362 // 1.2.2 OpenMP Language Terminology 12363 // Structured block - An executable statement with a single entry at the 12364 // top and a single exit at the bottom. 12365 // The point of exit cannot be a branch out of the structured block. 12366 // longjmp() and throw() must not violate the entry/exit criteria. 12367 OpenMPClauseKind AtomicKind = OMPC_unknown; 12368 SourceLocation AtomicKindLoc; 12369 OpenMPClauseKind MemOrderKind = OMPC_unknown; 12370 SourceLocation MemOrderLoc; 12371 bool MutexClauseEncountered = false; 12372 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds; 12373 for (const OMPClause *C : Clauses) { 12374 switch (C->getClauseKind()) { 12375 case OMPC_read: 12376 case OMPC_write: 12377 case OMPC_update: 12378 MutexClauseEncountered = true; 12379 [[fallthrough]]; 12380 case OMPC_capture: 12381 case OMPC_compare: { 12382 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) { 12383 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses) 12384 << SourceRange(C->getBeginLoc(), C->getEndLoc()); 12385 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause) 12386 << getOpenMPClauseName(AtomicKind); 12387 } else { 12388 AtomicKind = C->getClauseKind(); 12389 AtomicKindLoc = C->getBeginLoc(); 12390 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) { 12391 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses) 12392 << SourceRange(C->getBeginLoc(), C->getEndLoc()); 12393 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause) 12394 << getOpenMPClauseName(AtomicKind); 12395 } 12396 } 12397 break; 12398 } 12399 case OMPC_weak: 12400 case OMPC_fail: { 12401 if (!EncounteredAtomicKinds.contains(OMPC_compare)) { 12402 Diag(C->getBeginLoc(), diag::err_omp_atomic_no_compare) 12403 << getOpenMPClauseName(C->getClauseKind()) 12404 << SourceRange(C->getBeginLoc(), C->getEndLoc()); 12405 return StmtError(); 12406 } 12407 break; 12408 } 12409 case OMPC_seq_cst: 12410 case OMPC_acq_rel: 12411 case OMPC_acquire: 12412 case OMPC_release: 12413 case OMPC_relaxed: { 12414 if (MemOrderKind != OMPC_unknown) { 12415 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses) 12416 << getOpenMPDirectiveName(OMPD_atomic) << 0 12417 << SourceRange(C->getBeginLoc(), C->getEndLoc()); 12418 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause) 12419 << getOpenMPClauseName(MemOrderKind); 12420 } else { 12421 MemOrderKind = C->getClauseKind(); 12422 MemOrderLoc = C->getBeginLoc(); 12423 } 12424 break; 12425 } 12426 // The following clauses are allowed, but we don't need to do anything here. 12427 case OMPC_hint: 12428 break; 12429 default: 12430 llvm_unreachable("unknown clause is encountered"); 12431 } 12432 } 12433 bool IsCompareCapture = false; 12434 if (EncounteredAtomicKinds.contains(OMPC_compare) && 12435 EncounteredAtomicKinds.contains(OMPC_capture)) { 12436 IsCompareCapture = true; 12437 AtomicKind = OMPC_compare; 12438 } 12439 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions 12440 // If atomic-clause is read then memory-order-clause must not be acq_rel or 12441 // release. 12442 // If atomic-clause is write then memory-order-clause must not be acq_rel or 12443 // acquire. 12444 // If atomic-clause is update or not present then memory-order-clause must not 12445 // be acq_rel or acquire. 12446 if ((AtomicKind == OMPC_read && 12447 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) || 12448 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update || 12449 AtomicKind == OMPC_unknown) && 12450 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) { 12451 SourceLocation Loc = AtomicKindLoc; 12452 if (AtomicKind == OMPC_unknown) 12453 Loc = StartLoc; 12454 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause) 12455 << getOpenMPClauseName(AtomicKind) 12456 << (AtomicKind == OMPC_unknown ? 1 : 0) 12457 << getOpenMPClauseName(MemOrderKind); 12458 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause) 12459 << getOpenMPClauseName(MemOrderKind); 12460 } 12461 12462 Stmt *Body = AStmt; 12463 if (auto *EWC = dyn_cast<ExprWithCleanups>(Body)) 12464 Body = EWC->getSubExpr(); 12465 12466 Expr *X = nullptr; 12467 Expr *V = nullptr; 12468 Expr *E = nullptr; 12469 Expr *UE = nullptr; 12470 Expr *D = nullptr; 12471 Expr *CE = nullptr; 12472 Expr *R = nullptr; 12473 bool IsXLHSInRHSPart = false; 12474 bool IsPostfixUpdate = false; 12475 bool IsFailOnly = false; 12476 // OpenMP [2.12.6, atomic Construct] 12477 // In the next expressions: 12478 // * x and v (as applicable) are both l-value expressions with scalar type. 12479 // * During the execution of an atomic region, multiple syntactic 12480 // occurrences of x must designate the same storage location. 12481 // * Neither of v and expr (as applicable) may access the storage location 12482 // designated by x. 12483 // * Neither of x and expr (as applicable) may access the storage location 12484 // designated by v. 12485 // * expr is an expression with scalar type. 12486 // * binop is one of +, *, -, /, &, ^, |, <<, or >>. 12487 // * binop, binop=, ++, and -- are not overloaded operators. 12488 // * The expression x binop expr must be numerically equivalent to x binop 12489 // (expr). This requirement is satisfied if the operators in expr have 12490 // precedence greater than binop, or by using parentheses around expr or 12491 // subexpressions of expr. 12492 // * The expression expr binop x must be numerically equivalent to (expr) 12493 // binop x. This requirement is satisfied if the operators in expr have 12494 // precedence equal to or greater than binop, or by using parentheses around 12495 // expr or subexpressions of expr. 12496 // * For forms that allow multiple occurrences of x, the number of times 12497 // that x is evaluated is unspecified. 12498 if (AtomicKind == OMPC_read) { 12499 enum { 12500 NotAnExpression, 12501 NotAnAssignmentOp, 12502 NotAScalarType, 12503 NotAnLValue, 12504 NoError 12505 } ErrorFound = NoError; 12506 SourceLocation ErrorLoc, NoteLoc; 12507 SourceRange ErrorRange, NoteRange; 12508 // If clause is read: 12509 // v = x; 12510 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) { 12511 const auto *AtomicBinOp = 12512 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts()); 12513 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) { 12514 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts(); 12515 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts(); 12516 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) && 12517 (V->isInstantiationDependent() || V->getType()->isScalarType())) { 12518 if (!X->isLValue() || !V->isLValue()) { 12519 const Expr *NotLValueExpr = X->isLValue() ? V : X; 12520 ErrorFound = NotAnLValue; 12521 ErrorLoc = AtomicBinOp->getExprLoc(); 12522 ErrorRange = AtomicBinOp->getSourceRange(); 12523 NoteLoc = NotLValueExpr->getExprLoc(); 12524 NoteRange = NotLValueExpr->getSourceRange(); 12525 } 12526 } else if (!X->isInstantiationDependent() || 12527 !V->isInstantiationDependent()) { 12528 const Expr *NotScalarExpr = 12529 (X->isInstantiationDependent() || X->getType()->isScalarType()) 12530 ? V 12531 : X; 12532 ErrorFound = NotAScalarType; 12533 ErrorLoc = AtomicBinOp->getExprLoc(); 12534 ErrorRange = AtomicBinOp->getSourceRange(); 12535 NoteLoc = NotScalarExpr->getExprLoc(); 12536 NoteRange = NotScalarExpr->getSourceRange(); 12537 } 12538 } else if (!AtomicBody->isInstantiationDependent()) { 12539 ErrorFound = NotAnAssignmentOp; 12540 ErrorLoc = AtomicBody->getExprLoc(); 12541 ErrorRange = AtomicBody->getSourceRange(); 12542 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc() 12543 : AtomicBody->getExprLoc(); 12544 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange() 12545 : AtomicBody->getSourceRange(); 12546 } 12547 } else { 12548 ErrorFound = NotAnExpression; 12549 NoteLoc = ErrorLoc = Body->getBeginLoc(); 12550 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc); 12551 } 12552 if (ErrorFound != NoError) { 12553 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement) 12554 << ErrorRange; 12555 Diag(NoteLoc, diag::note_omp_atomic_read_write) 12556 << ErrorFound << NoteRange; 12557 return StmtError(); 12558 } 12559 if (SemaRef.CurContext->isDependentContext()) 12560 V = X = nullptr; 12561 } else if (AtomicKind == OMPC_write) { 12562 enum { 12563 NotAnExpression, 12564 NotAnAssignmentOp, 12565 NotAScalarType, 12566 NotAnLValue, 12567 NoError 12568 } ErrorFound = NoError; 12569 SourceLocation ErrorLoc, NoteLoc; 12570 SourceRange ErrorRange, NoteRange; 12571 // If clause is write: 12572 // x = expr; 12573 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) { 12574 const auto *AtomicBinOp = 12575 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts()); 12576 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) { 12577 X = AtomicBinOp->getLHS(); 12578 E = AtomicBinOp->getRHS(); 12579 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) && 12580 (E->isInstantiationDependent() || E->getType()->isScalarType())) { 12581 if (!X->isLValue()) { 12582 ErrorFound = NotAnLValue; 12583 ErrorLoc = AtomicBinOp->getExprLoc(); 12584 ErrorRange = AtomicBinOp->getSourceRange(); 12585 NoteLoc = X->getExprLoc(); 12586 NoteRange = X->getSourceRange(); 12587 } 12588 } else if (!X->isInstantiationDependent() || 12589 !E->isInstantiationDependent()) { 12590 const Expr *NotScalarExpr = 12591 (X->isInstantiationDependent() || X->getType()->isScalarType()) 12592 ? E 12593 : X; 12594 ErrorFound = NotAScalarType; 12595 ErrorLoc = AtomicBinOp->getExprLoc(); 12596 ErrorRange = AtomicBinOp->getSourceRange(); 12597 NoteLoc = NotScalarExpr->getExprLoc(); 12598 NoteRange = NotScalarExpr->getSourceRange(); 12599 } 12600 } else if (!AtomicBody->isInstantiationDependent()) { 12601 ErrorFound = NotAnAssignmentOp; 12602 ErrorLoc = AtomicBody->getExprLoc(); 12603 ErrorRange = AtomicBody->getSourceRange(); 12604 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc() 12605 : AtomicBody->getExprLoc(); 12606 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange() 12607 : AtomicBody->getSourceRange(); 12608 } 12609 } else { 12610 ErrorFound = NotAnExpression; 12611 NoteLoc = ErrorLoc = Body->getBeginLoc(); 12612 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc); 12613 } 12614 if (ErrorFound != NoError) { 12615 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement) 12616 << ErrorRange; 12617 Diag(NoteLoc, diag::note_omp_atomic_read_write) 12618 << ErrorFound << NoteRange; 12619 return StmtError(); 12620 } 12621 if (SemaRef.CurContext->isDependentContext()) 12622 E = X = nullptr; 12623 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) { 12624 // If clause is update: 12625 // x++; 12626 // x--; 12627 // ++x; 12628 // --x; 12629 // x binop= expr; 12630 // x = x binop expr; 12631 // x = expr binop x; 12632 OpenMPAtomicUpdateChecker Checker(SemaRef); 12633 if (Checker.checkStatement( 12634 Body, 12635 (AtomicKind == OMPC_update) 12636 ? diag::err_omp_atomic_update_not_expression_statement 12637 : diag::err_omp_atomic_not_expression_statement, 12638 diag::note_omp_atomic_update)) 12639 return StmtError(); 12640 if (!SemaRef.CurContext->isDependentContext()) { 12641 E = Checker.getExpr(); 12642 X = Checker.getX(); 12643 UE = Checker.getUpdateExpr(); 12644 IsXLHSInRHSPart = Checker.isXLHSInRHSPart(); 12645 } 12646 } else if (AtomicKind == OMPC_capture) { 12647 enum { 12648 NotAnAssignmentOp, 12649 NotACompoundStatement, 12650 NotTwoSubstatements, 12651 NotASpecificExpression, 12652 NoError 12653 } ErrorFound = NoError; 12654 SourceLocation ErrorLoc, NoteLoc; 12655 SourceRange ErrorRange, NoteRange; 12656 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) { 12657 // If clause is a capture: 12658 // v = x++; 12659 // v = x--; 12660 // v = ++x; 12661 // v = --x; 12662 // v = x binop= expr; 12663 // v = x = x binop expr; 12664 // v = x = expr binop x; 12665 const auto *AtomicBinOp = 12666 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts()); 12667 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) { 12668 V = AtomicBinOp->getLHS(); 12669 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts(); 12670 OpenMPAtomicUpdateChecker Checker(SemaRef); 12671 if (Checker.checkStatement( 12672 Body, diag::err_omp_atomic_capture_not_expression_statement, 12673 diag::note_omp_atomic_update)) 12674 return StmtError(); 12675 E = Checker.getExpr(); 12676 X = Checker.getX(); 12677 UE = Checker.getUpdateExpr(); 12678 IsXLHSInRHSPart = Checker.isXLHSInRHSPart(); 12679 IsPostfixUpdate = Checker.isPostfixUpdate(); 12680 } else if (!AtomicBody->isInstantiationDependent()) { 12681 ErrorLoc = AtomicBody->getExprLoc(); 12682 ErrorRange = AtomicBody->getSourceRange(); 12683 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc() 12684 : AtomicBody->getExprLoc(); 12685 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange() 12686 : AtomicBody->getSourceRange(); 12687 ErrorFound = NotAnAssignmentOp; 12688 } 12689 if (ErrorFound != NoError) { 12690 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement) 12691 << ErrorRange; 12692 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange; 12693 return StmtError(); 12694 } 12695 if (SemaRef.CurContext->isDependentContext()) 12696 UE = V = E = X = nullptr; 12697 } else { 12698 // If clause is a capture: 12699 // { v = x; x = expr; } 12700 // { v = x; x++; } 12701 // { v = x; x--; } 12702 // { v = x; ++x; } 12703 // { v = x; --x; } 12704 // { v = x; x binop= expr; } 12705 // { v = x; x = x binop expr; } 12706 // { v = x; x = expr binop x; } 12707 // { x++; v = x; } 12708 // { x--; v = x; } 12709 // { ++x; v = x; } 12710 // { --x; v = x; } 12711 // { x binop= expr; v = x; } 12712 // { x = x binop expr; v = x; } 12713 // { x = expr binop x; v = x; } 12714 if (auto *CS = dyn_cast<CompoundStmt>(Body)) { 12715 // Check that this is { expr1; expr2; } 12716 if (CS->size() == 2) { 12717 Stmt *First = CS->body_front(); 12718 Stmt *Second = CS->body_back(); 12719 if (auto *EWC = dyn_cast<ExprWithCleanups>(First)) 12720 First = EWC->getSubExpr()->IgnoreParenImpCasts(); 12721 if (auto *EWC = dyn_cast<ExprWithCleanups>(Second)) 12722 Second = EWC->getSubExpr()->IgnoreParenImpCasts(); 12723 // Need to find what subexpression is 'v' and what is 'x'. 12724 OpenMPAtomicUpdateChecker Checker(SemaRef); 12725 bool IsUpdateExprFound = !Checker.checkStatement(Second); 12726 BinaryOperator *BinOp = nullptr; 12727 if (IsUpdateExprFound) { 12728 BinOp = dyn_cast<BinaryOperator>(First); 12729 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign; 12730 } 12731 if (IsUpdateExprFound && !SemaRef.CurContext->isDependentContext()) { 12732 // { v = x; x++; } 12733 // { v = x; x--; } 12734 // { v = x; ++x; } 12735 // { v = x; --x; } 12736 // { v = x; x binop= expr; } 12737 // { v = x; x = x binop expr; } 12738 // { v = x; x = expr binop x; } 12739 // Check that the first expression has form v = x. 12740 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts(); 12741 llvm::FoldingSetNodeID XId, PossibleXId; 12742 Checker.getX()->Profile(XId, Context, /*Canonical=*/true); 12743 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true); 12744 IsUpdateExprFound = XId == PossibleXId; 12745 if (IsUpdateExprFound) { 12746 V = BinOp->getLHS(); 12747 X = Checker.getX(); 12748 E = Checker.getExpr(); 12749 UE = Checker.getUpdateExpr(); 12750 IsXLHSInRHSPart = Checker.isXLHSInRHSPart(); 12751 IsPostfixUpdate = true; 12752 } 12753 } 12754 if (!IsUpdateExprFound) { 12755 IsUpdateExprFound = !Checker.checkStatement(First); 12756 BinOp = nullptr; 12757 if (IsUpdateExprFound) { 12758 BinOp = dyn_cast<BinaryOperator>(Second); 12759 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign; 12760 } 12761 if (IsUpdateExprFound && 12762 !SemaRef.CurContext->isDependentContext()) { 12763 // { x++; v = x; } 12764 // { x--; v = x; } 12765 // { ++x; v = x; } 12766 // { --x; v = x; } 12767 // { x binop= expr; v = x; } 12768 // { x = x binop expr; v = x; } 12769 // { x = expr binop x; v = x; } 12770 // Check that the second expression has form v = x. 12771 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts(); 12772 llvm::FoldingSetNodeID XId, PossibleXId; 12773 Checker.getX()->Profile(XId, Context, /*Canonical=*/true); 12774 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true); 12775 IsUpdateExprFound = XId == PossibleXId; 12776 if (IsUpdateExprFound) { 12777 V = BinOp->getLHS(); 12778 X = Checker.getX(); 12779 E = Checker.getExpr(); 12780 UE = Checker.getUpdateExpr(); 12781 IsXLHSInRHSPart = Checker.isXLHSInRHSPart(); 12782 IsPostfixUpdate = false; 12783 } 12784 } 12785 } 12786 if (!IsUpdateExprFound) { 12787 // { v = x; x = expr; } 12788 auto *FirstExpr = dyn_cast<Expr>(First); 12789 auto *SecondExpr = dyn_cast<Expr>(Second); 12790 if (!FirstExpr || !SecondExpr || 12791 !(FirstExpr->isInstantiationDependent() || 12792 SecondExpr->isInstantiationDependent())) { 12793 auto *FirstBinOp = dyn_cast<BinaryOperator>(First); 12794 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) { 12795 ErrorFound = NotAnAssignmentOp; 12796 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc() 12797 : First->getBeginLoc(); 12798 NoteRange = ErrorRange = FirstBinOp 12799 ? FirstBinOp->getSourceRange() 12800 : SourceRange(ErrorLoc, ErrorLoc); 12801 } else { 12802 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second); 12803 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) { 12804 ErrorFound = NotAnAssignmentOp; 12805 NoteLoc = ErrorLoc = SecondBinOp 12806 ? SecondBinOp->getOperatorLoc() 12807 : Second->getBeginLoc(); 12808 NoteRange = ErrorRange = 12809 SecondBinOp ? SecondBinOp->getSourceRange() 12810 : SourceRange(ErrorLoc, ErrorLoc); 12811 } else { 12812 Expr *PossibleXRHSInFirst = 12813 FirstBinOp->getRHS()->IgnoreParenImpCasts(); 12814 Expr *PossibleXLHSInSecond = 12815 SecondBinOp->getLHS()->IgnoreParenImpCasts(); 12816 llvm::FoldingSetNodeID X1Id, X2Id; 12817 PossibleXRHSInFirst->Profile(X1Id, Context, 12818 /*Canonical=*/true); 12819 PossibleXLHSInSecond->Profile(X2Id, Context, 12820 /*Canonical=*/true); 12821 IsUpdateExprFound = X1Id == X2Id; 12822 if (IsUpdateExprFound) { 12823 V = FirstBinOp->getLHS(); 12824 X = SecondBinOp->getLHS(); 12825 E = SecondBinOp->getRHS(); 12826 UE = nullptr; 12827 IsXLHSInRHSPart = false; 12828 IsPostfixUpdate = true; 12829 } else { 12830 ErrorFound = NotASpecificExpression; 12831 ErrorLoc = FirstBinOp->getExprLoc(); 12832 ErrorRange = FirstBinOp->getSourceRange(); 12833 NoteLoc = SecondBinOp->getLHS()->getExprLoc(); 12834 NoteRange = SecondBinOp->getRHS()->getSourceRange(); 12835 } 12836 } 12837 } 12838 } 12839 } 12840 } else { 12841 NoteLoc = ErrorLoc = Body->getBeginLoc(); 12842 NoteRange = ErrorRange = 12843 SourceRange(Body->getBeginLoc(), Body->getBeginLoc()); 12844 ErrorFound = NotTwoSubstatements; 12845 } 12846 } else { 12847 NoteLoc = ErrorLoc = Body->getBeginLoc(); 12848 NoteRange = ErrorRange = 12849 SourceRange(Body->getBeginLoc(), Body->getBeginLoc()); 12850 ErrorFound = NotACompoundStatement; 12851 } 12852 } 12853 if (ErrorFound != NoError) { 12854 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement) 12855 << ErrorRange; 12856 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange; 12857 return StmtError(); 12858 } 12859 if (SemaRef.CurContext->isDependentContext()) 12860 UE = V = E = X = nullptr; 12861 } else if (AtomicKind == OMPC_compare) { 12862 if (IsCompareCapture) { 12863 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo; 12864 OpenMPAtomicCompareCaptureChecker Checker(SemaRef); 12865 if (!Checker.checkStmt(Body, ErrorInfo)) { 12866 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture) 12867 << ErrorInfo.ErrorRange; 12868 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare) 12869 << ErrorInfo.Error << ErrorInfo.NoteRange; 12870 return StmtError(); 12871 } 12872 X = Checker.getX(); 12873 E = Checker.getE(); 12874 D = Checker.getD(); 12875 CE = Checker.getCond(); 12876 V = Checker.getV(); 12877 R = Checker.getR(); 12878 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'. 12879 IsXLHSInRHSPart = Checker.isXBinopExpr(); 12880 IsFailOnly = Checker.isFailOnly(); 12881 IsPostfixUpdate = Checker.isPostfixUpdate(); 12882 } else { 12883 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo; 12884 OpenMPAtomicCompareChecker Checker(SemaRef); 12885 if (!Checker.checkStmt(Body, ErrorInfo)) { 12886 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare) 12887 << ErrorInfo.ErrorRange; 12888 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare) 12889 << ErrorInfo.Error << ErrorInfo.NoteRange; 12890 return StmtError(); 12891 } 12892 X = Checker.getX(); 12893 E = Checker.getE(); 12894 D = Checker.getD(); 12895 CE = Checker.getCond(); 12896 // The weak clause may only appear if the resulting atomic operation is 12897 // an atomic conditional update for which the comparison tests for 12898 // equality. It was not possible to do this check in 12899 // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak 12900 // could not be performed (Clauses are not available). 12901 auto *It = find_if(Clauses, [](OMPClause *C) { 12902 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak; 12903 }); 12904 if (It != Clauses.end()) { 12905 auto *Cond = dyn_cast<BinaryOperator>(CE); 12906 if (Cond->getOpcode() != BO_EQ) { 12907 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment; 12908 ErrorInfo.ErrorLoc = Cond->getExprLoc(); 12909 ErrorInfo.NoteLoc = Cond->getOperatorLoc(); 12910 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange(); 12911 12912 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality) 12913 << ErrorInfo.ErrorRange; 12914 return StmtError(); 12915 } 12916 } 12917 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'. 12918 IsXLHSInRHSPart = Checker.isXBinopExpr(); 12919 } 12920 } 12921 12922 SemaRef.setFunctionHasBranchProtectedScope(); 12923 12924 return OMPAtomicDirective::Create( 12925 Context, StartLoc, EndLoc, Clauses, AStmt, 12926 {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly}); 12927 } 12928 12929 StmtResult SemaOpenMP::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses, 12930 Stmt *AStmt, 12931 SourceLocation StartLoc, 12932 SourceLocation EndLoc) { 12933 if (!AStmt) 12934 return StmtError(); 12935 12936 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target, AStmt); 12937 12938 // OpenMP [2.16, Nesting of Regions] 12939 // If specified, a teams construct must be contained within a target 12940 // construct. That target construct must contain no statements or directives 12941 // outside of the teams construct. 12942 if (DSAStack->hasInnerTeamsRegion()) { 12943 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true); 12944 bool OMPTeamsFound = true; 12945 if (const auto *CS = dyn_cast<CompoundStmt>(S)) { 12946 auto I = CS->body_begin(); 12947 while (I != CS->body_end()) { 12948 const auto *OED = dyn_cast<OMPExecutableDirective>(*I); 12949 bool IsTeams = OED && isOpenMPTeamsDirective(OED->getDirectiveKind()); 12950 if (!IsTeams || I != CS->body_begin()) { 12951 OMPTeamsFound = false; 12952 if (IsTeams && I != CS->body_begin()) { 12953 // This is the two teams case. Since the InnerTeamsRegionLoc will 12954 // point to this second one reset the iterator to the other teams. 12955 --I; 12956 } 12957 break; 12958 } 12959 ++I; 12960 } 12961 assert(I != CS->body_end() && "Not found statement"); 12962 S = *I; 12963 } else { 12964 const auto *OED = dyn_cast<OMPExecutableDirective>(S); 12965 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind()); 12966 } 12967 if (!OMPTeamsFound) { 12968 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams); 12969 Diag(DSAStack->getInnerTeamsRegionLoc(), 12970 diag::note_omp_nested_teams_construct_here); 12971 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here) 12972 << isa<OMPExecutableDirective>(S); 12973 return StmtError(); 12974 } 12975 } 12976 12977 return OMPTargetDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses, 12978 AStmt); 12979 } 12980 12981 StmtResult SemaOpenMP::ActOnOpenMPTargetParallelDirective( 12982 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 12983 SourceLocation EndLoc) { 12984 if (!AStmt) 12985 return StmtError(); 12986 12987 setBranchProtectedScope(SemaRef, OMPD_target_parallel, AStmt); 12988 12989 return OMPTargetParallelDirective::Create( 12990 getASTContext(), StartLoc, EndLoc, Clauses, AStmt, 12991 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion()); 12992 } 12993 12994 StmtResult SemaOpenMP::ActOnOpenMPTargetParallelForDirective( 12995 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 12996 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 12997 if (!AStmt) 12998 return StmtError(); 12999 13000 CapturedStmt *CS = 13001 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for, AStmt); 13002 13003 OMPLoopBasedDirective::HelperExprs B; 13004 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 13005 // define the nested loops number. 13006 unsigned NestedLoopCount = 13007 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses), 13008 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack, 13009 VarsWithImplicitDSA, B); 13010 if (NestedLoopCount == 0) 13011 return StmtError(); 13012 13013 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 13014 return StmtError(); 13015 13016 return OMPTargetParallelForDirective::Create( 13017 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B, 13018 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion()); 13019 } 13020 13021 /// Check for existence of a map clause in the list of clauses. 13022 static bool hasClauses(ArrayRef<OMPClause *> Clauses, 13023 const OpenMPClauseKind K) { 13024 return llvm::any_of( 13025 Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; }); 13026 } 13027 13028 template <typename... Params> 13029 static bool hasClauses(ArrayRef<OMPClause *> Clauses, const OpenMPClauseKind K, 13030 const Params... ClauseTypes) { 13031 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...); 13032 } 13033 13034 /// Check if the variables in the mapping clause are externally visible. 13035 static bool isClauseMappable(ArrayRef<OMPClause *> Clauses) { 13036 for (const OMPClause *C : Clauses) { 13037 if (auto *TC = dyn_cast<OMPToClause>(C)) 13038 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) { 13039 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() || 13040 (VD->isExternallyVisible() && 13041 VD->getVisibility() != HiddenVisibility); 13042 }); 13043 else if (auto *FC = dyn_cast<OMPFromClause>(C)) 13044 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) { 13045 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() || 13046 (VD->isExternallyVisible() && 13047 VD->getVisibility() != HiddenVisibility); 13048 }); 13049 } 13050 13051 return true; 13052 } 13053 13054 StmtResult 13055 SemaOpenMP::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses, 13056 Stmt *AStmt, SourceLocation StartLoc, 13057 SourceLocation EndLoc) { 13058 if (!AStmt) 13059 return StmtError(); 13060 13061 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 13062 13063 // OpenMP [2.12.2, target data Construct, Restrictions] 13064 // At least one map, use_device_addr or use_device_ptr clause must appear on 13065 // the directive. 13066 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) && 13067 (getLangOpts().OpenMP < 50 || 13068 !hasClauses(Clauses, OMPC_use_device_addr))) { 13069 StringRef Expected; 13070 if (getLangOpts().OpenMP < 50) 13071 Expected = "'map' or 'use_device_ptr'"; 13072 else 13073 Expected = "'map', 'use_device_ptr', or 'use_device_addr'"; 13074 Diag(StartLoc, diag::err_omp_no_clause_for_directive) 13075 << Expected << getOpenMPDirectiveName(OMPD_target_data); 13076 return StmtError(); 13077 } 13078 13079 SemaRef.setFunctionHasBranchProtectedScope(); 13080 13081 return OMPTargetDataDirective::Create(getASTContext(), StartLoc, EndLoc, 13082 Clauses, AStmt); 13083 } 13084 13085 StmtResult SemaOpenMP::ActOnOpenMPTargetEnterDataDirective( 13086 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc, 13087 SourceLocation EndLoc, Stmt *AStmt) { 13088 if (!AStmt) 13089 return StmtError(); 13090 13091 setBranchProtectedScope(SemaRef, OMPD_target_enter_data, AStmt); 13092 13093 // OpenMP [2.10.2, Restrictions, p. 99] 13094 // At least one map clause must appear on the directive. 13095 if (!hasClauses(Clauses, OMPC_map)) { 13096 Diag(StartLoc, diag::err_omp_no_clause_for_directive) 13097 << "'map'" << getOpenMPDirectiveName(OMPD_target_enter_data); 13098 return StmtError(); 13099 } 13100 13101 return OMPTargetEnterDataDirective::Create(getASTContext(), StartLoc, EndLoc, 13102 Clauses, AStmt); 13103 } 13104 13105 StmtResult SemaOpenMP::ActOnOpenMPTargetExitDataDirective( 13106 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc, 13107 SourceLocation EndLoc, Stmt *AStmt) { 13108 if (!AStmt) 13109 return StmtError(); 13110 13111 setBranchProtectedScope(SemaRef, OMPD_target_exit_data, AStmt); 13112 13113 // OpenMP [2.10.3, Restrictions, p. 102] 13114 // At least one map clause must appear on the directive. 13115 if (!hasClauses(Clauses, OMPC_map)) { 13116 Diag(StartLoc, diag::err_omp_no_clause_for_directive) 13117 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data); 13118 return StmtError(); 13119 } 13120 13121 return OMPTargetExitDataDirective::Create(getASTContext(), StartLoc, EndLoc, 13122 Clauses, AStmt); 13123 } 13124 13125 StmtResult SemaOpenMP::ActOnOpenMPTargetUpdateDirective( 13126 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc, 13127 SourceLocation EndLoc, Stmt *AStmt) { 13128 if (!AStmt) 13129 return StmtError(); 13130 13131 setBranchProtectedScope(SemaRef, OMPD_target_update, AStmt); 13132 13133 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) { 13134 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required); 13135 return StmtError(); 13136 } 13137 13138 if (!isClauseMappable(Clauses)) { 13139 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage); 13140 return StmtError(); 13141 } 13142 13143 return OMPTargetUpdateDirective::Create(getASTContext(), StartLoc, EndLoc, 13144 Clauses, AStmt); 13145 } 13146 13147 /// This checks whether a \p ClauseType clause \p C has at most \p Max 13148 /// expression. If not, a diag of number \p Diag will be emitted. 13149 template <typename ClauseType> 13150 static bool checkNumExprsInClause(SemaBase &SemaRef, 13151 ArrayRef<OMPClause *> Clauses, 13152 unsigned MaxNum, unsigned Diag) { 13153 auto ClauseItr = llvm::find_if(Clauses, llvm::IsaPred<ClauseType>); 13154 if (ClauseItr == Clauses.end()) 13155 return true; 13156 const auto *C = cast<ClauseType>(*ClauseItr); 13157 auto VarList = C->getVarRefs(); 13158 if (VarList.size() > MaxNum) { 13159 SemaRef.Diag(VarList[MaxNum]->getBeginLoc(), Diag) 13160 << getOpenMPClauseName(C->getClauseKind()); 13161 return false; 13162 } 13163 return true; 13164 } 13165 13166 StmtResult SemaOpenMP::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses, 13167 Stmt *AStmt, 13168 SourceLocation StartLoc, 13169 SourceLocation EndLoc) { 13170 if (!AStmt) 13171 return StmtError(); 13172 13173 if (!checkNumExprsInClause<OMPNumTeamsClause>( 13174 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) || 13175 !checkNumExprsInClause<OMPThreadLimitClause>( 13176 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed)) 13177 return StmtError(); 13178 13179 // Report affected OpenMP target offloading behavior when in HIP lang-mode. 13180 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target)) 13181 Diag(StartLoc, diag::warn_hip_omp_target_directives); 13182 13183 setBranchProtectedScope(SemaRef, OMPD_teams, AStmt); 13184 13185 DSAStack->setParentTeamsRegionLoc(StartLoc); 13186 13187 return OMPTeamsDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses, 13188 AStmt); 13189 } 13190 13191 StmtResult SemaOpenMP::ActOnOpenMPCancellationPointDirective( 13192 SourceLocation StartLoc, SourceLocation EndLoc, 13193 OpenMPDirectiveKind CancelRegion) { 13194 if (DSAStack->isParentNowaitRegion()) { 13195 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0; 13196 return StmtError(); 13197 } 13198 if (DSAStack->isParentOrderedRegion()) { 13199 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0; 13200 return StmtError(); 13201 } 13202 return OMPCancellationPointDirective::Create(getASTContext(), StartLoc, 13203 EndLoc, CancelRegion); 13204 } 13205 13206 StmtResult SemaOpenMP::ActOnOpenMPCancelDirective( 13207 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc, 13208 SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) { 13209 if (DSAStack->isParentNowaitRegion()) { 13210 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1; 13211 return StmtError(); 13212 } 13213 if (DSAStack->isParentOrderedRegion()) { 13214 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1; 13215 return StmtError(); 13216 } 13217 DSAStack->setParentCancelRegion(/*Cancel=*/true); 13218 return OMPCancelDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses, 13219 CancelRegion); 13220 } 13221 13222 static bool checkReductionClauseWithNogroup(Sema &S, 13223 ArrayRef<OMPClause *> Clauses) { 13224 const OMPClause *ReductionClause = nullptr; 13225 const OMPClause *NogroupClause = nullptr; 13226 for (const OMPClause *C : Clauses) { 13227 if (C->getClauseKind() == OMPC_reduction) { 13228 ReductionClause = C; 13229 if (NogroupClause) 13230 break; 13231 continue; 13232 } 13233 if (C->getClauseKind() == OMPC_nogroup) { 13234 NogroupClause = C; 13235 if (ReductionClause) 13236 break; 13237 continue; 13238 } 13239 } 13240 if (ReductionClause && NogroupClause) { 13241 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup) 13242 << SourceRange(NogroupClause->getBeginLoc(), 13243 NogroupClause->getEndLoc()); 13244 return true; 13245 } 13246 return false; 13247 } 13248 13249 StmtResult SemaOpenMP::ActOnOpenMPTaskLoopDirective( 13250 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13251 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13252 if (!AStmt) 13253 return StmtError(); 13254 13255 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 13256 OMPLoopBasedDirective::HelperExprs B; 13257 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 13258 // define the nested loops number. 13259 unsigned NestedLoopCount = 13260 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses), 13261 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef, 13262 *DSAStack, VarsWithImplicitDSA, B); 13263 if (NestedLoopCount == 0) 13264 return StmtError(); 13265 13266 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 13267 "omp for loop exprs were not built"); 13268 13269 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13270 // The grainsize clause and num_tasks clause are mutually exclusive and may 13271 // not appear on the same taskloop directive. 13272 if (checkMutuallyExclusiveClauses(SemaRef, Clauses, 13273 {OMPC_grainsize, OMPC_num_tasks})) 13274 return StmtError(); 13275 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13276 // If a reduction clause is present on the taskloop directive, the nogroup 13277 // clause must not be specified. 13278 if (checkReductionClauseWithNogroup(SemaRef, Clauses)) 13279 return StmtError(); 13280 13281 SemaRef.setFunctionHasBranchProtectedScope(); 13282 return OMPTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc, 13283 NestedLoopCount, Clauses, AStmt, B, 13284 DSAStack->isCancelRegion()); 13285 } 13286 13287 StmtResult SemaOpenMP::ActOnOpenMPTaskLoopSimdDirective( 13288 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13289 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13290 if (!AStmt) 13291 return StmtError(); 13292 13293 CapturedStmt *CS = 13294 setBranchProtectedScope(SemaRef, OMPD_taskloop_simd, AStmt); 13295 13296 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 13297 OMPLoopBasedDirective::HelperExprs B; 13298 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 13299 // define the nested loops number. 13300 unsigned NestedLoopCount = 13301 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses), 13302 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack, 13303 VarsWithImplicitDSA, B); 13304 if (NestedLoopCount == 0) 13305 return StmtError(); 13306 13307 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 13308 return StmtError(); 13309 13310 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13311 // The grainsize clause and num_tasks clause are mutually exclusive and may 13312 // not appear on the same taskloop directive. 13313 if (checkMutuallyExclusiveClauses(SemaRef, Clauses, 13314 {OMPC_grainsize, OMPC_num_tasks})) 13315 return StmtError(); 13316 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13317 // If a reduction clause is present on the taskloop directive, the nogroup 13318 // clause must not be specified. 13319 if (checkReductionClauseWithNogroup(SemaRef, Clauses)) 13320 return StmtError(); 13321 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 13322 return StmtError(); 13323 13324 return OMPTaskLoopSimdDirective::Create(getASTContext(), StartLoc, EndLoc, 13325 NestedLoopCount, Clauses, AStmt, B); 13326 } 13327 13328 StmtResult SemaOpenMP::ActOnOpenMPMasterTaskLoopDirective( 13329 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13330 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13331 if (!AStmt) 13332 return StmtError(); 13333 13334 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 13335 OMPLoopBasedDirective::HelperExprs B; 13336 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 13337 // define the nested loops number. 13338 unsigned NestedLoopCount = 13339 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses), 13340 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef, 13341 *DSAStack, VarsWithImplicitDSA, B); 13342 if (NestedLoopCount == 0) 13343 return StmtError(); 13344 13345 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 13346 "omp for loop exprs were not built"); 13347 13348 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13349 // The grainsize clause and num_tasks clause are mutually exclusive and may 13350 // not appear on the same taskloop directive. 13351 if (checkMutuallyExclusiveClauses(SemaRef, Clauses, 13352 {OMPC_grainsize, OMPC_num_tasks})) 13353 return StmtError(); 13354 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13355 // If a reduction clause is present on the taskloop directive, the nogroup 13356 // clause must not be specified. 13357 if (checkReductionClauseWithNogroup(SemaRef, Clauses)) 13358 return StmtError(); 13359 13360 SemaRef.setFunctionHasBranchProtectedScope(); 13361 return OMPMasterTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc, 13362 NestedLoopCount, Clauses, AStmt, B, 13363 DSAStack->isCancelRegion()); 13364 } 13365 13366 StmtResult SemaOpenMP::ActOnOpenMPMaskedTaskLoopDirective( 13367 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13368 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13369 if (!AStmt) 13370 return StmtError(); 13371 13372 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 13373 OMPLoopBasedDirective::HelperExprs B; 13374 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 13375 // define the nested loops number. 13376 unsigned NestedLoopCount = 13377 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses), 13378 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef, 13379 *DSAStack, VarsWithImplicitDSA, B); 13380 if (NestedLoopCount == 0) 13381 return StmtError(); 13382 13383 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 13384 "omp for loop exprs were not built"); 13385 13386 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13387 // The grainsize clause and num_tasks clause are mutually exclusive and may 13388 // not appear on the same taskloop directive. 13389 if (checkMutuallyExclusiveClauses(SemaRef, Clauses, 13390 {OMPC_grainsize, OMPC_num_tasks})) 13391 return StmtError(); 13392 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13393 // If a reduction clause is present on the taskloop directive, the nogroup 13394 // clause must not be specified. 13395 if (checkReductionClauseWithNogroup(SemaRef, Clauses)) 13396 return StmtError(); 13397 13398 SemaRef.setFunctionHasBranchProtectedScope(); 13399 return OMPMaskedTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc, 13400 NestedLoopCount, Clauses, AStmt, B, 13401 DSAStack->isCancelRegion()); 13402 } 13403 13404 StmtResult SemaOpenMP::ActOnOpenMPMasterTaskLoopSimdDirective( 13405 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13406 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13407 if (!AStmt) 13408 return StmtError(); 13409 13410 CapturedStmt *CS = 13411 setBranchProtectedScope(SemaRef, OMPD_master_taskloop_simd, AStmt); 13412 13413 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 13414 OMPLoopBasedDirective::HelperExprs B; 13415 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 13416 // define the nested loops number. 13417 unsigned NestedLoopCount = 13418 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses), 13419 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack, 13420 VarsWithImplicitDSA, B); 13421 if (NestedLoopCount == 0) 13422 return StmtError(); 13423 13424 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 13425 return StmtError(); 13426 13427 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13428 // The grainsize clause and num_tasks clause are mutually exclusive and may 13429 // not appear on the same taskloop directive. 13430 if (checkMutuallyExclusiveClauses(SemaRef, Clauses, 13431 {OMPC_grainsize, OMPC_num_tasks})) 13432 return StmtError(); 13433 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13434 // If a reduction clause is present on the taskloop directive, the nogroup 13435 // clause must not be specified. 13436 if (checkReductionClauseWithNogroup(SemaRef, Clauses)) 13437 return StmtError(); 13438 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 13439 return StmtError(); 13440 13441 return OMPMasterTaskLoopSimdDirective::Create( 13442 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 13443 } 13444 13445 StmtResult SemaOpenMP::ActOnOpenMPMaskedTaskLoopSimdDirective( 13446 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13447 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13448 if (!AStmt) 13449 return StmtError(); 13450 13451 CapturedStmt *CS = 13452 setBranchProtectedScope(SemaRef, OMPD_masked_taskloop_simd, AStmt); 13453 13454 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 13455 OMPLoopBasedDirective::HelperExprs B; 13456 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 13457 // define the nested loops number. 13458 unsigned NestedLoopCount = 13459 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses), 13460 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack, 13461 VarsWithImplicitDSA, B); 13462 if (NestedLoopCount == 0) 13463 return StmtError(); 13464 13465 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 13466 return StmtError(); 13467 13468 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13469 // The grainsize clause and num_tasks clause are mutually exclusive and may 13470 // not appear on the same taskloop directive. 13471 if (checkMutuallyExclusiveClauses(SemaRef, Clauses, 13472 {OMPC_grainsize, OMPC_num_tasks})) 13473 return StmtError(); 13474 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13475 // If a reduction clause is present on the taskloop directive, the nogroup 13476 // clause must not be specified. 13477 if (checkReductionClauseWithNogroup(SemaRef, Clauses)) 13478 return StmtError(); 13479 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 13480 return StmtError(); 13481 13482 return OMPMaskedTaskLoopSimdDirective::Create( 13483 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 13484 } 13485 13486 StmtResult SemaOpenMP::ActOnOpenMPParallelMasterTaskLoopDirective( 13487 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13488 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13489 if (!AStmt) 13490 return StmtError(); 13491 13492 CapturedStmt *CS = 13493 setBranchProtectedScope(SemaRef, OMPD_parallel_master_taskloop, AStmt); 13494 13495 OMPLoopBasedDirective::HelperExprs B; 13496 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 13497 // define the nested loops number. 13498 unsigned NestedLoopCount = checkOpenMPLoop( 13499 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses), 13500 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack, 13501 VarsWithImplicitDSA, B); 13502 if (NestedLoopCount == 0) 13503 return StmtError(); 13504 13505 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 13506 "omp for loop exprs were not built"); 13507 13508 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13509 // The grainsize clause and num_tasks clause are mutually exclusive and may 13510 // not appear on the same taskloop directive. 13511 if (checkMutuallyExclusiveClauses(SemaRef, Clauses, 13512 {OMPC_grainsize, OMPC_num_tasks})) 13513 return StmtError(); 13514 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13515 // If a reduction clause is present on the taskloop directive, the nogroup 13516 // clause must not be specified. 13517 if (checkReductionClauseWithNogroup(SemaRef, Clauses)) 13518 return StmtError(); 13519 13520 return OMPParallelMasterTaskLoopDirective::Create( 13521 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B, 13522 DSAStack->isCancelRegion()); 13523 } 13524 13525 StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedTaskLoopDirective( 13526 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13527 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13528 if (!AStmt) 13529 return StmtError(); 13530 13531 CapturedStmt *CS = 13532 setBranchProtectedScope(SemaRef, OMPD_parallel_masked_taskloop, AStmt); 13533 13534 OMPLoopBasedDirective::HelperExprs B; 13535 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 13536 // define the nested loops number. 13537 unsigned NestedLoopCount = checkOpenMPLoop( 13538 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses), 13539 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack, 13540 VarsWithImplicitDSA, B); 13541 if (NestedLoopCount == 0) 13542 return StmtError(); 13543 13544 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 13545 "omp for loop exprs were not built"); 13546 13547 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13548 // The grainsize clause and num_tasks clause are mutually exclusive and may 13549 // not appear on the same taskloop directive. 13550 if (checkMutuallyExclusiveClauses(SemaRef, Clauses, 13551 {OMPC_grainsize, OMPC_num_tasks})) 13552 return StmtError(); 13553 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13554 // If a reduction clause is present on the taskloop directive, the nogroup 13555 // clause must not be specified. 13556 if (checkReductionClauseWithNogroup(SemaRef, Clauses)) 13557 return StmtError(); 13558 13559 return OMPParallelMaskedTaskLoopDirective::Create( 13560 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B, 13561 DSAStack->isCancelRegion()); 13562 } 13563 13564 StmtResult SemaOpenMP::ActOnOpenMPParallelMasterTaskLoopSimdDirective( 13565 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13566 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13567 if (!AStmt) 13568 return StmtError(); 13569 13570 CapturedStmt *CS = setBranchProtectedScope( 13571 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt); 13572 13573 OMPLoopBasedDirective::HelperExprs B; 13574 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 13575 // define the nested loops number. 13576 unsigned NestedLoopCount = checkOpenMPLoop( 13577 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses), 13578 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack, 13579 VarsWithImplicitDSA, B); 13580 if (NestedLoopCount == 0) 13581 return StmtError(); 13582 13583 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 13584 return StmtError(); 13585 13586 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13587 // The grainsize clause and num_tasks clause are mutually exclusive and may 13588 // not appear on the same taskloop directive. 13589 if (checkMutuallyExclusiveClauses(SemaRef, Clauses, 13590 {OMPC_grainsize, OMPC_num_tasks})) 13591 return StmtError(); 13592 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13593 // If a reduction clause is present on the taskloop directive, the nogroup 13594 // clause must not be specified. 13595 if (checkReductionClauseWithNogroup(SemaRef, Clauses)) 13596 return StmtError(); 13597 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 13598 return StmtError(); 13599 13600 return OMPParallelMasterTaskLoopSimdDirective::Create( 13601 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 13602 } 13603 13604 StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedTaskLoopSimdDirective( 13605 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13606 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13607 if (!AStmt) 13608 return StmtError(); 13609 13610 CapturedStmt *CS = setBranchProtectedScope( 13611 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt); 13612 13613 OMPLoopBasedDirective::HelperExprs B; 13614 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 13615 // define the nested loops number. 13616 unsigned NestedLoopCount = checkOpenMPLoop( 13617 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses), 13618 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack, 13619 VarsWithImplicitDSA, B); 13620 if (NestedLoopCount == 0) 13621 return StmtError(); 13622 13623 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 13624 return StmtError(); 13625 13626 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13627 // The grainsize clause and num_tasks clause are mutually exclusive and may 13628 // not appear on the same taskloop directive. 13629 if (checkMutuallyExclusiveClauses(SemaRef, Clauses, 13630 {OMPC_grainsize, OMPC_num_tasks})) 13631 return StmtError(); 13632 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13633 // If a reduction clause is present on the taskloop directive, the nogroup 13634 // clause must not be specified. 13635 if (checkReductionClauseWithNogroup(SemaRef, Clauses)) 13636 return StmtError(); 13637 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 13638 return StmtError(); 13639 13640 return OMPParallelMaskedTaskLoopSimdDirective::Create( 13641 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 13642 } 13643 13644 StmtResult SemaOpenMP::ActOnOpenMPDistributeDirective( 13645 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13646 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13647 if (!AStmt) 13648 return StmtError(); 13649 13650 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 13651 OMPLoopBasedDirective::HelperExprs B; 13652 // In presence of clause 'collapse' with number of loops, it will 13653 // define the nested loops number. 13654 unsigned NestedLoopCount = 13655 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses), 13656 nullptr /*ordered not a clause on distribute*/, AStmt, 13657 SemaRef, *DSAStack, VarsWithImplicitDSA, B); 13658 if (NestedLoopCount == 0) 13659 return StmtError(); 13660 13661 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 13662 "omp for loop exprs were not built"); 13663 13664 SemaRef.setFunctionHasBranchProtectedScope(); 13665 auto *DistributeDirective = OMPDistributeDirective::Create( 13666 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 13667 return DistributeDirective; 13668 } 13669 13670 StmtResult SemaOpenMP::ActOnOpenMPDistributeParallelForDirective( 13671 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13672 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13673 if (!AStmt) 13674 return StmtError(); 13675 13676 CapturedStmt *CS = 13677 setBranchProtectedScope(SemaRef, OMPD_distribute_parallel_for, AStmt); 13678 13679 OMPLoopBasedDirective::HelperExprs B; 13680 // In presence of clause 'collapse' with number of loops, it will 13681 // define the nested loops number. 13682 unsigned NestedLoopCount = checkOpenMPLoop( 13683 OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses), 13684 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack, 13685 VarsWithImplicitDSA, B); 13686 if (NestedLoopCount == 0) 13687 return StmtError(); 13688 13689 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 13690 "omp for loop exprs were not built"); 13691 13692 return OMPDistributeParallelForDirective::Create( 13693 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B, 13694 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion()); 13695 } 13696 13697 StmtResult SemaOpenMP::ActOnOpenMPDistributeParallelForSimdDirective( 13698 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13699 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13700 if (!AStmt) 13701 return StmtError(); 13702 13703 CapturedStmt *CS = setBranchProtectedScope( 13704 SemaRef, OMPD_distribute_parallel_for_simd, AStmt); 13705 13706 OMPLoopBasedDirective::HelperExprs B; 13707 // In presence of clause 'collapse' with number of loops, it will 13708 // define the nested loops number. 13709 unsigned NestedLoopCount = checkOpenMPLoop( 13710 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses), 13711 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack, 13712 VarsWithImplicitDSA, B); 13713 if (NestedLoopCount == 0) 13714 return StmtError(); 13715 13716 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 13717 return StmtError(); 13718 13719 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 13720 return StmtError(); 13721 13722 return OMPDistributeParallelForSimdDirective::Create( 13723 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 13724 } 13725 13726 StmtResult SemaOpenMP::ActOnOpenMPDistributeSimdDirective( 13727 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13728 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13729 if (!AStmt) 13730 return StmtError(); 13731 13732 CapturedStmt *CS = 13733 setBranchProtectedScope(SemaRef, OMPD_distribute_simd, AStmt); 13734 13735 OMPLoopBasedDirective::HelperExprs B; 13736 // In presence of clause 'collapse' with number of loops, it will 13737 // define the nested loops number. 13738 unsigned NestedLoopCount = 13739 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses), 13740 nullptr /*ordered not a clause on distribute*/, CS, 13741 SemaRef, *DSAStack, VarsWithImplicitDSA, B); 13742 if (NestedLoopCount == 0) 13743 return StmtError(); 13744 13745 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 13746 return StmtError(); 13747 13748 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 13749 return StmtError(); 13750 13751 return OMPDistributeSimdDirective::Create(getASTContext(), StartLoc, EndLoc, 13752 NestedLoopCount, Clauses, AStmt, B); 13753 } 13754 13755 StmtResult SemaOpenMP::ActOnOpenMPTargetParallelForSimdDirective( 13756 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13757 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13758 if (!AStmt) 13759 return StmtError(); 13760 13761 CapturedStmt *CS = 13762 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for_simd, AStmt); 13763 13764 OMPLoopBasedDirective::HelperExprs B; 13765 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 13766 // define the nested loops number. 13767 unsigned NestedLoopCount = checkOpenMPLoop( 13768 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses), 13769 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack, 13770 VarsWithImplicitDSA, B); 13771 if (NestedLoopCount == 0) 13772 return StmtError(); 13773 13774 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 13775 return StmtError(); 13776 13777 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 13778 return StmtError(); 13779 13780 return OMPTargetParallelForSimdDirective::Create( 13781 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 13782 } 13783 13784 StmtResult SemaOpenMP::ActOnOpenMPTargetSimdDirective( 13785 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13786 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13787 if (!AStmt) 13788 return StmtError(); 13789 13790 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target_simd, AStmt); 13791 13792 OMPLoopBasedDirective::HelperExprs B; 13793 // In presence of clause 'collapse' with number of loops, it will define the 13794 // nested loops number. 13795 unsigned NestedLoopCount = 13796 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses), 13797 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack, 13798 VarsWithImplicitDSA, B); 13799 if (NestedLoopCount == 0) 13800 return StmtError(); 13801 13802 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 13803 return StmtError(); 13804 13805 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 13806 return StmtError(); 13807 13808 return OMPTargetSimdDirective::Create(getASTContext(), StartLoc, EndLoc, 13809 NestedLoopCount, Clauses, AStmt, B); 13810 } 13811 13812 StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeDirective( 13813 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13814 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13815 if (!AStmt) 13816 return StmtError(); 13817 13818 CapturedStmt *CS = 13819 setBranchProtectedScope(SemaRef, OMPD_teams_distribute, AStmt); 13820 13821 OMPLoopBasedDirective::HelperExprs B; 13822 // In presence of clause 'collapse' with number of loops, it will 13823 // define the nested loops number. 13824 unsigned NestedLoopCount = 13825 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses), 13826 nullptr /*ordered not a clause on distribute*/, CS, 13827 SemaRef, *DSAStack, VarsWithImplicitDSA, B); 13828 if (NestedLoopCount == 0) 13829 return StmtError(); 13830 13831 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 13832 "omp teams distribute loop exprs were not built"); 13833 13834 DSAStack->setParentTeamsRegionLoc(StartLoc); 13835 13836 return OMPTeamsDistributeDirective::Create( 13837 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 13838 } 13839 13840 StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeSimdDirective( 13841 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13842 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13843 if (!AStmt) 13844 return StmtError(); 13845 13846 CapturedStmt *CS = 13847 setBranchProtectedScope(SemaRef, OMPD_teams_distribute_simd, AStmt); 13848 13849 OMPLoopBasedDirective::HelperExprs B; 13850 // In presence of clause 'collapse' with number of loops, it will 13851 // define the nested loops number. 13852 unsigned NestedLoopCount = checkOpenMPLoop( 13853 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses), 13854 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack, 13855 VarsWithImplicitDSA, B); 13856 if (NestedLoopCount == 0) 13857 return StmtError(); 13858 13859 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 13860 return StmtError(); 13861 13862 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 13863 return StmtError(); 13864 13865 DSAStack->setParentTeamsRegionLoc(StartLoc); 13866 13867 return OMPTeamsDistributeSimdDirective::Create( 13868 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 13869 } 13870 13871 StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeParallelForSimdDirective( 13872 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13873 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13874 if (!AStmt) 13875 return StmtError(); 13876 13877 CapturedStmt *CS = setBranchProtectedScope( 13878 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt); 13879 13880 OMPLoopBasedDirective::HelperExprs B; 13881 // In presence of clause 'collapse' with number of loops, it will 13882 // define the nested loops number. 13883 unsigned NestedLoopCount = checkOpenMPLoop( 13884 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses), 13885 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack, 13886 VarsWithImplicitDSA, B); 13887 if (NestedLoopCount == 0) 13888 return StmtError(); 13889 13890 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 13891 return StmtError(); 13892 13893 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 13894 return StmtError(); 13895 13896 DSAStack->setParentTeamsRegionLoc(StartLoc); 13897 13898 return OMPTeamsDistributeParallelForSimdDirective::Create( 13899 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 13900 } 13901 13902 StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeParallelForDirective( 13903 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13904 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13905 if (!AStmt) 13906 return StmtError(); 13907 13908 CapturedStmt *CS = setBranchProtectedScope( 13909 SemaRef, OMPD_teams_distribute_parallel_for, AStmt); 13910 13911 OMPLoopBasedDirective::HelperExprs B; 13912 // In presence of clause 'collapse' with number of loops, it will 13913 // define the nested loops number. 13914 unsigned NestedLoopCount = checkOpenMPLoop( 13915 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses), 13916 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack, 13917 VarsWithImplicitDSA, B); 13918 13919 if (NestedLoopCount == 0) 13920 return StmtError(); 13921 13922 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 13923 "omp for loop exprs were not built"); 13924 13925 DSAStack->setParentTeamsRegionLoc(StartLoc); 13926 13927 return OMPTeamsDistributeParallelForDirective::Create( 13928 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B, 13929 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion()); 13930 } 13931 13932 StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDirective( 13933 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13934 SourceLocation EndLoc) { 13935 if (!AStmt) 13936 return StmtError(); 13937 13938 setBranchProtectedScope(SemaRef, OMPD_target_teams, AStmt); 13939 13940 const OMPClause *BareClause = nullptr; 13941 bool HasThreadLimitAndNumTeamsClause = hasClauses(Clauses, OMPC_num_teams) && 13942 hasClauses(Clauses, OMPC_thread_limit); 13943 bool HasBareClause = llvm::any_of(Clauses, [&](const OMPClause *C) { 13944 BareClause = C; 13945 return C->getClauseKind() == OMPC_ompx_bare; 13946 }); 13947 13948 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) { 13949 Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid); 13950 return StmtError(); 13951 } 13952 13953 unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 1; 13954 unsigned DiagNo = HasBareClause 13955 ? diag::err_ompx_more_than_three_expr_not_allowed 13956 : diag::err_omp_multi_expr_not_allowed; 13957 if (!checkNumExprsInClause<OMPNumTeamsClause>(*this, Clauses, 13958 ClauseMaxNumExprs, DiagNo) || 13959 !checkNumExprsInClause<OMPThreadLimitClause>(*this, Clauses, 13960 ClauseMaxNumExprs, DiagNo)) 13961 return StmtError(); 13962 13963 return OMPTargetTeamsDirective::Create(getASTContext(), StartLoc, EndLoc, 13964 Clauses, AStmt); 13965 } 13966 13967 StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeDirective( 13968 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13969 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13970 if (!AStmt) 13971 return StmtError(); 13972 13973 if (!checkNumExprsInClause<OMPNumTeamsClause>( 13974 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) || 13975 !checkNumExprsInClause<OMPThreadLimitClause>( 13976 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed)) 13977 return StmtError(); 13978 13979 CapturedStmt *CS = 13980 setBranchProtectedScope(SemaRef, OMPD_target_teams_distribute, AStmt); 13981 13982 OMPLoopBasedDirective::HelperExprs B; 13983 // In presence of clause 'collapse' with number of loops, it will 13984 // define the nested loops number. 13985 unsigned NestedLoopCount = checkOpenMPLoop( 13986 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses), 13987 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack, 13988 VarsWithImplicitDSA, B); 13989 if (NestedLoopCount == 0) 13990 return StmtError(); 13991 13992 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 13993 "omp target teams distribute loop exprs were not built"); 13994 13995 return OMPTargetTeamsDistributeDirective::Create( 13996 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 13997 } 13998 13999 StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeParallelForDirective( 14000 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 14001 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 14002 if (!AStmt) 14003 return StmtError(); 14004 14005 if (!checkNumExprsInClause<OMPNumTeamsClause>( 14006 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) || 14007 !checkNumExprsInClause<OMPThreadLimitClause>( 14008 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed)) 14009 return StmtError(); 14010 14011 CapturedStmt *CS = setBranchProtectedScope( 14012 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt); 14013 14014 OMPLoopBasedDirective::HelperExprs B; 14015 // In presence of clause 'collapse' with number of loops, it will 14016 // define the nested loops number. 14017 unsigned NestedLoopCount = checkOpenMPLoop( 14018 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses), 14019 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack, 14020 VarsWithImplicitDSA, B); 14021 if (NestedLoopCount == 0) 14022 return StmtError(); 14023 14024 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 14025 return StmtError(); 14026 14027 return OMPTargetTeamsDistributeParallelForDirective::Create( 14028 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B, 14029 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion()); 14030 } 14031 14032 StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective( 14033 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 14034 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 14035 if (!AStmt) 14036 return StmtError(); 14037 14038 if (!checkNumExprsInClause<OMPNumTeamsClause>( 14039 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) || 14040 !checkNumExprsInClause<OMPThreadLimitClause>( 14041 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed)) 14042 return StmtError(); 14043 14044 CapturedStmt *CS = setBranchProtectedScope( 14045 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt); 14046 14047 OMPLoopBasedDirective::HelperExprs B; 14048 // In presence of clause 'collapse' with number of loops, it will 14049 // define the nested loops number. 14050 unsigned NestedLoopCount = 14051 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd, 14052 getCollapseNumberExpr(Clauses), 14053 nullptr /*ordered not a clause on distribute*/, CS, 14054 SemaRef, *DSAStack, VarsWithImplicitDSA, B); 14055 if (NestedLoopCount == 0) 14056 return StmtError(); 14057 14058 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 14059 return StmtError(); 14060 14061 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 14062 return StmtError(); 14063 14064 return OMPTargetTeamsDistributeParallelForSimdDirective::Create( 14065 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 14066 } 14067 14068 StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeSimdDirective( 14069 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 14070 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 14071 if (!AStmt) 14072 return StmtError(); 14073 14074 if (!checkNumExprsInClause<OMPNumTeamsClause>( 14075 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) || 14076 !checkNumExprsInClause<OMPThreadLimitClause>( 14077 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed)) 14078 return StmtError(); 14079 14080 CapturedStmt *CS = setBranchProtectedScope( 14081 SemaRef, OMPD_target_teams_distribute_simd, AStmt); 14082 14083 OMPLoopBasedDirective::HelperExprs B; 14084 // In presence of clause 'collapse' with number of loops, it will 14085 // define the nested loops number. 14086 unsigned NestedLoopCount = checkOpenMPLoop( 14087 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses), 14088 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack, 14089 VarsWithImplicitDSA, B); 14090 if (NestedLoopCount == 0) 14091 return StmtError(); 14092 14093 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 14094 return StmtError(); 14095 14096 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 14097 return StmtError(); 14098 14099 return OMPTargetTeamsDistributeSimdDirective::Create( 14100 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 14101 } 14102 14103 bool SemaOpenMP::checkTransformableLoopNest( 14104 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops, 14105 SmallVectorImpl<OMPLoopBasedDirective::HelperExprs> &LoopHelpers, 14106 Stmt *&Body, SmallVectorImpl<SmallVector<Stmt *, 0>> &OriginalInits) { 14107 OriginalInits.emplace_back(); 14108 bool Result = OMPLoopBasedDirective::doForAllLoops( 14109 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops, 14110 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt, 14111 Stmt *CurStmt) { 14112 VarsWithInheritedDSAType TmpDSA; 14113 unsigned SingleNumLoops = 14114 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack, 14115 TmpDSA, LoopHelpers[Cnt]); 14116 if (SingleNumLoops == 0) 14117 return true; 14118 assert(SingleNumLoops == 1 && "Expect single loop iteration space"); 14119 if (auto *For = dyn_cast<ForStmt>(CurStmt)) { 14120 OriginalInits.back().push_back(For->getInit()); 14121 Body = For->getBody(); 14122 } else { 14123 assert(isa<CXXForRangeStmt>(CurStmt) && 14124 "Expected canonical for or range-based for loops."); 14125 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt); 14126 OriginalInits.back().push_back(CXXFor->getBeginStmt()); 14127 Body = CXXFor->getBody(); 14128 } 14129 OriginalInits.emplace_back(); 14130 return false; 14131 }, 14132 [&OriginalInits](OMPLoopBasedDirective *Transform) { 14133 Stmt *DependentPreInits; 14134 if (auto *Dir = dyn_cast<OMPTileDirective>(Transform)) 14135 DependentPreInits = Dir->getPreInits(); 14136 else if (auto *Dir = dyn_cast<OMPUnrollDirective>(Transform)) 14137 DependentPreInits = Dir->getPreInits(); 14138 else if (auto *Dir = dyn_cast<OMPReverseDirective>(Transform)) 14139 DependentPreInits = Dir->getPreInits(); 14140 else if (auto *Dir = dyn_cast<OMPInterchangeDirective>(Transform)) 14141 DependentPreInits = Dir->getPreInits(); 14142 else 14143 llvm_unreachable("Unhandled loop transformation"); 14144 14145 appendFlattenedStmtList(OriginalInits.back(), DependentPreInits); 14146 }); 14147 assert(OriginalInits.back().empty() && "No preinit after innermost loop"); 14148 OriginalInits.pop_back(); 14149 return Result; 14150 } 14151 14152 /// Add preinit statements that need to be propageted from the selected loop. 14153 static void addLoopPreInits(ASTContext &Context, 14154 OMPLoopBasedDirective::HelperExprs &LoopHelper, 14155 Stmt *LoopStmt, ArrayRef<Stmt *> OriginalInit, 14156 SmallVectorImpl<Stmt *> &PreInits) { 14157 14158 // For range-based for-statements, ensure that their syntactic sugar is 14159 // executed by adding them as pre-init statements. 14160 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) { 14161 Stmt *RangeInit = CXXRangeFor->getInit(); 14162 if (RangeInit) 14163 PreInits.push_back(RangeInit); 14164 14165 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt(); 14166 PreInits.push_back(new (Context) DeclStmt(RangeStmt->getDeclGroup(), 14167 RangeStmt->getBeginLoc(), 14168 RangeStmt->getEndLoc())); 14169 14170 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt(); 14171 PreInits.push_back(new (Context) DeclStmt(RangeEnd->getDeclGroup(), 14172 RangeEnd->getBeginLoc(), 14173 RangeEnd->getEndLoc())); 14174 } 14175 14176 llvm::append_range(PreInits, OriginalInit); 14177 14178 // List of OMPCapturedExprDecl, for __begin, __end, and NumIterations 14179 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits)) { 14180 PreInits.push_back(new (Context) DeclStmt( 14181 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc())); 14182 } 14183 14184 // Gather declarations for the data members used as counters. 14185 for (Expr *CounterRef : LoopHelper.Counters) { 14186 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl(); 14187 if (isa<OMPCapturedExprDecl>(CounterDecl)) 14188 PreInits.push_back(new (Context) DeclStmt( 14189 DeclGroupRef(CounterDecl), SourceLocation(), SourceLocation())); 14190 } 14191 } 14192 14193 /// Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected 14194 /// loop of a construct. 14195 static void collectLoopStmts(Stmt *AStmt, MutableArrayRef<Stmt *> LoopStmts) { 14196 size_t NumLoops = LoopStmts.size(); 14197 OMPLoopBasedDirective::doForAllLoops( 14198 AStmt, /*TryImperfectlyNestedLoops=*/false, NumLoops, 14199 [LoopStmts](unsigned Cnt, Stmt *CurStmt) { 14200 assert(!LoopStmts[Cnt] && "Loop statement must not yet be assigned"); 14201 LoopStmts[Cnt] = CurStmt; 14202 return false; 14203 }); 14204 assert(!is_contained(LoopStmts, nullptr) && 14205 "Expecting a loop statement for each affected loop"); 14206 } 14207 14208 StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef<OMPClause *> Clauses, 14209 Stmt *AStmt, 14210 SourceLocation StartLoc, 14211 SourceLocation EndLoc) { 14212 ASTContext &Context = getASTContext(); 14213 Scope *CurScope = SemaRef.getCurScope(); 14214 14215 const auto *SizesClause = 14216 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses); 14217 if (!SizesClause || 14218 llvm::any_of(SizesClause->getSizesRefs(), [](Expr *E) { return !E; })) 14219 return StmtError(); 14220 unsigned NumLoops = SizesClause->getNumSizes(); 14221 14222 // Empty statement should only be possible if there already was an error. 14223 if (!AStmt) 14224 return StmtError(); 14225 14226 // Verify and diagnose loop nest. 14227 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops); 14228 Stmt *Body = nullptr; 14229 SmallVector<SmallVector<Stmt *, 0>, 4> OriginalInits; 14230 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body, 14231 OriginalInits)) 14232 return StmtError(); 14233 14234 // Delay tiling to when template is completely instantiated. 14235 if (SemaRef.CurContext->isDependentContext()) 14236 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, 14237 NumLoops, AStmt, nullptr, nullptr); 14238 14239 assert(LoopHelpers.size() == NumLoops && 14240 "Expecting loop iteration space dimensionality to match number of " 14241 "affected loops"); 14242 assert(OriginalInits.size() == NumLoops && 14243 "Expecting loop iteration space dimensionality to match number of " 14244 "affected loops"); 14245 14246 // Collect all affected loop statements. 14247 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr); 14248 collectLoopStmts(AStmt, LoopStmts); 14249 14250 SmallVector<Stmt *, 4> PreInits; 14251 CaptureVars CopyTransformer(SemaRef); 14252 14253 // Create iteration variables for the generated loops. 14254 SmallVector<VarDecl *, 4> FloorIndVars; 14255 SmallVector<VarDecl *, 4> TileIndVars; 14256 FloorIndVars.resize(NumLoops); 14257 TileIndVars.resize(NumLoops); 14258 for (unsigned I = 0; I < NumLoops; ++I) { 14259 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I]; 14260 14261 assert(LoopHelper.Counters.size() == 1 && 14262 "Expect single-dimensional loop iteration space"); 14263 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front()); 14264 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString(); 14265 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef); 14266 QualType CntTy = IterVarRef->getType(); 14267 14268 // Iteration variable for the floor (i.e. outer) loop. 14269 { 14270 std::string FloorCntName = 14271 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str(); 14272 VarDecl *FloorCntDecl = 14273 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar); 14274 FloorIndVars[I] = FloorCntDecl; 14275 } 14276 14277 // Iteration variable for the tile (i.e. inner) loop. 14278 { 14279 std::string TileCntName = 14280 (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str(); 14281 14282 // Reuse the iteration variable created by checkOpenMPLoop. It is also 14283 // used by the expressions to derive the original iteration variable's 14284 // value from the logical iteration number. 14285 auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl()); 14286 TileCntDecl->setDeclName( 14287 &SemaRef.PP.getIdentifierTable().get(TileCntName)); 14288 TileIndVars[I] = TileCntDecl; 14289 } 14290 14291 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I], 14292 PreInits); 14293 } 14294 14295 // Once the original iteration values are set, append the innermost body. 14296 Stmt *Inner = Body; 14297 14298 auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context, 14299 SizesClause, CurScope](int I) -> Expr * { 14300 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I]; 14301 if (isa<ConstantExpr>(DimTileSizeExpr)) 14302 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)); 14303 14304 // When the tile size is not a constant but a variable, it is possible to 14305 // pass non-positive numbers. For instance: 14306 // \code{c} 14307 // int a = 0; 14308 // #pragma omp tile sizes(a) 14309 // for (int i = 0; i < 42; ++i) 14310 // body(i); 14311 // \endcode 14312 // Although there is no meaningful interpretation of the tile size, the body 14313 // should still be executed 42 times to avoid surprises. To preserve the 14314 // invariant that every loop iteration is executed exactly once and not 14315 // cause an infinite loop, apply a minimum tile size of one. 14316 // Build expr: 14317 // \code{c} 14318 // (TS <= 0) ? 1 : TS 14319 // \endcode 14320 QualType DimTy = DimTileSizeExpr->getType(); 14321 uint64_t DimWidth = Context.getTypeSize(DimTy); 14322 IntegerLiteral *Zero = IntegerLiteral::Create( 14323 Context, llvm::APInt::getZero(DimWidth), DimTy, {}); 14324 IntegerLiteral *One = 14325 IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {}); 14326 Expr *Cond = AssertSuccess(SemaRef.BuildBinOp( 14327 CurScope, {}, BO_LE, 14328 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero)); 14329 Expr *MinOne = new (Context) ConditionalOperator( 14330 Cond, {}, One, {}, 14331 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy, 14332 VK_PRValue, OK_Ordinary); 14333 return MinOne; 14334 }; 14335 14336 // Create tile loops from the inside to the outside. 14337 for (int I = NumLoops - 1; I >= 0; --I) { 14338 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I]; 14339 Expr *NumIterations = LoopHelper.NumIterations; 14340 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]); 14341 QualType IVTy = NumIterations->getType(); 14342 Stmt *LoopStmt = LoopStmts[I]; 14343 14344 // Commonly used variables. One of the constraints of an AST is that every 14345 // node object must appear at most once, hence we define lamdas that create 14346 // a new AST node at every use. 14347 auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, IVTy, 14348 OrigCntVar]() { 14349 return buildDeclRefExpr(SemaRef, TileIndVars[I], IVTy, 14350 OrigCntVar->getExprLoc()); 14351 }; 14352 auto MakeFloorIVRef = [&SemaRef = this->SemaRef, &FloorIndVars, I, IVTy, 14353 OrigCntVar]() { 14354 return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy, 14355 OrigCntVar->getExprLoc()); 14356 }; 14357 14358 // For init-statement: auto .tile.iv = .floor.iv 14359 SemaRef.AddInitializerToDecl( 14360 TileIndVars[I], SemaRef.DefaultLvalueConversion(MakeFloorIVRef()).get(), 14361 /*DirectInit=*/false); 14362 Decl *CounterDecl = TileIndVars[I]; 14363 StmtResult InitStmt = new (Context) 14364 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1), 14365 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc()); 14366 if (!InitStmt.isUsable()) 14367 return StmtError(); 14368 14369 // For cond-expression: 14370 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations) 14371 ExprResult EndOfTile = 14372 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add, 14373 MakeFloorIVRef(), MakeDimTileSize(I)); 14374 if (!EndOfTile.isUsable()) 14375 return StmtError(); 14376 ExprResult IsPartialTile = 14377 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, 14378 NumIterations, EndOfTile.get()); 14379 if (!IsPartialTile.isUsable()) 14380 return StmtError(); 14381 ExprResult MinTileAndIterSpace = SemaRef.ActOnConditionalOp( 14382 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(), 14383 IsPartialTile.get(), NumIterations, EndOfTile.get()); 14384 if (!MinTileAndIterSpace.isUsable()) 14385 return StmtError(); 14386 ExprResult CondExpr = 14387 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, 14388 MakeTileIVRef(), MinTileAndIterSpace.get()); 14389 if (!CondExpr.isUsable()) 14390 return StmtError(); 14391 14392 // For incr-statement: ++.tile.iv 14393 ExprResult IncrStmt = SemaRef.BuildUnaryOp( 14394 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef()); 14395 if (!IncrStmt.isUsable()) 14396 return StmtError(); 14397 14398 // Statements to set the original iteration variable's value from the 14399 // logical iteration number. 14400 // Generated for loop is: 14401 // \code 14402 // Original_for_init; 14403 // for (auto .tile.iv = .floor.iv; 14404 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations); 14405 // ++.tile.iv) { 14406 // Original_Body; 14407 // Original_counter_update; 14408 // } 14409 // \endcode 14410 // FIXME: If the innermost body is an loop itself, inserting these 14411 // statements stops it being recognized as a perfectly nested loop (e.g. 14412 // for applying tiling again). If this is the case, sink the expressions 14413 // further into the inner loop. 14414 SmallVector<Stmt *, 4> BodyParts; 14415 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end()); 14416 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) 14417 BodyParts.push_back(SourceCXXFor->getLoopVarStmt()); 14418 BodyParts.push_back(Inner); 14419 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(), 14420 Inner->getBeginLoc(), Inner->getEndLoc()); 14421 Inner = new (Context) 14422 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr, 14423 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(), 14424 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc()); 14425 } 14426 14427 // Create floor loops from the inside to the outside. 14428 for (int I = NumLoops - 1; I >= 0; --I) { 14429 auto &LoopHelper = LoopHelpers[I]; 14430 Expr *NumIterations = LoopHelper.NumIterations; 14431 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]); 14432 QualType IVTy = NumIterations->getType(); 14433 14434 // Commonly used variables. One of the constraints of an AST is that every 14435 // node object must appear at most once, hence we define lamdas that create 14436 // a new AST node at every use. 14437 auto MakeFloorIVRef = [&SemaRef = this->SemaRef, &FloorIndVars, I, IVTy, 14438 OrigCntVar]() { 14439 return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy, 14440 OrigCntVar->getExprLoc()); 14441 }; 14442 14443 // For init-statement: auto .floor.iv = 0 14444 SemaRef.AddInitializerToDecl( 14445 FloorIndVars[I], 14446 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(), 14447 /*DirectInit=*/false); 14448 Decl *CounterDecl = FloorIndVars[I]; 14449 StmtResult InitStmt = new (Context) 14450 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1), 14451 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc()); 14452 if (!InitStmt.isUsable()) 14453 return StmtError(); 14454 14455 // For cond-expression: .floor.iv < NumIterations 14456 ExprResult CondExpr = 14457 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, 14458 MakeFloorIVRef(), NumIterations); 14459 if (!CondExpr.isUsable()) 14460 return StmtError(); 14461 14462 // For incr-statement: .floor.iv += DimTileSize 14463 ExprResult IncrStmt = 14464 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign, 14465 MakeFloorIVRef(), MakeDimTileSize(I)); 14466 if (!IncrStmt.isUsable()) 14467 return StmtError(); 14468 14469 Inner = new (Context) 14470 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr, 14471 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(), 14472 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc()); 14473 } 14474 14475 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops, 14476 AStmt, Inner, 14477 buildPreInits(Context, PreInits)); 14478 } 14479 14480 StmtResult SemaOpenMP::ActOnOpenMPUnrollDirective(ArrayRef<OMPClause *> Clauses, 14481 Stmt *AStmt, 14482 SourceLocation StartLoc, 14483 SourceLocation EndLoc) { 14484 ASTContext &Context = getASTContext(); 14485 Scope *CurScope = SemaRef.getCurScope(); 14486 // Empty statement should only be possible if there already was an error. 14487 if (!AStmt) 14488 return StmtError(); 14489 14490 if (checkMutuallyExclusiveClauses(SemaRef, Clauses, 14491 {OMPC_partial, OMPC_full})) 14492 return StmtError(); 14493 14494 const OMPFullClause *FullClause = 14495 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses); 14496 const OMPPartialClause *PartialClause = 14497 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses); 14498 assert(!(FullClause && PartialClause) && 14499 "mutual exclusivity must have been checked before"); 14500 14501 constexpr unsigned NumLoops = 1; 14502 Stmt *Body = nullptr; 14503 SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers( 14504 NumLoops); 14505 SmallVector<SmallVector<Stmt *, 0>, NumLoops + 1> OriginalInits; 14506 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers, 14507 Body, OriginalInits)) 14508 return StmtError(); 14509 14510 unsigned NumGeneratedLoops = PartialClause ? 1 : 0; 14511 14512 // Delay unrolling to when template is completely instantiated. 14513 if (SemaRef.CurContext->isDependentContext()) 14514 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt, 14515 NumGeneratedLoops, nullptr, nullptr); 14516 14517 assert(LoopHelpers.size() == NumLoops && 14518 "Expecting a single-dimensional loop iteration space"); 14519 assert(OriginalInits.size() == NumLoops && 14520 "Expecting a single-dimensional loop iteration space"); 14521 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front(); 14522 14523 if (FullClause) { 14524 if (!VerifyPositiveIntegerConstantInClause( 14525 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false, 14526 /*SuppressExprDiags=*/true) 14527 .isUsable()) { 14528 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count); 14529 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here) 14530 << "#pragma omp unroll full"; 14531 return StmtError(); 14532 } 14533 } 14534 14535 // The generated loop may only be passed to other loop-associated directive 14536 // when a partial clause is specified. Without the requirement it is 14537 // sufficient to generate loop unroll metadata at code-generation. 14538 if (NumGeneratedLoops == 0) 14539 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt, 14540 NumGeneratedLoops, nullptr, nullptr); 14541 14542 // Otherwise, we need to provide a de-sugared/transformed AST that can be 14543 // associated with another loop directive. 14544 // 14545 // The canonical loop analysis return by checkTransformableLoopNest assumes 14546 // the following structure to be the same loop without transformations or 14547 // directives applied: \code OriginalInits; LoopHelper.PreInits; 14548 // LoopHelper.Counters; 14549 // for (; IV < LoopHelper.NumIterations; ++IV) { 14550 // LoopHelper.Updates; 14551 // Body; 14552 // } 14553 // \endcode 14554 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits 14555 // and referenced by LoopHelper.IterationVarRef. 14556 // 14557 // The unrolling directive transforms this into the following loop: 14558 // \code 14559 // OriginalInits; \ 14560 // LoopHelper.PreInits; > NewPreInits 14561 // LoopHelper.Counters; / 14562 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) { 14563 // #pragma clang loop unroll_count(Factor) 14564 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV) 14565 // { 14566 // LoopHelper.Updates; 14567 // Body; 14568 // } 14569 // } 14570 // \endcode 14571 // where UIV is a new logical iteration counter. IV must be the same VarDecl 14572 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates 14573 // references it. If the partially unrolled loop is associated with another 14574 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to 14575 // analyze this loop, i.e. the outer loop must fulfill the constraints of an 14576 // OpenMP canonical loop. The inner loop is not an associable canonical loop 14577 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of 14578 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a 14579 // property of the OMPLoopBasedDirective instead of statements in 14580 // CompoundStatement. This is to allow the loop to become a non-outermost loop 14581 // of a canonical loop nest where these PreInits are emitted before the 14582 // outermost directive. 14583 14584 // Find the loop statement. 14585 Stmt *LoopStmt = nullptr; 14586 collectLoopStmts(AStmt, {LoopStmt}); 14587 14588 // Determine the PreInit declarations. 14589 SmallVector<Stmt *, 4> PreInits; 14590 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits); 14591 14592 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef); 14593 QualType IVTy = IterationVarRef->getType(); 14594 assert(LoopHelper.Counters.size() == 1 && 14595 "Expecting a single-dimensional loop iteration space"); 14596 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front()); 14597 14598 // Determine the unroll factor. 14599 uint64_t Factor; 14600 SourceLocation FactorLoc; 14601 if (Expr *FactorVal = PartialClause->getFactor()) { 14602 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue(); 14603 FactorLoc = FactorVal->getExprLoc(); 14604 } else { 14605 // TODO: Use a better profitability model. 14606 Factor = 2; 14607 } 14608 assert(Factor > 0 && "Expected positive unroll factor"); 14609 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() { 14610 return IntegerLiteral::Create( 14611 getASTContext(), llvm::APInt(getASTContext().getIntWidth(IVTy), Factor), 14612 IVTy, FactorLoc); 14613 }; 14614 14615 // Iteration variable SourceLocations. 14616 SourceLocation OrigVarLoc = OrigVar->getExprLoc(); 14617 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc(); 14618 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc(); 14619 14620 // Internal variable names. 14621 std::string OrigVarName = OrigVar->getNameInfo().getAsString(); 14622 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str(); 14623 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str(); 14624 std::string InnerTripCountName = 14625 (Twine(".unroll_inner.tripcount.") + OrigVarName).str(); 14626 14627 // Create the iteration variable for the unrolled loop. 14628 VarDecl *OuterIVDecl = 14629 buildVarDecl(SemaRef, {}, IVTy, OuterIVName, nullptr, OrigVar); 14630 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() { 14631 return buildDeclRefExpr(SemaRef, OuterIVDecl, IVTy, OrigVarLoc); 14632 }; 14633 14634 // Iteration variable for the inner loop: Reuse the iteration variable created 14635 // by checkOpenMPLoop. 14636 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl()); 14637 InnerIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(InnerIVName)); 14638 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() { 14639 return buildDeclRefExpr(SemaRef, InnerIVDecl, IVTy, OrigVarLoc); 14640 }; 14641 14642 // Make a copy of the NumIterations expression for each use: By the AST 14643 // constraints, every expression object in a DeclContext must be unique. 14644 CaptureVars CopyTransformer(SemaRef); 14645 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * { 14646 return AssertSuccess( 14647 CopyTransformer.TransformExpr(LoopHelper.NumIterations)); 14648 }; 14649 14650 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv 14651 ExprResult LValueConv = SemaRef.DefaultLvalueConversion(MakeOuterRef()); 14652 SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.get(), 14653 /*DirectInit=*/false); 14654 StmtResult InnerInit = new (Context) 14655 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd); 14656 if (!InnerInit.isUsable()) 14657 return StmtError(); 14658 14659 // Inner For cond-expression: 14660 // \code 14661 // .unroll_inner.iv < .unrolled.iv + Factor && 14662 // .unroll_inner.iv < NumIterations 14663 // \endcode 14664 // This conjunction of two conditions allows ScalarEvolution to derive the 14665 // maximum trip count of the inner loop. 14666 ExprResult EndOfTile = 14667 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add, 14668 MakeOuterRef(), MakeFactorExpr()); 14669 if (!EndOfTile.isUsable()) 14670 return StmtError(); 14671 ExprResult InnerCond1 = 14672 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, 14673 MakeInnerRef(), EndOfTile.get()); 14674 if (!InnerCond1.isUsable()) 14675 return StmtError(); 14676 ExprResult InnerCond2 = 14677 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, 14678 MakeInnerRef(), MakeNumIterations()); 14679 if (!InnerCond2.isUsable()) 14680 return StmtError(); 14681 ExprResult InnerCond = 14682 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd, 14683 InnerCond1.get(), InnerCond2.get()); 14684 if (!InnerCond.isUsable()) 14685 return StmtError(); 14686 14687 // Inner For incr-statement: ++.unroll_inner.iv 14688 ExprResult InnerIncr = SemaRef.BuildUnaryOp( 14689 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef()); 14690 if (!InnerIncr.isUsable()) 14691 return StmtError(); 14692 14693 // Inner For statement. 14694 SmallVector<Stmt *> InnerBodyStmts; 14695 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end()); 14696 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) 14697 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt()); 14698 InnerBodyStmts.push_back(Body); 14699 CompoundStmt *InnerBody = 14700 CompoundStmt::Create(getASTContext(), InnerBodyStmts, FPOptionsOverride(), 14701 Body->getBeginLoc(), Body->getEndLoc()); 14702 ForStmt *InnerFor = new (Context) 14703 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr, 14704 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(), 14705 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc()); 14706 14707 // Unroll metadata for the inner loop. 14708 // This needs to take into account the remainder portion of the unrolled loop, 14709 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass 14710 // supports multiple loop exits. Instead, unroll using a factor equivalent to 14711 // the maximum trip count, which will also generate a remainder loop. Just 14712 // `unroll(enable)` (which could have been useful if the user has not 14713 // specified a concrete factor; even though the outer loop cannot be 14714 // influenced anymore, would avoid more code bloat than necessary) will refuse 14715 // the loop because "Won't unroll; remainder loop could not be generated when 14716 // assuming runtime trip count". Even if it did work, it must not choose a 14717 // larger unroll factor than the maximum loop length, or it would always just 14718 // execute the remainder loop. 14719 LoopHintAttr *UnrollHintAttr = 14720 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount, 14721 LoopHintAttr::Numeric, MakeFactorExpr()); 14722 AttributedStmt *InnerUnrolled = AttributedStmt::Create( 14723 getASTContext(), StartLoc, {UnrollHintAttr}, InnerFor); 14724 14725 // Outer For init-statement: auto .unrolled.iv = 0 14726 SemaRef.AddInitializerToDecl( 14727 OuterIVDecl, 14728 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(), 14729 /*DirectInit=*/false); 14730 StmtResult OuterInit = new (Context) 14731 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd); 14732 if (!OuterInit.isUsable()) 14733 return StmtError(); 14734 14735 // Outer For cond-expression: .unrolled.iv < NumIterations 14736 ExprResult OuterConde = 14737 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, 14738 MakeOuterRef(), MakeNumIterations()); 14739 if (!OuterConde.isUsable()) 14740 return StmtError(); 14741 14742 // Outer For incr-statement: .unrolled.iv += Factor 14743 ExprResult OuterIncr = 14744 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign, 14745 MakeOuterRef(), MakeFactorExpr()); 14746 if (!OuterIncr.isUsable()) 14747 return StmtError(); 14748 14749 // Outer For statement. 14750 ForStmt *OuterFor = new (Context) 14751 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr, 14752 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(), 14753 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc()); 14754 14755 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt, 14756 NumGeneratedLoops, OuterFor, 14757 buildPreInits(Context, PreInits)); 14758 } 14759 14760 StmtResult SemaOpenMP::ActOnOpenMPReverseDirective(Stmt *AStmt, 14761 SourceLocation StartLoc, 14762 SourceLocation EndLoc) { 14763 ASTContext &Context = getASTContext(); 14764 Scope *CurScope = SemaRef.getCurScope(); 14765 14766 // Empty statement should only be possible if there already was an error. 14767 if (!AStmt) 14768 return StmtError(); 14769 14770 constexpr unsigned NumLoops = 1; 14771 Stmt *Body = nullptr; 14772 SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers( 14773 NumLoops); 14774 SmallVector<SmallVector<Stmt *, 0>, NumLoops + 1> OriginalInits; 14775 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers, 14776 Body, OriginalInits)) 14777 return StmtError(); 14778 14779 // Delay applying the transformation to when template is completely 14780 // instantiated. 14781 if (SemaRef.CurContext->isDependentContext()) 14782 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt, 14783 nullptr, nullptr); 14784 14785 assert(LoopHelpers.size() == NumLoops && 14786 "Expecting a single-dimensional loop iteration space"); 14787 assert(OriginalInits.size() == NumLoops && 14788 "Expecting a single-dimensional loop iteration space"); 14789 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front(); 14790 14791 // Find the loop statement. 14792 Stmt *LoopStmt = nullptr; 14793 collectLoopStmts(AStmt, {LoopStmt}); 14794 14795 // Determine the PreInit declarations. 14796 SmallVector<Stmt *> PreInits; 14797 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits); 14798 14799 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef); 14800 QualType IVTy = IterationVarRef->getType(); 14801 uint64_t IVWidth = Context.getTypeSize(IVTy); 14802 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front()); 14803 14804 // Iteration variable SourceLocations. 14805 SourceLocation OrigVarLoc = OrigVar->getExprLoc(); 14806 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc(); 14807 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc(); 14808 14809 // Locations pointing to the transformation. 14810 SourceLocation TransformLoc = StartLoc; 14811 SourceLocation TransformLocBegin = StartLoc; 14812 SourceLocation TransformLocEnd = EndLoc; 14813 14814 // Internal variable names. 14815 std::string OrigVarName = OrigVar->getNameInfo().getAsString(); 14816 SmallString<64> ForwardIVName(".forward.iv."); 14817 ForwardIVName += OrigVarName; 14818 SmallString<64> ReversedIVName(".reversed.iv."); 14819 ReversedIVName += OrigVarName; 14820 14821 // LoopHelper.Updates will read the logical iteration number from 14822 // LoopHelper.IterationVarRef, compute the value of the user loop counter of 14823 // that logical iteration from it, then assign it to the user loop counter 14824 // variable. We cannot directly use LoopHelper.IterationVarRef as the 14825 // induction variable of the generated loop because it may cause an underflow: 14826 // \code{.c} 14827 // for (unsigned i = 0; i < n; ++i) 14828 // body(i); 14829 // \endcode 14830 // 14831 // Naive reversal: 14832 // \code{.c} 14833 // for (unsigned i = n-1; i >= 0; --i) 14834 // body(i); 14835 // \endcode 14836 // 14837 // Instead, we introduce a new iteration variable representing the logical 14838 // iteration counter of the original loop, convert it to the logical iteration 14839 // number of the reversed loop, then let LoopHelper.Updates compute the user's 14840 // loop iteration variable from it. 14841 // \code{.cpp} 14842 // for (auto .forward.iv = 0; .forward.iv < n; ++.forward.iv) { 14843 // auto .reversed.iv = n - .forward.iv - 1; 14844 // i = (.reversed.iv + 0) * 1; // LoopHelper.Updates 14845 // body(i); // Body 14846 // } 14847 // \endcode 14848 14849 // Subexpressions with more than one use. One of the constraints of an AST is 14850 // that every node object must appear at most once, hence we define a lambda 14851 // that creates a new AST node at every use. 14852 CaptureVars CopyTransformer(SemaRef); 14853 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * { 14854 return AssertSuccess( 14855 CopyTransformer.TransformExpr(LoopHelper.NumIterations)); 14856 }; 14857 14858 // Create the iteration variable for the forward loop (from 0 to n-1). 14859 VarDecl *ForwardIVDecl = 14860 buildVarDecl(SemaRef, {}, IVTy, ForwardIVName, nullptr, OrigVar); 14861 auto MakeForwardRef = [&SemaRef = this->SemaRef, ForwardIVDecl, IVTy, 14862 OrigVarLoc]() { 14863 return buildDeclRefExpr(SemaRef, ForwardIVDecl, IVTy, OrigVarLoc); 14864 }; 14865 14866 // Iteration variable for the reversed induction variable (from n-1 downto 0): 14867 // Reuse the iteration variable created by checkOpenMPLoop. 14868 auto *ReversedIVDecl = cast<VarDecl>(IterationVarRef->getDecl()); 14869 ReversedIVDecl->setDeclName( 14870 &SemaRef.PP.getIdentifierTable().get(ReversedIVName)); 14871 14872 // For init-statement: 14873 // \code{.cpp} 14874 // auto .forward.iv = 0; 14875 // \endcode 14876 auto *Zero = IntegerLiteral::Create(Context, llvm::APInt::getZero(IVWidth), 14877 ForwardIVDecl->getType(), OrigVarLoc); 14878 SemaRef.AddInitializerToDecl(ForwardIVDecl, Zero, /*DirectInit=*/false); 14879 StmtResult Init = new (Context) 14880 DeclStmt(DeclGroupRef(ForwardIVDecl), OrigVarLocBegin, OrigVarLocEnd); 14881 if (!Init.isUsable()) 14882 return StmtError(); 14883 14884 // Forward iv cond-expression: 14885 // \code{.cpp} 14886 // .forward.iv < MakeNumIterations() 14887 // \endcode 14888 ExprResult Cond = 14889 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, 14890 MakeForwardRef(), MakeNumIterations()); 14891 if (!Cond.isUsable()) 14892 return StmtError(); 14893 14894 // Forward incr-statement: 14895 // \code{.c} 14896 // ++.forward.iv 14897 // \endcode 14898 ExprResult Incr = SemaRef.BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(), 14899 UO_PreInc, MakeForwardRef()); 14900 if (!Incr.isUsable()) 14901 return StmtError(); 14902 14903 // Reverse the forward-iv: 14904 // \code{.cpp} 14905 // auto .reversed.iv = MakeNumIterations() - 1 - .forward.iv 14906 // \endcode 14907 auto *One = IntegerLiteral::Create(Context, llvm::APInt(IVWidth, 1), IVTy, 14908 TransformLoc); 14909 ExprResult Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, 14910 MakeNumIterations(), One); 14911 if (!Minus.isUsable()) 14912 return StmtError(); 14913 Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, Minus.get(), 14914 MakeForwardRef()); 14915 if (!Minus.isUsable()) 14916 return StmtError(); 14917 StmtResult InitReversed = new (Context) DeclStmt( 14918 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd); 14919 if (!InitReversed.isUsable()) 14920 return StmtError(); 14921 SemaRef.AddInitializerToDecl(ReversedIVDecl, Minus.get(), 14922 /*DirectInit=*/false); 14923 14924 // The new loop body. 14925 SmallVector<Stmt *, 4> BodyStmts; 14926 BodyStmts.reserve(LoopHelper.Updates.size() + 2 + 14927 (isa<CXXForRangeStmt>(LoopStmt) ? 1 : 0)); 14928 BodyStmts.push_back(InitReversed.get()); 14929 llvm::append_range(BodyStmts, LoopHelper.Updates); 14930 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) 14931 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt()); 14932 BodyStmts.push_back(Body); 14933 auto *ReversedBody = 14934 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(), 14935 Body->getBeginLoc(), Body->getEndLoc()); 14936 14937 // Finally create the reversed For-statement. 14938 auto *ReversedFor = new (Context) 14939 ForStmt(Context, Init.get(), Cond.get(), nullptr, Incr.get(), 14940 ReversedBody, LoopHelper.Init->getBeginLoc(), 14941 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc()); 14942 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt, 14943 ReversedFor, 14944 buildPreInits(Context, PreInits)); 14945 } 14946 14947 StmtResult SemaOpenMP::ActOnOpenMPInterchangeDirective( 14948 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 14949 SourceLocation EndLoc) { 14950 ASTContext &Context = getASTContext(); 14951 DeclContext *CurContext = SemaRef.CurContext; 14952 Scope *CurScope = SemaRef.getCurScope(); 14953 14954 // Empty statement should only be possible if there already was an error. 14955 if (!AStmt) 14956 return StmtError(); 14957 14958 // interchange without permutation clause swaps two loops. 14959 const OMPPermutationClause *PermutationClause = 14960 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses); 14961 size_t NumLoops = PermutationClause ? PermutationClause->getNumLoops() : 2; 14962 14963 // Verify and diagnose loop nest. 14964 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops); 14965 Stmt *Body = nullptr; 14966 SmallVector<SmallVector<Stmt *, 0>, 2> OriginalInits; 14967 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops, 14968 LoopHelpers, Body, OriginalInits)) 14969 return StmtError(); 14970 14971 // Delay interchange to when template is completely instantiated. 14972 if (CurContext->isDependentContext()) 14973 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses, 14974 NumLoops, AStmt, nullptr, nullptr); 14975 14976 // An invalid expression in the permutation clause is set to nullptr in 14977 // ActOnOpenMPPermutationClause. 14978 if (PermutationClause && 14979 llvm::is_contained(PermutationClause->getArgsRefs(), nullptr)) 14980 return StmtError(); 14981 14982 assert(LoopHelpers.size() == NumLoops && 14983 "Expecting loop iteration space dimensionaly to match number of " 14984 "affected loops"); 14985 assert(OriginalInits.size() == NumLoops && 14986 "Expecting loop iteration space dimensionaly to match number of " 14987 "affected loops"); 14988 14989 // Decode the permutation clause. 14990 SmallVector<uint64_t, 2> Permutation; 14991 if (!PermutationClause) { 14992 Permutation = {1, 0}; 14993 } else { 14994 ArrayRef<Expr *> PermArgs = PermutationClause->getArgsRefs(); 14995 llvm::BitVector Flags(PermArgs.size()); 14996 for (Expr *PermArg : PermArgs) { 14997 std::optional<llvm::APSInt> PermCstExpr = 14998 PermArg->getIntegerConstantExpr(Context); 14999 if (!PermCstExpr) 15000 continue; 15001 uint64_t PermInt = PermCstExpr->getZExtValue(); 15002 assert(1 <= PermInt && PermInt <= NumLoops && 15003 "Must be a permutation; diagnostic emitted in " 15004 "ActOnOpenMPPermutationClause"); 15005 if (Flags[PermInt - 1]) { 15006 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc()); 15007 Diag(PermArg->getExprLoc(), 15008 diag::err_omp_interchange_permutation_value_repeated) 15009 << PermInt << ExprRange; 15010 continue; 15011 } 15012 Flags[PermInt - 1] = true; 15013 15014 Permutation.push_back(PermInt - 1); 15015 } 15016 15017 if (Permutation.size() != NumLoops) 15018 return StmtError(); 15019 } 15020 15021 // Nothing to transform with trivial permutation. 15022 if (NumLoops <= 1 || llvm::all_of(llvm::enumerate(Permutation), [](auto P) { 15023 auto [Idx, Arg] = P; 15024 return Idx == Arg; 15025 })) 15026 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses, 15027 NumLoops, AStmt, AStmt, nullptr); 15028 15029 // Find the affected loops. 15030 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr); 15031 collectLoopStmts(AStmt, LoopStmts); 15032 15033 // Collect pre-init statements on the order before the permuation. 15034 SmallVector<Stmt *> PreInits; 15035 for (auto I : llvm::seq<int>(NumLoops)) { 15036 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I]; 15037 15038 assert(LoopHelper.Counters.size() == 1 && 15039 "Single-dimensional loop iteration space expected"); 15040 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front()); 15041 15042 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString(); 15043 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I], 15044 PreInits); 15045 } 15046 15047 SmallVector<VarDecl *> PermutedIndVars(NumLoops); 15048 CaptureVars CopyTransformer(SemaRef); 15049 15050 // Create the permuted loops from the inside to the outside of the 15051 // interchanged loop nest. Body of the innermost new loop is the original 15052 // innermost body. 15053 Stmt *Inner = Body; 15054 for (auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) { 15055 // Get the original loop that belongs to this new position. 15056 uint64_t SourceIdx = Permutation[TargetIdx]; 15057 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx]; 15058 Stmt *SourceLoopStmt = LoopStmts[SourceIdx]; 15059 assert(SourceHelper.Counters.size() == 1 && 15060 "Single-dimensional loop iteration space expected"); 15061 auto *OrigCntVar = cast<DeclRefExpr>(SourceHelper.Counters.front()); 15062 15063 // Normalized loop counter variable: From 0 to n-1, always an integer type. 15064 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(SourceHelper.IterationVarRef); 15065 QualType IVTy = IterVarRef->getType(); 15066 assert(IVTy->isIntegerType() && 15067 "Expected the logical iteration counter to be an integer"); 15068 15069 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString(); 15070 SourceLocation OrigVarLoc = IterVarRef->getExprLoc(); 15071 15072 // Make a copy of the NumIterations expression for each use: By the AST 15073 // constraints, every expression object in a DeclContext must be unique. 15074 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() -> Expr * { 15075 return AssertSuccess( 15076 CopyTransformer.TransformExpr(SourceHelper.NumIterations)); 15077 }; 15078 15079 // Iteration variable for the permuted loop. Reuse the one from 15080 // checkOpenMPLoop which will also be used to update the original loop 15081 // variable. 15082 SmallString<64> PermutedCntName(".permuted_"); 15083 PermutedCntName.append({llvm::utostr(TargetIdx), ".iv.", OrigVarName}); 15084 auto *PermutedCntDecl = cast<VarDecl>(IterVarRef->getDecl()); 15085 PermutedCntDecl->setDeclName( 15086 &SemaRef.PP.getIdentifierTable().get(PermutedCntName)); 15087 PermutedIndVars[TargetIdx] = PermutedCntDecl; 15088 auto MakePermutedRef = [this, PermutedCntDecl, IVTy, OrigVarLoc]() { 15089 return buildDeclRefExpr(SemaRef, PermutedCntDecl, IVTy, OrigVarLoc); 15090 }; 15091 15092 // For init-statement: 15093 // \code 15094 // auto .permuted_{target}.iv = 0 15095 // \endcode 15096 ExprResult Zero = SemaRef.ActOnIntegerConstant(OrigVarLoc, 0); 15097 if (!Zero.isUsable()) 15098 return StmtError(); 15099 SemaRef.AddInitializerToDecl(PermutedCntDecl, Zero.get(), 15100 /*DirectInit=*/false); 15101 StmtResult InitStmt = new (Context) 15102 DeclStmt(DeclGroupRef(PermutedCntDecl), OrigCntVar->getBeginLoc(), 15103 OrigCntVar->getEndLoc()); 15104 if (!InitStmt.isUsable()) 15105 return StmtError(); 15106 15107 // For cond-expression: 15108 // \code 15109 // .permuted_{target}.iv < MakeNumIterations() 15110 // \endcode 15111 ExprResult CondExpr = 15112 SemaRef.BuildBinOp(CurScope, SourceHelper.Cond->getExprLoc(), BO_LT, 15113 MakePermutedRef(), MakeNumIterations()); 15114 if (!CondExpr.isUsable()) 15115 return StmtError(); 15116 15117 // For incr-statement: 15118 // \code 15119 // ++.tile.iv 15120 // \endcode 15121 ExprResult IncrStmt = SemaRef.BuildUnaryOp( 15122 CurScope, SourceHelper.Inc->getExprLoc(), UO_PreInc, MakePermutedRef()); 15123 if (!IncrStmt.isUsable()) 15124 return StmtError(); 15125 15126 SmallVector<Stmt *, 4> BodyParts(SourceHelper.Updates.begin(), 15127 SourceHelper.Updates.end()); 15128 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt)) 15129 BodyParts.push_back(SourceCXXFor->getLoopVarStmt()); 15130 BodyParts.push_back(Inner); 15131 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(), 15132 Inner->getBeginLoc(), Inner->getEndLoc()); 15133 Inner = new (Context) ForStmt( 15134 Context, InitStmt.get(), CondExpr.get(), nullptr, IncrStmt.get(), Inner, 15135 SourceHelper.Init->getBeginLoc(), SourceHelper.Init->getBeginLoc(), 15136 SourceHelper.Inc->getEndLoc()); 15137 } 15138 15139 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses, 15140 NumLoops, AStmt, Inner, 15141 buildPreInits(Context, PreInits)); 15142 } 15143 15144 OMPClause *SemaOpenMP::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, 15145 Expr *Expr, 15146 SourceLocation StartLoc, 15147 SourceLocation LParenLoc, 15148 SourceLocation EndLoc) { 15149 OMPClause *Res = nullptr; 15150 switch (Kind) { 15151 case OMPC_final: 15152 Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc); 15153 break; 15154 case OMPC_num_threads: 15155 Res = ActOnOpenMPNumThreadsClause(Expr, StartLoc, LParenLoc, EndLoc); 15156 break; 15157 case OMPC_safelen: 15158 Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc); 15159 break; 15160 case OMPC_simdlen: 15161 Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc); 15162 break; 15163 case OMPC_allocator: 15164 Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc); 15165 break; 15166 case OMPC_collapse: 15167 Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc); 15168 break; 15169 case OMPC_ordered: 15170 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr); 15171 break; 15172 case OMPC_priority: 15173 Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc); 15174 break; 15175 case OMPC_hint: 15176 Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc); 15177 break; 15178 case OMPC_depobj: 15179 Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc); 15180 break; 15181 case OMPC_detach: 15182 Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc); 15183 break; 15184 case OMPC_novariants: 15185 Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc); 15186 break; 15187 case OMPC_nocontext: 15188 Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc); 15189 break; 15190 case OMPC_filter: 15191 Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc); 15192 break; 15193 case OMPC_partial: 15194 Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc); 15195 break; 15196 case OMPC_message: 15197 Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc); 15198 break; 15199 case OMPC_align: 15200 Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc); 15201 break; 15202 case OMPC_ompx_dyn_cgroup_mem: 15203 Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc); 15204 break; 15205 case OMPC_holds: 15206 Res = ActOnOpenMPHoldsClause(Expr, StartLoc, LParenLoc, EndLoc); 15207 break; 15208 case OMPC_grainsize: 15209 case OMPC_num_tasks: 15210 case OMPC_device: 15211 case OMPC_if: 15212 case OMPC_default: 15213 case OMPC_proc_bind: 15214 case OMPC_schedule: 15215 case OMPC_private: 15216 case OMPC_firstprivate: 15217 case OMPC_lastprivate: 15218 case OMPC_shared: 15219 case OMPC_reduction: 15220 case OMPC_task_reduction: 15221 case OMPC_in_reduction: 15222 case OMPC_linear: 15223 case OMPC_aligned: 15224 case OMPC_copyin: 15225 case OMPC_copyprivate: 15226 case OMPC_nowait: 15227 case OMPC_untied: 15228 case OMPC_mergeable: 15229 case OMPC_threadprivate: 15230 case OMPC_sizes: 15231 case OMPC_allocate: 15232 case OMPC_flush: 15233 case OMPC_read: 15234 case OMPC_write: 15235 case OMPC_update: 15236 case OMPC_capture: 15237 case OMPC_compare: 15238 case OMPC_seq_cst: 15239 case OMPC_acq_rel: 15240 case OMPC_acquire: 15241 case OMPC_release: 15242 case OMPC_relaxed: 15243 case OMPC_depend: 15244 case OMPC_threads: 15245 case OMPC_simd: 15246 case OMPC_map: 15247 case OMPC_nogroup: 15248 case OMPC_dist_schedule: 15249 case OMPC_defaultmap: 15250 case OMPC_unknown: 15251 case OMPC_uniform: 15252 case OMPC_to: 15253 case OMPC_from: 15254 case OMPC_use_device_ptr: 15255 case OMPC_use_device_addr: 15256 case OMPC_is_device_ptr: 15257 case OMPC_unified_address: 15258 case OMPC_unified_shared_memory: 15259 case OMPC_reverse_offload: 15260 case OMPC_dynamic_allocators: 15261 case OMPC_atomic_default_mem_order: 15262 case OMPC_device_type: 15263 case OMPC_match: 15264 case OMPC_nontemporal: 15265 case OMPC_order: 15266 case OMPC_at: 15267 case OMPC_severity: 15268 case OMPC_destroy: 15269 case OMPC_inclusive: 15270 case OMPC_exclusive: 15271 case OMPC_uses_allocators: 15272 case OMPC_affinity: 15273 case OMPC_when: 15274 case OMPC_bind: 15275 case OMPC_num_teams: 15276 case OMPC_thread_limit: 15277 default: 15278 llvm_unreachable("Clause is not allowed."); 15279 } 15280 return Res; 15281 } 15282 15283 // An OpenMP directive such as 'target parallel' has two captured regions: 15284 // for the 'target' and 'parallel' respectively. This function returns 15285 // the region in which to capture expressions associated with a clause. 15286 // A return value of OMPD_unknown signifies that the expression should not 15287 // be captured. 15288 static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( 15289 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion, 15290 OpenMPDirectiveKind NameModifier = OMPD_unknown) { 15291 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) && 15292 "Invalid directive with CKind-clause"); 15293 15294 // Invalid modifier will be diagnosed separately, just return OMPD_unknown. 15295 if (NameModifier != OMPD_unknown && 15296 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion)) 15297 return OMPD_unknown; 15298 15299 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(DKind); 15300 15301 // [5.2:341:24-30] 15302 // If the clauses have expressions on them, such as for various clauses where 15303 // the argument of the clause is an expression, or lower-bound, length, or 15304 // stride expressions inside array sections (or subscript and stride 15305 // expressions in subscript-triplet for Fortran), or linear-step or alignment 15306 // expressions, the expressions are evaluated immediately before the construct 15307 // to which the clause has been split or duplicated per the above rules 15308 // (therefore inside of the outer leaf constructs). However, the expressions 15309 // inside the num_teams and thread_limit clauses are always evaluated before 15310 // the outermost leaf construct. 15311 15312 // Process special cases first. 15313 switch (CKind) { 15314 case OMPC_if: 15315 switch (DKind) { 15316 case OMPD_teams_loop: 15317 case OMPD_target_teams_loop: 15318 // For [target] teams loop, assume capture region is 'teams' so it's 15319 // available for codegen later to use if/when necessary. 15320 return OMPD_teams; 15321 case OMPD_target_update: 15322 case OMPD_target_enter_data: 15323 case OMPD_target_exit_data: 15324 return OMPD_task; 15325 default: 15326 break; 15327 } 15328 break; 15329 case OMPC_num_teams: 15330 case OMPC_thread_limit: 15331 case OMPC_ompx_dyn_cgroup_mem: 15332 if (Leafs[0] == OMPD_target) 15333 return OMPD_target; 15334 break; 15335 case OMPC_device: 15336 if (Leafs[0] == OMPD_target || 15337 llvm::is_contained({OMPD_dispatch, OMPD_target_update, 15338 OMPD_target_enter_data, OMPD_target_exit_data}, 15339 DKind)) 15340 return OMPD_task; 15341 break; 15342 case OMPC_novariants: 15343 case OMPC_nocontext: 15344 if (DKind == OMPD_dispatch) 15345 return OMPD_task; 15346 break; 15347 case OMPC_when: 15348 if (DKind == OMPD_metadirective) 15349 return OMPD_metadirective; 15350 break; 15351 case OMPC_filter: 15352 return OMPD_unknown; 15353 default: 15354 break; 15355 } 15356 15357 // If none of the special cases above applied, and DKind is a capturing 15358 // directive, find the innermost enclosing leaf construct that allows the 15359 // clause, and returns the corresponding capture region. 15360 15361 auto GetEnclosingRegion = [&](int EndIdx, OpenMPClauseKind Clause) { 15362 // Find the index in "Leafs" of the last leaf that allows the given 15363 // clause. The search will only include indexes [0, EndIdx). 15364 // EndIdx may be set to the index of the NameModifier, if present. 15365 int InnermostIdx = [&]() { 15366 for (int I = EndIdx - 1; I >= 0; --I) { 15367 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion)) 15368 return I; 15369 } 15370 return -1; 15371 }(); 15372 15373 // Find the nearest enclosing capture region. 15374 SmallVector<OpenMPDirectiveKind, 2> Regions; 15375 for (int I = InnermostIdx - 1; I >= 0; --I) { 15376 if (!isOpenMPCapturingDirective(Leafs[I])) 15377 continue; 15378 Regions.clear(); 15379 getOpenMPCaptureRegions(Regions, Leafs[I]); 15380 if (Regions[0] != OMPD_unknown) 15381 return Regions.back(); 15382 } 15383 return OMPD_unknown; 15384 }; 15385 15386 if (isOpenMPCapturingDirective(DKind)) { 15387 auto GetLeafIndex = [&](OpenMPDirectiveKind Dir) { 15388 for (int I = 0, E = Leafs.size(); I != E; ++I) { 15389 if (Leafs[I] == Dir) 15390 return I + 1; 15391 } 15392 return 0; 15393 }; 15394 15395 int End = NameModifier == OMPD_unknown ? Leafs.size() 15396 : GetLeafIndex(NameModifier); 15397 return GetEnclosingRegion(End, CKind); 15398 } 15399 15400 return OMPD_unknown; 15401 } 15402 15403 OMPClause *SemaOpenMP::ActOnOpenMPIfClause( 15404 OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc, 15405 SourceLocation LParenLoc, SourceLocation NameModifierLoc, 15406 SourceLocation ColonLoc, SourceLocation EndLoc) { 15407 Expr *ValExpr = Condition; 15408 Stmt *HelperValStmt = nullptr; 15409 OpenMPDirectiveKind CaptureRegion = OMPD_unknown; 15410 if (!Condition->isValueDependent() && !Condition->isTypeDependent() && 15411 !Condition->isInstantiationDependent() && 15412 !Condition->containsUnexpandedParameterPack()) { 15413 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition); 15414 if (Val.isInvalid()) 15415 return nullptr; 15416 15417 ValExpr = Val.get(); 15418 15419 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); 15420 CaptureRegion = getOpenMPCaptureRegionForClause( 15421 DKind, OMPC_if, getLangOpts().OpenMP, NameModifier); 15422 if (CaptureRegion != OMPD_unknown && 15423 !SemaRef.CurContext->isDependentContext()) { 15424 ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); 15425 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 15426 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); 15427 HelperValStmt = buildPreInits(getASTContext(), Captures); 15428 } 15429 } 15430 15431 return new (getASTContext()) 15432 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc, 15433 LParenLoc, NameModifierLoc, ColonLoc, EndLoc); 15434 } 15435 15436 OMPClause *SemaOpenMP::ActOnOpenMPFinalClause(Expr *Condition, 15437 SourceLocation StartLoc, 15438 SourceLocation LParenLoc, 15439 SourceLocation EndLoc) { 15440 Expr *ValExpr = Condition; 15441 Stmt *HelperValStmt = nullptr; 15442 OpenMPDirectiveKind CaptureRegion = OMPD_unknown; 15443 if (!Condition->isValueDependent() && !Condition->isTypeDependent() && 15444 !Condition->isInstantiationDependent() && 15445 !Condition->containsUnexpandedParameterPack()) { 15446 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition); 15447 if (Val.isInvalid()) 15448 return nullptr; 15449 15450 ValExpr = SemaRef.MakeFullExpr(Val.get()).get(); 15451 15452 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); 15453 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_final, 15454 getLangOpts().OpenMP); 15455 if (CaptureRegion != OMPD_unknown && 15456 !SemaRef.CurContext->isDependentContext()) { 15457 ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); 15458 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 15459 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); 15460 HelperValStmt = buildPreInits(getASTContext(), Captures); 15461 } 15462 } 15463 15464 return new (getASTContext()) OMPFinalClause( 15465 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc); 15466 } 15467 15468 ExprResult 15469 SemaOpenMP::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc, 15470 Expr *Op) { 15471 if (!Op) 15472 return ExprError(); 15473 15474 class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser { 15475 public: 15476 IntConvertDiagnoser() 15477 : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false, false, true) {} 15478 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, 15479 QualType T) override { 15480 return S.Diag(Loc, diag::err_omp_not_integral) << T; 15481 } 15482 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc, 15483 QualType T) override { 15484 return S.Diag(Loc, diag::err_omp_incomplete_type) << T; 15485 } 15486 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc, 15487 QualType T, 15488 QualType ConvTy) override { 15489 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy; 15490 } 15491 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv, 15492 QualType ConvTy) override { 15493 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here) 15494 << ConvTy->isEnumeralType() << ConvTy; 15495 } 15496 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc, 15497 QualType T) override { 15498 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T; 15499 } 15500 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv, 15501 QualType ConvTy) override { 15502 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here) 15503 << ConvTy->isEnumeralType() << ConvTy; 15504 } 15505 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType, 15506 QualType) override { 15507 llvm_unreachable("conversion functions are permitted"); 15508 } 15509 } ConvertDiagnoser; 15510 return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser); 15511 } 15512 15513 static bool 15514 isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind, 15515 bool StrictlyPositive, bool BuildCapture = false, 15516 OpenMPDirectiveKind DKind = OMPD_unknown, 15517 OpenMPDirectiveKind *CaptureRegion = nullptr, 15518 Stmt **HelperValStmt = nullptr) { 15519 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() && 15520 !ValExpr->isInstantiationDependent()) { 15521 SourceLocation Loc = ValExpr->getExprLoc(); 15522 ExprResult Value = 15523 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(Loc, ValExpr); 15524 if (Value.isInvalid()) 15525 return false; 15526 15527 ValExpr = Value.get(); 15528 // The expression must evaluate to a non-negative integer value. 15529 if (std::optional<llvm::APSInt> Result = 15530 ValExpr->getIntegerConstantExpr(SemaRef.Context)) { 15531 if (Result->isSigned() && 15532 !((!StrictlyPositive && Result->isNonNegative()) || 15533 (StrictlyPositive && Result->isStrictlyPositive()))) { 15534 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause) 15535 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0) 15536 << ValExpr->getSourceRange(); 15537 return false; 15538 } 15539 } 15540 if (!BuildCapture) 15541 return true; 15542 *CaptureRegion = 15543 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP); 15544 if (*CaptureRegion != OMPD_unknown && 15545 !SemaRef.CurContext->isDependentContext()) { 15546 ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); 15547 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 15548 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); 15549 *HelperValStmt = buildPreInits(SemaRef.Context, Captures); 15550 } 15551 } 15552 return true; 15553 } 15554 15555 OMPClause *SemaOpenMP::ActOnOpenMPNumThreadsClause(Expr *NumThreads, 15556 SourceLocation StartLoc, 15557 SourceLocation LParenLoc, 15558 SourceLocation EndLoc) { 15559 Expr *ValExpr = NumThreads; 15560 Stmt *HelperValStmt = nullptr; 15561 15562 // OpenMP [2.5, Restrictions] 15563 // The num_threads expression must evaluate to a positive integer value. 15564 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_threads, 15565 /*StrictlyPositive=*/true)) 15566 return nullptr; 15567 15568 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); 15569 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause( 15570 DKind, OMPC_num_threads, getLangOpts().OpenMP); 15571 if (CaptureRegion != OMPD_unknown && 15572 !SemaRef.CurContext->isDependentContext()) { 15573 ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); 15574 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 15575 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); 15576 HelperValStmt = buildPreInits(getASTContext(), Captures); 15577 } 15578 15579 return new (getASTContext()) OMPNumThreadsClause( 15580 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc); 15581 } 15582 15583 ExprResult SemaOpenMP::VerifyPositiveIntegerConstantInClause( 15584 Expr *E, OpenMPClauseKind CKind, bool StrictlyPositive, 15585 bool SuppressExprDiags) { 15586 if (!E) 15587 return ExprError(); 15588 if (E->isValueDependent() || E->isTypeDependent() || 15589 E->isInstantiationDependent() || E->containsUnexpandedParameterPack()) 15590 return E; 15591 15592 llvm::APSInt Result; 15593 ExprResult ICE; 15594 if (SuppressExprDiags) { 15595 // Use a custom diagnoser that suppresses 'note' diagnostics about the 15596 // expression. 15597 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser { 15598 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {} 15599 SemaBase::SemaDiagnosticBuilder 15600 diagnoseNotICE(Sema &S, SourceLocation Loc) override { 15601 llvm_unreachable("Diagnostic suppressed"); 15602 } 15603 } Diagnoser; 15604 ICE = SemaRef.VerifyIntegerConstantExpression(E, &Result, Diagnoser, 15605 Sema::AllowFold); 15606 } else { 15607 ICE = SemaRef.VerifyIntegerConstantExpression(E, &Result, 15608 /*FIXME*/ Sema::AllowFold); 15609 } 15610 if (ICE.isInvalid()) 15611 return ExprError(); 15612 15613 if ((StrictlyPositive && !Result.isStrictlyPositive()) || 15614 (!StrictlyPositive && !Result.isNonNegative())) { 15615 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause) 15616 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0) 15617 << E->getSourceRange(); 15618 return ExprError(); 15619 } 15620 if ((CKind == OMPC_aligned || CKind == OMPC_align || 15621 CKind == OMPC_allocate) && 15622 !Result.isPowerOf2()) { 15623 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two) 15624 << E->getSourceRange(); 15625 return ExprError(); 15626 } 15627 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1) 15628 DSAStack->setAssociatedLoops(Result.getExtValue()); 15629 else if (CKind == OMPC_ordered) 15630 DSAStack->setAssociatedLoops(Result.getExtValue()); 15631 return ICE; 15632 } 15633 15634 OMPClause *SemaOpenMP::ActOnOpenMPSafelenClause(Expr *Len, 15635 SourceLocation StartLoc, 15636 SourceLocation LParenLoc, 15637 SourceLocation EndLoc) { 15638 // OpenMP [2.8.1, simd construct, Description] 15639 // The parameter of the safelen clause must be a constant 15640 // positive integer expression. 15641 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen); 15642 if (Safelen.isInvalid()) 15643 return nullptr; 15644 return new (getASTContext()) 15645 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc); 15646 } 15647 15648 OMPClause *SemaOpenMP::ActOnOpenMPSimdlenClause(Expr *Len, 15649 SourceLocation StartLoc, 15650 SourceLocation LParenLoc, 15651 SourceLocation EndLoc) { 15652 // OpenMP [2.8.1, simd construct, Description] 15653 // The parameter of the simdlen clause must be a constant 15654 // positive integer expression. 15655 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen); 15656 if (Simdlen.isInvalid()) 15657 return nullptr; 15658 return new (getASTContext()) 15659 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc); 15660 } 15661 15662 /// Tries to find omp_allocator_handle_t type. 15663 static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc, 15664 DSAStackTy *Stack) { 15665 if (!Stack->getOMPAllocatorHandleT().isNull()) 15666 return true; 15667 15668 // Set the allocator handle type. 15669 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t"); 15670 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope()); 15671 if (!PT.getAsOpaquePtr() || PT.get().isNull()) { 15672 S.Diag(Loc, diag::err_omp_implied_type_not_found) 15673 << "omp_allocator_handle_t"; 15674 return false; 15675 } 15676 QualType AllocatorHandleEnumTy = PT.get(); 15677 AllocatorHandleEnumTy.addConst(); 15678 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy); 15679 15680 // Fill the predefined allocator map. 15681 bool ErrorFound = false; 15682 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) { 15683 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I); 15684 StringRef Allocator = 15685 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind); 15686 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator); 15687 auto *VD = dyn_cast_or_null<ValueDecl>( 15688 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName)); 15689 if (!VD) { 15690 ErrorFound = true; 15691 break; 15692 } 15693 QualType AllocatorType = 15694 VD->getType().getNonLValueExprType(S.getASTContext()); 15695 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc); 15696 if (!Res.isUsable()) { 15697 ErrorFound = true; 15698 break; 15699 } 15700 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy, 15701 AssignmentAction::Initializing, 15702 /*AllowExplicit=*/true); 15703 if (!Res.isUsable()) { 15704 ErrorFound = true; 15705 break; 15706 } 15707 Stack->setAllocator(AllocatorKind, Res.get()); 15708 } 15709 if (ErrorFound) { 15710 S.Diag(Loc, diag::err_omp_implied_type_not_found) 15711 << "omp_allocator_handle_t"; 15712 return false; 15713 } 15714 15715 return true; 15716 } 15717 15718 OMPClause *SemaOpenMP::ActOnOpenMPAllocatorClause(Expr *A, 15719 SourceLocation StartLoc, 15720 SourceLocation LParenLoc, 15721 SourceLocation EndLoc) { 15722 // OpenMP [2.11.3, allocate Directive, Description] 15723 // allocator is an expression of omp_allocator_handle_t type. 15724 if (!findOMPAllocatorHandleT(SemaRef, A->getExprLoc(), DSAStack)) 15725 return nullptr; 15726 15727 ExprResult Allocator = SemaRef.DefaultLvalueConversion(A); 15728 if (Allocator.isInvalid()) 15729 return nullptr; 15730 Allocator = SemaRef.PerformImplicitConversion( 15731 Allocator.get(), DSAStack->getOMPAllocatorHandleT(), 15732 AssignmentAction::Initializing, 15733 /*AllowExplicit=*/true); 15734 if (Allocator.isInvalid()) 15735 return nullptr; 15736 return new (getASTContext()) 15737 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc); 15738 } 15739 15740 OMPClause *SemaOpenMP::ActOnOpenMPCollapseClause(Expr *NumForLoops, 15741 SourceLocation StartLoc, 15742 SourceLocation LParenLoc, 15743 SourceLocation EndLoc) { 15744 // OpenMP [2.7.1, loop construct, Description] 15745 // OpenMP [2.8.1, simd construct, Description] 15746 // OpenMP [2.9.6, distribute construct, Description] 15747 // The parameter of the collapse clause must be a constant 15748 // positive integer expression. 15749 ExprResult NumForLoopsResult = 15750 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse); 15751 if (NumForLoopsResult.isInvalid()) 15752 return nullptr; 15753 return new (getASTContext()) 15754 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc); 15755 } 15756 15757 OMPClause *SemaOpenMP::ActOnOpenMPOrderedClause(SourceLocation StartLoc, 15758 SourceLocation EndLoc, 15759 SourceLocation LParenLoc, 15760 Expr *NumForLoops) { 15761 // OpenMP [2.7.1, loop construct, Description] 15762 // OpenMP [2.8.1, simd construct, Description] 15763 // OpenMP [2.9.6, distribute construct, Description] 15764 // The parameter of the ordered clause must be a constant 15765 // positive integer expression if any. 15766 if (NumForLoops && LParenLoc.isValid()) { 15767 ExprResult NumForLoopsResult = 15768 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered); 15769 if (NumForLoopsResult.isInvalid()) 15770 return nullptr; 15771 NumForLoops = NumForLoopsResult.get(); 15772 } else { 15773 NumForLoops = nullptr; 15774 } 15775 auto *Clause = 15776 OMPOrderedClause::Create(getASTContext(), NumForLoops, 15777 NumForLoops ? DSAStack->getAssociatedLoops() : 0, 15778 StartLoc, LParenLoc, EndLoc); 15779 DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause); 15780 return Clause; 15781 } 15782 15783 OMPClause *SemaOpenMP::ActOnOpenMPSimpleClause( 15784 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, 15785 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { 15786 OMPClause *Res = nullptr; 15787 switch (Kind) { 15788 case OMPC_default: 15789 Res = ActOnOpenMPDefaultClause(static_cast<DefaultKind>(Argument), 15790 ArgumentLoc, StartLoc, LParenLoc, EndLoc); 15791 break; 15792 case OMPC_proc_bind: 15793 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument), 15794 ArgumentLoc, StartLoc, LParenLoc, EndLoc); 15795 break; 15796 case OMPC_atomic_default_mem_order: 15797 Res = ActOnOpenMPAtomicDefaultMemOrderClause( 15798 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument), 15799 ArgumentLoc, StartLoc, LParenLoc, EndLoc); 15800 break; 15801 case OMPC_fail: 15802 Res = ActOnOpenMPFailClause(static_cast<OpenMPClauseKind>(Argument), 15803 ArgumentLoc, StartLoc, LParenLoc, EndLoc); 15804 break; 15805 case OMPC_update: 15806 Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument), 15807 ArgumentLoc, StartLoc, LParenLoc, EndLoc); 15808 break; 15809 case OMPC_bind: 15810 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument), 15811 ArgumentLoc, StartLoc, LParenLoc, EndLoc); 15812 break; 15813 case OMPC_at: 15814 Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument), 15815 ArgumentLoc, StartLoc, LParenLoc, EndLoc); 15816 break; 15817 case OMPC_severity: 15818 Res = ActOnOpenMPSeverityClause( 15819 static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc, 15820 LParenLoc, EndLoc); 15821 break; 15822 case OMPC_if: 15823 case OMPC_final: 15824 case OMPC_num_threads: 15825 case OMPC_safelen: 15826 case OMPC_simdlen: 15827 case OMPC_sizes: 15828 case OMPC_allocator: 15829 case OMPC_collapse: 15830 case OMPC_schedule: 15831 case OMPC_private: 15832 case OMPC_firstprivate: 15833 case OMPC_lastprivate: 15834 case OMPC_shared: 15835 case OMPC_reduction: 15836 case OMPC_task_reduction: 15837 case OMPC_in_reduction: 15838 case OMPC_linear: 15839 case OMPC_aligned: 15840 case OMPC_copyin: 15841 case OMPC_copyprivate: 15842 case OMPC_ordered: 15843 case OMPC_nowait: 15844 case OMPC_untied: 15845 case OMPC_mergeable: 15846 case OMPC_threadprivate: 15847 case OMPC_allocate: 15848 case OMPC_flush: 15849 case OMPC_depobj: 15850 case OMPC_read: 15851 case OMPC_write: 15852 case OMPC_capture: 15853 case OMPC_compare: 15854 case OMPC_seq_cst: 15855 case OMPC_acq_rel: 15856 case OMPC_acquire: 15857 case OMPC_release: 15858 case OMPC_relaxed: 15859 case OMPC_depend: 15860 case OMPC_device: 15861 case OMPC_threads: 15862 case OMPC_simd: 15863 case OMPC_map: 15864 case OMPC_num_teams: 15865 case OMPC_thread_limit: 15866 case OMPC_priority: 15867 case OMPC_grainsize: 15868 case OMPC_nogroup: 15869 case OMPC_num_tasks: 15870 case OMPC_hint: 15871 case OMPC_dist_schedule: 15872 case OMPC_defaultmap: 15873 case OMPC_unknown: 15874 case OMPC_uniform: 15875 case OMPC_to: 15876 case OMPC_from: 15877 case OMPC_use_device_ptr: 15878 case OMPC_use_device_addr: 15879 case OMPC_is_device_ptr: 15880 case OMPC_has_device_addr: 15881 case OMPC_unified_address: 15882 case OMPC_unified_shared_memory: 15883 case OMPC_reverse_offload: 15884 case OMPC_dynamic_allocators: 15885 case OMPC_device_type: 15886 case OMPC_match: 15887 case OMPC_nontemporal: 15888 case OMPC_destroy: 15889 case OMPC_novariants: 15890 case OMPC_nocontext: 15891 case OMPC_detach: 15892 case OMPC_inclusive: 15893 case OMPC_exclusive: 15894 case OMPC_uses_allocators: 15895 case OMPC_affinity: 15896 case OMPC_when: 15897 case OMPC_message: 15898 default: 15899 llvm_unreachable("Clause is not allowed."); 15900 } 15901 return Res; 15902 } 15903 15904 static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First, 15905 unsigned Last, 15906 ArrayRef<unsigned> Exclude = {}) { 15907 SmallString<256> Buffer; 15908 llvm::raw_svector_ostream Out(Buffer); 15909 unsigned Skipped = Exclude.size(); 15910 for (unsigned I = First; I < Last; ++I) { 15911 if (llvm::is_contained(Exclude, I)) { 15912 --Skipped; 15913 continue; 15914 } 15915 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'"; 15916 if (I + Skipped + 2 == Last) 15917 Out << " or "; 15918 else if (I + Skipped + 1 != Last) 15919 Out << ", "; 15920 } 15921 return std::string(Out.str()); 15922 } 15923 15924 OMPClause *SemaOpenMP::ActOnOpenMPDefaultClause(DefaultKind Kind, 15925 SourceLocation KindKwLoc, 15926 SourceLocation StartLoc, 15927 SourceLocation LParenLoc, 15928 SourceLocation EndLoc) { 15929 if (Kind == OMP_DEFAULT_unknown) { 15930 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) 15931 << getListOfPossibleValues(OMPC_default, /*First=*/0, 15932 /*Last=*/unsigned(OMP_DEFAULT_unknown)) 15933 << getOpenMPClauseName(OMPC_default); 15934 return nullptr; 15935 } 15936 15937 switch (Kind) { 15938 case OMP_DEFAULT_none: 15939 DSAStack->setDefaultDSANone(KindKwLoc); 15940 break; 15941 case OMP_DEFAULT_shared: 15942 DSAStack->setDefaultDSAShared(KindKwLoc); 15943 break; 15944 case OMP_DEFAULT_firstprivate: 15945 DSAStack->setDefaultDSAFirstPrivate(KindKwLoc); 15946 break; 15947 case OMP_DEFAULT_private: 15948 DSAStack->setDefaultDSAPrivate(KindKwLoc); 15949 break; 15950 default: 15951 llvm_unreachable("DSA unexpected in OpenMP default clause"); 15952 } 15953 15954 return new (getASTContext()) 15955 OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc); 15956 } 15957 15958 OMPClause *SemaOpenMP::ActOnOpenMPProcBindClause(ProcBindKind Kind, 15959 SourceLocation KindKwLoc, 15960 SourceLocation StartLoc, 15961 SourceLocation LParenLoc, 15962 SourceLocation EndLoc) { 15963 if (Kind == OMP_PROC_BIND_unknown) { 15964 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) 15965 << getListOfPossibleValues(OMPC_proc_bind, 15966 /*First=*/unsigned(OMP_PROC_BIND_master), 15967 /*Last=*/ 15968 unsigned(getLangOpts().OpenMP > 50 15969 ? OMP_PROC_BIND_primary 15970 : OMP_PROC_BIND_spread) + 15971 1) 15972 << getOpenMPClauseName(OMPC_proc_bind); 15973 return nullptr; 15974 } 15975 if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51) 15976 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) 15977 << getListOfPossibleValues(OMPC_proc_bind, 15978 /*First=*/unsigned(OMP_PROC_BIND_master), 15979 /*Last=*/ 15980 unsigned(OMP_PROC_BIND_spread) + 1) 15981 << getOpenMPClauseName(OMPC_proc_bind); 15982 return new (getASTContext()) 15983 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc); 15984 } 15985 15986 OMPClause *SemaOpenMP::ActOnOpenMPAtomicDefaultMemOrderClause( 15987 OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindKwLoc, 15988 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { 15989 if (Kind == OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown) { 15990 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) 15991 << getListOfPossibleValues( 15992 OMPC_atomic_default_mem_order, /*First=*/0, 15993 /*Last=*/OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown) 15994 << getOpenMPClauseName(OMPC_atomic_default_mem_order); 15995 return nullptr; 15996 } 15997 return new (getASTContext()) OMPAtomicDefaultMemOrderClause( 15998 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc); 15999 } 16000 16001 OMPClause *SemaOpenMP::ActOnOpenMPAtClause(OpenMPAtClauseKind Kind, 16002 SourceLocation KindKwLoc, 16003 SourceLocation StartLoc, 16004 SourceLocation LParenLoc, 16005 SourceLocation EndLoc) { 16006 if (Kind == OMPC_AT_unknown) { 16007 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) 16008 << getListOfPossibleValues(OMPC_at, /*First=*/0, 16009 /*Last=*/OMPC_AT_unknown) 16010 << getOpenMPClauseName(OMPC_at); 16011 return nullptr; 16012 } 16013 return new (getASTContext()) 16014 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc); 16015 } 16016 16017 OMPClause *SemaOpenMP::ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind, 16018 SourceLocation KindKwLoc, 16019 SourceLocation StartLoc, 16020 SourceLocation LParenLoc, 16021 SourceLocation EndLoc) { 16022 if (Kind == OMPC_SEVERITY_unknown) { 16023 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) 16024 << getListOfPossibleValues(OMPC_severity, /*First=*/0, 16025 /*Last=*/OMPC_SEVERITY_unknown) 16026 << getOpenMPClauseName(OMPC_severity); 16027 return nullptr; 16028 } 16029 return new (getASTContext()) 16030 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc); 16031 } 16032 16033 OMPClause *SemaOpenMP::ActOnOpenMPMessageClause(Expr *ME, 16034 SourceLocation StartLoc, 16035 SourceLocation LParenLoc, 16036 SourceLocation EndLoc) { 16037 assert(ME && "NULL expr in Message clause"); 16038 if (!isa<StringLiteral>(ME)) { 16039 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string) 16040 << getOpenMPClauseName(OMPC_message); 16041 return nullptr; 16042 } 16043 return new (getASTContext()) 16044 OMPMessageClause(ME, StartLoc, LParenLoc, EndLoc); 16045 } 16046 16047 OMPClause *SemaOpenMP::ActOnOpenMPOrderClause( 16048 OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind, 16049 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, 16050 SourceLocation KindLoc, SourceLocation EndLoc) { 16051 if (Kind != OMPC_ORDER_concurrent || 16052 (getLangOpts().OpenMP < 51 && MLoc.isValid())) { 16053 // Kind should be concurrent, 16054 // Modifiers introduced in OpenMP 5.1 16055 static_assert(OMPC_ORDER_unknown > 0, 16056 "OMPC_ORDER_unknown not greater than 0"); 16057 16058 Diag(KindLoc, diag::err_omp_unexpected_clause_value) 16059 << getListOfPossibleValues(OMPC_order, 16060 /*First=*/0, 16061 /*Last=*/OMPC_ORDER_unknown) 16062 << getOpenMPClauseName(OMPC_order); 16063 return nullptr; 16064 } 16065 if (getLangOpts().OpenMP >= 51) { 16066 if (Modifier == OMPC_ORDER_MODIFIER_unknown && MLoc.isValid()) { 16067 Diag(MLoc, diag::err_omp_unexpected_clause_value) 16068 << getListOfPossibleValues(OMPC_order, 16069 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1, 16070 /*Last=*/OMPC_ORDER_MODIFIER_last) 16071 << getOpenMPClauseName(OMPC_order); 16072 } else { 16073 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true); 16074 if (DSAStack->getCurScope()) { 16075 // mark the current scope with 'order' flag 16076 unsigned existingFlags = DSAStack->getCurScope()->getFlags(); 16077 DSAStack->getCurScope()->setFlags(existingFlags | 16078 Scope::OpenMPOrderClauseScope); 16079 } 16080 } 16081 } 16082 return new (getASTContext()) OMPOrderClause( 16083 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc); 16084 } 16085 16086 OMPClause *SemaOpenMP::ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind, 16087 SourceLocation KindKwLoc, 16088 SourceLocation StartLoc, 16089 SourceLocation LParenLoc, 16090 SourceLocation EndLoc) { 16091 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source || 16092 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) { 16093 SmallVector<unsigned> Except = { 16094 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj, 16095 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory}; 16096 if (getLangOpts().OpenMP < 51) 16097 Except.push_back(OMPC_DEPEND_inoutset); 16098 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) 16099 << getListOfPossibleValues(OMPC_depend, /*First=*/0, 16100 /*Last=*/OMPC_DEPEND_unknown, Except) 16101 << getOpenMPClauseName(OMPC_update); 16102 return nullptr; 16103 } 16104 return OMPUpdateClause::Create(getASTContext(), StartLoc, LParenLoc, 16105 KindKwLoc, Kind, EndLoc); 16106 } 16107 16108 OMPClause *SemaOpenMP::ActOnOpenMPSizesClause(ArrayRef<Expr *> SizeExprs, 16109 SourceLocation StartLoc, 16110 SourceLocation LParenLoc, 16111 SourceLocation EndLoc) { 16112 SmallVector<Expr *> SanitizedSizeExprs(SizeExprs); 16113 16114 for (Expr *&SizeExpr : SanitizedSizeExprs) { 16115 // Skip if already sanitized, e.g. during a partial template instantiation. 16116 if (!SizeExpr) 16117 continue; 16118 16119 bool IsValid = isNonNegativeIntegerValue(SizeExpr, SemaRef, OMPC_sizes, 16120 /*StrictlyPositive=*/true); 16121 16122 // isNonNegativeIntegerValue returns true for non-integral types (but still 16123 // emits error diagnostic), so check for the expected type explicitly. 16124 QualType SizeTy = SizeExpr->getType(); 16125 if (!SizeTy->isIntegerType()) 16126 IsValid = false; 16127 16128 // Handling in templates is tricky. There are four possibilities to 16129 // consider: 16130 // 16131 // 1a. The expression is valid and we are in a instantiated template or not 16132 // in a template: 16133 // Pass valid expression to be further analysed later in Sema. 16134 // 1b. The expression is valid and we are in a template (including partial 16135 // instantiation): 16136 // isNonNegativeIntegerValue skipped any checks so there is no 16137 // guarantee it will be correct after instantiation. 16138 // ActOnOpenMPSizesClause will be called again at instantiation when 16139 // it is not in a dependent context anymore. This may cause warnings 16140 // to be emitted multiple times. 16141 // 2a. The expression is invalid and we are in an instantiated template or 16142 // not in a template: 16143 // Invalidate the expression with a clearly wrong value (nullptr) so 16144 // later in Sema we do not have to do the same validity analysis again 16145 // or crash from unexpected data. Error diagnostics have already been 16146 // emitted. 16147 // 2b. The expression is invalid and we are in a template (including partial 16148 // instantiation): 16149 // Pass the invalid expression as-is, template instantiation may 16150 // replace unexpected types/values with valid ones. The directives 16151 // with this clause must not try to use these expressions in dependent 16152 // contexts, but delay analysis until full instantiation. 16153 if (!SizeExpr->isInstantiationDependent() && !IsValid) 16154 SizeExpr = nullptr; 16155 } 16156 16157 return OMPSizesClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc, 16158 SanitizedSizeExprs); 16159 } 16160 16161 OMPClause *SemaOpenMP::ActOnOpenMPPermutationClause(ArrayRef<Expr *> PermExprs, 16162 SourceLocation StartLoc, 16163 SourceLocation LParenLoc, 16164 SourceLocation EndLoc) { 16165 size_t NumLoops = PermExprs.size(); 16166 SmallVector<Expr *> SanitizedPermExprs; 16167 llvm::append_range(SanitizedPermExprs, PermExprs); 16168 16169 for (Expr *&PermExpr : SanitizedPermExprs) { 16170 // Skip if template-dependent or already sanitized, e.g. during a partial 16171 // template instantiation. 16172 if (!PermExpr || PermExpr->isInstantiationDependent()) 16173 continue; 16174 16175 llvm::APSInt PermVal; 16176 ExprResult PermEvalExpr = SemaRef.VerifyIntegerConstantExpression( 16177 PermExpr, &PermVal, Sema::AllowFold); 16178 bool IsValid = PermEvalExpr.isUsable(); 16179 if (IsValid) 16180 PermExpr = PermEvalExpr.get(); 16181 16182 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) { 16183 SourceRange ExprRange(PermEvalExpr.get()->getBeginLoc(), 16184 PermEvalExpr.get()->getEndLoc()); 16185 Diag(PermEvalExpr.get()->getExprLoc(), 16186 diag::err_omp_interchange_permutation_value_range) 16187 << NumLoops << ExprRange; 16188 IsValid = false; 16189 } 16190 16191 if (!PermExpr->isInstantiationDependent() && !IsValid) 16192 PermExpr = nullptr; 16193 } 16194 16195 return OMPPermutationClause::Create(getASTContext(), StartLoc, LParenLoc, 16196 EndLoc, SanitizedPermExprs); 16197 } 16198 16199 OMPClause *SemaOpenMP::ActOnOpenMPFullClause(SourceLocation StartLoc, 16200 SourceLocation EndLoc) { 16201 return OMPFullClause::Create(getASTContext(), StartLoc, EndLoc); 16202 } 16203 16204 OMPClause *SemaOpenMP::ActOnOpenMPPartialClause(Expr *FactorExpr, 16205 SourceLocation StartLoc, 16206 SourceLocation LParenLoc, 16207 SourceLocation EndLoc) { 16208 if (FactorExpr) { 16209 // If an argument is specified, it must be a constant (or an unevaluated 16210 // template expression). 16211 ExprResult FactorResult = VerifyPositiveIntegerConstantInClause( 16212 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true); 16213 if (FactorResult.isInvalid()) 16214 return nullptr; 16215 FactorExpr = FactorResult.get(); 16216 } 16217 16218 return OMPPartialClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc, 16219 FactorExpr); 16220 } 16221 16222 OMPClause *SemaOpenMP::ActOnOpenMPAlignClause(Expr *A, SourceLocation StartLoc, 16223 SourceLocation LParenLoc, 16224 SourceLocation EndLoc) { 16225 ExprResult AlignVal; 16226 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align); 16227 if (AlignVal.isInvalid()) 16228 return nullptr; 16229 return OMPAlignClause::Create(getASTContext(), AlignVal.get(), StartLoc, 16230 LParenLoc, EndLoc); 16231 } 16232 16233 OMPClause *SemaOpenMP::ActOnOpenMPSingleExprWithArgClause( 16234 OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr, 16235 SourceLocation StartLoc, SourceLocation LParenLoc, 16236 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc, 16237 SourceLocation EndLoc) { 16238 OMPClause *Res = nullptr; 16239 switch (Kind) { 16240 case OMPC_schedule: 16241 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements }; 16242 assert(Argument.size() == NumberOfElements && 16243 ArgumentLoc.size() == NumberOfElements); 16244 Res = ActOnOpenMPScheduleClause( 16245 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]), 16246 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]), 16247 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr, 16248 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2], 16249 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc); 16250 break; 16251 case OMPC_if: 16252 assert(Argument.size() == 1 && ArgumentLoc.size() == 1); 16253 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()), 16254 Expr, StartLoc, LParenLoc, ArgumentLoc.back(), 16255 DelimLoc, EndLoc); 16256 break; 16257 case OMPC_dist_schedule: 16258 Res = ActOnOpenMPDistScheduleClause( 16259 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr, 16260 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc); 16261 break; 16262 case OMPC_defaultmap: 16263 enum { Modifier, DefaultmapKind }; 16264 Res = ActOnOpenMPDefaultmapClause( 16265 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]), 16266 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]), 16267 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind], 16268 EndLoc); 16269 break; 16270 case OMPC_order: 16271 enum { OrderModifier, OrderKind }; 16272 Res = ActOnOpenMPOrderClause( 16273 static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]), 16274 static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc, 16275 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc); 16276 break; 16277 case OMPC_device: 16278 assert(Argument.size() == 1 && ArgumentLoc.size() == 1); 16279 Res = ActOnOpenMPDeviceClause( 16280 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr, 16281 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc); 16282 break; 16283 case OMPC_grainsize: 16284 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 && 16285 "Modifier for grainsize clause and its location are expected."); 16286 Res = ActOnOpenMPGrainsizeClause( 16287 static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr, 16288 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc); 16289 break; 16290 case OMPC_num_tasks: 16291 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 && 16292 "Modifier for num_tasks clause and its location are expected."); 16293 Res = ActOnOpenMPNumTasksClause( 16294 static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr, 16295 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc); 16296 break; 16297 case OMPC_final: 16298 case OMPC_num_threads: 16299 case OMPC_safelen: 16300 case OMPC_simdlen: 16301 case OMPC_sizes: 16302 case OMPC_allocator: 16303 case OMPC_collapse: 16304 case OMPC_default: 16305 case OMPC_proc_bind: 16306 case OMPC_private: 16307 case OMPC_firstprivate: 16308 case OMPC_lastprivate: 16309 case OMPC_shared: 16310 case OMPC_reduction: 16311 case OMPC_task_reduction: 16312 case OMPC_in_reduction: 16313 case OMPC_linear: 16314 case OMPC_aligned: 16315 case OMPC_copyin: 16316 case OMPC_copyprivate: 16317 case OMPC_ordered: 16318 case OMPC_nowait: 16319 case OMPC_untied: 16320 case OMPC_mergeable: 16321 case OMPC_threadprivate: 16322 case OMPC_allocate: 16323 case OMPC_flush: 16324 case OMPC_depobj: 16325 case OMPC_read: 16326 case OMPC_write: 16327 case OMPC_update: 16328 case OMPC_capture: 16329 case OMPC_compare: 16330 case OMPC_seq_cst: 16331 case OMPC_acq_rel: 16332 case OMPC_acquire: 16333 case OMPC_release: 16334 case OMPC_relaxed: 16335 case OMPC_depend: 16336 case OMPC_threads: 16337 case OMPC_simd: 16338 case OMPC_map: 16339 case OMPC_num_teams: 16340 case OMPC_thread_limit: 16341 case OMPC_priority: 16342 case OMPC_nogroup: 16343 case OMPC_hint: 16344 case OMPC_unknown: 16345 case OMPC_uniform: 16346 case OMPC_to: 16347 case OMPC_from: 16348 case OMPC_use_device_ptr: 16349 case OMPC_use_device_addr: 16350 case OMPC_is_device_ptr: 16351 case OMPC_has_device_addr: 16352 case OMPC_unified_address: 16353 case OMPC_unified_shared_memory: 16354 case OMPC_reverse_offload: 16355 case OMPC_dynamic_allocators: 16356 case OMPC_atomic_default_mem_order: 16357 case OMPC_device_type: 16358 case OMPC_match: 16359 case OMPC_nontemporal: 16360 case OMPC_at: 16361 case OMPC_severity: 16362 case OMPC_message: 16363 case OMPC_destroy: 16364 case OMPC_novariants: 16365 case OMPC_nocontext: 16366 case OMPC_detach: 16367 case OMPC_inclusive: 16368 case OMPC_exclusive: 16369 case OMPC_uses_allocators: 16370 case OMPC_affinity: 16371 case OMPC_when: 16372 case OMPC_bind: 16373 default: 16374 llvm_unreachable("Clause is not allowed."); 16375 } 16376 return Res; 16377 } 16378 16379 static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1, 16380 OpenMPScheduleClauseModifier M2, 16381 SourceLocation M1Loc, SourceLocation M2Loc) { 16382 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) { 16383 SmallVector<unsigned, 2> Excluded; 16384 if (M2 != OMPC_SCHEDULE_MODIFIER_unknown) 16385 Excluded.push_back(M2); 16386 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) 16387 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic); 16388 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic) 16389 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic); 16390 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value) 16391 << getListOfPossibleValues(OMPC_schedule, 16392 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1, 16393 /*Last=*/OMPC_SCHEDULE_MODIFIER_last, 16394 Excluded) 16395 << getOpenMPClauseName(OMPC_schedule); 16396 return true; 16397 } 16398 return false; 16399 } 16400 16401 OMPClause *SemaOpenMP::ActOnOpenMPScheduleClause( 16402 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, 16403 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, 16404 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc, 16405 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) { 16406 if (checkScheduleModifiers(SemaRef, M1, M2, M1Loc, M2Loc) || 16407 checkScheduleModifiers(SemaRef, M2, M1, M2Loc, M1Loc)) 16408 return nullptr; 16409 // OpenMP, 2.7.1, Loop Construct, Restrictions 16410 // Either the monotonic modifier or the nonmonotonic modifier can be specified 16411 // but not both. 16412 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) || 16413 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic && 16414 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) || 16415 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic && 16416 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) { 16417 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier) 16418 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2) 16419 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1); 16420 return nullptr; 16421 } 16422 if (Kind == OMPC_SCHEDULE_unknown) { 16423 std::string Values; 16424 if (M1Loc.isInvalid() && M2Loc.isInvalid()) { 16425 unsigned Exclude[] = {OMPC_SCHEDULE_unknown}; 16426 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0, 16427 /*Last=*/OMPC_SCHEDULE_MODIFIER_last, 16428 Exclude); 16429 } else { 16430 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0, 16431 /*Last=*/OMPC_SCHEDULE_unknown); 16432 } 16433 Diag(KindLoc, diag::err_omp_unexpected_clause_value) 16434 << Values << getOpenMPClauseName(OMPC_schedule); 16435 return nullptr; 16436 } 16437 // OpenMP, 2.7.1, Loop Construct, Restrictions 16438 // The nonmonotonic modifier can only be specified with schedule(dynamic) or 16439 // schedule(guided). 16440 // OpenMP 5.0 does not have this restriction. 16441 if (getLangOpts().OpenMP < 50 && 16442 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic || 16443 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) && 16444 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) { 16445 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc, 16446 diag::err_omp_schedule_nonmonotonic_static); 16447 return nullptr; 16448 } 16449 Expr *ValExpr = ChunkSize; 16450 Stmt *HelperValStmt = nullptr; 16451 if (ChunkSize) { 16452 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() && 16453 !ChunkSize->isInstantiationDependent() && 16454 !ChunkSize->containsUnexpandedParameterPack()) { 16455 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc(); 16456 ExprResult Val = 16457 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize); 16458 if (Val.isInvalid()) 16459 return nullptr; 16460 16461 ValExpr = Val.get(); 16462 16463 // OpenMP [2.7.1, Restrictions] 16464 // chunk_size must be a loop invariant integer expression with a positive 16465 // value. 16466 if (std::optional<llvm::APSInt> Result = 16467 ValExpr->getIntegerConstantExpr(getASTContext())) { 16468 if (Result->isSigned() && !Result->isStrictlyPositive()) { 16469 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause) 16470 << "schedule" << 1 << ChunkSize->getSourceRange(); 16471 return nullptr; 16472 } 16473 } else if (getOpenMPCaptureRegionForClause( 16474 DSAStack->getCurrentDirective(), OMPC_schedule, 16475 getLangOpts().OpenMP) != OMPD_unknown && 16476 !SemaRef.CurContext->isDependentContext()) { 16477 ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); 16478 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 16479 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); 16480 HelperValStmt = buildPreInits(getASTContext(), Captures); 16481 } 16482 } 16483 } 16484 16485 return new (getASTContext()) 16486 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind, 16487 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc); 16488 } 16489 16490 OMPClause *SemaOpenMP::ActOnOpenMPClause(OpenMPClauseKind Kind, 16491 SourceLocation StartLoc, 16492 SourceLocation EndLoc) { 16493 OMPClause *Res = nullptr; 16494 switch (Kind) { 16495 case OMPC_ordered: 16496 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc); 16497 break; 16498 case OMPC_nowait: 16499 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc); 16500 break; 16501 case OMPC_untied: 16502 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc); 16503 break; 16504 case OMPC_mergeable: 16505 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc); 16506 break; 16507 case OMPC_read: 16508 Res = ActOnOpenMPReadClause(StartLoc, EndLoc); 16509 break; 16510 case OMPC_write: 16511 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc); 16512 break; 16513 case OMPC_update: 16514 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc); 16515 break; 16516 case OMPC_capture: 16517 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc); 16518 break; 16519 case OMPC_compare: 16520 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc); 16521 break; 16522 case OMPC_fail: 16523 Res = ActOnOpenMPFailClause(StartLoc, EndLoc); 16524 break; 16525 case OMPC_seq_cst: 16526 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc); 16527 break; 16528 case OMPC_acq_rel: 16529 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc); 16530 break; 16531 case OMPC_acquire: 16532 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc); 16533 break; 16534 case OMPC_release: 16535 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc); 16536 break; 16537 case OMPC_relaxed: 16538 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc); 16539 break; 16540 case OMPC_weak: 16541 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc); 16542 break; 16543 case OMPC_threads: 16544 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc); 16545 break; 16546 case OMPC_simd: 16547 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc); 16548 break; 16549 case OMPC_nogroup: 16550 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc); 16551 break; 16552 case OMPC_unified_address: 16553 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc); 16554 break; 16555 case OMPC_unified_shared_memory: 16556 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc); 16557 break; 16558 case OMPC_reverse_offload: 16559 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc); 16560 break; 16561 case OMPC_dynamic_allocators: 16562 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc); 16563 break; 16564 case OMPC_destroy: 16565 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc, 16566 /*LParenLoc=*/SourceLocation(), 16567 /*VarLoc=*/SourceLocation(), EndLoc); 16568 break; 16569 case OMPC_full: 16570 Res = ActOnOpenMPFullClause(StartLoc, EndLoc); 16571 break; 16572 case OMPC_partial: 16573 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc); 16574 break; 16575 case OMPC_ompx_bare: 16576 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc); 16577 break; 16578 case OMPC_if: 16579 case OMPC_final: 16580 case OMPC_num_threads: 16581 case OMPC_safelen: 16582 case OMPC_simdlen: 16583 case OMPC_sizes: 16584 case OMPC_allocator: 16585 case OMPC_collapse: 16586 case OMPC_schedule: 16587 case OMPC_private: 16588 case OMPC_firstprivate: 16589 case OMPC_lastprivate: 16590 case OMPC_shared: 16591 case OMPC_reduction: 16592 case OMPC_task_reduction: 16593 case OMPC_in_reduction: 16594 case OMPC_linear: 16595 case OMPC_aligned: 16596 case OMPC_copyin: 16597 case OMPC_copyprivate: 16598 case OMPC_default: 16599 case OMPC_proc_bind: 16600 case OMPC_threadprivate: 16601 case OMPC_allocate: 16602 case OMPC_flush: 16603 case OMPC_depobj: 16604 case OMPC_depend: 16605 case OMPC_device: 16606 case OMPC_map: 16607 case OMPC_num_teams: 16608 case OMPC_thread_limit: 16609 case OMPC_priority: 16610 case OMPC_grainsize: 16611 case OMPC_num_tasks: 16612 case OMPC_hint: 16613 case OMPC_dist_schedule: 16614 case OMPC_defaultmap: 16615 case OMPC_unknown: 16616 case OMPC_uniform: 16617 case OMPC_to: 16618 case OMPC_from: 16619 case OMPC_use_device_ptr: 16620 case OMPC_use_device_addr: 16621 case OMPC_is_device_ptr: 16622 case OMPC_has_device_addr: 16623 case OMPC_atomic_default_mem_order: 16624 case OMPC_device_type: 16625 case OMPC_match: 16626 case OMPC_nontemporal: 16627 case OMPC_order: 16628 case OMPC_at: 16629 case OMPC_severity: 16630 case OMPC_message: 16631 case OMPC_novariants: 16632 case OMPC_nocontext: 16633 case OMPC_detach: 16634 case OMPC_inclusive: 16635 case OMPC_exclusive: 16636 case OMPC_uses_allocators: 16637 case OMPC_affinity: 16638 case OMPC_when: 16639 case OMPC_ompx_dyn_cgroup_mem: 16640 default: 16641 llvm_unreachable("Clause is not allowed."); 16642 } 16643 return Res; 16644 } 16645 16646 OMPClause *SemaOpenMP::ActOnOpenMPNowaitClause(SourceLocation StartLoc, 16647 SourceLocation EndLoc) { 16648 DSAStack->setNowaitRegion(); 16649 return new (getASTContext()) OMPNowaitClause(StartLoc, EndLoc); 16650 } 16651 16652 OMPClause *SemaOpenMP::ActOnOpenMPUntiedClause(SourceLocation StartLoc, 16653 SourceLocation EndLoc) { 16654 DSAStack->setUntiedRegion(); 16655 return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc); 16656 } 16657 16658 OMPClause *SemaOpenMP::ActOnOpenMPMergeableClause(SourceLocation StartLoc, 16659 SourceLocation EndLoc) { 16660 return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc); 16661 } 16662 16663 OMPClause *SemaOpenMP::ActOnOpenMPReadClause(SourceLocation StartLoc, 16664 SourceLocation EndLoc) { 16665 return new (getASTContext()) OMPReadClause(StartLoc, EndLoc); 16666 } 16667 16668 OMPClause *SemaOpenMP::ActOnOpenMPWriteClause(SourceLocation StartLoc, 16669 SourceLocation EndLoc) { 16670 return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc); 16671 } 16672 16673 OMPClause *SemaOpenMP::ActOnOpenMPUpdateClause(SourceLocation StartLoc, 16674 SourceLocation EndLoc) { 16675 return OMPUpdateClause::Create(getASTContext(), StartLoc, EndLoc); 16676 } 16677 16678 OMPClause *SemaOpenMP::ActOnOpenMPCaptureClause(SourceLocation StartLoc, 16679 SourceLocation EndLoc) { 16680 return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc); 16681 } 16682 16683 OMPClause *SemaOpenMP::ActOnOpenMPCompareClause(SourceLocation StartLoc, 16684 SourceLocation EndLoc) { 16685 return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc); 16686 } 16687 16688 OMPClause *SemaOpenMP::ActOnOpenMPFailClause(SourceLocation StartLoc, 16689 SourceLocation EndLoc) { 16690 return new (getASTContext()) OMPFailClause(StartLoc, EndLoc); 16691 } 16692 16693 OMPClause *SemaOpenMP::ActOnOpenMPFailClause(OpenMPClauseKind Parameter, 16694 SourceLocation KindLoc, 16695 SourceLocation StartLoc, 16696 SourceLocation LParenLoc, 16697 SourceLocation EndLoc) { 16698 16699 if (!checkFailClauseParameter(Parameter)) { 16700 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses); 16701 return nullptr; 16702 } 16703 return new (getASTContext()) 16704 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc); 16705 } 16706 16707 OMPClause *SemaOpenMP::ActOnOpenMPSeqCstClause(SourceLocation StartLoc, 16708 SourceLocation EndLoc) { 16709 return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc); 16710 } 16711 16712 OMPClause *SemaOpenMP::ActOnOpenMPAcqRelClause(SourceLocation StartLoc, 16713 SourceLocation EndLoc) { 16714 return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc); 16715 } 16716 16717 OMPClause *SemaOpenMP::ActOnOpenMPAcquireClause(SourceLocation StartLoc, 16718 SourceLocation EndLoc) { 16719 return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc); 16720 } 16721 16722 OMPClause *SemaOpenMP::ActOnOpenMPReleaseClause(SourceLocation StartLoc, 16723 SourceLocation EndLoc) { 16724 return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc); 16725 } 16726 16727 OMPClause *SemaOpenMP::ActOnOpenMPRelaxedClause(SourceLocation StartLoc, 16728 SourceLocation EndLoc) { 16729 return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc); 16730 } 16731 16732 OMPClause *SemaOpenMP::ActOnOpenMPWeakClause(SourceLocation StartLoc, 16733 SourceLocation EndLoc) { 16734 return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc); 16735 } 16736 16737 OMPClause *SemaOpenMP::ActOnOpenMPThreadsClause(SourceLocation StartLoc, 16738 SourceLocation EndLoc) { 16739 return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc); 16740 } 16741 16742 OMPClause *SemaOpenMP::ActOnOpenMPSIMDClause(SourceLocation StartLoc, 16743 SourceLocation EndLoc) { 16744 return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc); 16745 } 16746 16747 OMPClause *SemaOpenMP::ActOnOpenMPNogroupClause(SourceLocation StartLoc, 16748 SourceLocation EndLoc) { 16749 return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc); 16750 } 16751 16752 OMPClause *SemaOpenMP::ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc, 16753 SourceLocation EndLoc) { 16754 return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc); 16755 } 16756 16757 OMPClause * 16758 SemaOpenMP::ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc, 16759 SourceLocation EndLoc) { 16760 return new (getASTContext()) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc); 16761 } 16762 16763 OMPClause *SemaOpenMP::ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc, 16764 SourceLocation EndLoc) { 16765 return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc); 16766 } 16767 16768 OMPClause * 16769 SemaOpenMP::ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc, 16770 SourceLocation EndLoc) { 16771 return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc); 16772 } 16773 16774 StmtResult 16775 SemaOpenMP::ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses, 16776 SourceLocation StartLoc, 16777 SourceLocation EndLoc) { 16778 16779 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions] 16780 // At least one action-clause must appear on a directive. 16781 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) { 16782 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'"; 16783 Diag(StartLoc, diag::err_omp_no_clause_for_directive) 16784 << Expected << getOpenMPDirectiveName(OMPD_interop); 16785 return StmtError(); 16786 } 16787 16788 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions] 16789 // A depend clause can only appear on the directive if a targetsync 16790 // interop-type is present or the interop-var was initialized with 16791 // the targetsync interop-type. 16792 16793 // If there is any 'init' clause diagnose if there is no 'init' clause with 16794 // interop-type of 'targetsync'. Cases involving other directives cannot be 16795 // diagnosed. 16796 const OMPDependClause *DependClause = nullptr; 16797 bool HasInitClause = false; 16798 bool IsTargetSync = false; 16799 for (const OMPClause *C : Clauses) { 16800 if (IsTargetSync) 16801 break; 16802 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) { 16803 HasInitClause = true; 16804 if (InitClause->getIsTargetSync()) 16805 IsTargetSync = true; 16806 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) { 16807 DependClause = DC; 16808 } 16809 } 16810 if (DependClause && HasInitClause && !IsTargetSync) { 16811 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause); 16812 return StmtError(); 16813 } 16814 16815 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions] 16816 // Each interop-var may be specified for at most one action-clause of each 16817 // interop construct. 16818 llvm::SmallPtrSet<const ValueDecl *, 4> InteropVars; 16819 for (OMPClause *C : Clauses) { 16820 OpenMPClauseKind ClauseKind = C->getClauseKind(); 16821 std::pair<ValueDecl *, bool> DeclResult; 16822 SourceLocation ELoc; 16823 SourceRange ERange; 16824 16825 if (ClauseKind == OMPC_init) { 16826 auto *E = cast<OMPInitClause>(C)->getInteropVar(); 16827 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange); 16828 } else if (ClauseKind == OMPC_use) { 16829 auto *E = cast<OMPUseClause>(C)->getInteropVar(); 16830 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange); 16831 } else if (ClauseKind == OMPC_destroy) { 16832 auto *E = cast<OMPDestroyClause>(C)->getInteropVar(); 16833 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange); 16834 } 16835 16836 if (DeclResult.first) { 16837 if (!InteropVars.insert(DeclResult.first).second) { 16838 Diag(ELoc, diag::err_omp_interop_var_multiple_actions) 16839 << DeclResult.first; 16840 return StmtError(); 16841 } 16842 } 16843 } 16844 16845 return OMPInteropDirective::Create(getASTContext(), StartLoc, EndLoc, 16846 Clauses); 16847 } 16848 16849 static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr, 16850 SourceLocation VarLoc, 16851 OpenMPClauseKind Kind) { 16852 SourceLocation ELoc; 16853 SourceRange ERange; 16854 Expr *RefExpr = InteropVarExpr; 16855 auto Res = 16856 getPrivateItem(SemaRef, RefExpr, ELoc, ERange, 16857 /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t"); 16858 16859 if (Res.second) { 16860 // It will be analyzed later. 16861 return true; 16862 } 16863 16864 if (!Res.first) 16865 return false; 16866 16867 // Interop variable should be of type omp_interop_t. 16868 bool HasError = false; 16869 QualType InteropType; 16870 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"), 16871 VarLoc, Sema::LookupOrdinaryName); 16872 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) { 16873 NamedDecl *ND = Result.getFoundDecl(); 16874 if (const auto *TD = dyn_cast<TypeDecl>(ND)) { 16875 InteropType = QualType(TD->getTypeForDecl(), 0); 16876 } else { 16877 HasError = true; 16878 } 16879 } else { 16880 HasError = true; 16881 } 16882 16883 if (HasError) { 16884 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found) 16885 << "omp_interop_t"; 16886 return false; 16887 } 16888 16889 QualType VarType = InteropVarExpr->getType().getUnqualifiedType(); 16890 if (!SemaRef.Context.hasSameType(InteropType, VarType)) { 16891 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type); 16892 return false; 16893 } 16894 16895 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions] 16896 // The interop-var passed to init or destroy must be non-const. 16897 if ((Kind == OMPC_init || Kind == OMPC_destroy) && 16898 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) { 16899 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected) 16900 << /*non-const*/ 1; 16901 return false; 16902 } 16903 return true; 16904 } 16905 16906 OMPClause *SemaOpenMP::ActOnOpenMPInitClause( 16907 Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, 16908 SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) { 16909 16910 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_init)) 16911 return nullptr; 16912 16913 // Check prefer_type values. These foreign-runtime-id values are either 16914 // string literals or constant integral expressions. 16915 for (const Expr *E : InteropInfo.PreferTypes) { 16916 if (E->isValueDependent() || E->isTypeDependent() || 16917 E->isInstantiationDependent() || E->containsUnexpandedParameterPack()) 16918 continue; 16919 if (E->isIntegerConstantExpr(getASTContext())) 16920 continue; 16921 if (isa<StringLiteral>(E)) 16922 continue; 16923 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type); 16924 return nullptr; 16925 } 16926 16927 return OMPInitClause::Create(getASTContext(), InteropVar, InteropInfo, 16928 StartLoc, LParenLoc, VarLoc, EndLoc); 16929 } 16930 16931 OMPClause *SemaOpenMP::ActOnOpenMPUseClause(Expr *InteropVar, 16932 SourceLocation StartLoc, 16933 SourceLocation LParenLoc, 16934 SourceLocation VarLoc, 16935 SourceLocation EndLoc) { 16936 16937 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_use)) 16938 return nullptr; 16939 16940 return new (getASTContext()) 16941 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc); 16942 } 16943 16944 OMPClause *SemaOpenMP::ActOnOpenMPDestroyClause(Expr *InteropVar, 16945 SourceLocation StartLoc, 16946 SourceLocation LParenLoc, 16947 SourceLocation VarLoc, 16948 SourceLocation EndLoc) { 16949 if (!InteropVar && getLangOpts().OpenMP >= 52 && 16950 DSAStack->getCurrentDirective() == OMPD_depobj) { 16951 Diag(StartLoc, diag::err_omp_expected_clause_argument) 16952 << getOpenMPClauseName(OMPC_destroy) 16953 << getOpenMPDirectiveName(OMPD_depobj); 16954 return nullptr; 16955 } 16956 if (InteropVar && 16957 !isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_destroy)) 16958 return nullptr; 16959 16960 return new (getASTContext()) 16961 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc); 16962 } 16963 16964 OMPClause *SemaOpenMP::ActOnOpenMPNovariantsClause(Expr *Condition, 16965 SourceLocation StartLoc, 16966 SourceLocation LParenLoc, 16967 SourceLocation EndLoc) { 16968 Expr *ValExpr = Condition; 16969 Stmt *HelperValStmt = nullptr; 16970 OpenMPDirectiveKind CaptureRegion = OMPD_unknown; 16971 if (!Condition->isValueDependent() && !Condition->isTypeDependent() && 16972 !Condition->isInstantiationDependent() && 16973 !Condition->containsUnexpandedParameterPack()) { 16974 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition); 16975 if (Val.isInvalid()) 16976 return nullptr; 16977 16978 ValExpr = SemaRef.MakeFullExpr(Val.get()).get(); 16979 16980 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); 16981 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants, 16982 getLangOpts().OpenMP); 16983 if (CaptureRegion != OMPD_unknown && 16984 !SemaRef.CurContext->isDependentContext()) { 16985 ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); 16986 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 16987 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); 16988 HelperValStmt = buildPreInits(getASTContext(), Captures); 16989 } 16990 } 16991 16992 return new (getASTContext()) OMPNovariantsClause( 16993 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc); 16994 } 16995 16996 OMPClause *SemaOpenMP::ActOnOpenMPNocontextClause(Expr *Condition, 16997 SourceLocation StartLoc, 16998 SourceLocation LParenLoc, 16999 SourceLocation EndLoc) { 17000 Expr *ValExpr = Condition; 17001 Stmt *HelperValStmt = nullptr; 17002 OpenMPDirectiveKind CaptureRegion = OMPD_unknown; 17003 if (!Condition->isValueDependent() && !Condition->isTypeDependent() && 17004 !Condition->isInstantiationDependent() && 17005 !Condition->containsUnexpandedParameterPack()) { 17006 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition); 17007 if (Val.isInvalid()) 17008 return nullptr; 17009 17010 ValExpr = SemaRef.MakeFullExpr(Val.get()).get(); 17011 17012 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); 17013 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext, 17014 getLangOpts().OpenMP); 17015 if (CaptureRegion != OMPD_unknown && 17016 !SemaRef.CurContext->isDependentContext()) { 17017 ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); 17018 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 17019 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); 17020 HelperValStmt = buildPreInits(getASTContext(), Captures); 17021 } 17022 } 17023 17024 return new (getASTContext()) OMPNocontextClause( 17025 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc); 17026 } 17027 17028 OMPClause *SemaOpenMP::ActOnOpenMPFilterClause(Expr *ThreadID, 17029 SourceLocation StartLoc, 17030 SourceLocation LParenLoc, 17031 SourceLocation EndLoc) { 17032 Expr *ValExpr = ThreadID; 17033 Stmt *HelperValStmt = nullptr; 17034 17035 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); 17036 OpenMPDirectiveKind CaptureRegion = 17037 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, getLangOpts().OpenMP); 17038 if (CaptureRegion != OMPD_unknown && 17039 !SemaRef.CurContext->isDependentContext()) { 17040 ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); 17041 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 17042 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); 17043 HelperValStmt = buildPreInits(getASTContext(), Captures); 17044 } 17045 17046 return new (getASTContext()) OMPFilterClause( 17047 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc); 17048 } 17049 17050 OMPClause *SemaOpenMP::ActOnOpenMPVarListClause(OpenMPClauseKind Kind, 17051 ArrayRef<Expr *> VarList, 17052 const OMPVarListLocTy &Locs, 17053 OpenMPVarListDataTy &Data) { 17054 SourceLocation StartLoc = Locs.StartLoc; 17055 SourceLocation LParenLoc = Locs.LParenLoc; 17056 SourceLocation EndLoc = Locs.EndLoc; 17057 OMPClause *Res = nullptr; 17058 int ExtraModifier = Data.ExtraModifier; 17059 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc; 17060 SourceLocation ColonLoc = Data.ColonLoc; 17061 switch (Kind) { 17062 case OMPC_private: 17063 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc); 17064 break; 17065 case OMPC_firstprivate: 17066 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc); 17067 break; 17068 case OMPC_lastprivate: 17069 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown && 17070 "Unexpected lastprivate modifier."); 17071 Res = ActOnOpenMPLastprivateClause( 17072 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier), 17073 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc); 17074 break; 17075 case OMPC_shared: 17076 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc); 17077 break; 17078 case OMPC_reduction: 17079 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown && 17080 "Unexpected lastprivate modifier."); 17081 Res = ActOnOpenMPReductionClause( 17082 VarList, static_cast<OpenMPReductionClauseModifier>(ExtraModifier), 17083 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc, 17084 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId); 17085 break; 17086 case OMPC_task_reduction: 17087 Res = ActOnOpenMPTaskReductionClause( 17088 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc, 17089 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId); 17090 break; 17091 case OMPC_in_reduction: 17092 Res = ActOnOpenMPInReductionClause( 17093 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc, 17094 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId); 17095 break; 17096 case OMPC_linear: 17097 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown && 17098 "Unexpected linear modifier."); 17099 Res = ActOnOpenMPLinearClause( 17100 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc, 17101 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc, 17102 ColonLoc, Data.StepModifierLoc, EndLoc); 17103 break; 17104 case OMPC_aligned: 17105 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc, 17106 LParenLoc, ColonLoc, EndLoc); 17107 break; 17108 case OMPC_copyin: 17109 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc); 17110 break; 17111 case OMPC_copyprivate: 17112 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc); 17113 break; 17114 case OMPC_flush: 17115 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc); 17116 break; 17117 case OMPC_depend: 17118 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown && 17119 "Unexpected depend modifier."); 17120 Res = ActOnOpenMPDependClause( 17121 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc, 17122 ColonLoc, Data.OmpAllMemoryLoc}, 17123 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc); 17124 break; 17125 case OMPC_map: 17126 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown && 17127 "Unexpected map modifier."); 17128 Res = ActOnOpenMPMapClause( 17129 Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc, 17130 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, 17131 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit, 17132 ExtraModifierLoc, ColonLoc, VarList, Locs); 17133 break; 17134 case OMPC_to: 17135 Res = 17136 ActOnOpenMPToClause(Data.MotionModifiers, Data.MotionModifiersLoc, 17137 Data.ReductionOrMapperIdScopeSpec, 17138 Data.ReductionOrMapperId, ColonLoc, VarList, Locs); 17139 break; 17140 case OMPC_from: 17141 Res = ActOnOpenMPFromClause(Data.MotionModifiers, Data.MotionModifiersLoc, 17142 Data.ReductionOrMapperIdScopeSpec, 17143 Data.ReductionOrMapperId, ColonLoc, VarList, 17144 Locs); 17145 break; 17146 case OMPC_use_device_ptr: 17147 Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs); 17148 break; 17149 case OMPC_use_device_addr: 17150 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs); 17151 break; 17152 case OMPC_is_device_ptr: 17153 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs); 17154 break; 17155 case OMPC_has_device_addr: 17156 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs); 17157 break; 17158 case OMPC_allocate: { 17159 OpenMPAllocateClauseModifier Modifier1 = OMPC_ALLOCATE_unknown; 17160 OpenMPAllocateClauseModifier Modifier2 = OMPC_ALLOCATE_unknown; 17161 SourceLocation Modifier1Loc, Modifier2Loc; 17162 if (!Data.AllocClauseModifiers.empty()) { 17163 assert(Data.AllocClauseModifiers.size() <= 2 && 17164 "More allocate modifiers than expected"); 17165 Modifier1 = Data.AllocClauseModifiers[0]; 17166 Modifier1Loc = Data.AllocClauseModifiersLoc[0]; 17167 if (Data.AllocClauseModifiers.size() == 2) { 17168 Modifier2 = Data.AllocClauseModifiers[1]; 17169 Modifier2Loc = Data.AllocClauseModifiersLoc[1]; 17170 } 17171 } 17172 Res = ActOnOpenMPAllocateClause( 17173 Data.DepModOrTailExpr, Data.AllocateAlignment, Modifier1, Modifier1Loc, 17174 Modifier2, Modifier2Loc, VarList, StartLoc, LParenLoc, ColonLoc, 17175 EndLoc); 17176 break; 17177 } 17178 case OMPC_nontemporal: 17179 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc); 17180 break; 17181 case OMPC_inclusive: 17182 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc); 17183 break; 17184 case OMPC_exclusive: 17185 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc); 17186 break; 17187 case OMPC_affinity: 17188 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc, 17189 Data.DepModOrTailExpr, VarList); 17190 break; 17191 case OMPC_doacross: 17192 Res = ActOnOpenMPDoacrossClause( 17193 static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier), 17194 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc); 17195 break; 17196 case OMPC_num_teams: 17197 Res = ActOnOpenMPNumTeamsClause(VarList, StartLoc, LParenLoc, EndLoc); 17198 break; 17199 case OMPC_thread_limit: 17200 Res = ActOnOpenMPThreadLimitClause(VarList, StartLoc, LParenLoc, EndLoc); 17201 break; 17202 case OMPC_if: 17203 case OMPC_depobj: 17204 case OMPC_final: 17205 case OMPC_num_threads: 17206 case OMPC_safelen: 17207 case OMPC_simdlen: 17208 case OMPC_sizes: 17209 case OMPC_allocator: 17210 case OMPC_collapse: 17211 case OMPC_default: 17212 case OMPC_proc_bind: 17213 case OMPC_schedule: 17214 case OMPC_ordered: 17215 case OMPC_nowait: 17216 case OMPC_untied: 17217 case OMPC_mergeable: 17218 case OMPC_threadprivate: 17219 case OMPC_read: 17220 case OMPC_write: 17221 case OMPC_update: 17222 case OMPC_capture: 17223 case OMPC_compare: 17224 case OMPC_seq_cst: 17225 case OMPC_acq_rel: 17226 case OMPC_acquire: 17227 case OMPC_release: 17228 case OMPC_relaxed: 17229 case OMPC_device: 17230 case OMPC_threads: 17231 case OMPC_simd: 17232 case OMPC_priority: 17233 case OMPC_grainsize: 17234 case OMPC_nogroup: 17235 case OMPC_num_tasks: 17236 case OMPC_hint: 17237 case OMPC_dist_schedule: 17238 case OMPC_defaultmap: 17239 case OMPC_unknown: 17240 case OMPC_uniform: 17241 case OMPC_unified_address: 17242 case OMPC_unified_shared_memory: 17243 case OMPC_reverse_offload: 17244 case OMPC_dynamic_allocators: 17245 case OMPC_atomic_default_mem_order: 17246 case OMPC_device_type: 17247 case OMPC_match: 17248 case OMPC_order: 17249 case OMPC_at: 17250 case OMPC_severity: 17251 case OMPC_message: 17252 case OMPC_destroy: 17253 case OMPC_novariants: 17254 case OMPC_nocontext: 17255 case OMPC_detach: 17256 case OMPC_uses_allocators: 17257 case OMPC_when: 17258 case OMPC_bind: 17259 default: 17260 llvm_unreachable("Clause is not allowed."); 17261 } 17262 return Res; 17263 } 17264 17265 ExprResult SemaOpenMP::getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK, 17266 ExprObjectKind OK, 17267 SourceLocation Loc) { 17268 ExprResult Res = SemaRef.BuildDeclRefExpr( 17269 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc); 17270 if (!Res.isUsable()) 17271 return ExprError(); 17272 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) { 17273 Res = SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get()); 17274 if (!Res.isUsable()) 17275 return ExprError(); 17276 } 17277 if (VK != VK_LValue && Res.get()->isGLValue()) { 17278 Res = SemaRef.DefaultLvalueConversion(Res.get()); 17279 if (!Res.isUsable()) 17280 return ExprError(); 17281 } 17282 return Res; 17283 } 17284 17285 OMPClause *SemaOpenMP::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList, 17286 SourceLocation StartLoc, 17287 SourceLocation LParenLoc, 17288 SourceLocation EndLoc) { 17289 SmallVector<Expr *, 8> Vars; 17290 SmallVector<Expr *, 8> PrivateCopies; 17291 bool IsImplicitClause = 17292 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid(); 17293 for (Expr *RefExpr : VarList) { 17294 assert(RefExpr && "NULL expr in OpenMP private clause."); 17295 SourceLocation ELoc; 17296 SourceRange ERange; 17297 Expr *SimpleRefExpr = RefExpr; 17298 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); 17299 if (Res.second) { 17300 // It will be analyzed later. 17301 Vars.push_back(RefExpr); 17302 PrivateCopies.push_back(nullptr); 17303 } 17304 ValueDecl *D = Res.first; 17305 if (!D) 17306 continue; 17307 17308 QualType Type = D->getType(); 17309 auto *VD = dyn_cast<VarDecl>(D); 17310 17311 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3] 17312 // A variable that appears in a private clause must not have an incomplete 17313 // type or a reference type. 17314 if (SemaRef.RequireCompleteType(ELoc, Type, 17315 diag::err_omp_private_incomplete_type)) 17316 continue; 17317 Type = Type.getNonReferenceType(); 17318 17319 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions] 17320 // A variable that is privatized must not have a const-qualified type 17321 // unless it is of class type with a mutable member. This restriction does 17322 // not apply to the firstprivate clause. 17323 // 17324 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions] 17325 // A variable that appears in a private clause must not have a 17326 // const-qualified type unless it is of class type with a mutable member. 17327 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_private, ELoc)) 17328 continue; 17329 17330 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 17331 // in a Construct] 17332 // Variables with the predetermined data-sharing attributes may not be 17333 // listed in data-sharing attributes clauses, except for the cases 17334 // listed below. For these exceptions only, listing a predetermined 17335 // variable in a data-sharing attribute clause is allowed and overrides 17336 // the variable's predetermined data-sharing attributes. 17337 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false); 17338 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) { 17339 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind) 17340 << getOpenMPClauseName(OMPC_private); 17341 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 17342 continue; 17343 } 17344 17345 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective(); 17346 // Variably modified types are not supported for tasks. 17347 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() && 17348 isOpenMPTaskingDirective(CurrDir)) { 17349 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported) 17350 << getOpenMPClauseName(OMPC_private) << Type 17351 << getOpenMPDirectiveName(CurrDir); 17352 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) == 17353 VarDecl::DeclarationOnly; 17354 Diag(D->getLocation(), 17355 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 17356 << D; 17357 continue; 17358 } 17359 17360 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3] 17361 // A list item cannot appear in both a map clause and a data-sharing 17362 // attribute clause on the same construct 17363 // 17364 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7] 17365 // A list item cannot appear in both a map clause and a data-sharing 17366 // attribute clause on the same construct unless the construct is a 17367 // combined construct. 17368 if ((getLangOpts().OpenMP <= 45 && 17369 isOpenMPTargetExecutionDirective(CurrDir)) || 17370 CurrDir == OMPD_target) { 17371 OpenMPClauseKind ConflictKind; 17372 if (DSAStack->checkMappableExprComponentListsForDecl( 17373 VD, /*CurrentRegionOnly=*/true, 17374 [&](OMPClauseMappableExprCommon::MappableExprComponentListRef, 17375 OpenMPClauseKind WhereFoundClauseKind) -> bool { 17376 ConflictKind = WhereFoundClauseKind; 17377 return true; 17378 })) { 17379 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa) 17380 << getOpenMPClauseName(OMPC_private) 17381 << getOpenMPClauseName(ConflictKind) 17382 << getOpenMPDirectiveName(CurrDir); 17383 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 17384 continue; 17385 } 17386 } 17387 17388 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1] 17389 // A variable of class type (or array thereof) that appears in a private 17390 // clause requires an accessible, unambiguous default constructor for the 17391 // class type. 17392 // Generate helper private variable and initialize it with the default 17393 // value. The address of the original variable is replaced by the address of 17394 // the new private variable in CodeGen. This new variable is not added to 17395 // IdResolver, so the code in the OpenMP region uses original variable for 17396 // proper diagnostics. 17397 Type = Type.getUnqualifiedType(); 17398 VarDecl *VDPrivate = 17399 buildVarDecl(SemaRef, ELoc, Type, D->getName(), 17400 D->hasAttrs() ? &D->getAttrs() : nullptr, 17401 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr); 17402 SemaRef.ActOnUninitializedDecl(VDPrivate); 17403 if (VDPrivate->isInvalidDecl()) 17404 continue; 17405 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr( 17406 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc); 17407 17408 DeclRefExpr *Ref = nullptr; 17409 if (!VD && !SemaRef.CurContext->isDependentContext()) { 17410 auto *FD = dyn_cast<FieldDecl>(D); 17411 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr; 17412 if (VD) 17413 Ref = buildDeclRefExpr(SemaRef, VD, VD->getType().getNonReferenceType(), 17414 RefExpr->getExprLoc()); 17415 else 17416 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false); 17417 } 17418 if (!IsImplicitClause) 17419 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref); 17420 Vars.push_back((VD || SemaRef.CurContext->isDependentContext()) 17421 ? RefExpr->IgnoreParens() 17422 : Ref); 17423 PrivateCopies.push_back(VDPrivateRefExpr); 17424 } 17425 17426 if (Vars.empty()) 17427 return nullptr; 17428 17429 return OMPPrivateClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc, 17430 Vars, PrivateCopies); 17431 } 17432 17433 OMPClause *SemaOpenMP::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, 17434 SourceLocation StartLoc, 17435 SourceLocation LParenLoc, 17436 SourceLocation EndLoc) { 17437 SmallVector<Expr *, 8> Vars; 17438 SmallVector<Expr *, 8> PrivateCopies; 17439 SmallVector<Expr *, 8> Inits; 17440 SmallVector<Decl *, 4> ExprCaptures; 17441 bool IsImplicitClause = 17442 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid(); 17443 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc(); 17444 17445 for (Expr *RefExpr : VarList) { 17446 assert(RefExpr && "NULL expr in OpenMP firstprivate clause."); 17447 SourceLocation ELoc; 17448 SourceRange ERange; 17449 Expr *SimpleRefExpr = RefExpr; 17450 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); 17451 if (Res.second) { 17452 // It will be analyzed later. 17453 Vars.push_back(RefExpr); 17454 PrivateCopies.push_back(nullptr); 17455 Inits.push_back(nullptr); 17456 } 17457 ValueDecl *D = Res.first; 17458 if (!D) 17459 continue; 17460 17461 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc; 17462 QualType Type = D->getType(); 17463 auto *VD = dyn_cast<VarDecl>(D); 17464 17465 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3] 17466 // A variable that appears in a private clause must not have an incomplete 17467 // type or a reference type. 17468 if (SemaRef.RequireCompleteType(ELoc, Type, 17469 diag::err_omp_firstprivate_incomplete_type)) 17470 continue; 17471 Type = Type.getNonReferenceType(); 17472 17473 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1] 17474 // A variable of class type (or array thereof) that appears in a private 17475 // clause requires an accessible, unambiguous copy constructor for the 17476 // class type. 17477 QualType ElemType = 17478 getASTContext().getBaseElementType(Type).getNonReferenceType(); 17479 17480 // If an implicit firstprivate variable found it was checked already. 17481 DSAStackTy::DSAVarData TopDVar; 17482 if (!IsImplicitClause) { 17483 DSAStackTy::DSAVarData DVar = 17484 DSAStack->getTopDSA(D, /*FromParent=*/false); 17485 TopDVar = DVar; 17486 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective(); 17487 bool IsConstant = ElemType.isConstant(getASTContext()); 17488 // OpenMP [2.4.13, Data-sharing Attribute Clauses] 17489 // A list item that specifies a given variable may not appear in more 17490 // than one clause on the same directive, except that a variable may be 17491 // specified in both firstprivate and lastprivate clauses. 17492 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3] 17493 // A list item may appear in a firstprivate or lastprivate clause but not 17494 // both. 17495 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate && 17496 (isOpenMPDistributeDirective(CurrDir) || 17497 DVar.CKind != OMPC_lastprivate) && 17498 DVar.RefExpr) { 17499 Diag(ELoc, diag::err_omp_wrong_dsa) 17500 << getOpenMPClauseName(DVar.CKind) 17501 << getOpenMPClauseName(OMPC_firstprivate); 17502 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 17503 continue; 17504 } 17505 17506 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 17507 // in a Construct] 17508 // Variables with the predetermined data-sharing attributes may not be 17509 // listed in data-sharing attributes clauses, except for the cases 17510 // listed below. For these exceptions only, listing a predetermined 17511 // variable in a data-sharing attribute clause is allowed and overrides 17512 // the variable's predetermined data-sharing attributes. 17513 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 17514 // in a Construct, C/C++, p.2] 17515 // Variables with const-qualified type having no mutable member may be 17516 // listed in a firstprivate clause, even if they are static data members. 17517 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr && 17518 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) { 17519 Diag(ELoc, diag::err_omp_wrong_dsa) 17520 << getOpenMPClauseName(DVar.CKind) 17521 << getOpenMPClauseName(OMPC_firstprivate); 17522 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 17523 continue; 17524 } 17525 17526 // OpenMP [2.9.3.4, Restrictions, p.2] 17527 // A list item that is private within a parallel region must not appear 17528 // in a firstprivate clause on a worksharing construct if any of the 17529 // worksharing regions arising from the worksharing construct ever bind 17530 // to any of the parallel regions arising from the parallel construct. 17531 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3] 17532 // A list item that is private within a teams region must not appear in a 17533 // firstprivate clause on a distribute construct if any of the distribute 17534 // regions arising from the distribute construct ever bind to any of the 17535 // teams regions arising from the teams construct. 17536 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3] 17537 // A list item that appears in a reduction clause of a teams construct 17538 // must not appear in a firstprivate clause on a distribute construct if 17539 // any of the distribute regions arising from the distribute construct 17540 // ever bind to any of the teams regions arising from the teams construct. 17541 if ((isOpenMPWorksharingDirective(CurrDir) || 17542 isOpenMPDistributeDirective(CurrDir)) && 17543 !isOpenMPParallelDirective(CurrDir) && 17544 !isOpenMPTeamsDirective(CurrDir)) { 17545 DVar = DSAStack->getImplicitDSA(D, true); 17546 if (DVar.CKind != OMPC_shared && 17547 (isOpenMPParallelDirective(DVar.DKind) || 17548 isOpenMPTeamsDirective(DVar.DKind) || 17549 DVar.DKind == OMPD_unknown)) { 17550 Diag(ELoc, diag::err_omp_required_access) 17551 << getOpenMPClauseName(OMPC_firstprivate) 17552 << getOpenMPClauseName(OMPC_shared); 17553 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 17554 continue; 17555 } 17556 } 17557 // OpenMP [2.9.3.4, Restrictions, p.3] 17558 // A list item that appears in a reduction clause of a parallel construct 17559 // must not appear in a firstprivate clause on a worksharing or task 17560 // construct if any of the worksharing or task regions arising from the 17561 // worksharing or task construct ever bind to any of the parallel regions 17562 // arising from the parallel construct. 17563 // OpenMP [2.9.3.4, Restrictions, p.4] 17564 // A list item that appears in a reduction clause in worksharing 17565 // construct must not appear in a firstprivate clause in a task construct 17566 // encountered during execution of any of the worksharing regions arising 17567 // from the worksharing construct. 17568 if (isOpenMPTaskingDirective(CurrDir)) { 17569 DVar = DSAStack->hasInnermostDSA( 17570 D, 17571 [](OpenMPClauseKind C, bool AppliedToPointee) { 17572 return C == OMPC_reduction && !AppliedToPointee; 17573 }, 17574 [](OpenMPDirectiveKind K) { 17575 return isOpenMPParallelDirective(K) || 17576 isOpenMPWorksharingDirective(K) || 17577 isOpenMPTeamsDirective(K); 17578 }, 17579 /*FromParent=*/true); 17580 if (DVar.CKind == OMPC_reduction && 17581 (isOpenMPParallelDirective(DVar.DKind) || 17582 isOpenMPWorksharingDirective(DVar.DKind) || 17583 isOpenMPTeamsDirective(DVar.DKind))) { 17584 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate) 17585 << getOpenMPDirectiveName(DVar.DKind); 17586 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 17587 continue; 17588 } 17589 } 17590 17591 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3] 17592 // A list item cannot appear in both a map clause and a data-sharing 17593 // attribute clause on the same construct 17594 // 17595 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7] 17596 // A list item cannot appear in both a map clause and a data-sharing 17597 // attribute clause on the same construct unless the construct is a 17598 // combined construct. 17599 if ((getLangOpts().OpenMP <= 45 && 17600 isOpenMPTargetExecutionDirective(CurrDir)) || 17601 CurrDir == OMPD_target) { 17602 OpenMPClauseKind ConflictKind; 17603 if (DSAStack->checkMappableExprComponentListsForDecl( 17604 VD, /*CurrentRegionOnly=*/true, 17605 [&ConflictKind]( 17606 OMPClauseMappableExprCommon::MappableExprComponentListRef, 17607 OpenMPClauseKind WhereFoundClauseKind) { 17608 ConflictKind = WhereFoundClauseKind; 17609 return true; 17610 })) { 17611 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa) 17612 << getOpenMPClauseName(OMPC_firstprivate) 17613 << getOpenMPClauseName(ConflictKind) 17614 << getOpenMPDirectiveName(DSAStack->getCurrentDirective()); 17615 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 17616 continue; 17617 } 17618 } 17619 } 17620 17621 // Variably modified types are not supported for tasks. 17622 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() && 17623 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) { 17624 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported) 17625 << getOpenMPClauseName(OMPC_firstprivate) << Type 17626 << getOpenMPDirectiveName(DSAStack->getCurrentDirective()); 17627 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) == 17628 VarDecl::DeclarationOnly; 17629 Diag(D->getLocation(), 17630 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 17631 << D; 17632 continue; 17633 } 17634 17635 Type = Type.getUnqualifiedType(); 17636 VarDecl *VDPrivate = 17637 buildVarDecl(SemaRef, ELoc, Type, D->getName(), 17638 D->hasAttrs() ? &D->getAttrs() : nullptr, 17639 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr); 17640 // Generate helper private variable and initialize it with the value of the 17641 // original variable. The address of the original variable is replaced by 17642 // the address of the new private variable in the CodeGen. This new variable 17643 // is not added to IdResolver, so the code in the OpenMP region uses 17644 // original variable for proper diagnostics and variable capturing. 17645 Expr *VDInitRefExpr = nullptr; 17646 // For arrays generate initializer for single element and replace it by the 17647 // original array element in CodeGen. 17648 if (Type->isArrayType()) { 17649 VarDecl *VDInit = 17650 buildVarDecl(SemaRef, RefExpr->getExprLoc(), ElemType, D->getName()); 17651 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, ElemType, ELoc); 17652 Expr *Init = SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(); 17653 ElemType = ElemType.getUnqualifiedType(); 17654 VarDecl *VDInitTemp = buildVarDecl(SemaRef, RefExpr->getExprLoc(), 17655 ElemType, ".firstprivate.temp"); 17656 InitializedEntity Entity = 17657 InitializedEntity::InitializeVariable(VDInitTemp); 17658 InitializationKind Kind = InitializationKind::CreateCopy(ELoc, ELoc); 17659 17660 InitializationSequence InitSeq(SemaRef, Entity, Kind, Init); 17661 ExprResult Result = InitSeq.Perform(SemaRef, Entity, Kind, Init); 17662 if (Result.isInvalid()) 17663 VDPrivate->setInvalidDecl(); 17664 else 17665 VDPrivate->setInit(Result.getAs<Expr>()); 17666 // Remove temp variable declaration. 17667 getASTContext().Deallocate(VDInitTemp); 17668 } else { 17669 VarDecl *VDInit = buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type, 17670 ".firstprivate.temp"); 17671 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, RefExpr->getType(), 17672 RefExpr->getExprLoc()); 17673 SemaRef.AddInitializerToDecl( 17674 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(), 17675 /*DirectInit=*/false); 17676 } 17677 if (VDPrivate->isInvalidDecl()) { 17678 if (IsImplicitClause) { 17679 Diag(RefExpr->getExprLoc(), 17680 diag::note_omp_task_predetermined_firstprivate_here); 17681 } 17682 continue; 17683 } 17684 SemaRef.CurContext->addDecl(VDPrivate); 17685 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr( 17686 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), 17687 RefExpr->getExprLoc()); 17688 DeclRefExpr *Ref = nullptr; 17689 if (!VD && !SemaRef.CurContext->isDependentContext()) { 17690 if (TopDVar.CKind == OMPC_lastprivate) { 17691 Ref = TopDVar.PrivateCopy; 17692 } else { 17693 auto *FD = dyn_cast<FieldDecl>(D); 17694 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr; 17695 if (VD) 17696 Ref = 17697 buildDeclRefExpr(SemaRef, VD, VD->getType().getNonReferenceType(), 17698 RefExpr->getExprLoc()); 17699 else 17700 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true); 17701 if (VD || !isOpenMPCapturedDecl(D)) 17702 ExprCaptures.push_back(Ref->getDecl()); 17703 } 17704 } 17705 if (!IsImplicitClause) 17706 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref); 17707 Vars.push_back((VD || SemaRef.CurContext->isDependentContext()) 17708 ? RefExpr->IgnoreParens() 17709 : Ref); 17710 PrivateCopies.push_back(VDPrivateRefExpr); 17711 Inits.push_back(VDInitRefExpr); 17712 } 17713 17714 if (Vars.empty()) 17715 return nullptr; 17716 17717 return OMPFirstprivateClause::Create( 17718 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits, 17719 buildPreInits(getASTContext(), ExprCaptures)); 17720 } 17721 17722 OMPClause *SemaOpenMP::ActOnOpenMPLastprivateClause( 17723 ArrayRef<Expr *> VarList, OpenMPLastprivateModifier LPKind, 17724 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc, 17725 SourceLocation LParenLoc, SourceLocation EndLoc) { 17726 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) { 17727 assert(ColonLoc.isValid() && "Colon location must be valid."); 17728 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value) 17729 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0, 17730 /*Last=*/OMPC_LASTPRIVATE_unknown) 17731 << getOpenMPClauseName(OMPC_lastprivate); 17732 return nullptr; 17733 } 17734 17735 SmallVector<Expr *, 8> Vars; 17736 SmallVector<Expr *, 8> SrcExprs; 17737 SmallVector<Expr *, 8> DstExprs; 17738 SmallVector<Expr *, 8> AssignmentOps; 17739 SmallVector<Decl *, 4> ExprCaptures; 17740 SmallVector<Expr *, 4> ExprPostUpdates; 17741 for (Expr *RefExpr : VarList) { 17742 assert(RefExpr && "NULL expr in OpenMP lastprivate clause."); 17743 SourceLocation ELoc; 17744 SourceRange ERange; 17745 Expr *SimpleRefExpr = RefExpr; 17746 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); 17747 if (Res.second) { 17748 // It will be analyzed later. 17749 Vars.push_back(RefExpr); 17750 SrcExprs.push_back(nullptr); 17751 DstExprs.push_back(nullptr); 17752 AssignmentOps.push_back(nullptr); 17753 } 17754 ValueDecl *D = Res.first; 17755 if (!D) 17756 continue; 17757 17758 QualType Type = D->getType(); 17759 auto *VD = dyn_cast<VarDecl>(D); 17760 17761 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2] 17762 // A variable that appears in a lastprivate clause must not have an 17763 // incomplete type or a reference type. 17764 if (SemaRef.RequireCompleteType(ELoc, Type, 17765 diag::err_omp_lastprivate_incomplete_type)) 17766 continue; 17767 Type = Type.getNonReferenceType(); 17768 17769 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions] 17770 // A variable that is privatized must not have a const-qualified type 17771 // unless it is of class type with a mutable member. This restriction does 17772 // not apply to the firstprivate clause. 17773 // 17774 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions] 17775 // A variable that appears in a lastprivate clause must not have a 17776 // const-qualified type unless it is of class type with a mutable member. 17777 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_lastprivate, ELoc)) 17778 continue; 17779 17780 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions] 17781 // A list item that appears in a lastprivate clause with the conditional 17782 // modifier must be a scalar variable. 17783 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) { 17784 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar); 17785 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) == 17786 VarDecl::DeclarationOnly; 17787 Diag(D->getLocation(), 17788 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 17789 << D; 17790 continue; 17791 } 17792 17793 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective(); 17794 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced 17795 // in a Construct] 17796 // Variables with the predetermined data-sharing attributes may not be 17797 // listed in data-sharing attributes clauses, except for the cases 17798 // listed below. 17799 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3] 17800 // A list item may appear in a firstprivate or lastprivate clause but not 17801 // both. 17802 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false); 17803 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate && 17804 (isOpenMPDistributeDirective(CurrDir) || 17805 DVar.CKind != OMPC_firstprivate) && 17806 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) { 17807 Diag(ELoc, diag::err_omp_wrong_dsa) 17808 << getOpenMPClauseName(DVar.CKind) 17809 << getOpenMPClauseName(OMPC_lastprivate); 17810 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 17811 continue; 17812 } 17813 17814 // OpenMP [2.14.3.5, Restrictions, p.2] 17815 // A list item that is private within a parallel region, or that appears in 17816 // the reduction clause of a parallel construct, must not appear in a 17817 // lastprivate clause on a worksharing construct if any of the corresponding 17818 // worksharing regions ever binds to any of the corresponding parallel 17819 // regions. 17820 DSAStackTy::DSAVarData TopDVar = DVar; 17821 if (isOpenMPWorksharingDirective(CurrDir) && 17822 !isOpenMPParallelDirective(CurrDir) && 17823 !isOpenMPTeamsDirective(CurrDir)) { 17824 DVar = DSAStack->getImplicitDSA(D, true); 17825 if (DVar.CKind != OMPC_shared) { 17826 Diag(ELoc, diag::err_omp_required_access) 17827 << getOpenMPClauseName(OMPC_lastprivate) 17828 << getOpenMPClauseName(OMPC_shared); 17829 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 17830 continue; 17831 } 17832 } 17833 17834 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2] 17835 // A variable of class type (or array thereof) that appears in a 17836 // lastprivate clause requires an accessible, unambiguous default 17837 // constructor for the class type, unless the list item is also specified 17838 // in a firstprivate clause. 17839 // A variable of class type (or array thereof) that appears in a 17840 // lastprivate clause requires an accessible, unambiguous copy assignment 17841 // operator for the class type. 17842 Type = getASTContext().getBaseElementType(Type).getNonReferenceType(); 17843 VarDecl *SrcVD = buildVarDecl(SemaRef, ERange.getBegin(), 17844 Type.getUnqualifiedType(), ".lastprivate.src", 17845 D->hasAttrs() ? &D->getAttrs() : nullptr); 17846 DeclRefExpr *PseudoSrcExpr = 17847 buildDeclRefExpr(SemaRef, SrcVD, Type.getUnqualifiedType(), ELoc); 17848 VarDecl *DstVD = 17849 buildVarDecl(SemaRef, ERange.getBegin(), Type, ".lastprivate.dst", 17850 D->hasAttrs() ? &D->getAttrs() : nullptr); 17851 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc); 17852 // For arrays generate assignment operation for single element and replace 17853 // it by the original array element in CodeGen. 17854 ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign, 17855 PseudoDstExpr, PseudoSrcExpr); 17856 if (AssignmentOp.isInvalid()) 17857 continue; 17858 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc, 17859 /*DiscardedValue=*/false); 17860 if (AssignmentOp.isInvalid()) 17861 continue; 17862 17863 DeclRefExpr *Ref = nullptr; 17864 if (!VD && !SemaRef.CurContext->isDependentContext()) { 17865 if (TopDVar.CKind == OMPC_firstprivate) { 17866 Ref = TopDVar.PrivateCopy; 17867 } else { 17868 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false); 17869 if (!isOpenMPCapturedDecl(D)) 17870 ExprCaptures.push_back(Ref->getDecl()); 17871 } 17872 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) || 17873 (!isOpenMPCapturedDecl(D) && 17874 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) { 17875 ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref); 17876 if (!RefRes.isUsable()) 17877 continue; 17878 ExprResult PostUpdateRes = 17879 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign, 17880 SimpleRefExpr, RefRes.get()); 17881 if (!PostUpdateRes.isUsable()) 17882 continue; 17883 ExprPostUpdates.push_back( 17884 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get()); 17885 } 17886 } 17887 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref); 17888 Vars.push_back((VD || SemaRef.CurContext->isDependentContext()) 17889 ? RefExpr->IgnoreParens() 17890 : Ref); 17891 SrcExprs.push_back(PseudoSrcExpr); 17892 DstExprs.push_back(PseudoDstExpr); 17893 AssignmentOps.push_back(AssignmentOp.get()); 17894 } 17895 17896 if (Vars.empty()) 17897 return nullptr; 17898 17899 return OMPLastprivateClause::Create( 17900 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs, 17901 AssignmentOps, LPKind, LPKindLoc, ColonLoc, 17902 buildPreInits(getASTContext(), ExprCaptures), 17903 buildPostUpdate(SemaRef, ExprPostUpdates)); 17904 } 17905 17906 OMPClause *SemaOpenMP::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList, 17907 SourceLocation StartLoc, 17908 SourceLocation LParenLoc, 17909 SourceLocation EndLoc) { 17910 SmallVector<Expr *, 8> Vars; 17911 for (Expr *RefExpr : VarList) { 17912 assert(RefExpr && "NULL expr in OpenMP lastprivate clause."); 17913 SourceLocation ELoc; 17914 SourceRange ERange; 17915 Expr *SimpleRefExpr = RefExpr; 17916 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); 17917 if (Res.second) { 17918 // It will be analyzed later. 17919 Vars.push_back(RefExpr); 17920 } 17921 ValueDecl *D = Res.first; 17922 if (!D) 17923 continue; 17924 17925 auto *VD = dyn_cast<VarDecl>(D); 17926 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 17927 // in a Construct] 17928 // Variables with the predetermined data-sharing attributes may not be 17929 // listed in data-sharing attributes clauses, except for the cases 17930 // listed below. For these exceptions only, listing a predetermined 17931 // variable in a data-sharing attribute clause is allowed and overrides 17932 // the variable's predetermined data-sharing attributes. 17933 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false); 17934 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared && 17935 DVar.RefExpr) { 17936 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind) 17937 << getOpenMPClauseName(OMPC_shared); 17938 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 17939 continue; 17940 } 17941 17942 DeclRefExpr *Ref = nullptr; 17943 if (!VD && isOpenMPCapturedDecl(D) && 17944 !SemaRef.CurContext->isDependentContext()) 17945 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true); 17946 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref); 17947 Vars.push_back((VD || !Ref || SemaRef.CurContext->isDependentContext()) 17948 ? RefExpr->IgnoreParens() 17949 : Ref); 17950 } 17951 17952 if (Vars.empty()) 17953 return nullptr; 17954 17955 return OMPSharedClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc, 17956 Vars); 17957 } 17958 17959 namespace { 17960 class DSARefChecker : public StmtVisitor<DSARefChecker, bool> { 17961 DSAStackTy *Stack; 17962 17963 public: 17964 bool VisitDeclRefExpr(DeclRefExpr *E) { 17965 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) { 17966 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false); 17967 if (DVar.CKind == OMPC_shared && !DVar.RefExpr) 17968 return false; 17969 if (DVar.CKind != OMPC_unknown) 17970 return true; 17971 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA( 17972 VD, 17973 [](OpenMPClauseKind C, bool AppliedToPointee, bool) { 17974 return isOpenMPPrivate(C) && !AppliedToPointee; 17975 }, 17976 [](OpenMPDirectiveKind) { return true; }, 17977 /*FromParent=*/true); 17978 return DVarPrivate.CKind != OMPC_unknown; 17979 } 17980 return false; 17981 } 17982 bool VisitStmt(Stmt *S) { 17983 for (Stmt *Child : S->children()) { 17984 if (Child && Visit(Child)) 17985 return true; 17986 } 17987 return false; 17988 } 17989 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {} 17990 }; 17991 } // namespace 17992 17993 namespace { 17994 // Transform MemberExpression for specified FieldDecl of current class to 17995 // DeclRefExpr to specified OMPCapturedExprDecl. 17996 class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> { 17997 typedef TreeTransform<TransformExprToCaptures> BaseTransform; 17998 ValueDecl *Field = nullptr; 17999 DeclRefExpr *CapturedExpr = nullptr; 18000 18001 public: 18002 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl) 18003 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {} 18004 18005 ExprResult TransformMemberExpr(MemberExpr *E) { 18006 if (isa<CXXThisExpr>(E->getBase()->IgnoreParenImpCasts()) && 18007 E->getMemberDecl() == Field) { 18008 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false); 18009 return CapturedExpr; 18010 } 18011 return BaseTransform::TransformMemberExpr(E); 18012 } 18013 DeclRefExpr *getCapturedExpr() { return CapturedExpr; } 18014 }; 18015 } // namespace 18016 18017 template <typename T, typename U> 18018 static T filterLookupForUDReductionAndMapper( 18019 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) { 18020 for (U &Set : Lookups) { 18021 for (auto *D : Set) { 18022 if (T Res = Gen(cast<ValueDecl>(D))) 18023 return Res; 18024 } 18025 } 18026 return T(); 18027 } 18028 18029 static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) { 18030 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case"); 18031 18032 for (auto *RD : D->redecls()) { 18033 // Don't bother with extra checks if we already know this one isn't visible. 18034 if (RD == D) 18035 continue; 18036 18037 auto ND = cast<NamedDecl>(RD); 18038 if (LookupResult::isVisible(SemaRef, ND)) 18039 return ND; 18040 } 18041 18042 return nullptr; 18043 } 18044 18045 static void 18046 argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id, 18047 SourceLocation Loc, QualType Ty, 18048 SmallVectorImpl<UnresolvedSet<8>> &Lookups) { 18049 // Find all of the associated namespaces and classes based on the 18050 // arguments we have. 18051 Sema::AssociatedNamespaceSet AssociatedNamespaces; 18052 Sema::AssociatedClassSet AssociatedClasses; 18053 OpaqueValueExpr OVE(Loc, Ty, VK_LValue); 18054 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces, 18055 AssociatedClasses); 18056 18057 // C++ [basic.lookup.argdep]p3: 18058 // Let X be the lookup set produced by unqualified lookup (3.4.1) 18059 // and let Y be the lookup set produced by argument dependent 18060 // lookup (defined as follows). If X contains [...] then Y is 18061 // empty. Otherwise Y is the set of declarations found in the 18062 // namespaces associated with the argument types as described 18063 // below. The set of declarations found by the lookup of the name 18064 // is the union of X and Y. 18065 // 18066 // Here, we compute Y and add its members to the overloaded 18067 // candidate set. 18068 for (auto *NS : AssociatedNamespaces) { 18069 // When considering an associated namespace, the lookup is the 18070 // same as the lookup performed when the associated namespace is 18071 // used as a qualifier (3.4.3.2) except that: 18072 // 18073 // -- Any using-directives in the associated namespace are 18074 // ignored. 18075 // 18076 // -- Any namespace-scope friend functions declared in 18077 // associated classes are visible within their respective 18078 // namespaces even if they are not visible during an ordinary 18079 // lookup (11.4). 18080 DeclContext::lookup_result R = NS->lookup(Id.getName()); 18081 for (auto *D : R) { 18082 auto *Underlying = D; 18083 if (auto *USD = dyn_cast<UsingShadowDecl>(D)) 18084 Underlying = USD->getTargetDecl(); 18085 18086 if (!isa<OMPDeclareReductionDecl>(Underlying) && 18087 !isa<OMPDeclareMapperDecl>(Underlying)) 18088 continue; 18089 18090 if (!SemaRef.isVisible(D)) { 18091 D = findAcceptableDecl(SemaRef, D); 18092 if (!D) 18093 continue; 18094 if (auto *USD = dyn_cast<UsingShadowDecl>(D)) 18095 Underlying = USD->getTargetDecl(); 18096 } 18097 Lookups.emplace_back(); 18098 Lookups.back().addDecl(Underlying); 18099 } 18100 } 18101 } 18102 18103 static ExprResult 18104 buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, 18105 Scope *S, CXXScopeSpec &ReductionIdScopeSpec, 18106 const DeclarationNameInfo &ReductionId, QualType Ty, 18107 CXXCastPath &BasePath, Expr *UnresolvedReduction) { 18108 if (ReductionIdScopeSpec.isInvalid()) 18109 return ExprError(); 18110 SmallVector<UnresolvedSet<8>, 4> Lookups; 18111 if (S) { 18112 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName); 18113 Lookup.suppressDiagnostics(); 18114 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec, 18115 /*ObjectType=*/QualType())) { 18116 NamedDecl *D = Lookup.getRepresentativeDecl(); 18117 do { 18118 S = S->getParent(); 18119 } while (S && !S->isDeclScope(D)); 18120 if (S) 18121 S = S->getParent(); 18122 Lookups.emplace_back(); 18123 Lookups.back().append(Lookup.begin(), Lookup.end()); 18124 Lookup.clear(); 18125 } 18126 } else if (auto *ULE = 18127 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) { 18128 Lookups.push_back(UnresolvedSet<8>()); 18129 Decl *PrevD = nullptr; 18130 for (NamedDecl *D : ULE->decls()) { 18131 if (D == PrevD) 18132 Lookups.push_back(UnresolvedSet<8>()); 18133 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D)) 18134 Lookups.back().addDecl(DRD); 18135 PrevD = D; 18136 } 18137 } 18138 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() || 18139 Ty->isInstantiationDependentType() || 18140 Ty->containsUnexpandedParameterPack() || 18141 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) { 18142 return !D->isInvalidDecl() && 18143 (D->getType()->isDependentType() || 18144 D->getType()->isInstantiationDependentType() || 18145 D->getType()->containsUnexpandedParameterPack()); 18146 })) { 18147 UnresolvedSet<8> ResSet; 18148 for (const UnresolvedSet<8> &Set : Lookups) { 18149 if (Set.empty()) 18150 continue; 18151 ResSet.append(Set.begin(), Set.end()); 18152 // The last item marks the end of all declarations at the specified scope. 18153 ResSet.addDecl(Set[Set.size() - 1]); 18154 } 18155 return UnresolvedLookupExpr::Create( 18156 SemaRef.Context, /*NamingClass=*/nullptr, 18157 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId, 18158 /*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false, 18159 /*KnownInstantiationDependent=*/false); 18160 } 18161 // Lookup inside the classes. 18162 // C++ [over.match.oper]p3: 18163 // For a unary operator @ with an operand of a type whose 18164 // cv-unqualified version is T1, and for a binary operator @ with 18165 // a left operand of a type whose cv-unqualified version is T1 and 18166 // a right operand of a type whose cv-unqualified version is T2, 18167 // three sets of candidate functions, designated member 18168 // candidates, non-member candidates and built-in candidates, are 18169 // constructed as follows: 18170 // -- If T1 is a complete class type or a class currently being 18171 // defined, the set of member candidates is the result of the 18172 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise, 18173 // the set of member candidates is empty. 18174 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName); 18175 Lookup.suppressDiagnostics(); 18176 if (const auto *TyRec = Ty->getAs<RecordType>()) { 18177 // Complete the type if it can be completed. 18178 // If the type is neither complete nor being defined, bail out now. 18179 if (SemaRef.isCompleteType(Loc, Ty) || TyRec->isBeingDefined() || 18180 TyRec->getDecl()->getDefinition()) { 18181 Lookup.clear(); 18182 SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl()); 18183 if (Lookup.empty()) { 18184 Lookups.emplace_back(); 18185 Lookups.back().append(Lookup.begin(), Lookup.end()); 18186 } 18187 } 18188 } 18189 // Perform ADL. 18190 if (SemaRef.getLangOpts().CPlusPlus) 18191 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups); 18192 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>( 18193 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * { 18194 if (!D->isInvalidDecl() && 18195 SemaRef.Context.hasSameType(D->getType(), Ty)) 18196 return D; 18197 return nullptr; 18198 })) 18199 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), 18200 VK_LValue, Loc); 18201 if (SemaRef.getLangOpts().CPlusPlus) { 18202 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>( 18203 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * { 18204 if (!D->isInvalidDecl() && 18205 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) && 18206 !Ty.isMoreQualifiedThan(D->getType(), 18207 SemaRef.getASTContext())) 18208 return D; 18209 return nullptr; 18210 })) { 18211 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, 18212 /*DetectVirtual=*/false); 18213 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) { 18214 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType( 18215 VD->getType().getUnqualifiedType()))) { 18216 if (SemaRef.CheckBaseClassAccess( 18217 Loc, VD->getType(), Ty, Paths.front(), 18218 /*DiagID=*/0) != Sema::AR_inaccessible) { 18219 SemaRef.BuildBasePathArray(Paths, BasePath); 18220 return SemaRef.BuildDeclRefExpr( 18221 VD, VD->getType().getNonReferenceType(), VK_LValue, Loc); 18222 } 18223 } 18224 } 18225 } 18226 } 18227 if (ReductionIdScopeSpec.isSet()) { 18228 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier) 18229 << Ty << Range; 18230 return ExprError(); 18231 } 18232 return ExprEmpty(); 18233 } 18234 18235 namespace { 18236 /// Data for the reduction-based clauses. 18237 struct ReductionData { 18238 /// List of original reduction items. 18239 SmallVector<Expr *, 8> Vars; 18240 /// List of private copies of the reduction items. 18241 SmallVector<Expr *, 8> Privates; 18242 /// LHS expressions for the reduction_op expressions. 18243 SmallVector<Expr *, 8> LHSs; 18244 /// RHS expressions for the reduction_op expressions. 18245 SmallVector<Expr *, 8> RHSs; 18246 /// Reduction operation expression. 18247 SmallVector<Expr *, 8> ReductionOps; 18248 /// inscan copy operation expressions. 18249 SmallVector<Expr *, 8> InscanCopyOps; 18250 /// inscan copy temp array expressions for prefix sums. 18251 SmallVector<Expr *, 8> InscanCopyArrayTemps; 18252 /// inscan copy temp array element expressions for prefix sums. 18253 SmallVector<Expr *, 8> InscanCopyArrayElems; 18254 /// Taskgroup descriptors for the corresponding reduction items in 18255 /// in_reduction clauses. 18256 SmallVector<Expr *, 8> TaskgroupDescriptors; 18257 /// List of captures for clause. 18258 SmallVector<Decl *, 4> ExprCaptures; 18259 /// List of postupdate expressions. 18260 SmallVector<Expr *, 4> ExprPostUpdates; 18261 /// Reduction modifier. 18262 unsigned RedModifier = 0; 18263 ReductionData() = delete; 18264 /// Reserves required memory for the reduction data. 18265 ReductionData(unsigned Size, unsigned Modifier = 0) : RedModifier(Modifier) { 18266 Vars.reserve(Size); 18267 Privates.reserve(Size); 18268 LHSs.reserve(Size); 18269 RHSs.reserve(Size); 18270 ReductionOps.reserve(Size); 18271 if (RedModifier == OMPC_REDUCTION_inscan) { 18272 InscanCopyOps.reserve(Size); 18273 InscanCopyArrayTemps.reserve(Size); 18274 InscanCopyArrayElems.reserve(Size); 18275 } 18276 TaskgroupDescriptors.reserve(Size); 18277 ExprCaptures.reserve(Size); 18278 ExprPostUpdates.reserve(Size); 18279 } 18280 /// Stores reduction item and reduction operation only (required for dependent 18281 /// reduction item). 18282 void push(Expr *Item, Expr *ReductionOp) { 18283 Vars.emplace_back(Item); 18284 Privates.emplace_back(nullptr); 18285 LHSs.emplace_back(nullptr); 18286 RHSs.emplace_back(nullptr); 18287 ReductionOps.emplace_back(ReductionOp); 18288 TaskgroupDescriptors.emplace_back(nullptr); 18289 if (RedModifier == OMPC_REDUCTION_inscan) { 18290 InscanCopyOps.push_back(nullptr); 18291 InscanCopyArrayTemps.push_back(nullptr); 18292 InscanCopyArrayElems.push_back(nullptr); 18293 } 18294 } 18295 /// Stores reduction data. 18296 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp, 18297 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp, 18298 Expr *CopyArrayElem) { 18299 Vars.emplace_back(Item); 18300 Privates.emplace_back(Private); 18301 LHSs.emplace_back(LHS); 18302 RHSs.emplace_back(RHS); 18303 ReductionOps.emplace_back(ReductionOp); 18304 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor); 18305 if (RedModifier == OMPC_REDUCTION_inscan) { 18306 InscanCopyOps.push_back(CopyOp); 18307 InscanCopyArrayTemps.push_back(CopyArrayTemp); 18308 InscanCopyArrayElems.push_back(CopyArrayElem); 18309 } else { 18310 assert(CopyOp == nullptr && CopyArrayTemp == nullptr && 18311 CopyArrayElem == nullptr && 18312 "Copy operation must be used for inscan reductions only."); 18313 } 18314 } 18315 }; 18316 } // namespace 18317 18318 static bool checkOMPArraySectionConstantForReduction( 18319 ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement, 18320 SmallVectorImpl<llvm::APSInt> &ArraySizes) { 18321 const Expr *Length = OASE->getLength(); 18322 if (Length == nullptr) { 18323 // For array sections of the form [1:] or [:], we would need to analyze 18324 // the lower bound... 18325 if (OASE->getColonLocFirst().isValid()) 18326 return false; 18327 18328 // This is an array subscript which has implicit length 1! 18329 SingleElement = true; 18330 ArraySizes.push_back(llvm::APSInt::get(1)); 18331 } else { 18332 Expr::EvalResult Result; 18333 if (!Length->EvaluateAsInt(Result, Context)) 18334 return false; 18335 18336 llvm::APSInt ConstantLengthValue = Result.Val.getInt(); 18337 SingleElement = (ConstantLengthValue.getSExtValue() == 1); 18338 ArraySizes.push_back(ConstantLengthValue); 18339 } 18340 18341 // Get the base of this array section and walk up from there. 18342 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts(); 18343 18344 // We require length = 1 for all array sections except the right-most to 18345 // guarantee that the memory region is contiguous and has no holes in it. 18346 while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Base)) { 18347 Length = TempOASE->getLength(); 18348 if (Length == nullptr) { 18349 // For array sections of the form [1:] or [:], we would need to analyze 18350 // the lower bound... 18351 if (OASE->getColonLocFirst().isValid()) 18352 return false; 18353 18354 // This is an array subscript which has implicit length 1! 18355 llvm::APSInt ConstantOne = llvm::APSInt::get(1); 18356 ArraySizes.push_back(ConstantOne); 18357 } else { 18358 Expr::EvalResult Result; 18359 if (!Length->EvaluateAsInt(Result, Context)) 18360 return false; 18361 18362 llvm::APSInt ConstantLengthValue = Result.Val.getInt(); 18363 if (ConstantLengthValue.getSExtValue() != 1) 18364 return false; 18365 18366 ArraySizes.push_back(ConstantLengthValue); 18367 } 18368 Base = TempOASE->getBase()->IgnoreParenImpCasts(); 18369 } 18370 18371 // If we have a single element, we don't need to add the implicit lengths. 18372 if (!SingleElement) { 18373 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) { 18374 // Has implicit length 1! 18375 llvm::APSInt ConstantOne = llvm::APSInt::get(1); 18376 ArraySizes.push_back(ConstantOne); 18377 Base = TempASE->getBase()->IgnoreParenImpCasts(); 18378 } 18379 } 18380 18381 // This array section can be privatized as a single value or as a constant 18382 // sized array. 18383 return true; 18384 } 18385 18386 static BinaryOperatorKind 18387 getRelatedCompoundReductionOp(BinaryOperatorKind BOK) { 18388 if (BOK == BO_Add) 18389 return BO_AddAssign; 18390 if (BOK == BO_Mul) 18391 return BO_MulAssign; 18392 if (BOK == BO_And) 18393 return BO_AndAssign; 18394 if (BOK == BO_Or) 18395 return BO_OrAssign; 18396 if (BOK == BO_Xor) 18397 return BO_XorAssign; 18398 return BOK; 18399 } 18400 18401 static bool actOnOMPReductionKindClause( 18402 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind, 18403 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, 18404 SourceLocation ColonLoc, SourceLocation EndLoc, 18405 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, 18406 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) { 18407 DeclarationName DN = ReductionId.getName(); 18408 OverloadedOperatorKind OOK = DN.getCXXOverloadedOperator(); 18409 BinaryOperatorKind BOK = BO_Comma; 18410 18411 ASTContext &Context = S.Context; 18412 // OpenMP [2.14.3.6, reduction clause] 18413 // C 18414 // reduction-identifier is either an identifier or one of the following 18415 // operators: +, -, *, &, |, ^, && and || 18416 // C++ 18417 // reduction-identifier is either an id-expression or one of the following 18418 // operators: +, -, *, &, |, ^, && and || 18419 switch (OOK) { 18420 case OO_Plus: 18421 BOK = BO_Add; 18422 break; 18423 case OO_Minus: 18424 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to 18425 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed 18426 // reduction identifier. 18427 if (S.LangOpts.OpenMP > 52) 18428 BOK = BO_Comma; 18429 else 18430 BOK = BO_Add; 18431 break; 18432 case OO_Star: 18433 BOK = BO_Mul; 18434 break; 18435 case OO_Amp: 18436 BOK = BO_And; 18437 break; 18438 case OO_Pipe: 18439 BOK = BO_Or; 18440 break; 18441 case OO_Caret: 18442 BOK = BO_Xor; 18443 break; 18444 case OO_AmpAmp: 18445 BOK = BO_LAnd; 18446 break; 18447 case OO_PipePipe: 18448 BOK = BO_LOr; 18449 break; 18450 case OO_New: 18451 case OO_Delete: 18452 case OO_Array_New: 18453 case OO_Array_Delete: 18454 case OO_Slash: 18455 case OO_Percent: 18456 case OO_Tilde: 18457 case OO_Exclaim: 18458 case OO_Equal: 18459 case OO_Less: 18460 case OO_Greater: 18461 case OO_LessEqual: 18462 case OO_GreaterEqual: 18463 case OO_PlusEqual: 18464 case OO_MinusEqual: 18465 case OO_StarEqual: 18466 case OO_SlashEqual: 18467 case OO_PercentEqual: 18468 case OO_CaretEqual: 18469 case OO_AmpEqual: 18470 case OO_PipeEqual: 18471 case OO_LessLess: 18472 case OO_GreaterGreater: 18473 case OO_LessLessEqual: 18474 case OO_GreaterGreaterEqual: 18475 case OO_EqualEqual: 18476 case OO_ExclaimEqual: 18477 case OO_Spaceship: 18478 case OO_PlusPlus: 18479 case OO_MinusMinus: 18480 case OO_Comma: 18481 case OO_ArrowStar: 18482 case OO_Arrow: 18483 case OO_Call: 18484 case OO_Subscript: 18485 case OO_Conditional: 18486 case OO_Coawait: 18487 case NUM_OVERLOADED_OPERATORS: 18488 llvm_unreachable("Unexpected reduction identifier"); 18489 case OO_None: 18490 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) { 18491 if (II->isStr("max")) 18492 BOK = BO_GT; 18493 else if (II->isStr("min")) 18494 BOK = BO_LT; 18495 } 18496 break; 18497 } 18498 18499 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions 18500 // A reduction clause with the minus (-) operator was deprecated 18501 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52) 18502 S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated); 18503 18504 SourceRange ReductionIdRange; 18505 if (ReductionIdScopeSpec.isValid()) 18506 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc()); 18507 else 18508 ReductionIdRange.setBegin(ReductionId.getBeginLoc()); 18509 ReductionIdRange.setEnd(ReductionId.getEndLoc()); 18510 18511 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end(); 18512 bool FirstIter = true; 18513 for (Expr *RefExpr : VarList) { 18514 assert(RefExpr && "nullptr expr in OpenMP reduction clause."); 18515 // OpenMP [2.1, C/C++] 18516 // A list item is a variable or array section, subject to the restrictions 18517 // specified in Section 2.4 on page 42 and in each of the sections 18518 // describing clauses and directives for which a list appears. 18519 // OpenMP [2.14.3.3, Restrictions, p.1] 18520 // A variable that is part of another variable (as an array or 18521 // structure element) cannot appear in a private clause. 18522 if (!FirstIter && IR != ER) 18523 ++IR; 18524 FirstIter = false; 18525 SourceLocation ELoc; 18526 SourceRange ERange; 18527 Expr *SimpleRefExpr = RefExpr; 18528 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange, 18529 /*AllowArraySection=*/true); 18530 if (Res.second) { 18531 // Try to find 'declare reduction' corresponding construct before using 18532 // builtin/overloaded operators. 18533 QualType Type = Context.DependentTy; 18534 CXXCastPath BasePath; 18535 ExprResult DeclareReductionRef = buildDeclareReductionRef( 18536 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec, 18537 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR); 18538 Expr *ReductionOp = nullptr; 18539 if (S.CurContext->isDependentContext() && 18540 (DeclareReductionRef.isUnset() || 18541 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) 18542 ReductionOp = DeclareReductionRef.get(); 18543 // It will be analyzed later. 18544 RD.push(RefExpr, ReductionOp); 18545 } 18546 ValueDecl *D = Res.first; 18547 if (!D) 18548 continue; 18549 18550 Expr *TaskgroupDescriptor = nullptr; 18551 QualType Type; 18552 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens()); 18553 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens()); 18554 if (ASE) { 18555 Type = ASE->getType().getNonReferenceType(); 18556 } else if (OASE) { 18557 QualType BaseType = 18558 ArraySectionExpr::getBaseOriginalType(OASE->getBase()); 18559 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe()) 18560 Type = ATy->getElementType(); 18561 else 18562 Type = BaseType->getPointeeType(); 18563 Type = Type.getNonReferenceType(); 18564 } else { 18565 Type = Context.getBaseElementType(D->getType().getNonReferenceType()); 18566 } 18567 auto *VD = dyn_cast<VarDecl>(D); 18568 18569 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3] 18570 // A variable that appears in a private clause must not have an incomplete 18571 // type or a reference type. 18572 if (S.RequireCompleteType(ELoc, D->getType(), 18573 diag::err_omp_reduction_incomplete_type)) 18574 continue; 18575 // OpenMP [2.14.3.6, reduction clause, Restrictions] 18576 // A list item that appears in a reduction clause must not be 18577 // const-qualified. 18578 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc, 18579 /*AcceptIfMutable=*/false, ASE || OASE)) 18580 continue; 18581 18582 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective(); 18583 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4] 18584 // If a list-item is a reference type then it must bind to the same object 18585 // for all threads of the team. 18586 if (!ASE && !OASE) { 18587 if (VD) { 18588 VarDecl *VDDef = VD->getDefinition(); 18589 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) { 18590 DSARefChecker Check(Stack); 18591 if (Check.Visit(VDDef->getInit())) { 18592 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg) 18593 << getOpenMPClauseName(ClauseKind) << ERange; 18594 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef; 18595 continue; 18596 } 18597 } 18598 } 18599 18600 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced 18601 // in a Construct] 18602 // Variables with the predetermined data-sharing attributes may not be 18603 // listed in data-sharing attributes clauses, except for the cases 18604 // listed below. For these exceptions only, listing a predetermined 18605 // variable in a data-sharing attribute clause is allowed and overrides 18606 // the variable's predetermined data-sharing attributes. 18607 // OpenMP [2.14.3.6, Restrictions, p.3] 18608 // Any number of reduction clauses can be specified on the directive, 18609 // but a list item can appear only once in the reduction clauses for that 18610 // directive. 18611 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false); 18612 if (DVar.CKind == OMPC_reduction) { 18613 S.Diag(ELoc, diag::err_omp_once_referenced) 18614 << getOpenMPClauseName(ClauseKind); 18615 if (DVar.RefExpr) 18616 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced); 18617 continue; 18618 } 18619 if (DVar.CKind != OMPC_unknown) { 18620 S.Diag(ELoc, diag::err_omp_wrong_dsa) 18621 << getOpenMPClauseName(DVar.CKind) 18622 << getOpenMPClauseName(OMPC_reduction); 18623 reportOriginalDsa(S, Stack, D, DVar); 18624 continue; 18625 } 18626 18627 // OpenMP [2.14.3.6, Restrictions, p.1] 18628 // A list item that appears in a reduction clause of a worksharing 18629 // construct must be shared in the parallel regions to which any of the 18630 // worksharing regions arising from the worksharing construct bind. 18631 if (isOpenMPWorksharingDirective(CurrDir) && 18632 !isOpenMPParallelDirective(CurrDir) && 18633 !isOpenMPTeamsDirective(CurrDir)) { 18634 DVar = Stack->getImplicitDSA(D, true); 18635 if (DVar.CKind != OMPC_shared) { 18636 S.Diag(ELoc, diag::err_omp_required_access) 18637 << getOpenMPClauseName(OMPC_reduction) 18638 << getOpenMPClauseName(OMPC_shared); 18639 reportOriginalDsa(S, Stack, D, DVar); 18640 continue; 18641 } 18642 } 18643 } else { 18644 // Threadprivates cannot be shared between threads, so dignose if the base 18645 // is a threadprivate variable. 18646 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false); 18647 if (DVar.CKind == OMPC_threadprivate) { 18648 S.Diag(ELoc, diag::err_omp_wrong_dsa) 18649 << getOpenMPClauseName(DVar.CKind) 18650 << getOpenMPClauseName(OMPC_reduction); 18651 reportOriginalDsa(S, Stack, D, DVar); 18652 continue; 18653 } 18654 } 18655 18656 // Try to find 'declare reduction' corresponding construct before using 18657 // builtin/overloaded operators. 18658 CXXCastPath BasePath; 18659 ExprResult DeclareReductionRef = buildDeclareReductionRef( 18660 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec, 18661 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR); 18662 if (DeclareReductionRef.isInvalid()) 18663 continue; 18664 if (S.CurContext->isDependentContext() && 18665 (DeclareReductionRef.isUnset() || 18666 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) { 18667 RD.push(RefExpr, DeclareReductionRef.get()); 18668 continue; 18669 } 18670 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) { 18671 // Not allowed reduction identifier is found. 18672 if (S.LangOpts.OpenMP > 52) 18673 S.Diag(ReductionId.getBeginLoc(), 18674 diag::err_omp_unknown_reduction_identifier_since_omp_6_0) 18675 << Type << ReductionIdRange; 18676 else 18677 S.Diag(ReductionId.getBeginLoc(), 18678 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0) 18679 << Type << ReductionIdRange; 18680 continue; 18681 } 18682 18683 // OpenMP [2.14.3.6, reduction clause, Restrictions] 18684 // The type of a list item that appears in a reduction clause must be valid 18685 // for the reduction-identifier. For a max or min reduction in C, the type 18686 // of the list item must be an allowed arithmetic data type: char, int, 18687 // float, double, or _Bool, possibly modified with long, short, signed, or 18688 // unsigned. For a max or min reduction in C++, the type of the list item 18689 // must be an allowed arithmetic data type: char, wchar_t, int, float, 18690 // double, or bool, possibly modified with long, short, signed, or unsigned. 18691 if (DeclareReductionRef.isUnset()) { 18692 if ((BOK == BO_GT || BOK == BO_LT) && 18693 !(Type->isScalarType() || 18694 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) { 18695 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg) 18696 << getOpenMPClauseName(ClauseKind) << S.getLangOpts().CPlusPlus; 18697 if (!ASE && !OASE) { 18698 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) == 18699 VarDecl::DeclarationOnly; 18700 S.Diag(D->getLocation(), 18701 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 18702 << D; 18703 } 18704 continue; 18705 } 18706 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) && 18707 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) { 18708 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg) 18709 << getOpenMPClauseName(ClauseKind); 18710 if (!ASE && !OASE) { 18711 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) == 18712 VarDecl::DeclarationOnly; 18713 S.Diag(D->getLocation(), 18714 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 18715 << D; 18716 } 18717 continue; 18718 } 18719 } 18720 18721 Type = Type.getNonLValueExprType(Context).getUnqualifiedType(); 18722 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs", 18723 D->hasAttrs() ? &D->getAttrs() : nullptr); 18724 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(), 18725 D->hasAttrs() ? &D->getAttrs() : nullptr); 18726 QualType PrivateTy = Type; 18727 18728 // Try if we can determine constant lengths for all array sections and avoid 18729 // the VLA. 18730 bool ConstantLengthOASE = false; 18731 if (OASE) { 18732 bool SingleElement; 18733 llvm::SmallVector<llvm::APSInt, 4> ArraySizes; 18734 ConstantLengthOASE = checkOMPArraySectionConstantForReduction( 18735 Context, OASE, SingleElement, ArraySizes); 18736 18737 // If we don't have a single element, we must emit a constant array type. 18738 if (ConstantLengthOASE && !SingleElement) { 18739 for (llvm::APSInt &Size : ArraySizes) 18740 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr, 18741 ArraySizeModifier::Normal, 18742 /*IndexTypeQuals=*/0); 18743 } 18744 } 18745 18746 if ((OASE && !ConstantLengthOASE) || 18747 (!OASE && !ASE && 18748 D->getType().getNonReferenceType()->isVariablyModifiedType())) { 18749 if (!Context.getTargetInfo().isVLASupported()) { 18750 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) { 18751 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE; 18752 S.Diag(ELoc, diag::note_vla_unsupported); 18753 continue; 18754 } else { 18755 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE; 18756 S.targetDiag(ELoc, diag::note_vla_unsupported); 18757 } 18758 } 18759 // For arrays/array sections only: 18760 // Create pseudo array type for private copy. The size for this array will 18761 // be generated during codegen. 18762 // For array subscripts or single variables Private Ty is the same as Type 18763 // (type of the variable or single array element). 18764 PrivateTy = Context.getVariableArrayType( 18765 Type, 18766 new (Context) 18767 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue), 18768 ArraySizeModifier::Normal, /*IndexTypeQuals=*/0, SourceRange()); 18769 } else if (!ASE && !OASE && 18770 Context.getAsArrayType(D->getType().getNonReferenceType())) { 18771 PrivateTy = D->getType().getNonReferenceType(); 18772 } 18773 // Private copy. 18774 VarDecl *PrivateVD = 18775 buildVarDecl(S, ELoc, PrivateTy, D->getName(), 18776 D->hasAttrs() ? &D->getAttrs() : nullptr, 18777 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr); 18778 // Add initializer for private variable. 18779 Expr *Init = nullptr; 18780 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc); 18781 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc); 18782 if (DeclareReductionRef.isUsable()) { 18783 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>(); 18784 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl()); 18785 if (DRD->getInitializer()) { 18786 Init = DRDRef; 18787 RHSVD->setInit(DRDRef); 18788 RHSVD->setInitStyle(VarDecl::CallInit); 18789 } 18790 } else { 18791 switch (BOK) { 18792 case BO_Add: 18793 case BO_Xor: 18794 case BO_Or: 18795 case BO_LOr: 18796 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'. 18797 if (Type->isScalarType() || Type->isAnyComplexType()) 18798 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get(); 18799 break; 18800 case BO_Mul: 18801 case BO_LAnd: 18802 if (Type->isScalarType() || Type->isAnyComplexType()) { 18803 // '*' and '&&' reduction ops - initializer is '1'. 18804 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get(); 18805 } 18806 break; 18807 case BO_And: { 18808 // '&' reduction op - initializer is '~0'. 18809 QualType OrigType = Type; 18810 if (auto *ComplexTy = OrigType->getAs<ComplexType>()) 18811 Type = ComplexTy->getElementType(); 18812 if (Type->isRealFloatingType()) { 18813 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue( 18814 Context.getFloatTypeSemantics(Type)); 18815 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true, 18816 Type, ELoc); 18817 } else if (Type->isScalarType()) { 18818 uint64_t Size = Context.getTypeSize(Type); 18819 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0); 18820 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size); 18821 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc); 18822 } 18823 if (Init && OrigType->isAnyComplexType()) { 18824 // Init = 0xFFFF + 0xFFFFi; 18825 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType); 18826 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get(); 18827 } 18828 Type = OrigType; 18829 break; 18830 } 18831 case BO_LT: 18832 case BO_GT: { 18833 // 'min' reduction op - initializer is 'Largest representable number in 18834 // the reduction list item type'. 18835 // 'max' reduction op - initializer is 'Least representable number in 18836 // the reduction list item type'. 18837 if (Type->isIntegerType() || Type->isPointerType()) { 18838 bool IsSigned = Type->hasSignedIntegerRepresentation(); 18839 uint64_t Size = Context.getTypeSize(Type); 18840 QualType IntTy = 18841 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned); 18842 llvm::APInt InitValue = 18843 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size) 18844 : llvm::APInt::getMinValue(Size) 18845 : IsSigned ? llvm::APInt::getSignedMaxValue(Size) 18846 : llvm::APInt::getMaxValue(Size); 18847 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc); 18848 if (Type->isPointerType()) { 18849 // Cast to pointer type. 18850 ExprResult CastExpr = S.BuildCStyleCastExpr( 18851 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init); 18852 if (CastExpr.isInvalid()) 18853 continue; 18854 Init = CastExpr.get(); 18855 } 18856 } else if (Type->isRealFloatingType()) { 18857 llvm::APFloat InitValue = llvm::APFloat::getLargest( 18858 Context.getFloatTypeSemantics(Type), BOK != BO_LT); 18859 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true, 18860 Type, ELoc); 18861 } 18862 break; 18863 } 18864 case BO_PtrMemD: 18865 case BO_PtrMemI: 18866 case BO_MulAssign: 18867 case BO_Div: 18868 case BO_Rem: 18869 case BO_Sub: 18870 case BO_Shl: 18871 case BO_Shr: 18872 case BO_LE: 18873 case BO_GE: 18874 case BO_EQ: 18875 case BO_NE: 18876 case BO_Cmp: 18877 case BO_AndAssign: 18878 case BO_XorAssign: 18879 case BO_OrAssign: 18880 case BO_Assign: 18881 case BO_AddAssign: 18882 case BO_SubAssign: 18883 case BO_DivAssign: 18884 case BO_RemAssign: 18885 case BO_ShlAssign: 18886 case BO_ShrAssign: 18887 case BO_Comma: 18888 llvm_unreachable("Unexpected reduction operation"); 18889 } 18890 } 18891 if (Init && DeclareReductionRef.isUnset()) { 18892 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false); 18893 // Store initializer for single element in private copy. Will be used 18894 // during codegen. 18895 PrivateVD->setInit(RHSVD->getInit()); 18896 PrivateVD->setInitStyle(RHSVD->getInitStyle()); 18897 } else if (!Init) { 18898 S.ActOnUninitializedDecl(RHSVD); 18899 // Store initializer for single element in private copy. Will be used 18900 // during codegen. 18901 PrivateVD->setInit(RHSVD->getInit()); 18902 PrivateVD->setInitStyle(RHSVD->getInitStyle()); 18903 } 18904 if (RHSVD->isInvalidDecl()) 18905 continue; 18906 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) { 18907 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible) 18908 << Type << ReductionIdRange; 18909 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) == 18910 VarDecl::DeclarationOnly; 18911 S.Diag(D->getLocation(), 18912 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 18913 << D; 18914 continue; 18915 } 18916 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc); 18917 ExprResult ReductionOp; 18918 if (DeclareReductionRef.isUsable()) { 18919 QualType RedTy = DeclareReductionRef.get()->getType(); 18920 QualType PtrRedTy = Context.getPointerType(RedTy); 18921 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE); 18922 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE); 18923 if (!BasePath.empty()) { 18924 LHS = S.DefaultLvalueConversion(LHS.get()); 18925 RHS = S.DefaultLvalueConversion(RHS.get()); 18926 LHS = ImplicitCastExpr::Create( 18927 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath, 18928 LHS.get()->getValueKind(), FPOptionsOverride()); 18929 RHS = ImplicitCastExpr::Create( 18930 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath, 18931 RHS.get()->getValueKind(), FPOptionsOverride()); 18932 } 18933 FunctionProtoType::ExtProtoInfo EPI; 18934 QualType Params[] = {PtrRedTy, PtrRedTy}; 18935 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI); 18936 auto *OVE = new (Context) OpaqueValueExpr( 18937 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary, 18938 S.DefaultLvalueConversion(DeclareReductionRef.get()).get()); 18939 Expr *Args[] = {LHS.get(), RHS.get()}; 18940 ReductionOp = 18941 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc, 18942 S.CurFPFeatureOverrides()); 18943 } else { 18944 BinaryOperatorKind CombBOK = getRelatedCompoundReductionOp(BOK); 18945 if (Type->isRecordType() && CombBOK != BOK) { 18946 Sema::TentativeAnalysisScope Trap(S); 18947 ReductionOp = 18948 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), 18949 CombBOK, LHSDRE, RHSDRE); 18950 } 18951 if (!ReductionOp.isUsable()) { 18952 ReductionOp = 18953 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK, 18954 LHSDRE, RHSDRE); 18955 if (ReductionOp.isUsable()) { 18956 if (BOK != BO_LT && BOK != BO_GT) { 18957 ReductionOp = 18958 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), 18959 BO_Assign, LHSDRE, ReductionOp.get()); 18960 } else { 18961 auto *ConditionalOp = new (Context) 18962 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc, 18963 RHSDRE, Type, VK_LValue, OK_Ordinary); 18964 ReductionOp = 18965 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), 18966 BO_Assign, LHSDRE, ConditionalOp); 18967 } 18968 } 18969 } 18970 if (ReductionOp.isUsable()) 18971 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(), 18972 /*DiscardedValue=*/false); 18973 if (!ReductionOp.isUsable()) 18974 continue; 18975 } 18976 18977 // Add copy operations for inscan reductions. 18978 // LHS = RHS; 18979 ExprResult CopyOpRes, TempArrayRes, TempArrayElem; 18980 if (ClauseKind == OMPC_reduction && 18981 RD.RedModifier == OMPC_REDUCTION_inscan) { 18982 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE); 18983 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE, 18984 RHS.get()); 18985 if (!CopyOpRes.isUsable()) 18986 continue; 18987 CopyOpRes = 18988 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true); 18989 if (!CopyOpRes.isUsable()) 18990 continue; 18991 // For simd directive and simd-based directives in simd mode no need to 18992 // construct temp array, need just a single temp element. 18993 if (Stack->getCurrentDirective() == OMPD_simd || 18994 (S.getLangOpts().OpenMPSimd && 18995 isOpenMPSimdDirective(Stack->getCurrentDirective()))) { 18996 VarDecl *TempArrayVD = 18997 buildVarDecl(S, ELoc, PrivateTy, D->getName(), 18998 D->hasAttrs() ? &D->getAttrs() : nullptr); 18999 // Add a constructor to the temp decl. 19000 S.ActOnUninitializedDecl(TempArrayVD); 19001 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc); 19002 } else { 19003 // Build temp array for prefix sum. 19004 auto *Dim = new (S.Context) 19005 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue); 19006 QualType ArrayTy = S.Context.getVariableArrayType( 19007 PrivateTy, Dim, ArraySizeModifier::Normal, 19008 /*IndexTypeQuals=*/0, {ELoc, ELoc}); 19009 VarDecl *TempArrayVD = 19010 buildVarDecl(S, ELoc, ArrayTy, D->getName(), 19011 D->hasAttrs() ? &D->getAttrs() : nullptr); 19012 // Add a constructor to the temp decl. 19013 S.ActOnUninitializedDecl(TempArrayVD); 19014 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc); 19015 TempArrayElem = 19016 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get()); 19017 auto *Idx = new (S.Context) 19018 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue); 19019 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(), 19020 ELoc, Idx, ELoc); 19021 } 19022 } 19023 19024 // OpenMP [2.15.4.6, Restrictions, p.2] 19025 // A list item that appears in an in_reduction clause of a task construct 19026 // must appear in a task_reduction clause of a construct associated with a 19027 // taskgroup region that includes the participating task in its taskgroup 19028 // set. The construct associated with the innermost region that meets this 19029 // condition must specify the same reduction-identifier as the in_reduction 19030 // clause. 19031 if (ClauseKind == OMPC_in_reduction) { 19032 SourceRange ParentSR; 19033 BinaryOperatorKind ParentBOK; 19034 const Expr *ParentReductionOp = nullptr; 19035 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr; 19036 DSAStackTy::DSAVarData ParentBOKDSA = 19037 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK, 19038 ParentBOKTD); 19039 DSAStackTy::DSAVarData ParentReductionOpDSA = 19040 Stack->getTopMostTaskgroupReductionData( 19041 D, ParentSR, ParentReductionOp, ParentReductionOpTD); 19042 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown; 19043 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown; 19044 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) || 19045 (DeclareReductionRef.isUsable() && IsParentBOK) || 19046 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) { 19047 bool EmitError = true; 19048 if (IsParentReductionOp && DeclareReductionRef.isUsable()) { 19049 llvm::FoldingSetNodeID RedId, ParentRedId; 19050 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true); 19051 DeclareReductionRef.get()->Profile(RedId, Context, 19052 /*Canonical=*/true); 19053 EmitError = RedId != ParentRedId; 19054 } 19055 if (EmitError) { 19056 S.Diag(ReductionId.getBeginLoc(), 19057 diag::err_omp_reduction_identifier_mismatch) 19058 << ReductionIdRange << RefExpr->getSourceRange(); 19059 S.Diag(ParentSR.getBegin(), 19060 diag::note_omp_previous_reduction_identifier) 19061 << ParentSR 19062 << (IsParentBOK ? ParentBOKDSA.RefExpr 19063 : ParentReductionOpDSA.RefExpr) 19064 ->getSourceRange(); 19065 continue; 19066 } 19067 } 19068 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD; 19069 } 19070 19071 DeclRefExpr *Ref = nullptr; 19072 Expr *VarsExpr = RefExpr->IgnoreParens(); 19073 if (!VD && !S.CurContext->isDependentContext()) { 19074 if (ASE || OASE) { 19075 TransformExprToCaptures RebuildToCapture(S, D); 19076 VarsExpr = 19077 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get(); 19078 Ref = RebuildToCapture.getCapturedExpr(); 19079 } else { 19080 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false); 19081 } 19082 if (!S.OpenMP().isOpenMPCapturedDecl(D)) { 19083 RD.ExprCaptures.emplace_back(Ref->getDecl()); 19084 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) { 19085 ExprResult RefRes = S.DefaultLvalueConversion(Ref); 19086 if (!RefRes.isUsable()) 19087 continue; 19088 ExprResult PostUpdateRes = 19089 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr, 19090 RefRes.get()); 19091 if (!PostUpdateRes.isUsable()) 19092 continue; 19093 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) || 19094 Stack->getCurrentDirective() == OMPD_taskgroup) { 19095 S.Diag(RefExpr->getExprLoc(), 19096 diag::err_omp_reduction_non_addressable_expression) 19097 << RefExpr->getSourceRange(); 19098 continue; 19099 } 19100 RD.ExprPostUpdates.emplace_back( 19101 S.IgnoredValueConversions(PostUpdateRes.get()).get()); 19102 } 19103 } 19104 } 19105 // All reduction items are still marked as reduction (to do not increase 19106 // code base size). 19107 unsigned Modifier = RD.RedModifier; 19108 // Consider task_reductions as reductions with task modifier. Required for 19109 // correct analysis of in_reduction clauses. 19110 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction) 19111 Modifier = OMPC_REDUCTION_task; 19112 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier, 19113 ASE || OASE); 19114 if (Modifier == OMPC_REDUCTION_task && 19115 (CurrDir == OMPD_taskgroup || 19116 ((isOpenMPParallelDirective(CurrDir) || 19117 isOpenMPWorksharingDirective(CurrDir)) && 19118 !isOpenMPSimdDirective(CurrDir)))) { 19119 if (DeclareReductionRef.isUsable()) 19120 Stack->addTaskgroupReductionData(D, ReductionIdRange, 19121 DeclareReductionRef.get()); 19122 else 19123 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK); 19124 } 19125 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(), 19126 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(), 19127 TempArrayElem.get()); 19128 } 19129 return RD.Vars.empty(); 19130 } 19131 19132 OMPClause *SemaOpenMP::ActOnOpenMPReductionClause( 19133 ArrayRef<Expr *> VarList, OpenMPReductionClauseModifier Modifier, 19134 SourceLocation StartLoc, SourceLocation LParenLoc, 19135 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, 19136 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, 19137 ArrayRef<Expr *> UnresolvedReductions) { 19138 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) { 19139 Diag(LParenLoc, diag::err_omp_unexpected_clause_value) 19140 << getListOfPossibleValues(OMPC_reduction, /*First=*/0, 19141 /*Last=*/OMPC_REDUCTION_unknown) 19142 << getOpenMPClauseName(OMPC_reduction); 19143 return nullptr; 19144 } 19145 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions 19146 // A reduction clause with the inscan reduction-modifier may only appear on a 19147 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd 19148 // construct, a parallel worksharing-loop construct or a parallel 19149 // worksharing-loop SIMD construct. 19150 if (Modifier == OMPC_REDUCTION_inscan && 19151 (DSAStack->getCurrentDirective() != OMPD_for && 19152 DSAStack->getCurrentDirective() != OMPD_for_simd && 19153 DSAStack->getCurrentDirective() != OMPD_simd && 19154 DSAStack->getCurrentDirective() != OMPD_parallel_for && 19155 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) { 19156 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction); 19157 return nullptr; 19158 } 19159 19160 ReductionData RD(VarList.size(), Modifier); 19161 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_reduction, VarList, 19162 StartLoc, LParenLoc, ColonLoc, EndLoc, 19163 ReductionIdScopeSpec, ReductionId, 19164 UnresolvedReductions, RD)) 19165 return nullptr; 19166 19167 return OMPReductionClause::Create( 19168 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc, 19169 Modifier, RD.Vars, 19170 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId, 19171 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps, 19172 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems, 19173 buildPreInits(getASTContext(), RD.ExprCaptures), 19174 buildPostUpdate(SemaRef, RD.ExprPostUpdates)); 19175 } 19176 19177 OMPClause *SemaOpenMP::ActOnOpenMPTaskReductionClause( 19178 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, 19179 SourceLocation ColonLoc, SourceLocation EndLoc, 19180 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, 19181 ArrayRef<Expr *> UnresolvedReductions) { 19182 ReductionData RD(VarList.size()); 19183 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_task_reduction, 19184 VarList, StartLoc, LParenLoc, ColonLoc, 19185 EndLoc, ReductionIdScopeSpec, ReductionId, 19186 UnresolvedReductions, RD)) 19187 return nullptr; 19188 19189 return OMPTaskReductionClause::Create( 19190 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars, 19191 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId, 19192 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, 19193 buildPreInits(getASTContext(), RD.ExprCaptures), 19194 buildPostUpdate(SemaRef, RD.ExprPostUpdates)); 19195 } 19196 19197 OMPClause *SemaOpenMP::ActOnOpenMPInReductionClause( 19198 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, 19199 SourceLocation ColonLoc, SourceLocation EndLoc, 19200 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, 19201 ArrayRef<Expr *> UnresolvedReductions) { 19202 ReductionData RD(VarList.size()); 19203 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_in_reduction, VarList, 19204 StartLoc, LParenLoc, ColonLoc, EndLoc, 19205 ReductionIdScopeSpec, ReductionId, 19206 UnresolvedReductions, RD)) 19207 return nullptr; 19208 19209 return OMPInReductionClause::Create( 19210 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars, 19211 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId, 19212 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors, 19213 buildPreInits(getASTContext(), RD.ExprCaptures), 19214 buildPostUpdate(SemaRef, RD.ExprPostUpdates)); 19215 } 19216 19217 bool SemaOpenMP::CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, 19218 SourceLocation LinLoc) { 19219 if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) || 19220 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) { 19221 Diag(LinLoc, diag::err_omp_wrong_linear_modifier) 19222 << getLangOpts().CPlusPlus; 19223 return true; 19224 } 19225 return false; 19226 } 19227 19228 bool SemaOpenMP::CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc, 19229 OpenMPLinearClauseKind LinKind, 19230 QualType Type, bool IsDeclareSimd) { 19231 const auto *VD = dyn_cast_or_null<VarDecl>(D); 19232 // A variable must not have an incomplete type or a reference type. 19233 if (SemaRef.RequireCompleteType(ELoc, Type, 19234 diag::err_omp_linear_incomplete_type)) 19235 return true; 19236 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) && 19237 !Type->isReferenceType()) { 19238 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference) 19239 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind); 19240 return true; 19241 } 19242 Type = Type.getNonReferenceType(); 19243 19244 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions] 19245 // A variable that is privatized must not have a const-qualified type 19246 // unless it is of class type with a mutable member. This restriction does 19247 // not apply to the firstprivate clause, nor to the linear clause on 19248 // declarative directives (like declare simd). 19249 if (!IsDeclareSimd && 19250 rejectConstNotMutableType(SemaRef, D, Type, OMPC_linear, ELoc)) 19251 return true; 19252 19253 // A list item must be of integral or pointer type. 19254 Type = Type.getUnqualifiedType().getCanonicalType(); 19255 const auto *Ty = Type.getTypePtrOrNull(); 19256 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() && 19257 !Ty->isIntegralType(getASTContext()) && !Ty->isPointerType())) { 19258 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type; 19259 if (D) { 19260 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) == 19261 VarDecl::DeclarationOnly; 19262 Diag(D->getLocation(), 19263 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 19264 << D; 19265 } 19266 return true; 19267 } 19268 return false; 19269 } 19270 19271 OMPClause *SemaOpenMP::ActOnOpenMPLinearClause( 19272 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc, 19273 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind, 19274 SourceLocation LinLoc, SourceLocation ColonLoc, 19275 SourceLocation StepModifierLoc, SourceLocation EndLoc) { 19276 SmallVector<Expr *, 8> Vars; 19277 SmallVector<Expr *, 8> Privates; 19278 SmallVector<Expr *, 8> Inits; 19279 SmallVector<Decl *, 4> ExprCaptures; 19280 SmallVector<Expr *, 4> ExprPostUpdates; 19281 // OpenMP 5.2 [Section 5.4.6, linear clause] 19282 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or 19283 // 'ref' 19284 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step && 19285 getLangOpts().OpenMP >= 52) 19286 Diag(Step->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive); 19287 if (CheckOpenMPLinearModifier(LinKind, LinLoc)) 19288 LinKind = OMPC_LINEAR_val; 19289 for (Expr *RefExpr : VarList) { 19290 assert(RefExpr && "NULL expr in OpenMP linear clause."); 19291 SourceLocation ELoc; 19292 SourceRange ERange; 19293 Expr *SimpleRefExpr = RefExpr; 19294 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); 19295 if (Res.second) { 19296 // It will be analyzed later. 19297 Vars.push_back(RefExpr); 19298 Privates.push_back(nullptr); 19299 Inits.push_back(nullptr); 19300 } 19301 ValueDecl *D = Res.first; 19302 if (!D) 19303 continue; 19304 19305 QualType Type = D->getType(); 19306 auto *VD = dyn_cast<VarDecl>(D); 19307 19308 // OpenMP [2.14.3.7, linear clause] 19309 // A list-item cannot appear in more than one linear clause. 19310 // A list-item that appears in a linear clause cannot appear in any 19311 // other data-sharing attribute clause. 19312 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false); 19313 if (DVar.RefExpr) { 19314 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind) 19315 << getOpenMPClauseName(OMPC_linear); 19316 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 19317 continue; 19318 } 19319 19320 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type)) 19321 continue; 19322 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType(); 19323 19324 // Build private copy of original var. 19325 VarDecl *Private = 19326 buildVarDecl(SemaRef, ELoc, Type, D->getName(), 19327 D->hasAttrs() ? &D->getAttrs() : nullptr, 19328 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr); 19329 DeclRefExpr *PrivateRef = buildDeclRefExpr(SemaRef, Private, Type, ELoc); 19330 // Build var to save initial value. 19331 VarDecl *Init = buildVarDecl(SemaRef, ELoc, Type, ".linear.start"); 19332 Expr *InitExpr; 19333 DeclRefExpr *Ref = nullptr; 19334 if (!VD && !SemaRef.CurContext->isDependentContext()) { 19335 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false); 19336 if (!isOpenMPCapturedDecl(D)) { 19337 ExprCaptures.push_back(Ref->getDecl()); 19338 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) { 19339 ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref); 19340 if (!RefRes.isUsable()) 19341 continue; 19342 ExprResult PostUpdateRes = 19343 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign, 19344 SimpleRefExpr, RefRes.get()); 19345 if (!PostUpdateRes.isUsable()) 19346 continue; 19347 ExprPostUpdates.push_back( 19348 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get()); 19349 } 19350 } 19351 } 19352 if (LinKind == OMPC_LINEAR_uval) 19353 InitExpr = VD ? VD->getInit() : SimpleRefExpr; 19354 else 19355 InitExpr = VD ? SimpleRefExpr : Ref; 19356 SemaRef.AddInitializerToDecl( 19357 Init, SemaRef.DefaultLvalueConversion(InitExpr).get(), 19358 /*DirectInit=*/false); 19359 DeclRefExpr *InitRef = buildDeclRefExpr(SemaRef, Init, Type, ELoc); 19360 19361 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref); 19362 Vars.push_back((VD || SemaRef.CurContext->isDependentContext()) 19363 ? RefExpr->IgnoreParens() 19364 : Ref); 19365 Privates.push_back(PrivateRef); 19366 Inits.push_back(InitRef); 19367 } 19368 19369 if (Vars.empty()) 19370 return nullptr; 19371 19372 Expr *StepExpr = Step; 19373 Expr *CalcStepExpr = nullptr; 19374 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() && 19375 !Step->isInstantiationDependent() && 19376 !Step->containsUnexpandedParameterPack()) { 19377 SourceLocation StepLoc = Step->getBeginLoc(); 19378 ExprResult Val = PerformOpenMPImplicitIntegerConversion(StepLoc, Step); 19379 if (Val.isInvalid()) 19380 return nullptr; 19381 StepExpr = Val.get(); 19382 19383 // Build var to save the step value. 19384 VarDecl *SaveVar = 19385 buildVarDecl(SemaRef, StepLoc, StepExpr->getType(), ".linear.step"); 19386 ExprResult SaveRef = 19387 buildDeclRefExpr(SemaRef, SaveVar, StepExpr->getType(), StepLoc); 19388 ExprResult CalcStep = SemaRef.BuildBinOp( 19389 SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.get(), StepExpr); 19390 CalcStep = 19391 SemaRef.ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue=*/false); 19392 19393 // Warn about zero linear step (it would be probably better specified as 19394 // making corresponding variables 'const'). 19395 if (std::optional<llvm::APSInt> Result = 19396 StepExpr->getIntegerConstantExpr(getASTContext())) { 19397 if (!Result->isNegative() && !Result->isStrictlyPositive()) 19398 Diag(StepLoc, diag::warn_omp_linear_step_zero) 19399 << Vars[0] << (Vars.size() > 1); 19400 } else if (CalcStep.isUsable()) { 19401 // Calculate the step beforehand instead of doing this on each iteration. 19402 // (This is not used if the number of iterations may be kfold-ed). 19403 CalcStepExpr = CalcStep.get(); 19404 } 19405 } 19406 19407 return OMPLinearClause::Create(getASTContext(), StartLoc, LParenLoc, LinKind, 19408 LinLoc, ColonLoc, StepModifierLoc, EndLoc, 19409 Vars, Privates, Inits, StepExpr, CalcStepExpr, 19410 buildPreInits(getASTContext(), ExprCaptures), 19411 buildPostUpdate(SemaRef, ExprPostUpdates)); 19412 } 19413 19414 static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, 19415 Expr *NumIterations, Sema &SemaRef, 19416 Scope *S, DSAStackTy *Stack) { 19417 // Walk the vars and build update/final expressions for the CodeGen. 19418 SmallVector<Expr *, 8> Updates; 19419 SmallVector<Expr *, 8> Finals; 19420 SmallVector<Expr *, 8> UsedExprs; 19421 Expr *Step = Clause.getStep(); 19422 Expr *CalcStep = Clause.getCalcStep(); 19423 // OpenMP [2.14.3.7, linear clause] 19424 // If linear-step is not specified it is assumed to be 1. 19425 if (!Step) 19426 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(); 19427 else if (CalcStep) 19428 Step = cast<BinaryOperator>(CalcStep)->getLHS(); 19429 bool HasErrors = false; 19430 auto CurInit = Clause.inits().begin(); 19431 auto CurPrivate = Clause.privates().begin(); 19432 OpenMPLinearClauseKind LinKind = Clause.getModifier(); 19433 for (Expr *RefExpr : Clause.varlist()) { 19434 SourceLocation ELoc; 19435 SourceRange ERange; 19436 Expr *SimpleRefExpr = RefExpr; 19437 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); 19438 ValueDecl *D = Res.first; 19439 if (Res.second || !D) { 19440 Updates.push_back(nullptr); 19441 Finals.push_back(nullptr); 19442 HasErrors = true; 19443 continue; 19444 } 19445 auto &&Info = Stack->isLoopControlVariable(D); 19446 // OpenMP [2.15.11, distribute simd Construct] 19447 // A list item may not appear in a linear clause, unless it is the loop 19448 // iteration variable. 19449 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) && 19450 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) { 19451 SemaRef.Diag(ELoc, 19452 diag::err_omp_linear_distribute_var_non_loop_iteration); 19453 Updates.push_back(nullptr); 19454 Finals.push_back(nullptr); 19455 HasErrors = true; 19456 continue; 19457 } 19458 Expr *InitExpr = *CurInit; 19459 19460 // Build privatized reference to the current linear var. 19461 auto *DE = cast<DeclRefExpr>(SimpleRefExpr); 19462 Expr *CapturedRef; 19463 if (LinKind == OMPC_LINEAR_uval) 19464 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit(); 19465 else 19466 CapturedRef = 19467 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()), 19468 DE->getType().getUnqualifiedType(), DE->getExprLoc(), 19469 /*RefersToCapture=*/true); 19470 19471 // Build update: Var = InitExpr + IV * Step 19472 ExprResult Update; 19473 if (!Info.first) 19474 Update = buildCounterUpdate( 19475 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step, 19476 /*Subtract=*/false, /*IsNonRectangularLB=*/false); 19477 else 19478 Update = *CurPrivate; 19479 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(), 19480 /*DiscardedValue=*/false); 19481 19482 // Build final: Var = PrivCopy; 19483 ExprResult Final; 19484 if (!Info.first) 19485 Final = SemaRef.BuildBinOp( 19486 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef, 19487 SemaRef.DefaultLvalueConversion(*CurPrivate).get()); 19488 else 19489 Final = *CurPrivate; 19490 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(), 19491 /*DiscardedValue=*/false); 19492 19493 if (!Update.isUsable() || !Final.isUsable()) { 19494 Updates.push_back(nullptr); 19495 Finals.push_back(nullptr); 19496 UsedExprs.push_back(nullptr); 19497 HasErrors = true; 19498 } else { 19499 Updates.push_back(Update.get()); 19500 Finals.push_back(Final.get()); 19501 if (!Info.first) 19502 UsedExprs.push_back(SimpleRefExpr); 19503 } 19504 ++CurInit; 19505 ++CurPrivate; 19506 } 19507 if (Expr *S = Clause.getStep()) 19508 UsedExprs.push_back(S); 19509 // Fill the remaining part with the nullptr. 19510 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr); 19511 Clause.setUpdates(Updates); 19512 Clause.setFinals(Finals); 19513 Clause.setUsedExprs(UsedExprs); 19514 return HasErrors; 19515 } 19516 19517 OMPClause *SemaOpenMP::ActOnOpenMPAlignedClause( 19518 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc, 19519 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) { 19520 SmallVector<Expr *, 8> Vars; 19521 for (Expr *RefExpr : VarList) { 19522 assert(RefExpr && "NULL expr in OpenMP linear clause."); 19523 SourceLocation ELoc; 19524 SourceRange ERange; 19525 Expr *SimpleRefExpr = RefExpr; 19526 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); 19527 if (Res.second) { 19528 // It will be analyzed later. 19529 Vars.push_back(RefExpr); 19530 } 19531 ValueDecl *D = Res.first; 19532 if (!D) 19533 continue; 19534 19535 QualType QType = D->getType(); 19536 auto *VD = dyn_cast<VarDecl>(D); 19537 19538 // OpenMP [2.8.1, simd construct, Restrictions] 19539 // The type of list items appearing in the aligned clause must be 19540 // array, pointer, reference to array, or reference to pointer. 19541 QType = QType.getNonReferenceType().getUnqualifiedType().getCanonicalType(); 19542 const Type *Ty = QType.getTypePtrOrNull(); 19543 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) { 19544 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr) 19545 << QType << getLangOpts().CPlusPlus << ERange; 19546 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) == 19547 VarDecl::DeclarationOnly; 19548 Diag(D->getLocation(), 19549 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 19550 << D; 19551 continue; 19552 } 19553 19554 // OpenMP [2.8.1, simd construct, Restrictions] 19555 // A list-item cannot appear in more than one aligned clause. 19556 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) { 19557 Diag(ELoc, diag::err_omp_used_in_clause_twice) 19558 << 0 << getOpenMPClauseName(OMPC_aligned) << ERange; 19559 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa) 19560 << getOpenMPClauseName(OMPC_aligned); 19561 continue; 19562 } 19563 19564 DeclRefExpr *Ref = nullptr; 19565 if (!VD && isOpenMPCapturedDecl(D)) 19566 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true); 19567 Vars.push_back(SemaRef 19568 .DefaultFunctionArrayConversion( 19569 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref) 19570 .get()); 19571 } 19572 19573 // OpenMP [2.8.1, simd construct, Description] 19574 // The parameter of the aligned clause, alignment, must be a constant 19575 // positive integer expression. 19576 // If no optional parameter is specified, implementation-defined default 19577 // alignments for SIMD instructions on the target platforms are assumed. 19578 if (Alignment != nullptr) { 19579 ExprResult AlignResult = 19580 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned); 19581 if (AlignResult.isInvalid()) 19582 return nullptr; 19583 Alignment = AlignResult.get(); 19584 } 19585 if (Vars.empty()) 19586 return nullptr; 19587 19588 return OMPAlignedClause::Create(getASTContext(), StartLoc, LParenLoc, 19589 ColonLoc, EndLoc, Vars, Alignment); 19590 } 19591 19592 OMPClause *SemaOpenMP::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList, 19593 SourceLocation StartLoc, 19594 SourceLocation LParenLoc, 19595 SourceLocation EndLoc) { 19596 SmallVector<Expr *, 8> Vars; 19597 SmallVector<Expr *, 8> SrcExprs; 19598 SmallVector<Expr *, 8> DstExprs; 19599 SmallVector<Expr *, 8> AssignmentOps; 19600 for (Expr *RefExpr : VarList) { 19601 assert(RefExpr && "NULL expr in OpenMP copyin clause."); 19602 if (isa<DependentScopeDeclRefExpr>(RefExpr)) { 19603 // It will be analyzed later. 19604 Vars.push_back(RefExpr); 19605 SrcExprs.push_back(nullptr); 19606 DstExprs.push_back(nullptr); 19607 AssignmentOps.push_back(nullptr); 19608 continue; 19609 } 19610 19611 SourceLocation ELoc = RefExpr->getExprLoc(); 19612 // OpenMP [2.1, C/C++] 19613 // A list item is a variable name. 19614 // OpenMP [2.14.4.1, Restrictions, p.1] 19615 // A list item that appears in a copyin clause must be threadprivate. 19616 auto *DE = dyn_cast<DeclRefExpr>(RefExpr); 19617 if (!DE || !isa<VarDecl>(DE->getDecl())) { 19618 Diag(ELoc, diag::err_omp_expected_var_name_member_expr) 19619 << 0 << RefExpr->getSourceRange(); 19620 continue; 19621 } 19622 19623 Decl *D = DE->getDecl(); 19624 auto *VD = cast<VarDecl>(D); 19625 19626 QualType Type = VD->getType(); 19627 if (Type->isDependentType() || Type->isInstantiationDependentType()) { 19628 // It will be analyzed later. 19629 Vars.push_back(DE); 19630 SrcExprs.push_back(nullptr); 19631 DstExprs.push_back(nullptr); 19632 AssignmentOps.push_back(nullptr); 19633 continue; 19634 } 19635 19636 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1] 19637 // A list item that appears in a copyin clause must be threadprivate. 19638 if (!DSAStack->isThreadPrivate(VD)) { 19639 Diag(ELoc, diag::err_omp_required_access) 19640 << getOpenMPClauseName(OMPC_copyin) 19641 << getOpenMPDirectiveName(OMPD_threadprivate); 19642 continue; 19643 } 19644 19645 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2] 19646 // A variable of class type (or array thereof) that appears in a 19647 // copyin clause requires an accessible, unambiguous copy assignment 19648 // operator for the class type. 19649 QualType ElemType = 19650 getASTContext().getBaseElementType(Type).getNonReferenceType(); 19651 VarDecl *SrcVD = 19652 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType.getUnqualifiedType(), 19653 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr); 19654 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr( 19655 SemaRef, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc()); 19656 VarDecl *DstVD = 19657 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType, ".copyin.dst", 19658 VD->hasAttrs() ? &VD->getAttrs() : nullptr); 19659 DeclRefExpr *PseudoDstExpr = 19660 buildDeclRefExpr(SemaRef, DstVD, ElemType, DE->getExprLoc()); 19661 // For arrays generate assignment operation for single element and replace 19662 // it by the original array element in CodeGen. 19663 ExprResult AssignmentOp = 19664 SemaRef.BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign, 19665 PseudoDstExpr, PseudoSrcExpr); 19666 if (AssignmentOp.isInvalid()) 19667 continue; 19668 AssignmentOp = 19669 SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(), 19670 /*DiscardedValue=*/false); 19671 if (AssignmentOp.isInvalid()) 19672 continue; 19673 19674 DSAStack->addDSA(VD, DE, OMPC_copyin); 19675 Vars.push_back(DE); 19676 SrcExprs.push_back(PseudoSrcExpr); 19677 DstExprs.push_back(PseudoDstExpr); 19678 AssignmentOps.push_back(AssignmentOp.get()); 19679 } 19680 19681 if (Vars.empty()) 19682 return nullptr; 19683 19684 return OMPCopyinClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc, 19685 Vars, SrcExprs, DstExprs, AssignmentOps); 19686 } 19687 19688 OMPClause *SemaOpenMP::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList, 19689 SourceLocation StartLoc, 19690 SourceLocation LParenLoc, 19691 SourceLocation EndLoc) { 19692 SmallVector<Expr *, 8> Vars; 19693 SmallVector<Expr *, 8> SrcExprs; 19694 SmallVector<Expr *, 8> DstExprs; 19695 SmallVector<Expr *, 8> AssignmentOps; 19696 for (Expr *RefExpr : VarList) { 19697 assert(RefExpr && "NULL expr in OpenMP linear clause."); 19698 SourceLocation ELoc; 19699 SourceRange ERange; 19700 Expr *SimpleRefExpr = RefExpr; 19701 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); 19702 if (Res.second) { 19703 // It will be analyzed later. 19704 Vars.push_back(RefExpr); 19705 SrcExprs.push_back(nullptr); 19706 DstExprs.push_back(nullptr); 19707 AssignmentOps.push_back(nullptr); 19708 } 19709 ValueDecl *D = Res.first; 19710 if (!D) 19711 continue; 19712 19713 QualType Type = D->getType(); 19714 auto *VD = dyn_cast<VarDecl>(D); 19715 19716 // OpenMP [2.14.4.2, Restrictions, p.2] 19717 // A list item that appears in a copyprivate clause may not appear in a 19718 // private or firstprivate clause on the single construct. 19719 if (!VD || !DSAStack->isThreadPrivate(VD)) { 19720 DSAStackTy::DSAVarData DVar = 19721 DSAStack->getTopDSA(D, /*FromParent=*/false); 19722 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate && 19723 DVar.RefExpr) { 19724 Diag(ELoc, diag::err_omp_wrong_dsa) 19725 << getOpenMPClauseName(DVar.CKind) 19726 << getOpenMPClauseName(OMPC_copyprivate); 19727 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 19728 continue; 19729 } 19730 19731 // OpenMP [2.11.4.2, Restrictions, p.1] 19732 // All list items that appear in a copyprivate clause must be either 19733 // threadprivate or private in the enclosing context. 19734 if (DVar.CKind == OMPC_unknown) { 19735 DVar = DSAStack->getImplicitDSA(D, false); 19736 if (DVar.CKind == OMPC_shared) { 19737 Diag(ELoc, diag::err_omp_required_access) 19738 << getOpenMPClauseName(OMPC_copyprivate) 19739 << "threadprivate or private in the enclosing context"; 19740 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 19741 continue; 19742 } 19743 } 19744 } 19745 19746 // Variably modified types are not supported. 19747 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType()) { 19748 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported) 19749 << getOpenMPClauseName(OMPC_copyprivate) << Type 19750 << getOpenMPDirectiveName(DSAStack->getCurrentDirective()); 19751 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) == 19752 VarDecl::DeclarationOnly; 19753 Diag(D->getLocation(), 19754 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 19755 << D; 19756 continue; 19757 } 19758 19759 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2] 19760 // A variable of class type (or array thereof) that appears in a 19761 // copyin clause requires an accessible, unambiguous copy assignment 19762 // operator for the class type. 19763 Type = getASTContext() 19764 .getBaseElementType(Type.getNonReferenceType()) 19765 .getUnqualifiedType(); 19766 VarDecl *SrcVD = 19767 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.src", 19768 D->hasAttrs() ? &D->getAttrs() : nullptr); 19769 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(SemaRef, SrcVD, Type, ELoc); 19770 VarDecl *DstVD = 19771 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.dst", 19772 D->hasAttrs() ? &D->getAttrs() : nullptr); 19773 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc); 19774 ExprResult AssignmentOp = SemaRef.BuildBinOp( 19775 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr); 19776 if (AssignmentOp.isInvalid()) 19777 continue; 19778 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc, 19779 /*DiscardedValue=*/false); 19780 if (AssignmentOp.isInvalid()) 19781 continue; 19782 19783 // No need to mark vars as copyprivate, they are already threadprivate or 19784 // implicitly private. 19785 assert(VD || isOpenMPCapturedDecl(D)); 19786 Vars.push_back( 19787 VD ? RefExpr->IgnoreParens() 19788 : buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false)); 19789 SrcExprs.push_back(PseudoSrcExpr); 19790 DstExprs.push_back(PseudoDstExpr); 19791 AssignmentOps.push_back(AssignmentOp.get()); 19792 } 19793 19794 if (Vars.empty()) 19795 return nullptr; 19796 19797 return OMPCopyprivateClause::Create(getASTContext(), StartLoc, LParenLoc, 19798 EndLoc, Vars, SrcExprs, DstExprs, 19799 AssignmentOps); 19800 } 19801 19802 OMPClause *SemaOpenMP::ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList, 19803 SourceLocation StartLoc, 19804 SourceLocation LParenLoc, 19805 SourceLocation EndLoc) { 19806 if (VarList.empty()) 19807 return nullptr; 19808 19809 return OMPFlushClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc, 19810 VarList); 19811 } 19812 19813 /// Tries to find omp_depend_t. type. 19814 static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack, 19815 bool Diagnose = true) { 19816 QualType OMPDependT = Stack->getOMPDependT(); 19817 if (!OMPDependT.isNull()) 19818 return true; 19819 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t"); 19820 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope()); 19821 if (!PT.getAsOpaquePtr() || PT.get().isNull()) { 19822 if (Diagnose) 19823 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t"; 19824 return false; 19825 } 19826 Stack->setOMPDependT(PT.get()); 19827 return true; 19828 } 19829 19830 OMPClause *SemaOpenMP::ActOnOpenMPDepobjClause(Expr *Depobj, 19831 SourceLocation StartLoc, 19832 SourceLocation LParenLoc, 19833 SourceLocation EndLoc) { 19834 if (!Depobj) 19835 return nullptr; 19836 19837 bool OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack); 19838 19839 // OpenMP 5.0, 2.17.10.1 depobj Construct 19840 // depobj is an lvalue expression of type omp_depend_t. 19841 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() && 19842 !Depobj->isInstantiationDependent() && 19843 !Depobj->containsUnexpandedParameterPack() && 19844 (OMPDependTFound && !getASTContext().typesAreCompatible( 19845 DSAStack->getOMPDependT(), Depobj->getType(), 19846 /*CompareUnqualified=*/true))) { 19847 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue) 19848 << 0 << Depobj->getType() << Depobj->getSourceRange(); 19849 } 19850 19851 if (!Depobj->isLValue()) { 19852 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue) 19853 << 1 << Depobj->getSourceRange(); 19854 } 19855 19856 return OMPDepobjClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc, 19857 Depobj); 19858 } 19859 19860 namespace { 19861 // Utility struct that gathers the related info for doacross clause. 19862 struct DoacrossDataInfoTy { 19863 // The list of expressions. 19864 SmallVector<Expr *, 8> Vars; 19865 // The OperatorOffset for doacross loop. 19866 DSAStackTy::OperatorOffsetTy OpsOffs; 19867 // The depended loop count. 19868 llvm::APSInt TotalDepCount; 19869 }; 19870 } // namespace 19871 static DoacrossDataInfoTy 19872 ProcessOpenMPDoacrossClauseCommon(Sema &SemaRef, bool IsSource, 19873 ArrayRef<Expr *> VarList, DSAStackTy *Stack, 19874 SourceLocation EndLoc) { 19875 19876 SmallVector<Expr *, 8> Vars; 19877 DSAStackTy::OperatorOffsetTy OpsOffs; 19878 llvm::APSInt DepCounter(/*BitWidth=*/32); 19879 llvm::APSInt TotalDepCount(/*BitWidth=*/32); 19880 19881 if (const Expr *OrderedCountExpr = 19882 Stack->getParentOrderedRegionParam().first) { 19883 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.Context); 19884 TotalDepCount.setIsUnsigned(/*Val=*/true); 19885 } 19886 19887 for (Expr *RefExpr : VarList) { 19888 assert(RefExpr && "NULL expr in OpenMP doacross clause."); 19889 if (isa<DependentScopeDeclRefExpr>(RefExpr)) { 19890 // It will be analyzed later. 19891 Vars.push_back(RefExpr); 19892 continue; 19893 } 19894 19895 SourceLocation ELoc = RefExpr->getExprLoc(); 19896 Expr *SimpleExpr = RefExpr->IgnoreParenCasts(); 19897 if (!IsSource) { 19898 if (Stack->getParentOrderedRegionParam().first && 19899 DepCounter >= TotalDepCount) { 19900 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr); 19901 continue; 19902 } 19903 ++DepCounter; 19904 // OpenMP [2.13.9, Summary] 19905 // depend(dependence-type : vec), where dependence-type is: 19906 // 'sink' and where vec is the iteration vector, which has the form: 19907 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn] 19908 // where n is the value specified by the ordered clause in the loop 19909 // directive, xi denotes the loop iteration variable of the i-th nested 19910 // loop associated with the loop directive, and di is a constant 19911 // non-negative integer. 19912 if (SemaRef.CurContext->isDependentContext()) { 19913 // It will be analyzed later. 19914 Vars.push_back(RefExpr); 19915 continue; 19916 } 19917 SimpleExpr = SimpleExpr->IgnoreImplicit(); 19918 OverloadedOperatorKind OOK = OO_None; 19919 SourceLocation OOLoc; 19920 Expr *LHS = SimpleExpr; 19921 Expr *RHS = nullptr; 19922 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) { 19923 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode()); 19924 OOLoc = BO->getOperatorLoc(); 19925 LHS = BO->getLHS()->IgnoreParenImpCasts(); 19926 RHS = BO->getRHS()->IgnoreParenImpCasts(); 19927 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) { 19928 OOK = OCE->getOperator(); 19929 OOLoc = OCE->getOperatorLoc(); 19930 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); 19931 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts(); 19932 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) { 19933 OOK = MCE->getMethodDecl() 19934 ->getNameInfo() 19935 .getName() 19936 .getCXXOverloadedOperator(); 19937 OOLoc = MCE->getCallee()->getExprLoc(); 19938 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts(); 19939 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); 19940 } 19941 SourceLocation ELoc; 19942 SourceRange ERange; 19943 auto Res = getPrivateItem(SemaRef, LHS, ELoc, ERange); 19944 if (Res.second) { 19945 // It will be analyzed later. 19946 Vars.push_back(RefExpr); 19947 } 19948 ValueDecl *D = Res.first; 19949 if (!D) 19950 continue; 19951 19952 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) { 19953 SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus); 19954 continue; 19955 } 19956 if (RHS) { 19957 ExprResult RHSRes = 19958 SemaRef.OpenMP().VerifyPositiveIntegerConstantInClause( 19959 RHS, OMPC_depend, /*StrictlyPositive=*/false); 19960 if (RHSRes.isInvalid()) 19961 continue; 19962 } 19963 if (!SemaRef.CurContext->isDependentContext() && 19964 Stack->getParentOrderedRegionParam().first && 19965 DepCounter != Stack->isParentLoopControlVariable(D).first) { 19966 const ValueDecl *VD = 19967 Stack->getParentLoopControlVariable(DepCounter.getZExtValue()); 19968 if (VD) 19969 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration) 19970 << 1 << VD; 19971 else 19972 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration) 19973 << 0; 19974 continue; 19975 } 19976 OpsOffs.emplace_back(RHS, OOK); 19977 } 19978 Vars.push_back(RefExpr->IgnoreParenImpCasts()); 19979 } 19980 if (!SemaRef.CurContext->isDependentContext() && !IsSource && 19981 TotalDepCount > VarList.size() && 19982 Stack->getParentOrderedRegionParam().first && 19983 Stack->getParentLoopControlVariable(VarList.size() + 1)) { 19984 SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration) 19985 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1); 19986 } 19987 return {Vars, OpsOffs, TotalDepCount}; 19988 } 19989 19990 OMPClause *SemaOpenMP::ActOnOpenMPDependClause( 19991 const OMPDependClause::DependDataTy &Data, Expr *DepModifier, 19992 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, 19993 SourceLocation EndLoc) { 19994 OpenMPDependClauseKind DepKind = Data.DepKind; 19995 SourceLocation DepLoc = Data.DepLoc; 19996 if (DSAStack->getCurrentDirective() == OMPD_ordered && 19997 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) { 19998 Diag(DepLoc, diag::err_omp_unexpected_clause_value) 19999 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend); 20000 return nullptr; 20001 } 20002 if (DSAStack->getCurrentDirective() == OMPD_taskwait && 20003 DepKind == OMPC_DEPEND_mutexinoutset) { 20004 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed); 20005 return nullptr; 20006 } 20007 if ((DSAStack->getCurrentDirective() != OMPD_ordered || 20008 DSAStack->getCurrentDirective() == OMPD_depobj) && 20009 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source || 20010 DepKind == OMPC_DEPEND_sink || 20011 ((getLangOpts().OpenMP < 50 || 20012 DSAStack->getCurrentDirective() == OMPD_depobj) && 20013 DepKind == OMPC_DEPEND_depobj))) { 20014 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink, 20015 OMPC_DEPEND_outallmemory, 20016 OMPC_DEPEND_inoutallmemory}; 20017 if (getLangOpts().OpenMP < 50 || 20018 DSAStack->getCurrentDirective() == OMPD_depobj) 20019 Except.push_back(OMPC_DEPEND_depobj); 20020 if (getLangOpts().OpenMP < 51) 20021 Except.push_back(OMPC_DEPEND_inoutset); 20022 std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier) 20023 ? "depend modifier(iterator) or " 20024 : ""; 20025 Diag(DepLoc, diag::err_omp_unexpected_clause_value) 20026 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0, 20027 /*Last=*/OMPC_DEPEND_unknown, 20028 Except) 20029 << getOpenMPClauseName(OMPC_depend); 20030 return nullptr; 20031 } 20032 if (DepModifier && 20033 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) { 20034 Diag(DepModifier->getExprLoc(), 20035 diag::err_omp_depend_sink_source_with_modifier); 20036 return nullptr; 20037 } 20038 if (DepModifier && 20039 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator)) 20040 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator); 20041 20042 SmallVector<Expr *, 8> Vars; 20043 DSAStackTy::OperatorOffsetTy OpsOffs; 20044 llvm::APSInt TotalDepCount(/*BitWidth=*/32); 20045 20046 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) { 20047 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon( 20048 SemaRef, DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc); 20049 Vars = VarOffset.Vars; 20050 OpsOffs = VarOffset.OpsOffs; 20051 TotalDepCount = VarOffset.TotalDepCount; 20052 } else { 20053 for (Expr *RefExpr : VarList) { 20054 assert(RefExpr && "NULL expr in OpenMP shared clause."); 20055 if (isa<DependentScopeDeclRefExpr>(RefExpr)) { 20056 // It will be analyzed later. 20057 Vars.push_back(RefExpr); 20058 continue; 20059 } 20060 20061 SourceLocation ELoc = RefExpr->getExprLoc(); 20062 Expr *SimpleExpr = RefExpr->IgnoreParenCasts(); 20063 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) { 20064 bool OMPDependTFound = getLangOpts().OpenMP >= 50; 20065 if (OMPDependTFound) 20066 OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack, 20067 DepKind == OMPC_DEPEND_depobj); 20068 if (DepKind == OMPC_DEPEND_depobj) { 20069 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++ 20070 // List items used in depend clauses with the depobj dependence type 20071 // must be expressions of the omp_depend_t type. 20072 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() && 20073 !RefExpr->isInstantiationDependent() && 20074 !RefExpr->containsUnexpandedParameterPack() && 20075 (OMPDependTFound && 20076 !getASTContext().hasSameUnqualifiedType( 20077 DSAStack->getOMPDependT(), RefExpr->getType()))) { 20078 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue) 20079 << 0 << RefExpr->getType() << RefExpr->getSourceRange(); 20080 continue; 20081 } 20082 if (!RefExpr->isLValue()) { 20083 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue) 20084 << 1 << RefExpr->getType() << RefExpr->getSourceRange(); 20085 continue; 20086 } 20087 } else { 20088 // OpenMP 5.0 [2.17.11, Restrictions] 20089 // List items used in depend clauses cannot be zero-length array 20090 // sections. 20091 QualType ExprTy = RefExpr->getType().getNonReferenceType(); 20092 const auto *OASE = dyn_cast<ArraySectionExpr>(SimpleExpr); 20093 if (OASE) { 20094 QualType BaseType = 20095 ArraySectionExpr::getBaseOriginalType(OASE->getBase()); 20096 if (BaseType.isNull()) 20097 return nullptr; 20098 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe()) 20099 ExprTy = ATy->getElementType(); 20100 else 20101 ExprTy = BaseType->getPointeeType(); 20102 if (BaseType.isNull() || ExprTy.isNull()) 20103 return nullptr; 20104 ExprTy = ExprTy.getNonReferenceType(); 20105 const Expr *Length = OASE->getLength(); 20106 Expr::EvalResult Result; 20107 if (Length && !Length->isValueDependent() && 20108 Length->EvaluateAsInt(Result, getASTContext()) && 20109 Result.Val.getInt().isZero()) { 20110 Diag(ELoc, 20111 diag::err_omp_depend_zero_length_array_section_not_allowed) 20112 << SimpleExpr->getSourceRange(); 20113 continue; 20114 } 20115 } 20116 20117 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++ 20118 // List items used in depend clauses with the in, out, inout, 20119 // inoutset, or mutexinoutset dependence types cannot be 20120 // expressions of the omp_depend_t type. 20121 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() && 20122 !RefExpr->isInstantiationDependent() && 20123 !RefExpr->containsUnexpandedParameterPack() && 20124 (!RefExpr->IgnoreParenImpCasts()->isLValue() || 20125 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() == 20126 ExprTy.getTypePtr()))) { 20127 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item) 20128 << (getLangOpts().OpenMP >= 50 ? 1 : 0) 20129 << (getLangOpts().OpenMP >= 50 ? 1 : 0) 20130 << RefExpr->getSourceRange(); 20131 continue; 20132 } 20133 20134 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr); 20135 if (ASE && !ASE->getBase()->isTypeDependent() && 20136 !ASE->getBase() 20137 ->getType() 20138 .getNonReferenceType() 20139 ->isPointerType() && 20140 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) { 20141 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item) 20142 << (getLangOpts().OpenMP >= 50 ? 1 : 0) 20143 << (getLangOpts().OpenMP >= 50 ? 1 : 0) 20144 << RefExpr->getSourceRange(); 20145 continue; 20146 } 20147 20148 ExprResult Res; 20149 { 20150 Sema::TentativeAnalysisScope Trap(SemaRef); 20151 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, 20152 RefExpr->IgnoreParenImpCasts()); 20153 } 20154 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) && 20155 !isa<OMPArrayShapingExpr>(SimpleExpr)) { 20156 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item) 20157 << (getLangOpts().OpenMP >= 50 ? 1 : 0) 20158 << (getLangOpts().OpenMP >= 50 ? 1 : 0) 20159 << RefExpr->getSourceRange(); 20160 continue; 20161 } 20162 } 20163 } 20164 Vars.push_back(RefExpr->IgnoreParenImpCasts()); 20165 } 20166 } 20167 20168 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink && 20169 DepKind != OMPC_DEPEND_outallmemory && 20170 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty()) 20171 return nullptr; 20172 20173 auto *C = OMPDependClause::Create( 20174 getASTContext(), StartLoc, LParenLoc, EndLoc, 20175 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars, 20176 TotalDepCount.getZExtValue()); 20177 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) && 20178 DSAStack->isParentOrderedRegion()) 20179 DSAStack->addDoacrossDependClause(C, OpsOffs); 20180 return C; 20181 } 20182 20183 OMPClause *SemaOpenMP::ActOnOpenMPDeviceClause( 20184 OpenMPDeviceClauseModifier Modifier, Expr *Device, SourceLocation StartLoc, 20185 SourceLocation LParenLoc, SourceLocation ModifierLoc, 20186 SourceLocation EndLoc) { 20187 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) && 20188 "Unexpected device modifier in OpenMP < 50."); 20189 20190 bool ErrorFound = false; 20191 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) { 20192 std::string Values = 20193 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown); 20194 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value) 20195 << Values << getOpenMPClauseName(OMPC_device); 20196 ErrorFound = true; 20197 } 20198 20199 Expr *ValExpr = Device; 20200 Stmt *HelperValStmt = nullptr; 20201 20202 // OpenMP [2.9.1, Restrictions] 20203 // The device expression must evaluate to a non-negative integer value. 20204 ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_device, 20205 /*StrictlyPositive=*/false) || 20206 ErrorFound; 20207 if (ErrorFound) 20208 return nullptr; 20209 20210 // OpenMP 5.0 [2.12.5, Restrictions] 20211 // In case of ancestor device-modifier, a requires directive with 20212 // the reverse_offload clause must be specified. 20213 if (Modifier == OMPC_DEVICE_ancestor) { 20214 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) { 20215 SemaRef.targetDiag( 20216 StartLoc, 20217 diag::err_omp_device_ancestor_without_requires_reverse_offload); 20218 ErrorFound = true; 20219 } 20220 } 20221 20222 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); 20223 OpenMPDirectiveKind CaptureRegion = 20224 getOpenMPCaptureRegionForClause(DKind, OMPC_device, getLangOpts().OpenMP); 20225 if (CaptureRegion != OMPD_unknown && 20226 !SemaRef.CurContext->isDependentContext()) { 20227 ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); 20228 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 20229 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); 20230 HelperValStmt = buildPreInits(getASTContext(), Captures); 20231 } 20232 20233 return new (getASTContext()) 20234 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc, 20235 LParenLoc, ModifierLoc, EndLoc); 20236 } 20237 20238 static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef, 20239 DSAStackTy *Stack, QualType QTy, 20240 bool FullCheck = true) { 20241 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type)) 20242 return false; 20243 if (FullCheck && !SemaRef.CurContext->isDependentContext() && 20244 !QTy.isTriviallyCopyableType(SemaRef.Context)) 20245 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR; 20246 return true; 20247 } 20248 20249 /// Return true if it can be proven that the provided array expression 20250 /// (array section or array subscript) does NOT specify the whole size of the 20251 /// array whose base type is \a BaseQTy. 20252 static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef, 20253 const Expr *E, 20254 QualType BaseQTy) { 20255 const auto *OASE = dyn_cast<ArraySectionExpr>(E); 20256 20257 // If this is an array subscript, it refers to the whole size if the size of 20258 // the dimension is constant and equals 1. Also, an array section assumes the 20259 // format of an array subscript if no colon is used. 20260 if (isa<ArraySubscriptExpr>(E) || 20261 (OASE && OASE->getColonLocFirst().isInvalid())) { 20262 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) 20263 return ATy->getSExtSize() != 1; 20264 // Size can't be evaluated statically. 20265 return false; 20266 } 20267 20268 assert(OASE && "Expecting array section if not an array subscript."); 20269 const Expr *LowerBound = OASE->getLowerBound(); 20270 const Expr *Length = OASE->getLength(); 20271 20272 // If there is a lower bound that does not evaluates to zero, we are not 20273 // covering the whole dimension. 20274 if (LowerBound) { 20275 Expr::EvalResult Result; 20276 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext())) 20277 return false; // Can't get the integer value as a constant. 20278 20279 llvm::APSInt ConstLowerBound = Result.Val.getInt(); 20280 if (ConstLowerBound.getSExtValue()) 20281 return true; 20282 } 20283 20284 // If we don't have a length we covering the whole dimension. 20285 if (!Length) 20286 return false; 20287 20288 // If the base is a pointer, we don't have a way to get the size of the 20289 // pointee. 20290 if (BaseQTy->isPointerType()) 20291 return false; 20292 20293 // We can only check if the length is the same as the size of the dimension 20294 // if we have a constant array. 20295 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()); 20296 if (!CATy) 20297 return false; 20298 20299 Expr::EvalResult Result; 20300 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext())) 20301 return false; // Can't get the integer value as a constant. 20302 20303 llvm::APSInt ConstLength = Result.Val.getInt(); 20304 return CATy->getSExtSize() != ConstLength.getSExtValue(); 20305 } 20306 20307 // Return true if it can be proven that the provided array expression (array 20308 // section or array subscript) does NOT specify a single element of the array 20309 // whose base type is \a BaseQTy. 20310 static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef, 20311 const Expr *E, 20312 QualType BaseQTy) { 20313 const auto *OASE = dyn_cast<ArraySectionExpr>(E); 20314 20315 // An array subscript always refer to a single element. Also, an array section 20316 // assumes the format of an array subscript if no colon is used. 20317 if (isa<ArraySubscriptExpr>(E) || 20318 (OASE && OASE->getColonLocFirst().isInvalid())) 20319 return false; 20320 20321 assert(OASE && "Expecting array section if not an array subscript."); 20322 const Expr *Length = OASE->getLength(); 20323 20324 // If we don't have a length we have to check if the array has unitary size 20325 // for this dimension. Also, we should always expect a length if the base type 20326 // is pointer. 20327 if (!Length) { 20328 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) 20329 return ATy->getSExtSize() != 1; 20330 // We cannot assume anything. 20331 return false; 20332 } 20333 20334 // Check if the length evaluates to 1. 20335 Expr::EvalResult Result; 20336 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext())) 20337 return false; // Can't get the integer value as a constant. 20338 20339 llvm::APSInt ConstLength = Result.Val.getInt(); 20340 return ConstLength.getSExtValue() != 1; 20341 } 20342 20343 // The base of elements of list in a map clause have to be either: 20344 // - a reference to variable or field. 20345 // - a member expression. 20346 // - an array expression. 20347 // 20348 // E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the 20349 // reference to 'r'. 20350 // 20351 // If we have: 20352 // 20353 // struct SS { 20354 // Bla S; 20355 // foo() { 20356 // #pragma omp target map (S.Arr[:12]); 20357 // } 20358 // } 20359 // 20360 // We want to retrieve the member expression 'this->S'; 20361 20362 // OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2] 20363 // If a list item is an array section, it must specify contiguous storage. 20364 // 20365 // For this restriction it is sufficient that we make sure only references 20366 // to variables or fields and array expressions, and that no array sections 20367 // exist except in the rightmost expression (unless they cover the whole 20368 // dimension of the array). E.g. these would be invalid: 20369 // 20370 // r.ArrS[3:5].Arr[6:7] 20371 // 20372 // r.ArrS[3:5].x 20373 // 20374 // but these would be valid: 20375 // r.ArrS[3].Arr[6:7] 20376 // 20377 // r.ArrS[3].x 20378 namespace { 20379 class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> { 20380 Sema &SemaRef; 20381 OpenMPClauseKind CKind = OMPC_unknown; 20382 OpenMPDirectiveKind DKind = OMPD_unknown; 20383 OMPClauseMappableExprCommon::MappableExprComponentList &Components; 20384 bool IsNonContiguous = false; 20385 bool NoDiagnose = false; 20386 const Expr *RelevantExpr = nullptr; 20387 bool AllowUnitySizeArraySection = true; 20388 bool AllowWholeSizeArraySection = true; 20389 bool AllowAnotherPtr = true; 20390 SourceLocation ELoc; 20391 SourceRange ERange; 20392 20393 void emitErrorMsg() { 20394 // If nothing else worked, this is not a valid map clause expression. 20395 if (SemaRef.getLangOpts().OpenMP < 50) { 20396 SemaRef.Diag(ELoc, 20397 diag::err_omp_expected_named_var_member_or_array_expression) 20398 << ERange; 20399 } else { 20400 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses) 20401 << getOpenMPClauseName(CKind) << ERange; 20402 } 20403 } 20404 20405 public: 20406 bool VisitDeclRefExpr(DeclRefExpr *DRE) { 20407 if (!isa<VarDecl>(DRE->getDecl())) { 20408 emitErrorMsg(); 20409 return false; 20410 } 20411 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr"); 20412 RelevantExpr = DRE; 20413 // Record the component. 20414 Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous); 20415 return true; 20416 } 20417 20418 bool VisitMemberExpr(MemberExpr *ME) { 20419 Expr *E = ME; 20420 Expr *BaseE = ME->getBase()->IgnoreParenCasts(); 20421 20422 if (isa<CXXThisExpr>(BaseE)) { 20423 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr"); 20424 // We found a base expression: this->Val. 20425 RelevantExpr = ME; 20426 } else { 20427 E = BaseE; 20428 } 20429 20430 if (!isa<FieldDecl>(ME->getMemberDecl())) { 20431 if (!NoDiagnose) { 20432 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field) 20433 << ME->getSourceRange(); 20434 return false; 20435 } 20436 if (RelevantExpr) 20437 return false; 20438 return Visit(E); 20439 } 20440 20441 auto *FD = cast<FieldDecl>(ME->getMemberDecl()); 20442 20443 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3] 20444 // A bit-field cannot appear in a map clause. 20445 // 20446 if (FD->isBitField()) { 20447 if (!NoDiagnose) { 20448 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause) 20449 << ME->getSourceRange() << getOpenMPClauseName(CKind); 20450 return false; 20451 } 20452 if (RelevantExpr) 20453 return false; 20454 return Visit(E); 20455 } 20456 20457 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1] 20458 // If the type of a list item is a reference to a type T then the type 20459 // will be considered to be T for all purposes of this clause. 20460 QualType CurType = BaseE->getType().getNonReferenceType(); 20461 20462 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2] 20463 // A list item cannot be a variable that is a member of a structure with 20464 // a union type. 20465 // 20466 if (CurType->isUnionType()) { 20467 if (!NoDiagnose) { 20468 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed) 20469 << ME->getSourceRange(); 20470 return false; 20471 } 20472 return RelevantExpr || Visit(E); 20473 } 20474 20475 // If we got a member expression, we should not expect any array section 20476 // before that: 20477 // 20478 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7] 20479 // If a list item is an element of a structure, only the rightmost symbol 20480 // of the variable reference can be an array section. 20481 // 20482 AllowUnitySizeArraySection = false; 20483 AllowWholeSizeArraySection = false; 20484 20485 // Record the component. 20486 Components.emplace_back(ME, FD, IsNonContiguous); 20487 return RelevantExpr || Visit(E); 20488 } 20489 20490 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) { 20491 Expr *E = AE->getBase()->IgnoreParenImpCasts(); 20492 20493 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) { 20494 if (!NoDiagnose) { 20495 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name) 20496 << 0 << AE->getSourceRange(); 20497 return false; 20498 } 20499 return RelevantExpr || Visit(E); 20500 } 20501 20502 // If we got an array subscript that express the whole dimension we 20503 // can have any array expressions before. If it only expressing part of 20504 // the dimension, we can only have unitary-size array expressions. 20505 if (checkArrayExpressionDoesNotReferToWholeSize(SemaRef, AE, E->getType())) 20506 AllowWholeSizeArraySection = false; 20507 20508 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) { 20509 Expr::EvalResult Result; 20510 if (!AE->getIdx()->isValueDependent() && 20511 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) && 20512 !Result.Val.getInt().isZero()) { 20513 SemaRef.Diag(AE->getIdx()->getExprLoc(), 20514 diag::err_omp_invalid_map_this_expr); 20515 SemaRef.Diag(AE->getIdx()->getExprLoc(), 20516 diag::note_omp_invalid_subscript_on_this_ptr_map); 20517 } 20518 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr"); 20519 RelevantExpr = TE; 20520 } 20521 20522 // Record the component - we don't have any declaration associated. 20523 Components.emplace_back(AE, nullptr, IsNonContiguous); 20524 20525 return RelevantExpr || Visit(E); 20526 } 20527 20528 bool VisitArraySectionExpr(ArraySectionExpr *OASE) { 20529 // After OMP 5.0 Array section in reduction clause will be implicitly 20530 // mapped 20531 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) && 20532 "Array sections cannot be implicitly mapped."); 20533 Expr *E = OASE->getBase()->IgnoreParenImpCasts(); 20534 QualType CurType = 20535 ArraySectionExpr::getBaseOriginalType(E).getCanonicalType(); 20536 20537 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1] 20538 // If the type of a list item is a reference to a type T then the type 20539 // will be considered to be T for all purposes of this clause. 20540 if (CurType->isReferenceType()) 20541 CurType = CurType->getPointeeType(); 20542 20543 bool IsPointer = CurType->isAnyPointerType(); 20544 20545 if (!IsPointer && !CurType->isArrayType()) { 20546 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name) 20547 << 0 << OASE->getSourceRange(); 20548 return false; 20549 } 20550 20551 bool NotWhole = 20552 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType); 20553 bool NotUnity = 20554 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType); 20555 20556 if (AllowWholeSizeArraySection) { 20557 // Any array section is currently allowed. Allowing a whole size array 20558 // section implies allowing a unity array section as well. 20559 // 20560 // If this array section refers to the whole dimension we can still 20561 // accept other array sections before this one, except if the base is a 20562 // pointer. Otherwise, only unitary sections are accepted. 20563 if (NotWhole || IsPointer) 20564 AllowWholeSizeArraySection = false; 20565 } else if (DKind == OMPD_target_update && 20566 SemaRef.getLangOpts().OpenMP >= 50) { 20567 if (IsPointer && !AllowAnotherPtr) 20568 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined) 20569 << /*array of unknown bound */ 1; 20570 else 20571 IsNonContiguous = true; 20572 } else if (AllowUnitySizeArraySection && NotUnity) { 20573 // A unity or whole array section is not allowed and that is not 20574 // compatible with the properties of the current array section. 20575 if (NoDiagnose) 20576 return false; 20577 SemaRef.Diag(ELoc, 20578 diag::err_array_section_does_not_specify_contiguous_storage) 20579 << OASE->getSourceRange(); 20580 return false; 20581 } 20582 20583 if (IsPointer) 20584 AllowAnotherPtr = false; 20585 20586 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) { 20587 Expr::EvalResult ResultR; 20588 Expr::EvalResult ResultL; 20589 if (!OASE->getLength()->isValueDependent() && 20590 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) && 20591 !ResultR.Val.getInt().isOne()) { 20592 SemaRef.Diag(OASE->getLength()->getExprLoc(), 20593 diag::err_omp_invalid_map_this_expr); 20594 SemaRef.Diag(OASE->getLength()->getExprLoc(), 20595 diag::note_omp_invalid_length_on_this_ptr_mapping); 20596 } 20597 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() && 20598 OASE->getLowerBound()->EvaluateAsInt(ResultL, 20599 SemaRef.getASTContext()) && 20600 !ResultL.Val.getInt().isZero()) { 20601 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(), 20602 diag::err_omp_invalid_map_this_expr); 20603 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(), 20604 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping); 20605 } 20606 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr"); 20607 RelevantExpr = TE; 20608 } 20609 20610 // Record the component - we don't have any declaration associated. 20611 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false); 20612 return RelevantExpr || Visit(E); 20613 } 20614 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) { 20615 Expr *Base = E->getBase(); 20616 20617 // Record the component - we don't have any declaration associated. 20618 Components.emplace_back(E, nullptr, IsNonContiguous); 20619 20620 return Visit(Base->IgnoreParenImpCasts()); 20621 } 20622 20623 bool VisitUnaryOperator(UnaryOperator *UO) { 20624 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() || 20625 UO->getOpcode() != UO_Deref) { 20626 emitErrorMsg(); 20627 return false; 20628 } 20629 if (!RelevantExpr) { 20630 // Record the component if haven't found base decl. 20631 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false); 20632 } 20633 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts()); 20634 } 20635 bool VisitBinaryOperator(BinaryOperator *BO) { 20636 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) { 20637 emitErrorMsg(); 20638 return false; 20639 } 20640 20641 // Pointer arithmetic is the only thing we expect to happen here so after we 20642 // make sure the binary operator is a pointer type, the only thing we need 20643 // to do is to visit the subtree that has the same type as root (so that we 20644 // know the other subtree is just an offset) 20645 Expr *LE = BO->getLHS()->IgnoreParenImpCasts(); 20646 Expr *RE = BO->getRHS()->IgnoreParenImpCasts(); 20647 Components.emplace_back(BO, nullptr, false); 20648 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() || 20649 RE->getType().getTypePtr() == BO->getType().getTypePtr()) && 20650 "Either LHS or RHS have base decl inside"); 20651 if (BO->getType().getTypePtr() == LE->getType().getTypePtr()) 20652 return RelevantExpr || Visit(LE); 20653 return RelevantExpr || Visit(RE); 20654 } 20655 bool VisitCXXThisExpr(CXXThisExpr *CTE) { 20656 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr"); 20657 RelevantExpr = CTE; 20658 Components.emplace_back(CTE, nullptr, IsNonContiguous); 20659 return true; 20660 } 20661 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) { 20662 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr"); 20663 Components.emplace_back(COCE, nullptr, IsNonContiguous); 20664 return true; 20665 } 20666 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) { 20667 Expr *Source = E->getSourceExpr(); 20668 if (!Source) { 20669 emitErrorMsg(); 20670 return false; 20671 } 20672 return Visit(Source); 20673 } 20674 bool VisitStmt(Stmt *) { 20675 emitErrorMsg(); 20676 return false; 20677 } 20678 const Expr *getFoundBase() const { return RelevantExpr; } 20679 explicit MapBaseChecker( 20680 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, 20681 OMPClauseMappableExprCommon::MappableExprComponentList &Components, 20682 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange) 20683 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components), 20684 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {} 20685 }; 20686 } // namespace 20687 20688 /// Return the expression of the base of the mappable expression or null if it 20689 /// cannot be determined and do all the necessary checks to see if the 20690 /// expression is valid as a standalone mappable expression. In the process, 20691 /// record all the components of the expression. 20692 static const Expr *checkMapClauseExpressionBase( 20693 Sema &SemaRef, Expr *E, 20694 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents, 20695 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) { 20696 SourceLocation ELoc = E->getExprLoc(); 20697 SourceRange ERange = E->getSourceRange(); 20698 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc, 20699 ERange); 20700 if (Checker.Visit(E->IgnoreParens())) { 20701 // Check if the highest dimension array section has length specified 20702 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() && 20703 (CKind == OMPC_to || CKind == OMPC_from)) { 20704 auto CI = CurComponents.rbegin(); 20705 auto CE = CurComponents.rend(); 20706 for (; CI != CE; ++CI) { 20707 const auto *OASE = 20708 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression()); 20709 if (!OASE) 20710 continue; 20711 if (OASE && OASE->getLength()) 20712 break; 20713 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length) 20714 << ERange; 20715 } 20716 } 20717 return Checker.getFoundBase(); 20718 } 20719 return nullptr; 20720 } 20721 20722 // Return true if expression E associated with value VD has conflicts with other 20723 // map information. 20724 static bool checkMapConflicts( 20725 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E, 20726 bool CurrentRegionOnly, 20727 OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents, 20728 OpenMPClauseKind CKind) { 20729 assert(VD && E); 20730 SourceLocation ELoc = E->getExprLoc(); 20731 SourceRange ERange = E->getSourceRange(); 20732 20733 // In order to easily check the conflicts we need to match each component of 20734 // the expression under test with the components of the expressions that are 20735 // already in the stack. 20736 20737 assert(!CurComponents.empty() && "Map clause expression with no components!"); 20738 assert(CurComponents.back().getAssociatedDeclaration() == VD && 20739 "Map clause expression with unexpected base!"); 20740 20741 // Variables to help detecting enclosing problems in data environment nests. 20742 bool IsEnclosedByDataEnvironmentExpr = false; 20743 const Expr *EnclosingExpr = nullptr; 20744 20745 bool FoundError = DSAS->checkMappableExprComponentListsForDecl( 20746 VD, CurrentRegionOnly, 20747 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc, 20748 ERange, CKind, &EnclosingExpr, 20749 CurComponents](OMPClauseMappableExprCommon::MappableExprComponentListRef 20750 StackComponents, 20751 OpenMPClauseKind Kind) { 20752 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50) 20753 return false; 20754 assert(!StackComponents.empty() && 20755 "Map clause expression with no components!"); 20756 assert(StackComponents.back().getAssociatedDeclaration() == VD && 20757 "Map clause expression with unexpected base!"); 20758 (void)VD; 20759 20760 // The whole expression in the stack. 20761 const Expr *RE = StackComponents.front().getAssociatedExpression(); 20762 20763 // Expressions must start from the same base. Here we detect at which 20764 // point both expressions diverge from each other and see if we can 20765 // detect if the memory referred to both expressions is contiguous and 20766 // do not overlap. 20767 auto CI = CurComponents.rbegin(); 20768 auto CE = CurComponents.rend(); 20769 auto SI = StackComponents.rbegin(); 20770 auto SE = StackComponents.rend(); 20771 for (; CI != CE && SI != SE; ++CI, ++SI) { 20772 20773 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3] 20774 // At most one list item can be an array item derived from a given 20775 // variable in map clauses of the same construct. 20776 if (CurrentRegionOnly && 20777 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) || 20778 isa<ArraySectionExpr>(CI->getAssociatedExpression()) || 20779 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) && 20780 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) || 20781 isa<ArraySectionExpr>(SI->getAssociatedExpression()) || 20782 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) { 20783 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(), 20784 diag::err_omp_multiple_array_items_in_map_clause) 20785 << CI->getAssociatedExpression()->getSourceRange(); 20786 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(), 20787 diag::note_used_here) 20788 << SI->getAssociatedExpression()->getSourceRange(); 20789 return true; 20790 } 20791 20792 // Do both expressions have the same kind? 20793 if (CI->getAssociatedExpression()->getStmtClass() != 20794 SI->getAssociatedExpression()->getStmtClass()) 20795 break; 20796 20797 // Are we dealing with different variables/fields? 20798 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration()) 20799 break; 20800 } 20801 // Check if the extra components of the expressions in the enclosing 20802 // data environment are redundant for the current base declaration. 20803 // If they are, the maps completely overlap, which is legal. 20804 for (; SI != SE; ++SI) { 20805 QualType Type; 20806 if (const auto *ASE = 20807 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) { 20808 Type = ASE->getBase()->IgnoreParenImpCasts()->getType(); 20809 } else if (const auto *OASE = dyn_cast<ArraySectionExpr>( 20810 SI->getAssociatedExpression())) { 20811 const Expr *E = OASE->getBase()->IgnoreParenImpCasts(); 20812 Type = ArraySectionExpr::getBaseOriginalType(E).getCanonicalType(); 20813 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>( 20814 SI->getAssociatedExpression())) { 20815 Type = OASE->getBase()->getType()->getPointeeType(); 20816 } 20817 if (Type.isNull() || Type->isAnyPointerType() || 20818 checkArrayExpressionDoesNotReferToWholeSize( 20819 SemaRef, SI->getAssociatedExpression(), Type)) 20820 break; 20821 } 20822 20823 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4] 20824 // List items of map clauses in the same construct must not share 20825 // original storage. 20826 // 20827 // If the expressions are exactly the same or one is a subset of the 20828 // other, it means they are sharing storage. 20829 if (CI == CE && SI == SE) { 20830 if (CurrentRegionOnly) { 20831 if (CKind == OMPC_map) { 20832 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange; 20833 } else { 20834 assert(CKind == OMPC_to || CKind == OMPC_from); 20835 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update) 20836 << ERange; 20837 } 20838 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here) 20839 << RE->getSourceRange(); 20840 return true; 20841 } 20842 // If we find the same expression in the enclosing data environment, 20843 // that is legal. 20844 IsEnclosedByDataEnvironmentExpr = true; 20845 return false; 20846 } 20847 20848 QualType DerivedType = 20849 std::prev(CI)->getAssociatedDeclaration()->getType(); 20850 SourceLocation DerivedLoc = 20851 std::prev(CI)->getAssociatedExpression()->getExprLoc(); 20852 20853 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1] 20854 // If the type of a list item is a reference to a type T then the type 20855 // will be considered to be T for all purposes of this clause. 20856 DerivedType = DerivedType.getNonReferenceType(); 20857 20858 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1] 20859 // A variable for which the type is pointer and an array section 20860 // derived from that variable must not appear as list items of map 20861 // clauses of the same construct. 20862 // 20863 // Also, cover one of the cases in: 20864 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5] 20865 // If any part of the original storage of a list item has corresponding 20866 // storage in the device data environment, all of the original storage 20867 // must have corresponding storage in the device data environment. 20868 // 20869 if (DerivedType->isAnyPointerType()) { 20870 if (CI == CE || SI == SE) { 20871 SemaRef.Diag( 20872 DerivedLoc, 20873 diag::err_omp_pointer_mapped_along_with_derived_section) 20874 << DerivedLoc; 20875 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here) 20876 << RE->getSourceRange(); 20877 return true; 20878 } 20879 if (CI->getAssociatedExpression()->getStmtClass() != 20880 SI->getAssociatedExpression()->getStmtClass() || 20881 CI->getAssociatedDeclaration()->getCanonicalDecl() == 20882 SI->getAssociatedDeclaration()->getCanonicalDecl()) { 20883 assert(CI != CE && SI != SE); 20884 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced) 20885 << DerivedLoc; 20886 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here) 20887 << RE->getSourceRange(); 20888 return true; 20889 } 20890 } 20891 20892 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4] 20893 // List items of map clauses in the same construct must not share 20894 // original storage. 20895 // 20896 // An expression is a subset of the other. 20897 if (CurrentRegionOnly && (CI == CE || SI == SE)) { 20898 if (CKind == OMPC_map) { 20899 if (CI != CE || SI != SE) { 20900 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is 20901 // a pointer. 20902 auto Begin = 20903 CI != CE ? CurComponents.begin() : StackComponents.begin(); 20904 auto End = CI != CE ? CurComponents.end() : StackComponents.end(); 20905 auto It = Begin; 20906 while (It != End && !It->getAssociatedDeclaration()) 20907 std::advance(It, 1); 20908 assert(It != End && 20909 "Expected at least one component with the declaration."); 20910 if (It != Begin && It->getAssociatedDeclaration() 20911 ->getType() 20912 .getCanonicalType() 20913 ->isAnyPointerType()) { 20914 IsEnclosedByDataEnvironmentExpr = false; 20915 EnclosingExpr = nullptr; 20916 return false; 20917 } 20918 } 20919 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange; 20920 } else { 20921 assert(CKind == OMPC_to || CKind == OMPC_from); 20922 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update) 20923 << ERange; 20924 } 20925 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here) 20926 << RE->getSourceRange(); 20927 return true; 20928 } 20929 20930 // The current expression uses the same base as other expression in the 20931 // data environment but does not contain it completely. 20932 if (!CurrentRegionOnly && SI != SE) 20933 EnclosingExpr = RE; 20934 20935 // The current expression is a subset of the expression in the data 20936 // environment. 20937 IsEnclosedByDataEnvironmentExpr |= 20938 (!CurrentRegionOnly && CI != CE && SI == SE); 20939 20940 return false; 20941 }); 20942 20943 if (CurrentRegionOnly) 20944 return FoundError; 20945 20946 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5] 20947 // If any part of the original storage of a list item has corresponding 20948 // storage in the device data environment, all of the original storage must 20949 // have corresponding storage in the device data environment. 20950 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6] 20951 // If a list item is an element of a structure, and a different element of 20952 // the structure has a corresponding list item in the device data environment 20953 // prior to a task encountering the construct associated with the map clause, 20954 // then the list item must also have a corresponding list item in the device 20955 // data environment prior to the task encountering the construct. 20956 // 20957 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) { 20958 SemaRef.Diag(ELoc, 20959 diag::err_omp_original_storage_is_shared_and_does_not_contain) 20960 << ERange; 20961 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here) 20962 << EnclosingExpr->getSourceRange(); 20963 return true; 20964 } 20965 20966 return FoundError; 20967 } 20968 20969 // Look up the user-defined mapper given the mapper name and mapped type, and 20970 // build a reference to it. 20971 static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, 20972 CXXScopeSpec &MapperIdScopeSpec, 20973 const DeclarationNameInfo &MapperId, 20974 QualType Type, 20975 Expr *UnresolvedMapper) { 20976 if (MapperIdScopeSpec.isInvalid()) 20977 return ExprError(); 20978 // Get the actual type for the array type. 20979 if (Type->isArrayType()) { 20980 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type"); 20981 Type = Type->getAsArrayTypeUnsafe()->getElementType().getCanonicalType(); 20982 } 20983 // Find all user-defined mappers with the given MapperId. 20984 SmallVector<UnresolvedSet<8>, 4> Lookups; 20985 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName); 20986 Lookup.suppressDiagnostics(); 20987 if (S) { 20988 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec, 20989 /*ObjectType=*/QualType())) { 20990 NamedDecl *D = Lookup.getRepresentativeDecl(); 20991 while (S && !S->isDeclScope(D)) 20992 S = S->getParent(); 20993 if (S) 20994 S = S->getParent(); 20995 Lookups.emplace_back(); 20996 Lookups.back().append(Lookup.begin(), Lookup.end()); 20997 Lookup.clear(); 20998 } 20999 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) { 21000 // Extract the user-defined mappers with the given MapperId. 21001 Lookups.push_back(UnresolvedSet<8>()); 21002 for (NamedDecl *D : ULE->decls()) { 21003 auto *DMD = cast<OMPDeclareMapperDecl>(D); 21004 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation."); 21005 Lookups.back().addDecl(DMD); 21006 } 21007 } 21008 // Defer the lookup for dependent types. The results will be passed through 21009 // UnresolvedMapper on instantiation. 21010 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() || 21011 Type->isInstantiationDependentType() || 21012 Type->containsUnexpandedParameterPack() || 21013 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) { 21014 return !D->isInvalidDecl() && 21015 (D->getType()->isDependentType() || 21016 D->getType()->isInstantiationDependentType() || 21017 D->getType()->containsUnexpandedParameterPack()); 21018 })) { 21019 UnresolvedSet<8> URS; 21020 for (const UnresolvedSet<8> &Set : Lookups) { 21021 if (Set.empty()) 21022 continue; 21023 URS.append(Set.begin(), Set.end()); 21024 } 21025 return UnresolvedLookupExpr::Create( 21026 SemaRef.Context, /*NamingClass=*/nullptr, 21027 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId, 21028 /*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false, 21029 /*KnownInstantiationDependent=*/false); 21030 } 21031 SourceLocation Loc = MapperId.getLoc(); 21032 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions 21033 // The type must be of struct, union or class type in C and C++ 21034 if (!Type->isStructureOrClassType() && !Type->isUnionType() && 21035 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) { 21036 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type); 21037 return ExprError(); 21038 } 21039 // Perform argument dependent lookup. 21040 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet()) 21041 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups); 21042 // Return the first user-defined mapper with the desired type. 21043 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>( 21044 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * { 21045 if (!D->isInvalidDecl() && 21046 SemaRef.Context.hasSameType(D->getType(), Type)) 21047 return D; 21048 return nullptr; 21049 })) 21050 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc); 21051 // Find the first user-defined mapper with a type derived from the desired 21052 // type. 21053 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>( 21054 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * { 21055 if (!D->isInvalidDecl() && 21056 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) && 21057 !Type.isMoreQualifiedThan(D->getType(), 21058 SemaRef.getASTContext())) 21059 return D; 21060 return nullptr; 21061 })) { 21062 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, 21063 /*DetectVirtual=*/false); 21064 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) { 21065 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType( 21066 VD->getType().getUnqualifiedType()))) { 21067 if (SemaRef.CheckBaseClassAccess( 21068 Loc, VD->getType(), Type, Paths.front(), 21069 /*DiagID=*/0) != Sema::AR_inaccessible) { 21070 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc); 21071 } 21072 } 21073 } 21074 } 21075 // Report error if a mapper is specified, but cannot be found. 21076 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") { 21077 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper) 21078 << Type << MapperId.getName(); 21079 return ExprError(); 21080 } 21081 return ExprEmpty(); 21082 } 21083 21084 namespace { 21085 // Utility struct that gathers all the related lists associated with a mappable 21086 // expression. 21087 struct MappableVarListInfo { 21088 // The list of expressions. 21089 ArrayRef<Expr *> VarList; 21090 // The list of processed expressions. 21091 SmallVector<Expr *, 16> ProcessedVarList; 21092 // The mappble components for each expression. 21093 OMPClauseMappableExprCommon::MappableExprComponentLists VarComponents; 21094 // The base declaration of the variable. 21095 SmallVector<ValueDecl *, 16> VarBaseDeclarations; 21096 // The reference to the user-defined mapper associated with every expression. 21097 SmallVector<Expr *, 16> UDMapperList; 21098 21099 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) { 21100 // We have a list of components and base declarations for each entry in the 21101 // variable list. 21102 VarComponents.reserve(VarList.size()); 21103 VarBaseDeclarations.reserve(VarList.size()); 21104 } 21105 }; 21106 } // namespace 21107 21108 static DeclRefExpr *buildImplicitMap(Sema &S, QualType BaseType, 21109 DSAStackTy *Stack, 21110 SmallVectorImpl<OMPClause *> &Maps) { 21111 21112 const RecordDecl *RD = BaseType->getAsRecordDecl(); 21113 SourceRange Range = RD->getSourceRange(); 21114 DeclarationNameInfo ImplicitName; 21115 // Dummy variable _s for Mapper. 21116 VarDecl *VD = buildVarDecl(S, Range.getEnd(), BaseType, "_s"); 21117 DeclRefExpr *MapperVarRef = 21118 buildDeclRefExpr(S, VD, BaseType, SourceLocation()); 21119 21120 // Create implicit map clause for mapper. 21121 SmallVector<Expr *, 4> SExprs; 21122 for (auto *FD : RD->fields()) { 21123 Expr *BE = S.BuildMemberExpr( 21124 MapperVarRef, /*IsArrow=*/false, Range.getBegin(), 21125 NestedNameSpecifierLoc(), Range.getBegin(), FD, 21126 DeclAccessPair::make(FD, FD->getAccess()), 21127 /*HadMultipleCandidates=*/false, 21128 DeclarationNameInfo(FD->getDeclName(), FD->getSourceRange().getBegin()), 21129 FD->getType(), VK_LValue, OK_Ordinary); 21130 SExprs.push_back(BE); 21131 } 21132 CXXScopeSpec MapperIdScopeSpec; 21133 DeclarationNameInfo MapperId; 21134 OpenMPDirectiveKind DKind = Stack->getCurrentDirective(); 21135 21136 OMPClause *MapClause = S.OpenMP().ActOnOpenMPMapClause( 21137 nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(), MapperIdScopeSpec, 21138 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom, 21139 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), SExprs, 21140 OMPVarListLocTy()); 21141 Maps.push_back(MapClause); 21142 return MapperVarRef; 21143 } 21144 21145 static ExprResult buildImplicitMapper(Sema &S, QualType BaseType, 21146 DSAStackTy *Stack) { 21147 21148 // Build impilicit map for mapper 21149 SmallVector<OMPClause *, 4> Maps; 21150 DeclRefExpr *MapperVarRef = buildImplicitMap(S, BaseType, Stack, Maps); 21151 21152 const RecordDecl *RD = BaseType->getAsRecordDecl(); 21153 // AST context is RD's ParentASTContext(). 21154 ASTContext &Ctx = RD->getParentASTContext(); 21155 // DeclContext is RD's DeclContext. 21156 DeclContext *DCT = const_cast<DeclContext *>(RD->getDeclContext()); 21157 21158 // Create implicit default mapper for "RD". 21159 DeclarationName MapperId; 21160 auto &DeclNames = Ctx.DeclarationNames; 21161 MapperId = DeclNames.getIdentifier(&Ctx.Idents.get("default")); 21162 auto *DMD = OMPDeclareMapperDecl::Create(Ctx, DCT, SourceLocation(), MapperId, 21163 BaseType, MapperId, Maps, nullptr); 21164 Scope *Scope = S.getScopeForContext(DCT); 21165 if (Scope) 21166 S.PushOnScopeChains(DMD, Scope, /*AddToContext=*/false); 21167 DCT->addDecl(DMD); 21168 DMD->setAccess(clang::AS_none); 21169 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl(); 21170 VD->setDeclContext(DMD); 21171 VD->setLexicalDeclContext(DMD); 21172 DMD->addDecl(VD); 21173 DMD->setMapperVarRef(MapperVarRef); 21174 FieldDecl *FD = *RD->field_begin(); 21175 // create mapper refence. 21176 return DeclRefExpr::Create(Ctx, NestedNameSpecifierLoc{}, FD->getLocation(), 21177 DMD, false, SourceLocation(), BaseType, VK_LValue); 21178 } 21179 21180 // Look up the user-defined mapper given the mapper name and mapper type, 21181 // return true if found one. 21182 static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S, 21183 CXXScopeSpec &MapperIdScopeSpec, 21184 const DeclarationNameInfo &MapperId, 21185 QualType Type) { 21186 // Find all user-defined mappers with the given MapperId. 21187 SmallVector<UnresolvedSet<8>, 4> Lookups; 21188 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName); 21189 Lookup.suppressDiagnostics(); 21190 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec, 21191 /*ObjectType=*/QualType())) { 21192 NamedDecl *D = Lookup.getRepresentativeDecl(); 21193 while (S && !S->isDeclScope(D)) 21194 S = S->getParent(); 21195 if (S) 21196 S = S->getParent(); 21197 Lookups.emplace_back(); 21198 Lookups.back().append(Lookup.begin(), Lookup.end()); 21199 Lookup.clear(); 21200 } 21201 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() || 21202 Type->isInstantiationDependentType() || 21203 Type->containsUnexpandedParameterPack() || 21204 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) { 21205 return !D->isInvalidDecl() && 21206 (D->getType()->isDependentType() || 21207 D->getType()->isInstantiationDependentType() || 21208 D->getType()->containsUnexpandedParameterPack()); 21209 })) 21210 return false; 21211 // Perform argument dependent lookup. 21212 SourceLocation Loc = MapperId.getLoc(); 21213 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet()) 21214 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups); 21215 if (filterLookupForUDReductionAndMapper<ValueDecl *>( 21216 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * { 21217 if (!D->isInvalidDecl() && 21218 SemaRef.Context.hasSameType(D->getType(), Type)) 21219 return D; 21220 return nullptr; 21221 })) 21222 return true; 21223 // Find the first user-defined mapper with a type derived from the desired 21224 // type. 21225 auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>( 21226 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * { 21227 if (!D->isInvalidDecl() && 21228 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) && 21229 !Type.isMoreQualifiedThan(D->getType(), SemaRef.getASTContext())) 21230 return D; 21231 return nullptr; 21232 }); 21233 if (!VD) 21234 return false; 21235 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, 21236 /*DetectVirtual=*/false); 21237 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) { 21238 bool IsAmbiguous = !Paths.isAmbiguous( 21239 SemaRef.Context.getCanonicalType(VD->getType().getUnqualifiedType())); 21240 if (IsAmbiguous) 21241 return false; 21242 if (SemaRef.CheckBaseClassAccess(Loc, VD->getType(), Type, Paths.front(), 21243 /*DiagID=*/0) != Sema::AR_inaccessible) 21244 return true; 21245 } 21246 return false; 21247 } 21248 21249 static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack, 21250 QualType CanonType, const Expr *E) { 21251 21252 // DFS over data members in structures/classes. 21253 SmallVector<std::pair<QualType, FieldDecl *>, 4> Types(1, 21254 {CanonType, nullptr}); 21255 llvm::DenseMap<const Type *, bool> Visited; 21256 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(1, {nullptr, 1}); 21257 while (!Types.empty()) { 21258 auto [BaseType, CurFD] = Types.pop_back_val(); 21259 while (ParentChain.back().second == 0) 21260 ParentChain.pop_back(); 21261 --ParentChain.back().second; 21262 if (BaseType.isNull()) 21263 continue; 21264 // Only structs/classes are allowed to have mappers. 21265 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl(); 21266 if (!RD) 21267 continue; 21268 auto It = Visited.find(BaseType.getTypePtr()); 21269 if (It == Visited.end()) { 21270 // Try to find the associated user-defined mapper. 21271 CXXScopeSpec MapperIdScopeSpec; 21272 DeclarationNameInfo DefaultMapperId; 21273 DefaultMapperId.setName(S.Context.DeclarationNames.getIdentifier( 21274 &S.Context.Idents.get("default"))); 21275 DefaultMapperId.setLoc(E->getExprLoc()); 21276 bool HasUDMapper = 21277 hasUserDefinedMapper(S, Stack->getCurScope(), MapperIdScopeSpec, 21278 DefaultMapperId, BaseType); 21279 It = Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first; 21280 } 21281 // Found default mapper. 21282 if (It->second) 21283 return true; 21284 // Check for the "default" mapper for data members. 21285 bool FirstIter = true; 21286 for (FieldDecl *FD : RD->fields()) { 21287 if (!FD) 21288 continue; 21289 QualType FieldTy = FD->getType(); 21290 if (FieldTy.isNull() || 21291 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType())) 21292 continue; 21293 if (FirstIter) { 21294 FirstIter = false; 21295 ParentChain.emplace_back(CurFD, 1); 21296 } else { 21297 ++ParentChain.back().second; 21298 } 21299 Types.emplace_back(FieldTy, FD); 21300 } 21301 } 21302 return false; 21303 } 21304 21305 // Check the validity of the provided variable list for the provided clause kind 21306 // \a CKind. In the check process the valid expressions, mappable expression 21307 // components, variables, and user-defined mappers are extracted and used to 21308 // fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a 21309 // UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec, 21310 // and \a MapperId are expected to be valid if the clause kind is 'map'. 21311 static void checkMappableExpressionList( 21312 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind, 21313 MappableVarListInfo &MVLI, SourceLocation StartLoc, 21314 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId, 21315 ArrayRef<Expr *> UnresolvedMappers, 21316 OpenMPMapClauseKind MapType = OMPC_MAP_unknown, 21317 ArrayRef<OpenMPMapModifierKind> Modifiers = {}, 21318 bool IsMapTypeImplicit = false, bool NoDiagnose = false) { 21319 // We only expect mappable expressions in 'to', 'from', and 'map' clauses. 21320 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) && 21321 "Unexpected clause kind with mappable expressions!"); 21322 21323 // If the identifier of user-defined mapper is not specified, it is "default". 21324 // We do not change the actual name in this clause to distinguish whether a 21325 // mapper is specified explicitly, i.e., it is not explicitly specified when 21326 // MapperId.getName() is empty. 21327 if (!MapperId.getName() || MapperId.getName().isEmpty()) { 21328 auto &DeclNames = SemaRef.getASTContext().DeclarationNames; 21329 MapperId.setName(DeclNames.getIdentifier( 21330 &SemaRef.getASTContext().Idents.get("default"))); 21331 MapperId.setLoc(StartLoc); 21332 } 21333 21334 // Iterators to find the current unresolved mapper expression. 21335 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end(); 21336 bool UpdateUMIt = false; 21337 Expr *UnresolvedMapper = nullptr; 21338 21339 bool HasHoldModifier = 21340 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold); 21341 21342 // Keep track of the mappable components and base declarations in this clause. 21343 // Each entry in the list is going to have a list of components associated. We 21344 // record each set of the components so that we can build the clause later on. 21345 // In the end we should have the same amount of declarations and component 21346 // lists. 21347 21348 for (Expr *RE : MVLI.VarList) { 21349 assert(RE && "Null expr in omp to/from/map clause"); 21350 SourceLocation ELoc = RE->getExprLoc(); 21351 21352 // Find the current unresolved mapper expression. 21353 if (UpdateUMIt && UMIt != UMEnd) { 21354 UMIt++; 21355 assert( 21356 UMIt != UMEnd && 21357 "Expect the size of UnresolvedMappers to match with that of VarList"); 21358 } 21359 UpdateUMIt = true; 21360 if (UMIt != UMEnd) 21361 UnresolvedMapper = *UMIt; 21362 21363 const Expr *VE = RE->IgnoreParenLValueCasts(); 21364 21365 if (VE->isValueDependent() || VE->isTypeDependent() || 21366 VE->isInstantiationDependent() || 21367 VE->containsUnexpandedParameterPack()) { 21368 // Try to find the associated user-defined mapper. 21369 ExprResult ER = buildUserDefinedMapperRef( 21370 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId, 21371 VE->getType().getCanonicalType(), UnresolvedMapper); 21372 if (ER.isInvalid()) 21373 continue; 21374 MVLI.UDMapperList.push_back(ER.get()); 21375 // We can only analyze this information once the missing information is 21376 // resolved. 21377 MVLI.ProcessedVarList.push_back(RE); 21378 continue; 21379 } 21380 21381 Expr *SimpleExpr = RE->IgnoreParenCasts(); 21382 21383 if (!RE->isLValue()) { 21384 if (SemaRef.getLangOpts().OpenMP < 50) { 21385 SemaRef.Diag( 21386 ELoc, diag::err_omp_expected_named_var_member_or_array_expression) 21387 << RE->getSourceRange(); 21388 } else { 21389 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses) 21390 << getOpenMPClauseName(CKind) << RE->getSourceRange(); 21391 } 21392 continue; 21393 } 21394 21395 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents; 21396 ValueDecl *CurDeclaration = nullptr; 21397 21398 // Obtain the array or member expression bases if required. Also, fill the 21399 // components array with all the components identified in the process. 21400 const Expr *BE = 21401 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind, 21402 DSAS->getCurrentDirective(), NoDiagnose); 21403 if (!BE) 21404 continue; 21405 21406 assert(!CurComponents.empty() && 21407 "Invalid mappable expression information."); 21408 21409 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) { 21410 // Add store "this" pointer to class in DSAStackTy for future checking 21411 DSAS->addMappedClassesQualTypes(TE->getType()); 21412 // Try to find the associated user-defined mapper. 21413 ExprResult ER = buildUserDefinedMapperRef( 21414 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId, 21415 VE->getType().getCanonicalType(), UnresolvedMapper); 21416 if (ER.isInvalid()) 21417 continue; 21418 MVLI.UDMapperList.push_back(ER.get()); 21419 // Skip restriction checking for variable or field declarations 21420 MVLI.ProcessedVarList.push_back(RE); 21421 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1); 21422 MVLI.VarComponents.back().append(CurComponents.begin(), 21423 CurComponents.end()); 21424 MVLI.VarBaseDeclarations.push_back(nullptr); 21425 continue; 21426 } 21427 21428 // For the following checks, we rely on the base declaration which is 21429 // expected to be associated with the last component. The declaration is 21430 // expected to be a variable or a field (if 'this' is being mapped). 21431 CurDeclaration = CurComponents.back().getAssociatedDeclaration(); 21432 assert(CurDeclaration && "Null decl on map clause."); 21433 assert( 21434 CurDeclaration->isCanonicalDecl() && 21435 "Expecting components to have associated only canonical declarations."); 21436 21437 auto *VD = dyn_cast<VarDecl>(CurDeclaration); 21438 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration); 21439 21440 assert((VD || FD) && "Only variables or fields are expected here!"); 21441 (void)FD; 21442 21443 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10] 21444 // threadprivate variables cannot appear in a map clause. 21445 // OpenMP 4.5 [2.10.5, target update Construct] 21446 // threadprivate variables cannot appear in a from clause. 21447 if (VD && DSAS->isThreadPrivate(VD)) { 21448 if (NoDiagnose) 21449 continue; 21450 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false); 21451 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause) 21452 << getOpenMPClauseName(CKind); 21453 reportOriginalDsa(SemaRef, DSAS, VD, DVar); 21454 continue; 21455 } 21456 21457 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9] 21458 // A list item cannot appear in both a map clause and a data-sharing 21459 // attribute clause on the same construct. 21460 21461 // Check conflicts with other map clause expressions. We check the conflicts 21462 // with the current construct separately from the enclosing data 21463 // environment, because the restrictions are different. We only have to 21464 // check conflicts across regions for the map clauses. 21465 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr, 21466 /*CurrentRegionOnly=*/true, CurComponents, CKind)) 21467 break; 21468 if (CKind == OMPC_map && 21469 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) && 21470 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr, 21471 /*CurrentRegionOnly=*/false, CurComponents, CKind)) 21472 break; 21473 21474 // OpenMP 4.5 [2.10.5, target update Construct] 21475 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1] 21476 // If the type of a list item is a reference to a type T then the type will 21477 // be considered to be T for all purposes of this clause. 21478 auto I = llvm::find_if( 21479 CurComponents, 21480 [](const OMPClauseMappableExprCommon::MappableComponent &MC) { 21481 return MC.getAssociatedDeclaration(); 21482 }); 21483 assert(I != CurComponents.end() && "Null decl on map clause."); 21484 (void)I; 21485 QualType Type; 21486 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens()); 21487 auto *OASE = dyn_cast<ArraySectionExpr>(VE->IgnoreParens()); 21488 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens()); 21489 if (ASE) { 21490 Type = ASE->getType().getNonReferenceType(); 21491 } else if (OASE) { 21492 QualType BaseType = 21493 ArraySectionExpr::getBaseOriginalType(OASE->getBase()); 21494 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe()) 21495 Type = ATy->getElementType(); 21496 else 21497 Type = BaseType->getPointeeType(); 21498 Type = Type.getNonReferenceType(); 21499 } else if (OAShE) { 21500 Type = OAShE->getBase()->getType()->getPointeeType(); 21501 } else { 21502 Type = VE->getType(); 21503 } 21504 21505 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4] 21506 // A list item in a to or from clause must have a mappable type. 21507 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9] 21508 // A list item must have a mappable type. 21509 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef, 21510 DSAS, Type, /*FullCheck=*/true)) 21511 continue; 21512 21513 if (CKind == OMPC_map) { 21514 // target enter data 21515 // OpenMP [2.10.2, Restrictions, p. 99] 21516 // A map-type must be specified in all map clauses and must be either 21517 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if 21518 // no map type is present. 21519 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective(); 21520 if (DKind == OMPD_target_enter_data && 21521 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc || 21522 SemaRef.getLangOpts().OpenMP >= 52)) { 21523 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive) 21524 << (IsMapTypeImplicit ? 1 : 0) 21525 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType) 21526 << getOpenMPDirectiveName(DKind); 21527 continue; 21528 } 21529 21530 // target exit_data 21531 // OpenMP [2.10.3, Restrictions, p. 102] 21532 // A map-type must be specified in all map clauses and must be either 21533 // from, release, or delete. Starting with OpenMP 5.2 the default map 21534 // type is `from` if no map type is present. 21535 if (DKind == OMPD_target_exit_data && 21536 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release || 21537 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) { 21538 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive) 21539 << (IsMapTypeImplicit ? 1 : 0) 21540 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType) 21541 << getOpenMPDirectiveName(DKind); 21542 continue; 21543 } 21544 21545 // The 'ompx_hold' modifier is specifically intended to be used on a 21546 // 'target' or 'target data' directive to prevent data from being unmapped 21547 // during the associated statement. It is not permitted on a 'target 21548 // enter data' or 'target exit data' directive, which have no associated 21549 // statement. 21550 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) && 21551 HasHoldModifier) { 21552 SemaRef.Diag(StartLoc, 21553 diag::err_omp_invalid_map_type_modifier_for_directive) 21554 << getOpenMPSimpleClauseTypeName(OMPC_map, 21555 OMPC_MAP_MODIFIER_ompx_hold) 21556 << getOpenMPDirectiveName(DKind); 21557 continue; 21558 } 21559 21560 // target, target data 21561 // OpenMP 5.0 [2.12.2, Restrictions, p. 163] 21562 // OpenMP 5.0 [2.12.5, Restrictions, p. 174] 21563 // A map-type in a map clause must be to, from, tofrom or alloc 21564 if ((DKind == OMPD_target_data || 21565 isOpenMPTargetExecutionDirective(DKind)) && 21566 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from || 21567 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) { 21568 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive) 21569 << (IsMapTypeImplicit ? 1 : 0) 21570 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType) 21571 << getOpenMPDirectiveName(DKind); 21572 continue; 21573 } 21574 21575 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3] 21576 // A list item cannot appear in both a map clause and a data-sharing 21577 // attribute clause on the same construct 21578 // 21579 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7] 21580 // A list item cannot appear in both a map clause and a data-sharing 21581 // attribute clause on the same construct unless the construct is a 21582 // combined construct. 21583 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 && 21584 isOpenMPTargetExecutionDirective(DKind)) || 21585 DKind == OMPD_target)) { 21586 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false); 21587 if (isOpenMPPrivate(DVar.CKind)) { 21588 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa) 21589 << getOpenMPClauseName(DVar.CKind) 21590 << getOpenMPClauseName(OMPC_map) 21591 << getOpenMPDirectiveName(DSAS->getCurrentDirective()); 21592 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar); 21593 continue; 21594 } 21595 } 21596 } 21597 21598 // Try to find the associated user-defined mapper. 21599 ExprResult ER = buildUserDefinedMapperRef( 21600 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId, 21601 Type.getCanonicalType(), UnresolvedMapper); 21602 if (ER.isInvalid()) 21603 continue; 21604 if (!ER.get() && isa<ArraySectionExpr>(VE)) { 21605 // Create implicit mapper as needed. 21606 QualType BaseType = VE->getType().getCanonicalType(); 21607 if (BaseType->isSpecificBuiltinType(BuiltinType::ArraySection)) { 21608 const auto *OASE = cast<ArraySectionExpr>(VE->IgnoreParenImpCasts()); 21609 QualType BType = ArraySectionExpr::getBaseOriginalType(OASE->getBase()); 21610 QualType ElemType; 21611 if (const auto *ATy = BType->getAsArrayTypeUnsafe()) 21612 ElemType = ATy->getElementType(); 21613 else 21614 ElemType = BType->getPointeeType(); 21615 BaseType = ElemType.getCanonicalType(); 21616 } 21617 if (BaseType->getAsRecordDecl() && 21618 isImplicitMapperNeeded(SemaRef, DSAS, BaseType, VE)) { 21619 ER = buildImplicitMapper(SemaRef, BaseType, DSAS); 21620 } 21621 } 21622 MVLI.UDMapperList.push_back(ER.get()); 21623 21624 // Save the current expression. 21625 MVLI.ProcessedVarList.push_back(RE); 21626 21627 // Store the components in the stack so that they can be used to check 21628 // against other clauses later on. 21629 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents, 21630 /*WhereFoundClauseKind=*/OMPC_map); 21631 21632 // Save the components and declaration to create the clause. For purposes of 21633 // the clause creation, any component list that has base 'this' uses 21634 // null as base declaration. 21635 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1); 21636 MVLI.VarComponents.back().append(CurComponents.begin(), 21637 CurComponents.end()); 21638 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr 21639 : CurDeclaration); 21640 } 21641 } 21642 21643 OMPClause *SemaOpenMP::ActOnOpenMPMapClause( 21644 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers, 21645 ArrayRef<SourceLocation> MapTypeModifiersLoc, 21646 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, 21647 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc, 21648 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, 21649 const OMPVarListLocTy &Locs, bool NoDiagnose, 21650 ArrayRef<Expr *> UnresolvedMappers) { 21651 OpenMPMapModifierKind Modifiers[] = { 21652 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown, 21653 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown, 21654 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown}; 21655 SourceLocation ModifiersLoc[NumberOfOMPMapClauseModifiers]; 21656 21657 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType( 21658 BuiltinType::OMPIterator)) 21659 Diag(IteratorModifier->getExprLoc(), 21660 diag::err_omp_map_modifier_not_iterator); 21661 21662 // Process map-type-modifiers, flag errors for duplicate modifiers. 21663 unsigned Count = 0; 21664 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) { 21665 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown && 21666 llvm::is_contained(Modifiers, MapTypeModifiers[I])) { 21667 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier); 21668 continue; 21669 } 21670 assert(Count < NumberOfOMPMapClauseModifiers && 21671 "Modifiers exceed the allowed number of map type modifiers"); 21672 Modifiers[Count] = MapTypeModifiers[I]; 21673 ModifiersLoc[Count] = MapTypeModifiersLoc[I]; 21674 ++Count; 21675 } 21676 21677 MappableVarListInfo MVLI(VarList); 21678 checkMappableExpressionList(SemaRef, DSAStack, OMPC_map, MVLI, Locs.StartLoc, 21679 MapperIdScopeSpec, MapperId, UnresolvedMappers, 21680 MapType, Modifiers, IsMapTypeImplicit, 21681 NoDiagnose); 21682 21683 // We need to produce a map clause even if we don't have variables so that 21684 // other diagnostics related with non-existing map clauses are accurate. 21685 return OMPMapClause::Create( 21686 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations, 21687 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers, 21688 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()), 21689 MapperId, MapType, IsMapTypeImplicit, MapLoc); 21690 } 21691 21692 QualType SemaOpenMP::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, 21693 TypeResult ParsedType) { 21694 assert(ParsedType.isUsable()); 21695 21696 QualType ReductionType = SemaRef.GetTypeFromParser(ParsedType.get()); 21697 if (ReductionType.isNull()) 21698 return QualType(); 21699 21700 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++ 21701 // A type name in a declare reduction directive cannot be a function type, an 21702 // array type, a reference type, or a type qualified with const, volatile or 21703 // restrict. 21704 if (ReductionType.hasQualifiers()) { 21705 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0; 21706 return QualType(); 21707 } 21708 21709 if (ReductionType->isFunctionType()) { 21710 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1; 21711 return QualType(); 21712 } 21713 if (ReductionType->isReferenceType()) { 21714 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2; 21715 return QualType(); 21716 } 21717 if (ReductionType->isArrayType()) { 21718 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3; 21719 return QualType(); 21720 } 21721 return ReductionType; 21722 } 21723 21724 SemaOpenMP::DeclGroupPtrTy 21725 SemaOpenMP::ActOnOpenMPDeclareReductionDirectiveStart( 21726 Scope *S, DeclContext *DC, DeclarationName Name, 21727 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes, 21728 AccessSpecifier AS, Decl *PrevDeclInScope) { 21729 SmallVector<Decl *, 8> Decls; 21730 Decls.reserve(ReductionTypes.size()); 21731 21732 LookupResult Lookup(SemaRef, Name, SourceLocation(), 21733 Sema::LookupOMPReductionName, 21734 SemaRef.forRedeclarationInCurContext()); 21735 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions 21736 // A reduction-identifier may not be re-declared in the current scope for the 21737 // same type or for a type that is compatible according to the base language 21738 // rules. 21739 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes; 21740 OMPDeclareReductionDecl *PrevDRD = nullptr; 21741 bool InCompoundScope = true; 21742 if (S != nullptr) { 21743 // Find previous declaration with the same name not referenced in other 21744 // declarations. 21745 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction(); 21746 InCompoundScope = 21747 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty(); 21748 SemaRef.LookupName(Lookup, S); 21749 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false, 21750 /*AllowInlineNamespace=*/false); 21751 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious; 21752 LookupResult::Filter Filter = Lookup.makeFilter(); 21753 while (Filter.hasNext()) { 21754 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next()); 21755 if (InCompoundScope) { 21756 UsedAsPrevious.try_emplace(PrevDecl, false); 21757 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope()) 21758 UsedAsPrevious[D] = true; 21759 } 21760 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] = 21761 PrevDecl->getLocation(); 21762 } 21763 Filter.done(); 21764 if (InCompoundScope) { 21765 for (const auto &PrevData : UsedAsPrevious) { 21766 if (!PrevData.second) { 21767 PrevDRD = PrevData.first; 21768 break; 21769 } 21770 } 21771 } 21772 } else if (PrevDeclInScope != nullptr) { 21773 auto *PrevDRDInScope = PrevDRD = 21774 cast<OMPDeclareReductionDecl>(PrevDeclInScope); 21775 do { 21776 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] = 21777 PrevDRDInScope->getLocation(); 21778 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope(); 21779 } while (PrevDRDInScope != nullptr); 21780 } 21781 for (const auto &TyData : ReductionTypes) { 21782 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType()); 21783 bool Invalid = false; 21784 if (I != PreviousRedeclTypes.end()) { 21785 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition) 21786 << TyData.first; 21787 Diag(I->second, diag::note_previous_definition); 21788 Invalid = true; 21789 } 21790 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second; 21791 auto *DRD = OMPDeclareReductionDecl::Create( 21792 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD); 21793 DC->addDecl(DRD); 21794 DRD->setAccess(AS); 21795 Decls.push_back(DRD); 21796 if (Invalid) 21797 DRD->setInvalidDecl(); 21798 else 21799 PrevDRD = DRD; 21800 } 21801 21802 return DeclGroupPtrTy::make( 21803 DeclGroupRef::Create(getASTContext(), Decls.begin(), Decls.size())); 21804 } 21805 21806 void SemaOpenMP::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) { 21807 auto *DRD = cast<OMPDeclareReductionDecl>(D); 21808 21809 // Enter new function scope. 21810 SemaRef.PushFunctionScope(); 21811 SemaRef.setFunctionHasBranchProtectedScope(); 21812 SemaRef.getCurFunction()->setHasOMPDeclareReductionCombiner(); 21813 21814 if (S != nullptr) 21815 SemaRef.PushDeclContext(S, DRD); 21816 else 21817 SemaRef.CurContext = DRD; 21818 21819 SemaRef.PushExpressionEvaluationContext( 21820 Sema::ExpressionEvaluationContext::PotentiallyEvaluated); 21821 21822 QualType ReductionType = DRD->getType(); 21823 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will 21824 // be replaced by '*omp_parm' during codegen. This required because 'omp_in' 21825 // uses semantics of argument handles by value, but it should be passed by 21826 // reference. C lang does not support references, so pass all parameters as 21827 // pointers. 21828 // Create 'T omp_in;' variable. 21829 VarDecl *OmpInParm = 21830 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_in"); 21831 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will 21832 // be replaced by '*omp_parm' during codegen. This required because 'omp_out' 21833 // uses semantics of argument handles by value, but it should be passed by 21834 // reference. C lang does not support references, so pass all parameters as 21835 // pointers. 21836 // Create 'T omp_out;' variable. 21837 VarDecl *OmpOutParm = 21838 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_out"); 21839 if (S != nullptr) { 21840 SemaRef.PushOnScopeChains(OmpInParm, S); 21841 SemaRef.PushOnScopeChains(OmpOutParm, S); 21842 } else { 21843 DRD->addDecl(OmpInParm); 21844 DRD->addDecl(OmpOutParm); 21845 } 21846 Expr *InE = 21847 ::buildDeclRefExpr(SemaRef, OmpInParm, ReductionType, D->getLocation()); 21848 Expr *OutE = 21849 ::buildDeclRefExpr(SemaRef, OmpOutParm, ReductionType, D->getLocation()); 21850 DRD->setCombinerData(InE, OutE); 21851 } 21852 21853 void SemaOpenMP::ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, 21854 Expr *Combiner) { 21855 auto *DRD = cast<OMPDeclareReductionDecl>(D); 21856 SemaRef.DiscardCleanupsInEvaluationContext(); 21857 SemaRef.PopExpressionEvaluationContext(); 21858 21859 SemaRef.PopDeclContext(); 21860 SemaRef.PopFunctionScopeInfo(); 21861 21862 if (Combiner != nullptr) 21863 DRD->setCombiner(Combiner); 21864 else 21865 DRD->setInvalidDecl(); 21866 } 21867 21868 VarDecl *SemaOpenMP::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, 21869 Decl *D) { 21870 auto *DRD = cast<OMPDeclareReductionDecl>(D); 21871 21872 // Enter new function scope. 21873 SemaRef.PushFunctionScope(); 21874 SemaRef.setFunctionHasBranchProtectedScope(); 21875 21876 if (S != nullptr) 21877 SemaRef.PushDeclContext(S, DRD); 21878 else 21879 SemaRef.CurContext = DRD; 21880 21881 SemaRef.PushExpressionEvaluationContext( 21882 Sema::ExpressionEvaluationContext::PotentiallyEvaluated); 21883 21884 QualType ReductionType = DRD->getType(); 21885 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will 21886 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv' 21887 // uses semantics of argument handles by value, but it should be passed by 21888 // reference. C lang does not support references, so pass all parameters as 21889 // pointers. 21890 // Create 'T omp_priv;' variable. 21891 VarDecl *OmpPrivParm = 21892 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_priv"); 21893 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will 21894 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig' 21895 // uses semantics of argument handles by value, but it should be passed by 21896 // reference. C lang does not support references, so pass all parameters as 21897 // pointers. 21898 // Create 'T omp_orig;' variable. 21899 VarDecl *OmpOrigParm = 21900 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_orig"); 21901 if (S != nullptr) { 21902 SemaRef.PushOnScopeChains(OmpPrivParm, S); 21903 SemaRef.PushOnScopeChains(OmpOrigParm, S); 21904 } else { 21905 DRD->addDecl(OmpPrivParm); 21906 DRD->addDecl(OmpOrigParm); 21907 } 21908 Expr *OrigE = 21909 ::buildDeclRefExpr(SemaRef, OmpOrigParm, ReductionType, D->getLocation()); 21910 Expr *PrivE = 21911 ::buildDeclRefExpr(SemaRef, OmpPrivParm, ReductionType, D->getLocation()); 21912 DRD->setInitializerData(OrigE, PrivE); 21913 return OmpPrivParm; 21914 } 21915 21916 void SemaOpenMP::ActOnOpenMPDeclareReductionInitializerEnd( 21917 Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) { 21918 auto *DRD = cast<OMPDeclareReductionDecl>(D); 21919 SemaRef.DiscardCleanupsInEvaluationContext(); 21920 SemaRef.PopExpressionEvaluationContext(); 21921 21922 SemaRef.PopDeclContext(); 21923 SemaRef.PopFunctionScopeInfo(); 21924 21925 if (Initializer != nullptr) { 21926 DRD->setInitializer(Initializer, OMPDeclareReductionInitKind::Call); 21927 } else if (OmpPrivParm->hasInit()) { 21928 DRD->setInitializer(OmpPrivParm->getInit(), 21929 OmpPrivParm->isDirectInit() 21930 ? OMPDeclareReductionInitKind::Direct 21931 : OMPDeclareReductionInitKind::Copy); 21932 } else { 21933 DRD->setInvalidDecl(); 21934 } 21935 } 21936 21937 SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareReductionDirectiveEnd( 21938 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) { 21939 for (Decl *D : DeclReductions.get()) { 21940 if (IsValid) { 21941 if (S) 21942 SemaRef.PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S, 21943 /*AddToContext=*/false); 21944 } else { 21945 D->setInvalidDecl(); 21946 } 21947 } 21948 return DeclReductions; 21949 } 21950 21951 TypeResult SemaOpenMP::ActOnOpenMPDeclareMapperVarDecl(Scope *S, 21952 Declarator &D) { 21953 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D); 21954 QualType T = TInfo->getType(); 21955 if (D.isInvalidType()) 21956 return true; 21957 21958 if (getLangOpts().CPlusPlus) { 21959 // Check that there are no default arguments (C++ only). 21960 SemaRef.CheckExtraCXXDefaultArguments(D); 21961 } 21962 21963 return SemaRef.CreateParsedType(T, TInfo); 21964 } 21965 21966 QualType SemaOpenMP::ActOnOpenMPDeclareMapperType(SourceLocation TyLoc, 21967 TypeResult ParsedType) { 21968 assert(ParsedType.isUsable() && "Expect usable parsed mapper type"); 21969 21970 QualType MapperType = SemaRef.GetTypeFromParser(ParsedType.get()); 21971 assert(!MapperType.isNull() && "Expect valid mapper type"); 21972 21973 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions 21974 // The type must be of struct, union or class type in C and C++ 21975 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) { 21976 Diag(TyLoc, diag::err_omp_mapper_wrong_type); 21977 return QualType(); 21978 } 21979 return MapperType; 21980 } 21981 21982 SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareMapperDirective( 21983 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType, 21984 SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS, 21985 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) { 21986 LookupResult Lookup(SemaRef, Name, SourceLocation(), 21987 Sema::LookupOMPMapperName, 21988 SemaRef.forRedeclarationInCurContext()); 21989 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions 21990 // A mapper-identifier may not be redeclared in the current scope for the 21991 // same type or for a type that is compatible according to the base language 21992 // rules. 21993 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes; 21994 OMPDeclareMapperDecl *PrevDMD = nullptr; 21995 bool InCompoundScope = true; 21996 if (S != nullptr) { 21997 // Find previous declaration with the same name not referenced in other 21998 // declarations. 21999 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction(); 22000 InCompoundScope = 22001 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty(); 22002 SemaRef.LookupName(Lookup, S); 22003 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false, 22004 /*AllowInlineNamespace=*/false); 22005 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious; 22006 LookupResult::Filter Filter = Lookup.makeFilter(); 22007 while (Filter.hasNext()) { 22008 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next()); 22009 if (InCompoundScope) { 22010 UsedAsPrevious.try_emplace(PrevDecl, false); 22011 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope()) 22012 UsedAsPrevious[D] = true; 22013 } 22014 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] = 22015 PrevDecl->getLocation(); 22016 } 22017 Filter.done(); 22018 if (InCompoundScope) { 22019 for (const auto &PrevData : UsedAsPrevious) { 22020 if (!PrevData.second) { 22021 PrevDMD = PrevData.first; 22022 break; 22023 } 22024 } 22025 } 22026 } else if (PrevDeclInScope) { 22027 auto *PrevDMDInScope = PrevDMD = 22028 cast<OMPDeclareMapperDecl>(PrevDeclInScope); 22029 do { 22030 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] = 22031 PrevDMDInScope->getLocation(); 22032 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope(); 22033 } while (PrevDMDInScope != nullptr); 22034 } 22035 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType()); 22036 bool Invalid = false; 22037 if (I != PreviousRedeclTypes.end()) { 22038 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition) 22039 << MapperType << Name; 22040 Diag(I->second, diag::note_previous_definition); 22041 Invalid = true; 22042 } 22043 // Build expressions for implicit maps of data members with 'default' 22044 // mappers. 22045 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses); 22046 if (getLangOpts().OpenMP >= 50) 22047 processImplicitMapsWithDefaultMappers(SemaRef, DSAStack, 22048 ClausesWithImplicit); 22049 auto *DMD = OMPDeclareMapperDecl::Create(getASTContext(), DC, StartLoc, Name, 22050 MapperType, VN, ClausesWithImplicit, 22051 PrevDMD); 22052 if (S) 22053 SemaRef.PushOnScopeChains(DMD, S); 22054 else 22055 DC->addDecl(DMD); 22056 DMD->setAccess(AS); 22057 if (Invalid) 22058 DMD->setInvalidDecl(); 22059 22060 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl(); 22061 VD->setDeclContext(DMD); 22062 VD->setLexicalDeclContext(DMD); 22063 DMD->addDecl(VD); 22064 DMD->setMapperVarRef(MapperVarRef); 22065 22066 return DeclGroupPtrTy::make(DeclGroupRef(DMD)); 22067 } 22068 22069 ExprResult SemaOpenMP::ActOnOpenMPDeclareMapperDirectiveVarDecl( 22070 Scope *S, QualType MapperType, SourceLocation StartLoc, 22071 DeclarationName VN) { 22072 TypeSourceInfo *TInfo = 22073 getASTContext().getTrivialTypeSourceInfo(MapperType, StartLoc); 22074 auto *VD = VarDecl::Create( 22075 getASTContext(), getASTContext().getTranslationUnitDecl(), StartLoc, 22076 StartLoc, VN.getAsIdentifierInfo(), MapperType, TInfo, SC_None); 22077 if (S) 22078 SemaRef.PushOnScopeChains(VD, S, /*AddToContext=*/false); 22079 Expr *E = buildDeclRefExpr(SemaRef, VD, MapperType, StartLoc); 22080 DSAStack->addDeclareMapperVarRef(E); 22081 return E; 22082 } 22083 22084 void SemaOpenMP::ActOnOpenMPIteratorVarDecl(VarDecl *VD) { 22085 if (DSAStack->getDeclareMapperVarRef()) 22086 DSAStack->addIteratorVarDecl(VD); 22087 } 22088 22089 bool SemaOpenMP::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const { 22090 assert(getLangOpts().OpenMP && "Expected OpenMP mode."); 22091 const Expr *Ref = DSAStack->getDeclareMapperVarRef(); 22092 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) { 22093 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl()) 22094 return true; 22095 if (VD->isUsableInConstantExpressions(getASTContext())) 22096 return true; 22097 if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD)) 22098 return true; 22099 return false; 22100 } 22101 return true; 22102 } 22103 22104 const ValueDecl *SemaOpenMP::getOpenMPDeclareMapperVarName() const { 22105 assert(getLangOpts().OpenMP && "Expected OpenMP mode."); 22106 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl(); 22107 } 22108 22109 OMPClause *SemaOpenMP::ActOnOpenMPNumTeamsClause(ArrayRef<Expr *> VarList, 22110 SourceLocation StartLoc, 22111 SourceLocation LParenLoc, 22112 SourceLocation EndLoc) { 22113 if (VarList.empty()) 22114 return nullptr; 22115 22116 for (Expr *ValExpr : VarList) { 22117 // OpenMP [teams Constrcut, Restrictions] 22118 // The num_teams expression must evaluate to a positive integer value. 22119 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_teams, 22120 /*StrictlyPositive=*/true)) 22121 return nullptr; 22122 } 22123 22124 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); 22125 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause( 22126 DKind, OMPC_num_teams, getLangOpts().OpenMP); 22127 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext()) 22128 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc, 22129 LParenLoc, EndLoc, VarList, 22130 /*PreInit=*/nullptr); 22131 22132 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 22133 SmallVector<Expr *, 3> Vars; 22134 for (Expr *ValExpr : VarList) { 22135 ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); 22136 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); 22137 Vars.push_back(ValExpr); 22138 } 22139 22140 Stmt *PreInit = buildPreInits(getASTContext(), Captures); 22141 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc, 22142 LParenLoc, EndLoc, Vars, PreInit); 22143 } 22144 22145 OMPClause *SemaOpenMP::ActOnOpenMPThreadLimitClause(ArrayRef<Expr *> VarList, 22146 SourceLocation StartLoc, 22147 SourceLocation LParenLoc, 22148 SourceLocation EndLoc) { 22149 if (VarList.empty()) 22150 return nullptr; 22151 22152 for (Expr *ValExpr : VarList) { 22153 // OpenMP [teams Constrcut, Restrictions] 22154 // The thread_limit expression must evaluate to a positive integer value. 22155 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_thread_limit, 22156 /*StrictlyPositive=*/true)) 22157 return nullptr; 22158 } 22159 22160 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); 22161 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause( 22162 DKind, OMPC_thread_limit, getLangOpts().OpenMP); 22163 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext()) 22164 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion, 22165 StartLoc, LParenLoc, EndLoc, VarList, 22166 /*PreInit=*/nullptr); 22167 22168 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 22169 SmallVector<Expr *, 3> Vars; 22170 for (Expr *ValExpr : VarList) { 22171 ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); 22172 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); 22173 Vars.push_back(ValExpr); 22174 } 22175 22176 Stmt *PreInit = buildPreInits(getASTContext(), Captures); 22177 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion, StartLoc, 22178 LParenLoc, EndLoc, Vars, PreInit); 22179 } 22180 22181 OMPClause *SemaOpenMP::ActOnOpenMPPriorityClause(Expr *Priority, 22182 SourceLocation StartLoc, 22183 SourceLocation LParenLoc, 22184 SourceLocation EndLoc) { 22185 Expr *ValExpr = Priority; 22186 Stmt *HelperValStmt = nullptr; 22187 OpenMPDirectiveKind CaptureRegion = OMPD_unknown; 22188 22189 // OpenMP [2.9.1, task Constrcut] 22190 // The priority-value is a non-negative numerical scalar expression. 22191 if (!isNonNegativeIntegerValue( 22192 ValExpr, SemaRef, OMPC_priority, 22193 /*StrictlyPositive=*/false, /*BuildCapture=*/true, 22194 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt)) 22195 return nullptr; 22196 22197 return new (getASTContext()) OMPPriorityClause( 22198 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc); 22199 } 22200 22201 OMPClause *SemaOpenMP::ActOnOpenMPGrainsizeClause( 22202 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize, 22203 SourceLocation StartLoc, SourceLocation LParenLoc, 22204 SourceLocation ModifierLoc, SourceLocation EndLoc) { 22205 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) && 22206 "Unexpected grainsize modifier in OpenMP < 51."); 22207 22208 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) { 22209 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0, 22210 OMPC_GRAINSIZE_unknown); 22211 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value) 22212 << Values << getOpenMPClauseName(OMPC_grainsize); 22213 return nullptr; 22214 } 22215 22216 Expr *ValExpr = Grainsize; 22217 Stmt *HelperValStmt = nullptr; 22218 OpenMPDirectiveKind CaptureRegion = OMPD_unknown; 22219 22220 // OpenMP [2.9.2, taskloop Constrcut] 22221 // The parameter of the grainsize clause must be a positive integer 22222 // expression. 22223 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_grainsize, 22224 /*StrictlyPositive=*/true, 22225 /*BuildCapture=*/true, 22226 DSAStack->getCurrentDirective(), 22227 &CaptureRegion, &HelperValStmt)) 22228 return nullptr; 22229 22230 return new (getASTContext()) 22231 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, 22232 StartLoc, LParenLoc, ModifierLoc, EndLoc); 22233 } 22234 22235 OMPClause *SemaOpenMP::ActOnOpenMPNumTasksClause( 22236 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks, 22237 SourceLocation StartLoc, SourceLocation LParenLoc, 22238 SourceLocation ModifierLoc, SourceLocation EndLoc) { 22239 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) && 22240 "Unexpected num_tasks modifier in OpenMP < 51."); 22241 22242 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) { 22243 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0, 22244 OMPC_NUMTASKS_unknown); 22245 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value) 22246 << Values << getOpenMPClauseName(OMPC_num_tasks); 22247 return nullptr; 22248 } 22249 22250 Expr *ValExpr = NumTasks; 22251 Stmt *HelperValStmt = nullptr; 22252 OpenMPDirectiveKind CaptureRegion = OMPD_unknown; 22253 22254 // OpenMP [2.9.2, taskloop Constrcut] 22255 // The parameter of the num_tasks clause must be a positive integer 22256 // expression. 22257 if (!isNonNegativeIntegerValue( 22258 ValExpr, SemaRef, OMPC_num_tasks, 22259 /*StrictlyPositive=*/true, /*BuildCapture=*/true, 22260 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt)) 22261 return nullptr; 22262 22263 return new (getASTContext()) 22264 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, 22265 StartLoc, LParenLoc, ModifierLoc, EndLoc); 22266 } 22267 22268 OMPClause *SemaOpenMP::ActOnOpenMPHintClause(Expr *Hint, 22269 SourceLocation StartLoc, 22270 SourceLocation LParenLoc, 22271 SourceLocation EndLoc) { 22272 // OpenMP [2.13.2, critical construct, Description] 22273 // ... where hint-expression is an integer constant expression that evaluates 22274 // to a valid lock hint. 22275 ExprResult HintExpr = 22276 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false); 22277 if (HintExpr.isInvalid()) 22278 return nullptr; 22279 return new (getASTContext()) 22280 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc); 22281 } 22282 22283 /// Tries to find omp_event_handle_t type. 22284 static bool findOMPEventHandleT(Sema &S, SourceLocation Loc, 22285 DSAStackTy *Stack) { 22286 QualType OMPEventHandleT = Stack->getOMPEventHandleT(); 22287 if (!OMPEventHandleT.isNull()) 22288 return true; 22289 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t"); 22290 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope()); 22291 if (!PT.getAsOpaquePtr() || PT.get().isNull()) { 22292 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t"; 22293 return false; 22294 } 22295 Stack->setOMPEventHandleT(PT.get()); 22296 return true; 22297 } 22298 22299 OMPClause *SemaOpenMP::ActOnOpenMPDetachClause(Expr *Evt, 22300 SourceLocation StartLoc, 22301 SourceLocation LParenLoc, 22302 SourceLocation EndLoc) { 22303 if (!Evt->isValueDependent() && !Evt->isTypeDependent() && 22304 !Evt->isInstantiationDependent() && 22305 !Evt->containsUnexpandedParameterPack()) { 22306 if (!findOMPEventHandleT(SemaRef, Evt->getExprLoc(), DSAStack)) 22307 return nullptr; 22308 // OpenMP 5.0, 2.10.1 task Construct. 22309 // event-handle is a variable of the omp_event_handle_t type. 22310 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts()); 22311 if (!Ref) { 22312 Diag(Evt->getExprLoc(), diag::err_omp_var_expected) 22313 << "omp_event_handle_t" << 0 << Evt->getSourceRange(); 22314 return nullptr; 22315 } 22316 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl()); 22317 if (!VD) { 22318 Diag(Evt->getExprLoc(), diag::err_omp_var_expected) 22319 << "omp_event_handle_t" << 0 << Evt->getSourceRange(); 22320 return nullptr; 22321 } 22322 if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(), 22323 VD->getType()) || 22324 VD->getType().isConstant(getASTContext())) { 22325 Diag(Evt->getExprLoc(), diag::err_omp_var_expected) 22326 << "omp_event_handle_t" << 1 << VD->getType() 22327 << Evt->getSourceRange(); 22328 return nullptr; 22329 } 22330 // OpenMP 5.0, 2.10.1 task Construct 22331 // [detach clause]... The event-handle will be considered as if it was 22332 // specified on a firstprivate clause. 22333 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false); 22334 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate && 22335 DVar.RefExpr) { 22336 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa) 22337 << getOpenMPClauseName(DVar.CKind) 22338 << getOpenMPClauseName(OMPC_firstprivate); 22339 reportOriginalDsa(SemaRef, DSAStack, VD, DVar); 22340 return nullptr; 22341 } 22342 } 22343 22344 return new (getASTContext()) 22345 OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc); 22346 } 22347 22348 OMPClause *SemaOpenMP::ActOnOpenMPDistScheduleClause( 22349 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, 22350 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc, 22351 SourceLocation EndLoc) { 22352 if (Kind == OMPC_DIST_SCHEDULE_unknown) { 22353 std::string Values; 22354 Values += "'"; 22355 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0); 22356 Values += "'"; 22357 Diag(KindLoc, diag::err_omp_unexpected_clause_value) 22358 << Values << getOpenMPClauseName(OMPC_dist_schedule); 22359 return nullptr; 22360 } 22361 Expr *ValExpr = ChunkSize; 22362 Stmt *HelperValStmt = nullptr; 22363 if (ChunkSize) { 22364 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() && 22365 !ChunkSize->isInstantiationDependent() && 22366 !ChunkSize->containsUnexpandedParameterPack()) { 22367 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc(); 22368 ExprResult Val = 22369 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize); 22370 if (Val.isInvalid()) 22371 return nullptr; 22372 22373 ValExpr = Val.get(); 22374 22375 // OpenMP [2.7.1, Restrictions] 22376 // chunk_size must be a loop invariant integer expression with a positive 22377 // value. 22378 if (std::optional<llvm::APSInt> Result = 22379 ValExpr->getIntegerConstantExpr(getASTContext())) { 22380 if (Result->isSigned() && !Result->isStrictlyPositive()) { 22381 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause) 22382 << "dist_schedule" << ChunkSize->getSourceRange(); 22383 return nullptr; 22384 } 22385 } else if (getOpenMPCaptureRegionForClause( 22386 DSAStack->getCurrentDirective(), OMPC_dist_schedule, 22387 getLangOpts().OpenMP) != OMPD_unknown && 22388 !SemaRef.CurContext->isDependentContext()) { 22389 ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); 22390 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 22391 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); 22392 HelperValStmt = buildPreInits(getASTContext(), Captures); 22393 } 22394 } 22395 } 22396 22397 return new (getASTContext()) 22398 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, 22399 Kind, ValExpr, HelperValStmt); 22400 } 22401 22402 OMPClause *SemaOpenMP::ActOnOpenMPDefaultmapClause( 22403 OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind, 22404 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, 22405 SourceLocation KindLoc, SourceLocation EndLoc) { 22406 if (getLangOpts().OpenMP < 50) { 22407 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom || 22408 Kind != OMPC_DEFAULTMAP_scalar) { 22409 std::string Value; 22410 SourceLocation Loc; 22411 Value += "'"; 22412 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) { 22413 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap, 22414 OMPC_DEFAULTMAP_MODIFIER_tofrom); 22415 Loc = MLoc; 22416 } else { 22417 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap, 22418 OMPC_DEFAULTMAP_scalar); 22419 Loc = KindLoc; 22420 } 22421 Value += "'"; 22422 Diag(Loc, diag::err_omp_unexpected_clause_value) 22423 << Value << getOpenMPClauseName(OMPC_defaultmap); 22424 return nullptr; 22425 } 22426 } else { 22427 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown); 22428 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) || 22429 (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid()); 22430 if (!isDefaultmapKind || !isDefaultmapModifier) { 22431 StringRef KindValue = getLangOpts().OpenMP < 52 22432 ? "'scalar', 'aggregate', 'pointer'" 22433 : "'scalar', 'aggregate', 'pointer', 'all'"; 22434 if (getLangOpts().OpenMP == 50) { 22435 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', " 22436 "'firstprivate', 'none', 'default'"; 22437 if (!isDefaultmapKind && isDefaultmapModifier) { 22438 Diag(KindLoc, diag::err_omp_unexpected_clause_value) 22439 << KindValue << getOpenMPClauseName(OMPC_defaultmap); 22440 } else if (isDefaultmapKind && !isDefaultmapModifier) { 22441 Diag(MLoc, diag::err_omp_unexpected_clause_value) 22442 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap); 22443 } else { 22444 Diag(MLoc, diag::err_omp_unexpected_clause_value) 22445 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap); 22446 Diag(KindLoc, diag::err_omp_unexpected_clause_value) 22447 << KindValue << getOpenMPClauseName(OMPC_defaultmap); 22448 } 22449 } else { 22450 StringRef ModifierValue = 22451 "'alloc', 'from', 'to', 'tofrom', " 22452 "'firstprivate', 'none', 'default', 'present'"; 22453 if (!isDefaultmapKind && isDefaultmapModifier) { 22454 Diag(KindLoc, diag::err_omp_unexpected_clause_value) 22455 << KindValue << getOpenMPClauseName(OMPC_defaultmap); 22456 } else if (isDefaultmapKind && !isDefaultmapModifier) { 22457 Diag(MLoc, diag::err_omp_unexpected_clause_value) 22458 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap); 22459 } else { 22460 Diag(MLoc, diag::err_omp_unexpected_clause_value) 22461 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap); 22462 Diag(KindLoc, diag::err_omp_unexpected_clause_value) 22463 << KindValue << getOpenMPClauseName(OMPC_defaultmap); 22464 } 22465 } 22466 return nullptr; 22467 } 22468 22469 // OpenMP [5.0, 2.12.5, Restrictions, p. 174] 22470 // At most one defaultmap clause for each category can appear on the 22471 // directive. 22472 if (DSAStack->checkDefaultmapCategory(Kind)) { 22473 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category); 22474 return nullptr; 22475 } 22476 } 22477 if (Kind == OMPC_DEFAULTMAP_unknown || Kind == OMPC_DEFAULTMAP_all) { 22478 // Variable category is not specified - mark all categories. 22479 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc); 22480 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc); 22481 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc); 22482 } else { 22483 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc); 22484 } 22485 22486 return new (getASTContext()) 22487 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M); 22488 } 22489 22490 bool SemaOpenMP::ActOnStartOpenMPDeclareTargetContext( 22491 DeclareTargetContextInfo &DTCI) { 22492 DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext(); 22493 if (!CurLexicalContext->isFileContext() && 22494 !CurLexicalContext->isExternCContext() && 22495 !CurLexicalContext->isExternCXXContext() && 22496 !isa<CXXRecordDecl>(CurLexicalContext) && 22497 !isa<ClassTemplateDecl>(CurLexicalContext) && 22498 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) && 22499 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) { 22500 Diag(DTCI.Loc, diag::err_omp_region_not_file_context); 22501 return false; 22502 } 22503 22504 // Report affected OpenMP target offloading behavior when in HIP lang-mode. 22505 if (getLangOpts().HIP) 22506 Diag(DTCI.Loc, diag::warn_hip_omp_target_directives); 22507 22508 DeclareTargetNesting.push_back(DTCI); 22509 return true; 22510 } 22511 22512 const SemaOpenMP::DeclareTargetContextInfo 22513 SemaOpenMP::ActOnOpenMPEndDeclareTargetDirective() { 22514 assert(!DeclareTargetNesting.empty() && 22515 "check isInOpenMPDeclareTargetContext() first!"); 22516 return DeclareTargetNesting.pop_back_val(); 22517 } 22518 22519 void SemaOpenMP::ActOnFinishedOpenMPDeclareTargetContext( 22520 DeclareTargetContextInfo &DTCI) { 22521 for (auto &It : DTCI.ExplicitlyMapped) 22522 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI); 22523 } 22524 22525 void SemaOpenMP::DiagnoseUnterminatedOpenMPDeclareTarget() { 22526 if (DeclareTargetNesting.empty()) 22527 return; 22528 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back(); 22529 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target) 22530 << getOpenMPDirectiveName(DTCI.Kind); 22531 } 22532 22533 NamedDecl *SemaOpenMP::lookupOpenMPDeclareTargetName( 22534 Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) { 22535 LookupResult Lookup(SemaRef, Id, Sema::LookupOrdinaryName); 22536 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec, 22537 /*ObjectType=*/QualType(), 22538 /*AllowBuiltinCreation=*/true); 22539 22540 if (Lookup.isAmbiguous()) 22541 return nullptr; 22542 Lookup.suppressDiagnostics(); 22543 22544 if (!Lookup.isSingleResult()) { 22545 VarOrFuncDeclFilterCCC CCC(SemaRef); 22546 if (TypoCorrection Corrected = 22547 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr, 22548 CCC, Sema::CTK_ErrorRecovery)) { 22549 SemaRef.diagnoseTypo(Corrected, 22550 SemaRef.PDiag(diag::err_undeclared_var_use_suggest) 22551 << Id.getName()); 22552 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl()); 22553 return nullptr; 22554 } 22555 22556 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName(); 22557 return nullptr; 22558 } 22559 22560 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>(); 22561 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) && 22562 !isa<FunctionTemplateDecl>(ND)) { 22563 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName(); 22564 return nullptr; 22565 } 22566 return ND; 22567 } 22568 22569 void SemaOpenMP::ActOnOpenMPDeclareTargetName( 22570 NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT, 22571 DeclareTargetContextInfo &DTCI) { 22572 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) || 22573 isa<FunctionTemplateDecl>(ND)) && 22574 "Expected variable, function or function template."); 22575 22576 if (auto *VD = dyn_cast<VarDecl>(ND)) { 22577 // Only global variables can be marked as declare target. 22578 if (!VD->isFileVarDecl() && !VD->isStaticLocal() && 22579 !VD->isStaticDataMember()) { 22580 Diag(Loc, diag::err_omp_declare_target_has_local_vars) 22581 << VD->getNameAsString(); 22582 return; 22583 } 22584 } 22585 // Diagnose marking after use as it may lead to incorrect diagnosis and 22586 // codegen. 22587 if (getLangOpts().OpenMP >= 50 && 22588 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced())) 22589 Diag(Loc, diag::warn_omp_declare_target_after_first_use); 22590 22591 // Report affected OpenMP target offloading behavior when in HIP lang-mode. 22592 if (getLangOpts().HIP) 22593 Diag(Loc, diag::warn_hip_omp_target_directives); 22594 22595 // Explicit declare target lists have precedence. 22596 const unsigned Level = -1; 22597 22598 auto *VD = cast<ValueDecl>(ND); 22599 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr = 22600 OMPDeclareTargetDeclAttr::getActiveAttr(VD); 22601 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT && 22602 (*ActiveAttr)->getLevel() == Level) { 22603 Diag(Loc, diag::err_omp_device_type_mismatch) 22604 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT) 22605 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr( 22606 (*ActiveAttr)->getDevType()); 22607 return; 22608 } 22609 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT && 22610 (*ActiveAttr)->getLevel() == Level) { 22611 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND; 22612 return; 22613 } 22614 22615 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level) 22616 return; 22617 22618 Expr *IndirectE = nullptr; 22619 bool IsIndirect = false; 22620 if (DTCI.Indirect) { 22621 IndirectE = *DTCI.Indirect; 22622 if (!IndirectE) 22623 IsIndirect = true; 22624 } 22625 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit( 22626 getASTContext(), MT, DTCI.DT, IndirectE, IsIndirect, Level, 22627 SourceRange(Loc, Loc)); 22628 ND->addAttr(A); 22629 if (ASTMutationListener *ML = getASTContext().getASTMutationListener()) 22630 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A); 22631 checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Loc); 22632 if (auto *VD = dyn_cast<VarDecl>(ND); 22633 getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() && 22634 VD->hasGlobalStorage()) 22635 ActOnOpenMPDeclareTargetInitializer(ND); 22636 } 22637 22638 static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR, 22639 Sema &SemaRef, Decl *D) { 22640 if (!D || !isa<VarDecl>(D)) 22641 return; 22642 auto *VD = cast<VarDecl>(D); 22643 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy = 22644 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 22645 if (SemaRef.LangOpts.OpenMP >= 50 && 22646 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) || 22647 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) && 22648 VD->hasGlobalStorage()) { 22649 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To && 22650 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) { 22651 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions 22652 // If a lambda declaration and definition appears between a 22653 // declare target directive and the matching end declare target 22654 // directive, all variables that are captured by the lambda 22655 // expression must also appear in a to clause. 22656 SemaRef.Diag(VD->getLocation(), 22657 diag::err_omp_lambda_capture_in_declare_target_not_to); 22658 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here) 22659 << VD << 0 << SR; 22660 return; 22661 } 22662 } 22663 if (MapTy) 22664 return; 22665 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context); 22666 SemaRef.Diag(SL, diag::note_used_here) << SR; 22667 } 22668 22669 static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR, 22670 Sema &SemaRef, DSAStackTy *Stack, 22671 ValueDecl *VD) { 22672 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) || 22673 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(), 22674 /*FullCheck=*/false); 22675 } 22676 22677 void SemaOpenMP::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, 22678 SourceLocation IdLoc) { 22679 if (!D || D->isInvalidDecl()) 22680 return; 22681 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange(); 22682 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation(); 22683 if (auto *VD = dyn_cast<VarDecl>(D)) { 22684 // Only global variables can be marked as declare target. 22685 if (!VD->isFileVarDecl() && !VD->isStaticLocal() && 22686 !VD->isStaticDataMember()) 22687 return; 22688 // 2.10.6: threadprivate variable cannot appear in a declare target 22689 // directive. 22690 if (DSAStack->isThreadPrivate(VD)) { 22691 Diag(SL, diag::err_omp_threadprivate_in_target); 22692 reportOriginalDsa(SemaRef, DSAStack, VD, DSAStack->getTopDSA(VD, false)); 22693 return; 22694 } 22695 } 22696 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D)) 22697 D = FTD->getTemplatedDecl(); 22698 if (auto *FD = dyn_cast<FunctionDecl>(D)) { 22699 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 22700 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD); 22701 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) { 22702 Diag(IdLoc, diag::err_omp_function_in_link_clause); 22703 Diag(FD->getLocation(), diag::note_defined_here) << FD; 22704 return; 22705 } 22706 } 22707 if (auto *VD = dyn_cast<ValueDecl>(D)) { 22708 // Problem if any with var declared with incomplete type will be reported 22709 // as normal, so no need to check it here. 22710 if ((E || !VD->getType()->isIncompleteType()) && 22711 !checkValueDeclInTarget(SL, SR, SemaRef, DSAStack, VD)) 22712 return; 22713 if (!E && isInOpenMPDeclareTargetContext()) { 22714 // Checking declaration inside declare target region. 22715 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) || 22716 isa<FunctionTemplateDecl>(D)) { 22717 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr = 22718 OMPDeclareTargetDeclAttr::getActiveAttr(VD); 22719 unsigned Level = DeclareTargetNesting.size(); 22720 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level) 22721 return; 22722 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back(); 22723 Expr *IndirectE = nullptr; 22724 bool IsIndirect = false; 22725 if (DTCI.Indirect) { 22726 IndirectE = *DTCI.Indirect; 22727 if (!IndirectE) 22728 IsIndirect = true; 22729 } 22730 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit( 22731 getASTContext(), 22732 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter 22733 : OMPDeclareTargetDeclAttr::MT_To, 22734 DTCI.DT, IndirectE, IsIndirect, Level, 22735 SourceRange(DTCI.Loc, DTCI.Loc)); 22736 D->addAttr(A); 22737 if (ASTMutationListener *ML = getASTContext().getASTMutationListener()) 22738 ML->DeclarationMarkedOpenMPDeclareTarget(D, A); 22739 } 22740 return; 22741 } 22742 } 22743 if (!E) 22744 return; 22745 checkDeclInTargetContext(E->getExprLoc(), E->getSourceRange(), SemaRef, D); 22746 } 22747 22748 /// This class visits every VarDecl that the initializer references and adds 22749 /// OMPDeclareTargetDeclAttr to each of them. 22750 class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> { 22751 SmallVector<VarDecl *> DeclVector; 22752 Attr *A; 22753 22754 public: 22755 /// A StmtVisitor class function that visits all DeclRefExpr and adds 22756 /// OMPDeclareTargetDeclAttr to them. 22757 void VisitDeclRefExpr(DeclRefExpr *Node) { 22758 if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) { 22759 VD->addAttr(A); 22760 DeclVector.push_back(VD); 22761 } 22762 } 22763 /// A function that iterates across each of the Expr's children. 22764 void VisitExpr(Expr *Ex) { 22765 for (auto *Child : Ex->children()) { 22766 Visit(Child); 22767 } 22768 } 22769 /// A function that keeps a record of all the Decls that are variables, has 22770 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop 22771 /// each Decl one at a time and use the inherited 'visit' functions to look 22772 /// for DeclRefExpr. 22773 void declareTargetInitializer(Decl *TD) { 22774 A = TD->getAttr<OMPDeclareTargetDeclAttr>(); 22775 DeclVector.push_back(cast<VarDecl>(TD)); 22776 while (!DeclVector.empty()) { 22777 VarDecl *TargetVarDecl = DeclVector.pop_back_val(); 22778 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() && 22779 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) { 22780 if (Expr *Ex = TargetVarDecl->getInit()) 22781 Visit(Ex); 22782 } 22783 } 22784 } 22785 }; 22786 22787 /// Adding OMPDeclareTargetDeclAttr to variables with static storage 22788 /// duration that are referenced in the initializer expression list of 22789 /// variables with static storage duration in declare target directive. 22790 void SemaOpenMP::ActOnOpenMPDeclareTargetInitializer(Decl *TargetDecl) { 22791 GlobalDeclRefChecker Checker; 22792 if (isa<VarDecl>(TargetDecl)) 22793 Checker.declareTargetInitializer(TargetDecl); 22794 } 22795 22796 OMPClause *SemaOpenMP::ActOnOpenMPToClause( 22797 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, 22798 ArrayRef<SourceLocation> MotionModifiersLoc, 22799 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, 22800 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, 22801 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) { 22802 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown, 22803 OMPC_MOTION_MODIFIER_unknown}; 22804 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers]; 22805 22806 // Process motion-modifiers, flag errors for duplicate modifiers. 22807 unsigned Count = 0; 22808 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) { 22809 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown && 22810 llvm::is_contained(Modifiers, MotionModifiers[I])) { 22811 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier); 22812 continue; 22813 } 22814 assert(Count < NumberOfOMPMotionModifiers && 22815 "Modifiers exceed the allowed number of motion modifiers"); 22816 Modifiers[Count] = MotionModifiers[I]; 22817 ModifiersLoc[Count] = MotionModifiersLoc[I]; 22818 ++Count; 22819 } 22820 22821 MappableVarListInfo MVLI(VarList); 22822 checkMappableExpressionList(SemaRef, DSAStack, OMPC_to, MVLI, Locs.StartLoc, 22823 MapperIdScopeSpec, MapperId, UnresolvedMappers); 22824 if (MVLI.ProcessedVarList.empty()) 22825 return nullptr; 22826 22827 return OMPToClause::Create( 22828 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations, 22829 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc, 22830 MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId); 22831 } 22832 22833 OMPClause *SemaOpenMP::ActOnOpenMPFromClause( 22834 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, 22835 ArrayRef<SourceLocation> MotionModifiersLoc, 22836 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, 22837 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, 22838 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) { 22839 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown, 22840 OMPC_MOTION_MODIFIER_unknown}; 22841 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers]; 22842 22843 // Process motion-modifiers, flag errors for duplicate modifiers. 22844 unsigned Count = 0; 22845 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) { 22846 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown && 22847 llvm::is_contained(Modifiers, MotionModifiers[I])) { 22848 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier); 22849 continue; 22850 } 22851 assert(Count < NumberOfOMPMotionModifiers && 22852 "Modifiers exceed the allowed number of motion modifiers"); 22853 Modifiers[Count] = MotionModifiers[I]; 22854 ModifiersLoc[Count] = MotionModifiersLoc[I]; 22855 ++Count; 22856 } 22857 22858 MappableVarListInfo MVLI(VarList); 22859 checkMappableExpressionList(SemaRef, DSAStack, OMPC_from, MVLI, Locs.StartLoc, 22860 MapperIdScopeSpec, MapperId, UnresolvedMappers); 22861 if (MVLI.ProcessedVarList.empty()) 22862 return nullptr; 22863 22864 return OMPFromClause::Create( 22865 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations, 22866 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc, 22867 MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId); 22868 } 22869 22870 OMPClause * 22871 SemaOpenMP::ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList, 22872 const OMPVarListLocTy &Locs) { 22873 MappableVarListInfo MVLI(VarList); 22874 SmallVector<Expr *, 8> PrivateCopies; 22875 SmallVector<Expr *, 8> Inits; 22876 22877 for (Expr *RefExpr : VarList) { 22878 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause."); 22879 SourceLocation ELoc; 22880 SourceRange ERange; 22881 Expr *SimpleRefExpr = RefExpr; 22882 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); 22883 if (Res.second) { 22884 // It will be analyzed later. 22885 MVLI.ProcessedVarList.push_back(RefExpr); 22886 PrivateCopies.push_back(nullptr); 22887 Inits.push_back(nullptr); 22888 } 22889 ValueDecl *D = Res.first; 22890 if (!D) 22891 continue; 22892 22893 QualType Type = D->getType(); 22894 Type = Type.getNonReferenceType().getUnqualifiedType(); 22895 22896 auto *VD = dyn_cast<VarDecl>(D); 22897 22898 // Item should be a pointer or reference to pointer. 22899 if (!Type->isPointerType()) { 22900 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer) 22901 << 0 << RefExpr->getSourceRange(); 22902 continue; 22903 } 22904 22905 // Build the private variable and the expression that refers to it. 22906 auto VDPrivate = 22907 buildVarDecl(SemaRef, ELoc, Type, D->getName(), 22908 D->hasAttrs() ? &D->getAttrs() : nullptr, 22909 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr); 22910 if (VDPrivate->isInvalidDecl()) 22911 continue; 22912 22913 SemaRef.CurContext->addDecl(VDPrivate); 22914 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr( 22915 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc); 22916 22917 // Add temporary variable to initialize the private copy of the pointer. 22918 VarDecl *VDInit = 22919 buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type, ".devptr.temp"); 22920 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr( 22921 SemaRef, VDInit, RefExpr->getType(), RefExpr->getExprLoc()); 22922 SemaRef.AddInitializerToDecl( 22923 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(), 22924 /*DirectInit=*/false); 22925 22926 // If required, build a capture to implement the privatization initialized 22927 // with the current list item value. 22928 DeclRefExpr *Ref = nullptr; 22929 if (!VD) 22930 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true); 22931 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref); 22932 PrivateCopies.push_back(VDPrivateRefExpr); 22933 Inits.push_back(VDInitRefExpr); 22934 22935 // We need to add a data sharing attribute for this variable to make sure it 22936 // is correctly captured. A variable that shows up in a use_device_ptr has 22937 // similar properties of a first private variable. 22938 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref); 22939 22940 // Create a mappable component for the list item. List items in this clause 22941 // only need a component. 22942 MVLI.VarBaseDeclarations.push_back(D); 22943 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1); 22944 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D, 22945 /*IsNonContiguous=*/false); 22946 } 22947 22948 if (MVLI.ProcessedVarList.empty()) 22949 return nullptr; 22950 22951 return OMPUseDevicePtrClause::Create( 22952 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits, 22953 MVLI.VarBaseDeclarations, MVLI.VarComponents); 22954 } 22955 22956 OMPClause * 22957 SemaOpenMP::ActOnOpenMPUseDeviceAddrClause(ArrayRef<Expr *> VarList, 22958 const OMPVarListLocTy &Locs) { 22959 MappableVarListInfo MVLI(VarList); 22960 22961 for (Expr *RefExpr : VarList) { 22962 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause."); 22963 SourceLocation ELoc; 22964 SourceRange ERange; 22965 Expr *SimpleRefExpr = RefExpr; 22966 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange, 22967 /*AllowArraySection=*/true); 22968 if (Res.second) { 22969 // It will be analyzed later. 22970 MVLI.ProcessedVarList.push_back(RefExpr); 22971 } 22972 ValueDecl *D = Res.first; 22973 if (!D) 22974 continue; 22975 auto *VD = dyn_cast<VarDecl>(D); 22976 22977 // If required, build a capture to implement the privatization initialized 22978 // with the current list item value. 22979 DeclRefExpr *Ref = nullptr; 22980 if (!VD) 22981 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true); 22982 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref); 22983 22984 // We need to add a data sharing attribute for this variable to make sure it 22985 // is correctly captured. A variable that shows up in a use_device_addr has 22986 // similar properties of a first private variable. 22987 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref); 22988 22989 // Create a mappable component for the list item. List items in this clause 22990 // only need a component. 22991 MVLI.VarBaseDeclarations.push_back(D); 22992 MVLI.VarComponents.emplace_back(); 22993 Expr *Component = SimpleRefExpr; 22994 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) || 22995 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts()))) 22996 Component = 22997 SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get(); 22998 MVLI.VarComponents.back().emplace_back(Component, D, 22999 /*IsNonContiguous=*/false); 23000 } 23001 23002 if (MVLI.ProcessedVarList.empty()) 23003 return nullptr; 23004 23005 return OMPUseDeviceAddrClause::Create( 23006 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations, 23007 MVLI.VarComponents); 23008 } 23009 23010 OMPClause * 23011 SemaOpenMP::ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList, 23012 const OMPVarListLocTy &Locs) { 23013 MappableVarListInfo MVLI(VarList); 23014 for (Expr *RefExpr : VarList) { 23015 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause."); 23016 SourceLocation ELoc; 23017 SourceRange ERange; 23018 Expr *SimpleRefExpr = RefExpr; 23019 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); 23020 if (Res.second) { 23021 // It will be analyzed later. 23022 MVLI.ProcessedVarList.push_back(RefExpr); 23023 } 23024 ValueDecl *D = Res.first; 23025 if (!D) 23026 continue; 23027 23028 QualType Type = D->getType(); 23029 // item should be a pointer or array or reference to pointer or array 23030 if (!Type.getNonReferenceType()->isPointerType() && 23031 !Type.getNonReferenceType()->isArrayType()) { 23032 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr) 23033 << 0 << RefExpr->getSourceRange(); 23034 continue; 23035 } 23036 23037 // Check if the declaration in the clause does not show up in any data 23038 // sharing attribute. 23039 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false); 23040 if (isOpenMPPrivate(DVar.CKind)) { 23041 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa) 23042 << getOpenMPClauseName(DVar.CKind) 23043 << getOpenMPClauseName(OMPC_is_device_ptr) 23044 << getOpenMPDirectiveName(DSAStack->getCurrentDirective()); 23045 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 23046 continue; 23047 } 23048 23049 const Expr *ConflictExpr; 23050 if (DSAStack->checkMappableExprComponentListsForDecl( 23051 D, /*CurrentRegionOnly=*/true, 23052 [&ConflictExpr]( 23053 OMPClauseMappableExprCommon::MappableExprComponentListRef R, 23054 OpenMPClauseKind) -> bool { 23055 ConflictExpr = R.front().getAssociatedExpression(); 23056 return true; 23057 })) { 23058 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange(); 23059 Diag(ConflictExpr->getExprLoc(), diag::note_used_here) 23060 << ConflictExpr->getSourceRange(); 23061 continue; 23062 } 23063 23064 // Store the components in the stack so that they can be used to check 23065 // against other clauses later on. 23066 OMPClauseMappableExprCommon::MappableComponent MC( 23067 SimpleRefExpr, D, /*IsNonContiguous=*/false); 23068 DSAStack->addMappableExpressionComponents( 23069 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr); 23070 23071 // Record the expression we've just processed. 23072 MVLI.ProcessedVarList.push_back(SimpleRefExpr); 23073 23074 // Create a mappable component for the list item. List items in this clause 23075 // only need a component. We use a null declaration to signal fields in 23076 // 'this'. 23077 assert((isa<DeclRefExpr>(SimpleRefExpr) || 23078 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) && 23079 "Unexpected device pointer expression!"); 23080 MVLI.VarBaseDeclarations.push_back( 23081 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr); 23082 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1); 23083 MVLI.VarComponents.back().push_back(MC); 23084 } 23085 23086 if (MVLI.ProcessedVarList.empty()) 23087 return nullptr; 23088 23089 return OMPIsDevicePtrClause::Create( 23090 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations, 23091 MVLI.VarComponents); 23092 } 23093 23094 OMPClause * 23095 SemaOpenMP::ActOnOpenMPHasDeviceAddrClause(ArrayRef<Expr *> VarList, 23096 const OMPVarListLocTy &Locs) { 23097 MappableVarListInfo MVLI(VarList); 23098 for (Expr *RefExpr : VarList) { 23099 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause."); 23100 SourceLocation ELoc; 23101 SourceRange ERange; 23102 Expr *SimpleRefExpr = RefExpr; 23103 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange, 23104 /*AllowArraySection=*/true); 23105 if (Res.second) { 23106 // It will be analyzed later. 23107 MVLI.ProcessedVarList.push_back(RefExpr); 23108 } 23109 ValueDecl *D = Res.first; 23110 if (!D) 23111 continue; 23112 23113 // Check if the declaration in the clause does not show up in any data 23114 // sharing attribute. 23115 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false); 23116 if (isOpenMPPrivate(DVar.CKind)) { 23117 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa) 23118 << getOpenMPClauseName(DVar.CKind) 23119 << getOpenMPClauseName(OMPC_has_device_addr) 23120 << getOpenMPDirectiveName(DSAStack->getCurrentDirective()); 23121 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 23122 continue; 23123 } 23124 23125 const Expr *ConflictExpr; 23126 if (DSAStack->checkMappableExprComponentListsForDecl( 23127 D, /*CurrentRegionOnly=*/true, 23128 [&ConflictExpr]( 23129 OMPClauseMappableExprCommon::MappableExprComponentListRef R, 23130 OpenMPClauseKind) -> bool { 23131 ConflictExpr = R.front().getAssociatedExpression(); 23132 return true; 23133 })) { 23134 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange(); 23135 Diag(ConflictExpr->getExprLoc(), diag::note_used_here) 23136 << ConflictExpr->getSourceRange(); 23137 continue; 23138 } 23139 23140 // Store the components in the stack so that they can be used to check 23141 // against other clauses later on. 23142 Expr *Component = SimpleRefExpr; 23143 auto *VD = dyn_cast<VarDecl>(D); 23144 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) || 23145 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts()))) 23146 Component = 23147 SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get(); 23148 OMPClauseMappableExprCommon::MappableComponent MC( 23149 Component, D, /*IsNonContiguous=*/false); 23150 DSAStack->addMappableExpressionComponents( 23151 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr); 23152 23153 // Record the expression we've just processed. 23154 if (!VD && !SemaRef.CurContext->isDependentContext()) { 23155 DeclRefExpr *Ref = 23156 buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true); 23157 assert(Ref && "has_device_addr capture failed"); 23158 MVLI.ProcessedVarList.push_back(Ref); 23159 } else 23160 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens()); 23161 23162 // Create a mappable component for the list item. List items in this clause 23163 // only need a component. We use a null declaration to signal fields in 23164 // 'this'. 23165 assert((isa<DeclRefExpr>(SimpleRefExpr) || 23166 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) && 23167 "Unexpected device pointer expression!"); 23168 MVLI.VarBaseDeclarations.push_back( 23169 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr); 23170 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1); 23171 MVLI.VarComponents.back().push_back(MC); 23172 } 23173 23174 if (MVLI.ProcessedVarList.empty()) 23175 return nullptr; 23176 23177 return OMPHasDeviceAddrClause::Create( 23178 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations, 23179 MVLI.VarComponents); 23180 } 23181 23182 OMPClause *SemaOpenMP::ActOnOpenMPAllocateClause( 23183 Expr *Allocator, Expr *Alignment, 23184 OpenMPAllocateClauseModifier FirstAllocateModifier, 23185 SourceLocation FirstAllocateModifierLoc, 23186 OpenMPAllocateClauseModifier SecondAllocateModifier, 23187 SourceLocation SecondAllocateModifierLoc, ArrayRef<Expr *> VarList, 23188 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, 23189 SourceLocation EndLoc) { 23190 if (Allocator) { 23191 // Allocator expression is dependent - skip it for now and build the 23192 // allocator when instantiated. 23193 bool AllocDependent = 23194 (Allocator->isTypeDependent() || Allocator->isValueDependent() || 23195 Allocator->isInstantiationDependent() || 23196 Allocator->containsUnexpandedParameterPack()); 23197 if (!AllocDependent) { 23198 // OpenMP [2.11.4 allocate Clause, Description] 23199 // allocator is an expression of omp_allocator_handle_t type. 23200 if (!findOMPAllocatorHandleT(SemaRef, Allocator->getExprLoc(), DSAStack)) 23201 return nullptr; 23202 23203 ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(Allocator); 23204 if (AllocatorRes.isInvalid()) 23205 return nullptr; 23206 AllocatorRes = SemaRef.PerformImplicitConversion( 23207 AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(), 23208 AssignmentAction::Initializing, 23209 /*AllowExplicit=*/true); 23210 if (AllocatorRes.isInvalid()) 23211 return nullptr; 23212 Allocator = AllocatorRes.isUsable() ? AllocatorRes.get() : nullptr; 23213 } 23214 } else { 23215 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions. 23216 // allocate clauses that appear on a target construct or on constructs in a 23217 // target region must specify an allocator expression unless a requires 23218 // directive with the dynamic_allocators clause is present in the same 23219 // compilation unit. 23220 if (getLangOpts().OpenMPIsTargetDevice && 23221 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>()) 23222 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression); 23223 } 23224 if (Alignment) { 23225 bool AlignmentDependent = Alignment->isTypeDependent() || 23226 Alignment->isValueDependent() || 23227 Alignment->isInstantiationDependent() || 23228 Alignment->containsUnexpandedParameterPack(); 23229 if (!AlignmentDependent) { 23230 ExprResult AlignResult = 23231 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_allocate); 23232 Alignment = AlignResult.isUsable() ? AlignResult.get() : nullptr; 23233 } 23234 } 23235 // Analyze and build list of variables. 23236 SmallVector<Expr *, 8> Vars; 23237 for (Expr *RefExpr : VarList) { 23238 assert(RefExpr && "NULL expr in OpenMP private clause."); 23239 SourceLocation ELoc; 23240 SourceRange ERange; 23241 Expr *SimpleRefExpr = RefExpr; 23242 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); 23243 if (Res.second) { 23244 // It will be analyzed later. 23245 Vars.push_back(RefExpr); 23246 } 23247 ValueDecl *D = Res.first; 23248 if (!D) 23249 continue; 23250 23251 auto *VD = dyn_cast<VarDecl>(D); 23252 DeclRefExpr *Ref = nullptr; 23253 if (!VD && !SemaRef.CurContext->isDependentContext()) 23254 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false); 23255 Vars.push_back((VD || SemaRef.CurContext->isDependentContext()) 23256 ? RefExpr->IgnoreParens() 23257 : Ref); 23258 } 23259 23260 if (Vars.empty()) 23261 return nullptr; 23262 23263 if (Allocator) 23264 DSAStack->addInnerAllocatorExpr(Allocator); 23265 23266 return OMPAllocateClause::Create( 23267 getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc, 23268 FirstAllocateModifier, FirstAllocateModifierLoc, SecondAllocateModifier, 23269 SecondAllocateModifierLoc, EndLoc, Vars); 23270 } 23271 23272 OMPClause *SemaOpenMP::ActOnOpenMPNontemporalClause(ArrayRef<Expr *> VarList, 23273 SourceLocation StartLoc, 23274 SourceLocation LParenLoc, 23275 SourceLocation EndLoc) { 23276 SmallVector<Expr *, 8> Vars; 23277 for (Expr *RefExpr : VarList) { 23278 assert(RefExpr && "NULL expr in OpenMP nontemporal clause."); 23279 SourceLocation ELoc; 23280 SourceRange ERange; 23281 Expr *SimpleRefExpr = RefExpr; 23282 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); 23283 if (Res.second) 23284 // It will be analyzed later. 23285 Vars.push_back(RefExpr); 23286 ValueDecl *D = Res.first; 23287 if (!D) 23288 continue; 23289 23290 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions. 23291 // A list-item cannot appear in more than one nontemporal clause. 23292 if (const Expr *PrevRef = 23293 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) { 23294 Diag(ELoc, diag::err_omp_used_in_clause_twice) 23295 << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange; 23296 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa) 23297 << getOpenMPClauseName(OMPC_nontemporal); 23298 continue; 23299 } 23300 23301 Vars.push_back(RefExpr); 23302 } 23303 23304 if (Vars.empty()) 23305 return nullptr; 23306 23307 return OMPNontemporalClause::Create(getASTContext(), StartLoc, LParenLoc, 23308 EndLoc, Vars); 23309 } 23310 23311 StmtResult SemaOpenMP::ActOnOpenMPScopeDirective(ArrayRef<OMPClause *> Clauses, 23312 Stmt *AStmt, 23313 SourceLocation StartLoc, 23314 SourceLocation EndLoc) { 23315 if (!AStmt) 23316 return StmtError(); 23317 23318 SemaRef.setFunctionHasBranchProtectedScope(); 23319 23320 return OMPScopeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses, 23321 AStmt); 23322 } 23323 23324 OMPClause *SemaOpenMP::ActOnOpenMPInclusiveClause(ArrayRef<Expr *> VarList, 23325 SourceLocation StartLoc, 23326 SourceLocation LParenLoc, 23327 SourceLocation EndLoc) { 23328 SmallVector<Expr *, 8> Vars; 23329 for (Expr *RefExpr : VarList) { 23330 assert(RefExpr && "NULL expr in OpenMP nontemporal clause."); 23331 SourceLocation ELoc; 23332 SourceRange ERange; 23333 Expr *SimpleRefExpr = RefExpr; 23334 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange, 23335 /*AllowArraySection=*/true); 23336 if (Res.second) 23337 // It will be analyzed later. 23338 Vars.push_back(RefExpr); 23339 ValueDecl *D = Res.first; 23340 if (!D) 23341 continue; 23342 23343 const DSAStackTy::DSAVarData DVar = 23344 DSAStack->getTopDSA(D, /*FromParent=*/true); 23345 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions. 23346 // A list item that appears in the inclusive or exclusive clause must appear 23347 // in a reduction clause with the inscan modifier on the enclosing 23348 // worksharing-loop, worksharing-loop SIMD, or simd construct. 23349 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan) 23350 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction) 23351 << RefExpr->getSourceRange(); 23352 23353 if (DSAStack->getParentDirective() != OMPD_unknown) 23354 DSAStack->markDeclAsUsedInScanDirective(D); 23355 Vars.push_back(RefExpr); 23356 } 23357 23358 if (Vars.empty()) 23359 return nullptr; 23360 23361 return OMPInclusiveClause::Create(getASTContext(), StartLoc, LParenLoc, 23362 EndLoc, Vars); 23363 } 23364 23365 OMPClause *SemaOpenMP::ActOnOpenMPExclusiveClause(ArrayRef<Expr *> VarList, 23366 SourceLocation StartLoc, 23367 SourceLocation LParenLoc, 23368 SourceLocation EndLoc) { 23369 SmallVector<Expr *, 8> Vars; 23370 for (Expr *RefExpr : VarList) { 23371 assert(RefExpr && "NULL expr in OpenMP nontemporal clause."); 23372 SourceLocation ELoc; 23373 SourceRange ERange; 23374 Expr *SimpleRefExpr = RefExpr; 23375 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange, 23376 /*AllowArraySection=*/true); 23377 if (Res.second) 23378 // It will be analyzed later. 23379 Vars.push_back(RefExpr); 23380 ValueDecl *D = Res.first; 23381 if (!D) 23382 continue; 23383 23384 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective(); 23385 DSAStackTy::DSAVarData DVar; 23386 if (ParentDirective != OMPD_unknown) 23387 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true); 23388 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions. 23389 // A list item that appears in the inclusive or exclusive clause must appear 23390 // in a reduction clause with the inscan modifier on the enclosing 23391 // worksharing-loop, worksharing-loop SIMD, or simd construct. 23392 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction || 23393 DVar.Modifier != OMPC_REDUCTION_inscan) { 23394 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction) 23395 << RefExpr->getSourceRange(); 23396 } else { 23397 DSAStack->markDeclAsUsedInScanDirective(D); 23398 } 23399 Vars.push_back(RefExpr); 23400 } 23401 23402 if (Vars.empty()) 23403 return nullptr; 23404 23405 return OMPExclusiveClause::Create(getASTContext(), StartLoc, LParenLoc, 23406 EndLoc, Vars); 23407 } 23408 23409 /// Tries to find omp_alloctrait_t type. 23410 static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) { 23411 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT(); 23412 if (!OMPAlloctraitT.isNull()) 23413 return true; 23414 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t"); 23415 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope()); 23416 if (!PT.getAsOpaquePtr() || PT.get().isNull()) { 23417 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t"; 23418 return false; 23419 } 23420 Stack->setOMPAlloctraitT(PT.get()); 23421 return true; 23422 } 23423 23424 OMPClause *SemaOpenMP::ActOnOpenMPUsesAllocatorClause( 23425 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, 23426 ArrayRef<UsesAllocatorsData> Data) { 23427 ASTContext &Context = getASTContext(); 23428 // OpenMP [2.12.5, target Construct] 23429 // allocator is an identifier of omp_allocator_handle_t type. 23430 if (!findOMPAllocatorHandleT(SemaRef, StartLoc, DSAStack)) 23431 return nullptr; 23432 // OpenMP [2.12.5, target Construct] 23433 // allocator-traits-array is an identifier of const omp_alloctrait_t * type. 23434 if (llvm::any_of( 23435 Data, 23436 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) && 23437 !findOMPAlloctraitT(SemaRef, StartLoc, DSAStack)) 23438 return nullptr; 23439 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators; 23440 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) { 23441 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I); 23442 StringRef Allocator = 23443 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind); 23444 DeclarationName AllocatorName = &Context.Idents.get(Allocator); 23445 PredefinedAllocators.insert(SemaRef.LookupSingleName( 23446 SemaRef.TUScope, AllocatorName, StartLoc, Sema::LookupAnyName)); 23447 } 23448 23449 SmallVector<OMPUsesAllocatorsClause::Data, 4> NewData; 23450 for (const UsesAllocatorsData &D : Data) { 23451 Expr *AllocatorExpr = nullptr; 23452 // Check allocator expression. 23453 if (D.Allocator->isTypeDependent()) { 23454 AllocatorExpr = D.Allocator; 23455 } else { 23456 // Traits were specified - need to assign new allocator to the specified 23457 // allocator, so it must be an lvalue. 23458 AllocatorExpr = D.Allocator->IgnoreParenImpCasts(); 23459 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr); 23460 bool IsPredefinedAllocator = false; 23461 if (DRE) { 23462 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy = 23463 getAllocatorKind(SemaRef, DSAStack, AllocatorExpr); 23464 IsPredefinedAllocator = 23465 AllocatorTy != 23466 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc; 23467 } 23468 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT(); 23469 QualType AllocatorExprType = AllocatorExpr->getType(); 23470 bool IsTypeCompatible = IsPredefinedAllocator; 23471 IsTypeCompatible = IsTypeCompatible || 23472 Context.hasSameUnqualifiedType(AllocatorExprType, 23473 OMPAllocatorHandleT); 23474 IsTypeCompatible = 23475 IsTypeCompatible || 23476 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT); 23477 bool IsNonConstantLValue = 23478 !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue(); 23479 if (!DRE || !IsTypeCompatible || 23480 (!IsPredefinedAllocator && !IsNonConstantLValue)) { 23481 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected) 23482 << "omp_allocator_handle_t" << (DRE ? 1 : 0) 23483 << AllocatorExpr->getType() << D.Allocator->getSourceRange(); 23484 continue; 23485 } 23486 // OpenMP [2.12.5, target Construct] 23487 // Predefined allocators appearing in a uses_allocators clause cannot have 23488 // traits specified. 23489 if (IsPredefinedAllocator && D.AllocatorTraits) { 23490 Diag(D.AllocatorTraits->getExprLoc(), 23491 diag::err_omp_predefined_allocator_with_traits) 23492 << D.AllocatorTraits->getSourceRange(); 23493 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator) 23494 << cast<NamedDecl>(DRE->getDecl())->getName() 23495 << D.Allocator->getSourceRange(); 23496 continue; 23497 } 23498 // OpenMP [2.12.5, target Construct] 23499 // Non-predefined allocators appearing in a uses_allocators clause must 23500 // have traits specified. 23501 if (!IsPredefinedAllocator && !D.AllocatorTraits) { 23502 Diag(D.Allocator->getExprLoc(), 23503 diag::err_omp_nonpredefined_allocator_without_traits); 23504 continue; 23505 } 23506 // No allocator traits - just convert it to rvalue. 23507 if (!D.AllocatorTraits) 23508 AllocatorExpr = SemaRef.DefaultLvalueConversion(AllocatorExpr).get(); 23509 DSAStack->addUsesAllocatorsDecl( 23510 DRE->getDecl(), 23511 IsPredefinedAllocator 23512 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator 23513 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator); 23514 } 23515 Expr *AllocatorTraitsExpr = nullptr; 23516 if (D.AllocatorTraits) { 23517 if (D.AllocatorTraits->isTypeDependent()) { 23518 AllocatorTraitsExpr = D.AllocatorTraits; 23519 } else { 23520 // OpenMP [2.12.5, target Construct] 23521 // Arrays that contain allocator traits that appear in a uses_allocators 23522 // clause must be constant arrays, have constant values and be defined 23523 // in the same scope as the construct in which the clause appears. 23524 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts(); 23525 // Check that traits expr is a constant array. 23526 QualType TraitTy; 23527 if (const ArrayType *Ty = 23528 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe()) 23529 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty)) 23530 TraitTy = ConstArrayTy->getElementType(); 23531 if (TraitTy.isNull() || 23532 !(Context.hasSameUnqualifiedType(TraitTy, 23533 DSAStack->getOMPAlloctraitT()) || 23534 Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(), 23535 /*CompareUnqualified=*/true))) { 23536 Diag(D.AllocatorTraits->getExprLoc(), 23537 diag::err_omp_expected_array_alloctraits) 23538 << AllocatorTraitsExpr->getType(); 23539 continue; 23540 } 23541 // Do not map by default allocator traits if it is a standalone 23542 // variable. 23543 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr)) 23544 DSAStack->addUsesAllocatorsDecl( 23545 DRE->getDecl(), 23546 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait); 23547 } 23548 } 23549 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back(); 23550 NewD.Allocator = AllocatorExpr; 23551 NewD.AllocatorTraits = AllocatorTraitsExpr; 23552 NewD.LParenLoc = D.LParenLoc; 23553 NewD.RParenLoc = D.RParenLoc; 23554 } 23555 return OMPUsesAllocatorsClause::Create(getASTContext(), StartLoc, LParenLoc, 23556 EndLoc, NewData); 23557 } 23558 23559 OMPClause *SemaOpenMP::ActOnOpenMPAffinityClause( 23560 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, 23561 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) { 23562 SmallVector<Expr *, 8> Vars; 23563 for (Expr *RefExpr : Locators) { 23564 assert(RefExpr && "NULL expr in OpenMP shared clause."); 23565 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) { 23566 // It will be analyzed later. 23567 Vars.push_back(RefExpr); 23568 continue; 23569 } 23570 23571 SourceLocation ELoc = RefExpr->getExprLoc(); 23572 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts(); 23573 23574 if (!SimpleExpr->isLValue()) { 23575 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item) 23576 << 1 << 0 << RefExpr->getSourceRange(); 23577 continue; 23578 } 23579 23580 ExprResult Res; 23581 { 23582 Sema::TentativeAnalysisScope Trap(SemaRef); 23583 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr); 23584 } 23585 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) && 23586 !isa<OMPArrayShapingExpr>(SimpleExpr)) { 23587 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item) 23588 << 1 << 0 << RefExpr->getSourceRange(); 23589 continue; 23590 } 23591 Vars.push_back(SimpleExpr); 23592 } 23593 23594 return OMPAffinityClause::Create(getASTContext(), StartLoc, LParenLoc, 23595 ColonLoc, EndLoc, Modifier, Vars); 23596 } 23597 23598 OMPClause *SemaOpenMP::ActOnOpenMPBindClause(OpenMPBindClauseKind Kind, 23599 SourceLocation KindLoc, 23600 SourceLocation StartLoc, 23601 SourceLocation LParenLoc, 23602 SourceLocation EndLoc) { 23603 if (Kind == OMPC_BIND_unknown) { 23604 Diag(KindLoc, diag::err_omp_unexpected_clause_value) 23605 << getListOfPossibleValues(OMPC_bind, /*First=*/0, 23606 /*Last=*/unsigned(OMPC_BIND_unknown)) 23607 << getOpenMPClauseName(OMPC_bind); 23608 return nullptr; 23609 } 23610 23611 return OMPBindClause::Create(getASTContext(), Kind, KindLoc, StartLoc, 23612 LParenLoc, EndLoc); 23613 } 23614 23615 OMPClause *SemaOpenMP::ActOnOpenMPXDynCGroupMemClause(Expr *Size, 23616 SourceLocation StartLoc, 23617 SourceLocation LParenLoc, 23618 SourceLocation EndLoc) { 23619 Expr *ValExpr = Size; 23620 Stmt *HelperValStmt = nullptr; 23621 23622 // OpenMP [2.5, Restrictions] 23623 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer 23624 // value. 23625 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_ompx_dyn_cgroup_mem, 23626 /*StrictlyPositive=*/false)) 23627 return nullptr; 23628 23629 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); 23630 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause( 23631 DKind, OMPC_ompx_dyn_cgroup_mem, getLangOpts().OpenMP); 23632 if (CaptureRegion != OMPD_unknown && 23633 !SemaRef.CurContext->isDependentContext()) { 23634 ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); 23635 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 23636 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); 23637 HelperValStmt = buildPreInits(getASTContext(), Captures); 23638 } 23639 23640 return new (getASTContext()) OMPXDynCGroupMemClause( 23641 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc); 23642 } 23643 23644 OMPClause *SemaOpenMP::ActOnOpenMPDoacrossClause( 23645 OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, 23646 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc, 23647 SourceLocation LParenLoc, SourceLocation EndLoc) { 23648 23649 if (DSAStack->getCurrentDirective() == OMPD_ordered && 23650 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink && 23651 DepType != OMPC_DOACROSS_sink_omp_cur_iteration && 23652 DepType != OMPC_DOACROSS_source_omp_cur_iteration) { 23653 Diag(DepLoc, diag::err_omp_unexpected_clause_value) 23654 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_doacross); 23655 return nullptr; 23656 } 23657 23658 SmallVector<Expr *, 8> Vars; 23659 DSAStackTy::OperatorOffsetTy OpsOffs; 23660 llvm::APSInt TotalDepCount(/*BitWidth=*/32); 23661 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon( 23662 SemaRef, 23663 DepType == OMPC_DOACROSS_source || 23664 DepType == OMPC_DOACROSS_source_omp_cur_iteration || 23665 DepType == OMPC_DOACROSS_sink_omp_cur_iteration, 23666 VarList, DSAStack, EndLoc); 23667 Vars = VarOffset.Vars; 23668 OpsOffs = VarOffset.OpsOffs; 23669 TotalDepCount = VarOffset.TotalDepCount; 23670 auto *C = OMPDoacrossClause::Create(getASTContext(), StartLoc, LParenLoc, 23671 EndLoc, DepType, DepLoc, ColonLoc, Vars, 23672 TotalDepCount.getZExtValue()); 23673 if (DSAStack->isParentOrderedRegion()) 23674 DSAStack->addDoacrossDependClause(C, OpsOffs); 23675 return C; 23676 } 23677 23678 OMPClause *SemaOpenMP::ActOnOpenMPXAttributeClause(ArrayRef<const Attr *> Attrs, 23679 SourceLocation StartLoc, 23680 SourceLocation LParenLoc, 23681 SourceLocation EndLoc) { 23682 return new (getASTContext()) 23683 OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc); 23684 } 23685 23686 OMPClause *SemaOpenMP::ActOnOpenMPXBareClause(SourceLocation StartLoc, 23687 SourceLocation EndLoc) { 23688 return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc); 23689 } 23690 23691 OMPClause *SemaOpenMP::ActOnOpenMPHoldsClause(Expr *E, SourceLocation StartLoc, 23692 SourceLocation LParenLoc, 23693 SourceLocation EndLoc) { 23694 return new (getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc); 23695 } 23696 23697 OMPClause *SemaOpenMP::ActOnOpenMPDirectivePresenceClause( 23698 OpenMPClauseKind CK, llvm::ArrayRef<OpenMPDirectiveKind> DKVec, 23699 SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc) { 23700 switch (CK) { 23701 case OMPC_absent: 23702 return OMPAbsentClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc); 23703 case OMPC_contains: 23704 return OMPContainsClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc); 23705 default: 23706 llvm_unreachable("Unexpected OpenMP clause"); 23707 } 23708 } 23709 23710 OMPClause *SemaOpenMP::ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK, 23711 SourceLocation Loc, 23712 SourceLocation RLoc) { 23713 switch (CK) { 23714 case OMPC_no_openmp: 23715 return new (getASTContext()) OMPNoOpenMPClause(Loc, RLoc); 23716 case OMPC_no_openmp_routines: 23717 return new (getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc); 23718 case OMPC_no_parallelism: 23719 return new (getASTContext()) OMPNoParallelismClause(Loc, RLoc); 23720 default: 23721 llvm_unreachable("Unexpected OpenMP clause"); 23722 } 23723 } 23724 23725 ExprResult SemaOpenMP::ActOnOMPArraySectionExpr( 23726 Expr *Base, SourceLocation LBLoc, Expr *LowerBound, 23727 SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length, 23728 Expr *Stride, SourceLocation RBLoc) { 23729 ASTContext &Context = getASTContext(); 23730 if (Base->hasPlaceholderType() && 23731 !Base->hasPlaceholderType(BuiltinType::ArraySection)) { 23732 ExprResult Result = SemaRef.CheckPlaceholderExpr(Base); 23733 if (Result.isInvalid()) 23734 return ExprError(); 23735 Base = Result.get(); 23736 } 23737 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) { 23738 ExprResult Result = SemaRef.CheckPlaceholderExpr(LowerBound); 23739 if (Result.isInvalid()) 23740 return ExprError(); 23741 Result = SemaRef.DefaultLvalueConversion(Result.get()); 23742 if (Result.isInvalid()) 23743 return ExprError(); 23744 LowerBound = Result.get(); 23745 } 23746 if (Length && Length->getType()->isNonOverloadPlaceholderType()) { 23747 ExprResult Result = SemaRef.CheckPlaceholderExpr(Length); 23748 if (Result.isInvalid()) 23749 return ExprError(); 23750 Result = SemaRef.DefaultLvalueConversion(Result.get()); 23751 if (Result.isInvalid()) 23752 return ExprError(); 23753 Length = Result.get(); 23754 } 23755 if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) { 23756 ExprResult Result = SemaRef.CheckPlaceholderExpr(Stride); 23757 if (Result.isInvalid()) 23758 return ExprError(); 23759 Result = SemaRef.DefaultLvalueConversion(Result.get()); 23760 if (Result.isInvalid()) 23761 return ExprError(); 23762 Stride = Result.get(); 23763 } 23764 23765 // Build an unanalyzed expression if either operand is type-dependent. 23766 if (Base->isTypeDependent() || 23767 (LowerBound && 23768 (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) || 23769 (Length && (Length->isTypeDependent() || Length->isValueDependent())) || 23770 (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) { 23771 return new (Context) ArraySectionExpr( 23772 Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue, 23773 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc); 23774 } 23775 23776 // Perform default conversions. 23777 QualType OriginalTy = ArraySectionExpr::getBaseOriginalType(Base); 23778 QualType ResultTy; 23779 if (OriginalTy->isAnyPointerType()) { 23780 ResultTy = OriginalTy->getPointeeType(); 23781 } else if (OriginalTy->isArrayType()) { 23782 ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType(); 23783 } else { 23784 return ExprError( 23785 Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value) 23786 << Base->getSourceRange()); 23787 } 23788 // C99 6.5.2.1p1 23789 if (LowerBound) { 23790 auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(), 23791 LowerBound); 23792 if (Res.isInvalid()) 23793 return ExprError(Diag(LowerBound->getExprLoc(), 23794 diag::err_omp_typecheck_section_not_integer) 23795 << 0 << LowerBound->getSourceRange()); 23796 LowerBound = Res.get(); 23797 23798 if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) || 23799 LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U)) 23800 Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char) 23801 << 0 << LowerBound->getSourceRange(); 23802 } 23803 if (Length) { 23804 auto Res = 23805 PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length); 23806 if (Res.isInvalid()) 23807 return ExprError(Diag(Length->getExprLoc(), 23808 diag::err_omp_typecheck_section_not_integer) 23809 << 1 << Length->getSourceRange()); 23810 Length = Res.get(); 23811 23812 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) || 23813 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U)) 23814 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char) 23815 << 1 << Length->getSourceRange(); 23816 } 23817 if (Stride) { 23818 ExprResult Res = 23819 PerformOpenMPImplicitIntegerConversion(Stride->getExprLoc(), Stride); 23820 if (Res.isInvalid()) 23821 return ExprError(Diag(Stride->getExprLoc(), 23822 diag::err_omp_typecheck_section_not_integer) 23823 << 1 << Stride->getSourceRange()); 23824 Stride = Res.get(); 23825 23826 if (Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_S) || 23827 Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_U)) 23828 Diag(Stride->getExprLoc(), diag::warn_omp_section_is_char) 23829 << 1 << Stride->getSourceRange(); 23830 } 23831 23832 // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly, 23833 // C++ [expr.sub]p1: The type "T" shall be a completely-defined object 23834 // type. Note that functions are not objects, and that (in C99 parlance) 23835 // incomplete types are not object types. 23836 if (ResultTy->isFunctionType()) { 23837 Diag(Base->getExprLoc(), diag::err_omp_section_function_type) 23838 << ResultTy << Base->getSourceRange(); 23839 return ExprError(); 23840 } 23841 23842 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy, 23843 diag::err_omp_section_incomplete_type, Base)) 23844 return ExprError(); 23845 23846 if (LowerBound && !OriginalTy->isAnyPointerType()) { 23847 Expr::EvalResult Result; 23848 if (LowerBound->EvaluateAsInt(Result, Context)) { 23849 // OpenMP 5.0, [2.1.5 Array Sections] 23850 // The array section must be a subset of the original array. 23851 llvm::APSInt LowerBoundValue = Result.Val.getInt(); 23852 if (LowerBoundValue.isNegative()) { 23853 Diag(LowerBound->getExprLoc(), 23854 diag::err_omp_section_not_subset_of_array) 23855 << LowerBound->getSourceRange(); 23856 return ExprError(); 23857 } 23858 } 23859 } 23860 23861 if (Length) { 23862 Expr::EvalResult Result; 23863 if (Length->EvaluateAsInt(Result, Context)) { 23864 // OpenMP 5.0, [2.1.5 Array Sections] 23865 // The length must evaluate to non-negative integers. 23866 llvm::APSInt LengthValue = Result.Val.getInt(); 23867 if (LengthValue.isNegative()) { 23868 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative) 23869 << toString(LengthValue, /*Radix=*/10, /*Signed=*/true) 23870 << Length->getSourceRange(); 23871 return ExprError(); 23872 } 23873 } 23874 } else if (ColonLocFirst.isValid() && 23875 (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() && 23876 !OriginalTy->isVariableArrayType()))) { 23877 // OpenMP 5.0, [2.1.5 Array Sections] 23878 // When the size of the array dimension is not known, the length must be 23879 // specified explicitly. 23880 Diag(ColonLocFirst, diag::err_omp_section_length_undefined) 23881 << (!OriginalTy.isNull() && OriginalTy->isArrayType()); 23882 return ExprError(); 23883 } 23884 23885 if (Stride) { 23886 Expr::EvalResult Result; 23887 if (Stride->EvaluateAsInt(Result, Context)) { 23888 // OpenMP 5.0, [2.1.5 Array Sections] 23889 // The stride must evaluate to a positive integer. 23890 llvm::APSInt StrideValue = Result.Val.getInt(); 23891 if (!StrideValue.isStrictlyPositive()) { 23892 Diag(Stride->getExprLoc(), diag::err_omp_section_stride_non_positive) 23893 << toString(StrideValue, /*Radix=*/10, /*Signed=*/true) 23894 << Stride->getSourceRange(); 23895 return ExprError(); 23896 } 23897 } 23898 } 23899 23900 if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) { 23901 ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(Base); 23902 if (Result.isInvalid()) 23903 return ExprError(); 23904 Base = Result.get(); 23905 } 23906 return new (Context) ArraySectionExpr( 23907 Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue, 23908 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc); 23909 } 23910 23911 ExprResult SemaOpenMP::ActOnOMPArrayShapingExpr( 23912 Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc, 23913 ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) { 23914 ASTContext &Context = getASTContext(); 23915 if (Base->hasPlaceholderType()) { 23916 ExprResult Result = SemaRef.CheckPlaceholderExpr(Base); 23917 if (Result.isInvalid()) 23918 return ExprError(); 23919 Result = SemaRef.DefaultLvalueConversion(Result.get()); 23920 if (Result.isInvalid()) 23921 return ExprError(); 23922 Base = Result.get(); 23923 } 23924 QualType BaseTy = Base->getType(); 23925 // Delay analysis of the types/expressions if instantiation/specialization is 23926 // required. 23927 if (!BaseTy->isPointerType() && Base->isTypeDependent()) 23928 return OMPArrayShapingExpr::Create(Context, Context.DependentTy, Base, 23929 LParenLoc, RParenLoc, Dims, Brackets); 23930 if (!BaseTy->isPointerType() || 23931 (!Base->isTypeDependent() && 23932 BaseTy->getPointeeType()->isIncompleteType())) 23933 return ExprError(Diag(Base->getExprLoc(), 23934 diag::err_omp_non_pointer_type_array_shaping_base) 23935 << Base->getSourceRange()); 23936 23937 SmallVector<Expr *, 4> NewDims; 23938 bool ErrorFound = false; 23939 for (Expr *Dim : Dims) { 23940 if (Dim->hasPlaceholderType()) { 23941 ExprResult Result = SemaRef.CheckPlaceholderExpr(Dim); 23942 if (Result.isInvalid()) { 23943 ErrorFound = true; 23944 continue; 23945 } 23946 Result = SemaRef.DefaultLvalueConversion(Result.get()); 23947 if (Result.isInvalid()) { 23948 ErrorFound = true; 23949 continue; 23950 } 23951 Dim = Result.get(); 23952 } 23953 if (!Dim->isTypeDependent()) { 23954 ExprResult Result = 23955 PerformOpenMPImplicitIntegerConversion(Dim->getExprLoc(), Dim); 23956 if (Result.isInvalid()) { 23957 ErrorFound = true; 23958 Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer) 23959 << Dim->getSourceRange(); 23960 continue; 23961 } 23962 Dim = Result.get(); 23963 Expr::EvalResult EvResult; 23964 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) { 23965 // OpenMP 5.0, [2.1.4 Array Shaping] 23966 // Each si is an integral type expression that must evaluate to a 23967 // positive integer. 23968 llvm::APSInt Value = EvResult.Val.getInt(); 23969 if (!Value.isStrictlyPositive()) { 23970 Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive) 23971 << toString(Value, /*Radix=*/10, /*Signed=*/true) 23972 << Dim->getSourceRange(); 23973 ErrorFound = true; 23974 continue; 23975 } 23976 } 23977 } 23978 NewDims.push_back(Dim); 23979 } 23980 if (ErrorFound) 23981 return ExprError(); 23982 return OMPArrayShapingExpr::Create(Context, Context.OMPArrayShapingTy, Base, 23983 LParenLoc, RParenLoc, NewDims, Brackets); 23984 } 23985 23986 ExprResult SemaOpenMP::ActOnOMPIteratorExpr(Scope *S, 23987 SourceLocation IteratorKwLoc, 23988 SourceLocation LLoc, 23989 SourceLocation RLoc, 23990 ArrayRef<OMPIteratorData> Data) { 23991 ASTContext &Context = getASTContext(); 23992 SmallVector<OMPIteratorExpr::IteratorDefinition, 4> ID; 23993 bool IsCorrect = true; 23994 for (const OMPIteratorData &D : Data) { 23995 TypeSourceInfo *TInfo = nullptr; 23996 SourceLocation StartLoc; 23997 QualType DeclTy; 23998 if (!D.Type.getAsOpaquePtr()) { 23999 // OpenMP 5.0, 2.1.6 Iterators 24000 // In an iterator-specifier, if the iterator-type is not specified then 24001 // the type of that iterator is of int type. 24002 DeclTy = Context.IntTy; 24003 StartLoc = D.DeclIdentLoc; 24004 } else { 24005 DeclTy = Sema::GetTypeFromParser(D.Type, &TInfo); 24006 StartLoc = TInfo->getTypeLoc().getBeginLoc(); 24007 } 24008 24009 bool IsDeclTyDependent = DeclTy->isDependentType() || 24010 DeclTy->containsUnexpandedParameterPack() || 24011 DeclTy->isInstantiationDependentType(); 24012 if (!IsDeclTyDependent) { 24013 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) { 24014 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++ 24015 // The iterator-type must be an integral or pointer type. 24016 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer) 24017 << DeclTy; 24018 IsCorrect = false; 24019 continue; 24020 } 24021 if (DeclTy.isConstant(Context)) { 24022 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++ 24023 // The iterator-type must not be const qualified. 24024 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer) 24025 << DeclTy; 24026 IsCorrect = false; 24027 continue; 24028 } 24029 } 24030 24031 // Iterator declaration. 24032 assert(D.DeclIdent && "Identifier expected."); 24033 // Always try to create iterator declarator to avoid extra error messages 24034 // about unknown declarations use. 24035 auto *VD = 24036 VarDecl::Create(Context, SemaRef.CurContext, StartLoc, D.DeclIdentLoc, 24037 D.DeclIdent, DeclTy, TInfo, SC_None); 24038 VD->setImplicit(); 24039 if (S) { 24040 // Check for conflicting previous declaration. 24041 DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc); 24042 LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName, 24043 RedeclarationKind::ForVisibleRedeclaration); 24044 Previous.suppressDiagnostics(); 24045 SemaRef.LookupName(Previous, S); 24046 24047 SemaRef.FilterLookupForScope(Previous, SemaRef.CurContext, S, 24048 /*ConsiderLinkage=*/false, 24049 /*AllowInlineNamespace=*/false); 24050 if (!Previous.empty()) { 24051 NamedDecl *Old = Previous.getRepresentativeDecl(); 24052 Diag(D.DeclIdentLoc, diag::err_redefinition) << VD->getDeclName(); 24053 Diag(Old->getLocation(), diag::note_previous_definition); 24054 } else { 24055 SemaRef.PushOnScopeChains(VD, S); 24056 } 24057 } else { 24058 SemaRef.CurContext->addDecl(VD); 24059 } 24060 24061 /// Act on the iterator variable declaration. 24062 ActOnOpenMPIteratorVarDecl(VD); 24063 24064 Expr *Begin = D.Range.Begin; 24065 if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) { 24066 ExprResult BeginRes = SemaRef.PerformImplicitConversion( 24067 Begin, DeclTy, AssignmentAction::Converting); 24068 Begin = BeginRes.get(); 24069 } 24070 Expr *End = D.Range.End; 24071 if (!IsDeclTyDependent && End && !End->isTypeDependent()) { 24072 ExprResult EndRes = SemaRef.PerformImplicitConversion( 24073 End, DeclTy, AssignmentAction::Converting); 24074 End = EndRes.get(); 24075 } 24076 Expr *Step = D.Range.Step; 24077 if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) { 24078 if (!Step->getType()->isIntegralType(Context)) { 24079 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_not_integral) 24080 << Step << Step->getSourceRange(); 24081 IsCorrect = false; 24082 continue; 24083 } 24084 std::optional<llvm::APSInt> Result = 24085 Step->getIntegerConstantExpr(Context); 24086 // OpenMP 5.0, 2.1.6 Iterators, Restrictions 24087 // If the step expression of a range-specification equals zero, the 24088 // behavior is unspecified. 24089 if (Result && Result->isZero()) { 24090 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero) 24091 << Step << Step->getSourceRange(); 24092 IsCorrect = false; 24093 continue; 24094 } 24095 } 24096 if (!Begin || !End || !IsCorrect) { 24097 IsCorrect = false; 24098 continue; 24099 } 24100 OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back(); 24101 IDElem.IteratorDecl = VD; 24102 IDElem.AssignmentLoc = D.AssignLoc; 24103 IDElem.Range.Begin = Begin; 24104 IDElem.Range.End = End; 24105 IDElem.Range.Step = Step; 24106 IDElem.ColonLoc = D.ColonLoc; 24107 IDElem.SecondColonLoc = D.SecColonLoc; 24108 } 24109 if (!IsCorrect) { 24110 // Invalidate all created iterator declarations if error is found. 24111 for (const OMPIteratorExpr::IteratorDefinition &D : ID) { 24112 if (Decl *ID = D.IteratorDecl) 24113 ID->setInvalidDecl(); 24114 } 24115 return ExprError(); 24116 } 24117 SmallVector<OMPIteratorHelperData, 4> Helpers; 24118 if (!SemaRef.CurContext->isDependentContext()) { 24119 // Build number of ityeration for each iteration range. 24120 // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) : 24121 // ((Begini-Stepi-1-Endi) / -Stepi); 24122 for (OMPIteratorExpr::IteratorDefinition &D : ID) { 24123 // (Endi - Begini) 24124 ExprResult Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub, 24125 D.Range.End, D.Range.Begin); 24126 if (!Res.isUsable()) { 24127 IsCorrect = false; 24128 continue; 24129 } 24130 ExprResult St, St1; 24131 if (D.Range.Step) { 24132 St = D.Range.Step; 24133 // (Endi - Begini) + Stepi 24134 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.get(), 24135 St.get()); 24136 if (!Res.isUsable()) { 24137 IsCorrect = false; 24138 continue; 24139 } 24140 // (Endi - Begini) + Stepi - 1 24141 Res = SemaRef.CreateBuiltinBinOp( 24142 D.AssignmentLoc, BO_Sub, Res.get(), 24143 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get()); 24144 if (!Res.isUsable()) { 24145 IsCorrect = false; 24146 continue; 24147 } 24148 // ((Endi - Begini) + Stepi - 1) / Stepi 24149 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.get(), 24150 St.get()); 24151 if (!Res.isUsable()) { 24152 IsCorrect = false; 24153 continue; 24154 } 24155 St1 = SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus, 24156 D.Range.Step); 24157 // (Begini - Endi) 24158 ExprResult Res1 = SemaRef.CreateBuiltinBinOp( 24159 D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End); 24160 if (!Res1.isUsable()) { 24161 IsCorrect = false; 24162 continue; 24163 } 24164 // (Begini - Endi) - Stepi 24165 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.get(), 24166 St1.get()); 24167 if (!Res1.isUsable()) { 24168 IsCorrect = false; 24169 continue; 24170 } 24171 // (Begini - Endi) - Stepi - 1 24172 Res1 = SemaRef.CreateBuiltinBinOp( 24173 D.AssignmentLoc, BO_Sub, Res1.get(), 24174 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get()); 24175 if (!Res1.isUsable()) { 24176 IsCorrect = false; 24177 continue; 24178 } 24179 // ((Begini - Endi) - Stepi - 1) / (-Stepi) 24180 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.get(), 24181 St1.get()); 24182 if (!Res1.isUsable()) { 24183 IsCorrect = false; 24184 continue; 24185 } 24186 // Stepi > 0. 24187 ExprResult CmpRes = SemaRef.CreateBuiltinBinOp( 24188 D.AssignmentLoc, BO_GT, D.Range.Step, 24189 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get()); 24190 if (!CmpRes.isUsable()) { 24191 IsCorrect = false; 24192 continue; 24193 } 24194 Res = SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc, 24195 CmpRes.get(), Res.get(), Res1.get()); 24196 if (!Res.isUsable()) { 24197 IsCorrect = false; 24198 continue; 24199 } 24200 } 24201 Res = SemaRef.ActOnFinishFullExpr(Res.get(), /*DiscardedValue=*/false); 24202 if (!Res.isUsable()) { 24203 IsCorrect = false; 24204 continue; 24205 } 24206 24207 // Build counter update. 24208 // Build counter. 24209 auto *CounterVD = VarDecl::Create(Context, SemaRef.CurContext, 24210 D.IteratorDecl->getBeginLoc(), 24211 D.IteratorDecl->getBeginLoc(), nullptr, 24212 Res.get()->getType(), nullptr, SC_None); 24213 CounterVD->setImplicit(); 24214 ExprResult RefRes = 24215 SemaRef.BuildDeclRefExpr(CounterVD, CounterVD->getType(), VK_LValue, 24216 D.IteratorDecl->getBeginLoc()); 24217 // Build counter update. 24218 // I = Begini + counter * Stepi; 24219 ExprResult UpdateRes; 24220 if (D.Range.Step) { 24221 UpdateRes = SemaRef.CreateBuiltinBinOp( 24222 D.AssignmentLoc, BO_Mul, 24223 SemaRef.DefaultLvalueConversion(RefRes.get()).get(), St.get()); 24224 } else { 24225 UpdateRes = SemaRef.DefaultLvalueConversion(RefRes.get()); 24226 } 24227 if (!UpdateRes.isUsable()) { 24228 IsCorrect = false; 24229 continue; 24230 } 24231 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, 24232 D.Range.Begin, UpdateRes.get()); 24233 if (!UpdateRes.isUsable()) { 24234 IsCorrect = false; 24235 continue; 24236 } 24237 ExprResult VDRes = 24238 SemaRef.BuildDeclRefExpr(cast<VarDecl>(D.IteratorDecl), 24239 cast<VarDecl>(D.IteratorDecl)->getType(), 24240 VK_LValue, D.IteratorDecl->getBeginLoc()); 24241 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign, 24242 VDRes.get(), UpdateRes.get()); 24243 if (!UpdateRes.isUsable()) { 24244 IsCorrect = false; 24245 continue; 24246 } 24247 UpdateRes = 24248 SemaRef.ActOnFinishFullExpr(UpdateRes.get(), /*DiscardedValue=*/true); 24249 if (!UpdateRes.isUsable()) { 24250 IsCorrect = false; 24251 continue; 24252 } 24253 ExprResult CounterUpdateRes = SemaRef.CreateBuiltinUnaryOp( 24254 D.AssignmentLoc, UO_PreInc, RefRes.get()); 24255 if (!CounterUpdateRes.isUsable()) { 24256 IsCorrect = false; 24257 continue; 24258 } 24259 CounterUpdateRes = SemaRef.ActOnFinishFullExpr(CounterUpdateRes.get(), 24260 /*DiscardedValue=*/true); 24261 if (!CounterUpdateRes.isUsable()) { 24262 IsCorrect = false; 24263 continue; 24264 } 24265 OMPIteratorHelperData &HD = Helpers.emplace_back(); 24266 HD.CounterVD = CounterVD; 24267 HD.Upper = Res.get(); 24268 HD.Update = UpdateRes.get(); 24269 HD.CounterUpdate = CounterUpdateRes.get(); 24270 } 24271 } else { 24272 Helpers.assign(ID.size(), {}); 24273 } 24274 if (!IsCorrect) { 24275 // Invalidate all created iterator declarations if error is found. 24276 for (const OMPIteratorExpr::IteratorDefinition &D : ID) { 24277 if (Decl *ID = D.IteratorDecl) 24278 ID->setInvalidDecl(); 24279 } 24280 return ExprError(); 24281 } 24282 return OMPIteratorExpr::Create(Context, Context.OMPIteratorTy, IteratorKwLoc, 24283 LLoc, RLoc, ID, Helpers); 24284 } 24285 24286 /// Check if \p AssumptionStr is a known assumption and warn if not. 24287 static void checkOMPAssumeAttr(Sema &S, SourceLocation Loc, 24288 StringRef AssumptionStr) { 24289 if (llvm::KnownAssumptionStrings.count(AssumptionStr)) 24290 return; 24291 24292 unsigned BestEditDistance = 3; 24293 StringRef Suggestion; 24294 for (const auto &KnownAssumptionIt : llvm::KnownAssumptionStrings) { 24295 unsigned EditDistance = 24296 AssumptionStr.edit_distance(KnownAssumptionIt.getKey()); 24297 if (EditDistance < BestEditDistance) { 24298 Suggestion = KnownAssumptionIt.getKey(); 24299 BestEditDistance = EditDistance; 24300 } 24301 } 24302 24303 if (!Suggestion.empty()) 24304 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested) 24305 << AssumptionStr << Suggestion; 24306 else 24307 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown) 24308 << AssumptionStr; 24309 } 24310 24311 void SemaOpenMP::handleOMPAssumeAttr(Decl *D, const ParsedAttr &AL) { 24312 // Handle the case where the attribute has a text message. 24313 StringRef Str; 24314 SourceLocation AttrStrLoc; 24315 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc)) 24316 return; 24317 24318 checkOMPAssumeAttr(SemaRef, AttrStrLoc, Str); 24319 24320 D->addAttr(::new (getASTContext()) OMPAssumeAttr(getASTContext(), AL, Str)); 24321 } 24322 24323 SemaOpenMP::SemaOpenMP(Sema &S) 24324 : SemaBase(S), VarDataSharingAttributesStack(nullptr) {} 24325