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/OpenMPClause.h" 24 #include "clang/AST/StmtCXX.h" 25 #include "clang/AST/StmtOpenMP.h" 26 #include "clang/AST/StmtVisitor.h" 27 #include "clang/AST/TypeOrdering.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 "clang/Sema/SemaInternal.h" 40 #include "llvm/ADT/IndexedMap.h" 41 #include "llvm/ADT/PointerEmbeddedInt.h" 42 #include "llvm/ADT/STLExtras.h" 43 #include "llvm/ADT/Sequence.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 #include <set> 51 52 using namespace clang; 53 using namespace llvm::omp; 54 55 //===----------------------------------------------------------------------===// 56 // Stack of data-sharing attributes for variables 57 //===----------------------------------------------------------------------===// 58 59 static const Expr *checkMapClauseExpressionBase( 60 Sema &SemaRef, Expr *E, 61 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents, 62 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose); 63 64 namespace { 65 /// Default data sharing attributes, which can be applied to directive. 66 enum DefaultDataSharingAttributes { 67 DSA_unspecified = 0, /// Data sharing attribute not specified. 68 DSA_none = 1 << 0, /// Default data sharing attribute 'none'. 69 DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'. 70 DSA_private = 1 << 2, /// Default data sharing attribute 'private'. 71 DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'. 72 }; 73 74 /// Stack for tracking declarations used in OpenMP directives and 75 /// clauses and their data-sharing attributes. 76 class DSAStackTy { 77 public: 78 struct DSAVarData { 79 OpenMPDirectiveKind DKind = OMPD_unknown; 80 OpenMPClauseKind CKind = OMPC_unknown; 81 unsigned Modifier = 0; 82 const Expr *RefExpr = nullptr; 83 DeclRefExpr *PrivateCopy = nullptr; 84 SourceLocation ImplicitDSALoc; 85 bool AppliedToPointee = false; 86 DSAVarData() = default; 87 DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, 88 const Expr *RefExpr, DeclRefExpr *PrivateCopy, 89 SourceLocation ImplicitDSALoc, unsigned Modifier, 90 bool AppliedToPointee) 91 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr), 92 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc), 93 AppliedToPointee(AppliedToPointee) {} 94 }; 95 using OperatorOffsetTy = 96 llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>; 97 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>; 98 /// Kind of the declaration used in the uses_allocators clauses. 99 enum class UsesAllocatorsDeclKind { 100 /// Predefined allocator 101 PredefinedAllocator, 102 /// User-defined allocator 103 UserDefinedAllocator, 104 /// The declaration that represent allocator trait 105 AllocatorTrait, 106 }; 107 108 private: 109 struct DSAInfo { 110 OpenMPClauseKind Attributes = OMPC_unknown; 111 unsigned Modifier = 0; 112 /// Pointer to a reference expression and a flag which shows that the 113 /// variable is marked as lastprivate(true) or not (false). 114 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr; 115 DeclRefExpr *PrivateCopy = nullptr; 116 /// true if the attribute is applied to the pointee, not the variable 117 /// itself. 118 bool AppliedToPointee = false; 119 }; 120 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>; 121 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>; 122 using LCDeclInfo = std::pair<unsigned, VarDecl *>; 123 using LoopControlVariablesMapTy = 124 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>; 125 /// Struct that associates a component with the clause kind where they are 126 /// found. 127 struct MappedExprComponentTy { 128 OMPClauseMappableExprCommon::MappableExprComponentLists Components; 129 OpenMPClauseKind Kind = OMPC_unknown; 130 }; 131 using MappedExprComponentsTy = 132 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>; 133 using CriticalsWithHintsTy = 134 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>; 135 struct ReductionData { 136 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>; 137 SourceRange ReductionRange; 138 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp; 139 ReductionData() = default; 140 void set(BinaryOperatorKind BO, SourceRange RR) { 141 ReductionRange = RR; 142 ReductionOp = BO; 143 } 144 void set(const Expr *RefExpr, SourceRange RR) { 145 ReductionRange = RR; 146 ReductionOp = RefExpr; 147 } 148 }; 149 using DeclReductionMapTy = 150 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>; 151 struct DefaultmapInfo { 152 OpenMPDefaultmapClauseModifier ImplicitBehavior = 153 OMPC_DEFAULTMAP_MODIFIER_unknown; 154 SourceLocation SLoc; 155 DefaultmapInfo() = default; 156 DefaultmapInfo(OpenMPDefaultmapClauseModifier M, SourceLocation Loc) 157 : ImplicitBehavior(M), SLoc(Loc) {} 158 }; 159 160 struct SharingMapTy { 161 DeclSAMapTy SharingMap; 162 DeclReductionMapTy ReductionMap; 163 UsedRefMapTy AlignedMap; 164 UsedRefMapTy NontemporalMap; 165 MappedExprComponentsTy MappedExprComponents; 166 LoopControlVariablesMapTy LCVMap; 167 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified; 168 SourceLocation DefaultAttrLoc; 169 DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown + 1]; 170 OpenMPDirectiveKind Directive = OMPD_unknown; 171 /// GenericLoopDirective with bind clause is mapped to other directives, 172 /// like for, distribute and simd. Presently, set MappedDirective to 173 /// OMPLoop. This may also be used in a similar way for other constructs. 174 OpenMPDirectiveKind MappedDirective = OMPD_unknown; 175 DeclarationNameInfo DirectiveName; 176 Scope *CurScope = nullptr; 177 DeclContext *Context = nullptr; 178 SourceLocation ConstructLoc; 179 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to 180 /// get the data (loop counters etc.) about enclosing loop-based construct. 181 /// This data is required during codegen. 182 DoacrossClauseMapTy DoacrossDepends; 183 /// First argument (Expr *) contains optional argument of the 184 /// 'ordered' clause, the second one is true if the regions has 'ordered' 185 /// clause, false otherwise. 186 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion; 187 bool RegionHasOrderConcurrent = false; 188 unsigned AssociatedLoops = 1; 189 bool HasMutipleLoops = false; 190 const Decl *PossiblyLoopCounter = nullptr; 191 bool NowaitRegion = false; 192 bool UntiedRegion = false; 193 bool CancelRegion = false; 194 bool LoopStart = false; 195 bool BodyComplete = false; 196 SourceLocation PrevScanLocation; 197 SourceLocation PrevOrderedLocation; 198 SourceLocation InnerTeamsRegionLoc; 199 /// Reference to the taskgroup task_reduction reference expression. 200 Expr *TaskgroupReductionRef = nullptr; 201 llvm::DenseSet<QualType> MappedClassesQualTypes; 202 SmallVector<Expr *, 4> InnerUsedAllocators; 203 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates; 204 /// List of globals marked as declare target link in this target region 205 /// (isOpenMPTargetExecutionDirective(Directive) == true). 206 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls; 207 /// List of decls used in inclusive/exclusive clauses of the scan directive. 208 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective; 209 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind> 210 UsesAllocatorsDecls; 211 /// Data is required on creating capture fields for implicit 212 /// default first|private clause. 213 struct ImplicitDefaultFDInfoTy { 214 /// Field decl. 215 const FieldDecl *FD = nullptr; 216 /// Nesting stack level 217 size_t StackLevel = 0; 218 /// Capture variable decl. 219 VarDecl *VD = nullptr; 220 ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel, 221 VarDecl *VD) 222 : FD(FD), StackLevel(StackLevel), VD(VD) {} 223 }; 224 /// List of captured fields 225 llvm::SmallVector<ImplicitDefaultFDInfoTy, 8> 226 ImplicitDefaultFirstprivateFDs; 227 Expr *DeclareMapperVar = nullptr; 228 SmallVector<VarDecl *, 16> IteratorVarDecls; 229 SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name, 230 Scope *CurScope, SourceLocation Loc) 231 : Directive(DKind), DirectiveName(Name), CurScope(CurScope), 232 ConstructLoc(Loc) {} 233 SharingMapTy() = default; 234 }; 235 236 using StackTy = SmallVector<SharingMapTy, 4>; 237 238 /// Stack of used declaration and their data-sharing attributes. 239 DeclSAMapTy Threadprivates; 240 const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr; 241 SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack; 242 /// true, if check for DSA must be from parent directive, false, if 243 /// from current directive. 244 OpenMPClauseKind ClauseKindMode = OMPC_unknown; 245 Sema &SemaRef; 246 bool ForceCapturing = false; 247 /// true if all the variables in the target executable directives must be 248 /// captured by reference. 249 bool ForceCaptureByReferenceInTargetExecutable = false; 250 CriticalsWithHintsTy Criticals; 251 unsigned IgnoredStackElements = 0; 252 253 /// Iterators over the stack iterate in order from innermost to outermost 254 /// directive. 255 using const_iterator = StackTy::const_reverse_iterator; 256 const_iterator begin() const { 257 return Stack.empty() ? const_iterator() 258 : Stack.back().first.rbegin() + IgnoredStackElements; 259 } 260 const_iterator end() const { 261 return Stack.empty() ? const_iterator() : Stack.back().first.rend(); 262 } 263 using iterator = StackTy::reverse_iterator; 264 iterator begin() { 265 return Stack.empty() ? iterator() 266 : Stack.back().first.rbegin() + IgnoredStackElements; 267 } 268 iterator end() { 269 return Stack.empty() ? iterator() : Stack.back().first.rend(); 270 } 271 272 // Convenience operations to get at the elements of the stack. 273 274 bool isStackEmpty() const { 275 return Stack.empty() || 276 Stack.back().second != CurrentNonCapturingFunctionScope || 277 Stack.back().first.size() <= IgnoredStackElements; 278 } 279 size_t getStackSize() const { 280 return isStackEmpty() ? 0 281 : Stack.back().first.size() - IgnoredStackElements; 282 } 283 284 SharingMapTy *getTopOfStackOrNull() { 285 size_t Size = getStackSize(); 286 if (Size == 0) 287 return nullptr; 288 return &Stack.back().first[Size - 1]; 289 } 290 const SharingMapTy *getTopOfStackOrNull() const { 291 return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull(); 292 } 293 SharingMapTy &getTopOfStack() { 294 assert(!isStackEmpty() && "no current directive"); 295 return *getTopOfStackOrNull(); 296 } 297 const SharingMapTy &getTopOfStack() const { 298 return const_cast<DSAStackTy &>(*this).getTopOfStack(); 299 } 300 301 SharingMapTy *getSecondOnStackOrNull() { 302 size_t Size = getStackSize(); 303 if (Size <= 1) 304 return nullptr; 305 return &Stack.back().first[Size - 2]; 306 } 307 const SharingMapTy *getSecondOnStackOrNull() const { 308 return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull(); 309 } 310 311 /// Get the stack element at a certain level (previously returned by 312 /// \c getNestingLevel). 313 /// 314 /// Note that nesting levels count from outermost to innermost, and this is 315 /// the reverse of our iteration order where new inner levels are pushed at 316 /// the front of the stack. 317 SharingMapTy &getStackElemAtLevel(unsigned Level) { 318 assert(Level < getStackSize() && "no such stack element"); 319 return Stack.back().first[Level]; 320 } 321 const SharingMapTy &getStackElemAtLevel(unsigned Level) const { 322 return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level); 323 } 324 325 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const; 326 327 /// Checks if the variable is a local for OpenMP region. 328 bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const; 329 330 /// Vector of previously declared requires directives 331 SmallVector<const OMPRequiresDecl *, 2> RequiresDecls; 332 /// omp_allocator_handle_t type. 333 QualType OMPAllocatorHandleT; 334 /// omp_depend_t type. 335 QualType OMPDependT; 336 /// omp_event_handle_t type. 337 QualType OMPEventHandleT; 338 /// omp_alloctrait_t type. 339 QualType OMPAlloctraitT; 340 /// Expression for the predefined allocators. 341 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = { 342 nullptr}; 343 /// Vector of previously encountered target directives 344 SmallVector<SourceLocation, 2> TargetLocations; 345 SourceLocation AtomicLocation; 346 /// Vector of declare variant construct traits. 347 SmallVector<llvm::omp::TraitProperty, 8> ConstructTraits; 348 349 public: 350 explicit DSAStackTy(Sema &S) : SemaRef(S) {} 351 352 /// Sets omp_allocator_handle_t type. 353 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; } 354 /// Gets omp_allocator_handle_t type. 355 QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; } 356 /// Sets omp_alloctrait_t type. 357 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; } 358 /// Gets omp_alloctrait_t type. 359 QualType getOMPAlloctraitT() const { return OMPAlloctraitT; } 360 /// Sets the given default allocator. 361 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, 362 Expr *Allocator) { 363 OMPPredefinedAllocators[AllocatorKind] = Allocator; 364 } 365 /// Returns the specified default allocator. 366 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const { 367 return OMPPredefinedAllocators[AllocatorKind]; 368 } 369 /// Sets omp_depend_t type. 370 void setOMPDependT(QualType Ty) { OMPDependT = Ty; } 371 /// Gets omp_depend_t type. 372 QualType getOMPDependT() const { return OMPDependT; } 373 374 /// Sets omp_event_handle_t type. 375 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; } 376 /// Gets omp_event_handle_t type. 377 QualType getOMPEventHandleT() const { return OMPEventHandleT; } 378 379 bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; } 380 OpenMPClauseKind getClauseParsingMode() const { 381 assert(isClauseParsingMode() && "Must be in clause parsing mode."); 382 return ClauseKindMode; 383 } 384 void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; } 385 386 bool isBodyComplete() const { 387 const SharingMapTy *Top = getTopOfStackOrNull(); 388 return Top && Top->BodyComplete; 389 } 390 void setBodyComplete() { getTopOfStack().BodyComplete = true; } 391 392 bool isForceVarCapturing() const { return ForceCapturing; } 393 void setForceVarCapturing(bool V) { ForceCapturing = V; } 394 395 void setForceCaptureByReferenceInTargetExecutable(bool V) { 396 ForceCaptureByReferenceInTargetExecutable = V; 397 } 398 bool isForceCaptureByReferenceInTargetExecutable() const { 399 return ForceCaptureByReferenceInTargetExecutable; 400 } 401 402 void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName, 403 Scope *CurScope, SourceLocation Loc) { 404 assert(!IgnoredStackElements && 405 "cannot change stack while ignoring elements"); 406 if (Stack.empty() || 407 Stack.back().second != CurrentNonCapturingFunctionScope) 408 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope); 409 Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc); 410 Stack.back().first.back().DefaultAttrLoc = Loc; 411 } 412 413 void pop() { 414 assert(!IgnoredStackElements && 415 "cannot change stack while ignoring elements"); 416 assert(!Stack.back().first.empty() && 417 "Data-sharing attributes stack is empty!"); 418 Stack.back().first.pop_back(); 419 } 420 421 /// RAII object to temporarily leave the scope of a directive when we want to 422 /// logically operate in its parent. 423 class ParentDirectiveScope { 424 DSAStackTy &Self; 425 bool Active; 426 427 public: 428 ParentDirectiveScope(DSAStackTy &Self, bool Activate) 429 : Self(Self), Active(false) { 430 if (Activate) 431 enable(); 432 } 433 ~ParentDirectiveScope() { disable(); } 434 void disable() { 435 if (Active) { 436 --Self.IgnoredStackElements; 437 Active = false; 438 } 439 } 440 void enable() { 441 if (!Active) { 442 ++Self.IgnoredStackElements; 443 Active = true; 444 } 445 } 446 }; 447 448 /// Marks that we're started loop parsing. 449 void loopInit() { 450 assert(isOpenMPLoopDirective(getCurrentDirective()) && 451 "Expected loop-based directive."); 452 getTopOfStack().LoopStart = true; 453 } 454 /// Start capturing of the variables in the loop context. 455 void loopStart() { 456 assert(isOpenMPLoopDirective(getCurrentDirective()) && 457 "Expected loop-based directive."); 458 getTopOfStack().LoopStart = false; 459 } 460 /// true, if variables are captured, false otherwise. 461 bool isLoopStarted() const { 462 assert(isOpenMPLoopDirective(getCurrentDirective()) && 463 "Expected loop-based directive."); 464 return !getTopOfStack().LoopStart; 465 } 466 /// Marks (or clears) declaration as possibly loop counter. 467 void resetPossibleLoopCounter(const Decl *D = nullptr) { 468 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D; 469 } 470 /// Gets the possible loop counter decl. 471 const Decl *getPossiblyLoopCounter() const { 472 return getTopOfStack().PossiblyLoopCounter; 473 } 474 /// Start new OpenMP region stack in new non-capturing function. 475 void pushFunction() { 476 assert(!IgnoredStackElements && 477 "cannot change stack while ignoring elements"); 478 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction(); 479 assert(!isa<CapturingScopeInfo>(CurFnScope)); 480 CurrentNonCapturingFunctionScope = CurFnScope; 481 } 482 /// Pop region stack for non-capturing function. 483 void popFunction(const FunctionScopeInfo *OldFSI) { 484 assert(!IgnoredStackElements && 485 "cannot change stack while ignoring elements"); 486 if (!Stack.empty() && Stack.back().second == OldFSI) { 487 assert(Stack.back().first.empty()); 488 Stack.pop_back(); 489 } 490 CurrentNonCapturingFunctionScope = nullptr; 491 for (const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) { 492 if (!isa<CapturingScopeInfo>(FSI)) { 493 CurrentNonCapturingFunctionScope = FSI; 494 break; 495 } 496 } 497 } 498 499 void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) { 500 Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint); 501 } 502 const std::pair<const OMPCriticalDirective *, llvm::APSInt> 503 getCriticalWithHint(const DeclarationNameInfo &Name) const { 504 auto I = Criticals.find(Name.getAsString()); 505 if (I != Criticals.end()) 506 return I->second; 507 return std::make_pair(nullptr, llvm::APSInt()); 508 } 509 /// If 'aligned' declaration for given variable \a D was not seen yet, 510 /// add it and return NULL; otherwise return previous occurrence's expression 511 /// for diagnostics. 512 const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE); 513 /// If 'nontemporal' declaration for given variable \a D was not seen yet, 514 /// add it and return NULL; otherwise return previous occurrence's expression 515 /// for diagnostics. 516 const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE); 517 518 /// Register specified variable as loop control variable. 519 void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture); 520 /// Check if the specified variable is a loop control variable for 521 /// current 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 isLoopControlVariable(const ValueDecl *D) const; 525 /// Check if the specified variable is a loop control variable for 526 /// parent 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 isParentLoopControlVariable(const ValueDecl *D) const; 530 /// Check if the specified variable is a loop control variable for 531 /// current region. 532 /// \return The index of the loop control variable in the list of associated 533 /// for-loops (from outer to inner). 534 const LCDeclInfo isLoopControlVariable(const ValueDecl *D, 535 unsigned Level) const; 536 /// Get the loop control variable for the I-th loop (or nullptr) in 537 /// parent directive. 538 const ValueDecl *getParentLoopControlVariable(unsigned I) const; 539 540 /// Marks the specified decl \p D as used in scan directive. 541 void markDeclAsUsedInScanDirective(ValueDecl *D) { 542 if (SharingMapTy *Stack = getSecondOnStackOrNull()) 543 Stack->UsedInScanDirective.insert(D); 544 } 545 546 /// Checks if the specified declaration was used in the inner scan directive. 547 bool isUsedInScanDirective(ValueDecl *D) const { 548 if (const SharingMapTy *Stack = getTopOfStackOrNull()) 549 return Stack->UsedInScanDirective.contains(D); 550 return false; 551 } 552 553 /// Adds explicit data sharing attribute to the specified declaration. 554 void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A, 555 DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0, 556 bool AppliedToPointee = false); 557 558 /// Adds additional information for the reduction items with the reduction id 559 /// represented as an operator. 560 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR, 561 BinaryOperatorKind BOK); 562 /// Adds additional information for the reduction items with the reduction id 563 /// represented as reduction identifier. 564 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR, 565 const Expr *ReductionRef); 566 /// Returns the location and reduction operation from the innermost parent 567 /// region for the given \p D. 568 const DSAVarData 569 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR, 570 BinaryOperatorKind &BOK, 571 Expr *&TaskgroupDescriptor) const; 572 /// Returns the location and reduction operation from the innermost parent 573 /// region for the given \p D. 574 const DSAVarData 575 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR, 576 const Expr *&ReductionRef, 577 Expr *&TaskgroupDescriptor) const; 578 /// Return reduction reference expression for the current taskgroup or 579 /// parallel/worksharing directives with task reductions. 580 Expr *getTaskgroupReductionRef() const { 581 assert((getTopOfStack().Directive == OMPD_taskgroup || 582 ((isOpenMPParallelDirective(getTopOfStack().Directive) || 583 isOpenMPWorksharingDirective(getTopOfStack().Directive)) && 584 !isOpenMPSimdDirective(getTopOfStack().Directive))) && 585 "taskgroup reference expression requested for non taskgroup or " 586 "parallel/worksharing directive."); 587 return getTopOfStack().TaskgroupReductionRef; 588 } 589 /// Checks if the given \p VD declaration is actually a taskgroup reduction 590 /// descriptor variable at the \p Level of OpenMP regions. 591 bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const { 592 return getStackElemAtLevel(Level).TaskgroupReductionRef && 593 cast<DeclRefExpr>(getStackElemAtLevel(Level).TaskgroupReductionRef) 594 ->getDecl() == VD; 595 } 596 597 /// Returns data sharing attributes from top of the stack for the 598 /// specified declaration. 599 const DSAVarData getTopDSA(ValueDecl *D, bool FromParent); 600 /// Returns data-sharing attributes for the specified declaration. 601 const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const; 602 /// Returns data-sharing attributes for the specified declaration. 603 const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const; 604 /// Checks if the specified variables has data-sharing attributes which 605 /// match specified \a CPred predicate in any directive which matches \a DPred 606 /// predicate. 607 const DSAVarData 608 hasDSA(ValueDecl *D, 609 const llvm::function_ref<bool(OpenMPClauseKind, bool, 610 DefaultDataSharingAttributes)> 611 CPred, 612 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred, 613 bool FromParent) const; 614 /// Checks if the specified variables has data-sharing attributes which 615 /// match specified \a CPred predicate in any innermost directive which 616 /// matches \a DPred predicate. 617 const DSAVarData 618 hasInnermostDSA(ValueDecl *D, 619 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred, 620 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred, 621 bool FromParent) const; 622 /// Checks if the specified variables has explicit data-sharing 623 /// attributes which match specified \a CPred predicate at the specified 624 /// OpenMP region. 625 bool 626 hasExplicitDSA(const ValueDecl *D, 627 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred, 628 unsigned Level, bool NotLastprivate = false) const; 629 630 /// Returns true if the directive at level \Level matches in the 631 /// specified \a DPred predicate. 632 bool hasExplicitDirective( 633 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred, 634 unsigned Level) const; 635 636 /// Finds a directive which matches specified \a DPred predicate. 637 bool hasDirective( 638 const llvm::function_ref<bool( 639 OpenMPDirectiveKind, const DeclarationNameInfo &, SourceLocation)> 640 DPred, 641 bool FromParent) const; 642 643 /// Returns currently analyzed directive. 644 OpenMPDirectiveKind getCurrentDirective() const { 645 const SharingMapTy *Top = getTopOfStackOrNull(); 646 return Top ? Top->Directive : OMPD_unknown; 647 } 648 OpenMPDirectiveKind getMappedDirective() const { 649 const SharingMapTy *Top = getTopOfStackOrNull(); 650 return Top ? Top->MappedDirective : OMPD_unknown; 651 } 652 void setCurrentDirective(OpenMPDirectiveKind NewDK) { 653 SharingMapTy *Top = getTopOfStackOrNull(); 654 assert(Top && 655 "Before calling setCurrentDirective Top of Stack not to be NULL."); 656 // Store the old into MappedDirective & assign argument NewDK to Directive. 657 Top->Directive = NewDK; 658 } 659 void setMappedDirective(OpenMPDirectiveKind NewDK) { 660 SharingMapTy *Top = getTopOfStackOrNull(); 661 assert(Top && 662 "Before calling setMappedDirective Top of Stack not to be NULL."); 663 // Store the old into MappedDirective & assign argument NewDK to Directive. 664 Top->MappedDirective = NewDK; 665 } 666 /// Returns directive kind at specified level. 667 OpenMPDirectiveKind getDirective(unsigned Level) const { 668 assert(!isStackEmpty() && "No directive at specified level."); 669 return getStackElemAtLevel(Level).Directive; 670 } 671 /// Returns the capture region at the specified level. 672 OpenMPDirectiveKind getCaptureRegion(unsigned Level, 673 unsigned OpenMPCaptureLevel) const { 674 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 675 getOpenMPCaptureRegions(CaptureRegions, getDirective(Level)); 676 return CaptureRegions[OpenMPCaptureLevel]; 677 } 678 /// Returns parent directive. 679 OpenMPDirectiveKind getParentDirective() const { 680 const SharingMapTy *Parent = getSecondOnStackOrNull(); 681 return Parent ? Parent->Directive : OMPD_unknown; 682 } 683 684 /// Add requires decl to internal vector 685 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); } 686 687 /// Checks if the defined 'requires' directive has specified type of clause. 688 template <typename ClauseType> bool hasRequiresDeclWithClause() const { 689 return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) { 690 return llvm::any_of(D->clauselists(), [](const OMPClause *C) { 691 return isa<ClauseType>(C); 692 }); 693 }); 694 } 695 696 /// Checks for a duplicate clause amongst previously declared requires 697 /// directives 698 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const { 699 bool IsDuplicate = false; 700 for (OMPClause *CNew : ClauseList) { 701 for (const OMPRequiresDecl *D : RequiresDecls) { 702 for (const OMPClause *CPrev : D->clauselists()) { 703 if (CNew->getClauseKind() == CPrev->getClauseKind()) { 704 SemaRef.Diag(CNew->getBeginLoc(), 705 diag::err_omp_requires_clause_redeclaration) 706 << getOpenMPClauseName(CNew->getClauseKind()); 707 SemaRef.Diag(CPrev->getBeginLoc(), 708 diag::note_omp_requires_previous_clause) 709 << getOpenMPClauseName(CPrev->getClauseKind()); 710 IsDuplicate = true; 711 } 712 } 713 } 714 } 715 return IsDuplicate; 716 } 717 718 /// Add location of previously encountered target to internal vector 719 void addTargetDirLocation(SourceLocation LocStart) { 720 TargetLocations.push_back(LocStart); 721 } 722 723 /// Add location for the first encountered atomic directive. 724 void addAtomicDirectiveLoc(SourceLocation Loc) { 725 if (AtomicLocation.isInvalid()) 726 AtomicLocation = Loc; 727 } 728 729 /// Returns the location of the first encountered atomic directive in the 730 /// module. 731 SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; } 732 733 // Return previously encountered target region locations. 734 ArrayRef<SourceLocation> getEncounteredTargetLocs() const { 735 return TargetLocations; 736 } 737 738 /// Set default data sharing attribute to none. 739 void setDefaultDSANone(SourceLocation Loc) { 740 getTopOfStack().DefaultAttr = DSA_none; 741 getTopOfStack().DefaultAttrLoc = Loc; 742 } 743 /// Set default data sharing attribute to shared. 744 void setDefaultDSAShared(SourceLocation Loc) { 745 getTopOfStack().DefaultAttr = DSA_shared; 746 getTopOfStack().DefaultAttrLoc = Loc; 747 } 748 /// Set default data sharing attribute to private. 749 void setDefaultDSAPrivate(SourceLocation Loc) { 750 getTopOfStack().DefaultAttr = DSA_private; 751 getTopOfStack().DefaultAttrLoc = Loc; 752 } 753 /// Set default data sharing attribute to firstprivate. 754 void setDefaultDSAFirstPrivate(SourceLocation Loc) { 755 getTopOfStack().DefaultAttr = DSA_firstprivate; 756 getTopOfStack().DefaultAttrLoc = Loc; 757 } 758 /// Set default data mapping attribute to Modifier:Kind 759 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M, 760 OpenMPDefaultmapClauseKind Kind, SourceLocation Loc) { 761 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind]; 762 DMI.ImplicitBehavior = M; 763 DMI.SLoc = Loc; 764 } 765 /// Check whether the implicit-behavior has been set in defaultmap 766 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) { 767 if (VariableCategory == OMPC_DEFAULTMAP_unknown) 768 return getTopOfStack() 769 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate] 770 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown || 771 getTopOfStack() 772 .DefaultmapMap[OMPC_DEFAULTMAP_scalar] 773 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown || 774 getTopOfStack() 775 .DefaultmapMap[OMPC_DEFAULTMAP_pointer] 776 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown; 777 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior != 778 OMPC_DEFAULTMAP_MODIFIER_unknown; 779 } 780 781 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() { 782 return ConstructTraits; 783 } 784 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits, 785 bool ScopeEntry) { 786 if (ScopeEntry) 787 ConstructTraits.append(Traits.begin(), Traits.end()); 788 else 789 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) { 790 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val(); 791 assert(Top == Trait && "Something left a trait on the stack!"); 792 (void)Trait; 793 (void)Top; 794 } 795 } 796 797 DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const { 798 return getStackSize() <= Level ? DSA_unspecified 799 : getStackElemAtLevel(Level).DefaultAttr; 800 } 801 DefaultDataSharingAttributes getDefaultDSA() const { 802 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr; 803 } 804 SourceLocation getDefaultDSALocation() const { 805 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc; 806 } 807 OpenMPDefaultmapClauseModifier 808 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const { 809 return isStackEmpty() 810 ? OMPC_DEFAULTMAP_MODIFIER_unknown 811 : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior; 812 } 813 OpenMPDefaultmapClauseModifier 814 getDefaultmapModifierAtLevel(unsigned Level, 815 OpenMPDefaultmapClauseKind Kind) const { 816 return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior; 817 } 818 bool isDefaultmapCapturedByRef(unsigned Level, 819 OpenMPDefaultmapClauseKind Kind) const { 820 OpenMPDefaultmapClauseModifier M = 821 getDefaultmapModifierAtLevel(Level, Kind); 822 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) { 823 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) || 824 (M == OMPC_DEFAULTMAP_MODIFIER_to) || 825 (M == OMPC_DEFAULTMAP_MODIFIER_from) || 826 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom); 827 } 828 return true; 829 } 830 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M, 831 OpenMPDefaultmapClauseKind Kind) { 832 switch (Kind) { 833 case OMPC_DEFAULTMAP_scalar: 834 case OMPC_DEFAULTMAP_pointer: 835 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) || 836 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) || 837 (M == OMPC_DEFAULTMAP_MODIFIER_default); 838 case OMPC_DEFAULTMAP_aggregate: 839 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate; 840 default: 841 break; 842 } 843 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum"); 844 } 845 bool mustBeFirstprivateAtLevel(unsigned Level, 846 OpenMPDefaultmapClauseKind Kind) const { 847 OpenMPDefaultmapClauseModifier M = 848 getDefaultmapModifierAtLevel(Level, Kind); 849 return mustBeFirstprivateBase(M, Kind); 850 } 851 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const { 852 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind); 853 return mustBeFirstprivateBase(M, Kind); 854 } 855 856 /// Checks if the specified variable is a threadprivate. 857 bool isThreadPrivate(VarDecl *D) { 858 const DSAVarData DVar = getTopDSA(D, false); 859 return isOpenMPThreadPrivate(DVar.CKind); 860 } 861 862 /// Marks current region as ordered (it has an 'ordered' clause). 863 void setOrderedRegion(bool IsOrdered, const Expr *Param, 864 OMPOrderedClause *Clause) { 865 if (IsOrdered) 866 getTopOfStack().OrderedRegion.emplace(Param, Clause); 867 else 868 getTopOfStack().OrderedRegion.reset(); 869 } 870 /// Returns true, if region is ordered (has associated 'ordered' clause), 871 /// false - otherwise. 872 bool isOrderedRegion() const { 873 if (const SharingMapTy *Top = getTopOfStackOrNull()) 874 return Top->OrderedRegion.has_value(); 875 return false; 876 } 877 /// Returns optional parameter for the ordered region. 878 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const { 879 if (const SharingMapTy *Top = getTopOfStackOrNull()) 880 if (Top->OrderedRegion) 881 return *Top->OrderedRegion; 882 return std::make_pair(nullptr, nullptr); 883 } 884 /// Returns true, if parent region is ordered (has associated 885 /// 'ordered' clause), false - otherwise. 886 bool isParentOrderedRegion() const { 887 if (const SharingMapTy *Parent = getSecondOnStackOrNull()) 888 return Parent->OrderedRegion.has_value(); 889 return false; 890 } 891 /// Returns optional parameter for the ordered region. 892 std::pair<const Expr *, OMPOrderedClause *> 893 getParentOrderedRegionParam() const { 894 if (const SharingMapTy *Parent = getSecondOnStackOrNull()) 895 if (Parent->OrderedRegion) 896 return *Parent->OrderedRegion; 897 return std::make_pair(nullptr, nullptr); 898 } 899 /// Marks current region as having an 'order' clause. 900 void setRegionHasOrderConcurrent(bool HasOrderConcurrent) { 901 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent; 902 } 903 /// Returns true, if parent region is order (has associated 904 /// 'order' clause), false - otherwise. 905 bool isParentOrderConcurrent() const { 906 if (const SharingMapTy *Parent = getSecondOnStackOrNull()) 907 return Parent->RegionHasOrderConcurrent; 908 return false; 909 } 910 /// Marks current region as nowait (it has a 'nowait' clause). 911 void setNowaitRegion(bool IsNowait = true) { 912 getTopOfStack().NowaitRegion = IsNowait; 913 } 914 /// Returns true, if parent region is nowait (has associated 915 /// 'nowait' clause), false - otherwise. 916 bool isParentNowaitRegion() const { 917 if (const SharingMapTy *Parent = getSecondOnStackOrNull()) 918 return Parent->NowaitRegion; 919 return false; 920 } 921 /// Marks current region as untied (it has a 'untied' clause). 922 void setUntiedRegion(bool IsUntied = true) { 923 getTopOfStack().UntiedRegion = IsUntied; 924 } 925 /// Return true if current region is untied. 926 bool isUntiedRegion() const { 927 const SharingMapTy *Top = getTopOfStackOrNull(); 928 return Top ? Top->UntiedRegion : false; 929 } 930 /// Marks parent region as cancel region. 931 void setParentCancelRegion(bool Cancel = true) { 932 if (SharingMapTy *Parent = getSecondOnStackOrNull()) 933 Parent->CancelRegion |= Cancel; 934 } 935 /// Return true if current region has inner cancel construct. 936 bool isCancelRegion() const { 937 const SharingMapTy *Top = getTopOfStackOrNull(); 938 return Top ? Top->CancelRegion : false; 939 } 940 941 /// Mark that parent region already has scan directive. 942 void setParentHasScanDirective(SourceLocation Loc) { 943 if (SharingMapTy *Parent = getSecondOnStackOrNull()) 944 Parent->PrevScanLocation = Loc; 945 } 946 /// Return true if current region has inner cancel construct. 947 bool doesParentHasScanDirective() const { 948 const SharingMapTy *Top = getSecondOnStackOrNull(); 949 return Top ? Top->PrevScanLocation.isValid() : false; 950 } 951 /// Return true if current region has inner cancel construct. 952 SourceLocation getParentScanDirectiveLoc() const { 953 const SharingMapTy *Top = getSecondOnStackOrNull(); 954 return Top ? Top->PrevScanLocation : SourceLocation(); 955 } 956 /// Mark that parent region already has ordered directive. 957 void setParentHasOrderedDirective(SourceLocation Loc) { 958 if (SharingMapTy *Parent = getSecondOnStackOrNull()) 959 Parent->PrevOrderedLocation = Loc; 960 } 961 /// Return true if current region has inner ordered construct. 962 bool doesParentHasOrderedDirective() const { 963 const SharingMapTy *Top = getSecondOnStackOrNull(); 964 return Top ? Top->PrevOrderedLocation.isValid() : false; 965 } 966 /// Returns the location of the previously specified ordered directive. 967 SourceLocation getParentOrderedDirectiveLoc() const { 968 const SharingMapTy *Top = getSecondOnStackOrNull(); 969 return Top ? Top->PrevOrderedLocation : SourceLocation(); 970 } 971 972 /// Set collapse value for the region. 973 void setAssociatedLoops(unsigned Val) { 974 getTopOfStack().AssociatedLoops = Val; 975 if (Val > 1) 976 getTopOfStack().HasMutipleLoops = true; 977 } 978 /// Return collapse value for region. 979 unsigned getAssociatedLoops() const { 980 const SharingMapTy *Top = getTopOfStackOrNull(); 981 return Top ? Top->AssociatedLoops : 0; 982 } 983 /// Returns true if the construct is associated with multiple loops. 984 bool hasMutipleLoops() const { 985 const SharingMapTy *Top = getTopOfStackOrNull(); 986 return Top ? Top->HasMutipleLoops : false; 987 } 988 989 /// Marks current target region as one with closely nested teams 990 /// region. 991 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) { 992 if (SharingMapTy *Parent = getSecondOnStackOrNull()) 993 Parent->InnerTeamsRegionLoc = TeamsRegionLoc; 994 } 995 /// Returns true, if current region has closely nested teams region. 996 bool hasInnerTeamsRegion() const { 997 return getInnerTeamsRegionLoc().isValid(); 998 } 999 /// Returns location of the nested teams region (if any). 1000 SourceLocation getInnerTeamsRegionLoc() const { 1001 const SharingMapTy *Top = getTopOfStackOrNull(); 1002 return Top ? Top->InnerTeamsRegionLoc : SourceLocation(); 1003 } 1004 1005 Scope *getCurScope() const { 1006 const SharingMapTy *Top = getTopOfStackOrNull(); 1007 return Top ? Top->CurScope : nullptr; 1008 } 1009 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; } 1010 SourceLocation getConstructLoc() const { 1011 const SharingMapTy *Top = getTopOfStackOrNull(); 1012 return Top ? Top->ConstructLoc : SourceLocation(); 1013 } 1014 1015 /// Do the check specified in \a Check to all component lists and return true 1016 /// if any issue is found. 1017 bool checkMappableExprComponentListsForDecl( 1018 const ValueDecl *VD, bool CurrentRegionOnly, 1019 const llvm::function_ref< 1020 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef, 1021 OpenMPClauseKind)> 1022 Check) const { 1023 if (isStackEmpty()) 1024 return false; 1025 auto SI = begin(); 1026 auto SE = end(); 1027 1028 if (SI == SE) 1029 return false; 1030 1031 if (CurrentRegionOnly) 1032 SE = std::next(SI); 1033 else 1034 std::advance(SI, 1); 1035 1036 for (; SI != SE; ++SI) { 1037 auto MI = SI->MappedExprComponents.find(VD); 1038 if (MI != SI->MappedExprComponents.end()) 1039 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L : 1040 MI->second.Components) 1041 if (Check(L, MI->second.Kind)) 1042 return true; 1043 } 1044 return false; 1045 } 1046 1047 /// Do the check specified in \a Check to all component lists at a given level 1048 /// and return true if any issue is found. 1049 bool checkMappableExprComponentListsForDeclAtLevel( 1050 const ValueDecl *VD, unsigned Level, 1051 const llvm::function_ref< 1052 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef, 1053 OpenMPClauseKind)> 1054 Check) const { 1055 if (getStackSize() <= Level) 1056 return false; 1057 1058 const SharingMapTy &StackElem = getStackElemAtLevel(Level); 1059 auto MI = StackElem.MappedExprComponents.find(VD); 1060 if (MI != StackElem.MappedExprComponents.end()) 1061 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L : 1062 MI->second.Components) 1063 if (Check(L, MI->second.Kind)) 1064 return true; 1065 return false; 1066 } 1067 1068 /// Create a new mappable expression component list associated with a given 1069 /// declaration and initialize it with the provided list of components. 1070 void addMappableExpressionComponents( 1071 const ValueDecl *VD, 1072 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 1073 OpenMPClauseKind WhereFoundClauseKind) { 1074 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD]; 1075 // Create new entry and append the new components there. 1076 MEC.Components.resize(MEC.Components.size() + 1); 1077 MEC.Components.back().append(Components.begin(), Components.end()); 1078 MEC.Kind = WhereFoundClauseKind; 1079 } 1080 1081 unsigned getNestingLevel() const { 1082 assert(!isStackEmpty()); 1083 return getStackSize() - 1; 1084 } 1085 void addDoacrossDependClause(OMPClause *C, const OperatorOffsetTy &OpsOffs) { 1086 SharingMapTy *Parent = getSecondOnStackOrNull(); 1087 assert(Parent && isOpenMPWorksharingDirective(Parent->Directive)); 1088 Parent->DoacrossDepends.try_emplace(C, OpsOffs); 1089 } 1090 llvm::iterator_range<DoacrossClauseMapTy::const_iterator> 1091 getDoacrossDependClauses() const { 1092 const SharingMapTy &StackElem = getTopOfStack(); 1093 if (isOpenMPWorksharingDirective(StackElem.Directive)) { 1094 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends; 1095 return llvm::make_range(Ref.begin(), Ref.end()); 1096 } 1097 return llvm::make_range(StackElem.DoacrossDepends.end(), 1098 StackElem.DoacrossDepends.end()); 1099 } 1100 1101 // Store types of classes which have been explicitly mapped 1102 void addMappedClassesQualTypes(QualType QT) { 1103 SharingMapTy &StackElem = getTopOfStack(); 1104 StackElem.MappedClassesQualTypes.insert(QT); 1105 } 1106 1107 // Return set of mapped classes types 1108 bool isClassPreviouslyMapped(QualType QT) const { 1109 const SharingMapTy &StackElem = getTopOfStack(); 1110 return StackElem.MappedClassesQualTypes.contains(QT); 1111 } 1112 1113 /// Adds global declare target to the parent target region. 1114 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) { 1115 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( 1116 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link && 1117 "Expected declare target link global."); 1118 for (auto &Elem : *this) { 1119 if (isOpenMPTargetExecutionDirective(Elem.Directive)) { 1120 Elem.DeclareTargetLinkVarDecls.push_back(E); 1121 return; 1122 } 1123 } 1124 } 1125 1126 /// Returns the list of globals with declare target link if current directive 1127 /// is target. 1128 ArrayRef<DeclRefExpr *> getLinkGlobals() const { 1129 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) && 1130 "Expected target executable directive."); 1131 return getTopOfStack().DeclareTargetLinkVarDecls; 1132 } 1133 1134 /// Adds list of allocators expressions. 1135 void addInnerAllocatorExpr(Expr *E) { 1136 getTopOfStack().InnerUsedAllocators.push_back(E); 1137 } 1138 /// Return list of used allocators. 1139 ArrayRef<Expr *> getInnerAllocators() const { 1140 return getTopOfStack().InnerUsedAllocators; 1141 } 1142 /// Marks the declaration as implicitly firstprivate nin the task-based 1143 /// regions. 1144 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) { 1145 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(D); 1146 } 1147 /// Checks if the decl is implicitly firstprivate in the task-based region. 1148 bool isImplicitTaskFirstprivate(Decl *D) const { 1149 return getTopOfStack().ImplicitTaskFirstprivates.contains(D); 1150 } 1151 1152 /// Marks decl as used in uses_allocators clause as the allocator. 1153 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) { 1154 getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind); 1155 } 1156 /// Checks if specified decl is used in uses allocator clause as the 1157 /// allocator. 1158 std::optional<UsesAllocatorsDeclKind> 1159 isUsesAllocatorsDecl(unsigned Level, const Decl *D) const { 1160 const SharingMapTy &StackElem = getTopOfStack(); 1161 auto I = StackElem.UsesAllocatorsDecls.find(D); 1162 if (I == StackElem.UsesAllocatorsDecls.end()) 1163 return std::nullopt; 1164 return I->getSecond(); 1165 } 1166 std::optional<UsesAllocatorsDeclKind> 1167 isUsesAllocatorsDecl(const Decl *D) const { 1168 const SharingMapTy &StackElem = getTopOfStack(); 1169 auto I = StackElem.UsesAllocatorsDecls.find(D); 1170 if (I == StackElem.UsesAllocatorsDecls.end()) 1171 return std::nullopt; 1172 return I->getSecond(); 1173 } 1174 1175 void addDeclareMapperVarRef(Expr *Ref) { 1176 SharingMapTy &StackElem = getTopOfStack(); 1177 StackElem.DeclareMapperVar = Ref; 1178 } 1179 const Expr *getDeclareMapperVarRef() const { 1180 const SharingMapTy *Top = getTopOfStackOrNull(); 1181 return Top ? Top->DeclareMapperVar : nullptr; 1182 } 1183 1184 /// Add a new iterator variable. 1185 void addIteratorVarDecl(VarDecl *VD) { 1186 SharingMapTy &StackElem = getTopOfStack(); 1187 StackElem.IteratorVarDecls.push_back(VD->getCanonicalDecl()); 1188 } 1189 /// Check if variable declaration is an iterator VarDecl. 1190 bool isIteratorVarDecl(const VarDecl *VD) const { 1191 const SharingMapTy *Top = getTopOfStackOrNull(); 1192 if (!Top) 1193 return false; 1194 1195 return llvm::is_contained(Top->IteratorVarDecls, VD->getCanonicalDecl()); 1196 } 1197 /// get captured field from ImplicitDefaultFirstprivateFDs 1198 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const { 1199 const_iterator I = begin(); 1200 const_iterator EndI = end(); 1201 size_t StackLevel = getStackSize(); 1202 for (; I != EndI; ++I) { 1203 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private) 1204 break; 1205 StackLevel--; 1206 } 1207 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI)); 1208 if (I == EndI) 1209 return nullptr; 1210 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs) 1211 if (IFD.FD == FD && IFD.StackLevel == StackLevel) 1212 return IFD.VD; 1213 return nullptr; 1214 } 1215 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs 1216 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const { 1217 const_iterator I = begin(); 1218 const_iterator EndI = end(); 1219 for (; I != EndI; ++I) 1220 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private) 1221 break; 1222 if (I == EndI) 1223 return false; 1224 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs) 1225 if (IFD.VD == VD) 1226 return true; 1227 return false; 1228 } 1229 /// Store capture FD info in ImplicitDefaultFirstprivateFDs 1230 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) { 1231 iterator I = begin(); 1232 const_iterator EndI = end(); 1233 size_t StackLevel = getStackSize(); 1234 for (; I != EndI; ++I) { 1235 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) { 1236 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD); 1237 break; 1238 } 1239 StackLevel--; 1240 } 1241 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI)); 1242 } 1243 }; 1244 1245 bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) { 1246 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind); 1247 } 1248 1249 bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) { 1250 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) || 1251 DKind == OMPD_unknown; 1252 } 1253 1254 } // namespace 1255 1256 static const Expr *getExprAsWritten(const Expr *E) { 1257 if (const auto *FE = dyn_cast<FullExpr>(E)) 1258 E = FE->getSubExpr(); 1259 1260 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) 1261 E = MTE->getSubExpr(); 1262 1263 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E)) 1264 E = Binder->getSubExpr(); 1265 1266 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) 1267 E = ICE->getSubExprAsWritten(); 1268 return E->IgnoreParens(); 1269 } 1270 1271 static Expr *getExprAsWritten(Expr *E) { 1272 return const_cast<Expr *>(getExprAsWritten(const_cast<const Expr *>(E))); 1273 } 1274 1275 static const ValueDecl *getCanonicalDecl(const ValueDecl *D) { 1276 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(D)) 1277 if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit()))) 1278 D = ME->getMemberDecl(); 1279 const auto *VD = dyn_cast<VarDecl>(D); 1280 const auto *FD = dyn_cast<FieldDecl>(D); 1281 if (VD != nullptr) { 1282 VD = VD->getCanonicalDecl(); 1283 D = VD; 1284 } else { 1285 assert(FD); 1286 FD = FD->getCanonicalDecl(); 1287 D = FD; 1288 } 1289 return D; 1290 } 1291 1292 static ValueDecl *getCanonicalDecl(ValueDecl *D) { 1293 return const_cast<ValueDecl *>( 1294 getCanonicalDecl(const_cast<const ValueDecl *>(D))); 1295 } 1296 1297 DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter, 1298 ValueDecl *D) const { 1299 D = getCanonicalDecl(D); 1300 auto *VD = dyn_cast<VarDecl>(D); 1301 const auto *FD = dyn_cast<FieldDecl>(D); 1302 DSAVarData DVar; 1303 if (Iter == end()) { 1304 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 1305 // in a region but not in construct] 1306 // File-scope or namespace-scope variables referenced in called routines 1307 // in the region are shared unless they appear in a threadprivate 1308 // directive. 1309 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD)) 1310 DVar.CKind = OMPC_shared; 1311 1312 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced 1313 // in a region but not in construct] 1314 // Variables with static storage duration that are declared in called 1315 // routines in the region are shared. 1316 if (VD && VD->hasGlobalStorage()) 1317 DVar.CKind = OMPC_shared; 1318 1319 // Non-static data members are shared by default. 1320 if (FD) 1321 DVar.CKind = OMPC_shared; 1322 1323 return DVar; 1324 } 1325 1326 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 1327 // in a Construct, C/C++, predetermined, p.1] 1328 // Variables with automatic storage duration that are declared in a scope 1329 // inside the construct are private. 1330 if (VD && isOpenMPLocal(VD, Iter) && VD->isLocalVarDecl() && 1331 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) { 1332 DVar.CKind = OMPC_private; 1333 return DVar; 1334 } 1335 1336 DVar.DKind = Iter->Directive; 1337 // Explicitly specified attributes and local variables with predetermined 1338 // attributes. 1339 if (Iter->SharingMap.count(D)) { 1340 const DSAInfo &Data = Iter->SharingMap.lookup(D); 1341 DVar.RefExpr = Data.RefExpr.getPointer(); 1342 DVar.PrivateCopy = Data.PrivateCopy; 1343 DVar.CKind = Data.Attributes; 1344 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc; 1345 DVar.Modifier = Data.Modifier; 1346 DVar.AppliedToPointee = Data.AppliedToPointee; 1347 return DVar; 1348 } 1349 1350 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 1351 // in a Construct, C/C++, implicitly determined, p.1] 1352 // In a parallel or task construct, the data-sharing attributes of these 1353 // variables are determined by the default clause, if present. 1354 switch (Iter->DefaultAttr) { 1355 case DSA_shared: 1356 DVar.CKind = OMPC_shared; 1357 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc; 1358 return DVar; 1359 case DSA_none: 1360 return DVar; 1361 case DSA_firstprivate: 1362 if (VD && VD->getStorageDuration() == SD_Static && 1363 VD->getDeclContext()->isFileContext()) { 1364 DVar.CKind = OMPC_unknown; 1365 } else { 1366 DVar.CKind = OMPC_firstprivate; 1367 } 1368 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc; 1369 return DVar; 1370 case DSA_private: 1371 // each variable with static storage duration that is declared 1372 // in a namespace or global scope and referenced in the construct, 1373 // and that does not have a predetermined data-sharing attribute 1374 if (VD && VD->getStorageDuration() == SD_Static && 1375 VD->getDeclContext()->isFileContext()) { 1376 DVar.CKind = OMPC_unknown; 1377 } else { 1378 DVar.CKind = OMPC_private; 1379 } 1380 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc; 1381 return DVar; 1382 case DSA_unspecified: 1383 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 1384 // in a Construct, implicitly determined, p.2] 1385 // In a parallel construct, if no default clause is present, these 1386 // variables are shared. 1387 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc; 1388 if ((isOpenMPParallelDirective(DVar.DKind) && 1389 !isOpenMPTaskLoopDirective(DVar.DKind)) || 1390 isOpenMPTeamsDirective(DVar.DKind)) { 1391 DVar.CKind = OMPC_shared; 1392 return DVar; 1393 } 1394 1395 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 1396 // in a Construct, implicitly determined, p.4] 1397 // In a task construct, if no default clause is present, a variable that in 1398 // the enclosing context is determined to be shared by all implicit tasks 1399 // bound to the current team is shared. 1400 if (isOpenMPTaskingDirective(DVar.DKind)) { 1401 DSAVarData DVarTemp; 1402 const_iterator I = Iter, E = end(); 1403 do { 1404 ++I; 1405 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables 1406 // Referenced in a Construct, implicitly determined, p.6] 1407 // In a task construct, if no default clause is present, a variable 1408 // whose data-sharing attribute is not determined by the rules above is 1409 // firstprivate. 1410 DVarTemp = getDSA(I, D); 1411 if (DVarTemp.CKind != OMPC_shared) { 1412 DVar.RefExpr = nullptr; 1413 DVar.CKind = OMPC_firstprivate; 1414 return DVar; 1415 } 1416 } while (I != E && !isImplicitTaskingRegion(I->Directive)); 1417 DVar.CKind = 1418 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared; 1419 return DVar; 1420 } 1421 } 1422 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 1423 // in a Construct, implicitly determined, p.3] 1424 // For constructs other than task, if no default clause is present, these 1425 // variables inherit their data-sharing attributes from the enclosing 1426 // context. 1427 return getDSA(++Iter, D); 1428 } 1429 1430 const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D, 1431 const Expr *NewDE) { 1432 assert(!isStackEmpty() && "Data sharing attributes stack is empty"); 1433 D = getCanonicalDecl(D); 1434 SharingMapTy &StackElem = getTopOfStack(); 1435 auto It = StackElem.AlignedMap.find(D); 1436 if (It == StackElem.AlignedMap.end()) { 1437 assert(NewDE && "Unexpected nullptr expr to be added into aligned map"); 1438 StackElem.AlignedMap[D] = NewDE; 1439 return nullptr; 1440 } 1441 assert(It->second && "Unexpected nullptr expr in the aligned map"); 1442 return It->second; 1443 } 1444 1445 const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D, 1446 const Expr *NewDE) { 1447 assert(!isStackEmpty() && "Data sharing attributes stack is empty"); 1448 D = getCanonicalDecl(D); 1449 SharingMapTy &StackElem = getTopOfStack(); 1450 auto It = StackElem.NontemporalMap.find(D); 1451 if (It == StackElem.NontemporalMap.end()) { 1452 assert(NewDE && "Unexpected nullptr expr to be added into aligned map"); 1453 StackElem.NontemporalMap[D] = NewDE; 1454 return nullptr; 1455 } 1456 assert(It->second && "Unexpected nullptr expr in the aligned map"); 1457 return It->second; 1458 } 1459 1460 void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) { 1461 assert(!isStackEmpty() && "Data-sharing attributes stack is empty"); 1462 D = getCanonicalDecl(D); 1463 SharingMapTy &StackElem = getTopOfStack(); 1464 StackElem.LCVMap.try_emplace( 1465 D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture)); 1466 } 1467 1468 const DSAStackTy::LCDeclInfo 1469 DSAStackTy::isLoopControlVariable(const ValueDecl *D) const { 1470 assert(!isStackEmpty() && "Data-sharing attributes stack is empty"); 1471 D = getCanonicalDecl(D); 1472 const SharingMapTy &StackElem = getTopOfStack(); 1473 auto It = StackElem.LCVMap.find(D); 1474 if (It != StackElem.LCVMap.end()) 1475 return It->second; 1476 return {0, nullptr}; 1477 } 1478 1479 const DSAStackTy::LCDeclInfo 1480 DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const { 1481 assert(!isStackEmpty() && "Data-sharing attributes stack is empty"); 1482 D = getCanonicalDecl(D); 1483 for (unsigned I = Level + 1; I > 0; --I) { 1484 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1); 1485 auto It = StackElem.LCVMap.find(D); 1486 if (It != StackElem.LCVMap.end()) 1487 return It->second; 1488 } 1489 return {0, nullptr}; 1490 } 1491 1492 const DSAStackTy::LCDeclInfo 1493 DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const { 1494 const SharingMapTy *Parent = getSecondOnStackOrNull(); 1495 assert(Parent && "Data-sharing attributes stack is empty"); 1496 D = getCanonicalDecl(D); 1497 auto It = Parent->LCVMap.find(D); 1498 if (It != Parent->LCVMap.end()) 1499 return It->second; 1500 return {0, nullptr}; 1501 } 1502 1503 const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const { 1504 const SharingMapTy *Parent = getSecondOnStackOrNull(); 1505 assert(Parent && "Data-sharing attributes stack is empty"); 1506 if (Parent->LCVMap.size() < I) 1507 return nullptr; 1508 for (const auto &Pair : Parent->LCVMap) 1509 if (Pair.second.first == I) 1510 return Pair.first; 1511 return nullptr; 1512 } 1513 1514 void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A, 1515 DeclRefExpr *PrivateCopy, unsigned Modifier, 1516 bool AppliedToPointee) { 1517 D = getCanonicalDecl(D); 1518 if (A == OMPC_threadprivate) { 1519 DSAInfo &Data = Threadprivates[D]; 1520 Data.Attributes = A; 1521 Data.RefExpr.setPointer(E); 1522 Data.PrivateCopy = nullptr; 1523 Data.Modifier = Modifier; 1524 } else { 1525 DSAInfo &Data = getTopOfStack().SharingMap[D]; 1526 assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) || 1527 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) || 1528 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) || 1529 (isLoopControlVariable(D).first && A == OMPC_private)); 1530 Data.Modifier = Modifier; 1531 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) { 1532 Data.RefExpr.setInt(/*IntVal=*/true); 1533 return; 1534 } 1535 const bool IsLastprivate = 1536 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate; 1537 Data.Attributes = A; 1538 Data.RefExpr.setPointerAndInt(E, IsLastprivate); 1539 Data.PrivateCopy = PrivateCopy; 1540 Data.AppliedToPointee = AppliedToPointee; 1541 if (PrivateCopy) { 1542 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()]; 1543 Data.Modifier = Modifier; 1544 Data.Attributes = A; 1545 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate); 1546 Data.PrivateCopy = nullptr; 1547 Data.AppliedToPointee = AppliedToPointee; 1548 } 1549 } 1550 } 1551 1552 /// Build a variable declaration for OpenMP loop iteration variable. 1553 static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type, 1554 StringRef Name, const AttrVec *Attrs = nullptr, 1555 DeclRefExpr *OrigRef = nullptr) { 1556 DeclContext *DC = SemaRef.CurContext; 1557 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name); 1558 TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc); 1559 auto *Decl = 1560 VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None); 1561 if (Attrs) { 1562 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end()); 1563 I != E; ++I) 1564 Decl->addAttr(*I); 1565 } 1566 Decl->setImplicit(); 1567 if (OrigRef) { 1568 Decl->addAttr( 1569 OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef)); 1570 } 1571 return Decl; 1572 } 1573 1574 static DeclRefExpr *buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty, 1575 SourceLocation Loc, 1576 bool RefersToCapture = false) { 1577 D->setReferenced(); 1578 D->markUsed(S.Context); 1579 return DeclRefExpr::Create(S.getASTContext(), NestedNameSpecifierLoc(), 1580 SourceLocation(), D, RefersToCapture, Loc, Ty, 1581 VK_LValue); 1582 } 1583 1584 void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR, 1585 BinaryOperatorKind BOK) { 1586 D = getCanonicalDecl(D); 1587 assert(!isStackEmpty() && "Data-sharing attributes stack is empty"); 1588 assert( 1589 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction && 1590 "Additional reduction info may be specified only for reduction items."); 1591 ReductionData &ReductionData = getTopOfStack().ReductionMap[D]; 1592 assert(ReductionData.ReductionRange.isInvalid() && 1593 (getTopOfStack().Directive == OMPD_taskgroup || 1594 ((isOpenMPParallelDirective(getTopOfStack().Directive) || 1595 isOpenMPWorksharingDirective(getTopOfStack().Directive)) && 1596 !isOpenMPSimdDirective(getTopOfStack().Directive))) && 1597 "Additional reduction info may be specified only once for reduction " 1598 "items."); 1599 ReductionData.set(BOK, SR); 1600 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef; 1601 if (!TaskgroupReductionRef) { 1602 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(), 1603 SemaRef.Context.VoidPtrTy, ".task_red."); 1604 TaskgroupReductionRef = 1605 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin()); 1606 } 1607 } 1608 1609 void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR, 1610 const Expr *ReductionRef) { 1611 D = getCanonicalDecl(D); 1612 assert(!isStackEmpty() && "Data-sharing attributes stack is empty"); 1613 assert( 1614 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction && 1615 "Additional reduction info may be specified only for reduction items."); 1616 ReductionData &ReductionData = getTopOfStack().ReductionMap[D]; 1617 assert(ReductionData.ReductionRange.isInvalid() && 1618 (getTopOfStack().Directive == OMPD_taskgroup || 1619 ((isOpenMPParallelDirective(getTopOfStack().Directive) || 1620 isOpenMPWorksharingDirective(getTopOfStack().Directive)) && 1621 !isOpenMPSimdDirective(getTopOfStack().Directive))) && 1622 "Additional reduction info may be specified only once for reduction " 1623 "items."); 1624 ReductionData.set(ReductionRef, SR); 1625 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef; 1626 if (!TaskgroupReductionRef) { 1627 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(), 1628 SemaRef.Context.VoidPtrTy, ".task_red."); 1629 TaskgroupReductionRef = 1630 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin()); 1631 } 1632 } 1633 1634 const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData( 1635 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK, 1636 Expr *&TaskgroupDescriptor) const { 1637 D = getCanonicalDecl(D); 1638 assert(!isStackEmpty() && "Data-sharing attributes stack is empty."); 1639 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) { 1640 const DSAInfo &Data = I->SharingMap.lookup(D); 1641 if (Data.Attributes != OMPC_reduction || 1642 Data.Modifier != OMPC_REDUCTION_task) 1643 continue; 1644 const ReductionData &ReductionData = I->ReductionMap.lookup(D); 1645 if (!ReductionData.ReductionOp || 1646 ReductionData.ReductionOp.is<const Expr *>()) 1647 return DSAVarData(); 1648 SR = ReductionData.ReductionRange; 1649 BOK = ReductionData.ReductionOp.get<ReductionData::BOKPtrType>(); 1650 assert(I->TaskgroupReductionRef && "taskgroup reduction reference " 1651 "expression for the descriptor is not " 1652 "set."); 1653 TaskgroupDescriptor = I->TaskgroupReductionRef; 1654 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(), 1655 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task, 1656 /*AppliedToPointee=*/false); 1657 } 1658 return DSAVarData(); 1659 } 1660 1661 const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData( 1662 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef, 1663 Expr *&TaskgroupDescriptor) const { 1664 D = getCanonicalDecl(D); 1665 assert(!isStackEmpty() && "Data-sharing attributes stack is empty."); 1666 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) { 1667 const DSAInfo &Data = I->SharingMap.lookup(D); 1668 if (Data.Attributes != OMPC_reduction || 1669 Data.Modifier != OMPC_REDUCTION_task) 1670 continue; 1671 const ReductionData &ReductionData = I->ReductionMap.lookup(D); 1672 if (!ReductionData.ReductionOp || 1673 !ReductionData.ReductionOp.is<const Expr *>()) 1674 return DSAVarData(); 1675 SR = ReductionData.ReductionRange; 1676 ReductionRef = ReductionData.ReductionOp.get<const Expr *>(); 1677 assert(I->TaskgroupReductionRef && "taskgroup reduction reference " 1678 "expression for the descriptor is not " 1679 "set."); 1680 TaskgroupDescriptor = I->TaskgroupReductionRef; 1681 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(), 1682 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task, 1683 /*AppliedToPointee=*/false); 1684 } 1685 return DSAVarData(); 1686 } 1687 1688 bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const { 1689 D = D->getCanonicalDecl(); 1690 for (const_iterator E = end(); I != E; ++I) { 1691 if (isImplicitOrExplicitTaskingRegion(I->Directive) || 1692 isOpenMPTargetExecutionDirective(I->Directive)) { 1693 if (I->CurScope) { 1694 Scope *TopScope = I->CurScope->getParent(); 1695 Scope *CurScope = getCurScope(); 1696 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D)) 1697 CurScope = CurScope->getParent(); 1698 return CurScope != TopScope; 1699 } 1700 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent()) 1701 if (I->Context == DC) 1702 return true; 1703 return false; 1704 } 1705 } 1706 return false; 1707 } 1708 1709 static bool isConstNotMutableType(Sema &SemaRef, QualType Type, 1710 bool AcceptIfMutable = true, 1711 bool *IsClassType = nullptr) { 1712 ASTContext &Context = SemaRef.getASTContext(); 1713 Type = Type.getNonReferenceType().getCanonicalType(); 1714 bool IsConstant = Type.isConstant(Context); 1715 Type = Context.getBaseElementType(Type); 1716 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus 1717 ? Type->getAsCXXRecordDecl() 1718 : nullptr; 1719 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD)) 1720 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate()) 1721 RD = CTD->getTemplatedDecl(); 1722 if (IsClassType) 1723 *IsClassType = RD; 1724 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD && 1725 RD->hasDefinition() && RD->hasMutableFields()); 1726 } 1727 1728 static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D, 1729 QualType Type, OpenMPClauseKind CKind, 1730 SourceLocation ELoc, 1731 bool AcceptIfMutable = true, 1732 bool ListItemNotVar = false) { 1733 ASTContext &Context = SemaRef.getASTContext(); 1734 bool IsClassType; 1735 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, &IsClassType)) { 1736 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item 1737 : IsClassType ? diag::err_omp_const_not_mutable_variable 1738 : diag::err_omp_const_variable; 1739 SemaRef.Diag(ELoc, Diag) << getOpenMPClauseName(CKind); 1740 if (!ListItemNotVar && D) { 1741 const VarDecl *VD = dyn_cast<VarDecl>(D); 1742 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) == 1743 VarDecl::DeclarationOnly; 1744 SemaRef.Diag(D->getLocation(), 1745 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 1746 << D; 1747 } 1748 return true; 1749 } 1750 return false; 1751 } 1752 1753 const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, 1754 bool FromParent) { 1755 D = getCanonicalDecl(D); 1756 DSAVarData DVar; 1757 1758 auto *VD = dyn_cast<VarDecl>(D); 1759 auto TI = Threadprivates.find(D); 1760 if (TI != Threadprivates.end()) { 1761 DVar.RefExpr = TI->getSecond().RefExpr.getPointer(); 1762 DVar.CKind = OMPC_threadprivate; 1763 DVar.Modifier = TI->getSecond().Modifier; 1764 return DVar; 1765 } 1766 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) { 1767 DVar.RefExpr = buildDeclRefExpr( 1768 SemaRef, VD, D->getType().getNonReferenceType(), 1769 VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation()); 1770 DVar.CKind = OMPC_threadprivate; 1771 addDSA(D, DVar.RefExpr, OMPC_threadprivate); 1772 return DVar; 1773 } 1774 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 1775 // in a Construct, C/C++, predetermined, p.1] 1776 // Variables appearing in threadprivate directives are threadprivate. 1777 if ((VD && VD->getTLSKind() != VarDecl::TLS_None && 1778 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() && 1779 SemaRef.getLangOpts().OpenMPUseTLS && 1780 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) || 1781 (VD && VD->getStorageClass() == SC_Register && 1782 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) { 1783 DVar.RefExpr = buildDeclRefExpr( 1784 SemaRef, VD, D->getType().getNonReferenceType(), D->getLocation()); 1785 DVar.CKind = OMPC_threadprivate; 1786 addDSA(D, DVar.RefExpr, OMPC_threadprivate); 1787 return DVar; 1788 } 1789 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD && 1790 VD->isLocalVarDeclOrParm() && !isStackEmpty() && 1791 !isLoopControlVariable(D).first) { 1792 const_iterator IterTarget = 1793 std::find_if(begin(), end(), [](const SharingMapTy &Data) { 1794 return isOpenMPTargetExecutionDirective(Data.Directive); 1795 }); 1796 if (IterTarget != end()) { 1797 const_iterator ParentIterTarget = IterTarget + 1; 1798 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) { 1799 if (isOpenMPLocal(VD, Iter)) { 1800 DVar.RefExpr = 1801 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(), 1802 D->getLocation()); 1803 DVar.CKind = OMPC_threadprivate; 1804 return DVar; 1805 } 1806 } 1807 if (!isClauseParsingMode() || IterTarget != begin()) { 1808 auto DSAIter = IterTarget->SharingMap.find(D); 1809 if (DSAIter != IterTarget->SharingMap.end() && 1810 isOpenMPPrivate(DSAIter->getSecond().Attributes)) { 1811 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer(); 1812 DVar.CKind = OMPC_threadprivate; 1813 return DVar; 1814 } 1815 const_iterator End = end(); 1816 if (!SemaRef.OpenMP().isOpenMPCapturedByRef( 1817 D, std::distance(ParentIterTarget, End), 1818 /*OpenMPCaptureLevel=*/0)) { 1819 DVar.RefExpr = 1820 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(), 1821 IterTarget->ConstructLoc); 1822 DVar.CKind = OMPC_threadprivate; 1823 return DVar; 1824 } 1825 } 1826 } 1827 } 1828 1829 if (isStackEmpty()) 1830 // Not in OpenMP execution region and top scope was already checked. 1831 return DVar; 1832 1833 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 1834 // in a Construct, C/C++, predetermined, p.4] 1835 // Static data members are shared. 1836 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 1837 // in a Construct, C/C++, predetermined, p.7] 1838 // Variables with static storage duration that are declared in a scope 1839 // inside the construct are shared. 1840 if (VD && VD->isStaticDataMember()) { 1841 // Check for explicitly specified attributes. 1842 const_iterator I = begin(); 1843 const_iterator EndI = end(); 1844 if (FromParent && I != EndI) 1845 ++I; 1846 if (I != EndI) { 1847 auto It = I->SharingMap.find(D); 1848 if (It != I->SharingMap.end()) { 1849 const DSAInfo &Data = It->getSecond(); 1850 DVar.RefExpr = Data.RefExpr.getPointer(); 1851 DVar.PrivateCopy = Data.PrivateCopy; 1852 DVar.CKind = Data.Attributes; 1853 DVar.ImplicitDSALoc = I->DefaultAttrLoc; 1854 DVar.DKind = I->Directive; 1855 DVar.Modifier = Data.Modifier; 1856 DVar.AppliedToPointee = Data.AppliedToPointee; 1857 return DVar; 1858 } 1859 } 1860 1861 DVar.CKind = OMPC_shared; 1862 return DVar; 1863 } 1864 1865 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; }; 1866 // The predetermined shared attribute for const-qualified types having no 1867 // mutable members was removed after OpenMP 3.1. 1868 if (SemaRef.LangOpts.OpenMP <= 31) { 1869 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 1870 // in a Construct, C/C++, predetermined, p.6] 1871 // Variables with const qualified type having no mutable member are 1872 // shared. 1873 if (isConstNotMutableType(SemaRef, D->getType())) { 1874 // Variables with const-qualified type having no mutable member may be 1875 // listed in a firstprivate clause, even if they are static data members. 1876 DSAVarData DVarTemp = hasInnermostDSA( 1877 D, 1878 [](OpenMPClauseKind C, bool) { 1879 return C == OMPC_firstprivate || C == OMPC_shared; 1880 }, 1881 MatchesAlways, FromParent); 1882 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr) 1883 return DVarTemp; 1884 1885 DVar.CKind = OMPC_shared; 1886 return DVar; 1887 } 1888 } 1889 1890 // Explicitly specified attributes and local variables with predetermined 1891 // attributes. 1892 const_iterator I = begin(); 1893 const_iterator EndI = end(); 1894 if (FromParent && I != EndI) 1895 ++I; 1896 if (I == EndI) 1897 return DVar; 1898 auto It = I->SharingMap.find(D); 1899 if (It != I->SharingMap.end()) { 1900 const DSAInfo &Data = It->getSecond(); 1901 DVar.RefExpr = Data.RefExpr.getPointer(); 1902 DVar.PrivateCopy = Data.PrivateCopy; 1903 DVar.CKind = Data.Attributes; 1904 DVar.ImplicitDSALoc = I->DefaultAttrLoc; 1905 DVar.DKind = I->Directive; 1906 DVar.Modifier = Data.Modifier; 1907 DVar.AppliedToPointee = Data.AppliedToPointee; 1908 } 1909 1910 return DVar; 1911 } 1912 1913 const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D, 1914 bool FromParent) const { 1915 if (isStackEmpty()) { 1916 const_iterator I; 1917 return getDSA(I, D); 1918 } 1919 D = getCanonicalDecl(D); 1920 const_iterator StartI = begin(); 1921 const_iterator EndI = end(); 1922 if (FromParent && StartI != EndI) 1923 ++StartI; 1924 return getDSA(StartI, D); 1925 } 1926 1927 const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D, 1928 unsigned Level) const { 1929 if (getStackSize() <= Level) 1930 return DSAVarData(); 1931 D = getCanonicalDecl(D); 1932 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level); 1933 return getDSA(StartI, D); 1934 } 1935 1936 const DSAStackTy::DSAVarData 1937 DSAStackTy::hasDSA(ValueDecl *D, 1938 const llvm::function_ref<bool(OpenMPClauseKind, bool, 1939 DefaultDataSharingAttributes)> 1940 CPred, 1941 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred, 1942 bool FromParent) const { 1943 if (isStackEmpty()) 1944 return {}; 1945 D = getCanonicalDecl(D); 1946 const_iterator I = begin(); 1947 const_iterator EndI = end(); 1948 if (FromParent && I != EndI) 1949 ++I; 1950 for (; I != EndI; ++I) { 1951 if (!DPred(I->Directive) && 1952 !isImplicitOrExplicitTaskingRegion(I->Directive)) 1953 continue; 1954 const_iterator NewI = I; 1955 DSAVarData DVar = getDSA(NewI, D); 1956 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr)) 1957 return DVar; 1958 } 1959 return {}; 1960 } 1961 1962 const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA( 1963 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred, 1964 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred, 1965 bool FromParent) const { 1966 if (isStackEmpty()) 1967 return {}; 1968 D = getCanonicalDecl(D); 1969 const_iterator StartI = begin(); 1970 const_iterator EndI = end(); 1971 if (FromParent && StartI != EndI) 1972 ++StartI; 1973 if (StartI == EndI || !DPred(StartI->Directive)) 1974 return {}; 1975 const_iterator NewI = StartI; 1976 DSAVarData DVar = getDSA(NewI, D); 1977 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee)) 1978 ? DVar 1979 : DSAVarData(); 1980 } 1981 1982 bool DSAStackTy::hasExplicitDSA( 1983 const ValueDecl *D, 1984 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred, 1985 unsigned Level, bool NotLastprivate) const { 1986 if (getStackSize() <= Level) 1987 return false; 1988 D = getCanonicalDecl(D); 1989 const SharingMapTy &StackElem = getStackElemAtLevel(Level); 1990 auto I = StackElem.SharingMap.find(D); 1991 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() && 1992 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) && 1993 (!NotLastprivate || !I->getSecond().RefExpr.getInt())) 1994 return true; 1995 // Check predetermined rules for the loop control variables. 1996 auto LI = StackElem.LCVMap.find(D); 1997 if (LI != StackElem.LCVMap.end()) 1998 return CPred(OMPC_private, /*AppliedToPointee=*/false); 1999 return false; 2000 } 2001 2002 bool DSAStackTy::hasExplicitDirective( 2003 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred, 2004 unsigned Level) const { 2005 if (getStackSize() <= Level) 2006 return false; 2007 const SharingMapTy &StackElem = getStackElemAtLevel(Level); 2008 return DPred(StackElem.Directive); 2009 } 2010 2011 bool DSAStackTy::hasDirective( 2012 const llvm::function_ref<bool(OpenMPDirectiveKind, 2013 const DeclarationNameInfo &, SourceLocation)> 2014 DPred, 2015 bool FromParent) const { 2016 // We look only in the enclosing region. 2017 size_t Skip = FromParent ? 2 : 1; 2018 for (const_iterator I = begin() + std::min(Skip, getStackSize()), E = end(); 2019 I != E; ++I) { 2020 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc)) 2021 return true; 2022 } 2023 return false; 2024 } 2025 2026 void SemaOpenMP::InitDataSharingAttributesStack() { 2027 VarDataSharingAttributesStack = new DSAStackTy(SemaRef); 2028 } 2029 2030 #define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack) 2031 2032 void SemaOpenMP::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); } 2033 2034 void SemaOpenMP::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) { 2035 DSAStack->popFunction(OldFSI); 2036 } 2037 2038 static bool isOpenMPDeviceDelayedContext(Sema &S) { 2039 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsTargetDevice && 2040 "Expected OpenMP device compilation."); 2041 return !S.OpenMP().isInOpenMPTargetExecutionDirective(); 2042 } 2043 2044 namespace { 2045 /// Status of the function emission on the host/device. 2046 enum class FunctionEmissionStatus { 2047 Emitted, 2048 Discarded, 2049 Unknown, 2050 }; 2051 } // anonymous namespace 2052 2053 SemaBase::SemaDiagnosticBuilder 2054 SemaOpenMP::diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID, 2055 const FunctionDecl *FD) { 2056 assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice && 2057 "Expected OpenMP device compilation."); 2058 2059 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop; 2060 if (FD) { 2061 Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(FD); 2062 switch (FES) { 2063 case Sema::FunctionEmissionStatus::Emitted: 2064 Kind = SemaDiagnosticBuilder::K_Immediate; 2065 break; 2066 case Sema::FunctionEmissionStatus::Unknown: 2067 // TODO: We should always delay diagnostics here in case a target 2068 // region is in a function we do not emit. However, as the 2069 // current diagnostics are associated with the function containing 2070 // the target region and we do not emit that one, we would miss out 2071 // on diagnostics for the target region itself. We need to anchor 2072 // the diagnostics with the new generated function *or* ensure we 2073 // emit diagnostics associated with the surrounding function. 2074 Kind = isOpenMPDeviceDelayedContext(SemaRef) 2075 ? SemaDiagnosticBuilder::K_Deferred 2076 : SemaDiagnosticBuilder::K_Immediate; 2077 break; 2078 case Sema::FunctionEmissionStatus::TemplateDiscarded: 2079 case Sema::FunctionEmissionStatus::OMPDiscarded: 2080 Kind = SemaDiagnosticBuilder::K_Nop; 2081 break; 2082 case Sema::FunctionEmissionStatus::CUDADiscarded: 2083 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation"); 2084 break; 2085 } 2086 } 2087 2088 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef); 2089 } 2090 2091 SemaBase::SemaDiagnosticBuilder 2092 SemaOpenMP::diagIfOpenMPHostCode(SourceLocation Loc, unsigned DiagID, 2093 const FunctionDecl *FD) { 2094 assert(getLangOpts().OpenMP && !getLangOpts().OpenMPIsTargetDevice && 2095 "Expected OpenMP host compilation."); 2096 2097 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop; 2098 if (FD) { 2099 Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(FD); 2100 switch (FES) { 2101 case Sema::FunctionEmissionStatus::Emitted: 2102 Kind = SemaDiagnosticBuilder::K_Immediate; 2103 break; 2104 case Sema::FunctionEmissionStatus::Unknown: 2105 Kind = SemaDiagnosticBuilder::K_Deferred; 2106 break; 2107 case Sema::FunctionEmissionStatus::TemplateDiscarded: 2108 case Sema::FunctionEmissionStatus::OMPDiscarded: 2109 case Sema::FunctionEmissionStatus::CUDADiscarded: 2110 Kind = SemaDiagnosticBuilder::K_Nop; 2111 break; 2112 } 2113 } 2114 2115 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef); 2116 } 2117 2118 static OpenMPDefaultmapClauseKind 2119 getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD) { 2120 if (LO.OpenMP <= 45) { 2121 if (VD->getType().getNonReferenceType()->isScalarType()) 2122 return OMPC_DEFAULTMAP_scalar; 2123 return OMPC_DEFAULTMAP_aggregate; 2124 } 2125 if (VD->getType().getNonReferenceType()->isAnyPointerType()) 2126 return OMPC_DEFAULTMAP_pointer; 2127 if (VD->getType().getNonReferenceType()->isScalarType()) 2128 return OMPC_DEFAULTMAP_scalar; 2129 return OMPC_DEFAULTMAP_aggregate; 2130 } 2131 2132 bool SemaOpenMP::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, 2133 unsigned OpenMPCaptureLevel) const { 2134 assert(getLangOpts().OpenMP && "OpenMP is not allowed"); 2135 2136 ASTContext &Ctx = getASTContext(); 2137 bool IsByRef = true; 2138 2139 // Find the directive that is associated with the provided scope. 2140 D = cast<ValueDecl>(D->getCanonicalDecl()); 2141 QualType Ty = D->getType(); 2142 2143 bool IsVariableUsedInMapClause = false; 2144 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) { 2145 // This table summarizes how a given variable should be passed to the device 2146 // given its type and the clauses where it appears. This table is based on 2147 // the description in OpenMP 4.5 [2.10.4, target Construct] and 2148 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses]. 2149 // 2150 // ========================================================================= 2151 // | type | defaultmap | pvt | first | is_device_ptr | map | res. | 2152 // | |(tofrom:scalar)| | pvt | |has_dv_adr| | 2153 // ========================================================================= 2154 // | scl | | | | - | | bycopy| 2155 // | scl | | - | x | - | - | bycopy| 2156 // | scl | | x | - | - | - | null | 2157 // | scl | x | | | - | | byref | 2158 // | scl | x | - | x | - | - | bycopy| 2159 // | scl | x | x | - | - | - | null | 2160 // | scl | | - | - | - | x | byref | 2161 // | scl | x | - | - | - | x | byref | 2162 // 2163 // | agg | n.a. | | | - | | byref | 2164 // | agg | n.a. | - | x | - | - | byref | 2165 // | agg | n.a. | x | - | - | - | null | 2166 // | agg | n.a. | - | - | - | x | byref | 2167 // | agg | n.a. | - | - | - | x[] | byref | 2168 // 2169 // | ptr | n.a. | | | - | | bycopy| 2170 // | ptr | n.a. | - | x | - | - | bycopy| 2171 // | ptr | n.a. | x | - | - | - | null | 2172 // | ptr | n.a. | - | - | - | x | byref | 2173 // | ptr | n.a. | - | - | - | x[] | bycopy| 2174 // | ptr | n.a. | - | - | x | | bycopy| 2175 // | ptr | n.a. | - | - | x | x | bycopy| 2176 // | ptr | n.a. | - | - | x | x[] | bycopy| 2177 // ========================================================================= 2178 // Legend: 2179 // scl - scalar 2180 // ptr - pointer 2181 // agg - aggregate 2182 // x - applies 2183 // - - invalid in this combination 2184 // [] - mapped with an array section 2185 // byref - should be mapped by reference 2186 // byval - should be mapped by value 2187 // null - initialize a local variable to null on the device 2188 // 2189 // Observations: 2190 // - All scalar declarations that show up in a map clause have to be passed 2191 // by reference, because they may have been mapped in the enclosing data 2192 // environment. 2193 // - If the scalar value does not fit the size of uintptr, it has to be 2194 // passed by reference, regardless the result in the table above. 2195 // - For pointers mapped by value that have either an implicit map or an 2196 // array section, the runtime library may pass the NULL value to the 2197 // device instead of the value passed to it by the compiler. 2198 2199 if (Ty->isReferenceType()) 2200 Ty = Ty->castAs<ReferenceType>()->getPointeeType(); 2201 2202 // Locate map clauses and see if the variable being captured is referred to 2203 // in any of those clauses. Here we only care about variables, not fields, 2204 // because fields are part of aggregates. 2205 bool IsVariableAssociatedWithSection = false; 2206 2207 DSAStack->checkMappableExprComponentListsForDeclAtLevel( 2208 D, Level, 2209 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection, 2210 D](OMPClauseMappableExprCommon::MappableExprComponentListRef 2211 MapExprComponents, 2212 OpenMPClauseKind WhereFoundClauseKind) { 2213 // Both map and has_device_addr clauses information influences how a 2214 // variable is captured. E.g. is_device_ptr does not require changing 2215 // the default behavior. 2216 if (WhereFoundClauseKind != OMPC_map && 2217 WhereFoundClauseKind != OMPC_has_device_addr) 2218 return false; 2219 2220 auto EI = MapExprComponents.rbegin(); 2221 auto EE = MapExprComponents.rend(); 2222 2223 assert(EI != EE && "Invalid map expression!"); 2224 2225 if (isa<DeclRefExpr>(EI->getAssociatedExpression())) 2226 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D; 2227 2228 ++EI; 2229 if (EI == EE) 2230 return false; 2231 auto Last = std::prev(EE); 2232 const auto *UO = 2233 dyn_cast<UnaryOperator>(Last->getAssociatedExpression()); 2234 if ((UO && UO->getOpcode() == UO_Deref) || 2235 isa<ArraySubscriptExpr>(Last->getAssociatedExpression()) || 2236 isa<ArraySectionExpr>(Last->getAssociatedExpression()) || 2237 isa<MemberExpr>(EI->getAssociatedExpression()) || 2238 isa<OMPArrayShapingExpr>(Last->getAssociatedExpression())) { 2239 IsVariableAssociatedWithSection = true; 2240 // There is nothing more we need to know about this variable. 2241 return true; 2242 } 2243 2244 // Keep looking for more map info. 2245 return false; 2246 }); 2247 2248 if (IsVariableUsedInMapClause) { 2249 // If variable is identified in a map clause it is always captured by 2250 // reference except if it is a pointer that is dereferenced somehow. 2251 IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection); 2252 } else { 2253 // By default, all the data that has a scalar type is mapped by copy 2254 // (except for reduction variables). 2255 // Defaultmap scalar is mutual exclusive to defaultmap pointer 2256 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() && 2257 !Ty->isAnyPointerType()) || 2258 !Ty->isScalarType() || 2259 DSAStack->isDefaultmapCapturedByRef( 2260 Level, getVariableCategoryFromDecl(getLangOpts(), D)) || 2261 DSAStack->hasExplicitDSA( 2262 D, 2263 [](OpenMPClauseKind K, bool AppliedToPointee) { 2264 return K == OMPC_reduction && !AppliedToPointee; 2265 }, 2266 Level); 2267 } 2268 } 2269 2270 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) { 2271 IsByRef = 2272 ((IsVariableUsedInMapClause && 2273 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) == 2274 OMPD_target) || 2275 !(DSAStack->hasExplicitDSA( 2276 D, 2277 [](OpenMPClauseKind K, bool AppliedToPointee) -> bool { 2278 return K == OMPC_firstprivate || 2279 (K == OMPC_reduction && AppliedToPointee); 2280 }, 2281 Level, /*NotLastprivate=*/true) || 2282 DSAStack->isUsesAllocatorsDecl(Level, D))) && 2283 // If the variable is artificial and must be captured by value - try to 2284 // capture by value. 2285 !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() && 2286 !cast<OMPCapturedExprDecl>(D)->getInit()->isGLValue()) && 2287 // If the variable is implicitly firstprivate and scalar - capture by 2288 // copy 2289 !((DSAStack->getDefaultDSA() == DSA_firstprivate || 2290 DSAStack->getDefaultDSA() == DSA_private) && 2291 !DSAStack->hasExplicitDSA( 2292 D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; }, 2293 Level) && 2294 !DSAStack->isLoopControlVariable(D, Level).first); 2295 } 2296 2297 // When passing data by copy, we need to make sure it fits the uintptr size 2298 // and alignment, because the runtime library only deals with uintptr types. 2299 // If it does not fit the uintptr size, we need to pass the data by reference 2300 // instead. 2301 if (!IsByRef && (Ctx.getTypeSizeInChars(Ty) > 2302 Ctx.getTypeSizeInChars(Ctx.getUIntPtrType()) || 2303 Ctx.getAlignOfGlobalVarInChars(Ty, dyn_cast<VarDecl>(D)) > 2304 Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) { 2305 IsByRef = true; 2306 } 2307 2308 return IsByRef; 2309 } 2310 2311 unsigned SemaOpenMP::getOpenMPNestingLevel() const { 2312 assert(getLangOpts().OpenMP); 2313 return DSAStack->getNestingLevel(); 2314 } 2315 2316 bool SemaOpenMP::isInOpenMPTaskUntiedContext() const { 2317 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) && 2318 DSAStack->isUntiedRegion(); 2319 } 2320 2321 bool SemaOpenMP::isInOpenMPTargetExecutionDirective() const { 2322 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) && 2323 !DSAStack->isClauseParsingMode()) || 2324 DSAStack->hasDirective( 2325 [](OpenMPDirectiveKind K, const DeclarationNameInfo &, 2326 SourceLocation) -> bool { 2327 return isOpenMPTargetExecutionDirective(K); 2328 }, 2329 false); 2330 } 2331 2332 bool SemaOpenMP::isOpenMPRebuildMemberExpr(ValueDecl *D) { 2333 // Only rebuild for Field. 2334 if (!dyn_cast<FieldDecl>(D)) 2335 return false; 2336 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA( 2337 D, 2338 [](OpenMPClauseKind C, bool AppliedToPointee, 2339 DefaultDataSharingAttributes DefaultAttr) { 2340 return isOpenMPPrivate(C) && !AppliedToPointee && 2341 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private); 2342 }, 2343 [](OpenMPDirectiveKind) { return true; }, 2344 DSAStack->isClauseParsingMode()); 2345 if (DVarPrivate.CKind != OMPC_unknown) 2346 return true; 2347 return false; 2348 } 2349 2350 static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id, 2351 Expr *CaptureExpr, bool WithInit, 2352 DeclContext *CurContext, 2353 bool AsExpression); 2354 2355 VarDecl *SemaOpenMP::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo, 2356 unsigned StopAt) { 2357 assert(getLangOpts().OpenMP && "OpenMP is not allowed"); 2358 D = getCanonicalDecl(D); 2359 2360 auto *VD = dyn_cast<VarDecl>(D); 2361 // Do not capture constexpr variables. 2362 if (VD && VD->isConstexpr()) 2363 return nullptr; 2364 2365 // If we want to determine whether the variable should be captured from the 2366 // perspective of the current capturing scope, and we've already left all the 2367 // capturing scopes of the top directive on the stack, check from the 2368 // perspective of its parent directive (if any) instead. 2369 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII( 2370 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete()); 2371 2372 // If we are attempting to capture a global variable in a directive with 2373 // 'target' we return true so that this global is also mapped to the device. 2374 // 2375 if (VD && !VD->hasLocalStorage() && 2376 (SemaRef.getCurCapturedRegion() || SemaRef.getCurBlock() || 2377 SemaRef.getCurLambda())) { 2378 if (isInOpenMPTargetExecutionDirective()) { 2379 DSAStackTy::DSAVarData DVarTop = 2380 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode()); 2381 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr) 2382 return VD; 2383 // If the declaration is enclosed in a 'declare target' directive, 2384 // then it should not be captured. 2385 // 2386 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) 2387 return nullptr; 2388 CapturedRegionScopeInfo *CSI = nullptr; 2389 for (FunctionScopeInfo *FSI : llvm::drop_begin( 2390 llvm::reverse(SemaRef.FunctionScopes), 2391 CheckScopeInfo ? (SemaRef.FunctionScopes.size() - (StopAt + 1)) 2392 : 0)) { 2393 if (!isa<CapturingScopeInfo>(FSI)) 2394 return nullptr; 2395 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI)) 2396 if (RSI->CapRegionKind == CR_OpenMP) { 2397 CSI = RSI; 2398 break; 2399 } 2400 } 2401 assert(CSI && "Failed to find CapturedRegionScopeInfo"); 2402 SmallVector<OpenMPDirectiveKind, 4> Regions; 2403 getOpenMPCaptureRegions(Regions, 2404 DSAStack->getDirective(CSI->OpenMPLevel)); 2405 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task) 2406 return VD; 2407 } 2408 if (isInOpenMPDeclareTargetContext()) { 2409 // Try to mark variable as declare target if it is used in capturing 2410 // regions. 2411 if (getLangOpts().OpenMP <= 45 && 2412 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) 2413 checkDeclIsAllowedInOpenMPTarget(nullptr, VD); 2414 return nullptr; 2415 } 2416 } 2417 2418 if (CheckScopeInfo) { 2419 bool OpenMPFound = false; 2420 for (unsigned I = StopAt + 1; I > 0; --I) { 2421 FunctionScopeInfo *FSI = SemaRef.FunctionScopes[I - 1]; 2422 if (!isa<CapturingScopeInfo>(FSI)) 2423 return nullptr; 2424 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI)) 2425 if (RSI->CapRegionKind == CR_OpenMP) { 2426 OpenMPFound = true; 2427 break; 2428 } 2429 } 2430 if (!OpenMPFound) 2431 return nullptr; 2432 } 2433 2434 if (DSAStack->getCurrentDirective() != OMPD_unknown && 2435 (!DSAStack->isClauseParsingMode() || 2436 DSAStack->getParentDirective() != OMPD_unknown)) { 2437 auto &&Info = DSAStack->isLoopControlVariable(D); 2438 if (Info.first || 2439 (VD && VD->hasLocalStorage() && 2440 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) || 2441 (VD && DSAStack->isForceVarCapturing())) 2442 return VD ? VD : Info.second; 2443 DSAStackTy::DSAVarData DVarTop = 2444 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode()); 2445 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) && 2446 (!VD || VD->hasLocalStorage() || !DVarTop.AppliedToPointee)) 2447 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl()); 2448 // Threadprivate variables must not be captured. 2449 if (isOpenMPThreadPrivate(DVarTop.CKind)) 2450 return nullptr; 2451 // The variable is not private or it is the variable in the directive with 2452 // default(none) clause and not used in any clause. 2453 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA( 2454 D, 2455 [](OpenMPClauseKind C, bool AppliedToPointee, bool) { 2456 return isOpenMPPrivate(C) && !AppliedToPointee; 2457 }, 2458 [](OpenMPDirectiveKind) { return true; }, 2459 DSAStack->isClauseParsingMode()); 2460 // Global shared must not be captured. 2461 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown && 2462 ((DSAStack->getDefaultDSA() != DSA_none && 2463 DSAStack->getDefaultDSA() != DSA_private && 2464 DSAStack->getDefaultDSA() != DSA_firstprivate) || 2465 DVarTop.CKind == OMPC_shared)) 2466 return nullptr; 2467 auto *FD = dyn_cast<FieldDecl>(D); 2468 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD && 2469 !DVarPrivate.PrivateCopy) { 2470 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA( 2471 D, 2472 [](OpenMPClauseKind C, bool AppliedToPointee, 2473 DefaultDataSharingAttributes DefaultAttr) { 2474 return isOpenMPPrivate(C) && !AppliedToPointee && 2475 (DefaultAttr == DSA_firstprivate || 2476 DefaultAttr == DSA_private); 2477 }, 2478 [](OpenMPDirectiveKind) { return true; }, 2479 DSAStack->isClauseParsingMode()); 2480 if (DVarPrivate.CKind == OMPC_unknown) 2481 return nullptr; 2482 2483 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD); 2484 if (VD) 2485 return VD; 2486 if (SemaRef.getCurrentThisType().isNull()) 2487 return nullptr; 2488 Expr *ThisExpr = SemaRef.BuildCXXThisExpr(SourceLocation(), 2489 SemaRef.getCurrentThisType(), 2490 /*IsImplicit=*/true); 2491 const CXXScopeSpec CS = CXXScopeSpec(); 2492 Expr *ME = SemaRef.BuildMemberExpr( 2493 ThisExpr, /*IsArrow=*/true, SourceLocation(), 2494 NestedNameSpecifierLoc(), SourceLocation(), FD, 2495 DeclAccessPair::make(FD, FD->getAccess()), 2496 /*HadMultipleCandidates=*/false, DeclarationNameInfo(), FD->getType(), 2497 VK_LValue, OK_Ordinary); 2498 OMPCapturedExprDecl *CD = buildCaptureDecl( 2499 SemaRef, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private, 2500 SemaRef.CurContext->getParent(), /*AsExpression=*/false); 2501 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr( 2502 SemaRef, CD, CD->getType().getNonReferenceType(), SourceLocation()); 2503 VD = cast<VarDecl>(VDPrivateRefExpr->getDecl()); 2504 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD); 2505 return VD; 2506 } 2507 if (DVarPrivate.CKind != OMPC_unknown || 2508 (VD && (DSAStack->getDefaultDSA() == DSA_none || 2509 DSAStack->getDefaultDSA() == DSA_private || 2510 DSAStack->getDefaultDSA() == DSA_firstprivate))) 2511 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl()); 2512 } 2513 return nullptr; 2514 } 2515 2516 void SemaOpenMP::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex, 2517 unsigned Level) const { 2518 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level)); 2519 } 2520 2521 void SemaOpenMP::startOpenMPLoop() { 2522 assert(getLangOpts().OpenMP && "OpenMP must be enabled."); 2523 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) 2524 DSAStack->loopInit(); 2525 } 2526 2527 void SemaOpenMP::startOpenMPCXXRangeFor() { 2528 assert(getLangOpts().OpenMP && "OpenMP must be enabled."); 2529 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) { 2530 DSAStack->resetPossibleLoopCounter(); 2531 DSAStack->loopStart(); 2532 } 2533 } 2534 2535 OpenMPClauseKind SemaOpenMP::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, 2536 unsigned CapLevel) const { 2537 assert(getLangOpts().OpenMP && "OpenMP is not allowed"); 2538 if (DSAStack->getCurrentDirective() != OMPD_unknown && 2539 (!DSAStack->isClauseParsingMode() || 2540 DSAStack->getParentDirective() != OMPD_unknown)) { 2541 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA( 2542 D, 2543 [](OpenMPClauseKind C, bool AppliedToPointee, 2544 DefaultDataSharingAttributes DefaultAttr) { 2545 return isOpenMPPrivate(C) && !AppliedToPointee && 2546 DefaultAttr == DSA_private; 2547 }, 2548 [](OpenMPDirectiveKind) { return true; }, 2549 DSAStack->isClauseParsingMode()); 2550 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) && 2551 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) && 2552 !DSAStack->isLoopControlVariable(D).first) 2553 return OMPC_private; 2554 } 2555 if (DSAStack->hasExplicitDirective(isOpenMPTaskingDirective, Level)) { 2556 bool IsTriviallyCopyable = 2557 D->getType().getNonReferenceType().isTriviallyCopyableType( 2558 getASTContext()) && 2559 !D->getType() 2560 .getNonReferenceType() 2561 .getCanonicalType() 2562 ->getAsCXXRecordDecl(); 2563 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level); 2564 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 2565 getOpenMPCaptureRegions(CaptureRegions, DKind); 2566 if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) && 2567 (IsTriviallyCopyable || 2568 !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) { 2569 if (DSAStack->hasExplicitDSA( 2570 D, 2571 [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; }, 2572 Level, /*NotLastprivate=*/true)) 2573 return OMPC_firstprivate; 2574 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level); 2575 if (DVar.CKind != OMPC_shared && 2576 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) { 2577 DSAStack->addImplicitTaskFirstprivate(Level, D); 2578 return OMPC_firstprivate; 2579 } 2580 } 2581 } 2582 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) && 2583 !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) { 2584 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) { 2585 DSAStack->resetPossibleLoopCounter(D); 2586 DSAStack->loopStart(); 2587 return OMPC_private; 2588 } 2589 if ((DSAStack->getPossiblyLoopCounter() == D->getCanonicalDecl() || 2590 DSAStack->isLoopControlVariable(D).first) && 2591 !DSAStack->hasExplicitDSA( 2592 D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; }, 2593 Level) && 2594 !isOpenMPSimdDirective(DSAStack->getCurrentDirective())) 2595 return OMPC_private; 2596 } 2597 if (const auto *VD = dyn_cast<VarDecl>(D)) { 2598 if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) && 2599 DSAStack->isForceVarCapturing() && 2600 !DSAStack->hasExplicitDSA( 2601 D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; }, 2602 Level)) 2603 return OMPC_private; 2604 } 2605 // User-defined allocators are private since they must be defined in the 2606 // context of target region. 2607 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) && 2608 DSAStack->isUsesAllocatorsDecl(Level, D).value_or( 2609 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) == 2610 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator) 2611 return OMPC_private; 2612 return (DSAStack->hasExplicitDSA( 2613 D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; }, 2614 Level) || 2615 (DSAStack->isClauseParsingMode() && 2616 DSAStack->getClauseParsingMode() == OMPC_private) || 2617 // Consider taskgroup reduction descriptor variable a private 2618 // to avoid possible capture in the region. 2619 (DSAStack->hasExplicitDirective( 2620 [](OpenMPDirectiveKind K) { 2621 return K == OMPD_taskgroup || 2622 ((isOpenMPParallelDirective(K) || 2623 isOpenMPWorksharingDirective(K)) && 2624 !isOpenMPSimdDirective(K)); 2625 }, 2626 Level) && 2627 DSAStack->isTaskgroupReductionRef(D, Level))) 2628 ? OMPC_private 2629 : OMPC_unknown; 2630 } 2631 2632 void SemaOpenMP::setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D, 2633 unsigned Level) { 2634 assert(getLangOpts().OpenMP && "OpenMP is not allowed"); 2635 D = getCanonicalDecl(D); 2636 OpenMPClauseKind OMPC = OMPC_unknown; 2637 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) { 2638 const unsigned NewLevel = I - 1; 2639 if (DSAStack->hasExplicitDSA( 2640 D, 2641 [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) { 2642 if (isOpenMPPrivate(K) && !AppliedToPointee) { 2643 OMPC = K; 2644 return true; 2645 } 2646 return false; 2647 }, 2648 NewLevel)) 2649 break; 2650 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel( 2651 D, NewLevel, 2652 [](OMPClauseMappableExprCommon::MappableExprComponentListRef, 2653 OpenMPClauseKind) { return true; })) { 2654 OMPC = OMPC_map; 2655 break; 2656 } 2657 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, 2658 NewLevel)) { 2659 OMPC = OMPC_map; 2660 if (DSAStack->mustBeFirstprivateAtLevel( 2661 NewLevel, getVariableCategoryFromDecl(getLangOpts(), D))) 2662 OMPC = OMPC_firstprivate; 2663 break; 2664 } 2665 } 2666 if (OMPC != OMPC_unknown) 2667 FD->addAttr( 2668 OMPCaptureKindAttr::CreateImplicit(getASTContext(), unsigned(OMPC))); 2669 } 2670 2671 bool SemaOpenMP::isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level, 2672 unsigned CaptureLevel) const { 2673 assert(getLangOpts().OpenMP && "OpenMP is not allowed"); 2674 // Return true if the current level is no longer enclosed in a target region. 2675 2676 SmallVector<OpenMPDirectiveKind, 4> Regions; 2677 getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level)); 2678 const auto *VD = dyn_cast<VarDecl>(D); 2679 return VD && !VD->hasLocalStorage() && 2680 DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, 2681 Level) && 2682 Regions[CaptureLevel] != OMPD_task; 2683 } 2684 2685 bool SemaOpenMP::isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level, 2686 unsigned CaptureLevel) const { 2687 assert(getLangOpts().OpenMP && "OpenMP is not allowed"); 2688 // Return true if the current level is no longer enclosed in a target region. 2689 2690 if (const auto *VD = dyn_cast<VarDecl>(D)) { 2691 if (!VD->hasLocalStorage()) { 2692 if (isInOpenMPTargetExecutionDirective()) 2693 return true; 2694 DSAStackTy::DSAVarData TopDVar = 2695 DSAStack->getTopDSA(D, /*FromParent=*/false); 2696 unsigned NumLevels = 2697 getOpenMPCaptureLevels(DSAStack->getDirective(Level)); 2698 if (Level == 0) 2699 // non-file scope static variable with default(firstprivate) 2700 // should be global captured. 2701 return (NumLevels == CaptureLevel + 1 && 2702 (TopDVar.CKind != OMPC_shared || 2703 DSAStack->getDefaultDSA() == DSA_firstprivate)); 2704 do { 2705 --Level; 2706 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level); 2707 if (DVar.CKind != OMPC_shared) 2708 return true; 2709 } while (Level > 0); 2710 } 2711 } 2712 return true; 2713 } 2714 2715 void SemaOpenMP::DestroyDataSharingAttributesStack() { delete DSAStack; } 2716 2717 void SemaOpenMP::ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, 2718 OMPTraitInfo &TI) { 2719 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI)); 2720 } 2721 2722 void SemaOpenMP::ActOnOpenMPEndDeclareVariant() { 2723 assert(isInOpenMPDeclareVariantScope() && 2724 "Not in OpenMP declare variant scope!"); 2725 2726 OMPDeclareVariantScopes.pop_back(); 2727 } 2728 2729 void SemaOpenMP::finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, 2730 const FunctionDecl *Callee, 2731 SourceLocation Loc) { 2732 assert(getLangOpts().OpenMP && "Expected OpenMP compilation mode."); 2733 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 2734 OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl()); 2735 // Ignore host functions during device analysis. 2736 if (getLangOpts().OpenMPIsTargetDevice && 2737 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)) 2738 return; 2739 // Ignore nohost functions during host analysis. 2740 if (!getLangOpts().OpenMPIsTargetDevice && DevTy && 2741 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) 2742 return; 2743 const FunctionDecl *FD = Callee->getMostRecentDecl(); 2744 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD); 2745 if (getLangOpts().OpenMPIsTargetDevice && DevTy && 2746 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) { 2747 // Diagnose host function called during device codegen. 2748 StringRef HostDevTy = 2749 getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host); 2750 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0; 2751 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD), 2752 diag::note_omp_marked_device_type_here) 2753 << HostDevTy; 2754 return; 2755 } 2756 if (!getLangOpts().OpenMPIsTargetDevice && 2757 !getLangOpts().OpenMPOffloadMandatory && DevTy && 2758 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) { 2759 // In OpenMP 5.2 or later, if the function has a host variant then allow 2760 // that to be called instead 2761 auto &&HasHostAttr = [](const FunctionDecl *Callee) { 2762 for (OMPDeclareVariantAttr *A : 2763 Callee->specific_attrs<OMPDeclareVariantAttr>()) { 2764 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef()); 2765 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl()); 2766 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 2767 OMPDeclareTargetDeclAttr::getDeviceType( 2768 VariantFD->getMostRecentDecl()); 2769 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host) 2770 return true; 2771 } 2772 return false; 2773 }; 2774 if (getLangOpts().OpenMP >= 52 && 2775 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee)) 2776 return; 2777 // Diagnose nohost function called during host codegen. 2778 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName( 2779 OMPC_device_type, OMPC_DEVICE_TYPE_nohost); 2780 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1; 2781 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD), 2782 diag::note_omp_marked_device_type_here) 2783 << NoHostDevTy; 2784 } 2785 } 2786 2787 void SemaOpenMP::StartOpenMPDSABlock(OpenMPDirectiveKind DKind, 2788 const DeclarationNameInfo &DirName, 2789 Scope *CurScope, SourceLocation Loc) { 2790 DSAStack->push(DKind, DirName, CurScope, Loc); 2791 SemaRef.PushExpressionEvaluationContext( 2792 Sema::ExpressionEvaluationContext::PotentiallyEvaluated); 2793 } 2794 2795 void SemaOpenMP::StartOpenMPClause(OpenMPClauseKind K) { 2796 DSAStack->setClauseParsingMode(K); 2797 } 2798 2799 void SemaOpenMP::EndOpenMPClause() { 2800 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown); 2801 SemaRef.CleanupVarDeclMarking(); 2802 } 2803 2804 static std::pair<ValueDecl *, bool> 2805 getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc, 2806 SourceRange &ERange, bool AllowArraySection = false, 2807 StringRef DiagType = ""); 2808 2809 /// Check consistency of the reduction clauses. 2810 static void checkReductionClauses(Sema &S, DSAStackTy *Stack, 2811 ArrayRef<OMPClause *> Clauses) { 2812 bool InscanFound = false; 2813 SourceLocation InscanLoc; 2814 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions. 2815 // A reduction clause without the inscan reduction-modifier may not appear on 2816 // a construct on which a reduction clause with the inscan reduction-modifier 2817 // appears. 2818 for (OMPClause *C : Clauses) { 2819 if (C->getClauseKind() != OMPC_reduction) 2820 continue; 2821 auto *RC = cast<OMPReductionClause>(C); 2822 if (RC->getModifier() == OMPC_REDUCTION_inscan) { 2823 InscanFound = true; 2824 InscanLoc = RC->getModifierLoc(); 2825 continue; 2826 } 2827 if (RC->getModifier() == OMPC_REDUCTION_task) { 2828 // OpenMP 5.0, 2.19.5.4 reduction Clause. 2829 // A reduction clause with the task reduction-modifier may only appear on 2830 // a parallel construct, a worksharing construct or a combined or 2831 // composite construct for which any of the aforementioned constructs is a 2832 // constituent construct and simd or loop are not constituent constructs. 2833 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective(); 2834 if (!(isOpenMPParallelDirective(CurDir) || 2835 isOpenMPWorksharingDirective(CurDir)) || 2836 isOpenMPSimdDirective(CurDir)) 2837 S.Diag(RC->getModifierLoc(), 2838 diag::err_omp_reduction_task_not_parallel_or_worksharing); 2839 continue; 2840 } 2841 } 2842 if (InscanFound) { 2843 for (OMPClause *C : Clauses) { 2844 if (C->getClauseKind() != OMPC_reduction) 2845 continue; 2846 auto *RC = cast<OMPReductionClause>(C); 2847 if (RC->getModifier() != OMPC_REDUCTION_inscan) { 2848 S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown 2849 ? RC->getBeginLoc() 2850 : RC->getModifierLoc(), 2851 diag::err_omp_inscan_reduction_expected); 2852 S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction); 2853 continue; 2854 } 2855 for (Expr *Ref : RC->varlists()) { 2856 assert(Ref && "NULL expr in OpenMP nontemporal clause."); 2857 SourceLocation ELoc; 2858 SourceRange ERange; 2859 Expr *SimpleRefExpr = Ref; 2860 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange, 2861 /*AllowArraySection=*/true); 2862 ValueDecl *D = Res.first; 2863 if (!D) 2864 continue; 2865 if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) { 2866 S.Diag(Ref->getExprLoc(), 2867 diag::err_omp_reduction_not_inclusive_exclusive) 2868 << Ref->getSourceRange(); 2869 } 2870 } 2871 } 2872 } 2873 } 2874 2875 static void checkAllocateClauses(Sema &S, DSAStackTy *Stack, 2876 ArrayRef<OMPClause *> Clauses); 2877 static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr, 2878 bool WithInit); 2879 2880 static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack, 2881 const ValueDecl *D, 2882 const DSAStackTy::DSAVarData &DVar, 2883 bool IsLoopIterVar = false); 2884 2885 void SemaOpenMP::EndOpenMPDSABlock(Stmt *CurDirective) { 2886 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1] 2887 // A variable of class type (or array thereof) that appears in a lastprivate 2888 // clause requires an accessible, unambiguous default constructor for the 2889 // class type, unless the list item is also specified in a firstprivate 2890 // clause. 2891 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) { 2892 for (OMPClause *C : D->clauses()) { 2893 if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) { 2894 SmallVector<Expr *, 8> PrivateCopies; 2895 for (Expr *DE : Clause->varlists()) { 2896 if (DE->isValueDependent() || DE->isTypeDependent()) { 2897 PrivateCopies.push_back(nullptr); 2898 continue; 2899 } 2900 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens()); 2901 auto *VD = cast<VarDecl>(DRE->getDecl()); 2902 QualType Type = VD->getType().getNonReferenceType(); 2903 const DSAStackTy::DSAVarData DVar = 2904 DSAStack->getTopDSA(VD, /*FromParent=*/false); 2905 if (DVar.CKind == OMPC_lastprivate) { 2906 // Generate helper private variable and initialize it with the 2907 // default value. The address of the original variable is replaced 2908 // by the address of the new private variable in CodeGen. This new 2909 // variable is not added to IdResolver, so the code in the OpenMP 2910 // region uses original variable for proper diagnostics. 2911 VarDecl *VDPrivate = buildVarDecl( 2912 SemaRef, DE->getExprLoc(), Type.getUnqualifiedType(), 2913 VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE); 2914 SemaRef.ActOnUninitializedDecl(VDPrivate); 2915 if (VDPrivate->isInvalidDecl()) { 2916 PrivateCopies.push_back(nullptr); 2917 continue; 2918 } 2919 PrivateCopies.push_back(buildDeclRefExpr( 2920 SemaRef, VDPrivate, DE->getType(), DE->getExprLoc())); 2921 } else { 2922 // The variable is also a firstprivate, so initialization sequence 2923 // for private copy is generated already. 2924 PrivateCopies.push_back(nullptr); 2925 } 2926 } 2927 Clause->setPrivateCopies(PrivateCopies); 2928 continue; 2929 } 2930 // Finalize nontemporal clause by handling private copies, if any. 2931 if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) { 2932 SmallVector<Expr *, 8> PrivateRefs; 2933 for (Expr *RefExpr : Clause->varlists()) { 2934 assert(RefExpr && "NULL expr in OpenMP nontemporal clause."); 2935 SourceLocation ELoc; 2936 SourceRange ERange; 2937 Expr *SimpleRefExpr = RefExpr; 2938 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); 2939 if (Res.second) 2940 // It will be analyzed later. 2941 PrivateRefs.push_back(RefExpr); 2942 ValueDecl *D = Res.first; 2943 if (!D) 2944 continue; 2945 2946 const DSAStackTy::DSAVarData DVar = 2947 DSAStack->getTopDSA(D, /*FromParent=*/false); 2948 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy 2949 : SimpleRefExpr); 2950 } 2951 Clause->setPrivateRefs(PrivateRefs); 2952 continue; 2953 } 2954 if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) { 2955 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) { 2956 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I); 2957 auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts()); 2958 if (!DRE) 2959 continue; 2960 ValueDecl *VD = DRE->getDecl(); 2961 if (!VD || !isa<VarDecl>(VD)) 2962 continue; 2963 DSAStackTy::DSAVarData DVar = 2964 DSAStack->getTopDSA(VD, /*FromParent=*/false); 2965 // OpenMP [2.12.5, target Construct] 2966 // Memory allocators that appear in a uses_allocators clause cannot 2967 // appear in other data-sharing attribute clauses or data-mapping 2968 // attribute clauses in the same construct. 2969 Expr *MapExpr = nullptr; 2970 if (DVar.RefExpr || 2971 DSAStack->checkMappableExprComponentListsForDecl( 2972 VD, /*CurrentRegionOnly=*/true, 2973 [VD, &MapExpr]( 2974 OMPClauseMappableExprCommon::MappableExprComponentListRef 2975 MapExprComponents, 2976 OpenMPClauseKind C) { 2977 auto MI = MapExprComponents.rbegin(); 2978 auto ME = MapExprComponents.rend(); 2979 if (MI != ME && 2980 MI->getAssociatedDeclaration()->getCanonicalDecl() == 2981 VD->getCanonicalDecl()) { 2982 MapExpr = MI->getAssociatedExpression(); 2983 return true; 2984 } 2985 return false; 2986 })) { 2987 Diag(D.Allocator->getExprLoc(), 2988 diag::err_omp_allocator_used_in_clauses) 2989 << D.Allocator->getSourceRange(); 2990 if (DVar.RefExpr) 2991 reportOriginalDsa(SemaRef, DSAStack, VD, DVar); 2992 else 2993 Diag(MapExpr->getExprLoc(), diag::note_used_here) 2994 << MapExpr->getSourceRange(); 2995 } 2996 } 2997 continue; 2998 } 2999 } 3000 // Check allocate clauses. 3001 if (!SemaRef.CurContext->isDependentContext()) 3002 checkAllocateClauses(SemaRef, DSAStack, D->clauses()); 3003 checkReductionClauses(SemaRef, DSAStack, D->clauses()); 3004 } 3005 3006 DSAStack->pop(); 3007 SemaRef.DiscardCleanupsInEvaluationContext(); 3008 SemaRef.PopExpressionEvaluationContext(); 3009 } 3010 3011 static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, 3012 Expr *NumIterations, Sema &SemaRef, 3013 Scope *S, DSAStackTy *Stack); 3014 3015 static bool finishLinearClauses(Sema &SemaRef, ArrayRef<OMPClause *> Clauses, 3016 OMPLoopBasedDirective::HelperExprs &B, 3017 DSAStackTy *Stack) { 3018 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 3019 "loop exprs were not built"); 3020 3021 if (SemaRef.CurContext->isDependentContext()) 3022 return false; 3023 3024 // Finalize the clauses that need pre-built expressions for CodeGen. 3025 for (OMPClause *C : Clauses) { 3026 auto *LC = dyn_cast<OMPLinearClause>(C); 3027 if (!LC) 3028 continue; 3029 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef), 3030 B.NumIterations, SemaRef, 3031 SemaRef.getCurScope(), Stack)) 3032 return true; 3033 } 3034 3035 return false; 3036 } 3037 3038 namespace { 3039 3040 class VarDeclFilterCCC final : public CorrectionCandidateCallback { 3041 private: 3042 Sema &SemaRef; 3043 3044 public: 3045 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {} 3046 bool ValidateCandidate(const TypoCorrection &Candidate) override { 3047 NamedDecl *ND = Candidate.getCorrectionDecl(); 3048 if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) { 3049 return VD->hasGlobalStorage() && 3050 SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(), 3051 SemaRef.getCurScope()); 3052 } 3053 return false; 3054 } 3055 3056 std::unique_ptr<CorrectionCandidateCallback> clone() override { 3057 return std::make_unique<VarDeclFilterCCC>(*this); 3058 } 3059 }; 3060 3061 class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback { 3062 private: 3063 Sema &SemaRef; 3064 3065 public: 3066 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {} 3067 bool ValidateCandidate(const TypoCorrection &Candidate) override { 3068 NamedDecl *ND = Candidate.getCorrectionDecl(); 3069 if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) || 3070 isa<FunctionDecl>(ND))) { 3071 return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(), 3072 SemaRef.getCurScope()); 3073 } 3074 return false; 3075 } 3076 3077 std::unique_ptr<CorrectionCandidateCallback> clone() override { 3078 return std::make_unique<VarOrFuncDeclFilterCCC>(*this); 3079 } 3080 }; 3081 3082 } // namespace 3083 3084 ExprResult SemaOpenMP::ActOnOpenMPIdExpression(Scope *CurScope, 3085 CXXScopeSpec &ScopeSpec, 3086 const DeclarationNameInfo &Id, 3087 OpenMPDirectiveKind Kind) { 3088 ASTContext &Context = getASTContext(); 3089 LookupResult Lookup(SemaRef, Id, Sema::LookupOrdinaryName); 3090 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec, 3091 /*ObjectType=*/QualType(), 3092 /*AllowBuiltinCreation=*/true); 3093 3094 if (Lookup.isAmbiguous()) 3095 return ExprError(); 3096 3097 VarDecl *VD; 3098 if (!Lookup.isSingleResult()) { 3099 VarDeclFilterCCC CCC(SemaRef); 3100 if (TypoCorrection Corrected = 3101 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr, 3102 CCC, Sema::CTK_ErrorRecovery)) { 3103 SemaRef.diagnoseTypo(Corrected, 3104 PDiag(Lookup.empty() 3105 ? diag::err_undeclared_var_use_suggest 3106 : diag::err_omp_expected_var_arg_suggest) 3107 << Id.getName()); 3108 VD = Corrected.getCorrectionDeclAs<VarDecl>(); 3109 } else { 3110 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use 3111 : diag::err_omp_expected_var_arg) 3112 << Id.getName(); 3113 return ExprError(); 3114 } 3115 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) { 3116 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName(); 3117 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at); 3118 return ExprError(); 3119 } 3120 Lookup.suppressDiagnostics(); 3121 3122 // OpenMP [2.9.2, Syntax, C/C++] 3123 // Variables must be file-scope, namespace-scope, or static block-scope. 3124 if (Kind == OMPD_threadprivate && !VD->hasGlobalStorage()) { 3125 Diag(Id.getLoc(), diag::err_omp_global_var_arg) 3126 << getOpenMPDirectiveName(Kind) << !VD->isStaticLocal(); 3127 bool IsDecl = 3128 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; 3129 Diag(VD->getLocation(), 3130 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 3131 << VD; 3132 return ExprError(); 3133 } 3134 3135 VarDecl *CanonicalVD = VD->getCanonicalDecl(); 3136 NamedDecl *ND = CanonicalVD; 3137 // OpenMP [2.9.2, Restrictions, C/C++, p.2] 3138 // A threadprivate directive for file-scope variables must appear outside 3139 // any definition or declaration. 3140 if (CanonicalVD->getDeclContext()->isTranslationUnit() && 3141 !SemaRef.getCurLexicalContext()->isTranslationUnit()) { 3142 Diag(Id.getLoc(), diag::err_omp_var_scope) 3143 << getOpenMPDirectiveName(Kind) << VD; 3144 bool IsDecl = 3145 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; 3146 Diag(VD->getLocation(), 3147 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 3148 << VD; 3149 return ExprError(); 3150 } 3151 // OpenMP [2.9.2, Restrictions, C/C++, p.3] 3152 // A threadprivate directive for static class member variables must appear 3153 // in the class definition, in the same scope in which the member 3154 // variables are declared. 3155 if (CanonicalVD->isStaticDataMember() && 3156 !CanonicalVD->getDeclContext()->Equals(SemaRef.getCurLexicalContext())) { 3157 Diag(Id.getLoc(), diag::err_omp_var_scope) 3158 << getOpenMPDirectiveName(Kind) << VD; 3159 bool IsDecl = 3160 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; 3161 Diag(VD->getLocation(), 3162 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 3163 << VD; 3164 return ExprError(); 3165 } 3166 // OpenMP [2.9.2, Restrictions, C/C++, p.4] 3167 // A threadprivate directive for namespace-scope variables must appear 3168 // outside any definition or declaration other than the namespace 3169 // definition itself. 3170 if (CanonicalVD->getDeclContext()->isNamespace() && 3171 (!SemaRef.getCurLexicalContext()->isFileContext() || 3172 !SemaRef.getCurLexicalContext()->Encloses( 3173 CanonicalVD->getDeclContext()))) { 3174 Diag(Id.getLoc(), diag::err_omp_var_scope) 3175 << getOpenMPDirectiveName(Kind) << VD; 3176 bool IsDecl = 3177 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; 3178 Diag(VD->getLocation(), 3179 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 3180 << VD; 3181 return ExprError(); 3182 } 3183 // OpenMP [2.9.2, Restrictions, C/C++, p.6] 3184 // A threadprivate directive for static block-scope variables must appear 3185 // in the scope of the variable and not in a nested scope. 3186 if (CanonicalVD->isLocalVarDecl() && CurScope && 3187 !SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(), CurScope)) { 3188 Diag(Id.getLoc(), diag::err_omp_var_scope) 3189 << getOpenMPDirectiveName(Kind) << VD; 3190 bool IsDecl = 3191 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; 3192 Diag(VD->getLocation(), 3193 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 3194 << VD; 3195 return ExprError(); 3196 } 3197 3198 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6] 3199 // A threadprivate directive must lexically precede all references to any 3200 // of the variables in its list. 3201 if (Kind == OMPD_threadprivate && VD->isUsed() && 3202 !DSAStack->isThreadPrivate(VD)) { 3203 Diag(Id.getLoc(), diag::err_omp_var_used) 3204 << getOpenMPDirectiveName(Kind) << VD; 3205 return ExprError(); 3206 } 3207 3208 QualType ExprType = VD->getType().getNonReferenceType(); 3209 return DeclRefExpr::Create(Context, NestedNameSpecifierLoc(), 3210 SourceLocation(), VD, 3211 /*RefersToEnclosingVariableOrCapture=*/false, 3212 Id.getLoc(), ExprType, VK_LValue); 3213 } 3214 3215 SemaOpenMP::DeclGroupPtrTy 3216 SemaOpenMP::ActOnOpenMPThreadprivateDirective(SourceLocation Loc, 3217 ArrayRef<Expr *> VarList) { 3218 if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) { 3219 SemaRef.CurContext->addDecl(D); 3220 return DeclGroupPtrTy::make(DeclGroupRef(D)); 3221 } 3222 return nullptr; 3223 } 3224 3225 namespace { 3226 class LocalVarRefChecker final 3227 : public ConstStmtVisitor<LocalVarRefChecker, bool> { 3228 Sema &SemaRef; 3229 3230 public: 3231 bool VisitDeclRefExpr(const DeclRefExpr *E) { 3232 if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) { 3233 if (VD->hasLocalStorage()) { 3234 SemaRef.Diag(E->getBeginLoc(), 3235 diag::err_omp_local_var_in_threadprivate_init) 3236 << E->getSourceRange(); 3237 SemaRef.Diag(VD->getLocation(), diag::note_defined_here) 3238 << VD << VD->getSourceRange(); 3239 return true; 3240 } 3241 } 3242 return false; 3243 } 3244 bool VisitStmt(const Stmt *S) { 3245 for (const Stmt *Child : S->children()) { 3246 if (Child && Visit(Child)) 3247 return true; 3248 } 3249 return false; 3250 } 3251 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {} 3252 }; 3253 } // namespace 3254 3255 OMPThreadPrivateDecl * 3256 SemaOpenMP::CheckOMPThreadPrivateDecl(SourceLocation Loc, 3257 ArrayRef<Expr *> VarList) { 3258 ASTContext &Context = getASTContext(); 3259 SmallVector<Expr *, 8> Vars; 3260 for (Expr *RefExpr : VarList) { 3261 auto *DE = cast<DeclRefExpr>(RefExpr); 3262 auto *VD = cast<VarDecl>(DE->getDecl()); 3263 SourceLocation ILoc = DE->getExprLoc(); 3264 3265 // Mark variable as used. 3266 VD->setReferenced(); 3267 VD->markUsed(Context); 3268 3269 QualType QType = VD->getType(); 3270 if (QType->isDependentType() || QType->isInstantiationDependentType()) { 3271 // It will be analyzed later. 3272 Vars.push_back(DE); 3273 continue; 3274 } 3275 3276 // OpenMP [2.9.2, Restrictions, C/C++, p.10] 3277 // A threadprivate variable must not have an incomplete type. 3278 if (SemaRef.RequireCompleteType( 3279 ILoc, VD->getType(), diag::err_omp_threadprivate_incomplete_type)) { 3280 continue; 3281 } 3282 3283 // OpenMP [2.9.2, Restrictions, C/C++, p.10] 3284 // A threadprivate variable must not have a reference type. 3285 if (VD->getType()->isReferenceType()) { 3286 Diag(ILoc, diag::err_omp_ref_type_arg) 3287 << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType(); 3288 bool IsDecl = 3289 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; 3290 Diag(VD->getLocation(), 3291 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 3292 << VD; 3293 continue; 3294 } 3295 3296 // Check if this is a TLS variable. If TLS is not being supported, produce 3297 // the corresponding diagnostic. 3298 if ((VD->getTLSKind() != VarDecl::TLS_None && 3299 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() && 3300 getLangOpts().OpenMPUseTLS && 3301 getASTContext().getTargetInfo().isTLSSupported())) || 3302 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() && 3303 !VD->isLocalVarDecl())) { 3304 Diag(ILoc, diag::err_omp_var_thread_local) 3305 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1); 3306 bool IsDecl = 3307 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; 3308 Diag(VD->getLocation(), 3309 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 3310 << VD; 3311 continue; 3312 } 3313 3314 // Check if initial value of threadprivate variable reference variable with 3315 // local storage (it is not supported by runtime). 3316 if (const Expr *Init = VD->getAnyInitializer()) { 3317 LocalVarRefChecker Checker(SemaRef); 3318 if (Checker.Visit(Init)) 3319 continue; 3320 } 3321 3322 Vars.push_back(RefExpr); 3323 DSAStack->addDSA(VD, DE, OMPC_threadprivate); 3324 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit( 3325 Context, SourceRange(Loc, Loc))); 3326 if (ASTMutationListener *ML = Context.getASTMutationListener()) 3327 ML->DeclarationMarkedOpenMPThreadPrivate(VD); 3328 } 3329 OMPThreadPrivateDecl *D = nullptr; 3330 if (!Vars.empty()) { 3331 D = OMPThreadPrivateDecl::Create(Context, SemaRef.getCurLexicalContext(), 3332 Loc, Vars); 3333 D->setAccess(AS_public); 3334 } 3335 return D; 3336 } 3337 3338 static OMPAllocateDeclAttr::AllocatorTypeTy 3339 getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) { 3340 if (!Allocator) 3341 return OMPAllocateDeclAttr::OMPNullMemAlloc; 3342 if (Allocator->isTypeDependent() || Allocator->isValueDependent() || 3343 Allocator->isInstantiationDependent() || 3344 Allocator->containsUnexpandedParameterPack()) 3345 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; 3346 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; 3347 llvm::FoldingSetNodeID AEId; 3348 const Expr *AE = Allocator->IgnoreParenImpCasts(); 3349 AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true); 3350 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) { 3351 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I); 3352 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind); 3353 llvm::FoldingSetNodeID DAEId; 3354 DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(), 3355 /*Canonical=*/true); 3356 if (AEId == DAEId) { 3357 AllocatorKindRes = AllocatorKind; 3358 break; 3359 } 3360 } 3361 return AllocatorKindRes; 3362 } 3363 3364 static bool checkPreviousOMPAllocateAttribute( 3365 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD, 3366 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) { 3367 if (!VD->hasAttr<OMPAllocateDeclAttr>()) 3368 return false; 3369 const auto *A = VD->getAttr<OMPAllocateDeclAttr>(); 3370 Expr *PrevAllocator = A->getAllocator(); 3371 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind = 3372 getAllocatorKind(S, Stack, PrevAllocator); 3373 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind; 3374 if (AllocatorsMatch && 3375 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc && 3376 Allocator && PrevAllocator) { 3377 const Expr *AE = Allocator->IgnoreParenImpCasts(); 3378 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts(); 3379 llvm::FoldingSetNodeID AEId, PAEId; 3380 AE->Profile(AEId, S.Context, /*Canonical=*/true); 3381 PAE->Profile(PAEId, S.Context, /*Canonical=*/true); 3382 AllocatorsMatch = AEId == PAEId; 3383 } 3384 if (!AllocatorsMatch) { 3385 SmallString<256> AllocatorBuffer; 3386 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer); 3387 if (Allocator) 3388 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy()); 3389 SmallString<256> PrevAllocatorBuffer; 3390 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer); 3391 if (PrevAllocator) 3392 PrevAllocator->printPretty(PrevAllocatorStream, nullptr, 3393 S.getPrintingPolicy()); 3394 3395 SourceLocation AllocatorLoc = 3396 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc(); 3397 SourceRange AllocatorRange = 3398 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange(); 3399 SourceLocation PrevAllocatorLoc = 3400 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation(); 3401 SourceRange PrevAllocatorRange = 3402 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange(); 3403 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator) 3404 << (Allocator ? 1 : 0) << AllocatorStream.str() 3405 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str() 3406 << AllocatorRange; 3407 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator) 3408 << PrevAllocatorRange; 3409 return true; 3410 } 3411 return false; 3412 } 3413 3414 static void 3415 applyOMPAllocateAttribute(Sema &S, VarDecl *VD, 3416 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, 3417 Expr *Allocator, Expr *Alignment, SourceRange SR) { 3418 if (VD->hasAttr<OMPAllocateDeclAttr>()) 3419 return; 3420 if (Alignment && 3421 (Alignment->isTypeDependent() || Alignment->isValueDependent() || 3422 Alignment->isInstantiationDependent() || 3423 Alignment->containsUnexpandedParameterPack())) 3424 // Apply later when we have a usable value. 3425 return; 3426 if (Allocator && 3427 (Allocator->isTypeDependent() || Allocator->isValueDependent() || 3428 Allocator->isInstantiationDependent() || 3429 Allocator->containsUnexpandedParameterPack())) 3430 return; 3431 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind, 3432 Allocator, Alignment, SR); 3433 VD->addAttr(A); 3434 if (ASTMutationListener *ML = S.Context.getASTMutationListener()) 3435 ML->DeclarationMarkedOpenMPAllocate(VD, A); 3436 } 3437 3438 SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPAllocateDirective( 3439 SourceLocation Loc, ArrayRef<Expr *> VarList, ArrayRef<OMPClause *> Clauses, 3440 DeclContext *Owner) { 3441 assert(Clauses.size() <= 2 && "Expected at most two clauses."); 3442 Expr *Alignment = nullptr; 3443 Expr *Allocator = nullptr; 3444 if (Clauses.empty()) { 3445 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions. 3446 // allocate directives that appear in a target region must specify an 3447 // allocator clause unless a requires directive with the dynamic_allocators 3448 // clause is present in the same compilation unit. 3449 if (getLangOpts().OpenMPIsTargetDevice && 3450 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>()) 3451 SemaRef.targetDiag(Loc, diag::err_expected_allocator_clause); 3452 } else { 3453 for (const OMPClause *C : Clauses) 3454 if (const auto *AC = dyn_cast<OMPAllocatorClause>(C)) 3455 Allocator = AC->getAllocator(); 3456 else if (const auto *AC = dyn_cast<OMPAlignClause>(C)) 3457 Alignment = AC->getAlignment(); 3458 else 3459 llvm_unreachable("Unexpected clause on allocate directive"); 3460 } 3461 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind = 3462 getAllocatorKind(SemaRef, DSAStack, Allocator); 3463 SmallVector<Expr *, 8> Vars; 3464 for (Expr *RefExpr : VarList) { 3465 auto *DE = cast<DeclRefExpr>(RefExpr); 3466 auto *VD = cast<VarDecl>(DE->getDecl()); 3467 3468 // Check if this is a TLS variable or global register. 3469 if (VD->getTLSKind() != VarDecl::TLS_None || 3470 VD->hasAttr<OMPThreadPrivateDeclAttr>() || 3471 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() && 3472 !VD->isLocalVarDecl())) 3473 continue; 3474 3475 // If the used several times in the allocate directive, the same allocator 3476 // must be used. 3477 if (checkPreviousOMPAllocateAttribute(SemaRef, DSAStack, RefExpr, VD, 3478 AllocatorKind, Allocator)) 3479 continue; 3480 3481 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++ 3482 // If a list item has a static storage type, the allocator expression in the 3483 // allocator clause must be a constant expression that evaluates to one of 3484 // the predefined memory allocator values. 3485 if (Allocator && VD->hasGlobalStorage()) { 3486 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) { 3487 Diag(Allocator->getExprLoc(), 3488 diag::err_omp_expected_predefined_allocator) 3489 << Allocator->getSourceRange(); 3490 bool IsDecl = VD->isThisDeclarationADefinition(getASTContext()) == 3491 VarDecl::DeclarationOnly; 3492 Diag(VD->getLocation(), 3493 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 3494 << VD; 3495 continue; 3496 } 3497 } 3498 3499 Vars.push_back(RefExpr); 3500 applyOMPAllocateAttribute(SemaRef, VD, AllocatorKind, Allocator, Alignment, 3501 DE->getSourceRange()); 3502 } 3503 if (Vars.empty()) 3504 return nullptr; 3505 if (!Owner) 3506 Owner = SemaRef.getCurLexicalContext(); 3507 auto *D = OMPAllocateDecl::Create(getASTContext(), Owner, Loc, Vars, Clauses); 3508 D->setAccess(AS_public); 3509 Owner->addDecl(D); 3510 return DeclGroupPtrTy::make(DeclGroupRef(D)); 3511 } 3512 3513 SemaOpenMP::DeclGroupPtrTy 3514 SemaOpenMP::ActOnOpenMPRequiresDirective(SourceLocation Loc, 3515 ArrayRef<OMPClause *> ClauseList) { 3516 OMPRequiresDecl *D = nullptr; 3517 if (!SemaRef.CurContext->isFileContext()) { 3518 Diag(Loc, diag::err_omp_invalid_scope) << "requires"; 3519 } else { 3520 D = CheckOMPRequiresDecl(Loc, ClauseList); 3521 if (D) { 3522 SemaRef.CurContext->addDecl(D); 3523 DSAStack->addRequiresDecl(D); 3524 } 3525 } 3526 return DeclGroupPtrTy::make(DeclGroupRef(D)); 3527 } 3528 3529 void SemaOpenMP::ActOnOpenMPAssumesDirective(SourceLocation Loc, 3530 OpenMPDirectiveKind DKind, 3531 ArrayRef<std::string> Assumptions, 3532 bool SkippedClauses) { 3533 if (!SkippedClauses && Assumptions.empty()) 3534 Diag(Loc, diag::err_omp_no_clause_for_directive) 3535 << llvm::omp::getAllAssumeClauseOptions() 3536 << llvm::omp::getOpenMPDirectiveName(DKind); 3537 3538 auto *AA = 3539 OMPAssumeAttr::Create(getASTContext(), llvm::join(Assumptions, ","), Loc); 3540 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) { 3541 OMPAssumeScoped.push_back(AA); 3542 return; 3543 } 3544 3545 // Global assumes without assumption clauses are ignored. 3546 if (Assumptions.empty()) 3547 return; 3548 3549 assert(DKind == llvm::omp::Directive::OMPD_assumes && 3550 "Unexpected omp assumption directive!"); 3551 OMPAssumeGlobal.push_back(AA); 3552 3553 // The OMPAssumeGlobal scope above will take care of new declarations but 3554 // we also want to apply the assumption to existing ones, e.g., to 3555 // declarations in included headers. To this end, we traverse all existing 3556 // declaration contexts and annotate function declarations here. 3557 SmallVector<DeclContext *, 8> DeclContexts; 3558 auto *Ctx = SemaRef.CurContext; 3559 while (Ctx->getLexicalParent()) 3560 Ctx = Ctx->getLexicalParent(); 3561 DeclContexts.push_back(Ctx); 3562 while (!DeclContexts.empty()) { 3563 DeclContext *DC = DeclContexts.pop_back_val(); 3564 for (auto *SubDC : DC->decls()) { 3565 if (SubDC->isInvalidDecl()) 3566 continue; 3567 if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) { 3568 DeclContexts.push_back(CTD->getTemplatedDecl()); 3569 llvm::append_range(DeclContexts, CTD->specializations()); 3570 continue; 3571 } 3572 if (auto *DC = dyn_cast<DeclContext>(SubDC)) 3573 DeclContexts.push_back(DC); 3574 if (auto *F = dyn_cast<FunctionDecl>(SubDC)) { 3575 F->addAttr(AA); 3576 continue; 3577 } 3578 } 3579 } 3580 } 3581 3582 void SemaOpenMP::ActOnOpenMPEndAssumesDirective() { 3583 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!"); 3584 OMPAssumeScoped.pop_back(); 3585 } 3586 3587 OMPRequiresDecl * 3588 SemaOpenMP::CheckOMPRequiresDecl(SourceLocation Loc, 3589 ArrayRef<OMPClause *> ClauseList) { 3590 /// For target specific clauses, the requires directive cannot be 3591 /// specified after the handling of any of the target regions in the 3592 /// current compilation unit. 3593 ArrayRef<SourceLocation> TargetLocations = 3594 DSAStack->getEncounteredTargetLocs(); 3595 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc(); 3596 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) { 3597 for (const OMPClause *CNew : ClauseList) { 3598 // Check if any of the requires clauses affect target regions. 3599 if (isa<OMPUnifiedSharedMemoryClause>(CNew) || 3600 isa<OMPUnifiedAddressClause>(CNew) || 3601 isa<OMPReverseOffloadClause>(CNew) || 3602 isa<OMPDynamicAllocatorsClause>(CNew)) { 3603 Diag(Loc, diag::err_omp_directive_before_requires) 3604 << "target" << getOpenMPClauseName(CNew->getClauseKind()); 3605 for (SourceLocation TargetLoc : TargetLocations) { 3606 Diag(TargetLoc, diag::note_omp_requires_encountered_directive) 3607 << "target"; 3608 } 3609 } else if (!AtomicLoc.isInvalid() && 3610 isa<OMPAtomicDefaultMemOrderClause>(CNew)) { 3611 Diag(Loc, diag::err_omp_directive_before_requires) 3612 << "atomic" << getOpenMPClauseName(CNew->getClauseKind()); 3613 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive) 3614 << "atomic"; 3615 } 3616 } 3617 } 3618 3619 if (!DSAStack->hasDuplicateRequiresClause(ClauseList)) 3620 return OMPRequiresDecl::Create( 3621 getASTContext(), SemaRef.getCurLexicalContext(), Loc, ClauseList); 3622 return nullptr; 3623 } 3624 3625 static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack, 3626 const ValueDecl *D, 3627 const DSAStackTy::DSAVarData &DVar, 3628 bool IsLoopIterVar) { 3629 if (DVar.RefExpr) { 3630 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa) 3631 << getOpenMPClauseName(DVar.CKind); 3632 return; 3633 } 3634 enum { 3635 PDSA_StaticMemberShared, 3636 PDSA_StaticLocalVarShared, 3637 PDSA_LoopIterVarPrivate, 3638 PDSA_LoopIterVarLinear, 3639 PDSA_LoopIterVarLastprivate, 3640 PDSA_ConstVarShared, 3641 PDSA_GlobalVarShared, 3642 PDSA_TaskVarFirstprivate, 3643 PDSA_LocalVarPrivate, 3644 PDSA_Implicit 3645 } Reason = PDSA_Implicit; 3646 bool ReportHint = false; 3647 auto ReportLoc = D->getLocation(); 3648 auto *VD = dyn_cast<VarDecl>(D); 3649 if (IsLoopIterVar) { 3650 if (DVar.CKind == OMPC_private) 3651 Reason = PDSA_LoopIterVarPrivate; 3652 else if (DVar.CKind == OMPC_lastprivate) 3653 Reason = PDSA_LoopIterVarLastprivate; 3654 else 3655 Reason = PDSA_LoopIterVarLinear; 3656 } else if (isOpenMPTaskingDirective(DVar.DKind) && 3657 DVar.CKind == OMPC_firstprivate) { 3658 Reason = PDSA_TaskVarFirstprivate; 3659 ReportLoc = DVar.ImplicitDSALoc; 3660 } else if (VD && VD->isStaticLocal()) 3661 Reason = PDSA_StaticLocalVarShared; 3662 else if (VD && VD->isStaticDataMember()) 3663 Reason = PDSA_StaticMemberShared; 3664 else if (VD && VD->isFileVarDecl()) 3665 Reason = PDSA_GlobalVarShared; 3666 else if (D->getType().isConstant(SemaRef.getASTContext())) 3667 Reason = PDSA_ConstVarShared; 3668 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) { 3669 ReportHint = true; 3670 Reason = PDSA_LocalVarPrivate; 3671 } 3672 if (Reason != PDSA_Implicit) { 3673 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa) 3674 << Reason << ReportHint 3675 << getOpenMPDirectiveName(Stack->getCurrentDirective()); 3676 } else if (DVar.ImplicitDSALoc.isValid()) { 3677 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa) 3678 << getOpenMPClauseName(DVar.CKind); 3679 } 3680 } 3681 3682 static OpenMPMapClauseKind 3683 getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M, 3684 bool IsAggregateOrDeclareTarget) { 3685 OpenMPMapClauseKind Kind = OMPC_MAP_unknown; 3686 switch (M) { 3687 case OMPC_DEFAULTMAP_MODIFIER_alloc: 3688 Kind = OMPC_MAP_alloc; 3689 break; 3690 case OMPC_DEFAULTMAP_MODIFIER_to: 3691 Kind = OMPC_MAP_to; 3692 break; 3693 case OMPC_DEFAULTMAP_MODIFIER_from: 3694 Kind = OMPC_MAP_from; 3695 break; 3696 case OMPC_DEFAULTMAP_MODIFIER_tofrom: 3697 Kind = OMPC_MAP_tofrom; 3698 break; 3699 case OMPC_DEFAULTMAP_MODIFIER_present: 3700 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description] 3701 // If implicit-behavior is present, each variable referenced in the 3702 // construct in the category specified by variable-category is treated as if 3703 // it had been listed in a map clause with the map-type of alloc and 3704 // map-type-modifier of present. 3705 Kind = OMPC_MAP_alloc; 3706 break; 3707 case OMPC_DEFAULTMAP_MODIFIER_firstprivate: 3708 case OMPC_DEFAULTMAP_MODIFIER_last: 3709 llvm_unreachable("Unexpected defaultmap implicit behavior"); 3710 case OMPC_DEFAULTMAP_MODIFIER_none: 3711 case OMPC_DEFAULTMAP_MODIFIER_default: 3712 case OMPC_DEFAULTMAP_MODIFIER_unknown: 3713 // IsAggregateOrDeclareTarget could be true if: 3714 // 1. the implicit behavior for aggregate is tofrom 3715 // 2. it's a declare target link 3716 if (IsAggregateOrDeclareTarget) { 3717 Kind = OMPC_MAP_tofrom; 3718 break; 3719 } 3720 llvm_unreachable("Unexpected defaultmap implicit behavior"); 3721 } 3722 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known"); 3723 return Kind; 3724 } 3725 3726 namespace { 3727 class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> { 3728 DSAStackTy *Stack; 3729 Sema &SemaRef; 3730 bool ErrorFound = false; 3731 bool TryCaptureCXXThisMembers = false; 3732 CapturedStmt *CS = nullptr; 3733 const static unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1; 3734 llvm::SmallVector<Expr *, 4> ImplicitFirstprivate; 3735 llvm::SmallVector<Expr *, 4> ImplicitPrivate; 3736 llvm::SmallVector<Expr *, 4> ImplicitMap[DefaultmapKindNum][OMPC_MAP_delete]; 3737 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers> 3738 ImplicitMapModifier[DefaultmapKindNum]; 3739 SemaOpenMP::VarsWithInheritedDSAType VarsWithInheritedDSA; 3740 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations; 3741 3742 void VisitSubCaptures(OMPExecutableDirective *S) { 3743 // Check implicitly captured variables. 3744 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt()) 3745 return; 3746 if (S->getDirectiveKind() == OMPD_atomic || 3747 S->getDirectiveKind() == OMPD_critical || 3748 S->getDirectiveKind() == OMPD_section || 3749 S->getDirectiveKind() == OMPD_master || 3750 S->getDirectiveKind() == OMPD_masked || 3751 S->getDirectiveKind() == OMPD_scope || 3752 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) { 3753 Visit(S->getAssociatedStmt()); 3754 return; 3755 } 3756 visitSubCaptures(S->getInnermostCapturedStmt()); 3757 // Try to capture inner this->member references to generate correct mappings 3758 // and diagnostics. 3759 if (TryCaptureCXXThisMembers || 3760 (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) && 3761 llvm::any_of(S->getInnermostCapturedStmt()->captures(), 3762 [](const CapturedStmt::Capture &C) { 3763 return C.capturesThis(); 3764 }))) { 3765 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers; 3766 TryCaptureCXXThisMembers = true; 3767 Visit(S->getInnermostCapturedStmt()->getCapturedStmt()); 3768 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers; 3769 } 3770 // In tasks firstprivates are not captured anymore, need to analyze them 3771 // explicitly. 3772 if (isOpenMPTaskingDirective(S->getDirectiveKind()) && 3773 !isOpenMPTaskLoopDirective(S->getDirectiveKind())) { 3774 for (OMPClause *C : S->clauses()) 3775 if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) { 3776 for (Expr *Ref : FC->varlists()) 3777 Visit(Ref); 3778 } 3779 } 3780 } 3781 3782 public: 3783 void VisitDeclRefExpr(DeclRefExpr *E) { 3784 if (TryCaptureCXXThisMembers || E->isTypeDependent() || 3785 E->isValueDependent() || E->containsUnexpandedParameterPack() || 3786 E->isInstantiationDependent() || 3787 E->isNonOdrUse() == clang::NOUR_Unevaluated) 3788 return; 3789 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) { 3790 // Check the datasharing rules for the expressions in the clauses. 3791 if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) && 3792 !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr && 3793 !Stack->isImplicitDefaultFirstprivateFD(VD))) { 3794 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD)) 3795 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) { 3796 Visit(CED->getInit()); 3797 return; 3798 } 3799 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD)) 3800 // Do not analyze internal variables and do not enclose them into 3801 // implicit clauses. 3802 if (!Stack->isImplicitDefaultFirstprivateFD(VD)) 3803 return; 3804 VD = VD->getCanonicalDecl(); 3805 // Skip internally declared variables. 3806 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) && 3807 !Stack->isImplicitDefaultFirstprivateFD(VD) && 3808 !Stack->isImplicitTaskFirstprivate(VD)) 3809 return; 3810 // Skip allocators in uses_allocators clauses. 3811 if (Stack->isUsesAllocatorsDecl(VD)) 3812 return; 3813 3814 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false); 3815 // Check if the variable has explicit DSA set and stop analysis if it so. 3816 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second) 3817 return; 3818 3819 // Skip internally declared static variables. 3820 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 3821 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 3822 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) && 3823 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() || 3824 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) && 3825 !Stack->isImplicitDefaultFirstprivateFD(VD) && 3826 !Stack->isImplicitTaskFirstprivate(VD)) 3827 return; 3828 3829 SourceLocation ELoc = E->getExprLoc(); 3830 OpenMPDirectiveKind DKind = Stack->getCurrentDirective(); 3831 // The default(none) clause requires that each variable that is referenced 3832 // in the construct, and does not have a predetermined data-sharing 3833 // attribute, must have its data-sharing attribute explicitly determined 3834 // by being listed in a data-sharing attribute clause. 3835 if (DVar.CKind == OMPC_unknown && 3836 (Stack->getDefaultDSA() == DSA_none || 3837 Stack->getDefaultDSA() == DSA_private || 3838 Stack->getDefaultDSA() == DSA_firstprivate) && 3839 isImplicitOrExplicitTaskingRegion(DKind) && 3840 VarsWithInheritedDSA.count(VD) == 0) { 3841 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none; 3842 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate || 3843 Stack->getDefaultDSA() == DSA_private)) { 3844 DSAStackTy::DSAVarData DVar = 3845 Stack->getImplicitDSA(VD, /*FromParent=*/false); 3846 InheritedDSA = DVar.CKind == OMPC_unknown; 3847 } 3848 if (InheritedDSA) 3849 VarsWithInheritedDSA[VD] = E; 3850 if (Stack->getDefaultDSA() == DSA_none) 3851 return; 3852 } 3853 3854 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description] 3855 // If implicit-behavior is none, each variable referenced in the 3856 // construct that does not have a predetermined data-sharing attribute 3857 // and does not appear in a to or link clause on a declare target 3858 // directive must be listed in a data-mapping attribute clause, a 3859 // data-sharing attribute clause (including a data-sharing attribute 3860 // clause on a combined construct where target. is one of the 3861 // constituent constructs), or an is_device_ptr clause. 3862 OpenMPDefaultmapClauseKind ClauseKind = 3863 getVariableCategoryFromDecl(SemaRef.getLangOpts(), VD); 3864 if (SemaRef.getLangOpts().OpenMP >= 50) { 3865 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) == 3866 OMPC_DEFAULTMAP_MODIFIER_none; 3867 if (DVar.CKind == OMPC_unknown && IsModifierNone && 3868 VarsWithInheritedDSA.count(VD) == 0 && !Res) { 3869 // Only check for data-mapping attribute and is_device_ptr here 3870 // since we have already make sure that the declaration does not 3871 // have a data-sharing attribute above 3872 if (!Stack->checkMappableExprComponentListsForDecl( 3873 VD, /*CurrentRegionOnly=*/true, 3874 [VD](OMPClauseMappableExprCommon::MappableExprComponentListRef 3875 MapExprComponents, 3876 OpenMPClauseKind) { 3877 auto MI = MapExprComponents.rbegin(); 3878 auto ME = MapExprComponents.rend(); 3879 return MI != ME && MI->getAssociatedDeclaration() == VD; 3880 })) { 3881 VarsWithInheritedDSA[VD] = E; 3882 return; 3883 } 3884 } 3885 } 3886 if (SemaRef.getLangOpts().OpenMP > 50) { 3887 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) == 3888 OMPC_DEFAULTMAP_MODIFIER_present; 3889 if (IsModifierPresent) { 3890 if (!llvm::is_contained(ImplicitMapModifier[ClauseKind], 3891 OMPC_MAP_MODIFIER_present)) { 3892 ImplicitMapModifier[ClauseKind].push_back( 3893 OMPC_MAP_MODIFIER_present); 3894 } 3895 } 3896 } 3897 3898 if (isOpenMPTargetExecutionDirective(DKind) && 3899 !Stack->isLoopControlVariable(VD).first) { 3900 if (!Stack->checkMappableExprComponentListsForDecl( 3901 VD, /*CurrentRegionOnly=*/true, 3902 [this](OMPClauseMappableExprCommon::MappableExprComponentListRef 3903 StackComponents, 3904 OpenMPClauseKind) { 3905 if (SemaRef.LangOpts.OpenMP >= 50) 3906 return !StackComponents.empty(); 3907 // Variable is used if it has been marked as an array, array 3908 // section, array shaping or the variable itself. 3909 return StackComponents.size() == 1 || 3910 llvm::all_of( 3911 llvm::drop_begin(llvm::reverse(StackComponents)), 3912 [](const OMPClauseMappableExprCommon:: 3913 MappableComponent &MC) { 3914 return MC.getAssociatedDeclaration() == 3915 nullptr && 3916 (isa<ArraySectionExpr>( 3917 MC.getAssociatedExpression()) || 3918 isa<OMPArrayShapingExpr>( 3919 MC.getAssociatedExpression()) || 3920 isa<ArraySubscriptExpr>( 3921 MC.getAssociatedExpression())); 3922 }); 3923 })) { 3924 bool IsFirstprivate = false; 3925 // By default lambdas are captured as firstprivates. 3926 if (const auto *RD = 3927 VD->getType().getNonReferenceType()->getAsCXXRecordDecl()) 3928 IsFirstprivate = RD->isLambda(); 3929 IsFirstprivate = 3930 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res); 3931 if (IsFirstprivate) { 3932 ImplicitFirstprivate.emplace_back(E); 3933 } else { 3934 OpenMPDefaultmapClauseModifier M = 3935 Stack->getDefaultmapModifier(ClauseKind); 3936 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier( 3937 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res); 3938 ImplicitMap[ClauseKind][Kind].emplace_back(E); 3939 } 3940 return; 3941 } 3942 } 3943 3944 // OpenMP [2.9.3.6, Restrictions, p.2] 3945 // A list item that appears in a reduction clause of the innermost 3946 // enclosing worksharing or parallel construct may not be accessed in an 3947 // explicit task. 3948 DVar = Stack->hasInnermostDSA( 3949 VD, 3950 [](OpenMPClauseKind C, bool AppliedToPointee) { 3951 return C == OMPC_reduction && !AppliedToPointee; 3952 }, 3953 [](OpenMPDirectiveKind K) { 3954 return isOpenMPParallelDirective(K) || 3955 isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K); 3956 }, 3957 /*FromParent=*/true); 3958 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) { 3959 ErrorFound = true; 3960 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task); 3961 reportOriginalDsa(SemaRef, Stack, VD, DVar); 3962 return; 3963 } 3964 3965 // Define implicit data-sharing attributes for task. 3966 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false); 3967 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) || 3968 (((Stack->getDefaultDSA() == DSA_firstprivate && 3969 DVar.CKind == OMPC_firstprivate) || 3970 (Stack->getDefaultDSA() == DSA_private && 3971 DVar.CKind == OMPC_private)) && 3972 !DVar.RefExpr)) && 3973 !Stack->isLoopControlVariable(VD).first) { 3974 if (Stack->getDefaultDSA() == DSA_private) 3975 ImplicitPrivate.push_back(E); 3976 else 3977 ImplicitFirstprivate.push_back(E); 3978 return; 3979 } 3980 3981 // Store implicitly used globals with declare target link for parent 3982 // target. 3983 if (!isOpenMPTargetExecutionDirective(DKind) && Res && 3984 *Res == OMPDeclareTargetDeclAttr::MT_Link) { 3985 Stack->addToParentTargetRegionLinkGlobals(E); 3986 return; 3987 } 3988 } 3989 } 3990 void VisitMemberExpr(MemberExpr *E) { 3991 if (E->isTypeDependent() || E->isValueDependent() || 3992 E->containsUnexpandedParameterPack() || E->isInstantiationDependent()) 3993 return; 3994 auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl()); 3995 OpenMPDirectiveKind DKind = Stack->getCurrentDirective(); 3996 if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) { 3997 if (!FD) 3998 return; 3999 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false); 4000 // Check if the variable has explicit DSA set and stop analysis if it 4001 // so. 4002 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second) 4003 return; 4004 4005 if (isOpenMPTargetExecutionDirective(DKind) && 4006 !Stack->isLoopControlVariable(FD).first && 4007 !Stack->checkMappableExprComponentListsForDecl( 4008 FD, /*CurrentRegionOnly=*/true, 4009 [](OMPClauseMappableExprCommon::MappableExprComponentListRef 4010 StackComponents, 4011 OpenMPClauseKind) { 4012 return isa<CXXThisExpr>( 4013 cast<MemberExpr>( 4014 StackComponents.back().getAssociatedExpression()) 4015 ->getBase() 4016 ->IgnoreParens()); 4017 })) { 4018 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3] 4019 // A bit-field cannot appear in a map clause. 4020 // 4021 if (FD->isBitField()) 4022 return; 4023 4024 // Check to see if the member expression is referencing a class that 4025 // has already been explicitly mapped 4026 if (Stack->isClassPreviouslyMapped(TE->getType())) 4027 return; 4028 4029 OpenMPDefaultmapClauseModifier Modifier = 4030 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate); 4031 OpenMPDefaultmapClauseKind ClauseKind = 4032 getVariableCategoryFromDecl(SemaRef.getLangOpts(), FD); 4033 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier( 4034 Modifier, /*IsAggregateOrDeclareTarget*/ true); 4035 ImplicitMap[ClauseKind][Kind].emplace_back(E); 4036 return; 4037 } 4038 4039 SourceLocation ELoc = E->getExprLoc(); 4040 // OpenMP [2.9.3.6, Restrictions, p.2] 4041 // A list item that appears in a reduction clause of the innermost 4042 // enclosing worksharing or parallel construct may not be accessed in 4043 // an explicit task. 4044 DVar = Stack->hasInnermostDSA( 4045 FD, 4046 [](OpenMPClauseKind C, bool AppliedToPointee) { 4047 return C == OMPC_reduction && !AppliedToPointee; 4048 }, 4049 [](OpenMPDirectiveKind K) { 4050 return isOpenMPParallelDirective(K) || 4051 isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K); 4052 }, 4053 /*FromParent=*/true); 4054 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) { 4055 ErrorFound = true; 4056 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task); 4057 reportOriginalDsa(SemaRef, Stack, FD, DVar); 4058 return; 4059 } 4060 4061 // Define implicit data-sharing attributes for task. 4062 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false); 4063 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared && 4064 !Stack->isLoopControlVariable(FD).first) { 4065 // Check if there is a captured expression for the current field in the 4066 // region. Do not mark it as firstprivate unless there is no captured 4067 // expression. 4068 // TODO: try to make it firstprivate. 4069 if (DVar.CKind != OMPC_unknown) 4070 ImplicitFirstprivate.push_back(E); 4071 } 4072 return; 4073 } 4074 if (isOpenMPTargetExecutionDirective(DKind)) { 4075 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents; 4076 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map, 4077 Stack->getCurrentDirective(), 4078 /*NoDiagnose=*/true)) 4079 return; 4080 const auto *VD = cast<ValueDecl>( 4081 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl()); 4082 if (!Stack->checkMappableExprComponentListsForDecl( 4083 VD, /*CurrentRegionOnly=*/true, 4084 [&CurComponents]( 4085 OMPClauseMappableExprCommon::MappableExprComponentListRef 4086 StackComponents, 4087 OpenMPClauseKind) { 4088 auto CCI = CurComponents.rbegin(); 4089 auto CCE = CurComponents.rend(); 4090 for (const auto &SC : llvm::reverse(StackComponents)) { 4091 // Do both expressions have the same kind? 4092 if (CCI->getAssociatedExpression()->getStmtClass() != 4093 SC.getAssociatedExpression()->getStmtClass()) 4094 if (!((isa<ArraySectionExpr>( 4095 SC.getAssociatedExpression()) || 4096 isa<OMPArrayShapingExpr>( 4097 SC.getAssociatedExpression())) && 4098 isa<ArraySubscriptExpr>( 4099 CCI->getAssociatedExpression()))) 4100 return false; 4101 4102 const Decl *CCD = CCI->getAssociatedDeclaration(); 4103 const Decl *SCD = SC.getAssociatedDeclaration(); 4104 CCD = CCD ? CCD->getCanonicalDecl() : nullptr; 4105 SCD = SCD ? SCD->getCanonicalDecl() : nullptr; 4106 if (SCD != CCD) 4107 return false; 4108 std::advance(CCI, 1); 4109 if (CCI == CCE) 4110 break; 4111 } 4112 return true; 4113 })) { 4114 Visit(E->getBase()); 4115 } 4116 } else if (!TryCaptureCXXThisMembers) { 4117 Visit(E->getBase()); 4118 } 4119 } 4120 void VisitOMPExecutableDirective(OMPExecutableDirective *S) { 4121 for (OMPClause *C : S->clauses()) { 4122 // Skip analysis of arguments of private clauses for task|target 4123 // directives. 4124 if (isa_and_nonnull<OMPPrivateClause>(C)) 4125 continue; 4126 // Skip analysis of arguments of implicitly defined firstprivate clause 4127 // for task|target directives. 4128 // Skip analysis of arguments of implicitly defined map clause for target 4129 // directives. 4130 if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) && 4131 C->isImplicit() && 4132 !isOpenMPTaskingDirective(Stack->getCurrentDirective()))) { 4133 for (Stmt *CC : C->children()) { 4134 if (CC) 4135 Visit(CC); 4136 } 4137 } 4138 } 4139 // Check implicitly captured variables. 4140 VisitSubCaptures(S); 4141 } 4142 4143 void VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective *S) { 4144 // Loop transformation directives do not introduce data sharing 4145 VisitStmt(S); 4146 } 4147 4148 void VisitCallExpr(CallExpr *S) { 4149 for (Stmt *C : S->arguments()) { 4150 if (C) { 4151 // Check implicitly captured variables in the task-based directives to 4152 // check if they must be firstprivatized. 4153 Visit(C); 4154 } 4155 } 4156 if (Expr *Callee = S->getCallee()) { 4157 auto *CI = Callee->IgnoreParenImpCasts(); 4158 if (auto *CE = dyn_cast<MemberExpr>(CI)) 4159 Visit(CE->getBase()); 4160 else if (auto *CE = dyn_cast<DeclRefExpr>(CI)) 4161 Visit(CE); 4162 } 4163 } 4164 void VisitStmt(Stmt *S) { 4165 for (Stmt *C : S->children()) { 4166 if (C) { 4167 // Check implicitly captured variables in the task-based directives to 4168 // check if they must be firstprivatized. 4169 Visit(C); 4170 } 4171 } 4172 } 4173 4174 void visitSubCaptures(CapturedStmt *S) { 4175 for (const CapturedStmt::Capture &Cap : S->captures()) { 4176 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy()) 4177 continue; 4178 VarDecl *VD = Cap.getCapturedVar(); 4179 // Do not try to map the variable if it or its sub-component was mapped 4180 // already. 4181 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) && 4182 Stack->checkMappableExprComponentListsForDecl( 4183 VD, /*CurrentRegionOnly=*/true, 4184 [](OMPClauseMappableExprCommon::MappableExprComponentListRef, 4185 OpenMPClauseKind) { return true; })) 4186 continue; 4187 DeclRefExpr *DRE = buildDeclRefExpr( 4188 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context), 4189 Cap.getLocation(), /*RefersToCapture=*/true); 4190 Visit(DRE); 4191 } 4192 } 4193 bool isErrorFound() const { return ErrorFound; } 4194 ArrayRef<Expr *> getImplicitFirstprivate() const { 4195 return ImplicitFirstprivate; 4196 } 4197 ArrayRef<Expr *> getImplicitPrivate() const { return ImplicitPrivate; } 4198 ArrayRef<Expr *> getImplicitMap(OpenMPDefaultmapClauseKind DK, 4199 OpenMPMapClauseKind MK) const { 4200 return ImplicitMap[DK][MK]; 4201 } 4202 ArrayRef<OpenMPMapModifierKind> 4203 getImplicitMapModifier(OpenMPDefaultmapClauseKind Kind) const { 4204 return ImplicitMapModifier[Kind]; 4205 } 4206 const SemaOpenMP::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const { 4207 return VarsWithInheritedDSA; 4208 } 4209 4210 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS) 4211 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) { 4212 // Process declare target link variables for the target directives. 4213 if (isOpenMPTargetExecutionDirective(S->getCurrentDirective())) { 4214 for (DeclRefExpr *E : Stack->getLinkGlobals()) 4215 Visit(E); 4216 } 4217 } 4218 }; 4219 } // namespace 4220 4221 static void handleDeclareVariantConstructTrait(DSAStackTy *Stack, 4222 OpenMPDirectiveKind DKind, 4223 bool ScopeEntry) { 4224 SmallVector<llvm::omp::TraitProperty, 8> Traits; 4225 if (isOpenMPTargetExecutionDirective(DKind)) 4226 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target); 4227 if (isOpenMPTeamsDirective(DKind)) 4228 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams); 4229 if (isOpenMPParallelDirective(DKind)) 4230 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel); 4231 if (isOpenMPWorksharingDirective(DKind)) 4232 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for); 4233 if (isOpenMPSimdDirective(DKind)) 4234 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd); 4235 Stack->handleConstructTrait(Traits, ScopeEntry); 4236 } 4237 4238 static SmallVector<SemaOpenMP::CapturedParamNameType> 4239 getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing) { 4240 ASTContext &Context = SemaRef.getASTContext(); 4241 QualType KmpInt32Ty = 4242 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst(); 4243 QualType KmpInt32PtrTy = 4244 Context.getPointerType(KmpInt32Ty).withConst().withRestrict(); 4245 SmallVector<SemaOpenMP::CapturedParamNameType> Params{ 4246 std::make_pair(".global_tid.", KmpInt32PtrTy), 4247 std::make_pair(".bound_tid.", KmpInt32PtrTy), 4248 }; 4249 if (LoopBoundSharing) { 4250 QualType KmpSizeTy = Context.getSizeType().withConst(); 4251 Params.push_back(std::make_pair(".previous.lb.", KmpSizeTy)); 4252 Params.push_back(std::make_pair(".previous.ub.", KmpSizeTy)); 4253 } 4254 4255 // __context with shared vars 4256 Params.push_back(std::make_pair(StringRef(), QualType())); 4257 return Params; 4258 } 4259 4260 static SmallVector<SemaOpenMP::CapturedParamNameType> 4261 getTeamsRegionParams(Sema &SemaRef) { 4262 return getParallelRegionParams(SemaRef, /*LoopBoundSharing=*/false); 4263 } 4264 4265 static SmallVector<SemaOpenMP::CapturedParamNameType> 4266 getTaskRegionParams(Sema &SemaRef) { 4267 ASTContext &Context = SemaRef.getASTContext(); 4268 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst(); 4269 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict(); 4270 QualType KmpInt32PtrTy = 4271 Context.getPointerType(KmpInt32Ty).withConst().withRestrict(); 4272 QualType Args[] = {VoidPtrTy}; 4273 FunctionProtoType::ExtProtoInfo EPI; 4274 EPI.Variadic = true; 4275 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI); 4276 SmallVector<SemaOpenMP::CapturedParamNameType> Params{ 4277 std::make_pair(".global_tid.", KmpInt32Ty), 4278 std::make_pair(".part_id.", KmpInt32PtrTy), 4279 std::make_pair(".privates.", VoidPtrTy), 4280 std::make_pair( 4281 ".copy_fn.", 4282 Context.getPointerType(CopyFnType).withConst().withRestrict()), 4283 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()), 4284 std::make_pair(StringRef(), QualType()) // __context with shared vars 4285 }; 4286 return Params; 4287 } 4288 4289 static SmallVector<SemaOpenMP::CapturedParamNameType> 4290 getTargetRegionParams(Sema &SemaRef) { 4291 ASTContext &Context = SemaRef.getASTContext(); 4292 SmallVector<SemaOpenMP::CapturedParamNameType> Params; 4293 if (SemaRef.getLangOpts().OpenMPIsTargetDevice) { 4294 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict(); 4295 Params.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy)); 4296 } 4297 // __context with shared vars 4298 Params.push_back(std::make_pair(StringRef(), QualType())); 4299 return Params; 4300 } 4301 4302 static SmallVector<SemaOpenMP::CapturedParamNameType> 4303 getUnknownRegionParams(Sema &SemaRef) { 4304 SmallVector<SemaOpenMP::CapturedParamNameType> Params{ 4305 std::make_pair(StringRef(), QualType()) // __context with shared vars 4306 }; 4307 return Params; 4308 } 4309 4310 static SmallVector<SemaOpenMP::CapturedParamNameType> 4311 getTaskloopRegionParams(Sema &SemaRef) { 4312 ASTContext &Context = SemaRef.getASTContext(); 4313 QualType KmpInt32Ty = 4314 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst(); 4315 QualType KmpUInt64Ty = 4316 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0).withConst(); 4317 QualType KmpInt64Ty = 4318 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1).withConst(); 4319 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict(); 4320 QualType KmpInt32PtrTy = 4321 Context.getPointerType(KmpInt32Ty).withConst().withRestrict(); 4322 QualType Args[] = {VoidPtrTy}; 4323 FunctionProtoType::ExtProtoInfo EPI; 4324 EPI.Variadic = true; 4325 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI); 4326 SmallVector<SemaOpenMP::CapturedParamNameType> Params{ 4327 std::make_pair(".global_tid.", KmpInt32Ty), 4328 std::make_pair(".part_id.", KmpInt32PtrTy), 4329 std::make_pair(".privates.", VoidPtrTy), 4330 std::make_pair( 4331 ".copy_fn.", 4332 Context.getPointerType(CopyFnType).withConst().withRestrict()), 4333 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()), 4334 std::make_pair(".lb.", KmpUInt64Ty), 4335 std::make_pair(".ub.", KmpUInt64Ty), 4336 std::make_pair(".st.", KmpInt64Ty), 4337 std::make_pair(".liter.", KmpInt32Ty), 4338 std::make_pair(".reductions.", VoidPtrTy), 4339 std::make_pair(StringRef(), QualType()) // __context with shared vars 4340 }; 4341 return Params; 4342 } 4343 4344 static void processCapturedRegions(Sema &SemaRef, OpenMPDirectiveKind DKind, 4345 Scope *CurScope, SourceLocation Loc) { 4346 SmallVector<OpenMPDirectiveKind> Regions; 4347 getOpenMPCaptureRegions(Regions, DKind); 4348 4349 bool LoopBoundSharing = isOpenMPLoopBoundSharingDirective(DKind); 4350 4351 auto MarkAsInlined = [&](CapturedRegionScopeInfo *CSI) { 4352 CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit( 4353 SemaRef.getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline)); 4354 }; 4355 4356 for (auto [Level, RKind] : llvm::enumerate(Regions)) { 4357 switch (RKind) { 4358 // All region kinds that can be returned from `getOpenMPCaptureRegions` 4359 // are listed here. 4360 case OMPD_parallel: 4361 SemaRef.ActOnCapturedRegionStart( 4362 Loc, CurScope, CR_OpenMP, 4363 getParallelRegionParams(SemaRef, LoopBoundSharing), Level); 4364 break; 4365 case OMPD_teams: 4366 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, 4367 getTeamsRegionParams(SemaRef), Level); 4368 break; 4369 case OMPD_task: 4370 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, 4371 getTaskRegionParams(SemaRef), Level); 4372 // Mark this captured region as inlined, because we don't use outlined 4373 // function directly. 4374 MarkAsInlined(SemaRef.getCurCapturedRegion()); 4375 break; 4376 case OMPD_taskloop: 4377 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, 4378 getTaskloopRegionParams(SemaRef), Level); 4379 // Mark this captured region as inlined, because we don't use outlined 4380 // function directly. 4381 MarkAsInlined(SemaRef.getCurCapturedRegion()); 4382 break; 4383 case OMPD_target: 4384 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, 4385 getTargetRegionParams(SemaRef), Level); 4386 break; 4387 case OMPD_unknown: 4388 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, 4389 getUnknownRegionParams(SemaRef)); 4390 break; 4391 case OMPD_metadirective: 4392 case OMPD_nothing: 4393 default: 4394 llvm_unreachable("Unexpected capture region"); 4395 } 4396 } 4397 } 4398 4399 void SemaOpenMP::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, 4400 Scope *CurScope) { 4401 switch (DKind) { 4402 case OMPD_atomic: 4403 case OMPD_critical: 4404 case OMPD_masked: 4405 case OMPD_master: 4406 case OMPD_section: 4407 case OMPD_tile: 4408 case OMPD_unroll: 4409 case OMPD_reverse: 4410 case OMPD_interchange: 4411 break; 4412 default: 4413 processCapturedRegions(SemaRef, DKind, CurScope, 4414 DSAStack->getConstructLoc()); 4415 break; 4416 } 4417 4418 DSAStack->setContext(SemaRef.CurContext); 4419 handleDeclareVariantConstructTrait(DSAStack, DKind, /*ScopeEntry=*/true); 4420 } 4421 4422 int SemaOpenMP::getNumberOfConstructScopes(unsigned Level) const { 4423 return getOpenMPCaptureLevels(DSAStack->getDirective(Level)); 4424 } 4425 4426 int SemaOpenMP::getOpenMPCaptureLevels(OpenMPDirectiveKind DKind) { 4427 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 4428 getOpenMPCaptureRegions(CaptureRegions, DKind); 4429 return CaptureRegions.size(); 4430 } 4431 4432 static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id, 4433 Expr *CaptureExpr, bool WithInit, 4434 DeclContext *CurContext, 4435 bool AsExpression) { 4436 assert(CaptureExpr); 4437 ASTContext &C = S.getASTContext(); 4438 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts(); 4439 QualType Ty = Init->getType(); 4440 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) { 4441 if (S.getLangOpts().CPlusPlus) { 4442 Ty = C.getLValueReferenceType(Ty); 4443 } else { 4444 Ty = C.getPointerType(Ty); 4445 ExprResult Res = 4446 S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init); 4447 if (!Res.isUsable()) 4448 return nullptr; 4449 Init = Res.get(); 4450 } 4451 WithInit = true; 4452 } 4453 auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty, 4454 CaptureExpr->getBeginLoc()); 4455 if (!WithInit) 4456 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C)); 4457 CurContext->addHiddenDecl(CED); 4458 Sema::TentativeAnalysisScope Trap(S); 4459 S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false); 4460 return CED; 4461 } 4462 4463 static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr, 4464 bool WithInit) { 4465 OMPCapturedExprDecl *CD; 4466 if (VarDecl *VD = S.OpenMP().isOpenMPCapturedDecl(D)) 4467 CD = cast<OMPCapturedExprDecl>(VD); 4468 else 4469 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit, 4470 S.CurContext, 4471 /*AsExpression=*/false); 4472 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(), 4473 CaptureExpr->getExprLoc()); 4474 } 4475 4476 static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref, 4477 StringRef Name) { 4478 CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get(); 4479 if (!Ref) { 4480 OMPCapturedExprDecl *CD = buildCaptureDecl( 4481 S, &S.getASTContext().Idents.get(Name), CaptureExpr, 4482 /*WithInit=*/true, S.CurContext, /*AsExpression=*/true); 4483 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(), 4484 CaptureExpr->getExprLoc()); 4485 } 4486 ExprResult Res = Ref; 4487 if (!S.getLangOpts().CPlusPlus && 4488 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() && 4489 Ref->getType()->isPointerType()) { 4490 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref); 4491 if (!Res.isUsable()) 4492 return ExprError(); 4493 } 4494 return S.DefaultLvalueConversion(Res.get()); 4495 } 4496 4497 namespace { 4498 // OpenMP directives parsed in this section are represented as a 4499 // CapturedStatement with an associated statement. If a syntax error 4500 // is detected during the parsing of the associated statement, the 4501 // compiler must abort processing and close the CapturedStatement. 4502 // 4503 // Combined directives such as 'target parallel' have more than one 4504 // nested CapturedStatements. This RAII ensures that we unwind out 4505 // of all the nested CapturedStatements when an error is found. 4506 class CaptureRegionUnwinderRAII { 4507 private: 4508 Sema &S; 4509 bool &ErrorFound; 4510 OpenMPDirectiveKind DKind = OMPD_unknown; 4511 4512 public: 4513 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound, 4514 OpenMPDirectiveKind DKind) 4515 : S(S), ErrorFound(ErrorFound), DKind(DKind) {} 4516 ~CaptureRegionUnwinderRAII() { 4517 if (ErrorFound) { 4518 int ThisCaptureLevel = S.OpenMP().getOpenMPCaptureLevels(DKind); 4519 while (--ThisCaptureLevel >= 0) 4520 S.ActOnCapturedRegionError(); 4521 } 4522 } 4523 }; 4524 } // namespace 4525 4526 void SemaOpenMP::tryCaptureOpenMPLambdas(ValueDecl *V) { 4527 // Capture variables captured by reference in lambdas for target-based 4528 // directives. 4529 if (!SemaRef.CurContext->isDependentContext() && 4530 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) || 4531 isOpenMPTargetDataManagementDirective( 4532 DSAStack->getCurrentDirective()))) { 4533 QualType Type = V->getType(); 4534 if (const auto *RD = Type.getCanonicalType() 4535 .getNonReferenceType() 4536 ->getAsCXXRecordDecl()) { 4537 bool SavedForceCaptureByReferenceInTargetExecutable = 4538 DSAStack->isForceCaptureByReferenceInTargetExecutable(); 4539 DSAStack->setForceCaptureByReferenceInTargetExecutable( 4540 /*V=*/true); 4541 if (RD->isLambda()) { 4542 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures; 4543 FieldDecl *ThisCapture; 4544 RD->getCaptureFields(Captures, ThisCapture); 4545 for (const LambdaCapture &LC : RD->captures()) { 4546 if (LC.getCaptureKind() == LCK_ByRef) { 4547 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar()); 4548 DeclContext *VDC = VD->getDeclContext(); 4549 if (!VDC->Encloses(SemaRef.CurContext)) 4550 continue; 4551 SemaRef.MarkVariableReferenced(LC.getLocation(), VD); 4552 } else if (LC.getCaptureKind() == LCK_This) { 4553 QualType ThisTy = SemaRef.getCurrentThisType(); 4554 if (!ThisTy.isNull() && getASTContext().typesAreCompatible( 4555 ThisTy, ThisCapture->getType())) 4556 SemaRef.CheckCXXThisCapture(LC.getLocation()); 4557 } 4558 } 4559 } 4560 DSAStack->setForceCaptureByReferenceInTargetExecutable( 4561 SavedForceCaptureByReferenceInTargetExecutable); 4562 } 4563 } 4564 } 4565 4566 static bool checkOrderedOrderSpecified(Sema &S, 4567 const ArrayRef<OMPClause *> Clauses) { 4568 const OMPOrderedClause *Ordered = nullptr; 4569 const OMPOrderClause *Order = nullptr; 4570 4571 for (const OMPClause *Clause : Clauses) { 4572 if (Clause->getClauseKind() == OMPC_ordered) 4573 Ordered = cast<OMPOrderedClause>(Clause); 4574 else if (Clause->getClauseKind() == OMPC_order) { 4575 Order = cast<OMPOrderClause>(Clause); 4576 if (Order->getKind() != OMPC_ORDER_concurrent) 4577 Order = nullptr; 4578 } 4579 if (Ordered && Order) 4580 break; 4581 } 4582 4583 if (Ordered && Order) { 4584 S.Diag(Order->getKindKwLoc(), 4585 diag::err_omp_simple_clause_incompatible_with_ordered) 4586 << getOpenMPClauseName(OMPC_order) 4587 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent) 4588 << SourceRange(Order->getBeginLoc(), Order->getEndLoc()); 4589 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param) 4590 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc()); 4591 return true; 4592 } 4593 return false; 4594 } 4595 4596 StmtResult SemaOpenMP::ActOnOpenMPRegionEnd(StmtResult S, 4597 ArrayRef<OMPClause *> Clauses) { 4598 handleDeclareVariantConstructTrait(DSAStack, DSAStack->getCurrentDirective(), 4599 /* ScopeEntry */ false); 4600 if (!isOpenMPCapturingDirective(DSAStack->getCurrentDirective())) 4601 return S; 4602 4603 bool ErrorFound = false; 4604 CaptureRegionUnwinderRAII CaptureRegionUnwinder( 4605 SemaRef, ErrorFound, DSAStack->getCurrentDirective()); 4606 if (!S.isUsable()) { 4607 ErrorFound = true; 4608 return StmtError(); 4609 } 4610 4611 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 4612 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective()); 4613 OMPOrderedClause *OC = nullptr; 4614 OMPScheduleClause *SC = nullptr; 4615 SmallVector<const OMPLinearClause *, 4> LCs; 4616 SmallVector<const OMPClauseWithPreInit *, 4> PICs; 4617 // This is required for proper codegen. 4618 for (OMPClause *Clause : Clauses) { 4619 if (!getLangOpts().OpenMPSimd && 4620 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) || 4621 DSAStack->getCurrentDirective() == OMPD_target) && 4622 Clause->getClauseKind() == OMPC_in_reduction) { 4623 // Capture taskgroup task_reduction descriptors inside the tasking regions 4624 // with the corresponding in_reduction items. 4625 auto *IRC = cast<OMPInReductionClause>(Clause); 4626 for (Expr *E : IRC->taskgroup_descriptors()) 4627 if (E) 4628 SemaRef.MarkDeclarationsReferencedInExpr(E); 4629 } 4630 if (isOpenMPPrivate(Clause->getClauseKind()) || 4631 Clause->getClauseKind() == OMPC_copyprivate || 4632 (getLangOpts().OpenMPUseTLS && 4633 getASTContext().getTargetInfo().isTLSSupported() && 4634 Clause->getClauseKind() == OMPC_copyin)) { 4635 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin); 4636 // Mark all variables in private list clauses as used in inner region. 4637 for (Stmt *VarRef : Clause->children()) { 4638 if (auto *E = cast_or_null<Expr>(VarRef)) { 4639 SemaRef.MarkDeclarationsReferencedInExpr(E); 4640 } 4641 } 4642 DSAStack->setForceVarCapturing(/*V=*/false); 4643 } else if (CaptureRegions.size() > 1 || 4644 CaptureRegions.back() != OMPD_unknown) { 4645 if (auto *C = OMPClauseWithPreInit::get(Clause)) 4646 PICs.push_back(C); 4647 if (auto *C = OMPClauseWithPostUpdate::get(Clause)) { 4648 if (Expr *E = C->getPostUpdateExpr()) 4649 SemaRef.MarkDeclarationsReferencedInExpr(E); 4650 } 4651 } 4652 if (Clause->getClauseKind() == OMPC_schedule) 4653 SC = cast<OMPScheduleClause>(Clause); 4654 else if (Clause->getClauseKind() == OMPC_ordered) 4655 OC = cast<OMPOrderedClause>(Clause); 4656 else if (Clause->getClauseKind() == OMPC_linear) 4657 LCs.push_back(cast<OMPLinearClause>(Clause)); 4658 } 4659 // Capture allocator expressions if used. 4660 for (Expr *E : DSAStack->getInnerAllocators()) 4661 SemaRef.MarkDeclarationsReferencedInExpr(E); 4662 // OpenMP, 2.7.1 Loop Construct, Restrictions 4663 // The nonmonotonic modifier cannot be specified if an ordered clause is 4664 // specified. 4665 if (SC && 4666 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic || 4667 SC->getSecondScheduleModifier() == 4668 OMPC_SCHEDULE_MODIFIER_nonmonotonic) && 4669 OC) { 4670 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic 4671 ? SC->getFirstScheduleModifierLoc() 4672 : SC->getSecondScheduleModifierLoc(), 4673 diag::err_omp_simple_clause_incompatible_with_ordered) 4674 << getOpenMPClauseName(OMPC_schedule) 4675 << getOpenMPSimpleClauseTypeName(OMPC_schedule, 4676 OMPC_SCHEDULE_MODIFIER_nonmonotonic) 4677 << SourceRange(OC->getBeginLoc(), OC->getEndLoc()); 4678 ErrorFound = true; 4679 } 4680 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions. 4681 // If an order(concurrent) clause is present, an ordered clause may not appear 4682 // on the same directive. 4683 if (checkOrderedOrderSpecified(SemaRef, Clauses)) 4684 ErrorFound = true; 4685 if (!LCs.empty() && OC && OC->getNumForLoops()) { 4686 for (const OMPLinearClause *C : LCs) { 4687 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered) 4688 << SourceRange(OC->getBeginLoc(), OC->getEndLoc()); 4689 } 4690 ErrorFound = true; 4691 } 4692 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) && 4693 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC && 4694 OC->getNumForLoops()) { 4695 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd) 4696 << getOpenMPDirectiveName(DSAStack->getCurrentDirective()); 4697 ErrorFound = true; 4698 } 4699 if (ErrorFound) { 4700 return StmtError(); 4701 } 4702 StmtResult SR = S; 4703 unsigned CompletedRegions = 0; 4704 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) { 4705 // Mark all variables in private list clauses as used in inner region. 4706 // Required for proper codegen of combined directives. 4707 // TODO: add processing for other clauses. 4708 if (ThisCaptureRegion != OMPD_unknown) { 4709 for (const clang::OMPClauseWithPreInit *C : PICs) { 4710 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion(); 4711 // Find the particular capture region for the clause if the 4712 // directive is a combined one with multiple capture regions. 4713 // If the directive is not a combined one, the capture region 4714 // associated with the clause is OMPD_unknown and is generated 4715 // only once. 4716 if (CaptureRegion == ThisCaptureRegion || 4717 CaptureRegion == OMPD_unknown) { 4718 if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) { 4719 for (Decl *D : DS->decls()) 4720 SemaRef.MarkVariableReferenced(D->getLocation(), 4721 cast<VarDecl>(D)); 4722 } 4723 } 4724 } 4725 } 4726 if (ThisCaptureRegion == OMPD_target) { 4727 // Capture allocator traits in the target region. They are used implicitly 4728 // and, thus, are not captured by default. 4729 for (OMPClause *C : Clauses) { 4730 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) { 4731 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End; 4732 ++I) { 4733 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I); 4734 if (Expr *E = D.AllocatorTraits) 4735 SemaRef.MarkDeclarationsReferencedInExpr(E); 4736 } 4737 continue; 4738 } 4739 } 4740 } 4741 if (ThisCaptureRegion == OMPD_parallel) { 4742 // Capture temp arrays for inscan reductions and locals in aligned 4743 // clauses. 4744 for (OMPClause *C : Clauses) { 4745 if (auto *RC = dyn_cast<OMPReductionClause>(C)) { 4746 if (RC->getModifier() != OMPC_REDUCTION_inscan) 4747 continue; 4748 for (Expr *E : RC->copy_array_temps()) 4749 if (E) 4750 SemaRef.MarkDeclarationsReferencedInExpr(E); 4751 } 4752 if (auto *AC = dyn_cast<OMPAlignedClause>(C)) { 4753 for (Expr *E : AC->varlists()) 4754 SemaRef.MarkDeclarationsReferencedInExpr(E); 4755 } 4756 } 4757 } 4758 if (++CompletedRegions == CaptureRegions.size()) 4759 DSAStack->setBodyComplete(); 4760 SR = SemaRef.ActOnCapturedRegionEnd(SR.get()); 4761 } 4762 return SR; 4763 } 4764 4765 static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion, 4766 OpenMPDirectiveKind CancelRegion, 4767 SourceLocation StartLoc) { 4768 // CancelRegion is only needed for cancel and cancellation_point. 4769 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point) 4770 return false; 4771 4772 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for || 4773 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup) 4774 return false; 4775 4776 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region) 4777 << getOpenMPDirectiveName(CancelRegion); 4778 return true; 4779 } 4780 4781 static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack, 4782 OpenMPDirectiveKind CurrentRegion, 4783 const DeclarationNameInfo &CurrentName, 4784 OpenMPDirectiveKind CancelRegion, 4785 OpenMPBindClauseKind BindKind, 4786 SourceLocation StartLoc) { 4787 if (!Stack->getCurScope()) 4788 return false; 4789 4790 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective(); 4791 OpenMPDirectiveKind OffendingRegion = ParentRegion; 4792 bool NestingProhibited = false; 4793 bool CloseNesting = true; 4794 bool OrphanSeen = false; 4795 enum { 4796 NoRecommend, 4797 ShouldBeInParallelRegion, 4798 ShouldBeInOrderedRegion, 4799 ShouldBeInTargetRegion, 4800 ShouldBeInTeamsRegion, 4801 ShouldBeInLoopSimdRegion, 4802 } Recommend = NoRecommend; 4803 4804 SmallVector<OpenMPDirectiveKind, 4> LeafOrComposite; 4805 ArrayRef<OpenMPDirectiveKind> ParentLOC = 4806 getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite); 4807 OpenMPDirectiveKind EnclosingConstruct = ParentLOC.back(); 4808 4809 if (SemaRef.LangOpts.OpenMP >= 51 && Stack->isParentOrderConcurrent() && 4810 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_loop && 4811 CurrentRegion != OMPD_parallel && 4812 !isOpenMPCombinedParallelADirective(CurrentRegion)) { 4813 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order) 4814 << getOpenMPDirectiveName(CurrentRegion); 4815 return true; 4816 } 4817 if (isOpenMPSimdDirective(ParentRegion) && 4818 ((SemaRef.LangOpts.OpenMP <= 45 && CurrentRegion != OMPD_ordered) || 4819 (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion != OMPD_ordered && 4820 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic && 4821 CurrentRegion != OMPD_scan))) { 4822 // OpenMP [2.16, Nesting of Regions] 4823 // OpenMP constructs may not be nested inside a simd region. 4824 // OpenMP [2.8.1,simd Construct, Restrictions] 4825 // An ordered construct with the simd clause is the only OpenMP 4826 // construct that can appear in the simd region. 4827 // Allowing a SIMD construct nested in another SIMD construct is an 4828 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning 4829 // message. 4830 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions] 4831 // The only OpenMP constructs that can be encountered during execution of 4832 // a simd region are the atomic construct, the loop construct, the simd 4833 // construct and the ordered construct with the simd clause. 4834 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd) 4835 ? diag::err_omp_prohibited_region_simd 4836 : diag::warn_omp_nesting_simd) 4837 << (SemaRef.LangOpts.OpenMP >= 50 ? 1 : 0); 4838 return CurrentRegion != OMPD_simd; 4839 } 4840 if (EnclosingConstruct == OMPD_atomic) { 4841 // OpenMP [2.16, Nesting of Regions] 4842 // OpenMP constructs may not be nested inside an atomic region. 4843 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic); 4844 return true; 4845 } 4846 if (CurrentRegion == OMPD_section) { 4847 // OpenMP [2.7.2, sections Construct, Restrictions] 4848 // Orphaned section directives are prohibited. That is, the section 4849 // directives must appear within the sections construct and must not be 4850 // encountered elsewhere in the sections region. 4851 if (EnclosingConstruct != OMPD_sections) { 4852 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive) 4853 << (ParentRegion != OMPD_unknown) 4854 << getOpenMPDirectiveName(ParentRegion); 4855 return true; 4856 } 4857 return false; 4858 } 4859 // Allow some constructs (except teams and cancellation constructs) to be 4860 // orphaned (they could be used in functions, called from OpenMP regions 4861 // with the required preconditions). 4862 if (ParentRegion == OMPD_unknown && 4863 !isOpenMPNestingTeamsDirective(CurrentRegion) && 4864 CurrentRegion != OMPD_cancellation_point && 4865 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan) 4866 return false; 4867 // Checks needed for mapping "loop" construct. Please check mapLoopConstruct 4868 // for a detailed explanation 4869 if (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion == OMPD_loop && 4870 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) && 4871 (isOpenMPWorksharingDirective(ParentRegion) || 4872 EnclosingConstruct == OMPD_loop)) { 4873 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4; 4874 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region) 4875 << true << getOpenMPDirectiveName(ParentRegion) << ErrorMsgNumber 4876 << getOpenMPDirectiveName(CurrentRegion); 4877 return true; 4878 } 4879 if (CurrentRegion == OMPD_cancellation_point || 4880 CurrentRegion == OMPD_cancel) { 4881 // OpenMP [2.16, Nesting of Regions] 4882 // A cancellation point construct for which construct-type-clause is 4883 // taskgroup must be nested inside a task construct. A cancellation 4884 // point construct for which construct-type-clause is not taskgroup must 4885 // be closely nested inside an OpenMP construct that matches the type 4886 // specified in construct-type-clause. 4887 // A cancel construct for which construct-type-clause is taskgroup must be 4888 // nested inside a task construct. A cancel construct for which 4889 // construct-type-clause is not taskgroup must be closely nested inside an 4890 // OpenMP construct that matches the type specified in 4891 // construct-type-clause. 4892 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(ParentRegion); 4893 if (CancelRegion == OMPD_taskgroup) { 4894 NestingProhibited = EnclosingConstruct != OMPD_task && 4895 (SemaRef.getLangOpts().OpenMP < 50 || 4896 EnclosingConstruct != OMPD_taskloop); 4897 } else if (CancelRegion == OMPD_sections) { 4898 NestingProhibited = EnclosingConstruct != OMPD_section && 4899 EnclosingConstruct != OMPD_sections; 4900 } else { 4901 NestingProhibited = CancelRegion != Leafs.back(); 4902 } 4903 OrphanSeen = ParentRegion == OMPD_unknown; 4904 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) { 4905 // OpenMP 5.1 [2.22, Nesting of Regions] 4906 // A masked region may not be closely nested inside a worksharing, loop, 4907 // atomic, task, or taskloop region. 4908 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) || 4909 isOpenMPGenericLoopDirective(ParentRegion) || 4910 isOpenMPTaskingDirective(ParentRegion); 4911 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) { 4912 // OpenMP [2.16, Nesting of Regions] 4913 // A critical region may not be nested (closely or otherwise) inside a 4914 // critical region with the same name. Note that this restriction is not 4915 // sufficient to prevent deadlock. 4916 SourceLocation PreviousCriticalLoc; 4917 bool DeadLock = Stack->hasDirective( 4918 [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K, 4919 const DeclarationNameInfo &DNI, 4920 SourceLocation Loc) { 4921 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) { 4922 PreviousCriticalLoc = Loc; 4923 return true; 4924 } 4925 return false; 4926 }, 4927 false /* skip top directive */); 4928 if (DeadLock) { 4929 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name) 4930 << CurrentName.getName(); 4931 if (PreviousCriticalLoc.isValid()) 4932 SemaRef.Diag(PreviousCriticalLoc, 4933 diag::note_omp_previous_critical_region); 4934 return true; 4935 } 4936 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) { 4937 // OpenMP 5.1 [2.22, Nesting of Regions] 4938 // A scope region may not be closely nested inside a worksharing, loop, 4939 // task, taskloop, critical, ordered, atomic, or masked region. 4940 // OpenMP 5.1 [2.22, Nesting of Regions] 4941 // A barrier region may not be closely nested inside a worksharing, loop, 4942 // task, taskloop, critical, ordered, atomic, or masked region. 4943 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) || 4944 isOpenMPGenericLoopDirective(ParentRegion) || 4945 isOpenMPTaskingDirective(ParentRegion) || 4946 llvm::is_contained({OMPD_masked, OMPD_master, 4947 OMPD_critical, OMPD_ordered}, 4948 EnclosingConstruct); 4949 } else if (isOpenMPWorksharingDirective(CurrentRegion) && 4950 !isOpenMPParallelDirective(CurrentRegion) && 4951 !isOpenMPTeamsDirective(CurrentRegion)) { 4952 // OpenMP 5.1 [2.22, Nesting of Regions] 4953 // A loop region that binds to a parallel region or a worksharing region 4954 // may not be closely nested inside a worksharing, loop, task, taskloop, 4955 // critical, ordered, atomic, or masked region. 4956 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) || 4957 isOpenMPGenericLoopDirective(ParentRegion) || 4958 isOpenMPTaskingDirective(ParentRegion) || 4959 llvm::is_contained({OMPD_masked, OMPD_master, 4960 OMPD_critical, OMPD_ordered}, 4961 EnclosingConstruct); 4962 Recommend = ShouldBeInParallelRegion; 4963 } else if (CurrentRegion == OMPD_ordered) { 4964 // OpenMP [2.16, Nesting of Regions] 4965 // An ordered region may not be closely nested inside a critical, 4966 // atomic, or explicit task region. 4967 // An ordered region must be closely nested inside a loop region (or 4968 // parallel loop region) with an ordered clause. 4969 // OpenMP [2.8.1,simd Construct, Restrictions] 4970 // An ordered construct with the simd clause is the only OpenMP construct 4971 // that can appear in the simd region. 4972 NestingProhibited = EnclosingConstruct == OMPD_critical || 4973 isOpenMPTaskingDirective(ParentRegion) || 4974 !(isOpenMPSimdDirective(ParentRegion) || 4975 Stack->isParentOrderedRegion()); 4976 Recommend = ShouldBeInOrderedRegion; 4977 } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) { 4978 // OpenMP [2.16, Nesting of Regions] 4979 // If specified, a teams construct must be contained within a target 4980 // construct. 4981 NestingProhibited = 4982 (SemaRef.LangOpts.OpenMP <= 45 && EnclosingConstruct != OMPD_target) || 4983 (SemaRef.LangOpts.OpenMP >= 50 && EnclosingConstruct != OMPD_unknown && 4984 EnclosingConstruct != OMPD_target); 4985 OrphanSeen = ParentRegion == OMPD_unknown; 4986 Recommend = ShouldBeInTargetRegion; 4987 } else if (CurrentRegion == OMPD_scan) { 4988 if (SemaRef.LangOpts.OpenMP >= 50) { 4989 // OpenMP spec 5.0 and 5.1 require scan to be directly enclosed by for, 4990 // simd, or for simd. This has to take into account combined directives. 4991 // In 5.2 this seems to be implied by the fact that the specified 4992 // separated constructs are do, for, and simd. 4993 NestingProhibited = !llvm::is_contained( 4994 {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct); 4995 } else { 4996 NestingProhibited = true; 4997 } 4998 OrphanSeen = ParentRegion == OMPD_unknown; 4999 Recommend = ShouldBeInLoopSimdRegion; 5000 } 5001 if (!NestingProhibited && !isOpenMPTargetExecutionDirective(CurrentRegion) && 5002 !isOpenMPTargetDataManagementDirective(CurrentRegion) && 5003 EnclosingConstruct == OMPD_teams) { 5004 // OpenMP [5.1, 2.22, Nesting of Regions] 5005 // distribute, distribute simd, distribute parallel worksharing-loop, 5006 // distribute parallel worksharing-loop SIMD, loop, parallel regions, 5007 // including any parallel regions arising from combined constructs, 5008 // omp_get_num_teams() regions, and omp_get_team_num() regions are the 5009 // only OpenMP regions that may be strictly nested inside the teams 5010 // region. 5011 // 5012 // As an extension, we permit atomic within teams as well. 5013 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) && 5014 !isOpenMPDistributeDirective(CurrentRegion) && 5015 CurrentRegion != OMPD_loop && 5016 !(SemaRef.getLangOpts().OpenMPExtensions && 5017 CurrentRegion == OMPD_atomic); 5018 Recommend = ShouldBeInParallelRegion; 5019 } 5020 if (!NestingProhibited && CurrentRegion == OMPD_loop) { 5021 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions] 5022 // If the bind clause is present on the loop construct and binding is 5023 // teams then the corresponding loop region must be strictly nested inside 5024 // a teams region. 5025 NestingProhibited = 5026 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams; 5027 Recommend = ShouldBeInTeamsRegion; 5028 } 5029 if (!NestingProhibited && isOpenMPNestingDistributeDirective(CurrentRegion)) { 5030 // OpenMP 4.5 [2.17 Nesting of Regions] 5031 // The region associated with the distribute construct must be strictly 5032 // nested inside a teams region 5033 NestingProhibited = EnclosingConstruct != OMPD_teams; 5034 Recommend = ShouldBeInTeamsRegion; 5035 } 5036 if (!NestingProhibited && 5037 (isOpenMPTargetExecutionDirective(CurrentRegion) || 5038 isOpenMPTargetDataManagementDirective(CurrentRegion))) { 5039 // OpenMP 4.5 [2.17 Nesting of Regions] 5040 // If a target, target update, target data, target enter data, or 5041 // target exit data construct is encountered during execution of a 5042 // target region, the behavior is unspecified. 5043 NestingProhibited = Stack->hasDirective( 5044 [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &, 5045 SourceLocation) { 5046 if (isOpenMPTargetExecutionDirective(K)) { 5047 OffendingRegion = K; 5048 return true; 5049 } 5050 return false; 5051 }, 5052 false /* don't skip top directive */); 5053 CloseNesting = false; 5054 } 5055 if (NestingProhibited) { 5056 if (OrphanSeen) { 5057 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive) 5058 << getOpenMPDirectiveName(CurrentRegion) << Recommend; 5059 } else { 5060 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region) 5061 << CloseNesting << getOpenMPDirectiveName(OffendingRegion) 5062 << Recommend << getOpenMPDirectiveName(CurrentRegion); 5063 } 5064 return true; 5065 } 5066 return false; 5067 } 5068 5069 struct Kind2Unsigned { 5070 using argument_type = OpenMPDirectiveKind; 5071 unsigned operator()(argument_type DK) { return unsigned(DK); } 5072 }; 5073 static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind, 5074 ArrayRef<OMPClause *> Clauses, 5075 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) { 5076 bool ErrorFound = false; 5077 unsigned NamedModifiersNumber = 0; 5078 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers; 5079 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1); 5080 SmallVector<SourceLocation, 4> NameModifierLoc; 5081 for (const OMPClause *C : Clauses) { 5082 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) { 5083 // At most one if clause without a directive-name-modifier can appear on 5084 // the directive. 5085 OpenMPDirectiveKind CurNM = IC->getNameModifier(); 5086 if (FoundNameModifiers[CurNM]) { 5087 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause) 5088 << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if) 5089 << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM); 5090 ErrorFound = true; 5091 } else if (CurNM != OMPD_unknown) { 5092 NameModifierLoc.push_back(IC->getNameModifierLoc()); 5093 ++NamedModifiersNumber; 5094 } 5095 FoundNameModifiers[CurNM] = IC; 5096 if (CurNM == OMPD_unknown) 5097 continue; 5098 // Check if the specified name modifier is allowed for the current 5099 // directive. 5100 // At most one if clause with the particular directive-name-modifier can 5101 // appear on the directive. 5102 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) { 5103 S.Diag(IC->getNameModifierLoc(), 5104 diag::err_omp_wrong_if_directive_name_modifier) 5105 << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind); 5106 ErrorFound = true; 5107 } 5108 } 5109 } 5110 // If any if clause on the directive includes a directive-name-modifier then 5111 // all if clauses on the directive must include a directive-name-modifier. 5112 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) { 5113 if (NamedModifiersNumber == AllowedNameModifiers.size()) { 5114 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(), 5115 diag::err_omp_no_more_if_clause); 5116 } else { 5117 std::string Values; 5118 std::string Sep(", "); 5119 unsigned AllowedCnt = 0; 5120 unsigned TotalAllowedNum = 5121 AllowedNameModifiers.size() - NamedModifiersNumber; 5122 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End; 5123 ++Cnt) { 5124 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt]; 5125 if (!FoundNameModifiers[NM]) { 5126 Values += "'"; 5127 Values += getOpenMPDirectiveName(NM); 5128 Values += "'"; 5129 if (AllowedCnt + 2 == TotalAllowedNum) 5130 Values += " or "; 5131 else if (AllowedCnt + 1 != TotalAllowedNum) 5132 Values += Sep; 5133 ++AllowedCnt; 5134 } 5135 } 5136 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(), 5137 diag::err_omp_unnamed_if_clause) 5138 << (TotalAllowedNum > 1) << Values; 5139 } 5140 for (SourceLocation Loc : NameModifierLoc) { 5141 S.Diag(Loc, diag::note_omp_previous_named_if_clause); 5142 } 5143 ErrorFound = true; 5144 } 5145 return ErrorFound; 5146 } 5147 5148 static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr, 5149 SourceLocation &ELoc, 5150 SourceRange &ERange, 5151 bool AllowArraySection, 5152 StringRef DiagType) { 5153 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() || 5154 RefExpr->containsUnexpandedParameterPack()) 5155 return std::make_pair(nullptr, true); 5156 5157 // OpenMP [3.1, C/C++] 5158 // A list item is a variable name. 5159 // OpenMP [2.9.3.3, Restrictions, p.1] 5160 // A variable that is part of another variable (as an array or 5161 // structure element) cannot appear in a private clause. 5162 RefExpr = RefExpr->IgnoreParens(); 5163 enum { 5164 NoArrayExpr = -1, 5165 ArraySubscript = 0, 5166 OMPArraySection = 1 5167 } IsArrayExpr = NoArrayExpr; 5168 if (AllowArraySection) { 5169 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) { 5170 Expr *Base = ASE->getBase()->IgnoreParenImpCasts(); 5171 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 5172 Base = TempASE->getBase()->IgnoreParenImpCasts(); 5173 RefExpr = Base; 5174 IsArrayExpr = ArraySubscript; 5175 } else if (auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) { 5176 Expr *Base = OASE->getBase()->IgnoreParenImpCasts(); 5177 while (auto *TempOASE = dyn_cast<ArraySectionExpr>(Base)) 5178 Base = TempOASE->getBase()->IgnoreParenImpCasts(); 5179 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 5180 Base = TempASE->getBase()->IgnoreParenImpCasts(); 5181 RefExpr = Base; 5182 IsArrayExpr = OMPArraySection; 5183 } 5184 } 5185 ELoc = RefExpr->getExprLoc(); 5186 ERange = RefExpr->getSourceRange(); 5187 RefExpr = RefExpr->IgnoreParenImpCasts(); 5188 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr); 5189 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr); 5190 if ((!DE || !isa<VarDecl>(DE->getDecl())) && 5191 (S.getCurrentThisType().isNull() || !ME || 5192 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) || 5193 !isa<FieldDecl>(ME->getMemberDecl()))) { 5194 if (IsArrayExpr != NoArrayExpr) { 5195 S.Diag(ELoc, diag::err_omp_expected_base_var_name) 5196 << IsArrayExpr << ERange; 5197 } else if (!DiagType.empty()) { 5198 unsigned DiagSelect = S.getLangOpts().CPlusPlus 5199 ? (S.getCurrentThisType().isNull() ? 1 : 2) 5200 : 0; 5201 S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type) 5202 << DiagSelect << DiagType << ERange; 5203 } else { 5204 S.Diag(ELoc, 5205 AllowArraySection 5206 ? diag::err_omp_expected_var_name_member_expr_or_array_item 5207 : diag::err_omp_expected_var_name_member_expr) 5208 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange; 5209 } 5210 return std::make_pair(nullptr, false); 5211 } 5212 return std::make_pair( 5213 getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false); 5214 } 5215 5216 namespace { 5217 /// Checks if the allocator is used in uses_allocators clause to be allowed in 5218 /// target regions. 5219 class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> { 5220 DSAStackTy *S = nullptr; 5221 5222 public: 5223 bool VisitDeclRefExpr(const DeclRefExpr *E) { 5224 return S->isUsesAllocatorsDecl(E->getDecl()) 5225 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) == 5226 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait; 5227 } 5228 bool VisitStmt(const Stmt *S) { 5229 for (const Stmt *Child : S->children()) { 5230 if (Child && Visit(Child)) 5231 return true; 5232 } 5233 return false; 5234 } 5235 explicit AllocatorChecker(DSAStackTy *S) : S(S) {} 5236 }; 5237 } // namespace 5238 5239 static void checkAllocateClauses(Sema &S, DSAStackTy *Stack, 5240 ArrayRef<OMPClause *> Clauses) { 5241 assert(!S.CurContext->isDependentContext() && 5242 "Expected non-dependent context."); 5243 auto AllocateRange = 5244 llvm::make_filter_range(Clauses, OMPAllocateClause::classof); 5245 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy; 5246 auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) { 5247 return isOpenMPPrivate(C->getClauseKind()); 5248 }); 5249 for (OMPClause *Cl : PrivateRange) { 5250 MutableArrayRef<Expr *>::iterator I, It, Et; 5251 if (Cl->getClauseKind() == OMPC_private) { 5252 auto *PC = cast<OMPPrivateClause>(Cl); 5253 I = PC->private_copies().begin(); 5254 It = PC->varlist_begin(); 5255 Et = PC->varlist_end(); 5256 } else if (Cl->getClauseKind() == OMPC_firstprivate) { 5257 auto *PC = cast<OMPFirstprivateClause>(Cl); 5258 I = PC->private_copies().begin(); 5259 It = PC->varlist_begin(); 5260 Et = PC->varlist_end(); 5261 } else if (Cl->getClauseKind() == OMPC_lastprivate) { 5262 auto *PC = cast<OMPLastprivateClause>(Cl); 5263 I = PC->private_copies().begin(); 5264 It = PC->varlist_begin(); 5265 Et = PC->varlist_end(); 5266 } else if (Cl->getClauseKind() == OMPC_linear) { 5267 auto *PC = cast<OMPLinearClause>(Cl); 5268 I = PC->privates().begin(); 5269 It = PC->varlist_begin(); 5270 Et = PC->varlist_end(); 5271 } else if (Cl->getClauseKind() == OMPC_reduction) { 5272 auto *PC = cast<OMPReductionClause>(Cl); 5273 I = PC->privates().begin(); 5274 It = PC->varlist_begin(); 5275 Et = PC->varlist_end(); 5276 } else if (Cl->getClauseKind() == OMPC_task_reduction) { 5277 auto *PC = cast<OMPTaskReductionClause>(Cl); 5278 I = PC->privates().begin(); 5279 It = PC->varlist_begin(); 5280 Et = PC->varlist_end(); 5281 } else if (Cl->getClauseKind() == OMPC_in_reduction) { 5282 auto *PC = cast<OMPInReductionClause>(Cl); 5283 I = PC->privates().begin(); 5284 It = PC->varlist_begin(); 5285 Et = PC->varlist_end(); 5286 } else { 5287 llvm_unreachable("Expected private clause."); 5288 } 5289 for (Expr *E : llvm::make_range(It, Et)) { 5290 if (!*I) { 5291 ++I; 5292 continue; 5293 } 5294 SourceLocation ELoc; 5295 SourceRange ERange; 5296 Expr *SimpleRefExpr = E; 5297 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange, 5298 /*AllowArraySection=*/true); 5299 DeclToCopy.try_emplace(Res.first, 5300 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl())); 5301 ++I; 5302 } 5303 } 5304 for (OMPClause *C : AllocateRange) { 5305 auto *AC = cast<OMPAllocateClause>(C); 5306 if (S.getLangOpts().OpenMP >= 50 && 5307 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() && 5308 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) && 5309 AC->getAllocator()) { 5310 Expr *Allocator = AC->getAllocator(); 5311 // OpenMP, 2.12.5 target Construct 5312 // Memory allocators that do not appear in a uses_allocators clause cannot 5313 // appear as an allocator in an allocate clause or be used in the target 5314 // region unless a requires directive with the dynamic_allocators clause 5315 // is present in the same compilation unit. 5316 AllocatorChecker Checker(Stack); 5317 if (Checker.Visit(Allocator)) 5318 S.Diag(Allocator->getExprLoc(), 5319 diag::err_omp_allocator_not_in_uses_allocators) 5320 << Allocator->getSourceRange(); 5321 } 5322 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind = 5323 getAllocatorKind(S, Stack, AC->getAllocator()); 5324 // OpenMP, 2.11.4 allocate Clause, Restrictions. 5325 // For task, taskloop or target directives, allocation requests to memory 5326 // allocators with the trait access set to thread result in unspecified 5327 // behavior. 5328 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc && 5329 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) || 5330 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) { 5331 S.Diag(AC->getAllocator()->getExprLoc(), 5332 diag::warn_omp_allocate_thread_on_task_target_directive) 5333 << getOpenMPDirectiveName(Stack->getCurrentDirective()); 5334 } 5335 for (Expr *E : AC->varlists()) { 5336 SourceLocation ELoc; 5337 SourceRange ERange; 5338 Expr *SimpleRefExpr = E; 5339 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange); 5340 ValueDecl *VD = Res.first; 5341 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false); 5342 if (!isOpenMPPrivate(Data.CKind)) { 5343 S.Diag(E->getExprLoc(), 5344 diag::err_omp_expected_private_copy_for_allocate); 5345 continue; 5346 } 5347 VarDecl *PrivateVD = DeclToCopy[VD]; 5348 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD, 5349 AllocatorKind, AC->getAllocator())) 5350 continue; 5351 // Placeholder until allocate clause supports align modifier. 5352 Expr *Alignment = nullptr; 5353 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(), 5354 Alignment, E->getSourceRange()); 5355 } 5356 } 5357 } 5358 5359 namespace { 5360 /// Rewrite statements and expressions for Sema \p Actions CurContext. 5361 /// 5362 /// Used to wrap already parsed statements/expressions into a new CapturedStmt 5363 /// context. DeclRefExpr used inside the new context are changed to refer to the 5364 /// captured variable instead. 5365 class CaptureVars : public TreeTransform<CaptureVars> { 5366 using BaseTransform = TreeTransform<CaptureVars>; 5367 5368 public: 5369 CaptureVars(Sema &Actions) : BaseTransform(Actions) {} 5370 5371 bool AlwaysRebuild() { return true; } 5372 }; 5373 } // namespace 5374 5375 static VarDecl *precomputeExpr(Sema &Actions, 5376 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E, 5377 StringRef Name) { 5378 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E)); 5379 VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr, 5380 dyn_cast<DeclRefExpr>(E->IgnoreImplicit())); 5381 auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess( 5382 Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {}))); 5383 Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false); 5384 BodyStmts.push_back(NewDeclStmt); 5385 return NewVar; 5386 } 5387 5388 /// Create a closure that computes the number of iterations of a loop. 5389 /// 5390 /// \param Actions The Sema object. 5391 /// \param LogicalTy Type for the logical iteration number. 5392 /// \param Rel Comparison operator of the loop condition. 5393 /// \param StartExpr Value of the loop counter at the first iteration. 5394 /// \param StopExpr Expression the loop counter is compared against in the loop 5395 /// condition. \param StepExpr Amount of increment after each iteration. 5396 /// 5397 /// \return Closure (CapturedStmt) of the distance calculation. 5398 static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy, 5399 BinaryOperator::Opcode Rel, 5400 Expr *StartExpr, Expr *StopExpr, 5401 Expr *StepExpr) { 5402 ASTContext &Ctx = Actions.getASTContext(); 5403 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy); 5404 5405 // Captured regions currently don't support return values, we use an 5406 // out-parameter instead. All inputs are implicit captures. 5407 // TODO: Instead of capturing each DeclRefExpr occurring in 5408 // StartExpr/StopExpr/Step, these could also be passed as a value capture. 5409 QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy); 5410 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy}, 5411 {StringRef(), QualType()}}; 5412 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params); 5413 5414 Stmt *Body; 5415 { 5416 Sema::CompoundScopeRAII CompoundScope(Actions); 5417 CapturedDecl *CS = cast<CapturedDecl>(Actions.CurContext); 5418 5419 // Get the LValue expression for the result. 5420 ImplicitParamDecl *DistParam = CS->getParam(0); 5421 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr( 5422 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr); 5423 5424 SmallVector<Stmt *, 4> BodyStmts; 5425 5426 // Capture all referenced variable references. 5427 // TODO: Instead of computing NewStart/NewStop/NewStep inside the 5428 // CapturedStmt, we could compute them before and capture the result, to be 5429 // used jointly with the LoopVar function. 5430 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start"); 5431 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop"); 5432 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step"); 5433 auto BuildVarRef = [&](VarDecl *VD) { 5434 return buildDeclRefExpr(Actions, VD, VD->getType(), {}); 5435 }; 5436 5437 IntegerLiteral *Zero = IntegerLiteral::Create( 5438 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {}); 5439 IntegerLiteral *One = IntegerLiteral::Create( 5440 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {}); 5441 Expr *Dist; 5442 if (Rel == BO_NE) { 5443 // When using a != comparison, the increment can be +1 or -1. This can be 5444 // dynamic at runtime, so we need to check for the direction. 5445 Expr *IsNegStep = AssertSuccess( 5446 Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero)); 5447 5448 // Positive increment. 5449 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp( 5450 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart))); 5451 ForwardRange = AssertSuccess( 5452 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange)); 5453 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp( 5454 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep))); 5455 5456 // Negative increment. 5457 Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp( 5458 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop))); 5459 BackwardRange = AssertSuccess( 5460 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange)); 5461 Expr *NegIncAmount = AssertSuccess( 5462 Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep))); 5463 Expr *BackwardDist = AssertSuccess( 5464 Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount)); 5465 5466 // Use the appropriate case. 5467 Dist = AssertSuccess(Actions.ActOnConditionalOp( 5468 {}, {}, IsNegStep, BackwardDist, ForwardDist)); 5469 } else { 5470 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) && 5471 "Expected one of these relational operators"); 5472 5473 // We can derive the direction from any other comparison operator. It is 5474 // non well-formed OpenMP if Step increments/decrements in the other 5475 // directions. Whether at least the first iteration passes the loop 5476 // condition. 5477 Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp( 5478 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop))); 5479 5480 // Compute the range between first and last counter value. 5481 Expr *Range; 5482 if (Rel == BO_GE || Rel == BO_GT) 5483 Range = AssertSuccess(Actions.BuildBinOp( 5484 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop))); 5485 else 5486 Range = AssertSuccess(Actions.BuildBinOp( 5487 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart))); 5488 5489 // Ensure unsigned range space. 5490 Range = 5491 AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range)); 5492 5493 if (Rel == BO_LE || Rel == BO_GE) { 5494 // Add one to the range if the relational operator is inclusive. 5495 Range = 5496 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One)); 5497 } 5498 5499 // Divide by the absolute step amount. If the range is not a multiple of 5500 // the step size, rounding-up the effective upper bound ensures that the 5501 // last iteration is included. 5502 // Note that the rounding-up may cause an overflow in a temporary that 5503 // could be avoided, but would have occurred in a C-style for-loop as 5504 // well. 5505 Expr *Divisor = BuildVarRef(NewStep); 5506 if (Rel == BO_GE || Rel == BO_GT) 5507 Divisor = 5508 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor)); 5509 Expr *DivisorMinusOne = 5510 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One)); 5511 Expr *RangeRoundUp = AssertSuccess( 5512 Actions.BuildBinOp(nullptr, {}, BO_Add, Range, DivisorMinusOne)); 5513 Dist = AssertSuccess( 5514 Actions.BuildBinOp(nullptr, {}, BO_Div, RangeRoundUp, Divisor)); 5515 5516 // If there is not at least one iteration, the range contains garbage. Fix 5517 // to zero in this case. 5518 Dist = AssertSuccess( 5519 Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero)); 5520 } 5521 5522 // Assign the result to the out-parameter. 5523 Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp( 5524 Actions.getCurScope(), {}, BO_Assign, DistRef, Dist)); 5525 BodyStmts.push_back(ResultAssign); 5526 5527 Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false)); 5528 } 5529 5530 return cast<CapturedStmt>( 5531 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body))); 5532 } 5533 5534 /// Create a closure that computes the loop variable from the logical iteration 5535 /// number. 5536 /// 5537 /// \param Actions The Sema object. 5538 /// \param LoopVarTy Type for the loop variable used for result value. 5539 /// \param LogicalTy Type for the logical iteration number. 5540 /// \param StartExpr Value of the loop counter at the first iteration. 5541 /// \param Step Amount of increment after each iteration. 5542 /// \param Deref Whether the loop variable is a dereference of the loop 5543 /// counter variable. 5544 /// 5545 /// \return Closure (CapturedStmt) of the loop value calculation. 5546 static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy, 5547 QualType LogicalTy, 5548 DeclRefExpr *StartExpr, Expr *Step, 5549 bool Deref) { 5550 ASTContext &Ctx = Actions.getASTContext(); 5551 5552 // Pass the result as an out-parameter. Passing as return value would require 5553 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to 5554 // invoke a copy constructor. 5555 QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy); 5556 SemaOpenMP::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy}, 5557 {"Logical", LogicalTy}, 5558 {StringRef(), QualType()}}; 5559 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params); 5560 5561 // Capture the initial iterator which represents the LoopVar value at the 5562 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update 5563 // it in every iteration, capture it by value before it is modified. 5564 VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl()); 5565 bool Invalid = Actions.tryCaptureVariable(StartVar, {}, 5566 Sema::TryCapture_ExplicitByVal, {}); 5567 (void)Invalid; 5568 assert(!Invalid && "Expecting capture-by-value to work."); 5569 5570 Expr *Body; 5571 { 5572 Sema::CompoundScopeRAII CompoundScope(Actions); 5573 auto *CS = cast<CapturedDecl>(Actions.CurContext); 5574 5575 ImplicitParamDecl *TargetParam = CS->getParam(0); 5576 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr( 5577 TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr); 5578 ImplicitParamDecl *IndvarParam = CS->getParam(1); 5579 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr( 5580 IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr); 5581 5582 // Capture the Start expression. 5583 CaptureVars Recap(Actions); 5584 Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr)); 5585 Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step)); 5586 5587 Expr *Skip = AssertSuccess( 5588 Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef)); 5589 // TODO: Explicitly cast to the iterator's difference_type instead of 5590 // relying on implicit conversion. 5591 Expr *Advanced = 5592 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip)); 5593 5594 if (Deref) { 5595 // For range-based for-loops convert the loop counter value to a concrete 5596 // loop variable value by dereferencing the iterator. 5597 Advanced = 5598 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced)); 5599 } 5600 5601 // Assign the result to the output parameter. 5602 Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {}, 5603 BO_Assign, TargetRef, Advanced)); 5604 } 5605 return cast<CapturedStmt>( 5606 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body))); 5607 } 5608 5609 StmtResult SemaOpenMP::ActOnOpenMPCanonicalLoop(Stmt *AStmt) { 5610 ASTContext &Ctx = getASTContext(); 5611 5612 // Extract the common elements of ForStmt and CXXForRangeStmt: 5613 // Loop variable, repeat condition, increment 5614 Expr *Cond, *Inc; 5615 VarDecl *LIVDecl, *LUVDecl; 5616 if (auto *For = dyn_cast<ForStmt>(AStmt)) { 5617 Stmt *Init = For->getInit(); 5618 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) { 5619 // For statement declares loop variable. 5620 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl()); 5621 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) { 5622 // For statement reuses variable. 5623 assert(LCAssign->getOpcode() == BO_Assign && 5624 "init part must be a loop variable assignment"); 5625 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS()); 5626 LIVDecl = cast<VarDecl>(CounterRef->getDecl()); 5627 } else 5628 llvm_unreachable("Cannot determine loop variable"); 5629 LUVDecl = LIVDecl; 5630 5631 Cond = For->getCond(); 5632 Inc = For->getInc(); 5633 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) { 5634 DeclStmt *BeginStmt = RangeFor->getBeginStmt(); 5635 LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl()); 5636 LUVDecl = RangeFor->getLoopVariable(); 5637 5638 Cond = RangeFor->getCond(); 5639 Inc = RangeFor->getInc(); 5640 } else 5641 llvm_unreachable("unhandled kind of loop"); 5642 5643 QualType CounterTy = LIVDecl->getType(); 5644 QualType LVTy = LUVDecl->getType(); 5645 5646 // Analyze the loop condition. 5647 Expr *LHS, *RHS; 5648 BinaryOperator::Opcode CondRel; 5649 Cond = Cond->IgnoreImplicit(); 5650 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) { 5651 LHS = CondBinExpr->getLHS(); 5652 RHS = CondBinExpr->getRHS(); 5653 CondRel = CondBinExpr->getOpcode(); 5654 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) { 5655 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands"); 5656 LHS = CondCXXOp->getArg(0); 5657 RHS = CondCXXOp->getArg(1); 5658 switch (CondCXXOp->getOperator()) { 5659 case OO_ExclaimEqual: 5660 CondRel = BO_NE; 5661 break; 5662 case OO_Less: 5663 CondRel = BO_LT; 5664 break; 5665 case OO_LessEqual: 5666 CondRel = BO_LE; 5667 break; 5668 case OO_Greater: 5669 CondRel = BO_GT; 5670 break; 5671 case OO_GreaterEqual: 5672 CondRel = BO_GE; 5673 break; 5674 default: 5675 llvm_unreachable("unexpected iterator operator"); 5676 } 5677 } else 5678 llvm_unreachable("unexpected loop condition"); 5679 5680 // Normalize such that the loop counter is on the LHS. 5681 if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) || 5682 cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) { 5683 std::swap(LHS, RHS); 5684 CondRel = BinaryOperator::reverseComparisonOp(CondRel); 5685 } 5686 auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit()); 5687 5688 // Decide the bit width for the logical iteration counter. By default use the 5689 // unsigned ptrdiff_t integer size (for iterators and pointers). 5690 // TODO: For iterators, use iterator::difference_type, 5691 // std::iterator_traits<>::difference_type or decltype(it - end). 5692 QualType LogicalTy = Ctx.getUnsignedPointerDiffType(); 5693 if (CounterTy->isIntegerType()) { 5694 unsigned BitWidth = Ctx.getIntWidth(CounterTy); 5695 LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false); 5696 } 5697 5698 // Analyze the loop increment. 5699 Expr *Step; 5700 if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) { 5701 int Direction; 5702 switch (IncUn->getOpcode()) { 5703 case UO_PreInc: 5704 case UO_PostInc: 5705 Direction = 1; 5706 break; 5707 case UO_PreDec: 5708 case UO_PostDec: 5709 Direction = -1; 5710 break; 5711 default: 5712 llvm_unreachable("unhandled unary increment operator"); 5713 } 5714 Step = IntegerLiteral::Create( 5715 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction), LogicalTy, {}); 5716 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) { 5717 if (IncBin->getOpcode() == BO_AddAssign) { 5718 Step = IncBin->getRHS(); 5719 } else if (IncBin->getOpcode() == BO_SubAssign) { 5720 Step = AssertSuccess( 5721 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS())); 5722 } else 5723 llvm_unreachable("unhandled binary increment operator"); 5724 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) { 5725 switch (CondCXXOp->getOperator()) { 5726 case OO_PlusPlus: 5727 Step = IntegerLiteral::Create( 5728 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {}); 5729 break; 5730 case OO_MinusMinus: 5731 Step = IntegerLiteral::Create( 5732 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {}); 5733 break; 5734 case OO_PlusEqual: 5735 Step = CondCXXOp->getArg(1); 5736 break; 5737 case OO_MinusEqual: 5738 Step = AssertSuccess( 5739 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1))); 5740 break; 5741 default: 5742 llvm_unreachable("unhandled overloaded increment operator"); 5743 } 5744 } else 5745 llvm_unreachable("unknown increment expression"); 5746 5747 CapturedStmt *DistanceFunc = 5748 buildDistanceFunc(SemaRef, LogicalTy, CondRel, LHS, RHS, Step); 5749 CapturedStmt *LoopVarFunc = buildLoopVarFunc( 5750 SemaRef, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt)); 5751 DeclRefExpr *LVRef = 5752 SemaRef.BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue, {}, 5753 nullptr, nullptr, {}, nullptr); 5754 return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc, 5755 LoopVarFunc, LVRef); 5756 } 5757 5758 StmtResult SemaOpenMP::ActOnOpenMPLoopnest(Stmt *AStmt) { 5759 // Handle a literal loop. 5760 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt)) 5761 return ActOnOpenMPCanonicalLoop(AStmt); 5762 5763 // If not a literal loop, it must be the result of a loop transformation. 5764 OMPExecutableDirective *LoopTransform = cast<OMPExecutableDirective>(AStmt); 5765 assert( 5766 isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) && 5767 "Loop transformation directive expected"); 5768 return LoopTransform; 5769 } 5770 5771 static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, 5772 CXXScopeSpec &MapperIdScopeSpec, 5773 const DeclarationNameInfo &MapperId, 5774 QualType Type, 5775 Expr *UnresolvedMapper); 5776 5777 /// Perform DFS through the structure/class data members trying to find 5778 /// member(s) with user-defined 'default' mapper and generate implicit map 5779 /// clauses for such members with the found 'default' mapper. 5780 static void 5781 processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack, 5782 SmallVectorImpl<OMPClause *> &Clauses) { 5783 // Check for the default mapper for data members. 5784 if (S.getLangOpts().OpenMP < 50) 5785 return; 5786 SmallVector<OMPClause *, 4> ImplicitMaps; 5787 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) { 5788 auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]); 5789 if (!C) 5790 continue; 5791 SmallVector<Expr *, 4> SubExprs; 5792 auto *MI = C->mapperlist_begin(); 5793 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End; 5794 ++I, ++MI) { 5795 // Expression is mapped using mapper - skip it. 5796 if (*MI) 5797 continue; 5798 Expr *E = *I; 5799 // Expression is dependent - skip it, build the mapper when it gets 5800 // instantiated. 5801 if (E->isTypeDependent() || E->isValueDependent() || 5802 E->containsUnexpandedParameterPack()) 5803 continue; 5804 // Array section - need to check for the mapping of the array section 5805 // element. 5806 QualType CanonType = E->getType().getCanonicalType(); 5807 if (CanonType->isSpecificBuiltinType(BuiltinType::ArraySection)) { 5808 const auto *OASE = cast<ArraySectionExpr>(E->IgnoreParenImpCasts()); 5809 QualType BaseType = 5810 ArraySectionExpr::getBaseOriginalType(OASE->getBase()); 5811 QualType ElemType; 5812 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe()) 5813 ElemType = ATy->getElementType(); 5814 else 5815 ElemType = BaseType->getPointeeType(); 5816 CanonType = ElemType; 5817 } 5818 5819 // DFS over data members in structures/classes. 5820 SmallVector<std::pair<QualType, FieldDecl *>, 4> Types( 5821 1, {CanonType, nullptr}); 5822 llvm::DenseMap<const Type *, Expr *> Visited; 5823 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain( 5824 1, {nullptr, 1}); 5825 while (!Types.empty()) { 5826 QualType BaseType; 5827 FieldDecl *CurFD; 5828 std::tie(BaseType, CurFD) = Types.pop_back_val(); 5829 while (ParentChain.back().second == 0) 5830 ParentChain.pop_back(); 5831 --ParentChain.back().second; 5832 if (BaseType.isNull()) 5833 continue; 5834 // Only structs/classes are allowed to have mappers. 5835 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl(); 5836 if (!RD) 5837 continue; 5838 auto It = Visited.find(BaseType.getTypePtr()); 5839 if (It == Visited.end()) { 5840 // Try to find the associated user-defined mapper. 5841 CXXScopeSpec MapperIdScopeSpec; 5842 DeclarationNameInfo DefaultMapperId; 5843 DefaultMapperId.setName(S.Context.DeclarationNames.getIdentifier( 5844 &S.Context.Idents.get("default"))); 5845 DefaultMapperId.setLoc(E->getExprLoc()); 5846 ExprResult ER = buildUserDefinedMapperRef( 5847 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId, 5848 BaseType, /*UnresolvedMapper=*/nullptr); 5849 if (ER.isInvalid()) 5850 continue; 5851 It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first; 5852 } 5853 // Found default mapper. 5854 if (It->second) { 5855 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType, 5856 VK_LValue, OK_Ordinary, E); 5857 OE->setIsUnique(/*V=*/true); 5858 Expr *BaseExpr = OE; 5859 for (const auto &P : ParentChain) { 5860 if (P.first) { 5861 BaseExpr = S.BuildMemberExpr( 5862 BaseExpr, /*IsArrow=*/false, E->getExprLoc(), 5863 NestedNameSpecifierLoc(), SourceLocation(), P.first, 5864 DeclAccessPair::make(P.first, P.first->getAccess()), 5865 /*HadMultipleCandidates=*/false, DeclarationNameInfo(), 5866 P.first->getType(), VK_LValue, OK_Ordinary); 5867 BaseExpr = S.DefaultLvalueConversion(BaseExpr).get(); 5868 } 5869 } 5870 if (CurFD) 5871 BaseExpr = S.BuildMemberExpr( 5872 BaseExpr, /*IsArrow=*/false, E->getExprLoc(), 5873 NestedNameSpecifierLoc(), SourceLocation(), CurFD, 5874 DeclAccessPair::make(CurFD, CurFD->getAccess()), 5875 /*HadMultipleCandidates=*/false, DeclarationNameInfo(), 5876 CurFD->getType(), VK_LValue, OK_Ordinary); 5877 SubExprs.push_back(BaseExpr); 5878 continue; 5879 } 5880 // Check for the "default" mapper for data members. 5881 bool FirstIter = true; 5882 for (FieldDecl *FD : RD->fields()) { 5883 if (!FD) 5884 continue; 5885 QualType FieldTy = FD->getType(); 5886 if (FieldTy.isNull() || 5887 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType())) 5888 continue; 5889 if (FirstIter) { 5890 FirstIter = false; 5891 ParentChain.emplace_back(CurFD, 1); 5892 } else { 5893 ++ParentChain.back().second; 5894 } 5895 Types.emplace_back(FieldTy, FD); 5896 } 5897 } 5898 } 5899 if (SubExprs.empty()) 5900 continue; 5901 CXXScopeSpec MapperIdScopeSpec; 5902 DeclarationNameInfo MapperId; 5903 if (OMPClause *NewClause = S.OpenMP().ActOnOpenMPMapClause( 5904 nullptr, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(), 5905 MapperIdScopeSpec, MapperId, C->getMapType(), 5906 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), 5907 SubExprs, OMPVarListLocTy())) 5908 Clauses.push_back(NewClause); 5909 } 5910 } 5911 5912 namespace { 5913 /// A 'teams loop' with a nested 'loop bind(parallel)' or generic function 5914 /// call in the associated loop-nest cannot be a 'parallel for'. 5915 class TeamsLoopChecker final : public ConstStmtVisitor<TeamsLoopChecker> { 5916 Sema &SemaRef; 5917 5918 public: 5919 bool teamsLoopCanBeParallelFor() const { return TeamsLoopCanBeParallelFor; } 5920 5921 // Is there a nested OpenMP loop bind(parallel) 5922 void VisitOMPExecutableDirective(const OMPExecutableDirective *D) { 5923 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) { 5924 if (const auto *C = D->getSingleClause<OMPBindClause>()) 5925 if (C->getBindKind() == OMPC_BIND_parallel) { 5926 TeamsLoopCanBeParallelFor = false; 5927 // No need to continue visiting any more 5928 return; 5929 } 5930 } 5931 for (const Stmt *Child : D->children()) 5932 if (Child) 5933 Visit(Child); 5934 } 5935 5936 void VisitCallExpr(const CallExpr *C) { 5937 // Function calls inhibit parallel loop translation of 'target teams loop' 5938 // unless the assume-no-nested-parallelism flag has been specified. 5939 // OpenMP API runtime library calls do not inhibit parallel loop 5940 // translation, regardless of the assume-no-nested-parallelism. 5941 bool IsOpenMPAPI = false; 5942 auto *FD = dyn_cast_or_null<FunctionDecl>(C->getCalleeDecl()); 5943 if (FD) { 5944 std::string Name = FD->getNameInfo().getAsString(); 5945 IsOpenMPAPI = Name.find("omp_") == 0; 5946 } 5947 TeamsLoopCanBeParallelFor = 5948 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism; 5949 if (!TeamsLoopCanBeParallelFor) 5950 return; 5951 5952 for (const Stmt *Child : C->children()) 5953 if (Child) 5954 Visit(Child); 5955 } 5956 5957 void VisitCapturedStmt(const CapturedStmt *S) { 5958 if (!S) 5959 return; 5960 Visit(S->getCapturedDecl()->getBody()); 5961 } 5962 5963 void VisitStmt(const Stmt *S) { 5964 if (!S) 5965 return; 5966 for (const Stmt *Child : S->children()) 5967 if (Child) 5968 Visit(Child); 5969 } 5970 explicit TeamsLoopChecker(Sema &SemaRef) 5971 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(true) {} 5972 5973 private: 5974 bool TeamsLoopCanBeParallelFor; 5975 }; 5976 } // namespace 5977 5978 static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) { 5979 TeamsLoopChecker Checker(SemaRef); 5980 Checker.Visit(AStmt); 5981 return Checker.teamsLoopCanBeParallelFor(); 5982 } 5983 5984 bool SemaOpenMP::mapLoopConstruct( 5985 llvm::SmallVector<OMPClause *> &ClausesWithoutBind, 5986 ArrayRef<OMPClause *> Clauses, OpenMPBindClauseKind &BindKind, 5987 OpenMPDirectiveKind &Kind, OpenMPDirectiveKind &PrevMappedDirective, 5988 SourceLocation StartLoc, SourceLocation EndLoc, 5989 const DeclarationNameInfo &DirName, OpenMPDirectiveKind CancelRegion) { 5990 5991 bool UseClausesWithoutBind = false; 5992 5993 // Restricting to "#pragma omp loop bind" 5994 if (getLangOpts().OpenMP >= 50 && Kind == OMPD_loop) { 5995 5996 const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective(); 5997 5998 if (BindKind == OMPC_BIND_unknown) { 5999 // Setting the enclosing teams or parallel construct for the loop 6000 // directive without bind clause. 6001 // [5.0:129:25-28] If the bind clause is not present on the construct and 6002 // the loop construct is closely nested inside a teams or parallel 6003 // construct, the binding region is the corresponding teams or parallel 6004 // region. If none of those conditions hold, the binding region is not 6005 // defined. 6006 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown 6007 ArrayRef<OpenMPDirectiveKind> ParentLeafs = 6008 getLeafConstructsOrSelf(ParentDirective); 6009 6010 if (ParentDirective == OMPD_unknown) { 6011 Diag(DSAStack->getDefaultDSALocation(), 6012 diag::err_omp_bind_required_on_loop); 6013 } else if (ParentLeafs.back() == OMPD_parallel) { 6014 BindKind = OMPC_BIND_parallel; 6015 } else if (ParentLeafs.back() == OMPD_teams) { 6016 BindKind = OMPC_BIND_teams; 6017 } 6018 } else { 6019 // bind clause is present in loop directive. When the loop directive is 6020 // changed to a new directive the bind clause is not used. So, we should 6021 // set flag indicating to only use the clauses that aren't the 6022 // bind clause. 6023 UseClausesWithoutBind = true; 6024 } 6025 6026 for (OMPClause *C : Clauses) { 6027 // Spec restriction : bind(teams) and reduction not permitted. 6028 if (BindKind == OMPC_BIND_teams && 6029 C->getClauseKind() == llvm::omp::Clause::OMPC_reduction) 6030 Diag(DSAStack->getDefaultDSALocation(), 6031 diag::err_omp_loop_reduction_clause); 6032 6033 // A new Vector ClausesWithoutBind, which does not contain the bind 6034 // clause, for passing to new directive. 6035 if (C->getClauseKind() != llvm::omp::Clause::OMPC_bind) 6036 ClausesWithoutBind.push_back(C); 6037 } 6038 6039 switch (BindKind) { 6040 case OMPC_BIND_parallel: 6041 Kind = OMPD_for; 6042 DSAStack->setCurrentDirective(OMPD_for); 6043 DSAStack->setMappedDirective(OMPD_loop); 6044 PrevMappedDirective = OMPD_loop; 6045 break; 6046 case OMPC_BIND_teams: 6047 Kind = OMPD_distribute; 6048 DSAStack->setCurrentDirective(OMPD_distribute); 6049 DSAStack->setMappedDirective(OMPD_loop); 6050 PrevMappedDirective = OMPD_loop; 6051 break; 6052 case OMPC_BIND_thread: 6053 Kind = OMPD_simd; 6054 DSAStack->setCurrentDirective(OMPD_simd); 6055 DSAStack->setMappedDirective(OMPD_loop); 6056 PrevMappedDirective = OMPD_loop; 6057 break; 6058 case OMPC_BIND_unknown: 6059 break; 6060 } 6061 } else if (PrevMappedDirective == OMPD_loop) { 6062 /// An initial pass after recognizing all the statements is done in the 6063 /// Parser when the directive OMPD_loop is mapped to OMPD_for, 6064 /// OMPD_distribute or OMPD_simd. A second transform pass with call from 6065 /// clang::TreeTransform::TransformOMPExecutableDirective() is done 6066 /// with the Directive as one of the above mapped directive without 6067 /// the bind clause. Then "PrevMappedDirective" stored in the 6068 /// OMPExecutableDirective is accessed and hence this else statement. 6069 6070 DSAStack->setMappedDirective(OMPD_loop); 6071 } 6072 6073 return UseClausesWithoutBind; 6074 } 6075 6076 StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective( 6077 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, 6078 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses, 6079 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, 6080 OpenMPDirectiveKind PrevMappedDirective) { 6081 assert(isOpenMPExecutableDirective(Kind) && "Unexpected directive category"); 6082 6083 StmtResult Res = StmtError(); 6084 OpenMPBindClauseKind BindKind = OMPC_BIND_unknown; 6085 llvm::SmallVector<OMPClause *> ClausesWithoutBind; 6086 bool UseClausesWithoutBind = false; 6087 6088 if (const OMPBindClause *BC = 6089 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses)) 6090 BindKind = BC->getBindKind(); 6091 6092 // Variable used to note down the DirectiveKind because mapLoopConstruct may 6093 // change "Kind" variable, due to mapping of "omp loop" to other directives. 6094 OpenMPDirectiveKind DK = Kind; 6095 if (Kind == OMPD_loop || PrevMappedDirective == OMPD_loop) { 6096 UseClausesWithoutBind = mapLoopConstruct( 6097 ClausesWithoutBind, Clauses, BindKind, Kind, PrevMappedDirective, 6098 StartLoc, EndLoc, DirName, CancelRegion); 6099 DK = OMPD_loop; 6100 } 6101 6102 // First check CancelRegion which is then used in checkNestingOfRegions. 6103 if (checkCancelRegion(SemaRef, Kind, CancelRegion, StartLoc) || 6104 checkNestingOfRegions(SemaRef, DSAStack, DK, DirName, CancelRegion, 6105 BindKind, StartLoc)) { 6106 return StmtError(); 6107 } 6108 6109 // Report affected OpenMP target offloading behavior when in HIP lang-mode. 6110 if (getLangOpts().HIP && (isOpenMPTargetExecutionDirective(Kind) || 6111 isOpenMPTargetDataManagementDirective(Kind))) 6112 Diag(StartLoc, diag::warn_hip_omp_target_directives); 6113 6114 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit; 6115 VarsWithInheritedDSAType VarsWithInheritedDSA; 6116 bool ErrorFound = false; 6117 if (getLangOpts().OpenMP >= 50 && UseClausesWithoutBind) { 6118 ClausesWithImplicit.append(ClausesWithoutBind.begin(), 6119 ClausesWithoutBind.end()); 6120 } else { 6121 ClausesWithImplicit.append(Clauses.begin(), Clauses.end()); 6122 } 6123 if (AStmt && !SemaRef.CurContext->isDependentContext() && 6124 isOpenMPCapturingDirective(Kind)) { 6125 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 6126 6127 // Check default data sharing attributes for referenced variables. 6128 DSAAttrChecker DSAChecker(DSAStack, SemaRef, cast<CapturedStmt>(AStmt)); 6129 int ThisCaptureLevel = getOpenMPCaptureLevels(Kind); 6130 Stmt *S = AStmt; 6131 while (--ThisCaptureLevel >= 0) 6132 S = cast<CapturedStmt>(S)->getCapturedStmt(); 6133 DSAChecker.Visit(S); 6134 if (!isOpenMPTargetDataManagementDirective(Kind) && 6135 !isOpenMPTaskingDirective(Kind)) { 6136 // Visit subcaptures to generate implicit clauses for captured vars. 6137 auto *CS = cast<CapturedStmt>(AStmt); 6138 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 6139 getOpenMPCaptureRegions(CaptureRegions, Kind); 6140 // Ignore outer tasking regions for target directives. 6141 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task) 6142 CS = cast<CapturedStmt>(CS->getCapturedStmt()); 6143 DSAChecker.visitSubCaptures(CS); 6144 } 6145 if (DSAChecker.isErrorFound()) 6146 return StmtError(); 6147 // Generate list of implicitly defined firstprivate variables. 6148 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA(); 6149 6150 SmallVector<Expr *, 4> ImplicitFirstprivates( 6151 DSAChecker.getImplicitFirstprivate().begin(), 6152 DSAChecker.getImplicitFirstprivate().end()); 6153 SmallVector<Expr *, 4> ImplicitPrivates( 6154 DSAChecker.getImplicitPrivate().begin(), 6155 DSAChecker.getImplicitPrivate().end()); 6156 const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1; 6157 SmallVector<Expr *, 4> ImplicitMaps[DefaultmapKindNum][OMPC_MAP_delete]; 6158 SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers> 6159 ImplicitMapModifiers[DefaultmapKindNum]; 6160 SmallVector<SourceLocation, NumberOfOMPMapClauseModifiers> 6161 ImplicitMapModifiersLoc[DefaultmapKindNum]; 6162 // Get the original location of present modifier from Defaultmap clause. 6163 SourceLocation PresentModifierLocs[DefaultmapKindNum]; 6164 for (OMPClause *C : Clauses) { 6165 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C)) 6166 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present) 6167 PresentModifierLocs[DMC->getDefaultmapKind()] = 6168 DMC->getDefaultmapModifierLoc(); 6169 } 6170 for (unsigned VC = 0; VC < DefaultmapKindNum; ++VC) { 6171 auto K = static_cast<OpenMPDefaultmapClauseKind>(VC); 6172 for (unsigned I = 0; I < OMPC_MAP_delete; ++I) { 6173 ArrayRef<Expr *> ImplicitMap = 6174 DSAChecker.getImplicitMap(K, static_cast<OpenMPMapClauseKind>(I)); 6175 ImplicitMaps[VC][I].append(ImplicitMap.begin(), ImplicitMap.end()); 6176 } 6177 ArrayRef<OpenMPMapModifierKind> ImplicitModifier = 6178 DSAChecker.getImplicitMapModifier(K); 6179 ImplicitMapModifiers[VC].append(ImplicitModifier.begin(), 6180 ImplicitModifier.end()); 6181 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[VC]), 6182 ImplicitModifier.size(), PresentModifierLocs[VC]); 6183 } 6184 // Mark taskgroup task_reduction descriptors as implicitly firstprivate. 6185 for (OMPClause *C : Clauses) { 6186 if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) { 6187 for (Expr *E : IRC->taskgroup_descriptors()) 6188 if (E) 6189 ImplicitFirstprivates.emplace_back(E); 6190 } 6191 // OpenMP 5.0, 2.10.1 task Construct 6192 // [detach clause]... The event-handle will be considered as if it was 6193 // specified on a firstprivate clause. 6194 if (auto *DC = dyn_cast<OMPDetachClause>(C)) 6195 ImplicitFirstprivates.push_back(DC->getEventHandler()); 6196 } 6197 if (!ImplicitFirstprivates.empty()) { 6198 if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause( 6199 ImplicitFirstprivates, SourceLocation(), SourceLocation(), 6200 SourceLocation())) { 6201 ClausesWithImplicit.push_back(Implicit); 6202 ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() != 6203 ImplicitFirstprivates.size(); 6204 } else { 6205 ErrorFound = true; 6206 } 6207 } 6208 if (!ImplicitPrivates.empty()) { 6209 if (OMPClause *Implicit = 6210 ActOnOpenMPPrivateClause(ImplicitPrivates, SourceLocation(), 6211 SourceLocation(), SourceLocation())) { 6212 ClausesWithImplicit.push_back(Implicit); 6213 ErrorFound = cast<OMPPrivateClause>(Implicit)->varlist_size() != 6214 ImplicitPrivates.size(); 6215 } else { 6216 ErrorFound = true; 6217 } 6218 } 6219 // OpenMP 5.0 [2.19.7] 6220 // If a list item appears in a reduction, lastprivate or linear 6221 // clause on a combined target construct then it is treated as 6222 // if it also appears in a map clause with a map-type of tofrom 6223 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target && 6224 isOpenMPTargetExecutionDirective(Kind)) { 6225 SmallVector<Expr *, 4> ImplicitExprs; 6226 for (OMPClause *C : Clauses) { 6227 if (auto *RC = dyn_cast<OMPReductionClause>(C)) 6228 for (Expr *E : RC->varlists()) 6229 if (!isa<DeclRefExpr>(E->IgnoreParenImpCasts())) 6230 ImplicitExprs.emplace_back(E); 6231 } 6232 if (!ImplicitExprs.empty()) { 6233 ArrayRef<Expr *> Exprs = ImplicitExprs; 6234 CXXScopeSpec MapperIdScopeSpec; 6235 DeclarationNameInfo MapperId; 6236 if (OMPClause *Implicit = ActOnOpenMPMapClause( 6237 nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(), 6238 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom, 6239 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), 6240 Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true)) 6241 ClausesWithImplicit.emplace_back(Implicit); 6242 } 6243 } 6244 for (unsigned I = 0, E = DefaultmapKindNum; I < E; ++I) { 6245 int ClauseKindCnt = -1; 6246 for (ArrayRef<Expr *> ImplicitMap : ImplicitMaps[I]) { 6247 ++ClauseKindCnt; 6248 if (ImplicitMap.empty()) 6249 continue; 6250 CXXScopeSpec MapperIdScopeSpec; 6251 DeclarationNameInfo MapperId; 6252 auto K = static_cast<OpenMPMapClauseKind>(ClauseKindCnt); 6253 if (OMPClause *Implicit = ActOnOpenMPMapClause( 6254 nullptr, ImplicitMapModifiers[I], ImplicitMapModifiersLoc[I], 6255 MapperIdScopeSpec, MapperId, K, /*IsMapTypeImplicit=*/true, 6256 SourceLocation(), SourceLocation(), ImplicitMap, 6257 OMPVarListLocTy())) { 6258 ClausesWithImplicit.emplace_back(Implicit); 6259 ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() != 6260 ImplicitMap.size(); 6261 } else { 6262 ErrorFound = true; 6263 } 6264 } 6265 } 6266 // Build expressions for implicit maps of data members with 'default' 6267 // mappers. 6268 if (getLangOpts().OpenMP >= 50) 6269 processImplicitMapsWithDefaultMappers(SemaRef, DSAStack, 6270 ClausesWithImplicit); 6271 } 6272 6273 switch (Kind) { 6274 case OMPD_parallel: 6275 Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc, 6276 EndLoc); 6277 break; 6278 case OMPD_simd: 6279 Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc, 6280 VarsWithInheritedDSA); 6281 break; 6282 case OMPD_tile: 6283 Res = 6284 ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc); 6285 break; 6286 case OMPD_unroll: 6287 Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc, 6288 EndLoc); 6289 break; 6290 case OMPD_reverse: 6291 assert(ClausesWithImplicit.empty() && 6292 "reverse directive does not support any clauses"); 6293 Res = ActOnOpenMPReverseDirective(AStmt, StartLoc, EndLoc); 6294 break; 6295 case OMPD_interchange: 6296 Res = ActOnOpenMPInterchangeDirective(ClausesWithImplicit, AStmt, StartLoc, 6297 EndLoc); 6298 break; 6299 case OMPD_for: 6300 Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc, 6301 VarsWithInheritedDSA); 6302 break; 6303 case OMPD_for_simd: 6304 Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc, 6305 EndLoc, VarsWithInheritedDSA); 6306 break; 6307 case OMPD_sections: 6308 Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc, 6309 EndLoc); 6310 break; 6311 case OMPD_section: 6312 assert(ClausesWithImplicit.empty() && 6313 "No clauses are allowed for 'omp section' directive"); 6314 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc); 6315 break; 6316 case OMPD_single: 6317 Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc, 6318 EndLoc); 6319 break; 6320 case OMPD_master: 6321 assert(ClausesWithImplicit.empty() && 6322 "No clauses are allowed for 'omp master' directive"); 6323 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc); 6324 break; 6325 case OMPD_masked: 6326 Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc, 6327 EndLoc); 6328 break; 6329 case OMPD_critical: 6330 Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt, 6331 StartLoc, EndLoc); 6332 break; 6333 case OMPD_parallel_for: 6334 Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc, 6335 EndLoc, VarsWithInheritedDSA); 6336 break; 6337 case OMPD_parallel_for_simd: 6338 Res = ActOnOpenMPParallelForSimdDirective( 6339 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6340 break; 6341 case OMPD_scope: 6342 Res = 6343 ActOnOpenMPScopeDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc); 6344 break; 6345 case OMPD_parallel_master: 6346 Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt, 6347 StartLoc, EndLoc); 6348 break; 6349 case OMPD_parallel_masked: 6350 Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt, 6351 StartLoc, EndLoc); 6352 break; 6353 case OMPD_parallel_sections: 6354 Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt, 6355 StartLoc, EndLoc); 6356 break; 6357 case OMPD_task: 6358 Res = 6359 ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc); 6360 break; 6361 case OMPD_taskyield: 6362 assert(ClausesWithImplicit.empty() && 6363 "No clauses are allowed for 'omp taskyield' directive"); 6364 assert(AStmt == nullptr && 6365 "No associated statement allowed for 'omp taskyield' directive"); 6366 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc); 6367 break; 6368 case OMPD_error: 6369 assert(AStmt == nullptr && 6370 "No associated statement allowed for 'omp error' directive"); 6371 Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc); 6372 break; 6373 case OMPD_barrier: 6374 assert(ClausesWithImplicit.empty() && 6375 "No clauses are allowed for 'omp barrier' directive"); 6376 assert(AStmt == nullptr && 6377 "No associated statement allowed for 'omp barrier' directive"); 6378 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc); 6379 break; 6380 case OMPD_taskwait: 6381 assert(AStmt == nullptr && 6382 "No associated statement allowed for 'omp taskwait' directive"); 6383 Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc); 6384 break; 6385 case OMPD_taskgroup: 6386 Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc, 6387 EndLoc); 6388 break; 6389 case OMPD_flush: 6390 assert(AStmt == nullptr && 6391 "No associated statement allowed for 'omp flush' directive"); 6392 Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc); 6393 break; 6394 case OMPD_depobj: 6395 assert(AStmt == nullptr && 6396 "No associated statement allowed for 'omp depobj' directive"); 6397 Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc); 6398 break; 6399 case OMPD_scan: 6400 assert(AStmt == nullptr && 6401 "No associated statement allowed for 'omp scan' directive"); 6402 Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc); 6403 break; 6404 case OMPD_ordered: 6405 Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc, 6406 EndLoc); 6407 break; 6408 case OMPD_atomic: 6409 Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc, 6410 EndLoc); 6411 break; 6412 case OMPD_teams: 6413 Res = 6414 ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc); 6415 break; 6416 case OMPD_target: 6417 Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc, 6418 EndLoc); 6419 break; 6420 case OMPD_target_parallel: 6421 Res = ActOnOpenMPTargetParallelDirective(ClausesWithImplicit, AStmt, 6422 StartLoc, EndLoc); 6423 break; 6424 case OMPD_target_parallel_for: 6425 Res = ActOnOpenMPTargetParallelForDirective( 6426 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6427 break; 6428 case OMPD_cancellation_point: 6429 assert(ClausesWithImplicit.empty() && 6430 "No clauses are allowed for 'omp cancellation point' directive"); 6431 assert(AStmt == nullptr && "No associated statement allowed for 'omp " 6432 "cancellation point' directive"); 6433 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion); 6434 break; 6435 case OMPD_cancel: 6436 assert(AStmt == nullptr && 6437 "No associated statement allowed for 'omp cancel' directive"); 6438 Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc, 6439 CancelRegion); 6440 break; 6441 case OMPD_target_data: 6442 Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc, 6443 EndLoc); 6444 break; 6445 case OMPD_target_enter_data: 6446 Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc, 6447 EndLoc, AStmt); 6448 break; 6449 case OMPD_target_exit_data: 6450 Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc, 6451 EndLoc, AStmt); 6452 break; 6453 case OMPD_taskloop: 6454 Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc, 6455 EndLoc, VarsWithInheritedDSA); 6456 break; 6457 case OMPD_taskloop_simd: 6458 Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc, 6459 EndLoc, VarsWithInheritedDSA); 6460 break; 6461 case OMPD_master_taskloop: 6462 Res = ActOnOpenMPMasterTaskLoopDirective( 6463 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6464 break; 6465 case OMPD_masked_taskloop: 6466 Res = ActOnOpenMPMaskedTaskLoopDirective( 6467 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6468 break; 6469 case OMPD_master_taskloop_simd: 6470 Res = ActOnOpenMPMasterTaskLoopSimdDirective( 6471 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6472 break; 6473 case OMPD_masked_taskloop_simd: 6474 Res = ActOnOpenMPMaskedTaskLoopSimdDirective( 6475 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6476 break; 6477 case OMPD_parallel_master_taskloop: 6478 Res = ActOnOpenMPParallelMasterTaskLoopDirective( 6479 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6480 break; 6481 case OMPD_parallel_masked_taskloop: 6482 Res = ActOnOpenMPParallelMaskedTaskLoopDirective( 6483 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6484 break; 6485 case OMPD_parallel_master_taskloop_simd: 6486 Res = ActOnOpenMPParallelMasterTaskLoopSimdDirective( 6487 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6488 break; 6489 case OMPD_parallel_masked_taskloop_simd: 6490 Res = ActOnOpenMPParallelMaskedTaskLoopSimdDirective( 6491 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6492 break; 6493 case OMPD_distribute: 6494 Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc, 6495 EndLoc, VarsWithInheritedDSA); 6496 break; 6497 case OMPD_target_update: 6498 Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc, 6499 EndLoc, AStmt); 6500 break; 6501 case OMPD_distribute_parallel_for: 6502 Res = ActOnOpenMPDistributeParallelForDirective( 6503 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6504 break; 6505 case OMPD_distribute_parallel_for_simd: 6506 Res = ActOnOpenMPDistributeParallelForSimdDirective( 6507 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6508 break; 6509 case OMPD_distribute_simd: 6510 Res = ActOnOpenMPDistributeSimdDirective( 6511 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6512 break; 6513 case OMPD_target_parallel_for_simd: 6514 Res = ActOnOpenMPTargetParallelForSimdDirective( 6515 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6516 break; 6517 case OMPD_target_simd: 6518 Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc, 6519 EndLoc, VarsWithInheritedDSA); 6520 break; 6521 case OMPD_teams_distribute: 6522 Res = ActOnOpenMPTeamsDistributeDirective( 6523 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6524 break; 6525 case OMPD_teams_distribute_simd: 6526 Res = ActOnOpenMPTeamsDistributeSimdDirective( 6527 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6528 break; 6529 case OMPD_teams_distribute_parallel_for_simd: 6530 Res = ActOnOpenMPTeamsDistributeParallelForSimdDirective( 6531 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6532 break; 6533 case OMPD_teams_distribute_parallel_for: 6534 Res = ActOnOpenMPTeamsDistributeParallelForDirective( 6535 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6536 break; 6537 case OMPD_target_teams: 6538 Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, 6539 EndLoc); 6540 break; 6541 case OMPD_target_teams_distribute: 6542 Res = ActOnOpenMPTargetTeamsDistributeDirective( 6543 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6544 break; 6545 case OMPD_target_teams_distribute_parallel_for: 6546 Res = ActOnOpenMPTargetTeamsDistributeParallelForDirective( 6547 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6548 break; 6549 case OMPD_target_teams_distribute_parallel_for_simd: 6550 Res = ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective( 6551 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6552 break; 6553 case OMPD_target_teams_distribute_simd: 6554 Res = ActOnOpenMPTargetTeamsDistributeSimdDirective( 6555 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6556 break; 6557 case OMPD_interop: 6558 assert(AStmt == nullptr && 6559 "No associated statement allowed for 'omp interop' directive"); 6560 Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc); 6561 break; 6562 case OMPD_dispatch: 6563 Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc, 6564 EndLoc); 6565 break; 6566 case OMPD_loop: 6567 Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc, 6568 EndLoc, VarsWithInheritedDSA); 6569 break; 6570 case OMPD_teams_loop: 6571 Res = ActOnOpenMPTeamsGenericLoopDirective( 6572 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6573 break; 6574 case OMPD_target_teams_loop: 6575 Res = ActOnOpenMPTargetTeamsGenericLoopDirective( 6576 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6577 break; 6578 case OMPD_parallel_loop: 6579 Res = ActOnOpenMPParallelGenericLoopDirective( 6580 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6581 break; 6582 case OMPD_target_parallel_loop: 6583 Res = ActOnOpenMPTargetParallelGenericLoopDirective( 6584 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 6585 break; 6586 case OMPD_declare_target: 6587 case OMPD_end_declare_target: 6588 case OMPD_threadprivate: 6589 case OMPD_allocate: 6590 case OMPD_declare_reduction: 6591 case OMPD_declare_mapper: 6592 case OMPD_declare_simd: 6593 case OMPD_requires: 6594 case OMPD_declare_variant: 6595 case OMPD_begin_declare_variant: 6596 case OMPD_end_declare_variant: 6597 llvm_unreachable("OpenMP Directive is not allowed"); 6598 case OMPD_unknown: 6599 default: 6600 llvm_unreachable("Unknown OpenMP directive"); 6601 } 6602 6603 ErrorFound = Res.isInvalid() || ErrorFound; 6604 6605 // Check variables in the clauses if default(none) or 6606 // default(firstprivate) was specified. 6607 if (DSAStack->getDefaultDSA() == DSA_none || 6608 DSAStack->getDefaultDSA() == DSA_private || 6609 DSAStack->getDefaultDSA() == DSA_firstprivate) { 6610 DSAAttrChecker DSAChecker(DSAStack, SemaRef, nullptr); 6611 for (OMPClause *C : Clauses) { 6612 switch (C->getClauseKind()) { 6613 case OMPC_num_threads: 6614 case OMPC_dist_schedule: 6615 // Do not analyze if no parent teams directive. 6616 if (isOpenMPTeamsDirective(Kind)) 6617 break; 6618 continue; 6619 case OMPC_if: 6620 if (isOpenMPTeamsDirective(Kind) && 6621 cast<OMPIfClause>(C)->getNameModifier() != OMPD_target) 6622 break; 6623 if (isOpenMPParallelDirective(Kind) && 6624 isOpenMPTaskLoopDirective(Kind) && 6625 cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel) 6626 break; 6627 continue; 6628 case OMPC_schedule: 6629 case OMPC_detach: 6630 break; 6631 case OMPC_grainsize: 6632 case OMPC_num_tasks: 6633 case OMPC_final: 6634 case OMPC_priority: 6635 case OMPC_novariants: 6636 case OMPC_nocontext: 6637 // Do not analyze if no parent parallel directive. 6638 if (isOpenMPParallelDirective(Kind)) 6639 break; 6640 continue; 6641 case OMPC_ordered: 6642 case OMPC_device: 6643 case OMPC_num_teams: 6644 case OMPC_thread_limit: 6645 case OMPC_hint: 6646 case OMPC_collapse: 6647 case OMPC_safelen: 6648 case OMPC_simdlen: 6649 case OMPC_sizes: 6650 case OMPC_default: 6651 case OMPC_proc_bind: 6652 case OMPC_private: 6653 case OMPC_firstprivate: 6654 case OMPC_lastprivate: 6655 case OMPC_shared: 6656 case OMPC_reduction: 6657 case OMPC_task_reduction: 6658 case OMPC_in_reduction: 6659 case OMPC_linear: 6660 case OMPC_aligned: 6661 case OMPC_copyin: 6662 case OMPC_copyprivate: 6663 case OMPC_nowait: 6664 case OMPC_untied: 6665 case OMPC_mergeable: 6666 case OMPC_allocate: 6667 case OMPC_read: 6668 case OMPC_write: 6669 case OMPC_update: 6670 case OMPC_capture: 6671 case OMPC_compare: 6672 case OMPC_seq_cst: 6673 case OMPC_acq_rel: 6674 case OMPC_acquire: 6675 case OMPC_release: 6676 case OMPC_relaxed: 6677 case OMPC_depend: 6678 case OMPC_threads: 6679 case OMPC_simd: 6680 case OMPC_map: 6681 case OMPC_nogroup: 6682 case OMPC_defaultmap: 6683 case OMPC_to: 6684 case OMPC_from: 6685 case OMPC_use_device_ptr: 6686 case OMPC_use_device_addr: 6687 case OMPC_is_device_ptr: 6688 case OMPC_has_device_addr: 6689 case OMPC_nontemporal: 6690 case OMPC_order: 6691 case OMPC_destroy: 6692 case OMPC_inclusive: 6693 case OMPC_exclusive: 6694 case OMPC_uses_allocators: 6695 case OMPC_affinity: 6696 case OMPC_bind: 6697 case OMPC_filter: 6698 continue; 6699 case OMPC_allocator: 6700 case OMPC_flush: 6701 case OMPC_depobj: 6702 case OMPC_threadprivate: 6703 case OMPC_uniform: 6704 case OMPC_unknown: 6705 case OMPC_unified_address: 6706 case OMPC_unified_shared_memory: 6707 case OMPC_reverse_offload: 6708 case OMPC_dynamic_allocators: 6709 case OMPC_atomic_default_mem_order: 6710 case OMPC_device_type: 6711 case OMPC_match: 6712 case OMPC_when: 6713 case OMPC_at: 6714 case OMPC_severity: 6715 case OMPC_message: 6716 default: 6717 llvm_unreachable("Unexpected clause"); 6718 } 6719 for (Stmt *CC : C->children()) { 6720 if (CC) 6721 DSAChecker.Visit(CC); 6722 } 6723 } 6724 for (const auto &P : DSAChecker.getVarsWithInheritedDSA()) 6725 VarsWithInheritedDSA[P.getFirst()] = P.getSecond(); 6726 } 6727 for (const auto &P : VarsWithInheritedDSA) { 6728 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst())) 6729 continue; 6730 ErrorFound = true; 6731 if (DSAStack->getDefaultDSA() == DSA_none || 6732 DSAStack->getDefaultDSA() == DSA_private || 6733 DSAStack->getDefaultDSA() == DSA_firstprivate) { 6734 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable) 6735 << P.first << P.second->getSourceRange(); 6736 Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none); 6737 } else if (getLangOpts().OpenMP >= 50) { 6738 Diag(P.second->getExprLoc(), 6739 diag::err_omp_defaultmap_no_attr_for_variable) 6740 << P.first << P.second->getSourceRange(); 6741 Diag(DSAStack->getDefaultDSALocation(), 6742 diag::note_omp_defaultmap_attr_none); 6743 } 6744 } 6745 6746 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers; 6747 for (OpenMPDirectiveKind D : getLeafConstructsOrSelf(Kind)) { 6748 if (isAllowedClauseForDirective(D, OMPC_if, getLangOpts().OpenMP)) 6749 AllowedNameModifiers.push_back(D); 6750 } 6751 if (!AllowedNameModifiers.empty()) 6752 ErrorFound = checkIfClauses(SemaRef, Kind, Clauses, AllowedNameModifiers) || 6753 ErrorFound; 6754 6755 if (ErrorFound) 6756 return StmtError(); 6757 6758 if (!SemaRef.CurContext->isDependentContext() && 6759 isOpenMPTargetExecutionDirective(Kind) && 6760 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() || 6761 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() || 6762 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() || 6763 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) { 6764 // Register target to DSA Stack. 6765 DSAStack->addTargetDirLocation(StartLoc); 6766 } 6767 6768 return Res; 6769 } 6770 6771 SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareSimdDirective( 6772 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen, 6773 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds, 6774 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears, 6775 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) { 6776 assert(Aligneds.size() == Alignments.size()); 6777 assert(Linears.size() == LinModifiers.size()); 6778 assert(Linears.size() == Steps.size()); 6779 if (!DG || DG.get().isNull()) 6780 return DeclGroupPtrTy(); 6781 6782 const int SimdId = 0; 6783 if (!DG.get().isSingleDecl()) { 6784 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant) 6785 << SimdId; 6786 return DG; 6787 } 6788 Decl *ADecl = DG.get().getSingleDecl(); 6789 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl)) 6790 ADecl = FTD->getTemplatedDecl(); 6791 6792 auto *FD = dyn_cast<FunctionDecl>(ADecl); 6793 if (!FD) { 6794 Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId; 6795 return DeclGroupPtrTy(); 6796 } 6797 6798 // OpenMP [2.8.2, declare simd construct, Description] 6799 // The parameter of the simdlen clause must be a constant positive integer 6800 // expression. 6801 ExprResult SL; 6802 if (Simdlen) 6803 SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen); 6804 // OpenMP [2.8.2, declare simd construct, Description] 6805 // The special this pointer can be used as if was one of the arguments to the 6806 // function in any of the linear, aligned, or uniform clauses. 6807 // The uniform clause declares one or more arguments to have an invariant 6808 // value for all concurrent invocations of the function in the execution of a 6809 // single SIMD loop. 6810 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs; 6811 const Expr *UniformedLinearThis = nullptr; 6812 for (const Expr *E : Uniforms) { 6813 E = E->IgnoreParenImpCasts(); 6814 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) 6815 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) 6816 if (FD->getNumParams() > PVD->getFunctionScopeIndex() && 6817 FD->getParamDecl(PVD->getFunctionScopeIndex()) 6818 ->getCanonicalDecl() == PVD->getCanonicalDecl()) { 6819 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E); 6820 continue; 6821 } 6822 if (isa<CXXThisExpr>(E)) { 6823 UniformedLinearThis = E; 6824 continue; 6825 } 6826 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) 6827 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0); 6828 } 6829 // OpenMP [2.8.2, declare simd construct, Description] 6830 // The aligned clause declares that the object to which each list item points 6831 // is aligned to the number of bytes expressed in the optional parameter of 6832 // the aligned clause. 6833 // The special this pointer can be used as if was one of the arguments to the 6834 // function in any of the linear, aligned, or uniform clauses. 6835 // The type of list items appearing in the aligned clause must be array, 6836 // pointer, reference to array, or reference to pointer. 6837 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs; 6838 const Expr *AlignedThis = nullptr; 6839 for (const Expr *E : Aligneds) { 6840 E = E->IgnoreParenImpCasts(); 6841 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) 6842 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) { 6843 const VarDecl *CanonPVD = PVD->getCanonicalDecl(); 6844 if (FD->getNumParams() > PVD->getFunctionScopeIndex() && 6845 FD->getParamDecl(PVD->getFunctionScopeIndex()) 6846 ->getCanonicalDecl() == CanonPVD) { 6847 // OpenMP [2.8.1, simd construct, Restrictions] 6848 // A list-item cannot appear in more than one aligned clause. 6849 if (AlignedArgs.count(CanonPVD) > 0) { 6850 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice) 6851 << 1 << getOpenMPClauseName(OMPC_aligned) 6852 << E->getSourceRange(); 6853 Diag(AlignedArgs[CanonPVD]->getExprLoc(), 6854 diag::note_omp_explicit_dsa) 6855 << getOpenMPClauseName(OMPC_aligned); 6856 continue; 6857 } 6858 AlignedArgs[CanonPVD] = E; 6859 QualType QTy = PVD->getType() 6860 .getNonReferenceType() 6861 .getUnqualifiedType() 6862 .getCanonicalType(); 6863 const Type *Ty = QTy.getTypePtrOrNull(); 6864 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) { 6865 Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr) 6866 << QTy << getLangOpts().CPlusPlus << E->getSourceRange(); 6867 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD; 6868 } 6869 continue; 6870 } 6871 } 6872 if (isa<CXXThisExpr>(E)) { 6873 if (AlignedThis) { 6874 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice) 6875 << 2 << getOpenMPClauseName(OMPC_aligned) << E->getSourceRange(); 6876 Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa) 6877 << getOpenMPClauseName(OMPC_aligned); 6878 } 6879 AlignedThis = E; 6880 continue; 6881 } 6882 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) 6883 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0); 6884 } 6885 // The optional parameter of the aligned clause, alignment, must be a constant 6886 // positive integer expression. If no optional parameter is specified, 6887 // implementation-defined default alignments for SIMD instructions on the 6888 // target platforms are assumed. 6889 SmallVector<const Expr *, 4> NewAligns; 6890 for (Expr *E : Alignments) { 6891 ExprResult Align; 6892 if (E) 6893 Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned); 6894 NewAligns.push_back(Align.get()); 6895 } 6896 // OpenMP [2.8.2, declare simd construct, Description] 6897 // The linear clause declares one or more list items to be private to a SIMD 6898 // lane and to have a linear relationship with respect to the iteration space 6899 // of a loop. 6900 // The special this pointer can be used as if was one of the arguments to the 6901 // function in any of the linear, aligned, or uniform clauses. 6902 // When a linear-step expression is specified in a linear clause it must be 6903 // either a constant integer expression or an integer-typed parameter that is 6904 // specified in a uniform clause on the directive. 6905 llvm::DenseMap<const Decl *, const Expr *> LinearArgs; 6906 const bool IsUniformedThis = UniformedLinearThis != nullptr; 6907 auto MI = LinModifiers.begin(); 6908 for (const Expr *E : Linears) { 6909 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI); 6910 ++MI; 6911 E = E->IgnoreParenImpCasts(); 6912 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) 6913 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) { 6914 const VarDecl *CanonPVD = PVD->getCanonicalDecl(); 6915 if (FD->getNumParams() > PVD->getFunctionScopeIndex() && 6916 FD->getParamDecl(PVD->getFunctionScopeIndex()) 6917 ->getCanonicalDecl() == CanonPVD) { 6918 // OpenMP [2.15.3.7, linear Clause, Restrictions] 6919 // A list-item cannot appear in more than one linear clause. 6920 if (LinearArgs.count(CanonPVD) > 0) { 6921 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa) 6922 << getOpenMPClauseName(OMPC_linear) 6923 << getOpenMPClauseName(OMPC_linear) << E->getSourceRange(); 6924 Diag(LinearArgs[CanonPVD]->getExprLoc(), 6925 diag::note_omp_explicit_dsa) 6926 << getOpenMPClauseName(OMPC_linear); 6927 continue; 6928 } 6929 // Each argument can appear in at most one uniform or linear clause. 6930 if (UniformedArgs.count(CanonPVD) > 0) { 6931 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa) 6932 << getOpenMPClauseName(OMPC_linear) 6933 << getOpenMPClauseName(OMPC_uniform) << E->getSourceRange(); 6934 Diag(UniformedArgs[CanonPVD]->getExprLoc(), 6935 diag::note_omp_explicit_dsa) 6936 << getOpenMPClauseName(OMPC_uniform); 6937 continue; 6938 } 6939 LinearArgs[CanonPVD] = E; 6940 if (E->isValueDependent() || E->isTypeDependent() || 6941 E->isInstantiationDependent() || 6942 E->containsUnexpandedParameterPack()) 6943 continue; 6944 (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind, 6945 PVD->getOriginalType(), 6946 /*IsDeclareSimd=*/true); 6947 continue; 6948 } 6949 } 6950 if (isa<CXXThisExpr>(E)) { 6951 if (UniformedLinearThis) { 6952 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa) 6953 << getOpenMPClauseName(OMPC_linear) 6954 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform : OMPC_linear) 6955 << E->getSourceRange(); 6956 Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa) 6957 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform 6958 : OMPC_linear); 6959 continue; 6960 } 6961 UniformedLinearThis = E; 6962 if (E->isValueDependent() || E->isTypeDependent() || 6963 E->isInstantiationDependent() || E->containsUnexpandedParameterPack()) 6964 continue; 6965 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind, 6966 E->getType(), /*IsDeclareSimd=*/true); 6967 continue; 6968 } 6969 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) 6970 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0); 6971 } 6972 Expr *Step = nullptr; 6973 Expr *NewStep = nullptr; 6974 SmallVector<Expr *, 4> NewSteps; 6975 for (Expr *E : Steps) { 6976 // Skip the same step expression, it was checked already. 6977 if (Step == E || !E) { 6978 NewSteps.push_back(E ? NewStep : nullptr); 6979 continue; 6980 } 6981 Step = E; 6982 if (const auto *DRE = dyn_cast<DeclRefExpr>(Step)) 6983 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) { 6984 const VarDecl *CanonPVD = PVD->getCanonicalDecl(); 6985 if (UniformedArgs.count(CanonPVD) == 0) { 6986 Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param) 6987 << Step->getSourceRange(); 6988 } else if (E->isValueDependent() || E->isTypeDependent() || 6989 E->isInstantiationDependent() || 6990 E->containsUnexpandedParameterPack() || 6991 CanonPVD->getType()->hasIntegerRepresentation()) { 6992 NewSteps.push_back(Step); 6993 } else { 6994 Diag(Step->getExprLoc(), diag::err_omp_expected_int_param) 6995 << Step->getSourceRange(); 6996 } 6997 continue; 6998 } 6999 NewStep = Step; 7000 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() && 7001 !Step->isInstantiationDependent() && 7002 !Step->containsUnexpandedParameterPack()) { 7003 NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step) 7004 .get(); 7005 if (NewStep) 7006 NewStep = SemaRef 7007 .VerifyIntegerConstantExpression( 7008 NewStep, /*FIXME*/ Sema::AllowFold) 7009 .get(); 7010 } 7011 NewSteps.push_back(NewStep); 7012 } 7013 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit( 7014 getASTContext(), BS, SL.get(), const_cast<Expr **>(Uniforms.data()), 7015 Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(), 7016 const_cast<Expr **>(NewAligns.data()), NewAligns.size(), 7017 const_cast<Expr **>(Linears.data()), Linears.size(), 7018 const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(), 7019 NewSteps.data(), NewSteps.size(), SR); 7020 ADecl->addAttr(NewAttr); 7021 return DG; 7022 } 7023 7024 static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto, 7025 QualType NewType) { 7026 assert(NewType->isFunctionProtoType() && 7027 "Expected function type with prototype."); 7028 assert(FD->getType()->isFunctionNoProtoType() && 7029 "Expected function with type with no prototype."); 7030 assert(FDWithProto->getType()->isFunctionProtoType() && 7031 "Expected function with prototype."); 7032 // Synthesize parameters with the same types. 7033 FD->setType(NewType); 7034 SmallVector<ParmVarDecl *, 16> Params; 7035 for (const ParmVarDecl *P : FDWithProto->parameters()) { 7036 auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(), 7037 SourceLocation(), nullptr, P->getType(), 7038 /*TInfo=*/nullptr, SC_None, nullptr); 7039 Param->setScopeInfo(0, Params.size()); 7040 Param->setImplicit(); 7041 Params.push_back(Param); 7042 } 7043 7044 FD->setParams(Params); 7045 } 7046 7047 void SemaOpenMP::ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D) { 7048 if (D->isInvalidDecl()) 7049 return; 7050 FunctionDecl *FD = nullptr; 7051 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D)) 7052 FD = UTemplDecl->getTemplatedDecl(); 7053 else 7054 FD = cast<FunctionDecl>(D); 7055 assert(FD && "Expected a function declaration!"); 7056 7057 // If we are instantiating templates we do *not* apply scoped assumptions but 7058 // only global ones. We apply scoped assumption to the template definition 7059 // though. 7060 if (!SemaRef.inTemplateInstantiation()) { 7061 for (OMPAssumeAttr *AA : OMPAssumeScoped) 7062 FD->addAttr(AA); 7063 } 7064 for (OMPAssumeAttr *AA : OMPAssumeGlobal) 7065 FD->addAttr(AA); 7066 } 7067 7068 SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI) 7069 : TI(&TI), NameSuffix(TI.getMangledName()) {} 7070 7071 void SemaOpenMP::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope( 7072 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists, 7073 SmallVectorImpl<FunctionDecl *> &Bases) { 7074 if (!D.getIdentifier()) 7075 return; 7076 7077 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back(); 7078 7079 // Template specialization is an extension, check if we do it. 7080 bool IsTemplated = !TemplateParamLists.empty(); 7081 if (IsTemplated && 7082 !DVScope.TI->isExtensionActive( 7083 llvm::omp::TraitProperty::implementation_extension_allow_templates)) 7084 return; 7085 7086 const IdentifierInfo *BaseII = D.getIdentifier(); 7087 LookupResult Lookup(SemaRef, DeclarationName(BaseII), D.getIdentifierLoc(), 7088 Sema::LookupOrdinaryName); 7089 SemaRef.LookupParsedName(Lookup, S, &D.getCXXScopeSpec(), 7090 /*ObjectType=*/QualType()); 7091 7092 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D); 7093 QualType FType = TInfo->getType(); 7094 7095 bool IsConstexpr = 7096 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr; 7097 bool IsConsteval = 7098 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Consteval; 7099 7100 for (auto *Candidate : Lookup) { 7101 auto *CandidateDecl = Candidate->getUnderlyingDecl(); 7102 FunctionDecl *UDecl = nullptr; 7103 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) { 7104 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl); 7105 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size()) 7106 UDecl = FTD->getTemplatedDecl(); 7107 } else if (!IsTemplated) 7108 UDecl = dyn_cast<FunctionDecl>(CandidateDecl); 7109 if (!UDecl) 7110 continue; 7111 7112 // Don't specialize constexpr/consteval functions with 7113 // non-constexpr/consteval functions. 7114 if (UDecl->isConstexpr() && !IsConstexpr) 7115 continue; 7116 if (UDecl->isConsteval() && !IsConsteval) 7117 continue; 7118 7119 QualType UDeclTy = UDecl->getType(); 7120 if (!UDeclTy->isDependentType()) { 7121 QualType NewType = getASTContext().mergeFunctionTypes( 7122 FType, UDeclTy, /* OfBlockPointer */ false, 7123 /* Unqualified */ false, /* AllowCXX */ true); 7124 if (NewType.isNull()) 7125 continue; 7126 } 7127 7128 // Found a base! 7129 Bases.push_back(UDecl); 7130 } 7131 7132 bool UseImplicitBase = !DVScope.TI->isExtensionActive( 7133 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base); 7134 // If no base was found we create a declaration that we use as base. 7135 if (Bases.empty() && UseImplicitBase) { 7136 D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration); 7137 Decl *BaseD = SemaRef.HandleDeclarator(S, D, TemplateParamLists); 7138 BaseD->setImplicit(true); 7139 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD)) 7140 Bases.push_back(BaseTemplD->getTemplatedDecl()); 7141 else 7142 Bases.push_back(cast<FunctionDecl>(BaseD)); 7143 } 7144 7145 std::string MangledName; 7146 MangledName += D.getIdentifier()->getName(); 7147 MangledName += getOpenMPVariantManglingSeparatorStr(); 7148 MangledName += DVScope.NameSuffix; 7149 IdentifierInfo &VariantII = getASTContext().Idents.get(MangledName); 7150 7151 VariantII.setMangledOpenMPVariantName(true); 7152 D.SetIdentifier(&VariantII, D.getBeginLoc()); 7153 } 7154 7155 void SemaOpenMP::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope( 7156 Decl *D, SmallVectorImpl<FunctionDecl *> &Bases) { 7157 // Do not mark function as is used to prevent its emission if this is the 7158 // only place where it is used. 7159 EnterExpressionEvaluationContext Unevaluated( 7160 SemaRef, Sema::ExpressionEvaluationContext::Unevaluated); 7161 7162 FunctionDecl *FD = nullptr; 7163 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D)) 7164 FD = UTemplDecl->getTemplatedDecl(); 7165 else 7166 FD = cast<FunctionDecl>(D); 7167 auto *VariantFuncRef = DeclRefExpr::Create( 7168 getASTContext(), NestedNameSpecifierLoc(), SourceLocation(), FD, 7169 /* RefersToEnclosingVariableOrCapture */ false, 7170 /* NameLoc */ FD->getLocation(), FD->getType(), 7171 ExprValueKind::VK_PRValue); 7172 7173 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back(); 7174 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit( 7175 getASTContext(), VariantFuncRef, DVScope.TI, 7176 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0, 7177 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0, 7178 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0); 7179 for (FunctionDecl *BaseFD : Bases) 7180 BaseFD->addAttr(OMPDeclareVariantA); 7181 } 7182 7183 ExprResult SemaOpenMP::ActOnOpenMPCall(ExprResult Call, Scope *Scope, 7184 SourceLocation LParenLoc, 7185 MultiExprArg ArgExprs, 7186 SourceLocation RParenLoc, 7187 Expr *ExecConfig) { 7188 // The common case is a regular call we do not want to specialize at all. Try 7189 // to make that case fast by bailing early. 7190 CallExpr *CE = dyn_cast<CallExpr>(Call.get()); 7191 if (!CE) 7192 return Call; 7193 7194 FunctionDecl *CalleeFnDecl = CE->getDirectCallee(); 7195 if (!CalleeFnDecl) 7196 return Call; 7197 7198 if (getLangOpts().OpenMP >= 51 && CalleeFnDecl->getIdentifier() && 7199 CalleeFnDecl->getName().starts_with_insensitive("omp_")) { 7200 // checking for any calls inside an Order region 7201 if (Scope && Scope->isOpenMPOrderClauseScope()) 7202 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api); 7203 } 7204 7205 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>()) 7206 return Call; 7207 7208 ASTContext &Context = getASTContext(); 7209 std::function<void(StringRef)> DiagUnknownTrait = [this, 7210 CE](StringRef ISATrait) { 7211 // TODO Track the selector locations in a way that is accessible here to 7212 // improve the diagnostic location. 7213 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait) 7214 << ISATrait; 7215 }; 7216 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait), 7217 SemaRef.getCurFunctionDecl(), 7218 DSAStack->getConstructTraits()); 7219 7220 QualType CalleeFnType = CalleeFnDecl->getType(); 7221 7222 SmallVector<Expr *, 4> Exprs; 7223 SmallVector<VariantMatchInfo, 4> VMIs; 7224 while (CalleeFnDecl) { 7225 for (OMPDeclareVariantAttr *A : 7226 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) { 7227 Expr *VariantRef = A->getVariantFuncRef(); 7228 7229 VariantMatchInfo VMI; 7230 OMPTraitInfo &TI = A->getTraitInfo(); 7231 TI.getAsVariantMatchInfo(Context, VMI); 7232 if (!isVariantApplicableInContext(VMI, OMPCtx, 7233 /* DeviceSetOnly */ false)) 7234 continue; 7235 7236 VMIs.push_back(VMI); 7237 Exprs.push_back(VariantRef); 7238 } 7239 7240 CalleeFnDecl = CalleeFnDecl->getPreviousDecl(); 7241 } 7242 7243 ExprResult NewCall; 7244 do { 7245 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx); 7246 if (BestIdx < 0) 7247 return Call; 7248 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]); 7249 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl(); 7250 7251 { 7252 // Try to build a (member) call expression for the current best applicable 7253 // variant expression. We allow this to fail in which case we continue 7254 // with the next best variant expression. The fail case is part of the 7255 // implementation defined behavior in the OpenMP standard when it talks 7256 // about what differences in the function prototypes: "Any differences 7257 // that the specific OpenMP context requires in the prototype of the 7258 // variant from the base function prototype are implementation defined." 7259 // This wording is there to allow the specialized variant to have a 7260 // different type than the base function. This is intended and OK but if 7261 // we cannot create a call the difference is not in the "implementation 7262 // defined range" we allow. 7263 Sema::TentativeAnalysisScope Trap(SemaRef); 7264 7265 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) { 7266 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE); 7267 BestExpr = MemberExpr::CreateImplicit( 7268 Context, MemberCall->getImplicitObjectArgument(), 7269 /* IsArrow */ false, SpecializedMethod, Context.BoundMemberTy, 7270 MemberCall->getValueKind(), MemberCall->getObjectKind()); 7271 } 7272 NewCall = SemaRef.BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs, 7273 RParenLoc, ExecConfig); 7274 if (NewCall.isUsable()) { 7275 if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) { 7276 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee(); 7277 QualType NewType = getASTContext().mergeFunctionTypes( 7278 CalleeFnType, NewCalleeFnDecl->getType(), 7279 /* OfBlockPointer */ false, 7280 /* Unqualified */ false, /* AllowCXX */ true); 7281 if (!NewType.isNull()) 7282 break; 7283 // Don't use the call if the function type was not compatible. 7284 NewCall = nullptr; 7285 } 7286 } 7287 } 7288 7289 VMIs.erase(VMIs.begin() + BestIdx); 7290 Exprs.erase(Exprs.begin() + BestIdx); 7291 } while (!VMIs.empty()); 7292 7293 if (!NewCall.isUsable()) 7294 return Call; 7295 return PseudoObjectExpr::Create(getASTContext(), CE, {NewCall.get()}, 0); 7296 } 7297 7298 std::optional<std::pair<FunctionDecl *, Expr *>> 7299 SemaOpenMP::checkOpenMPDeclareVariantFunction(SemaOpenMP::DeclGroupPtrTy DG, 7300 Expr *VariantRef, 7301 OMPTraitInfo &TI, 7302 unsigned NumAppendArgs, 7303 SourceRange SR) { 7304 ASTContext &Context = getASTContext(); 7305 if (!DG || DG.get().isNull()) 7306 return std::nullopt; 7307 7308 const int VariantId = 1; 7309 // Must be applied only to single decl. 7310 if (!DG.get().isSingleDecl()) { 7311 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant) 7312 << VariantId << SR; 7313 return std::nullopt; 7314 } 7315 Decl *ADecl = DG.get().getSingleDecl(); 7316 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl)) 7317 ADecl = FTD->getTemplatedDecl(); 7318 7319 // Decl must be a function. 7320 auto *FD = dyn_cast<FunctionDecl>(ADecl); 7321 if (!FD) { 7322 Diag(ADecl->getLocation(), diag::err_omp_function_expected) 7323 << VariantId << SR; 7324 return std::nullopt; 7325 } 7326 7327 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) { 7328 // The 'target' attribute needs to be separately checked because it does 7329 // not always signify a multiversion function declaration. 7330 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>(); 7331 }; 7332 // OpenMP is not compatible with multiversion function attributes. 7333 if (HasMultiVersionAttributes(FD)) { 7334 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes) 7335 << SR; 7336 return std::nullopt; 7337 } 7338 7339 // Allow #pragma omp declare variant only if the function is not used. 7340 if (FD->isUsed(false)) 7341 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used) 7342 << FD->getLocation(); 7343 7344 // Check if the function was emitted already. 7345 const FunctionDecl *Definition; 7346 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) && 7347 (getLangOpts().EmitAllDecls || Context.DeclMustBeEmitted(Definition))) 7348 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted) 7349 << FD->getLocation(); 7350 7351 // The VariantRef must point to function. 7352 if (!VariantRef) { 7353 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId; 7354 return std::nullopt; 7355 } 7356 7357 auto ShouldDelayChecks = [](Expr *&E, bool) { 7358 return E && (E->isTypeDependent() || E->isValueDependent() || 7359 E->containsUnexpandedParameterPack() || 7360 E->isInstantiationDependent()); 7361 }; 7362 // Do not check templates, wait until instantiation. 7363 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) || 7364 TI.anyScoreOrCondition(ShouldDelayChecks)) 7365 return std::make_pair(FD, VariantRef); 7366 7367 // Deal with non-constant score and user condition expressions. 7368 auto HandleNonConstantScoresAndConditions = [this](Expr *&E, 7369 bool IsScore) -> bool { 7370 if (!E || E->isIntegerConstantExpr(getASTContext())) 7371 return false; 7372 7373 if (IsScore) { 7374 // We warn on non-constant scores and pretend they were not present. 7375 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant) 7376 << E; 7377 E = nullptr; 7378 } else { 7379 // We could replace a non-constant user condition with "false" but we 7380 // will soon need to handle these anyway for the dynamic version of 7381 // OpenMP context selectors. 7382 Diag(E->getExprLoc(), 7383 diag::err_omp_declare_variant_user_condition_not_constant) 7384 << E; 7385 } 7386 return true; 7387 }; 7388 if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions)) 7389 return std::nullopt; 7390 7391 QualType AdjustedFnType = FD->getType(); 7392 if (NumAppendArgs) { 7393 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>(); 7394 if (!PTy) { 7395 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required) 7396 << SR; 7397 return std::nullopt; 7398 } 7399 // Adjust the function type to account for an extra omp_interop_t for each 7400 // specified in the append_args clause. 7401 const TypeDecl *TD = nullptr; 7402 LookupResult Result(SemaRef, &Context.Idents.get("omp_interop_t"), 7403 SR.getBegin(), Sema::LookupOrdinaryName); 7404 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) { 7405 NamedDecl *ND = Result.getFoundDecl(); 7406 TD = dyn_cast_or_null<TypeDecl>(ND); 7407 } 7408 if (!TD) { 7409 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR; 7410 return std::nullopt; 7411 } 7412 QualType InteropType = Context.getTypeDeclType(TD); 7413 if (PTy->isVariadic()) { 7414 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR; 7415 return std::nullopt; 7416 } 7417 llvm::SmallVector<QualType, 8> Params; 7418 Params.append(PTy->param_type_begin(), PTy->param_type_end()); 7419 Params.insert(Params.end(), NumAppendArgs, InteropType); 7420 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params, 7421 PTy->getExtProtoInfo()); 7422 } 7423 7424 // Convert VariantRef expression to the type of the original function to 7425 // resolve possible conflicts. 7426 ExprResult VariantRefCast = VariantRef; 7427 if (getLangOpts().CPlusPlus) { 7428 QualType FnPtrType; 7429 auto *Method = dyn_cast<CXXMethodDecl>(FD); 7430 if (Method && !Method->isStatic()) { 7431 const Type *ClassType = 7432 Context.getTypeDeclType(Method->getParent()).getTypePtr(); 7433 FnPtrType = Context.getMemberPointerType(AdjustedFnType, ClassType); 7434 ExprResult ER; 7435 { 7436 // Build addr_of unary op to correctly handle type checks for member 7437 // functions. 7438 Sema::TentativeAnalysisScope Trap(SemaRef); 7439 ER = SemaRef.CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf, 7440 VariantRef); 7441 } 7442 if (!ER.isUsable()) { 7443 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected) 7444 << VariantId << VariantRef->getSourceRange(); 7445 return std::nullopt; 7446 } 7447 VariantRef = ER.get(); 7448 } else { 7449 FnPtrType = Context.getPointerType(AdjustedFnType); 7450 } 7451 QualType VarianPtrType = Context.getPointerType(VariantRef->getType()); 7452 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) { 7453 ImplicitConversionSequence ICS = SemaRef.TryImplicitConversion( 7454 VariantRef, FnPtrType.getUnqualifiedType(), 7455 /*SuppressUserConversions=*/false, Sema::AllowedExplicit::None, 7456 /*InOverloadResolution=*/false, 7457 /*CStyle=*/false, 7458 /*AllowObjCWritebackConversion=*/false); 7459 if (ICS.isFailure()) { 7460 Diag(VariantRef->getExprLoc(), 7461 diag::err_omp_declare_variant_incompat_types) 7462 << VariantRef->getType() 7463 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType()) 7464 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange(); 7465 return std::nullopt; 7466 } 7467 VariantRefCast = SemaRef.PerformImplicitConversion( 7468 VariantRef, FnPtrType.getUnqualifiedType(), Sema::AA_Converting); 7469 if (!VariantRefCast.isUsable()) 7470 return std::nullopt; 7471 } 7472 // Drop previously built artificial addr_of unary op for member functions. 7473 if (Method && !Method->isStatic()) { 7474 Expr *PossibleAddrOfVariantRef = VariantRefCast.get(); 7475 if (auto *UO = dyn_cast<UnaryOperator>( 7476 PossibleAddrOfVariantRef->IgnoreImplicit())) 7477 VariantRefCast = UO->getSubExpr(); 7478 } 7479 } 7480 7481 ExprResult ER = SemaRef.CheckPlaceholderExpr(VariantRefCast.get()); 7482 if (!ER.isUsable() || 7483 !ER.get()->IgnoreParenImpCasts()->getType()->isFunctionType()) { 7484 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected) 7485 << VariantId << VariantRef->getSourceRange(); 7486 return std::nullopt; 7487 } 7488 7489 // The VariantRef must point to function. 7490 auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts()); 7491 if (!DRE) { 7492 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected) 7493 << VariantId << VariantRef->getSourceRange(); 7494 return std::nullopt; 7495 } 7496 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl()); 7497 if (!NewFD) { 7498 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected) 7499 << VariantId << VariantRef->getSourceRange(); 7500 return std::nullopt; 7501 } 7502 7503 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) { 7504 Diag(VariantRef->getExprLoc(), 7505 diag::err_omp_declare_variant_same_base_function) 7506 << VariantRef->getSourceRange(); 7507 return std::nullopt; 7508 } 7509 7510 // Check if function types are compatible in C. 7511 if (!getLangOpts().CPlusPlus) { 7512 QualType NewType = 7513 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType()); 7514 if (NewType.isNull()) { 7515 Diag(VariantRef->getExprLoc(), 7516 diag::err_omp_declare_variant_incompat_types) 7517 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0) 7518 << VariantRef->getSourceRange(); 7519 return std::nullopt; 7520 } 7521 if (NewType->isFunctionProtoType()) { 7522 if (FD->getType()->isFunctionNoProtoType()) 7523 setPrototype(SemaRef, FD, NewFD, NewType); 7524 else if (NewFD->getType()->isFunctionNoProtoType()) 7525 setPrototype(SemaRef, NewFD, FD, NewType); 7526 } 7527 } 7528 7529 // Check if variant function is not marked with declare variant directive. 7530 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) { 7531 Diag(VariantRef->getExprLoc(), 7532 diag::warn_omp_declare_variant_marked_as_declare_variant) 7533 << VariantRef->getSourceRange(); 7534 SourceRange SR = 7535 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange(); 7536 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR; 7537 return std::nullopt; 7538 } 7539 7540 enum DoesntSupport { 7541 VirtFuncs = 1, 7542 Constructors = 3, 7543 Destructors = 4, 7544 DeletedFuncs = 5, 7545 DefaultedFuncs = 6, 7546 ConstexprFuncs = 7, 7547 ConstevalFuncs = 8, 7548 }; 7549 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) { 7550 if (CXXFD->isVirtual()) { 7551 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support) 7552 << VirtFuncs; 7553 return std::nullopt; 7554 } 7555 7556 if (isa<CXXConstructorDecl>(FD)) { 7557 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support) 7558 << Constructors; 7559 return std::nullopt; 7560 } 7561 7562 if (isa<CXXDestructorDecl>(FD)) { 7563 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support) 7564 << Destructors; 7565 return std::nullopt; 7566 } 7567 } 7568 7569 if (FD->isDeleted()) { 7570 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support) 7571 << DeletedFuncs; 7572 return std::nullopt; 7573 } 7574 7575 if (FD->isDefaulted()) { 7576 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support) 7577 << DefaultedFuncs; 7578 return std::nullopt; 7579 } 7580 7581 if (FD->isConstexpr()) { 7582 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support) 7583 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs); 7584 return std::nullopt; 7585 } 7586 7587 // Check general compatibility. 7588 if (SemaRef.areMultiversionVariantFunctionsCompatible( 7589 FD, NewFD, PartialDiagnostic::NullDiagnostic(), 7590 PartialDiagnosticAt(SourceLocation(), 7591 PartialDiagnostic::NullDiagnostic()), 7592 PartialDiagnosticAt( 7593 VariantRef->getExprLoc(), 7594 PDiag(diag::err_omp_declare_variant_doesnt_support)), 7595 PartialDiagnosticAt(VariantRef->getExprLoc(), 7596 PDiag(diag::err_omp_declare_variant_diff) 7597 << FD->getLocation()), 7598 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false, 7599 /*CLinkageMayDiffer=*/true)) 7600 return std::nullopt; 7601 return std::make_pair(FD, cast<Expr>(DRE)); 7602 } 7603 7604 void SemaOpenMP::ActOnOpenMPDeclareVariantDirective( 7605 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, 7606 ArrayRef<Expr *> AdjustArgsNothing, 7607 ArrayRef<Expr *> AdjustArgsNeedDevicePtr, 7608 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc, 7609 SourceLocation AppendArgsLoc, SourceRange SR) { 7610 7611 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions] 7612 // An adjust_args clause or append_args clause can only be specified if the 7613 // dispatch selector of the construct selector set appears in the match 7614 // clause. 7615 7616 SmallVector<Expr *, 8> AllAdjustArgs; 7617 llvm::append_range(AllAdjustArgs, AdjustArgsNothing); 7618 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr); 7619 7620 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) { 7621 VariantMatchInfo VMI; 7622 TI.getAsVariantMatchInfo(getASTContext(), VMI); 7623 if (!llvm::is_contained( 7624 VMI.ConstructTraits, 7625 llvm::omp::TraitProperty::construct_dispatch_dispatch)) { 7626 if (!AllAdjustArgs.empty()) 7627 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct) 7628 << getOpenMPClauseName(OMPC_adjust_args); 7629 if (!AppendArgs.empty()) 7630 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct) 7631 << getOpenMPClauseName(OMPC_append_args); 7632 return; 7633 } 7634 } 7635 7636 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions] 7637 // Each argument can only appear in a single adjust_args clause for each 7638 // declare variant directive. 7639 llvm::SmallPtrSet<const VarDecl *, 4> AdjustVars; 7640 7641 for (Expr *E : AllAdjustArgs) { 7642 E = E->IgnoreParenImpCasts(); 7643 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) { 7644 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) { 7645 const VarDecl *CanonPVD = PVD->getCanonicalDecl(); 7646 if (FD->getNumParams() > PVD->getFunctionScopeIndex() && 7647 FD->getParamDecl(PVD->getFunctionScopeIndex()) 7648 ->getCanonicalDecl() == CanonPVD) { 7649 // It's a parameter of the function, check duplicates. 7650 if (!AdjustVars.insert(CanonPVD).second) { 7651 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses) 7652 << PVD; 7653 return; 7654 } 7655 continue; 7656 } 7657 } 7658 } 7659 // Anything that is not a function parameter is an error. 7660 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0; 7661 return; 7662 } 7663 7664 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit( 7665 getASTContext(), VariantRef, &TI, 7666 const_cast<Expr **>(AdjustArgsNothing.data()), AdjustArgsNothing.size(), 7667 const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()), 7668 AdjustArgsNeedDevicePtr.size(), 7669 const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR); 7670 FD->addAttr(NewAttr); 7671 } 7672 7673 static CapturedStmt * 7674 setBranchProtectedScope(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt) { 7675 auto *CS = dyn_cast<CapturedStmt>(AStmt); 7676 assert(CS && "Captured statement expected"); 7677 // 1.2.2 OpenMP Language Terminology 7678 // Structured block - An executable statement with a single entry at the 7679 // top and a single exit at the bottom. 7680 // The point of exit cannot be a branch out of the structured block. 7681 // longjmp() and throw() must not violate the entry/exit criteria. 7682 CS->getCapturedDecl()->setNothrow(); 7683 7684 for (int ThisCaptureLevel = SemaRef.OpenMP().getOpenMPCaptureLevels(DKind); 7685 ThisCaptureLevel > 1; --ThisCaptureLevel) { 7686 CS = cast<CapturedStmt>(CS->getCapturedStmt()); 7687 // 1.2.2 OpenMP Language Terminology 7688 // Structured block - An executable statement with a single entry at the 7689 // top and a single exit at the bottom. 7690 // The point of exit cannot be a branch out of the structured block. 7691 // longjmp() and throw() must not violate the entry/exit criteria. 7692 CS->getCapturedDecl()->setNothrow(); 7693 } 7694 SemaRef.setFunctionHasBranchProtectedScope(); 7695 return CS; 7696 } 7697 7698 StmtResult 7699 SemaOpenMP::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses, 7700 Stmt *AStmt, SourceLocation StartLoc, 7701 SourceLocation EndLoc) { 7702 if (!AStmt) 7703 return StmtError(); 7704 7705 setBranchProtectedScope(SemaRef, OMPD_parallel, AStmt); 7706 7707 return OMPParallelDirective::Create( 7708 getASTContext(), StartLoc, EndLoc, Clauses, AStmt, 7709 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion()); 7710 } 7711 7712 namespace { 7713 /// Iteration space of a single for loop. 7714 struct LoopIterationSpace final { 7715 /// True if the condition operator is the strict compare operator (<, > or 7716 /// !=). 7717 bool IsStrictCompare = false; 7718 /// Condition of the loop. 7719 Expr *PreCond = nullptr; 7720 /// This expression calculates the number of iterations in the loop. 7721 /// It is always possible to calculate it before starting the loop. 7722 Expr *NumIterations = nullptr; 7723 /// The loop counter variable. 7724 Expr *CounterVar = nullptr; 7725 /// Private loop counter variable. 7726 Expr *PrivateCounterVar = nullptr; 7727 /// This is initializer for the initial value of #CounterVar. 7728 Expr *CounterInit = nullptr; 7729 /// This is step for the #CounterVar used to generate its update: 7730 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration. 7731 Expr *CounterStep = nullptr; 7732 /// Should step be subtracted? 7733 bool Subtract = false; 7734 /// Source range of the loop init. 7735 SourceRange InitSrcRange; 7736 /// Source range of the loop condition. 7737 SourceRange CondSrcRange; 7738 /// Source range of the loop increment. 7739 SourceRange IncSrcRange; 7740 /// Minimum value that can have the loop control variable. Used to support 7741 /// non-rectangular loops. Applied only for LCV with the non-iterator types, 7742 /// since only such variables can be used in non-loop invariant expressions. 7743 Expr *MinValue = nullptr; 7744 /// Maximum value that can have the loop control variable. Used to support 7745 /// non-rectangular loops. Applied only for LCV with the non-iterator type, 7746 /// since only such variables can be used in non-loop invariant expressions. 7747 Expr *MaxValue = nullptr; 7748 /// true, if the lower bound depends on the outer loop control var. 7749 bool IsNonRectangularLB = false; 7750 /// true, if the upper bound depends on the outer loop control var. 7751 bool IsNonRectangularUB = false; 7752 /// Index of the loop this loop depends on and forms non-rectangular loop 7753 /// nest. 7754 unsigned LoopDependentIdx = 0; 7755 /// Final condition for the non-rectangular loop nest support. It is used to 7756 /// check that the number of iterations for this particular counter must be 7757 /// finished. 7758 Expr *FinalCondition = nullptr; 7759 }; 7760 7761 /// Helper class for checking canonical form of the OpenMP loops and 7762 /// extracting iteration space of each loop in the loop nest, that will be used 7763 /// for IR generation. 7764 class OpenMPIterationSpaceChecker { 7765 /// Reference to Sema. 7766 Sema &SemaRef; 7767 /// Does the loop associated directive support non-rectangular loops? 7768 bool SupportsNonRectangular; 7769 /// Data-sharing stack. 7770 DSAStackTy &Stack; 7771 /// A location for diagnostics (when there is no some better location). 7772 SourceLocation DefaultLoc; 7773 /// A location for diagnostics (when increment is not compatible). 7774 SourceLocation ConditionLoc; 7775 /// A source location for referring to loop init later. 7776 SourceRange InitSrcRange; 7777 /// A source location for referring to condition later. 7778 SourceRange ConditionSrcRange; 7779 /// A source location for referring to increment later. 7780 SourceRange IncrementSrcRange; 7781 /// Loop variable. 7782 ValueDecl *LCDecl = nullptr; 7783 /// Reference to loop variable. 7784 Expr *LCRef = nullptr; 7785 /// Lower bound (initializer for the var). 7786 Expr *LB = nullptr; 7787 /// Upper bound. 7788 Expr *UB = nullptr; 7789 /// Loop step (increment). 7790 Expr *Step = nullptr; 7791 /// This flag is true when condition is one of: 7792 /// Var < UB 7793 /// Var <= UB 7794 /// UB > Var 7795 /// UB >= Var 7796 /// This will have no value when the condition is != 7797 std::optional<bool> TestIsLessOp; 7798 /// This flag is true when condition is strict ( < or > ). 7799 bool TestIsStrictOp = false; 7800 /// This flag is true when step is subtracted on each iteration. 7801 bool SubtractStep = false; 7802 /// The outer loop counter this loop depends on (if any). 7803 const ValueDecl *DepDecl = nullptr; 7804 /// Contains number of loop (starts from 1) on which loop counter init 7805 /// expression of this loop depends on. 7806 std::optional<unsigned> InitDependOnLC; 7807 /// Contains number of loop (starts from 1) on which loop counter condition 7808 /// expression of this loop depends on. 7809 std::optional<unsigned> CondDependOnLC; 7810 /// Checks if the provide statement depends on the loop counter. 7811 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S, 7812 bool IsInitializer); 7813 /// Original condition required for checking of the exit condition for 7814 /// non-rectangular loop. 7815 Expr *Condition = nullptr; 7816 7817 public: 7818 OpenMPIterationSpaceChecker(Sema &SemaRef, bool SupportsNonRectangular, 7819 DSAStackTy &Stack, SourceLocation DefaultLoc) 7820 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular), 7821 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc) {} 7822 /// Check init-expr for canonical loop form and save loop counter 7823 /// variable - #Var and its initialization value - #LB. 7824 bool checkAndSetInit(Stmt *S, bool EmitDiags = true); 7825 /// Check test-expr for canonical form, save upper-bound (#UB), flags 7826 /// for less/greater and for strict/non-strict comparison. 7827 bool checkAndSetCond(Expr *S); 7828 /// Check incr-expr for canonical loop form and return true if it 7829 /// does not conform, otherwise save loop step (#Step). 7830 bool checkAndSetInc(Expr *S); 7831 /// Return the loop counter variable. 7832 ValueDecl *getLoopDecl() const { return LCDecl; } 7833 /// Return the reference expression to loop counter variable. 7834 Expr *getLoopDeclRefExpr() const { return LCRef; } 7835 /// Source range of the loop init. 7836 SourceRange getInitSrcRange() const { return InitSrcRange; } 7837 /// Source range of the loop condition. 7838 SourceRange getConditionSrcRange() const { return ConditionSrcRange; } 7839 /// Source range of the loop increment. 7840 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; } 7841 /// True if the step should be subtracted. 7842 bool shouldSubtractStep() const { return SubtractStep; } 7843 /// True, if the compare operator is strict (<, > or !=). 7844 bool isStrictTestOp() const { return TestIsStrictOp; } 7845 /// Build the expression to calculate the number of iterations. 7846 Expr *buildNumIterations( 7847 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType, 7848 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const; 7849 /// Build the precondition expression for the loops. 7850 Expr * 7851 buildPreCond(Scope *S, Expr *Cond, 7852 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const; 7853 /// Build reference expression to the counter be used for codegen. 7854 DeclRefExpr * 7855 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, 7856 DSAStackTy &DSA) const; 7857 /// Build reference expression to the private counter be used for 7858 /// codegen. 7859 Expr *buildPrivateCounterVar() const; 7860 /// Build initialization of the counter be used for codegen. 7861 Expr *buildCounterInit() const; 7862 /// Build step of the counter be used for codegen. 7863 Expr *buildCounterStep() const; 7864 /// Build loop data with counter value for depend clauses in ordered 7865 /// directives. 7866 Expr * 7867 buildOrderedLoopData(Scope *S, Expr *Counter, 7868 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, 7869 SourceLocation Loc, Expr *Inc = nullptr, 7870 OverloadedOperatorKind OOK = OO_Amp); 7871 /// Builds the minimum value for the loop counter. 7872 std::pair<Expr *, Expr *> buildMinMaxValues( 7873 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const; 7874 /// Builds final condition for the non-rectangular loops. 7875 Expr *buildFinalCondition(Scope *S) const; 7876 /// Return true if any expression is dependent. 7877 bool dependent() const; 7878 /// Returns true if the initializer forms non-rectangular loop. 7879 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); } 7880 /// Returns true if the condition forms non-rectangular loop. 7881 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); } 7882 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise. 7883 unsigned getLoopDependentIdx() const { 7884 return InitDependOnLC.value_or(CondDependOnLC.value_or(0)); 7885 } 7886 7887 private: 7888 /// Check the right-hand side of an assignment in the increment 7889 /// expression. 7890 bool checkAndSetIncRHS(Expr *RHS); 7891 /// Helper to set loop counter variable and its initializer. 7892 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB, 7893 bool EmitDiags); 7894 /// Helper to set upper bound. 7895 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp, 7896 SourceRange SR, SourceLocation SL); 7897 /// Helper to set loop increment. 7898 bool setStep(Expr *NewStep, bool Subtract); 7899 }; 7900 7901 bool OpenMPIterationSpaceChecker::dependent() const { 7902 if (!LCDecl) { 7903 assert(!LB && !UB && !Step); 7904 return false; 7905 } 7906 return LCDecl->getType()->isDependentType() || 7907 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) || 7908 (Step && Step->isValueDependent()); 7909 } 7910 7911 bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl, 7912 Expr *NewLCRefExpr, 7913 Expr *NewLB, bool EmitDiags) { 7914 // State consistency checking to ensure correct usage. 7915 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr && 7916 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp); 7917 if (!NewLCDecl || !NewLB || NewLB->containsErrors()) 7918 return true; 7919 LCDecl = getCanonicalDecl(NewLCDecl); 7920 LCRef = NewLCRefExpr; 7921 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB)) 7922 if (const CXXConstructorDecl *Ctor = CE->getConstructor()) 7923 if ((Ctor->isCopyOrMoveConstructor() || 7924 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) && 7925 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr) 7926 NewLB = CE->getArg(0)->IgnoreParenImpCasts(); 7927 LB = NewLB; 7928 if (EmitDiags) 7929 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true); 7930 return false; 7931 } 7932 7933 bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp, 7934 bool StrictOp, SourceRange SR, 7935 SourceLocation SL) { 7936 // State consistency checking to ensure correct usage. 7937 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr && 7938 Step == nullptr && !TestIsLessOp && !TestIsStrictOp); 7939 if (!NewUB || NewUB->containsErrors()) 7940 return true; 7941 UB = NewUB; 7942 if (LessOp) 7943 TestIsLessOp = LessOp; 7944 TestIsStrictOp = StrictOp; 7945 ConditionSrcRange = SR; 7946 ConditionLoc = SL; 7947 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false); 7948 return false; 7949 } 7950 7951 bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) { 7952 // State consistency checking to ensure correct usage. 7953 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr); 7954 if (!NewStep || NewStep->containsErrors()) 7955 return true; 7956 if (!NewStep->isValueDependent()) { 7957 // Check that the step is integer expression. 7958 SourceLocation StepLoc = NewStep->getBeginLoc(); 7959 ExprResult Val = SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion( 7960 StepLoc, getExprAsWritten(NewStep)); 7961 if (Val.isInvalid()) 7962 return true; 7963 NewStep = Val.get(); 7964 7965 // OpenMP [2.6, Canonical Loop Form, Restrictions] 7966 // If test-expr is of form var relational-op b and relational-op is < or 7967 // <= then incr-expr must cause var to increase on each iteration of the 7968 // loop. If test-expr is of form var relational-op b and relational-op is 7969 // > or >= then incr-expr must cause var to decrease on each iteration of 7970 // the loop. 7971 // If test-expr is of form b relational-op var and relational-op is < or 7972 // <= then incr-expr must cause var to decrease on each iteration of the 7973 // loop. If test-expr is of form b relational-op var and relational-op is 7974 // > or >= then incr-expr must cause var to increase on each iteration of 7975 // the loop. 7976 std::optional<llvm::APSInt> Result = 7977 NewStep->getIntegerConstantExpr(SemaRef.Context); 7978 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation(); 7979 bool IsConstNeg = 7980 Result && Result->isSigned() && (Subtract != Result->isNegative()); 7981 bool IsConstPos = 7982 Result && Result->isSigned() && (Subtract == Result->isNegative()); 7983 bool IsConstZero = Result && !Result->getBoolValue(); 7984 7985 // != with increment is treated as <; != with decrement is treated as > 7986 if (!TestIsLessOp) 7987 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract); 7988 if (UB && (IsConstZero || 7989 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract)) 7990 : (IsConstPos || (IsUnsigned && !Subtract))))) { 7991 SemaRef.Diag(NewStep->getExprLoc(), 7992 diag::err_omp_loop_incr_not_compatible) 7993 << LCDecl << *TestIsLessOp << NewStep->getSourceRange(); 7994 SemaRef.Diag(ConditionLoc, 7995 diag::note_omp_loop_cond_requires_compatible_incr) 7996 << *TestIsLessOp << ConditionSrcRange; 7997 return true; 7998 } 7999 if (*TestIsLessOp == Subtract) { 8000 NewStep = 8001 SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep) 8002 .get(); 8003 Subtract = !Subtract; 8004 } 8005 } 8006 8007 Step = NewStep; 8008 SubtractStep = Subtract; 8009 return false; 8010 } 8011 8012 namespace { 8013 /// Checker for the non-rectangular loops. Checks if the initializer or 8014 /// condition expression references loop counter variable. 8015 class LoopCounterRefChecker final 8016 : public ConstStmtVisitor<LoopCounterRefChecker, bool> { 8017 Sema &SemaRef; 8018 DSAStackTy &Stack; 8019 const ValueDecl *CurLCDecl = nullptr; 8020 const ValueDecl *DepDecl = nullptr; 8021 const ValueDecl *PrevDepDecl = nullptr; 8022 bool IsInitializer = true; 8023 bool SupportsNonRectangular; 8024 unsigned BaseLoopId = 0; 8025 bool checkDecl(const Expr *E, const ValueDecl *VD) { 8026 if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) { 8027 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter) 8028 << (IsInitializer ? 0 : 1); 8029 return false; 8030 } 8031 const auto &&Data = Stack.isLoopControlVariable(VD); 8032 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions. 8033 // The type of the loop iterator on which we depend may not have a random 8034 // access iterator type. 8035 if (Data.first && VD->getType()->isRecordType()) { 8036 SmallString<128> Name; 8037 llvm::raw_svector_ostream OS(Name); 8038 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(), 8039 /*Qualified=*/true); 8040 SemaRef.Diag(E->getExprLoc(), 8041 diag::err_omp_wrong_dependency_iterator_type) 8042 << OS.str(); 8043 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD; 8044 return false; 8045 } 8046 if (Data.first && !SupportsNonRectangular) { 8047 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency); 8048 return false; 8049 } 8050 if (Data.first && 8051 (DepDecl || (PrevDepDecl && 8052 getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) { 8053 if (!DepDecl && PrevDepDecl) 8054 DepDecl = PrevDepDecl; 8055 SmallString<128> Name; 8056 llvm::raw_svector_ostream OS(Name); 8057 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(), 8058 /*Qualified=*/true); 8059 SemaRef.Diag(E->getExprLoc(), 8060 diag::err_omp_invariant_or_linear_dependency) 8061 << OS.str(); 8062 return false; 8063 } 8064 if (Data.first) { 8065 DepDecl = VD; 8066 BaseLoopId = Data.first; 8067 } 8068 return Data.first; 8069 } 8070 8071 public: 8072 bool VisitDeclRefExpr(const DeclRefExpr *E) { 8073 const ValueDecl *VD = E->getDecl(); 8074 if (isa<VarDecl>(VD)) 8075 return checkDecl(E, VD); 8076 return false; 8077 } 8078 bool VisitMemberExpr(const MemberExpr *E) { 8079 if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) { 8080 const ValueDecl *VD = E->getMemberDecl(); 8081 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD)) 8082 return checkDecl(E, VD); 8083 } 8084 return false; 8085 } 8086 bool VisitStmt(const Stmt *S) { 8087 bool Res = false; 8088 for (const Stmt *Child : S->children()) 8089 Res = (Child && Visit(Child)) || Res; 8090 return Res; 8091 } 8092 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack, 8093 const ValueDecl *CurLCDecl, bool IsInitializer, 8094 const ValueDecl *PrevDepDecl = nullptr, 8095 bool SupportsNonRectangular = true) 8096 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl), 8097 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer), 8098 SupportsNonRectangular(SupportsNonRectangular) {} 8099 unsigned getBaseLoopId() const { 8100 assert(CurLCDecl && "Expected loop dependency."); 8101 return BaseLoopId; 8102 } 8103 const ValueDecl *getDepDecl() const { 8104 assert(CurLCDecl && "Expected loop dependency."); 8105 return DepDecl; 8106 } 8107 }; 8108 } // namespace 8109 8110 std::optional<unsigned> 8111 OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S, 8112 bool IsInitializer) { 8113 // Check for the non-rectangular loops. 8114 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer, 8115 DepDecl, SupportsNonRectangular); 8116 if (LoopStmtChecker.Visit(S)) { 8117 DepDecl = LoopStmtChecker.getDepDecl(); 8118 return LoopStmtChecker.getBaseLoopId(); 8119 } 8120 return std::nullopt; 8121 } 8122 8123 bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) { 8124 // Check init-expr for canonical loop form and save loop counter 8125 // variable - #Var and its initialization value - #LB. 8126 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following: 8127 // var = lb 8128 // integer-type var = lb 8129 // random-access-iterator-type var = lb 8130 // pointer-type var = lb 8131 // 8132 if (!S) { 8133 if (EmitDiags) { 8134 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init); 8135 } 8136 return true; 8137 } 8138 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S)) 8139 if (!ExprTemp->cleanupsHaveSideEffects()) 8140 S = ExprTemp->getSubExpr(); 8141 8142 InitSrcRange = S->getSourceRange(); 8143 if (Expr *E = dyn_cast<Expr>(S)) 8144 S = E->IgnoreParens(); 8145 if (auto *BO = dyn_cast<BinaryOperator>(S)) { 8146 if (BO->getOpcode() == BO_Assign) { 8147 Expr *LHS = BO->getLHS()->IgnoreParens(); 8148 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) { 8149 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl())) 8150 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit()))) 8151 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(), 8152 EmitDiags); 8153 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags); 8154 } 8155 if (auto *ME = dyn_cast<MemberExpr>(LHS)) { 8156 if (ME->isArrow() && 8157 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) 8158 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(), 8159 EmitDiags); 8160 } 8161 } 8162 } else if (auto *DS = dyn_cast<DeclStmt>(S)) { 8163 if (DS->isSingleDecl()) { 8164 if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) { 8165 if (Var->hasInit() && !Var->getType()->isReferenceType()) { 8166 // Accept non-canonical init form here but emit ext. warning. 8167 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags) 8168 SemaRef.Diag(S->getBeginLoc(), 8169 diag::ext_omp_loop_not_canonical_init) 8170 << S->getSourceRange(); 8171 return setLCDeclAndLB( 8172 Var, 8173 buildDeclRefExpr(SemaRef, Var, 8174 Var->getType().getNonReferenceType(), 8175 DS->getBeginLoc()), 8176 Var->getInit(), EmitDiags); 8177 } 8178 } 8179 } 8180 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) { 8181 if (CE->getOperator() == OO_Equal) { 8182 Expr *LHS = CE->getArg(0); 8183 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) { 8184 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl())) 8185 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit()))) 8186 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(), 8187 EmitDiags); 8188 return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags); 8189 } 8190 if (auto *ME = dyn_cast<MemberExpr>(LHS)) { 8191 if (ME->isArrow() && 8192 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) 8193 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(), 8194 EmitDiags); 8195 } 8196 } 8197 } 8198 8199 if (dependent() || SemaRef.CurContext->isDependentContext()) 8200 return false; 8201 if (EmitDiags) { 8202 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init) 8203 << S->getSourceRange(); 8204 } 8205 return true; 8206 } 8207 8208 /// Ignore parenthesizes, implicit casts, copy constructor and return the 8209 /// variable (which may be the loop variable) if possible. 8210 static const ValueDecl *getInitLCDecl(const Expr *E) { 8211 if (!E) 8212 return nullptr; 8213 E = getExprAsWritten(E); 8214 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E)) 8215 if (const CXXConstructorDecl *Ctor = CE->getConstructor()) 8216 if ((Ctor->isCopyOrMoveConstructor() || 8217 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) && 8218 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr) 8219 E = CE->getArg(0)->IgnoreParenImpCasts(); 8220 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) { 8221 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) 8222 return getCanonicalDecl(VD); 8223 } 8224 if (const auto *ME = dyn_cast_or_null<MemberExpr>(E)) 8225 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) 8226 return getCanonicalDecl(ME->getMemberDecl()); 8227 return nullptr; 8228 } 8229 8230 bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) { 8231 // Check test-expr for canonical form, save upper-bound UB, flags for 8232 // less/greater and for strict/non-strict comparison. 8233 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following: 8234 // var relational-op b 8235 // b relational-op var 8236 // 8237 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50; 8238 if (!S) { 8239 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond) 8240 << (IneqCondIsCanonical ? 1 : 0) << LCDecl; 8241 return true; 8242 } 8243 Condition = S; 8244 S = getExprAsWritten(S); 8245 SourceLocation CondLoc = S->getBeginLoc(); 8246 auto &&CheckAndSetCond = 8247 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS, 8248 const Expr *RHS, SourceRange SR, 8249 SourceLocation OpLoc) -> std::optional<bool> { 8250 if (BinaryOperator::isRelationalOp(Opcode)) { 8251 if (getInitLCDecl(LHS) == LCDecl) 8252 return setUB(const_cast<Expr *>(RHS), 8253 (Opcode == BO_LT || Opcode == BO_LE), 8254 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc); 8255 if (getInitLCDecl(RHS) == LCDecl) 8256 return setUB(const_cast<Expr *>(LHS), 8257 (Opcode == BO_GT || Opcode == BO_GE), 8258 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc); 8259 } else if (IneqCondIsCanonical && Opcode == BO_NE) { 8260 return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS), 8261 /*LessOp=*/std::nullopt, 8262 /*StrictOp=*/true, SR, OpLoc); 8263 } 8264 return std::nullopt; 8265 }; 8266 std::optional<bool> Res; 8267 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) { 8268 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm(); 8269 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(), 8270 RBO->getOperatorLoc()); 8271 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) { 8272 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(), 8273 BO->getSourceRange(), BO->getOperatorLoc()); 8274 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) { 8275 if (CE->getNumArgs() == 2) { 8276 Res = CheckAndSetCond( 8277 BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0), 8278 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc()); 8279 } 8280 } 8281 if (Res) 8282 return *Res; 8283 if (dependent() || SemaRef.CurContext->isDependentContext()) 8284 return false; 8285 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond) 8286 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl; 8287 return true; 8288 } 8289 8290 bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) { 8291 // RHS of canonical loop form increment can be: 8292 // var + incr 8293 // incr + var 8294 // var - incr 8295 // 8296 RHS = RHS->IgnoreParenImpCasts(); 8297 if (auto *BO = dyn_cast<BinaryOperator>(RHS)) { 8298 if (BO->isAdditiveOp()) { 8299 bool IsAdd = BO->getOpcode() == BO_Add; 8300 if (getInitLCDecl(BO->getLHS()) == LCDecl) 8301 return setStep(BO->getRHS(), !IsAdd); 8302 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl) 8303 return setStep(BO->getLHS(), /*Subtract=*/false); 8304 } 8305 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) { 8306 bool IsAdd = CE->getOperator() == OO_Plus; 8307 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) { 8308 if (getInitLCDecl(CE->getArg(0)) == LCDecl) 8309 return setStep(CE->getArg(1), !IsAdd); 8310 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl) 8311 return setStep(CE->getArg(0), /*Subtract=*/false); 8312 } 8313 } 8314 if (dependent() || SemaRef.CurContext->isDependentContext()) 8315 return false; 8316 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr) 8317 << RHS->getSourceRange() << LCDecl; 8318 return true; 8319 } 8320 8321 bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) { 8322 // Check incr-expr for canonical loop form and return true if it 8323 // does not conform. 8324 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following: 8325 // ++var 8326 // var++ 8327 // --var 8328 // var-- 8329 // var += incr 8330 // var -= incr 8331 // var = var + incr 8332 // var = incr + var 8333 // var = var - incr 8334 // 8335 if (!S) { 8336 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl; 8337 return true; 8338 } 8339 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S)) 8340 if (!ExprTemp->cleanupsHaveSideEffects()) 8341 S = ExprTemp->getSubExpr(); 8342 8343 IncrementSrcRange = S->getSourceRange(); 8344 S = S->IgnoreParens(); 8345 if (auto *UO = dyn_cast<UnaryOperator>(S)) { 8346 if (UO->isIncrementDecrementOp() && 8347 getInitLCDecl(UO->getSubExpr()) == LCDecl) 8348 return setStep(SemaRef 8349 .ActOnIntegerConstant(UO->getBeginLoc(), 8350 (UO->isDecrementOp() ? -1 : 1)) 8351 .get(), 8352 /*Subtract=*/false); 8353 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) { 8354 switch (BO->getOpcode()) { 8355 case BO_AddAssign: 8356 case BO_SubAssign: 8357 if (getInitLCDecl(BO->getLHS()) == LCDecl) 8358 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign); 8359 break; 8360 case BO_Assign: 8361 if (getInitLCDecl(BO->getLHS()) == LCDecl) 8362 return checkAndSetIncRHS(BO->getRHS()); 8363 break; 8364 default: 8365 break; 8366 } 8367 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) { 8368 switch (CE->getOperator()) { 8369 case OO_PlusPlus: 8370 case OO_MinusMinus: 8371 if (getInitLCDecl(CE->getArg(0)) == LCDecl) 8372 return setStep(SemaRef 8373 .ActOnIntegerConstant( 8374 CE->getBeginLoc(), 8375 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1)) 8376 .get(), 8377 /*Subtract=*/false); 8378 break; 8379 case OO_PlusEqual: 8380 case OO_MinusEqual: 8381 if (getInitLCDecl(CE->getArg(0)) == LCDecl) 8382 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual); 8383 break; 8384 case OO_Equal: 8385 if (getInitLCDecl(CE->getArg(0)) == LCDecl) 8386 return checkAndSetIncRHS(CE->getArg(1)); 8387 break; 8388 default: 8389 break; 8390 } 8391 } 8392 if (dependent() || SemaRef.CurContext->isDependentContext()) 8393 return false; 8394 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr) 8395 << S->getSourceRange() << LCDecl; 8396 return true; 8397 } 8398 8399 static ExprResult 8400 tryBuildCapture(Sema &SemaRef, Expr *Capture, 8401 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, 8402 StringRef Name = ".capture_expr.") { 8403 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors()) 8404 return Capture; 8405 if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects)) 8406 return SemaRef.PerformImplicitConversion( 8407 Capture->IgnoreImpCasts(), Capture->getType(), Sema::AA_Converting, 8408 /*AllowExplicit=*/true); 8409 auto I = Captures.find(Capture); 8410 if (I != Captures.end()) 8411 return buildCapture(SemaRef, Capture, I->second, Name); 8412 DeclRefExpr *Ref = nullptr; 8413 ExprResult Res = buildCapture(SemaRef, Capture, Ref, Name); 8414 Captures[Capture] = Ref; 8415 return Res; 8416 } 8417 8418 /// Calculate number of iterations, transforming to unsigned, if number of 8419 /// iterations may be larger than the original type. 8420 static Expr * 8421 calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc, 8422 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy, 8423 bool TestIsStrictOp, bool RoundToStep, 8424 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) { 8425 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step"); 8426 if (!NewStep.isUsable()) 8427 return nullptr; 8428 llvm::APSInt LRes, SRes; 8429 bool IsLowerConst = false, IsStepConst = false; 8430 if (std::optional<llvm::APSInt> Res = 8431 Lower->getIntegerConstantExpr(SemaRef.Context)) { 8432 LRes = *Res; 8433 IsLowerConst = true; 8434 } 8435 if (std::optional<llvm::APSInt> Res = 8436 Step->getIntegerConstantExpr(SemaRef.Context)) { 8437 SRes = *Res; 8438 IsStepConst = true; 8439 } 8440 bool NoNeedToConvert = IsLowerConst && !RoundToStep && 8441 ((!TestIsStrictOp && LRes.isNonNegative()) || 8442 (TestIsStrictOp && LRes.isStrictlyPositive())); 8443 bool NeedToReorganize = false; 8444 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow. 8445 if (!NoNeedToConvert && IsLowerConst && 8446 (TestIsStrictOp || (RoundToStep && IsStepConst))) { 8447 NoNeedToConvert = true; 8448 if (RoundToStep) { 8449 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth() 8450 ? LRes.getBitWidth() 8451 : SRes.getBitWidth(); 8452 LRes = LRes.extend(BW + 1); 8453 LRes.setIsSigned(true); 8454 SRes = SRes.extend(BW + 1); 8455 SRes.setIsSigned(true); 8456 LRes -= SRes; 8457 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes; 8458 LRes = LRes.trunc(BW); 8459 } 8460 if (TestIsStrictOp) { 8461 unsigned BW = LRes.getBitWidth(); 8462 LRes = LRes.extend(BW + 1); 8463 LRes.setIsSigned(true); 8464 ++LRes; 8465 NoNeedToConvert = 8466 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes; 8467 // truncate to the original bitwidth. 8468 LRes = LRes.trunc(BW); 8469 } 8470 NeedToReorganize = NoNeedToConvert; 8471 } 8472 llvm::APSInt URes; 8473 bool IsUpperConst = false; 8474 if (std::optional<llvm::APSInt> Res = 8475 Upper->getIntegerConstantExpr(SemaRef.Context)) { 8476 URes = *Res; 8477 IsUpperConst = true; 8478 } 8479 if (NoNeedToConvert && IsLowerConst && IsUpperConst && 8480 (!RoundToStep || IsStepConst)) { 8481 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth() 8482 : URes.getBitWidth(); 8483 LRes = LRes.extend(BW + 1); 8484 LRes.setIsSigned(true); 8485 URes = URes.extend(BW + 1); 8486 URes.setIsSigned(true); 8487 URes -= LRes; 8488 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes; 8489 NeedToReorganize = NoNeedToConvert; 8490 } 8491 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant 8492 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to 8493 // unsigned. 8494 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) && 8495 !LCTy->isDependentType() && LCTy->isIntegerType()) { 8496 QualType LowerTy = Lower->getType(); 8497 QualType UpperTy = Upper->getType(); 8498 uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy); 8499 uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy); 8500 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) || 8501 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) { 8502 QualType CastType = SemaRef.Context.getIntTypeForBitwidth( 8503 LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0); 8504 Upper = 8505 SemaRef 8506 .PerformImplicitConversion( 8507 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(), 8508 CastType, Sema::AA_Converting) 8509 .get(); 8510 Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(); 8511 NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get()); 8512 } 8513 } 8514 if (!Lower || !Upper || NewStep.isInvalid()) 8515 return nullptr; 8516 8517 ExprResult Diff; 8518 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+ 8519 // 1]). 8520 if (NeedToReorganize) { 8521 Diff = Lower; 8522 8523 if (RoundToStep) { 8524 // Lower - Step 8525 Diff = 8526 SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get()); 8527 if (!Diff.isUsable()) 8528 return nullptr; 8529 } 8530 8531 // Lower - Step [+ 1] 8532 if (TestIsStrictOp) 8533 Diff = SemaRef.BuildBinOp( 8534 S, DefaultLoc, BO_Add, Diff.get(), 8535 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get()); 8536 if (!Diff.isUsable()) 8537 return nullptr; 8538 8539 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get()); 8540 if (!Diff.isUsable()) 8541 return nullptr; 8542 8543 // Upper - (Lower - Step [+ 1]). 8544 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get()); 8545 if (!Diff.isUsable()) 8546 return nullptr; 8547 } else { 8548 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower); 8549 8550 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) { 8551 // BuildBinOp already emitted error, this one is to point user to upper 8552 // and lower bound, and to tell what is passed to 'operator-'. 8553 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx) 8554 << Upper->getSourceRange() << Lower->getSourceRange(); 8555 return nullptr; 8556 } 8557 8558 if (!Diff.isUsable()) 8559 return nullptr; 8560 8561 // Upper - Lower [- 1] 8562 if (TestIsStrictOp) 8563 Diff = SemaRef.BuildBinOp( 8564 S, DefaultLoc, BO_Sub, Diff.get(), 8565 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get()); 8566 if (!Diff.isUsable()) 8567 return nullptr; 8568 8569 if (RoundToStep) { 8570 // Upper - Lower [- 1] + Step 8571 Diff = 8572 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get()); 8573 if (!Diff.isUsable()) 8574 return nullptr; 8575 } 8576 } 8577 8578 // Parentheses (for dumping/debugging purposes only). 8579 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get()); 8580 if (!Diff.isUsable()) 8581 return nullptr; 8582 8583 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step 8584 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get()); 8585 if (!Diff.isUsable()) 8586 return nullptr; 8587 8588 return Diff.get(); 8589 } 8590 8591 /// Build the expression to calculate the number of iterations. 8592 Expr *OpenMPIterationSpaceChecker::buildNumIterations( 8593 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType, 8594 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const { 8595 QualType VarType = LCDecl->getType().getNonReferenceType(); 8596 if (!VarType->isIntegerType() && !VarType->isPointerType() && 8597 !SemaRef.getLangOpts().CPlusPlus) 8598 return nullptr; 8599 Expr *LBVal = LB; 8600 Expr *UBVal = UB; 8601 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) : 8602 // max(LB(MinVal), LB(MaxVal))) 8603 if (InitDependOnLC) { 8604 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1]; 8605 if (!IS.MinValue || !IS.MaxValue) 8606 return nullptr; 8607 // OuterVar = Min 8608 ExprResult MinValue = 8609 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue); 8610 if (!MinValue.isUsable()) 8611 return nullptr; 8612 8613 ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, 8614 IS.CounterVar, MinValue.get()); 8615 if (!LBMinVal.isUsable()) 8616 return nullptr; 8617 // OuterVar = Min, LBVal 8618 LBMinVal = 8619 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal); 8620 if (!LBMinVal.isUsable()) 8621 return nullptr; 8622 // (OuterVar = Min, LBVal) 8623 LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get()); 8624 if (!LBMinVal.isUsable()) 8625 return nullptr; 8626 8627 // OuterVar = Max 8628 ExprResult MaxValue = 8629 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue); 8630 if (!MaxValue.isUsable()) 8631 return nullptr; 8632 8633 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, 8634 IS.CounterVar, MaxValue.get()); 8635 if (!LBMaxVal.isUsable()) 8636 return nullptr; 8637 // OuterVar = Max, LBVal 8638 LBMaxVal = 8639 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal); 8640 if (!LBMaxVal.isUsable()) 8641 return nullptr; 8642 // (OuterVar = Max, LBVal) 8643 LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get()); 8644 if (!LBMaxVal.isUsable()) 8645 return nullptr; 8646 8647 Expr *LBMin = 8648 tryBuildCapture(SemaRef, LBMinVal.get(), Captures, ".lb_min").get(); 8649 Expr *LBMax = 8650 tryBuildCapture(SemaRef, LBMaxVal.get(), Captures, ".lb_max").get(); 8651 if (!LBMin || !LBMax) 8652 return nullptr; 8653 // LB(MinVal) < LB(MaxVal) 8654 ExprResult MinLessMaxRes = 8655 SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax); 8656 if (!MinLessMaxRes.isUsable()) 8657 return nullptr; 8658 Expr *MinLessMax = 8659 tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures, ".min_less_max") 8660 .get(); 8661 if (!MinLessMax) 8662 return nullptr; 8663 if (*TestIsLessOp) { 8664 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal), 8665 // LB(MaxVal)) 8666 ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc, 8667 MinLessMax, LBMin, LBMax); 8668 if (!MinLB.isUsable()) 8669 return nullptr; 8670 LBVal = MinLB.get(); 8671 } else { 8672 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal), 8673 // LB(MaxVal)) 8674 ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc, 8675 MinLessMax, LBMax, LBMin); 8676 if (!MaxLB.isUsable()) 8677 return nullptr; 8678 LBVal = MaxLB.get(); 8679 } 8680 // OuterVar = LB 8681 LBMinVal = 8682 SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal); 8683 if (!LBMinVal.isUsable()) 8684 return nullptr; 8685 LBVal = LBMinVal.get(); 8686 } 8687 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) : 8688 // min(UB(MinVal), UB(MaxVal)) 8689 if (CondDependOnLC) { 8690 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1]; 8691 if (!IS.MinValue || !IS.MaxValue) 8692 return nullptr; 8693 // OuterVar = Min 8694 ExprResult MinValue = 8695 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue); 8696 if (!MinValue.isUsable()) 8697 return nullptr; 8698 8699 ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, 8700 IS.CounterVar, MinValue.get()); 8701 if (!UBMinVal.isUsable()) 8702 return nullptr; 8703 // OuterVar = Min, UBVal 8704 UBMinVal = 8705 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal); 8706 if (!UBMinVal.isUsable()) 8707 return nullptr; 8708 // (OuterVar = Min, UBVal) 8709 UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get()); 8710 if (!UBMinVal.isUsable()) 8711 return nullptr; 8712 8713 // OuterVar = Max 8714 ExprResult MaxValue = 8715 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue); 8716 if (!MaxValue.isUsable()) 8717 return nullptr; 8718 8719 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, 8720 IS.CounterVar, MaxValue.get()); 8721 if (!UBMaxVal.isUsable()) 8722 return nullptr; 8723 // OuterVar = Max, UBVal 8724 UBMaxVal = 8725 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal); 8726 if (!UBMaxVal.isUsable()) 8727 return nullptr; 8728 // (OuterVar = Max, UBVal) 8729 UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get()); 8730 if (!UBMaxVal.isUsable()) 8731 return nullptr; 8732 8733 Expr *UBMin = 8734 tryBuildCapture(SemaRef, UBMinVal.get(), Captures, ".ub_min").get(); 8735 Expr *UBMax = 8736 tryBuildCapture(SemaRef, UBMaxVal.get(), Captures, ".ub_max").get(); 8737 if (!UBMin || !UBMax) 8738 return nullptr; 8739 // UB(MinVal) > UB(MaxVal) 8740 ExprResult MinGreaterMaxRes = 8741 SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax); 8742 if (!MinGreaterMaxRes.isUsable()) 8743 return nullptr; 8744 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.get(), 8745 Captures, ".min_greater_max") 8746 .get(); 8747 if (!MinGreaterMax) 8748 return nullptr; 8749 if (*TestIsLessOp) { 8750 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal), 8751 // UB(MaxVal)) 8752 ExprResult MaxUB = SemaRef.ActOnConditionalOp( 8753 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax); 8754 if (!MaxUB.isUsable()) 8755 return nullptr; 8756 UBVal = MaxUB.get(); 8757 } else { 8758 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal), 8759 // UB(MaxVal)) 8760 ExprResult MinUB = SemaRef.ActOnConditionalOp( 8761 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin); 8762 if (!MinUB.isUsable()) 8763 return nullptr; 8764 UBVal = MinUB.get(); 8765 } 8766 } 8767 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal; 8768 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal; 8769 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures, ".upper").get(); 8770 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures, ".lower").get(); 8771 if (!Upper || !Lower) 8772 return nullptr; 8773 8774 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper, 8775 Step, VarType, TestIsStrictOp, 8776 /*RoundToStep=*/true, Captures); 8777 if (!Diff.isUsable()) 8778 return nullptr; 8779 8780 // OpenMP runtime requires 32-bit or 64-bit loop variables. 8781 QualType Type = Diff.get()->getType(); 8782 ASTContext &C = SemaRef.Context; 8783 bool UseVarType = VarType->hasIntegerRepresentation() && 8784 C.getTypeSize(Type) > C.getTypeSize(VarType); 8785 if (!Type->isIntegerType() || UseVarType) { 8786 unsigned NewSize = 8787 UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type); 8788 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation() 8789 : Type->hasSignedIntegerRepresentation(); 8790 Type = C.getIntTypeForBitwidth(NewSize, IsSigned); 8791 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) { 8792 Diff = SemaRef.PerformImplicitConversion( 8793 Diff.get(), Type, Sema::AA_Converting, /*AllowExplicit=*/true); 8794 if (!Diff.isUsable()) 8795 return nullptr; 8796 } 8797 } 8798 if (LimitedType) { 8799 unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32; 8800 if (NewSize != C.getTypeSize(Type)) { 8801 if (NewSize < C.getTypeSize(Type)) { 8802 assert(NewSize == 64 && "incorrect loop var size"); 8803 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var) 8804 << InitSrcRange << ConditionSrcRange; 8805 } 8806 QualType NewType = C.getIntTypeForBitwidth( 8807 NewSize, Type->hasSignedIntegerRepresentation() || 8808 C.getTypeSize(Type) < NewSize); 8809 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) { 8810 Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType, 8811 Sema::AA_Converting, true); 8812 if (!Diff.isUsable()) 8813 return nullptr; 8814 } 8815 } 8816 } 8817 8818 return Diff.get(); 8819 } 8820 8821 std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues( 8822 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const { 8823 // Do not build for iterators, they cannot be used in non-rectangular loop 8824 // nests. 8825 if (LCDecl->getType()->isRecordType()) 8826 return std::make_pair(nullptr, nullptr); 8827 // If we subtract, the min is in the condition, otherwise the min is in the 8828 // init value. 8829 Expr *MinExpr = nullptr; 8830 Expr *MaxExpr = nullptr; 8831 Expr *LBExpr = *TestIsLessOp ? LB : UB; 8832 Expr *UBExpr = *TestIsLessOp ? UB : LB; 8833 bool LBNonRect = 8834 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value(); 8835 bool UBNonRect = 8836 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value(); 8837 Expr *Lower = 8838 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get(); 8839 Expr *Upper = 8840 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get(); 8841 if (!Upper || !Lower) 8842 return std::make_pair(nullptr, nullptr); 8843 8844 if (*TestIsLessOp) 8845 MinExpr = Lower; 8846 else 8847 MaxExpr = Upper; 8848 8849 // Build minimum/maximum value based on number of iterations. 8850 QualType VarType = LCDecl->getType().getNonReferenceType(); 8851 8852 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper, 8853 Step, VarType, TestIsStrictOp, 8854 /*RoundToStep=*/false, Captures); 8855 if (!Diff.isUsable()) 8856 return std::make_pair(nullptr, nullptr); 8857 8858 // ((Upper - Lower [- 1]) / Step) * Step 8859 // Parentheses (for dumping/debugging purposes only). 8860 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get()); 8861 if (!Diff.isUsable()) 8862 return std::make_pair(nullptr, nullptr); 8863 8864 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step"); 8865 if (!NewStep.isUsable()) 8866 return std::make_pair(nullptr, nullptr); 8867 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get()); 8868 if (!Diff.isUsable()) 8869 return std::make_pair(nullptr, nullptr); 8870 8871 // Parentheses (for dumping/debugging purposes only). 8872 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get()); 8873 if (!Diff.isUsable()) 8874 return std::make_pair(nullptr, nullptr); 8875 8876 // Convert to the ptrdiff_t, if original type is pointer. 8877 if (VarType->isAnyPointerType() && 8878 !SemaRef.Context.hasSameType( 8879 Diff.get()->getType(), 8880 SemaRef.Context.getUnsignedPointerDiffType())) { 8881 Diff = SemaRef.PerformImplicitConversion( 8882 Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(), 8883 Sema::AA_Converting, /*AllowExplicit=*/true); 8884 } 8885 if (!Diff.isUsable()) 8886 return std::make_pair(nullptr, nullptr); 8887 8888 if (*TestIsLessOp) { 8889 // MinExpr = Lower; 8890 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step) 8891 Diff = SemaRef.BuildBinOp( 8892 S, DefaultLoc, BO_Add, 8893 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(), 8894 Diff.get()); 8895 if (!Diff.isUsable()) 8896 return std::make_pair(nullptr, nullptr); 8897 } else { 8898 // MaxExpr = Upper; 8899 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step) 8900 Diff = SemaRef.BuildBinOp( 8901 S, DefaultLoc, BO_Sub, 8902 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(), 8903 Diff.get()); 8904 if (!Diff.isUsable()) 8905 return std::make_pair(nullptr, nullptr); 8906 } 8907 8908 // Convert to the original type. 8909 if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType)) 8910 Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType, 8911 Sema::AA_Converting, 8912 /*AllowExplicit=*/true); 8913 if (!Diff.isUsable()) 8914 return std::make_pair(nullptr, nullptr); 8915 8916 Sema::TentativeAnalysisScope Trap(SemaRef); 8917 Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false); 8918 if (!Diff.isUsable()) 8919 return std::make_pair(nullptr, nullptr); 8920 8921 if (*TestIsLessOp) 8922 MaxExpr = Diff.get(); 8923 else 8924 MinExpr = Diff.get(); 8925 8926 return std::make_pair(MinExpr, MaxExpr); 8927 } 8928 8929 Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const { 8930 if (InitDependOnLC || CondDependOnLC) 8931 return Condition; 8932 return nullptr; 8933 } 8934 8935 Expr *OpenMPIterationSpaceChecker::buildPreCond( 8936 Scope *S, Expr *Cond, 8937 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const { 8938 // Do not build a precondition when the condition/initialization is dependent 8939 // to prevent pessimistic early loop exit. 8940 // TODO: this can be improved by calculating min/max values but not sure that 8941 // it will be very effective. 8942 if (CondDependOnLC || InitDependOnLC) 8943 return SemaRef 8944 .PerformImplicitConversion( 8945 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(), 8946 SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting, 8947 /*AllowExplicit=*/true) 8948 .get(); 8949 8950 // Try to build LB <op> UB, where <op> is <, >, <=, or >=. 8951 Sema::TentativeAnalysisScope Trap(SemaRef); 8952 8953 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures); 8954 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures); 8955 if (!NewLB.isUsable() || !NewUB.isUsable()) 8956 return nullptr; 8957 8958 ExprResult CondExpr = 8959 SemaRef.BuildBinOp(S, DefaultLoc, 8960 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE) 8961 : (TestIsStrictOp ? BO_GT : BO_GE), 8962 NewLB.get(), NewUB.get()); 8963 if (CondExpr.isUsable()) { 8964 if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(), 8965 SemaRef.Context.BoolTy)) 8966 CondExpr = SemaRef.PerformImplicitConversion( 8967 CondExpr.get(), SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting, 8968 /*AllowExplicit=*/true); 8969 } 8970 8971 // Otherwise use original loop condition and evaluate it in runtime. 8972 return CondExpr.isUsable() ? CondExpr.get() : Cond; 8973 } 8974 8975 /// Build reference expression to the counter be used for codegen. 8976 DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar( 8977 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, 8978 DSAStackTy &DSA) const { 8979 auto *VD = dyn_cast<VarDecl>(LCDecl); 8980 if (!VD) { 8981 VD = SemaRef.OpenMP().isOpenMPCapturedDecl(LCDecl); 8982 DeclRefExpr *Ref = buildDeclRefExpr( 8983 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc); 8984 const DSAStackTy::DSAVarData Data = 8985 DSA.getTopDSA(LCDecl, /*FromParent=*/false); 8986 // If the loop control decl is explicitly marked as private, do not mark it 8987 // as captured again. 8988 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr) 8989 Captures.insert(std::make_pair(LCRef, Ref)); 8990 return Ref; 8991 } 8992 return cast<DeclRefExpr>(LCRef); 8993 } 8994 8995 Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const { 8996 if (LCDecl && !LCDecl->isInvalidDecl()) { 8997 QualType Type = LCDecl->getType().getNonReferenceType(); 8998 VarDecl *PrivateVar = buildVarDecl( 8999 SemaRef, DefaultLoc, Type, LCDecl->getName(), 9000 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr, 9001 isa<VarDecl>(LCDecl) 9002 ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc) 9003 : nullptr); 9004 if (PrivateVar->isInvalidDecl()) 9005 return nullptr; 9006 return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc); 9007 } 9008 return nullptr; 9009 } 9010 9011 /// Build initialization of the counter to be used for codegen. 9012 Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; } 9013 9014 /// Build step of the counter be used for codegen. 9015 Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; } 9016 9017 Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData( 9018 Scope *S, Expr *Counter, 9019 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc, 9020 Expr *Inc, OverloadedOperatorKind OOK) { 9021 Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get(); 9022 if (!Cnt) 9023 return nullptr; 9024 if (Inc) { 9025 assert((OOK == OO_Plus || OOK == OO_Minus) && 9026 "Expected only + or - operations for depend clauses."); 9027 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub; 9028 Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get(); 9029 if (!Cnt) 9030 return nullptr; 9031 } 9032 QualType VarType = LCDecl->getType().getNonReferenceType(); 9033 if (!VarType->isIntegerType() && !VarType->isPointerType() && 9034 !SemaRef.getLangOpts().CPlusPlus) 9035 return nullptr; 9036 // Upper - Lower 9037 Expr *Upper = 9038 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get(); 9039 Expr *Lower = 9040 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt; 9041 if (!Upper || !Lower) 9042 return nullptr; 9043 9044 ExprResult Diff = calculateNumIters( 9045 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType, 9046 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures); 9047 if (!Diff.isUsable()) 9048 return nullptr; 9049 9050 return Diff.get(); 9051 } 9052 } // namespace 9053 9054 void SemaOpenMP::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, 9055 Stmt *Init) { 9056 assert(getLangOpts().OpenMP && "OpenMP is not active."); 9057 assert(Init && "Expected loop in canonical form."); 9058 unsigned AssociatedLoops = DSAStack->getAssociatedLoops(); 9059 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); 9060 if (AssociatedLoops == 0 || !isOpenMPLoopDirective(DKind)) 9061 return; 9062 9063 DSAStack->loopStart(); 9064 OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true, 9065 *DSAStack, ForLoc); 9066 if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) { 9067 if (ValueDecl *D = ISC.getLoopDecl()) { 9068 auto *VD = dyn_cast<VarDecl>(D); 9069 DeclRefExpr *PrivateRef = nullptr; 9070 if (!VD) { 9071 if (VarDecl *Private = isOpenMPCapturedDecl(D)) { 9072 VD = Private; 9073 } else { 9074 PrivateRef = buildCapture(SemaRef, D, ISC.getLoopDeclRefExpr(), 9075 /*WithInit=*/false); 9076 VD = cast<VarDecl>(PrivateRef->getDecl()); 9077 } 9078 } 9079 DSAStack->addLoopControlVariable(D, VD); 9080 const Decl *LD = DSAStack->getPossiblyLoopCounter(); 9081 if (LD != D->getCanonicalDecl()) { 9082 DSAStack->resetPossibleLoopCounter(); 9083 if (auto *Var = dyn_cast_or_null<VarDecl>(LD)) 9084 SemaRef.MarkDeclarationsReferencedInExpr(buildDeclRefExpr( 9085 SemaRef, const_cast<VarDecl *>(Var), 9086 Var->getType().getNonLValueExprType(getASTContext()), ForLoc, 9087 /*RefersToCapture=*/true)); 9088 } 9089 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables 9090 // Referenced in a Construct, C/C++]. The loop iteration variable in the 9091 // associated for-loop of a simd construct with just one associated 9092 // for-loop may be listed in a linear clause with a constant-linear-step 9093 // that is the increment of the associated for-loop. The loop iteration 9094 // variable(s) in the associated for-loop(s) of a for or parallel for 9095 // construct may be listed in a private or lastprivate clause. 9096 DSAStackTy::DSAVarData DVar = 9097 DSAStack->getTopDSA(D, /*FromParent=*/false); 9098 // If LoopVarRefExpr is nullptr it means the corresponding loop variable 9099 // is declared in the loop and it is predetermined as a private. 9100 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr(); 9101 OpenMPClauseKind PredeterminedCKind = 9102 isOpenMPSimdDirective(DKind) 9103 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear) 9104 : OMPC_private; 9105 auto IsOpenMPTaskloopDirective = [](OpenMPDirectiveKind DK) { 9106 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop; 9107 }; 9108 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown && 9109 DVar.CKind != PredeterminedCKind && DVar.RefExpr && 9110 (getLangOpts().OpenMP <= 45 || 9111 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) || 9112 ((isOpenMPWorksharingDirective(DKind) || 9113 IsOpenMPTaskloopDirective(DKind) || 9114 isOpenMPDistributeDirective(DKind)) && 9115 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown && 9116 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) && 9117 (DVar.CKind != OMPC_private || DVar.RefExpr)) { 9118 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa) 9119 << getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind) 9120 << getOpenMPClauseName(PredeterminedCKind); 9121 if (DVar.RefExpr == nullptr) 9122 DVar.CKind = PredeterminedCKind; 9123 reportOriginalDsa(SemaRef, DSAStack, D, DVar, /*IsLoopIterVar=*/true); 9124 } else if (LoopDeclRefExpr) { 9125 // Make the loop iteration variable private (for worksharing 9126 // constructs), linear (for simd directives with the only one 9127 // associated loop) or lastprivate (for simd directives with several 9128 // collapsed or ordered loops). 9129 if (DVar.CKind == OMPC_unknown) 9130 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef); 9131 } 9132 } 9133 } 9134 DSAStack->setAssociatedLoops(AssociatedLoops - 1); 9135 } 9136 9137 namespace { 9138 // Utility for OpenMP doacross clause kind 9139 class OMPDoacrossKind { 9140 public: 9141 bool isSource(const OMPDoacrossClause *C) { 9142 return C->getDependenceType() == OMPC_DOACROSS_source || 9143 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration; 9144 } 9145 bool isSink(const OMPDoacrossClause *C) { 9146 return C->getDependenceType() == OMPC_DOACROSS_sink; 9147 } 9148 bool isSinkIter(const OMPDoacrossClause *C) { 9149 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration; 9150 } 9151 }; 9152 } // namespace 9153 /// Called on a for stmt to check and extract its iteration space 9154 /// for further processing (such as collapsing). 9155 static bool checkOpenMPIterationSpace( 9156 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA, 9157 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount, 9158 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr, 9159 Expr *OrderedLoopCountExpr, 9160 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA, 9161 llvm::MutableArrayRef<LoopIterationSpace> ResultIterSpaces, 9162 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) { 9163 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind); 9164 // OpenMP [2.9.1, Canonical Loop Form] 9165 // for (init-expr; test-expr; incr-expr) structured-block 9166 // for (range-decl: range-expr) structured-block 9167 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S)) 9168 S = CanonLoop->getLoopStmt(); 9169 auto *For = dyn_cast_or_null<ForStmt>(S); 9170 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S); 9171 // Ranged for is supported only in OpenMP 5.0. 9172 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) { 9173 OpenMPDirectiveKind DK = (SemaRef.getLangOpts().OpenMP < 50 || 9174 DSA.getMappedDirective() == OMPD_unknown) 9175 ? DKind 9176 : DSA.getMappedDirective(); 9177 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for) 9178 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr) 9179 << getOpenMPDirectiveName(DK) << TotalNestedLoopCount 9180 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount; 9181 if (TotalNestedLoopCount > 1) { 9182 if (CollapseLoopCountExpr && OrderedLoopCountExpr) 9183 SemaRef.Diag(DSA.getConstructLoc(), 9184 diag::note_omp_collapse_ordered_expr) 9185 << 2 << CollapseLoopCountExpr->getSourceRange() 9186 << OrderedLoopCountExpr->getSourceRange(); 9187 else if (CollapseLoopCountExpr) 9188 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(), 9189 diag::note_omp_collapse_ordered_expr) 9190 << 0 << CollapseLoopCountExpr->getSourceRange(); 9191 else 9192 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(), 9193 diag::note_omp_collapse_ordered_expr) 9194 << 1 << OrderedLoopCountExpr->getSourceRange(); 9195 } 9196 return true; 9197 } 9198 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) && 9199 "No loop body."); 9200 // Postpone analysis in dependent contexts for ranged for loops. 9201 if (CXXFor && SemaRef.CurContext->isDependentContext()) 9202 return false; 9203 9204 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA, 9205 For ? For->getForLoc() : CXXFor->getForLoc()); 9206 9207 // Check init. 9208 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt(); 9209 if (ISC.checkAndSetInit(Init)) 9210 return true; 9211 9212 bool HasErrors = false; 9213 9214 // Check loop variable's type. 9215 if (ValueDecl *LCDecl = ISC.getLoopDecl()) { 9216 // OpenMP [2.6, Canonical Loop Form] 9217 // Var is one of the following: 9218 // A variable of signed or unsigned integer type. 9219 // For C++, a variable of a random access iterator type. 9220 // For C, a variable of a pointer type. 9221 QualType VarType = LCDecl->getType().getNonReferenceType(); 9222 if (!VarType->isDependentType() && !VarType->isIntegerType() && 9223 !VarType->isPointerType() && 9224 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) { 9225 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type) 9226 << SemaRef.getLangOpts().CPlusPlus; 9227 HasErrors = true; 9228 } 9229 9230 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in 9231 // a Construct 9232 // The loop iteration variable(s) in the associated for-loop(s) of a for or 9233 // parallel for construct is (are) private. 9234 // The loop iteration variable in the associated for-loop of a simd 9235 // construct with just one associated for-loop is linear with a 9236 // constant-linear-step that is the increment of the associated for-loop. 9237 // Exclude loop var from the list of variables with implicitly defined data 9238 // sharing attributes. 9239 VarsWithImplicitDSA.erase(LCDecl); 9240 9241 assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars"); 9242 9243 // Check test-expr. 9244 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond()); 9245 9246 // Check incr-expr. 9247 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc()); 9248 } 9249 9250 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors) 9251 return HasErrors; 9252 9253 // Build the loop's iteration space representation. 9254 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond( 9255 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures); 9256 ResultIterSpaces[CurrentNestedLoopCount].NumIterations = 9257 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces, 9258 (isOpenMPWorksharingDirective(DKind) || 9259 isOpenMPGenericLoopDirective(DKind) || 9260 isOpenMPTaskLoopDirective(DKind) || 9261 isOpenMPDistributeDirective(DKind) || 9262 isOpenMPLoopTransformationDirective(DKind)), 9263 Captures); 9264 ResultIterSpaces[CurrentNestedLoopCount].CounterVar = 9265 ISC.buildCounterVar(Captures, DSA); 9266 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar = 9267 ISC.buildPrivateCounterVar(); 9268 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit(); 9269 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep(); 9270 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange(); 9271 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange = 9272 ISC.getConditionSrcRange(); 9273 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange = 9274 ISC.getIncrementSrcRange(); 9275 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep(); 9276 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare = 9277 ISC.isStrictTestOp(); 9278 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue, 9279 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) = 9280 ISC.buildMinMaxValues(DSA.getCurScope(), Captures); 9281 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition = 9282 ISC.buildFinalCondition(DSA.getCurScope()); 9283 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB = 9284 ISC.doesInitDependOnLC(); 9285 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB = 9286 ISC.doesCondDependOnLC(); 9287 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx = 9288 ISC.getLoopDependentIdx(); 9289 9290 HasErrors |= 9291 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr || 9292 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr || 9293 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr || 9294 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr || 9295 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr || 9296 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr); 9297 if (!HasErrors && DSA.isOrderedRegion()) { 9298 if (DSA.getOrderedRegionParam().second->getNumForLoops()) { 9299 if (CurrentNestedLoopCount < 9300 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) { 9301 DSA.getOrderedRegionParam().second->setLoopNumIterations( 9302 CurrentNestedLoopCount, 9303 ResultIterSpaces[CurrentNestedLoopCount].NumIterations); 9304 DSA.getOrderedRegionParam().second->setLoopCounter( 9305 CurrentNestedLoopCount, 9306 ResultIterSpaces[CurrentNestedLoopCount].CounterVar); 9307 } 9308 } 9309 for (auto &Pair : DSA.getDoacrossDependClauses()) { 9310 auto *DependC = dyn_cast<OMPDependClause>(Pair.first); 9311 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first); 9312 unsigned NumLoops = 9313 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops(); 9314 if (CurrentNestedLoopCount >= NumLoops) { 9315 // Erroneous case - clause has some problems. 9316 continue; 9317 } 9318 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink && 9319 Pair.second.size() <= CurrentNestedLoopCount) { 9320 // Erroneous case - clause has some problems. 9321 DependC->setLoopData(CurrentNestedLoopCount, nullptr); 9322 continue; 9323 } 9324 OMPDoacrossKind ODK; 9325 if (DoacrossC && ODK.isSink(DoacrossC) && 9326 Pair.second.size() <= CurrentNestedLoopCount) { 9327 // Erroneous case - clause has some problems. 9328 DoacrossC->setLoopData(CurrentNestedLoopCount, nullptr); 9329 continue; 9330 } 9331 Expr *CntValue; 9332 SourceLocation DepLoc = 9333 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc(); 9334 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) || 9335 (DoacrossC && ODK.isSource(DoacrossC))) 9336 CntValue = ISC.buildOrderedLoopData( 9337 DSA.getCurScope(), 9338 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures, 9339 DepLoc); 9340 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) { 9341 Expr *Cnt = SemaRef 9342 .DefaultLvalueConversion( 9343 ResultIterSpaces[CurrentNestedLoopCount].CounterVar) 9344 .get(); 9345 if (!Cnt) 9346 continue; 9347 // build CounterVar - 1 9348 Expr *Inc = 9349 SemaRef.ActOnIntegerConstant(DoacrossC->getColonLoc(), /*Val=*/1) 9350 .get(); 9351 CntValue = ISC.buildOrderedLoopData( 9352 DSA.getCurScope(), 9353 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures, 9354 DepLoc, Inc, clang::OO_Minus); 9355 } else 9356 CntValue = ISC.buildOrderedLoopData( 9357 DSA.getCurScope(), 9358 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures, 9359 DepLoc, Pair.second[CurrentNestedLoopCount].first, 9360 Pair.second[CurrentNestedLoopCount].second); 9361 if (DependC) 9362 DependC->setLoopData(CurrentNestedLoopCount, CntValue); 9363 else 9364 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue); 9365 } 9366 } 9367 9368 return HasErrors; 9369 } 9370 9371 /// Build 'VarRef = Start. 9372 static ExprResult 9373 buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef, 9374 ExprResult Start, bool IsNonRectangularLB, 9375 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) { 9376 // Build 'VarRef = Start. 9377 ExprResult NewStart = IsNonRectangularLB 9378 ? Start.get() 9379 : tryBuildCapture(SemaRef, Start.get(), Captures); 9380 if (!NewStart.isUsable()) 9381 return ExprError(); 9382 if (!SemaRef.Context.hasSameType(NewStart.get()->getType(), 9383 VarRef.get()->getType())) { 9384 NewStart = SemaRef.PerformImplicitConversion( 9385 NewStart.get(), VarRef.get()->getType(), Sema::AA_Converting, 9386 /*AllowExplicit=*/true); 9387 if (!NewStart.isUsable()) 9388 return ExprError(); 9389 } 9390 9391 ExprResult Init = 9392 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get()); 9393 return Init; 9394 } 9395 9396 /// Build 'VarRef = Start + Iter * Step'. 9397 static ExprResult buildCounterUpdate( 9398 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef, 9399 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract, 9400 bool IsNonRectangularLB, 9401 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) { 9402 // Add parentheses (for debugging purposes only). 9403 Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get()); 9404 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() || 9405 !Step.isUsable()) 9406 return ExprError(); 9407 9408 ExprResult NewStep = Step; 9409 if (Captures) 9410 NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures); 9411 if (NewStep.isInvalid()) 9412 return ExprError(); 9413 ExprResult Update = 9414 SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get()); 9415 if (!Update.isUsable()) 9416 return ExprError(); 9417 9418 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or 9419 // 'VarRef = Start (+|-) Iter * Step'. 9420 if (!Start.isUsable()) 9421 return ExprError(); 9422 ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get()); 9423 if (!NewStart.isUsable()) 9424 return ExprError(); 9425 if (Captures && !IsNonRectangularLB) 9426 NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures); 9427 if (NewStart.isInvalid()) 9428 return ExprError(); 9429 9430 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'. 9431 ExprResult SavedUpdate = Update; 9432 ExprResult UpdateVal; 9433 if (VarRef.get()->getType()->isOverloadableType() || 9434 NewStart.get()->getType()->isOverloadableType() || 9435 Update.get()->getType()->isOverloadableType()) { 9436 Sema::TentativeAnalysisScope Trap(SemaRef); 9437 9438 Update = 9439 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get()); 9440 if (Update.isUsable()) { 9441 UpdateVal = 9442 SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign, 9443 VarRef.get(), SavedUpdate.get()); 9444 if (UpdateVal.isUsable()) { 9445 Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(), 9446 UpdateVal.get()); 9447 } 9448 } 9449 } 9450 9451 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'. 9452 if (!Update.isUsable() || !UpdateVal.isUsable()) { 9453 Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add, 9454 NewStart.get(), SavedUpdate.get()); 9455 if (!Update.isUsable()) 9456 return ExprError(); 9457 9458 if (!SemaRef.Context.hasSameType(Update.get()->getType(), 9459 VarRef.get()->getType())) { 9460 Update = SemaRef.PerformImplicitConversion( 9461 Update.get(), VarRef.get()->getType(), Sema::AA_Converting, true); 9462 if (!Update.isUsable()) 9463 return ExprError(); 9464 } 9465 9466 Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get()); 9467 } 9468 return Update; 9469 } 9470 9471 /// Convert integer expression \a E to make it have at least \a Bits 9472 /// bits. 9473 static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) { 9474 if (E == nullptr) 9475 return ExprError(); 9476 ASTContext &C = SemaRef.Context; 9477 QualType OldType = E->getType(); 9478 unsigned HasBits = C.getTypeSize(OldType); 9479 if (HasBits >= Bits) 9480 return ExprResult(E); 9481 // OK to convert to signed, because new type has more bits than old. 9482 QualType NewType = C.getIntTypeForBitwidth(Bits, /* Signed */ true); 9483 return SemaRef.PerformImplicitConversion(E, NewType, Sema::AA_Converting, 9484 true); 9485 } 9486 9487 /// Check if the given expression \a E is a constant integer that fits 9488 /// into \a Bits bits. 9489 static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) { 9490 if (E == nullptr) 9491 return false; 9492 if (std::optional<llvm::APSInt> Result = 9493 E->getIntegerConstantExpr(SemaRef.Context)) 9494 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits); 9495 return false; 9496 } 9497 9498 /// Build preinits statement for the given declarations. 9499 static Stmt *buildPreInits(ASTContext &Context, 9500 MutableArrayRef<Decl *> PreInits) { 9501 if (!PreInits.empty()) { 9502 return new (Context) DeclStmt( 9503 DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()), 9504 SourceLocation(), SourceLocation()); 9505 } 9506 return nullptr; 9507 } 9508 9509 /// Append the \p Item or the content of a CompoundStmt to the list \p 9510 /// TargetList. 9511 /// 9512 /// A CompoundStmt is used as container in case multiple statements need to be 9513 /// stored in lieu of using an explicit list. Flattening is necessary because 9514 /// contained DeclStmts need to be visible after the execution of the list. Used 9515 /// for OpenMP pre-init declarations/statements. 9516 static void appendFlattenedStmtList(SmallVectorImpl<Stmt *> &TargetList, 9517 Stmt *Item) { 9518 // nullptr represents an empty list. 9519 if (!Item) 9520 return; 9521 9522 if (auto *CS = dyn_cast<CompoundStmt>(Item)) 9523 llvm::append_range(TargetList, CS->body()); 9524 else 9525 TargetList.push_back(Item); 9526 } 9527 9528 /// Build preinits statement for the given declarations. 9529 static Stmt * 9530 buildPreInits(ASTContext &Context, 9531 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) { 9532 if (!Captures.empty()) { 9533 SmallVector<Decl *, 16> PreInits; 9534 for (const auto &Pair : Captures) 9535 PreInits.push_back(Pair.second->getDecl()); 9536 return buildPreInits(Context, PreInits); 9537 } 9538 return nullptr; 9539 } 9540 9541 /// Build pre-init statement for the given statements. 9542 static Stmt *buildPreInits(ASTContext &Context, ArrayRef<Stmt *> PreInits) { 9543 if (PreInits.empty()) 9544 return nullptr; 9545 9546 SmallVector<Stmt *> Stmts; 9547 for (Stmt *S : PreInits) 9548 appendFlattenedStmtList(Stmts, S); 9549 return CompoundStmt::Create(Context, PreInits, FPOptionsOverride(), {}, {}); 9550 } 9551 9552 /// Build postupdate expression for the given list of postupdates expressions. 9553 static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) { 9554 Expr *PostUpdate = nullptr; 9555 if (!PostUpdates.empty()) { 9556 for (Expr *E : PostUpdates) { 9557 Expr *ConvE = S.BuildCStyleCastExpr( 9558 E->getExprLoc(), 9559 S.Context.getTrivialTypeSourceInfo(S.Context.VoidTy), 9560 E->getExprLoc(), E) 9561 .get(); 9562 PostUpdate = PostUpdate 9563 ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma, 9564 PostUpdate, ConvE) 9565 .get() 9566 : ConvE; 9567 } 9568 } 9569 return PostUpdate; 9570 } 9571 9572 /// Called on a for stmt to check itself and nested loops (if any). 9573 /// \return Returns 0 if one of the collapsed stmts is not canonical for loop, 9574 /// number of collapsed loops otherwise. 9575 static unsigned 9576 checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, 9577 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef, 9578 DSAStackTy &DSA, 9579 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA, 9580 OMPLoopBasedDirective::HelperExprs &Built) { 9581 unsigned NestedLoopCount = 1; 9582 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) && 9583 !isOpenMPLoopTransformationDirective(DKind); 9584 9585 if (CollapseLoopCountExpr) { 9586 // Found 'collapse' clause - calculate collapse number. 9587 Expr::EvalResult Result; 9588 if (!CollapseLoopCountExpr->isValueDependent() && 9589 CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) { 9590 NestedLoopCount = Result.Val.getInt().getLimitedValue(); 9591 } else { 9592 Built.clear(/*Size=*/1); 9593 return 1; 9594 } 9595 } 9596 unsigned OrderedLoopCount = 1; 9597 if (OrderedLoopCountExpr) { 9598 // Found 'ordered' clause - calculate collapse number. 9599 Expr::EvalResult EVResult; 9600 if (!OrderedLoopCountExpr->isValueDependent() && 9601 OrderedLoopCountExpr->EvaluateAsInt(EVResult, 9602 SemaRef.getASTContext())) { 9603 llvm::APSInt Result = EVResult.Val.getInt(); 9604 if (Result.getLimitedValue() < NestedLoopCount) { 9605 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(), 9606 diag::err_omp_wrong_ordered_loop_count) 9607 << OrderedLoopCountExpr->getSourceRange(); 9608 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(), 9609 diag::note_collapse_loop_count) 9610 << CollapseLoopCountExpr->getSourceRange(); 9611 } 9612 OrderedLoopCount = Result.getLimitedValue(); 9613 } else { 9614 Built.clear(/*Size=*/1); 9615 return 1; 9616 } 9617 } 9618 // This is helper routine for loop directives (e.g., 'for', 'simd', 9619 // 'for simd', etc.). 9620 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 9621 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount); 9622 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops); 9623 if (!OMPLoopBasedDirective::doForAllLoops( 9624 AStmt->IgnoreContainers(!isOpenMPLoopTransformationDirective(DKind)), 9625 SupportsNonPerfectlyNested, NumLoops, 9626 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount, 9627 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA, 9628 &IterSpaces, &Captures](unsigned Cnt, Stmt *CurStmt) { 9629 if (checkOpenMPIterationSpace( 9630 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount, 9631 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr, 9632 VarsWithImplicitDSA, IterSpaces, Captures)) 9633 return true; 9634 if (Cnt > 0 && Cnt >= NestedLoopCount && 9635 IterSpaces[Cnt].CounterVar) { 9636 // Handle initialization of captured loop iterator variables. 9637 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar); 9638 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) { 9639 Captures[DRE] = DRE; 9640 } 9641 } 9642 return false; 9643 }, 9644 [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) { 9645 Stmt *DependentPreInits = Transform->getPreInits(); 9646 if (!DependentPreInits) 9647 return; 9648 9649 // Search for pre-init declared variables that need to be captured 9650 // to be referenceable inside the directive. 9651 SmallVector<Stmt *> Constituents; 9652 appendFlattenedStmtList(Constituents, DependentPreInits); 9653 for (Stmt *S : Constituents) { 9654 if (auto *DC = dyn_cast<DeclStmt>(S)) { 9655 for (Decl *C : DC->decls()) { 9656 auto *D = cast<VarDecl>(C); 9657 DeclRefExpr *Ref = buildDeclRefExpr( 9658 SemaRef, D, D->getType().getNonReferenceType(), 9659 Transform->getBeginLoc()); 9660 Captures[Ref] = Ref; 9661 } 9662 } 9663 } 9664 })) 9665 return 0; 9666 9667 Built.clear(/* size */ NestedLoopCount); 9668 9669 if (SemaRef.CurContext->isDependentContext()) 9670 return NestedLoopCount; 9671 9672 // An example of what is generated for the following code: 9673 // 9674 // #pragma omp simd collapse(2) ordered(2) 9675 // for (i = 0; i < NI; ++i) 9676 // for (k = 0; k < NK; ++k) 9677 // for (j = J0; j < NJ; j+=2) { 9678 // <loop body> 9679 // } 9680 // 9681 // We generate the code below. 9682 // Note: the loop body may be outlined in CodeGen. 9683 // Note: some counters may be C++ classes, operator- is used to find number of 9684 // iterations and operator+= to calculate counter value. 9685 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32 9686 // or i64 is currently supported). 9687 // 9688 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2)) 9689 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) { 9690 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2); 9691 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2; 9692 // // similar updates for vars in clauses (e.g. 'linear') 9693 // <loop body (using local i and j)> 9694 // } 9695 // i = NI; // assign final values of counters 9696 // j = NJ; 9697 // 9698 9699 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are 9700 // the iteration counts of the collapsed for loops. 9701 // Precondition tests if there is at least one iteration (all conditions are 9702 // true). 9703 auto PreCond = ExprResult(IterSpaces[0].PreCond); 9704 Expr *N0 = IterSpaces[0].NumIterations; 9705 ExprResult LastIteration32 = 9706 widenIterationCount(/*Bits=*/32, 9707 SemaRef 9708 .PerformImplicitConversion( 9709 N0->IgnoreImpCasts(), N0->getType(), 9710 Sema::AA_Converting, /*AllowExplicit=*/true) 9711 .get(), 9712 SemaRef); 9713 ExprResult LastIteration64 = widenIterationCount( 9714 /*Bits=*/64, 9715 SemaRef 9716 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(), 9717 Sema::AA_Converting, 9718 /*AllowExplicit=*/true) 9719 .get(), 9720 SemaRef); 9721 9722 if (!LastIteration32.isUsable() || !LastIteration64.isUsable()) 9723 return NestedLoopCount; 9724 9725 ASTContext &C = SemaRef.Context; 9726 bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32; 9727 9728 Scope *CurScope = DSA.getCurScope(); 9729 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) { 9730 if (PreCond.isUsable()) { 9731 PreCond = 9732 SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd, 9733 PreCond.get(), IterSpaces[Cnt].PreCond); 9734 } 9735 Expr *N = IterSpaces[Cnt].NumIterations; 9736 SourceLocation Loc = N->getExprLoc(); 9737 AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32; 9738 if (LastIteration32.isUsable()) 9739 LastIteration32 = SemaRef.BuildBinOp( 9740 CurScope, Loc, BO_Mul, LastIteration32.get(), 9741 SemaRef 9742 .PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(), 9743 Sema::AA_Converting, 9744 /*AllowExplicit=*/true) 9745 .get()); 9746 if (LastIteration64.isUsable()) 9747 LastIteration64 = SemaRef.BuildBinOp( 9748 CurScope, Loc, BO_Mul, LastIteration64.get(), 9749 SemaRef 9750 .PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(), 9751 Sema::AA_Converting, 9752 /*AllowExplicit=*/true) 9753 .get()); 9754 } 9755 9756 // Choose either the 32-bit or 64-bit version. 9757 ExprResult LastIteration = LastIteration64; 9758 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse || 9759 (LastIteration32.isUsable() && 9760 C.getTypeSize(LastIteration32.get()->getType()) == 32 && 9761 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 || 9762 fitsInto( 9763 /*Bits=*/32, 9764 LastIteration32.get()->getType()->hasSignedIntegerRepresentation(), 9765 LastIteration64.get(), SemaRef)))) 9766 LastIteration = LastIteration32; 9767 QualType VType = LastIteration.get()->getType(); 9768 QualType RealVType = VType; 9769 QualType StrideVType = VType; 9770 if (isOpenMPTaskLoopDirective(DKind)) { 9771 VType = 9772 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 9773 StrideVType = 9774 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 9775 } 9776 9777 if (!LastIteration.isUsable()) 9778 return 0; 9779 9780 // Save the number of iterations. 9781 ExprResult NumIterations = LastIteration; 9782 { 9783 LastIteration = SemaRef.BuildBinOp( 9784 CurScope, LastIteration.get()->getExprLoc(), BO_Sub, 9785 LastIteration.get(), 9786 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get()); 9787 if (!LastIteration.isUsable()) 9788 return 0; 9789 } 9790 9791 // Calculate the last iteration number beforehand instead of doing this on 9792 // each iteration. Do not do this if the number of iterations may be kfold-ed. 9793 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context); 9794 ExprResult CalcLastIteration; 9795 if (!IsConstant) { 9796 ExprResult SaveRef = 9797 tryBuildCapture(SemaRef, LastIteration.get(), Captures); 9798 LastIteration = SaveRef; 9799 9800 // Prepare SaveRef + 1. 9801 NumIterations = SemaRef.BuildBinOp( 9802 CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(), 9803 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get()); 9804 if (!NumIterations.isUsable()) 9805 return 0; 9806 } 9807 9808 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin(); 9809 9810 // Build variables passed into runtime, necessary for worksharing directives. 9811 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB; 9812 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) || 9813 isOpenMPDistributeDirective(DKind) || 9814 isOpenMPGenericLoopDirective(DKind) || 9815 isOpenMPLoopTransformationDirective(DKind)) { 9816 // Lower bound variable, initialized with zero. 9817 VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb"); 9818 LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc); 9819 SemaRef.AddInitializerToDecl(LBDecl, 9820 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(), 9821 /*DirectInit*/ false); 9822 9823 // Upper bound variable, initialized with last iteration number. 9824 VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub"); 9825 UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc); 9826 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(), 9827 /*DirectInit*/ false); 9828 9829 // A 32-bit variable-flag where runtime returns 1 for the last iteration. 9830 // This will be used to implement clause 'lastprivate'. 9831 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true); 9832 VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last"); 9833 IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc); 9834 SemaRef.AddInitializerToDecl(ILDecl, 9835 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(), 9836 /*DirectInit*/ false); 9837 9838 // Stride variable returned by runtime (we initialize it to 1 by default). 9839 VarDecl *STDecl = 9840 buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride"); 9841 ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc); 9842 SemaRef.AddInitializerToDecl(STDecl, 9843 SemaRef.ActOnIntegerConstant(InitLoc, 1).get(), 9844 /*DirectInit*/ false); 9845 9846 // Build expression: UB = min(UB, LastIteration) 9847 // It is necessary for CodeGen of directives with static scheduling. 9848 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT, 9849 UB.get(), LastIteration.get()); 9850 ExprResult CondOp = SemaRef.ActOnConditionalOp( 9851 LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(), 9852 LastIteration.get(), UB.get()); 9853 EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(), 9854 CondOp.get()); 9855 EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue*/ false); 9856 9857 // If we have a combined directive that combines 'distribute', 'for' or 9858 // 'simd' we need to be able to access the bounds of the schedule of the 9859 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained 9860 // by scheduling 'distribute' have to be passed to the schedule of 'for'. 9861 if (isOpenMPLoopBoundSharingDirective(DKind)) { 9862 // Lower bound variable, initialized with zero. 9863 VarDecl *CombLBDecl = 9864 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb"); 9865 CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc); 9866 SemaRef.AddInitializerToDecl( 9867 CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(), 9868 /*DirectInit*/ false); 9869 9870 // Upper bound variable, initialized with last iteration number. 9871 VarDecl *CombUBDecl = 9872 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub"); 9873 CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc); 9874 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(), 9875 /*DirectInit*/ false); 9876 9877 ExprResult CombIsUBGreater = SemaRef.BuildBinOp( 9878 CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get()); 9879 ExprResult CombCondOp = 9880 SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(), 9881 LastIteration.get(), CombUB.get()); 9882 CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(), 9883 CombCondOp.get()); 9884 CombEUB = 9885 SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue*/ false); 9886 9887 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl(); 9888 // We expect to have at least 2 more parameters than the 'parallel' 9889 // directive does - the lower and upper bounds of the previous schedule. 9890 assert(CD->getNumParams() >= 4 && 9891 "Unexpected number of parameters in loop combined directive"); 9892 9893 // Set the proper type for the bounds given what we learned from the 9894 // enclosed loops. 9895 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2); 9896 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3); 9897 9898 // Previous lower and upper bounds are obtained from the region 9899 // parameters. 9900 PrevLB = 9901 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc); 9902 PrevUB = 9903 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc); 9904 } 9905 } 9906 9907 // Build the iteration variable and its initialization before loop. 9908 ExprResult IV; 9909 ExprResult Init, CombInit; 9910 { 9911 VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv"); 9912 IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc); 9913 Expr *RHS = (isOpenMPWorksharingDirective(DKind) || 9914 isOpenMPGenericLoopDirective(DKind) || 9915 isOpenMPTaskLoopDirective(DKind) || 9916 isOpenMPDistributeDirective(DKind) || 9917 isOpenMPLoopTransformationDirective(DKind)) 9918 ? LB.get() 9919 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get(); 9920 Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS); 9921 Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false); 9922 9923 if (isOpenMPLoopBoundSharingDirective(DKind)) { 9924 Expr *CombRHS = 9925 (isOpenMPWorksharingDirective(DKind) || 9926 isOpenMPGenericLoopDirective(DKind) || 9927 isOpenMPTaskLoopDirective(DKind) || 9928 isOpenMPDistributeDirective(DKind)) 9929 ? CombLB.get() 9930 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get(); 9931 CombInit = 9932 SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS); 9933 CombInit = 9934 SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue*/ false); 9935 } 9936 } 9937 9938 bool UseStrictCompare = 9939 RealVType->hasUnsignedIntegerRepresentation() && 9940 llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) { 9941 return LIS.IsStrictCompare; 9942 }); 9943 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for 9944 // unsigned IV)) for worksharing loops. 9945 SourceLocation CondLoc = AStmt->getBeginLoc(); 9946 Expr *BoundUB = UB.get(); 9947 if (UseStrictCompare) { 9948 BoundUB = 9949 SemaRef 9950 .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB, 9951 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get()) 9952 .get(); 9953 BoundUB = 9954 SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue*/ false).get(); 9955 } 9956 ExprResult Cond = 9957 (isOpenMPWorksharingDirective(DKind) || 9958 isOpenMPGenericLoopDirective(DKind) || 9959 isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind) || 9960 isOpenMPLoopTransformationDirective(DKind)) 9961 ? SemaRef.BuildBinOp(CurScope, CondLoc, 9962 UseStrictCompare ? BO_LT : BO_LE, IV.get(), 9963 BoundUB) 9964 : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(), 9965 NumIterations.get()); 9966 ExprResult CombDistCond; 9967 if (isOpenMPLoopBoundSharingDirective(DKind)) { 9968 CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(), 9969 NumIterations.get()); 9970 } 9971 9972 ExprResult CombCond; 9973 if (isOpenMPLoopBoundSharingDirective(DKind)) { 9974 Expr *BoundCombUB = CombUB.get(); 9975 if (UseStrictCompare) { 9976 BoundCombUB = 9977 SemaRef 9978 .BuildBinOp( 9979 CurScope, CondLoc, BO_Add, BoundCombUB, 9980 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get()) 9981 .get(); 9982 BoundCombUB = 9983 SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue*/ false) 9984 .get(); 9985 } 9986 CombCond = 9987 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, 9988 IV.get(), BoundCombUB); 9989 } 9990 // Loop increment (IV = IV + 1) 9991 SourceLocation IncLoc = AStmt->getBeginLoc(); 9992 ExprResult Inc = 9993 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(), 9994 SemaRef.ActOnIntegerConstant(IncLoc, 1).get()); 9995 if (!Inc.isUsable()) 9996 return 0; 9997 Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get()); 9998 Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue*/ false); 9999 if (!Inc.isUsable()) 10000 return 0; 10001 10002 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST). 10003 // Used for directives with static scheduling. 10004 // In combined construct, add combined version that use CombLB and CombUB 10005 // base variables for the update 10006 ExprResult NextLB, NextUB, CombNextLB, CombNextUB; 10007 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) || 10008 isOpenMPGenericLoopDirective(DKind) || 10009 isOpenMPDistributeDirective(DKind) || 10010 isOpenMPLoopTransformationDirective(DKind)) { 10011 // LB + ST 10012 NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get()); 10013 if (!NextLB.isUsable()) 10014 return 0; 10015 // LB = LB + ST 10016 NextLB = 10017 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get()); 10018 NextLB = 10019 SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue*/ false); 10020 if (!NextLB.isUsable()) 10021 return 0; 10022 // UB + ST 10023 NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get()); 10024 if (!NextUB.isUsable()) 10025 return 0; 10026 // UB = UB + ST 10027 NextUB = 10028 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get()); 10029 NextUB = 10030 SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue*/ false); 10031 if (!NextUB.isUsable()) 10032 return 0; 10033 if (isOpenMPLoopBoundSharingDirective(DKind)) { 10034 CombNextLB = 10035 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get()); 10036 if (!NextLB.isUsable()) 10037 return 0; 10038 // LB = LB + ST 10039 CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(), 10040 CombNextLB.get()); 10041 CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(), 10042 /*DiscardedValue*/ false); 10043 if (!CombNextLB.isUsable()) 10044 return 0; 10045 // UB + ST 10046 CombNextUB = 10047 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get()); 10048 if (!CombNextUB.isUsable()) 10049 return 0; 10050 // UB = UB + ST 10051 CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(), 10052 CombNextUB.get()); 10053 CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(), 10054 /*DiscardedValue*/ false); 10055 if (!CombNextUB.isUsable()) 10056 return 0; 10057 } 10058 } 10059 10060 // Create increment expression for distribute loop when combined in a same 10061 // directive with for as IV = IV + ST; ensure upper bound expression based 10062 // on PrevUB instead of NumIterations - used to implement 'for' when found 10063 // in combination with 'distribute', like in 'distribute parallel for' 10064 SourceLocation DistIncLoc = AStmt->getBeginLoc(); 10065 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond; 10066 if (isOpenMPLoopBoundSharingDirective(DKind)) { 10067 DistCond = SemaRef.BuildBinOp( 10068 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB); 10069 assert(DistCond.isUsable() && "distribute cond expr was not built"); 10070 10071 DistInc = 10072 SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get()); 10073 assert(DistInc.isUsable() && "distribute inc expr was not built"); 10074 DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(), 10075 DistInc.get()); 10076 DistInc = 10077 SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue*/ false); 10078 assert(DistInc.isUsable() && "distribute inc expr was not built"); 10079 10080 // Build expression: UB = min(UB, prevUB) for #for in composite or combined 10081 // construct 10082 ExprResult NewPrevUB = PrevUB; 10083 SourceLocation DistEUBLoc = AStmt->getBeginLoc(); 10084 if (!SemaRef.Context.hasSameType(UB.get()->getType(), 10085 PrevUB.get()->getType())) { 10086 NewPrevUB = SemaRef.BuildCStyleCastExpr( 10087 DistEUBLoc, 10088 SemaRef.Context.getTrivialTypeSourceInfo(UB.get()->getType()), 10089 DistEUBLoc, NewPrevUB.get()); 10090 if (!NewPrevUB.isUsable()) 10091 return 0; 10092 } 10093 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT, 10094 UB.get(), NewPrevUB.get()); 10095 ExprResult CondOp = SemaRef.ActOnConditionalOp( 10096 DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get()); 10097 PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(), 10098 CondOp.get()); 10099 PrevEUB = 10100 SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue*/ false); 10101 10102 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in 10103 // parallel for is in combination with a distribute directive with 10104 // schedule(static, 1) 10105 Expr *BoundPrevUB = PrevUB.get(); 10106 if (UseStrictCompare) { 10107 BoundPrevUB = 10108 SemaRef 10109 .BuildBinOp( 10110 CurScope, CondLoc, BO_Add, BoundPrevUB, 10111 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get()) 10112 .get(); 10113 BoundPrevUB = 10114 SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue*/ false) 10115 .get(); 10116 } 10117 ParForInDistCond = 10118 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, 10119 IV.get(), BoundPrevUB); 10120 } 10121 10122 // Build updates and final values of the loop counters. 10123 bool HasErrors = false; 10124 Built.Counters.resize(NestedLoopCount); 10125 Built.Inits.resize(NestedLoopCount); 10126 Built.Updates.resize(NestedLoopCount); 10127 Built.Finals.resize(NestedLoopCount); 10128 Built.DependentCounters.resize(NestedLoopCount); 10129 Built.DependentInits.resize(NestedLoopCount); 10130 Built.FinalsConditions.resize(NestedLoopCount); 10131 { 10132 // We implement the following algorithm for obtaining the 10133 // original loop iteration variable values based on the 10134 // value of the collapsed loop iteration variable IV. 10135 // 10136 // Let n+1 be the number of collapsed loops in the nest. 10137 // Iteration variables (I0, I1, .... In) 10138 // Iteration counts (N0, N1, ... Nn) 10139 // 10140 // Acc = IV; 10141 // 10142 // To compute Ik for loop k, 0 <= k <= n, generate: 10143 // Prod = N(k+1) * N(k+2) * ... * Nn; 10144 // Ik = Acc / Prod; 10145 // Acc -= Ik * Prod; 10146 // 10147 ExprResult Acc = IV; 10148 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) { 10149 LoopIterationSpace &IS = IterSpaces[Cnt]; 10150 SourceLocation UpdLoc = IS.IncSrcRange.getBegin(); 10151 ExprResult Iter; 10152 10153 // Compute prod 10154 ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(); 10155 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K) 10156 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(), 10157 IterSpaces[K].NumIterations); 10158 10159 // Iter = Acc / Prod 10160 // If there is at least one more inner loop to avoid 10161 // multiplication by 1. 10162 if (Cnt + 1 < NestedLoopCount) 10163 Iter = 10164 SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get()); 10165 else 10166 Iter = Acc; 10167 if (!Iter.isUsable()) { 10168 HasErrors = true; 10169 break; 10170 } 10171 10172 // Update Acc: 10173 // Acc -= Iter * Prod 10174 // Check if there is at least one more inner loop to avoid 10175 // multiplication by 1. 10176 if (Cnt + 1 < NestedLoopCount) 10177 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(), 10178 Prod.get()); 10179 else 10180 Prod = Iter; 10181 Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get()); 10182 10183 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step 10184 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl()); 10185 DeclRefExpr *CounterVar = buildDeclRefExpr( 10186 SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(), 10187 /*RefersToCapture=*/true); 10188 ExprResult Init = 10189 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar, 10190 IS.CounterInit, IS.IsNonRectangularLB, Captures); 10191 if (!Init.isUsable()) { 10192 HasErrors = true; 10193 break; 10194 } 10195 ExprResult Update = buildCounterUpdate( 10196 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter, 10197 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures); 10198 if (!Update.isUsable()) { 10199 HasErrors = true; 10200 break; 10201 } 10202 10203 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step 10204 ExprResult Final = 10205 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar, 10206 IS.CounterInit, IS.NumIterations, IS.CounterStep, 10207 IS.Subtract, IS.IsNonRectangularLB, &Captures); 10208 if (!Final.isUsable()) { 10209 HasErrors = true; 10210 break; 10211 } 10212 10213 if (!Update.isUsable() || !Final.isUsable()) { 10214 HasErrors = true; 10215 break; 10216 } 10217 // Save results 10218 Built.Counters[Cnt] = IS.CounterVar; 10219 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar; 10220 Built.Inits[Cnt] = Init.get(); 10221 Built.Updates[Cnt] = Update.get(); 10222 Built.Finals[Cnt] = Final.get(); 10223 Built.DependentCounters[Cnt] = nullptr; 10224 Built.DependentInits[Cnt] = nullptr; 10225 Built.FinalsConditions[Cnt] = nullptr; 10226 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) { 10227 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1]; 10228 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1]; 10229 Built.FinalsConditions[Cnt] = IS.FinalCondition; 10230 } 10231 } 10232 } 10233 10234 if (HasErrors) 10235 return 0; 10236 10237 // Save results 10238 Built.IterationVarRef = IV.get(); 10239 Built.LastIteration = LastIteration.get(); 10240 Built.NumIterations = NumIterations.get(); 10241 Built.CalcLastIteration = SemaRef 10242 .ActOnFinishFullExpr(CalcLastIteration.get(), 10243 /*DiscardedValue=*/false) 10244 .get(); 10245 Built.PreCond = PreCond.get(); 10246 Built.PreInits = buildPreInits(C, Captures); 10247 Built.Cond = Cond.get(); 10248 Built.Init = Init.get(); 10249 Built.Inc = Inc.get(); 10250 Built.LB = LB.get(); 10251 Built.UB = UB.get(); 10252 Built.IL = IL.get(); 10253 Built.ST = ST.get(); 10254 Built.EUB = EUB.get(); 10255 Built.NLB = NextLB.get(); 10256 Built.NUB = NextUB.get(); 10257 Built.PrevLB = PrevLB.get(); 10258 Built.PrevUB = PrevUB.get(); 10259 Built.DistInc = DistInc.get(); 10260 Built.PrevEUB = PrevEUB.get(); 10261 Built.DistCombinedFields.LB = CombLB.get(); 10262 Built.DistCombinedFields.UB = CombUB.get(); 10263 Built.DistCombinedFields.EUB = CombEUB.get(); 10264 Built.DistCombinedFields.Init = CombInit.get(); 10265 Built.DistCombinedFields.Cond = CombCond.get(); 10266 Built.DistCombinedFields.NLB = CombNextLB.get(); 10267 Built.DistCombinedFields.NUB = CombNextUB.get(); 10268 Built.DistCombinedFields.DistCond = CombDistCond.get(); 10269 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get(); 10270 10271 return NestedLoopCount; 10272 } 10273 10274 static Expr *getCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) { 10275 auto CollapseClauses = 10276 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses); 10277 if (CollapseClauses.begin() != CollapseClauses.end()) 10278 return (*CollapseClauses.begin())->getNumForLoops(); 10279 return nullptr; 10280 } 10281 10282 static Expr *getOrderedNumberExpr(ArrayRef<OMPClause *> Clauses) { 10283 auto OrderedClauses = 10284 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses); 10285 if (OrderedClauses.begin() != OrderedClauses.end()) 10286 return (*OrderedClauses.begin())->getNumForLoops(); 10287 return nullptr; 10288 } 10289 10290 static bool checkSimdlenSafelenSpecified(Sema &S, 10291 const ArrayRef<OMPClause *> Clauses) { 10292 const OMPSafelenClause *Safelen = nullptr; 10293 const OMPSimdlenClause *Simdlen = nullptr; 10294 10295 for (const OMPClause *Clause : Clauses) { 10296 if (Clause->getClauseKind() == OMPC_safelen) 10297 Safelen = cast<OMPSafelenClause>(Clause); 10298 else if (Clause->getClauseKind() == OMPC_simdlen) 10299 Simdlen = cast<OMPSimdlenClause>(Clause); 10300 if (Safelen && Simdlen) 10301 break; 10302 } 10303 10304 if (Simdlen && Safelen) { 10305 const Expr *SimdlenLength = Simdlen->getSimdlen(); 10306 const Expr *SafelenLength = Safelen->getSafelen(); 10307 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() || 10308 SimdlenLength->isInstantiationDependent() || 10309 SimdlenLength->containsUnexpandedParameterPack()) 10310 return false; 10311 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() || 10312 SafelenLength->isInstantiationDependent() || 10313 SafelenLength->containsUnexpandedParameterPack()) 10314 return false; 10315 Expr::EvalResult SimdlenResult, SafelenResult; 10316 SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context); 10317 SafelenLength->EvaluateAsInt(SafelenResult, S.Context); 10318 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt(); 10319 llvm::APSInt SafelenRes = SafelenResult.Val.getInt(); 10320 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions] 10321 // If both simdlen and safelen clauses are specified, the value of the 10322 // simdlen parameter must be less than or equal to the value of the safelen 10323 // parameter. 10324 if (SimdlenRes > SafelenRes) { 10325 S.Diag(SimdlenLength->getExprLoc(), 10326 diag::err_omp_wrong_simdlen_safelen_values) 10327 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange(); 10328 return true; 10329 } 10330 } 10331 return false; 10332 } 10333 10334 static bool checkGenericLoopLastprivate(Sema &S, ArrayRef<OMPClause *> Clauses, 10335 OpenMPDirectiveKind K, 10336 DSAStackTy *Stack); 10337 10338 bool SemaOpenMP::checkLastPrivateForMappedDirectives( 10339 ArrayRef<OMPClause *> Clauses) { 10340 10341 // Check for syntax of lastprivate 10342 // Param of the lastprivate have different meanings in the mapped directives 10343 // e.g. "omp loop" Only loop iteration vars are allowed in lastprivate clause 10344 // "omp for" lastprivate vars must be shared 10345 if (getLangOpts().OpenMP >= 50 && 10346 DSAStack->getMappedDirective() == OMPD_loop && 10347 checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_loop, DSAStack)) { 10348 return false; 10349 } 10350 return true; 10351 } 10352 10353 StmtResult SemaOpenMP::ActOnOpenMPSimdDirective( 10354 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 10355 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 10356 if (!AStmt) 10357 return StmtError(); 10358 10359 if (!checkLastPrivateForMappedDirectives(Clauses)) 10360 return StmtError(); 10361 10362 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 10363 OMPLoopBasedDirective::HelperExprs B; 10364 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 10365 // define the nested loops number. 10366 unsigned NestedLoopCount = checkOpenMPLoop( 10367 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses), 10368 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B); 10369 if (NestedLoopCount == 0) 10370 return StmtError(); 10371 10372 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 10373 return StmtError(); 10374 10375 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 10376 return StmtError(); 10377 10378 SemaRef.setFunctionHasBranchProtectedScope(); 10379 auto *SimdDirective = OMPSimdDirective::Create( 10380 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B, 10381 DSAStack->getMappedDirective()); 10382 return SimdDirective; 10383 } 10384 10385 StmtResult SemaOpenMP::ActOnOpenMPForDirective( 10386 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 10387 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 10388 if (!AStmt) 10389 return StmtError(); 10390 10391 if (!checkLastPrivateForMappedDirectives(Clauses)) 10392 return StmtError(); 10393 10394 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 10395 OMPLoopBasedDirective::HelperExprs B; 10396 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 10397 // define the nested loops number. 10398 unsigned NestedLoopCount = checkOpenMPLoop( 10399 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses), 10400 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B); 10401 if (NestedLoopCount == 0) 10402 return StmtError(); 10403 10404 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 10405 return StmtError(); 10406 10407 auto *ForDirective = OMPForDirective::Create( 10408 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B, 10409 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion(), 10410 DSAStack->getMappedDirective()); 10411 return ForDirective; 10412 } 10413 10414 StmtResult SemaOpenMP::ActOnOpenMPForSimdDirective( 10415 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 10416 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 10417 if (!AStmt) 10418 return StmtError(); 10419 10420 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 10421 OMPLoopBasedDirective::HelperExprs B; 10422 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 10423 // define the nested loops number. 10424 unsigned NestedLoopCount = 10425 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses), 10426 getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack, 10427 VarsWithImplicitDSA, B); 10428 if (NestedLoopCount == 0) 10429 return StmtError(); 10430 10431 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 10432 return StmtError(); 10433 10434 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 10435 return StmtError(); 10436 10437 SemaRef.setFunctionHasBranchProtectedScope(); 10438 return OMPForSimdDirective::Create(getASTContext(), StartLoc, EndLoc, 10439 NestedLoopCount, Clauses, AStmt, B); 10440 } 10441 10442 static bool checkSectionsDirective(Sema &SemaRef, OpenMPDirectiveKind DKind, 10443 Stmt *AStmt, DSAStackTy *Stack) { 10444 if (!AStmt) 10445 return true; 10446 10447 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 10448 auto BaseStmt = AStmt; 10449 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt)) 10450 BaseStmt = CS->getCapturedStmt(); 10451 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) { 10452 auto S = C->children(); 10453 if (S.begin() == S.end()) 10454 return true; 10455 // All associated statements must be '#pragma omp section' except for 10456 // the first one. 10457 for (Stmt *SectionStmt : llvm::drop_begin(S)) { 10458 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) { 10459 if (SectionStmt) 10460 SemaRef.Diag(SectionStmt->getBeginLoc(), 10461 diag::err_omp_sections_substmt_not_section) 10462 << getOpenMPDirectiveName(DKind); 10463 return true; 10464 } 10465 cast<OMPSectionDirective>(SectionStmt) 10466 ->setHasCancel(Stack->isCancelRegion()); 10467 } 10468 } else { 10469 SemaRef.Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt) 10470 << getOpenMPDirectiveName(DKind); 10471 return true; 10472 } 10473 return false; 10474 } 10475 10476 StmtResult 10477 SemaOpenMP::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses, 10478 Stmt *AStmt, SourceLocation StartLoc, 10479 SourceLocation EndLoc) { 10480 if (checkSectionsDirective(SemaRef, OMPD_sections, AStmt, DSAStack)) 10481 return StmtError(); 10482 10483 SemaRef.setFunctionHasBranchProtectedScope(); 10484 10485 return OMPSectionsDirective::Create( 10486 getASTContext(), StartLoc, EndLoc, Clauses, AStmt, 10487 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion()); 10488 } 10489 10490 StmtResult SemaOpenMP::ActOnOpenMPSectionDirective(Stmt *AStmt, 10491 SourceLocation StartLoc, 10492 SourceLocation EndLoc) { 10493 if (!AStmt) 10494 return StmtError(); 10495 10496 SemaRef.setFunctionHasBranchProtectedScope(); 10497 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion()); 10498 10499 return OMPSectionDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt, 10500 DSAStack->isCancelRegion()); 10501 } 10502 10503 static Expr *getDirectCallExpr(Expr *E) { 10504 E = E->IgnoreParenCasts()->IgnoreImplicit(); 10505 if (auto *CE = dyn_cast<CallExpr>(E)) 10506 if (CE->getDirectCallee()) 10507 return E; 10508 return nullptr; 10509 } 10510 10511 StmtResult 10512 SemaOpenMP::ActOnOpenMPDispatchDirective(ArrayRef<OMPClause *> Clauses, 10513 Stmt *AStmt, SourceLocation StartLoc, 10514 SourceLocation EndLoc) { 10515 if (!AStmt) 10516 return StmtError(); 10517 10518 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt(); 10519 10520 // 5.1 OpenMP 10521 // expression-stmt : an expression statement with one of the following forms: 10522 // expression = target-call ( [expression-list] ); 10523 // target-call ( [expression-list] ); 10524 10525 SourceLocation TargetCallLoc; 10526 10527 if (!SemaRef.CurContext->isDependentContext()) { 10528 Expr *TargetCall = nullptr; 10529 10530 auto *E = dyn_cast<Expr>(S); 10531 if (!E) { 10532 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call); 10533 return StmtError(); 10534 } 10535 10536 E = E->IgnoreParenCasts()->IgnoreImplicit(); 10537 10538 if (auto *BO = dyn_cast<BinaryOperator>(E)) { 10539 if (BO->getOpcode() == BO_Assign) 10540 TargetCall = getDirectCallExpr(BO->getRHS()); 10541 } else { 10542 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E)) 10543 if (COCE->getOperator() == OO_Equal) 10544 TargetCall = getDirectCallExpr(COCE->getArg(1)); 10545 if (!TargetCall) 10546 TargetCall = getDirectCallExpr(E); 10547 } 10548 if (!TargetCall) { 10549 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call); 10550 return StmtError(); 10551 } 10552 TargetCallLoc = TargetCall->getExprLoc(); 10553 } 10554 10555 SemaRef.setFunctionHasBranchProtectedScope(); 10556 10557 return OMPDispatchDirective::Create(getASTContext(), StartLoc, EndLoc, 10558 Clauses, AStmt, TargetCallLoc); 10559 } 10560 10561 static bool checkGenericLoopLastprivate(Sema &S, ArrayRef<OMPClause *> Clauses, 10562 OpenMPDirectiveKind K, 10563 DSAStackTy *Stack) { 10564 bool ErrorFound = false; 10565 for (OMPClause *C : Clauses) { 10566 if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) { 10567 for (Expr *RefExpr : LPC->varlists()) { 10568 SourceLocation ELoc; 10569 SourceRange ERange; 10570 Expr *SimpleRefExpr = RefExpr; 10571 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange); 10572 if (ValueDecl *D = Res.first) { 10573 auto &&Info = Stack->isLoopControlVariable(D); 10574 if (!Info.first) { 10575 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration) 10576 << getOpenMPDirectiveName(K); 10577 ErrorFound = true; 10578 } 10579 } 10580 } 10581 } 10582 } 10583 return ErrorFound; 10584 } 10585 10586 StmtResult SemaOpenMP::ActOnOpenMPGenericLoopDirective( 10587 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 10588 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 10589 if (!AStmt) 10590 return StmtError(); 10591 10592 // OpenMP 5.1 [2.11.7, loop construct, Restrictions] 10593 // A list item may not appear in a lastprivate clause unless it is the 10594 // loop iteration variable of a loop that is associated with the construct. 10595 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_loop, DSAStack)) 10596 return StmtError(); 10597 10598 setBranchProtectedScope(SemaRef, OMPD_loop, AStmt); 10599 10600 OMPLoopDirective::HelperExprs B; 10601 // In presence of clause 'collapse', it will define the nested loops number. 10602 unsigned NestedLoopCount = checkOpenMPLoop( 10603 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses), 10604 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B); 10605 if (NestedLoopCount == 0) 10606 return StmtError(); 10607 10608 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 10609 "omp loop exprs were not built"); 10610 10611 return OMPGenericLoopDirective::Create(getASTContext(), StartLoc, EndLoc, 10612 NestedLoopCount, Clauses, AStmt, B); 10613 } 10614 10615 StmtResult SemaOpenMP::ActOnOpenMPTeamsGenericLoopDirective( 10616 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 10617 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 10618 if (!AStmt) 10619 return StmtError(); 10620 10621 // OpenMP 5.1 [2.11.7, loop construct, Restrictions] 10622 // A list item may not appear in a lastprivate clause unless it is the 10623 // loop iteration variable of a loop that is associated with the construct. 10624 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_teams_loop, DSAStack)) 10625 return StmtError(); 10626 10627 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_teams_loop, AStmt); 10628 10629 OMPLoopDirective::HelperExprs B; 10630 // In presence of clause 'collapse', it will define the nested loops number. 10631 unsigned NestedLoopCount = 10632 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses), 10633 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack, 10634 VarsWithImplicitDSA, B); 10635 if (NestedLoopCount == 0) 10636 return StmtError(); 10637 10638 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 10639 "omp loop exprs were not built"); 10640 10641 DSAStack->setParentTeamsRegionLoc(StartLoc); 10642 10643 return OMPTeamsGenericLoopDirective::Create( 10644 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 10645 } 10646 10647 StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsGenericLoopDirective( 10648 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 10649 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 10650 if (!AStmt) 10651 return StmtError(); 10652 10653 // OpenMP 5.1 [2.11.7, loop construct, Restrictions] 10654 // A list item may not appear in a lastprivate clause unless it is the 10655 // loop iteration variable of a loop that is associated with the construct. 10656 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_teams_loop, 10657 DSAStack)) 10658 return StmtError(); 10659 10660 CapturedStmt *CS = 10661 setBranchProtectedScope(SemaRef, OMPD_target_teams_loop, AStmt); 10662 10663 OMPLoopDirective::HelperExprs B; 10664 // In presence of clause 'collapse', it will define the nested loops number. 10665 unsigned NestedLoopCount = 10666 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses), 10667 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack, 10668 VarsWithImplicitDSA, B); 10669 if (NestedLoopCount == 0) 10670 return StmtError(); 10671 10672 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 10673 "omp loop exprs were not built"); 10674 10675 return OMPTargetTeamsGenericLoopDirective::Create( 10676 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B, 10677 teamsLoopCanBeParallelFor(AStmt, SemaRef)); 10678 } 10679 10680 StmtResult SemaOpenMP::ActOnOpenMPParallelGenericLoopDirective( 10681 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 10682 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 10683 if (!AStmt) 10684 return StmtError(); 10685 10686 // OpenMP 5.1 [2.11.7, loop construct, Restrictions] 10687 // A list item may not appear in a lastprivate clause unless it is the 10688 // loop iteration variable of a loop that is associated with the construct. 10689 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_parallel_loop, 10690 DSAStack)) 10691 return StmtError(); 10692 10693 CapturedStmt *CS = 10694 setBranchProtectedScope(SemaRef, OMPD_parallel_loop, AStmt); 10695 10696 OMPLoopDirective::HelperExprs B; 10697 // In presence of clause 'collapse', it will define the nested loops number. 10698 unsigned NestedLoopCount = 10699 checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses), 10700 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack, 10701 VarsWithImplicitDSA, B); 10702 if (NestedLoopCount == 0) 10703 return StmtError(); 10704 10705 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 10706 "omp loop exprs were not built"); 10707 10708 return OMPParallelGenericLoopDirective::Create( 10709 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 10710 } 10711 10712 StmtResult SemaOpenMP::ActOnOpenMPTargetParallelGenericLoopDirective( 10713 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 10714 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 10715 if (!AStmt) 10716 return StmtError(); 10717 10718 // OpenMP 5.1 [2.11.7, loop construct, Restrictions] 10719 // A list item may not appear in a lastprivate clause unless it is the 10720 // loop iteration variable of a loop that is associated with the construct. 10721 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_parallel_loop, 10722 DSAStack)) 10723 return StmtError(); 10724 10725 CapturedStmt *CS = 10726 setBranchProtectedScope(SemaRef, OMPD_target_parallel_loop, AStmt); 10727 10728 OMPLoopDirective::HelperExprs B; 10729 // In presence of clause 'collapse', it will define the nested loops number. 10730 unsigned NestedLoopCount = 10731 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses), 10732 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack, 10733 VarsWithImplicitDSA, B); 10734 if (NestedLoopCount == 0) 10735 return StmtError(); 10736 10737 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 10738 "omp loop exprs were not built"); 10739 10740 return OMPTargetParallelGenericLoopDirective::Create( 10741 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 10742 } 10743 10744 StmtResult SemaOpenMP::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses, 10745 Stmt *AStmt, 10746 SourceLocation StartLoc, 10747 SourceLocation EndLoc) { 10748 if (!AStmt) 10749 return StmtError(); 10750 10751 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 10752 10753 SemaRef.setFunctionHasBranchProtectedScope(); 10754 10755 // OpenMP [2.7.3, single Construct, Restrictions] 10756 // The copyprivate clause must not be used with the nowait clause. 10757 const OMPClause *Nowait = nullptr; 10758 const OMPClause *Copyprivate = nullptr; 10759 for (const OMPClause *Clause : Clauses) { 10760 if (Clause->getClauseKind() == OMPC_nowait) 10761 Nowait = Clause; 10762 else if (Clause->getClauseKind() == OMPC_copyprivate) 10763 Copyprivate = Clause; 10764 if (Copyprivate && Nowait) { 10765 Diag(Copyprivate->getBeginLoc(), 10766 diag::err_omp_single_copyprivate_with_nowait); 10767 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here); 10768 return StmtError(); 10769 } 10770 } 10771 10772 return OMPSingleDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses, 10773 AStmt); 10774 } 10775 10776 StmtResult SemaOpenMP::ActOnOpenMPMasterDirective(Stmt *AStmt, 10777 SourceLocation StartLoc, 10778 SourceLocation EndLoc) { 10779 if (!AStmt) 10780 return StmtError(); 10781 10782 SemaRef.setFunctionHasBranchProtectedScope(); 10783 10784 return OMPMasterDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt); 10785 } 10786 10787 StmtResult SemaOpenMP::ActOnOpenMPMaskedDirective(ArrayRef<OMPClause *> Clauses, 10788 Stmt *AStmt, 10789 SourceLocation StartLoc, 10790 SourceLocation EndLoc) { 10791 if (!AStmt) 10792 return StmtError(); 10793 10794 SemaRef.setFunctionHasBranchProtectedScope(); 10795 10796 return OMPMaskedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses, 10797 AStmt); 10798 } 10799 10800 StmtResult SemaOpenMP::ActOnOpenMPCriticalDirective( 10801 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses, 10802 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { 10803 if (!AStmt) 10804 return StmtError(); 10805 10806 bool ErrorFound = false; 10807 llvm::APSInt Hint; 10808 SourceLocation HintLoc; 10809 bool DependentHint = false; 10810 for (const OMPClause *C : Clauses) { 10811 if (C->getClauseKind() == OMPC_hint) { 10812 if (!DirName.getName()) { 10813 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name); 10814 ErrorFound = true; 10815 } 10816 Expr *E = cast<OMPHintClause>(C)->getHint(); 10817 if (E->isTypeDependent() || E->isValueDependent() || 10818 E->isInstantiationDependent()) { 10819 DependentHint = true; 10820 } else { 10821 Hint = E->EvaluateKnownConstInt(getASTContext()); 10822 HintLoc = C->getBeginLoc(); 10823 } 10824 } 10825 } 10826 if (ErrorFound) 10827 return StmtError(); 10828 const auto Pair = DSAStack->getCriticalWithHint(DirName); 10829 if (Pair.first && DirName.getName() && !DependentHint) { 10830 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) { 10831 Diag(StartLoc, diag::err_omp_critical_with_hint); 10832 if (HintLoc.isValid()) 10833 Diag(HintLoc, diag::note_omp_critical_hint_here) 10834 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false); 10835 else 10836 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0; 10837 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) { 10838 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here) 10839 << 1 10840 << toString(C->getHint()->EvaluateKnownConstInt(getASTContext()), 10841 /*Radix=*/10, /*Signed=*/false); 10842 } else { 10843 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1; 10844 } 10845 } 10846 } 10847 10848 SemaRef.setFunctionHasBranchProtectedScope(); 10849 10850 auto *Dir = OMPCriticalDirective::Create(getASTContext(), DirName, StartLoc, 10851 EndLoc, Clauses, AStmt); 10852 if (!Pair.first && DirName.getName() && !DependentHint) 10853 DSAStack->addCriticalWithHint(Dir, Hint); 10854 return Dir; 10855 } 10856 10857 StmtResult SemaOpenMP::ActOnOpenMPParallelForDirective( 10858 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 10859 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 10860 if (!AStmt) 10861 return StmtError(); 10862 10863 setBranchProtectedScope(SemaRef, OMPD_parallel_for, AStmt); 10864 10865 OMPLoopBasedDirective::HelperExprs B; 10866 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 10867 // define the nested loops number. 10868 unsigned NestedLoopCount = 10869 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses), 10870 getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack, 10871 VarsWithImplicitDSA, B); 10872 if (NestedLoopCount == 0) 10873 return StmtError(); 10874 10875 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 10876 return StmtError(); 10877 10878 return OMPParallelForDirective::Create( 10879 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B, 10880 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion()); 10881 } 10882 10883 StmtResult SemaOpenMP::ActOnOpenMPParallelForSimdDirective( 10884 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 10885 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 10886 if (!AStmt) 10887 return StmtError(); 10888 10889 setBranchProtectedScope(SemaRef, OMPD_parallel_for_simd, AStmt); 10890 10891 OMPLoopBasedDirective::HelperExprs B; 10892 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 10893 // define the nested loops number. 10894 unsigned NestedLoopCount = 10895 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses), 10896 getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack, 10897 VarsWithImplicitDSA, B); 10898 if (NestedLoopCount == 0) 10899 return StmtError(); 10900 10901 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 10902 return StmtError(); 10903 10904 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 10905 return StmtError(); 10906 10907 return OMPParallelForSimdDirective::Create( 10908 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 10909 } 10910 10911 StmtResult SemaOpenMP::ActOnOpenMPParallelMasterDirective( 10912 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 10913 SourceLocation EndLoc) { 10914 if (!AStmt) 10915 return StmtError(); 10916 10917 setBranchProtectedScope(SemaRef, OMPD_parallel_master, AStmt); 10918 10919 return OMPParallelMasterDirective::Create( 10920 getASTContext(), StartLoc, EndLoc, Clauses, AStmt, 10921 DSAStack->getTaskgroupReductionRef()); 10922 } 10923 10924 StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedDirective( 10925 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 10926 SourceLocation EndLoc) { 10927 if (!AStmt) 10928 return StmtError(); 10929 10930 setBranchProtectedScope(SemaRef, OMPD_parallel_masked, AStmt); 10931 10932 return OMPParallelMaskedDirective::Create( 10933 getASTContext(), StartLoc, EndLoc, Clauses, AStmt, 10934 DSAStack->getTaskgroupReductionRef()); 10935 } 10936 10937 StmtResult SemaOpenMP::ActOnOpenMPParallelSectionsDirective( 10938 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 10939 SourceLocation EndLoc) { 10940 if (checkSectionsDirective(SemaRef, OMPD_parallel_sections, AStmt, DSAStack)) 10941 return StmtError(); 10942 10943 SemaRef.setFunctionHasBranchProtectedScope(); 10944 10945 return OMPParallelSectionsDirective::Create( 10946 getASTContext(), StartLoc, EndLoc, Clauses, AStmt, 10947 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion()); 10948 } 10949 10950 /// Find and diagnose mutually exclusive clause kinds. 10951 static bool checkMutuallyExclusiveClauses( 10952 Sema &S, ArrayRef<OMPClause *> Clauses, 10953 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) { 10954 const OMPClause *PrevClause = nullptr; 10955 bool ErrorFound = false; 10956 for (const OMPClause *C : Clauses) { 10957 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) { 10958 if (!PrevClause) { 10959 PrevClause = C; 10960 } else if (PrevClause->getClauseKind() != C->getClauseKind()) { 10961 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive) 10962 << getOpenMPClauseName(C->getClauseKind()) 10963 << getOpenMPClauseName(PrevClause->getClauseKind()); 10964 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause) 10965 << getOpenMPClauseName(PrevClause->getClauseKind()); 10966 ErrorFound = true; 10967 } 10968 } 10969 } 10970 return ErrorFound; 10971 } 10972 10973 StmtResult SemaOpenMP::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses, 10974 Stmt *AStmt, 10975 SourceLocation StartLoc, 10976 SourceLocation EndLoc) { 10977 if (!AStmt) 10978 return StmtError(); 10979 10980 // OpenMP 5.0, 2.10.1 task Construct 10981 // If a detach clause appears on the directive, then a mergeable clause cannot 10982 // appear on the same directive. 10983 if (checkMutuallyExclusiveClauses(SemaRef, Clauses, 10984 {OMPC_detach, OMPC_mergeable})) 10985 return StmtError(); 10986 10987 setBranchProtectedScope(SemaRef, OMPD_task, AStmt); 10988 10989 return OMPTaskDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses, 10990 AStmt, DSAStack->isCancelRegion()); 10991 } 10992 10993 StmtResult SemaOpenMP::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc, 10994 SourceLocation EndLoc) { 10995 return OMPTaskyieldDirective::Create(getASTContext(), StartLoc, EndLoc); 10996 } 10997 10998 StmtResult SemaOpenMP::ActOnOpenMPBarrierDirective(SourceLocation StartLoc, 10999 SourceLocation EndLoc) { 11000 return OMPBarrierDirective::Create(getASTContext(), StartLoc, EndLoc); 11001 } 11002 11003 StmtResult SemaOpenMP::ActOnOpenMPErrorDirective(ArrayRef<OMPClause *> Clauses, 11004 SourceLocation StartLoc, 11005 SourceLocation EndLoc, 11006 bool InExContext) { 11007 const OMPAtClause *AtC = 11008 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses); 11009 11010 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) { 11011 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier); 11012 return StmtError(); 11013 } 11014 11015 const OMPSeverityClause *SeverityC = 11016 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses); 11017 const OMPMessageClause *MessageC = 11018 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses); 11019 Expr *ME = MessageC ? MessageC->getMessageString() : nullptr; 11020 11021 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) { 11022 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning) 11023 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded) 11024 << (ME ? cast<StringLiteral>(ME)->getString() : "WARNING"); 11025 else 11026 Diag(StartLoc, diag::err_diagnose_if_succeeded) 11027 << (ME ? cast<StringLiteral>(ME)->getString() : "ERROR"); 11028 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning) 11029 return StmtError(); 11030 } 11031 return OMPErrorDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses); 11032 } 11033 11034 StmtResult 11035 SemaOpenMP::ActOnOpenMPTaskwaitDirective(ArrayRef<OMPClause *> Clauses, 11036 SourceLocation StartLoc, 11037 SourceLocation EndLoc) { 11038 const OMPNowaitClause *NowaitC = 11039 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses); 11040 bool HasDependC = 11041 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses) 11042 .empty(); 11043 if (NowaitC && !HasDependC) { 11044 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend); 11045 return StmtError(); 11046 } 11047 11048 return OMPTaskwaitDirective::Create(getASTContext(), StartLoc, EndLoc, 11049 Clauses); 11050 } 11051 11052 StmtResult 11053 SemaOpenMP::ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause *> Clauses, 11054 Stmt *AStmt, SourceLocation StartLoc, 11055 SourceLocation EndLoc) { 11056 if (!AStmt) 11057 return StmtError(); 11058 11059 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 11060 11061 SemaRef.setFunctionHasBranchProtectedScope(); 11062 11063 return OMPTaskgroupDirective::Create(getASTContext(), StartLoc, EndLoc, 11064 Clauses, AStmt, 11065 DSAStack->getTaskgroupReductionRef()); 11066 } 11067 11068 StmtResult SemaOpenMP::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses, 11069 SourceLocation StartLoc, 11070 SourceLocation EndLoc) { 11071 OMPFlushClause *FC = nullptr; 11072 OMPClause *OrderClause = nullptr; 11073 for (OMPClause *C : Clauses) { 11074 if (C->getClauseKind() == OMPC_flush) 11075 FC = cast<OMPFlushClause>(C); 11076 else 11077 OrderClause = C; 11078 } 11079 OpenMPClauseKind MemOrderKind = OMPC_unknown; 11080 SourceLocation MemOrderLoc; 11081 for (const OMPClause *C : Clauses) { 11082 if (C->getClauseKind() == OMPC_acq_rel || 11083 C->getClauseKind() == OMPC_acquire || 11084 C->getClauseKind() == OMPC_release) { 11085 if (MemOrderKind != OMPC_unknown) { 11086 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses) 11087 << getOpenMPDirectiveName(OMPD_flush) << 1 11088 << SourceRange(C->getBeginLoc(), C->getEndLoc()); 11089 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause) 11090 << getOpenMPClauseName(MemOrderKind); 11091 } else { 11092 MemOrderKind = C->getClauseKind(); 11093 MemOrderLoc = C->getBeginLoc(); 11094 } 11095 } 11096 } 11097 if (FC && OrderClause) { 11098 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list) 11099 << getOpenMPClauseName(OrderClause->getClauseKind()); 11100 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here) 11101 << getOpenMPClauseName(OrderClause->getClauseKind()); 11102 return StmtError(); 11103 } 11104 return OMPFlushDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses); 11105 } 11106 11107 StmtResult SemaOpenMP::ActOnOpenMPDepobjDirective(ArrayRef<OMPClause *> Clauses, 11108 SourceLocation StartLoc, 11109 SourceLocation EndLoc) { 11110 if (Clauses.empty()) { 11111 Diag(StartLoc, diag::err_omp_depobj_expected); 11112 return StmtError(); 11113 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) { 11114 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected); 11115 return StmtError(); 11116 } 11117 // Only depobj expression and another single clause is allowed. 11118 if (Clauses.size() > 2) { 11119 Diag(Clauses[2]->getBeginLoc(), 11120 diag::err_omp_depobj_single_clause_expected); 11121 return StmtError(); 11122 } else if (Clauses.size() < 1) { 11123 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected); 11124 return StmtError(); 11125 } 11126 return OMPDepobjDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses); 11127 } 11128 11129 StmtResult SemaOpenMP::ActOnOpenMPScanDirective(ArrayRef<OMPClause *> Clauses, 11130 SourceLocation StartLoc, 11131 SourceLocation EndLoc) { 11132 // Check that exactly one clause is specified. 11133 if (Clauses.size() != 1) { 11134 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(), 11135 diag::err_omp_scan_single_clause_expected); 11136 return StmtError(); 11137 } 11138 // Check that scan directive is used in the scope of the OpenMP loop body. 11139 if (Scope *S = DSAStack->getCurScope()) { 11140 Scope *ParentS = S->getParent(); 11141 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() || 11142 !ParentS->getBreakParent()->isOpenMPLoopScope()) 11143 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive) 11144 << getOpenMPDirectiveName(OMPD_scan) << 5); 11145 } 11146 // Check that only one instance of scan directives is used in the same outer 11147 // region. 11148 if (DSAStack->doesParentHasScanDirective()) { 11149 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan"; 11150 Diag(DSAStack->getParentScanDirectiveLoc(), 11151 diag::note_omp_previous_directive) 11152 << "scan"; 11153 return StmtError(); 11154 } 11155 DSAStack->setParentHasScanDirective(StartLoc); 11156 return OMPScanDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses); 11157 } 11158 11159 StmtResult 11160 SemaOpenMP::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses, 11161 Stmt *AStmt, SourceLocation StartLoc, 11162 SourceLocation EndLoc) { 11163 const OMPClause *DependFound = nullptr; 11164 const OMPClause *DependSourceClause = nullptr; 11165 const OMPClause *DependSinkClause = nullptr; 11166 const OMPClause *DoacrossFound = nullptr; 11167 const OMPClause *DoacrossSourceClause = nullptr; 11168 const OMPClause *DoacrossSinkClause = nullptr; 11169 bool ErrorFound = false; 11170 const OMPThreadsClause *TC = nullptr; 11171 const OMPSIMDClause *SC = nullptr; 11172 for (const OMPClause *C : Clauses) { 11173 auto DOC = dyn_cast<OMPDoacrossClause>(C); 11174 auto DC = dyn_cast<OMPDependClause>(C); 11175 if (DC || DOC) { 11176 DependFound = DC ? C : nullptr; 11177 DoacrossFound = DOC ? C : nullptr; 11178 OMPDoacrossKind ODK; 11179 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) || 11180 (DOC && (ODK.isSource(DOC)))) { 11181 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) { 11182 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause) 11183 << getOpenMPDirectiveName(OMPD_ordered) 11184 << getOpenMPClauseName(DC ? OMPC_depend : OMPC_doacross) << 2; 11185 ErrorFound = true; 11186 } else { 11187 if (DC) 11188 DependSourceClause = C; 11189 else 11190 DoacrossSourceClause = C; 11191 } 11192 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) { 11193 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed) 11194 << (DC ? "depend" : "doacross") << 0; 11195 ErrorFound = true; 11196 } 11197 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) || 11198 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) { 11199 if (DependSourceClause || DoacrossSourceClause) { 11200 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed) 11201 << (DC ? "depend" : "doacross") << 1; 11202 ErrorFound = true; 11203 } 11204 if (DC) 11205 DependSinkClause = C; 11206 else 11207 DoacrossSinkClause = C; 11208 } 11209 } else if (C->getClauseKind() == OMPC_threads) { 11210 TC = cast<OMPThreadsClause>(C); 11211 } else if (C->getClauseKind() == OMPC_simd) { 11212 SC = cast<OMPSIMDClause>(C); 11213 } 11214 } 11215 if (!ErrorFound && !SC && 11216 isOpenMPSimdDirective(DSAStack->getParentDirective())) { 11217 // OpenMP [2.8.1,simd Construct, Restrictions] 11218 // An ordered construct with the simd clause is the only OpenMP construct 11219 // that can appear in the simd region. 11220 Diag(StartLoc, diag::err_omp_prohibited_region_simd) 11221 << (getLangOpts().OpenMP >= 50 ? 1 : 0); 11222 ErrorFound = true; 11223 } else if ((DependFound || DoacrossFound) && (TC || SC)) { 11224 SourceLocation Loc = 11225 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc(); 11226 Diag(Loc, diag::err_omp_depend_clause_thread_simd) 11227 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross) 11228 << getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind()); 11229 ErrorFound = true; 11230 } else if ((DependFound || DoacrossFound) && 11231 !DSAStack->getParentOrderedRegionParam().first) { 11232 SourceLocation Loc = 11233 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc(); 11234 Diag(Loc, diag::err_omp_ordered_directive_without_param) 11235 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross); 11236 ErrorFound = true; 11237 } else if (TC || Clauses.empty()) { 11238 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) { 11239 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc; 11240 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param) 11241 << (TC != nullptr); 11242 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1; 11243 ErrorFound = true; 11244 } 11245 } 11246 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound) 11247 return StmtError(); 11248 11249 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions. 11250 // During execution of an iteration of a worksharing-loop or a loop nest 11251 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread 11252 // must not execute more than one ordered region corresponding to an ordered 11253 // construct without a depend clause. 11254 if (!DependFound && !DoacrossFound) { 11255 if (DSAStack->doesParentHasOrderedDirective()) { 11256 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered"; 11257 Diag(DSAStack->getParentOrderedDirectiveLoc(), 11258 diag::note_omp_previous_directive) 11259 << "ordered"; 11260 return StmtError(); 11261 } 11262 DSAStack->setParentHasOrderedDirective(StartLoc); 11263 } 11264 11265 if (AStmt) { 11266 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 11267 11268 SemaRef.setFunctionHasBranchProtectedScope(); 11269 } 11270 11271 return OMPOrderedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses, 11272 AStmt); 11273 } 11274 11275 namespace { 11276 /// Helper class for checking expression in 'omp atomic [update]' 11277 /// construct. 11278 class OpenMPAtomicUpdateChecker { 11279 /// Error results for atomic update expressions. 11280 enum ExprAnalysisErrorCode { 11281 /// A statement is not an expression statement. 11282 NotAnExpression, 11283 /// Expression is not builtin binary or unary operation. 11284 NotABinaryOrUnaryExpression, 11285 /// Unary operation is not post-/pre- increment/decrement operation. 11286 NotAnUnaryIncDecExpression, 11287 /// An expression is not of scalar type. 11288 NotAScalarType, 11289 /// A binary operation is not an assignment operation. 11290 NotAnAssignmentOp, 11291 /// RHS part of the binary operation is not a binary expression. 11292 NotABinaryExpression, 11293 /// RHS part is not additive/multiplicative/shift/bitwise binary 11294 /// expression. 11295 NotABinaryOperator, 11296 /// RHS binary operation does not have reference to the updated LHS 11297 /// part. 11298 NotAnUpdateExpression, 11299 /// An expression contains semantical error not related to 11300 /// 'omp atomic [update]' 11301 NotAValidExpression, 11302 /// No errors is found. 11303 NoError 11304 }; 11305 /// Reference to Sema. 11306 Sema &SemaRef; 11307 /// A location for note diagnostics (when error is found). 11308 SourceLocation NoteLoc; 11309 /// 'x' lvalue part of the source atomic expression. 11310 Expr *X; 11311 /// 'expr' rvalue part of the source atomic expression. 11312 Expr *E; 11313 /// Helper expression of the form 11314 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or 11315 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'. 11316 Expr *UpdateExpr; 11317 /// Is 'x' a LHS in a RHS part of full update expression. It is 11318 /// important for non-associative operations. 11319 bool IsXLHSInRHSPart; 11320 BinaryOperatorKind Op; 11321 SourceLocation OpLoc; 11322 /// true if the source expression is a postfix unary operation, false 11323 /// if it is a prefix unary operation. 11324 bool IsPostfixUpdate; 11325 11326 public: 11327 OpenMPAtomicUpdateChecker(Sema &SemaRef) 11328 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr), 11329 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {} 11330 /// Check specified statement that it is suitable for 'atomic update' 11331 /// constructs and extract 'x', 'expr' and Operation from the original 11332 /// expression. If DiagId and NoteId == 0, then only check is performed 11333 /// without error notification. 11334 /// \param DiagId Diagnostic which should be emitted if error is found. 11335 /// \param NoteId Diagnostic note for the main error message. 11336 /// \return true if statement is not an update expression, false otherwise. 11337 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0); 11338 /// Return the 'x' lvalue part of the source atomic expression. 11339 Expr *getX() const { return X; } 11340 /// Return the 'expr' rvalue part of the source atomic expression. 11341 Expr *getExpr() const { return E; } 11342 /// Return the update expression used in calculation of the updated 11343 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or 11344 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'. 11345 Expr *getUpdateExpr() const { return UpdateExpr; } 11346 /// Return true if 'x' is LHS in RHS part of full update expression, 11347 /// false otherwise. 11348 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; } 11349 11350 /// true if the source expression is a postfix unary operation, false 11351 /// if it is a prefix unary operation. 11352 bool isPostfixUpdate() const { return IsPostfixUpdate; } 11353 11354 private: 11355 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0, 11356 unsigned NoteId = 0); 11357 }; 11358 11359 bool OpenMPAtomicUpdateChecker::checkBinaryOperation( 11360 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) { 11361 ExprAnalysisErrorCode ErrorFound = NoError; 11362 SourceLocation ErrorLoc, NoteLoc; 11363 SourceRange ErrorRange, NoteRange; 11364 // Allowed constructs are: 11365 // x = x binop expr; 11366 // x = expr binop x; 11367 if (AtomicBinOp->getOpcode() == BO_Assign) { 11368 X = AtomicBinOp->getLHS(); 11369 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>( 11370 AtomicBinOp->getRHS()->IgnoreParenImpCasts())) { 11371 if (AtomicInnerBinOp->isMultiplicativeOp() || 11372 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() || 11373 AtomicInnerBinOp->isBitwiseOp()) { 11374 Op = AtomicInnerBinOp->getOpcode(); 11375 OpLoc = AtomicInnerBinOp->getOperatorLoc(); 11376 Expr *LHS = AtomicInnerBinOp->getLHS(); 11377 Expr *RHS = AtomicInnerBinOp->getRHS(); 11378 llvm::FoldingSetNodeID XId, LHSId, RHSId; 11379 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(), 11380 /*Canonical=*/true); 11381 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(), 11382 /*Canonical=*/true); 11383 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(), 11384 /*Canonical=*/true); 11385 if (XId == LHSId) { 11386 E = RHS; 11387 IsXLHSInRHSPart = true; 11388 } else if (XId == RHSId) { 11389 E = LHS; 11390 IsXLHSInRHSPart = false; 11391 } else { 11392 ErrorLoc = AtomicInnerBinOp->getExprLoc(); 11393 ErrorRange = AtomicInnerBinOp->getSourceRange(); 11394 NoteLoc = X->getExprLoc(); 11395 NoteRange = X->getSourceRange(); 11396 ErrorFound = NotAnUpdateExpression; 11397 } 11398 } else { 11399 ErrorLoc = AtomicInnerBinOp->getExprLoc(); 11400 ErrorRange = AtomicInnerBinOp->getSourceRange(); 11401 NoteLoc = AtomicInnerBinOp->getOperatorLoc(); 11402 NoteRange = SourceRange(NoteLoc, NoteLoc); 11403 ErrorFound = NotABinaryOperator; 11404 } 11405 } else { 11406 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc(); 11407 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange(); 11408 ErrorFound = NotABinaryExpression; 11409 } 11410 } else { 11411 ErrorLoc = AtomicBinOp->getExprLoc(); 11412 ErrorRange = AtomicBinOp->getSourceRange(); 11413 NoteLoc = AtomicBinOp->getOperatorLoc(); 11414 NoteRange = SourceRange(NoteLoc, NoteLoc); 11415 ErrorFound = NotAnAssignmentOp; 11416 } 11417 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) { 11418 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange; 11419 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange; 11420 return true; 11421 } 11422 if (SemaRef.CurContext->isDependentContext()) 11423 E = X = UpdateExpr = nullptr; 11424 return ErrorFound != NoError; 11425 } 11426 11427 bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId, 11428 unsigned NoteId) { 11429 ExprAnalysisErrorCode ErrorFound = NoError; 11430 SourceLocation ErrorLoc, NoteLoc; 11431 SourceRange ErrorRange, NoteRange; 11432 // Allowed constructs are: 11433 // x++; 11434 // x--; 11435 // ++x; 11436 // --x; 11437 // x binop= expr; 11438 // x = x binop expr; 11439 // x = expr binop x; 11440 if (auto *AtomicBody = dyn_cast<Expr>(S)) { 11441 AtomicBody = AtomicBody->IgnoreParenImpCasts(); 11442 if (AtomicBody->getType()->isScalarType() || 11443 AtomicBody->isInstantiationDependent()) { 11444 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>( 11445 AtomicBody->IgnoreParenImpCasts())) { 11446 // Check for Compound Assignment Operation 11447 Op = BinaryOperator::getOpForCompoundAssignment( 11448 AtomicCompAssignOp->getOpcode()); 11449 OpLoc = AtomicCompAssignOp->getOperatorLoc(); 11450 E = AtomicCompAssignOp->getRHS(); 11451 X = AtomicCompAssignOp->getLHS()->IgnoreParens(); 11452 IsXLHSInRHSPart = true; 11453 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>( 11454 AtomicBody->IgnoreParenImpCasts())) { 11455 // Check for Binary Operation 11456 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId)) 11457 return true; 11458 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>( 11459 AtomicBody->IgnoreParenImpCasts())) { 11460 // Check for Unary Operation 11461 if (AtomicUnaryOp->isIncrementDecrementOp()) { 11462 IsPostfixUpdate = AtomicUnaryOp->isPostfix(); 11463 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub; 11464 OpLoc = AtomicUnaryOp->getOperatorLoc(); 11465 X = AtomicUnaryOp->getSubExpr()->IgnoreParens(); 11466 E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get(); 11467 IsXLHSInRHSPart = true; 11468 } else { 11469 ErrorFound = NotAnUnaryIncDecExpression; 11470 ErrorLoc = AtomicUnaryOp->getExprLoc(); 11471 ErrorRange = AtomicUnaryOp->getSourceRange(); 11472 NoteLoc = AtomicUnaryOp->getOperatorLoc(); 11473 NoteRange = SourceRange(NoteLoc, NoteLoc); 11474 } 11475 } else if (!AtomicBody->isInstantiationDependent()) { 11476 ErrorFound = NotABinaryOrUnaryExpression; 11477 NoteLoc = ErrorLoc = AtomicBody->getExprLoc(); 11478 NoteRange = ErrorRange = AtomicBody->getSourceRange(); 11479 } else if (AtomicBody->containsErrors()) { 11480 ErrorFound = NotAValidExpression; 11481 NoteLoc = ErrorLoc = AtomicBody->getExprLoc(); 11482 NoteRange = ErrorRange = AtomicBody->getSourceRange(); 11483 } 11484 } else { 11485 ErrorFound = NotAScalarType; 11486 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc(); 11487 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc); 11488 } 11489 } else { 11490 ErrorFound = NotAnExpression; 11491 NoteLoc = ErrorLoc = S->getBeginLoc(); 11492 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc); 11493 } 11494 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) { 11495 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange; 11496 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange; 11497 return true; 11498 } 11499 if (SemaRef.CurContext->isDependentContext()) 11500 E = X = UpdateExpr = nullptr; 11501 if (ErrorFound == NoError && E && X) { 11502 // Build an update expression of form 'OpaqueValueExpr(x) binop 11503 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop 11504 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression. 11505 auto *OVEX = new (SemaRef.getASTContext()) 11506 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue); 11507 auto *OVEExpr = new (SemaRef.getASTContext()) 11508 OpaqueValueExpr(E->getExprLoc(), E->getType(), VK_PRValue); 11509 ExprResult Update = 11510 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr, 11511 IsXLHSInRHSPart ? OVEExpr : OVEX); 11512 if (Update.isInvalid()) 11513 return true; 11514 Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(), 11515 Sema::AA_Casting); 11516 if (Update.isInvalid()) 11517 return true; 11518 UpdateExpr = Update.get(); 11519 } 11520 return ErrorFound != NoError; 11521 } 11522 11523 /// Get the node id of the fixed point of an expression \a S. 11524 llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) { 11525 llvm::FoldingSetNodeID Id; 11526 S->IgnoreParenImpCasts()->Profile(Id, Context, true); 11527 return Id; 11528 } 11529 11530 /// Check if two expressions are same. 11531 bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS, 11532 const Expr *RHS) { 11533 return getNodeId(Context, LHS) == getNodeId(Context, RHS); 11534 } 11535 11536 class OpenMPAtomicCompareChecker { 11537 public: 11538 /// All kinds of errors that can occur in `atomic compare` 11539 enum ErrorTy { 11540 /// Empty compound statement. 11541 NoStmt = 0, 11542 /// More than one statement in a compound statement. 11543 MoreThanOneStmt, 11544 /// Not an assignment binary operator. 11545 NotAnAssignment, 11546 /// Not a conditional operator. 11547 NotCondOp, 11548 /// Wrong false expr. According to the spec, 'x' should be at the false 11549 /// expression of a conditional expression. 11550 WrongFalseExpr, 11551 /// The condition of a conditional expression is not a binary operator. 11552 NotABinaryOp, 11553 /// Invalid binary operator (not <, >, or ==). 11554 InvalidBinaryOp, 11555 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x). 11556 InvalidComparison, 11557 /// X is not a lvalue. 11558 XNotLValue, 11559 /// Not a scalar. 11560 NotScalar, 11561 /// Not an integer. 11562 NotInteger, 11563 /// 'else' statement is not expected. 11564 UnexpectedElse, 11565 /// Not an equality operator. 11566 NotEQ, 11567 /// Invalid assignment (not v == x). 11568 InvalidAssignment, 11569 /// Not if statement 11570 NotIfStmt, 11571 /// More than two statements in a compound statement. 11572 MoreThanTwoStmts, 11573 /// Not a compound statement. 11574 NotCompoundStmt, 11575 /// No else statement. 11576 NoElse, 11577 /// Not 'if (r)'. 11578 InvalidCondition, 11579 /// No error. 11580 NoError, 11581 }; 11582 11583 struct ErrorInfoTy { 11584 ErrorTy Error; 11585 SourceLocation ErrorLoc; 11586 SourceRange ErrorRange; 11587 SourceLocation NoteLoc; 11588 SourceRange NoteRange; 11589 }; 11590 11591 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {} 11592 11593 /// Check if statement \a S is valid for <tt>atomic compare</tt>. 11594 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo); 11595 11596 Expr *getX() const { return X; } 11597 Expr *getE() const { return E; } 11598 Expr *getD() const { return D; } 11599 Expr *getCond() const { return C; } 11600 bool isXBinopExpr() const { return IsXBinopExpr; } 11601 11602 protected: 11603 /// Reference to ASTContext 11604 ASTContext &ContextRef; 11605 /// 'x' lvalue part of the source atomic expression. 11606 Expr *X = nullptr; 11607 /// 'expr' or 'e' rvalue part of the source atomic expression. 11608 Expr *E = nullptr; 11609 /// 'd' rvalue part of the source atomic expression. 11610 Expr *D = nullptr; 11611 /// 'cond' part of the source atomic expression. It is in one of the following 11612 /// forms: 11613 /// expr ordop x 11614 /// x ordop expr 11615 /// x == e 11616 /// e == x 11617 Expr *C = nullptr; 11618 /// True if the cond expr is in the form of 'x ordop expr'. 11619 bool IsXBinopExpr = true; 11620 11621 /// Check if it is a valid conditional update statement (cond-update-stmt). 11622 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo); 11623 11624 /// Check if it is a valid conditional expression statement (cond-expr-stmt). 11625 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo); 11626 11627 /// Check if all captured values have right type. 11628 bool checkType(ErrorInfoTy &ErrorInfo) const; 11629 11630 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo, 11631 bool ShouldBeLValue, bool ShouldBeInteger = false) { 11632 if (E->isInstantiationDependent()) 11633 return true; 11634 11635 if (ShouldBeLValue && !E->isLValue()) { 11636 ErrorInfo.Error = ErrorTy::XNotLValue; 11637 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc(); 11638 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange(); 11639 return false; 11640 } 11641 11642 QualType QTy = E->getType(); 11643 if (!QTy->isScalarType()) { 11644 ErrorInfo.Error = ErrorTy::NotScalar; 11645 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc(); 11646 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange(); 11647 return false; 11648 } 11649 if (ShouldBeInteger && !QTy->isIntegerType()) { 11650 ErrorInfo.Error = ErrorTy::NotInteger; 11651 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc(); 11652 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange(); 11653 return false; 11654 } 11655 11656 return true; 11657 } 11658 }; 11659 11660 bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S, 11661 ErrorInfoTy &ErrorInfo) { 11662 auto *Then = S->getThen(); 11663 if (auto *CS = dyn_cast<CompoundStmt>(Then)) { 11664 if (CS->body_empty()) { 11665 ErrorInfo.Error = ErrorTy::NoStmt; 11666 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc(); 11667 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange(); 11668 return false; 11669 } 11670 if (CS->size() > 1) { 11671 ErrorInfo.Error = ErrorTy::MoreThanOneStmt; 11672 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc(); 11673 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange(); 11674 return false; 11675 } 11676 Then = CS->body_front(); 11677 } 11678 11679 auto *BO = dyn_cast<BinaryOperator>(Then); 11680 if (!BO) { 11681 ErrorInfo.Error = ErrorTy::NotAnAssignment; 11682 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc(); 11683 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange(); 11684 return false; 11685 } 11686 if (BO->getOpcode() != BO_Assign) { 11687 ErrorInfo.Error = ErrorTy::NotAnAssignment; 11688 ErrorInfo.ErrorLoc = BO->getExprLoc(); 11689 ErrorInfo.NoteLoc = BO->getOperatorLoc(); 11690 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange(); 11691 return false; 11692 } 11693 11694 X = BO->getLHS(); 11695 11696 auto *Cond = dyn_cast<BinaryOperator>(S->getCond()); 11697 if (!Cond) { 11698 ErrorInfo.Error = ErrorTy::NotABinaryOp; 11699 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc(); 11700 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange(); 11701 return false; 11702 } 11703 11704 switch (Cond->getOpcode()) { 11705 case BO_EQ: { 11706 C = Cond; 11707 D = BO->getRHS(); 11708 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) { 11709 E = Cond->getRHS(); 11710 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) { 11711 E = Cond->getLHS(); 11712 } else { 11713 ErrorInfo.Error = ErrorTy::InvalidComparison; 11714 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc(); 11715 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange(); 11716 return false; 11717 } 11718 break; 11719 } 11720 case BO_LT: 11721 case BO_GT: { 11722 E = BO->getRHS(); 11723 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) && 11724 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) { 11725 C = Cond; 11726 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) && 11727 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) { 11728 C = Cond; 11729 IsXBinopExpr = false; 11730 } else { 11731 ErrorInfo.Error = ErrorTy::InvalidComparison; 11732 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc(); 11733 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange(); 11734 return false; 11735 } 11736 break; 11737 } 11738 default: 11739 ErrorInfo.Error = ErrorTy::InvalidBinaryOp; 11740 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc(); 11741 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange(); 11742 return false; 11743 } 11744 11745 if (S->getElse()) { 11746 ErrorInfo.Error = ErrorTy::UnexpectedElse; 11747 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc(); 11748 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange(); 11749 return false; 11750 } 11751 11752 return true; 11753 } 11754 11755 bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S, 11756 ErrorInfoTy &ErrorInfo) { 11757 auto *BO = dyn_cast<BinaryOperator>(S); 11758 if (!BO) { 11759 ErrorInfo.Error = ErrorTy::NotAnAssignment; 11760 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc(); 11761 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange(); 11762 return false; 11763 } 11764 if (BO->getOpcode() != BO_Assign) { 11765 ErrorInfo.Error = ErrorTy::NotAnAssignment; 11766 ErrorInfo.ErrorLoc = BO->getExprLoc(); 11767 ErrorInfo.NoteLoc = BO->getOperatorLoc(); 11768 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange(); 11769 return false; 11770 } 11771 11772 X = BO->getLHS(); 11773 11774 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts()); 11775 if (!CO) { 11776 ErrorInfo.Error = ErrorTy::NotCondOp; 11777 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc(); 11778 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange(); 11779 return false; 11780 } 11781 11782 if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) { 11783 ErrorInfo.Error = ErrorTy::WrongFalseExpr; 11784 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc(); 11785 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = 11786 CO->getFalseExpr()->getSourceRange(); 11787 return false; 11788 } 11789 11790 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond()); 11791 if (!Cond) { 11792 ErrorInfo.Error = ErrorTy::NotABinaryOp; 11793 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc(); 11794 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = 11795 CO->getCond()->getSourceRange(); 11796 return false; 11797 } 11798 11799 switch (Cond->getOpcode()) { 11800 case BO_EQ: { 11801 C = Cond; 11802 D = CO->getTrueExpr(); 11803 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) { 11804 E = Cond->getRHS(); 11805 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) { 11806 E = Cond->getLHS(); 11807 } else { 11808 ErrorInfo.Error = ErrorTy::InvalidComparison; 11809 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc(); 11810 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange(); 11811 return false; 11812 } 11813 break; 11814 } 11815 case BO_LT: 11816 case BO_GT: { 11817 E = CO->getTrueExpr(); 11818 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) && 11819 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) { 11820 C = Cond; 11821 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) && 11822 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) { 11823 C = Cond; 11824 IsXBinopExpr = false; 11825 } else { 11826 ErrorInfo.Error = ErrorTy::InvalidComparison; 11827 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc(); 11828 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange(); 11829 return false; 11830 } 11831 break; 11832 } 11833 default: 11834 ErrorInfo.Error = ErrorTy::InvalidBinaryOp; 11835 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc(); 11836 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange(); 11837 return false; 11838 } 11839 11840 return true; 11841 } 11842 11843 bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const { 11844 // 'x' and 'e' cannot be nullptr 11845 assert(X && E && "X and E cannot be nullptr"); 11846 11847 if (!CheckValue(X, ErrorInfo, true)) 11848 return false; 11849 11850 if (!CheckValue(E, ErrorInfo, false)) 11851 return false; 11852 11853 if (D && !CheckValue(D, ErrorInfo, false)) 11854 return false; 11855 11856 return true; 11857 } 11858 11859 bool OpenMPAtomicCompareChecker::checkStmt( 11860 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) { 11861 auto *CS = dyn_cast<CompoundStmt>(S); 11862 if (CS) { 11863 if (CS->body_empty()) { 11864 ErrorInfo.Error = ErrorTy::NoStmt; 11865 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc(); 11866 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange(); 11867 return false; 11868 } 11869 11870 if (CS->size() != 1) { 11871 ErrorInfo.Error = ErrorTy::MoreThanOneStmt; 11872 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc(); 11873 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange(); 11874 return false; 11875 } 11876 S = CS->body_front(); 11877 } 11878 11879 auto Res = false; 11880 11881 if (auto *IS = dyn_cast<IfStmt>(S)) { 11882 // Check if the statement is in one of the following forms 11883 // (cond-update-stmt): 11884 // if (expr ordop x) { x = expr; } 11885 // if (x ordop expr) { x = expr; } 11886 // if (x == e) { x = d; } 11887 Res = checkCondUpdateStmt(IS, ErrorInfo); 11888 } else { 11889 // Check if the statement is in one of the following forms (cond-expr-stmt): 11890 // x = expr ordop x ? expr : x; 11891 // x = x ordop expr ? expr : x; 11892 // x = x == e ? d : x; 11893 Res = checkCondExprStmt(S, ErrorInfo); 11894 } 11895 11896 if (!Res) 11897 return false; 11898 11899 return checkType(ErrorInfo); 11900 } 11901 11902 class OpenMPAtomicCompareCaptureChecker final 11903 : public OpenMPAtomicCompareChecker { 11904 public: 11905 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {} 11906 11907 Expr *getV() const { return V; } 11908 Expr *getR() const { return R; } 11909 bool isFailOnly() const { return IsFailOnly; } 11910 bool isPostfixUpdate() const { return IsPostfixUpdate; } 11911 11912 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>. 11913 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo); 11914 11915 private: 11916 bool checkType(ErrorInfoTy &ErrorInfo); 11917 11918 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th 11919 // form of 'conditional-update-capture-atomic' structured block on the v5.2 11920 // spec p.p. 82: 11921 // (1) { v = x; cond-update-stmt } 11922 // (2) { cond-update-stmt v = x; } 11923 // (3) if(x == e) { x = d; } else { v = x; } 11924 // (4) { r = x == e; if(r) { x = d; } } 11925 // (5) { r = x == e; if(r) { x = d; } else { v = x; } } 11926 11927 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3) 11928 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo); 11929 11930 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }', 11931 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5) 11932 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo); 11933 11934 /// 'v' lvalue part of the source atomic expression. 11935 Expr *V = nullptr; 11936 /// 'r' lvalue part of the source atomic expression. 11937 Expr *R = nullptr; 11938 /// If 'v' is only updated when the comparison fails. 11939 bool IsFailOnly = false; 11940 /// If original value of 'x' must be stored in 'v', not an updated one. 11941 bool IsPostfixUpdate = false; 11942 }; 11943 11944 bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) { 11945 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo)) 11946 return false; 11947 11948 if (V && !CheckValue(V, ErrorInfo, true)) 11949 return false; 11950 11951 if (R && !CheckValue(R, ErrorInfo, true, true)) 11952 return false; 11953 11954 return true; 11955 } 11956 11957 bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S, 11958 ErrorInfoTy &ErrorInfo) { 11959 IsFailOnly = true; 11960 11961 auto *Then = S->getThen(); 11962 if (auto *CS = dyn_cast<CompoundStmt>(Then)) { 11963 if (CS->body_empty()) { 11964 ErrorInfo.Error = ErrorTy::NoStmt; 11965 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc(); 11966 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange(); 11967 return false; 11968 } 11969 if (CS->size() > 1) { 11970 ErrorInfo.Error = ErrorTy::MoreThanOneStmt; 11971 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc(); 11972 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange(); 11973 return false; 11974 } 11975 Then = CS->body_front(); 11976 } 11977 11978 auto *BO = dyn_cast<BinaryOperator>(Then); 11979 if (!BO) { 11980 ErrorInfo.Error = ErrorTy::NotAnAssignment; 11981 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc(); 11982 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange(); 11983 return false; 11984 } 11985 if (BO->getOpcode() != BO_Assign) { 11986 ErrorInfo.Error = ErrorTy::NotAnAssignment; 11987 ErrorInfo.ErrorLoc = BO->getExprLoc(); 11988 ErrorInfo.NoteLoc = BO->getOperatorLoc(); 11989 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange(); 11990 return false; 11991 } 11992 11993 X = BO->getLHS(); 11994 D = BO->getRHS(); 11995 11996 auto *Cond = dyn_cast<BinaryOperator>(S->getCond()); 11997 if (!Cond) { 11998 ErrorInfo.Error = ErrorTy::NotABinaryOp; 11999 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc(); 12000 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange(); 12001 return false; 12002 } 12003 if (Cond->getOpcode() != BO_EQ) { 12004 ErrorInfo.Error = ErrorTy::NotEQ; 12005 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc(); 12006 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange(); 12007 return false; 12008 } 12009 12010 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) { 12011 E = Cond->getRHS(); 12012 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) { 12013 E = Cond->getLHS(); 12014 } else { 12015 ErrorInfo.Error = ErrorTy::InvalidComparison; 12016 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc(); 12017 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange(); 12018 return false; 12019 } 12020 12021 C = Cond; 12022 12023 if (!S->getElse()) { 12024 ErrorInfo.Error = ErrorTy::NoElse; 12025 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc(); 12026 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange(); 12027 return false; 12028 } 12029 12030 auto *Else = S->getElse(); 12031 if (auto *CS = dyn_cast<CompoundStmt>(Else)) { 12032 if (CS->body_empty()) { 12033 ErrorInfo.Error = ErrorTy::NoStmt; 12034 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc(); 12035 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange(); 12036 return false; 12037 } 12038 if (CS->size() > 1) { 12039 ErrorInfo.Error = ErrorTy::MoreThanOneStmt; 12040 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc(); 12041 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange(); 12042 return false; 12043 } 12044 Else = CS->body_front(); 12045 } 12046 12047 auto *ElseBO = dyn_cast<BinaryOperator>(Else); 12048 if (!ElseBO) { 12049 ErrorInfo.Error = ErrorTy::NotAnAssignment; 12050 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc(); 12051 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange(); 12052 return false; 12053 } 12054 if (ElseBO->getOpcode() != BO_Assign) { 12055 ErrorInfo.Error = ErrorTy::NotAnAssignment; 12056 ErrorInfo.ErrorLoc = ElseBO->getExprLoc(); 12057 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc(); 12058 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange(); 12059 return false; 12060 } 12061 12062 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) { 12063 ErrorInfo.Error = ErrorTy::InvalidAssignment; 12064 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc(); 12065 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = 12066 ElseBO->getRHS()->getSourceRange(); 12067 return false; 12068 } 12069 12070 V = ElseBO->getLHS(); 12071 12072 return checkType(ErrorInfo); 12073 } 12074 12075 bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S, 12076 ErrorInfoTy &ErrorInfo) { 12077 // We don't check here as they should be already done before call this 12078 // function. 12079 auto *CS = cast<CompoundStmt>(S); 12080 assert(CS->size() == 2 && "CompoundStmt size is not expected"); 12081 auto *S1 = cast<BinaryOperator>(CS->body_front()); 12082 auto *S2 = cast<IfStmt>(CS->body_back()); 12083 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator"); 12084 12085 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) { 12086 ErrorInfo.Error = ErrorTy::InvalidCondition; 12087 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc(); 12088 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange(); 12089 return false; 12090 } 12091 12092 R = S1->getLHS(); 12093 12094 auto *Then = S2->getThen(); 12095 if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) { 12096 if (ThenCS->body_empty()) { 12097 ErrorInfo.Error = ErrorTy::NoStmt; 12098 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc(); 12099 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange(); 12100 return false; 12101 } 12102 if (ThenCS->size() > 1) { 12103 ErrorInfo.Error = ErrorTy::MoreThanOneStmt; 12104 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc(); 12105 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange(); 12106 return false; 12107 } 12108 Then = ThenCS->body_front(); 12109 } 12110 12111 auto *ThenBO = dyn_cast<BinaryOperator>(Then); 12112 if (!ThenBO) { 12113 ErrorInfo.Error = ErrorTy::NotAnAssignment; 12114 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc(); 12115 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange(); 12116 return false; 12117 } 12118 if (ThenBO->getOpcode() != BO_Assign) { 12119 ErrorInfo.Error = ErrorTy::NotAnAssignment; 12120 ErrorInfo.ErrorLoc = ThenBO->getExprLoc(); 12121 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc(); 12122 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange(); 12123 return false; 12124 } 12125 12126 X = ThenBO->getLHS(); 12127 D = ThenBO->getRHS(); 12128 12129 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts()); 12130 if (BO->getOpcode() != BO_EQ) { 12131 ErrorInfo.Error = ErrorTy::NotEQ; 12132 ErrorInfo.ErrorLoc = BO->getExprLoc(); 12133 ErrorInfo.NoteLoc = BO->getOperatorLoc(); 12134 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange(); 12135 return false; 12136 } 12137 12138 C = BO; 12139 12140 if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) { 12141 E = BO->getRHS(); 12142 } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) { 12143 E = BO->getLHS(); 12144 } else { 12145 ErrorInfo.Error = ErrorTy::InvalidComparison; 12146 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc(); 12147 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange(); 12148 return false; 12149 } 12150 12151 if (S2->getElse()) { 12152 IsFailOnly = true; 12153 12154 auto *Else = S2->getElse(); 12155 if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) { 12156 if (ElseCS->body_empty()) { 12157 ErrorInfo.Error = ErrorTy::NoStmt; 12158 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc(); 12159 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange(); 12160 return false; 12161 } 12162 if (ElseCS->size() > 1) { 12163 ErrorInfo.Error = ErrorTy::MoreThanOneStmt; 12164 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc(); 12165 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange(); 12166 return false; 12167 } 12168 Else = ElseCS->body_front(); 12169 } 12170 12171 auto *ElseBO = dyn_cast<BinaryOperator>(Else); 12172 if (!ElseBO) { 12173 ErrorInfo.Error = ErrorTy::NotAnAssignment; 12174 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc(); 12175 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange(); 12176 return false; 12177 } 12178 if (ElseBO->getOpcode() != BO_Assign) { 12179 ErrorInfo.Error = ErrorTy::NotAnAssignment; 12180 ErrorInfo.ErrorLoc = ElseBO->getExprLoc(); 12181 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc(); 12182 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange(); 12183 return false; 12184 } 12185 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) { 12186 ErrorInfo.Error = ErrorTy::InvalidAssignment; 12187 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc(); 12188 ErrorInfo.NoteLoc = X->getExprLoc(); 12189 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange(); 12190 ErrorInfo.NoteRange = X->getSourceRange(); 12191 return false; 12192 } 12193 12194 V = ElseBO->getLHS(); 12195 } 12196 12197 return checkType(ErrorInfo); 12198 } 12199 12200 bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S, 12201 ErrorInfoTy &ErrorInfo) { 12202 // if(x == e) { x = d; } else { v = x; } 12203 if (auto *IS = dyn_cast<IfStmt>(S)) 12204 return checkForm3(IS, ErrorInfo); 12205 12206 auto *CS = dyn_cast<CompoundStmt>(S); 12207 if (!CS) { 12208 ErrorInfo.Error = ErrorTy::NotCompoundStmt; 12209 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc(); 12210 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange(); 12211 return false; 12212 } 12213 if (CS->body_empty()) { 12214 ErrorInfo.Error = ErrorTy::NoStmt; 12215 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc(); 12216 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange(); 12217 return false; 12218 } 12219 12220 // { if(x == e) { x = d; } else { v = x; } } 12221 if (CS->size() == 1) { 12222 auto *IS = dyn_cast<IfStmt>(CS->body_front()); 12223 if (!IS) { 12224 ErrorInfo.Error = ErrorTy::NotIfStmt; 12225 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc(); 12226 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = 12227 CS->body_front()->getSourceRange(); 12228 return false; 12229 } 12230 12231 return checkForm3(IS, ErrorInfo); 12232 } else if (CS->size() == 2) { 12233 auto *S1 = CS->body_front(); 12234 auto *S2 = CS->body_back(); 12235 12236 Stmt *UpdateStmt = nullptr; 12237 Stmt *CondUpdateStmt = nullptr; 12238 Stmt *CondExprStmt = nullptr; 12239 12240 if (auto *BO = dyn_cast<BinaryOperator>(S1)) { 12241 // It could be one of the following cases: 12242 // { v = x; cond-update-stmt } 12243 // { v = x; cond-expr-stmt } 12244 // { cond-expr-stmt; v = x; } 12245 // form 45 12246 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) || 12247 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) { 12248 // check if form 45 12249 if (isa<IfStmt>(S2)) 12250 return checkForm45(CS, ErrorInfo); 12251 // { cond-expr-stmt; v = x; } 12252 CondExprStmt = S1; 12253 UpdateStmt = S2; 12254 } else { 12255 IsPostfixUpdate = true; 12256 UpdateStmt = S1; 12257 if (isa<IfStmt>(S2)) { 12258 // { v = x; cond-update-stmt } 12259 CondUpdateStmt = S2; 12260 } else { 12261 // { v = x; cond-expr-stmt } 12262 CondExprStmt = S2; 12263 } 12264 } 12265 } else { 12266 // { cond-update-stmt v = x; } 12267 UpdateStmt = S2; 12268 CondUpdateStmt = S1; 12269 } 12270 12271 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) { 12272 auto *IS = dyn_cast<IfStmt>(CUS); 12273 if (!IS) { 12274 ErrorInfo.Error = ErrorTy::NotIfStmt; 12275 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc(); 12276 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange(); 12277 return false; 12278 } 12279 12280 return checkCondUpdateStmt(IS, ErrorInfo); 12281 }; 12282 12283 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt. 12284 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) { 12285 auto *BO = dyn_cast<BinaryOperator>(US); 12286 if (!BO) { 12287 ErrorInfo.Error = ErrorTy::NotAnAssignment; 12288 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc(); 12289 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange(); 12290 return false; 12291 } 12292 if (BO->getOpcode() != BO_Assign) { 12293 ErrorInfo.Error = ErrorTy::NotAnAssignment; 12294 ErrorInfo.ErrorLoc = BO->getExprLoc(); 12295 ErrorInfo.NoteLoc = BO->getOperatorLoc(); 12296 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange(); 12297 return false; 12298 } 12299 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) { 12300 ErrorInfo.Error = ErrorTy::InvalidAssignment; 12301 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc(); 12302 ErrorInfo.NoteLoc = this->X->getExprLoc(); 12303 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange(); 12304 ErrorInfo.NoteRange = this->X->getSourceRange(); 12305 return false; 12306 } 12307 12308 this->V = BO->getLHS(); 12309 12310 return true; 12311 }; 12312 12313 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt)) 12314 return false; 12315 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo)) 12316 return false; 12317 if (!CheckUpdateStmt(UpdateStmt)) 12318 return false; 12319 } else { 12320 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts; 12321 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc(); 12322 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange(); 12323 return false; 12324 } 12325 12326 return checkType(ErrorInfo); 12327 } 12328 } // namespace 12329 12330 StmtResult SemaOpenMP::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, 12331 Stmt *AStmt, 12332 SourceLocation StartLoc, 12333 SourceLocation EndLoc) { 12334 ASTContext &Context = getASTContext(); 12335 // Register location of the first atomic directive. 12336 DSAStack->addAtomicDirectiveLoc(StartLoc); 12337 if (!AStmt) 12338 return StmtError(); 12339 12340 // 1.2.2 OpenMP Language Terminology 12341 // Structured block - An executable statement with a single entry at the 12342 // top and a single exit at the bottom. 12343 // The point of exit cannot be a branch out of the structured block. 12344 // longjmp() and throw() must not violate the entry/exit criteria. 12345 OpenMPClauseKind AtomicKind = OMPC_unknown; 12346 SourceLocation AtomicKindLoc; 12347 OpenMPClauseKind MemOrderKind = OMPC_unknown; 12348 SourceLocation MemOrderLoc; 12349 bool MutexClauseEncountered = false; 12350 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds; 12351 for (const OMPClause *C : Clauses) { 12352 switch (C->getClauseKind()) { 12353 case OMPC_read: 12354 case OMPC_write: 12355 case OMPC_update: 12356 MutexClauseEncountered = true; 12357 [[fallthrough]]; 12358 case OMPC_capture: 12359 case OMPC_compare: { 12360 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) { 12361 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses) 12362 << SourceRange(C->getBeginLoc(), C->getEndLoc()); 12363 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause) 12364 << getOpenMPClauseName(AtomicKind); 12365 } else { 12366 AtomicKind = C->getClauseKind(); 12367 AtomicKindLoc = C->getBeginLoc(); 12368 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) { 12369 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses) 12370 << SourceRange(C->getBeginLoc(), C->getEndLoc()); 12371 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause) 12372 << getOpenMPClauseName(AtomicKind); 12373 } 12374 } 12375 break; 12376 } 12377 case OMPC_weak: 12378 case OMPC_fail: { 12379 if (!EncounteredAtomicKinds.contains(OMPC_compare)) { 12380 Diag(C->getBeginLoc(), diag::err_omp_atomic_no_compare) 12381 << getOpenMPClauseName(C->getClauseKind()) 12382 << SourceRange(C->getBeginLoc(), C->getEndLoc()); 12383 return StmtError(); 12384 } 12385 break; 12386 } 12387 case OMPC_seq_cst: 12388 case OMPC_acq_rel: 12389 case OMPC_acquire: 12390 case OMPC_release: 12391 case OMPC_relaxed: { 12392 if (MemOrderKind != OMPC_unknown) { 12393 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses) 12394 << getOpenMPDirectiveName(OMPD_atomic) << 0 12395 << SourceRange(C->getBeginLoc(), C->getEndLoc()); 12396 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause) 12397 << getOpenMPClauseName(MemOrderKind); 12398 } else { 12399 MemOrderKind = C->getClauseKind(); 12400 MemOrderLoc = C->getBeginLoc(); 12401 } 12402 break; 12403 } 12404 // The following clauses are allowed, but we don't need to do anything here. 12405 case OMPC_hint: 12406 break; 12407 default: 12408 llvm_unreachable("unknown clause is encountered"); 12409 } 12410 } 12411 bool IsCompareCapture = false; 12412 if (EncounteredAtomicKinds.contains(OMPC_compare) && 12413 EncounteredAtomicKinds.contains(OMPC_capture)) { 12414 IsCompareCapture = true; 12415 AtomicKind = OMPC_compare; 12416 } 12417 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions 12418 // If atomic-clause is read then memory-order-clause must not be acq_rel or 12419 // release. 12420 // If atomic-clause is write then memory-order-clause must not be acq_rel or 12421 // acquire. 12422 // If atomic-clause is update or not present then memory-order-clause must not 12423 // be acq_rel or acquire. 12424 if ((AtomicKind == OMPC_read && 12425 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) || 12426 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update || 12427 AtomicKind == OMPC_unknown) && 12428 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) { 12429 SourceLocation Loc = AtomicKindLoc; 12430 if (AtomicKind == OMPC_unknown) 12431 Loc = StartLoc; 12432 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause) 12433 << getOpenMPClauseName(AtomicKind) 12434 << (AtomicKind == OMPC_unknown ? 1 : 0) 12435 << getOpenMPClauseName(MemOrderKind); 12436 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause) 12437 << getOpenMPClauseName(MemOrderKind); 12438 } 12439 12440 Stmt *Body = AStmt; 12441 if (auto *EWC = dyn_cast<ExprWithCleanups>(Body)) 12442 Body = EWC->getSubExpr(); 12443 12444 Expr *X = nullptr; 12445 Expr *V = nullptr; 12446 Expr *E = nullptr; 12447 Expr *UE = nullptr; 12448 Expr *D = nullptr; 12449 Expr *CE = nullptr; 12450 Expr *R = nullptr; 12451 bool IsXLHSInRHSPart = false; 12452 bool IsPostfixUpdate = false; 12453 bool IsFailOnly = false; 12454 // OpenMP [2.12.6, atomic Construct] 12455 // In the next expressions: 12456 // * x and v (as applicable) are both l-value expressions with scalar type. 12457 // * During the execution of an atomic region, multiple syntactic 12458 // occurrences of x must designate the same storage location. 12459 // * Neither of v and expr (as applicable) may access the storage location 12460 // designated by x. 12461 // * Neither of x and expr (as applicable) may access the storage location 12462 // designated by v. 12463 // * expr is an expression with scalar type. 12464 // * binop is one of +, *, -, /, &, ^, |, <<, or >>. 12465 // * binop, binop=, ++, and -- are not overloaded operators. 12466 // * The expression x binop expr must be numerically equivalent to x binop 12467 // (expr). This requirement is satisfied if the operators in expr have 12468 // precedence greater than binop, or by using parentheses around expr or 12469 // subexpressions of expr. 12470 // * The expression expr binop x must be numerically equivalent to (expr) 12471 // binop x. This requirement is satisfied if the operators in expr have 12472 // precedence equal to or greater than binop, or by using parentheses around 12473 // expr or subexpressions of expr. 12474 // * For forms that allow multiple occurrences of x, the number of times 12475 // that x is evaluated is unspecified. 12476 if (AtomicKind == OMPC_read) { 12477 enum { 12478 NotAnExpression, 12479 NotAnAssignmentOp, 12480 NotAScalarType, 12481 NotAnLValue, 12482 NoError 12483 } ErrorFound = NoError; 12484 SourceLocation ErrorLoc, NoteLoc; 12485 SourceRange ErrorRange, NoteRange; 12486 // If clause is read: 12487 // v = x; 12488 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) { 12489 const auto *AtomicBinOp = 12490 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts()); 12491 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) { 12492 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts(); 12493 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts(); 12494 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) && 12495 (V->isInstantiationDependent() || V->getType()->isScalarType())) { 12496 if (!X->isLValue() || !V->isLValue()) { 12497 const Expr *NotLValueExpr = X->isLValue() ? V : X; 12498 ErrorFound = NotAnLValue; 12499 ErrorLoc = AtomicBinOp->getExprLoc(); 12500 ErrorRange = AtomicBinOp->getSourceRange(); 12501 NoteLoc = NotLValueExpr->getExprLoc(); 12502 NoteRange = NotLValueExpr->getSourceRange(); 12503 } 12504 } else if (!X->isInstantiationDependent() || 12505 !V->isInstantiationDependent()) { 12506 const Expr *NotScalarExpr = 12507 (X->isInstantiationDependent() || X->getType()->isScalarType()) 12508 ? V 12509 : X; 12510 ErrorFound = NotAScalarType; 12511 ErrorLoc = AtomicBinOp->getExprLoc(); 12512 ErrorRange = AtomicBinOp->getSourceRange(); 12513 NoteLoc = NotScalarExpr->getExprLoc(); 12514 NoteRange = NotScalarExpr->getSourceRange(); 12515 } 12516 } else if (!AtomicBody->isInstantiationDependent()) { 12517 ErrorFound = NotAnAssignmentOp; 12518 ErrorLoc = AtomicBody->getExprLoc(); 12519 ErrorRange = AtomicBody->getSourceRange(); 12520 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc() 12521 : AtomicBody->getExprLoc(); 12522 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange() 12523 : AtomicBody->getSourceRange(); 12524 } 12525 } else { 12526 ErrorFound = NotAnExpression; 12527 NoteLoc = ErrorLoc = Body->getBeginLoc(); 12528 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc); 12529 } 12530 if (ErrorFound != NoError) { 12531 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement) 12532 << ErrorRange; 12533 Diag(NoteLoc, diag::note_omp_atomic_read_write) 12534 << ErrorFound << NoteRange; 12535 return StmtError(); 12536 } 12537 if (SemaRef.CurContext->isDependentContext()) 12538 V = X = nullptr; 12539 } else if (AtomicKind == OMPC_write) { 12540 enum { 12541 NotAnExpression, 12542 NotAnAssignmentOp, 12543 NotAScalarType, 12544 NotAnLValue, 12545 NoError 12546 } ErrorFound = NoError; 12547 SourceLocation ErrorLoc, NoteLoc; 12548 SourceRange ErrorRange, NoteRange; 12549 // If clause is write: 12550 // x = expr; 12551 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) { 12552 const auto *AtomicBinOp = 12553 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts()); 12554 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) { 12555 X = AtomicBinOp->getLHS(); 12556 E = AtomicBinOp->getRHS(); 12557 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) && 12558 (E->isInstantiationDependent() || E->getType()->isScalarType())) { 12559 if (!X->isLValue()) { 12560 ErrorFound = NotAnLValue; 12561 ErrorLoc = AtomicBinOp->getExprLoc(); 12562 ErrorRange = AtomicBinOp->getSourceRange(); 12563 NoteLoc = X->getExprLoc(); 12564 NoteRange = X->getSourceRange(); 12565 } 12566 } else if (!X->isInstantiationDependent() || 12567 !E->isInstantiationDependent()) { 12568 const Expr *NotScalarExpr = 12569 (X->isInstantiationDependent() || X->getType()->isScalarType()) 12570 ? E 12571 : X; 12572 ErrorFound = NotAScalarType; 12573 ErrorLoc = AtomicBinOp->getExprLoc(); 12574 ErrorRange = AtomicBinOp->getSourceRange(); 12575 NoteLoc = NotScalarExpr->getExprLoc(); 12576 NoteRange = NotScalarExpr->getSourceRange(); 12577 } 12578 } else if (!AtomicBody->isInstantiationDependent()) { 12579 ErrorFound = NotAnAssignmentOp; 12580 ErrorLoc = AtomicBody->getExprLoc(); 12581 ErrorRange = AtomicBody->getSourceRange(); 12582 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc() 12583 : AtomicBody->getExprLoc(); 12584 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange() 12585 : AtomicBody->getSourceRange(); 12586 } 12587 } else { 12588 ErrorFound = NotAnExpression; 12589 NoteLoc = ErrorLoc = Body->getBeginLoc(); 12590 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc); 12591 } 12592 if (ErrorFound != NoError) { 12593 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement) 12594 << ErrorRange; 12595 Diag(NoteLoc, diag::note_omp_atomic_read_write) 12596 << ErrorFound << NoteRange; 12597 return StmtError(); 12598 } 12599 if (SemaRef.CurContext->isDependentContext()) 12600 E = X = nullptr; 12601 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) { 12602 // If clause is update: 12603 // x++; 12604 // x--; 12605 // ++x; 12606 // --x; 12607 // x binop= expr; 12608 // x = x binop expr; 12609 // x = expr binop x; 12610 OpenMPAtomicUpdateChecker Checker(SemaRef); 12611 if (Checker.checkStatement( 12612 Body, 12613 (AtomicKind == OMPC_update) 12614 ? diag::err_omp_atomic_update_not_expression_statement 12615 : diag::err_omp_atomic_not_expression_statement, 12616 diag::note_omp_atomic_update)) 12617 return StmtError(); 12618 if (!SemaRef.CurContext->isDependentContext()) { 12619 E = Checker.getExpr(); 12620 X = Checker.getX(); 12621 UE = Checker.getUpdateExpr(); 12622 IsXLHSInRHSPart = Checker.isXLHSInRHSPart(); 12623 } 12624 } else if (AtomicKind == OMPC_capture) { 12625 enum { 12626 NotAnAssignmentOp, 12627 NotACompoundStatement, 12628 NotTwoSubstatements, 12629 NotASpecificExpression, 12630 NoError 12631 } ErrorFound = NoError; 12632 SourceLocation ErrorLoc, NoteLoc; 12633 SourceRange ErrorRange, NoteRange; 12634 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) { 12635 // If clause is a capture: 12636 // v = x++; 12637 // v = x--; 12638 // v = ++x; 12639 // v = --x; 12640 // v = x binop= expr; 12641 // v = x = x binop expr; 12642 // v = x = expr binop x; 12643 const auto *AtomicBinOp = 12644 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts()); 12645 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) { 12646 V = AtomicBinOp->getLHS(); 12647 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts(); 12648 OpenMPAtomicUpdateChecker Checker(SemaRef); 12649 if (Checker.checkStatement( 12650 Body, diag::err_omp_atomic_capture_not_expression_statement, 12651 diag::note_omp_atomic_update)) 12652 return StmtError(); 12653 E = Checker.getExpr(); 12654 X = Checker.getX(); 12655 UE = Checker.getUpdateExpr(); 12656 IsXLHSInRHSPart = Checker.isXLHSInRHSPart(); 12657 IsPostfixUpdate = Checker.isPostfixUpdate(); 12658 } else if (!AtomicBody->isInstantiationDependent()) { 12659 ErrorLoc = AtomicBody->getExprLoc(); 12660 ErrorRange = AtomicBody->getSourceRange(); 12661 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc() 12662 : AtomicBody->getExprLoc(); 12663 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange() 12664 : AtomicBody->getSourceRange(); 12665 ErrorFound = NotAnAssignmentOp; 12666 } 12667 if (ErrorFound != NoError) { 12668 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement) 12669 << ErrorRange; 12670 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange; 12671 return StmtError(); 12672 } 12673 if (SemaRef.CurContext->isDependentContext()) 12674 UE = V = E = X = nullptr; 12675 } else { 12676 // If clause is a capture: 12677 // { v = x; x = expr; } 12678 // { v = x; x++; } 12679 // { v = x; x--; } 12680 // { v = x; ++x; } 12681 // { v = x; --x; } 12682 // { v = x; x binop= expr; } 12683 // { v = x; x = x binop expr; } 12684 // { v = x; x = expr binop x; } 12685 // { x++; v = x; } 12686 // { x--; v = x; } 12687 // { ++x; v = x; } 12688 // { --x; v = x; } 12689 // { x binop= expr; v = x; } 12690 // { x = x binop expr; v = x; } 12691 // { x = expr binop x; v = x; } 12692 if (auto *CS = dyn_cast<CompoundStmt>(Body)) { 12693 // Check that this is { expr1; expr2; } 12694 if (CS->size() == 2) { 12695 Stmt *First = CS->body_front(); 12696 Stmt *Second = CS->body_back(); 12697 if (auto *EWC = dyn_cast<ExprWithCleanups>(First)) 12698 First = EWC->getSubExpr()->IgnoreParenImpCasts(); 12699 if (auto *EWC = dyn_cast<ExprWithCleanups>(Second)) 12700 Second = EWC->getSubExpr()->IgnoreParenImpCasts(); 12701 // Need to find what subexpression is 'v' and what is 'x'. 12702 OpenMPAtomicUpdateChecker Checker(SemaRef); 12703 bool IsUpdateExprFound = !Checker.checkStatement(Second); 12704 BinaryOperator *BinOp = nullptr; 12705 if (IsUpdateExprFound) { 12706 BinOp = dyn_cast<BinaryOperator>(First); 12707 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign; 12708 } 12709 if (IsUpdateExprFound && !SemaRef.CurContext->isDependentContext()) { 12710 // { v = x; x++; } 12711 // { v = x; x--; } 12712 // { v = x; ++x; } 12713 // { v = x; --x; } 12714 // { v = x; x binop= expr; } 12715 // { v = x; x = x binop expr; } 12716 // { v = x; x = expr binop x; } 12717 // Check that the first expression has form v = x. 12718 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts(); 12719 llvm::FoldingSetNodeID XId, PossibleXId; 12720 Checker.getX()->Profile(XId, Context, /*Canonical=*/true); 12721 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true); 12722 IsUpdateExprFound = XId == PossibleXId; 12723 if (IsUpdateExprFound) { 12724 V = BinOp->getLHS(); 12725 X = Checker.getX(); 12726 E = Checker.getExpr(); 12727 UE = Checker.getUpdateExpr(); 12728 IsXLHSInRHSPart = Checker.isXLHSInRHSPart(); 12729 IsPostfixUpdate = true; 12730 } 12731 } 12732 if (!IsUpdateExprFound) { 12733 IsUpdateExprFound = !Checker.checkStatement(First); 12734 BinOp = nullptr; 12735 if (IsUpdateExprFound) { 12736 BinOp = dyn_cast<BinaryOperator>(Second); 12737 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign; 12738 } 12739 if (IsUpdateExprFound && 12740 !SemaRef.CurContext->isDependentContext()) { 12741 // { x++; v = x; } 12742 // { x--; v = x; } 12743 // { ++x; v = x; } 12744 // { --x; v = x; } 12745 // { x binop= expr; v = x; } 12746 // { x = x binop expr; v = x; } 12747 // { x = expr binop x; v = x; } 12748 // Check that the second expression has form v = x. 12749 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts(); 12750 llvm::FoldingSetNodeID XId, PossibleXId; 12751 Checker.getX()->Profile(XId, Context, /*Canonical=*/true); 12752 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true); 12753 IsUpdateExprFound = XId == PossibleXId; 12754 if (IsUpdateExprFound) { 12755 V = BinOp->getLHS(); 12756 X = Checker.getX(); 12757 E = Checker.getExpr(); 12758 UE = Checker.getUpdateExpr(); 12759 IsXLHSInRHSPart = Checker.isXLHSInRHSPart(); 12760 IsPostfixUpdate = false; 12761 } 12762 } 12763 } 12764 if (!IsUpdateExprFound) { 12765 // { v = x; x = expr; } 12766 auto *FirstExpr = dyn_cast<Expr>(First); 12767 auto *SecondExpr = dyn_cast<Expr>(Second); 12768 if (!FirstExpr || !SecondExpr || 12769 !(FirstExpr->isInstantiationDependent() || 12770 SecondExpr->isInstantiationDependent())) { 12771 auto *FirstBinOp = dyn_cast<BinaryOperator>(First); 12772 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) { 12773 ErrorFound = NotAnAssignmentOp; 12774 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc() 12775 : First->getBeginLoc(); 12776 NoteRange = ErrorRange = FirstBinOp 12777 ? FirstBinOp->getSourceRange() 12778 : SourceRange(ErrorLoc, ErrorLoc); 12779 } else { 12780 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second); 12781 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) { 12782 ErrorFound = NotAnAssignmentOp; 12783 NoteLoc = ErrorLoc = SecondBinOp 12784 ? SecondBinOp->getOperatorLoc() 12785 : Second->getBeginLoc(); 12786 NoteRange = ErrorRange = 12787 SecondBinOp ? SecondBinOp->getSourceRange() 12788 : SourceRange(ErrorLoc, ErrorLoc); 12789 } else { 12790 Expr *PossibleXRHSInFirst = 12791 FirstBinOp->getRHS()->IgnoreParenImpCasts(); 12792 Expr *PossibleXLHSInSecond = 12793 SecondBinOp->getLHS()->IgnoreParenImpCasts(); 12794 llvm::FoldingSetNodeID X1Id, X2Id; 12795 PossibleXRHSInFirst->Profile(X1Id, Context, 12796 /*Canonical=*/true); 12797 PossibleXLHSInSecond->Profile(X2Id, Context, 12798 /*Canonical=*/true); 12799 IsUpdateExprFound = X1Id == X2Id; 12800 if (IsUpdateExprFound) { 12801 V = FirstBinOp->getLHS(); 12802 X = SecondBinOp->getLHS(); 12803 E = SecondBinOp->getRHS(); 12804 UE = nullptr; 12805 IsXLHSInRHSPart = false; 12806 IsPostfixUpdate = true; 12807 } else { 12808 ErrorFound = NotASpecificExpression; 12809 ErrorLoc = FirstBinOp->getExprLoc(); 12810 ErrorRange = FirstBinOp->getSourceRange(); 12811 NoteLoc = SecondBinOp->getLHS()->getExprLoc(); 12812 NoteRange = SecondBinOp->getRHS()->getSourceRange(); 12813 } 12814 } 12815 } 12816 } 12817 } 12818 } else { 12819 NoteLoc = ErrorLoc = Body->getBeginLoc(); 12820 NoteRange = ErrorRange = 12821 SourceRange(Body->getBeginLoc(), Body->getBeginLoc()); 12822 ErrorFound = NotTwoSubstatements; 12823 } 12824 } else { 12825 NoteLoc = ErrorLoc = Body->getBeginLoc(); 12826 NoteRange = ErrorRange = 12827 SourceRange(Body->getBeginLoc(), Body->getBeginLoc()); 12828 ErrorFound = NotACompoundStatement; 12829 } 12830 } 12831 if (ErrorFound != NoError) { 12832 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement) 12833 << ErrorRange; 12834 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange; 12835 return StmtError(); 12836 } 12837 if (SemaRef.CurContext->isDependentContext()) 12838 UE = V = E = X = nullptr; 12839 } else if (AtomicKind == OMPC_compare) { 12840 if (IsCompareCapture) { 12841 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo; 12842 OpenMPAtomicCompareCaptureChecker Checker(SemaRef); 12843 if (!Checker.checkStmt(Body, ErrorInfo)) { 12844 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture) 12845 << ErrorInfo.ErrorRange; 12846 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare) 12847 << ErrorInfo.Error << ErrorInfo.NoteRange; 12848 return StmtError(); 12849 } 12850 X = Checker.getX(); 12851 E = Checker.getE(); 12852 D = Checker.getD(); 12853 CE = Checker.getCond(); 12854 V = Checker.getV(); 12855 R = Checker.getR(); 12856 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'. 12857 IsXLHSInRHSPart = Checker.isXBinopExpr(); 12858 IsFailOnly = Checker.isFailOnly(); 12859 IsPostfixUpdate = Checker.isPostfixUpdate(); 12860 } else { 12861 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo; 12862 OpenMPAtomicCompareChecker Checker(SemaRef); 12863 if (!Checker.checkStmt(Body, ErrorInfo)) { 12864 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare) 12865 << ErrorInfo.ErrorRange; 12866 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare) 12867 << ErrorInfo.Error << ErrorInfo.NoteRange; 12868 return StmtError(); 12869 } 12870 X = Checker.getX(); 12871 E = Checker.getE(); 12872 D = Checker.getD(); 12873 CE = Checker.getCond(); 12874 // The weak clause may only appear if the resulting atomic operation is 12875 // an atomic conditional update for which the comparison tests for 12876 // equality. It was not possible to do this check in 12877 // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak 12878 // could not be performed (Clauses are not available). 12879 auto *It = find_if(Clauses, [](OMPClause *C) { 12880 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak; 12881 }); 12882 if (It != Clauses.end()) { 12883 auto *Cond = dyn_cast<BinaryOperator>(CE); 12884 if (Cond->getOpcode() != BO_EQ) { 12885 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment; 12886 ErrorInfo.ErrorLoc = Cond->getExprLoc(); 12887 ErrorInfo.NoteLoc = Cond->getOperatorLoc(); 12888 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange(); 12889 12890 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality) 12891 << ErrorInfo.ErrorRange; 12892 return StmtError(); 12893 } 12894 } 12895 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'. 12896 IsXLHSInRHSPart = Checker.isXBinopExpr(); 12897 } 12898 } 12899 12900 SemaRef.setFunctionHasBranchProtectedScope(); 12901 12902 return OMPAtomicDirective::Create( 12903 Context, StartLoc, EndLoc, Clauses, AStmt, 12904 {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly}); 12905 } 12906 12907 StmtResult SemaOpenMP::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses, 12908 Stmt *AStmt, 12909 SourceLocation StartLoc, 12910 SourceLocation EndLoc) { 12911 if (!AStmt) 12912 return StmtError(); 12913 12914 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target, AStmt); 12915 12916 // OpenMP [2.16, Nesting of Regions] 12917 // If specified, a teams construct must be contained within a target 12918 // construct. That target construct must contain no statements or directives 12919 // outside of the teams construct. 12920 if (DSAStack->hasInnerTeamsRegion()) { 12921 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true); 12922 bool OMPTeamsFound = true; 12923 if (const auto *CS = dyn_cast<CompoundStmt>(S)) { 12924 auto I = CS->body_begin(); 12925 while (I != CS->body_end()) { 12926 const auto *OED = dyn_cast<OMPExecutableDirective>(*I); 12927 bool IsTeams = OED && isOpenMPTeamsDirective(OED->getDirectiveKind()); 12928 if (!IsTeams || I != CS->body_begin()) { 12929 OMPTeamsFound = false; 12930 if (IsTeams && I != CS->body_begin()) { 12931 // This is the two teams case. Since the InnerTeamsRegionLoc will 12932 // point to this second one reset the iterator to the other teams. 12933 --I; 12934 } 12935 break; 12936 } 12937 ++I; 12938 } 12939 assert(I != CS->body_end() && "Not found statement"); 12940 S = *I; 12941 } else { 12942 const auto *OED = dyn_cast<OMPExecutableDirective>(S); 12943 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind()); 12944 } 12945 if (!OMPTeamsFound) { 12946 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams); 12947 Diag(DSAStack->getInnerTeamsRegionLoc(), 12948 diag::note_omp_nested_teams_construct_here); 12949 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here) 12950 << isa<OMPExecutableDirective>(S); 12951 return StmtError(); 12952 } 12953 } 12954 12955 return OMPTargetDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses, 12956 AStmt); 12957 } 12958 12959 StmtResult SemaOpenMP::ActOnOpenMPTargetParallelDirective( 12960 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 12961 SourceLocation EndLoc) { 12962 if (!AStmt) 12963 return StmtError(); 12964 12965 setBranchProtectedScope(SemaRef, OMPD_target_parallel, AStmt); 12966 12967 return OMPTargetParallelDirective::Create( 12968 getASTContext(), StartLoc, EndLoc, Clauses, AStmt, 12969 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion()); 12970 } 12971 12972 StmtResult SemaOpenMP::ActOnOpenMPTargetParallelForDirective( 12973 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 12974 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 12975 if (!AStmt) 12976 return StmtError(); 12977 12978 CapturedStmt *CS = 12979 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for, AStmt); 12980 12981 OMPLoopBasedDirective::HelperExprs B; 12982 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 12983 // define the nested loops number. 12984 unsigned NestedLoopCount = 12985 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses), 12986 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack, 12987 VarsWithImplicitDSA, B); 12988 if (NestedLoopCount == 0) 12989 return StmtError(); 12990 12991 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 12992 return StmtError(); 12993 12994 return OMPTargetParallelForDirective::Create( 12995 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B, 12996 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion()); 12997 } 12998 12999 /// Check for existence of a map clause in the list of clauses. 13000 static bool hasClauses(ArrayRef<OMPClause *> Clauses, 13001 const OpenMPClauseKind K) { 13002 return llvm::any_of( 13003 Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; }); 13004 } 13005 13006 template <typename... Params> 13007 static bool hasClauses(ArrayRef<OMPClause *> Clauses, const OpenMPClauseKind K, 13008 const Params... ClauseTypes) { 13009 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...); 13010 } 13011 13012 /// Check if the variables in the mapping clause are externally visible. 13013 static bool isClauseMappable(ArrayRef<OMPClause *> Clauses) { 13014 for (const OMPClause *C : Clauses) { 13015 if (auto *TC = dyn_cast<OMPToClause>(C)) 13016 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) { 13017 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() || 13018 (VD->isExternallyVisible() && 13019 VD->getVisibility() != HiddenVisibility); 13020 }); 13021 else if (auto *FC = dyn_cast<OMPFromClause>(C)) 13022 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) { 13023 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() || 13024 (VD->isExternallyVisible() && 13025 VD->getVisibility() != HiddenVisibility); 13026 }); 13027 } 13028 13029 return true; 13030 } 13031 13032 StmtResult 13033 SemaOpenMP::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses, 13034 Stmt *AStmt, SourceLocation StartLoc, 13035 SourceLocation EndLoc) { 13036 if (!AStmt) 13037 return StmtError(); 13038 13039 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 13040 13041 // OpenMP [2.12.2, target data Construct, Restrictions] 13042 // At least one map, use_device_addr or use_device_ptr clause must appear on 13043 // the directive. 13044 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) && 13045 (getLangOpts().OpenMP < 50 || 13046 !hasClauses(Clauses, OMPC_use_device_addr))) { 13047 StringRef Expected; 13048 if (getLangOpts().OpenMP < 50) 13049 Expected = "'map' or 'use_device_ptr'"; 13050 else 13051 Expected = "'map', 'use_device_ptr', or 'use_device_addr'"; 13052 Diag(StartLoc, diag::err_omp_no_clause_for_directive) 13053 << Expected << getOpenMPDirectiveName(OMPD_target_data); 13054 return StmtError(); 13055 } 13056 13057 SemaRef.setFunctionHasBranchProtectedScope(); 13058 13059 return OMPTargetDataDirective::Create(getASTContext(), StartLoc, EndLoc, 13060 Clauses, AStmt); 13061 } 13062 13063 StmtResult SemaOpenMP::ActOnOpenMPTargetEnterDataDirective( 13064 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc, 13065 SourceLocation EndLoc, Stmt *AStmt) { 13066 if (!AStmt) 13067 return StmtError(); 13068 13069 setBranchProtectedScope(SemaRef, OMPD_target_enter_data, AStmt); 13070 13071 // OpenMP [2.10.2, Restrictions, p. 99] 13072 // At least one map clause must appear on the directive. 13073 if (!hasClauses(Clauses, OMPC_map)) { 13074 Diag(StartLoc, diag::err_omp_no_clause_for_directive) 13075 << "'map'" << getOpenMPDirectiveName(OMPD_target_enter_data); 13076 return StmtError(); 13077 } 13078 13079 return OMPTargetEnterDataDirective::Create(getASTContext(), StartLoc, EndLoc, 13080 Clauses, AStmt); 13081 } 13082 13083 StmtResult SemaOpenMP::ActOnOpenMPTargetExitDataDirective( 13084 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc, 13085 SourceLocation EndLoc, Stmt *AStmt) { 13086 if (!AStmt) 13087 return StmtError(); 13088 13089 setBranchProtectedScope(SemaRef, OMPD_target_exit_data, AStmt); 13090 13091 // OpenMP [2.10.3, Restrictions, p. 102] 13092 // At least one map clause must appear on the directive. 13093 if (!hasClauses(Clauses, OMPC_map)) { 13094 Diag(StartLoc, diag::err_omp_no_clause_for_directive) 13095 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data); 13096 return StmtError(); 13097 } 13098 13099 return OMPTargetExitDataDirective::Create(getASTContext(), StartLoc, EndLoc, 13100 Clauses, AStmt); 13101 } 13102 13103 StmtResult SemaOpenMP::ActOnOpenMPTargetUpdateDirective( 13104 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc, 13105 SourceLocation EndLoc, Stmt *AStmt) { 13106 if (!AStmt) 13107 return StmtError(); 13108 13109 setBranchProtectedScope(SemaRef, OMPD_target_update, AStmt); 13110 13111 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) { 13112 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required); 13113 return StmtError(); 13114 } 13115 13116 if (!isClauseMappable(Clauses)) { 13117 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage); 13118 return StmtError(); 13119 } 13120 13121 return OMPTargetUpdateDirective::Create(getASTContext(), StartLoc, EndLoc, 13122 Clauses, AStmt); 13123 } 13124 13125 StmtResult SemaOpenMP::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses, 13126 Stmt *AStmt, 13127 SourceLocation StartLoc, 13128 SourceLocation EndLoc) { 13129 if (!AStmt) 13130 return StmtError(); 13131 13132 // Report affected OpenMP target offloading behavior when in HIP lang-mode. 13133 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target)) 13134 Diag(StartLoc, diag::warn_hip_omp_target_directives); 13135 13136 setBranchProtectedScope(SemaRef, OMPD_teams, AStmt); 13137 13138 DSAStack->setParentTeamsRegionLoc(StartLoc); 13139 13140 return OMPTeamsDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses, 13141 AStmt); 13142 } 13143 13144 StmtResult SemaOpenMP::ActOnOpenMPCancellationPointDirective( 13145 SourceLocation StartLoc, SourceLocation EndLoc, 13146 OpenMPDirectiveKind CancelRegion) { 13147 if (DSAStack->isParentNowaitRegion()) { 13148 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0; 13149 return StmtError(); 13150 } 13151 if (DSAStack->isParentOrderedRegion()) { 13152 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0; 13153 return StmtError(); 13154 } 13155 return OMPCancellationPointDirective::Create(getASTContext(), StartLoc, 13156 EndLoc, CancelRegion); 13157 } 13158 13159 StmtResult SemaOpenMP::ActOnOpenMPCancelDirective( 13160 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc, 13161 SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) { 13162 if (DSAStack->isParentNowaitRegion()) { 13163 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1; 13164 return StmtError(); 13165 } 13166 if (DSAStack->isParentOrderedRegion()) { 13167 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1; 13168 return StmtError(); 13169 } 13170 DSAStack->setParentCancelRegion(/*Cancel=*/true); 13171 return OMPCancelDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses, 13172 CancelRegion); 13173 } 13174 13175 static bool checkReductionClauseWithNogroup(Sema &S, 13176 ArrayRef<OMPClause *> Clauses) { 13177 const OMPClause *ReductionClause = nullptr; 13178 const OMPClause *NogroupClause = nullptr; 13179 for (const OMPClause *C : Clauses) { 13180 if (C->getClauseKind() == OMPC_reduction) { 13181 ReductionClause = C; 13182 if (NogroupClause) 13183 break; 13184 continue; 13185 } 13186 if (C->getClauseKind() == OMPC_nogroup) { 13187 NogroupClause = C; 13188 if (ReductionClause) 13189 break; 13190 continue; 13191 } 13192 } 13193 if (ReductionClause && NogroupClause) { 13194 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup) 13195 << SourceRange(NogroupClause->getBeginLoc(), 13196 NogroupClause->getEndLoc()); 13197 return true; 13198 } 13199 return false; 13200 } 13201 13202 StmtResult SemaOpenMP::ActOnOpenMPTaskLoopDirective( 13203 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13204 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13205 if (!AStmt) 13206 return StmtError(); 13207 13208 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 13209 OMPLoopBasedDirective::HelperExprs B; 13210 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 13211 // define the nested loops number. 13212 unsigned NestedLoopCount = 13213 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses), 13214 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef, 13215 *DSAStack, VarsWithImplicitDSA, B); 13216 if (NestedLoopCount == 0) 13217 return StmtError(); 13218 13219 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 13220 "omp for loop exprs were not built"); 13221 13222 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13223 // The grainsize clause and num_tasks clause are mutually exclusive and may 13224 // not appear on the same taskloop directive. 13225 if (checkMutuallyExclusiveClauses(SemaRef, Clauses, 13226 {OMPC_grainsize, OMPC_num_tasks})) 13227 return StmtError(); 13228 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13229 // If a reduction clause is present on the taskloop directive, the nogroup 13230 // clause must not be specified. 13231 if (checkReductionClauseWithNogroup(SemaRef, Clauses)) 13232 return StmtError(); 13233 13234 SemaRef.setFunctionHasBranchProtectedScope(); 13235 return OMPTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc, 13236 NestedLoopCount, Clauses, AStmt, B, 13237 DSAStack->isCancelRegion()); 13238 } 13239 13240 StmtResult SemaOpenMP::ActOnOpenMPTaskLoopSimdDirective( 13241 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13242 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13243 if (!AStmt) 13244 return StmtError(); 13245 13246 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 13247 OMPLoopBasedDirective::HelperExprs B; 13248 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 13249 // define the nested loops number. 13250 unsigned NestedLoopCount = 13251 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses), 13252 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef, 13253 *DSAStack, VarsWithImplicitDSA, B); 13254 if (NestedLoopCount == 0) 13255 return StmtError(); 13256 13257 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 13258 return StmtError(); 13259 13260 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13261 // The grainsize clause and num_tasks clause are mutually exclusive and may 13262 // not appear on the same taskloop directive. 13263 if (checkMutuallyExclusiveClauses(SemaRef, Clauses, 13264 {OMPC_grainsize, OMPC_num_tasks})) 13265 return StmtError(); 13266 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13267 // If a reduction clause is present on the taskloop directive, the nogroup 13268 // clause must not be specified. 13269 if (checkReductionClauseWithNogroup(SemaRef, Clauses)) 13270 return StmtError(); 13271 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 13272 return StmtError(); 13273 13274 SemaRef.setFunctionHasBranchProtectedScope(); 13275 return OMPTaskLoopSimdDirective::Create(getASTContext(), StartLoc, EndLoc, 13276 NestedLoopCount, Clauses, AStmt, B); 13277 } 13278 13279 StmtResult SemaOpenMP::ActOnOpenMPMasterTaskLoopDirective( 13280 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13281 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13282 if (!AStmt) 13283 return StmtError(); 13284 13285 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 13286 OMPLoopBasedDirective::HelperExprs B; 13287 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 13288 // define the nested loops number. 13289 unsigned NestedLoopCount = 13290 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses), 13291 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef, 13292 *DSAStack, VarsWithImplicitDSA, B); 13293 if (NestedLoopCount == 0) 13294 return StmtError(); 13295 13296 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 13297 "omp for loop exprs were not built"); 13298 13299 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13300 // The grainsize clause and num_tasks clause are mutually exclusive and may 13301 // not appear on the same taskloop directive. 13302 if (checkMutuallyExclusiveClauses(SemaRef, Clauses, 13303 {OMPC_grainsize, OMPC_num_tasks})) 13304 return StmtError(); 13305 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13306 // If a reduction clause is present on the taskloop directive, the nogroup 13307 // clause must not be specified. 13308 if (checkReductionClauseWithNogroup(SemaRef, Clauses)) 13309 return StmtError(); 13310 13311 SemaRef.setFunctionHasBranchProtectedScope(); 13312 return OMPMasterTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc, 13313 NestedLoopCount, Clauses, AStmt, B, 13314 DSAStack->isCancelRegion()); 13315 } 13316 13317 StmtResult SemaOpenMP::ActOnOpenMPMaskedTaskLoopDirective( 13318 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13319 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13320 if (!AStmt) 13321 return StmtError(); 13322 13323 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 13324 OMPLoopBasedDirective::HelperExprs B; 13325 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 13326 // define the nested loops number. 13327 unsigned NestedLoopCount = 13328 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses), 13329 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef, 13330 *DSAStack, VarsWithImplicitDSA, B); 13331 if (NestedLoopCount == 0) 13332 return StmtError(); 13333 13334 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 13335 "omp for loop exprs were not built"); 13336 13337 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13338 // The grainsize clause and num_tasks clause are mutually exclusive and may 13339 // not appear on the same taskloop directive. 13340 if (checkMutuallyExclusiveClauses(SemaRef, Clauses, 13341 {OMPC_grainsize, OMPC_num_tasks})) 13342 return StmtError(); 13343 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13344 // If a reduction clause is present on the taskloop directive, the nogroup 13345 // clause must not be specified. 13346 if (checkReductionClauseWithNogroup(SemaRef, Clauses)) 13347 return StmtError(); 13348 13349 SemaRef.setFunctionHasBranchProtectedScope(); 13350 return OMPMaskedTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc, 13351 NestedLoopCount, Clauses, AStmt, B, 13352 DSAStack->isCancelRegion()); 13353 } 13354 13355 StmtResult SemaOpenMP::ActOnOpenMPMasterTaskLoopSimdDirective( 13356 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13357 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13358 if (!AStmt) 13359 return StmtError(); 13360 13361 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 13362 OMPLoopBasedDirective::HelperExprs B; 13363 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 13364 // define the nested loops number. 13365 unsigned NestedLoopCount = 13366 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses), 13367 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef, 13368 *DSAStack, VarsWithImplicitDSA, B); 13369 if (NestedLoopCount == 0) 13370 return StmtError(); 13371 13372 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 13373 return StmtError(); 13374 13375 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13376 // The grainsize clause and num_tasks clause are mutually exclusive and may 13377 // not appear on the same taskloop directive. 13378 if (checkMutuallyExclusiveClauses(SemaRef, Clauses, 13379 {OMPC_grainsize, OMPC_num_tasks})) 13380 return StmtError(); 13381 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13382 // If a reduction clause is present on the taskloop directive, the nogroup 13383 // clause must not be specified. 13384 if (checkReductionClauseWithNogroup(SemaRef, Clauses)) 13385 return StmtError(); 13386 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 13387 return StmtError(); 13388 13389 SemaRef.setFunctionHasBranchProtectedScope(); 13390 return OMPMasterTaskLoopSimdDirective::Create( 13391 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 13392 } 13393 13394 StmtResult SemaOpenMP::ActOnOpenMPMaskedTaskLoopSimdDirective( 13395 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13396 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13397 if (!AStmt) 13398 return StmtError(); 13399 13400 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 13401 OMPLoopBasedDirective::HelperExprs B; 13402 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 13403 // define the nested loops number. 13404 unsigned NestedLoopCount = 13405 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses), 13406 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef, 13407 *DSAStack, VarsWithImplicitDSA, B); 13408 if (NestedLoopCount == 0) 13409 return StmtError(); 13410 13411 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 13412 return StmtError(); 13413 13414 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13415 // The grainsize clause and num_tasks clause are mutually exclusive and may 13416 // not appear on the same taskloop directive. 13417 if (checkMutuallyExclusiveClauses(SemaRef, Clauses, 13418 {OMPC_grainsize, OMPC_num_tasks})) 13419 return StmtError(); 13420 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13421 // If a reduction clause is present on the taskloop directive, the nogroup 13422 // clause must not be specified. 13423 if (checkReductionClauseWithNogroup(SemaRef, Clauses)) 13424 return StmtError(); 13425 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 13426 return StmtError(); 13427 13428 SemaRef.setFunctionHasBranchProtectedScope(); 13429 return OMPMaskedTaskLoopSimdDirective::Create( 13430 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 13431 } 13432 13433 StmtResult SemaOpenMP::ActOnOpenMPParallelMasterTaskLoopDirective( 13434 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13435 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13436 if (!AStmt) 13437 return StmtError(); 13438 13439 CapturedStmt *CS = 13440 setBranchProtectedScope(SemaRef, OMPD_parallel_master_taskloop, AStmt); 13441 13442 OMPLoopBasedDirective::HelperExprs B; 13443 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 13444 // define the nested loops number. 13445 unsigned NestedLoopCount = checkOpenMPLoop( 13446 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses), 13447 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack, 13448 VarsWithImplicitDSA, B); 13449 if (NestedLoopCount == 0) 13450 return StmtError(); 13451 13452 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 13453 "omp for loop exprs were not built"); 13454 13455 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13456 // The grainsize clause and num_tasks clause are mutually exclusive and may 13457 // not appear on the same taskloop directive. 13458 if (checkMutuallyExclusiveClauses(SemaRef, Clauses, 13459 {OMPC_grainsize, OMPC_num_tasks})) 13460 return StmtError(); 13461 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13462 // If a reduction clause is present on the taskloop directive, the nogroup 13463 // clause must not be specified. 13464 if (checkReductionClauseWithNogroup(SemaRef, Clauses)) 13465 return StmtError(); 13466 13467 return OMPParallelMasterTaskLoopDirective::Create( 13468 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B, 13469 DSAStack->isCancelRegion()); 13470 } 13471 13472 StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedTaskLoopDirective( 13473 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13474 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13475 if (!AStmt) 13476 return StmtError(); 13477 13478 CapturedStmt *CS = 13479 setBranchProtectedScope(SemaRef, OMPD_parallel_masked_taskloop, AStmt); 13480 13481 OMPLoopBasedDirective::HelperExprs B; 13482 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 13483 // define the nested loops number. 13484 unsigned NestedLoopCount = checkOpenMPLoop( 13485 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses), 13486 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack, 13487 VarsWithImplicitDSA, B); 13488 if (NestedLoopCount == 0) 13489 return StmtError(); 13490 13491 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 13492 "omp for loop exprs were not built"); 13493 13494 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13495 // The grainsize clause and num_tasks clause are mutually exclusive and may 13496 // not appear on the same taskloop directive. 13497 if (checkMutuallyExclusiveClauses(SemaRef, Clauses, 13498 {OMPC_grainsize, OMPC_num_tasks})) 13499 return StmtError(); 13500 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13501 // If a reduction clause is present on the taskloop directive, the nogroup 13502 // clause must not be specified. 13503 if (checkReductionClauseWithNogroup(SemaRef, Clauses)) 13504 return StmtError(); 13505 13506 return OMPParallelMaskedTaskLoopDirective::Create( 13507 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B, 13508 DSAStack->isCancelRegion()); 13509 } 13510 13511 StmtResult SemaOpenMP::ActOnOpenMPParallelMasterTaskLoopSimdDirective( 13512 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13513 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13514 if (!AStmt) 13515 return StmtError(); 13516 13517 CapturedStmt *CS = setBranchProtectedScope( 13518 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt); 13519 13520 OMPLoopBasedDirective::HelperExprs B; 13521 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 13522 // define the nested loops number. 13523 unsigned NestedLoopCount = checkOpenMPLoop( 13524 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses), 13525 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack, 13526 VarsWithImplicitDSA, B); 13527 if (NestedLoopCount == 0) 13528 return StmtError(); 13529 13530 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 13531 return StmtError(); 13532 13533 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13534 // The grainsize clause and num_tasks clause are mutually exclusive and may 13535 // not appear on the same taskloop directive. 13536 if (checkMutuallyExclusiveClauses(SemaRef, Clauses, 13537 {OMPC_grainsize, OMPC_num_tasks})) 13538 return StmtError(); 13539 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13540 // If a reduction clause is present on the taskloop directive, the nogroup 13541 // clause must not be specified. 13542 if (checkReductionClauseWithNogroup(SemaRef, Clauses)) 13543 return StmtError(); 13544 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 13545 return StmtError(); 13546 13547 return OMPParallelMasterTaskLoopSimdDirective::Create( 13548 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 13549 } 13550 13551 StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedTaskLoopSimdDirective( 13552 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13553 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13554 if (!AStmt) 13555 return StmtError(); 13556 13557 CapturedStmt *CS = setBranchProtectedScope( 13558 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt); 13559 13560 OMPLoopBasedDirective::HelperExprs B; 13561 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 13562 // define the nested loops number. 13563 unsigned NestedLoopCount = checkOpenMPLoop( 13564 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses), 13565 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack, 13566 VarsWithImplicitDSA, B); 13567 if (NestedLoopCount == 0) 13568 return StmtError(); 13569 13570 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 13571 return StmtError(); 13572 13573 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13574 // The grainsize clause and num_tasks clause are mutually exclusive and may 13575 // not appear on the same taskloop directive. 13576 if (checkMutuallyExclusiveClauses(SemaRef, Clauses, 13577 {OMPC_grainsize, OMPC_num_tasks})) 13578 return StmtError(); 13579 // OpenMP, [2.9.2 taskloop Construct, Restrictions] 13580 // If a reduction clause is present on the taskloop directive, the nogroup 13581 // clause must not be specified. 13582 if (checkReductionClauseWithNogroup(SemaRef, Clauses)) 13583 return StmtError(); 13584 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 13585 return StmtError(); 13586 13587 return OMPParallelMaskedTaskLoopSimdDirective::Create( 13588 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 13589 } 13590 13591 StmtResult SemaOpenMP::ActOnOpenMPDistributeDirective( 13592 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13593 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13594 if (!AStmt) 13595 return StmtError(); 13596 13597 if (!checkLastPrivateForMappedDirectives(Clauses)) 13598 return StmtError(); 13599 13600 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 13601 OMPLoopBasedDirective::HelperExprs B; 13602 // In presence of clause 'collapse' with number of loops, it will 13603 // define the nested loops number. 13604 unsigned NestedLoopCount = 13605 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses), 13606 nullptr /*ordered not a clause on distribute*/, AStmt, 13607 SemaRef, *DSAStack, VarsWithImplicitDSA, B); 13608 if (NestedLoopCount == 0) 13609 return StmtError(); 13610 13611 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 13612 "omp for loop exprs were not built"); 13613 13614 SemaRef.setFunctionHasBranchProtectedScope(); 13615 auto *DistributeDirective = OMPDistributeDirective::Create( 13616 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B, 13617 DSAStack->getMappedDirective()); 13618 return DistributeDirective; 13619 } 13620 13621 StmtResult SemaOpenMP::ActOnOpenMPDistributeParallelForDirective( 13622 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13623 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13624 if (!AStmt) 13625 return StmtError(); 13626 13627 CapturedStmt *CS = 13628 setBranchProtectedScope(SemaRef, OMPD_distribute_parallel_for, AStmt); 13629 13630 OMPLoopBasedDirective::HelperExprs B; 13631 // In presence of clause 'collapse' with number of loops, it will 13632 // define the nested loops number. 13633 unsigned NestedLoopCount = checkOpenMPLoop( 13634 OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses), 13635 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack, 13636 VarsWithImplicitDSA, B); 13637 if (NestedLoopCount == 0) 13638 return StmtError(); 13639 13640 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 13641 "omp for loop exprs were not built"); 13642 13643 return OMPDistributeParallelForDirective::Create( 13644 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B, 13645 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion()); 13646 } 13647 13648 StmtResult SemaOpenMP::ActOnOpenMPDistributeParallelForSimdDirective( 13649 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13650 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13651 if (!AStmt) 13652 return StmtError(); 13653 13654 CapturedStmt *CS = setBranchProtectedScope( 13655 SemaRef, OMPD_distribute_parallel_for_simd, AStmt); 13656 13657 OMPLoopBasedDirective::HelperExprs B; 13658 // In presence of clause 'collapse' with number of loops, it will 13659 // define the nested loops number. 13660 unsigned NestedLoopCount = checkOpenMPLoop( 13661 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses), 13662 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack, 13663 VarsWithImplicitDSA, B); 13664 if (NestedLoopCount == 0) 13665 return StmtError(); 13666 13667 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 13668 return StmtError(); 13669 13670 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 13671 return StmtError(); 13672 13673 return OMPDistributeParallelForSimdDirective::Create( 13674 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 13675 } 13676 13677 StmtResult SemaOpenMP::ActOnOpenMPDistributeSimdDirective( 13678 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13679 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13680 if (!AStmt) 13681 return StmtError(); 13682 13683 CapturedStmt *CS = 13684 setBranchProtectedScope(SemaRef, OMPD_distribute_simd, AStmt); 13685 13686 OMPLoopBasedDirective::HelperExprs B; 13687 // In presence of clause 'collapse' with number of loops, it will 13688 // define the nested loops number. 13689 unsigned NestedLoopCount = 13690 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses), 13691 nullptr /*ordered not a clause on distribute*/, CS, 13692 SemaRef, *DSAStack, VarsWithImplicitDSA, B); 13693 if (NestedLoopCount == 0) 13694 return StmtError(); 13695 13696 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 13697 return StmtError(); 13698 13699 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 13700 return StmtError(); 13701 13702 return OMPDistributeSimdDirective::Create(getASTContext(), StartLoc, EndLoc, 13703 NestedLoopCount, Clauses, AStmt, B); 13704 } 13705 13706 StmtResult SemaOpenMP::ActOnOpenMPTargetParallelForSimdDirective( 13707 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13708 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13709 if (!AStmt) 13710 return StmtError(); 13711 13712 CapturedStmt *CS = 13713 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for_simd, AStmt); 13714 13715 OMPLoopBasedDirective::HelperExprs B; 13716 // In presence of clause 'collapse' or 'ordered' with number of loops, it will 13717 // define the nested loops number. 13718 unsigned NestedLoopCount = checkOpenMPLoop( 13719 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses), 13720 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack, 13721 VarsWithImplicitDSA, B); 13722 if (NestedLoopCount == 0) 13723 return StmtError(); 13724 13725 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 13726 return StmtError(); 13727 13728 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 13729 return StmtError(); 13730 13731 return OMPTargetParallelForSimdDirective::Create( 13732 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 13733 } 13734 13735 StmtResult SemaOpenMP::ActOnOpenMPTargetSimdDirective( 13736 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13737 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13738 if (!AStmt) 13739 return StmtError(); 13740 13741 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target_simd, AStmt); 13742 13743 OMPLoopBasedDirective::HelperExprs B; 13744 // In presence of clause 'collapse' with number of loops, it will define the 13745 // nested loops number. 13746 unsigned NestedLoopCount = 13747 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses), 13748 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack, 13749 VarsWithImplicitDSA, B); 13750 if (NestedLoopCount == 0) 13751 return StmtError(); 13752 13753 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 13754 return StmtError(); 13755 13756 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 13757 return StmtError(); 13758 13759 return OMPTargetSimdDirective::Create(getASTContext(), StartLoc, EndLoc, 13760 NestedLoopCount, Clauses, AStmt, B); 13761 } 13762 13763 StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeDirective( 13764 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13765 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13766 if (!AStmt) 13767 return StmtError(); 13768 13769 CapturedStmt *CS = 13770 setBranchProtectedScope(SemaRef, OMPD_teams_distribute, AStmt); 13771 13772 OMPLoopBasedDirective::HelperExprs B; 13773 // In presence of clause 'collapse' with number of loops, it will 13774 // define the nested loops number. 13775 unsigned NestedLoopCount = 13776 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses), 13777 nullptr /*ordered not a clause on distribute*/, CS, 13778 SemaRef, *DSAStack, VarsWithImplicitDSA, B); 13779 if (NestedLoopCount == 0) 13780 return StmtError(); 13781 13782 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 13783 "omp teams distribute loop exprs were not built"); 13784 13785 DSAStack->setParentTeamsRegionLoc(StartLoc); 13786 13787 return OMPTeamsDistributeDirective::Create( 13788 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 13789 } 13790 13791 StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeSimdDirective( 13792 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13793 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13794 if (!AStmt) 13795 return StmtError(); 13796 13797 CapturedStmt *CS = 13798 setBranchProtectedScope(SemaRef, OMPD_teams_distribute_simd, AStmt); 13799 13800 OMPLoopBasedDirective::HelperExprs B; 13801 // In presence of clause 'collapse' with number of loops, it will 13802 // define the nested loops number. 13803 unsigned NestedLoopCount = checkOpenMPLoop( 13804 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses), 13805 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack, 13806 VarsWithImplicitDSA, B); 13807 if (NestedLoopCount == 0) 13808 return StmtError(); 13809 13810 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 13811 return StmtError(); 13812 13813 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 13814 return StmtError(); 13815 13816 DSAStack->setParentTeamsRegionLoc(StartLoc); 13817 13818 return OMPTeamsDistributeSimdDirective::Create( 13819 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 13820 } 13821 13822 StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeParallelForSimdDirective( 13823 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13824 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13825 if (!AStmt) 13826 return StmtError(); 13827 13828 CapturedStmt *CS = setBranchProtectedScope( 13829 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt); 13830 13831 OMPLoopBasedDirective::HelperExprs B; 13832 // In presence of clause 'collapse' with number of loops, it will 13833 // define the nested loops number. 13834 unsigned NestedLoopCount = checkOpenMPLoop( 13835 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses), 13836 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack, 13837 VarsWithImplicitDSA, B); 13838 if (NestedLoopCount == 0) 13839 return StmtError(); 13840 13841 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 13842 return StmtError(); 13843 13844 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 13845 return StmtError(); 13846 13847 DSAStack->setParentTeamsRegionLoc(StartLoc); 13848 13849 return OMPTeamsDistributeParallelForSimdDirective::Create( 13850 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 13851 } 13852 13853 StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeParallelForDirective( 13854 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13855 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13856 if (!AStmt) 13857 return StmtError(); 13858 13859 CapturedStmt *CS = setBranchProtectedScope( 13860 SemaRef, OMPD_teams_distribute_parallel_for, AStmt); 13861 13862 OMPLoopBasedDirective::HelperExprs B; 13863 // In presence of clause 'collapse' with number of loops, it will 13864 // define the nested loops number. 13865 unsigned NestedLoopCount = checkOpenMPLoop( 13866 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses), 13867 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack, 13868 VarsWithImplicitDSA, B); 13869 13870 if (NestedLoopCount == 0) 13871 return StmtError(); 13872 13873 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 13874 "omp for loop exprs were not built"); 13875 13876 DSAStack->setParentTeamsRegionLoc(StartLoc); 13877 13878 return OMPTeamsDistributeParallelForDirective::Create( 13879 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B, 13880 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion()); 13881 } 13882 13883 StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDirective( 13884 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13885 SourceLocation EndLoc) { 13886 if (!AStmt) 13887 return StmtError(); 13888 13889 setBranchProtectedScope(SemaRef, OMPD_target_teams, AStmt); 13890 13891 const OMPClause *BareClause = nullptr; 13892 bool HasThreadLimitAndNumTeamsClause = hasClauses(Clauses, OMPC_num_teams) && 13893 hasClauses(Clauses, OMPC_thread_limit); 13894 bool HasBareClause = llvm::any_of(Clauses, [&](const OMPClause *C) { 13895 BareClause = C; 13896 return C->getClauseKind() == OMPC_ompx_bare; 13897 }); 13898 13899 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) { 13900 Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid); 13901 return StmtError(); 13902 } 13903 13904 return OMPTargetTeamsDirective::Create(getASTContext(), StartLoc, EndLoc, 13905 Clauses, AStmt); 13906 } 13907 13908 StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeDirective( 13909 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13910 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13911 if (!AStmt) 13912 return StmtError(); 13913 13914 CapturedStmt *CS = 13915 setBranchProtectedScope(SemaRef, OMPD_target_teams_distribute, AStmt); 13916 13917 OMPLoopBasedDirective::HelperExprs B; 13918 // In presence of clause 'collapse' with number of loops, it will 13919 // define the nested loops number. 13920 unsigned NestedLoopCount = checkOpenMPLoop( 13921 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses), 13922 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack, 13923 VarsWithImplicitDSA, B); 13924 if (NestedLoopCount == 0) 13925 return StmtError(); 13926 13927 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) && 13928 "omp target teams distribute loop exprs were not built"); 13929 13930 return OMPTargetTeamsDistributeDirective::Create( 13931 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 13932 } 13933 13934 StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeParallelForDirective( 13935 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13936 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13937 if (!AStmt) 13938 return StmtError(); 13939 13940 CapturedStmt *CS = setBranchProtectedScope( 13941 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt); 13942 13943 OMPLoopBasedDirective::HelperExprs B; 13944 // In presence of clause 'collapse' with number of loops, it will 13945 // define the nested loops number. 13946 unsigned NestedLoopCount = checkOpenMPLoop( 13947 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses), 13948 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack, 13949 VarsWithImplicitDSA, B); 13950 if (NestedLoopCount == 0) 13951 return StmtError(); 13952 13953 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 13954 return StmtError(); 13955 13956 return OMPTargetTeamsDistributeParallelForDirective::Create( 13957 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B, 13958 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion()); 13959 } 13960 13961 StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective( 13962 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13963 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13964 if (!AStmt) 13965 return StmtError(); 13966 13967 CapturedStmt *CS = setBranchProtectedScope( 13968 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt); 13969 13970 OMPLoopBasedDirective::HelperExprs B; 13971 // In presence of clause 'collapse' with number of loops, it will 13972 // define the nested loops number. 13973 unsigned NestedLoopCount = 13974 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd, 13975 getCollapseNumberExpr(Clauses), 13976 nullptr /*ordered not a clause on distribute*/, CS, 13977 SemaRef, *DSAStack, VarsWithImplicitDSA, B); 13978 if (NestedLoopCount == 0) 13979 return StmtError(); 13980 13981 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 13982 return StmtError(); 13983 13984 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 13985 return StmtError(); 13986 13987 return OMPTargetTeamsDistributeParallelForSimdDirective::Create( 13988 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 13989 } 13990 13991 StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeSimdDirective( 13992 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 13993 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { 13994 if (!AStmt) 13995 return StmtError(); 13996 13997 CapturedStmt *CS = setBranchProtectedScope( 13998 SemaRef, OMPD_target_teams_distribute_simd, AStmt); 13999 14000 OMPLoopBasedDirective::HelperExprs B; 14001 // In presence of clause 'collapse' with number of loops, it will 14002 // define the nested loops number. 14003 unsigned NestedLoopCount = checkOpenMPLoop( 14004 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses), 14005 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack, 14006 VarsWithImplicitDSA, B); 14007 if (NestedLoopCount == 0) 14008 return StmtError(); 14009 14010 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack)) 14011 return StmtError(); 14012 14013 if (checkSimdlenSafelenSpecified(SemaRef, Clauses)) 14014 return StmtError(); 14015 14016 return OMPTargetTeamsDistributeSimdDirective::Create( 14017 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 14018 } 14019 14020 bool SemaOpenMP::checkTransformableLoopNest( 14021 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops, 14022 SmallVectorImpl<OMPLoopBasedDirective::HelperExprs> &LoopHelpers, 14023 Stmt *&Body, SmallVectorImpl<SmallVector<Stmt *, 0>> &OriginalInits) { 14024 OriginalInits.emplace_back(); 14025 bool Result = OMPLoopBasedDirective::doForAllLoops( 14026 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops, 14027 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt, 14028 Stmt *CurStmt) { 14029 VarsWithInheritedDSAType TmpDSA; 14030 unsigned SingleNumLoops = 14031 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack, 14032 TmpDSA, LoopHelpers[Cnt]); 14033 if (SingleNumLoops == 0) 14034 return true; 14035 assert(SingleNumLoops == 1 && "Expect single loop iteration space"); 14036 if (auto *For = dyn_cast<ForStmt>(CurStmt)) { 14037 OriginalInits.back().push_back(For->getInit()); 14038 Body = For->getBody(); 14039 } else { 14040 assert(isa<CXXForRangeStmt>(CurStmt) && 14041 "Expected canonical for or range-based for loops."); 14042 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt); 14043 OriginalInits.back().push_back(CXXFor->getBeginStmt()); 14044 Body = CXXFor->getBody(); 14045 } 14046 OriginalInits.emplace_back(); 14047 return false; 14048 }, 14049 [&OriginalInits](OMPLoopBasedDirective *Transform) { 14050 Stmt *DependentPreInits; 14051 if (auto *Dir = dyn_cast<OMPTileDirective>(Transform)) 14052 DependentPreInits = Dir->getPreInits(); 14053 else if (auto *Dir = dyn_cast<OMPUnrollDirective>(Transform)) 14054 DependentPreInits = Dir->getPreInits(); 14055 else if (auto *Dir = dyn_cast<OMPReverseDirective>(Transform)) 14056 DependentPreInits = Dir->getPreInits(); 14057 else if (auto *Dir = dyn_cast<OMPInterchangeDirective>(Transform)) 14058 DependentPreInits = Dir->getPreInits(); 14059 else 14060 llvm_unreachable("Unhandled loop transformation"); 14061 14062 appendFlattenedStmtList(OriginalInits.back(), DependentPreInits); 14063 }); 14064 assert(OriginalInits.back().empty() && "No preinit after innermost loop"); 14065 OriginalInits.pop_back(); 14066 return Result; 14067 } 14068 14069 /// Add preinit statements that need to be propageted from the selected loop. 14070 static void addLoopPreInits(ASTContext &Context, 14071 OMPLoopBasedDirective::HelperExprs &LoopHelper, 14072 Stmt *LoopStmt, ArrayRef<Stmt *> OriginalInit, 14073 SmallVectorImpl<Stmt *> &PreInits) { 14074 14075 // For range-based for-statements, ensure that their syntactic sugar is 14076 // executed by adding them as pre-init statements. 14077 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) { 14078 Stmt *RangeInit = CXXRangeFor->getInit(); 14079 if (RangeInit) 14080 PreInits.push_back(RangeInit); 14081 14082 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt(); 14083 PreInits.push_back(new (Context) DeclStmt(RangeStmt->getDeclGroup(), 14084 RangeStmt->getBeginLoc(), 14085 RangeStmt->getEndLoc())); 14086 14087 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt(); 14088 PreInits.push_back(new (Context) DeclStmt(RangeEnd->getDeclGroup(), 14089 RangeEnd->getBeginLoc(), 14090 RangeEnd->getEndLoc())); 14091 } 14092 14093 llvm::append_range(PreInits, OriginalInit); 14094 14095 // List of OMPCapturedExprDecl, for __begin, __end, and NumIterations 14096 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits)) { 14097 PreInits.push_back(new (Context) DeclStmt( 14098 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc())); 14099 } 14100 14101 // Gather declarations for the data members used as counters. 14102 for (Expr *CounterRef : LoopHelper.Counters) { 14103 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl(); 14104 if (isa<OMPCapturedExprDecl>(CounterDecl)) 14105 PreInits.push_back(new (Context) DeclStmt( 14106 DeclGroupRef(CounterDecl), SourceLocation(), SourceLocation())); 14107 } 14108 } 14109 14110 /// Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected 14111 /// loop of a construct. 14112 static void collectLoopStmts(Stmt *AStmt, MutableArrayRef<Stmt *> LoopStmts) { 14113 size_t NumLoops = LoopStmts.size(); 14114 OMPLoopBasedDirective::doForAllLoops( 14115 AStmt, /*TryImperfectlyNestedLoops=*/false, NumLoops, 14116 [LoopStmts](unsigned Cnt, Stmt *CurStmt) { 14117 assert(!LoopStmts[Cnt] && "Loop statement must not yet be assigned"); 14118 LoopStmts[Cnt] = CurStmt; 14119 return false; 14120 }); 14121 assert(!is_contained(LoopStmts, nullptr) && 14122 "Expecting a loop statement for each affected loop"); 14123 } 14124 14125 StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef<OMPClause *> Clauses, 14126 Stmt *AStmt, 14127 SourceLocation StartLoc, 14128 SourceLocation EndLoc) { 14129 ASTContext &Context = getASTContext(); 14130 Scope *CurScope = SemaRef.getCurScope(); 14131 14132 const auto *SizesClause = 14133 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses); 14134 if (!SizesClause || 14135 llvm::any_of(SizesClause->getSizesRefs(), [](Expr *E) { return !E; })) 14136 return StmtError(); 14137 unsigned NumLoops = SizesClause->getNumSizes(); 14138 14139 // Empty statement should only be possible if there already was an error. 14140 if (!AStmt) 14141 return StmtError(); 14142 14143 // Verify and diagnose loop nest. 14144 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops); 14145 Stmt *Body = nullptr; 14146 SmallVector<SmallVector<Stmt *, 0>, 4> OriginalInits; 14147 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body, 14148 OriginalInits)) 14149 return StmtError(); 14150 14151 // Delay tiling to when template is completely instantiated. 14152 if (SemaRef.CurContext->isDependentContext()) 14153 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, 14154 NumLoops, AStmt, nullptr, nullptr); 14155 14156 assert(LoopHelpers.size() == NumLoops && 14157 "Expecting loop iteration space dimensionality to match number of " 14158 "affected loops"); 14159 assert(OriginalInits.size() == NumLoops && 14160 "Expecting loop iteration space dimensionality to match number of " 14161 "affected loops"); 14162 14163 // Collect all affected loop statements. 14164 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr); 14165 collectLoopStmts(AStmt, LoopStmts); 14166 14167 SmallVector<Stmt *, 4> PreInits; 14168 CaptureVars CopyTransformer(SemaRef); 14169 14170 // Create iteration variables for the generated loops. 14171 SmallVector<VarDecl *, 4> FloorIndVars; 14172 SmallVector<VarDecl *, 4> TileIndVars; 14173 FloorIndVars.resize(NumLoops); 14174 TileIndVars.resize(NumLoops); 14175 for (unsigned I = 0; I < NumLoops; ++I) { 14176 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I]; 14177 14178 assert(LoopHelper.Counters.size() == 1 && 14179 "Expect single-dimensional loop iteration space"); 14180 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front()); 14181 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString(); 14182 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef); 14183 QualType CntTy = IterVarRef->getType(); 14184 14185 // Iteration variable for the floor (i.e. outer) loop. 14186 { 14187 std::string FloorCntName = 14188 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str(); 14189 VarDecl *FloorCntDecl = 14190 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar); 14191 FloorIndVars[I] = FloorCntDecl; 14192 } 14193 14194 // Iteration variable for the tile (i.e. inner) loop. 14195 { 14196 std::string TileCntName = 14197 (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str(); 14198 14199 // Reuse the iteration variable created by checkOpenMPLoop. It is also 14200 // used by the expressions to derive the original iteration variable's 14201 // value from the logical iteration number. 14202 auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl()); 14203 TileCntDecl->setDeclName( 14204 &SemaRef.PP.getIdentifierTable().get(TileCntName)); 14205 TileIndVars[I] = TileCntDecl; 14206 } 14207 14208 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I], 14209 PreInits); 14210 } 14211 14212 // Once the original iteration values are set, append the innermost body. 14213 Stmt *Inner = Body; 14214 14215 auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context, 14216 SizesClause, CurScope](int I) -> Expr * { 14217 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I]; 14218 if (isa<ConstantExpr>(DimTileSizeExpr)) 14219 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)); 14220 14221 // When the tile size is not a constant but a variable, it is possible to 14222 // pass non-positive numbers. For instance: 14223 // \code{c} 14224 // int a = 0; 14225 // #pragma omp tile sizes(a) 14226 // for (int i = 0; i < 42; ++i) 14227 // body(i); 14228 // \endcode 14229 // Although there is no meaningful interpretation of the tile size, the body 14230 // should still be executed 42 times to avoid surprises. To preserve the 14231 // invariant that every loop iteration is executed exactly once and not 14232 // cause an infinite loop, apply a minimum tile size of one. 14233 // Build expr: 14234 // \code{c} 14235 // (TS <= 0) ? 1 : TS 14236 // \endcode 14237 QualType DimTy = DimTileSizeExpr->getType(); 14238 uint64_t DimWidth = Context.getTypeSize(DimTy); 14239 IntegerLiteral *Zero = IntegerLiteral::Create( 14240 Context, llvm::APInt::getZero(DimWidth), DimTy, {}); 14241 IntegerLiteral *One = 14242 IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {}); 14243 Expr *Cond = AssertSuccess(SemaRef.BuildBinOp( 14244 CurScope, {}, BO_LE, 14245 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero)); 14246 Expr *MinOne = new (Context) ConditionalOperator( 14247 Cond, {}, One, {}, 14248 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy, 14249 VK_PRValue, OK_Ordinary); 14250 return MinOne; 14251 }; 14252 14253 // Create tile loops from the inside to the outside. 14254 for (int I = NumLoops - 1; I >= 0; --I) { 14255 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I]; 14256 Expr *NumIterations = LoopHelper.NumIterations; 14257 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]); 14258 QualType IVTy = NumIterations->getType(); 14259 Stmt *LoopStmt = LoopStmts[I]; 14260 14261 // Commonly used variables. One of the constraints of an AST is that every 14262 // node object must appear at most once, hence we define lamdas that create 14263 // a new AST node at every use. 14264 auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, IVTy, 14265 OrigCntVar]() { 14266 return buildDeclRefExpr(SemaRef, TileIndVars[I], IVTy, 14267 OrigCntVar->getExprLoc()); 14268 }; 14269 auto MakeFloorIVRef = [&SemaRef = this->SemaRef, &FloorIndVars, I, IVTy, 14270 OrigCntVar]() { 14271 return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy, 14272 OrigCntVar->getExprLoc()); 14273 }; 14274 14275 // For init-statement: auto .tile.iv = .floor.iv 14276 SemaRef.AddInitializerToDecl( 14277 TileIndVars[I], SemaRef.DefaultLvalueConversion(MakeFloorIVRef()).get(), 14278 /*DirectInit=*/false); 14279 Decl *CounterDecl = TileIndVars[I]; 14280 StmtResult InitStmt = new (Context) 14281 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1), 14282 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc()); 14283 if (!InitStmt.isUsable()) 14284 return StmtError(); 14285 14286 // For cond-expression: 14287 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations) 14288 ExprResult EndOfTile = 14289 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add, 14290 MakeFloorIVRef(), MakeDimTileSize(I)); 14291 if (!EndOfTile.isUsable()) 14292 return StmtError(); 14293 ExprResult IsPartialTile = 14294 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, 14295 NumIterations, EndOfTile.get()); 14296 if (!IsPartialTile.isUsable()) 14297 return StmtError(); 14298 ExprResult MinTileAndIterSpace = SemaRef.ActOnConditionalOp( 14299 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(), 14300 IsPartialTile.get(), NumIterations, EndOfTile.get()); 14301 if (!MinTileAndIterSpace.isUsable()) 14302 return StmtError(); 14303 ExprResult CondExpr = 14304 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, 14305 MakeTileIVRef(), MinTileAndIterSpace.get()); 14306 if (!CondExpr.isUsable()) 14307 return StmtError(); 14308 14309 // For incr-statement: ++.tile.iv 14310 ExprResult IncrStmt = SemaRef.BuildUnaryOp( 14311 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef()); 14312 if (!IncrStmt.isUsable()) 14313 return StmtError(); 14314 14315 // Statements to set the original iteration variable's value from the 14316 // logical iteration number. 14317 // Generated for loop is: 14318 // \code 14319 // Original_for_init; 14320 // for (auto .tile.iv = .floor.iv; 14321 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations); 14322 // ++.tile.iv) { 14323 // Original_Body; 14324 // Original_counter_update; 14325 // } 14326 // \endcode 14327 // FIXME: If the innermost body is an loop itself, inserting these 14328 // statements stops it being recognized as a perfectly nested loop (e.g. 14329 // for applying tiling again). If this is the case, sink the expressions 14330 // further into the inner loop. 14331 SmallVector<Stmt *, 4> BodyParts; 14332 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end()); 14333 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) 14334 BodyParts.push_back(SourceCXXFor->getLoopVarStmt()); 14335 BodyParts.push_back(Inner); 14336 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(), 14337 Inner->getBeginLoc(), Inner->getEndLoc()); 14338 Inner = new (Context) 14339 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr, 14340 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(), 14341 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc()); 14342 } 14343 14344 // Create floor loops from the inside to the outside. 14345 for (int I = NumLoops - 1; I >= 0; --I) { 14346 auto &LoopHelper = LoopHelpers[I]; 14347 Expr *NumIterations = LoopHelper.NumIterations; 14348 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]); 14349 QualType IVTy = NumIterations->getType(); 14350 14351 // Commonly used variables. One of the constraints of an AST is that every 14352 // node object must appear at most once, hence we define lamdas that create 14353 // a new AST node at every use. 14354 auto MakeFloorIVRef = [&SemaRef = this->SemaRef, &FloorIndVars, I, IVTy, 14355 OrigCntVar]() { 14356 return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy, 14357 OrigCntVar->getExprLoc()); 14358 }; 14359 14360 // For init-statement: auto .floor.iv = 0 14361 SemaRef.AddInitializerToDecl( 14362 FloorIndVars[I], 14363 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(), 14364 /*DirectInit=*/false); 14365 Decl *CounterDecl = FloorIndVars[I]; 14366 StmtResult InitStmt = new (Context) 14367 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1), 14368 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc()); 14369 if (!InitStmt.isUsable()) 14370 return StmtError(); 14371 14372 // For cond-expression: .floor.iv < NumIterations 14373 ExprResult CondExpr = 14374 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, 14375 MakeFloorIVRef(), NumIterations); 14376 if (!CondExpr.isUsable()) 14377 return StmtError(); 14378 14379 // For incr-statement: .floor.iv += DimTileSize 14380 ExprResult IncrStmt = 14381 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign, 14382 MakeFloorIVRef(), MakeDimTileSize(I)); 14383 if (!IncrStmt.isUsable()) 14384 return StmtError(); 14385 14386 Inner = new (Context) 14387 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr, 14388 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(), 14389 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc()); 14390 } 14391 14392 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops, 14393 AStmt, Inner, 14394 buildPreInits(Context, PreInits)); 14395 } 14396 14397 StmtResult SemaOpenMP::ActOnOpenMPUnrollDirective(ArrayRef<OMPClause *> Clauses, 14398 Stmt *AStmt, 14399 SourceLocation StartLoc, 14400 SourceLocation EndLoc) { 14401 ASTContext &Context = getASTContext(); 14402 Scope *CurScope = SemaRef.getCurScope(); 14403 // Empty statement should only be possible if there already was an error. 14404 if (!AStmt) 14405 return StmtError(); 14406 14407 if (checkMutuallyExclusiveClauses(SemaRef, Clauses, 14408 {OMPC_partial, OMPC_full})) 14409 return StmtError(); 14410 14411 const OMPFullClause *FullClause = 14412 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses); 14413 const OMPPartialClause *PartialClause = 14414 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses); 14415 assert(!(FullClause && PartialClause) && 14416 "mutual exclusivity must have been checked before"); 14417 14418 constexpr unsigned NumLoops = 1; 14419 Stmt *Body = nullptr; 14420 SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers( 14421 NumLoops); 14422 SmallVector<SmallVector<Stmt *, 0>, NumLoops + 1> OriginalInits; 14423 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers, 14424 Body, OriginalInits)) 14425 return StmtError(); 14426 14427 unsigned NumGeneratedLoops = PartialClause ? 1 : 0; 14428 14429 // Delay unrolling to when template is completely instantiated. 14430 if (SemaRef.CurContext->isDependentContext()) 14431 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt, 14432 NumGeneratedLoops, nullptr, nullptr); 14433 14434 assert(LoopHelpers.size() == NumLoops && 14435 "Expecting a single-dimensional loop iteration space"); 14436 assert(OriginalInits.size() == NumLoops && 14437 "Expecting a single-dimensional loop iteration space"); 14438 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front(); 14439 14440 if (FullClause) { 14441 if (!VerifyPositiveIntegerConstantInClause( 14442 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false, 14443 /*SuppressExprDiags=*/true) 14444 .isUsable()) { 14445 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count); 14446 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here) 14447 << "#pragma omp unroll full"; 14448 return StmtError(); 14449 } 14450 } 14451 14452 // The generated loop may only be passed to other loop-associated directive 14453 // when a partial clause is specified. Without the requirement it is 14454 // sufficient to generate loop unroll metadata at code-generation. 14455 if (NumGeneratedLoops == 0) 14456 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt, 14457 NumGeneratedLoops, nullptr, nullptr); 14458 14459 // Otherwise, we need to provide a de-sugared/transformed AST that can be 14460 // associated with another loop directive. 14461 // 14462 // The canonical loop analysis return by checkTransformableLoopNest assumes 14463 // the following structure to be the same loop without transformations or 14464 // directives applied: \code OriginalInits; LoopHelper.PreInits; 14465 // LoopHelper.Counters; 14466 // for (; IV < LoopHelper.NumIterations; ++IV) { 14467 // LoopHelper.Updates; 14468 // Body; 14469 // } 14470 // \endcode 14471 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits 14472 // and referenced by LoopHelper.IterationVarRef. 14473 // 14474 // The unrolling directive transforms this into the following loop: 14475 // \code 14476 // OriginalInits; \ 14477 // LoopHelper.PreInits; > NewPreInits 14478 // LoopHelper.Counters; / 14479 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) { 14480 // #pragma clang loop unroll_count(Factor) 14481 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV) 14482 // { 14483 // LoopHelper.Updates; 14484 // Body; 14485 // } 14486 // } 14487 // \endcode 14488 // where UIV is a new logical iteration counter. IV must be the same VarDecl 14489 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates 14490 // references it. If the partially unrolled loop is associated with another 14491 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to 14492 // analyze this loop, i.e. the outer loop must fulfill the constraints of an 14493 // OpenMP canonical loop. The inner loop is not an associable canonical loop 14494 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of 14495 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a 14496 // property of the OMPLoopBasedDirective instead of statements in 14497 // CompoundStatement. This is to allow the loop to become a non-outermost loop 14498 // of a canonical loop nest where these PreInits are emitted before the 14499 // outermost directive. 14500 14501 // Find the loop statement. 14502 Stmt *LoopStmt = nullptr; 14503 collectLoopStmts(AStmt, {LoopStmt}); 14504 14505 // Determine the PreInit declarations. 14506 SmallVector<Stmt *, 4> PreInits; 14507 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits); 14508 14509 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef); 14510 QualType IVTy = IterationVarRef->getType(); 14511 assert(LoopHelper.Counters.size() == 1 && 14512 "Expecting a single-dimensional loop iteration space"); 14513 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front()); 14514 14515 // Determine the unroll factor. 14516 uint64_t Factor; 14517 SourceLocation FactorLoc; 14518 if (Expr *FactorVal = PartialClause->getFactor()) { 14519 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue(); 14520 FactorLoc = FactorVal->getExprLoc(); 14521 } else { 14522 // TODO: Use a better profitability model. 14523 Factor = 2; 14524 } 14525 assert(Factor > 0 && "Expected positive unroll factor"); 14526 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() { 14527 return IntegerLiteral::Create( 14528 getASTContext(), llvm::APInt(getASTContext().getIntWidth(IVTy), Factor), 14529 IVTy, FactorLoc); 14530 }; 14531 14532 // Iteration variable SourceLocations. 14533 SourceLocation OrigVarLoc = OrigVar->getExprLoc(); 14534 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc(); 14535 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc(); 14536 14537 // Internal variable names. 14538 std::string OrigVarName = OrigVar->getNameInfo().getAsString(); 14539 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str(); 14540 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str(); 14541 std::string InnerTripCountName = 14542 (Twine(".unroll_inner.tripcount.") + OrigVarName).str(); 14543 14544 // Create the iteration variable for the unrolled loop. 14545 VarDecl *OuterIVDecl = 14546 buildVarDecl(SemaRef, {}, IVTy, OuterIVName, nullptr, OrigVar); 14547 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() { 14548 return buildDeclRefExpr(SemaRef, OuterIVDecl, IVTy, OrigVarLoc); 14549 }; 14550 14551 // Iteration variable for the inner loop: Reuse the iteration variable created 14552 // by checkOpenMPLoop. 14553 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl()); 14554 InnerIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(InnerIVName)); 14555 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() { 14556 return buildDeclRefExpr(SemaRef, InnerIVDecl, IVTy, OrigVarLoc); 14557 }; 14558 14559 // Make a copy of the NumIterations expression for each use: By the AST 14560 // constraints, every expression object in a DeclContext must be unique. 14561 CaptureVars CopyTransformer(SemaRef); 14562 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * { 14563 return AssertSuccess( 14564 CopyTransformer.TransformExpr(LoopHelper.NumIterations)); 14565 }; 14566 14567 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv 14568 ExprResult LValueConv = SemaRef.DefaultLvalueConversion(MakeOuterRef()); 14569 SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.get(), 14570 /*DirectInit=*/false); 14571 StmtResult InnerInit = new (Context) 14572 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd); 14573 if (!InnerInit.isUsable()) 14574 return StmtError(); 14575 14576 // Inner For cond-expression: 14577 // \code 14578 // .unroll_inner.iv < .unrolled.iv + Factor && 14579 // .unroll_inner.iv < NumIterations 14580 // \endcode 14581 // This conjunction of two conditions allows ScalarEvolution to derive the 14582 // maximum trip count of the inner loop. 14583 ExprResult EndOfTile = 14584 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add, 14585 MakeOuterRef(), MakeFactorExpr()); 14586 if (!EndOfTile.isUsable()) 14587 return StmtError(); 14588 ExprResult InnerCond1 = 14589 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, 14590 MakeInnerRef(), EndOfTile.get()); 14591 if (!InnerCond1.isUsable()) 14592 return StmtError(); 14593 ExprResult InnerCond2 = 14594 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, 14595 MakeInnerRef(), MakeNumIterations()); 14596 if (!InnerCond2.isUsable()) 14597 return StmtError(); 14598 ExprResult InnerCond = 14599 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd, 14600 InnerCond1.get(), InnerCond2.get()); 14601 if (!InnerCond.isUsable()) 14602 return StmtError(); 14603 14604 // Inner For incr-statement: ++.unroll_inner.iv 14605 ExprResult InnerIncr = SemaRef.BuildUnaryOp( 14606 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef()); 14607 if (!InnerIncr.isUsable()) 14608 return StmtError(); 14609 14610 // Inner For statement. 14611 SmallVector<Stmt *> InnerBodyStmts; 14612 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end()); 14613 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) 14614 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt()); 14615 InnerBodyStmts.push_back(Body); 14616 CompoundStmt *InnerBody = 14617 CompoundStmt::Create(getASTContext(), InnerBodyStmts, FPOptionsOverride(), 14618 Body->getBeginLoc(), Body->getEndLoc()); 14619 ForStmt *InnerFor = new (Context) 14620 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr, 14621 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(), 14622 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc()); 14623 14624 // Unroll metadata for the inner loop. 14625 // This needs to take into account the remainder portion of the unrolled loop, 14626 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass 14627 // supports multiple loop exits. Instead, unroll using a factor equivalent to 14628 // the maximum trip count, which will also generate a remainder loop. Just 14629 // `unroll(enable)` (which could have been useful if the user has not 14630 // specified a concrete factor; even though the outer loop cannot be 14631 // influenced anymore, would avoid more code bloat than necessary) will refuse 14632 // the loop because "Won't unroll; remainder loop could not be generated when 14633 // assuming runtime trip count". Even if it did work, it must not choose a 14634 // larger unroll factor than the maximum loop length, or it would always just 14635 // execute the remainder loop. 14636 LoopHintAttr *UnrollHintAttr = 14637 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount, 14638 LoopHintAttr::Numeric, MakeFactorExpr()); 14639 AttributedStmt *InnerUnrolled = AttributedStmt::Create( 14640 getASTContext(), StartLoc, {UnrollHintAttr}, InnerFor); 14641 14642 // Outer For init-statement: auto .unrolled.iv = 0 14643 SemaRef.AddInitializerToDecl( 14644 OuterIVDecl, 14645 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(), 14646 /*DirectInit=*/false); 14647 StmtResult OuterInit = new (Context) 14648 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd); 14649 if (!OuterInit.isUsable()) 14650 return StmtError(); 14651 14652 // Outer For cond-expression: .unrolled.iv < NumIterations 14653 ExprResult OuterConde = 14654 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, 14655 MakeOuterRef(), MakeNumIterations()); 14656 if (!OuterConde.isUsable()) 14657 return StmtError(); 14658 14659 // Outer For incr-statement: .unrolled.iv += Factor 14660 ExprResult OuterIncr = 14661 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign, 14662 MakeOuterRef(), MakeFactorExpr()); 14663 if (!OuterIncr.isUsable()) 14664 return StmtError(); 14665 14666 // Outer For statement. 14667 ForStmt *OuterFor = new (Context) 14668 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr, 14669 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(), 14670 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc()); 14671 14672 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt, 14673 NumGeneratedLoops, OuterFor, 14674 buildPreInits(Context, PreInits)); 14675 } 14676 14677 StmtResult SemaOpenMP::ActOnOpenMPReverseDirective(Stmt *AStmt, 14678 SourceLocation StartLoc, 14679 SourceLocation EndLoc) { 14680 ASTContext &Context = getASTContext(); 14681 Scope *CurScope = SemaRef.getCurScope(); 14682 14683 // Empty statement should only be possible if there already was an error. 14684 if (!AStmt) 14685 return StmtError(); 14686 14687 constexpr unsigned NumLoops = 1; 14688 Stmt *Body = nullptr; 14689 SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers( 14690 NumLoops); 14691 SmallVector<SmallVector<Stmt *, 0>, NumLoops + 1> OriginalInits; 14692 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers, 14693 Body, OriginalInits)) 14694 return StmtError(); 14695 14696 // Delay applying the transformation to when template is completely 14697 // instantiated. 14698 if (SemaRef.CurContext->isDependentContext()) 14699 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt, 14700 nullptr, nullptr); 14701 14702 assert(LoopHelpers.size() == NumLoops && 14703 "Expecting a single-dimensional loop iteration space"); 14704 assert(OriginalInits.size() == NumLoops && 14705 "Expecting a single-dimensional loop iteration space"); 14706 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front(); 14707 14708 // Find the loop statement. 14709 Stmt *LoopStmt = nullptr; 14710 collectLoopStmts(AStmt, {LoopStmt}); 14711 14712 // Determine the PreInit declarations. 14713 SmallVector<Stmt *> PreInits; 14714 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits); 14715 14716 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef); 14717 QualType IVTy = IterationVarRef->getType(); 14718 uint64_t IVWidth = Context.getTypeSize(IVTy); 14719 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front()); 14720 14721 // Iteration variable SourceLocations. 14722 SourceLocation OrigVarLoc = OrigVar->getExprLoc(); 14723 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc(); 14724 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc(); 14725 14726 // Locations pointing to the transformation. 14727 SourceLocation TransformLoc = StartLoc; 14728 SourceLocation TransformLocBegin = StartLoc; 14729 SourceLocation TransformLocEnd = EndLoc; 14730 14731 // Internal variable names. 14732 std::string OrigVarName = OrigVar->getNameInfo().getAsString(); 14733 SmallString<64> ForwardIVName(".forward.iv."); 14734 ForwardIVName += OrigVarName; 14735 SmallString<64> ReversedIVName(".reversed.iv."); 14736 ReversedIVName += OrigVarName; 14737 14738 // LoopHelper.Updates will read the logical iteration number from 14739 // LoopHelper.IterationVarRef, compute the value of the user loop counter of 14740 // that logical iteration from it, then assign it to the user loop counter 14741 // variable. We cannot directly use LoopHelper.IterationVarRef as the 14742 // induction variable of the generated loop because it may cause an underflow: 14743 // \code{.c} 14744 // for (unsigned i = 0; i < n; ++i) 14745 // body(i); 14746 // \endcode 14747 // 14748 // Naive reversal: 14749 // \code{.c} 14750 // for (unsigned i = n-1; i >= 0; --i) 14751 // body(i); 14752 // \endcode 14753 // 14754 // Instead, we introduce a new iteration variable representing the logical 14755 // iteration counter of the original loop, convert it to the logical iteration 14756 // number of the reversed loop, then let LoopHelper.Updates compute the user's 14757 // loop iteration variable from it. 14758 // \code{.cpp} 14759 // for (auto .forward.iv = 0; .forward.iv < n; ++.forward.iv) { 14760 // auto .reversed.iv = n - .forward.iv - 1; 14761 // i = (.reversed.iv + 0) * 1; // LoopHelper.Updates 14762 // body(i); // Body 14763 // } 14764 // \endcode 14765 14766 // Subexpressions with more than one use. One of the constraints of an AST is 14767 // that every node object must appear at most once, hence we define a lambda 14768 // that creates a new AST node at every use. 14769 CaptureVars CopyTransformer(SemaRef); 14770 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * { 14771 return AssertSuccess( 14772 CopyTransformer.TransformExpr(LoopHelper.NumIterations)); 14773 }; 14774 14775 // Create the iteration variable for the forward loop (from 0 to n-1). 14776 VarDecl *ForwardIVDecl = 14777 buildVarDecl(SemaRef, {}, IVTy, ForwardIVName, nullptr, OrigVar); 14778 auto MakeForwardRef = [&SemaRef = this->SemaRef, ForwardIVDecl, IVTy, 14779 OrigVarLoc]() { 14780 return buildDeclRefExpr(SemaRef, ForwardIVDecl, IVTy, OrigVarLoc); 14781 }; 14782 14783 // Iteration variable for the reversed induction variable (from n-1 downto 0): 14784 // Reuse the iteration variable created by checkOpenMPLoop. 14785 auto *ReversedIVDecl = cast<VarDecl>(IterationVarRef->getDecl()); 14786 ReversedIVDecl->setDeclName( 14787 &SemaRef.PP.getIdentifierTable().get(ReversedIVName)); 14788 14789 // For init-statement: 14790 // \code{.cpp} 14791 // auto .forward.iv = 0; 14792 // \endcode 14793 auto *Zero = IntegerLiteral::Create(Context, llvm::APInt::getZero(IVWidth), 14794 ForwardIVDecl->getType(), OrigVarLoc); 14795 SemaRef.AddInitializerToDecl(ForwardIVDecl, Zero, /*DirectInit=*/false); 14796 StmtResult Init = new (Context) 14797 DeclStmt(DeclGroupRef(ForwardIVDecl), OrigVarLocBegin, OrigVarLocEnd); 14798 if (!Init.isUsable()) 14799 return StmtError(); 14800 14801 // Forward iv cond-expression: 14802 // \code{.cpp} 14803 // .forward.iv < MakeNumIterations() 14804 // \endcode 14805 ExprResult Cond = 14806 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, 14807 MakeForwardRef(), MakeNumIterations()); 14808 if (!Cond.isUsable()) 14809 return StmtError(); 14810 14811 // Forward incr-statement: 14812 // \code{.c} 14813 // ++.forward.iv 14814 // \endcode 14815 ExprResult Incr = SemaRef.BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(), 14816 UO_PreInc, MakeForwardRef()); 14817 if (!Incr.isUsable()) 14818 return StmtError(); 14819 14820 // Reverse the forward-iv: 14821 // \code{.cpp} 14822 // auto .reversed.iv = MakeNumIterations() - 1 - .forward.iv 14823 // \endcode 14824 auto *One = IntegerLiteral::Create(Context, llvm::APInt(IVWidth, 1), IVTy, 14825 TransformLoc); 14826 ExprResult Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, 14827 MakeNumIterations(), One); 14828 if (!Minus.isUsable()) 14829 return StmtError(); 14830 Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, Minus.get(), 14831 MakeForwardRef()); 14832 if (!Minus.isUsable()) 14833 return StmtError(); 14834 StmtResult InitReversed = new (Context) DeclStmt( 14835 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd); 14836 if (!InitReversed.isUsable()) 14837 return StmtError(); 14838 SemaRef.AddInitializerToDecl(ReversedIVDecl, Minus.get(), 14839 /*DirectInit=*/false); 14840 14841 // The new loop body. 14842 SmallVector<Stmt *, 4> BodyStmts; 14843 BodyStmts.reserve(LoopHelper.Updates.size() + 2 + 14844 (isa<CXXForRangeStmt>(LoopStmt) ? 1 : 0)); 14845 BodyStmts.push_back(InitReversed.get()); 14846 llvm::append_range(BodyStmts, LoopHelper.Updates); 14847 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) 14848 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt()); 14849 BodyStmts.push_back(Body); 14850 auto *ReversedBody = 14851 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(), 14852 Body->getBeginLoc(), Body->getEndLoc()); 14853 14854 // Finally create the reversed For-statement. 14855 auto *ReversedFor = new (Context) 14856 ForStmt(Context, Init.get(), Cond.get(), nullptr, Incr.get(), 14857 ReversedBody, LoopHelper.Init->getBeginLoc(), 14858 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc()); 14859 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt, 14860 ReversedFor, 14861 buildPreInits(Context, PreInits)); 14862 } 14863 14864 StmtResult SemaOpenMP::ActOnOpenMPInterchangeDirective( 14865 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 14866 SourceLocation EndLoc) { 14867 ASTContext &Context = getASTContext(); 14868 DeclContext *CurContext = SemaRef.CurContext; 14869 Scope *CurScope = SemaRef.getCurScope(); 14870 14871 // Empty statement should only be possible if there already was an error. 14872 if (!AStmt) 14873 return StmtError(); 14874 14875 // interchange without permutation clause swaps two loops. 14876 constexpr size_t NumLoops = 2; 14877 14878 // Verify and diagnose loop nest. 14879 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops); 14880 Stmt *Body = nullptr; 14881 SmallVector<SmallVector<Stmt *, 0>, 2> OriginalInits; 14882 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops, 14883 LoopHelpers, Body, OriginalInits)) 14884 return StmtError(); 14885 14886 // Delay interchange to when template is completely instantiated. 14887 if (CurContext->isDependentContext()) 14888 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses, 14889 NumLoops, AStmt, nullptr, nullptr); 14890 14891 assert(LoopHelpers.size() == NumLoops && 14892 "Expecting loop iteration space dimensionaly to match number of " 14893 "affected loops"); 14894 assert(OriginalInits.size() == NumLoops && 14895 "Expecting loop iteration space dimensionaly to match number of " 14896 "affected loops"); 14897 14898 // Decode the permutation clause. 14899 constexpr uint64_t Permutation[] = {1, 0}; 14900 14901 // Find the affected loops. 14902 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr); 14903 collectLoopStmts(AStmt, LoopStmts); 14904 14905 // Collect pre-init statements on the order before the permuation. 14906 SmallVector<Stmt *> PreInits; 14907 for (auto I : llvm::seq<int>(NumLoops)) { 14908 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I]; 14909 14910 assert(LoopHelper.Counters.size() == 1 && 14911 "Single-dimensional loop iteration space expected"); 14912 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front()); 14913 14914 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString(); 14915 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I], 14916 PreInits); 14917 } 14918 14919 SmallVector<VarDecl *> PermutedIndVars(NumLoops); 14920 CaptureVars CopyTransformer(SemaRef); 14921 14922 // Create the permuted loops from the inside to the outside of the 14923 // interchanged loop nest. Body of the innermost new loop is the original 14924 // innermost body. 14925 Stmt *Inner = Body; 14926 for (auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) { 14927 // Get the original loop that belongs to this new position. 14928 uint64_t SourceIdx = Permutation[TargetIdx]; 14929 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx]; 14930 Stmt *SourceLoopStmt = LoopStmts[SourceIdx]; 14931 assert(SourceHelper.Counters.size() == 1 && 14932 "Single-dimensional loop iteration space expected"); 14933 auto *OrigCntVar = cast<DeclRefExpr>(SourceHelper.Counters.front()); 14934 14935 // Normalized loop counter variable: From 0 to n-1, always an integer type. 14936 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(SourceHelper.IterationVarRef); 14937 QualType IVTy = IterVarRef->getType(); 14938 assert(IVTy->isIntegerType() && 14939 "Expected the logical iteration counter to be an integer"); 14940 14941 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString(); 14942 SourceLocation OrigVarLoc = IterVarRef->getExprLoc(); 14943 14944 // Make a copy of the NumIterations expression for each use: By the AST 14945 // constraints, every expression object in a DeclContext must be unique. 14946 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() -> Expr * { 14947 return AssertSuccess( 14948 CopyTransformer.TransformExpr(SourceHelper.NumIterations)); 14949 }; 14950 14951 // Iteration variable for the permuted loop. Reuse the one from 14952 // checkOpenMPLoop which will also be used to update the original loop 14953 // variable. 14954 SmallString<64> PermutedCntName(".permuted_"); 14955 PermutedCntName.append({llvm::utostr(TargetIdx), ".iv.", OrigVarName}); 14956 auto *PermutedCntDecl = cast<VarDecl>(IterVarRef->getDecl()); 14957 PermutedCntDecl->setDeclName( 14958 &SemaRef.PP.getIdentifierTable().get(PermutedCntName)); 14959 PermutedIndVars[TargetIdx] = PermutedCntDecl; 14960 auto MakePermutedRef = [this, PermutedCntDecl, IVTy, OrigVarLoc]() { 14961 return buildDeclRefExpr(SemaRef, PermutedCntDecl, IVTy, OrigVarLoc); 14962 }; 14963 14964 // For init-statement: 14965 // \code 14966 // auto .permuted_{target}.iv = 0 14967 // \endcode 14968 ExprResult Zero = SemaRef.ActOnIntegerConstant(OrigVarLoc, 0); 14969 if (!Zero.isUsable()) 14970 return StmtError(); 14971 SemaRef.AddInitializerToDecl(PermutedCntDecl, Zero.get(), 14972 /*DirectInit=*/false); 14973 StmtResult InitStmt = new (Context) 14974 DeclStmt(DeclGroupRef(PermutedCntDecl), OrigCntVar->getBeginLoc(), 14975 OrigCntVar->getEndLoc()); 14976 if (!InitStmt.isUsable()) 14977 return StmtError(); 14978 14979 // For cond-expression: 14980 // \code 14981 // .permuted_{target}.iv < MakeNumIterations() 14982 // \endcode 14983 ExprResult CondExpr = 14984 SemaRef.BuildBinOp(CurScope, SourceHelper.Cond->getExprLoc(), BO_LT, 14985 MakePermutedRef(), MakeNumIterations()); 14986 if (!CondExpr.isUsable()) 14987 return StmtError(); 14988 14989 // For incr-statement: 14990 // \code 14991 // ++.tile.iv 14992 // \endcode 14993 ExprResult IncrStmt = SemaRef.BuildUnaryOp( 14994 CurScope, SourceHelper.Inc->getExprLoc(), UO_PreInc, MakePermutedRef()); 14995 if (!IncrStmt.isUsable()) 14996 return StmtError(); 14997 14998 SmallVector<Stmt *, 4> BodyParts(SourceHelper.Updates.begin(), 14999 SourceHelper.Updates.end()); 15000 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt)) 15001 BodyParts.push_back(SourceCXXFor->getLoopVarStmt()); 15002 BodyParts.push_back(Inner); 15003 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(), 15004 Inner->getBeginLoc(), Inner->getEndLoc()); 15005 Inner = new (Context) ForStmt( 15006 Context, InitStmt.get(), CondExpr.get(), nullptr, IncrStmt.get(), Inner, 15007 SourceHelper.Init->getBeginLoc(), SourceHelper.Init->getBeginLoc(), 15008 SourceHelper.Inc->getEndLoc()); 15009 } 15010 15011 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses, 15012 NumLoops, AStmt, Inner, 15013 buildPreInits(Context, PreInits)); 15014 } 15015 15016 OMPClause *SemaOpenMP::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, 15017 Expr *Expr, 15018 SourceLocation StartLoc, 15019 SourceLocation LParenLoc, 15020 SourceLocation EndLoc) { 15021 OMPClause *Res = nullptr; 15022 switch (Kind) { 15023 case OMPC_final: 15024 Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc); 15025 break; 15026 case OMPC_num_threads: 15027 Res = ActOnOpenMPNumThreadsClause(Expr, StartLoc, LParenLoc, EndLoc); 15028 break; 15029 case OMPC_safelen: 15030 Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc); 15031 break; 15032 case OMPC_simdlen: 15033 Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc); 15034 break; 15035 case OMPC_allocator: 15036 Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc); 15037 break; 15038 case OMPC_collapse: 15039 Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc); 15040 break; 15041 case OMPC_ordered: 15042 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr); 15043 break; 15044 case OMPC_num_teams: 15045 Res = ActOnOpenMPNumTeamsClause(Expr, StartLoc, LParenLoc, EndLoc); 15046 break; 15047 case OMPC_thread_limit: 15048 Res = ActOnOpenMPThreadLimitClause(Expr, StartLoc, LParenLoc, EndLoc); 15049 break; 15050 case OMPC_priority: 15051 Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc); 15052 break; 15053 case OMPC_hint: 15054 Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc); 15055 break; 15056 case OMPC_depobj: 15057 Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc); 15058 break; 15059 case OMPC_detach: 15060 Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc); 15061 break; 15062 case OMPC_novariants: 15063 Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc); 15064 break; 15065 case OMPC_nocontext: 15066 Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc); 15067 break; 15068 case OMPC_filter: 15069 Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc); 15070 break; 15071 case OMPC_partial: 15072 Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc); 15073 break; 15074 case OMPC_message: 15075 Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc); 15076 break; 15077 case OMPC_align: 15078 Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc); 15079 break; 15080 case OMPC_ompx_dyn_cgroup_mem: 15081 Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc); 15082 break; 15083 case OMPC_grainsize: 15084 case OMPC_num_tasks: 15085 case OMPC_device: 15086 case OMPC_if: 15087 case OMPC_default: 15088 case OMPC_proc_bind: 15089 case OMPC_schedule: 15090 case OMPC_private: 15091 case OMPC_firstprivate: 15092 case OMPC_lastprivate: 15093 case OMPC_shared: 15094 case OMPC_reduction: 15095 case OMPC_task_reduction: 15096 case OMPC_in_reduction: 15097 case OMPC_linear: 15098 case OMPC_aligned: 15099 case OMPC_copyin: 15100 case OMPC_copyprivate: 15101 case OMPC_nowait: 15102 case OMPC_untied: 15103 case OMPC_mergeable: 15104 case OMPC_threadprivate: 15105 case OMPC_sizes: 15106 case OMPC_allocate: 15107 case OMPC_flush: 15108 case OMPC_read: 15109 case OMPC_write: 15110 case OMPC_update: 15111 case OMPC_capture: 15112 case OMPC_compare: 15113 case OMPC_seq_cst: 15114 case OMPC_acq_rel: 15115 case OMPC_acquire: 15116 case OMPC_release: 15117 case OMPC_relaxed: 15118 case OMPC_depend: 15119 case OMPC_threads: 15120 case OMPC_simd: 15121 case OMPC_map: 15122 case OMPC_nogroup: 15123 case OMPC_dist_schedule: 15124 case OMPC_defaultmap: 15125 case OMPC_unknown: 15126 case OMPC_uniform: 15127 case OMPC_to: 15128 case OMPC_from: 15129 case OMPC_use_device_ptr: 15130 case OMPC_use_device_addr: 15131 case OMPC_is_device_ptr: 15132 case OMPC_unified_address: 15133 case OMPC_unified_shared_memory: 15134 case OMPC_reverse_offload: 15135 case OMPC_dynamic_allocators: 15136 case OMPC_atomic_default_mem_order: 15137 case OMPC_device_type: 15138 case OMPC_match: 15139 case OMPC_nontemporal: 15140 case OMPC_order: 15141 case OMPC_at: 15142 case OMPC_severity: 15143 case OMPC_destroy: 15144 case OMPC_inclusive: 15145 case OMPC_exclusive: 15146 case OMPC_uses_allocators: 15147 case OMPC_affinity: 15148 case OMPC_when: 15149 case OMPC_bind: 15150 default: 15151 llvm_unreachable("Clause is not allowed."); 15152 } 15153 return Res; 15154 } 15155 15156 // An OpenMP directive such as 'target parallel' has two captured regions: 15157 // for the 'target' and 'parallel' respectively. This function returns 15158 // the region in which to capture expressions associated with a clause. 15159 // A return value of OMPD_unknown signifies that the expression should not 15160 // be captured. 15161 static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( 15162 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion, 15163 OpenMPDirectiveKind NameModifier = OMPD_unknown) { 15164 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) && 15165 "Invalid directive with CKind-clause"); 15166 15167 // Invalid modifier will be diagnosed separately, just return OMPD_unknown. 15168 if (NameModifier != OMPD_unknown && 15169 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion)) 15170 return OMPD_unknown; 15171 15172 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(DKind); 15173 15174 // [5.2:341:24-30] 15175 // If the clauses have expressions on them, such as for various clauses where 15176 // the argument of the clause is an expression, or lower-bound, length, or 15177 // stride expressions inside array sections (or subscript and stride 15178 // expressions in subscript-triplet for Fortran), or linear-step or alignment 15179 // expressions, the expressions are evaluated immediately before the construct 15180 // to which the clause has been split or duplicated per the above rules 15181 // (therefore inside of the outer leaf constructs). However, the expressions 15182 // inside the num_teams and thread_limit clauses are always evaluated before 15183 // the outermost leaf construct. 15184 15185 // Process special cases first. 15186 switch (CKind) { 15187 case OMPC_if: 15188 switch (DKind) { 15189 case OMPD_teams_loop: 15190 case OMPD_target_teams_loop: 15191 // For [target] teams loop, assume capture region is 'teams' so it's 15192 // available for codegen later to use if/when necessary. 15193 return OMPD_teams; 15194 case OMPD_target_update: 15195 case OMPD_target_enter_data: 15196 case OMPD_target_exit_data: 15197 return OMPD_task; 15198 default: 15199 break; 15200 } 15201 break; 15202 case OMPC_num_teams: 15203 case OMPC_thread_limit: 15204 case OMPC_ompx_dyn_cgroup_mem: 15205 if (Leafs[0] == OMPD_target) 15206 return OMPD_target; 15207 break; 15208 case OMPC_device: 15209 if (Leafs[0] == OMPD_target || 15210 llvm::is_contained({OMPD_dispatch, OMPD_target_update, 15211 OMPD_target_enter_data, OMPD_target_exit_data}, 15212 DKind)) 15213 return OMPD_task; 15214 break; 15215 case OMPC_novariants: 15216 case OMPC_nocontext: 15217 if (DKind == OMPD_dispatch) 15218 return OMPD_task; 15219 break; 15220 case OMPC_when: 15221 if (DKind == OMPD_metadirective) 15222 return OMPD_metadirective; 15223 break; 15224 case OMPC_filter: 15225 return OMPD_unknown; 15226 default: 15227 break; 15228 } 15229 15230 // If none of the special cases above applied, and DKind is a capturing 15231 // directive, find the innermost enclosing leaf construct that allows the 15232 // clause, and returns the corresponding capture region. 15233 15234 auto GetEnclosingRegion = [&](int EndIdx, OpenMPClauseKind Clause) { 15235 // Find the index in "Leafs" of the last leaf that allows the given 15236 // clause. The search will only include indexes [0, EndIdx). 15237 // EndIdx may be set to the index of the NameModifier, if present. 15238 int InnermostIdx = [&]() { 15239 for (int I = EndIdx - 1; I >= 0; --I) { 15240 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion)) 15241 return I; 15242 } 15243 return -1; 15244 }(); 15245 15246 // Find the nearest enclosing capture region. 15247 SmallVector<OpenMPDirectiveKind, 2> Regions; 15248 for (int I = InnermostIdx - 1; I >= 0; --I) { 15249 if (!isOpenMPCapturingDirective(Leafs[I])) 15250 continue; 15251 Regions.clear(); 15252 getOpenMPCaptureRegions(Regions, Leafs[I]); 15253 if (Regions[0] != OMPD_unknown) 15254 return Regions.back(); 15255 } 15256 return OMPD_unknown; 15257 }; 15258 15259 if (isOpenMPCapturingDirective(DKind)) { 15260 auto GetLeafIndex = [&](OpenMPDirectiveKind Dir) { 15261 for (int I = 0, E = Leafs.size(); I != E; ++I) { 15262 if (Leafs[I] == Dir) 15263 return I + 1; 15264 } 15265 return 0; 15266 }; 15267 15268 int End = NameModifier == OMPD_unknown ? Leafs.size() 15269 : GetLeafIndex(NameModifier); 15270 return GetEnclosingRegion(End, CKind); 15271 } 15272 15273 return OMPD_unknown; 15274 } 15275 15276 OMPClause *SemaOpenMP::ActOnOpenMPIfClause( 15277 OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc, 15278 SourceLocation LParenLoc, SourceLocation NameModifierLoc, 15279 SourceLocation ColonLoc, SourceLocation EndLoc) { 15280 Expr *ValExpr = Condition; 15281 Stmt *HelperValStmt = nullptr; 15282 OpenMPDirectiveKind CaptureRegion = OMPD_unknown; 15283 if (!Condition->isValueDependent() && !Condition->isTypeDependent() && 15284 !Condition->isInstantiationDependent() && 15285 !Condition->containsUnexpandedParameterPack()) { 15286 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition); 15287 if (Val.isInvalid()) 15288 return nullptr; 15289 15290 ValExpr = Val.get(); 15291 15292 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); 15293 CaptureRegion = getOpenMPCaptureRegionForClause( 15294 DKind, OMPC_if, getLangOpts().OpenMP, NameModifier); 15295 if (CaptureRegion != OMPD_unknown && 15296 !SemaRef.CurContext->isDependentContext()) { 15297 ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); 15298 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 15299 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); 15300 HelperValStmt = buildPreInits(getASTContext(), Captures); 15301 } 15302 } 15303 15304 return new (getASTContext()) 15305 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc, 15306 LParenLoc, NameModifierLoc, ColonLoc, EndLoc); 15307 } 15308 15309 OMPClause *SemaOpenMP::ActOnOpenMPFinalClause(Expr *Condition, 15310 SourceLocation StartLoc, 15311 SourceLocation LParenLoc, 15312 SourceLocation EndLoc) { 15313 Expr *ValExpr = Condition; 15314 Stmt *HelperValStmt = nullptr; 15315 OpenMPDirectiveKind CaptureRegion = OMPD_unknown; 15316 if (!Condition->isValueDependent() && !Condition->isTypeDependent() && 15317 !Condition->isInstantiationDependent() && 15318 !Condition->containsUnexpandedParameterPack()) { 15319 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition); 15320 if (Val.isInvalid()) 15321 return nullptr; 15322 15323 ValExpr = SemaRef.MakeFullExpr(Val.get()).get(); 15324 15325 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); 15326 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_final, 15327 getLangOpts().OpenMP); 15328 if (CaptureRegion != OMPD_unknown && 15329 !SemaRef.CurContext->isDependentContext()) { 15330 ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); 15331 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 15332 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); 15333 HelperValStmt = buildPreInits(getASTContext(), Captures); 15334 } 15335 } 15336 15337 return new (getASTContext()) OMPFinalClause( 15338 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc); 15339 } 15340 15341 ExprResult 15342 SemaOpenMP::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc, 15343 Expr *Op) { 15344 if (!Op) 15345 return ExprError(); 15346 15347 class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser { 15348 public: 15349 IntConvertDiagnoser() 15350 : ICEConvertDiagnoser(/*AllowScopedEnumerations*/ false, false, true) {} 15351 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, 15352 QualType T) override { 15353 return S.Diag(Loc, diag::err_omp_not_integral) << T; 15354 } 15355 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc, 15356 QualType T) override { 15357 return S.Diag(Loc, diag::err_omp_incomplete_type) << T; 15358 } 15359 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc, 15360 QualType T, 15361 QualType ConvTy) override { 15362 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy; 15363 } 15364 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv, 15365 QualType ConvTy) override { 15366 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here) 15367 << ConvTy->isEnumeralType() << ConvTy; 15368 } 15369 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc, 15370 QualType T) override { 15371 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T; 15372 } 15373 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv, 15374 QualType ConvTy) override { 15375 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here) 15376 << ConvTy->isEnumeralType() << ConvTy; 15377 } 15378 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType, 15379 QualType) override { 15380 llvm_unreachable("conversion functions are permitted"); 15381 } 15382 } ConvertDiagnoser; 15383 return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser); 15384 } 15385 15386 static bool 15387 isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind, 15388 bool StrictlyPositive, bool BuildCapture = false, 15389 OpenMPDirectiveKind DKind = OMPD_unknown, 15390 OpenMPDirectiveKind *CaptureRegion = nullptr, 15391 Stmt **HelperValStmt = nullptr) { 15392 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() && 15393 !ValExpr->isInstantiationDependent()) { 15394 SourceLocation Loc = ValExpr->getExprLoc(); 15395 ExprResult Value = 15396 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(Loc, ValExpr); 15397 if (Value.isInvalid()) 15398 return false; 15399 15400 ValExpr = Value.get(); 15401 // The expression must evaluate to a non-negative integer value. 15402 if (std::optional<llvm::APSInt> Result = 15403 ValExpr->getIntegerConstantExpr(SemaRef.Context)) { 15404 if (Result->isSigned() && 15405 !((!StrictlyPositive && Result->isNonNegative()) || 15406 (StrictlyPositive && Result->isStrictlyPositive()))) { 15407 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause) 15408 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0) 15409 << ValExpr->getSourceRange(); 15410 return false; 15411 } 15412 } 15413 if (!BuildCapture) 15414 return true; 15415 *CaptureRegion = 15416 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP); 15417 if (*CaptureRegion != OMPD_unknown && 15418 !SemaRef.CurContext->isDependentContext()) { 15419 ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); 15420 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 15421 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); 15422 *HelperValStmt = buildPreInits(SemaRef.Context, Captures); 15423 } 15424 } 15425 return true; 15426 } 15427 15428 OMPClause *SemaOpenMP::ActOnOpenMPNumThreadsClause(Expr *NumThreads, 15429 SourceLocation StartLoc, 15430 SourceLocation LParenLoc, 15431 SourceLocation EndLoc) { 15432 Expr *ValExpr = NumThreads; 15433 Stmt *HelperValStmt = nullptr; 15434 15435 // OpenMP [2.5, Restrictions] 15436 // The num_threads expression must evaluate to a positive integer value. 15437 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_threads, 15438 /*StrictlyPositive=*/true)) 15439 return nullptr; 15440 15441 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); 15442 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause( 15443 DKind, OMPC_num_threads, getLangOpts().OpenMP); 15444 if (CaptureRegion != OMPD_unknown && 15445 !SemaRef.CurContext->isDependentContext()) { 15446 ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); 15447 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 15448 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); 15449 HelperValStmt = buildPreInits(getASTContext(), Captures); 15450 } 15451 15452 return new (getASTContext()) OMPNumThreadsClause( 15453 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc); 15454 } 15455 15456 ExprResult SemaOpenMP::VerifyPositiveIntegerConstantInClause( 15457 Expr *E, OpenMPClauseKind CKind, bool StrictlyPositive, 15458 bool SuppressExprDiags) { 15459 if (!E) 15460 return ExprError(); 15461 if (E->isValueDependent() || E->isTypeDependent() || 15462 E->isInstantiationDependent() || E->containsUnexpandedParameterPack()) 15463 return E; 15464 15465 llvm::APSInt Result; 15466 ExprResult ICE; 15467 if (SuppressExprDiags) { 15468 // Use a custom diagnoser that suppresses 'note' diagnostics about the 15469 // expression. 15470 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser { 15471 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {} 15472 SemaBase::SemaDiagnosticBuilder 15473 diagnoseNotICE(Sema &S, SourceLocation Loc) override { 15474 llvm_unreachable("Diagnostic suppressed"); 15475 } 15476 } Diagnoser; 15477 ICE = SemaRef.VerifyIntegerConstantExpression(E, &Result, Diagnoser, 15478 Sema::AllowFold); 15479 } else { 15480 ICE = SemaRef.VerifyIntegerConstantExpression(E, &Result, 15481 /*FIXME*/ Sema::AllowFold); 15482 } 15483 if (ICE.isInvalid()) 15484 return ExprError(); 15485 15486 if ((StrictlyPositive && !Result.isStrictlyPositive()) || 15487 (!StrictlyPositive && !Result.isNonNegative())) { 15488 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause) 15489 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0) 15490 << E->getSourceRange(); 15491 return ExprError(); 15492 } 15493 if ((CKind == OMPC_aligned || CKind == OMPC_align) && !Result.isPowerOf2()) { 15494 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two) 15495 << E->getSourceRange(); 15496 return ExprError(); 15497 } 15498 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1) 15499 DSAStack->setAssociatedLoops(Result.getExtValue()); 15500 else if (CKind == OMPC_ordered) 15501 DSAStack->setAssociatedLoops(Result.getExtValue()); 15502 return ICE; 15503 } 15504 15505 OMPClause *SemaOpenMP::ActOnOpenMPSafelenClause(Expr *Len, 15506 SourceLocation StartLoc, 15507 SourceLocation LParenLoc, 15508 SourceLocation EndLoc) { 15509 // OpenMP [2.8.1, simd construct, Description] 15510 // The parameter of the safelen clause must be a constant 15511 // positive integer expression. 15512 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen); 15513 if (Safelen.isInvalid()) 15514 return nullptr; 15515 return new (getASTContext()) 15516 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc); 15517 } 15518 15519 OMPClause *SemaOpenMP::ActOnOpenMPSimdlenClause(Expr *Len, 15520 SourceLocation StartLoc, 15521 SourceLocation LParenLoc, 15522 SourceLocation EndLoc) { 15523 // OpenMP [2.8.1, simd construct, Description] 15524 // The parameter of the simdlen clause must be a constant 15525 // positive integer expression. 15526 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen); 15527 if (Simdlen.isInvalid()) 15528 return nullptr; 15529 return new (getASTContext()) 15530 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc); 15531 } 15532 15533 /// Tries to find omp_allocator_handle_t type. 15534 static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc, 15535 DSAStackTy *Stack) { 15536 if (!Stack->getOMPAllocatorHandleT().isNull()) 15537 return true; 15538 15539 // Set the allocator handle type. 15540 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t"); 15541 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope()); 15542 if (!PT.getAsOpaquePtr() || PT.get().isNull()) { 15543 S.Diag(Loc, diag::err_omp_implied_type_not_found) 15544 << "omp_allocator_handle_t"; 15545 return false; 15546 } 15547 QualType AllocatorHandleEnumTy = PT.get(); 15548 AllocatorHandleEnumTy.addConst(); 15549 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy); 15550 15551 // Fill the predefined allocator map. 15552 bool ErrorFound = false; 15553 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) { 15554 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I); 15555 StringRef Allocator = 15556 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind); 15557 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator); 15558 auto *VD = dyn_cast_or_null<ValueDecl>( 15559 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName)); 15560 if (!VD) { 15561 ErrorFound = true; 15562 break; 15563 } 15564 QualType AllocatorType = 15565 VD->getType().getNonLValueExprType(S.getASTContext()); 15566 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc); 15567 if (!Res.isUsable()) { 15568 ErrorFound = true; 15569 break; 15570 } 15571 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy, 15572 Sema::AA_Initializing, 15573 /* AllowExplicit */ true); 15574 if (!Res.isUsable()) { 15575 ErrorFound = true; 15576 break; 15577 } 15578 Stack->setAllocator(AllocatorKind, Res.get()); 15579 } 15580 if (ErrorFound) { 15581 S.Diag(Loc, diag::err_omp_implied_type_not_found) 15582 << "omp_allocator_handle_t"; 15583 return false; 15584 } 15585 15586 return true; 15587 } 15588 15589 OMPClause *SemaOpenMP::ActOnOpenMPAllocatorClause(Expr *A, 15590 SourceLocation StartLoc, 15591 SourceLocation LParenLoc, 15592 SourceLocation EndLoc) { 15593 // OpenMP [2.11.3, allocate Directive, Description] 15594 // allocator is an expression of omp_allocator_handle_t type. 15595 if (!findOMPAllocatorHandleT(SemaRef, A->getExprLoc(), DSAStack)) 15596 return nullptr; 15597 15598 ExprResult Allocator = SemaRef.DefaultLvalueConversion(A); 15599 if (Allocator.isInvalid()) 15600 return nullptr; 15601 Allocator = SemaRef.PerformImplicitConversion( 15602 Allocator.get(), DSAStack->getOMPAllocatorHandleT(), 15603 Sema::AA_Initializing, 15604 /*AllowExplicit=*/true); 15605 if (Allocator.isInvalid()) 15606 return nullptr; 15607 return new (getASTContext()) 15608 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc); 15609 } 15610 15611 OMPClause *SemaOpenMP::ActOnOpenMPCollapseClause(Expr *NumForLoops, 15612 SourceLocation StartLoc, 15613 SourceLocation LParenLoc, 15614 SourceLocation EndLoc) { 15615 // OpenMP [2.7.1, loop construct, Description] 15616 // OpenMP [2.8.1, simd construct, Description] 15617 // OpenMP [2.9.6, distribute construct, Description] 15618 // The parameter of the collapse clause must be a constant 15619 // positive integer expression. 15620 ExprResult NumForLoopsResult = 15621 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse); 15622 if (NumForLoopsResult.isInvalid()) 15623 return nullptr; 15624 return new (getASTContext()) 15625 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc); 15626 } 15627 15628 OMPClause *SemaOpenMP::ActOnOpenMPOrderedClause(SourceLocation StartLoc, 15629 SourceLocation EndLoc, 15630 SourceLocation LParenLoc, 15631 Expr *NumForLoops) { 15632 // OpenMP [2.7.1, loop construct, Description] 15633 // OpenMP [2.8.1, simd construct, Description] 15634 // OpenMP [2.9.6, distribute construct, Description] 15635 // The parameter of the ordered clause must be a constant 15636 // positive integer expression if any. 15637 if (NumForLoops && LParenLoc.isValid()) { 15638 ExprResult NumForLoopsResult = 15639 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered); 15640 if (NumForLoopsResult.isInvalid()) 15641 return nullptr; 15642 NumForLoops = NumForLoopsResult.get(); 15643 } else { 15644 NumForLoops = nullptr; 15645 } 15646 auto *Clause = 15647 OMPOrderedClause::Create(getASTContext(), NumForLoops, 15648 NumForLoops ? DSAStack->getAssociatedLoops() : 0, 15649 StartLoc, LParenLoc, EndLoc); 15650 DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause); 15651 return Clause; 15652 } 15653 15654 OMPClause *SemaOpenMP::ActOnOpenMPSimpleClause( 15655 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, 15656 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { 15657 OMPClause *Res = nullptr; 15658 switch (Kind) { 15659 case OMPC_default: 15660 Res = ActOnOpenMPDefaultClause(static_cast<DefaultKind>(Argument), 15661 ArgumentLoc, StartLoc, LParenLoc, EndLoc); 15662 break; 15663 case OMPC_proc_bind: 15664 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument), 15665 ArgumentLoc, StartLoc, LParenLoc, EndLoc); 15666 break; 15667 case OMPC_atomic_default_mem_order: 15668 Res = ActOnOpenMPAtomicDefaultMemOrderClause( 15669 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument), 15670 ArgumentLoc, StartLoc, LParenLoc, EndLoc); 15671 break; 15672 case OMPC_fail: 15673 Res = ActOnOpenMPFailClause(static_cast<OpenMPClauseKind>(Argument), 15674 ArgumentLoc, StartLoc, LParenLoc, EndLoc); 15675 break; 15676 case OMPC_update: 15677 Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument), 15678 ArgumentLoc, StartLoc, LParenLoc, EndLoc); 15679 break; 15680 case OMPC_bind: 15681 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument), 15682 ArgumentLoc, StartLoc, LParenLoc, EndLoc); 15683 break; 15684 case OMPC_at: 15685 Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument), 15686 ArgumentLoc, StartLoc, LParenLoc, EndLoc); 15687 break; 15688 case OMPC_severity: 15689 Res = ActOnOpenMPSeverityClause( 15690 static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc, 15691 LParenLoc, EndLoc); 15692 break; 15693 case OMPC_if: 15694 case OMPC_final: 15695 case OMPC_num_threads: 15696 case OMPC_safelen: 15697 case OMPC_simdlen: 15698 case OMPC_sizes: 15699 case OMPC_allocator: 15700 case OMPC_collapse: 15701 case OMPC_schedule: 15702 case OMPC_private: 15703 case OMPC_firstprivate: 15704 case OMPC_lastprivate: 15705 case OMPC_shared: 15706 case OMPC_reduction: 15707 case OMPC_task_reduction: 15708 case OMPC_in_reduction: 15709 case OMPC_linear: 15710 case OMPC_aligned: 15711 case OMPC_copyin: 15712 case OMPC_copyprivate: 15713 case OMPC_ordered: 15714 case OMPC_nowait: 15715 case OMPC_untied: 15716 case OMPC_mergeable: 15717 case OMPC_threadprivate: 15718 case OMPC_allocate: 15719 case OMPC_flush: 15720 case OMPC_depobj: 15721 case OMPC_read: 15722 case OMPC_write: 15723 case OMPC_capture: 15724 case OMPC_compare: 15725 case OMPC_seq_cst: 15726 case OMPC_acq_rel: 15727 case OMPC_acquire: 15728 case OMPC_release: 15729 case OMPC_relaxed: 15730 case OMPC_depend: 15731 case OMPC_device: 15732 case OMPC_threads: 15733 case OMPC_simd: 15734 case OMPC_map: 15735 case OMPC_num_teams: 15736 case OMPC_thread_limit: 15737 case OMPC_priority: 15738 case OMPC_grainsize: 15739 case OMPC_nogroup: 15740 case OMPC_num_tasks: 15741 case OMPC_hint: 15742 case OMPC_dist_schedule: 15743 case OMPC_defaultmap: 15744 case OMPC_unknown: 15745 case OMPC_uniform: 15746 case OMPC_to: 15747 case OMPC_from: 15748 case OMPC_use_device_ptr: 15749 case OMPC_use_device_addr: 15750 case OMPC_is_device_ptr: 15751 case OMPC_has_device_addr: 15752 case OMPC_unified_address: 15753 case OMPC_unified_shared_memory: 15754 case OMPC_reverse_offload: 15755 case OMPC_dynamic_allocators: 15756 case OMPC_device_type: 15757 case OMPC_match: 15758 case OMPC_nontemporal: 15759 case OMPC_destroy: 15760 case OMPC_novariants: 15761 case OMPC_nocontext: 15762 case OMPC_detach: 15763 case OMPC_inclusive: 15764 case OMPC_exclusive: 15765 case OMPC_uses_allocators: 15766 case OMPC_affinity: 15767 case OMPC_when: 15768 case OMPC_message: 15769 default: 15770 llvm_unreachable("Clause is not allowed."); 15771 } 15772 return Res; 15773 } 15774 15775 static std::string 15776 getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last, 15777 ArrayRef<unsigned> Exclude = std::nullopt) { 15778 SmallString<256> Buffer; 15779 llvm::raw_svector_ostream Out(Buffer); 15780 unsigned Skipped = Exclude.size(); 15781 for (unsigned I = First; I < Last; ++I) { 15782 if (llvm::is_contained(Exclude, I)) { 15783 --Skipped; 15784 continue; 15785 } 15786 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'"; 15787 if (I + Skipped + 2 == Last) 15788 Out << " or "; 15789 else if (I + Skipped + 1 != Last) 15790 Out << ", "; 15791 } 15792 return std::string(Out.str()); 15793 } 15794 15795 OMPClause *SemaOpenMP::ActOnOpenMPDefaultClause(DefaultKind Kind, 15796 SourceLocation KindKwLoc, 15797 SourceLocation StartLoc, 15798 SourceLocation LParenLoc, 15799 SourceLocation EndLoc) { 15800 if (Kind == OMP_DEFAULT_unknown) { 15801 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) 15802 << getListOfPossibleValues(OMPC_default, /*First=*/0, 15803 /*Last=*/unsigned(OMP_DEFAULT_unknown)) 15804 << getOpenMPClauseName(OMPC_default); 15805 return nullptr; 15806 } 15807 15808 switch (Kind) { 15809 case OMP_DEFAULT_none: 15810 DSAStack->setDefaultDSANone(KindKwLoc); 15811 break; 15812 case OMP_DEFAULT_shared: 15813 DSAStack->setDefaultDSAShared(KindKwLoc); 15814 break; 15815 case OMP_DEFAULT_firstprivate: 15816 DSAStack->setDefaultDSAFirstPrivate(KindKwLoc); 15817 break; 15818 case OMP_DEFAULT_private: 15819 DSAStack->setDefaultDSAPrivate(KindKwLoc); 15820 break; 15821 default: 15822 llvm_unreachable("DSA unexpected in OpenMP default clause"); 15823 } 15824 15825 return new (getASTContext()) 15826 OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc); 15827 } 15828 15829 OMPClause *SemaOpenMP::ActOnOpenMPProcBindClause(ProcBindKind Kind, 15830 SourceLocation KindKwLoc, 15831 SourceLocation StartLoc, 15832 SourceLocation LParenLoc, 15833 SourceLocation EndLoc) { 15834 if (Kind == OMP_PROC_BIND_unknown) { 15835 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) 15836 << getListOfPossibleValues(OMPC_proc_bind, 15837 /*First=*/unsigned(OMP_PROC_BIND_master), 15838 /*Last=*/ 15839 unsigned(getLangOpts().OpenMP > 50 15840 ? OMP_PROC_BIND_primary 15841 : OMP_PROC_BIND_spread) + 15842 1) 15843 << getOpenMPClauseName(OMPC_proc_bind); 15844 return nullptr; 15845 } 15846 if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51) 15847 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) 15848 << getListOfPossibleValues(OMPC_proc_bind, 15849 /*First=*/unsigned(OMP_PROC_BIND_master), 15850 /*Last=*/ 15851 unsigned(OMP_PROC_BIND_spread) + 1) 15852 << getOpenMPClauseName(OMPC_proc_bind); 15853 return new (getASTContext()) 15854 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc); 15855 } 15856 15857 OMPClause *SemaOpenMP::ActOnOpenMPAtomicDefaultMemOrderClause( 15858 OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindKwLoc, 15859 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { 15860 if (Kind == OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown) { 15861 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) 15862 << getListOfPossibleValues( 15863 OMPC_atomic_default_mem_order, /*First=*/0, 15864 /*Last=*/OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown) 15865 << getOpenMPClauseName(OMPC_atomic_default_mem_order); 15866 return nullptr; 15867 } 15868 return new (getASTContext()) OMPAtomicDefaultMemOrderClause( 15869 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc); 15870 } 15871 15872 OMPClause *SemaOpenMP::ActOnOpenMPAtClause(OpenMPAtClauseKind Kind, 15873 SourceLocation KindKwLoc, 15874 SourceLocation StartLoc, 15875 SourceLocation LParenLoc, 15876 SourceLocation EndLoc) { 15877 if (Kind == OMPC_AT_unknown) { 15878 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) 15879 << getListOfPossibleValues(OMPC_at, /*First=*/0, 15880 /*Last=*/OMPC_AT_unknown) 15881 << getOpenMPClauseName(OMPC_at); 15882 return nullptr; 15883 } 15884 return new (getASTContext()) 15885 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc); 15886 } 15887 15888 OMPClause *SemaOpenMP::ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind, 15889 SourceLocation KindKwLoc, 15890 SourceLocation StartLoc, 15891 SourceLocation LParenLoc, 15892 SourceLocation EndLoc) { 15893 if (Kind == OMPC_SEVERITY_unknown) { 15894 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) 15895 << getListOfPossibleValues(OMPC_severity, /*First=*/0, 15896 /*Last=*/OMPC_SEVERITY_unknown) 15897 << getOpenMPClauseName(OMPC_severity); 15898 return nullptr; 15899 } 15900 return new (getASTContext()) 15901 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc); 15902 } 15903 15904 OMPClause *SemaOpenMP::ActOnOpenMPMessageClause(Expr *ME, 15905 SourceLocation StartLoc, 15906 SourceLocation LParenLoc, 15907 SourceLocation EndLoc) { 15908 assert(ME && "NULL expr in Message clause"); 15909 if (!isa<StringLiteral>(ME)) { 15910 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string) 15911 << getOpenMPClauseName(OMPC_message); 15912 return nullptr; 15913 } 15914 return new (getASTContext()) 15915 OMPMessageClause(ME, StartLoc, LParenLoc, EndLoc); 15916 } 15917 15918 OMPClause *SemaOpenMP::ActOnOpenMPOrderClause( 15919 OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind, 15920 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, 15921 SourceLocation KindLoc, SourceLocation EndLoc) { 15922 if (Kind != OMPC_ORDER_concurrent || 15923 (getLangOpts().OpenMP < 51 && MLoc.isValid())) { 15924 // Kind should be concurrent, 15925 // Modifiers introduced in OpenMP 5.1 15926 static_assert(OMPC_ORDER_unknown > 0, 15927 "OMPC_ORDER_unknown not greater than 0"); 15928 15929 Diag(KindLoc, diag::err_omp_unexpected_clause_value) 15930 << getListOfPossibleValues(OMPC_order, 15931 /*First=*/0, 15932 /*Last=*/OMPC_ORDER_unknown) 15933 << getOpenMPClauseName(OMPC_order); 15934 return nullptr; 15935 } 15936 if (getLangOpts().OpenMP >= 51) { 15937 if (Modifier == OMPC_ORDER_MODIFIER_unknown && MLoc.isValid()) { 15938 Diag(MLoc, diag::err_omp_unexpected_clause_value) 15939 << getListOfPossibleValues(OMPC_order, 15940 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1, 15941 /*Last=*/OMPC_ORDER_MODIFIER_last) 15942 << getOpenMPClauseName(OMPC_order); 15943 } else { 15944 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true); 15945 if (DSAStack->getCurScope()) { 15946 // mark the current scope with 'order' flag 15947 unsigned existingFlags = DSAStack->getCurScope()->getFlags(); 15948 DSAStack->getCurScope()->setFlags(existingFlags | 15949 Scope::OpenMPOrderClauseScope); 15950 } 15951 } 15952 } 15953 return new (getASTContext()) OMPOrderClause( 15954 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc); 15955 } 15956 15957 OMPClause *SemaOpenMP::ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind, 15958 SourceLocation KindKwLoc, 15959 SourceLocation StartLoc, 15960 SourceLocation LParenLoc, 15961 SourceLocation EndLoc) { 15962 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source || 15963 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) { 15964 SmallVector<unsigned> Except = { 15965 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj, 15966 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory}; 15967 if (getLangOpts().OpenMP < 51) 15968 Except.push_back(OMPC_DEPEND_inoutset); 15969 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) 15970 << getListOfPossibleValues(OMPC_depend, /*First=*/0, 15971 /*Last=*/OMPC_DEPEND_unknown, Except) 15972 << getOpenMPClauseName(OMPC_update); 15973 return nullptr; 15974 } 15975 return OMPUpdateClause::Create(getASTContext(), StartLoc, LParenLoc, 15976 KindKwLoc, Kind, EndLoc); 15977 } 15978 15979 OMPClause *SemaOpenMP::ActOnOpenMPSizesClause(ArrayRef<Expr *> SizeExprs, 15980 SourceLocation StartLoc, 15981 SourceLocation LParenLoc, 15982 SourceLocation EndLoc) { 15983 SmallVector<Expr *> SanitizedSizeExprs(SizeExprs); 15984 15985 for (Expr *&SizeExpr : SanitizedSizeExprs) { 15986 // Skip if already sanitized, e.g. during a partial template instantiation. 15987 if (!SizeExpr) 15988 continue; 15989 15990 bool IsValid = isNonNegativeIntegerValue(SizeExpr, SemaRef, OMPC_sizes, 15991 /*StrictlyPositive=*/true); 15992 15993 // isNonNegativeIntegerValue returns true for non-integral types (but still 15994 // emits error diagnostic), so check for the expected type explicitly. 15995 QualType SizeTy = SizeExpr->getType(); 15996 if (!SizeTy->isIntegerType()) 15997 IsValid = false; 15998 15999 // Handling in templates is tricky. There are four possibilities to 16000 // consider: 16001 // 16002 // 1a. The expression is valid and we are in a instantiated template or not 16003 // in a template: 16004 // Pass valid expression to be further analysed later in Sema. 16005 // 1b. The expression is valid and we are in a template (including partial 16006 // instantiation): 16007 // isNonNegativeIntegerValue skipped any checks so there is no 16008 // guarantee it will be correct after instantiation. 16009 // ActOnOpenMPSizesClause will be called again at instantiation when 16010 // it is not in a dependent context anymore. This may cause warnings 16011 // to be emitted multiple times. 16012 // 2a. The expression is invalid and we are in an instantiated template or 16013 // not in a template: 16014 // Invalidate the expression with a clearly wrong value (nullptr) so 16015 // later in Sema we do not have to do the same validity analysis again 16016 // or crash from unexpected data. Error diagnostics have already been 16017 // emitted. 16018 // 2b. The expression is invalid and we are in a template (including partial 16019 // instantiation): 16020 // Pass the invalid expression as-is, template instantiation may 16021 // replace unexpected types/values with valid ones. The directives 16022 // with this clause must not try to use these expressions in dependent 16023 // contexts, but delay analysis until full instantiation. 16024 if (!SizeExpr->isInstantiationDependent() && !IsValid) 16025 SizeExpr = nullptr; 16026 } 16027 16028 return OMPSizesClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc, 16029 SanitizedSizeExprs); 16030 } 16031 16032 OMPClause *SemaOpenMP::ActOnOpenMPFullClause(SourceLocation StartLoc, 16033 SourceLocation EndLoc) { 16034 return OMPFullClause::Create(getASTContext(), StartLoc, EndLoc); 16035 } 16036 16037 OMPClause *SemaOpenMP::ActOnOpenMPPartialClause(Expr *FactorExpr, 16038 SourceLocation StartLoc, 16039 SourceLocation LParenLoc, 16040 SourceLocation EndLoc) { 16041 if (FactorExpr) { 16042 // If an argument is specified, it must be a constant (or an unevaluated 16043 // template expression). 16044 ExprResult FactorResult = VerifyPositiveIntegerConstantInClause( 16045 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true); 16046 if (FactorResult.isInvalid()) 16047 return nullptr; 16048 FactorExpr = FactorResult.get(); 16049 } 16050 16051 return OMPPartialClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc, 16052 FactorExpr); 16053 } 16054 16055 OMPClause *SemaOpenMP::ActOnOpenMPAlignClause(Expr *A, SourceLocation StartLoc, 16056 SourceLocation LParenLoc, 16057 SourceLocation EndLoc) { 16058 ExprResult AlignVal; 16059 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align); 16060 if (AlignVal.isInvalid()) 16061 return nullptr; 16062 return OMPAlignClause::Create(getASTContext(), AlignVal.get(), StartLoc, 16063 LParenLoc, EndLoc); 16064 } 16065 16066 OMPClause *SemaOpenMP::ActOnOpenMPSingleExprWithArgClause( 16067 OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr, 16068 SourceLocation StartLoc, SourceLocation LParenLoc, 16069 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc, 16070 SourceLocation EndLoc) { 16071 OMPClause *Res = nullptr; 16072 switch (Kind) { 16073 case OMPC_schedule: 16074 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements }; 16075 assert(Argument.size() == NumberOfElements && 16076 ArgumentLoc.size() == NumberOfElements); 16077 Res = ActOnOpenMPScheduleClause( 16078 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]), 16079 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]), 16080 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr, 16081 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2], 16082 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc); 16083 break; 16084 case OMPC_if: 16085 assert(Argument.size() == 1 && ArgumentLoc.size() == 1); 16086 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()), 16087 Expr, StartLoc, LParenLoc, ArgumentLoc.back(), 16088 DelimLoc, EndLoc); 16089 break; 16090 case OMPC_dist_schedule: 16091 Res = ActOnOpenMPDistScheduleClause( 16092 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr, 16093 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc); 16094 break; 16095 case OMPC_defaultmap: 16096 enum { Modifier, DefaultmapKind }; 16097 Res = ActOnOpenMPDefaultmapClause( 16098 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]), 16099 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]), 16100 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind], 16101 EndLoc); 16102 break; 16103 case OMPC_order: 16104 enum { OrderModifier, OrderKind }; 16105 Res = ActOnOpenMPOrderClause( 16106 static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]), 16107 static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc, 16108 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc); 16109 break; 16110 case OMPC_device: 16111 assert(Argument.size() == 1 && ArgumentLoc.size() == 1); 16112 Res = ActOnOpenMPDeviceClause( 16113 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr, 16114 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc); 16115 break; 16116 case OMPC_grainsize: 16117 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 && 16118 "Modifier for grainsize clause and its location are expected."); 16119 Res = ActOnOpenMPGrainsizeClause( 16120 static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr, 16121 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc); 16122 break; 16123 case OMPC_num_tasks: 16124 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 && 16125 "Modifier for num_tasks clause and its location are expected."); 16126 Res = ActOnOpenMPNumTasksClause( 16127 static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr, 16128 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc); 16129 break; 16130 case OMPC_final: 16131 case OMPC_num_threads: 16132 case OMPC_safelen: 16133 case OMPC_simdlen: 16134 case OMPC_sizes: 16135 case OMPC_allocator: 16136 case OMPC_collapse: 16137 case OMPC_default: 16138 case OMPC_proc_bind: 16139 case OMPC_private: 16140 case OMPC_firstprivate: 16141 case OMPC_lastprivate: 16142 case OMPC_shared: 16143 case OMPC_reduction: 16144 case OMPC_task_reduction: 16145 case OMPC_in_reduction: 16146 case OMPC_linear: 16147 case OMPC_aligned: 16148 case OMPC_copyin: 16149 case OMPC_copyprivate: 16150 case OMPC_ordered: 16151 case OMPC_nowait: 16152 case OMPC_untied: 16153 case OMPC_mergeable: 16154 case OMPC_threadprivate: 16155 case OMPC_allocate: 16156 case OMPC_flush: 16157 case OMPC_depobj: 16158 case OMPC_read: 16159 case OMPC_write: 16160 case OMPC_update: 16161 case OMPC_capture: 16162 case OMPC_compare: 16163 case OMPC_seq_cst: 16164 case OMPC_acq_rel: 16165 case OMPC_acquire: 16166 case OMPC_release: 16167 case OMPC_relaxed: 16168 case OMPC_depend: 16169 case OMPC_threads: 16170 case OMPC_simd: 16171 case OMPC_map: 16172 case OMPC_num_teams: 16173 case OMPC_thread_limit: 16174 case OMPC_priority: 16175 case OMPC_nogroup: 16176 case OMPC_hint: 16177 case OMPC_unknown: 16178 case OMPC_uniform: 16179 case OMPC_to: 16180 case OMPC_from: 16181 case OMPC_use_device_ptr: 16182 case OMPC_use_device_addr: 16183 case OMPC_is_device_ptr: 16184 case OMPC_has_device_addr: 16185 case OMPC_unified_address: 16186 case OMPC_unified_shared_memory: 16187 case OMPC_reverse_offload: 16188 case OMPC_dynamic_allocators: 16189 case OMPC_atomic_default_mem_order: 16190 case OMPC_device_type: 16191 case OMPC_match: 16192 case OMPC_nontemporal: 16193 case OMPC_at: 16194 case OMPC_severity: 16195 case OMPC_message: 16196 case OMPC_destroy: 16197 case OMPC_novariants: 16198 case OMPC_nocontext: 16199 case OMPC_detach: 16200 case OMPC_inclusive: 16201 case OMPC_exclusive: 16202 case OMPC_uses_allocators: 16203 case OMPC_affinity: 16204 case OMPC_when: 16205 case OMPC_bind: 16206 default: 16207 llvm_unreachable("Clause is not allowed."); 16208 } 16209 return Res; 16210 } 16211 16212 static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1, 16213 OpenMPScheduleClauseModifier M2, 16214 SourceLocation M1Loc, SourceLocation M2Loc) { 16215 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) { 16216 SmallVector<unsigned, 2> Excluded; 16217 if (M2 != OMPC_SCHEDULE_MODIFIER_unknown) 16218 Excluded.push_back(M2); 16219 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) 16220 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic); 16221 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic) 16222 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic); 16223 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value) 16224 << getListOfPossibleValues(OMPC_schedule, 16225 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1, 16226 /*Last=*/OMPC_SCHEDULE_MODIFIER_last, 16227 Excluded) 16228 << getOpenMPClauseName(OMPC_schedule); 16229 return true; 16230 } 16231 return false; 16232 } 16233 16234 OMPClause *SemaOpenMP::ActOnOpenMPScheduleClause( 16235 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, 16236 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, 16237 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc, 16238 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) { 16239 if (checkScheduleModifiers(SemaRef, M1, M2, M1Loc, M2Loc) || 16240 checkScheduleModifiers(SemaRef, M2, M1, M2Loc, M1Loc)) 16241 return nullptr; 16242 // OpenMP, 2.7.1, Loop Construct, Restrictions 16243 // Either the monotonic modifier or the nonmonotonic modifier can be specified 16244 // but not both. 16245 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) || 16246 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic && 16247 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) || 16248 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic && 16249 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) { 16250 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier) 16251 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2) 16252 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1); 16253 return nullptr; 16254 } 16255 if (Kind == OMPC_SCHEDULE_unknown) { 16256 std::string Values; 16257 if (M1Loc.isInvalid() && M2Loc.isInvalid()) { 16258 unsigned Exclude[] = {OMPC_SCHEDULE_unknown}; 16259 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0, 16260 /*Last=*/OMPC_SCHEDULE_MODIFIER_last, 16261 Exclude); 16262 } else { 16263 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0, 16264 /*Last=*/OMPC_SCHEDULE_unknown); 16265 } 16266 Diag(KindLoc, diag::err_omp_unexpected_clause_value) 16267 << Values << getOpenMPClauseName(OMPC_schedule); 16268 return nullptr; 16269 } 16270 // OpenMP, 2.7.1, Loop Construct, Restrictions 16271 // The nonmonotonic modifier can only be specified with schedule(dynamic) or 16272 // schedule(guided). 16273 // OpenMP 5.0 does not have this restriction. 16274 if (getLangOpts().OpenMP < 50 && 16275 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic || 16276 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) && 16277 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) { 16278 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc, 16279 diag::err_omp_schedule_nonmonotonic_static); 16280 return nullptr; 16281 } 16282 Expr *ValExpr = ChunkSize; 16283 Stmt *HelperValStmt = nullptr; 16284 if (ChunkSize) { 16285 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() && 16286 !ChunkSize->isInstantiationDependent() && 16287 !ChunkSize->containsUnexpandedParameterPack()) { 16288 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc(); 16289 ExprResult Val = 16290 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize); 16291 if (Val.isInvalid()) 16292 return nullptr; 16293 16294 ValExpr = Val.get(); 16295 16296 // OpenMP [2.7.1, Restrictions] 16297 // chunk_size must be a loop invariant integer expression with a positive 16298 // value. 16299 if (std::optional<llvm::APSInt> Result = 16300 ValExpr->getIntegerConstantExpr(getASTContext())) { 16301 if (Result->isSigned() && !Result->isStrictlyPositive()) { 16302 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause) 16303 << "schedule" << 1 << ChunkSize->getSourceRange(); 16304 return nullptr; 16305 } 16306 } else if (getOpenMPCaptureRegionForClause( 16307 DSAStack->getCurrentDirective(), OMPC_schedule, 16308 getLangOpts().OpenMP) != OMPD_unknown && 16309 !SemaRef.CurContext->isDependentContext()) { 16310 ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); 16311 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 16312 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); 16313 HelperValStmt = buildPreInits(getASTContext(), Captures); 16314 } 16315 } 16316 } 16317 16318 return new (getASTContext()) 16319 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind, 16320 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc); 16321 } 16322 16323 OMPClause *SemaOpenMP::ActOnOpenMPClause(OpenMPClauseKind Kind, 16324 SourceLocation StartLoc, 16325 SourceLocation EndLoc) { 16326 OMPClause *Res = nullptr; 16327 switch (Kind) { 16328 case OMPC_ordered: 16329 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc); 16330 break; 16331 case OMPC_nowait: 16332 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc); 16333 break; 16334 case OMPC_untied: 16335 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc); 16336 break; 16337 case OMPC_mergeable: 16338 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc); 16339 break; 16340 case OMPC_read: 16341 Res = ActOnOpenMPReadClause(StartLoc, EndLoc); 16342 break; 16343 case OMPC_write: 16344 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc); 16345 break; 16346 case OMPC_update: 16347 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc); 16348 break; 16349 case OMPC_capture: 16350 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc); 16351 break; 16352 case OMPC_compare: 16353 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc); 16354 break; 16355 case OMPC_fail: 16356 Res = ActOnOpenMPFailClause(StartLoc, EndLoc); 16357 break; 16358 case OMPC_seq_cst: 16359 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc); 16360 break; 16361 case OMPC_acq_rel: 16362 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc); 16363 break; 16364 case OMPC_acquire: 16365 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc); 16366 break; 16367 case OMPC_release: 16368 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc); 16369 break; 16370 case OMPC_relaxed: 16371 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc); 16372 break; 16373 case OMPC_weak: 16374 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc); 16375 break; 16376 case OMPC_threads: 16377 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc); 16378 break; 16379 case OMPC_simd: 16380 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc); 16381 break; 16382 case OMPC_nogroup: 16383 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc); 16384 break; 16385 case OMPC_unified_address: 16386 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc); 16387 break; 16388 case OMPC_unified_shared_memory: 16389 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc); 16390 break; 16391 case OMPC_reverse_offload: 16392 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc); 16393 break; 16394 case OMPC_dynamic_allocators: 16395 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc); 16396 break; 16397 case OMPC_destroy: 16398 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc, 16399 /*LParenLoc=*/SourceLocation(), 16400 /*VarLoc=*/SourceLocation(), EndLoc); 16401 break; 16402 case OMPC_full: 16403 Res = ActOnOpenMPFullClause(StartLoc, EndLoc); 16404 break; 16405 case OMPC_partial: 16406 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc); 16407 break; 16408 case OMPC_ompx_bare: 16409 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc); 16410 break; 16411 case OMPC_if: 16412 case OMPC_final: 16413 case OMPC_num_threads: 16414 case OMPC_safelen: 16415 case OMPC_simdlen: 16416 case OMPC_sizes: 16417 case OMPC_allocator: 16418 case OMPC_collapse: 16419 case OMPC_schedule: 16420 case OMPC_private: 16421 case OMPC_firstprivate: 16422 case OMPC_lastprivate: 16423 case OMPC_shared: 16424 case OMPC_reduction: 16425 case OMPC_task_reduction: 16426 case OMPC_in_reduction: 16427 case OMPC_linear: 16428 case OMPC_aligned: 16429 case OMPC_copyin: 16430 case OMPC_copyprivate: 16431 case OMPC_default: 16432 case OMPC_proc_bind: 16433 case OMPC_threadprivate: 16434 case OMPC_allocate: 16435 case OMPC_flush: 16436 case OMPC_depobj: 16437 case OMPC_depend: 16438 case OMPC_device: 16439 case OMPC_map: 16440 case OMPC_num_teams: 16441 case OMPC_thread_limit: 16442 case OMPC_priority: 16443 case OMPC_grainsize: 16444 case OMPC_num_tasks: 16445 case OMPC_hint: 16446 case OMPC_dist_schedule: 16447 case OMPC_defaultmap: 16448 case OMPC_unknown: 16449 case OMPC_uniform: 16450 case OMPC_to: 16451 case OMPC_from: 16452 case OMPC_use_device_ptr: 16453 case OMPC_use_device_addr: 16454 case OMPC_is_device_ptr: 16455 case OMPC_has_device_addr: 16456 case OMPC_atomic_default_mem_order: 16457 case OMPC_device_type: 16458 case OMPC_match: 16459 case OMPC_nontemporal: 16460 case OMPC_order: 16461 case OMPC_at: 16462 case OMPC_severity: 16463 case OMPC_message: 16464 case OMPC_novariants: 16465 case OMPC_nocontext: 16466 case OMPC_detach: 16467 case OMPC_inclusive: 16468 case OMPC_exclusive: 16469 case OMPC_uses_allocators: 16470 case OMPC_affinity: 16471 case OMPC_when: 16472 case OMPC_ompx_dyn_cgroup_mem: 16473 default: 16474 llvm_unreachable("Clause is not allowed."); 16475 } 16476 return Res; 16477 } 16478 16479 OMPClause *SemaOpenMP::ActOnOpenMPNowaitClause(SourceLocation StartLoc, 16480 SourceLocation EndLoc) { 16481 DSAStack->setNowaitRegion(); 16482 return new (getASTContext()) OMPNowaitClause(StartLoc, EndLoc); 16483 } 16484 16485 OMPClause *SemaOpenMP::ActOnOpenMPUntiedClause(SourceLocation StartLoc, 16486 SourceLocation EndLoc) { 16487 DSAStack->setUntiedRegion(); 16488 return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc); 16489 } 16490 16491 OMPClause *SemaOpenMP::ActOnOpenMPMergeableClause(SourceLocation StartLoc, 16492 SourceLocation EndLoc) { 16493 return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc); 16494 } 16495 16496 OMPClause *SemaOpenMP::ActOnOpenMPReadClause(SourceLocation StartLoc, 16497 SourceLocation EndLoc) { 16498 return new (getASTContext()) OMPReadClause(StartLoc, EndLoc); 16499 } 16500 16501 OMPClause *SemaOpenMP::ActOnOpenMPWriteClause(SourceLocation StartLoc, 16502 SourceLocation EndLoc) { 16503 return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc); 16504 } 16505 16506 OMPClause *SemaOpenMP::ActOnOpenMPUpdateClause(SourceLocation StartLoc, 16507 SourceLocation EndLoc) { 16508 return OMPUpdateClause::Create(getASTContext(), StartLoc, EndLoc); 16509 } 16510 16511 OMPClause *SemaOpenMP::ActOnOpenMPCaptureClause(SourceLocation StartLoc, 16512 SourceLocation EndLoc) { 16513 return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc); 16514 } 16515 16516 OMPClause *SemaOpenMP::ActOnOpenMPCompareClause(SourceLocation StartLoc, 16517 SourceLocation EndLoc) { 16518 return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc); 16519 } 16520 16521 OMPClause *SemaOpenMP::ActOnOpenMPFailClause(SourceLocation StartLoc, 16522 SourceLocation EndLoc) { 16523 return new (getASTContext()) OMPFailClause(StartLoc, EndLoc); 16524 } 16525 16526 OMPClause *SemaOpenMP::ActOnOpenMPFailClause(OpenMPClauseKind Parameter, 16527 SourceLocation KindLoc, 16528 SourceLocation StartLoc, 16529 SourceLocation LParenLoc, 16530 SourceLocation EndLoc) { 16531 16532 if (!checkFailClauseParameter(Parameter)) { 16533 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses); 16534 return nullptr; 16535 } 16536 return new (getASTContext()) 16537 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc); 16538 } 16539 16540 OMPClause *SemaOpenMP::ActOnOpenMPSeqCstClause(SourceLocation StartLoc, 16541 SourceLocation EndLoc) { 16542 return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc); 16543 } 16544 16545 OMPClause *SemaOpenMP::ActOnOpenMPAcqRelClause(SourceLocation StartLoc, 16546 SourceLocation EndLoc) { 16547 return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc); 16548 } 16549 16550 OMPClause *SemaOpenMP::ActOnOpenMPAcquireClause(SourceLocation StartLoc, 16551 SourceLocation EndLoc) { 16552 return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc); 16553 } 16554 16555 OMPClause *SemaOpenMP::ActOnOpenMPReleaseClause(SourceLocation StartLoc, 16556 SourceLocation EndLoc) { 16557 return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc); 16558 } 16559 16560 OMPClause *SemaOpenMP::ActOnOpenMPRelaxedClause(SourceLocation StartLoc, 16561 SourceLocation EndLoc) { 16562 return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc); 16563 } 16564 16565 OMPClause *SemaOpenMP::ActOnOpenMPWeakClause(SourceLocation StartLoc, 16566 SourceLocation EndLoc) { 16567 return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc); 16568 } 16569 16570 OMPClause *SemaOpenMP::ActOnOpenMPThreadsClause(SourceLocation StartLoc, 16571 SourceLocation EndLoc) { 16572 return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc); 16573 } 16574 16575 OMPClause *SemaOpenMP::ActOnOpenMPSIMDClause(SourceLocation StartLoc, 16576 SourceLocation EndLoc) { 16577 return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc); 16578 } 16579 16580 OMPClause *SemaOpenMP::ActOnOpenMPNogroupClause(SourceLocation StartLoc, 16581 SourceLocation EndLoc) { 16582 return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc); 16583 } 16584 16585 OMPClause *SemaOpenMP::ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc, 16586 SourceLocation EndLoc) { 16587 return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc); 16588 } 16589 16590 OMPClause * 16591 SemaOpenMP::ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc, 16592 SourceLocation EndLoc) { 16593 return new (getASTContext()) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc); 16594 } 16595 16596 OMPClause *SemaOpenMP::ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc, 16597 SourceLocation EndLoc) { 16598 return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc); 16599 } 16600 16601 OMPClause * 16602 SemaOpenMP::ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc, 16603 SourceLocation EndLoc) { 16604 return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc); 16605 } 16606 16607 StmtResult 16608 SemaOpenMP::ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses, 16609 SourceLocation StartLoc, 16610 SourceLocation EndLoc) { 16611 16612 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions] 16613 // At least one action-clause must appear on a directive. 16614 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) { 16615 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'"; 16616 Diag(StartLoc, diag::err_omp_no_clause_for_directive) 16617 << Expected << getOpenMPDirectiveName(OMPD_interop); 16618 return StmtError(); 16619 } 16620 16621 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions] 16622 // A depend clause can only appear on the directive if a targetsync 16623 // interop-type is present or the interop-var was initialized with 16624 // the targetsync interop-type. 16625 16626 // If there is any 'init' clause diagnose if there is no 'init' clause with 16627 // interop-type of 'targetsync'. Cases involving other directives cannot be 16628 // diagnosed. 16629 const OMPDependClause *DependClause = nullptr; 16630 bool HasInitClause = false; 16631 bool IsTargetSync = false; 16632 for (const OMPClause *C : Clauses) { 16633 if (IsTargetSync) 16634 break; 16635 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) { 16636 HasInitClause = true; 16637 if (InitClause->getIsTargetSync()) 16638 IsTargetSync = true; 16639 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) { 16640 DependClause = DC; 16641 } 16642 } 16643 if (DependClause && HasInitClause && !IsTargetSync) { 16644 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause); 16645 return StmtError(); 16646 } 16647 16648 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions] 16649 // Each interop-var may be specified for at most one action-clause of each 16650 // interop construct. 16651 llvm::SmallPtrSet<const ValueDecl *, 4> InteropVars; 16652 for (OMPClause *C : Clauses) { 16653 OpenMPClauseKind ClauseKind = C->getClauseKind(); 16654 std::pair<ValueDecl *, bool> DeclResult; 16655 SourceLocation ELoc; 16656 SourceRange ERange; 16657 16658 if (ClauseKind == OMPC_init) { 16659 auto *E = cast<OMPInitClause>(C)->getInteropVar(); 16660 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange); 16661 } else if (ClauseKind == OMPC_use) { 16662 auto *E = cast<OMPUseClause>(C)->getInteropVar(); 16663 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange); 16664 } else if (ClauseKind == OMPC_destroy) { 16665 auto *E = cast<OMPDestroyClause>(C)->getInteropVar(); 16666 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange); 16667 } 16668 16669 if (DeclResult.first) { 16670 if (!InteropVars.insert(DeclResult.first).second) { 16671 Diag(ELoc, diag::err_omp_interop_var_multiple_actions) 16672 << DeclResult.first; 16673 return StmtError(); 16674 } 16675 } 16676 } 16677 16678 return OMPInteropDirective::Create(getASTContext(), StartLoc, EndLoc, 16679 Clauses); 16680 } 16681 16682 static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr, 16683 SourceLocation VarLoc, 16684 OpenMPClauseKind Kind) { 16685 SourceLocation ELoc; 16686 SourceRange ERange; 16687 Expr *RefExpr = InteropVarExpr; 16688 auto Res = 16689 getPrivateItem(SemaRef, RefExpr, ELoc, ERange, 16690 /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t"); 16691 16692 if (Res.second) { 16693 // It will be analyzed later. 16694 return true; 16695 } 16696 16697 if (!Res.first) 16698 return false; 16699 16700 // Interop variable should be of type omp_interop_t. 16701 bool HasError = false; 16702 QualType InteropType; 16703 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"), 16704 VarLoc, Sema::LookupOrdinaryName); 16705 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) { 16706 NamedDecl *ND = Result.getFoundDecl(); 16707 if (const auto *TD = dyn_cast<TypeDecl>(ND)) { 16708 InteropType = QualType(TD->getTypeForDecl(), 0); 16709 } else { 16710 HasError = true; 16711 } 16712 } else { 16713 HasError = true; 16714 } 16715 16716 if (HasError) { 16717 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found) 16718 << "omp_interop_t"; 16719 return false; 16720 } 16721 16722 QualType VarType = InteropVarExpr->getType().getUnqualifiedType(); 16723 if (!SemaRef.Context.hasSameType(InteropType, VarType)) { 16724 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type); 16725 return false; 16726 } 16727 16728 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions] 16729 // The interop-var passed to init or destroy must be non-const. 16730 if ((Kind == OMPC_init || Kind == OMPC_destroy) && 16731 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) { 16732 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected) 16733 << /*non-const*/ 1; 16734 return false; 16735 } 16736 return true; 16737 } 16738 16739 OMPClause *SemaOpenMP::ActOnOpenMPInitClause( 16740 Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, 16741 SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) { 16742 16743 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_init)) 16744 return nullptr; 16745 16746 // Check prefer_type values. These foreign-runtime-id values are either 16747 // string literals or constant integral expressions. 16748 for (const Expr *E : InteropInfo.PreferTypes) { 16749 if (E->isValueDependent() || E->isTypeDependent() || 16750 E->isInstantiationDependent() || E->containsUnexpandedParameterPack()) 16751 continue; 16752 if (E->isIntegerConstantExpr(getASTContext())) 16753 continue; 16754 if (isa<StringLiteral>(E)) 16755 continue; 16756 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type); 16757 return nullptr; 16758 } 16759 16760 return OMPInitClause::Create(getASTContext(), InteropVar, InteropInfo, 16761 StartLoc, LParenLoc, VarLoc, EndLoc); 16762 } 16763 16764 OMPClause *SemaOpenMP::ActOnOpenMPUseClause(Expr *InteropVar, 16765 SourceLocation StartLoc, 16766 SourceLocation LParenLoc, 16767 SourceLocation VarLoc, 16768 SourceLocation EndLoc) { 16769 16770 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_use)) 16771 return nullptr; 16772 16773 return new (getASTContext()) 16774 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc); 16775 } 16776 16777 OMPClause *SemaOpenMP::ActOnOpenMPDestroyClause(Expr *InteropVar, 16778 SourceLocation StartLoc, 16779 SourceLocation LParenLoc, 16780 SourceLocation VarLoc, 16781 SourceLocation EndLoc) { 16782 if (!InteropVar && getLangOpts().OpenMP >= 52 && 16783 DSAStack->getCurrentDirective() == OMPD_depobj) { 16784 Diag(StartLoc, diag::err_omp_expected_clause_argument) 16785 << getOpenMPClauseName(OMPC_destroy) 16786 << getOpenMPDirectiveName(OMPD_depobj); 16787 return nullptr; 16788 } 16789 if (InteropVar && 16790 !isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_destroy)) 16791 return nullptr; 16792 16793 return new (getASTContext()) 16794 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc); 16795 } 16796 16797 OMPClause *SemaOpenMP::ActOnOpenMPNovariantsClause(Expr *Condition, 16798 SourceLocation StartLoc, 16799 SourceLocation LParenLoc, 16800 SourceLocation EndLoc) { 16801 Expr *ValExpr = Condition; 16802 Stmt *HelperValStmt = nullptr; 16803 OpenMPDirectiveKind CaptureRegion = OMPD_unknown; 16804 if (!Condition->isValueDependent() && !Condition->isTypeDependent() && 16805 !Condition->isInstantiationDependent() && 16806 !Condition->containsUnexpandedParameterPack()) { 16807 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition); 16808 if (Val.isInvalid()) 16809 return nullptr; 16810 16811 ValExpr = SemaRef.MakeFullExpr(Val.get()).get(); 16812 16813 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); 16814 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants, 16815 getLangOpts().OpenMP); 16816 if (CaptureRegion != OMPD_unknown && 16817 !SemaRef.CurContext->isDependentContext()) { 16818 ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); 16819 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 16820 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); 16821 HelperValStmt = buildPreInits(getASTContext(), Captures); 16822 } 16823 } 16824 16825 return new (getASTContext()) OMPNovariantsClause( 16826 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc); 16827 } 16828 16829 OMPClause *SemaOpenMP::ActOnOpenMPNocontextClause(Expr *Condition, 16830 SourceLocation StartLoc, 16831 SourceLocation LParenLoc, 16832 SourceLocation EndLoc) { 16833 Expr *ValExpr = Condition; 16834 Stmt *HelperValStmt = nullptr; 16835 OpenMPDirectiveKind CaptureRegion = OMPD_unknown; 16836 if (!Condition->isValueDependent() && !Condition->isTypeDependent() && 16837 !Condition->isInstantiationDependent() && 16838 !Condition->containsUnexpandedParameterPack()) { 16839 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition); 16840 if (Val.isInvalid()) 16841 return nullptr; 16842 16843 ValExpr = SemaRef.MakeFullExpr(Val.get()).get(); 16844 16845 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); 16846 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext, 16847 getLangOpts().OpenMP); 16848 if (CaptureRegion != OMPD_unknown && 16849 !SemaRef.CurContext->isDependentContext()) { 16850 ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); 16851 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 16852 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); 16853 HelperValStmt = buildPreInits(getASTContext(), Captures); 16854 } 16855 } 16856 16857 return new (getASTContext()) OMPNocontextClause( 16858 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc); 16859 } 16860 16861 OMPClause *SemaOpenMP::ActOnOpenMPFilterClause(Expr *ThreadID, 16862 SourceLocation StartLoc, 16863 SourceLocation LParenLoc, 16864 SourceLocation EndLoc) { 16865 Expr *ValExpr = ThreadID; 16866 Stmt *HelperValStmt = nullptr; 16867 16868 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); 16869 OpenMPDirectiveKind CaptureRegion = 16870 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, getLangOpts().OpenMP); 16871 if (CaptureRegion != OMPD_unknown && 16872 !SemaRef.CurContext->isDependentContext()) { 16873 ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); 16874 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 16875 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); 16876 HelperValStmt = buildPreInits(getASTContext(), Captures); 16877 } 16878 16879 return new (getASTContext()) OMPFilterClause( 16880 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc); 16881 } 16882 16883 OMPClause *SemaOpenMP::ActOnOpenMPVarListClause(OpenMPClauseKind Kind, 16884 ArrayRef<Expr *> VarList, 16885 const OMPVarListLocTy &Locs, 16886 OpenMPVarListDataTy &Data) { 16887 SourceLocation StartLoc = Locs.StartLoc; 16888 SourceLocation LParenLoc = Locs.LParenLoc; 16889 SourceLocation EndLoc = Locs.EndLoc; 16890 OMPClause *Res = nullptr; 16891 int ExtraModifier = Data.ExtraModifier; 16892 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc; 16893 SourceLocation ColonLoc = Data.ColonLoc; 16894 switch (Kind) { 16895 case OMPC_private: 16896 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc); 16897 break; 16898 case OMPC_firstprivate: 16899 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc); 16900 break; 16901 case OMPC_lastprivate: 16902 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown && 16903 "Unexpected lastprivate modifier."); 16904 Res = ActOnOpenMPLastprivateClause( 16905 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier), 16906 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc); 16907 break; 16908 case OMPC_shared: 16909 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc); 16910 break; 16911 case OMPC_reduction: 16912 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown && 16913 "Unexpected lastprivate modifier."); 16914 Res = ActOnOpenMPReductionClause( 16915 VarList, static_cast<OpenMPReductionClauseModifier>(ExtraModifier), 16916 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc, 16917 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId); 16918 break; 16919 case OMPC_task_reduction: 16920 Res = ActOnOpenMPTaskReductionClause( 16921 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc, 16922 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId); 16923 break; 16924 case OMPC_in_reduction: 16925 Res = ActOnOpenMPInReductionClause( 16926 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc, 16927 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId); 16928 break; 16929 case OMPC_linear: 16930 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown && 16931 "Unexpected linear modifier."); 16932 Res = ActOnOpenMPLinearClause( 16933 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc, 16934 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc, 16935 ColonLoc, Data.StepModifierLoc, EndLoc); 16936 break; 16937 case OMPC_aligned: 16938 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc, 16939 LParenLoc, ColonLoc, EndLoc); 16940 break; 16941 case OMPC_copyin: 16942 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc); 16943 break; 16944 case OMPC_copyprivate: 16945 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc); 16946 break; 16947 case OMPC_flush: 16948 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc); 16949 break; 16950 case OMPC_depend: 16951 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown && 16952 "Unexpected depend modifier."); 16953 Res = ActOnOpenMPDependClause( 16954 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc, 16955 ColonLoc, Data.OmpAllMemoryLoc}, 16956 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc); 16957 break; 16958 case OMPC_map: 16959 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown && 16960 "Unexpected map modifier."); 16961 Res = ActOnOpenMPMapClause( 16962 Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc, 16963 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, 16964 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit, 16965 ExtraModifierLoc, ColonLoc, VarList, Locs); 16966 break; 16967 case OMPC_to: 16968 Res = 16969 ActOnOpenMPToClause(Data.MotionModifiers, Data.MotionModifiersLoc, 16970 Data.ReductionOrMapperIdScopeSpec, 16971 Data.ReductionOrMapperId, ColonLoc, VarList, Locs); 16972 break; 16973 case OMPC_from: 16974 Res = ActOnOpenMPFromClause(Data.MotionModifiers, Data.MotionModifiersLoc, 16975 Data.ReductionOrMapperIdScopeSpec, 16976 Data.ReductionOrMapperId, ColonLoc, VarList, 16977 Locs); 16978 break; 16979 case OMPC_use_device_ptr: 16980 Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs); 16981 break; 16982 case OMPC_use_device_addr: 16983 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs); 16984 break; 16985 case OMPC_is_device_ptr: 16986 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs); 16987 break; 16988 case OMPC_has_device_addr: 16989 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs); 16990 break; 16991 case OMPC_allocate: 16992 Res = ActOnOpenMPAllocateClause(Data.DepModOrTailExpr, VarList, StartLoc, 16993 LParenLoc, ColonLoc, EndLoc); 16994 break; 16995 case OMPC_nontemporal: 16996 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc); 16997 break; 16998 case OMPC_inclusive: 16999 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc); 17000 break; 17001 case OMPC_exclusive: 17002 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc); 17003 break; 17004 case OMPC_affinity: 17005 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc, 17006 Data.DepModOrTailExpr, VarList); 17007 break; 17008 case OMPC_doacross: 17009 Res = ActOnOpenMPDoacrossClause( 17010 static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier), 17011 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc); 17012 break; 17013 case OMPC_if: 17014 case OMPC_depobj: 17015 case OMPC_final: 17016 case OMPC_num_threads: 17017 case OMPC_safelen: 17018 case OMPC_simdlen: 17019 case OMPC_sizes: 17020 case OMPC_allocator: 17021 case OMPC_collapse: 17022 case OMPC_default: 17023 case OMPC_proc_bind: 17024 case OMPC_schedule: 17025 case OMPC_ordered: 17026 case OMPC_nowait: 17027 case OMPC_untied: 17028 case OMPC_mergeable: 17029 case OMPC_threadprivate: 17030 case OMPC_read: 17031 case OMPC_write: 17032 case OMPC_update: 17033 case OMPC_capture: 17034 case OMPC_compare: 17035 case OMPC_seq_cst: 17036 case OMPC_acq_rel: 17037 case OMPC_acquire: 17038 case OMPC_release: 17039 case OMPC_relaxed: 17040 case OMPC_device: 17041 case OMPC_threads: 17042 case OMPC_simd: 17043 case OMPC_num_teams: 17044 case OMPC_thread_limit: 17045 case OMPC_priority: 17046 case OMPC_grainsize: 17047 case OMPC_nogroup: 17048 case OMPC_num_tasks: 17049 case OMPC_hint: 17050 case OMPC_dist_schedule: 17051 case OMPC_defaultmap: 17052 case OMPC_unknown: 17053 case OMPC_uniform: 17054 case OMPC_unified_address: 17055 case OMPC_unified_shared_memory: 17056 case OMPC_reverse_offload: 17057 case OMPC_dynamic_allocators: 17058 case OMPC_atomic_default_mem_order: 17059 case OMPC_device_type: 17060 case OMPC_match: 17061 case OMPC_order: 17062 case OMPC_at: 17063 case OMPC_severity: 17064 case OMPC_message: 17065 case OMPC_destroy: 17066 case OMPC_novariants: 17067 case OMPC_nocontext: 17068 case OMPC_detach: 17069 case OMPC_uses_allocators: 17070 case OMPC_when: 17071 case OMPC_bind: 17072 default: 17073 llvm_unreachable("Clause is not allowed."); 17074 } 17075 return Res; 17076 } 17077 17078 ExprResult SemaOpenMP::getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK, 17079 ExprObjectKind OK, 17080 SourceLocation Loc) { 17081 ExprResult Res = SemaRef.BuildDeclRefExpr( 17082 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc); 17083 if (!Res.isUsable()) 17084 return ExprError(); 17085 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) { 17086 Res = SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get()); 17087 if (!Res.isUsable()) 17088 return ExprError(); 17089 } 17090 if (VK != VK_LValue && Res.get()->isGLValue()) { 17091 Res = SemaRef.DefaultLvalueConversion(Res.get()); 17092 if (!Res.isUsable()) 17093 return ExprError(); 17094 } 17095 return Res; 17096 } 17097 17098 OMPClause *SemaOpenMP::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList, 17099 SourceLocation StartLoc, 17100 SourceLocation LParenLoc, 17101 SourceLocation EndLoc) { 17102 SmallVector<Expr *, 8> Vars; 17103 SmallVector<Expr *, 8> PrivateCopies; 17104 bool IsImplicitClause = 17105 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid(); 17106 for (Expr *RefExpr : VarList) { 17107 assert(RefExpr && "NULL expr in OpenMP private clause."); 17108 SourceLocation ELoc; 17109 SourceRange ERange; 17110 Expr *SimpleRefExpr = RefExpr; 17111 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); 17112 if (Res.second) { 17113 // It will be analyzed later. 17114 Vars.push_back(RefExpr); 17115 PrivateCopies.push_back(nullptr); 17116 } 17117 ValueDecl *D = Res.first; 17118 if (!D) 17119 continue; 17120 17121 QualType Type = D->getType(); 17122 auto *VD = dyn_cast<VarDecl>(D); 17123 17124 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3] 17125 // A variable that appears in a private clause must not have an incomplete 17126 // type or a reference type. 17127 if (SemaRef.RequireCompleteType(ELoc, Type, 17128 diag::err_omp_private_incomplete_type)) 17129 continue; 17130 Type = Type.getNonReferenceType(); 17131 17132 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions] 17133 // A variable that is privatized must not have a const-qualified type 17134 // unless it is of class type with a mutable member. This restriction does 17135 // not apply to the firstprivate clause. 17136 // 17137 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions] 17138 // A variable that appears in a private clause must not have a 17139 // const-qualified type unless it is of class type with a mutable member. 17140 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_private, ELoc)) 17141 continue; 17142 17143 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 17144 // in a Construct] 17145 // Variables with the predetermined data-sharing attributes may not be 17146 // listed in data-sharing attributes clauses, except for the cases 17147 // listed below. For these exceptions only, listing a predetermined 17148 // variable in a data-sharing attribute clause is allowed and overrides 17149 // the variable's predetermined data-sharing attributes. 17150 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false); 17151 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) { 17152 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind) 17153 << getOpenMPClauseName(OMPC_private); 17154 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 17155 continue; 17156 } 17157 17158 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective(); 17159 // Variably modified types are not supported for tasks. 17160 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() && 17161 isOpenMPTaskingDirective(CurrDir)) { 17162 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported) 17163 << getOpenMPClauseName(OMPC_private) << Type 17164 << getOpenMPDirectiveName(CurrDir); 17165 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) == 17166 VarDecl::DeclarationOnly; 17167 Diag(D->getLocation(), 17168 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 17169 << D; 17170 continue; 17171 } 17172 17173 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3] 17174 // A list item cannot appear in both a map clause and a data-sharing 17175 // attribute clause on the same construct 17176 // 17177 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7] 17178 // A list item cannot appear in both a map clause and a data-sharing 17179 // attribute clause on the same construct unless the construct is a 17180 // combined construct. 17181 if ((getLangOpts().OpenMP <= 45 && 17182 isOpenMPTargetExecutionDirective(CurrDir)) || 17183 CurrDir == OMPD_target) { 17184 OpenMPClauseKind ConflictKind; 17185 if (DSAStack->checkMappableExprComponentListsForDecl( 17186 VD, /*CurrentRegionOnly=*/true, 17187 [&](OMPClauseMappableExprCommon::MappableExprComponentListRef, 17188 OpenMPClauseKind WhereFoundClauseKind) -> bool { 17189 ConflictKind = WhereFoundClauseKind; 17190 return true; 17191 })) { 17192 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa) 17193 << getOpenMPClauseName(OMPC_private) 17194 << getOpenMPClauseName(ConflictKind) 17195 << getOpenMPDirectiveName(CurrDir); 17196 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 17197 continue; 17198 } 17199 } 17200 17201 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1] 17202 // A variable of class type (or array thereof) that appears in a private 17203 // clause requires an accessible, unambiguous default constructor for the 17204 // class type. 17205 // Generate helper private variable and initialize it with the default 17206 // value. The address of the original variable is replaced by the address of 17207 // the new private variable in CodeGen. This new variable is not added to 17208 // IdResolver, so the code in the OpenMP region uses original variable for 17209 // proper diagnostics. 17210 Type = Type.getUnqualifiedType(); 17211 VarDecl *VDPrivate = 17212 buildVarDecl(SemaRef, ELoc, Type, D->getName(), 17213 D->hasAttrs() ? &D->getAttrs() : nullptr, 17214 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr); 17215 SemaRef.ActOnUninitializedDecl(VDPrivate); 17216 if (VDPrivate->isInvalidDecl()) 17217 continue; 17218 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr( 17219 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc); 17220 17221 DeclRefExpr *Ref = nullptr; 17222 if (!VD && !SemaRef.CurContext->isDependentContext()) { 17223 auto *FD = dyn_cast<FieldDecl>(D); 17224 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr; 17225 if (VD) 17226 Ref = buildDeclRefExpr(SemaRef, VD, VD->getType().getNonReferenceType(), 17227 RefExpr->getExprLoc()); 17228 else 17229 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false); 17230 } 17231 if (!IsImplicitClause) 17232 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref); 17233 Vars.push_back((VD || SemaRef.CurContext->isDependentContext()) 17234 ? RefExpr->IgnoreParens() 17235 : Ref); 17236 PrivateCopies.push_back(VDPrivateRefExpr); 17237 } 17238 17239 if (Vars.empty()) 17240 return nullptr; 17241 17242 return OMPPrivateClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc, 17243 Vars, PrivateCopies); 17244 } 17245 17246 OMPClause *SemaOpenMP::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, 17247 SourceLocation StartLoc, 17248 SourceLocation LParenLoc, 17249 SourceLocation EndLoc) { 17250 SmallVector<Expr *, 8> Vars; 17251 SmallVector<Expr *, 8> PrivateCopies; 17252 SmallVector<Expr *, 8> Inits; 17253 SmallVector<Decl *, 4> ExprCaptures; 17254 bool IsImplicitClause = 17255 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid(); 17256 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc(); 17257 17258 for (Expr *RefExpr : VarList) { 17259 assert(RefExpr && "NULL expr in OpenMP firstprivate clause."); 17260 SourceLocation ELoc; 17261 SourceRange ERange; 17262 Expr *SimpleRefExpr = RefExpr; 17263 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); 17264 if (Res.second) { 17265 // It will be analyzed later. 17266 Vars.push_back(RefExpr); 17267 PrivateCopies.push_back(nullptr); 17268 Inits.push_back(nullptr); 17269 } 17270 ValueDecl *D = Res.first; 17271 if (!D) 17272 continue; 17273 17274 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc; 17275 QualType Type = D->getType(); 17276 auto *VD = dyn_cast<VarDecl>(D); 17277 17278 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3] 17279 // A variable that appears in a private clause must not have an incomplete 17280 // type or a reference type. 17281 if (SemaRef.RequireCompleteType(ELoc, Type, 17282 diag::err_omp_firstprivate_incomplete_type)) 17283 continue; 17284 Type = Type.getNonReferenceType(); 17285 17286 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1] 17287 // A variable of class type (or array thereof) that appears in a private 17288 // clause requires an accessible, unambiguous copy constructor for the 17289 // class type. 17290 QualType ElemType = 17291 getASTContext().getBaseElementType(Type).getNonReferenceType(); 17292 17293 // If an implicit firstprivate variable found it was checked already. 17294 DSAStackTy::DSAVarData TopDVar; 17295 if (!IsImplicitClause) { 17296 DSAStackTy::DSAVarData DVar = 17297 DSAStack->getTopDSA(D, /*FromParent=*/false); 17298 TopDVar = DVar; 17299 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective(); 17300 bool IsConstant = ElemType.isConstant(getASTContext()); 17301 // OpenMP [2.4.13, Data-sharing Attribute Clauses] 17302 // A list item that specifies a given variable may not appear in more 17303 // than one clause on the same directive, except that a variable may be 17304 // specified in both firstprivate and lastprivate clauses. 17305 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3] 17306 // A list item may appear in a firstprivate or lastprivate clause but not 17307 // both. 17308 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate && 17309 (isOpenMPDistributeDirective(CurrDir) || 17310 DVar.CKind != OMPC_lastprivate) && 17311 DVar.RefExpr) { 17312 Diag(ELoc, diag::err_omp_wrong_dsa) 17313 << getOpenMPClauseName(DVar.CKind) 17314 << getOpenMPClauseName(OMPC_firstprivate); 17315 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 17316 continue; 17317 } 17318 17319 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 17320 // in a Construct] 17321 // Variables with the predetermined data-sharing attributes may not be 17322 // listed in data-sharing attributes clauses, except for the cases 17323 // listed below. For these exceptions only, listing a predetermined 17324 // variable in a data-sharing attribute clause is allowed and overrides 17325 // the variable's predetermined data-sharing attributes. 17326 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 17327 // in a Construct, C/C++, p.2] 17328 // Variables with const-qualified type having no mutable member may be 17329 // listed in a firstprivate clause, even if they are static data members. 17330 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr && 17331 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) { 17332 Diag(ELoc, diag::err_omp_wrong_dsa) 17333 << getOpenMPClauseName(DVar.CKind) 17334 << getOpenMPClauseName(OMPC_firstprivate); 17335 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 17336 continue; 17337 } 17338 17339 // OpenMP [2.9.3.4, Restrictions, p.2] 17340 // A list item that is private within a parallel region must not appear 17341 // in a firstprivate clause on a worksharing construct if any of the 17342 // worksharing regions arising from the worksharing construct ever bind 17343 // to any of the parallel regions arising from the parallel construct. 17344 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3] 17345 // A list item that is private within a teams region must not appear in a 17346 // firstprivate clause on a distribute construct if any of the distribute 17347 // regions arising from the distribute construct ever bind to any of the 17348 // teams regions arising from the teams construct. 17349 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3] 17350 // A list item that appears in a reduction clause of a teams construct 17351 // must not appear in a firstprivate clause on a distribute construct if 17352 // any of the distribute regions arising from the distribute construct 17353 // ever bind to any of the teams regions arising from the teams construct. 17354 if ((isOpenMPWorksharingDirective(CurrDir) || 17355 isOpenMPDistributeDirective(CurrDir)) && 17356 !isOpenMPParallelDirective(CurrDir) && 17357 !isOpenMPTeamsDirective(CurrDir)) { 17358 DVar = DSAStack->getImplicitDSA(D, true); 17359 if (DVar.CKind != OMPC_shared && 17360 (isOpenMPParallelDirective(DVar.DKind) || 17361 isOpenMPTeamsDirective(DVar.DKind) || 17362 DVar.DKind == OMPD_unknown)) { 17363 Diag(ELoc, diag::err_omp_required_access) 17364 << getOpenMPClauseName(OMPC_firstprivate) 17365 << getOpenMPClauseName(OMPC_shared); 17366 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 17367 continue; 17368 } 17369 } 17370 // OpenMP [2.9.3.4, Restrictions, p.3] 17371 // A list item that appears in a reduction clause of a parallel construct 17372 // must not appear in a firstprivate clause on a worksharing or task 17373 // construct if any of the worksharing or task regions arising from the 17374 // worksharing or task construct ever bind to any of the parallel regions 17375 // arising from the parallel construct. 17376 // OpenMP [2.9.3.4, Restrictions, p.4] 17377 // A list item that appears in a reduction clause in worksharing 17378 // construct must not appear in a firstprivate clause in a task construct 17379 // encountered during execution of any of the worksharing regions arising 17380 // from the worksharing construct. 17381 if (isOpenMPTaskingDirective(CurrDir)) { 17382 DVar = DSAStack->hasInnermostDSA( 17383 D, 17384 [](OpenMPClauseKind C, bool AppliedToPointee) { 17385 return C == OMPC_reduction && !AppliedToPointee; 17386 }, 17387 [](OpenMPDirectiveKind K) { 17388 return isOpenMPParallelDirective(K) || 17389 isOpenMPWorksharingDirective(K) || 17390 isOpenMPTeamsDirective(K); 17391 }, 17392 /*FromParent=*/true); 17393 if (DVar.CKind == OMPC_reduction && 17394 (isOpenMPParallelDirective(DVar.DKind) || 17395 isOpenMPWorksharingDirective(DVar.DKind) || 17396 isOpenMPTeamsDirective(DVar.DKind))) { 17397 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate) 17398 << getOpenMPDirectiveName(DVar.DKind); 17399 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 17400 continue; 17401 } 17402 } 17403 17404 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3] 17405 // A list item cannot appear in both a map clause and a data-sharing 17406 // attribute clause on the same construct 17407 // 17408 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7] 17409 // A list item cannot appear in both a map clause and a data-sharing 17410 // attribute clause on the same construct unless the construct is a 17411 // combined construct. 17412 if ((getLangOpts().OpenMP <= 45 && 17413 isOpenMPTargetExecutionDirective(CurrDir)) || 17414 CurrDir == OMPD_target) { 17415 OpenMPClauseKind ConflictKind; 17416 if (DSAStack->checkMappableExprComponentListsForDecl( 17417 VD, /*CurrentRegionOnly=*/true, 17418 [&ConflictKind]( 17419 OMPClauseMappableExprCommon::MappableExprComponentListRef, 17420 OpenMPClauseKind WhereFoundClauseKind) { 17421 ConflictKind = WhereFoundClauseKind; 17422 return true; 17423 })) { 17424 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa) 17425 << getOpenMPClauseName(OMPC_firstprivate) 17426 << getOpenMPClauseName(ConflictKind) 17427 << getOpenMPDirectiveName(DSAStack->getCurrentDirective()); 17428 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 17429 continue; 17430 } 17431 } 17432 } 17433 17434 // Variably modified types are not supported for tasks. 17435 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() && 17436 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) { 17437 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported) 17438 << getOpenMPClauseName(OMPC_firstprivate) << Type 17439 << getOpenMPDirectiveName(DSAStack->getCurrentDirective()); 17440 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) == 17441 VarDecl::DeclarationOnly; 17442 Diag(D->getLocation(), 17443 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 17444 << D; 17445 continue; 17446 } 17447 17448 Type = Type.getUnqualifiedType(); 17449 VarDecl *VDPrivate = 17450 buildVarDecl(SemaRef, ELoc, Type, D->getName(), 17451 D->hasAttrs() ? &D->getAttrs() : nullptr, 17452 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr); 17453 // Generate helper private variable and initialize it with the value of the 17454 // original variable. The address of the original variable is replaced by 17455 // the address of the new private variable in the CodeGen. This new variable 17456 // is not added to IdResolver, so the code in the OpenMP region uses 17457 // original variable for proper diagnostics and variable capturing. 17458 Expr *VDInitRefExpr = nullptr; 17459 // For arrays generate initializer for single element and replace it by the 17460 // original array element in CodeGen. 17461 if (Type->isArrayType()) { 17462 VarDecl *VDInit = 17463 buildVarDecl(SemaRef, RefExpr->getExprLoc(), ElemType, D->getName()); 17464 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, ElemType, ELoc); 17465 Expr *Init = SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(); 17466 ElemType = ElemType.getUnqualifiedType(); 17467 VarDecl *VDInitTemp = buildVarDecl(SemaRef, RefExpr->getExprLoc(), 17468 ElemType, ".firstprivate.temp"); 17469 InitializedEntity Entity = 17470 InitializedEntity::InitializeVariable(VDInitTemp); 17471 InitializationKind Kind = InitializationKind::CreateCopy(ELoc, ELoc); 17472 17473 InitializationSequence InitSeq(SemaRef, Entity, Kind, Init); 17474 ExprResult Result = InitSeq.Perform(SemaRef, Entity, Kind, Init); 17475 if (Result.isInvalid()) 17476 VDPrivate->setInvalidDecl(); 17477 else 17478 VDPrivate->setInit(Result.getAs<Expr>()); 17479 // Remove temp variable declaration. 17480 getASTContext().Deallocate(VDInitTemp); 17481 } else { 17482 VarDecl *VDInit = buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type, 17483 ".firstprivate.temp"); 17484 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, RefExpr->getType(), 17485 RefExpr->getExprLoc()); 17486 SemaRef.AddInitializerToDecl( 17487 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(), 17488 /*DirectInit=*/false); 17489 } 17490 if (VDPrivate->isInvalidDecl()) { 17491 if (IsImplicitClause) { 17492 Diag(RefExpr->getExprLoc(), 17493 diag::note_omp_task_predetermined_firstprivate_here); 17494 } 17495 continue; 17496 } 17497 SemaRef.CurContext->addDecl(VDPrivate); 17498 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr( 17499 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), 17500 RefExpr->getExprLoc()); 17501 DeclRefExpr *Ref = nullptr; 17502 if (!VD && !SemaRef.CurContext->isDependentContext()) { 17503 if (TopDVar.CKind == OMPC_lastprivate) { 17504 Ref = TopDVar.PrivateCopy; 17505 } else { 17506 auto *FD = dyn_cast<FieldDecl>(D); 17507 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr; 17508 if (VD) 17509 Ref = 17510 buildDeclRefExpr(SemaRef, VD, VD->getType().getNonReferenceType(), 17511 RefExpr->getExprLoc()); 17512 else 17513 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true); 17514 if (VD || !isOpenMPCapturedDecl(D)) 17515 ExprCaptures.push_back(Ref->getDecl()); 17516 } 17517 } 17518 if (!IsImplicitClause) 17519 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref); 17520 Vars.push_back((VD || SemaRef.CurContext->isDependentContext()) 17521 ? RefExpr->IgnoreParens() 17522 : Ref); 17523 PrivateCopies.push_back(VDPrivateRefExpr); 17524 Inits.push_back(VDInitRefExpr); 17525 } 17526 17527 if (Vars.empty()) 17528 return nullptr; 17529 17530 return OMPFirstprivateClause::Create( 17531 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits, 17532 buildPreInits(getASTContext(), ExprCaptures)); 17533 } 17534 17535 OMPClause *SemaOpenMP::ActOnOpenMPLastprivateClause( 17536 ArrayRef<Expr *> VarList, OpenMPLastprivateModifier LPKind, 17537 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc, 17538 SourceLocation LParenLoc, SourceLocation EndLoc) { 17539 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) { 17540 assert(ColonLoc.isValid() && "Colon location must be valid."); 17541 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value) 17542 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0, 17543 /*Last=*/OMPC_LASTPRIVATE_unknown) 17544 << getOpenMPClauseName(OMPC_lastprivate); 17545 return nullptr; 17546 } 17547 17548 SmallVector<Expr *, 8> Vars; 17549 SmallVector<Expr *, 8> SrcExprs; 17550 SmallVector<Expr *, 8> DstExprs; 17551 SmallVector<Expr *, 8> AssignmentOps; 17552 SmallVector<Decl *, 4> ExprCaptures; 17553 SmallVector<Expr *, 4> ExprPostUpdates; 17554 for (Expr *RefExpr : VarList) { 17555 assert(RefExpr && "NULL expr in OpenMP lastprivate clause."); 17556 SourceLocation ELoc; 17557 SourceRange ERange; 17558 Expr *SimpleRefExpr = RefExpr; 17559 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); 17560 if (Res.second) { 17561 // It will be analyzed later. 17562 Vars.push_back(RefExpr); 17563 SrcExprs.push_back(nullptr); 17564 DstExprs.push_back(nullptr); 17565 AssignmentOps.push_back(nullptr); 17566 } 17567 ValueDecl *D = Res.first; 17568 if (!D) 17569 continue; 17570 17571 QualType Type = D->getType(); 17572 auto *VD = dyn_cast<VarDecl>(D); 17573 17574 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2] 17575 // A variable that appears in a lastprivate clause must not have an 17576 // incomplete type or a reference type. 17577 if (SemaRef.RequireCompleteType(ELoc, Type, 17578 diag::err_omp_lastprivate_incomplete_type)) 17579 continue; 17580 Type = Type.getNonReferenceType(); 17581 17582 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions] 17583 // A variable that is privatized must not have a const-qualified type 17584 // unless it is of class type with a mutable member. This restriction does 17585 // not apply to the firstprivate clause. 17586 // 17587 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions] 17588 // A variable that appears in a lastprivate clause must not have a 17589 // const-qualified type unless it is of class type with a mutable member. 17590 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_lastprivate, ELoc)) 17591 continue; 17592 17593 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions] 17594 // A list item that appears in a lastprivate clause with the conditional 17595 // modifier must be a scalar variable. 17596 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) { 17597 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar); 17598 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) == 17599 VarDecl::DeclarationOnly; 17600 Diag(D->getLocation(), 17601 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 17602 << D; 17603 continue; 17604 } 17605 17606 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective(); 17607 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced 17608 // in a Construct] 17609 // Variables with the predetermined data-sharing attributes may not be 17610 // listed in data-sharing attributes clauses, except for the cases 17611 // listed below. 17612 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3] 17613 // A list item may appear in a firstprivate or lastprivate clause but not 17614 // both. 17615 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false); 17616 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate && 17617 (isOpenMPDistributeDirective(CurrDir) || 17618 DVar.CKind != OMPC_firstprivate) && 17619 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) { 17620 Diag(ELoc, diag::err_omp_wrong_dsa) 17621 << getOpenMPClauseName(DVar.CKind) 17622 << getOpenMPClauseName(OMPC_lastprivate); 17623 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 17624 continue; 17625 } 17626 17627 // OpenMP [2.14.3.5, Restrictions, p.2] 17628 // A list item that is private within a parallel region, or that appears in 17629 // the reduction clause of a parallel construct, must not appear in a 17630 // lastprivate clause on a worksharing construct if any of the corresponding 17631 // worksharing regions ever binds to any of the corresponding parallel 17632 // regions. 17633 DSAStackTy::DSAVarData TopDVar = DVar; 17634 if (isOpenMPWorksharingDirective(CurrDir) && 17635 !isOpenMPParallelDirective(CurrDir) && 17636 !isOpenMPTeamsDirective(CurrDir)) { 17637 DVar = DSAStack->getImplicitDSA(D, true); 17638 if (DVar.CKind != OMPC_shared) { 17639 Diag(ELoc, diag::err_omp_required_access) 17640 << getOpenMPClauseName(OMPC_lastprivate) 17641 << getOpenMPClauseName(OMPC_shared); 17642 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 17643 continue; 17644 } 17645 } 17646 17647 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2] 17648 // A variable of class type (or array thereof) that appears in a 17649 // lastprivate clause requires an accessible, unambiguous default 17650 // constructor for the class type, unless the list item is also specified 17651 // in a firstprivate clause. 17652 // A variable of class type (or array thereof) that appears in a 17653 // lastprivate clause requires an accessible, unambiguous copy assignment 17654 // operator for the class type. 17655 Type = getASTContext().getBaseElementType(Type).getNonReferenceType(); 17656 VarDecl *SrcVD = buildVarDecl(SemaRef, ERange.getBegin(), 17657 Type.getUnqualifiedType(), ".lastprivate.src", 17658 D->hasAttrs() ? &D->getAttrs() : nullptr); 17659 DeclRefExpr *PseudoSrcExpr = 17660 buildDeclRefExpr(SemaRef, SrcVD, Type.getUnqualifiedType(), ELoc); 17661 VarDecl *DstVD = 17662 buildVarDecl(SemaRef, ERange.getBegin(), Type, ".lastprivate.dst", 17663 D->hasAttrs() ? &D->getAttrs() : nullptr); 17664 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc); 17665 // For arrays generate assignment operation for single element and replace 17666 // it by the original array element in CodeGen. 17667 ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign, 17668 PseudoDstExpr, PseudoSrcExpr); 17669 if (AssignmentOp.isInvalid()) 17670 continue; 17671 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc, 17672 /*DiscardedValue*/ false); 17673 if (AssignmentOp.isInvalid()) 17674 continue; 17675 17676 DeclRefExpr *Ref = nullptr; 17677 if (!VD && !SemaRef.CurContext->isDependentContext()) { 17678 if (TopDVar.CKind == OMPC_firstprivate) { 17679 Ref = TopDVar.PrivateCopy; 17680 } else { 17681 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false); 17682 if (!isOpenMPCapturedDecl(D)) 17683 ExprCaptures.push_back(Ref->getDecl()); 17684 } 17685 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) || 17686 (!isOpenMPCapturedDecl(D) && 17687 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) { 17688 ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref); 17689 if (!RefRes.isUsable()) 17690 continue; 17691 ExprResult PostUpdateRes = 17692 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign, 17693 SimpleRefExpr, RefRes.get()); 17694 if (!PostUpdateRes.isUsable()) 17695 continue; 17696 ExprPostUpdates.push_back( 17697 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get()); 17698 } 17699 } 17700 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref); 17701 Vars.push_back((VD || SemaRef.CurContext->isDependentContext()) 17702 ? RefExpr->IgnoreParens() 17703 : Ref); 17704 SrcExprs.push_back(PseudoSrcExpr); 17705 DstExprs.push_back(PseudoDstExpr); 17706 AssignmentOps.push_back(AssignmentOp.get()); 17707 } 17708 17709 if (Vars.empty()) 17710 return nullptr; 17711 17712 return OMPLastprivateClause::Create( 17713 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs, 17714 AssignmentOps, LPKind, LPKindLoc, ColonLoc, 17715 buildPreInits(getASTContext(), ExprCaptures), 17716 buildPostUpdate(SemaRef, ExprPostUpdates)); 17717 } 17718 17719 OMPClause *SemaOpenMP::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList, 17720 SourceLocation StartLoc, 17721 SourceLocation LParenLoc, 17722 SourceLocation EndLoc) { 17723 SmallVector<Expr *, 8> Vars; 17724 for (Expr *RefExpr : VarList) { 17725 assert(RefExpr && "NULL expr in OpenMP lastprivate clause."); 17726 SourceLocation ELoc; 17727 SourceRange ERange; 17728 Expr *SimpleRefExpr = RefExpr; 17729 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); 17730 if (Res.second) { 17731 // It will be analyzed later. 17732 Vars.push_back(RefExpr); 17733 } 17734 ValueDecl *D = Res.first; 17735 if (!D) 17736 continue; 17737 17738 auto *VD = dyn_cast<VarDecl>(D); 17739 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 17740 // in a Construct] 17741 // Variables with the predetermined data-sharing attributes may not be 17742 // listed in data-sharing attributes clauses, except for the cases 17743 // listed below. For these exceptions only, listing a predetermined 17744 // variable in a data-sharing attribute clause is allowed and overrides 17745 // the variable's predetermined data-sharing attributes. 17746 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false); 17747 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared && 17748 DVar.RefExpr) { 17749 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind) 17750 << getOpenMPClauseName(OMPC_shared); 17751 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 17752 continue; 17753 } 17754 17755 DeclRefExpr *Ref = nullptr; 17756 if (!VD && isOpenMPCapturedDecl(D) && 17757 !SemaRef.CurContext->isDependentContext()) 17758 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true); 17759 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref); 17760 Vars.push_back((VD || !Ref || SemaRef.CurContext->isDependentContext()) 17761 ? RefExpr->IgnoreParens() 17762 : Ref); 17763 } 17764 17765 if (Vars.empty()) 17766 return nullptr; 17767 17768 return OMPSharedClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc, 17769 Vars); 17770 } 17771 17772 namespace { 17773 class DSARefChecker : public StmtVisitor<DSARefChecker, bool> { 17774 DSAStackTy *Stack; 17775 17776 public: 17777 bool VisitDeclRefExpr(DeclRefExpr *E) { 17778 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) { 17779 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false); 17780 if (DVar.CKind == OMPC_shared && !DVar.RefExpr) 17781 return false; 17782 if (DVar.CKind != OMPC_unknown) 17783 return true; 17784 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA( 17785 VD, 17786 [](OpenMPClauseKind C, bool AppliedToPointee, bool) { 17787 return isOpenMPPrivate(C) && !AppliedToPointee; 17788 }, 17789 [](OpenMPDirectiveKind) { return true; }, 17790 /*FromParent=*/true); 17791 return DVarPrivate.CKind != OMPC_unknown; 17792 } 17793 return false; 17794 } 17795 bool VisitStmt(Stmt *S) { 17796 for (Stmt *Child : S->children()) { 17797 if (Child && Visit(Child)) 17798 return true; 17799 } 17800 return false; 17801 } 17802 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {} 17803 }; 17804 } // namespace 17805 17806 namespace { 17807 // Transform MemberExpression for specified FieldDecl of current class to 17808 // DeclRefExpr to specified OMPCapturedExprDecl. 17809 class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> { 17810 typedef TreeTransform<TransformExprToCaptures> BaseTransform; 17811 ValueDecl *Field = nullptr; 17812 DeclRefExpr *CapturedExpr = nullptr; 17813 17814 public: 17815 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl) 17816 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {} 17817 17818 ExprResult TransformMemberExpr(MemberExpr *E) { 17819 if (isa<CXXThisExpr>(E->getBase()->IgnoreParenImpCasts()) && 17820 E->getMemberDecl() == Field) { 17821 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false); 17822 return CapturedExpr; 17823 } 17824 return BaseTransform::TransformMemberExpr(E); 17825 } 17826 DeclRefExpr *getCapturedExpr() { return CapturedExpr; } 17827 }; 17828 } // namespace 17829 17830 template <typename T, typename U> 17831 static T filterLookupForUDReductionAndMapper( 17832 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) { 17833 for (U &Set : Lookups) { 17834 for (auto *D : Set) { 17835 if (T Res = Gen(cast<ValueDecl>(D))) 17836 return Res; 17837 } 17838 } 17839 return T(); 17840 } 17841 17842 static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) { 17843 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case"); 17844 17845 for (auto *RD : D->redecls()) { 17846 // Don't bother with extra checks if we already know this one isn't visible. 17847 if (RD == D) 17848 continue; 17849 17850 auto ND = cast<NamedDecl>(RD); 17851 if (LookupResult::isVisible(SemaRef, ND)) 17852 return ND; 17853 } 17854 17855 return nullptr; 17856 } 17857 17858 static void 17859 argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id, 17860 SourceLocation Loc, QualType Ty, 17861 SmallVectorImpl<UnresolvedSet<8>> &Lookups) { 17862 // Find all of the associated namespaces and classes based on the 17863 // arguments we have. 17864 Sema::AssociatedNamespaceSet AssociatedNamespaces; 17865 Sema::AssociatedClassSet AssociatedClasses; 17866 OpaqueValueExpr OVE(Loc, Ty, VK_LValue); 17867 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces, 17868 AssociatedClasses); 17869 17870 // C++ [basic.lookup.argdep]p3: 17871 // Let X be the lookup set produced by unqualified lookup (3.4.1) 17872 // and let Y be the lookup set produced by argument dependent 17873 // lookup (defined as follows). If X contains [...] then Y is 17874 // empty. Otherwise Y is the set of declarations found in the 17875 // namespaces associated with the argument types as described 17876 // below. The set of declarations found by the lookup of the name 17877 // is the union of X and Y. 17878 // 17879 // Here, we compute Y and add its members to the overloaded 17880 // candidate set. 17881 for (auto *NS : AssociatedNamespaces) { 17882 // When considering an associated namespace, the lookup is the 17883 // same as the lookup performed when the associated namespace is 17884 // used as a qualifier (3.4.3.2) except that: 17885 // 17886 // -- Any using-directives in the associated namespace are 17887 // ignored. 17888 // 17889 // -- Any namespace-scope friend functions declared in 17890 // associated classes are visible within their respective 17891 // namespaces even if they are not visible during an ordinary 17892 // lookup (11.4). 17893 DeclContext::lookup_result R = NS->lookup(Id.getName()); 17894 for (auto *D : R) { 17895 auto *Underlying = D; 17896 if (auto *USD = dyn_cast<UsingShadowDecl>(D)) 17897 Underlying = USD->getTargetDecl(); 17898 17899 if (!isa<OMPDeclareReductionDecl>(Underlying) && 17900 !isa<OMPDeclareMapperDecl>(Underlying)) 17901 continue; 17902 17903 if (!SemaRef.isVisible(D)) { 17904 D = findAcceptableDecl(SemaRef, D); 17905 if (!D) 17906 continue; 17907 if (auto *USD = dyn_cast<UsingShadowDecl>(D)) 17908 Underlying = USD->getTargetDecl(); 17909 } 17910 Lookups.emplace_back(); 17911 Lookups.back().addDecl(Underlying); 17912 } 17913 } 17914 } 17915 17916 static ExprResult 17917 buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, 17918 Scope *S, CXXScopeSpec &ReductionIdScopeSpec, 17919 const DeclarationNameInfo &ReductionId, QualType Ty, 17920 CXXCastPath &BasePath, Expr *UnresolvedReduction) { 17921 if (ReductionIdScopeSpec.isInvalid()) 17922 return ExprError(); 17923 SmallVector<UnresolvedSet<8>, 4> Lookups; 17924 if (S) { 17925 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName); 17926 Lookup.suppressDiagnostics(); 17927 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec, 17928 /*ObjectType=*/QualType())) { 17929 NamedDecl *D = Lookup.getRepresentativeDecl(); 17930 do { 17931 S = S->getParent(); 17932 } while (S && !S->isDeclScope(D)); 17933 if (S) 17934 S = S->getParent(); 17935 Lookups.emplace_back(); 17936 Lookups.back().append(Lookup.begin(), Lookup.end()); 17937 Lookup.clear(); 17938 } 17939 } else if (auto *ULE = 17940 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) { 17941 Lookups.push_back(UnresolvedSet<8>()); 17942 Decl *PrevD = nullptr; 17943 for (NamedDecl *D : ULE->decls()) { 17944 if (D == PrevD) 17945 Lookups.push_back(UnresolvedSet<8>()); 17946 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D)) 17947 Lookups.back().addDecl(DRD); 17948 PrevD = D; 17949 } 17950 } 17951 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() || 17952 Ty->isInstantiationDependentType() || 17953 Ty->containsUnexpandedParameterPack() || 17954 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) { 17955 return !D->isInvalidDecl() && 17956 (D->getType()->isDependentType() || 17957 D->getType()->isInstantiationDependentType() || 17958 D->getType()->containsUnexpandedParameterPack()); 17959 })) { 17960 UnresolvedSet<8> ResSet; 17961 for (const UnresolvedSet<8> &Set : Lookups) { 17962 if (Set.empty()) 17963 continue; 17964 ResSet.append(Set.begin(), Set.end()); 17965 // The last item marks the end of all declarations at the specified scope. 17966 ResSet.addDecl(Set[Set.size() - 1]); 17967 } 17968 return UnresolvedLookupExpr::Create( 17969 SemaRef.Context, /*NamingClass=*/nullptr, 17970 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId, 17971 /*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false, 17972 /*KnownInstantiationDependent=*/false); 17973 } 17974 // Lookup inside the classes. 17975 // C++ [over.match.oper]p3: 17976 // For a unary operator @ with an operand of a type whose 17977 // cv-unqualified version is T1, and for a binary operator @ with 17978 // a left operand of a type whose cv-unqualified version is T1 and 17979 // a right operand of a type whose cv-unqualified version is T2, 17980 // three sets of candidate functions, designated member 17981 // candidates, non-member candidates and built-in candidates, are 17982 // constructed as follows: 17983 // -- If T1 is a complete class type or a class currently being 17984 // defined, the set of member candidates is the result of the 17985 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise, 17986 // the set of member candidates is empty. 17987 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName); 17988 Lookup.suppressDiagnostics(); 17989 if (const auto *TyRec = Ty->getAs<RecordType>()) { 17990 // Complete the type if it can be completed. 17991 // If the type is neither complete nor being defined, bail out now. 17992 if (SemaRef.isCompleteType(Loc, Ty) || TyRec->isBeingDefined() || 17993 TyRec->getDecl()->getDefinition()) { 17994 Lookup.clear(); 17995 SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl()); 17996 if (Lookup.empty()) { 17997 Lookups.emplace_back(); 17998 Lookups.back().append(Lookup.begin(), Lookup.end()); 17999 } 18000 } 18001 } 18002 // Perform ADL. 18003 if (SemaRef.getLangOpts().CPlusPlus) 18004 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups); 18005 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>( 18006 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * { 18007 if (!D->isInvalidDecl() && 18008 SemaRef.Context.hasSameType(D->getType(), Ty)) 18009 return D; 18010 return nullptr; 18011 })) 18012 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), 18013 VK_LValue, Loc); 18014 if (SemaRef.getLangOpts().CPlusPlus) { 18015 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>( 18016 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * { 18017 if (!D->isInvalidDecl() && 18018 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) && 18019 !Ty.isMoreQualifiedThan(D->getType())) 18020 return D; 18021 return nullptr; 18022 })) { 18023 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, 18024 /*DetectVirtual=*/false); 18025 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) { 18026 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType( 18027 VD->getType().getUnqualifiedType()))) { 18028 if (SemaRef.CheckBaseClassAccess( 18029 Loc, VD->getType(), Ty, Paths.front(), 18030 /*DiagID=*/0) != Sema::AR_inaccessible) { 18031 SemaRef.BuildBasePathArray(Paths, BasePath); 18032 return SemaRef.BuildDeclRefExpr( 18033 VD, VD->getType().getNonReferenceType(), VK_LValue, Loc); 18034 } 18035 } 18036 } 18037 } 18038 } 18039 if (ReductionIdScopeSpec.isSet()) { 18040 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier) 18041 << Ty << Range; 18042 return ExprError(); 18043 } 18044 return ExprEmpty(); 18045 } 18046 18047 namespace { 18048 /// Data for the reduction-based clauses. 18049 struct ReductionData { 18050 /// List of original reduction items. 18051 SmallVector<Expr *, 8> Vars; 18052 /// List of private copies of the reduction items. 18053 SmallVector<Expr *, 8> Privates; 18054 /// LHS expressions for the reduction_op expressions. 18055 SmallVector<Expr *, 8> LHSs; 18056 /// RHS expressions for the reduction_op expressions. 18057 SmallVector<Expr *, 8> RHSs; 18058 /// Reduction operation expression. 18059 SmallVector<Expr *, 8> ReductionOps; 18060 /// inscan copy operation expressions. 18061 SmallVector<Expr *, 8> InscanCopyOps; 18062 /// inscan copy temp array expressions for prefix sums. 18063 SmallVector<Expr *, 8> InscanCopyArrayTemps; 18064 /// inscan copy temp array element expressions for prefix sums. 18065 SmallVector<Expr *, 8> InscanCopyArrayElems; 18066 /// Taskgroup descriptors for the corresponding reduction items in 18067 /// in_reduction clauses. 18068 SmallVector<Expr *, 8> TaskgroupDescriptors; 18069 /// List of captures for clause. 18070 SmallVector<Decl *, 4> ExprCaptures; 18071 /// List of postupdate expressions. 18072 SmallVector<Expr *, 4> ExprPostUpdates; 18073 /// Reduction modifier. 18074 unsigned RedModifier = 0; 18075 ReductionData() = delete; 18076 /// Reserves required memory for the reduction data. 18077 ReductionData(unsigned Size, unsigned Modifier = 0) : RedModifier(Modifier) { 18078 Vars.reserve(Size); 18079 Privates.reserve(Size); 18080 LHSs.reserve(Size); 18081 RHSs.reserve(Size); 18082 ReductionOps.reserve(Size); 18083 if (RedModifier == OMPC_REDUCTION_inscan) { 18084 InscanCopyOps.reserve(Size); 18085 InscanCopyArrayTemps.reserve(Size); 18086 InscanCopyArrayElems.reserve(Size); 18087 } 18088 TaskgroupDescriptors.reserve(Size); 18089 ExprCaptures.reserve(Size); 18090 ExprPostUpdates.reserve(Size); 18091 } 18092 /// Stores reduction item and reduction operation only (required for dependent 18093 /// reduction item). 18094 void push(Expr *Item, Expr *ReductionOp) { 18095 Vars.emplace_back(Item); 18096 Privates.emplace_back(nullptr); 18097 LHSs.emplace_back(nullptr); 18098 RHSs.emplace_back(nullptr); 18099 ReductionOps.emplace_back(ReductionOp); 18100 TaskgroupDescriptors.emplace_back(nullptr); 18101 if (RedModifier == OMPC_REDUCTION_inscan) { 18102 InscanCopyOps.push_back(nullptr); 18103 InscanCopyArrayTemps.push_back(nullptr); 18104 InscanCopyArrayElems.push_back(nullptr); 18105 } 18106 } 18107 /// Stores reduction data. 18108 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp, 18109 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp, 18110 Expr *CopyArrayElem) { 18111 Vars.emplace_back(Item); 18112 Privates.emplace_back(Private); 18113 LHSs.emplace_back(LHS); 18114 RHSs.emplace_back(RHS); 18115 ReductionOps.emplace_back(ReductionOp); 18116 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor); 18117 if (RedModifier == OMPC_REDUCTION_inscan) { 18118 InscanCopyOps.push_back(CopyOp); 18119 InscanCopyArrayTemps.push_back(CopyArrayTemp); 18120 InscanCopyArrayElems.push_back(CopyArrayElem); 18121 } else { 18122 assert(CopyOp == nullptr && CopyArrayTemp == nullptr && 18123 CopyArrayElem == nullptr && 18124 "Copy operation must be used for inscan reductions only."); 18125 } 18126 } 18127 }; 18128 } // namespace 18129 18130 static bool checkOMPArraySectionConstantForReduction( 18131 ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement, 18132 SmallVectorImpl<llvm::APSInt> &ArraySizes) { 18133 const Expr *Length = OASE->getLength(); 18134 if (Length == nullptr) { 18135 // For array sections of the form [1:] or [:], we would need to analyze 18136 // the lower bound... 18137 if (OASE->getColonLocFirst().isValid()) 18138 return false; 18139 18140 // This is an array subscript which has implicit length 1! 18141 SingleElement = true; 18142 ArraySizes.push_back(llvm::APSInt::get(1)); 18143 } else { 18144 Expr::EvalResult Result; 18145 if (!Length->EvaluateAsInt(Result, Context)) 18146 return false; 18147 18148 llvm::APSInt ConstantLengthValue = Result.Val.getInt(); 18149 SingleElement = (ConstantLengthValue.getSExtValue() == 1); 18150 ArraySizes.push_back(ConstantLengthValue); 18151 } 18152 18153 // Get the base of this array section and walk up from there. 18154 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts(); 18155 18156 // We require length = 1 for all array sections except the right-most to 18157 // guarantee that the memory region is contiguous and has no holes in it. 18158 while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Base)) { 18159 Length = TempOASE->getLength(); 18160 if (Length == nullptr) { 18161 // For array sections of the form [1:] or [:], we would need to analyze 18162 // the lower bound... 18163 if (OASE->getColonLocFirst().isValid()) 18164 return false; 18165 18166 // This is an array subscript which has implicit length 1! 18167 ArraySizes.push_back(llvm::APSInt::get(1)); 18168 } else { 18169 Expr::EvalResult Result; 18170 if (!Length->EvaluateAsInt(Result, Context)) 18171 return false; 18172 18173 llvm::APSInt ConstantLengthValue = Result.Val.getInt(); 18174 if (ConstantLengthValue.getSExtValue() != 1) 18175 return false; 18176 18177 ArraySizes.push_back(ConstantLengthValue); 18178 } 18179 Base = TempOASE->getBase()->IgnoreParenImpCasts(); 18180 } 18181 18182 // If we have a single element, we don't need to add the implicit lengths. 18183 if (!SingleElement) { 18184 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) { 18185 // Has implicit length 1! 18186 ArraySizes.push_back(llvm::APSInt::get(1)); 18187 Base = TempASE->getBase()->IgnoreParenImpCasts(); 18188 } 18189 } 18190 18191 // This array section can be privatized as a single value or as a constant 18192 // sized array. 18193 return true; 18194 } 18195 18196 static BinaryOperatorKind 18197 getRelatedCompoundReductionOp(BinaryOperatorKind BOK) { 18198 if (BOK == BO_Add) 18199 return BO_AddAssign; 18200 if (BOK == BO_Mul) 18201 return BO_MulAssign; 18202 if (BOK == BO_And) 18203 return BO_AndAssign; 18204 if (BOK == BO_Or) 18205 return BO_OrAssign; 18206 if (BOK == BO_Xor) 18207 return BO_XorAssign; 18208 return BOK; 18209 } 18210 18211 static bool actOnOMPReductionKindClause( 18212 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind, 18213 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, 18214 SourceLocation ColonLoc, SourceLocation EndLoc, 18215 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, 18216 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) { 18217 DeclarationName DN = ReductionId.getName(); 18218 OverloadedOperatorKind OOK = DN.getCXXOverloadedOperator(); 18219 BinaryOperatorKind BOK = BO_Comma; 18220 18221 ASTContext &Context = S.Context; 18222 // OpenMP [2.14.3.6, reduction clause] 18223 // C 18224 // reduction-identifier is either an identifier or one of the following 18225 // operators: +, -, *, &, |, ^, && and || 18226 // C++ 18227 // reduction-identifier is either an id-expression or one of the following 18228 // operators: +, -, *, &, |, ^, && and || 18229 switch (OOK) { 18230 case OO_Plus: 18231 BOK = BO_Add; 18232 break; 18233 case OO_Minus: 18234 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to 18235 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed 18236 // reduction identifier. 18237 if (S.LangOpts.OpenMP > 52) 18238 BOK = BO_Comma; 18239 else 18240 BOK = BO_Add; 18241 break; 18242 case OO_Star: 18243 BOK = BO_Mul; 18244 break; 18245 case OO_Amp: 18246 BOK = BO_And; 18247 break; 18248 case OO_Pipe: 18249 BOK = BO_Or; 18250 break; 18251 case OO_Caret: 18252 BOK = BO_Xor; 18253 break; 18254 case OO_AmpAmp: 18255 BOK = BO_LAnd; 18256 break; 18257 case OO_PipePipe: 18258 BOK = BO_LOr; 18259 break; 18260 case OO_New: 18261 case OO_Delete: 18262 case OO_Array_New: 18263 case OO_Array_Delete: 18264 case OO_Slash: 18265 case OO_Percent: 18266 case OO_Tilde: 18267 case OO_Exclaim: 18268 case OO_Equal: 18269 case OO_Less: 18270 case OO_Greater: 18271 case OO_LessEqual: 18272 case OO_GreaterEqual: 18273 case OO_PlusEqual: 18274 case OO_MinusEqual: 18275 case OO_StarEqual: 18276 case OO_SlashEqual: 18277 case OO_PercentEqual: 18278 case OO_CaretEqual: 18279 case OO_AmpEqual: 18280 case OO_PipeEqual: 18281 case OO_LessLess: 18282 case OO_GreaterGreater: 18283 case OO_LessLessEqual: 18284 case OO_GreaterGreaterEqual: 18285 case OO_EqualEqual: 18286 case OO_ExclaimEqual: 18287 case OO_Spaceship: 18288 case OO_PlusPlus: 18289 case OO_MinusMinus: 18290 case OO_Comma: 18291 case OO_ArrowStar: 18292 case OO_Arrow: 18293 case OO_Call: 18294 case OO_Subscript: 18295 case OO_Conditional: 18296 case OO_Coawait: 18297 case NUM_OVERLOADED_OPERATORS: 18298 llvm_unreachable("Unexpected reduction identifier"); 18299 case OO_None: 18300 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) { 18301 if (II->isStr("max")) 18302 BOK = BO_GT; 18303 else if (II->isStr("min")) 18304 BOK = BO_LT; 18305 } 18306 break; 18307 } 18308 18309 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions 18310 // A reduction clause with the minus (-) operator was deprecated 18311 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52) 18312 S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated); 18313 18314 SourceRange ReductionIdRange; 18315 if (ReductionIdScopeSpec.isValid()) 18316 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc()); 18317 else 18318 ReductionIdRange.setBegin(ReductionId.getBeginLoc()); 18319 ReductionIdRange.setEnd(ReductionId.getEndLoc()); 18320 18321 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end(); 18322 bool FirstIter = true; 18323 for (Expr *RefExpr : VarList) { 18324 assert(RefExpr && "nullptr expr in OpenMP reduction clause."); 18325 // OpenMP [2.1, C/C++] 18326 // A list item is a variable or array section, subject to the restrictions 18327 // specified in Section 2.4 on page 42 and in each of the sections 18328 // describing clauses and directives for which a list appears. 18329 // OpenMP [2.14.3.3, Restrictions, p.1] 18330 // A variable that is part of another variable (as an array or 18331 // structure element) cannot appear in a private clause. 18332 if (!FirstIter && IR != ER) 18333 ++IR; 18334 FirstIter = false; 18335 SourceLocation ELoc; 18336 SourceRange ERange; 18337 Expr *SimpleRefExpr = RefExpr; 18338 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange, 18339 /*AllowArraySection=*/true); 18340 if (Res.second) { 18341 // Try to find 'declare reduction' corresponding construct before using 18342 // builtin/overloaded operators. 18343 QualType Type = Context.DependentTy; 18344 CXXCastPath BasePath; 18345 ExprResult DeclareReductionRef = buildDeclareReductionRef( 18346 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec, 18347 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR); 18348 Expr *ReductionOp = nullptr; 18349 if (S.CurContext->isDependentContext() && 18350 (DeclareReductionRef.isUnset() || 18351 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) 18352 ReductionOp = DeclareReductionRef.get(); 18353 // It will be analyzed later. 18354 RD.push(RefExpr, ReductionOp); 18355 } 18356 ValueDecl *D = Res.first; 18357 if (!D) 18358 continue; 18359 18360 Expr *TaskgroupDescriptor = nullptr; 18361 QualType Type; 18362 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens()); 18363 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens()); 18364 if (ASE) { 18365 Type = ASE->getType().getNonReferenceType(); 18366 } else if (OASE) { 18367 QualType BaseType = 18368 ArraySectionExpr::getBaseOriginalType(OASE->getBase()); 18369 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe()) 18370 Type = ATy->getElementType(); 18371 else 18372 Type = BaseType->getPointeeType(); 18373 Type = Type.getNonReferenceType(); 18374 } else { 18375 Type = Context.getBaseElementType(D->getType().getNonReferenceType()); 18376 } 18377 auto *VD = dyn_cast<VarDecl>(D); 18378 18379 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3] 18380 // A variable that appears in a private clause must not have an incomplete 18381 // type or a reference type. 18382 if (S.RequireCompleteType(ELoc, D->getType(), 18383 diag::err_omp_reduction_incomplete_type)) 18384 continue; 18385 // OpenMP [2.14.3.6, reduction clause, Restrictions] 18386 // A list item that appears in a reduction clause must not be 18387 // const-qualified. 18388 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc, 18389 /*AcceptIfMutable*/ false, ASE || OASE)) 18390 continue; 18391 18392 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective(); 18393 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4] 18394 // If a list-item is a reference type then it must bind to the same object 18395 // for all threads of the team. 18396 if (!ASE && !OASE) { 18397 if (VD) { 18398 VarDecl *VDDef = VD->getDefinition(); 18399 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) { 18400 DSARefChecker Check(Stack); 18401 if (Check.Visit(VDDef->getInit())) { 18402 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg) 18403 << getOpenMPClauseName(ClauseKind) << ERange; 18404 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef; 18405 continue; 18406 } 18407 } 18408 } 18409 18410 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced 18411 // in a Construct] 18412 // Variables with the predetermined data-sharing attributes may not be 18413 // listed in data-sharing attributes clauses, except for the cases 18414 // listed below. For these exceptions only, listing a predetermined 18415 // variable in a data-sharing attribute clause is allowed and overrides 18416 // the variable's predetermined data-sharing attributes. 18417 // OpenMP [2.14.3.6, Restrictions, p.3] 18418 // Any number of reduction clauses can be specified on the directive, 18419 // but a list item can appear only once in the reduction clauses for that 18420 // directive. 18421 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false); 18422 if (DVar.CKind == OMPC_reduction) { 18423 S.Diag(ELoc, diag::err_omp_once_referenced) 18424 << getOpenMPClauseName(ClauseKind); 18425 if (DVar.RefExpr) 18426 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced); 18427 continue; 18428 } 18429 if (DVar.CKind != OMPC_unknown) { 18430 S.Diag(ELoc, diag::err_omp_wrong_dsa) 18431 << getOpenMPClauseName(DVar.CKind) 18432 << getOpenMPClauseName(OMPC_reduction); 18433 reportOriginalDsa(S, Stack, D, DVar); 18434 continue; 18435 } 18436 18437 // OpenMP [2.14.3.6, Restrictions, p.1] 18438 // A list item that appears in a reduction clause of a worksharing 18439 // construct must be shared in the parallel regions to which any of the 18440 // worksharing regions arising from the worksharing construct bind. 18441 if (isOpenMPWorksharingDirective(CurrDir) && 18442 !isOpenMPParallelDirective(CurrDir) && 18443 !isOpenMPTeamsDirective(CurrDir)) { 18444 DVar = Stack->getImplicitDSA(D, true); 18445 if (DVar.CKind != OMPC_shared) { 18446 S.Diag(ELoc, diag::err_omp_required_access) 18447 << getOpenMPClauseName(OMPC_reduction) 18448 << getOpenMPClauseName(OMPC_shared); 18449 reportOriginalDsa(S, Stack, D, DVar); 18450 continue; 18451 } 18452 } 18453 } else { 18454 // Threadprivates cannot be shared between threads, so dignose if the base 18455 // is a threadprivate variable. 18456 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false); 18457 if (DVar.CKind == OMPC_threadprivate) { 18458 S.Diag(ELoc, diag::err_omp_wrong_dsa) 18459 << getOpenMPClauseName(DVar.CKind) 18460 << getOpenMPClauseName(OMPC_reduction); 18461 reportOriginalDsa(S, Stack, D, DVar); 18462 continue; 18463 } 18464 } 18465 18466 // Try to find 'declare reduction' corresponding construct before using 18467 // builtin/overloaded operators. 18468 CXXCastPath BasePath; 18469 ExprResult DeclareReductionRef = buildDeclareReductionRef( 18470 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec, 18471 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR); 18472 if (DeclareReductionRef.isInvalid()) 18473 continue; 18474 if (S.CurContext->isDependentContext() && 18475 (DeclareReductionRef.isUnset() || 18476 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) { 18477 RD.push(RefExpr, DeclareReductionRef.get()); 18478 continue; 18479 } 18480 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) { 18481 // Not allowed reduction identifier is found. 18482 if (S.LangOpts.OpenMP > 52) 18483 S.Diag(ReductionId.getBeginLoc(), 18484 diag::err_omp_unknown_reduction_identifier_since_omp_6_0) 18485 << Type << ReductionIdRange; 18486 else 18487 S.Diag(ReductionId.getBeginLoc(), 18488 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0) 18489 << Type << ReductionIdRange; 18490 continue; 18491 } 18492 18493 // OpenMP [2.14.3.6, reduction clause, Restrictions] 18494 // The type of a list item that appears in a reduction clause must be valid 18495 // for the reduction-identifier. For a max or min reduction in C, the type 18496 // of the list item must be an allowed arithmetic data type: char, int, 18497 // float, double, or _Bool, possibly modified with long, short, signed, or 18498 // unsigned. For a max or min reduction in C++, the type of the list item 18499 // must be an allowed arithmetic data type: char, wchar_t, int, float, 18500 // double, or bool, possibly modified with long, short, signed, or unsigned. 18501 if (DeclareReductionRef.isUnset()) { 18502 if ((BOK == BO_GT || BOK == BO_LT) && 18503 !(Type->isScalarType() || 18504 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) { 18505 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg) 18506 << getOpenMPClauseName(ClauseKind) << S.getLangOpts().CPlusPlus; 18507 if (!ASE && !OASE) { 18508 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) == 18509 VarDecl::DeclarationOnly; 18510 S.Diag(D->getLocation(), 18511 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 18512 << D; 18513 } 18514 continue; 18515 } 18516 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) && 18517 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) { 18518 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg) 18519 << getOpenMPClauseName(ClauseKind); 18520 if (!ASE && !OASE) { 18521 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) == 18522 VarDecl::DeclarationOnly; 18523 S.Diag(D->getLocation(), 18524 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 18525 << D; 18526 } 18527 continue; 18528 } 18529 } 18530 18531 Type = Type.getNonLValueExprType(Context).getUnqualifiedType(); 18532 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs", 18533 D->hasAttrs() ? &D->getAttrs() : nullptr); 18534 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(), 18535 D->hasAttrs() ? &D->getAttrs() : nullptr); 18536 QualType PrivateTy = Type; 18537 18538 // Try if we can determine constant lengths for all array sections and avoid 18539 // the VLA. 18540 bool ConstantLengthOASE = false; 18541 if (OASE) { 18542 bool SingleElement; 18543 llvm::SmallVector<llvm::APSInt, 4> ArraySizes; 18544 ConstantLengthOASE = checkOMPArraySectionConstantForReduction( 18545 Context, OASE, SingleElement, ArraySizes); 18546 18547 // If we don't have a single element, we must emit a constant array type. 18548 if (ConstantLengthOASE && !SingleElement) { 18549 for (llvm::APSInt &Size : ArraySizes) 18550 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr, 18551 ArraySizeModifier::Normal, 18552 /*IndexTypeQuals=*/0); 18553 } 18554 } 18555 18556 if ((OASE && !ConstantLengthOASE) || 18557 (!OASE && !ASE && 18558 D->getType().getNonReferenceType()->isVariablyModifiedType())) { 18559 if (!Context.getTargetInfo().isVLASupported()) { 18560 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) { 18561 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE; 18562 S.Diag(ELoc, diag::note_vla_unsupported); 18563 continue; 18564 } else { 18565 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE; 18566 S.targetDiag(ELoc, diag::note_vla_unsupported); 18567 } 18568 } 18569 // For arrays/array sections only: 18570 // Create pseudo array type for private copy. The size for this array will 18571 // be generated during codegen. 18572 // For array subscripts or single variables Private Ty is the same as Type 18573 // (type of the variable or single array element). 18574 PrivateTy = Context.getVariableArrayType( 18575 Type, 18576 new (Context) 18577 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue), 18578 ArraySizeModifier::Normal, /*IndexTypeQuals=*/0, SourceRange()); 18579 } else if (!ASE && !OASE && 18580 Context.getAsArrayType(D->getType().getNonReferenceType())) { 18581 PrivateTy = D->getType().getNonReferenceType(); 18582 } 18583 // Private copy. 18584 VarDecl *PrivateVD = 18585 buildVarDecl(S, ELoc, PrivateTy, D->getName(), 18586 D->hasAttrs() ? &D->getAttrs() : nullptr, 18587 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr); 18588 // Add initializer for private variable. 18589 Expr *Init = nullptr; 18590 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc); 18591 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc); 18592 if (DeclareReductionRef.isUsable()) { 18593 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>(); 18594 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl()); 18595 if (DRD->getInitializer()) { 18596 Init = DRDRef; 18597 RHSVD->setInit(DRDRef); 18598 RHSVD->setInitStyle(VarDecl::CallInit); 18599 } 18600 } else { 18601 switch (BOK) { 18602 case BO_Add: 18603 case BO_Xor: 18604 case BO_Or: 18605 case BO_LOr: 18606 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'. 18607 if (Type->isScalarType() || Type->isAnyComplexType()) 18608 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get(); 18609 break; 18610 case BO_Mul: 18611 case BO_LAnd: 18612 if (Type->isScalarType() || Type->isAnyComplexType()) { 18613 // '*' and '&&' reduction ops - initializer is '1'. 18614 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get(); 18615 } 18616 break; 18617 case BO_And: { 18618 // '&' reduction op - initializer is '~0'. 18619 QualType OrigType = Type; 18620 if (auto *ComplexTy = OrigType->getAs<ComplexType>()) 18621 Type = ComplexTy->getElementType(); 18622 if (Type->isRealFloatingType()) { 18623 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue( 18624 Context.getFloatTypeSemantics(Type)); 18625 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true, 18626 Type, ELoc); 18627 } else if (Type->isScalarType()) { 18628 uint64_t Size = Context.getTypeSize(Type); 18629 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0); 18630 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size); 18631 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc); 18632 } 18633 if (Init && OrigType->isAnyComplexType()) { 18634 // Init = 0xFFFF + 0xFFFFi; 18635 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType); 18636 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get(); 18637 } 18638 Type = OrigType; 18639 break; 18640 } 18641 case BO_LT: 18642 case BO_GT: { 18643 // 'min' reduction op - initializer is 'Largest representable number in 18644 // the reduction list item type'. 18645 // 'max' reduction op - initializer is 'Least representable number in 18646 // the reduction list item type'. 18647 if (Type->isIntegerType() || Type->isPointerType()) { 18648 bool IsSigned = Type->hasSignedIntegerRepresentation(); 18649 uint64_t Size = Context.getTypeSize(Type); 18650 QualType IntTy = 18651 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned); 18652 llvm::APInt InitValue = 18653 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size) 18654 : llvm::APInt::getMinValue(Size) 18655 : IsSigned ? llvm::APInt::getSignedMaxValue(Size) 18656 : llvm::APInt::getMaxValue(Size); 18657 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc); 18658 if (Type->isPointerType()) { 18659 // Cast to pointer type. 18660 ExprResult CastExpr = S.BuildCStyleCastExpr( 18661 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init); 18662 if (CastExpr.isInvalid()) 18663 continue; 18664 Init = CastExpr.get(); 18665 } 18666 } else if (Type->isRealFloatingType()) { 18667 llvm::APFloat InitValue = llvm::APFloat::getLargest( 18668 Context.getFloatTypeSemantics(Type), BOK != BO_LT); 18669 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true, 18670 Type, ELoc); 18671 } 18672 break; 18673 } 18674 case BO_PtrMemD: 18675 case BO_PtrMemI: 18676 case BO_MulAssign: 18677 case BO_Div: 18678 case BO_Rem: 18679 case BO_Sub: 18680 case BO_Shl: 18681 case BO_Shr: 18682 case BO_LE: 18683 case BO_GE: 18684 case BO_EQ: 18685 case BO_NE: 18686 case BO_Cmp: 18687 case BO_AndAssign: 18688 case BO_XorAssign: 18689 case BO_OrAssign: 18690 case BO_Assign: 18691 case BO_AddAssign: 18692 case BO_SubAssign: 18693 case BO_DivAssign: 18694 case BO_RemAssign: 18695 case BO_ShlAssign: 18696 case BO_ShrAssign: 18697 case BO_Comma: 18698 llvm_unreachable("Unexpected reduction operation"); 18699 } 18700 } 18701 if (Init && DeclareReductionRef.isUnset()) { 18702 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false); 18703 // Store initializer for single element in private copy. Will be used 18704 // during codegen. 18705 PrivateVD->setInit(RHSVD->getInit()); 18706 PrivateVD->setInitStyle(RHSVD->getInitStyle()); 18707 } else if (!Init) { 18708 S.ActOnUninitializedDecl(RHSVD); 18709 // Store initializer for single element in private copy. Will be used 18710 // during codegen. 18711 PrivateVD->setInit(RHSVD->getInit()); 18712 PrivateVD->setInitStyle(RHSVD->getInitStyle()); 18713 } 18714 if (RHSVD->isInvalidDecl()) 18715 continue; 18716 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) { 18717 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible) 18718 << Type << ReductionIdRange; 18719 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) == 18720 VarDecl::DeclarationOnly; 18721 S.Diag(D->getLocation(), 18722 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 18723 << D; 18724 continue; 18725 } 18726 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc); 18727 ExprResult ReductionOp; 18728 if (DeclareReductionRef.isUsable()) { 18729 QualType RedTy = DeclareReductionRef.get()->getType(); 18730 QualType PtrRedTy = Context.getPointerType(RedTy); 18731 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE); 18732 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE); 18733 if (!BasePath.empty()) { 18734 LHS = S.DefaultLvalueConversion(LHS.get()); 18735 RHS = S.DefaultLvalueConversion(RHS.get()); 18736 LHS = ImplicitCastExpr::Create( 18737 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath, 18738 LHS.get()->getValueKind(), FPOptionsOverride()); 18739 RHS = ImplicitCastExpr::Create( 18740 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath, 18741 RHS.get()->getValueKind(), FPOptionsOverride()); 18742 } 18743 FunctionProtoType::ExtProtoInfo EPI; 18744 QualType Params[] = {PtrRedTy, PtrRedTy}; 18745 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI); 18746 auto *OVE = new (Context) OpaqueValueExpr( 18747 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary, 18748 S.DefaultLvalueConversion(DeclareReductionRef.get()).get()); 18749 Expr *Args[] = {LHS.get(), RHS.get()}; 18750 ReductionOp = 18751 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc, 18752 S.CurFPFeatureOverrides()); 18753 } else { 18754 BinaryOperatorKind CombBOK = getRelatedCompoundReductionOp(BOK); 18755 if (Type->isRecordType() && CombBOK != BOK) { 18756 Sema::TentativeAnalysisScope Trap(S); 18757 ReductionOp = 18758 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), 18759 CombBOK, LHSDRE, RHSDRE); 18760 } 18761 if (!ReductionOp.isUsable()) { 18762 ReductionOp = 18763 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK, 18764 LHSDRE, RHSDRE); 18765 if (ReductionOp.isUsable()) { 18766 if (BOK != BO_LT && BOK != BO_GT) { 18767 ReductionOp = 18768 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), 18769 BO_Assign, LHSDRE, ReductionOp.get()); 18770 } else { 18771 auto *ConditionalOp = new (Context) 18772 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc, 18773 RHSDRE, Type, VK_LValue, OK_Ordinary); 18774 ReductionOp = 18775 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), 18776 BO_Assign, LHSDRE, ConditionalOp); 18777 } 18778 } 18779 } 18780 if (ReductionOp.isUsable()) 18781 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(), 18782 /*DiscardedValue*/ false); 18783 if (!ReductionOp.isUsable()) 18784 continue; 18785 } 18786 18787 // Add copy operations for inscan reductions. 18788 // LHS = RHS; 18789 ExprResult CopyOpRes, TempArrayRes, TempArrayElem; 18790 if (ClauseKind == OMPC_reduction && 18791 RD.RedModifier == OMPC_REDUCTION_inscan) { 18792 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE); 18793 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE, 18794 RHS.get()); 18795 if (!CopyOpRes.isUsable()) 18796 continue; 18797 CopyOpRes = 18798 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true); 18799 if (!CopyOpRes.isUsable()) 18800 continue; 18801 // For simd directive and simd-based directives in simd mode no need to 18802 // construct temp array, need just a single temp element. 18803 if (Stack->getCurrentDirective() == OMPD_simd || 18804 (S.getLangOpts().OpenMPSimd && 18805 isOpenMPSimdDirective(Stack->getCurrentDirective()))) { 18806 VarDecl *TempArrayVD = 18807 buildVarDecl(S, ELoc, PrivateTy, D->getName(), 18808 D->hasAttrs() ? &D->getAttrs() : nullptr); 18809 // Add a constructor to the temp decl. 18810 S.ActOnUninitializedDecl(TempArrayVD); 18811 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc); 18812 } else { 18813 // Build temp array for prefix sum. 18814 auto *Dim = new (S.Context) 18815 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue); 18816 QualType ArrayTy = S.Context.getVariableArrayType( 18817 PrivateTy, Dim, ArraySizeModifier::Normal, 18818 /*IndexTypeQuals=*/0, {ELoc, ELoc}); 18819 VarDecl *TempArrayVD = 18820 buildVarDecl(S, ELoc, ArrayTy, D->getName(), 18821 D->hasAttrs() ? &D->getAttrs() : nullptr); 18822 // Add a constructor to the temp decl. 18823 S.ActOnUninitializedDecl(TempArrayVD); 18824 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc); 18825 TempArrayElem = 18826 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get()); 18827 auto *Idx = new (S.Context) 18828 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue); 18829 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(), 18830 ELoc, Idx, ELoc); 18831 } 18832 } 18833 18834 // OpenMP [2.15.4.6, Restrictions, p.2] 18835 // A list item that appears in an in_reduction clause of a task construct 18836 // must appear in a task_reduction clause of a construct associated with a 18837 // taskgroup region that includes the participating task in its taskgroup 18838 // set. The construct associated with the innermost region that meets this 18839 // condition must specify the same reduction-identifier as the in_reduction 18840 // clause. 18841 if (ClauseKind == OMPC_in_reduction) { 18842 SourceRange ParentSR; 18843 BinaryOperatorKind ParentBOK; 18844 const Expr *ParentReductionOp = nullptr; 18845 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr; 18846 DSAStackTy::DSAVarData ParentBOKDSA = 18847 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK, 18848 ParentBOKTD); 18849 DSAStackTy::DSAVarData ParentReductionOpDSA = 18850 Stack->getTopMostTaskgroupReductionData( 18851 D, ParentSR, ParentReductionOp, ParentReductionOpTD); 18852 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown; 18853 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown; 18854 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) || 18855 (DeclareReductionRef.isUsable() && IsParentBOK) || 18856 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) { 18857 bool EmitError = true; 18858 if (IsParentReductionOp && DeclareReductionRef.isUsable()) { 18859 llvm::FoldingSetNodeID RedId, ParentRedId; 18860 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true); 18861 DeclareReductionRef.get()->Profile(RedId, Context, 18862 /*Canonical=*/true); 18863 EmitError = RedId != ParentRedId; 18864 } 18865 if (EmitError) { 18866 S.Diag(ReductionId.getBeginLoc(), 18867 diag::err_omp_reduction_identifier_mismatch) 18868 << ReductionIdRange << RefExpr->getSourceRange(); 18869 S.Diag(ParentSR.getBegin(), 18870 diag::note_omp_previous_reduction_identifier) 18871 << ParentSR 18872 << (IsParentBOK ? ParentBOKDSA.RefExpr 18873 : ParentReductionOpDSA.RefExpr) 18874 ->getSourceRange(); 18875 continue; 18876 } 18877 } 18878 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD; 18879 } 18880 18881 DeclRefExpr *Ref = nullptr; 18882 Expr *VarsExpr = RefExpr->IgnoreParens(); 18883 if (!VD && !S.CurContext->isDependentContext()) { 18884 if (ASE || OASE) { 18885 TransformExprToCaptures RebuildToCapture(S, D); 18886 VarsExpr = 18887 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get(); 18888 Ref = RebuildToCapture.getCapturedExpr(); 18889 } else { 18890 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false); 18891 } 18892 if (!S.OpenMP().isOpenMPCapturedDecl(D)) { 18893 RD.ExprCaptures.emplace_back(Ref->getDecl()); 18894 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) { 18895 ExprResult RefRes = S.DefaultLvalueConversion(Ref); 18896 if (!RefRes.isUsable()) 18897 continue; 18898 ExprResult PostUpdateRes = 18899 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr, 18900 RefRes.get()); 18901 if (!PostUpdateRes.isUsable()) 18902 continue; 18903 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) || 18904 Stack->getCurrentDirective() == OMPD_taskgroup) { 18905 S.Diag(RefExpr->getExprLoc(), 18906 diag::err_omp_reduction_non_addressable_expression) 18907 << RefExpr->getSourceRange(); 18908 continue; 18909 } 18910 RD.ExprPostUpdates.emplace_back( 18911 S.IgnoredValueConversions(PostUpdateRes.get()).get()); 18912 } 18913 } 18914 } 18915 // All reduction items are still marked as reduction (to do not increase 18916 // code base size). 18917 unsigned Modifier = RD.RedModifier; 18918 // Consider task_reductions as reductions with task modifier. Required for 18919 // correct analysis of in_reduction clauses. 18920 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction) 18921 Modifier = OMPC_REDUCTION_task; 18922 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier, 18923 ASE || OASE); 18924 if (Modifier == OMPC_REDUCTION_task && 18925 (CurrDir == OMPD_taskgroup || 18926 ((isOpenMPParallelDirective(CurrDir) || 18927 isOpenMPWorksharingDirective(CurrDir)) && 18928 !isOpenMPSimdDirective(CurrDir)))) { 18929 if (DeclareReductionRef.isUsable()) 18930 Stack->addTaskgroupReductionData(D, ReductionIdRange, 18931 DeclareReductionRef.get()); 18932 else 18933 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK); 18934 } 18935 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(), 18936 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(), 18937 TempArrayElem.get()); 18938 } 18939 return RD.Vars.empty(); 18940 } 18941 18942 OMPClause *SemaOpenMP::ActOnOpenMPReductionClause( 18943 ArrayRef<Expr *> VarList, OpenMPReductionClauseModifier Modifier, 18944 SourceLocation StartLoc, SourceLocation LParenLoc, 18945 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, 18946 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, 18947 ArrayRef<Expr *> UnresolvedReductions) { 18948 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) { 18949 Diag(LParenLoc, diag::err_omp_unexpected_clause_value) 18950 << getListOfPossibleValues(OMPC_reduction, /*First=*/0, 18951 /*Last=*/OMPC_REDUCTION_unknown) 18952 << getOpenMPClauseName(OMPC_reduction); 18953 return nullptr; 18954 } 18955 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions 18956 // A reduction clause with the inscan reduction-modifier may only appear on a 18957 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd 18958 // construct, a parallel worksharing-loop construct or a parallel 18959 // worksharing-loop SIMD construct. 18960 if (Modifier == OMPC_REDUCTION_inscan && 18961 (DSAStack->getCurrentDirective() != OMPD_for && 18962 DSAStack->getCurrentDirective() != OMPD_for_simd && 18963 DSAStack->getCurrentDirective() != OMPD_simd && 18964 DSAStack->getCurrentDirective() != OMPD_parallel_for && 18965 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) { 18966 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction); 18967 return nullptr; 18968 } 18969 18970 ReductionData RD(VarList.size(), Modifier); 18971 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_reduction, VarList, 18972 StartLoc, LParenLoc, ColonLoc, EndLoc, 18973 ReductionIdScopeSpec, ReductionId, 18974 UnresolvedReductions, RD)) 18975 return nullptr; 18976 18977 return OMPReductionClause::Create( 18978 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc, 18979 Modifier, RD.Vars, 18980 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId, 18981 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps, 18982 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems, 18983 buildPreInits(getASTContext(), RD.ExprCaptures), 18984 buildPostUpdate(SemaRef, RD.ExprPostUpdates)); 18985 } 18986 18987 OMPClause *SemaOpenMP::ActOnOpenMPTaskReductionClause( 18988 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, 18989 SourceLocation ColonLoc, SourceLocation EndLoc, 18990 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, 18991 ArrayRef<Expr *> UnresolvedReductions) { 18992 ReductionData RD(VarList.size()); 18993 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_task_reduction, 18994 VarList, StartLoc, LParenLoc, ColonLoc, 18995 EndLoc, ReductionIdScopeSpec, ReductionId, 18996 UnresolvedReductions, RD)) 18997 return nullptr; 18998 18999 return OMPTaskReductionClause::Create( 19000 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars, 19001 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId, 19002 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, 19003 buildPreInits(getASTContext(), RD.ExprCaptures), 19004 buildPostUpdate(SemaRef, RD.ExprPostUpdates)); 19005 } 19006 19007 OMPClause *SemaOpenMP::ActOnOpenMPInReductionClause( 19008 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, 19009 SourceLocation ColonLoc, SourceLocation EndLoc, 19010 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, 19011 ArrayRef<Expr *> UnresolvedReductions) { 19012 ReductionData RD(VarList.size()); 19013 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_in_reduction, VarList, 19014 StartLoc, LParenLoc, ColonLoc, EndLoc, 19015 ReductionIdScopeSpec, ReductionId, 19016 UnresolvedReductions, RD)) 19017 return nullptr; 19018 19019 return OMPInReductionClause::Create( 19020 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars, 19021 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId, 19022 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors, 19023 buildPreInits(getASTContext(), RD.ExprCaptures), 19024 buildPostUpdate(SemaRef, RD.ExprPostUpdates)); 19025 } 19026 19027 bool SemaOpenMP::CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, 19028 SourceLocation LinLoc) { 19029 if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) || 19030 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) { 19031 Diag(LinLoc, diag::err_omp_wrong_linear_modifier) 19032 << getLangOpts().CPlusPlus; 19033 return true; 19034 } 19035 return false; 19036 } 19037 19038 bool SemaOpenMP::CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc, 19039 OpenMPLinearClauseKind LinKind, 19040 QualType Type, bool IsDeclareSimd) { 19041 const auto *VD = dyn_cast_or_null<VarDecl>(D); 19042 // A variable must not have an incomplete type or a reference type. 19043 if (SemaRef.RequireCompleteType(ELoc, Type, 19044 diag::err_omp_linear_incomplete_type)) 19045 return true; 19046 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) && 19047 !Type->isReferenceType()) { 19048 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference) 19049 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind); 19050 return true; 19051 } 19052 Type = Type.getNonReferenceType(); 19053 19054 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions] 19055 // A variable that is privatized must not have a const-qualified type 19056 // unless it is of class type with a mutable member. This restriction does 19057 // not apply to the firstprivate clause, nor to the linear clause on 19058 // declarative directives (like declare simd). 19059 if (!IsDeclareSimd && 19060 rejectConstNotMutableType(SemaRef, D, Type, OMPC_linear, ELoc)) 19061 return true; 19062 19063 // A list item must be of integral or pointer type. 19064 Type = Type.getUnqualifiedType().getCanonicalType(); 19065 const auto *Ty = Type.getTypePtrOrNull(); 19066 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() && 19067 !Ty->isIntegralType(getASTContext()) && !Ty->isPointerType())) { 19068 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type; 19069 if (D) { 19070 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) == 19071 VarDecl::DeclarationOnly; 19072 Diag(D->getLocation(), 19073 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 19074 << D; 19075 } 19076 return true; 19077 } 19078 return false; 19079 } 19080 19081 OMPClause *SemaOpenMP::ActOnOpenMPLinearClause( 19082 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc, 19083 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind, 19084 SourceLocation LinLoc, SourceLocation ColonLoc, 19085 SourceLocation StepModifierLoc, SourceLocation EndLoc) { 19086 SmallVector<Expr *, 8> Vars; 19087 SmallVector<Expr *, 8> Privates; 19088 SmallVector<Expr *, 8> Inits; 19089 SmallVector<Decl *, 4> ExprCaptures; 19090 SmallVector<Expr *, 4> ExprPostUpdates; 19091 // OpenMP 5.2 [Section 5.4.6, linear clause] 19092 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or 19093 // 'ref' 19094 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step && 19095 getLangOpts().OpenMP >= 52) 19096 Diag(Step->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive); 19097 if (CheckOpenMPLinearModifier(LinKind, LinLoc)) 19098 LinKind = OMPC_LINEAR_val; 19099 for (Expr *RefExpr : VarList) { 19100 assert(RefExpr && "NULL expr in OpenMP linear clause."); 19101 SourceLocation ELoc; 19102 SourceRange ERange; 19103 Expr *SimpleRefExpr = RefExpr; 19104 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); 19105 if (Res.second) { 19106 // It will be analyzed later. 19107 Vars.push_back(RefExpr); 19108 Privates.push_back(nullptr); 19109 Inits.push_back(nullptr); 19110 } 19111 ValueDecl *D = Res.first; 19112 if (!D) 19113 continue; 19114 19115 QualType Type = D->getType(); 19116 auto *VD = dyn_cast<VarDecl>(D); 19117 19118 // OpenMP [2.14.3.7, linear clause] 19119 // A list-item cannot appear in more than one linear clause. 19120 // A list-item that appears in a linear clause cannot appear in any 19121 // other data-sharing attribute clause. 19122 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false); 19123 if (DVar.RefExpr) { 19124 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind) 19125 << getOpenMPClauseName(OMPC_linear); 19126 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 19127 continue; 19128 } 19129 19130 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type)) 19131 continue; 19132 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType(); 19133 19134 // Build private copy of original var. 19135 VarDecl *Private = 19136 buildVarDecl(SemaRef, ELoc, Type, D->getName(), 19137 D->hasAttrs() ? &D->getAttrs() : nullptr, 19138 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr); 19139 DeclRefExpr *PrivateRef = buildDeclRefExpr(SemaRef, Private, Type, ELoc); 19140 // Build var to save initial value. 19141 VarDecl *Init = buildVarDecl(SemaRef, ELoc, Type, ".linear.start"); 19142 Expr *InitExpr; 19143 DeclRefExpr *Ref = nullptr; 19144 if (!VD && !SemaRef.CurContext->isDependentContext()) { 19145 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false); 19146 if (!isOpenMPCapturedDecl(D)) { 19147 ExprCaptures.push_back(Ref->getDecl()); 19148 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) { 19149 ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref); 19150 if (!RefRes.isUsable()) 19151 continue; 19152 ExprResult PostUpdateRes = 19153 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign, 19154 SimpleRefExpr, RefRes.get()); 19155 if (!PostUpdateRes.isUsable()) 19156 continue; 19157 ExprPostUpdates.push_back( 19158 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get()); 19159 } 19160 } 19161 } 19162 if (LinKind == OMPC_LINEAR_uval) 19163 InitExpr = VD ? VD->getInit() : SimpleRefExpr; 19164 else 19165 InitExpr = VD ? SimpleRefExpr : Ref; 19166 SemaRef.AddInitializerToDecl( 19167 Init, SemaRef.DefaultLvalueConversion(InitExpr).get(), 19168 /*DirectInit=*/false); 19169 DeclRefExpr *InitRef = buildDeclRefExpr(SemaRef, Init, Type, ELoc); 19170 19171 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref); 19172 Vars.push_back((VD || SemaRef.CurContext->isDependentContext()) 19173 ? RefExpr->IgnoreParens() 19174 : Ref); 19175 Privates.push_back(PrivateRef); 19176 Inits.push_back(InitRef); 19177 } 19178 19179 if (Vars.empty()) 19180 return nullptr; 19181 19182 Expr *StepExpr = Step; 19183 Expr *CalcStepExpr = nullptr; 19184 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() && 19185 !Step->isInstantiationDependent() && 19186 !Step->containsUnexpandedParameterPack()) { 19187 SourceLocation StepLoc = Step->getBeginLoc(); 19188 ExprResult Val = PerformOpenMPImplicitIntegerConversion(StepLoc, Step); 19189 if (Val.isInvalid()) 19190 return nullptr; 19191 StepExpr = Val.get(); 19192 19193 // Build var to save the step value. 19194 VarDecl *SaveVar = 19195 buildVarDecl(SemaRef, StepLoc, StepExpr->getType(), ".linear.step"); 19196 ExprResult SaveRef = 19197 buildDeclRefExpr(SemaRef, SaveVar, StepExpr->getType(), StepLoc); 19198 ExprResult CalcStep = SemaRef.BuildBinOp( 19199 SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.get(), StepExpr); 19200 CalcStep = 19201 SemaRef.ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue*/ false); 19202 19203 // Warn about zero linear step (it would be probably better specified as 19204 // making corresponding variables 'const'). 19205 if (std::optional<llvm::APSInt> Result = 19206 StepExpr->getIntegerConstantExpr(getASTContext())) { 19207 if (!Result->isNegative() && !Result->isStrictlyPositive()) 19208 Diag(StepLoc, diag::warn_omp_linear_step_zero) 19209 << Vars[0] << (Vars.size() > 1); 19210 } else if (CalcStep.isUsable()) { 19211 // Calculate the step beforehand instead of doing this on each iteration. 19212 // (This is not used if the number of iterations may be kfold-ed). 19213 CalcStepExpr = CalcStep.get(); 19214 } 19215 } 19216 19217 return OMPLinearClause::Create(getASTContext(), StartLoc, LParenLoc, LinKind, 19218 LinLoc, ColonLoc, StepModifierLoc, EndLoc, 19219 Vars, Privates, Inits, StepExpr, CalcStepExpr, 19220 buildPreInits(getASTContext(), ExprCaptures), 19221 buildPostUpdate(SemaRef, ExprPostUpdates)); 19222 } 19223 19224 static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, 19225 Expr *NumIterations, Sema &SemaRef, 19226 Scope *S, DSAStackTy *Stack) { 19227 // Walk the vars and build update/final expressions for the CodeGen. 19228 SmallVector<Expr *, 8> Updates; 19229 SmallVector<Expr *, 8> Finals; 19230 SmallVector<Expr *, 8> UsedExprs; 19231 Expr *Step = Clause.getStep(); 19232 Expr *CalcStep = Clause.getCalcStep(); 19233 // OpenMP [2.14.3.7, linear clause] 19234 // If linear-step is not specified it is assumed to be 1. 19235 if (!Step) 19236 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(); 19237 else if (CalcStep) 19238 Step = cast<BinaryOperator>(CalcStep)->getLHS(); 19239 bool HasErrors = false; 19240 auto CurInit = Clause.inits().begin(); 19241 auto CurPrivate = Clause.privates().begin(); 19242 OpenMPLinearClauseKind LinKind = Clause.getModifier(); 19243 for (Expr *RefExpr : Clause.varlists()) { 19244 SourceLocation ELoc; 19245 SourceRange ERange; 19246 Expr *SimpleRefExpr = RefExpr; 19247 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); 19248 ValueDecl *D = Res.first; 19249 if (Res.second || !D) { 19250 Updates.push_back(nullptr); 19251 Finals.push_back(nullptr); 19252 HasErrors = true; 19253 continue; 19254 } 19255 auto &&Info = Stack->isLoopControlVariable(D); 19256 // OpenMP [2.15.11, distribute simd Construct] 19257 // A list item may not appear in a linear clause, unless it is the loop 19258 // iteration variable. 19259 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) && 19260 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) { 19261 SemaRef.Diag(ELoc, 19262 diag::err_omp_linear_distribute_var_non_loop_iteration); 19263 Updates.push_back(nullptr); 19264 Finals.push_back(nullptr); 19265 HasErrors = true; 19266 continue; 19267 } 19268 Expr *InitExpr = *CurInit; 19269 19270 // Build privatized reference to the current linear var. 19271 auto *DE = cast<DeclRefExpr>(SimpleRefExpr); 19272 Expr *CapturedRef; 19273 if (LinKind == OMPC_LINEAR_uval) 19274 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit(); 19275 else 19276 CapturedRef = 19277 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()), 19278 DE->getType().getUnqualifiedType(), DE->getExprLoc(), 19279 /*RefersToCapture=*/true); 19280 19281 // Build update: Var = InitExpr + IV * Step 19282 ExprResult Update; 19283 if (!Info.first) 19284 Update = buildCounterUpdate( 19285 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step, 19286 /*Subtract=*/false, /*IsNonRectangularLB=*/false); 19287 else 19288 Update = *CurPrivate; 19289 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(), 19290 /*DiscardedValue*/ false); 19291 19292 // Build final: Var = PrivCopy; 19293 ExprResult Final; 19294 if (!Info.first) 19295 Final = SemaRef.BuildBinOp( 19296 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef, 19297 SemaRef.DefaultLvalueConversion(*CurPrivate).get()); 19298 else 19299 Final = *CurPrivate; 19300 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(), 19301 /*DiscardedValue*/ false); 19302 19303 if (!Update.isUsable() || !Final.isUsable()) { 19304 Updates.push_back(nullptr); 19305 Finals.push_back(nullptr); 19306 UsedExprs.push_back(nullptr); 19307 HasErrors = true; 19308 } else { 19309 Updates.push_back(Update.get()); 19310 Finals.push_back(Final.get()); 19311 if (!Info.first) 19312 UsedExprs.push_back(SimpleRefExpr); 19313 } 19314 ++CurInit; 19315 ++CurPrivate; 19316 } 19317 if (Expr *S = Clause.getStep()) 19318 UsedExprs.push_back(S); 19319 // Fill the remaining part with the nullptr. 19320 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr); 19321 Clause.setUpdates(Updates); 19322 Clause.setFinals(Finals); 19323 Clause.setUsedExprs(UsedExprs); 19324 return HasErrors; 19325 } 19326 19327 OMPClause *SemaOpenMP::ActOnOpenMPAlignedClause( 19328 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc, 19329 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) { 19330 SmallVector<Expr *, 8> Vars; 19331 for (Expr *RefExpr : VarList) { 19332 assert(RefExpr && "NULL expr in OpenMP linear clause."); 19333 SourceLocation ELoc; 19334 SourceRange ERange; 19335 Expr *SimpleRefExpr = RefExpr; 19336 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); 19337 if (Res.second) { 19338 // It will be analyzed later. 19339 Vars.push_back(RefExpr); 19340 } 19341 ValueDecl *D = Res.first; 19342 if (!D) 19343 continue; 19344 19345 QualType QType = D->getType(); 19346 auto *VD = dyn_cast<VarDecl>(D); 19347 19348 // OpenMP [2.8.1, simd construct, Restrictions] 19349 // The type of list items appearing in the aligned clause must be 19350 // array, pointer, reference to array, or reference to pointer. 19351 QType = QType.getNonReferenceType().getUnqualifiedType().getCanonicalType(); 19352 const Type *Ty = QType.getTypePtrOrNull(); 19353 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) { 19354 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr) 19355 << QType << getLangOpts().CPlusPlus << ERange; 19356 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) == 19357 VarDecl::DeclarationOnly; 19358 Diag(D->getLocation(), 19359 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 19360 << D; 19361 continue; 19362 } 19363 19364 // OpenMP [2.8.1, simd construct, Restrictions] 19365 // A list-item cannot appear in more than one aligned clause. 19366 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) { 19367 Diag(ELoc, diag::err_omp_used_in_clause_twice) 19368 << 0 << getOpenMPClauseName(OMPC_aligned) << ERange; 19369 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa) 19370 << getOpenMPClauseName(OMPC_aligned); 19371 continue; 19372 } 19373 19374 DeclRefExpr *Ref = nullptr; 19375 if (!VD && isOpenMPCapturedDecl(D)) 19376 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true); 19377 Vars.push_back(SemaRef 19378 .DefaultFunctionArrayConversion( 19379 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref) 19380 .get()); 19381 } 19382 19383 // OpenMP [2.8.1, simd construct, Description] 19384 // The parameter of the aligned clause, alignment, must be a constant 19385 // positive integer expression. 19386 // If no optional parameter is specified, implementation-defined default 19387 // alignments for SIMD instructions on the target platforms are assumed. 19388 if (Alignment != nullptr) { 19389 ExprResult AlignResult = 19390 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned); 19391 if (AlignResult.isInvalid()) 19392 return nullptr; 19393 Alignment = AlignResult.get(); 19394 } 19395 if (Vars.empty()) 19396 return nullptr; 19397 19398 return OMPAlignedClause::Create(getASTContext(), StartLoc, LParenLoc, 19399 ColonLoc, EndLoc, Vars, Alignment); 19400 } 19401 19402 OMPClause *SemaOpenMP::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList, 19403 SourceLocation StartLoc, 19404 SourceLocation LParenLoc, 19405 SourceLocation EndLoc) { 19406 SmallVector<Expr *, 8> Vars; 19407 SmallVector<Expr *, 8> SrcExprs; 19408 SmallVector<Expr *, 8> DstExprs; 19409 SmallVector<Expr *, 8> AssignmentOps; 19410 for (Expr *RefExpr : VarList) { 19411 assert(RefExpr && "NULL expr in OpenMP copyin clause."); 19412 if (isa<DependentScopeDeclRefExpr>(RefExpr)) { 19413 // It will be analyzed later. 19414 Vars.push_back(RefExpr); 19415 SrcExprs.push_back(nullptr); 19416 DstExprs.push_back(nullptr); 19417 AssignmentOps.push_back(nullptr); 19418 continue; 19419 } 19420 19421 SourceLocation ELoc = RefExpr->getExprLoc(); 19422 // OpenMP [2.1, C/C++] 19423 // A list item is a variable name. 19424 // OpenMP [2.14.4.1, Restrictions, p.1] 19425 // A list item that appears in a copyin clause must be threadprivate. 19426 auto *DE = dyn_cast<DeclRefExpr>(RefExpr); 19427 if (!DE || !isa<VarDecl>(DE->getDecl())) { 19428 Diag(ELoc, diag::err_omp_expected_var_name_member_expr) 19429 << 0 << RefExpr->getSourceRange(); 19430 continue; 19431 } 19432 19433 Decl *D = DE->getDecl(); 19434 auto *VD = cast<VarDecl>(D); 19435 19436 QualType Type = VD->getType(); 19437 if (Type->isDependentType() || Type->isInstantiationDependentType()) { 19438 // It will be analyzed later. 19439 Vars.push_back(DE); 19440 SrcExprs.push_back(nullptr); 19441 DstExprs.push_back(nullptr); 19442 AssignmentOps.push_back(nullptr); 19443 continue; 19444 } 19445 19446 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1] 19447 // A list item that appears in a copyin clause must be threadprivate. 19448 if (!DSAStack->isThreadPrivate(VD)) { 19449 Diag(ELoc, diag::err_omp_required_access) 19450 << getOpenMPClauseName(OMPC_copyin) 19451 << getOpenMPDirectiveName(OMPD_threadprivate); 19452 continue; 19453 } 19454 19455 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2] 19456 // A variable of class type (or array thereof) that appears in a 19457 // copyin clause requires an accessible, unambiguous copy assignment 19458 // operator for the class type. 19459 QualType ElemType = 19460 getASTContext().getBaseElementType(Type).getNonReferenceType(); 19461 VarDecl *SrcVD = 19462 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType.getUnqualifiedType(), 19463 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr); 19464 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr( 19465 SemaRef, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc()); 19466 VarDecl *DstVD = 19467 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType, ".copyin.dst", 19468 VD->hasAttrs() ? &VD->getAttrs() : nullptr); 19469 DeclRefExpr *PseudoDstExpr = 19470 buildDeclRefExpr(SemaRef, DstVD, ElemType, DE->getExprLoc()); 19471 // For arrays generate assignment operation for single element and replace 19472 // it by the original array element in CodeGen. 19473 ExprResult AssignmentOp = 19474 SemaRef.BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign, 19475 PseudoDstExpr, PseudoSrcExpr); 19476 if (AssignmentOp.isInvalid()) 19477 continue; 19478 AssignmentOp = 19479 SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(), 19480 /*DiscardedValue*/ false); 19481 if (AssignmentOp.isInvalid()) 19482 continue; 19483 19484 DSAStack->addDSA(VD, DE, OMPC_copyin); 19485 Vars.push_back(DE); 19486 SrcExprs.push_back(PseudoSrcExpr); 19487 DstExprs.push_back(PseudoDstExpr); 19488 AssignmentOps.push_back(AssignmentOp.get()); 19489 } 19490 19491 if (Vars.empty()) 19492 return nullptr; 19493 19494 return OMPCopyinClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc, 19495 Vars, SrcExprs, DstExprs, AssignmentOps); 19496 } 19497 19498 OMPClause *SemaOpenMP::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList, 19499 SourceLocation StartLoc, 19500 SourceLocation LParenLoc, 19501 SourceLocation EndLoc) { 19502 SmallVector<Expr *, 8> Vars; 19503 SmallVector<Expr *, 8> SrcExprs; 19504 SmallVector<Expr *, 8> DstExprs; 19505 SmallVector<Expr *, 8> AssignmentOps; 19506 for (Expr *RefExpr : VarList) { 19507 assert(RefExpr && "NULL expr in OpenMP linear clause."); 19508 SourceLocation ELoc; 19509 SourceRange ERange; 19510 Expr *SimpleRefExpr = RefExpr; 19511 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); 19512 if (Res.second) { 19513 // It will be analyzed later. 19514 Vars.push_back(RefExpr); 19515 SrcExprs.push_back(nullptr); 19516 DstExprs.push_back(nullptr); 19517 AssignmentOps.push_back(nullptr); 19518 } 19519 ValueDecl *D = Res.first; 19520 if (!D) 19521 continue; 19522 19523 QualType Type = D->getType(); 19524 auto *VD = dyn_cast<VarDecl>(D); 19525 19526 // OpenMP [2.14.4.2, Restrictions, p.2] 19527 // A list item that appears in a copyprivate clause may not appear in a 19528 // private or firstprivate clause on the single construct. 19529 if (!VD || !DSAStack->isThreadPrivate(VD)) { 19530 DSAStackTy::DSAVarData DVar = 19531 DSAStack->getTopDSA(D, /*FromParent=*/false); 19532 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate && 19533 DVar.RefExpr) { 19534 Diag(ELoc, diag::err_omp_wrong_dsa) 19535 << getOpenMPClauseName(DVar.CKind) 19536 << getOpenMPClauseName(OMPC_copyprivate); 19537 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 19538 continue; 19539 } 19540 19541 // OpenMP [2.11.4.2, Restrictions, p.1] 19542 // All list items that appear in a copyprivate clause must be either 19543 // threadprivate or private in the enclosing context. 19544 if (DVar.CKind == OMPC_unknown) { 19545 DVar = DSAStack->getImplicitDSA(D, false); 19546 if (DVar.CKind == OMPC_shared) { 19547 Diag(ELoc, diag::err_omp_required_access) 19548 << getOpenMPClauseName(OMPC_copyprivate) 19549 << "threadprivate or private in the enclosing context"; 19550 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 19551 continue; 19552 } 19553 } 19554 } 19555 19556 // Variably modified types are not supported. 19557 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType()) { 19558 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported) 19559 << getOpenMPClauseName(OMPC_copyprivate) << Type 19560 << getOpenMPDirectiveName(DSAStack->getCurrentDirective()); 19561 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) == 19562 VarDecl::DeclarationOnly; 19563 Diag(D->getLocation(), 19564 IsDecl ? diag::note_previous_decl : diag::note_defined_here) 19565 << D; 19566 continue; 19567 } 19568 19569 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2] 19570 // A variable of class type (or array thereof) that appears in a 19571 // copyin clause requires an accessible, unambiguous copy assignment 19572 // operator for the class type. 19573 Type = getASTContext() 19574 .getBaseElementType(Type.getNonReferenceType()) 19575 .getUnqualifiedType(); 19576 VarDecl *SrcVD = 19577 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.src", 19578 D->hasAttrs() ? &D->getAttrs() : nullptr); 19579 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(SemaRef, SrcVD, Type, ELoc); 19580 VarDecl *DstVD = 19581 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.dst", 19582 D->hasAttrs() ? &D->getAttrs() : nullptr); 19583 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc); 19584 ExprResult AssignmentOp = SemaRef.BuildBinOp( 19585 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr); 19586 if (AssignmentOp.isInvalid()) 19587 continue; 19588 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc, 19589 /*DiscardedValue*/ false); 19590 if (AssignmentOp.isInvalid()) 19591 continue; 19592 19593 // No need to mark vars as copyprivate, they are already threadprivate or 19594 // implicitly private. 19595 assert(VD || isOpenMPCapturedDecl(D)); 19596 Vars.push_back( 19597 VD ? RefExpr->IgnoreParens() 19598 : buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false)); 19599 SrcExprs.push_back(PseudoSrcExpr); 19600 DstExprs.push_back(PseudoDstExpr); 19601 AssignmentOps.push_back(AssignmentOp.get()); 19602 } 19603 19604 if (Vars.empty()) 19605 return nullptr; 19606 19607 return OMPCopyprivateClause::Create(getASTContext(), StartLoc, LParenLoc, 19608 EndLoc, Vars, SrcExprs, DstExprs, 19609 AssignmentOps); 19610 } 19611 19612 OMPClause *SemaOpenMP::ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList, 19613 SourceLocation StartLoc, 19614 SourceLocation LParenLoc, 19615 SourceLocation EndLoc) { 19616 if (VarList.empty()) 19617 return nullptr; 19618 19619 return OMPFlushClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc, 19620 VarList); 19621 } 19622 19623 /// Tries to find omp_depend_t. type. 19624 static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack, 19625 bool Diagnose = true) { 19626 QualType OMPDependT = Stack->getOMPDependT(); 19627 if (!OMPDependT.isNull()) 19628 return true; 19629 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t"); 19630 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope()); 19631 if (!PT.getAsOpaquePtr() || PT.get().isNull()) { 19632 if (Diagnose) 19633 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t"; 19634 return false; 19635 } 19636 Stack->setOMPDependT(PT.get()); 19637 return true; 19638 } 19639 19640 OMPClause *SemaOpenMP::ActOnOpenMPDepobjClause(Expr *Depobj, 19641 SourceLocation StartLoc, 19642 SourceLocation LParenLoc, 19643 SourceLocation EndLoc) { 19644 if (!Depobj) 19645 return nullptr; 19646 19647 bool OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack); 19648 19649 // OpenMP 5.0, 2.17.10.1 depobj Construct 19650 // depobj is an lvalue expression of type omp_depend_t. 19651 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() && 19652 !Depobj->isInstantiationDependent() && 19653 !Depobj->containsUnexpandedParameterPack() && 19654 (OMPDependTFound && !getASTContext().typesAreCompatible( 19655 DSAStack->getOMPDependT(), Depobj->getType(), 19656 /*CompareUnqualified=*/true))) { 19657 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue) 19658 << 0 << Depobj->getType() << Depobj->getSourceRange(); 19659 } 19660 19661 if (!Depobj->isLValue()) { 19662 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue) 19663 << 1 << Depobj->getSourceRange(); 19664 } 19665 19666 return OMPDepobjClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc, 19667 Depobj); 19668 } 19669 19670 namespace { 19671 // Utility struct that gathers the related info for doacross clause. 19672 struct DoacrossDataInfoTy { 19673 // The list of expressions. 19674 SmallVector<Expr *, 8> Vars; 19675 // The OperatorOffset for doacross loop. 19676 DSAStackTy::OperatorOffsetTy OpsOffs; 19677 // The depended loop count. 19678 llvm::APSInt TotalDepCount; 19679 }; 19680 } // namespace 19681 static DoacrossDataInfoTy 19682 ProcessOpenMPDoacrossClauseCommon(Sema &SemaRef, bool IsSource, 19683 ArrayRef<Expr *> VarList, DSAStackTy *Stack, 19684 SourceLocation EndLoc) { 19685 19686 SmallVector<Expr *, 8> Vars; 19687 DSAStackTy::OperatorOffsetTy OpsOffs; 19688 llvm::APSInt DepCounter(/*BitWidth=*/32); 19689 llvm::APSInt TotalDepCount(/*BitWidth=*/32); 19690 19691 if (const Expr *OrderedCountExpr = 19692 Stack->getParentOrderedRegionParam().first) { 19693 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.Context); 19694 TotalDepCount.setIsUnsigned(/*Val=*/true); 19695 } 19696 19697 for (Expr *RefExpr : VarList) { 19698 assert(RefExpr && "NULL expr in OpenMP doacross clause."); 19699 if (isa<DependentScopeDeclRefExpr>(RefExpr)) { 19700 // It will be analyzed later. 19701 Vars.push_back(RefExpr); 19702 continue; 19703 } 19704 19705 SourceLocation ELoc = RefExpr->getExprLoc(); 19706 Expr *SimpleExpr = RefExpr->IgnoreParenCasts(); 19707 if (!IsSource) { 19708 if (Stack->getParentOrderedRegionParam().first && 19709 DepCounter >= TotalDepCount) { 19710 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr); 19711 continue; 19712 } 19713 ++DepCounter; 19714 // OpenMP [2.13.9, Summary] 19715 // depend(dependence-type : vec), where dependence-type is: 19716 // 'sink' and where vec is the iteration vector, which has the form: 19717 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn] 19718 // where n is the value specified by the ordered clause in the loop 19719 // directive, xi denotes the loop iteration variable of the i-th nested 19720 // loop associated with the loop directive, and di is a constant 19721 // non-negative integer. 19722 if (SemaRef.CurContext->isDependentContext()) { 19723 // It will be analyzed later. 19724 Vars.push_back(RefExpr); 19725 continue; 19726 } 19727 SimpleExpr = SimpleExpr->IgnoreImplicit(); 19728 OverloadedOperatorKind OOK = OO_None; 19729 SourceLocation OOLoc; 19730 Expr *LHS = SimpleExpr; 19731 Expr *RHS = nullptr; 19732 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) { 19733 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode()); 19734 OOLoc = BO->getOperatorLoc(); 19735 LHS = BO->getLHS()->IgnoreParenImpCasts(); 19736 RHS = BO->getRHS()->IgnoreParenImpCasts(); 19737 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) { 19738 OOK = OCE->getOperator(); 19739 OOLoc = OCE->getOperatorLoc(); 19740 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); 19741 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts(); 19742 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) { 19743 OOK = MCE->getMethodDecl() 19744 ->getNameInfo() 19745 .getName() 19746 .getCXXOverloadedOperator(); 19747 OOLoc = MCE->getCallee()->getExprLoc(); 19748 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts(); 19749 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); 19750 } 19751 SourceLocation ELoc; 19752 SourceRange ERange; 19753 auto Res = getPrivateItem(SemaRef, LHS, ELoc, ERange); 19754 if (Res.second) { 19755 // It will be analyzed later. 19756 Vars.push_back(RefExpr); 19757 } 19758 ValueDecl *D = Res.first; 19759 if (!D) 19760 continue; 19761 19762 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) { 19763 SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus); 19764 continue; 19765 } 19766 if (RHS) { 19767 ExprResult RHSRes = 19768 SemaRef.OpenMP().VerifyPositiveIntegerConstantInClause( 19769 RHS, OMPC_depend, /*StrictlyPositive=*/false); 19770 if (RHSRes.isInvalid()) 19771 continue; 19772 } 19773 if (!SemaRef.CurContext->isDependentContext() && 19774 Stack->getParentOrderedRegionParam().first && 19775 DepCounter != Stack->isParentLoopControlVariable(D).first) { 19776 const ValueDecl *VD = 19777 Stack->getParentLoopControlVariable(DepCounter.getZExtValue()); 19778 if (VD) 19779 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration) 19780 << 1 << VD; 19781 else 19782 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration) 19783 << 0; 19784 continue; 19785 } 19786 OpsOffs.emplace_back(RHS, OOK); 19787 } 19788 Vars.push_back(RefExpr->IgnoreParenImpCasts()); 19789 } 19790 if (!SemaRef.CurContext->isDependentContext() && !IsSource && 19791 TotalDepCount > VarList.size() && 19792 Stack->getParentOrderedRegionParam().first && 19793 Stack->getParentLoopControlVariable(VarList.size() + 1)) { 19794 SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration) 19795 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1); 19796 } 19797 return {Vars, OpsOffs, TotalDepCount}; 19798 } 19799 19800 OMPClause *SemaOpenMP::ActOnOpenMPDependClause( 19801 const OMPDependClause::DependDataTy &Data, Expr *DepModifier, 19802 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, 19803 SourceLocation EndLoc) { 19804 OpenMPDependClauseKind DepKind = Data.DepKind; 19805 SourceLocation DepLoc = Data.DepLoc; 19806 if (DSAStack->getCurrentDirective() == OMPD_ordered && 19807 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) { 19808 Diag(DepLoc, diag::err_omp_unexpected_clause_value) 19809 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend); 19810 return nullptr; 19811 } 19812 if (DSAStack->getCurrentDirective() == OMPD_taskwait && 19813 DepKind == OMPC_DEPEND_mutexinoutset) { 19814 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed); 19815 return nullptr; 19816 } 19817 if ((DSAStack->getCurrentDirective() != OMPD_ordered || 19818 DSAStack->getCurrentDirective() == OMPD_depobj) && 19819 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source || 19820 DepKind == OMPC_DEPEND_sink || 19821 ((getLangOpts().OpenMP < 50 || 19822 DSAStack->getCurrentDirective() == OMPD_depobj) && 19823 DepKind == OMPC_DEPEND_depobj))) { 19824 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink, 19825 OMPC_DEPEND_outallmemory, 19826 OMPC_DEPEND_inoutallmemory}; 19827 if (getLangOpts().OpenMP < 50 || 19828 DSAStack->getCurrentDirective() == OMPD_depobj) 19829 Except.push_back(OMPC_DEPEND_depobj); 19830 if (getLangOpts().OpenMP < 51) 19831 Except.push_back(OMPC_DEPEND_inoutset); 19832 std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier) 19833 ? "depend modifier(iterator) or " 19834 : ""; 19835 Diag(DepLoc, diag::err_omp_unexpected_clause_value) 19836 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0, 19837 /*Last=*/OMPC_DEPEND_unknown, 19838 Except) 19839 << getOpenMPClauseName(OMPC_depend); 19840 return nullptr; 19841 } 19842 if (DepModifier && 19843 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) { 19844 Diag(DepModifier->getExprLoc(), 19845 diag::err_omp_depend_sink_source_with_modifier); 19846 return nullptr; 19847 } 19848 if (DepModifier && 19849 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator)) 19850 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator); 19851 19852 SmallVector<Expr *, 8> Vars; 19853 DSAStackTy::OperatorOffsetTy OpsOffs; 19854 llvm::APSInt TotalDepCount(/*BitWidth=*/32); 19855 19856 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) { 19857 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon( 19858 SemaRef, DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc); 19859 Vars = VarOffset.Vars; 19860 OpsOffs = VarOffset.OpsOffs; 19861 TotalDepCount = VarOffset.TotalDepCount; 19862 } else { 19863 for (Expr *RefExpr : VarList) { 19864 assert(RefExpr && "NULL expr in OpenMP shared clause."); 19865 if (isa<DependentScopeDeclRefExpr>(RefExpr)) { 19866 // It will be analyzed later. 19867 Vars.push_back(RefExpr); 19868 continue; 19869 } 19870 19871 SourceLocation ELoc = RefExpr->getExprLoc(); 19872 Expr *SimpleExpr = RefExpr->IgnoreParenCasts(); 19873 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) { 19874 bool OMPDependTFound = getLangOpts().OpenMP >= 50; 19875 if (OMPDependTFound) 19876 OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack, 19877 DepKind == OMPC_DEPEND_depobj); 19878 if (DepKind == OMPC_DEPEND_depobj) { 19879 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++ 19880 // List items used in depend clauses with the depobj dependence type 19881 // must be expressions of the omp_depend_t type. 19882 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() && 19883 !RefExpr->isInstantiationDependent() && 19884 !RefExpr->containsUnexpandedParameterPack() && 19885 (OMPDependTFound && 19886 !getASTContext().hasSameUnqualifiedType( 19887 DSAStack->getOMPDependT(), RefExpr->getType()))) { 19888 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue) 19889 << 0 << RefExpr->getType() << RefExpr->getSourceRange(); 19890 continue; 19891 } 19892 if (!RefExpr->isLValue()) { 19893 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue) 19894 << 1 << RefExpr->getType() << RefExpr->getSourceRange(); 19895 continue; 19896 } 19897 } else { 19898 // OpenMP 5.0 [2.17.11, Restrictions] 19899 // List items used in depend clauses cannot be zero-length array 19900 // sections. 19901 QualType ExprTy = RefExpr->getType().getNonReferenceType(); 19902 const auto *OASE = dyn_cast<ArraySectionExpr>(SimpleExpr); 19903 if (OASE) { 19904 QualType BaseType = 19905 ArraySectionExpr::getBaseOriginalType(OASE->getBase()); 19906 if (BaseType.isNull()) 19907 return nullptr; 19908 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe()) 19909 ExprTy = ATy->getElementType(); 19910 else 19911 ExprTy = BaseType->getPointeeType(); 19912 if (BaseType.isNull() || ExprTy.isNull()) 19913 return nullptr; 19914 ExprTy = ExprTy.getNonReferenceType(); 19915 const Expr *Length = OASE->getLength(); 19916 Expr::EvalResult Result; 19917 if (Length && !Length->isValueDependent() && 19918 Length->EvaluateAsInt(Result, getASTContext()) && 19919 Result.Val.getInt().isZero()) { 19920 Diag(ELoc, 19921 diag::err_omp_depend_zero_length_array_section_not_allowed) 19922 << SimpleExpr->getSourceRange(); 19923 continue; 19924 } 19925 } 19926 19927 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++ 19928 // List items used in depend clauses with the in, out, inout, 19929 // inoutset, or mutexinoutset dependence types cannot be 19930 // expressions of the omp_depend_t type. 19931 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() && 19932 !RefExpr->isInstantiationDependent() && 19933 !RefExpr->containsUnexpandedParameterPack() && 19934 (!RefExpr->IgnoreParenImpCasts()->isLValue() || 19935 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() == 19936 ExprTy.getTypePtr()))) { 19937 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item) 19938 << (getLangOpts().OpenMP >= 50 ? 1 : 0) 19939 << (getLangOpts().OpenMP >= 50 ? 1 : 0) 19940 << RefExpr->getSourceRange(); 19941 continue; 19942 } 19943 19944 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr); 19945 if (ASE && !ASE->getBase()->isTypeDependent() && 19946 !ASE->getBase() 19947 ->getType() 19948 .getNonReferenceType() 19949 ->isPointerType() && 19950 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) { 19951 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item) 19952 << (getLangOpts().OpenMP >= 50 ? 1 : 0) 19953 << (getLangOpts().OpenMP >= 50 ? 1 : 0) 19954 << RefExpr->getSourceRange(); 19955 continue; 19956 } 19957 19958 ExprResult Res; 19959 { 19960 Sema::TentativeAnalysisScope Trap(SemaRef); 19961 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, 19962 RefExpr->IgnoreParenImpCasts()); 19963 } 19964 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) && 19965 !isa<OMPArrayShapingExpr>(SimpleExpr)) { 19966 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item) 19967 << (getLangOpts().OpenMP >= 50 ? 1 : 0) 19968 << (getLangOpts().OpenMP >= 50 ? 1 : 0) 19969 << RefExpr->getSourceRange(); 19970 continue; 19971 } 19972 } 19973 } 19974 Vars.push_back(RefExpr->IgnoreParenImpCasts()); 19975 } 19976 } 19977 19978 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink && 19979 DepKind != OMPC_DEPEND_outallmemory && 19980 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty()) 19981 return nullptr; 19982 19983 auto *C = OMPDependClause::Create( 19984 getASTContext(), StartLoc, LParenLoc, EndLoc, 19985 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars, 19986 TotalDepCount.getZExtValue()); 19987 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) && 19988 DSAStack->isParentOrderedRegion()) 19989 DSAStack->addDoacrossDependClause(C, OpsOffs); 19990 return C; 19991 } 19992 19993 OMPClause *SemaOpenMP::ActOnOpenMPDeviceClause( 19994 OpenMPDeviceClauseModifier Modifier, Expr *Device, SourceLocation StartLoc, 19995 SourceLocation LParenLoc, SourceLocation ModifierLoc, 19996 SourceLocation EndLoc) { 19997 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) && 19998 "Unexpected device modifier in OpenMP < 50."); 19999 20000 bool ErrorFound = false; 20001 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) { 20002 std::string Values = 20003 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown); 20004 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value) 20005 << Values << getOpenMPClauseName(OMPC_device); 20006 ErrorFound = true; 20007 } 20008 20009 Expr *ValExpr = Device; 20010 Stmt *HelperValStmt = nullptr; 20011 20012 // OpenMP [2.9.1, Restrictions] 20013 // The device expression must evaluate to a non-negative integer value. 20014 ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_device, 20015 /*StrictlyPositive=*/false) || 20016 ErrorFound; 20017 if (ErrorFound) 20018 return nullptr; 20019 20020 // OpenMP 5.0 [2.12.5, Restrictions] 20021 // In case of ancestor device-modifier, a requires directive with 20022 // the reverse_offload clause must be specified. 20023 if (Modifier == OMPC_DEVICE_ancestor) { 20024 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) { 20025 SemaRef.targetDiag( 20026 StartLoc, 20027 diag::err_omp_device_ancestor_without_requires_reverse_offload); 20028 ErrorFound = true; 20029 } 20030 } 20031 20032 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); 20033 OpenMPDirectiveKind CaptureRegion = 20034 getOpenMPCaptureRegionForClause(DKind, OMPC_device, getLangOpts().OpenMP); 20035 if (CaptureRegion != OMPD_unknown && 20036 !SemaRef.CurContext->isDependentContext()) { 20037 ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); 20038 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 20039 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); 20040 HelperValStmt = buildPreInits(getASTContext(), Captures); 20041 } 20042 20043 return new (getASTContext()) 20044 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc, 20045 LParenLoc, ModifierLoc, EndLoc); 20046 } 20047 20048 static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef, 20049 DSAStackTy *Stack, QualType QTy, 20050 bool FullCheck = true) { 20051 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type)) 20052 return false; 20053 if (FullCheck && !SemaRef.CurContext->isDependentContext() && 20054 !QTy.isTriviallyCopyableType(SemaRef.Context)) 20055 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR; 20056 return true; 20057 } 20058 20059 /// Return true if it can be proven that the provided array expression 20060 /// (array section or array subscript) does NOT specify the whole size of the 20061 /// array whose base type is \a BaseQTy. 20062 static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef, 20063 const Expr *E, 20064 QualType BaseQTy) { 20065 const auto *OASE = dyn_cast<ArraySectionExpr>(E); 20066 20067 // If this is an array subscript, it refers to the whole size if the size of 20068 // the dimension is constant and equals 1. Also, an array section assumes the 20069 // format of an array subscript if no colon is used. 20070 if (isa<ArraySubscriptExpr>(E) || 20071 (OASE && OASE->getColonLocFirst().isInvalid())) { 20072 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) 20073 return ATy->getSExtSize() != 1; 20074 // Size can't be evaluated statically. 20075 return false; 20076 } 20077 20078 assert(OASE && "Expecting array section if not an array subscript."); 20079 const Expr *LowerBound = OASE->getLowerBound(); 20080 const Expr *Length = OASE->getLength(); 20081 20082 // If there is a lower bound that does not evaluates to zero, we are not 20083 // covering the whole dimension. 20084 if (LowerBound) { 20085 Expr::EvalResult Result; 20086 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext())) 20087 return false; // Can't get the integer value as a constant. 20088 20089 llvm::APSInt ConstLowerBound = Result.Val.getInt(); 20090 if (ConstLowerBound.getSExtValue()) 20091 return true; 20092 } 20093 20094 // If we don't have a length we covering the whole dimension. 20095 if (!Length) 20096 return false; 20097 20098 // If the base is a pointer, we don't have a way to get the size of the 20099 // pointee. 20100 if (BaseQTy->isPointerType()) 20101 return false; 20102 20103 // We can only check if the length is the same as the size of the dimension 20104 // if we have a constant array. 20105 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()); 20106 if (!CATy) 20107 return false; 20108 20109 Expr::EvalResult Result; 20110 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext())) 20111 return false; // Can't get the integer value as a constant. 20112 20113 llvm::APSInt ConstLength = Result.Val.getInt(); 20114 return CATy->getSExtSize() != ConstLength.getSExtValue(); 20115 } 20116 20117 // Return true if it can be proven that the provided array expression (array 20118 // section or array subscript) does NOT specify a single element of the array 20119 // whose base type is \a BaseQTy. 20120 static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef, 20121 const Expr *E, 20122 QualType BaseQTy) { 20123 const auto *OASE = dyn_cast<ArraySectionExpr>(E); 20124 20125 // An array subscript always refer to a single element. Also, an array section 20126 // assumes the format of an array subscript if no colon is used. 20127 if (isa<ArraySubscriptExpr>(E) || 20128 (OASE && OASE->getColonLocFirst().isInvalid())) 20129 return false; 20130 20131 assert(OASE && "Expecting array section if not an array subscript."); 20132 const Expr *Length = OASE->getLength(); 20133 20134 // If we don't have a length we have to check if the array has unitary size 20135 // for this dimension. Also, we should always expect a length if the base type 20136 // is pointer. 20137 if (!Length) { 20138 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) 20139 return ATy->getSExtSize() != 1; 20140 // We cannot assume anything. 20141 return false; 20142 } 20143 20144 // Check if the length evaluates to 1. 20145 Expr::EvalResult Result; 20146 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext())) 20147 return false; // Can't get the integer value as a constant. 20148 20149 llvm::APSInt ConstLength = Result.Val.getInt(); 20150 return ConstLength.getSExtValue() != 1; 20151 } 20152 20153 // The base of elements of list in a map clause have to be either: 20154 // - a reference to variable or field. 20155 // - a member expression. 20156 // - an array expression. 20157 // 20158 // E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the 20159 // reference to 'r'. 20160 // 20161 // If we have: 20162 // 20163 // struct SS { 20164 // Bla S; 20165 // foo() { 20166 // #pragma omp target map (S.Arr[:12]); 20167 // } 20168 // } 20169 // 20170 // We want to retrieve the member expression 'this->S'; 20171 20172 // OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2] 20173 // If a list item is an array section, it must specify contiguous storage. 20174 // 20175 // For this restriction it is sufficient that we make sure only references 20176 // to variables or fields and array expressions, and that no array sections 20177 // exist except in the rightmost expression (unless they cover the whole 20178 // dimension of the array). E.g. these would be invalid: 20179 // 20180 // r.ArrS[3:5].Arr[6:7] 20181 // 20182 // r.ArrS[3:5].x 20183 // 20184 // but these would be valid: 20185 // r.ArrS[3].Arr[6:7] 20186 // 20187 // r.ArrS[3].x 20188 namespace { 20189 class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> { 20190 Sema &SemaRef; 20191 OpenMPClauseKind CKind = OMPC_unknown; 20192 OpenMPDirectiveKind DKind = OMPD_unknown; 20193 OMPClauseMappableExprCommon::MappableExprComponentList &Components; 20194 bool IsNonContiguous = false; 20195 bool NoDiagnose = false; 20196 const Expr *RelevantExpr = nullptr; 20197 bool AllowUnitySizeArraySection = true; 20198 bool AllowWholeSizeArraySection = true; 20199 bool AllowAnotherPtr = true; 20200 SourceLocation ELoc; 20201 SourceRange ERange; 20202 20203 void emitErrorMsg() { 20204 // If nothing else worked, this is not a valid map clause expression. 20205 if (SemaRef.getLangOpts().OpenMP < 50) { 20206 SemaRef.Diag(ELoc, 20207 diag::err_omp_expected_named_var_member_or_array_expression) 20208 << ERange; 20209 } else { 20210 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses) 20211 << getOpenMPClauseName(CKind) << ERange; 20212 } 20213 } 20214 20215 public: 20216 bool VisitDeclRefExpr(DeclRefExpr *DRE) { 20217 if (!isa<VarDecl>(DRE->getDecl())) { 20218 emitErrorMsg(); 20219 return false; 20220 } 20221 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr"); 20222 RelevantExpr = DRE; 20223 // Record the component. 20224 Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous); 20225 return true; 20226 } 20227 20228 bool VisitMemberExpr(MemberExpr *ME) { 20229 Expr *E = ME; 20230 Expr *BaseE = ME->getBase()->IgnoreParenCasts(); 20231 20232 if (isa<CXXThisExpr>(BaseE)) { 20233 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr"); 20234 // We found a base expression: this->Val. 20235 RelevantExpr = ME; 20236 } else { 20237 E = BaseE; 20238 } 20239 20240 if (!isa<FieldDecl>(ME->getMemberDecl())) { 20241 if (!NoDiagnose) { 20242 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field) 20243 << ME->getSourceRange(); 20244 return false; 20245 } 20246 if (RelevantExpr) 20247 return false; 20248 return Visit(E); 20249 } 20250 20251 auto *FD = cast<FieldDecl>(ME->getMemberDecl()); 20252 20253 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3] 20254 // A bit-field cannot appear in a map clause. 20255 // 20256 if (FD->isBitField()) { 20257 if (!NoDiagnose) { 20258 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause) 20259 << ME->getSourceRange() << getOpenMPClauseName(CKind); 20260 return false; 20261 } 20262 if (RelevantExpr) 20263 return false; 20264 return Visit(E); 20265 } 20266 20267 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1] 20268 // If the type of a list item is a reference to a type T then the type 20269 // will be considered to be T for all purposes of this clause. 20270 QualType CurType = BaseE->getType().getNonReferenceType(); 20271 20272 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2] 20273 // A list item cannot be a variable that is a member of a structure with 20274 // a union type. 20275 // 20276 if (CurType->isUnionType()) { 20277 if (!NoDiagnose) { 20278 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed) 20279 << ME->getSourceRange(); 20280 return false; 20281 } 20282 return RelevantExpr || Visit(E); 20283 } 20284 20285 // If we got a member expression, we should not expect any array section 20286 // before that: 20287 // 20288 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7] 20289 // If a list item is an element of a structure, only the rightmost symbol 20290 // of the variable reference can be an array section. 20291 // 20292 AllowUnitySizeArraySection = false; 20293 AllowWholeSizeArraySection = false; 20294 20295 // Record the component. 20296 Components.emplace_back(ME, FD, IsNonContiguous); 20297 return RelevantExpr || Visit(E); 20298 } 20299 20300 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) { 20301 Expr *E = AE->getBase()->IgnoreParenImpCasts(); 20302 20303 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) { 20304 if (!NoDiagnose) { 20305 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name) 20306 << 0 << AE->getSourceRange(); 20307 return false; 20308 } 20309 return RelevantExpr || Visit(E); 20310 } 20311 20312 // If we got an array subscript that express the whole dimension we 20313 // can have any array expressions before. If it only expressing part of 20314 // the dimension, we can only have unitary-size array expressions. 20315 if (checkArrayExpressionDoesNotReferToWholeSize(SemaRef, AE, E->getType())) 20316 AllowWholeSizeArraySection = false; 20317 20318 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) { 20319 Expr::EvalResult Result; 20320 if (!AE->getIdx()->isValueDependent() && 20321 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) && 20322 !Result.Val.getInt().isZero()) { 20323 SemaRef.Diag(AE->getIdx()->getExprLoc(), 20324 diag::err_omp_invalid_map_this_expr); 20325 SemaRef.Diag(AE->getIdx()->getExprLoc(), 20326 diag::note_omp_invalid_subscript_on_this_ptr_map); 20327 } 20328 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr"); 20329 RelevantExpr = TE; 20330 } 20331 20332 // Record the component - we don't have any declaration associated. 20333 Components.emplace_back(AE, nullptr, IsNonContiguous); 20334 20335 return RelevantExpr || Visit(E); 20336 } 20337 20338 bool VisitArraySectionExpr(ArraySectionExpr *OASE) { 20339 // After OMP 5.0 Array section in reduction clause will be implicitly 20340 // mapped 20341 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) && 20342 "Array sections cannot be implicitly mapped."); 20343 Expr *E = OASE->getBase()->IgnoreParenImpCasts(); 20344 QualType CurType = 20345 ArraySectionExpr::getBaseOriginalType(E).getCanonicalType(); 20346 20347 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1] 20348 // If the type of a list item is a reference to a type T then the type 20349 // will be considered to be T for all purposes of this clause. 20350 if (CurType->isReferenceType()) 20351 CurType = CurType->getPointeeType(); 20352 20353 bool IsPointer = CurType->isAnyPointerType(); 20354 20355 if (!IsPointer && !CurType->isArrayType()) { 20356 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name) 20357 << 0 << OASE->getSourceRange(); 20358 return false; 20359 } 20360 20361 bool NotWhole = 20362 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType); 20363 bool NotUnity = 20364 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType); 20365 20366 if (AllowWholeSizeArraySection) { 20367 // Any array section is currently allowed. Allowing a whole size array 20368 // section implies allowing a unity array section as well. 20369 // 20370 // If this array section refers to the whole dimension we can still 20371 // accept other array sections before this one, except if the base is a 20372 // pointer. Otherwise, only unitary sections are accepted. 20373 if (NotWhole || IsPointer) 20374 AllowWholeSizeArraySection = false; 20375 } else if (DKind == OMPD_target_update && 20376 SemaRef.getLangOpts().OpenMP >= 50) { 20377 if (IsPointer && !AllowAnotherPtr) 20378 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined) 20379 << /*array of unknown bound */ 1; 20380 else 20381 IsNonContiguous = true; 20382 } else if (AllowUnitySizeArraySection && NotUnity) { 20383 // A unity or whole array section is not allowed and that is not 20384 // compatible with the properties of the current array section. 20385 if (NoDiagnose) 20386 return false; 20387 SemaRef.Diag(ELoc, 20388 diag::err_array_section_does_not_specify_contiguous_storage) 20389 << OASE->getSourceRange(); 20390 return false; 20391 } 20392 20393 if (IsPointer) 20394 AllowAnotherPtr = false; 20395 20396 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) { 20397 Expr::EvalResult ResultR; 20398 Expr::EvalResult ResultL; 20399 if (!OASE->getLength()->isValueDependent() && 20400 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) && 20401 !ResultR.Val.getInt().isOne()) { 20402 SemaRef.Diag(OASE->getLength()->getExprLoc(), 20403 diag::err_omp_invalid_map_this_expr); 20404 SemaRef.Diag(OASE->getLength()->getExprLoc(), 20405 diag::note_omp_invalid_length_on_this_ptr_mapping); 20406 } 20407 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() && 20408 OASE->getLowerBound()->EvaluateAsInt(ResultL, 20409 SemaRef.getASTContext()) && 20410 !ResultL.Val.getInt().isZero()) { 20411 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(), 20412 diag::err_omp_invalid_map_this_expr); 20413 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(), 20414 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping); 20415 } 20416 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr"); 20417 RelevantExpr = TE; 20418 } 20419 20420 // Record the component - we don't have any declaration associated. 20421 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false); 20422 return RelevantExpr || Visit(E); 20423 } 20424 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) { 20425 Expr *Base = E->getBase(); 20426 20427 // Record the component - we don't have any declaration associated. 20428 Components.emplace_back(E, nullptr, IsNonContiguous); 20429 20430 return Visit(Base->IgnoreParenImpCasts()); 20431 } 20432 20433 bool VisitUnaryOperator(UnaryOperator *UO) { 20434 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() || 20435 UO->getOpcode() != UO_Deref) { 20436 emitErrorMsg(); 20437 return false; 20438 } 20439 if (!RelevantExpr) { 20440 // Record the component if haven't found base decl. 20441 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false); 20442 } 20443 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts()); 20444 } 20445 bool VisitBinaryOperator(BinaryOperator *BO) { 20446 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) { 20447 emitErrorMsg(); 20448 return false; 20449 } 20450 20451 // Pointer arithmetic is the only thing we expect to happen here so after we 20452 // make sure the binary operator is a pointer type, the only thing we need 20453 // to do is to visit the subtree that has the same type as root (so that we 20454 // know the other subtree is just an offset) 20455 Expr *LE = BO->getLHS()->IgnoreParenImpCasts(); 20456 Expr *RE = BO->getRHS()->IgnoreParenImpCasts(); 20457 Components.emplace_back(BO, nullptr, false); 20458 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() || 20459 RE->getType().getTypePtr() == BO->getType().getTypePtr()) && 20460 "Either LHS or RHS have base decl inside"); 20461 if (BO->getType().getTypePtr() == LE->getType().getTypePtr()) 20462 return RelevantExpr || Visit(LE); 20463 return RelevantExpr || Visit(RE); 20464 } 20465 bool VisitCXXThisExpr(CXXThisExpr *CTE) { 20466 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr"); 20467 RelevantExpr = CTE; 20468 Components.emplace_back(CTE, nullptr, IsNonContiguous); 20469 return true; 20470 } 20471 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) { 20472 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr"); 20473 Components.emplace_back(COCE, nullptr, IsNonContiguous); 20474 return true; 20475 } 20476 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) { 20477 Expr *Source = E->getSourceExpr(); 20478 if (!Source) { 20479 emitErrorMsg(); 20480 return false; 20481 } 20482 return Visit(Source); 20483 } 20484 bool VisitStmt(Stmt *) { 20485 emitErrorMsg(); 20486 return false; 20487 } 20488 const Expr *getFoundBase() const { return RelevantExpr; } 20489 explicit MapBaseChecker( 20490 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, 20491 OMPClauseMappableExprCommon::MappableExprComponentList &Components, 20492 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange) 20493 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components), 20494 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {} 20495 }; 20496 } // namespace 20497 20498 /// Return the expression of the base of the mappable expression or null if it 20499 /// cannot be determined and do all the necessary checks to see if the 20500 /// expression is valid as a standalone mappable expression. In the process, 20501 /// record all the components of the expression. 20502 static const Expr *checkMapClauseExpressionBase( 20503 Sema &SemaRef, Expr *E, 20504 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents, 20505 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) { 20506 SourceLocation ELoc = E->getExprLoc(); 20507 SourceRange ERange = E->getSourceRange(); 20508 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc, 20509 ERange); 20510 if (Checker.Visit(E->IgnoreParens())) { 20511 // Check if the highest dimension array section has length specified 20512 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() && 20513 (CKind == OMPC_to || CKind == OMPC_from)) { 20514 auto CI = CurComponents.rbegin(); 20515 auto CE = CurComponents.rend(); 20516 for (; CI != CE; ++CI) { 20517 const auto *OASE = 20518 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression()); 20519 if (!OASE) 20520 continue; 20521 if (OASE && OASE->getLength()) 20522 break; 20523 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length) 20524 << ERange; 20525 } 20526 } 20527 return Checker.getFoundBase(); 20528 } 20529 return nullptr; 20530 } 20531 20532 // Return true if expression E associated with value VD has conflicts with other 20533 // map information. 20534 static bool checkMapConflicts( 20535 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E, 20536 bool CurrentRegionOnly, 20537 OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents, 20538 OpenMPClauseKind CKind) { 20539 assert(VD && E); 20540 SourceLocation ELoc = E->getExprLoc(); 20541 SourceRange ERange = E->getSourceRange(); 20542 20543 // In order to easily check the conflicts we need to match each component of 20544 // the expression under test with the components of the expressions that are 20545 // already in the stack. 20546 20547 assert(!CurComponents.empty() && "Map clause expression with no components!"); 20548 assert(CurComponents.back().getAssociatedDeclaration() == VD && 20549 "Map clause expression with unexpected base!"); 20550 20551 // Variables to help detecting enclosing problems in data environment nests. 20552 bool IsEnclosedByDataEnvironmentExpr = false; 20553 const Expr *EnclosingExpr = nullptr; 20554 20555 bool FoundError = DSAS->checkMappableExprComponentListsForDecl( 20556 VD, CurrentRegionOnly, 20557 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc, 20558 ERange, CKind, &EnclosingExpr, 20559 CurComponents](OMPClauseMappableExprCommon::MappableExprComponentListRef 20560 StackComponents, 20561 OpenMPClauseKind Kind) { 20562 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50) 20563 return false; 20564 assert(!StackComponents.empty() && 20565 "Map clause expression with no components!"); 20566 assert(StackComponents.back().getAssociatedDeclaration() == VD && 20567 "Map clause expression with unexpected base!"); 20568 (void)VD; 20569 20570 // The whole expression in the stack. 20571 const Expr *RE = StackComponents.front().getAssociatedExpression(); 20572 20573 // Expressions must start from the same base. Here we detect at which 20574 // point both expressions diverge from each other and see if we can 20575 // detect if the memory referred to both expressions is contiguous and 20576 // do not overlap. 20577 auto CI = CurComponents.rbegin(); 20578 auto CE = CurComponents.rend(); 20579 auto SI = StackComponents.rbegin(); 20580 auto SE = StackComponents.rend(); 20581 for (; CI != CE && SI != SE; ++CI, ++SI) { 20582 20583 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3] 20584 // At most one list item can be an array item derived from a given 20585 // variable in map clauses of the same construct. 20586 if (CurrentRegionOnly && 20587 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) || 20588 isa<ArraySectionExpr>(CI->getAssociatedExpression()) || 20589 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) && 20590 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) || 20591 isa<ArraySectionExpr>(SI->getAssociatedExpression()) || 20592 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) { 20593 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(), 20594 diag::err_omp_multiple_array_items_in_map_clause) 20595 << CI->getAssociatedExpression()->getSourceRange(); 20596 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(), 20597 diag::note_used_here) 20598 << SI->getAssociatedExpression()->getSourceRange(); 20599 return true; 20600 } 20601 20602 // Do both expressions have the same kind? 20603 if (CI->getAssociatedExpression()->getStmtClass() != 20604 SI->getAssociatedExpression()->getStmtClass()) 20605 break; 20606 20607 // Are we dealing with different variables/fields? 20608 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration()) 20609 break; 20610 } 20611 // Check if the extra components of the expressions in the enclosing 20612 // data environment are redundant for the current base declaration. 20613 // If they are, the maps completely overlap, which is legal. 20614 for (; SI != SE; ++SI) { 20615 QualType Type; 20616 if (const auto *ASE = 20617 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) { 20618 Type = ASE->getBase()->IgnoreParenImpCasts()->getType(); 20619 } else if (const auto *OASE = dyn_cast<ArraySectionExpr>( 20620 SI->getAssociatedExpression())) { 20621 const Expr *E = OASE->getBase()->IgnoreParenImpCasts(); 20622 Type = ArraySectionExpr::getBaseOriginalType(E).getCanonicalType(); 20623 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>( 20624 SI->getAssociatedExpression())) { 20625 Type = OASE->getBase()->getType()->getPointeeType(); 20626 } 20627 if (Type.isNull() || Type->isAnyPointerType() || 20628 checkArrayExpressionDoesNotReferToWholeSize( 20629 SemaRef, SI->getAssociatedExpression(), Type)) 20630 break; 20631 } 20632 20633 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4] 20634 // List items of map clauses in the same construct must not share 20635 // original storage. 20636 // 20637 // If the expressions are exactly the same or one is a subset of the 20638 // other, it means they are sharing storage. 20639 if (CI == CE && SI == SE) { 20640 if (CurrentRegionOnly) { 20641 if (CKind == OMPC_map) { 20642 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange; 20643 } else { 20644 assert(CKind == OMPC_to || CKind == OMPC_from); 20645 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update) 20646 << ERange; 20647 } 20648 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here) 20649 << RE->getSourceRange(); 20650 return true; 20651 } 20652 // If we find the same expression in the enclosing data environment, 20653 // that is legal. 20654 IsEnclosedByDataEnvironmentExpr = true; 20655 return false; 20656 } 20657 20658 QualType DerivedType = 20659 std::prev(CI)->getAssociatedDeclaration()->getType(); 20660 SourceLocation DerivedLoc = 20661 std::prev(CI)->getAssociatedExpression()->getExprLoc(); 20662 20663 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1] 20664 // If the type of a list item is a reference to a type T then the type 20665 // will be considered to be T for all purposes of this clause. 20666 DerivedType = DerivedType.getNonReferenceType(); 20667 20668 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1] 20669 // A variable for which the type is pointer and an array section 20670 // derived from that variable must not appear as list items of map 20671 // clauses of the same construct. 20672 // 20673 // Also, cover one of the cases in: 20674 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5] 20675 // If any part of the original storage of a list item has corresponding 20676 // storage in the device data environment, all of the original storage 20677 // must have corresponding storage in the device data environment. 20678 // 20679 if (DerivedType->isAnyPointerType()) { 20680 if (CI == CE || SI == SE) { 20681 SemaRef.Diag( 20682 DerivedLoc, 20683 diag::err_omp_pointer_mapped_along_with_derived_section) 20684 << DerivedLoc; 20685 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here) 20686 << RE->getSourceRange(); 20687 return true; 20688 } 20689 if (CI->getAssociatedExpression()->getStmtClass() != 20690 SI->getAssociatedExpression()->getStmtClass() || 20691 CI->getAssociatedDeclaration()->getCanonicalDecl() == 20692 SI->getAssociatedDeclaration()->getCanonicalDecl()) { 20693 assert(CI != CE && SI != SE); 20694 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced) 20695 << DerivedLoc; 20696 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here) 20697 << RE->getSourceRange(); 20698 return true; 20699 } 20700 } 20701 20702 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4] 20703 // List items of map clauses in the same construct must not share 20704 // original storage. 20705 // 20706 // An expression is a subset of the other. 20707 if (CurrentRegionOnly && (CI == CE || SI == SE)) { 20708 if (CKind == OMPC_map) { 20709 if (CI != CE || SI != SE) { 20710 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is 20711 // a pointer. 20712 auto Begin = 20713 CI != CE ? CurComponents.begin() : StackComponents.begin(); 20714 auto End = CI != CE ? CurComponents.end() : StackComponents.end(); 20715 auto It = Begin; 20716 while (It != End && !It->getAssociatedDeclaration()) 20717 std::advance(It, 1); 20718 assert(It != End && 20719 "Expected at least one component with the declaration."); 20720 if (It != Begin && It->getAssociatedDeclaration() 20721 ->getType() 20722 .getCanonicalType() 20723 ->isAnyPointerType()) { 20724 IsEnclosedByDataEnvironmentExpr = false; 20725 EnclosingExpr = nullptr; 20726 return false; 20727 } 20728 } 20729 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange; 20730 } else { 20731 assert(CKind == OMPC_to || CKind == OMPC_from); 20732 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update) 20733 << ERange; 20734 } 20735 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here) 20736 << RE->getSourceRange(); 20737 return true; 20738 } 20739 20740 // The current expression uses the same base as other expression in the 20741 // data environment but does not contain it completely. 20742 if (!CurrentRegionOnly && SI != SE) 20743 EnclosingExpr = RE; 20744 20745 // The current expression is a subset of the expression in the data 20746 // environment. 20747 IsEnclosedByDataEnvironmentExpr |= 20748 (!CurrentRegionOnly && CI != CE && SI == SE); 20749 20750 return false; 20751 }); 20752 20753 if (CurrentRegionOnly) 20754 return FoundError; 20755 20756 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5] 20757 // If any part of the original storage of a list item has corresponding 20758 // storage in the device data environment, all of the original storage must 20759 // have corresponding storage in the device data environment. 20760 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6] 20761 // If a list item is an element of a structure, and a different element of 20762 // the structure has a corresponding list item in the device data environment 20763 // prior to a task encountering the construct associated with the map clause, 20764 // then the list item must also have a corresponding list item in the device 20765 // data environment prior to the task encountering the construct. 20766 // 20767 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) { 20768 SemaRef.Diag(ELoc, 20769 diag::err_omp_original_storage_is_shared_and_does_not_contain) 20770 << ERange; 20771 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here) 20772 << EnclosingExpr->getSourceRange(); 20773 return true; 20774 } 20775 20776 return FoundError; 20777 } 20778 20779 // Look up the user-defined mapper given the mapper name and mapped type, and 20780 // build a reference to it. 20781 static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, 20782 CXXScopeSpec &MapperIdScopeSpec, 20783 const DeclarationNameInfo &MapperId, 20784 QualType Type, 20785 Expr *UnresolvedMapper) { 20786 if (MapperIdScopeSpec.isInvalid()) 20787 return ExprError(); 20788 // Get the actual type for the array type. 20789 if (Type->isArrayType()) { 20790 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type"); 20791 Type = Type->getAsArrayTypeUnsafe()->getElementType().getCanonicalType(); 20792 } 20793 // Find all user-defined mappers with the given MapperId. 20794 SmallVector<UnresolvedSet<8>, 4> Lookups; 20795 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName); 20796 Lookup.suppressDiagnostics(); 20797 if (S) { 20798 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec, 20799 /*ObjectType=*/QualType())) { 20800 NamedDecl *D = Lookup.getRepresentativeDecl(); 20801 while (S && !S->isDeclScope(D)) 20802 S = S->getParent(); 20803 if (S) 20804 S = S->getParent(); 20805 Lookups.emplace_back(); 20806 Lookups.back().append(Lookup.begin(), Lookup.end()); 20807 Lookup.clear(); 20808 } 20809 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) { 20810 // Extract the user-defined mappers with the given MapperId. 20811 Lookups.push_back(UnresolvedSet<8>()); 20812 for (NamedDecl *D : ULE->decls()) { 20813 auto *DMD = cast<OMPDeclareMapperDecl>(D); 20814 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation."); 20815 Lookups.back().addDecl(DMD); 20816 } 20817 } 20818 // Defer the lookup for dependent types. The results will be passed through 20819 // UnresolvedMapper on instantiation. 20820 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() || 20821 Type->isInstantiationDependentType() || 20822 Type->containsUnexpandedParameterPack() || 20823 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) { 20824 return !D->isInvalidDecl() && 20825 (D->getType()->isDependentType() || 20826 D->getType()->isInstantiationDependentType() || 20827 D->getType()->containsUnexpandedParameterPack()); 20828 })) { 20829 UnresolvedSet<8> URS; 20830 for (const UnresolvedSet<8> &Set : Lookups) { 20831 if (Set.empty()) 20832 continue; 20833 URS.append(Set.begin(), Set.end()); 20834 } 20835 return UnresolvedLookupExpr::Create( 20836 SemaRef.Context, /*NamingClass=*/nullptr, 20837 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId, 20838 /*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false, 20839 /*KnownInstantiationDependent=*/false); 20840 } 20841 SourceLocation Loc = MapperId.getLoc(); 20842 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions 20843 // The type must be of struct, union or class type in C and C++ 20844 if (!Type->isStructureOrClassType() && !Type->isUnionType() && 20845 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) { 20846 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type); 20847 return ExprError(); 20848 } 20849 // Perform argument dependent lookup. 20850 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet()) 20851 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups); 20852 // Return the first user-defined mapper with the desired type. 20853 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>( 20854 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * { 20855 if (!D->isInvalidDecl() && 20856 SemaRef.Context.hasSameType(D->getType(), Type)) 20857 return D; 20858 return nullptr; 20859 })) 20860 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc); 20861 // Find the first user-defined mapper with a type derived from the desired 20862 // type. 20863 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>( 20864 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * { 20865 if (!D->isInvalidDecl() && 20866 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) && 20867 !Type.isMoreQualifiedThan(D->getType())) 20868 return D; 20869 return nullptr; 20870 })) { 20871 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, 20872 /*DetectVirtual=*/false); 20873 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) { 20874 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType( 20875 VD->getType().getUnqualifiedType()))) { 20876 if (SemaRef.CheckBaseClassAccess( 20877 Loc, VD->getType(), Type, Paths.front(), 20878 /*DiagID=*/0) != Sema::AR_inaccessible) { 20879 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc); 20880 } 20881 } 20882 } 20883 } 20884 // Report error if a mapper is specified, but cannot be found. 20885 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") { 20886 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper) 20887 << Type << MapperId.getName(); 20888 return ExprError(); 20889 } 20890 return ExprEmpty(); 20891 } 20892 20893 namespace { 20894 // Utility struct that gathers all the related lists associated with a mappable 20895 // expression. 20896 struct MappableVarListInfo { 20897 // The list of expressions. 20898 ArrayRef<Expr *> VarList; 20899 // The list of processed expressions. 20900 SmallVector<Expr *, 16> ProcessedVarList; 20901 // The mappble components for each expression. 20902 OMPClauseMappableExprCommon::MappableExprComponentLists VarComponents; 20903 // The base declaration of the variable. 20904 SmallVector<ValueDecl *, 16> VarBaseDeclarations; 20905 // The reference to the user-defined mapper associated with every expression. 20906 SmallVector<Expr *, 16> UDMapperList; 20907 20908 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) { 20909 // We have a list of components and base declarations for each entry in the 20910 // variable list. 20911 VarComponents.reserve(VarList.size()); 20912 VarBaseDeclarations.reserve(VarList.size()); 20913 } 20914 }; 20915 } // namespace 20916 20917 // Check the validity of the provided variable list for the provided clause kind 20918 // \a CKind. In the check process the valid expressions, mappable expression 20919 // components, variables, and user-defined mappers are extracted and used to 20920 // fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a 20921 // UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec, 20922 // and \a MapperId are expected to be valid if the clause kind is 'map'. 20923 static void checkMappableExpressionList( 20924 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind, 20925 MappableVarListInfo &MVLI, SourceLocation StartLoc, 20926 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId, 20927 ArrayRef<Expr *> UnresolvedMappers, 20928 OpenMPMapClauseKind MapType = OMPC_MAP_unknown, 20929 ArrayRef<OpenMPMapModifierKind> Modifiers = std::nullopt, 20930 bool IsMapTypeImplicit = false, bool NoDiagnose = false) { 20931 // We only expect mappable expressions in 'to', 'from', and 'map' clauses. 20932 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) && 20933 "Unexpected clause kind with mappable expressions!"); 20934 20935 // If the identifier of user-defined mapper is not specified, it is "default". 20936 // We do not change the actual name in this clause to distinguish whether a 20937 // mapper is specified explicitly, i.e., it is not explicitly specified when 20938 // MapperId.getName() is empty. 20939 if (!MapperId.getName() || MapperId.getName().isEmpty()) { 20940 auto &DeclNames = SemaRef.getASTContext().DeclarationNames; 20941 MapperId.setName(DeclNames.getIdentifier( 20942 &SemaRef.getASTContext().Idents.get("default"))); 20943 MapperId.setLoc(StartLoc); 20944 } 20945 20946 // Iterators to find the current unresolved mapper expression. 20947 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end(); 20948 bool UpdateUMIt = false; 20949 Expr *UnresolvedMapper = nullptr; 20950 20951 bool HasHoldModifier = 20952 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold); 20953 20954 // Keep track of the mappable components and base declarations in this clause. 20955 // Each entry in the list is going to have a list of components associated. We 20956 // record each set of the components so that we can build the clause later on. 20957 // In the end we should have the same amount of declarations and component 20958 // lists. 20959 20960 for (Expr *RE : MVLI.VarList) { 20961 assert(RE && "Null expr in omp to/from/map clause"); 20962 SourceLocation ELoc = RE->getExprLoc(); 20963 20964 // Find the current unresolved mapper expression. 20965 if (UpdateUMIt && UMIt != UMEnd) { 20966 UMIt++; 20967 assert( 20968 UMIt != UMEnd && 20969 "Expect the size of UnresolvedMappers to match with that of VarList"); 20970 } 20971 UpdateUMIt = true; 20972 if (UMIt != UMEnd) 20973 UnresolvedMapper = *UMIt; 20974 20975 const Expr *VE = RE->IgnoreParenLValueCasts(); 20976 20977 if (VE->isValueDependent() || VE->isTypeDependent() || 20978 VE->isInstantiationDependent() || 20979 VE->containsUnexpandedParameterPack()) { 20980 // Try to find the associated user-defined mapper. 20981 ExprResult ER = buildUserDefinedMapperRef( 20982 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId, 20983 VE->getType().getCanonicalType(), UnresolvedMapper); 20984 if (ER.isInvalid()) 20985 continue; 20986 MVLI.UDMapperList.push_back(ER.get()); 20987 // We can only analyze this information once the missing information is 20988 // resolved. 20989 MVLI.ProcessedVarList.push_back(RE); 20990 continue; 20991 } 20992 20993 Expr *SimpleExpr = RE->IgnoreParenCasts(); 20994 20995 if (!RE->isLValue()) { 20996 if (SemaRef.getLangOpts().OpenMP < 50) { 20997 SemaRef.Diag( 20998 ELoc, diag::err_omp_expected_named_var_member_or_array_expression) 20999 << RE->getSourceRange(); 21000 } else { 21001 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses) 21002 << getOpenMPClauseName(CKind) << RE->getSourceRange(); 21003 } 21004 continue; 21005 } 21006 21007 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents; 21008 ValueDecl *CurDeclaration = nullptr; 21009 21010 // Obtain the array or member expression bases if required. Also, fill the 21011 // components array with all the components identified in the process. 21012 const Expr *BE = 21013 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind, 21014 DSAS->getCurrentDirective(), NoDiagnose); 21015 if (!BE) 21016 continue; 21017 21018 assert(!CurComponents.empty() && 21019 "Invalid mappable expression information."); 21020 21021 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) { 21022 // Add store "this" pointer to class in DSAStackTy for future checking 21023 DSAS->addMappedClassesQualTypes(TE->getType()); 21024 // Try to find the associated user-defined mapper. 21025 ExprResult ER = buildUserDefinedMapperRef( 21026 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId, 21027 VE->getType().getCanonicalType(), UnresolvedMapper); 21028 if (ER.isInvalid()) 21029 continue; 21030 MVLI.UDMapperList.push_back(ER.get()); 21031 // Skip restriction checking for variable or field declarations 21032 MVLI.ProcessedVarList.push_back(RE); 21033 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1); 21034 MVLI.VarComponents.back().append(CurComponents.begin(), 21035 CurComponents.end()); 21036 MVLI.VarBaseDeclarations.push_back(nullptr); 21037 continue; 21038 } 21039 21040 // For the following checks, we rely on the base declaration which is 21041 // expected to be associated with the last component. The declaration is 21042 // expected to be a variable or a field (if 'this' is being mapped). 21043 CurDeclaration = CurComponents.back().getAssociatedDeclaration(); 21044 assert(CurDeclaration && "Null decl on map clause."); 21045 assert( 21046 CurDeclaration->isCanonicalDecl() && 21047 "Expecting components to have associated only canonical declarations."); 21048 21049 auto *VD = dyn_cast<VarDecl>(CurDeclaration); 21050 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration); 21051 21052 assert((VD || FD) && "Only variables or fields are expected here!"); 21053 (void)FD; 21054 21055 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10] 21056 // threadprivate variables cannot appear in a map clause. 21057 // OpenMP 4.5 [2.10.5, target update Construct] 21058 // threadprivate variables cannot appear in a from clause. 21059 if (VD && DSAS->isThreadPrivate(VD)) { 21060 if (NoDiagnose) 21061 continue; 21062 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false); 21063 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause) 21064 << getOpenMPClauseName(CKind); 21065 reportOriginalDsa(SemaRef, DSAS, VD, DVar); 21066 continue; 21067 } 21068 21069 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9] 21070 // A list item cannot appear in both a map clause and a data-sharing 21071 // attribute clause on the same construct. 21072 21073 // Check conflicts with other map clause expressions. We check the conflicts 21074 // with the current construct separately from the enclosing data 21075 // environment, because the restrictions are different. We only have to 21076 // check conflicts across regions for the map clauses. 21077 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr, 21078 /*CurrentRegionOnly=*/true, CurComponents, CKind)) 21079 break; 21080 if (CKind == OMPC_map && 21081 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) && 21082 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr, 21083 /*CurrentRegionOnly=*/false, CurComponents, CKind)) 21084 break; 21085 21086 // OpenMP 4.5 [2.10.5, target update Construct] 21087 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1] 21088 // If the type of a list item is a reference to a type T then the type will 21089 // be considered to be T for all purposes of this clause. 21090 auto I = llvm::find_if( 21091 CurComponents, 21092 [](const OMPClauseMappableExprCommon::MappableComponent &MC) { 21093 return MC.getAssociatedDeclaration(); 21094 }); 21095 assert(I != CurComponents.end() && "Null decl on map clause."); 21096 (void)I; 21097 QualType Type; 21098 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens()); 21099 auto *OASE = dyn_cast<ArraySectionExpr>(VE->IgnoreParens()); 21100 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens()); 21101 if (ASE) { 21102 Type = ASE->getType().getNonReferenceType(); 21103 } else if (OASE) { 21104 QualType BaseType = 21105 ArraySectionExpr::getBaseOriginalType(OASE->getBase()); 21106 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe()) 21107 Type = ATy->getElementType(); 21108 else 21109 Type = BaseType->getPointeeType(); 21110 Type = Type.getNonReferenceType(); 21111 } else if (OAShE) { 21112 Type = OAShE->getBase()->getType()->getPointeeType(); 21113 } else { 21114 Type = VE->getType(); 21115 } 21116 21117 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4] 21118 // A list item in a to or from clause must have a mappable type. 21119 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9] 21120 // A list item must have a mappable type. 21121 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef, 21122 DSAS, Type, /*FullCheck=*/true)) 21123 continue; 21124 21125 if (CKind == OMPC_map) { 21126 // target enter data 21127 // OpenMP [2.10.2, Restrictions, p. 99] 21128 // A map-type must be specified in all map clauses and must be either 21129 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if 21130 // no map type is present. 21131 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective(); 21132 if (DKind == OMPD_target_enter_data && 21133 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc || 21134 SemaRef.getLangOpts().OpenMP >= 52)) { 21135 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive) 21136 << (IsMapTypeImplicit ? 1 : 0) 21137 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType) 21138 << getOpenMPDirectiveName(DKind); 21139 continue; 21140 } 21141 21142 // target exit_data 21143 // OpenMP [2.10.3, Restrictions, p. 102] 21144 // A map-type must be specified in all map clauses and must be either 21145 // from, release, or delete. Starting with OpenMP 5.2 the default map 21146 // type is `from` if no map type is present. 21147 if (DKind == OMPD_target_exit_data && 21148 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release || 21149 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) { 21150 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive) 21151 << (IsMapTypeImplicit ? 1 : 0) 21152 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType) 21153 << getOpenMPDirectiveName(DKind); 21154 continue; 21155 } 21156 21157 // The 'ompx_hold' modifier is specifically intended to be used on a 21158 // 'target' or 'target data' directive to prevent data from being unmapped 21159 // during the associated statement. It is not permitted on a 'target 21160 // enter data' or 'target exit data' directive, which have no associated 21161 // statement. 21162 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) && 21163 HasHoldModifier) { 21164 SemaRef.Diag(StartLoc, 21165 diag::err_omp_invalid_map_type_modifier_for_directive) 21166 << getOpenMPSimpleClauseTypeName(OMPC_map, 21167 OMPC_MAP_MODIFIER_ompx_hold) 21168 << getOpenMPDirectiveName(DKind); 21169 continue; 21170 } 21171 21172 // target, target data 21173 // OpenMP 5.0 [2.12.2, Restrictions, p. 163] 21174 // OpenMP 5.0 [2.12.5, Restrictions, p. 174] 21175 // A map-type in a map clause must be to, from, tofrom or alloc 21176 if ((DKind == OMPD_target_data || 21177 isOpenMPTargetExecutionDirective(DKind)) && 21178 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from || 21179 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) { 21180 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive) 21181 << (IsMapTypeImplicit ? 1 : 0) 21182 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType) 21183 << getOpenMPDirectiveName(DKind); 21184 continue; 21185 } 21186 21187 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3] 21188 // A list item cannot appear in both a map clause and a data-sharing 21189 // attribute clause on the same construct 21190 // 21191 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7] 21192 // A list item cannot appear in both a map clause and a data-sharing 21193 // attribute clause on the same construct unless the construct is a 21194 // combined construct. 21195 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 && 21196 isOpenMPTargetExecutionDirective(DKind)) || 21197 DKind == OMPD_target)) { 21198 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false); 21199 if (isOpenMPPrivate(DVar.CKind)) { 21200 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa) 21201 << getOpenMPClauseName(DVar.CKind) 21202 << getOpenMPClauseName(OMPC_map) 21203 << getOpenMPDirectiveName(DSAS->getCurrentDirective()); 21204 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar); 21205 continue; 21206 } 21207 } 21208 } 21209 21210 // Try to find the associated user-defined mapper. 21211 ExprResult ER = buildUserDefinedMapperRef( 21212 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId, 21213 Type.getCanonicalType(), UnresolvedMapper); 21214 if (ER.isInvalid()) 21215 continue; 21216 MVLI.UDMapperList.push_back(ER.get()); 21217 21218 // Save the current expression. 21219 MVLI.ProcessedVarList.push_back(RE); 21220 21221 // Store the components in the stack so that they can be used to check 21222 // against other clauses later on. 21223 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents, 21224 /*WhereFoundClauseKind=*/OMPC_map); 21225 21226 // Save the components and declaration to create the clause. For purposes of 21227 // the clause creation, any component list that has base 'this' uses 21228 // null as base declaration. 21229 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1); 21230 MVLI.VarComponents.back().append(CurComponents.begin(), 21231 CurComponents.end()); 21232 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr 21233 : CurDeclaration); 21234 } 21235 } 21236 21237 OMPClause *SemaOpenMP::ActOnOpenMPMapClause( 21238 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers, 21239 ArrayRef<SourceLocation> MapTypeModifiersLoc, 21240 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, 21241 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc, 21242 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, 21243 const OMPVarListLocTy &Locs, bool NoDiagnose, 21244 ArrayRef<Expr *> UnresolvedMappers) { 21245 OpenMPMapModifierKind Modifiers[] = { 21246 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown, 21247 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown, 21248 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown}; 21249 SourceLocation ModifiersLoc[NumberOfOMPMapClauseModifiers]; 21250 21251 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType( 21252 BuiltinType::OMPIterator)) 21253 Diag(IteratorModifier->getExprLoc(), 21254 diag::err_omp_map_modifier_not_iterator); 21255 21256 // Process map-type-modifiers, flag errors for duplicate modifiers. 21257 unsigned Count = 0; 21258 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) { 21259 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown && 21260 llvm::is_contained(Modifiers, MapTypeModifiers[I])) { 21261 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier); 21262 continue; 21263 } 21264 assert(Count < NumberOfOMPMapClauseModifiers && 21265 "Modifiers exceed the allowed number of map type modifiers"); 21266 Modifiers[Count] = MapTypeModifiers[I]; 21267 ModifiersLoc[Count] = MapTypeModifiersLoc[I]; 21268 ++Count; 21269 } 21270 21271 MappableVarListInfo MVLI(VarList); 21272 checkMappableExpressionList(SemaRef, DSAStack, OMPC_map, MVLI, Locs.StartLoc, 21273 MapperIdScopeSpec, MapperId, UnresolvedMappers, 21274 MapType, Modifiers, IsMapTypeImplicit, 21275 NoDiagnose); 21276 21277 // We need to produce a map clause even if we don't have variables so that 21278 // other diagnostics related with non-existing map clauses are accurate. 21279 return OMPMapClause::Create( 21280 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations, 21281 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers, 21282 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()), 21283 MapperId, MapType, IsMapTypeImplicit, MapLoc); 21284 } 21285 21286 QualType SemaOpenMP::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, 21287 TypeResult ParsedType) { 21288 assert(ParsedType.isUsable()); 21289 21290 QualType ReductionType = SemaRef.GetTypeFromParser(ParsedType.get()); 21291 if (ReductionType.isNull()) 21292 return QualType(); 21293 21294 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++ 21295 // A type name in a declare reduction directive cannot be a function type, an 21296 // array type, a reference type, or a type qualified with const, volatile or 21297 // restrict. 21298 if (ReductionType.hasQualifiers()) { 21299 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0; 21300 return QualType(); 21301 } 21302 21303 if (ReductionType->isFunctionType()) { 21304 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1; 21305 return QualType(); 21306 } 21307 if (ReductionType->isReferenceType()) { 21308 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2; 21309 return QualType(); 21310 } 21311 if (ReductionType->isArrayType()) { 21312 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3; 21313 return QualType(); 21314 } 21315 return ReductionType; 21316 } 21317 21318 SemaOpenMP::DeclGroupPtrTy 21319 SemaOpenMP::ActOnOpenMPDeclareReductionDirectiveStart( 21320 Scope *S, DeclContext *DC, DeclarationName Name, 21321 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes, 21322 AccessSpecifier AS, Decl *PrevDeclInScope) { 21323 SmallVector<Decl *, 8> Decls; 21324 Decls.reserve(ReductionTypes.size()); 21325 21326 LookupResult Lookup(SemaRef, Name, SourceLocation(), 21327 Sema::LookupOMPReductionName, 21328 SemaRef.forRedeclarationInCurContext()); 21329 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions 21330 // A reduction-identifier may not be re-declared in the current scope for the 21331 // same type or for a type that is compatible according to the base language 21332 // rules. 21333 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes; 21334 OMPDeclareReductionDecl *PrevDRD = nullptr; 21335 bool InCompoundScope = true; 21336 if (S != nullptr) { 21337 // Find previous declaration with the same name not referenced in other 21338 // declarations. 21339 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction(); 21340 InCompoundScope = 21341 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty(); 21342 SemaRef.LookupName(Lookup, S); 21343 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false, 21344 /*AllowInlineNamespace=*/false); 21345 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious; 21346 LookupResult::Filter Filter = Lookup.makeFilter(); 21347 while (Filter.hasNext()) { 21348 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next()); 21349 if (InCompoundScope) { 21350 auto I = UsedAsPrevious.find(PrevDecl); 21351 if (I == UsedAsPrevious.end()) 21352 UsedAsPrevious[PrevDecl] = false; 21353 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope()) 21354 UsedAsPrevious[D] = true; 21355 } 21356 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] = 21357 PrevDecl->getLocation(); 21358 } 21359 Filter.done(); 21360 if (InCompoundScope) { 21361 for (const auto &PrevData : UsedAsPrevious) { 21362 if (!PrevData.second) { 21363 PrevDRD = PrevData.first; 21364 break; 21365 } 21366 } 21367 } 21368 } else if (PrevDeclInScope != nullptr) { 21369 auto *PrevDRDInScope = PrevDRD = 21370 cast<OMPDeclareReductionDecl>(PrevDeclInScope); 21371 do { 21372 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] = 21373 PrevDRDInScope->getLocation(); 21374 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope(); 21375 } while (PrevDRDInScope != nullptr); 21376 } 21377 for (const auto &TyData : ReductionTypes) { 21378 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType()); 21379 bool Invalid = false; 21380 if (I != PreviousRedeclTypes.end()) { 21381 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition) 21382 << TyData.first; 21383 Diag(I->second, diag::note_previous_definition); 21384 Invalid = true; 21385 } 21386 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second; 21387 auto *DRD = OMPDeclareReductionDecl::Create( 21388 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD); 21389 DC->addDecl(DRD); 21390 DRD->setAccess(AS); 21391 Decls.push_back(DRD); 21392 if (Invalid) 21393 DRD->setInvalidDecl(); 21394 else 21395 PrevDRD = DRD; 21396 } 21397 21398 return DeclGroupPtrTy::make( 21399 DeclGroupRef::Create(getASTContext(), Decls.begin(), Decls.size())); 21400 } 21401 21402 void SemaOpenMP::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) { 21403 auto *DRD = cast<OMPDeclareReductionDecl>(D); 21404 21405 // Enter new function scope. 21406 SemaRef.PushFunctionScope(); 21407 SemaRef.setFunctionHasBranchProtectedScope(); 21408 SemaRef.getCurFunction()->setHasOMPDeclareReductionCombiner(); 21409 21410 if (S != nullptr) 21411 SemaRef.PushDeclContext(S, DRD); 21412 else 21413 SemaRef.CurContext = DRD; 21414 21415 SemaRef.PushExpressionEvaluationContext( 21416 Sema::ExpressionEvaluationContext::PotentiallyEvaluated); 21417 21418 QualType ReductionType = DRD->getType(); 21419 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will 21420 // be replaced by '*omp_parm' during codegen. This required because 'omp_in' 21421 // uses semantics of argument handles by value, but it should be passed by 21422 // reference. C lang does not support references, so pass all parameters as 21423 // pointers. 21424 // Create 'T omp_in;' variable. 21425 VarDecl *OmpInParm = 21426 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_in"); 21427 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will 21428 // be replaced by '*omp_parm' during codegen. This required because 'omp_out' 21429 // uses semantics of argument handles by value, but it should be passed by 21430 // reference. C lang does not support references, so pass all parameters as 21431 // pointers. 21432 // Create 'T omp_out;' variable. 21433 VarDecl *OmpOutParm = 21434 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_out"); 21435 if (S != nullptr) { 21436 SemaRef.PushOnScopeChains(OmpInParm, S); 21437 SemaRef.PushOnScopeChains(OmpOutParm, S); 21438 } else { 21439 DRD->addDecl(OmpInParm); 21440 DRD->addDecl(OmpOutParm); 21441 } 21442 Expr *InE = 21443 ::buildDeclRefExpr(SemaRef, OmpInParm, ReductionType, D->getLocation()); 21444 Expr *OutE = 21445 ::buildDeclRefExpr(SemaRef, OmpOutParm, ReductionType, D->getLocation()); 21446 DRD->setCombinerData(InE, OutE); 21447 } 21448 21449 void SemaOpenMP::ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, 21450 Expr *Combiner) { 21451 auto *DRD = cast<OMPDeclareReductionDecl>(D); 21452 SemaRef.DiscardCleanupsInEvaluationContext(); 21453 SemaRef.PopExpressionEvaluationContext(); 21454 21455 SemaRef.PopDeclContext(); 21456 SemaRef.PopFunctionScopeInfo(); 21457 21458 if (Combiner != nullptr) 21459 DRD->setCombiner(Combiner); 21460 else 21461 DRD->setInvalidDecl(); 21462 } 21463 21464 VarDecl *SemaOpenMP::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, 21465 Decl *D) { 21466 auto *DRD = cast<OMPDeclareReductionDecl>(D); 21467 21468 // Enter new function scope. 21469 SemaRef.PushFunctionScope(); 21470 SemaRef.setFunctionHasBranchProtectedScope(); 21471 21472 if (S != nullptr) 21473 SemaRef.PushDeclContext(S, DRD); 21474 else 21475 SemaRef.CurContext = DRD; 21476 21477 SemaRef.PushExpressionEvaluationContext( 21478 Sema::ExpressionEvaluationContext::PotentiallyEvaluated); 21479 21480 QualType ReductionType = DRD->getType(); 21481 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will 21482 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv' 21483 // uses semantics of argument handles by value, but it should be passed by 21484 // reference. C lang does not support references, so pass all parameters as 21485 // pointers. 21486 // Create 'T omp_priv;' variable. 21487 VarDecl *OmpPrivParm = 21488 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_priv"); 21489 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will 21490 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig' 21491 // uses semantics of argument handles by value, but it should be passed by 21492 // reference. C lang does not support references, so pass all parameters as 21493 // pointers. 21494 // Create 'T omp_orig;' variable. 21495 VarDecl *OmpOrigParm = 21496 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_orig"); 21497 if (S != nullptr) { 21498 SemaRef.PushOnScopeChains(OmpPrivParm, S); 21499 SemaRef.PushOnScopeChains(OmpOrigParm, S); 21500 } else { 21501 DRD->addDecl(OmpPrivParm); 21502 DRD->addDecl(OmpOrigParm); 21503 } 21504 Expr *OrigE = 21505 ::buildDeclRefExpr(SemaRef, OmpOrigParm, ReductionType, D->getLocation()); 21506 Expr *PrivE = 21507 ::buildDeclRefExpr(SemaRef, OmpPrivParm, ReductionType, D->getLocation()); 21508 DRD->setInitializerData(OrigE, PrivE); 21509 return OmpPrivParm; 21510 } 21511 21512 void SemaOpenMP::ActOnOpenMPDeclareReductionInitializerEnd( 21513 Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) { 21514 auto *DRD = cast<OMPDeclareReductionDecl>(D); 21515 SemaRef.DiscardCleanupsInEvaluationContext(); 21516 SemaRef.PopExpressionEvaluationContext(); 21517 21518 SemaRef.PopDeclContext(); 21519 SemaRef.PopFunctionScopeInfo(); 21520 21521 if (Initializer != nullptr) { 21522 DRD->setInitializer(Initializer, OMPDeclareReductionInitKind::Call); 21523 } else if (OmpPrivParm->hasInit()) { 21524 DRD->setInitializer(OmpPrivParm->getInit(), 21525 OmpPrivParm->isDirectInit() 21526 ? OMPDeclareReductionInitKind::Direct 21527 : OMPDeclareReductionInitKind::Copy); 21528 } else { 21529 DRD->setInvalidDecl(); 21530 } 21531 } 21532 21533 SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareReductionDirectiveEnd( 21534 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) { 21535 for (Decl *D : DeclReductions.get()) { 21536 if (IsValid) { 21537 if (S) 21538 SemaRef.PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S, 21539 /*AddToContext=*/false); 21540 } else { 21541 D->setInvalidDecl(); 21542 } 21543 } 21544 return DeclReductions; 21545 } 21546 21547 TypeResult SemaOpenMP::ActOnOpenMPDeclareMapperVarDecl(Scope *S, 21548 Declarator &D) { 21549 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D); 21550 QualType T = TInfo->getType(); 21551 if (D.isInvalidType()) 21552 return true; 21553 21554 if (getLangOpts().CPlusPlus) { 21555 // Check that there are no default arguments (C++ only). 21556 SemaRef.CheckExtraCXXDefaultArguments(D); 21557 } 21558 21559 return SemaRef.CreateParsedType(T, TInfo); 21560 } 21561 21562 QualType SemaOpenMP::ActOnOpenMPDeclareMapperType(SourceLocation TyLoc, 21563 TypeResult ParsedType) { 21564 assert(ParsedType.isUsable() && "Expect usable parsed mapper type"); 21565 21566 QualType MapperType = SemaRef.GetTypeFromParser(ParsedType.get()); 21567 assert(!MapperType.isNull() && "Expect valid mapper type"); 21568 21569 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions 21570 // The type must be of struct, union or class type in C and C++ 21571 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) { 21572 Diag(TyLoc, diag::err_omp_mapper_wrong_type); 21573 return QualType(); 21574 } 21575 return MapperType; 21576 } 21577 21578 SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareMapperDirective( 21579 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType, 21580 SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS, 21581 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) { 21582 LookupResult Lookup(SemaRef, Name, SourceLocation(), 21583 Sema::LookupOMPMapperName, 21584 SemaRef.forRedeclarationInCurContext()); 21585 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions 21586 // A mapper-identifier may not be redeclared in the current scope for the 21587 // same type or for a type that is compatible according to the base language 21588 // rules. 21589 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes; 21590 OMPDeclareMapperDecl *PrevDMD = nullptr; 21591 bool InCompoundScope = true; 21592 if (S != nullptr) { 21593 // Find previous declaration with the same name not referenced in other 21594 // declarations. 21595 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction(); 21596 InCompoundScope = 21597 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty(); 21598 SemaRef.LookupName(Lookup, S); 21599 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false, 21600 /*AllowInlineNamespace=*/false); 21601 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious; 21602 LookupResult::Filter Filter = Lookup.makeFilter(); 21603 while (Filter.hasNext()) { 21604 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next()); 21605 if (InCompoundScope) { 21606 auto I = UsedAsPrevious.find(PrevDecl); 21607 if (I == UsedAsPrevious.end()) 21608 UsedAsPrevious[PrevDecl] = false; 21609 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope()) 21610 UsedAsPrevious[D] = true; 21611 } 21612 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] = 21613 PrevDecl->getLocation(); 21614 } 21615 Filter.done(); 21616 if (InCompoundScope) { 21617 for (const auto &PrevData : UsedAsPrevious) { 21618 if (!PrevData.second) { 21619 PrevDMD = PrevData.first; 21620 break; 21621 } 21622 } 21623 } 21624 } else if (PrevDeclInScope) { 21625 auto *PrevDMDInScope = PrevDMD = 21626 cast<OMPDeclareMapperDecl>(PrevDeclInScope); 21627 do { 21628 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] = 21629 PrevDMDInScope->getLocation(); 21630 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope(); 21631 } while (PrevDMDInScope != nullptr); 21632 } 21633 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType()); 21634 bool Invalid = false; 21635 if (I != PreviousRedeclTypes.end()) { 21636 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition) 21637 << MapperType << Name; 21638 Diag(I->second, diag::note_previous_definition); 21639 Invalid = true; 21640 } 21641 // Build expressions for implicit maps of data members with 'default' 21642 // mappers. 21643 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses.begin(), 21644 Clauses.end()); 21645 if (getLangOpts().OpenMP >= 50) 21646 processImplicitMapsWithDefaultMappers(SemaRef, DSAStack, 21647 ClausesWithImplicit); 21648 auto *DMD = OMPDeclareMapperDecl::Create(getASTContext(), DC, StartLoc, Name, 21649 MapperType, VN, ClausesWithImplicit, 21650 PrevDMD); 21651 if (S) 21652 SemaRef.PushOnScopeChains(DMD, S); 21653 else 21654 DC->addDecl(DMD); 21655 DMD->setAccess(AS); 21656 if (Invalid) 21657 DMD->setInvalidDecl(); 21658 21659 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl(); 21660 VD->setDeclContext(DMD); 21661 VD->setLexicalDeclContext(DMD); 21662 DMD->addDecl(VD); 21663 DMD->setMapperVarRef(MapperVarRef); 21664 21665 return DeclGroupPtrTy::make(DeclGroupRef(DMD)); 21666 } 21667 21668 ExprResult SemaOpenMP::ActOnOpenMPDeclareMapperDirectiveVarDecl( 21669 Scope *S, QualType MapperType, SourceLocation StartLoc, 21670 DeclarationName VN) { 21671 TypeSourceInfo *TInfo = 21672 getASTContext().getTrivialTypeSourceInfo(MapperType, StartLoc); 21673 auto *VD = VarDecl::Create( 21674 getASTContext(), getASTContext().getTranslationUnitDecl(), StartLoc, 21675 StartLoc, VN.getAsIdentifierInfo(), MapperType, TInfo, SC_None); 21676 if (S) 21677 SemaRef.PushOnScopeChains(VD, S, /*AddToContext=*/false); 21678 Expr *E = buildDeclRefExpr(SemaRef, VD, MapperType, StartLoc); 21679 DSAStack->addDeclareMapperVarRef(E); 21680 return E; 21681 } 21682 21683 void SemaOpenMP::ActOnOpenMPIteratorVarDecl(VarDecl *VD) { 21684 if (DSAStack->getDeclareMapperVarRef()) 21685 DSAStack->addIteratorVarDecl(VD); 21686 } 21687 21688 bool SemaOpenMP::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const { 21689 assert(getLangOpts().OpenMP && "Expected OpenMP mode."); 21690 const Expr *Ref = DSAStack->getDeclareMapperVarRef(); 21691 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) { 21692 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl()) 21693 return true; 21694 if (VD->isUsableInConstantExpressions(getASTContext())) 21695 return true; 21696 if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD)) 21697 return true; 21698 return false; 21699 } 21700 return true; 21701 } 21702 21703 const ValueDecl *SemaOpenMP::getOpenMPDeclareMapperVarName() const { 21704 assert(getLangOpts().OpenMP && "Expected OpenMP mode."); 21705 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl(); 21706 } 21707 21708 OMPClause *SemaOpenMP::ActOnOpenMPNumTeamsClause(Expr *NumTeams, 21709 SourceLocation StartLoc, 21710 SourceLocation LParenLoc, 21711 SourceLocation EndLoc) { 21712 Expr *ValExpr = NumTeams; 21713 Stmt *HelperValStmt = nullptr; 21714 21715 // OpenMP [teams Constrcut, Restrictions] 21716 // The num_teams expression must evaluate to a positive integer value. 21717 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_teams, 21718 /*StrictlyPositive=*/true)) 21719 return nullptr; 21720 21721 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); 21722 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause( 21723 DKind, OMPC_num_teams, getLangOpts().OpenMP); 21724 if (CaptureRegion != OMPD_unknown && 21725 !SemaRef.CurContext->isDependentContext()) { 21726 ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); 21727 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 21728 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); 21729 HelperValStmt = buildPreInits(getASTContext(), Captures); 21730 } 21731 21732 return new (getASTContext()) OMPNumTeamsClause( 21733 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc); 21734 } 21735 21736 OMPClause *SemaOpenMP::ActOnOpenMPThreadLimitClause(Expr *ThreadLimit, 21737 SourceLocation StartLoc, 21738 SourceLocation LParenLoc, 21739 SourceLocation EndLoc) { 21740 Expr *ValExpr = ThreadLimit; 21741 Stmt *HelperValStmt = nullptr; 21742 21743 // OpenMP [teams Constrcut, Restrictions] 21744 // The thread_limit expression must evaluate to a positive integer value. 21745 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_thread_limit, 21746 /*StrictlyPositive=*/true)) 21747 return nullptr; 21748 21749 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); 21750 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause( 21751 DKind, OMPC_thread_limit, getLangOpts().OpenMP); 21752 if (CaptureRegion != OMPD_unknown && 21753 !SemaRef.CurContext->isDependentContext()) { 21754 ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); 21755 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 21756 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); 21757 HelperValStmt = buildPreInits(getASTContext(), Captures); 21758 } 21759 21760 return new (getASTContext()) OMPThreadLimitClause( 21761 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc); 21762 } 21763 21764 OMPClause *SemaOpenMP::ActOnOpenMPPriorityClause(Expr *Priority, 21765 SourceLocation StartLoc, 21766 SourceLocation LParenLoc, 21767 SourceLocation EndLoc) { 21768 Expr *ValExpr = Priority; 21769 Stmt *HelperValStmt = nullptr; 21770 OpenMPDirectiveKind CaptureRegion = OMPD_unknown; 21771 21772 // OpenMP [2.9.1, task Constrcut] 21773 // The priority-value is a non-negative numerical scalar expression. 21774 if (!isNonNegativeIntegerValue( 21775 ValExpr, SemaRef, OMPC_priority, 21776 /*StrictlyPositive=*/false, /*BuildCapture=*/true, 21777 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt)) 21778 return nullptr; 21779 21780 return new (getASTContext()) OMPPriorityClause( 21781 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc); 21782 } 21783 21784 OMPClause *SemaOpenMP::ActOnOpenMPGrainsizeClause( 21785 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize, 21786 SourceLocation StartLoc, SourceLocation LParenLoc, 21787 SourceLocation ModifierLoc, SourceLocation EndLoc) { 21788 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) && 21789 "Unexpected grainsize modifier in OpenMP < 51."); 21790 21791 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) { 21792 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0, 21793 OMPC_GRAINSIZE_unknown); 21794 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value) 21795 << Values << getOpenMPClauseName(OMPC_grainsize); 21796 return nullptr; 21797 } 21798 21799 Expr *ValExpr = Grainsize; 21800 Stmt *HelperValStmt = nullptr; 21801 OpenMPDirectiveKind CaptureRegion = OMPD_unknown; 21802 21803 // OpenMP [2.9.2, taskloop Constrcut] 21804 // The parameter of the grainsize clause must be a positive integer 21805 // expression. 21806 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_grainsize, 21807 /*StrictlyPositive=*/true, 21808 /*BuildCapture=*/true, 21809 DSAStack->getCurrentDirective(), 21810 &CaptureRegion, &HelperValStmt)) 21811 return nullptr; 21812 21813 return new (getASTContext()) 21814 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, 21815 StartLoc, LParenLoc, ModifierLoc, EndLoc); 21816 } 21817 21818 OMPClause *SemaOpenMP::ActOnOpenMPNumTasksClause( 21819 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks, 21820 SourceLocation StartLoc, SourceLocation LParenLoc, 21821 SourceLocation ModifierLoc, SourceLocation EndLoc) { 21822 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) && 21823 "Unexpected num_tasks modifier in OpenMP < 51."); 21824 21825 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) { 21826 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0, 21827 OMPC_NUMTASKS_unknown); 21828 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value) 21829 << Values << getOpenMPClauseName(OMPC_num_tasks); 21830 return nullptr; 21831 } 21832 21833 Expr *ValExpr = NumTasks; 21834 Stmt *HelperValStmt = nullptr; 21835 OpenMPDirectiveKind CaptureRegion = OMPD_unknown; 21836 21837 // OpenMP [2.9.2, taskloop Constrcut] 21838 // The parameter of the num_tasks clause must be a positive integer 21839 // expression. 21840 if (!isNonNegativeIntegerValue( 21841 ValExpr, SemaRef, OMPC_num_tasks, 21842 /*StrictlyPositive=*/true, /*BuildCapture=*/true, 21843 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt)) 21844 return nullptr; 21845 21846 return new (getASTContext()) 21847 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, 21848 StartLoc, LParenLoc, ModifierLoc, EndLoc); 21849 } 21850 21851 OMPClause *SemaOpenMP::ActOnOpenMPHintClause(Expr *Hint, 21852 SourceLocation StartLoc, 21853 SourceLocation LParenLoc, 21854 SourceLocation EndLoc) { 21855 // OpenMP [2.13.2, critical construct, Description] 21856 // ... where hint-expression is an integer constant expression that evaluates 21857 // to a valid lock hint. 21858 ExprResult HintExpr = 21859 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false); 21860 if (HintExpr.isInvalid()) 21861 return nullptr; 21862 return new (getASTContext()) 21863 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc); 21864 } 21865 21866 /// Tries to find omp_event_handle_t type. 21867 static bool findOMPEventHandleT(Sema &S, SourceLocation Loc, 21868 DSAStackTy *Stack) { 21869 QualType OMPEventHandleT = Stack->getOMPEventHandleT(); 21870 if (!OMPEventHandleT.isNull()) 21871 return true; 21872 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t"); 21873 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope()); 21874 if (!PT.getAsOpaquePtr() || PT.get().isNull()) { 21875 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t"; 21876 return false; 21877 } 21878 Stack->setOMPEventHandleT(PT.get()); 21879 return true; 21880 } 21881 21882 OMPClause *SemaOpenMP::ActOnOpenMPDetachClause(Expr *Evt, 21883 SourceLocation StartLoc, 21884 SourceLocation LParenLoc, 21885 SourceLocation EndLoc) { 21886 if (!Evt->isValueDependent() && !Evt->isTypeDependent() && 21887 !Evt->isInstantiationDependent() && 21888 !Evt->containsUnexpandedParameterPack()) { 21889 if (!findOMPEventHandleT(SemaRef, Evt->getExprLoc(), DSAStack)) 21890 return nullptr; 21891 // OpenMP 5.0, 2.10.1 task Construct. 21892 // event-handle is a variable of the omp_event_handle_t type. 21893 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts()); 21894 if (!Ref) { 21895 Diag(Evt->getExprLoc(), diag::err_omp_var_expected) 21896 << "omp_event_handle_t" << 0 << Evt->getSourceRange(); 21897 return nullptr; 21898 } 21899 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl()); 21900 if (!VD) { 21901 Diag(Evt->getExprLoc(), diag::err_omp_var_expected) 21902 << "omp_event_handle_t" << 0 << Evt->getSourceRange(); 21903 return nullptr; 21904 } 21905 if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(), 21906 VD->getType()) || 21907 VD->getType().isConstant(getASTContext())) { 21908 Diag(Evt->getExprLoc(), diag::err_omp_var_expected) 21909 << "omp_event_handle_t" << 1 << VD->getType() 21910 << Evt->getSourceRange(); 21911 return nullptr; 21912 } 21913 // OpenMP 5.0, 2.10.1 task Construct 21914 // [detach clause]... The event-handle will be considered as if it was 21915 // specified on a firstprivate clause. 21916 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false); 21917 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate && 21918 DVar.RefExpr) { 21919 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa) 21920 << getOpenMPClauseName(DVar.CKind) 21921 << getOpenMPClauseName(OMPC_firstprivate); 21922 reportOriginalDsa(SemaRef, DSAStack, VD, DVar); 21923 return nullptr; 21924 } 21925 } 21926 21927 return new (getASTContext()) 21928 OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc); 21929 } 21930 21931 OMPClause *SemaOpenMP::ActOnOpenMPDistScheduleClause( 21932 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, 21933 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc, 21934 SourceLocation EndLoc) { 21935 if (Kind == OMPC_DIST_SCHEDULE_unknown) { 21936 std::string Values; 21937 Values += "'"; 21938 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0); 21939 Values += "'"; 21940 Diag(KindLoc, diag::err_omp_unexpected_clause_value) 21941 << Values << getOpenMPClauseName(OMPC_dist_schedule); 21942 return nullptr; 21943 } 21944 Expr *ValExpr = ChunkSize; 21945 Stmt *HelperValStmt = nullptr; 21946 if (ChunkSize) { 21947 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() && 21948 !ChunkSize->isInstantiationDependent() && 21949 !ChunkSize->containsUnexpandedParameterPack()) { 21950 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc(); 21951 ExprResult Val = 21952 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize); 21953 if (Val.isInvalid()) 21954 return nullptr; 21955 21956 ValExpr = Val.get(); 21957 21958 // OpenMP [2.7.1, Restrictions] 21959 // chunk_size must be a loop invariant integer expression with a positive 21960 // value. 21961 if (std::optional<llvm::APSInt> Result = 21962 ValExpr->getIntegerConstantExpr(getASTContext())) { 21963 if (Result->isSigned() && !Result->isStrictlyPositive()) { 21964 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause) 21965 << "dist_schedule" << ChunkSize->getSourceRange(); 21966 return nullptr; 21967 } 21968 } else if (getOpenMPCaptureRegionForClause( 21969 DSAStack->getCurrentDirective(), OMPC_dist_schedule, 21970 getLangOpts().OpenMP) != OMPD_unknown && 21971 !SemaRef.CurContext->isDependentContext()) { 21972 ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); 21973 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 21974 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); 21975 HelperValStmt = buildPreInits(getASTContext(), Captures); 21976 } 21977 } 21978 } 21979 21980 return new (getASTContext()) 21981 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, 21982 Kind, ValExpr, HelperValStmt); 21983 } 21984 21985 OMPClause *SemaOpenMP::ActOnOpenMPDefaultmapClause( 21986 OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind, 21987 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, 21988 SourceLocation KindLoc, SourceLocation EndLoc) { 21989 if (getLangOpts().OpenMP < 50) { 21990 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom || 21991 Kind != OMPC_DEFAULTMAP_scalar) { 21992 std::string Value; 21993 SourceLocation Loc; 21994 Value += "'"; 21995 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) { 21996 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap, 21997 OMPC_DEFAULTMAP_MODIFIER_tofrom); 21998 Loc = MLoc; 21999 } else { 22000 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap, 22001 OMPC_DEFAULTMAP_scalar); 22002 Loc = KindLoc; 22003 } 22004 Value += "'"; 22005 Diag(Loc, diag::err_omp_unexpected_clause_value) 22006 << Value << getOpenMPClauseName(OMPC_defaultmap); 22007 return nullptr; 22008 } 22009 } else { 22010 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown); 22011 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) || 22012 (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid()); 22013 if (!isDefaultmapKind || !isDefaultmapModifier) { 22014 StringRef KindValue = "'scalar', 'aggregate', 'pointer'"; 22015 if (getLangOpts().OpenMP == 50) { 22016 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', " 22017 "'firstprivate', 'none', 'default'"; 22018 if (!isDefaultmapKind && isDefaultmapModifier) { 22019 Diag(KindLoc, diag::err_omp_unexpected_clause_value) 22020 << KindValue << getOpenMPClauseName(OMPC_defaultmap); 22021 } else if (isDefaultmapKind && !isDefaultmapModifier) { 22022 Diag(MLoc, diag::err_omp_unexpected_clause_value) 22023 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap); 22024 } else { 22025 Diag(MLoc, diag::err_omp_unexpected_clause_value) 22026 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap); 22027 Diag(KindLoc, diag::err_omp_unexpected_clause_value) 22028 << KindValue << getOpenMPClauseName(OMPC_defaultmap); 22029 } 22030 } else { 22031 StringRef ModifierValue = 22032 "'alloc', 'from', 'to', 'tofrom', " 22033 "'firstprivate', 'none', 'default', 'present'"; 22034 if (!isDefaultmapKind && isDefaultmapModifier) { 22035 Diag(KindLoc, diag::err_omp_unexpected_clause_value) 22036 << KindValue << getOpenMPClauseName(OMPC_defaultmap); 22037 } else if (isDefaultmapKind && !isDefaultmapModifier) { 22038 Diag(MLoc, diag::err_omp_unexpected_clause_value) 22039 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap); 22040 } else { 22041 Diag(MLoc, diag::err_omp_unexpected_clause_value) 22042 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap); 22043 Diag(KindLoc, diag::err_omp_unexpected_clause_value) 22044 << KindValue << getOpenMPClauseName(OMPC_defaultmap); 22045 } 22046 } 22047 return nullptr; 22048 } 22049 22050 // OpenMP [5.0, 2.12.5, Restrictions, p. 174] 22051 // At most one defaultmap clause for each category can appear on the 22052 // directive. 22053 if (DSAStack->checkDefaultmapCategory(Kind)) { 22054 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category); 22055 return nullptr; 22056 } 22057 } 22058 if (Kind == OMPC_DEFAULTMAP_unknown) { 22059 // Variable category is not specified - mark all categories. 22060 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc); 22061 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc); 22062 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc); 22063 } else { 22064 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc); 22065 } 22066 22067 return new (getASTContext()) 22068 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M); 22069 } 22070 22071 bool SemaOpenMP::ActOnStartOpenMPDeclareTargetContext( 22072 DeclareTargetContextInfo &DTCI) { 22073 DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext(); 22074 if (!CurLexicalContext->isFileContext() && 22075 !CurLexicalContext->isExternCContext() && 22076 !CurLexicalContext->isExternCXXContext() && 22077 !isa<CXXRecordDecl>(CurLexicalContext) && 22078 !isa<ClassTemplateDecl>(CurLexicalContext) && 22079 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) && 22080 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) { 22081 Diag(DTCI.Loc, diag::err_omp_region_not_file_context); 22082 return false; 22083 } 22084 22085 // Report affected OpenMP target offloading behavior when in HIP lang-mode. 22086 if (getLangOpts().HIP) 22087 Diag(DTCI.Loc, diag::warn_hip_omp_target_directives); 22088 22089 DeclareTargetNesting.push_back(DTCI); 22090 return true; 22091 } 22092 22093 const SemaOpenMP::DeclareTargetContextInfo 22094 SemaOpenMP::ActOnOpenMPEndDeclareTargetDirective() { 22095 assert(!DeclareTargetNesting.empty() && 22096 "check isInOpenMPDeclareTargetContext() first!"); 22097 return DeclareTargetNesting.pop_back_val(); 22098 } 22099 22100 void SemaOpenMP::ActOnFinishedOpenMPDeclareTargetContext( 22101 DeclareTargetContextInfo &DTCI) { 22102 for (auto &It : DTCI.ExplicitlyMapped) 22103 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI); 22104 } 22105 22106 void SemaOpenMP::DiagnoseUnterminatedOpenMPDeclareTarget() { 22107 if (DeclareTargetNesting.empty()) 22108 return; 22109 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back(); 22110 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target) 22111 << getOpenMPDirectiveName(DTCI.Kind); 22112 } 22113 22114 NamedDecl *SemaOpenMP::lookupOpenMPDeclareTargetName( 22115 Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) { 22116 LookupResult Lookup(SemaRef, Id, Sema::LookupOrdinaryName); 22117 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec, 22118 /*ObjectType=*/QualType(), 22119 /*AllowBuiltinCreation=*/true); 22120 22121 if (Lookup.isAmbiguous()) 22122 return nullptr; 22123 Lookup.suppressDiagnostics(); 22124 22125 if (!Lookup.isSingleResult()) { 22126 VarOrFuncDeclFilterCCC CCC(SemaRef); 22127 if (TypoCorrection Corrected = 22128 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr, 22129 CCC, Sema::CTK_ErrorRecovery)) { 22130 SemaRef.diagnoseTypo(Corrected, 22131 PDiag(diag::err_undeclared_var_use_suggest) 22132 << Id.getName()); 22133 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl()); 22134 return nullptr; 22135 } 22136 22137 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName(); 22138 return nullptr; 22139 } 22140 22141 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>(); 22142 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) && 22143 !isa<FunctionTemplateDecl>(ND)) { 22144 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName(); 22145 return nullptr; 22146 } 22147 return ND; 22148 } 22149 22150 void SemaOpenMP::ActOnOpenMPDeclareTargetName( 22151 NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT, 22152 DeclareTargetContextInfo &DTCI) { 22153 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) || 22154 isa<FunctionTemplateDecl>(ND)) && 22155 "Expected variable, function or function template."); 22156 22157 if (auto *VD = dyn_cast<VarDecl>(ND)) { 22158 // Only global variables can be marked as declare target. 22159 if (!VD->isFileVarDecl() && !VD->isStaticLocal() && 22160 !VD->isStaticDataMember()) { 22161 Diag(Loc, diag::err_omp_declare_target_has_local_vars) 22162 << VD->getNameAsString(); 22163 return; 22164 } 22165 } 22166 // Diagnose marking after use as it may lead to incorrect diagnosis and 22167 // codegen. 22168 if (getLangOpts().OpenMP >= 50 && 22169 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced())) 22170 Diag(Loc, diag::warn_omp_declare_target_after_first_use); 22171 22172 // Report affected OpenMP target offloading behavior when in HIP lang-mode. 22173 if (getLangOpts().HIP) 22174 Diag(Loc, diag::warn_hip_omp_target_directives); 22175 22176 // Explicit declare target lists have precedence. 22177 const unsigned Level = -1; 22178 22179 auto *VD = cast<ValueDecl>(ND); 22180 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr = 22181 OMPDeclareTargetDeclAttr::getActiveAttr(VD); 22182 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT && 22183 (*ActiveAttr)->getLevel() == Level) { 22184 Diag(Loc, diag::err_omp_device_type_mismatch) 22185 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT) 22186 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr( 22187 (*ActiveAttr)->getDevType()); 22188 return; 22189 } 22190 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT && 22191 (*ActiveAttr)->getLevel() == Level) { 22192 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND; 22193 return; 22194 } 22195 22196 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level) 22197 return; 22198 22199 Expr *IndirectE = nullptr; 22200 bool IsIndirect = false; 22201 if (DTCI.Indirect) { 22202 IndirectE = *DTCI.Indirect; 22203 if (!IndirectE) 22204 IsIndirect = true; 22205 } 22206 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit( 22207 getASTContext(), MT, DTCI.DT, IndirectE, IsIndirect, Level, 22208 SourceRange(Loc, Loc)); 22209 ND->addAttr(A); 22210 if (ASTMutationListener *ML = getASTContext().getASTMutationListener()) 22211 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A); 22212 checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Loc); 22213 if (auto *VD = dyn_cast<VarDecl>(ND); 22214 getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() && 22215 VD->hasGlobalStorage()) 22216 ActOnOpenMPDeclareTargetInitializer(ND); 22217 } 22218 22219 static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR, 22220 Sema &SemaRef, Decl *D) { 22221 if (!D || !isa<VarDecl>(D)) 22222 return; 22223 auto *VD = cast<VarDecl>(D); 22224 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy = 22225 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 22226 if (SemaRef.LangOpts.OpenMP >= 50 && 22227 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) || 22228 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) && 22229 VD->hasGlobalStorage()) { 22230 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To && 22231 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) { 22232 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions 22233 // If a lambda declaration and definition appears between a 22234 // declare target directive and the matching end declare target 22235 // directive, all variables that are captured by the lambda 22236 // expression must also appear in a to clause. 22237 SemaRef.Diag(VD->getLocation(), 22238 diag::err_omp_lambda_capture_in_declare_target_not_to); 22239 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here) 22240 << VD << 0 << SR; 22241 return; 22242 } 22243 } 22244 if (MapTy) 22245 return; 22246 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context); 22247 SemaRef.Diag(SL, diag::note_used_here) << SR; 22248 } 22249 22250 static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR, 22251 Sema &SemaRef, DSAStackTy *Stack, 22252 ValueDecl *VD) { 22253 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) || 22254 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(), 22255 /*FullCheck=*/false); 22256 } 22257 22258 void SemaOpenMP::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, 22259 SourceLocation IdLoc) { 22260 if (!D || D->isInvalidDecl()) 22261 return; 22262 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange(); 22263 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation(); 22264 if (auto *VD = dyn_cast<VarDecl>(D)) { 22265 // Only global variables can be marked as declare target. 22266 if (!VD->isFileVarDecl() && !VD->isStaticLocal() && 22267 !VD->isStaticDataMember()) 22268 return; 22269 // 2.10.6: threadprivate variable cannot appear in a declare target 22270 // directive. 22271 if (DSAStack->isThreadPrivate(VD)) { 22272 Diag(SL, diag::err_omp_threadprivate_in_target); 22273 reportOriginalDsa(SemaRef, DSAStack, VD, DSAStack->getTopDSA(VD, false)); 22274 return; 22275 } 22276 } 22277 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D)) 22278 D = FTD->getTemplatedDecl(); 22279 if (auto *FD = dyn_cast<FunctionDecl>(D)) { 22280 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 22281 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD); 22282 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) { 22283 Diag(IdLoc, diag::err_omp_function_in_link_clause); 22284 Diag(FD->getLocation(), diag::note_defined_here) << FD; 22285 return; 22286 } 22287 } 22288 if (auto *VD = dyn_cast<ValueDecl>(D)) { 22289 // Problem if any with var declared with incomplete type will be reported 22290 // as normal, so no need to check it here. 22291 if ((E || !VD->getType()->isIncompleteType()) && 22292 !checkValueDeclInTarget(SL, SR, SemaRef, DSAStack, VD)) 22293 return; 22294 if (!E && isInOpenMPDeclareTargetContext()) { 22295 // Checking declaration inside declare target region. 22296 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) || 22297 isa<FunctionTemplateDecl>(D)) { 22298 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr = 22299 OMPDeclareTargetDeclAttr::getActiveAttr(VD); 22300 unsigned Level = DeclareTargetNesting.size(); 22301 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level) 22302 return; 22303 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back(); 22304 Expr *IndirectE = nullptr; 22305 bool IsIndirect = false; 22306 if (DTCI.Indirect) { 22307 IndirectE = *DTCI.Indirect; 22308 if (!IndirectE) 22309 IsIndirect = true; 22310 } 22311 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit( 22312 getASTContext(), 22313 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter 22314 : OMPDeclareTargetDeclAttr::MT_To, 22315 DTCI.DT, IndirectE, IsIndirect, Level, 22316 SourceRange(DTCI.Loc, DTCI.Loc)); 22317 D->addAttr(A); 22318 if (ASTMutationListener *ML = getASTContext().getASTMutationListener()) 22319 ML->DeclarationMarkedOpenMPDeclareTarget(D, A); 22320 } 22321 return; 22322 } 22323 } 22324 if (!E) 22325 return; 22326 checkDeclInTargetContext(E->getExprLoc(), E->getSourceRange(), SemaRef, D); 22327 } 22328 22329 /// This class visits every VarDecl that the initializer references and adds 22330 /// OMPDeclareTargetDeclAttr to each of them. 22331 class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> { 22332 SmallVector<VarDecl *> DeclVector; 22333 Attr *A; 22334 22335 public: 22336 /// A StmtVisitor class function that visits all DeclRefExpr and adds 22337 /// OMPDeclareTargetDeclAttr to them. 22338 void VisitDeclRefExpr(DeclRefExpr *Node) { 22339 if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) { 22340 VD->addAttr(A); 22341 DeclVector.push_back(VD); 22342 } 22343 } 22344 /// A function that iterates across each of the Expr's children. 22345 void VisitExpr(Expr *Ex) { 22346 for (auto *Child : Ex->children()) { 22347 Visit(Child); 22348 } 22349 } 22350 /// A function that keeps a record of all the Decls that are variables, has 22351 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop 22352 /// each Decl one at a time and use the inherited 'visit' functions to look 22353 /// for DeclRefExpr. 22354 void declareTargetInitializer(Decl *TD) { 22355 A = TD->getAttr<OMPDeclareTargetDeclAttr>(); 22356 DeclVector.push_back(cast<VarDecl>(TD)); 22357 while (!DeclVector.empty()) { 22358 VarDecl *TargetVarDecl = DeclVector.pop_back_val(); 22359 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() && 22360 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) { 22361 if (Expr *Ex = TargetVarDecl->getInit()) 22362 Visit(Ex); 22363 } 22364 } 22365 } 22366 }; 22367 22368 /// Adding OMPDeclareTargetDeclAttr to variables with static storage 22369 /// duration that are referenced in the initializer expression list of 22370 /// variables with static storage duration in declare target directive. 22371 void SemaOpenMP::ActOnOpenMPDeclareTargetInitializer(Decl *TargetDecl) { 22372 GlobalDeclRefChecker Checker; 22373 if (isa<VarDecl>(TargetDecl)) 22374 Checker.declareTargetInitializer(TargetDecl); 22375 } 22376 22377 OMPClause *SemaOpenMP::ActOnOpenMPToClause( 22378 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, 22379 ArrayRef<SourceLocation> MotionModifiersLoc, 22380 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, 22381 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, 22382 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) { 22383 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown, 22384 OMPC_MOTION_MODIFIER_unknown}; 22385 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers]; 22386 22387 // Process motion-modifiers, flag errors for duplicate modifiers. 22388 unsigned Count = 0; 22389 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) { 22390 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown && 22391 llvm::is_contained(Modifiers, MotionModifiers[I])) { 22392 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier); 22393 continue; 22394 } 22395 assert(Count < NumberOfOMPMotionModifiers && 22396 "Modifiers exceed the allowed number of motion modifiers"); 22397 Modifiers[Count] = MotionModifiers[I]; 22398 ModifiersLoc[Count] = MotionModifiersLoc[I]; 22399 ++Count; 22400 } 22401 22402 MappableVarListInfo MVLI(VarList); 22403 checkMappableExpressionList(SemaRef, DSAStack, OMPC_to, MVLI, Locs.StartLoc, 22404 MapperIdScopeSpec, MapperId, UnresolvedMappers); 22405 if (MVLI.ProcessedVarList.empty()) 22406 return nullptr; 22407 22408 return OMPToClause::Create( 22409 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations, 22410 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc, 22411 MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId); 22412 } 22413 22414 OMPClause *SemaOpenMP::ActOnOpenMPFromClause( 22415 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, 22416 ArrayRef<SourceLocation> MotionModifiersLoc, 22417 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, 22418 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, 22419 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) { 22420 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown, 22421 OMPC_MOTION_MODIFIER_unknown}; 22422 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers]; 22423 22424 // Process motion-modifiers, flag errors for duplicate modifiers. 22425 unsigned Count = 0; 22426 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) { 22427 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown && 22428 llvm::is_contained(Modifiers, MotionModifiers[I])) { 22429 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier); 22430 continue; 22431 } 22432 assert(Count < NumberOfOMPMotionModifiers && 22433 "Modifiers exceed the allowed number of motion modifiers"); 22434 Modifiers[Count] = MotionModifiers[I]; 22435 ModifiersLoc[Count] = MotionModifiersLoc[I]; 22436 ++Count; 22437 } 22438 22439 MappableVarListInfo MVLI(VarList); 22440 checkMappableExpressionList(SemaRef, DSAStack, OMPC_from, MVLI, Locs.StartLoc, 22441 MapperIdScopeSpec, MapperId, UnresolvedMappers); 22442 if (MVLI.ProcessedVarList.empty()) 22443 return nullptr; 22444 22445 return OMPFromClause::Create( 22446 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations, 22447 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc, 22448 MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId); 22449 } 22450 22451 OMPClause * 22452 SemaOpenMP::ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList, 22453 const OMPVarListLocTy &Locs) { 22454 MappableVarListInfo MVLI(VarList); 22455 SmallVector<Expr *, 8> PrivateCopies; 22456 SmallVector<Expr *, 8> Inits; 22457 22458 for (Expr *RefExpr : VarList) { 22459 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause."); 22460 SourceLocation ELoc; 22461 SourceRange ERange; 22462 Expr *SimpleRefExpr = RefExpr; 22463 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); 22464 if (Res.second) { 22465 // It will be analyzed later. 22466 MVLI.ProcessedVarList.push_back(RefExpr); 22467 PrivateCopies.push_back(nullptr); 22468 Inits.push_back(nullptr); 22469 } 22470 ValueDecl *D = Res.first; 22471 if (!D) 22472 continue; 22473 22474 QualType Type = D->getType(); 22475 Type = Type.getNonReferenceType().getUnqualifiedType(); 22476 22477 auto *VD = dyn_cast<VarDecl>(D); 22478 22479 // Item should be a pointer or reference to pointer. 22480 if (!Type->isPointerType()) { 22481 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer) 22482 << 0 << RefExpr->getSourceRange(); 22483 continue; 22484 } 22485 22486 // Build the private variable and the expression that refers to it. 22487 auto VDPrivate = 22488 buildVarDecl(SemaRef, ELoc, Type, D->getName(), 22489 D->hasAttrs() ? &D->getAttrs() : nullptr, 22490 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr); 22491 if (VDPrivate->isInvalidDecl()) 22492 continue; 22493 22494 SemaRef.CurContext->addDecl(VDPrivate); 22495 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr( 22496 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc); 22497 22498 // Add temporary variable to initialize the private copy of the pointer. 22499 VarDecl *VDInit = 22500 buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type, ".devptr.temp"); 22501 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr( 22502 SemaRef, VDInit, RefExpr->getType(), RefExpr->getExprLoc()); 22503 SemaRef.AddInitializerToDecl( 22504 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(), 22505 /*DirectInit=*/false); 22506 22507 // If required, build a capture to implement the privatization initialized 22508 // with the current list item value. 22509 DeclRefExpr *Ref = nullptr; 22510 if (!VD) 22511 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true); 22512 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref); 22513 PrivateCopies.push_back(VDPrivateRefExpr); 22514 Inits.push_back(VDInitRefExpr); 22515 22516 // We need to add a data sharing attribute for this variable to make sure it 22517 // is correctly captured. A variable that shows up in a use_device_ptr has 22518 // similar properties of a first private variable. 22519 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref); 22520 22521 // Create a mappable component for the list item. List items in this clause 22522 // only need a component. 22523 MVLI.VarBaseDeclarations.push_back(D); 22524 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1); 22525 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D, 22526 /*IsNonContiguous=*/false); 22527 } 22528 22529 if (MVLI.ProcessedVarList.empty()) 22530 return nullptr; 22531 22532 return OMPUseDevicePtrClause::Create( 22533 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits, 22534 MVLI.VarBaseDeclarations, MVLI.VarComponents); 22535 } 22536 22537 OMPClause * 22538 SemaOpenMP::ActOnOpenMPUseDeviceAddrClause(ArrayRef<Expr *> VarList, 22539 const OMPVarListLocTy &Locs) { 22540 MappableVarListInfo MVLI(VarList); 22541 22542 for (Expr *RefExpr : VarList) { 22543 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause."); 22544 SourceLocation ELoc; 22545 SourceRange ERange; 22546 Expr *SimpleRefExpr = RefExpr; 22547 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange, 22548 /*AllowArraySection=*/true); 22549 if (Res.second) { 22550 // It will be analyzed later. 22551 MVLI.ProcessedVarList.push_back(RefExpr); 22552 } 22553 ValueDecl *D = Res.first; 22554 if (!D) 22555 continue; 22556 auto *VD = dyn_cast<VarDecl>(D); 22557 22558 // If required, build a capture to implement the privatization initialized 22559 // with the current list item value. 22560 DeclRefExpr *Ref = nullptr; 22561 if (!VD) 22562 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true); 22563 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref); 22564 22565 // We need to add a data sharing attribute for this variable to make sure it 22566 // is correctly captured. A variable that shows up in a use_device_addr has 22567 // similar properties of a first private variable. 22568 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref); 22569 22570 // Create a mappable component for the list item. List items in this clause 22571 // only need a component. 22572 MVLI.VarBaseDeclarations.push_back(D); 22573 MVLI.VarComponents.emplace_back(); 22574 Expr *Component = SimpleRefExpr; 22575 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) || 22576 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts()))) 22577 Component = 22578 SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get(); 22579 MVLI.VarComponents.back().emplace_back(Component, D, 22580 /*IsNonContiguous=*/false); 22581 } 22582 22583 if (MVLI.ProcessedVarList.empty()) 22584 return nullptr; 22585 22586 return OMPUseDeviceAddrClause::Create( 22587 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations, 22588 MVLI.VarComponents); 22589 } 22590 22591 OMPClause * 22592 SemaOpenMP::ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList, 22593 const OMPVarListLocTy &Locs) { 22594 MappableVarListInfo MVLI(VarList); 22595 for (Expr *RefExpr : VarList) { 22596 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause."); 22597 SourceLocation ELoc; 22598 SourceRange ERange; 22599 Expr *SimpleRefExpr = RefExpr; 22600 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); 22601 if (Res.second) { 22602 // It will be analyzed later. 22603 MVLI.ProcessedVarList.push_back(RefExpr); 22604 } 22605 ValueDecl *D = Res.first; 22606 if (!D) 22607 continue; 22608 22609 QualType Type = D->getType(); 22610 // item should be a pointer or array or reference to pointer or array 22611 if (!Type.getNonReferenceType()->isPointerType() && 22612 !Type.getNonReferenceType()->isArrayType()) { 22613 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr) 22614 << 0 << RefExpr->getSourceRange(); 22615 continue; 22616 } 22617 22618 // Check if the declaration in the clause does not show up in any data 22619 // sharing attribute. 22620 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false); 22621 if (isOpenMPPrivate(DVar.CKind)) { 22622 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa) 22623 << getOpenMPClauseName(DVar.CKind) 22624 << getOpenMPClauseName(OMPC_is_device_ptr) 22625 << getOpenMPDirectiveName(DSAStack->getCurrentDirective()); 22626 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 22627 continue; 22628 } 22629 22630 const Expr *ConflictExpr; 22631 if (DSAStack->checkMappableExprComponentListsForDecl( 22632 D, /*CurrentRegionOnly=*/true, 22633 [&ConflictExpr]( 22634 OMPClauseMappableExprCommon::MappableExprComponentListRef R, 22635 OpenMPClauseKind) -> bool { 22636 ConflictExpr = R.front().getAssociatedExpression(); 22637 return true; 22638 })) { 22639 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange(); 22640 Diag(ConflictExpr->getExprLoc(), diag::note_used_here) 22641 << ConflictExpr->getSourceRange(); 22642 continue; 22643 } 22644 22645 // Store the components in the stack so that they can be used to check 22646 // against other clauses later on. 22647 OMPClauseMappableExprCommon::MappableComponent MC( 22648 SimpleRefExpr, D, /*IsNonContiguous=*/false); 22649 DSAStack->addMappableExpressionComponents( 22650 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr); 22651 22652 // Record the expression we've just processed. 22653 MVLI.ProcessedVarList.push_back(SimpleRefExpr); 22654 22655 // Create a mappable component for the list item. List items in this clause 22656 // only need a component. We use a null declaration to signal fields in 22657 // 'this'. 22658 assert((isa<DeclRefExpr>(SimpleRefExpr) || 22659 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) && 22660 "Unexpected device pointer expression!"); 22661 MVLI.VarBaseDeclarations.push_back( 22662 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr); 22663 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1); 22664 MVLI.VarComponents.back().push_back(MC); 22665 } 22666 22667 if (MVLI.ProcessedVarList.empty()) 22668 return nullptr; 22669 22670 return OMPIsDevicePtrClause::Create( 22671 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations, 22672 MVLI.VarComponents); 22673 } 22674 22675 OMPClause * 22676 SemaOpenMP::ActOnOpenMPHasDeviceAddrClause(ArrayRef<Expr *> VarList, 22677 const OMPVarListLocTy &Locs) { 22678 MappableVarListInfo MVLI(VarList); 22679 for (Expr *RefExpr : VarList) { 22680 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause."); 22681 SourceLocation ELoc; 22682 SourceRange ERange; 22683 Expr *SimpleRefExpr = RefExpr; 22684 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange, 22685 /*AllowArraySection=*/true); 22686 if (Res.second) { 22687 // It will be analyzed later. 22688 MVLI.ProcessedVarList.push_back(RefExpr); 22689 } 22690 ValueDecl *D = Res.first; 22691 if (!D) 22692 continue; 22693 22694 // Check if the declaration in the clause does not show up in any data 22695 // sharing attribute. 22696 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false); 22697 if (isOpenMPPrivate(DVar.CKind)) { 22698 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa) 22699 << getOpenMPClauseName(DVar.CKind) 22700 << getOpenMPClauseName(OMPC_has_device_addr) 22701 << getOpenMPDirectiveName(DSAStack->getCurrentDirective()); 22702 reportOriginalDsa(SemaRef, DSAStack, D, DVar); 22703 continue; 22704 } 22705 22706 const Expr *ConflictExpr; 22707 if (DSAStack->checkMappableExprComponentListsForDecl( 22708 D, /*CurrentRegionOnly=*/true, 22709 [&ConflictExpr]( 22710 OMPClauseMappableExprCommon::MappableExprComponentListRef R, 22711 OpenMPClauseKind) -> bool { 22712 ConflictExpr = R.front().getAssociatedExpression(); 22713 return true; 22714 })) { 22715 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange(); 22716 Diag(ConflictExpr->getExprLoc(), diag::note_used_here) 22717 << ConflictExpr->getSourceRange(); 22718 continue; 22719 } 22720 22721 // Store the components in the stack so that they can be used to check 22722 // against other clauses later on. 22723 Expr *Component = SimpleRefExpr; 22724 auto *VD = dyn_cast<VarDecl>(D); 22725 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) || 22726 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts()))) 22727 Component = 22728 SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get(); 22729 OMPClauseMappableExprCommon::MappableComponent MC( 22730 Component, D, /*IsNonContiguous=*/false); 22731 DSAStack->addMappableExpressionComponents( 22732 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr); 22733 22734 // Record the expression we've just processed. 22735 if (!VD && !SemaRef.CurContext->isDependentContext()) { 22736 DeclRefExpr *Ref = 22737 buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true); 22738 assert(Ref && "has_device_addr capture failed"); 22739 MVLI.ProcessedVarList.push_back(Ref); 22740 } else 22741 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens()); 22742 22743 // Create a mappable component for the list item. List items in this clause 22744 // only need a component. We use a null declaration to signal fields in 22745 // 'this'. 22746 assert((isa<DeclRefExpr>(SimpleRefExpr) || 22747 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) && 22748 "Unexpected device pointer expression!"); 22749 MVLI.VarBaseDeclarations.push_back( 22750 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr); 22751 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1); 22752 MVLI.VarComponents.back().push_back(MC); 22753 } 22754 22755 if (MVLI.ProcessedVarList.empty()) 22756 return nullptr; 22757 22758 return OMPHasDeviceAddrClause::Create( 22759 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations, 22760 MVLI.VarComponents); 22761 } 22762 22763 OMPClause *SemaOpenMP::ActOnOpenMPAllocateClause( 22764 Expr *Allocator, ArrayRef<Expr *> VarList, SourceLocation StartLoc, 22765 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) { 22766 if (Allocator) { 22767 // OpenMP [2.11.4 allocate Clause, Description] 22768 // allocator is an expression of omp_allocator_handle_t type. 22769 if (!findOMPAllocatorHandleT(SemaRef, Allocator->getExprLoc(), DSAStack)) 22770 return nullptr; 22771 22772 ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(Allocator); 22773 if (AllocatorRes.isInvalid()) 22774 return nullptr; 22775 AllocatorRes = SemaRef.PerformImplicitConversion( 22776 AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(), 22777 Sema::AA_Initializing, 22778 /*AllowExplicit=*/true); 22779 if (AllocatorRes.isInvalid()) 22780 return nullptr; 22781 Allocator = AllocatorRes.get(); 22782 } else { 22783 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions. 22784 // allocate clauses that appear on a target construct or on constructs in a 22785 // target region must specify an allocator expression unless a requires 22786 // directive with the dynamic_allocators clause is present in the same 22787 // compilation unit. 22788 if (getLangOpts().OpenMPIsTargetDevice && 22789 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>()) 22790 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression); 22791 } 22792 // Analyze and build list of variables. 22793 SmallVector<Expr *, 8> Vars; 22794 for (Expr *RefExpr : VarList) { 22795 assert(RefExpr && "NULL expr in OpenMP private clause."); 22796 SourceLocation ELoc; 22797 SourceRange ERange; 22798 Expr *SimpleRefExpr = RefExpr; 22799 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); 22800 if (Res.second) { 22801 // It will be analyzed later. 22802 Vars.push_back(RefExpr); 22803 } 22804 ValueDecl *D = Res.first; 22805 if (!D) 22806 continue; 22807 22808 auto *VD = dyn_cast<VarDecl>(D); 22809 DeclRefExpr *Ref = nullptr; 22810 if (!VD && !SemaRef.CurContext->isDependentContext()) 22811 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false); 22812 Vars.push_back((VD || SemaRef.CurContext->isDependentContext()) 22813 ? RefExpr->IgnoreParens() 22814 : Ref); 22815 } 22816 22817 if (Vars.empty()) 22818 return nullptr; 22819 22820 if (Allocator) 22821 DSAStack->addInnerAllocatorExpr(Allocator); 22822 return OMPAllocateClause::Create(getASTContext(), StartLoc, LParenLoc, 22823 Allocator, ColonLoc, EndLoc, Vars); 22824 } 22825 22826 OMPClause *SemaOpenMP::ActOnOpenMPNontemporalClause(ArrayRef<Expr *> VarList, 22827 SourceLocation StartLoc, 22828 SourceLocation LParenLoc, 22829 SourceLocation EndLoc) { 22830 SmallVector<Expr *, 8> Vars; 22831 for (Expr *RefExpr : VarList) { 22832 assert(RefExpr && "NULL expr in OpenMP nontemporal clause."); 22833 SourceLocation ELoc; 22834 SourceRange ERange; 22835 Expr *SimpleRefExpr = RefExpr; 22836 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); 22837 if (Res.second) 22838 // It will be analyzed later. 22839 Vars.push_back(RefExpr); 22840 ValueDecl *D = Res.first; 22841 if (!D) 22842 continue; 22843 22844 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions. 22845 // A list-item cannot appear in more than one nontemporal clause. 22846 if (const Expr *PrevRef = 22847 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) { 22848 Diag(ELoc, diag::err_omp_used_in_clause_twice) 22849 << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange; 22850 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa) 22851 << getOpenMPClauseName(OMPC_nontemporal); 22852 continue; 22853 } 22854 22855 Vars.push_back(RefExpr); 22856 } 22857 22858 if (Vars.empty()) 22859 return nullptr; 22860 22861 return OMPNontemporalClause::Create(getASTContext(), StartLoc, LParenLoc, 22862 EndLoc, Vars); 22863 } 22864 22865 StmtResult SemaOpenMP::ActOnOpenMPScopeDirective(ArrayRef<OMPClause *> Clauses, 22866 Stmt *AStmt, 22867 SourceLocation StartLoc, 22868 SourceLocation EndLoc) { 22869 if (!AStmt) 22870 return StmtError(); 22871 22872 SemaRef.setFunctionHasBranchProtectedScope(); 22873 22874 return OMPScopeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses, 22875 AStmt); 22876 } 22877 22878 OMPClause *SemaOpenMP::ActOnOpenMPInclusiveClause(ArrayRef<Expr *> VarList, 22879 SourceLocation StartLoc, 22880 SourceLocation LParenLoc, 22881 SourceLocation EndLoc) { 22882 SmallVector<Expr *, 8> Vars; 22883 for (Expr *RefExpr : VarList) { 22884 assert(RefExpr && "NULL expr in OpenMP nontemporal clause."); 22885 SourceLocation ELoc; 22886 SourceRange ERange; 22887 Expr *SimpleRefExpr = RefExpr; 22888 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange, 22889 /*AllowArraySection=*/true); 22890 if (Res.second) 22891 // It will be analyzed later. 22892 Vars.push_back(RefExpr); 22893 ValueDecl *D = Res.first; 22894 if (!D) 22895 continue; 22896 22897 const DSAStackTy::DSAVarData DVar = 22898 DSAStack->getTopDSA(D, /*FromParent=*/true); 22899 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions. 22900 // A list item that appears in the inclusive or exclusive clause must appear 22901 // in a reduction clause with the inscan modifier on the enclosing 22902 // worksharing-loop, worksharing-loop SIMD, or simd construct. 22903 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan) 22904 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction) 22905 << RefExpr->getSourceRange(); 22906 22907 if (DSAStack->getParentDirective() != OMPD_unknown) 22908 DSAStack->markDeclAsUsedInScanDirective(D); 22909 Vars.push_back(RefExpr); 22910 } 22911 22912 if (Vars.empty()) 22913 return nullptr; 22914 22915 return OMPInclusiveClause::Create(getASTContext(), StartLoc, LParenLoc, 22916 EndLoc, Vars); 22917 } 22918 22919 OMPClause *SemaOpenMP::ActOnOpenMPExclusiveClause(ArrayRef<Expr *> VarList, 22920 SourceLocation StartLoc, 22921 SourceLocation LParenLoc, 22922 SourceLocation EndLoc) { 22923 SmallVector<Expr *, 8> Vars; 22924 for (Expr *RefExpr : VarList) { 22925 assert(RefExpr && "NULL expr in OpenMP nontemporal clause."); 22926 SourceLocation ELoc; 22927 SourceRange ERange; 22928 Expr *SimpleRefExpr = RefExpr; 22929 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange, 22930 /*AllowArraySection=*/true); 22931 if (Res.second) 22932 // It will be analyzed later. 22933 Vars.push_back(RefExpr); 22934 ValueDecl *D = Res.first; 22935 if (!D) 22936 continue; 22937 22938 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective(); 22939 DSAStackTy::DSAVarData DVar; 22940 if (ParentDirective != OMPD_unknown) 22941 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true); 22942 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions. 22943 // A list item that appears in the inclusive or exclusive clause must appear 22944 // in a reduction clause with the inscan modifier on the enclosing 22945 // worksharing-loop, worksharing-loop SIMD, or simd construct. 22946 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction || 22947 DVar.Modifier != OMPC_REDUCTION_inscan) { 22948 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction) 22949 << RefExpr->getSourceRange(); 22950 } else { 22951 DSAStack->markDeclAsUsedInScanDirective(D); 22952 } 22953 Vars.push_back(RefExpr); 22954 } 22955 22956 if (Vars.empty()) 22957 return nullptr; 22958 22959 return OMPExclusiveClause::Create(getASTContext(), StartLoc, LParenLoc, 22960 EndLoc, Vars); 22961 } 22962 22963 /// Tries to find omp_alloctrait_t type. 22964 static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) { 22965 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT(); 22966 if (!OMPAlloctraitT.isNull()) 22967 return true; 22968 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t"); 22969 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope()); 22970 if (!PT.getAsOpaquePtr() || PT.get().isNull()) { 22971 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t"; 22972 return false; 22973 } 22974 Stack->setOMPAlloctraitT(PT.get()); 22975 return true; 22976 } 22977 22978 OMPClause *SemaOpenMP::ActOnOpenMPUsesAllocatorClause( 22979 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, 22980 ArrayRef<UsesAllocatorsData> Data) { 22981 ASTContext &Context = getASTContext(); 22982 // OpenMP [2.12.5, target Construct] 22983 // allocator is an identifier of omp_allocator_handle_t type. 22984 if (!findOMPAllocatorHandleT(SemaRef, StartLoc, DSAStack)) 22985 return nullptr; 22986 // OpenMP [2.12.5, target Construct] 22987 // allocator-traits-array is an identifier of const omp_alloctrait_t * type. 22988 if (llvm::any_of( 22989 Data, 22990 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) && 22991 !findOMPAlloctraitT(SemaRef, StartLoc, DSAStack)) 22992 return nullptr; 22993 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators; 22994 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) { 22995 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I); 22996 StringRef Allocator = 22997 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind); 22998 DeclarationName AllocatorName = &Context.Idents.get(Allocator); 22999 PredefinedAllocators.insert(SemaRef.LookupSingleName( 23000 SemaRef.TUScope, AllocatorName, StartLoc, Sema::LookupAnyName)); 23001 } 23002 23003 SmallVector<OMPUsesAllocatorsClause::Data, 4> NewData; 23004 for (const UsesAllocatorsData &D : Data) { 23005 Expr *AllocatorExpr = nullptr; 23006 // Check allocator expression. 23007 if (D.Allocator->isTypeDependent()) { 23008 AllocatorExpr = D.Allocator; 23009 } else { 23010 // Traits were specified - need to assign new allocator to the specified 23011 // allocator, so it must be an lvalue. 23012 AllocatorExpr = D.Allocator->IgnoreParenImpCasts(); 23013 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr); 23014 bool IsPredefinedAllocator = false; 23015 if (DRE) { 23016 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy = 23017 getAllocatorKind(SemaRef, DSAStack, AllocatorExpr); 23018 IsPredefinedAllocator = 23019 AllocatorTy != 23020 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc; 23021 } 23022 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT(); 23023 QualType AllocatorExprType = AllocatorExpr->getType(); 23024 bool IsTypeCompatible = IsPredefinedAllocator; 23025 IsTypeCompatible = IsTypeCompatible || 23026 Context.hasSameUnqualifiedType(AllocatorExprType, 23027 OMPAllocatorHandleT); 23028 IsTypeCompatible = 23029 IsTypeCompatible || 23030 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT); 23031 bool IsNonConstantLValue = 23032 !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue(); 23033 if (!DRE || !IsTypeCompatible || 23034 (!IsPredefinedAllocator && !IsNonConstantLValue)) { 23035 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected) 23036 << "omp_allocator_handle_t" << (DRE ? 1 : 0) 23037 << AllocatorExpr->getType() << D.Allocator->getSourceRange(); 23038 continue; 23039 } 23040 // OpenMP [2.12.5, target Construct] 23041 // Predefined allocators appearing in a uses_allocators clause cannot have 23042 // traits specified. 23043 if (IsPredefinedAllocator && D.AllocatorTraits) { 23044 Diag(D.AllocatorTraits->getExprLoc(), 23045 diag::err_omp_predefined_allocator_with_traits) 23046 << D.AllocatorTraits->getSourceRange(); 23047 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator) 23048 << cast<NamedDecl>(DRE->getDecl())->getName() 23049 << D.Allocator->getSourceRange(); 23050 continue; 23051 } 23052 // OpenMP [2.12.5, target Construct] 23053 // Non-predefined allocators appearing in a uses_allocators clause must 23054 // have traits specified. 23055 if (!IsPredefinedAllocator && !D.AllocatorTraits) { 23056 Diag(D.Allocator->getExprLoc(), 23057 diag::err_omp_nonpredefined_allocator_without_traits); 23058 continue; 23059 } 23060 // No allocator traits - just convert it to rvalue. 23061 if (!D.AllocatorTraits) 23062 AllocatorExpr = SemaRef.DefaultLvalueConversion(AllocatorExpr).get(); 23063 DSAStack->addUsesAllocatorsDecl( 23064 DRE->getDecl(), 23065 IsPredefinedAllocator 23066 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator 23067 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator); 23068 } 23069 Expr *AllocatorTraitsExpr = nullptr; 23070 if (D.AllocatorTraits) { 23071 if (D.AllocatorTraits->isTypeDependent()) { 23072 AllocatorTraitsExpr = D.AllocatorTraits; 23073 } else { 23074 // OpenMP [2.12.5, target Construct] 23075 // Arrays that contain allocator traits that appear in a uses_allocators 23076 // clause must be constant arrays, have constant values and be defined 23077 // in the same scope as the construct in which the clause appears. 23078 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts(); 23079 // Check that traits expr is a constant array. 23080 QualType TraitTy; 23081 if (const ArrayType *Ty = 23082 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe()) 23083 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty)) 23084 TraitTy = ConstArrayTy->getElementType(); 23085 if (TraitTy.isNull() || 23086 !(Context.hasSameUnqualifiedType(TraitTy, 23087 DSAStack->getOMPAlloctraitT()) || 23088 Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(), 23089 /*CompareUnqualified=*/true))) { 23090 Diag(D.AllocatorTraits->getExprLoc(), 23091 diag::err_omp_expected_array_alloctraits) 23092 << AllocatorTraitsExpr->getType(); 23093 continue; 23094 } 23095 // Do not map by default allocator traits if it is a standalone 23096 // variable. 23097 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr)) 23098 DSAStack->addUsesAllocatorsDecl( 23099 DRE->getDecl(), 23100 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait); 23101 } 23102 } 23103 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back(); 23104 NewD.Allocator = AllocatorExpr; 23105 NewD.AllocatorTraits = AllocatorTraitsExpr; 23106 NewD.LParenLoc = D.LParenLoc; 23107 NewD.RParenLoc = D.RParenLoc; 23108 } 23109 return OMPUsesAllocatorsClause::Create(getASTContext(), StartLoc, LParenLoc, 23110 EndLoc, NewData); 23111 } 23112 23113 OMPClause *SemaOpenMP::ActOnOpenMPAffinityClause( 23114 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, 23115 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) { 23116 SmallVector<Expr *, 8> Vars; 23117 for (Expr *RefExpr : Locators) { 23118 assert(RefExpr && "NULL expr in OpenMP shared clause."); 23119 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) { 23120 // It will be analyzed later. 23121 Vars.push_back(RefExpr); 23122 continue; 23123 } 23124 23125 SourceLocation ELoc = RefExpr->getExprLoc(); 23126 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts(); 23127 23128 if (!SimpleExpr->isLValue()) { 23129 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item) 23130 << 1 << 0 << RefExpr->getSourceRange(); 23131 continue; 23132 } 23133 23134 ExprResult Res; 23135 { 23136 Sema::TentativeAnalysisScope Trap(SemaRef); 23137 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr); 23138 } 23139 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) && 23140 !isa<OMPArrayShapingExpr>(SimpleExpr)) { 23141 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item) 23142 << 1 << 0 << RefExpr->getSourceRange(); 23143 continue; 23144 } 23145 Vars.push_back(SimpleExpr); 23146 } 23147 23148 return OMPAffinityClause::Create(getASTContext(), StartLoc, LParenLoc, 23149 ColonLoc, EndLoc, Modifier, Vars); 23150 } 23151 23152 OMPClause *SemaOpenMP::ActOnOpenMPBindClause(OpenMPBindClauseKind Kind, 23153 SourceLocation KindLoc, 23154 SourceLocation StartLoc, 23155 SourceLocation LParenLoc, 23156 SourceLocation EndLoc) { 23157 if (Kind == OMPC_BIND_unknown) { 23158 Diag(KindLoc, diag::err_omp_unexpected_clause_value) 23159 << getListOfPossibleValues(OMPC_bind, /*First=*/0, 23160 /*Last=*/unsigned(OMPC_BIND_unknown)) 23161 << getOpenMPClauseName(OMPC_bind); 23162 return nullptr; 23163 } 23164 23165 return OMPBindClause::Create(getASTContext(), Kind, KindLoc, StartLoc, 23166 LParenLoc, EndLoc); 23167 } 23168 23169 OMPClause *SemaOpenMP::ActOnOpenMPXDynCGroupMemClause(Expr *Size, 23170 SourceLocation StartLoc, 23171 SourceLocation LParenLoc, 23172 SourceLocation EndLoc) { 23173 Expr *ValExpr = Size; 23174 Stmt *HelperValStmt = nullptr; 23175 23176 // OpenMP [2.5, Restrictions] 23177 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer 23178 // value. 23179 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_ompx_dyn_cgroup_mem, 23180 /*StrictlyPositive=*/false)) 23181 return nullptr; 23182 23183 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); 23184 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause( 23185 DKind, OMPC_ompx_dyn_cgroup_mem, getLangOpts().OpenMP); 23186 if (CaptureRegion != OMPD_unknown && 23187 !SemaRef.CurContext->isDependentContext()) { 23188 ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); 23189 llvm::MapVector<const Expr *, DeclRefExpr *> Captures; 23190 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); 23191 HelperValStmt = buildPreInits(getASTContext(), Captures); 23192 } 23193 23194 return new (getASTContext()) OMPXDynCGroupMemClause( 23195 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc); 23196 } 23197 23198 OMPClause *SemaOpenMP::ActOnOpenMPDoacrossClause( 23199 OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, 23200 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc, 23201 SourceLocation LParenLoc, SourceLocation EndLoc) { 23202 23203 if (DSAStack->getCurrentDirective() == OMPD_ordered && 23204 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink && 23205 DepType != OMPC_DOACROSS_sink_omp_cur_iteration && 23206 DepType != OMPC_DOACROSS_source_omp_cur_iteration && 23207 DepType != OMPC_DOACROSS_source) { 23208 Diag(DepLoc, diag::err_omp_unexpected_clause_value) 23209 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_doacross); 23210 return nullptr; 23211 } 23212 23213 SmallVector<Expr *, 8> Vars; 23214 DSAStackTy::OperatorOffsetTy OpsOffs; 23215 llvm::APSInt TotalDepCount(/*BitWidth=*/32); 23216 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon( 23217 SemaRef, 23218 DepType == OMPC_DOACROSS_source || 23219 DepType == OMPC_DOACROSS_source_omp_cur_iteration || 23220 DepType == OMPC_DOACROSS_sink_omp_cur_iteration, 23221 VarList, DSAStack, EndLoc); 23222 Vars = VarOffset.Vars; 23223 OpsOffs = VarOffset.OpsOffs; 23224 TotalDepCount = VarOffset.TotalDepCount; 23225 auto *C = OMPDoacrossClause::Create(getASTContext(), StartLoc, LParenLoc, 23226 EndLoc, DepType, DepLoc, ColonLoc, Vars, 23227 TotalDepCount.getZExtValue()); 23228 if (DSAStack->isParentOrderedRegion()) 23229 DSAStack->addDoacrossDependClause(C, OpsOffs); 23230 return C; 23231 } 23232 23233 OMPClause *SemaOpenMP::ActOnOpenMPXAttributeClause(ArrayRef<const Attr *> Attrs, 23234 SourceLocation StartLoc, 23235 SourceLocation LParenLoc, 23236 SourceLocation EndLoc) { 23237 return new (getASTContext()) 23238 OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc); 23239 } 23240 23241 OMPClause *SemaOpenMP::ActOnOpenMPXBareClause(SourceLocation StartLoc, 23242 SourceLocation EndLoc) { 23243 return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc); 23244 } 23245 23246 ExprResult SemaOpenMP::ActOnOMPArraySectionExpr( 23247 Expr *Base, SourceLocation LBLoc, Expr *LowerBound, 23248 SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length, 23249 Expr *Stride, SourceLocation RBLoc) { 23250 ASTContext &Context = getASTContext(); 23251 if (Base->hasPlaceholderType() && 23252 !Base->hasPlaceholderType(BuiltinType::ArraySection)) { 23253 ExprResult Result = SemaRef.CheckPlaceholderExpr(Base); 23254 if (Result.isInvalid()) 23255 return ExprError(); 23256 Base = Result.get(); 23257 } 23258 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) { 23259 ExprResult Result = SemaRef.CheckPlaceholderExpr(LowerBound); 23260 if (Result.isInvalid()) 23261 return ExprError(); 23262 Result = SemaRef.DefaultLvalueConversion(Result.get()); 23263 if (Result.isInvalid()) 23264 return ExprError(); 23265 LowerBound = Result.get(); 23266 } 23267 if (Length && Length->getType()->isNonOverloadPlaceholderType()) { 23268 ExprResult Result = SemaRef.CheckPlaceholderExpr(Length); 23269 if (Result.isInvalid()) 23270 return ExprError(); 23271 Result = SemaRef.DefaultLvalueConversion(Result.get()); 23272 if (Result.isInvalid()) 23273 return ExprError(); 23274 Length = Result.get(); 23275 } 23276 if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) { 23277 ExprResult Result = SemaRef.CheckPlaceholderExpr(Stride); 23278 if (Result.isInvalid()) 23279 return ExprError(); 23280 Result = SemaRef.DefaultLvalueConversion(Result.get()); 23281 if (Result.isInvalid()) 23282 return ExprError(); 23283 Stride = Result.get(); 23284 } 23285 23286 // Build an unanalyzed expression if either operand is type-dependent. 23287 if (Base->isTypeDependent() || 23288 (LowerBound && 23289 (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) || 23290 (Length && (Length->isTypeDependent() || Length->isValueDependent())) || 23291 (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) { 23292 return new (Context) ArraySectionExpr( 23293 Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue, 23294 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc); 23295 } 23296 23297 // Perform default conversions. 23298 QualType OriginalTy = ArraySectionExpr::getBaseOriginalType(Base); 23299 QualType ResultTy; 23300 if (OriginalTy->isAnyPointerType()) { 23301 ResultTy = OriginalTy->getPointeeType(); 23302 } else if (OriginalTy->isArrayType()) { 23303 ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType(); 23304 } else { 23305 return ExprError( 23306 Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value) 23307 << Base->getSourceRange()); 23308 } 23309 // C99 6.5.2.1p1 23310 if (LowerBound) { 23311 auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(), 23312 LowerBound); 23313 if (Res.isInvalid()) 23314 return ExprError(Diag(LowerBound->getExprLoc(), 23315 diag::err_omp_typecheck_section_not_integer) 23316 << 0 << LowerBound->getSourceRange()); 23317 LowerBound = Res.get(); 23318 23319 if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) || 23320 LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U)) 23321 Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char) 23322 << 0 << LowerBound->getSourceRange(); 23323 } 23324 if (Length) { 23325 auto Res = 23326 PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length); 23327 if (Res.isInvalid()) 23328 return ExprError(Diag(Length->getExprLoc(), 23329 diag::err_omp_typecheck_section_not_integer) 23330 << 1 << Length->getSourceRange()); 23331 Length = Res.get(); 23332 23333 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) || 23334 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U)) 23335 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char) 23336 << 1 << Length->getSourceRange(); 23337 } 23338 if (Stride) { 23339 ExprResult Res = 23340 PerformOpenMPImplicitIntegerConversion(Stride->getExprLoc(), Stride); 23341 if (Res.isInvalid()) 23342 return ExprError(Diag(Stride->getExprLoc(), 23343 diag::err_omp_typecheck_section_not_integer) 23344 << 1 << Stride->getSourceRange()); 23345 Stride = Res.get(); 23346 23347 if (Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_S) || 23348 Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_U)) 23349 Diag(Stride->getExprLoc(), diag::warn_omp_section_is_char) 23350 << 1 << Stride->getSourceRange(); 23351 } 23352 23353 // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly, 23354 // C++ [expr.sub]p1: The type "T" shall be a completely-defined object 23355 // type. Note that functions are not objects, and that (in C99 parlance) 23356 // incomplete types are not object types. 23357 if (ResultTy->isFunctionType()) { 23358 Diag(Base->getExprLoc(), diag::err_omp_section_function_type) 23359 << ResultTy << Base->getSourceRange(); 23360 return ExprError(); 23361 } 23362 23363 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy, 23364 diag::err_omp_section_incomplete_type, Base)) 23365 return ExprError(); 23366 23367 if (LowerBound && !OriginalTy->isAnyPointerType()) { 23368 Expr::EvalResult Result; 23369 if (LowerBound->EvaluateAsInt(Result, Context)) { 23370 // OpenMP 5.0, [2.1.5 Array Sections] 23371 // The array section must be a subset of the original array. 23372 llvm::APSInt LowerBoundValue = Result.Val.getInt(); 23373 if (LowerBoundValue.isNegative()) { 23374 Diag(LowerBound->getExprLoc(), 23375 diag::err_omp_section_not_subset_of_array) 23376 << LowerBound->getSourceRange(); 23377 return ExprError(); 23378 } 23379 } 23380 } 23381 23382 if (Length) { 23383 Expr::EvalResult Result; 23384 if (Length->EvaluateAsInt(Result, Context)) { 23385 // OpenMP 5.0, [2.1.5 Array Sections] 23386 // The length must evaluate to non-negative integers. 23387 llvm::APSInt LengthValue = Result.Val.getInt(); 23388 if (LengthValue.isNegative()) { 23389 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative) 23390 << toString(LengthValue, /*Radix=*/10, /*Signed=*/true) 23391 << Length->getSourceRange(); 23392 return ExprError(); 23393 } 23394 } 23395 } else if (ColonLocFirst.isValid() && 23396 (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() && 23397 !OriginalTy->isVariableArrayType()))) { 23398 // OpenMP 5.0, [2.1.5 Array Sections] 23399 // When the size of the array dimension is not known, the length must be 23400 // specified explicitly. 23401 Diag(ColonLocFirst, diag::err_omp_section_length_undefined) 23402 << (!OriginalTy.isNull() && OriginalTy->isArrayType()); 23403 return ExprError(); 23404 } 23405 23406 if (Stride) { 23407 Expr::EvalResult Result; 23408 if (Stride->EvaluateAsInt(Result, Context)) { 23409 // OpenMP 5.0, [2.1.5 Array Sections] 23410 // The stride must evaluate to a positive integer. 23411 llvm::APSInt StrideValue = Result.Val.getInt(); 23412 if (!StrideValue.isStrictlyPositive()) { 23413 Diag(Stride->getExprLoc(), diag::err_omp_section_stride_non_positive) 23414 << toString(StrideValue, /*Radix=*/10, /*Signed=*/true) 23415 << Stride->getSourceRange(); 23416 return ExprError(); 23417 } 23418 } 23419 } 23420 23421 if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) { 23422 ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(Base); 23423 if (Result.isInvalid()) 23424 return ExprError(); 23425 Base = Result.get(); 23426 } 23427 return new (Context) ArraySectionExpr( 23428 Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue, 23429 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc); 23430 } 23431 23432 ExprResult SemaOpenMP::ActOnOMPArrayShapingExpr( 23433 Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc, 23434 ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) { 23435 ASTContext &Context = getASTContext(); 23436 if (Base->hasPlaceholderType()) { 23437 ExprResult Result = SemaRef.CheckPlaceholderExpr(Base); 23438 if (Result.isInvalid()) 23439 return ExprError(); 23440 Result = SemaRef.DefaultLvalueConversion(Result.get()); 23441 if (Result.isInvalid()) 23442 return ExprError(); 23443 Base = Result.get(); 23444 } 23445 QualType BaseTy = Base->getType(); 23446 // Delay analysis of the types/expressions if instantiation/specialization is 23447 // required. 23448 if (!BaseTy->isPointerType() && Base->isTypeDependent()) 23449 return OMPArrayShapingExpr::Create(Context, Context.DependentTy, Base, 23450 LParenLoc, RParenLoc, Dims, Brackets); 23451 if (!BaseTy->isPointerType() || 23452 (!Base->isTypeDependent() && 23453 BaseTy->getPointeeType()->isIncompleteType())) 23454 return ExprError(Diag(Base->getExprLoc(), 23455 diag::err_omp_non_pointer_type_array_shaping_base) 23456 << Base->getSourceRange()); 23457 23458 SmallVector<Expr *, 4> NewDims; 23459 bool ErrorFound = false; 23460 for (Expr *Dim : Dims) { 23461 if (Dim->hasPlaceholderType()) { 23462 ExprResult Result = SemaRef.CheckPlaceholderExpr(Dim); 23463 if (Result.isInvalid()) { 23464 ErrorFound = true; 23465 continue; 23466 } 23467 Result = SemaRef.DefaultLvalueConversion(Result.get()); 23468 if (Result.isInvalid()) { 23469 ErrorFound = true; 23470 continue; 23471 } 23472 Dim = Result.get(); 23473 } 23474 if (!Dim->isTypeDependent()) { 23475 ExprResult Result = 23476 PerformOpenMPImplicitIntegerConversion(Dim->getExprLoc(), Dim); 23477 if (Result.isInvalid()) { 23478 ErrorFound = true; 23479 Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer) 23480 << Dim->getSourceRange(); 23481 continue; 23482 } 23483 Dim = Result.get(); 23484 Expr::EvalResult EvResult; 23485 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) { 23486 // OpenMP 5.0, [2.1.4 Array Shaping] 23487 // Each si is an integral type expression that must evaluate to a 23488 // positive integer. 23489 llvm::APSInt Value = EvResult.Val.getInt(); 23490 if (!Value.isStrictlyPositive()) { 23491 Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive) 23492 << toString(Value, /*Radix=*/10, /*Signed=*/true) 23493 << Dim->getSourceRange(); 23494 ErrorFound = true; 23495 continue; 23496 } 23497 } 23498 } 23499 NewDims.push_back(Dim); 23500 } 23501 if (ErrorFound) 23502 return ExprError(); 23503 return OMPArrayShapingExpr::Create(Context, Context.OMPArrayShapingTy, Base, 23504 LParenLoc, RParenLoc, NewDims, Brackets); 23505 } 23506 23507 ExprResult SemaOpenMP::ActOnOMPIteratorExpr(Scope *S, 23508 SourceLocation IteratorKwLoc, 23509 SourceLocation LLoc, 23510 SourceLocation RLoc, 23511 ArrayRef<OMPIteratorData> Data) { 23512 ASTContext &Context = getASTContext(); 23513 SmallVector<OMPIteratorExpr::IteratorDefinition, 4> ID; 23514 bool IsCorrect = true; 23515 for (const OMPIteratorData &D : Data) { 23516 TypeSourceInfo *TInfo = nullptr; 23517 SourceLocation StartLoc; 23518 QualType DeclTy; 23519 if (!D.Type.getAsOpaquePtr()) { 23520 // OpenMP 5.0, 2.1.6 Iterators 23521 // In an iterator-specifier, if the iterator-type is not specified then 23522 // the type of that iterator is of int type. 23523 DeclTy = Context.IntTy; 23524 StartLoc = D.DeclIdentLoc; 23525 } else { 23526 DeclTy = Sema::GetTypeFromParser(D.Type, &TInfo); 23527 StartLoc = TInfo->getTypeLoc().getBeginLoc(); 23528 } 23529 23530 bool IsDeclTyDependent = DeclTy->isDependentType() || 23531 DeclTy->containsUnexpandedParameterPack() || 23532 DeclTy->isInstantiationDependentType(); 23533 if (!IsDeclTyDependent) { 23534 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) { 23535 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++ 23536 // The iterator-type must be an integral or pointer type. 23537 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer) 23538 << DeclTy; 23539 IsCorrect = false; 23540 continue; 23541 } 23542 if (DeclTy.isConstant(Context)) { 23543 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++ 23544 // The iterator-type must not be const qualified. 23545 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer) 23546 << DeclTy; 23547 IsCorrect = false; 23548 continue; 23549 } 23550 } 23551 23552 // Iterator declaration. 23553 assert(D.DeclIdent && "Identifier expected."); 23554 // Always try to create iterator declarator to avoid extra error messages 23555 // about unknown declarations use. 23556 auto *VD = 23557 VarDecl::Create(Context, SemaRef.CurContext, StartLoc, D.DeclIdentLoc, 23558 D.DeclIdent, DeclTy, TInfo, SC_None); 23559 VD->setImplicit(); 23560 if (S) { 23561 // Check for conflicting previous declaration. 23562 DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc); 23563 LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName, 23564 RedeclarationKind::ForVisibleRedeclaration); 23565 Previous.suppressDiagnostics(); 23566 SemaRef.LookupName(Previous, S); 23567 23568 SemaRef.FilterLookupForScope(Previous, SemaRef.CurContext, S, 23569 /*ConsiderLinkage=*/false, 23570 /*AllowInlineNamespace=*/false); 23571 if (!Previous.empty()) { 23572 NamedDecl *Old = Previous.getRepresentativeDecl(); 23573 Diag(D.DeclIdentLoc, diag::err_redefinition) << VD->getDeclName(); 23574 Diag(Old->getLocation(), diag::note_previous_definition); 23575 } else { 23576 SemaRef.PushOnScopeChains(VD, S); 23577 } 23578 } else { 23579 SemaRef.CurContext->addDecl(VD); 23580 } 23581 23582 /// Act on the iterator variable declaration. 23583 ActOnOpenMPIteratorVarDecl(VD); 23584 23585 Expr *Begin = D.Range.Begin; 23586 if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) { 23587 ExprResult BeginRes = 23588 SemaRef.PerformImplicitConversion(Begin, DeclTy, Sema::AA_Converting); 23589 Begin = BeginRes.get(); 23590 } 23591 Expr *End = D.Range.End; 23592 if (!IsDeclTyDependent && End && !End->isTypeDependent()) { 23593 ExprResult EndRes = 23594 SemaRef.PerformImplicitConversion(End, DeclTy, Sema::AA_Converting); 23595 End = EndRes.get(); 23596 } 23597 Expr *Step = D.Range.Step; 23598 if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) { 23599 if (!Step->getType()->isIntegralType(Context)) { 23600 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_not_integral) 23601 << Step << Step->getSourceRange(); 23602 IsCorrect = false; 23603 continue; 23604 } 23605 std::optional<llvm::APSInt> Result = 23606 Step->getIntegerConstantExpr(Context); 23607 // OpenMP 5.0, 2.1.6 Iterators, Restrictions 23608 // If the step expression of a range-specification equals zero, the 23609 // behavior is unspecified. 23610 if (Result && Result->isZero()) { 23611 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero) 23612 << Step << Step->getSourceRange(); 23613 IsCorrect = false; 23614 continue; 23615 } 23616 } 23617 if (!Begin || !End || !IsCorrect) { 23618 IsCorrect = false; 23619 continue; 23620 } 23621 OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back(); 23622 IDElem.IteratorDecl = VD; 23623 IDElem.AssignmentLoc = D.AssignLoc; 23624 IDElem.Range.Begin = Begin; 23625 IDElem.Range.End = End; 23626 IDElem.Range.Step = Step; 23627 IDElem.ColonLoc = D.ColonLoc; 23628 IDElem.SecondColonLoc = D.SecColonLoc; 23629 } 23630 if (!IsCorrect) { 23631 // Invalidate all created iterator declarations if error is found. 23632 for (const OMPIteratorExpr::IteratorDefinition &D : ID) { 23633 if (Decl *ID = D.IteratorDecl) 23634 ID->setInvalidDecl(); 23635 } 23636 return ExprError(); 23637 } 23638 SmallVector<OMPIteratorHelperData, 4> Helpers; 23639 if (!SemaRef.CurContext->isDependentContext()) { 23640 // Build number of ityeration for each iteration range. 23641 // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) : 23642 // ((Begini-Stepi-1-Endi) / -Stepi); 23643 for (OMPIteratorExpr::IteratorDefinition &D : ID) { 23644 // (Endi - Begini) 23645 ExprResult Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub, 23646 D.Range.End, D.Range.Begin); 23647 if (!Res.isUsable()) { 23648 IsCorrect = false; 23649 continue; 23650 } 23651 ExprResult St, St1; 23652 if (D.Range.Step) { 23653 St = D.Range.Step; 23654 // (Endi - Begini) + Stepi 23655 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.get(), 23656 St.get()); 23657 if (!Res.isUsable()) { 23658 IsCorrect = false; 23659 continue; 23660 } 23661 // (Endi - Begini) + Stepi - 1 23662 Res = SemaRef.CreateBuiltinBinOp( 23663 D.AssignmentLoc, BO_Sub, Res.get(), 23664 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get()); 23665 if (!Res.isUsable()) { 23666 IsCorrect = false; 23667 continue; 23668 } 23669 // ((Endi - Begini) + Stepi - 1) / Stepi 23670 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.get(), 23671 St.get()); 23672 if (!Res.isUsable()) { 23673 IsCorrect = false; 23674 continue; 23675 } 23676 St1 = SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus, 23677 D.Range.Step); 23678 // (Begini - Endi) 23679 ExprResult Res1 = SemaRef.CreateBuiltinBinOp( 23680 D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End); 23681 if (!Res1.isUsable()) { 23682 IsCorrect = false; 23683 continue; 23684 } 23685 // (Begini - Endi) - Stepi 23686 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.get(), 23687 St1.get()); 23688 if (!Res1.isUsable()) { 23689 IsCorrect = false; 23690 continue; 23691 } 23692 // (Begini - Endi) - Stepi - 1 23693 Res1 = SemaRef.CreateBuiltinBinOp( 23694 D.AssignmentLoc, BO_Sub, Res1.get(), 23695 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get()); 23696 if (!Res1.isUsable()) { 23697 IsCorrect = false; 23698 continue; 23699 } 23700 // ((Begini - Endi) - Stepi - 1) / (-Stepi) 23701 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.get(), 23702 St1.get()); 23703 if (!Res1.isUsable()) { 23704 IsCorrect = false; 23705 continue; 23706 } 23707 // Stepi > 0. 23708 ExprResult CmpRes = SemaRef.CreateBuiltinBinOp( 23709 D.AssignmentLoc, BO_GT, D.Range.Step, 23710 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get()); 23711 if (!CmpRes.isUsable()) { 23712 IsCorrect = false; 23713 continue; 23714 } 23715 Res = SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc, 23716 CmpRes.get(), Res.get(), Res1.get()); 23717 if (!Res.isUsable()) { 23718 IsCorrect = false; 23719 continue; 23720 } 23721 } 23722 Res = SemaRef.ActOnFinishFullExpr(Res.get(), /*DiscardedValue=*/false); 23723 if (!Res.isUsable()) { 23724 IsCorrect = false; 23725 continue; 23726 } 23727 23728 // Build counter update. 23729 // Build counter. 23730 auto *CounterVD = VarDecl::Create(Context, SemaRef.CurContext, 23731 D.IteratorDecl->getBeginLoc(), 23732 D.IteratorDecl->getBeginLoc(), nullptr, 23733 Res.get()->getType(), nullptr, SC_None); 23734 CounterVD->setImplicit(); 23735 ExprResult RefRes = 23736 SemaRef.BuildDeclRefExpr(CounterVD, CounterVD->getType(), VK_LValue, 23737 D.IteratorDecl->getBeginLoc()); 23738 // Build counter update. 23739 // I = Begini + counter * Stepi; 23740 ExprResult UpdateRes; 23741 if (D.Range.Step) { 23742 UpdateRes = SemaRef.CreateBuiltinBinOp( 23743 D.AssignmentLoc, BO_Mul, 23744 SemaRef.DefaultLvalueConversion(RefRes.get()).get(), St.get()); 23745 } else { 23746 UpdateRes = SemaRef.DefaultLvalueConversion(RefRes.get()); 23747 } 23748 if (!UpdateRes.isUsable()) { 23749 IsCorrect = false; 23750 continue; 23751 } 23752 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, 23753 D.Range.Begin, UpdateRes.get()); 23754 if (!UpdateRes.isUsable()) { 23755 IsCorrect = false; 23756 continue; 23757 } 23758 ExprResult VDRes = 23759 SemaRef.BuildDeclRefExpr(cast<VarDecl>(D.IteratorDecl), 23760 cast<VarDecl>(D.IteratorDecl)->getType(), 23761 VK_LValue, D.IteratorDecl->getBeginLoc()); 23762 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign, 23763 VDRes.get(), UpdateRes.get()); 23764 if (!UpdateRes.isUsable()) { 23765 IsCorrect = false; 23766 continue; 23767 } 23768 UpdateRes = 23769 SemaRef.ActOnFinishFullExpr(UpdateRes.get(), /*DiscardedValue=*/true); 23770 if (!UpdateRes.isUsable()) { 23771 IsCorrect = false; 23772 continue; 23773 } 23774 ExprResult CounterUpdateRes = SemaRef.CreateBuiltinUnaryOp( 23775 D.AssignmentLoc, UO_PreInc, RefRes.get()); 23776 if (!CounterUpdateRes.isUsable()) { 23777 IsCorrect = false; 23778 continue; 23779 } 23780 CounterUpdateRes = SemaRef.ActOnFinishFullExpr(CounterUpdateRes.get(), 23781 /*DiscardedValue=*/true); 23782 if (!CounterUpdateRes.isUsable()) { 23783 IsCorrect = false; 23784 continue; 23785 } 23786 OMPIteratorHelperData &HD = Helpers.emplace_back(); 23787 HD.CounterVD = CounterVD; 23788 HD.Upper = Res.get(); 23789 HD.Update = UpdateRes.get(); 23790 HD.CounterUpdate = CounterUpdateRes.get(); 23791 } 23792 } else { 23793 Helpers.assign(ID.size(), {}); 23794 } 23795 if (!IsCorrect) { 23796 // Invalidate all created iterator declarations if error is found. 23797 for (const OMPIteratorExpr::IteratorDefinition &D : ID) { 23798 if (Decl *ID = D.IteratorDecl) 23799 ID->setInvalidDecl(); 23800 } 23801 return ExprError(); 23802 } 23803 return OMPIteratorExpr::Create(Context, Context.OMPIteratorTy, IteratorKwLoc, 23804 LLoc, RLoc, ID, Helpers); 23805 } 23806 23807 /// Check if \p AssumptionStr is a known assumption and warn if not. 23808 static void checkOMPAssumeAttr(Sema &S, SourceLocation Loc, 23809 StringRef AssumptionStr) { 23810 if (llvm::KnownAssumptionStrings.count(AssumptionStr)) 23811 return; 23812 23813 unsigned BestEditDistance = 3; 23814 StringRef Suggestion; 23815 for (const auto &KnownAssumptionIt : llvm::KnownAssumptionStrings) { 23816 unsigned EditDistance = 23817 AssumptionStr.edit_distance(KnownAssumptionIt.getKey()); 23818 if (EditDistance < BestEditDistance) { 23819 Suggestion = KnownAssumptionIt.getKey(); 23820 BestEditDistance = EditDistance; 23821 } 23822 } 23823 23824 if (!Suggestion.empty()) 23825 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested) 23826 << AssumptionStr << Suggestion; 23827 else 23828 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown) 23829 << AssumptionStr; 23830 } 23831 23832 void SemaOpenMP::handleOMPAssumeAttr(Decl *D, const ParsedAttr &AL) { 23833 // Handle the case where the attribute has a text message. 23834 StringRef Str; 23835 SourceLocation AttrStrLoc; 23836 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc)) 23837 return; 23838 23839 checkOMPAssumeAttr(SemaRef, AttrStrLoc, Str); 23840 23841 D->addAttr(::new (getASTContext()) OMPAssumeAttr(getASTContext(), AL, Str)); 23842 } 23843 23844 SemaOpenMP::SemaOpenMP(Sema &S) 23845 : SemaBase(S), VarDataSharingAttributesStack(nullptr) {} 23846