[lld][WebAssembly] Add `--table-base` setting
[llvm-project.git] / clang / lib / Sema / SemaOpenMP.cpp
blob04aac12efe8bf029e9033b05f3a181a8fd33c386
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 //===----------------------------------------------------------------------===//
14 #include "TreeTransform.h"
15 #include "clang/AST/ASTContext.h"
16 #include "clang/AST/ASTMutationListener.h"
17 #include "clang/AST/CXXInheritance.h"
18 #include "clang/AST/Decl.h"
19 #include "clang/AST/DeclCXX.h"
20 #include "clang/AST/DeclOpenMP.h"
21 #include "clang/AST/OpenMPClause.h"
22 #include "clang/AST/StmtCXX.h"
23 #include "clang/AST/StmtOpenMP.h"
24 #include "clang/AST/StmtVisitor.h"
25 #include "clang/AST/TypeOrdering.h"
26 #include "clang/Basic/DiagnosticSema.h"
27 #include "clang/Basic/OpenMPKinds.h"
28 #include "clang/Basic/PartialDiagnostic.h"
29 #include "clang/Basic/TargetInfo.h"
30 #include "clang/Sema/EnterExpressionEvaluationContext.h"
31 #include "clang/Sema/Initialization.h"
32 #include "clang/Sema/Lookup.h"
33 #include "clang/Sema/ParsedAttr.h"
34 #include "clang/Sema/Scope.h"
35 #include "clang/Sema/ScopeInfo.h"
36 #include "clang/Sema/SemaInternal.h"
37 #include "llvm/ADT/IndexedMap.h"
38 #include "llvm/ADT/PointerEmbeddedInt.h"
39 #include "llvm/ADT/STLExtras.h"
40 #include "llvm/ADT/SmallSet.h"
41 #include "llvm/ADT/StringExtras.h"
42 #include "llvm/Frontend/OpenMP/OMPAssume.h"
43 #include "llvm/Frontend/OpenMP/OMPConstants.h"
44 #include <optional>
45 #include <set>
47 using namespace clang;
48 using namespace llvm::omp;
50 //===----------------------------------------------------------------------===//
51 // Stack of data-sharing attributes for variables
52 //===----------------------------------------------------------------------===//
54 static const Expr *checkMapClauseExpressionBase(
55 Sema &SemaRef, Expr *E,
56 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
57 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose);
59 namespace {
60 /// Default data sharing attributes, which can be applied to directive.
61 enum DefaultDataSharingAttributes {
62 DSA_unspecified = 0, /// Data sharing attribute not specified.
63 DSA_none = 1 << 0, /// Default data sharing attribute 'none'.
64 DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
65 DSA_private = 1 << 2, /// Default data sharing attribute 'private'.
66 DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'.
69 /// Stack for tracking declarations used in OpenMP directives and
70 /// clauses and their data-sharing attributes.
71 class DSAStackTy {
72 public:
73 struct DSAVarData {
74 OpenMPDirectiveKind DKind = OMPD_unknown;
75 OpenMPClauseKind CKind = OMPC_unknown;
76 unsigned Modifier = 0;
77 const Expr *RefExpr = nullptr;
78 DeclRefExpr *PrivateCopy = nullptr;
79 SourceLocation ImplicitDSALoc;
80 bool AppliedToPointee = false;
81 DSAVarData() = default;
82 DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
83 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
84 SourceLocation ImplicitDSALoc, unsigned Modifier,
85 bool AppliedToPointee)
86 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
87 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
88 AppliedToPointee(AppliedToPointee) {}
90 using OperatorOffsetTy =
91 llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
92 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
93 /// Kind of the declaration used in the uses_allocators clauses.
94 enum class UsesAllocatorsDeclKind {
95 /// Predefined allocator
96 PredefinedAllocator,
97 /// User-defined allocator
98 UserDefinedAllocator,
99 /// The declaration that represent allocator trait
100 AllocatorTrait,
103 private:
104 struct DSAInfo {
105 OpenMPClauseKind Attributes = OMPC_unknown;
106 unsigned Modifier = 0;
107 /// Pointer to a reference expression and a flag which shows that the
108 /// variable is marked as lastprivate(true) or not (false).
109 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
110 DeclRefExpr *PrivateCopy = nullptr;
111 /// true if the attribute is applied to the pointee, not the variable
112 /// itself.
113 bool AppliedToPointee = false;
115 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
116 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
117 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
118 using LoopControlVariablesMapTy =
119 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
120 /// Struct that associates a component with the clause kind where they are
121 /// found.
122 struct MappedExprComponentTy {
123 OMPClauseMappableExprCommon::MappableExprComponentLists Components;
124 OpenMPClauseKind Kind = OMPC_unknown;
126 using MappedExprComponentsTy =
127 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
128 using CriticalsWithHintsTy =
129 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
130 struct ReductionData {
131 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
132 SourceRange ReductionRange;
133 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
134 ReductionData() = default;
135 void set(BinaryOperatorKind BO, SourceRange RR) {
136 ReductionRange = RR;
137 ReductionOp = BO;
139 void set(const Expr *RefExpr, SourceRange RR) {
140 ReductionRange = RR;
141 ReductionOp = RefExpr;
144 using DeclReductionMapTy =
145 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
146 struct DefaultmapInfo {
147 OpenMPDefaultmapClauseModifier ImplicitBehavior =
148 OMPC_DEFAULTMAP_MODIFIER_unknown;
149 SourceLocation SLoc;
150 DefaultmapInfo() = default;
151 DefaultmapInfo(OpenMPDefaultmapClauseModifier M, SourceLocation Loc)
152 : ImplicitBehavior(M), SLoc(Loc) {}
155 struct SharingMapTy {
156 DeclSAMapTy SharingMap;
157 DeclReductionMapTy ReductionMap;
158 UsedRefMapTy AlignedMap;
159 UsedRefMapTy NontemporalMap;
160 MappedExprComponentsTy MappedExprComponents;
161 LoopControlVariablesMapTy LCVMap;
162 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
163 SourceLocation DefaultAttrLoc;
164 DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown];
165 OpenMPDirectiveKind Directive = OMPD_unknown;
166 /// GenericLoopDirective with bind clause is mapped to other directives,
167 /// like for, distribute and simd. Presently, set MappedDirective to
168 /// OMPLoop. This may also be used in a similar way for other constructs.
169 OpenMPDirectiveKind MappedDirective = OMPD_unknown;
170 DeclarationNameInfo DirectiveName;
171 Scope *CurScope = nullptr;
172 DeclContext *Context = nullptr;
173 SourceLocation ConstructLoc;
174 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
175 /// get the data (loop counters etc.) about enclosing loop-based construct.
176 /// This data is required during codegen.
177 DoacrossClauseMapTy DoacrossDepends;
178 /// First argument (Expr *) contains optional argument of the
179 /// 'ordered' clause, the second one is true if the regions has 'ordered'
180 /// clause, false otherwise.
181 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
182 bool RegionHasOrderConcurrent = false;
183 unsigned AssociatedLoops = 1;
184 bool HasMutipleLoops = false;
185 const Decl *PossiblyLoopCounter = nullptr;
186 bool NowaitRegion = false;
187 bool UntiedRegion = false;
188 bool CancelRegion = false;
189 bool LoopStart = false;
190 bool BodyComplete = false;
191 SourceLocation PrevScanLocation;
192 SourceLocation PrevOrderedLocation;
193 SourceLocation InnerTeamsRegionLoc;
194 /// Reference to the taskgroup task_reduction reference expression.
195 Expr *TaskgroupReductionRef = nullptr;
196 llvm::DenseSet<QualType> MappedClassesQualTypes;
197 SmallVector<Expr *, 4> InnerUsedAllocators;
198 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
199 /// List of globals marked as declare target link in this target region
200 /// (isOpenMPTargetExecutionDirective(Directive) == true).
201 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
202 /// List of decls used in inclusive/exclusive clauses of the scan directive.
203 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
204 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
205 UsesAllocatorsDecls;
206 /// Data is required on creating capture fields for implicit
207 /// default first|private clause.
208 struct ImplicitDefaultFDInfoTy {
209 /// Field decl.
210 const FieldDecl *FD = nullptr;
211 /// Nesting stack level
212 size_t StackLevel = 0;
213 /// Capture variable decl.
214 VarDecl *VD = nullptr;
215 ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel,
216 VarDecl *VD)
217 : FD(FD), StackLevel(StackLevel), VD(VD) {}
219 /// List of captured fields
220 llvm::SmallVector<ImplicitDefaultFDInfoTy, 8>
221 ImplicitDefaultFirstprivateFDs;
222 Expr *DeclareMapperVar = nullptr;
223 SmallVector<VarDecl *, 16> IteratorVarDecls;
224 SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
225 Scope *CurScope, SourceLocation Loc)
226 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
227 ConstructLoc(Loc) {}
228 SharingMapTy() = default;
231 using StackTy = SmallVector<SharingMapTy, 4>;
233 /// Stack of used declaration and their data-sharing attributes.
234 DeclSAMapTy Threadprivates;
235 const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
236 SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack;
237 /// true, if check for DSA must be from parent directive, false, if
238 /// from current directive.
239 OpenMPClauseKind ClauseKindMode = OMPC_unknown;
240 Sema &SemaRef;
241 bool ForceCapturing = false;
242 /// true if all the variables in the target executable directives must be
243 /// captured by reference.
244 bool ForceCaptureByReferenceInTargetExecutable = false;
245 CriticalsWithHintsTy Criticals;
246 unsigned IgnoredStackElements = 0;
248 /// Iterators over the stack iterate in order from innermost to outermost
249 /// directive.
250 using const_iterator = StackTy::const_reverse_iterator;
251 const_iterator begin() const {
252 return Stack.empty() ? const_iterator()
253 : Stack.back().first.rbegin() + IgnoredStackElements;
255 const_iterator end() const {
256 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
258 using iterator = StackTy::reverse_iterator;
259 iterator begin() {
260 return Stack.empty() ? iterator()
261 : Stack.back().first.rbegin() + IgnoredStackElements;
263 iterator end() {
264 return Stack.empty() ? iterator() : Stack.back().first.rend();
267 // Convenience operations to get at the elements of the stack.
269 bool isStackEmpty() const {
270 return Stack.empty() ||
271 Stack.back().second != CurrentNonCapturingFunctionScope ||
272 Stack.back().first.size() <= IgnoredStackElements;
274 size_t getStackSize() const {
275 return isStackEmpty() ? 0
276 : Stack.back().first.size() - IgnoredStackElements;
279 SharingMapTy *getTopOfStackOrNull() {
280 size_t Size = getStackSize();
281 if (Size == 0)
282 return nullptr;
283 return &Stack.back().first[Size - 1];
285 const SharingMapTy *getTopOfStackOrNull() const {
286 return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull();
288 SharingMapTy &getTopOfStack() {
289 assert(!isStackEmpty() && "no current directive");
290 return *getTopOfStackOrNull();
292 const SharingMapTy &getTopOfStack() const {
293 return const_cast<DSAStackTy &>(*this).getTopOfStack();
296 SharingMapTy *getSecondOnStackOrNull() {
297 size_t Size = getStackSize();
298 if (Size <= 1)
299 return nullptr;
300 return &Stack.back().first[Size - 2];
302 const SharingMapTy *getSecondOnStackOrNull() const {
303 return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull();
306 /// Get the stack element at a certain level (previously returned by
307 /// \c getNestingLevel).
309 /// Note that nesting levels count from outermost to innermost, and this is
310 /// the reverse of our iteration order where new inner levels are pushed at
311 /// the front of the stack.
312 SharingMapTy &getStackElemAtLevel(unsigned Level) {
313 assert(Level < getStackSize() && "no such stack element");
314 return Stack.back().first[Level];
316 const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
317 return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level);
320 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
322 /// Checks if the variable is a local for OpenMP region.
323 bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
325 /// Vector of previously declared requires directives
326 SmallVector<const OMPRequiresDecl *, 2> RequiresDecls;
327 /// omp_allocator_handle_t type.
328 QualType OMPAllocatorHandleT;
329 /// omp_depend_t type.
330 QualType OMPDependT;
331 /// omp_event_handle_t type.
332 QualType OMPEventHandleT;
333 /// omp_alloctrait_t type.
334 QualType OMPAlloctraitT;
335 /// Expression for the predefined allocators.
336 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
337 nullptr};
338 /// Vector of previously encountered target directives
339 SmallVector<SourceLocation, 2> TargetLocations;
340 SourceLocation AtomicLocation;
341 /// Vector of declare variant construct traits.
342 SmallVector<llvm::omp::TraitProperty, 8> ConstructTraits;
344 public:
345 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
347 /// Sets omp_allocator_handle_t type.
348 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
349 /// Gets omp_allocator_handle_t type.
350 QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
351 /// Sets omp_alloctrait_t type.
352 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
353 /// Gets omp_alloctrait_t type.
354 QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
355 /// Sets the given default allocator.
356 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
357 Expr *Allocator) {
358 OMPPredefinedAllocators[AllocatorKind] = Allocator;
360 /// Returns the specified default allocator.
361 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
362 return OMPPredefinedAllocators[AllocatorKind];
364 /// Sets omp_depend_t type.
365 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
366 /// Gets omp_depend_t type.
367 QualType getOMPDependT() const { return OMPDependT; }
369 /// Sets omp_event_handle_t type.
370 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
371 /// Gets omp_event_handle_t type.
372 QualType getOMPEventHandleT() const { return OMPEventHandleT; }
374 bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
375 OpenMPClauseKind getClauseParsingMode() const {
376 assert(isClauseParsingMode() && "Must be in clause parsing mode.");
377 return ClauseKindMode;
379 void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
381 bool isBodyComplete() const {
382 const SharingMapTy *Top = getTopOfStackOrNull();
383 return Top && Top->BodyComplete;
385 void setBodyComplete() { getTopOfStack().BodyComplete = true; }
387 bool isForceVarCapturing() const { return ForceCapturing; }
388 void setForceVarCapturing(bool V) { ForceCapturing = V; }
390 void setForceCaptureByReferenceInTargetExecutable(bool V) {
391 ForceCaptureByReferenceInTargetExecutable = V;
393 bool isForceCaptureByReferenceInTargetExecutable() const {
394 return ForceCaptureByReferenceInTargetExecutable;
397 void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
398 Scope *CurScope, SourceLocation Loc) {
399 assert(!IgnoredStackElements &&
400 "cannot change stack while ignoring elements");
401 if (Stack.empty() ||
402 Stack.back().second != CurrentNonCapturingFunctionScope)
403 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
404 Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc);
405 Stack.back().first.back().DefaultAttrLoc = Loc;
408 void pop() {
409 assert(!IgnoredStackElements &&
410 "cannot change stack while ignoring elements");
411 assert(!Stack.back().first.empty() &&
412 "Data-sharing attributes stack is empty!");
413 Stack.back().first.pop_back();
416 /// RAII object to temporarily leave the scope of a directive when we want to
417 /// logically operate in its parent.
418 class ParentDirectiveScope {
419 DSAStackTy &Self;
420 bool Active;
422 public:
423 ParentDirectiveScope(DSAStackTy &Self, bool Activate)
424 : Self(Self), Active(false) {
425 if (Activate)
426 enable();
428 ~ParentDirectiveScope() { disable(); }
429 void disable() {
430 if (Active) {
431 --Self.IgnoredStackElements;
432 Active = false;
435 void enable() {
436 if (!Active) {
437 ++Self.IgnoredStackElements;
438 Active = true;
443 /// Marks that we're started loop parsing.
444 void loopInit() {
445 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
446 "Expected loop-based directive.");
447 getTopOfStack().LoopStart = true;
449 /// Start capturing of the variables in the loop context.
450 void loopStart() {
451 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
452 "Expected loop-based directive.");
453 getTopOfStack().LoopStart = false;
455 /// true, if variables are captured, false otherwise.
456 bool isLoopStarted() const {
457 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
458 "Expected loop-based directive.");
459 return !getTopOfStack().LoopStart;
461 /// Marks (or clears) declaration as possibly loop counter.
462 void resetPossibleLoopCounter(const Decl *D = nullptr) {
463 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
465 /// Gets the possible loop counter decl.
466 const Decl *getPossiblyLoopCunter() const {
467 return getTopOfStack().PossiblyLoopCounter;
469 /// Start new OpenMP region stack in new non-capturing function.
470 void pushFunction() {
471 assert(!IgnoredStackElements &&
472 "cannot change stack while ignoring elements");
473 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
474 assert(!isa<CapturingScopeInfo>(CurFnScope));
475 CurrentNonCapturingFunctionScope = CurFnScope;
477 /// Pop region stack for non-capturing function.
478 void popFunction(const FunctionScopeInfo *OldFSI) {
479 assert(!IgnoredStackElements &&
480 "cannot change stack while ignoring elements");
481 if (!Stack.empty() && Stack.back().second == OldFSI) {
482 assert(Stack.back().first.empty());
483 Stack.pop_back();
485 CurrentNonCapturingFunctionScope = nullptr;
486 for (const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) {
487 if (!isa<CapturingScopeInfo>(FSI)) {
488 CurrentNonCapturingFunctionScope = FSI;
489 break;
494 void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
495 Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint);
497 const std::pair<const OMPCriticalDirective *, llvm::APSInt>
498 getCriticalWithHint(const DeclarationNameInfo &Name) const {
499 auto I = Criticals.find(Name.getAsString());
500 if (I != Criticals.end())
501 return I->second;
502 return std::make_pair(nullptr, llvm::APSInt());
504 /// If 'aligned' declaration for given variable \a D was not seen yet,
505 /// add it and return NULL; otherwise return previous occurrence's expression
506 /// for diagnostics.
507 const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
508 /// If 'nontemporal' declaration for given variable \a D was not seen yet,
509 /// add it and return NULL; otherwise return previous occurrence's expression
510 /// for diagnostics.
511 const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
513 /// Register specified variable as loop control variable.
514 void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
515 /// Check if the specified variable is a loop control variable for
516 /// current region.
517 /// \return The index of the loop control variable in the list of associated
518 /// for-loops (from outer to inner).
519 const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
520 /// Check if the specified variable is a loop control variable for
521 /// parent region.
522 /// \return The index of the loop control variable in the list of associated
523 /// for-loops (from outer to inner).
524 const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const;
525 /// Check if the specified variable is a loop control variable for
526 /// current region.
527 /// \return The index of the loop control variable in the list of associated
528 /// for-loops (from outer to inner).
529 const LCDeclInfo isLoopControlVariable(const ValueDecl *D,
530 unsigned Level) const;
531 /// Get the loop control variable for the I-th loop (or nullptr) in
532 /// parent directive.
533 const ValueDecl *getParentLoopControlVariable(unsigned I) const;
535 /// Marks the specified decl \p D as used in scan directive.
536 void markDeclAsUsedInScanDirective(ValueDecl *D) {
537 if (SharingMapTy *Stack = getSecondOnStackOrNull())
538 Stack->UsedInScanDirective.insert(D);
541 /// Checks if the specified declaration was used in the inner scan directive.
542 bool isUsedInScanDirective(ValueDecl *D) const {
543 if (const SharingMapTy *Stack = getTopOfStackOrNull())
544 return Stack->UsedInScanDirective.contains(D);
545 return false;
548 /// Adds explicit data sharing attribute to the specified declaration.
549 void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
550 DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
551 bool AppliedToPointee = false);
553 /// Adds additional information for the reduction items with the reduction id
554 /// represented as an operator.
555 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
556 BinaryOperatorKind BOK);
557 /// Adds additional information for the reduction items with the reduction id
558 /// represented as reduction identifier.
559 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
560 const Expr *ReductionRef);
561 /// Returns the location and reduction operation from the innermost parent
562 /// region for the given \p D.
563 const DSAVarData
564 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
565 BinaryOperatorKind &BOK,
566 Expr *&TaskgroupDescriptor) const;
567 /// Returns the location and reduction operation from the innermost parent
568 /// region for the given \p D.
569 const DSAVarData
570 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
571 const Expr *&ReductionRef,
572 Expr *&TaskgroupDescriptor) const;
573 /// Return reduction reference expression for the current taskgroup or
574 /// parallel/worksharing directives with task reductions.
575 Expr *getTaskgroupReductionRef() const {
576 assert((getTopOfStack().Directive == OMPD_taskgroup ||
577 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
578 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
579 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
580 "taskgroup reference expression requested for non taskgroup or "
581 "parallel/worksharing directive.");
582 return getTopOfStack().TaskgroupReductionRef;
584 /// Checks if the given \p VD declaration is actually a taskgroup reduction
585 /// descriptor variable at the \p Level of OpenMP regions.
586 bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
587 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
588 cast<DeclRefExpr>(getStackElemAtLevel(Level).TaskgroupReductionRef)
589 ->getDecl() == VD;
592 /// Returns data sharing attributes from top of the stack for the
593 /// specified declaration.
594 const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
595 /// Returns data-sharing attributes for the specified declaration.
596 const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
597 /// Returns data-sharing attributes for the specified declaration.
598 const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const;
599 /// Checks if the specified variables has data-sharing attributes which
600 /// match specified \a CPred predicate in any directive which matches \a DPred
601 /// predicate.
602 const DSAVarData
603 hasDSA(ValueDecl *D,
604 const llvm::function_ref<bool(OpenMPClauseKind, bool,
605 DefaultDataSharingAttributes)>
606 CPred,
607 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
608 bool FromParent) const;
609 /// Checks if the specified variables has data-sharing attributes which
610 /// match specified \a CPred predicate in any innermost directive which
611 /// matches \a DPred predicate.
612 const DSAVarData
613 hasInnermostDSA(ValueDecl *D,
614 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
615 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
616 bool FromParent) const;
617 /// Checks if the specified variables has explicit data-sharing
618 /// attributes which match specified \a CPred predicate at the specified
619 /// OpenMP region.
620 bool
621 hasExplicitDSA(const ValueDecl *D,
622 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
623 unsigned Level, bool NotLastprivate = false) const;
625 /// Returns true if the directive at level \Level matches in the
626 /// specified \a DPred predicate.
627 bool hasExplicitDirective(
628 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
629 unsigned Level) const;
631 /// Finds a directive which matches specified \a DPred predicate.
632 bool hasDirective(
633 const llvm::function_ref<bool(
634 OpenMPDirectiveKind, const DeclarationNameInfo &, SourceLocation)>
635 DPred,
636 bool FromParent) const;
638 /// Returns currently analyzed directive.
639 OpenMPDirectiveKind getCurrentDirective() const {
640 const SharingMapTy *Top = getTopOfStackOrNull();
641 return Top ? Top->Directive : OMPD_unknown;
643 OpenMPDirectiveKind getMappedDirective() const {
644 const SharingMapTy *Top = getTopOfStackOrNull();
645 return Top ? Top->MappedDirective : OMPD_unknown;
647 void setCurrentDirective(OpenMPDirectiveKind NewDK) {
648 SharingMapTy *Top = getTopOfStackOrNull();
649 assert(Top &&
650 "Before calling setCurrentDirective Top of Stack not to be NULL.");
651 // Store the old into MappedDirective & assign argument NewDK to Directive.
652 Top->Directive = NewDK;
654 void setMappedDirective(OpenMPDirectiveKind NewDK) {
655 SharingMapTy *Top = getTopOfStackOrNull();
656 assert(Top &&
657 "Before calling setMappedDirective Top of Stack not to be NULL.");
658 // Store the old into MappedDirective & assign argument NewDK to Directive.
659 Top->MappedDirective = NewDK;
661 /// Returns directive kind at specified level.
662 OpenMPDirectiveKind getDirective(unsigned Level) const {
663 assert(!isStackEmpty() && "No directive at specified level.");
664 return getStackElemAtLevel(Level).Directive;
666 /// Returns the capture region at the specified level.
667 OpenMPDirectiveKind getCaptureRegion(unsigned Level,
668 unsigned OpenMPCaptureLevel) const {
669 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
670 getOpenMPCaptureRegions(CaptureRegions, getDirective(Level));
671 return CaptureRegions[OpenMPCaptureLevel];
673 /// Returns parent directive.
674 OpenMPDirectiveKind getParentDirective() const {
675 const SharingMapTy *Parent = getSecondOnStackOrNull();
676 return Parent ? Parent->Directive : OMPD_unknown;
679 /// Add requires decl to internal vector
680 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
682 /// Checks if the defined 'requires' directive has specified type of clause.
683 template <typename ClauseType> bool hasRequiresDeclWithClause() const {
684 return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
685 return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
686 return isa<ClauseType>(C);
691 /// Checks for a duplicate clause amongst previously declared requires
692 /// directives
693 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
694 bool IsDuplicate = false;
695 for (OMPClause *CNew : ClauseList) {
696 for (const OMPRequiresDecl *D : RequiresDecls) {
697 for (const OMPClause *CPrev : D->clauselists()) {
698 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
699 SemaRef.Diag(CNew->getBeginLoc(),
700 diag::err_omp_requires_clause_redeclaration)
701 << getOpenMPClauseName(CNew->getClauseKind());
702 SemaRef.Diag(CPrev->getBeginLoc(),
703 diag::note_omp_requires_previous_clause)
704 << getOpenMPClauseName(CPrev->getClauseKind());
705 IsDuplicate = true;
710 return IsDuplicate;
713 /// Add location of previously encountered target to internal vector
714 void addTargetDirLocation(SourceLocation LocStart) {
715 TargetLocations.push_back(LocStart);
718 /// Add location for the first encountered atomicc directive.
719 void addAtomicDirectiveLoc(SourceLocation Loc) {
720 if (AtomicLocation.isInvalid())
721 AtomicLocation = Loc;
724 /// Returns the location of the first encountered atomic directive in the
725 /// module.
726 SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; }
728 // Return previously encountered target region locations.
729 ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
730 return TargetLocations;
733 /// Set default data sharing attribute to none.
734 void setDefaultDSANone(SourceLocation Loc) {
735 getTopOfStack().DefaultAttr = DSA_none;
736 getTopOfStack().DefaultAttrLoc = Loc;
738 /// Set default data sharing attribute to shared.
739 void setDefaultDSAShared(SourceLocation Loc) {
740 getTopOfStack().DefaultAttr = DSA_shared;
741 getTopOfStack().DefaultAttrLoc = Loc;
743 /// Set default data sharing attribute to private.
744 void setDefaultDSAPrivate(SourceLocation Loc) {
745 getTopOfStack().DefaultAttr = DSA_private;
746 getTopOfStack().DefaultAttrLoc = Loc;
748 /// Set default data sharing attribute to firstprivate.
749 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
750 getTopOfStack().DefaultAttr = DSA_firstprivate;
751 getTopOfStack().DefaultAttrLoc = Loc;
753 /// Set default data mapping attribute to Modifier:Kind
754 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
755 OpenMPDefaultmapClauseKind Kind, SourceLocation Loc) {
756 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind];
757 DMI.ImplicitBehavior = M;
758 DMI.SLoc = Loc;
760 /// Check whether the implicit-behavior has been set in defaultmap
761 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) {
762 if (VariableCategory == OMPC_DEFAULTMAP_unknown)
763 return getTopOfStack()
764 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
765 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
766 getTopOfStack()
767 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
768 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
769 getTopOfStack()
770 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
771 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown;
772 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
773 OMPC_DEFAULTMAP_MODIFIER_unknown;
776 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
777 return ConstructTraits;
779 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
780 bool ScopeEntry) {
781 if (ScopeEntry)
782 ConstructTraits.append(Traits.begin(), Traits.end());
783 else
784 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
785 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
786 assert(Top == Trait && "Something left a trait on the stack!");
787 (void)Trait;
788 (void)Top;
792 DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const {
793 return getStackSize() <= Level ? DSA_unspecified
794 : getStackElemAtLevel(Level).DefaultAttr;
796 DefaultDataSharingAttributes getDefaultDSA() const {
797 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
799 SourceLocation getDefaultDSALocation() const {
800 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
802 OpenMPDefaultmapClauseModifier
803 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const {
804 return isStackEmpty()
805 ? OMPC_DEFAULTMAP_MODIFIER_unknown
806 : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior;
808 OpenMPDefaultmapClauseModifier
809 getDefaultmapModifierAtLevel(unsigned Level,
810 OpenMPDefaultmapClauseKind Kind) const {
811 return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior;
813 bool isDefaultmapCapturedByRef(unsigned Level,
814 OpenMPDefaultmapClauseKind Kind) const {
815 OpenMPDefaultmapClauseModifier M =
816 getDefaultmapModifierAtLevel(Level, Kind);
817 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
818 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
819 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
820 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
821 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom);
823 return true;
825 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
826 OpenMPDefaultmapClauseKind Kind) {
827 switch (Kind) {
828 case OMPC_DEFAULTMAP_scalar:
829 case OMPC_DEFAULTMAP_pointer:
830 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
831 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
832 (M == OMPC_DEFAULTMAP_MODIFIER_default);
833 case OMPC_DEFAULTMAP_aggregate:
834 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
835 default:
836 break;
838 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum");
840 bool mustBeFirstprivateAtLevel(unsigned Level,
841 OpenMPDefaultmapClauseKind Kind) const {
842 OpenMPDefaultmapClauseModifier M =
843 getDefaultmapModifierAtLevel(Level, Kind);
844 return mustBeFirstprivateBase(M, Kind);
846 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
847 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
848 return mustBeFirstprivateBase(M, Kind);
851 /// Checks if the specified variable is a threadprivate.
852 bool isThreadPrivate(VarDecl *D) {
853 const DSAVarData DVar = getTopDSA(D, false);
854 return isOpenMPThreadPrivate(DVar.CKind);
857 /// Marks current region as ordered (it has an 'ordered' clause).
858 void setOrderedRegion(bool IsOrdered, const Expr *Param,
859 OMPOrderedClause *Clause) {
860 if (IsOrdered)
861 getTopOfStack().OrderedRegion.emplace(Param, Clause);
862 else
863 getTopOfStack().OrderedRegion.reset();
865 /// Returns true, if region is ordered (has associated 'ordered' clause),
866 /// false - otherwise.
867 bool isOrderedRegion() const {
868 if (const SharingMapTy *Top = getTopOfStackOrNull())
869 return Top->OrderedRegion.has_value();
870 return false;
872 /// Returns optional parameter for the ordered region.
873 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
874 if (const SharingMapTy *Top = getTopOfStackOrNull())
875 if (Top->OrderedRegion)
876 return *Top->OrderedRegion;
877 return std::make_pair(nullptr, nullptr);
879 /// Returns true, if parent region is ordered (has associated
880 /// 'ordered' clause), false - otherwise.
881 bool isParentOrderedRegion() const {
882 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
883 return Parent->OrderedRegion.has_value();
884 return false;
886 /// Returns optional parameter for the ordered region.
887 std::pair<const Expr *, OMPOrderedClause *>
888 getParentOrderedRegionParam() const {
889 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
890 if (Parent->OrderedRegion)
891 return *Parent->OrderedRegion;
892 return std::make_pair(nullptr, nullptr);
894 /// Marks current region as having an 'order' clause.
895 void setRegionHasOrderConcurrent(bool HasOrderConcurrent) {
896 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
898 /// Returns true, if parent region is order (has associated
899 /// 'order' clause), false - otherwise.
900 bool isParentOrderConcurrent() const {
901 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
902 return Parent->RegionHasOrderConcurrent;
903 return false;
905 /// Marks current region as nowait (it has a 'nowait' clause).
906 void setNowaitRegion(bool IsNowait = true) {
907 getTopOfStack().NowaitRegion = IsNowait;
909 /// Returns true, if parent region is nowait (has associated
910 /// 'nowait' clause), false - otherwise.
911 bool isParentNowaitRegion() const {
912 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
913 return Parent->NowaitRegion;
914 return false;
916 /// Marks current region as untied (it has a 'untied' clause).
917 void setUntiedRegion(bool IsUntied = true) {
918 getTopOfStack().UntiedRegion = IsUntied;
920 /// Return true if current region is untied.
921 bool isUntiedRegion() const {
922 const SharingMapTy *Top = getTopOfStackOrNull();
923 return Top ? Top->UntiedRegion : false;
925 /// Marks parent region as cancel region.
926 void setParentCancelRegion(bool Cancel = true) {
927 if (SharingMapTy *Parent = getSecondOnStackOrNull())
928 Parent->CancelRegion |= Cancel;
930 /// Return true if current region has inner cancel construct.
931 bool isCancelRegion() const {
932 const SharingMapTy *Top = getTopOfStackOrNull();
933 return Top ? Top->CancelRegion : false;
936 /// Mark that parent region already has scan directive.
937 void setParentHasScanDirective(SourceLocation Loc) {
938 if (SharingMapTy *Parent = getSecondOnStackOrNull())
939 Parent->PrevScanLocation = Loc;
941 /// Return true if current region has inner cancel construct.
942 bool doesParentHasScanDirective() const {
943 const SharingMapTy *Top = getSecondOnStackOrNull();
944 return Top ? Top->PrevScanLocation.isValid() : false;
946 /// Return true if current region has inner cancel construct.
947 SourceLocation getParentScanDirectiveLoc() const {
948 const SharingMapTy *Top = getSecondOnStackOrNull();
949 return Top ? Top->PrevScanLocation : SourceLocation();
951 /// Mark that parent region already has ordered directive.
952 void setParentHasOrderedDirective(SourceLocation Loc) {
953 if (SharingMapTy *Parent = getSecondOnStackOrNull())
954 Parent->PrevOrderedLocation = Loc;
956 /// Return true if current region has inner ordered construct.
957 bool doesParentHasOrderedDirective() const {
958 const SharingMapTy *Top = getSecondOnStackOrNull();
959 return Top ? Top->PrevOrderedLocation.isValid() : false;
961 /// Returns the location of the previously specified ordered directive.
962 SourceLocation getParentOrderedDirectiveLoc() const {
963 const SharingMapTy *Top = getSecondOnStackOrNull();
964 return Top ? Top->PrevOrderedLocation : SourceLocation();
967 /// Set collapse value for the region.
968 void setAssociatedLoops(unsigned Val) {
969 getTopOfStack().AssociatedLoops = Val;
970 if (Val > 1)
971 getTopOfStack().HasMutipleLoops = true;
973 /// Return collapse value for region.
974 unsigned getAssociatedLoops() const {
975 const SharingMapTy *Top = getTopOfStackOrNull();
976 return Top ? Top->AssociatedLoops : 0;
978 /// Returns true if the construct is associated with multiple loops.
979 bool hasMutipleLoops() const {
980 const SharingMapTy *Top = getTopOfStackOrNull();
981 return Top ? Top->HasMutipleLoops : false;
984 /// Marks current target region as one with closely nested teams
985 /// region.
986 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
987 if (SharingMapTy *Parent = getSecondOnStackOrNull())
988 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
990 /// Returns true, if current region has closely nested teams region.
991 bool hasInnerTeamsRegion() const {
992 return getInnerTeamsRegionLoc().isValid();
994 /// Returns location of the nested teams region (if any).
995 SourceLocation getInnerTeamsRegionLoc() const {
996 const SharingMapTy *Top = getTopOfStackOrNull();
997 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
1000 Scope *getCurScope() const {
1001 const SharingMapTy *Top = getTopOfStackOrNull();
1002 return Top ? Top->CurScope : nullptr;
1004 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
1005 SourceLocation getConstructLoc() const {
1006 const SharingMapTy *Top = getTopOfStackOrNull();
1007 return Top ? Top->ConstructLoc : SourceLocation();
1010 /// Do the check specified in \a Check to all component lists and return true
1011 /// if any issue is found.
1012 bool checkMappableExprComponentListsForDecl(
1013 const ValueDecl *VD, bool CurrentRegionOnly,
1014 const llvm::function_ref<
1015 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
1016 OpenMPClauseKind)>
1017 Check) const {
1018 if (isStackEmpty())
1019 return false;
1020 auto SI = begin();
1021 auto SE = end();
1023 if (SI == SE)
1024 return false;
1026 if (CurrentRegionOnly)
1027 SE = std::next(SI);
1028 else
1029 std::advance(SI, 1);
1031 for (; SI != SE; ++SI) {
1032 auto MI = SI->MappedExprComponents.find(VD);
1033 if (MI != SI->MappedExprComponents.end())
1034 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
1035 MI->second.Components)
1036 if (Check(L, MI->second.Kind))
1037 return true;
1039 return false;
1042 /// Do the check specified in \a Check to all component lists at a given level
1043 /// and return true if any issue is found.
1044 bool checkMappableExprComponentListsForDeclAtLevel(
1045 const ValueDecl *VD, unsigned Level,
1046 const llvm::function_ref<
1047 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
1048 OpenMPClauseKind)>
1049 Check) const {
1050 if (getStackSize() <= Level)
1051 return false;
1053 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1054 auto MI = StackElem.MappedExprComponents.find(VD);
1055 if (MI != StackElem.MappedExprComponents.end())
1056 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
1057 MI->second.Components)
1058 if (Check(L, MI->second.Kind))
1059 return true;
1060 return false;
1063 /// Create a new mappable expression component list associated with a given
1064 /// declaration and initialize it with the provided list of components.
1065 void addMappableExpressionComponents(
1066 const ValueDecl *VD,
1067 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
1068 OpenMPClauseKind WhereFoundClauseKind) {
1069 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1070 // Create new entry and append the new components there.
1071 MEC.Components.resize(MEC.Components.size() + 1);
1072 MEC.Components.back().append(Components.begin(), Components.end());
1073 MEC.Kind = WhereFoundClauseKind;
1076 unsigned getNestingLevel() const {
1077 assert(!isStackEmpty());
1078 return getStackSize() - 1;
1080 void addDoacrossDependClause(OMPClause *C, const OperatorOffsetTy &OpsOffs) {
1081 SharingMapTy *Parent = getSecondOnStackOrNull();
1082 assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
1083 Parent->DoacrossDepends.try_emplace(C, OpsOffs);
1085 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1086 getDoacrossDependClauses() const {
1087 const SharingMapTy &StackElem = getTopOfStack();
1088 if (isOpenMPWorksharingDirective(StackElem.Directive)) {
1089 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1090 return llvm::make_range(Ref.begin(), Ref.end());
1092 return llvm::make_range(StackElem.DoacrossDepends.end(),
1093 StackElem.DoacrossDepends.end());
1096 // Store types of classes which have been explicitly mapped
1097 void addMappedClassesQualTypes(QualType QT) {
1098 SharingMapTy &StackElem = getTopOfStack();
1099 StackElem.MappedClassesQualTypes.insert(QT);
1102 // Return set of mapped classes types
1103 bool isClassPreviouslyMapped(QualType QT) const {
1104 const SharingMapTy &StackElem = getTopOfStack();
1105 return StackElem.MappedClassesQualTypes.contains(QT);
1108 /// Adds global declare target to the parent target region.
1109 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1110 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1111 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1112 "Expected declare target link global.");
1113 for (auto &Elem : *this) {
1114 if (isOpenMPTargetExecutionDirective(Elem.Directive)) {
1115 Elem.DeclareTargetLinkVarDecls.push_back(E);
1116 return;
1121 /// Returns the list of globals with declare target link if current directive
1122 /// is target.
1123 ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1124 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
1125 "Expected target executable directive.");
1126 return getTopOfStack().DeclareTargetLinkVarDecls;
1129 /// Adds list of allocators expressions.
1130 void addInnerAllocatorExpr(Expr *E) {
1131 getTopOfStack().InnerUsedAllocators.push_back(E);
1133 /// Return list of used allocators.
1134 ArrayRef<Expr *> getInnerAllocators() const {
1135 return getTopOfStack().InnerUsedAllocators;
1137 /// Marks the declaration as implicitly firstprivate nin the task-based
1138 /// regions.
1139 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1140 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(D);
1142 /// Checks if the decl is implicitly firstprivate in the task-based region.
1143 bool isImplicitTaskFirstprivate(Decl *D) const {
1144 return getTopOfStack().ImplicitTaskFirstprivates.contains(D);
1147 /// Marks decl as used in uses_allocators clause as the allocator.
1148 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1149 getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind);
1151 /// Checks if specified decl is used in uses allocator clause as the
1152 /// allocator.
1153 std::optional<UsesAllocatorsDeclKind>
1154 isUsesAllocatorsDecl(unsigned Level, const Decl *D) const {
1155 const SharingMapTy &StackElem = getTopOfStack();
1156 auto I = StackElem.UsesAllocatorsDecls.find(D);
1157 if (I == StackElem.UsesAllocatorsDecls.end())
1158 return std::nullopt;
1159 return I->getSecond();
1161 std::optional<UsesAllocatorsDeclKind>
1162 isUsesAllocatorsDecl(const Decl *D) const {
1163 const SharingMapTy &StackElem = getTopOfStack();
1164 auto I = StackElem.UsesAllocatorsDecls.find(D);
1165 if (I == StackElem.UsesAllocatorsDecls.end())
1166 return std::nullopt;
1167 return I->getSecond();
1170 void addDeclareMapperVarRef(Expr *Ref) {
1171 SharingMapTy &StackElem = getTopOfStack();
1172 StackElem.DeclareMapperVar = Ref;
1174 const Expr *getDeclareMapperVarRef() const {
1175 const SharingMapTy *Top = getTopOfStackOrNull();
1176 return Top ? Top->DeclareMapperVar : nullptr;
1179 /// Add a new iterator variable.
1180 void addIteratorVarDecl(VarDecl *VD) {
1181 SharingMapTy &StackElem = getTopOfStack();
1182 StackElem.IteratorVarDecls.push_back(VD->getCanonicalDecl());
1184 /// Check if variable declaration is an iterator VarDecl.
1185 bool isIteratorVarDecl(const VarDecl *VD) const {
1186 const SharingMapTy *Top = getTopOfStackOrNull();
1187 if (!Top)
1188 return false;
1190 return llvm::any_of(Top->IteratorVarDecls, [VD](const VarDecl *IteratorVD) {
1191 return IteratorVD == VD->getCanonicalDecl();
1194 /// get captured field from ImplicitDefaultFirstprivateFDs
1195 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1196 const_iterator I = begin();
1197 const_iterator EndI = end();
1198 size_t StackLevel = getStackSize();
1199 for (; I != EndI; ++I) {
1200 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1201 break;
1202 StackLevel--;
1204 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1205 if (I == EndI)
1206 return nullptr;
1207 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1208 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1209 return IFD.VD;
1210 return nullptr;
1212 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
1213 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1214 const_iterator I = begin();
1215 const_iterator EndI = end();
1216 for (; I != EndI; ++I)
1217 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1218 break;
1219 if (I == EndI)
1220 return false;
1221 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1222 if (IFD.VD == VD)
1223 return true;
1224 return false;
1226 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
1227 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1228 iterator I = begin();
1229 const_iterator EndI = end();
1230 size_t StackLevel = getStackSize();
1231 for (; I != EndI; ++I) {
1232 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1233 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1234 break;
1236 StackLevel--;
1238 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1242 bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1243 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1246 bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1247 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) ||
1248 DKind == OMPD_unknown;
1251 } // namespace
1253 static const Expr *getExprAsWritten(const Expr *E) {
1254 if (const auto *FE = dyn_cast<FullExpr>(E))
1255 E = FE->getSubExpr();
1257 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
1258 E = MTE->getSubExpr();
1260 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
1261 E = Binder->getSubExpr();
1263 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
1264 E = ICE->getSubExprAsWritten();
1265 return E->IgnoreParens();
1268 static Expr *getExprAsWritten(Expr *E) {
1269 return const_cast<Expr *>(getExprAsWritten(const_cast<const Expr *>(E)));
1272 static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1273 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
1274 if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
1275 D = ME->getMemberDecl();
1276 const auto *VD = dyn_cast<VarDecl>(D);
1277 const auto *FD = dyn_cast<FieldDecl>(D);
1278 if (VD != nullptr) {
1279 VD = VD->getCanonicalDecl();
1280 D = VD;
1281 } else {
1282 assert(FD);
1283 FD = FD->getCanonicalDecl();
1284 D = FD;
1286 return D;
1289 static ValueDecl *getCanonicalDecl(ValueDecl *D) {
1290 return const_cast<ValueDecl *>(
1291 getCanonicalDecl(const_cast<const ValueDecl *>(D)));
1294 DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1295 ValueDecl *D) const {
1296 D = getCanonicalDecl(D);
1297 auto *VD = dyn_cast<VarDecl>(D);
1298 const auto *FD = dyn_cast<FieldDecl>(D);
1299 DSAVarData DVar;
1300 if (Iter == end()) {
1301 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1302 // in a region but not in construct]
1303 // File-scope or namespace-scope variables referenced in called routines
1304 // in the region are shared unless they appear in a threadprivate
1305 // directive.
1306 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD))
1307 DVar.CKind = OMPC_shared;
1309 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1310 // in a region but not in construct]
1311 // Variables with static storage duration that are declared in called
1312 // routines in the region are shared.
1313 if (VD && VD->hasGlobalStorage())
1314 DVar.CKind = OMPC_shared;
1316 // Non-static data members are shared by default.
1317 if (FD)
1318 DVar.CKind = OMPC_shared;
1320 return DVar;
1323 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1324 // in a Construct, C/C++, predetermined, p.1]
1325 // Variables with automatic storage duration that are declared in a scope
1326 // inside the construct are private.
1327 if (VD && isOpenMPLocal(VD, Iter) && VD->isLocalVarDecl() &&
1328 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1329 DVar.CKind = OMPC_private;
1330 return DVar;
1333 DVar.DKind = Iter->Directive;
1334 // Explicitly specified attributes and local variables with predetermined
1335 // attributes.
1336 if (Iter->SharingMap.count(D)) {
1337 const DSAInfo &Data = Iter->SharingMap.lookup(D);
1338 DVar.RefExpr = Data.RefExpr.getPointer();
1339 DVar.PrivateCopy = Data.PrivateCopy;
1340 DVar.CKind = Data.Attributes;
1341 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1342 DVar.Modifier = Data.Modifier;
1343 DVar.AppliedToPointee = Data.AppliedToPointee;
1344 return DVar;
1347 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1348 // in a Construct, C/C++, implicitly determined, p.1]
1349 // In a parallel or task construct, the data-sharing attributes of these
1350 // variables are determined by the default clause, if present.
1351 switch (Iter->DefaultAttr) {
1352 case DSA_shared:
1353 DVar.CKind = OMPC_shared;
1354 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1355 return DVar;
1356 case DSA_none:
1357 return DVar;
1358 case DSA_firstprivate:
1359 if (VD && VD->getStorageDuration() == SD_Static &&
1360 VD->getDeclContext()->isFileContext()) {
1361 DVar.CKind = OMPC_unknown;
1362 } else {
1363 DVar.CKind = OMPC_firstprivate;
1365 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1366 return DVar;
1367 case DSA_private:
1368 // each variable with static storage duration that is declared
1369 // in a namespace or global scope and referenced in the construct,
1370 // and that does not have a predetermined data-sharing attribute
1371 if (VD && VD->getStorageDuration() == SD_Static &&
1372 VD->getDeclContext()->isFileContext()) {
1373 DVar.CKind = OMPC_unknown;
1374 } else {
1375 DVar.CKind = OMPC_private;
1377 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1378 return DVar;
1379 case DSA_unspecified:
1380 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1381 // in a Construct, implicitly determined, p.2]
1382 // In a parallel construct, if no default clause is present, these
1383 // variables are shared.
1384 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1385 if ((isOpenMPParallelDirective(DVar.DKind) &&
1386 !isOpenMPTaskLoopDirective(DVar.DKind)) ||
1387 isOpenMPTeamsDirective(DVar.DKind)) {
1388 DVar.CKind = OMPC_shared;
1389 return DVar;
1392 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1393 // in a Construct, implicitly determined, p.4]
1394 // In a task construct, if no default clause is present, a variable that in
1395 // the enclosing context is determined to be shared by all implicit tasks
1396 // bound to the current team is shared.
1397 if (isOpenMPTaskingDirective(DVar.DKind)) {
1398 DSAVarData DVarTemp;
1399 const_iterator I = Iter, E = end();
1400 do {
1401 ++I;
1402 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1403 // Referenced in a Construct, implicitly determined, p.6]
1404 // In a task construct, if no default clause is present, a variable
1405 // whose data-sharing attribute is not determined by the rules above is
1406 // firstprivate.
1407 DVarTemp = getDSA(I, D);
1408 if (DVarTemp.CKind != OMPC_shared) {
1409 DVar.RefExpr = nullptr;
1410 DVar.CKind = OMPC_firstprivate;
1411 return DVar;
1413 } while (I != E && !isImplicitTaskingRegion(I->Directive));
1414 DVar.CKind =
1415 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1416 return DVar;
1419 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1420 // in a Construct, implicitly determined, p.3]
1421 // For constructs other than task, if no default clause is present, these
1422 // variables inherit their data-sharing attributes from the enclosing
1423 // context.
1424 return getDSA(++Iter, D);
1427 const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1428 const Expr *NewDE) {
1429 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1430 D = getCanonicalDecl(D);
1431 SharingMapTy &StackElem = getTopOfStack();
1432 auto It = StackElem.AlignedMap.find(D);
1433 if (It == StackElem.AlignedMap.end()) {
1434 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1435 StackElem.AlignedMap[D] = NewDE;
1436 return nullptr;
1438 assert(It->second && "Unexpected nullptr expr in the aligned map");
1439 return It->second;
1442 const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1443 const Expr *NewDE) {
1444 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1445 D = getCanonicalDecl(D);
1446 SharingMapTy &StackElem = getTopOfStack();
1447 auto It = StackElem.NontemporalMap.find(D);
1448 if (It == StackElem.NontemporalMap.end()) {
1449 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1450 StackElem.NontemporalMap[D] = NewDE;
1451 return nullptr;
1453 assert(It->second && "Unexpected nullptr expr in the aligned map");
1454 return It->second;
1457 void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1458 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1459 D = getCanonicalDecl(D);
1460 SharingMapTy &StackElem = getTopOfStack();
1461 StackElem.LCVMap.try_emplace(
1462 D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1465 const DSAStackTy::LCDeclInfo
1466 DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1467 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1468 D = getCanonicalDecl(D);
1469 const SharingMapTy &StackElem = getTopOfStack();
1470 auto It = StackElem.LCVMap.find(D);
1471 if (It != StackElem.LCVMap.end())
1472 return It->second;
1473 return {0, nullptr};
1476 const DSAStackTy::LCDeclInfo
1477 DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1478 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1479 D = getCanonicalDecl(D);
1480 for (unsigned I = Level + 1; I > 0; --I) {
1481 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1482 auto It = StackElem.LCVMap.find(D);
1483 if (It != StackElem.LCVMap.end())
1484 return It->second;
1486 return {0, nullptr};
1489 const DSAStackTy::LCDeclInfo
1490 DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1491 const SharingMapTy *Parent = getSecondOnStackOrNull();
1492 assert(Parent && "Data-sharing attributes stack is empty");
1493 D = getCanonicalDecl(D);
1494 auto It = Parent->LCVMap.find(D);
1495 if (It != Parent->LCVMap.end())
1496 return It->second;
1497 return {0, nullptr};
1500 const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1501 const SharingMapTy *Parent = getSecondOnStackOrNull();
1502 assert(Parent && "Data-sharing attributes stack is empty");
1503 if (Parent->LCVMap.size() < I)
1504 return nullptr;
1505 for (const auto &Pair : Parent->LCVMap)
1506 if (Pair.second.first == I)
1507 return Pair.first;
1508 return nullptr;
1511 void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1512 DeclRefExpr *PrivateCopy, unsigned Modifier,
1513 bool AppliedToPointee) {
1514 D = getCanonicalDecl(D);
1515 if (A == OMPC_threadprivate) {
1516 DSAInfo &Data = Threadprivates[D];
1517 Data.Attributes = A;
1518 Data.RefExpr.setPointer(E);
1519 Data.PrivateCopy = nullptr;
1520 Data.Modifier = Modifier;
1521 } else {
1522 DSAInfo &Data = getTopOfStack().SharingMap[D];
1523 assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1524 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1525 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1526 (isLoopControlVariable(D).first && A == OMPC_private));
1527 Data.Modifier = Modifier;
1528 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1529 Data.RefExpr.setInt(/*IntVal=*/true);
1530 return;
1532 const bool IsLastprivate =
1533 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1534 Data.Attributes = A;
1535 Data.RefExpr.setPointerAndInt(E, IsLastprivate);
1536 Data.PrivateCopy = PrivateCopy;
1537 Data.AppliedToPointee = AppliedToPointee;
1538 if (PrivateCopy) {
1539 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1540 Data.Modifier = Modifier;
1541 Data.Attributes = A;
1542 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1543 Data.PrivateCopy = nullptr;
1544 Data.AppliedToPointee = AppliedToPointee;
1549 /// Build a variable declaration for OpenMP loop iteration variable.
1550 static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type,
1551 StringRef Name, const AttrVec *Attrs = nullptr,
1552 DeclRefExpr *OrigRef = nullptr) {
1553 DeclContext *DC = SemaRef.CurContext;
1554 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1555 TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
1556 auto *Decl =
1557 VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
1558 if (Attrs) {
1559 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1560 I != E; ++I)
1561 Decl->addAttr(*I);
1563 Decl->setImplicit();
1564 if (OrigRef) {
1565 Decl->addAttr(
1566 OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef));
1568 return Decl;
1571 static DeclRefExpr *buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty,
1572 SourceLocation Loc,
1573 bool RefersToCapture = false) {
1574 D->setReferenced();
1575 D->markUsed(S.Context);
1576 return DeclRefExpr::Create(S.getASTContext(), NestedNameSpecifierLoc(),
1577 SourceLocation(), D, RefersToCapture, Loc, Ty,
1578 VK_LValue);
1581 void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1582 BinaryOperatorKind BOK) {
1583 D = getCanonicalDecl(D);
1584 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1585 assert(
1586 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1587 "Additional reduction info may be specified only for reduction items.");
1588 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1589 assert(ReductionData.ReductionRange.isInvalid() &&
1590 (getTopOfStack().Directive == OMPD_taskgroup ||
1591 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1592 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1593 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1594 "Additional reduction info may be specified only once for reduction "
1595 "items.");
1596 ReductionData.set(BOK, SR);
1597 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1598 if (!TaskgroupReductionRef) {
1599 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1600 SemaRef.Context.VoidPtrTy, ".task_red.");
1601 TaskgroupReductionRef =
1602 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1606 void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1607 const Expr *ReductionRef) {
1608 D = getCanonicalDecl(D);
1609 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1610 assert(
1611 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1612 "Additional reduction info may be specified only for reduction items.");
1613 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1614 assert(ReductionData.ReductionRange.isInvalid() &&
1615 (getTopOfStack().Directive == OMPD_taskgroup ||
1616 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1617 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1618 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1619 "Additional reduction info may be specified only once for reduction "
1620 "items.");
1621 ReductionData.set(ReductionRef, SR);
1622 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1623 if (!TaskgroupReductionRef) {
1624 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1625 SemaRef.Context.VoidPtrTy, ".task_red.");
1626 TaskgroupReductionRef =
1627 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1631 const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1632 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1633 Expr *&TaskgroupDescriptor) const {
1634 D = getCanonicalDecl(D);
1635 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1636 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1637 const DSAInfo &Data = I->SharingMap.lookup(D);
1638 if (Data.Attributes != OMPC_reduction ||
1639 Data.Modifier != OMPC_REDUCTION_task)
1640 continue;
1641 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1642 if (!ReductionData.ReductionOp ||
1643 ReductionData.ReductionOp.is<const Expr *>())
1644 return DSAVarData();
1645 SR = ReductionData.ReductionRange;
1646 BOK = ReductionData.ReductionOp.get<ReductionData::BOKPtrType>();
1647 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1648 "expression for the descriptor is not "
1649 "set.");
1650 TaskgroupDescriptor = I->TaskgroupReductionRef;
1651 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1652 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1653 /*AppliedToPointee=*/false);
1655 return DSAVarData();
1658 const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1659 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1660 Expr *&TaskgroupDescriptor) const {
1661 D = getCanonicalDecl(D);
1662 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1663 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1664 const DSAInfo &Data = I->SharingMap.lookup(D);
1665 if (Data.Attributes != OMPC_reduction ||
1666 Data.Modifier != OMPC_REDUCTION_task)
1667 continue;
1668 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1669 if (!ReductionData.ReductionOp ||
1670 !ReductionData.ReductionOp.is<const Expr *>())
1671 return DSAVarData();
1672 SR = ReductionData.ReductionRange;
1673 ReductionRef = ReductionData.ReductionOp.get<const Expr *>();
1674 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1675 "expression for the descriptor is not "
1676 "set.");
1677 TaskgroupDescriptor = I->TaskgroupReductionRef;
1678 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1679 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1680 /*AppliedToPointee=*/false);
1682 return DSAVarData();
1685 bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1686 D = D->getCanonicalDecl();
1687 for (const_iterator E = end(); I != E; ++I) {
1688 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1689 isOpenMPTargetExecutionDirective(I->Directive)) {
1690 if (I->CurScope) {
1691 Scope *TopScope = I->CurScope->getParent();
1692 Scope *CurScope = getCurScope();
1693 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1694 CurScope = CurScope->getParent();
1695 return CurScope != TopScope;
1697 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1698 if (I->Context == DC)
1699 return true;
1700 return false;
1703 return false;
1706 static bool isConstNotMutableType(Sema &SemaRef, QualType Type,
1707 bool AcceptIfMutable = true,
1708 bool *IsClassType = nullptr) {
1709 ASTContext &Context = SemaRef.getASTContext();
1710 Type = Type.getNonReferenceType().getCanonicalType();
1711 bool IsConstant = Type.isConstant(Context);
1712 Type = Context.getBaseElementType(Type);
1713 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1714 ? Type->getAsCXXRecordDecl()
1715 : nullptr;
1716 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1717 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1718 RD = CTD->getTemplatedDecl();
1719 if (IsClassType)
1720 *IsClassType = RD;
1721 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1722 RD->hasDefinition() && RD->hasMutableFields());
1725 static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1726 QualType Type, OpenMPClauseKind CKind,
1727 SourceLocation ELoc,
1728 bool AcceptIfMutable = true,
1729 bool ListItemNotVar = false) {
1730 ASTContext &Context = SemaRef.getASTContext();
1731 bool IsClassType;
1732 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, &IsClassType)) {
1733 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1734 : IsClassType ? diag::err_omp_const_not_mutable_variable
1735 : diag::err_omp_const_variable;
1736 SemaRef.Diag(ELoc, Diag) << getOpenMPClauseName(CKind);
1737 if (!ListItemNotVar && D) {
1738 const VarDecl *VD = dyn_cast<VarDecl>(D);
1739 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1740 VarDecl::DeclarationOnly;
1741 SemaRef.Diag(D->getLocation(),
1742 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1743 << D;
1745 return true;
1747 return false;
1750 const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1751 bool FromParent) {
1752 D = getCanonicalDecl(D);
1753 DSAVarData DVar;
1755 auto *VD = dyn_cast<VarDecl>(D);
1756 auto TI = Threadprivates.find(D);
1757 if (TI != Threadprivates.end()) {
1758 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1759 DVar.CKind = OMPC_threadprivate;
1760 DVar.Modifier = TI->getSecond().Modifier;
1761 return DVar;
1763 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1764 DVar.RefExpr = buildDeclRefExpr(
1765 SemaRef, VD, D->getType().getNonReferenceType(),
1766 VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1767 DVar.CKind = OMPC_threadprivate;
1768 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1769 return DVar;
1771 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1772 // in a Construct, C/C++, predetermined, p.1]
1773 // Variables appearing in threadprivate directives are threadprivate.
1774 if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1775 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1776 SemaRef.getLangOpts().OpenMPUseTLS &&
1777 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1778 (VD && VD->getStorageClass() == SC_Register &&
1779 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1780 DVar.RefExpr = buildDeclRefExpr(
1781 SemaRef, VD, D->getType().getNonReferenceType(), D->getLocation());
1782 DVar.CKind = OMPC_threadprivate;
1783 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1784 return DVar;
1786 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1787 VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1788 !isLoopControlVariable(D).first) {
1789 const_iterator IterTarget =
1790 std::find_if(begin(), end(), [](const SharingMapTy &Data) {
1791 return isOpenMPTargetExecutionDirective(Data.Directive);
1793 if (IterTarget != end()) {
1794 const_iterator ParentIterTarget = IterTarget + 1;
1795 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1796 if (isOpenMPLocal(VD, Iter)) {
1797 DVar.RefExpr =
1798 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1799 D->getLocation());
1800 DVar.CKind = OMPC_threadprivate;
1801 return DVar;
1804 if (!isClauseParsingMode() || IterTarget != begin()) {
1805 auto DSAIter = IterTarget->SharingMap.find(D);
1806 if (DSAIter != IterTarget->SharingMap.end() &&
1807 isOpenMPPrivate(DSAIter->getSecond().Attributes)) {
1808 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1809 DVar.CKind = OMPC_threadprivate;
1810 return DVar;
1812 const_iterator End = end();
1813 if (!SemaRef.isOpenMPCapturedByRef(D,
1814 std::distance(ParentIterTarget, End),
1815 /*OpenMPCaptureLevel=*/0)) {
1816 DVar.RefExpr =
1817 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1818 IterTarget->ConstructLoc);
1819 DVar.CKind = OMPC_threadprivate;
1820 return DVar;
1826 if (isStackEmpty())
1827 // Not in OpenMP execution region and top scope was already checked.
1828 return DVar;
1830 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1831 // in a Construct, C/C++, predetermined, p.4]
1832 // Static data members are shared.
1833 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1834 // in a Construct, C/C++, predetermined, p.7]
1835 // Variables with static storage duration that are declared in a scope
1836 // inside the construct are shared.
1837 if (VD && VD->isStaticDataMember()) {
1838 // Check for explicitly specified attributes.
1839 const_iterator I = begin();
1840 const_iterator EndI = end();
1841 if (FromParent && I != EndI)
1842 ++I;
1843 if (I != EndI) {
1844 auto It = I->SharingMap.find(D);
1845 if (It != I->SharingMap.end()) {
1846 const DSAInfo &Data = It->getSecond();
1847 DVar.RefExpr = Data.RefExpr.getPointer();
1848 DVar.PrivateCopy = Data.PrivateCopy;
1849 DVar.CKind = Data.Attributes;
1850 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1851 DVar.DKind = I->Directive;
1852 DVar.Modifier = Data.Modifier;
1853 DVar.AppliedToPointee = Data.AppliedToPointee;
1854 return DVar;
1858 DVar.CKind = OMPC_shared;
1859 return DVar;
1862 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1863 // The predetermined shared attribute for const-qualified types having no
1864 // mutable members was removed after OpenMP 3.1.
1865 if (SemaRef.LangOpts.OpenMP <= 31) {
1866 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1867 // in a Construct, C/C++, predetermined, p.6]
1868 // Variables with const qualified type having no mutable member are
1869 // shared.
1870 if (isConstNotMutableType(SemaRef, D->getType())) {
1871 // Variables with const-qualified type having no mutable member may be
1872 // listed in a firstprivate clause, even if they are static data members.
1873 DSAVarData DVarTemp = hasInnermostDSA(
1875 [](OpenMPClauseKind C, bool) {
1876 return C == OMPC_firstprivate || C == OMPC_shared;
1878 MatchesAlways, FromParent);
1879 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1880 return DVarTemp;
1882 DVar.CKind = OMPC_shared;
1883 return DVar;
1887 // Explicitly specified attributes and local variables with predetermined
1888 // attributes.
1889 const_iterator I = begin();
1890 const_iterator EndI = end();
1891 if (FromParent && I != EndI)
1892 ++I;
1893 if (I == EndI)
1894 return DVar;
1895 auto It = I->SharingMap.find(D);
1896 if (It != I->SharingMap.end()) {
1897 const DSAInfo &Data = It->getSecond();
1898 DVar.RefExpr = Data.RefExpr.getPointer();
1899 DVar.PrivateCopy = Data.PrivateCopy;
1900 DVar.CKind = Data.Attributes;
1901 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1902 DVar.DKind = I->Directive;
1903 DVar.Modifier = Data.Modifier;
1904 DVar.AppliedToPointee = Data.AppliedToPointee;
1907 return DVar;
1910 const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1911 bool FromParent) const {
1912 if (isStackEmpty()) {
1913 const_iterator I;
1914 return getDSA(I, D);
1916 D = getCanonicalDecl(D);
1917 const_iterator StartI = begin();
1918 const_iterator EndI = end();
1919 if (FromParent && StartI != EndI)
1920 ++StartI;
1921 return getDSA(StartI, D);
1924 const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1925 unsigned Level) const {
1926 if (getStackSize() <= Level)
1927 return DSAVarData();
1928 D = getCanonicalDecl(D);
1929 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
1930 return getDSA(StartI, D);
1933 const DSAStackTy::DSAVarData
1934 DSAStackTy::hasDSA(ValueDecl *D,
1935 const llvm::function_ref<bool(OpenMPClauseKind, bool,
1936 DefaultDataSharingAttributes)>
1937 CPred,
1938 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1939 bool FromParent) const {
1940 if (isStackEmpty())
1941 return {};
1942 D = getCanonicalDecl(D);
1943 const_iterator I = begin();
1944 const_iterator EndI = end();
1945 if (FromParent && I != EndI)
1946 ++I;
1947 for (; I != EndI; ++I) {
1948 if (!DPred(I->Directive) &&
1949 !isImplicitOrExplicitTaskingRegion(I->Directive))
1950 continue;
1951 const_iterator NewI = I;
1952 DSAVarData DVar = getDSA(NewI, D);
1953 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1954 return DVar;
1956 return {};
1959 const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1960 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1961 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1962 bool FromParent) const {
1963 if (isStackEmpty())
1964 return {};
1965 D = getCanonicalDecl(D);
1966 const_iterator StartI = begin();
1967 const_iterator EndI = end();
1968 if (FromParent && StartI != EndI)
1969 ++StartI;
1970 if (StartI == EndI || !DPred(StartI->Directive))
1971 return {};
1972 const_iterator NewI = StartI;
1973 DSAVarData DVar = getDSA(NewI, D);
1974 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
1975 ? DVar
1976 : DSAVarData();
1979 bool DSAStackTy::hasExplicitDSA(
1980 const ValueDecl *D,
1981 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1982 unsigned Level, bool NotLastprivate) const {
1983 if (getStackSize() <= Level)
1984 return false;
1985 D = getCanonicalDecl(D);
1986 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1987 auto I = StackElem.SharingMap.find(D);
1988 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
1989 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
1990 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
1991 return true;
1992 // Check predetermined rules for the loop control variables.
1993 auto LI = StackElem.LCVMap.find(D);
1994 if (LI != StackElem.LCVMap.end())
1995 return CPred(OMPC_private, /*AppliedToPointee=*/false);
1996 return false;
1999 bool DSAStackTy::hasExplicitDirective(
2000 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
2001 unsigned Level) const {
2002 if (getStackSize() <= Level)
2003 return false;
2004 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2005 return DPred(StackElem.Directive);
2008 bool DSAStackTy::hasDirective(
2009 const llvm::function_ref<bool(OpenMPDirectiveKind,
2010 const DeclarationNameInfo &, SourceLocation)>
2011 DPred,
2012 bool FromParent) const {
2013 // We look only in the enclosing region.
2014 size_t Skip = FromParent ? 2 : 1;
2015 for (const_iterator I = begin() + std::min(Skip, getStackSize()), E = end();
2016 I != E; ++I) {
2017 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
2018 return true;
2020 return false;
2023 void Sema::InitDataSharingAttributesStack() {
2024 VarDataSharingAttributesStack = new DSAStackTy(*this);
2027 #define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2029 void Sema::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); }
2031 void Sema::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
2032 DSAStack->popFunction(OldFSI);
2035 static bool isOpenMPDeviceDelayedContext(Sema &S) {
2036 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsTargetDevice &&
2037 "Expected OpenMP device compilation.");
2038 return !S.isInOpenMPTargetExecutionDirective();
2041 namespace {
2042 /// Status of the function emission on the host/device.
2043 enum class FunctionEmissionStatus {
2044 Emitted,
2045 Discarded,
2046 Unknown,
2048 } // anonymous namespace
2050 Sema::SemaDiagnosticBuilder
2051 Sema::diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID,
2052 const FunctionDecl *FD) {
2053 assert(LangOpts.OpenMP && LangOpts.OpenMPIsTargetDevice &&
2054 "Expected OpenMP device compilation.");
2056 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2057 if (FD) {
2058 FunctionEmissionStatus FES = getEmissionStatus(FD);
2059 switch (FES) {
2060 case FunctionEmissionStatus::Emitted:
2061 Kind = SemaDiagnosticBuilder::K_Immediate;
2062 break;
2063 case FunctionEmissionStatus::Unknown:
2064 // TODO: We should always delay diagnostics here in case a target
2065 // region is in a function we do not emit. However, as the
2066 // current diagnostics are associated with the function containing
2067 // the target region and we do not emit that one, we would miss out
2068 // on diagnostics for the target region itself. We need to anchor
2069 // the diagnostics with the new generated function *or* ensure we
2070 // emit diagnostics associated with the surrounding function.
2071 Kind = isOpenMPDeviceDelayedContext(*this)
2072 ? SemaDiagnosticBuilder::K_Deferred
2073 : SemaDiagnosticBuilder::K_Immediate;
2074 break;
2075 case FunctionEmissionStatus::TemplateDiscarded:
2076 case FunctionEmissionStatus::OMPDiscarded:
2077 Kind = SemaDiagnosticBuilder::K_Nop;
2078 break;
2079 case FunctionEmissionStatus::CUDADiscarded:
2080 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2081 break;
2085 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, *this);
2088 Sema::SemaDiagnosticBuilder Sema::diagIfOpenMPHostCode(SourceLocation Loc,
2089 unsigned DiagID,
2090 const FunctionDecl *FD) {
2091 assert(LangOpts.OpenMP && !LangOpts.OpenMPIsTargetDevice &&
2092 "Expected OpenMP host compilation.");
2094 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2095 if (FD) {
2096 FunctionEmissionStatus FES = getEmissionStatus(FD);
2097 switch (FES) {
2098 case FunctionEmissionStatus::Emitted:
2099 Kind = SemaDiagnosticBuilder::K_Immediate;
2100 break;
2101 case FunctionEmissionStatus::Unknown:
2102 Kind = SemaDiagnosticBuilder::K_Deferred;
2103 break;
2104 case FunctionEmissionStatus::TemplateDiscarded:
2105 case FunctionEmissionStatus::OMPDiscarded:
2106 case FunctionEmissionStatus::CUDADiscarded:
2107 Kind = SemaDiagnosticBuilder::K_Nop;
2108 break;
2112 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, *this);
2115 static OpenMPDefaultmapClauseKind
2116 getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD) {
2117 if (LO.OpenMP <= 45) {
2118 if (VD->getType().getNonReferenceType()->isScalarType())
2119 return OMPC_DEFAULTMAP_scalar;
2120 return OMPC_DEFAULTMAP_aggregate;
2122 if (VD->getType().getNonReferenceType()->isAnyPointerType())
2123 return OMPC_DEFAULTMAP_pointer;
2124 if (VD->getType().getNonReferenceType()->isScalarType())
2125 return OMPC_DEFAULTMAP_scalar;
2126 return OMPC_DEFAULTMAP_aggregate;
2129 bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
2130 unsigned OpenMPCaptureLevel) const {
2131 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2133 ASTContext &Ctx = getASTContext();
2134 bool IsByRef = true;
2136 // Find the directive that is associated with the provided scope.
2137 D = cast<ValueDecl>(D->getCanonicalDecl());
2138 QualType Ty = D->getType();
2140 bool IsVariableUsedInMapClause = false;
2141 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) {
2142 // This table summarizes how a given variable should be passed to the device
2143 // given its type and the clauses where it appears. This table is based on
2144 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2145 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2147 // =========================================================================
2148 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2149 // | |(tofrom:scalar)| | pvt | |has_dv_adr| |
2150 // =========================================================================
2151 // | scl | | | | - | | bycopy|
2152 // | scl | | - | x | - | - | bycopy|
2153 // | scl | | x | - | - | - | null |
2154 // | scl | x | | | - | | byref |
2155 // | scl | x | - | x | - | - | bycopy|
2156 // | scl | x | x | - | - | - | null |
2157 // | scl | | - | - | - | x | byref |
2158 // | scl | x | - | - | - | x | byref |
2160 // | agg | n.a. | | | - | | byref |
2161 // | agg | n.a. | - | x | - | - | byref |
2162 // | agg | n.a. | x | - | - | - | null |
2163 // | agg | n.a. | - | - | - | x | byref |
2164 // | agg | n.a. | - | - | - | x[] | byref |
2166 // | ptr | n.a. | | | - | | bycopy|
2167 // | ptr | n.a. | - | x | - | - | bycopy|
2168 // | ptr | n.a. | x | - | - | - | null |
2169 // | ptr | n.a. | - | - | - | x | byref |
2170 // | ptr | n.a. | - | - | - | x[] | bycopy|
2171 // | ptr | n.a. | - | - | x | | bycopy|
2172 // | ptr | n.a. | - | - | x | x | bycopy|
2173 // | ptr | n.a. | - | - | x | x[] | bycopy|
2174 // =========================================================================
2175 // Legend:
2176 // scl - scalar
2177 // ptr - pointer
2178 // agg - aggregate
2179 // x - applies
2180 // - - invalid in this combination
2181 // [] - mapped with an array section
2182 // byref - should be mapped by reference
2183 // byval - should be mapped by value
2184 // null - initialize a local variable to null on the device
2186 // Observations:
2187 // - All scalar declarations that show up in a map clause have to be passed
2188 // by reference, because they may have been mapped in the enclosing data
2189 // environment.
2190 // - If the scalar value does not fit the size of uintptr, it has to be
2191 // passed by reference, regardless the result in the table above.
2192 // - For pointers mapped by value that have either an implicit map or an
2193 // array section, the runtime library may pass the NULL value to the
2194 // device instead of the value passed to it by the compiler.
2196 if (Ty->isReferenceType())
2197 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2199 // Locate map clauses and see if the variable being captured is referred to
2200 // in any of those clauses. Here we only care about variables, not fields,
2201 // because fields are part of aggregates.
2202 bool IsVariableAssociatedWithSection = false;
2204 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2205 D, Level,
2206 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2207 D](OMPClauseMappableExprCommon::MappableExprComponentListRef
2208 MapExprComponents,
2209 OpenMPClauseKind WhereFoundClauseKind) {
2210 // Both map and has_device_addr clauses information influences how a
2211 // variable is captured. E.g. is_device_ptr does not require changing
2212 // the default behavior.
2213 if (WhereFoundClauseKind != OMPC_map &&
2214 WhereFoundClauseKind != OMPC_has_device_addr)
2215 return false;
2217 auto EI = MapExprComponents.rbegin();
2218 auto EE = MapExprComponents.rend();
2220 assert(EI != EE && "Invalid map expression!");
2222 if (isa<DeclRefExpr>(EI->getAssociatedExpression()))
2223 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D;
2225 ++EI;
2226 if (EI == EE)
2227 return false;
2228 auto Last = std::prev(EE);
2229 const auto *UO =
2230 dyn_cast<UnaryOperator>(Last->getAssociatedExpression());
2231 if ((UO && UO->getOpcode() == UO_Deref) ||
2232 isa<ArraySubscriptExpr>(Last->getAssociatedExpression()) ||
2233 isa<OMPArraySectionExpr>(Last->getAssociatedExpression()) ||
2234 isa<MemberExpr>(EI->getAssociatedExpression()) ||
2235 isa<OMPArrayShapingExpr>(Last->getAssociatedExpression())) {
2236 IsVariableAssociatedWithSection = true;
2237 // There is nothing more we need to know about this variable.
2238 return true;
2241 // Keep looking for more map info.
2242 return false;
2245 if (IsVariableUsedInMapClause) {
2246 // If variable is identified in a map clause it is always captured by
2247 // reference except if it is a pointer that is dereferenced somehow.
2248 IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2249 } else {
2250 // By default, all the data that has a scalar type is mapped by copy
2251 // (except for reduction variables).
2252 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2253 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2254 !Ty->isAnyPointerType()) ||
2255 !Ty->isScalarType() ||
2256 DSAStack->isDefaultmapCapturedByRef(
2257 Level, getVariableCategoryFromDecl(LangOpts, D)) ||
2258 DSAStack->hasExplicitDSA(
2260 [](OpenMPClauseKind K, bool AppliedToPointee) {
2261 return K == OMPC_reduction && !AppliedToPointee;
2263 Level);
2267 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2268 IsByRef =
2269 ((IsVariableUsedInMapClause &&
2270 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2271 OMPD_target) ||
2272 !(DSAStack->hasExplicitDSA(
2274 [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2275 return K == OMPC_firstprivate ||
2276 (K == OMPC_reduction && AppliedToPointee);
2278 Level, /*NotLastprivate=*/true) ||
2279 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2280 // If the variable is artificial and must be captured by value - try to
2281 // capture by value.
2282 !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2283 !cast<OMPCapturedExprDecl>(D)->getInit()->isGLValue()) &&
2284 // If the variable is implicitly firstprivate and scalar - capture by
2285 // copy
2286 !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2287 DSAStack->getDefaultDSA() == DSA_private) &&
2288 !DSAStack->hasExplicitDSA(
2289 D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2290 Level) &&
2291 !DSAStack->isLoopControlVariable(D, Level).first);
2294 // When passing data by copy, we need to make sure it fits the uintptr size
2295 // and alignment, because the runtime library only deals with uintptr types.
2296 // If it does not fit the uintptr size, we need to pass the data by reference
2297 // instead.
2298 if (!IsByRef && (Ctx.getTypeSizeInChars(Ty) >
2299 Ctx.getTypeSizeInChars(Ctx.getUIntPtrType()) ||
2300 Ctx.getAlignOfGlobalVarInChars(Ty) >
2301 Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) {
2302 IsByRef = true;
2305 return IsByRef;
2308 unsigned Sema::getOpenMPNestingLevel() const {
2309 assert(getLangOpts().OpenMP);
2310 return DSAStack->getNestingLevel();
2313 bool Sema::isInOpenMPTaskUntiedContext() const {
2314 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2315 DSAStack->isUntiedRegion();
2318 bool Sema::isInOpenMPTargetExecutionDirective() const {
2319 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2320 !DSAStack->isClauseParsingMode()) ||
2321 DSAStack->hasDirective(
2322 [](OpenMPDirectiveKind K, const DeclarationNameInfo &,
2323 SourceLocation) -> bool {
2324 return isOpenMPTargetExecutionDirective(K);
2326 false);
2329 bool Sema::isOpenMPRebuildMemberExpr(ValueDecl *D) {
2330 // Only rebuild for Field.
2331 if (!dyn_cast<FieldDecl>(D))
2332 return false;
2333 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2335 [](OpenMPClauseKind C, bool AppliedToPointee,
2336 DefaultDataSharingAttributes DefaultAttr) {
2337 return isOpenMPPrivate(C) && !AppliedToPointee &&
2338 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2340 [](OpenMPDirectiveKind) { return true; },
2341 DSAStack->isClauseParsingMode());
2342 if (DVarPrivate.CKind != OMPC_unknown)
2343 return true;
2344 return false;
2347 static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
2348 Expr *CaptureExpr, bool WithInit,
2349 DeclContext *CurContext,
2350 bool AsExpression);
2352 VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo,
2353 unsigned StopAt) {
2354 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2355 D = getCanonicalDecl(D);
2357 auto *VD = dyn_cast<VarDecl>(D);
2358 // Do not capture constexpr variables.
2359 if (VD && VD->isConstexpr())
2360 return nullptr;
2362 // If we want to determine whether the variable should be captured from the
2363 // perspective of the current capturing scope, and we've already left all the
2364 // capturing scopes of the top directive on the stack, check from the
2365 // perspective of its parent directive (if any) instead.
2366 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2367 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2369 // If we are attempting to capture a global variable in a directive with
2370 // 'target' we return true so that this global is also mapped to the device.
2372 if (VD && !VD->hasLocalStorage() &&
2373 (getCurCapturedRegion() || getCurBlock() || getCurLambda())) {
2374 if (isInOpenMPTargetExecutionDirective()) {
2375 DSAStackTy::DSAVarData DVarTop =
2376 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2377 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2378 return VD;
2379 // If the declaration is enclosed in a 'declare target' directive,
2380 // then it should not be captured.
2382 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2383 return nullptr;
2384 CapturedRegionScopeInfo *CSI = nullptr;
2385 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2386 llvm::reverse(FunctionScopes),
2387 CheckScopeInfo ? (FunctionScopes.size() - (StopAt + 1)) : 0)) {
2388 if (!isa<CapturingScopeInfo>(FSI))
2389 return nullptr;
2390 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2391 if (RSI->CapRegionKind == CR_OpenMP) {
2392 CSI = RSI;
2393 break;
2396 assert(CSI && "Failed to find CapturedRegionScopeInfo");
2397 SmallVector<OpenMPDirectiveKind, 4> Regions;
2398 getOpenMPCaptureRegions(Regions,
2399 DSAStack->getDirective(CSI->OpenMPLevel));
2400 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2401 return VD;
2403 if (isInOpenMPDeclareTargetContext()) {
2404 // Try to mark variable as declare target if it is used in capturing
2405 // regions.
2406 if (LangOpts.OpenMP <= 45 &&
2407 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2408 checkDeclIsAllowedInOpenMPTarget(nullptr, VD);
2409 return nullptr;
2413 if (CheckScopeInfo) {
2414 bool OpenMPFound = false;
2415 for (unsigned I = StopAt + 1; I > 0; --I) {
2416 FunctionScopeInfo *FSI = FunctionScopes[I - 1];
2417 if (!isa<CapturingScopeInfo>(FSI))
2418 return nullptr;
2419 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2420 if (RSI->CapRegionKind == CR_OpenMP) {
2421 OpenMPFound = true;
2422 break;
2425 if (!OpenMPFound)
2426 return nullptr;
2429 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2430 (!DSAStack->isClauseParsingMode() ||
2431 DSAStack->getParentDirective() != OMPD_unknown)) {
2432 auto &&Info = DSAStack->isLoopControlVariable(D);
2433 if (Info.first ||
2434 (VD && VD->hasLocalStorage() &&
2435 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2436 (VD && DSAStack->isForceVarCapturing()))
2437 return VD ? VD : Info.second;
2438 DSAStackTy::DSAVarData DVarTop =
2439 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2440 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) &&
2441 (!VD || VD->hasLocalStorage() || !DVarTop.AppliedToPointee))
2442 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2443 // Threadprivate variables must not be captured.
2444 if (isOpenMPThreadPrivate(DVarTop.CKind))
2445 return nullptr;
2446 // The variable is not private or it is the variable in the directive with
2447 // default(none) clause and not used in any clause.
2448 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2450 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2451 return isOpenMPPrivate(C) && !AppliedToPointee;
2453 [](OpenMPDirectiveKind) { return true; },
2454 DSAStack->isClauseParsingMode());
2455 // Global shared must not be captured.
2456 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2457 ((DSAStack->getDefaultDSA() != DSA_none &&
2458 DSAStack->getDefaultDSA() != DSA_private &&
2459 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2460 DVarTop.CKind == OMPC_shared))
2461 return nullptr;
2462 auto *FD = dyn_cast<FieldDecl>(D);
2463 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2464 !DVarPrivate.PrivateCopy) {
2465 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2467 [](OpenMPClauseKind C, bool AppliedToPointee,
2468 DefaultDataSharingAttributes DefaultAttr) {
2469 return isOpenMPPrivate(C) && !AppliedToPointee &&
2470 (DefaultAttr == DSA_firstprivate ||
2471 DefaultAttr == DSA_private);
2473 [](OpenMPDirectiveKind) { return true; },
2474 DSAStack->isClauseParsingMode());
2475 if (DVarPrivate.CKind == OMPC_unknown)
2476 return nullptr;
2478 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2479 if (VD)
2480 return VD;
2481 if (getCurrentThisType().isNull())
2482 return nullptr;
2483 Expr *ThisExpr = BuildCXXThisExpr(SourceLocation(), getCurrentThisType(),
2484 /*IsImplicit=*/true);
2485 const CXXScopeSpec CS = CXXScopeSpec();
2486 Expr *ME = BuildMemberExpr(ThisExpr, /*IsArrow=*/true, SourceLocation(),
2487 NestedNameSpecifierLoc(), SourceLocation(), FD,
2488 DeclAccessPair::make(FD, FD->getAccess()),
2489 /*HadMultipleCandidates=*/false,
2490 DeclarationNameInfo(), FD->getType(),
2491 VK_LValue, OK_Ordinary);
2492 OMPCapturedExprDecl *CD = buildCaptureDecl(
2493 *this, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private,
2494 CurContext->getParent(), /*AsExpression=*/false);
2495 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2496 *this, CD, CD->getType().getNonReferenceType(), SourceLocation());
2497 VD = cast<VarDecl>(VDPrivateRefExpr->getDecl());
2498 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2499 return VD;
2501 if (DVarPrivate.CKind != OMPC_unknown ||
2502 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2503 DSAStack->getDefaultDSA() == DSA_private ||
2504 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2505 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2507 return nullptr;
2510 void Sema::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2511 unsigned Level) const {
2512 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2515 void Sema::startOpenMPLoop() {
2516 assert(LangOpts.OpenMP && "OpenMP must be enabled.");
2517 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2518 DSAStack->loopInit();
2521 void Sema::startOpenMPCXXRangeFor() {
2522 assert(LangOpts.OpenMP && "OpenMP must be enabled.");
2523 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2524 DSAStack->resetPossibleLoopCounter();
2525 DSAStack->loopStart();
2529 OpenMPClauseKind Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level,
2530 unsigned CapLevel) const {
2531 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2532 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2533 (!DSAStack->isClauseParsingMode() ||
2534 DSAStack->getParentDirective() != OMPD_unknown)) {
2535 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2537 [](OpenMPClauseKind C, bool AppliedToPointee,
2538 DefaultDataSharingAttributes DefaultAttr) {
2539 return isOpenMPPrivate(C) && !AppliedToPointee &&
2540 DefaultAttr == DSA_private;
2542 [](OpenMPDirectiveKind) { return true; },
2543 DSAStack->isClauseParsingMode());
2544 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) &&
2545 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) &&
2546 !DSAStack->isLoopControlVariable(D).first)
2547 return OMPC_private;
2549 if (DSAStack->hasExplicitDirective(isOpenMPTaskingDirective, Level)) {
2550 bool IsTriviallyCopyable =
2551 D->getType().getNonReferenceType().isTriviallyCopyableType(Context) &&
2552 !D->getType()
2553 .getNonReferenceType()
2554 .getCanonicalType()
2555 ->getAsCXXRecordDecl();
2556 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2557 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
2558 getOpenMPCaptureRegions(CaptureRegions, DKind);
2559 if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) &&
2560 (IsTriviallyCopyable ||
2561 !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) {
2562 if (DSAStack->hasExplicitDSA(
2564 [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2565 Level, /*NotLastprivate=*/true))
2566 return OMPC_firstprivate;
2567 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2568 if (DVar.CKind != OMPC_shared &&
2569 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2570 DSAStack->addImplicitTaskFirstprivate(Level, D);
2571 return OMPC_firstprivate;
2575 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) &&
2576 !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) {
2577 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2578 DSAStack->resetPossibleLoopCounter(D);
2579 DSAStack->loopStart();
2580 return OMPC_private;
2582 if ((DSAStack->getPossiblyLoopCunter() == D->getCanonicalDecl() ||
2583 DSAStack->isLoopControlVariable(D).first) &&
2584 !DSAStack->hasExplicitDSA(
2585 D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2586 Level) &&
2587 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2588 return OMPC_private;
2590 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2591 if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
2592 DSAStack->isForceVarCapturing() &&
2593 !DSAStack->hasExplicitDSA(
2594 D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2595 Level))
2596 return OMPC_private;
2598 // User-defined allocators are private since they must be defined in the
2599 // context of target region.
2600 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) &&
2601 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2602 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2603 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2604 return OMPC_private;
2605 return (DSAStack->hasExplicitDSA(
2606 D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2607 Level) ||
2608 (DSAStack->isClauseParsingMode() &&
2609 DSAStack->getClauseParsingMode() == OMPC_private) ||
2610 // Consider taskgroup reduction descriptor variable a private
2611 // to avoid possible capture in the region.
2612 (DSAStack->hasExplicitDirective(
2613 [](OpenMPDirectiveKind K) {
2614 return K == OMPD_taskgroup ||
2615 ((isOpenMPParallelDirective(K) ||
2616 isOpenMPWorksharingDirective(K)) &&
2617 !isOpenMPSimdDirective(K));
2619 Level) &&
2620 DSAStack->isTaskgroupReductionRef(D, Level)))
2621 ? OMPC_private
2622 : OMPC_unknown;
2625 void Sema::setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D,
2626 unsigned Level) {
2627 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2628 D = getCanonicalDecl(D);
2629 OpenMPClauseKind OMPC = OMPC_unknown;
2630 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2631 const unsigned NewLevel = I - 1;
2632 if (DSAStack->hasExplicitDSA(
2634 [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2635 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2636 OMPC = K;
2637 return true;
2639 return false;
2641 NewLevel))
2642 break;
2643 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2644 D, NewLevel,
2645 [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
2646 OpenMPClauseKind) { return true; })) {
2647 OMPC = OMPC_map;
2648 break;
2650 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2651 NewLevel)) {
2652 OMPC = OMPC_map;
2653 if (DSAStack->mustBeFirstprivateAtLevel(
2654 NewLevel, getVariableCategoryFromDecl(LangOpts, D)))
2655 OMPC = OMPC_firstprivate;
2656 break;
2659 if (OMPC != OMPC_unknown)
2660 FD->addAttr(OMPCaptureKindAttr::CreateImplicit(Context, unsigned(OMPC)));
2663 bool Sema::isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level,
2664 unsigned CaptureLevel) const {
2665 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2666 // Return true if the current level is no longer enclosed in a target region.
2668 SmallVector<OpenMPDirectiveKind, 4> Regions;
2669 getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level));
2670 const auto *VD = dyn_cast<VarDecl>(D);
2671 return VD && !VD->hasLocalStorage() &&
2672 DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2673 Level) &&
2674 Regions[CaptureLevel] != OMPD_task;
2677 bool Sema::isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level,
2678 unsigned CaptureLevel) const {
2679 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2680 // Return true if the current level is no longer enclosed in a target region.
2682 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2683 if (!VD->hasLocalStorage()) {
2684 if (isInOpenMPTargetExecutionDirective())
2685 return true;
2686 DSAStackTy::DSAVarData TopDVar =
2687 DSAStack->getTopDSA(D, /*FromParent=*/false);
2688 unsigned NumLevels =
2689 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2690 if (Level == 0)
2691 // non-file scope static variale with default(firstprivate)
2692 // should be gloabal captured.
2693 return (NumLevels == CaptureLevel + 1 &&
2694 (TopDVar.CKind != OMPC_shared ||
2695 DSAStack->getDefaultDSA() == DSA_firstprivate));
2696 do {
2697 --Level;
2698 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2699 if (DVar.CKind != OMPC_shared)
2700 return true;
2701 } while (Level > 0);
2704 return true;
2707 void Sema::DestroyDataSharingAttributesStack() { delete DSAStack; }
2709 void Sema::ActOnOpenMPBeginDeclareVariant(SourceLocation Loc,
2710 OMPTraitInfo &TI) {
2711 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2714 void Sema::ActOnOpenMPEndDeclareVariant() {
2715 assert(isInOpenMPDeclareVariantScope() &&
2716 "Not in OpenMP declare variant scope!");
2718 OMPDeclareVariantScopes.pop_back();
2721 void Sema::finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller,
2722 const FunctionDecl *Callee,
2723 SourceLocation Loc) {
2724 assert(LangOpts.OpenMP && "Expected OpenMP compilation mode.");
2725 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2726 OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
2727 // Ignore host functions during device analyzis.
2728 if (LangOpts.OpenMPIsTargetDevice &&
2729 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2730 return;
2731 // Ignore nohost functions during host analyzis.
2732 if (!LangOpts.OpenMPIsTargetDevice && DevTy &&
2733 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2734 return;
2735 const FunctionDecl *FD = Callee->getMostRecentDecl();
2736 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2737 if (LangOpts.OpenMPIsTargetDevice && DevTy &&
2738 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2739 // Diagnose host function called during device codegen.
2740 StringRef HostDevTy =
2741 getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
2742 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2743 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2744 diag::note_omp_marked_device_type_here)
2745 << HostDevTy;
2746 return;
2748 if (!LangOpts.OpenMPIsTargetDevice && !LangOpts.OpenMPOffloadMandatory &&
2749 DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2750 // In OpenMP 5.2 or later, if the function has a host variant then allow
2751 // that to be called instead
2752 auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2753 for (OMPDeclareVariantAttr *A :
2754 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2755 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2756 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2757 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2758 OMPDeclareTargetDeclAttr::getDeviceType(
2759 VariantFD->getMostRecentDecl());
2760 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2761 return true;
2763 return false;
2765 if (getLangOpts().OpenMP >= 52 &&
2766 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2767 return;
2768 // Diagnose nohost function called during host codegen.
2769 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2770 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2771 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2772 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2773 diag::note_omp_marked_device_type_here)
2774 << NoHostDevTy;
2778 void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
2779 const DeclarationNameInfo &DirName,
2780 Scope *CurScope, SourceLocation Loc) {
2781 DSAStack->push(DKind, DirName, CurScope, Loc);
2782 PushExpressionEvaluationContext(
2783 ExpressionEvaluationContext::PotentiallyEvaluated);
2786 void Sema::StartOpenMPClause(OpenMPClauseKind K) {
2787 DSAStack->setClauseParsingMode(K);
2790 void Sema::EndOpenMPClause() {
2791 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2792 CleanupVarDeclMarking();
2795 static std::pair<ValueDecl *, bool>
2796 getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2797 SourceRange &ERange, bool AllowArraySection = false,
2798 StringRef DiagType = "");
2800 /// Check consistency of the reduction clauses.
2801 static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2802 ArrayRef<OMPClause *> Clauses) {
2803 bool InscanFound = false;
2804 SourceLocation InscanLoc;
2805 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2806 // A reduction clause without the inscan reduction-modifier may not appear on
2807 // a construct on which a reduction clause with the inscan reduction-modifier
2808 // appears.
2809 for (OMPClause *C : Clauses) {
2810 if (C->getClauseKind() != OMPC_reduction)
2811 continue;
2812 auto *RC = cast<OMPReductionClause>(C);
2813 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2814 InscanFound = true;
2815 InscanLoc = RC->getModifierLoc();
2816 continue;
2818 if (RC->getModifier() == OMPC_REDUCTION_task) {
2819 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2820 // A reduction clause with the task reduction-modifier may only appear on
2821 // a parallel construct, a worksharing construct or a combined or
2822 // composite construct for which any of the aforementioned constructs is a
2823 // constituent construct and simd or loop are not constituent constructs.
2824 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2825 if (!(isOpenMPParallelDirective(CurDir) ||
2826 isOpenMPWorksharingDirective(CurDir)) ||
2827 isOpenMPSimdDirective(CurDir))
2828 S.Diag(RC->getModifierLoc(),
2829 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2830 continue;
2833 if (InscanFound) {
2834 for (OMPClause *C : Clauses) {
2835 if (C->getClauseKind() != OMPC_reduction)
2836 continue;
2837 auto *RC = cast<OMPReductionClause>(C);
2838 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2839 S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2840 ? RC->getBeginLoc()
2841 : RC->getModifierLoc(),
2842 diag::err_omp_inscan_reduction_expected);
2843 S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2844 continue;
2846 for (Expr *Ref : RC->varlists()) {
2847 assert(Ref && "NULL expr in OpenMP nontemporal clause.");
2848 SourceLocation ELoc;
2849 SourceRange ERange;
2850 Expr *SimpleRefExpr = Ref;
2851 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2852 /*AllowArraySection=*/true);
2853 ValueDecl *D = Res.first;
2854 if (!D)
2855 continue;
2856 if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2857 S.Diag(Ref->getExprLoc(),
2858 diag::err_omp_reduction_not_inclusive_exclusive)
2859 << Ref->getSourceRange();
2866 static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2867 ArrayRef<OMPClause *> Clauses);
2868 static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2869 bool WithInit);
2871 static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2872 const ValueDecl *D,
2873 const DSAStackTy::DSAVarData &DVar,
2874 bool IsLoopIterVar = false);
2876 void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
2877 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2878 // A variable of class type (or array thereof) that appears in a lastprivate
2879 // clause requires an accessible, unambiguous default constructor for the
2880 // class type, unless the list item is also specified in a firstprivate
2881 // clause.
2882 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
2883 for (OMPClause *C : D->clauses()) {
2884 if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
2885 SmallVector<Expr *, 8> PrivateCopies;
2886 for (Expr *DE : Clause->varlists()) {
2887 if (DE->isValueDependent() || DE->isTypeDependent()) {
2888 PrivateCopies.push_back(nullptr);
2889 continue;
2891 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2892 auto *VD = cast<VarDecl>(DRE->getDecl());
2893 QualType Type = VD->getType().getNonReferenceType();
2894 const DSAStackTy::DSAVarData DVar =
2895 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2896 if (DVar.CKind == OMPC_lastprivate) {
2897 // Generate helper private variable and initialize it with the
2898 // default value. The address of the original variable is replaced
2899 // by the address of the new private variable in CodeGen. This new
2900 // variable is not added to IdResolver, so the code in the OpenMP
2901 // region uses original variable for proper diagnostics.
2902 VarDecl *VDPrivate = buildVarDecl(
2903 *this, DE->getExprLoc(), Type.getUnqualifiedType(),
2904 VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
2905 ActOnUninitializedDecl(VDPrivate);
2906 if (VDPrivate->isInvalidDecl()) {
2907 PrivateCopies.push_back(nullptr);
2908 continue;
2910 PrivateCopies.push_back(buildDeclRefExpr(
2911 *this, VDPrivate, DE->getType(), DE->getExprLoc()));
2912 } else {
2913 // The variable is also a firstprivate, so initialization sequence
2914 // for private copy is generated already.
2915 PrivateCopies.push_back(nullptr);
2918 Clause->setPrivateCopies(PrivateCopies);
2919 continue;
2921 // Finalize nontemporal clause by handling private copies, if any.
2922 if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) {
2923 SmallVector<Expr *, 8> PrivateRefs;
2924 for (Expr *RefExpr : Clause->varlists()) {
2925 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
2926 SourceLocation ELoc;
2927 SourceRange ERange;
2928 Expr *SimpleRefExpr = RefExpr;
2929 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
2930 if (Res.second)
2931 // It will be analyzed later.
2932 PrivateRefs.push_back(RefExpr);
2933 ValueDecl *D = Res.first;
2934 if (!D)
2935 continue;
2937 const DSAStackTy::DSAVarData DVar =
2938 DSAStack->getTopDSA(D, /*FromParent=*/false);
2939 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2940 : SimpleRefExpr);
2942 Clause->setPrivateRefs(PrivateRefs);
2943 continue;
2945 if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) {
2946 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
2947 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
2948 auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts());
2949 if (!DRE)
2950 continue;
2951 ValueDecl *VD = DRE->getDecl();
2952 if (!VD || !isa<VarDecl>(VD))
2953 continue;
2954 DSAStackTy::DSAVarData DVar =
2955 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2956 // OpenMP [2.12.5, target Construct]
2957 // Memory allocators that appear in a uses_allocators clause cannot
2958 // appear in other data-sharing attribute clauses or data-mapping
2959 // attribute clauses in the same construct.
2960 Expr *MapExpr = nullptr;
2961 if (DVar.RefExpr ||
2962 DSAStack->checkMappableExprComponentListsForDecl(
2963 VD, /*CurrentRegionOnly=*/true,
2964 [VD, &MapExpr](
2965 OMPClauseMappableExprCommon::MappableExprComponentListRef
2966 MapExprComponents,
2967 OpenMPClauseKind C) {
2968 auto MI = MapExprComponents.rbegin();
2969 auto ME = MapExprComponents.rend();
2970 if (MI != ME &&
2971 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
2972 VD->getCanonicalDecl()) {
2973 MapExpr = MI->getAssociatedExpression();
2974 return true;
2976 return false;
2977 })) {
2978 Diag(D.Allocator->getExprLoc(),
2979 diag::err_omp_allocator_used_in_clauses)
2980 << D.Allocator->getSourceRange();
2981 if (DVar.RefExpr)
2982 reportOriginalDsa(*this, DSAStack, VD, DVar);
2983 else
2984 Diag(MapExpr->getExprLoc(), diag::note_used_here)
2985 << MapExpr->getSourceRange();
2988 continue;
2991 // Check allocate clauses.
2992 if (!CurContext->isDependentContext())
2993 checkAllocateClauses(*this, DSAStack, D->clauses());
2994 checkReductionClauses(*this, DSAStack, D->clauses());
2997 DSAStack->pop();
2998 DiscardCleanupsInEvaluationContext();
2999 PopExpressionEvaluationContext();
3002 static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
3003 Expr *NumIterations, Sema &SemaRef,
3004 Scope *S, DSAStackTy *Stack);
3006 namespace {
3008 class VarDeclFilterCCC final : public CorrectionCandidateCallback {
3009 private:
3010 Sema &SemaRef;
3012 public:
3013 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3014 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3015 NamedDecl *ND = Candidate.getCorrectionDecl();
3016 if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3017 return VD->hasGlobalStorage() &&
3018 SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3019 SemaRef.getCurScope());
3021 return false;
3024 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3025 return std::make_unique<VarDeclFilterCCC>(*this);
3029 class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3030 private:
3031 Sema &SemaRef;
3033 public:
3034 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3035 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3036 NamedDecl *ND = Candidate.getCorrectionDecl();
3037 if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
3038 isa<FunctionDecl>(ND))) {
3039 return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3040 SemaRef.getCurScope());
3042 return false;
3045 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3046 return std::make_unique<VarOrFuncDeclFilterCCC>(*this);
3050 } // namespace
3052 ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
3053 CXXScopeSpec &ScopeSpec,
3054 const DeclarationNameInfo &Id,
3055 OpenMPDirectiveKind Kind) {
3056 LookupResult Lookup(*this, Id, LookupOrdinaryName);
3057 LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
3059 if (Lookup.isAmbiguous())
3060 return ExprError();
3062 VarDecl *VD;
3063 if (!Lookup.isSingleResult()) {
3064 VarDeclFilterCCC CCC(*this);
3065 if (TypoCorrection Corrected =
3066 CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr, CCC,
3067 CTK_ErrorRecovery)) {
3068 diagnoseTypo(Corrected,
3069 PDiag(Lookup.empty()
3070 ? diag::err_undeclared_var_use_suggest
3071 : diag::err_omp_expected_var_arg_suggest)
3072 << Id.getName());
3073 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3074 } else {
3075 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
3076 : diag::err_omp_expected_var_arg)
3077 << Id.getName();
3078 return ExprError();
3080 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3081 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3082 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3083 return ExprError();
3085 Lookup.suppressDiagnostics();
3087 // OpenMP [2.9.2, Syntax, C/C++]
3088 // Variables must be file-scope, namespace-scope, or static block-scope.
3089 if (Kind == OMPD_threadprivate && !VD->hasGlobalStorage()) {
3090 Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3091 << getOpenMPDirectiveName(Kind) << !VD->isStaticLocal();
3092 bool IsDecl =
3093 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3094 Diag(VD->getLocation(),
3095 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3096 << VD;
3097 return ExprError();
3100 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3101 NamedDecl *ND = CanonicalVD;
3102 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3103 // A threadprivate directive for file-scope variables must appear outside
3104 // any definition or declaration.
3105 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3106 !getCurLexicalContext()->isTranslationUnit()) {
3107 Diag(Id.getLoc(), diag::err_omp_var_scope)
3108 << getOpenMPDirectiveName(Kind) << VD;
3109 bool IsDecl =
3110 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3111 Diag(VD->getLocation(),
3112 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3113 << VD;
3114 return ExprError();
3116 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3117 // A threadprivate directive for static class member variables must appear
3118 // in the class definition, in the same scope in which the member
3119 // variables are declared.
3120 if (CanonicalVD->isStaticDataMember() &&
3121 !CanonicalVD->getDeclContext()->Equals(getCurLexicalContext())) {
3122 Diag(Id.getLoc(), diag::err_omp_var_scope)
3123 << getOpenMPDirectiveName(Kind) << VD;
3124 bool IsDecl =
3125 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3126 Diag(VD->getLocation(),
3127 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3128 << VD;
3129 return ExprError();
3131 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3132 // A threadprivate directive for namespace-scope variables must appear
3133 // outside any definition or declaration other than the namespace
3134 // definition itself.
3135 if (CanonicalVD->getDeclContext()->isNamespace() &&
3136 (!getCurLexicalContext()->isFileContext() ||
3137 !getCurLexicalContext()->Encloses(CanonicalVD->getDeclContext()))) {
3138 Diag(Id.getLoc(), diag::err_omp_var_scope)
3139 << getOpenMPDirectiveName(Kind) << VD;
3140 bool IsDecl =
3141 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3142 Diag(VD->getLocation(),
3143 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3144 << VD;
3145 return ExprError();
3147 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3148 // A threadprivate directive for static block-scope variables must appear
3149 // in the scope of the variable and not in a nested scope.
3150 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3151 !isDeclInScope(ND, getCurLexicalContext(), CurScope)) {
3152 Diag(Id.getLoc(), diag::err_omp_var_scope)
3153 << getOpenMPDirectiveName(Kind) << VD;
3154 bool IsDecl =
3155 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3156 Diag(VD->getLocation(),
3157 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3158 << VD;
3159 return ExprError();
3162 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3163 // A threadprivate directive must lexically precede all references to any
3164 // of the variables in its list.
3165 if (Kind == OMPD_threadprivate && VD->isUsed() &&
3166 !DSAStack->isThreadPrivate(VD)) {
3167 Diag(Id.getLoc(), diag::err_omp_var_used)
3168 << getOpenMPDirectiveName(Kind) << VD;
3169 return ExprError();
3172 QualType ExprType = VD->getType().getNonReferenceType();
3173 return DeclRefExpr::Create(Context, NestedNameSpecifierLoc(),
3174 SourceLocation(), VD,
3175 /*RefersToEnclosingVariableOrCapture=*/false,
3176 Id.getLoc(), ExprType, VK_LValue);
3179 Sema::DeclGroupPtrTy
3180 Sema::ActOnOpenMPThreadprivateDirective(SourceLocation Loc,
3181 ArrayRef<Expr *> VarList) {
3182 if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
3183 CurContext->addDecl(D);
3184 return DeclGroupPtrTy::make(DeclGroupRef(D));
3186 return nullptr;
3189 namespace {
3190 class LocalVarRefChecker final
3191 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3192 Sema &SemaRef;
3194 public:
3195 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3196 if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3197 if (VD->hasLocalStorage()) {
3198 SemaRef.Diag(E->getBeginLoc(),
3199 diag::err_omp_local_var_in_threadprivate_init)
3200 << E->getSourceRange();
3201 SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3202 << VD << VD->getSourceRange();
3203 return true;
3206 return false;
3208 bool VisitStmt(const Stmt *S) {
3209 for (const Stmt *Child : S->children()) {
3210 if (Child && Visit(Child))
3211 return true;
3213 return false;
3215 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3217 } // namespace
3219 OMPThreadPrivateDecl *
3220 Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) {
3221 SmallVector<Expr *, 8> Vars;
3222 for (Expr *RefExpr : VarList) {
3223 auto *DE = cast<DeclRefExpr>(RefExpr);
3224 auto *VD = cast<VarDecl>(DE->getDecl());
3225 SourceLocation ILoc = DE->getExprLoc();
3227 // Mark variable as used.
3228 VD->setReferenced();
3229 VD->markUsed(Context);
3231 QualType QType = VD->getType();
3232 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3233 // It will be analyzed later.
3234 Vars.push_back(DE);
3235 continue;
3238 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3239 // A threadprivate variable must not have an incomplete type.
3240 if (RequireCompleteType(ILoc, VD->getType(),
3241 diag::err_omp_threadprivate_incomplete_type)) {
3242 continue;
3245 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3246 // A threadprivate variable must not have a reference type.
3247 if (VD->getType()->isReferenceType()) {
3248 Diag(ILoc, diag::err_omp_ref_type_arg)
3249 << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType();
3250 bool IsDecl =
3251 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3252 Diag(VD->getLocation(),
3253 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3254 << VD;
3255 continue;
3258 // Check if this is a TLS variable. If TLS is not being supported, produce
3259 // the corresponding diagnostic.
3260 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3261 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3262 getLangOpts().OpenMPUseTLS &&
3263 getASTContext().getTargetInfo().isTLSSupported())) ||
3264 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3265 !VD->isLocalVarDecl())) {
3266 Diag(ILoc, diag::err_omp_var_thread_local)
3267 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3268 bool IsDecl =
3269 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3270 Diag(VD->getLocation(),
3271 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3272 << VD;
3273 continue;
3276 // Check if initial value of threadprivate variable reference variable with
3277 // local storage (it is not supported by runtime).
3278 if (const Expr *Init = VD->getAnyInitializer()) {
3279 LocalVarRefChecker Checker(*this);
3280 if (Checker.Visit(Init))
3281 continue;
3284 Vars.push_back(RefExpr);
3285 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3286 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3287 Context, SourceRange(Loc, Loc)));
3288 if (ASTMutationListener *ML = Context.getASTMutationListener())
3289 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3291 OMPThreadPrivateDecl *D = nullptr;
3292 if (!Vars.empty()) {
3293 D = OMPThreadPrivateDecl::Create(Context, getCurLexicalContext(), Loc,
3294 Vars);
3295 D->setAccess(AS_public);
3297 return D;
3300 static OMPAllocateDeclAttr::AllocatorTypeTy
3301 getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3302 if (!Allocator)
3303 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3304 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3305 Allocator->isInstantiationDependent() ||
3306 Allocator->containsUnexpandedParameterPack())
3307 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3308 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3309 llvm::FoldingSetNodeID AEId;
3310 const Expr *AE = Allocator->IgnoreParenImpCasts();
3311 AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3312 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3313 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3314 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3315 llvm::FoldingSetNodeID DAEId;
3316 DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(),
3317 /*Canonical=*/true);
3318 if (AEId == DAEId) {
3319 AllocatorKindRes = AllocatorKind;
3320 break;
3323 return AllocatorKindRes;
3326 static bool checkPreviousOMPAllocateAttribute(
3327 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3328 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3329 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3330 return false;
3331 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3332 Expr *PrevAllocator = A->getAllocator();
3333 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3334 getAllocatorKind(S, Stack, PrevAllocator);
3335 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3336 if (AllocatorsMatch &&
3337 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3338 Allocator && PrevAllocator) {
3339 const Expr *AE = Allocator->IgnoreParenImpCasts();
3340 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3341 llvm::FoldingSetNodeID AEId, PAEId;
3342 AE->Profile(AEId, S.Context, /*Canonical=*/true);
3343 PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3344 AllocatorsMatch = AEId == PAEId;
3346 if (!AllocatorsMatch) {
3347 SmallString<256> AllocatorBuffer;
3348 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3349 if (Allocator)
3350 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3351 SmallString<256> PrevAllocatorBuffer;
3352 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3353 if (PrevAllocator)
3354 PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3355 S.getPrintingPolicy());
3357 SourceLocation AllocatorLoc =
3358 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3359 SourceRange AllocatorRange =
3360 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3361 SourceLocation PrevAllocatorLoc =
3362 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3363 SourceRange PrevAllocatorRange =
3364 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3365 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3366 << (Allocator ? 1 : 0) << AllocatorStream.str()
3367 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3368 << AllocatorRange;
3369 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3370 << PrevAllocatorRange;
3371 return true;
3373 return false;
3376 static void
3377 applyOMPAllocateAttribute(Sema &S, VarDecl *VD,
3378 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3379 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3380 if (VD->hasAttr<OMPAllocateDeclAttr>())
3381 return;
3382 if (Alignment &&
3383 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3384 Alignment->isInstantiationDependent() ||
3385 Alignment->containsUnexpandedParameterPack()))
3386 // Apply later when we have a usable value.
3387 return;
3388 if (Allocator &&
3389 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3390 Allocator->isInstantiationDependent() ||
3391 Allocator->containsUnexpandedParameterPack()))
3392 return;
3393 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3394 Allocator, Alignment, SR);
3395 VD->addAttr(A);
3396 if (ASTMutationListener *ML = S.Context.getASTMutationListener())
3397 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3400 Sema::DeclGroupPtrTy
3401 Sema::ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef<Expr *> VarList,
3402 ArrayRef<OMPClause *> Clauses,
3403 DeclContext *Owner) {
3404 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3405 Expr *Alignment = nullptr;
3406 Expr *Allocator = nullptr;
3407 if (Clauses.empty()) {
3408 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3409 // allocate directives that appear in a target region must specify an
3410 // allocator clause unless a requires directive with the dynamic_allocators
3411 // clause is present in the same compilation unit.
3412 if (LangOpts.OpenMPIsTargetDevice &&
3413 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3414 targetDiag(Loc, diag::err_expected_allocator_clause);
3415 } else {
3416 for (const OMPClause *C : Clauses)
3417 if (const auto *AC = dyn_cast<OMPAllocatorClause>(C))
3418 Allocator = AC->getAllocator();
3419 else if (const auto *AC = dyn_cast<OMPAlignClause>(C))
3420 Alignment = AC->getAlignment();
3421 else
3422 llvm_unreachable("Unexpected clause on allocate directive");
3424 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3425 getAllocatorKind(*this, DSAStack, Allocator);
3426 SmallVector<Expr *, 8> Vars;
3427 for (Expr *RefExpr : VarList) {
3428 auto *DE = cast<DeclRefExpr>(RefExpr);
3429 auto *VD = cast<VarDecl>(DE->getDecl());
3431 // Check if this is a TLS variable or global register.
3432 if (VD->getTLSKind() != VarDecl::TLS_None ||
3433 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3434 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3435 !VD->isLocalVarDecl()))
3436 continue;
3438 // If the used several times in the allocate directive, the same allocator
3439 // must be used.
3440 if (checkPreviousOMPAllocateAttribute(*this, DSAStack, RefExpr, VD,
3441 AllocatorKind, Allocator))
3442 continue;
3444 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3445 // If a list item has a static storage type, the allocator expression in the
3446 // allocator clause must be a constant expression that evaluates to one of
3447 // the predefined memory allocator values.
3448 if (Allocator && VD->hasGlobalStorage()) {
3449 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3450 Diag(Allocator->getExprLoc(),
3451 diag::err_omp_expected_predefined_allocator)
3452 << Allocator->getSourceRange();
3453 bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
3454 VarDecl::DeclarationOnly;
3455 Diag(VD->getLocation(),
3456 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3457 << VD;
3458 continue;
3462 Vars.push_back(RefExpr);
3463 applyOMPAllocateAttribute(*this, VD, AllocatorKind, Allocator, Alignment,
3464 DE->getSourceRange());
3466 if (Vars.empty())
3467 return nullptr;
3468 if (!Owner)
3469 Owner = getCurLexicalContext();
3470 auto *D = OMPAllocateDecl::Create(Context, Owner, Loc, Vars, Clauses);
3471 D->setAccess(AS_public);
3472 Owner->addDecl(D);
3473 return DeclGroupPtrTy::make(DeclGroupRef(D));
3476 Sema::DeclGroupPtrTy
3477 Sema::ActOnOpenMPRequiresDirective(SourceLocation Loc,
3478 ArrayRef<OMPClause *> ClauseList) {
3479 OMPRequiresDecl *D = nullptr;
3480 if (!CurContext->isFileContext()) {
3481 Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3482 } else {
3483 D = CheckOMPRequiresDecl(Loc, ClauseList);
3484 if (D) {
3485 CurContext->addDecl(D);
3486 DSAStack->addRequiresDecl(D);
3489 return DeclGroupPtrTy::make(DeclGroupRef(D));
3492 void Sema::ActOnOpenMPAssumesDirective(SourceLocation Loc,
3493 OpenMPDirectiveKind DKind,
3494 ArrayRef<std::string> Assumptions,
3495 bool SkippedClauses) {
3496 if (!SkippedClauses && Assumptions.empty())
3497 Diag(Loc, diag::err_omp_no_clause_for_directive)
3498 << llvm::omp::getAllAssumeClauseOptions()
3499 << llvm::omp::getOpenMPDirectiveName(DKind);
3501 auto *AA = AssumptionAttr::Create(Context, llvm::join(Assumptions, ","), Loc);
3502 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3503 OMPAssumeScoped.push_back(AA);
3504 return;
3507 // Global assumes without assumption clauses are ignored.
3508 if (Assumptions.empty())
3509 return;
3511 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3512 "Unexpected omp assumption directive!");
3513 OMPAssumeGlobal.push_back(AA);
3515 // The OMPAssumeGlobal scope above will take care of new declarations but
3516 // we also want to apply the assumption to existing ones, e.g., to
3517 // declarations in included headers. To this end, we traverse all existing
3518 // declaration contexts and annotate function declarations here.
3519 SmallVector<DeclContext *, 8> DeclContexts;
3520 auto *Ctx = CurContext;
3521 while (Ctx->getLexicalParent())
3522 Ctx = Ctx->getLexicalParent();
3523 DeclContexts.push_back(Ctx);
3524 while (!DeclContexts.empty()) {
3525 DeclContext *DC = DeclContexts.pop_back_val();
3526 for (auto *SubDC : DC->decls()) {
3527 if (SubDC->isInvalidDecl())
3528 continue;
3529 if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3530 DeclContexts.push_back(CTD->getTemplatedDecl());
3531 llvm::append_range(DeclContexts, CTD->specializations());
3532 continue;
3534 if (auto *DC = dyn_cast<DeclContext>(SubDC))
3535 DeclContexts.push_back(DC);
3536 if (auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3537 F->addAttr(AA);
3538 continue;
3544 void Sema::ActOnOpenMPEndAssumesDirective() {
3545 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3546 OMPAssumeScoped.pop_back();
3549 OMPRequiresDecl *Sema::CheckOMPRequiresDecl(SourceLocation Loc,
3550 ArrayRef<OMPClause *> ClauseList) {
3551 /// For target specific clauses, the requires directive cannot be
3552 /// specified after the handling of any of the target regions in the
3553 /// current compilation unit.
3554 ArrayRef<SourceLocation> TargetLocations =
3555 DSAStack->getEncounteredTargetLocs();
3556 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3557 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3558 for (const OMPClause *CNew : ClauseList) {
3559 // Check if any of the requires clauses affect target regions.
3560 if (isa<OMPUnifiedSharedMemoryClause>(CNew) ||
3561 isa<OMPUnifiedAddressClause>(CNew) ||
3562 isa<OMPReverseOffloadClause>(CNew) ||
3563 isa<OMPDynamicAllocatorsClause>(CNew)) {
3564 Diag(Loc, diag::err_omp_directive_before_requires)
3565 << "target" << getOpenMPClauseName(CNew->getClauseKind());
3566 for (SourceLocation TargetLoc : TargetLocations) {
3567 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3568 << "target";
3570 } else if (!AtomicLoc.isInvalid() &&
3571 isa<OMPAtomicDefaultMemOrderClause>(CNew)) {
3572 Diag(Loc, diag::err_omp_directive_before_requires)
3573 << "atomic" << getOpenMPClauseName(CNew->getClauseKind());
3574 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3575 << "atomic";
3580 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3581 return OMPRequiresDecl::Create(Context, getCurLexicalContext(), Loc,
3582 ClauseList);
3583 return nullptr;
3586 static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3587 const ValueDecl *D,
3588 const DSAStackTy::DSAVarData &DVar,
3589 bool IsLoopIterVar) {
3590 if (DVar.RefExpr) {
3591 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3592 << getOpenMPClauseName(DVar.CKind);
3593 return;
3595 enum {
3596 PDSA_StaticMemberShared,
3597 PDSA_StaticLocalVarShared,
3598 PDSA_LoopIterVarPrivate,
3599 PDSA_LoopIterVarLinear,
3600 PDSA_LoopIterVarLastprivate,
3601 PDSA_ConstVarShared,
3602 PDSA_GlobalVarShared,
3603 PDSA_TaskVarFirstprivate,
3604 PDSA_LocalVarPrivate,
3605 PDSA_Implicit
3606 } Reason = PDSA_Implicit;
3607 bool ReportHint = false;
3608 auto ReportLoc = D->getLocation();
3609 auto *VD = dyn_cast<VarDecl>(D);
3610 if (IsLoopIterVar) {
3611 if (DVar.CKind == OMPC_private)
3612 Reason = PDSA_LoopIterVarPrivate;
3613 else if (DVar.CKind == OMPC_lastprivate)
3614 Reason = PDSA_LoopIterVarLastprivate;
3615 else
3616 Reason = PDSA_LoopIterVarLinear;
3617 } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3618 DVar.CKind == OMPC_firstprivate) {
3619 Reason = PDSA_TaskVarFirstprivate;
3620 ReportLoc = DVar.ImplicitDSALoc;
3621 } else if (VD && VD->isStaticLocal())
3622 Reason = PDSA_StaticLocalVarShared;
3623 else if (VD && VD->isStaticDataMember())
3624 Reason = PDSA_StaticMemberShared;
3625 else if (VD && VD->isFileVarDecl())
3626 Reason = PDSA_GlobalVarShared;
3627 else if (D->getType().isConstant(SemaRef.getASTContext()))
3628 Reason = PDSA_ConstVarShared;
3629 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3630 ReportHint = true;
3631 Reason = PDSA_LocalVarPrivate;
3633 if (Reason != PDSA_Implicit) {
3634 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3635 << Reason << ReportHint
3636 << getOpenMPDirectiveName(Stack->getCurrentDirective());
3637 } else if (DVar.ImplicitDSALoc.isValid()) {
3638 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3639 << getOpenMPClauseName(DVar.CKind);
3643 static OpenMPMapClauseKind
3644 getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M,
3645 bool IsAggregateOrDeclareTarget) {
3646 OpenMPMapClauseKind Kind = OMPC_MAP_unknown;
3647 switch (M) {
3648 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3649 Kind = OMPC_MAP_alloc;
3650 break;
3651 case OMPC_DEFAULTMAP_MODIFIER_to:
3652 Kind = OMPC_MAP_to;
3653 break;
3654 case OMPC_DEFAULTMAP_MODIFIER_from:
3655 Kind = OMPC_MAP_from;
3656 break;
3657 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3658 Kind = OMPC_MAP_tofrom;
3659 break;
3660 case OMPC_DEFAULTMAP_MODIFIER_present:
3661 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3662 // If implicit-behavior is present, each variable referenced in the
3663 // construct in the category specified by variable-category is treated as if
3664 // it had been listed in a map clause with the map-type of alloc and
3665 // map-type-modifier of present.
3666 Kind = OMPC_MAP_alloc;
3667 break;
3668 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3669 case OMPC_DEFAULTMAP_MODIFIER_last:
3670 llvm_unreachable("Unexpected defaultmap implicit behavior");
3671 case OMPC_DEFAULTMAP_MODIFIER_none:
3672 case OMPC_DEFAULTMAP_MODIFIER_default:
3673 case OMPC_DEFAULTMAP_MODIFIER_unknown:
3674 // IsAggregateOrDeclareTarget could be true if:
3675 // 1. the implicit behavior for aggregate is tofrom
3676 // 2. it's a declare target link
3677 if (IsAggregateOrDeclareTarget) {
3678 Kind = OMPC_MAP_tofrom;
3679 break;
3681 llvm_unreachable("Unexpected defaultmap implicit behavior");
3683 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3684 return Kind;
3687 namespace {
3688 class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3689 DSAStackTy *Stack;
3690 Sema &SemaRef;
3691 bool ErrorFound = false;
3692 bool TryCaptureCXXThisMembers = false;
3693 CapturedStmt *CS = nullptr;
3694 const static unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_pointer + 1;
3695 llvm::SmallVector<Expr *, 4> ImplicitFirstprivate;
3696 llvm::SmallVector<Expr *, 4> ImplicitPrivate;
3697 llvm::SmallVector<Expr *, 4> ImplicitMap[DefaultmapKindNum][OMPC_MAP_delete];
3698 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
3699 ImplicitMapModifier[DefaultmapKindNum];
3700 Sema::VarsWithInheritedDSAType VarsWithInheritedDSA;
3701 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3703 void VisitSubCaptures(OMPExecutableDirective *S) {
3704 // Check implicitly captured variables.
3705 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3706 return;
3707 if (S->getDirectiveKind() == OMPD_atomic ||
3708 S->getDirectiveKind() == OMPD_critical ||
3709 S->getDirectiveKind() == OMPD_section ||
3710 S->getDirectiveKind() == OMPD_master ||
3711 S->getDirectiveKind() == OMPD_masked ||
3712 S->getDirectiveKind() == OMPD_scope ||
3713 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
3714 Visit(S->getAssociatedStmt());
3715 return;
3717 visitSubCaptures(S->getInnermostCapturedStmt());
3718 // Try to capture inner this->member references to generate correct mappings
3719 // and diagnostics.
3720 if (TryCaptureCXXThisMembers ||
3721 (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
3722 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3723 [](const CapturedStmt::Capture &C) {
3724 return C.capturesThis();
3725 }))) {
3726 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3727 TryCaptureCXXThisMembers = true;
3728 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3729 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3731 // In tasks firstprivates are not captured anymore, need to analyze them
3732 // explicitly.
3733 if (isOpenMPTaskingDirective(S->getDirectiveKind()) &&
3734 !isOpenMPTaskLoopDirective(S->getDirectiveKind())) {
3735 for (OMPClause *C : S->clauses())
3736 if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) {
3737 for (Expr *Ref : FC->varlists())
3738 Visit(Ref);
3743 public:
3744 void VisitDeclRefExpr(DeclRefExpr *E) {
3745 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
3746 E->isValueDependent() || E->containsUnexpandedParameterPack() ||
3747 E->isInstantiationDependent())
3748 return;
3749 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3750 // Check the datasharing rules for the expressions in the clauses.
3751 if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) &&
3752 !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr &&
3753 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3754 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3755 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3756 Visit(CED->getInit());
3757 return;
3759 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD))
3760 // Do not analyze internal variables and do not enclose them into
3761 // implicit clauses.
3762 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3763 return;
3764 VD = VD->getCanonicalDecl();
3765 // Skip internally declared variables.
3766 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) &&
3767 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3768 !Stack->isImplicitTaskFirstprivate(VD))
3769 return;
3770 // Skip allocators in uses_allocators clauses.
3771 if (Stack->isUsesAllocatorsDecl(VD))
3772 return;
3774 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
3775 // Check if the variable has explicit DSA set and stop analysis if it so.
3776 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3777 return;
3779 // Skip internally declared static variables.
3780 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3781 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3782 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
3783 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
3784 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3785 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3786 !Stack->isImplicitTaskFirstprivate(VD))
3787 return;
3789 SourceLocation ELoc = E->getExprLoc();
3790 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3791 // The default(none) clause requires that each variable that is referenced
3792 // in the construct, and does not have a predetermined data-sharing
3793 // attribute, must have its data-sharing attribute explicitly determined
3794 // by being listed in a data-sharing attribute clause.
3795 if (DVar.CKind == OMPC_unknown &&
3796 (Stack->getDefaultDSA() == DSA_none ||
3797 Stack->getDefaultDSA() == DSA_private ||
3798 Stack->getDefaultDSA() == DSA_firstprivate) &&
3799 isImplicitOrExplicitTaskingRegion(DKind) &&
3800 VarsWithInheritedDSA.count(VD) == 0) {
3801 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
3802 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
3803 Stack->getDefaultDSA() == DSA_private)) {
3804 DSAStackTy::DSAVarData DVar =
3805 Stack->getImplicitDSA(VD, /*FromParent=*/false);
3806 InheritedDSA = DVar.CKind == OMPC_unknown;
3808 if (InheritedDSA)
3809 VarsWithInheritedDSA[VD] = E;
3810 if (Stack->getDefaultDSA() == DSA_none)
3811 return;
3814 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
3815 // If implicit-behavior is none, each variable referenced in the
3816 // construct that does not have a predetermined data-sharing attribute
3817 // and does not appear in a to or link clause on a declare target
3818 // directive must be listed in a data-mapping attribute clause, a
3819 // data-sharing attribute clause (including a data-sharing attribute
3820 // clause on a combined construct where target. is one of the
3821 // constituent constructs), or an is_device_ptr clause.
3822 OpenMPDefaultmapClauseKind ClauseKind =
3823 getVariableCategoryFromDecl(SemaRef.getLangOpts(), VD);
3824 if (SemaRef.getLangOpts().OpenMP >= 50) {
3825 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
3826 OMPC_DEFAULTMAP_MODIFIER_none;
3827 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
3828 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
3829 // Only check for data-mapping attribute and is_device_ptr here
3830 // since we have already make sure that the declaration does not
3831 // have a data-sharing attribute above
3832 if (!Stack->checkMappableExprComponentListsForDecl(
3833 VD, /*CurrentRegionOnly=*/true,
3834 [VD](OMPClauseMappableExprCommon::MappableExprComponentListRef
3835 MapExprComponents,
3836 OpenMPClauseKind) {
3837 auto MI = MapExprComponents.rbegin();
3838 auto ME = MapExprComponents.rend();
3839 return MI != ME && MI->getAssociatedDeclaration() == VD;
3840 })) {
3841 VarsWithInheritedDSA[VD] = E;
3842 return;
3846 if (SemaRef.getLangOpts().OpenMP > 50) {
3847 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
3848 OMPC_DEFAULTMAP_MODIFIER_present;
3849 if (IsModifierPresent) {
3850 if (!llvm::is_contained(ImplicitMapModifier[ClauseKind],
3851 OMPC_MAP_MODIFIER_present)) {
3852 ImplicitMapModifier[ClauseKind].push_back(
3853 OMPC_MAP_MODIFIER_present);
3858 if (isOpenMPTargetExecutionDirective(DKind) &&
3859 !Stack->isLoopControlVariable(VD).first) {
3860 if (!Stack->checkMappableExprComponentListsForDecl(
3861 VD, /*CurrentRegionOnly=*/true,
3862 [this](OMPClauseMappableExprCommon::MappableExprComponentListRef
3863 StackComponents,
3864 OpenMPClauseKind) {
3865 if (SemaRef.LangOpts.OpenMP >= 50)
3866 return !StackComponents.empty();
3867 // Variable is used if it has been marked as an array, array
3868 // section, array shaping or the variable iself.
3869 return StackComponents.size() == 1 ||
3870 llvm::all_of(
3871 llvm::drop_begin(llvm::reverse(StackComponents)),
3872 [](const OMPClauseMappableExprCommon::
3873 MappableComponent &MC) {
3874 return MC.getAssociatedDeclaration() ==
3875 nullptr &&
3876 (isa<OMPArraySectionExpr>(
3877 MC.getAssociatedExpression()) ||
3878 isa<OMPArrayShapingExpr>(
3879 MC.getAssociatedExpression()) ||
3880 isa<ArraySubscriptExpr>(
3881 MC.getAssociatedExpression()));
3883 })) {
3884 bool IsFirstprivate = false;
3885 // By default lambdas are captured as firstprivates.
3886 if (const auto *RD =
3887 VD->getType().getNonReferenceType()->getAsCXXRecordDecl())
3888 IsFirstprivate = RD->isLambda();
3889 IsFirstprivate =
3890 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
3891 if (IsFirstprivate) {
3892 ImplicitFirstprivate.emplace_back(E);
3893 } else {
3894 OpenMPDefaultmapClauseModifier M =
3895 Stack->getDefaultmapModifier(ClauseKind);
3896 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
3897 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
3898 ImplicitMap[ClauseKind][Kind].emplace_back(E);
3900 return;
3904 // OpenMP [2.9.3.6, Restrictions, p.2]
3905 // A list item that appears in a reduction clause of the innermost
3906 // enclosing worksharing or parallel construct may not be accessed in an
3907 // explicit task.
3908 DVar = Stack->hasInnermostDSA(
3910 [](OpenMPClauseKind C, bool AppliedToPointee) {
3911 return C == OMPC_reduction && !AppliedToPointee;
3913 [](OpenMPDirectiveKind K) {
3914 return isOpenMPParallelDirective(K) ||
3915 isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K);
3917 /*FromParent=*/true);
3918 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
3919 ErrorFound = true;
3920 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
3921 reportOriginalDsa(SemaRef, Stack, VD, DVar);
3922 return;
3925 // Define implicit data-sharing attributes for task.
3926 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
3927 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
3928 (((Stack->getDefaultDSA() == DSA_firstprivate &&
3929 DVar.CKind == OMPC_firstprivate) ||
3930 (Stack->getDefaultDSA() == DSA_private &&
3931 DVar.CKind == OMPC_private)) &&
3932 !DVar.RefExpr)) &&
3933 !Stack->isLoopControlVariable(VD).first) {
3934 if (Stack->getDefaultDSA() == DSA_private)
3935 ImplicitPrivate.push_back(E);
3936 else
3937 ImplicitFirstprivate.push_back(E);
3938 return;
3941 // Store implicitly used globals with declare target link for parent
3942 // target.
3943 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
3944 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
3945 Stack->addToParentTargetRegionLinkGlobals(E);
3946 return;
3950 void VisitMemberExpr(MemberExpr *E) {
3951 if (E->isTypeDependent() || E->isValueDependent() ||
3952 E->containsUnexpandedParameterPack() || E->isInstantiationDependent())
3953 return;
3954 auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
3955 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3956 if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) {
3957 if (!FD)
3958 return;
3959 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
3960 // Check if the variable has explicit DSA set and stop analysis if it
3961 // so.
3962 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
3963 return;
3965 if (isOpenMPTargetExecutionDirective(DKind) &&
3966 !Stack->isLoopControlVariable(FD).first &&
3967 !Stack->checkMappableExprComponentListsForDecl(
3968 FD, /*CurrentRegionOnly=*/true,
3969 [](OMPClauseMappableExprCommon::MappableExprComponentListRef
3970 StackComponents,
3971 OpenMPClauseKind) {
3972 return isa<CXXThisExpr>(
3973 cast<MemberExpr>(
3974 StackComponents.back().getAssociatedExpression())
3975 ->getBase()
3976 ->IgnoreParens());
3977 })) {
3978 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
3979 // A bit-field cannot appear in a map clause.
3981 if (FD->isBitField())
3982 return;
3984 // Check to see if the member expression is referencing a class that
3985 // has already been explicitly mapped
3986 if (Stack->isClassPreviouslyMapped(TE->getType()))
3987 return;
3989 OpenMPDefaultmapClauseModifier Modifier =
3990 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
3991 OpenMPDefaultmapClauseKind ClauseKind =
3992 getVariableCategoryFromDecl(SemaRef.getLangOpts(), FD);
3993 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
3994 Modifier, /*IsAggregateOrDeclareTarget*/ true);
3995 ImplicitMap[ClauseKind][Kind].emplace_back(E);
3996 return;
3999 SourceLocation ELoc = E->getExprLoc();
4000 // OpenMP [2.9.3.6, Restrictions, p.2]
4001 // A list item that appears in a reduction clause of the innermost
4002 // enclosing worksharing or parallel construct may not be accessed in
4003 // an explicit task.
4004 DVar = Stack->hasInnermostDSA(
4006 [](OpenMPClauseKind C, bool AppliedToPointee) {
4007 return C == OMPC_reduction && !AppliedToPointee;
4009 [](OpenMPDirectiveKind K) {
4010 return isOpenMPParallelDirective(K) ||
4011 isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K);
4013 /*FromParent=*/true);
4014 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4015 ErrorFound = true;
4016 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4017 reportOriginalDsa(SemaRef, Stack, FD, DVar);
4018 return;
4021 // Define implicit data-sharing attributes for task.
4022 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
4023 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
4024 !Stack->isLoopControlVariable(FD).first) {
4025 // Check if there is a captured expression for the current field in the
4026 // region. Do not mark it as firstprivate unless there is no captured
4027 // expression.
4028 // TODO: try to make it firstprivate.
4029 if (DVar.CKind != OMPC_unknown)
4030 ImplicitFirstprivate.push_back(E);
4032 return;
4034 if (isOpenMPTargetExecutionDirective(DKind)) {
4035 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
4036 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
4037 Stack->getCurrentDirective(),
4038 /*NoDiagnose=*/true))
4039 return;
4040 const auto *VD = cast<ValueDecl>(
4041 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4042 if (!Stack->checkMappableExprComponentListsForDecl(
4043 VD, /*CurrentRegionOnly=*/true,
4044 [&CurComponents](
4045 OMPClauseMappableExprCommon::MappableExprComponentListRef
4046 StackComponents,
4047 OpenMPClauseKind) {
4048 auto CCI = CurComponents.rbegin();
4049 auto CCE = CurComponents.rend();
4050 for (const auto &SC : llvm::reverse(StackComponents)) {
4051 // Do both expressions have the same kind?
4052 if (CCI->getAssociatedExpression()->getStmtClass() !=
4053 SC.getAssociatedExpression()->getStmtClass())
4054 if (!((isa<OMPArraySectionExpr>(
4055 SC.getAssociatedExpression()) ||
4056 isa<OMPArrayShapingExpr>(
4057 SC.getAssociatedExpression())) &&
4058 isa<ArraySubscriptExpr>(
4059 CCI->getAssociatedExpression())))
4060 return false;
4062 const Decl *CCD = CCI->getAssociatedDeclaration();
4063 const Decl *SCD = SC.getAssociatedDeclaration();
4064 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4065 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4066 if (SCD != CCD)
4067 return false;
4068 std::advance(CCI, 1);
4069 if (CCI == CCE)
4070 break;
4072 return true;
4073 })) {
4074 Visit(E->getBase());
4076 } else if (!TryCaptureCXXThisMembers) {
4077 Visit(E->getBase());
4080 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4081 for (OMPClause *C : S->clauses()) {
4082 // Skip analysis of arguments of private clauses for task|target
4083 // directives.
4084 if (isa_and_nonnull<OMPPrivateClause>(C))
4085 continue;
4086 // Skip analysis of arguments of implicitly defined firstprivate clause
4087 // for task|target directives.
4088 // Skip analysis of arguments of implicitly defined map clause for target
4089 // directives.
4090 if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) &&
4091 C->isImplicit() &&
4092 !isOpenMPTaskingDirective(Stack->getCurrentDirective()))) {
4093 for (Stmt *CC : C->children()) {
4094 if (CC)
4095 Visit(CC);
4099 // Check implicitly captured variables.
4100 VisitSubCaptures(S);
4103 void VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective *S) {
4104 // Loop transformation directives do not introduce data sharing
4105 VisitStmt(S);
4108 void VisitCallExpr(CallExpr *S) {
4109 for (Stmt *C : S->arguments()) {
4110 if (C) {
4111 // Check implicitly captured variables in the task-based directives to
4112 // check if they must be firstprivatized.
4113 Visit(C);
4116 if (Expr *Callee = S->getCallee()) {
4117 auto *CI = Callee->IgnoreParenImpCasts();
4118 if (auto *CE = dyn_cast<MemberExpr>(CI))
4119 Visit(CE->getBase());
4120 else if (auto *CE = dyn_cast<DeclRefExpr>(CI))
4121 Visit(CE);
4124 void VisitStmt(Stmt *S) {
4125 for (Stmt *C : S->children()) {
4126 if (C) {
4127 // Check implicitly captured variables in the task-based directives to
4128 // check if they must be firstprivatized.
4129 Visit(C);
4134 void visitSubCaptures(CapturedStmt *S) {
4135 for (const CapturedStmt::Capture &Cap : S->captures()) {
4136 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4137 continue;
4138 VarDecl *VD = Cap.getCapturedVar();
4139 // Do not try to map the variable if it or its sub-component was mapped
4140 // already.
4141 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
4142 Stack->checkMappableExprComponentListsForDecl(
4143 VD, /*CurrentRegionOnly=*/true,
4144 [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
4145 OpenMPClauseKind) { return true; }))
4146 continue;
4147 DeclRefExpr *DRE = buildDeclRefExpr(
4148 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4149 Cap.getLocation(), /*RefersToCapture=*/true);
4150 Visit(DRE);
4153 bool isErrorFound() const { return ErrorFound; }
4154 ArrayRef<Expr *> getImplicitFirstprivate() const {
4155 return ImplicitFirstprivate;
4157 ArrayRef<Expr *> getImplicitPrivate() const { return ImplicitPrivate; }
4158 ArrayRef<Expr *> getImplicitMap(OpenMPDefaultmapClauseKind DK,
4159 OpenMPMapClauseKind MK) const {
4160 return ImplicitMap[DK][MK];
4162 ArrayRef<OpenMPMapModifierKind>
4163 getImplicitMapModifier(OpenMPDefaultmapClauseKind Kind) const {
4164 return ImplicitMapModifier[Kind];
4166 const Sema::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4167 return VarsWithInheritedDSA;
4170 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4171 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4172 // Process declare target link variables for the target directives.
4173 if (isOpenMPTargetExecutionDirective(S->getCurrentDirective())) {
4174 for (DeclRefExpr *E : Stack->getLinkGlobals())
4175 Visit(E);
4179 } // namespace
4181 static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4182 OpenMPDirectiveKind DKind,
4183 bool ScopeEntry) {
4184 SmallVector<llvm::omp::TraitProperty, 8> Traits;
4185 if (isOpenMPTargetExecutionDirective(DKind))
4186 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4187 if (isOpenMPTeamsDirective(DKind))
4188 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4189 if (isOpenMPParallelDirective(DKind))
4190 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4191 if (isOpenMPWorksharingDirective(DKind))
4192 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4193 if (isOpenMPSimdDirective(DKind))
4194 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4195 Stack->handleConstructTrait(Traits, ScopeEntry);
4198 void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
4199 switch (DKind) {
4200 case OMPD_parallel:
4201 case OMPD_parallel_for:
4202 case OMPD_parallel_for_simd:
4203 case OMPD_parallel_sections:
4204 case OMPD_parallel_master:
4205 case OMPD_parallel_masked:
4206 case OMPD_parallel_loop:
4207 case OMPD_teams:
4208 case OMPD_teams_distribute:
4209 case OMPD_teams_distribute_simd: {
4210 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4211 QualType KmpInt32PtrTy =
4212 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4213 Sema::CapturedParamNameType Params[] = {
4214 std::make_pair(".global_tid.", KmpInt32PtrTy),
4215 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4216 std::make_pair(StringRef(), QualType()) // __context with shared vars
4218 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4219 Params);
4220 break;
4222 case OMPD_target_teams:
4223 case OMPD_target_parallel:
4224 case OMPD_target_parallel_for:
4225 case OMPD_target_parallel_for_simd:
4226 case OMPD_target_parallel_loop:
4227 case OMPD_target_teams_distribute:
4228 case OMPD_target_teams_distribute_simd: {
4229 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4230 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4231 QualType KmpInt32PtrTy =
4232 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4233 QualType Args[] = {VoidPtrTy};
4234 FunctionProtoType::ExtProtoInfo EPI;
4235 EPI.Variadic = true;
4236 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4237 Sema::CapturedParamNameType Params[] = {
4238 std::make_pair(".global_tid.", KmpInt32Ty),
4239 std::make_pair(".part_id.", KmpInt32PtrTy),
4240 std::make_pair(".privates.", VoidPtrTy),
4241 std::make_pair(
4242 ".copy_fn.",
4243 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4244 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4245 std::make_pair(StringRef(), QualType()) // __context with shared vars
4247 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4248 Params, /*OpenMPCaptureLevel=*/0);
4249 // Mark this captured region as inlined, because we don't use outlined
4250 // function directly.
4251 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4252 AlwaysInlineAttr::CreateImplicit(
4253 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4254 Sema::CapturedParamNameType ParamsTarget[] = {
4255 std::make_pair(StringRef(), QualType()) // __context with shared vars
4257 // Start a captured region for 'target' with no implicit parameters.
4258 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4259 ParamsTarget, /*OpenMPCaptureLevel=*/1);
4260 Sema::CapturedParamNameType ParamsTeamsOrParallel[] = {
4261 std::make_pair(".global_tid.", KmpInt32PtrTy),
4262 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4263 std::make_pair(StringRef(), QualType()) // __context with shared vars
4265 // Start a captured region for 'teams' or 'parallel'. Both regions have
4266 // the same implicit parameters.
4267 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4268 ParamsTeamsOrParallel, /*OpenMPCaptureLevel=*/2);
4269 break;
4271 case OMPD_target:
4272 case OMPD_target_simd: {
4273 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4274 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4275 QualType KmpInt32PtrTy =
4276 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4277 QualType Args[] = {VoidPtrTy};
4278 FunctionProtoType::ExtProtoInfo EPI;
4279 EPI.Variadic = true;
4280 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4281 Sema::CapturedParamNameType Params[] = {
4282 std::make_pair(".global_tid.", KmpInt32Ty),
4283 std::make_pair(".part_id.", KmpInt32PtrTy),
4284 std::make_pair(".privates.", VoidPtrTy),
4285 std::make_pair(
4286 ".copy_fn.",
4287 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4288 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4289 std::make_pair(StringRef(), QualType()) // __context with shared vars
4291 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4292 Params, /*OpenMPCaptureLevel=*/0);
4293 // Mark this captured region as inlined, because we don't use outlined
4294 // function directly.
4295 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4296 AlwaysInlineAttr::CreateImplicit(
4297 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4298 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4299 std::make_pair(StringRef(), QualType()),
4300 /*OpenMPCaptureLevel=*/1);
4301 break;
4303 case OMPD_atomic:
4304 case OMPD_critical:
4305 case OMPD_section:
4306 case OMPD_master:
4307 case OMPD_masked:
4308 case OMPD_tile:
4309 case OMPD_unroll:
4310 break;
4311 case OMPD_loop:
4312 // TODO: 'loop' may require additional parameters depending on the binding.
4313 // Treat similar to OMPD_simd/OMPD_for for now.
4314 case OMPD_simd:
4315 case OMPD_for:
4316 case OMPD_for_simd:
4317 case OMPD_sections:
4318 case OMPD_single:
4319 case OMPD_taskgroup:
4320 case OMPD_distribute:
4321 case OMPD_distribute_simd:
4322 case OMPD_ordered:
4323 case OMPD_scope:
4324 case OMPD_target_data:
4325 case OMPD_dispatch: {
4326 Sema::CapturedParamNameType Params[] = {
4327 std::make_pair(StringRef(), QualType()) // __context with shared vars
4329 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4330 Params);
4331 break;
4333 case OMPD_task: {
4334 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4335 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4336 QualType KmpInt32PtrTy =
4337 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4338 QualType Args[] = {VoidPtrTy};
4339 FunctionProtoType::ExtProtoInfo EPI;
4340 EPI.Variadic = true;
4341 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4342 Sema::CapturedParamNameType Params[] = {
4343 std::make_pair(".global_tid.", KmpInt32Ty),
4344 std::make_pair(".part_id.", KmpInt32PtrTy),
4345 std::make_pair(".privates.", VoidPtrTy),
4346 std::make_pair(
4347 ".copy_fn.",
4348 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4349 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4350 std::make_pair(StringRef(), QualType()) // __context with shared vars
4352 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4353 Params);
4354 // Mark this captured region as inlined, because we don't use outlined
4355 // function directly.
4356 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4357 AlwaysInlineAttr::CreateImplicit(
4358 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4359 break;
4361 case OMPD_taskloop:
4362 case OMPD_taskloop_simd:
4363 case OMPD_master_taskloop:
4364 case OMPD_masked_taskloop:
4365 case OMPD_masked_taskloop_simd:
4366 case OMPD_master_taskloop_simd: {
4367 QualType KmpInt32Ty =
4368 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
4369 .withConst();
4370 QualType KmpUInt64Ty =
4371 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
4372 .withConst();
4373 QualType KmpInt64Ty =
4374 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
4375 .withConst();
4376 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4377 QualType KmpInt32PtrTy =
4378 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4379 QualType Args[] = {VoidPtrTy};
4380 FunctionProtoType::ExtProtoInfo EPI;
4381 EPI.Variadic = true;
4382 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4383 Sema::CapturedParamNameType Params[] = {
4384 std::make_pair(".global_tid.", KmpInt32Ty),
4385 std::make_pair(".part_id.", KmpInt32PtrTy),
4386 std::make_pair(".privates.", VoidPtrTy),
4387 std::make_pair(
4388 ".copy_fn.",
4389 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4390 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4391 std::make_pair(".lb.", KmpUInt64Ty),
4392 std::make_pair(".ub.", KmpUInt64Ty),
4393 std::make_pair(".st.", KmpInt64Ty),
4394 std::make_pair(".liter.", KmpInt32Ty),
4395 std::make_pair(".reductions.", VoidPtrTy),
4396 std::make_pair(StringRef(), QualType()) // __context with shared vars
4398 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4399 Params);
4400 // Mark this captured region as inlined, because we don't use outlined
4401 // function directly.
4402 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4403 AlwaysInlineAttr::CreateImplicit(
4404 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4405 break;
4407 case OMPD_parallel_masked_taskloop:
4408 case OMPD_parallel_masked_taskloop_simd:
4409 case OMPD_parallel_master_taskloop:
4410 case OMPD_parallel_master_taskloop_simd: {
4411 QualType KmpInt32Ty =
4412 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
4413 .withConst();
4414 QualType KmpUInt64Ty =
4415 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
4416 .withConst();
4417 QualType KmpInt64Ty =
4418 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
4419 .withConst();
4420 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4421 QualType KmpInt32PtrTy =
4422 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4423 Sema::CapturedParamNameType ParamsParallel[] = {
4424 std::make_pair(".global_tid.", KmpInt32PtrTy),
4425 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4426 std::make_pair(StringRef(), QualType()) // __context with shared vars
4428 // Start a captured region for 'parallel'.
4429 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4430 ParamsParallel, /*OpenMPCaptureLevel=*/0);
4431 QualType Args[] = {VoidPtrTy};
4432 FunctionProtoType::ExtProtoInfo EPI;
4433 EPI.Variadic = true;
4434 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4435 Sema::CapturedParamNameType Params[] = {
4436 std::make_pair(".global_tid.", KmpInt32Ty),
4437 std::make_pair(".part_id.", KmpInt32PtrTy),
4438 std::make_pair(".privates.", VoidPtrTy),
4439 std::make_pair(
4440 ".copy_fn.",
4441 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4442 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4443 std::make_pair(".lb.", KmpUInt64Ty),
4444 std::make_pair(".ub.", KmpUInt64Ty),
4445 std::make_pair(".st.", KmpInt64Ty),
4446 std::make_pair(".liter.", KmpInt32Ty),
4447 std::make_pair(".reductions.", VoidPtrTy),
4448 std::make_pair(StringRef(), QualType()) // __context with shared vars
4450 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4451 Params, /*OpenMPCaptureLevel=*/1);
4452 // Mark this captured region as inlined, because we don't use outlined
4453 // function directly.
4454 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4455 AlwaysInlineAttr::CreateImplicit(
4456 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4457 break;
4459 case OMPD_distribute_parallel_for_simd:
4460 case OMPD_distribute_parallel_for: {
4461 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4462 QualType KmpInt32PtrTy =
4463 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4464 Sema::CapturedParamNameType Params[] = {
4465 std::make_pair(".global_tid.", KmpInt32PtrTy),
4466 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4467 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4468 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4469 std::make_pair(StringRef(), QualType()) // __context with shared vars
4471 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4472 Params);
4473 break;
4475 case OMPD_target_teams_loop:
4476 case OMPD_target_teams_distribute_parallel_for:
4477 case OMPD_target_teams_distribute_parallel_for_simd: {
4478 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4479 QualType KmpInt32PtrTy =
4480 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4481 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4483 QualType Args[] = {VoidPtrTy};
4484 FunctionProtoType::ExtProtoInfo EPI;
4485 EPI.Variadic = true;
4486 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4487 Sema::CapturedParamNameType Params[] = {
4488 std::make_pair(".global_tid.", KmpInt32Ty),
4489 std::make_pair(".part_id.", KmpInt32PtrTy),
4490 std::make_pair(".privates.", VoidPtrTy),
4491 std::make_pair(
4492 ".copy_fn.",
4493 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4494 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4495 std::make_pair(StringRef(), QualType()) // __context with shared vars
4497 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4498 Params, /*OpenMPCaptureLevel=*/0);
4499 // Mark this captured region as inlined, because we don't use outlined
4500 // function directly.
4501 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4502 AlwaysInlineAttr::CreateImplicit(
4503 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4504 Sema::CapturedParamNameType ParamsTarget[] = {
4505 std::make_pair(StringRef(), QualType()) // __context with shared vars
4507 // Start a captured region for 'target' with no implicit parameters.
4508 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4509 ParamsTarget, /*OpenMPCaptureLevel=*/1);
4511 Sema::CapturedParamNameType ParamsTeams[] = {
4512 std::make_pair(".global_tid.", KmpInt32PtrTy),
4513 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4514 std::make_pair(StringRef(), QualType()) // __context with shared vars
4516 // Start a captured region for 'target' with no implicit parameters.
4517 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4518 ParamsTeams, /*OpenMPCaptureLevel=*/2);
4520 Sema::CapturedParamNameType ParamsParallel[] = {
4521 std::make_pair(".global_tid.", KmpInt32PtrTy),
4522 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4523 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4524 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4525 std::make_pair(StringRef(), QualType()) // __context with shared vars
4527 // Start a captured region for 'teams' or 'parallel'. Both regions have
4528 // the same implicit parameters.
4529 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4530 ParamsParallel, /*OpenMPCaptureLevel=*/3);
4531 break;
4534 case OMPD_teams_loop:
4535 case OMPD_teams_distribute_parallel_for:
4536 case OMPD_teams_distribute_parallel_for_simd: {
4537 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4538 QualType KmpInt32PtrTy =
4539 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4541 Sema::CapturedParamNameType ParamsTeams[] = {
4542 std::make_pair(".global_tid.", KmpInt32PtrTy),
4543 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4544 std::make_pair(StringRef(), QualType()) // __context with shared vars
4546 // Start a captured region for 'target' with no implicit parameters.
4547 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4548 ParamsTeams, /*OpenMPCaptureLevel=*/0);
4550 Sema::CapturedParamNameType ParamsParallel[] = {
4551 std::make_pair(".global_tid.", KmpInt32PtrTy),
4552 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4553 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4554 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4555 std::make_pair(StringRef(), QualType()) // __context with shared vars
4557 // Start a captured region for 'teams' or 'parallel'. Both regions have
4558 // the same implicit parameters.
4559 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4560 ParamsParallel, /*OpenMPCaptureLevel=*/1);
4561 break;
4563 case OMPD_target_update:
4564 case OMPD_target_enter_data:
4565 case OMPD_target_exit_data: {
4566 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4567 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4568 QualType KmpInt32PtrTy =
4569 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4570 QualType Args[] = {VoidPtrTy};
4571 FunctionProtoType::ExtProtoInfo EPI;
4572 EPI.Variadic = true;
4573 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4574 Sema::CapturedParamNameType Params[] = {
4575 std::make_pair(".global_tid.", KmpInt32Ty),
4576 std::make_pair(".part_id.", KmpInt32PtrTy),
4577 std::make_pair(".privates.", VoidPtrTy),
4578 std::make_pair(
4579 ".copy_fn.",
4580 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4581 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4582 std::make_pair(StringRef(), QualType()) // __context with shared vars
4584 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4585 Params);
4586 // Mark this captured region as inlined, because we don't use outlined
4587 // function directly.
4588 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4589 AlwaysInlineAttr::CreateImplicit(
4590 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4591 break;
4593 case OMPD_threadprivate:
4594 case OMPD_allocate:
4595 case OMPD_taskyield:
4596 case OMPD_error:
4597 case OMPD_barrier:
4598 case OMPD_taskwait:
4599 case OMPD_cancellation_point:
4600 case OMPD_cancel:
4601 case OMPD_flush:
4602 case OMPD_depobj:
4603 case OMPD_scan:
4604 case OMPD_declare_reduction:
4605 case OMPD_declare_mapper:
4606 case OMPD_declare_simd:
4607 case OMPD_declare_target:
4608 case OMPD_end_declare_target:
4609 case OMPD_requires:
4610 case OMPD_declare_variant:
4611 case OMPD_begin_declare_variant:
4612 case OMPD_end_declare_variant:
4613 case OMPD_metadirective:
4614 llvm_unreachable("OpenMP Directive is not allowed");
4615 case OMPD_unknown:
4616 default:
4617 llvm_unreachable("Unknown OpenMP directive");
4619 DSAStack->setContext(CurContext);
4620 handleDeclareVariantConstructTrait(DSAStack, DKind, /* ScopeEntry */ true);
4623 int Sema::getNumberOfConstructScopes(unsigned Level) const {
4624 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4627 int Sema::getOpenMPCaptureLevels(OpenMPDirectiveKind DKind) {
4628 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4629 getOpenMPCaptureRegions(CaptureRegions, DKind);
4630 return CaptureRegions.size();
4633 static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
4634 Expr *CaptureExpr, bool WithInit,
4635 DeclContext *CurContext,
4636 bool AsExpression) {
4637 assert(CaptureExpr);
4638 ASTContext &C = S.getASTContext();
4639 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4640 QualType Ty = Init->getType();
4641 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4642 if (S.getLangOpts().CPlusPlus) {
4643 Ty = C.getLValueReferenceType(Ty);
4644 } else {
4645 Ty = C.getPointerType(Ty);
4646 ExprResult Res =
4647 S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init);
4648 if (!Res.isUsable())
4649 return nullptr;
4650 Init = Res.get();
4652 WithInit = true;
4654 auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty,
4655 CaptureExpr->getBeginLoc());
4656 if (!WithInit)
4657 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
4658 CurContext->addHiddenDecl(CED);
4659 Sema::TentativeAnalysisScope Trap(S);
4660 S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
4661 return CED;
4664 static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4665 bool WithInit) {
4666 OMPCapturedExprDecl *CD;
4667 if (VarDecl *VD = S.isOpenMPCapturedDecl(D))
4668 CD = cast<OMPCapturedExprDecl>(VD);
4669 else
4670 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
4671 S.CurContext,
4672 /*AsExpression=*/false);
4673 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4674 CaptureExpr->getExprLoc());
4677 static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
4678 StringRef Name) {
4679 CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get();
4680 if (!Ref) {
4681 OMPCapturedExprDecl *CD = buildCaptureDecl(
4682 S, &S.getASTContext().Idents.get(Name), CaptureExpr,
4683 /*WithInit=*/true, S.CurContext, /*AsExpression=*/true);
4684 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4685 CaptureExpr->getExprLoc());
4687 ExprResult Res = Ref;
4688 if (!S.getLangOpts().CPlusPlus &&
4689 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4690 Ref->getType()->isPointerType()) {
4691 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
4692 if (!Res.isUsable())
4693 return ExprError();
4695 return S.DefaultLvalueConversion(Res.get());
4698 namespace {
4699 // OpenMP directives parsed in this section are represented as a
4700 // CapturedStatement with an associated statement. If a syntax error
4701 // is detected during the parsing of the associated statement, the
4702 // compiler must abort processing and close the CapturedStatement.
4704 // Combined directives such as 'target parallel' have more than one
4705 // nested CapturedStatements. This RAII ensures that we unwind out
4706 // of all the nested CapturedStatements when an error is found.
4707 class CaptureRegionUnwinderRAII {
4708 private:
4709 Sema &S;
4710 bool &ErrorFound;
4711 OpenMPDirectiveKind DKind = OMPD_unknown;
4713 public:
4714 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4715 OpenMPDirectiveKind DKind)
4716 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4717 ~CaptureRegionUnwinderRAII() {
4718 if (ErrorFound) {
4719 int ThisCaptureLevel = S.getOpenMPCaptureLevels(DKind);
4720 while (--ThisCaptureLevel >= 0)
4721 S.ActOnCapturedRegionError();
4725 } // namespace
4727 void Sema::tryCaptureOpenMPLambdas(ValueDecl *V) {
4728 // Capture variables captured by reference in lambdas for target-based
4729 // directives.
4730 if (!CurContext->isDependentContext() &&
4731 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4732 isOpenMPTargetDataManagementDirective(
4733 DSAStack->getCurrentDirective()))) {
4734 QualType Type = V->getType();
4735 if (const auto *RD = Type.getCanonicalType()
4736 .getNonReferenceType()
4737 ->getAsCXXRecordDecl()) {
4738 bool SavedForceCaptureByReferenceInTargetExecutable =
4739 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4740 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4741 /*V=*/true);
4742 if (RD->isLambda()) {
4743 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4744 FieldDecl *ThisCapture;
4745 RD->getCaptureFields(Captures, ThisCapture);
4746 for (const LambdaCapture &LC : RD->captures()) {
4747 if (LC.getCaptureKind() == LCK_ByRef) {
4748 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4749 DeclContext *VDC = VD->getDeclContext();
4750 if (!VDC->Encloses(CurContext))
4751 continue;
4752 MarkVariableReferenced(LC.getLocation(), VD);
4753 } else if (LC.getCaptureKind() == LCK_This) {
4754 QualType ThisTy = getCurrentThisType();
4755 if (!ThisTy.isNull() &&
4756 Context.typesAreCompatible(ThisTy, ThisCapture->getType()))
4757 CheckCXXThisCapture(LC.getLocation());
4761 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4762 SavedForceCaptureByReferenceInTargetExecutable);
4767 static bool checkOrderedOrderSpecified(Sema &S,
4768 const ArrayRef<OMPClause *> Clauses) {
4769 const OMPOrderedClause *Ordered = nullptr;
4770 const OMPOrderClause *Order = nullptr;
4772 for (const OMPClause *Clause : Clauses) {
4773 if (Clause->getClauseKind() == OMPC_ordered)
4774 Ordered = cast<OMPOrderedClause>(Clause);
4775 else if (Clause->getClauseKind() == OMPC_order) {
4776 Order = cast<OMPOrderClause>(Clause);
4777 if (Order->getKind() != OMPC_ORDER_concurrent)
4778 Order = nullptr;
4780 if (Ordered && Order)
4781 break;
4784 if (Ordered && Order) {
4785 S.Diag(Order->getKindKwLoc(),
4786 diag::err_omp_simple_clause_incompatible_with_ordered)
4787 << getOpenMPClauseName(OMPC_order)
4788 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
4789 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4790 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4791 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4792 return true;
4794 return false;
4797 StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
4798 ArrayRef<OMPClause *> Clauses) {
4799 handleDeclareVariantConstructTrait(DSAStack, DSAStack->getCurrentDirective(),
4800 /* ScopeEntry */ false);
4801 if (DSAStack->getCurrentDirective() == OMPD_atomic ||
4802 DSAStack->getCurrentDirective() == OMPD_critical ||
4803 DSAStack->getCurrentDirective() == OMPD_section ||
4804 DSAStack->getCurrentDirective() == OMPD_master ||
4805 DSAStack->getCurrentDirective() == OMPD_masked)
4806 return S;
4808 bool ErrorFound = false;
4809 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4810 *this, ErrorFound, DSAStack->getCurrentDirective());
4811 if (!S.isUsable()) {
4812 ErrorFound = true;
4813 return StmtError();
4816 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4817 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4818 OMPOrderedClause *OC = nullptr;
4819 OMPScheduleClause *SC = nullptr;
4820 SmallVector<const OMPLinearClause *, 4> LCs;
4821 SmallVector<const OMPClauseWithPreInit *, 4> PICs;
4822 // This is required for proper codegen.
4823 for (OMPClause *Clause : Clauses) {
4824 if (!LangOpts.OpenMPSimd &&
4825 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4826 DSAStack->getCurrentDirective() == OMPD_target) &&
4827 Clause->getClauseKind() == OMPC_in_reduction) {
4828 // Capture taskgroup task_reduction descriptors inside the tasking regions
4829 // with the corresponding in_reduction items.
4830 auto *IRC = cast<OMPInReductionClause>(Clause);
4831 for (Expr *E : IRC->taskgroup_descriptors())
4832 if (E)
4833 MarkDeclarationsReferencedInExpr(E);
4835 if (isOpenMPPrivate(Clause->getClauseKind()) ||
4836 Clause->getClauseKind() == OMPC_copyprivate ||
4837 (getLangOpts().OpenMPUseTLS &&
4838 getASTContext().getTargetInfo().isTLSSupported() &&
4839 Clause->getClauseKind() == OMPC_copyin)) {
4840 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4841 // Mark all variables in private list clauses as used in inner region.
4842 for (Stmt *VarRef : Clause->children()) {
4843 if (auto *E = cast_or_null<Expr>(VarRef)) {
4844 MarkDeclarationsReferencedInExpr(E);
4847 DSAStack->setForceVarCapturing(/*V=*/false);
4848 } else if (isOpenMPLoopTransformationDirective(
4849 DSAStack->getCurrentDirective())) {
4850 assert(CaptureRegions.empty() &&
4851 "No captured regions in loop transformation directives.");
4852 } else if (CaptureRegions.size() > 1 ||
4853 CaptureRegions.back() != OMPD_unknown) {
4854 if (auto *C = OMPClauseWithPreInit::get(Clause))
4855 PICs.push_back(C);
4856 if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
4857 if (Expr *E = C->getPostUpdateExpr())
4858 MarkDeclarationsReferencedInExpr(E);
4861 if (Clause->getClauseKind() == OMPC_schedule)
4862 SC = cast<OMPScheduleClause>(Clause);
4863 else if (Clause->getClauseKind() == OMPC_ordered)
4864 OC = cast<OMPOrderedClause>(Clause);
4865 else if (Clause->getClauseKind() == OMPC_linear)
4866 LCs.push_back(cast<OMPLinearClause>(Clause));
4868 // Capture allocator expressions if used.
4869 for (Expr *E : DSAStack->getInnerAllocators())
4870 MarkDeclarationsReferencedInExpr(E);
4871 // OpenMP, 2.7.1 Loop Construct, Restrictions
4872 // The nonmonotonic modifier cannot be specified if an ordered clause is
4873 // specified.
4874 if (SC &&
4875 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4876 SC->getSecondScheduleModifier() ==
4877 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4878 OC) {
4879 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4880 ? SC->getFirstScheduleModifierLoc()
4881 : SC->getSecondScheduleModifierLoc(),
4882 diag::err_omp_simple_clause_incompatible_with_ordered)
4883 << getOpenMPClauseName(OMPC_schedule)
4884 << getOpenMPSimpleClauseTypeName(OMPC_schedule,
4885 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4886 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4887 ErrorFound = true;
4889 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4890 // If an order(concurrent) clause is present, an ordered clause may not appear
4891 // on the same directive.
4892 if (checkOrderedOrderSpecified(*this, Clauses))
4893 ErrorFound = true;
4894 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4895 for (const OMPLinearClause *C : LCs) {
4896 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
4897 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4899 ErrorFound = true;
4901 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4902 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4903 OC->getNumForLoops()) {
4904 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4905 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
4906 ErrorFound = true;
4908 if (ErrorFound) {
4909 return StmtError();
4911 StmtResult SR = S;
4912 unsigned CompletedRegions = 0;
4913 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
4914 // Mark all variables in private list clauses as used in inner region.
4915 // Required for proper codegen of combined directives.
4916 // TODO: add processing for other clauses.
4917 if (ThisCaptureRegion != OMPD_unknown) {
4918 for (const clang::OMPClauseWithPreInit *C : PICs) {
4919 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4920 // Find the particular capture region for the clause if the
4921 // directive is a combined one with multiple capture regions.
4922 // If the directive is not a combined one, the capture region
4923 // associated with the clause is OMPD_unknown and is generated
4924 // only once.
4925 if (CaptureRegion == ThisCaptureRegion ||
4926 CaptureRegion == OMPD_unknown) {
4927 if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
4928 for (Decl *D : DS->decls())
4929 MarkVariableReferenced(D->getLocation(), cast<VarDecl>(D));
4934 if (ThisCaptureRegion == OMPD_target) {
4935 // Capture allocator traits in the target region. They are used implicitly
4936 // and, thus, are not captured by default.
4937 for (OMPClause *C : Clauses) {
4938 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) {
4939 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4940 ++I) {
4941 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4942 if (Expr *E = D.AllocatorTraits)
4943 MarkDeclarationsReferencedInExpr(E);
4945 continue;
4949 if (ThisCaptureRegion == OMPD_parallel) {
4950 // Capture temp arrays for inscan reductions and locals in aligned
4951 // clauses.
4952 for (OMPClause *C : Clauses) {
4953 if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
4954 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4955 continue;
4956 for (Expr *E : RC->copy_array_temps())
4957 MarkDeclarationsReferencedInExpr(E);
4959 if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
4960 for (Expr *E : AC->varlists())
4961 MarkDeclarationsReferencedInExpr(E);
4965 if (++CompletedRegions == CaptureRegions.size())
4966 DSAStack->setBodyComplete();
4967 SR = ActOnCapturedRegionEnd(SR.get());
4969 return SR;
4972 static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4973 OpenMPDirectiveKind CancelRegion,
4974 SourceLocation StartLoc) {
4975 // CancelRegion is only needed for cancel and cancellation_point.
4976 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4977 return false;
4979 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4980 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4981 return false;
4983 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4984 << getOpenMPDirectiveName(CancelRegion);
4985 return true;
4988 static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
4989 OpenMPDirectiveKind CurrentRegion,
4990 const DeclarationNameInfo &CurrentName,
4991 OpenMPDirectiveKind CancelRegion,
4992 OpenMPBindClauseKind BindKind,
4993 SourceLocation StartLoc) {
4994 if (Stack->getCurScope()) {
4995 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
4996 OpenMPDirectiveKind OffendingRegion = ParentRegion;
4997 bool NestingProhibited = false;
4998 bool CloseNesting = true;
4999 bool OrphanSeen = false;
5000 enum {
5001 NoRecommend,
5002 ShouldBeInParallelRegion,
5003 ShouldBeInOrderedRegion,
5004 ShouldBeInTargetRegion,
5005 ShouldBeInTeamsRegion,
5006 ShouldBeInLoopSimdRegion,
5007 } Recommend = NoRecommend;
5008 if (SemaRef.LangOpts.OpenMP >= 51 && Stack->isParentOrderConcurrent() &&
5009 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_loop &&
5010 CurrentRegion != OMPD_parallel &&
5011 !isOpenMPCombinedParallelADirective(CurrentRegion)) {
5012 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order)
5013 << getOpenMPDirectiveName(CurrentRegion);
5014 return true;
5016 if (isOpenMPSimdDirective(ParentRegion) &&
5017 ((SemaRef.LangOpts.OpenMP <= 45 && CurrentRegion != OMPD_ordered) ||
5018 (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion != OMPD_ordered &&
5019 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
5020 CurrentRegion != OMPD_scan))) {
5021 // OpenMP [2.16, Nesting of Regions]
5022 // OpenMP constructs may not be nested inside a simd region.
5023 // OpenMP [2.8.1,simd Construct, Restrictions]
5024 // An ordered construct with the simd clause is the only OpenMP
5025 // construct that can appear in the simd region.
5026 // Allowing a SIMD construct nested in another SIMD construct is an
5027 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
5028 // message.
5029 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
5030 // The only OpenMP constructs that can be encountered during execution of
5031 // a simd region are the atomic construct, the loop construct, the simd
5032 // construct and the ordered construct with the simd clause.
5033 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
5034 ? diag::err_omp_prohibited_region_simd
5035 : diag::warn_omp_nesting_simd)
5036 << (SemaRef.LangOpts.OpenMP >= 50 ? 1 : 0);
5037 return CurrentRegion != OMPD_simd;
5039 if (ParentRegion == OMPD_atomic) {
5040 // OpenMP [2.16, Nesting of Regions]
5041 // OpenMP constructs may not be nested inside an atomic region.
5042 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
5043 return true;
5045 if (CurrentRegion == OMPD_section) {
5046 // OpenMP [2.7.2, sections Construct, Restrictions]
5047 // Orphaned section directives are prohibited. That is, the section
5048 // directives must appear within the sections construct and must not be
5049 // encountered elsewhere in the sections region.
5050 if (ParentRegion != OMPD_sections &&
5051 ParentRegion != OMPD_parallel_sections) {
5052 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
5053 << (ParentRegion != OMPD_unknown)
5054 << getOpenMPDirectiveName(ParentRegion);
5055 return true;
5057 return false;
5059 // Allow some constructs (except teams and cancellation constructs) to be
5060 // orphaned (they could be used in functions, called from OpenMP regions
5061 // with the required preconditions).
5062 if (ParentRegion == OMPD_unknown &&
5063 !isOpenMPNestingTeamsDirective(CurrentRegion) &&
5064 CurrentRegion != OMPD_cancellation_point &&
5065 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
5066 return false;
5067 if (CurrentRegion == OMPD_cancellation_point ||
5068 CurrentRegion == OMPD_cancel) {
5069 // OpenMP [2.16, Nesting of Regions]
5070 // A cancellation point construct for which construct-type-clause is
5071 // taskgroup must be nested inside a task construct. A cancellation
5072 // point construct for which construct-type-clause is not taskgroup must
5073 // be closely nested inside an OpenMP construct that matches the type
5074 // specified in construct-type-clause.
5075 // A cancel construct for which construct-type-clause is taskgroup must be
5076 // nested inside a task construct. A cancel construct for which
5077 // construct-type-clause is not taskgroup must be closely nested inside an
5078 // OpenMP construct that matches the type specified in
5079 // construct-type-clause.
5080 NestingProhibited =
5081 !((CancelRegion == OMPD_parallel &&
5082 (ParentRegion == OMPD_parallel ||
5083 ParentRegion == OMPD_target_parallel)) ||
5084 (CancelRegion == OMPD_for &&
5085 (ParentRegion == OMPD_for || ParentRegion == OMPD_parallel_for ||
5086 ParentRegion == OMPD_target_parallel_for ||
5087 ParentRegion == OMPD_distribute_parallel_for ||
5088 ParentRegion == OMPD_teams_distribute_parallel_for ||
5089 ParentRegion == OMPD_target_teams_distribute_parallel_for)) ||
5090 (CancelRegion == OMPD_taskgroup &&
5091 (ParentRegion == OMPD_task ||
5092 (SemaRef.getLangOpts().OpenMP >= 50 &&
5093 (ParentRegion == OMPD_taskloop ||
5094 ParentRegion == OMPD_master_taskloop ||
5095 ParentRegion == OMPD_masked_taskloop ||
5096 ParentRegion == OMPD_parallel_masked_taskloop ||
5097 ParentRegion == OMPD_parallel_master_taskloop)))) ||
5098 (CancelRegion == OMPD_sections &&
5099 (ParentRegion == OMPD_section || ParentRegion == OMPD_sections ||
5100 ParentRegion == OMPD_parallel_sections)));
5101 OrphanSeen = ParentRegion == OMPD_unknown;
5102 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5103 // OpenMP 5.1 [2.22, Nesting of Regions]
5104 // A masked region may not be closely nested inside a worksharing, loop,
5105 // atomic, task, or taskloop region.
5106 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5107 isOpenMPGenericLoopDirective(ParentRegion) ||
5108 isOpenMPTaskingDirective(ParentRegion);
5109 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
5110 // OpenMP [2.16, Nesting of Regions]
5111 // A critical region may not be nested (closely or otherwise) inside a
5112 // critical region with the same name. Note that this restriction is not
5113 // sufficient to prevent deadlock.
5114 SourceLocation PreviousCriticalLoc;
5115 bool DeadLock = Stack->hasDirective(
5116 [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
5117 const DeclarationNameInfo &DNI,
5118 SourceLocation Loc) {
5119 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
5120 PreviousCriticalLoc = Loc;
5121 return true;
5123 return false;
5125 false /* skip top directive */);
5126 if (DeadLock) {
5127 SemaRef.Diag(StartLoc,
5128 diag::err_omp_prohibited_region_critical_same_name)
5129 << CurrentName.getName();
5130 if (PreviousCriticalLoc.isValid())
5131 SemaRef.Diag(PreviousCriticalLoc,
5132 diag::note_omp_previous_critical_region);
5133 return true;
5135 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
5136 // OpenMP 5.1 [2.22, Nesting of Regions]
5137 // A scope region may not be closely nested inside a worksharing, loop,
5138 // task, taskloop, critical, ordered, atomic, or masked region.
5139 // OpenMP 5.1 [2.22, Nesting of Regions]
5140 // A barrier region may not be closely nested inside a worksharing, loop,
5141 // task, taskloop, critical, ordered, atomic, or masked region.
5142 NestingProhibited =
5143 isOpenMPWorksharingDirective(ParentRegion) ||
5144 isOpenMPGenericLoopDirective(ParentRegion) ||
5145 isOpenMPTaskingDirective(ParentRegion) ||
5146 ParentRegion == OMPD_master || ParentRegion == OMPD_masked ||
5147 ParentRegion == OMPD_parallel_master ||
5148 ParentRegion == OMPD_parallel_masked ||
5149 ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
5150 } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
5151 !isOpenMPParallelDirective(CurrentRegion) &&
5152 !isOpenMPTeamsDirective(CurrentRegion)) {
5153 // OpenMP 5.1 [2.22, Nesting of Regions]
5154 // A loop region that binds to a parallel region or a worksharing region
5155 // may not be closely nested inside a worksharing, loop, task, taskloop,
5156 // critical, ordered, atomic, or masked region.
5157 NestingProhibited =
5158 isOpenMPWorksharingDirective(ParentRegion) ||
5159 isOpenMPGenericLoopDirective(ParentRegion) ||
5160 isOpenMPTaskingDirective(ParentRegion) ||
5161 ParentRegion == OMPD_master || ParentRegion == OMPD_masked ||
5162 ParentRegion == OMPD_parallel_master ||
5163 ParentRegion == OMPD_parallel_masked ||
5164 ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
5165 Recommend = ShouldBeInParallelRegion;
5166 } else if (CurrentRegion == OMPD_ordered) {
5167 // OpenMP [2.16, Nesting of Regions]
5168 // An ordered region may not be closely nested inside a critical,
5169 // atomic, or explicit task region.
5170 // An ordered region must be closely nested inside a loop region (or
5171 // parallel loop region) with an ordered clause.
5172 // OpenMP [2.8.1,simd Construct, Restrictions]
5173 // An ordered construct with the simd clause is the only OpenMP construct
5174 // that can appear in the simd region.
5175 NestingProhibited = ParentRegion == OMPD_critical ||
5176 isOpenMPTaskingDirective(ParentRegion) ||
5177 !(isOpenMPSimdDirective(ParentRegion) ||
5178 Stack->isParentOrderedRegion());
5179 Recommend = ShouldBeInOrderedRegion;
5180 } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
5181 // OpenMP [2.16, Nesting of Regions]
5182 // If specified, a teams construct must be contained within a target
5183 // construct.
5184 NestingProhibited =
5185 (SemaRef.LangOpts.OpenMP <= 45 && ParentRegion != OMPD_target) ||
5186 (SemaRef.LangOpts.OpenMP >= 50 && ParentRegion != OMPD_unknown &&
5187 ParentRegion != OMPD_target);
5188 OrphanSeen = ParentRegion == OMPD_unknown;
5189 Recommend = ShouldBeInTargetRegion;
5190 } else if (CurrentRegion == OMPD_scan) {
5191 // OpenMP [2.16, Nesting of Regions]
5192 // If specified, a teams construct must be contained within a target
5193 // construct.
5194 NestingProhibited =
5195 SemaRef.LangOpts.OpenMP < 50 ||
5196 (ParentRegion != OMPD_simd && ParentRegion != OMPD_for &&
5197 ParentRegion != OMPD_for_simd && ParentRegion != OMPD_parallel_for &&
5198 ParentRegion != OMPD_parallel_for_simd);
5199 OrphanSeen = ParentRegion == OMPD_unknown;
5200 Recommend = ShouldBeInLoopSimdRegion;
5202 if (!NestingProhibited &&
5203 !isOpenMPTargetExecutionDirective(CurrentRegion) &&
5204 !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
5205 (ParentRegion == OMPD_teams || ParentRegion == OMPD_target_teams)) {
5206 // OpenMP [5.1, 2.22, Nesting of Regions]
5207 // distribute, distribute simd, distribute parallel worksharing-loop,
5208 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5209 // including any parallel regions arising from combined constructs,
5210 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5211 // only OpenMP regions that may be strictly nested inside the teams
5212 // region.
5214 // As an extension, we permit atomic within teams as well.
5215 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
5216 !isOpenMPDistributeDirective(CurrentRegion) &&
5217 CurrentRegion != OMPD_loop &&
5218 !(SemaRef.getLangOpts().OpenMPExtensions &&
5219 CurrentRegion == OMPD_atomic);
5220 Recommend = ShouldBeInParallelRegion;
5222 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5223 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5224 // If the bind clause is present on the loop construct and binding is
5225 // teams then the corresponding loop region must be strictly nested inside
5226 // a teams region.
5227 NestingProhibited = BindKind == OMPC_BIND_teams &&
5228 ParentRegion != OMPD_teams &&
5229 ParentRegion != OMPD_target_teams;
5230 Recommend = ShouldBeInTeamsRegion;
5232 if (!NestingProhibited &&
5233 isOpenMPNestingDistributeDirective(CurrentRegion)) {
5234 // OpenMP 4.5 [2.17 Nesting of Regions]
5235 // The region associated with the distribute construct must be strictly
5236 // nested inside a teams region
5237 NestingProhibited =
5238 (ParentRegion != OMPD_teams && ParentRegion != OMPD_target_teams);
5239 Recommend = ShouldBeInTeamsRegion;
5241 if (!NestingProhibited &&
5242 (isOpenMPTargetExecutionDirective(CurrentRegion) ||
5243 isOpenMPTargetDataManagementDirective(CurrentRegion))) {
5244 // OpenMP 4.5 [2.17 Nesting of Regions]
5245 // If a target, target update, target data, target enter data, or
5246 // target exit data construct is encountered during execution of a
5247 // target region, the behavior is unspecified.
5248 NestingProhibited = Stack->hasDirective(
5249 [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5250 SourceLocation) {
5251 if (isOpenMPTargetExecutionDirective(K)) {
5252 OffendingRegion = K;
5253 return true;
5255 return false;
5257 false /* don't skip top directive */);
5258 CloseNesting = false;
5260 if (NestingProhibited) {
5261 if (OrphanSeen) {
5262 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5263 << getOpenMPDirectiveName(CurrentRegion) << Recommend;
5264 } else {
5265 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5266 << CloseNesting << getOpenMPDirectiveName(OffendingRegion)
5267 << Recommend << getOpenMPDirectiveName(CurrentRegion);
5269 return true;
5272 return false;
5275 struct Kind2Unsigned {
5276 using argument_type = OpenMPDirectiveKind;
5277 unsigned operator()(argument_type DK) { return unsigned(DK); }
5279 static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind,
5280 ArrayRef<OMPClause *> Clauses,
5281 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5282 bool ErrorFound = false;
5283 unsigned NamedModifiersNumber = 0;
5284 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5285 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5286 SmallVector<SourceLocation, 4> NameModifierLoc;
5287 for (const OMPClause *C : Clauses) {
5288 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
5289 // At most one if clause without a directive-name-modifier can appear on
5290 // the directive.
5291 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5292 if (FoundNameModifiers[CurNM]) {
5293 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5294 << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if)
5295 << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM);
5296 ErrorFound = true;
5297 } else if (CurNM != OMPD_unknown) {
5298 NameModifierLoc.push_back(IC->getNameModifierLoc());
5299 ++NamedModifiersNumber;
5301 FoundNameModifiers[CurNM] = IC;
5302 if (CurNM == OMPD_unknown)
5303 continue;
5304 // Check if the specified name modifier is allowed for the current
5305 // directive.
5306 // At most one if clause with the particular directive-name-modifier can
5307 // appear on the directive.
5308 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5309 S.Diag(IC->getNameModifierLoc(),
5310 diag::err_omp_wrong_if_directive_name_modifier)
5311 << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind);
5312 ErrorFound = true;
5316 // If any if clause on the directive includes a directive-name-modifier then
5317 // all if clauses on the directive must include a directive-name-modifier.
5318 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5319 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5320 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5321 diag::err_omp_no_more_if_clause);
5322 } else {
5323 std::string Values;
5324 std::string Sep(", ");
5325 unsigned AllowedCnt = 0;
5326 unsigned TotalAllowedNum =
5327 AllowedNameModifiers.size() - NamedModifiersNumber;
5328 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5329 ++Cnt) {
5330 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5331 if (!FoundNameModifiers[NM]) {
5332 Values += "'";
5333 Values += getOpenMPDirectiveName(NM);
5334 Values += "'";
5335 if (AllowedCnt + 2 == TotalAllowedNum)
5336 Values += " or ";
5337 else if (AllowedCnt + 1 != TotalAllowedNum)
5338 Values += Sep;
5339 ++AllowedCnt;
5342 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5343 diag::err_omp_unnamed_if_clause)
5344 << (TotalAllowedNum > 1) << Values;
5346 for (SourceLocation Loc : NameModifierLoc) {
5347 S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5349 ErrorFound = true;
5351 return ErrorFound;
5354 static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr,
5355 SourceLocation &ELoc,
5356 SourceRange &ERange,
5357 bool AllowArraySection,
5358 StringRef DiagType) {
5359 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5360 RefExpr->containsUnexpandedParameterPack())
5361 return std::make_pair(nullptr, true);
5363 // OpenMP [3.1, C/C++]
5364 // A list item is a variable name.
5365 // OpenMP [2.9.3.3, Restrictions, p.1]
5366 // A variable that is part of another variable (as an array or
5367 // structure element) cannot appear in a private clause.
5368 RefExpr = RefExpr->IgnoreParens();
5369 enum {
5370 NoArrayExpr = -1,
5371 ArraySubscript = 0,
5372 OMPArraySection = 1
5373 } IsArrayExpr = NoArrayExpr;
5374 if (AllowArraySection) {
5375 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5376 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5377 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5378 Base = TempASE->getBase()->IgnoreParenImpCasts();
5379 RefExpr = Base;
5380 IsArrayExpr = ArraySubscript;
5381 } else if (auto *OASE = dyn_cast_or_null<OMPArraySectionExpr>(RefExpr)) {
5382 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5383 while (auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
5384 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5385 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5386 Base = TempASE->getBase()->IgnoreParenImpCasts();
5387 RefExpr = Base;
5388 IsArrayExpr = OMPArraySection;
5391 ELoc = RefExpr->getExprLoc();
5392 ERange = RefExpr->getSourceRange();
5393 RefExpr = RefExpr->IgnoreParenImpCasts();
5394 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5395 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5396 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5397 (S.getCurrentThisType().isNull() || !ME ||
5398 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5399 !isa<FieldDecl>(ME->getMemberDecl()))) {
5400 if (IsArrayExpr != NoArrayExpr) {
5401 S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5402 << IsArrayExpr << ERange;
5403 } else if (!DiagType.empty()) {
5404 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5405 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5406 : 0;
5407 S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5408 << DiagSelect << DiagType << ERange;
5409 } else {
5410 S.Diag(ELoc,
5411 AllowArraySection
5412 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5413 : diag::err_omp_expected_var_name_member_expr)
5414 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5416 return std::make_pair(nullptr, false);
5418 return std::make_pair(
5419 getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
5422 namespace {
5423 /// Checks if the allocator is used in uses_allocators clause to be allowed in
5424 /// target regions.
5425 class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5426 DSAStackTy *S = nullptr;
5428 public:
5429 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5430 return S->isUsesAllocatorsDecl(E->getDecl())
5431 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5432 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5434 bool VisitStmt(const Stmt *S) {
5435 for (const Stmt *Child : S->children()) {
5436 if (Child && Visit(Child))
5437 return true;
5439 return false;
5441 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5443 } // namespace
5445 static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5446 ArrayRef<OMPClause *> Clauses) {
5447 assert(!S.CurContext->isDependentContext() &&
5448 "Expected non-dependent context.");
5449 auto AllocateRange =
5450 llvm::make_filter_range(Clauses, OMPAllocateClause::classof);
5451 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5452 auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) {
5453 return isOpenMPPrivate(C->getClauseKind());
5455 for (OMPClause *Cl : PrivateRange) {
5456 MutableArrayRef<Expr *>::iterator I, It, Et;
5457 if (Cl->getClauseKind() == OMPC_private) {
5458 auto *PC = cast<OMPPrivateClause>(Cl);
5459 I = PC->private_copies().begin();
5460 It = PC->varlist_begin();
5461 Et = PC->varlist_end();
5462 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5463 auto *PC = cast<OMPFirstprivateClause>(Cl);
5464 I = PC->private_copies().begin();
5465 It = PC->varlist_begin();
5466 Et = PC->varlist_end();
5467 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5468 auto *PC = cast<OMPLastprivateClause>(Cl);
5469 I = PC->private_copies().begin();
5470 It = PC->varlist_begin();
5471 Et = PC->varlist_end();
5472 } else if (Cl->getClauseKind() == OMPC_linear) {
5473 auto *PC = cast<OMPLinearClause>(Cl);
5474 I = PC->privates().begin();
5475 It = PC->varlist_begin();
5476 Et = PC->varlist_end();
5477 } else if (Cl->getClauseKind() == OMPC_reduction) {
5478 auto *PC = cast<OMPReductionClause>(Cl);
5479 I = PC->privates().begin();
5480 It = PC->varlist_begin();
5481 Et = PC->varlist_end();
5482 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5483 auto *PC = cast<OMPTaskReductionClause>(Cl);
5484 I = PC->privates().begin();
5485 It = PC->varlist_begin();
5486 Et = PC->varlist_end();
5487 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5488 auto *PC = cast<OMPInReductionClause>(Cl);
5489 I = PC->privates().begin();
5490 It = PC->varlist_begin();
5491 Et = PC->varlist_end();
5492 } else {
5493 llvm_unreachable("Expected private clause.");
5495 for (Expr *E : llvm::make_range(It, Et)) {
5496 if (!*I) {
5497 ++I;
5498 continue;
5500 SourceLocation ELoc;
5501 SourceRange ERange;
5502 Expr *SimpleRefExpr = E;
5503 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
5504 /*AllowArraySection=*/true);
5505 DeclToCopy.try_emplace(Res.first,
5506 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5507 ++I;
5510 for (OMPClause *C : AllocateRange) {
5511 auto *AC = cast<OMPAllocateClause>(C);
5512 if (S.getLangOpts().OpenMP >= 50 &&
5513 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5514 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
5515 AC->getAllocator()) {
5516 Expr *Allocator = AC->getAllocator();
5517 // OpenMP, 2.12.5 target Construct
5518 // Memory allocators that do not appear in a uses_allocators clause cannot
5519 // appear as an allocator in an allocate clause or be used in the target
5520 // region unless a requires directive with the dynamic_allocators clause
5521 // is present in the same compilation unit.
5522 AllocatorChecker Checker(Stack);
5523 if (Checker.Visit(Allocator))
5524 S.Diag(Allocator->getExprLoc(),
5525 diag::err_omp_allocator_not_in_uses_allocators)
5526 << Allocator->getSourceRange();
5528 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5529 getAllocatorKind(S, Stack, AC->getAllocator());
5530 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5531 // For task, taskloop or target directives, allocation requests to memory
5532 // allocators with the trait access set to thread result in unspecified
5533 // behavior.
5534 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5535 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
5536 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
5537 S.Diag(AC->getAllocator()->getExprLoc(),
5538 diag::warn_omp_allocate_thread_on_task_target_directive)
5539 << getOpenMPDirectiveName(Stack->getCurrentDirective());
5541 for (Expr *E : AC->varlists()) {
5542 SourceLocation ELoc;
5543 SourceRange ERange;
5544 Expr *SimpleRefExpr = E;
5545 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
5546 ValueDecl *VD = Res.first;
5547 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
5548 if (!isOpenMPPrivate(Data.CKind)) {
5549 S.Diag(E->getExprLoc(),
5550 diag::err_omp_expected_private_copy_for_allocate);
5551 continue;
5553 VarDecl *PrivateVD = DeclToCopy[VD];
5554 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5555 AllocatorKind, AC->getAllocator()))
5556 continue;
5557 // Placeholder until allocate clause supports align modifier.
5558 Expr *Alignment = nullptr;
5559 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5560 Alignment, E->getSourceRange());
5565 namespace {
5566 /// Rewrite statements and expressions for Sema \p Actions CurContext.
5568 /// Used to wrap already parsed statements/expressions into a new CapturedStmt
5569 /// context. DeclRefExpr used inside the new context are changed to refer to the
5570 /// captured variable instead.
5571 class CaptureVars : public TreeTransform<CaptureVars> {
5572 using BaseTransform = TreeTransform<CaptureVars>;
5574 public:
5575 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5577 bool AlwaysRebuild() { return true; }
5579 } // namespace
5581 static VarDecl *precomputeExpr(Sema &Actions,
5582 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5583 StringRef Name) {
5584 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
5585 VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
5586 dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
5587 auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
5588 Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
5589 Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
5590 BodyStmts.push_back(NewDeclStmt);
5591 return NewVar;
5594 /// Create a closure that computes the number of iterations of a loop.
5596 /// \param Actions The Sema object.
5597 /// \param LogicalTy Type for the logical iteration number.
5598 /// \param Rel Comparison operator of the loop condition.
5599 /// \param StartExpr Value of the loop counter at the first iteration.
5600 /// \param StopExpr Expression the loop counter is compared against in the loop
5601 /// condition. \param StepExpr Amount of increment after each iteration.
5603 /// \return Closure (CapturedStmt) of the distance calculation.
5604 static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5605 BinaryOperator::Opcode Rel,
5606 Expr *StartExpr, Expr *StopExpr,
5607 Expr *StepExpr) {
5608 ASTContext &Ctx = Actions.getASTContext();
5609 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
5611 // Captured regions currently don't support return values, we use an
5612 // out-parameter instead. All inputs are implicit captures.
5613 // TODO: Instead of capturing each DeclRefExpr occurring in
5614 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5615 QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
5616 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5617 {StringRef(), QualType()}};
5618 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5620 Stmt *Body;
5622 Sema::CompoundScopeRAII CompoundScope(Actions);
5623 CapturedDecl *CS = cast<CapturedDecl>(Actions.CurContext);
5625 // Get the LValue expression for the result.
5626 ImplicitParamDecl *DistParam = CS->getParam(0);
5627 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5628 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5630 SmallVector<Stmt *, 4> BodyStmts;
5632 // Capture all referenced variable references.
5633 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5634 // CapturedStmt, we could compute them before and capture the result, to be
5635 // used jointly with the LoopVar function.
5636 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
5637 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
5638 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
5639 auto BuildVarRef = [&](VarDecl *VD) {
5640 return buildDeclRefExpr(Actions, VD, VD->getType(), {});
5643 IntegerLiteral *Zero = IntegerLiteral::Create(
5644 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
5645 IntegerLiteral *One = IntegerLiteral::Create(
5646 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5647 Expr *Dist;
5648 if (Rel == BO_NE) {
5649 // When using a != comparison, the increment can be +1 or -1. This can be
5650 // dynamic at runtime, so we need to check for the direction.
5651 Expr *IsNegStep = AssertSuccess(
5652 Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5654 // Positive increment.
5655 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
5656 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5657 ForwardRange = AssertSuccess(
5658 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
5659 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
5660 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5662 // Negative increment.
5663 Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
5664 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5665 BackwardRange = AssertSuccess(
5666 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange));
5667 Expr *NegIncAmount = AssertSuccess(
5668 Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5669 Expr *BackwardDist = AssertSuccess(
5670 Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5672 // Use the appropriate case.
5673 Dist = AssertSuccess(Actions.ActOnConditionalOp(
5674 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5675 } else {
5676 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5677 "Expected one of these relational operators");
5679 // We can derive the direction from any other comparison operator. It is
5680 // non well-formed OpenMP if Step increments/decrements in the other
5681 // directions. Whether at least the first iteration passes the loop
5682 // condition.
5683 Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
5684 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5686 // Compute the range between first and last counter value.
5687 Expr *Range;
5688 if (Rel == BO_GE || Rel == BO_GT)
5689 Range = AssertSuccess(Actions.BuildBinOp(
5690 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5691 else
5692 Range = AssertSuccess(Actions.BuildBinOp(
5693 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5695 // Ensure unsigned range space.
5696 Range =
5697 AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range));
5699 if (Rel == BO_LE || Rel == BO_GE) {
5700 // Add one to the range if the relational operator is inclusive.
5701 Range =
5702 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One));
5705 // Divide by the absolute step amount. If the range is not a multiple of
5706 // the step size, rounding-up the effective upper bound ensures that the
5707 // last iteration is included.
5708 // Note that the rounding-up may cause an overflow in a temporry that
5709 // could be avoided, but would have occurred in a C-style for-loop as
5710 // well.
5711 Expr *Divisor = BuildVarRef(NewStep);
5712 if (Rel == BO_GE || Rel == BO_GT)
5713 Divisor =
5714 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor));
5715 Expr *DivisorMinusOne =
5716 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One));
5717 Expr *RangeRoundUp = AssertSuccess(
5718 Actions.BuildBinOp(nullptr, {}, BO_Add, Range, DivisorMinusOne));
5719 Dist = AssertSuccess(
5720 Actions.BuildBinOp(nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5722 // If there is not at least one iteration, the range contains garbage. Fix
5723 // to zero in this case.
5724 Dist = AssertSuccess(
5725 Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
5728 // Assign the result to the out-parameter.
5729 Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp(
5730 Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
5731 BodyStmts.push_back(ResultAssign);
5733 Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false));
5736 return cast<CapturedStmt>(
5737 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5740 /// Create a closure that computes the loop variable from the logical iteration
5741 /// number.
5743 /// \param Actions The Sema object.
5744 /// \param LoopVarTy Type for the loop variable used for result value.
5745 /// \param LogicalTy Type for the logical iteration number.
5746 /// \param StartExpr Value of the loop counter at the first iteration.
5747 /// \param Step Amount of increment after each iteration.
5748 /// \param Deref Whether the loop variable is a dereference of the loop
5749 /// counter variable.
5751 /// \return Closure (CapturedStmt) of the loop value calculation.
5752 static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5753 QualType LogicalTy,
5754 DeclRefExpr *StartExpr, Expr *Step,
5755 bool Deref) {
5756 ASTContext &Ctx = Actions.getASTContext();
5758 // Pass the result as an out-parameter. Passing as return value would require
5759 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5760 // invoke a copy constructor.
5761 QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy);
5762 Sema::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5763 {"Logical", LogicalTy},
5764 {StringRef(), QualType()}};
5765 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5767 // Capture the initial iterator which represents the LoopVar value at the
5768 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5769 // it in every iteration, capture it by value before it is modified.
5770 VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl());
5771 bool Invalid = Actions.tryCaptureVariable(StartVar, {},
5772 Sema::TryCapture_ExplicitByVal, {});
5773 (void)Invalid;
5774 assert(!Invalid && "Expecting capture-by-value to work.");
5776 Expr *Body;
5778 Sema::CompoundScopeRAII CompoundScope(Actions);
5779 auto *CS = cast<CapturedDecl>(Actions.CurContext);
5781 ImplicitParamDecl *TargetParam = CS->getParam(0);
5782 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5783 TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5784 ImplicitParamDecl *IndvarParam = CS->getParam(1);
5785 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5786 IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5788 // Capture the Start expression.
5789 CaptureVars Recap(Actions);
5790 Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
5791 Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
5793 Expr *Skip = AssertSuccess(
5794 Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
5795 // TODO: Explicitly cast to the iterator's difference_type instead of
5796 // relying on implicit conversion.
5797 Expr *Advanced =
5798 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip));
5800 if (Deref) {
5801 // For range-based for-loops convert the loop counter value to a concrete
5802 // loop variable value by dereferencing the iterator.
5803 Advanced =
5804 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced));
5807 // Assign the result to the output parameter.
5808 Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {},
5809 BO_Assign, TargetRef, Advanced));
5811 return cast<CapturedStmt>(
5812 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5815 StmtResult Sema::ActOnOpenMPCanonicalLoop(Stmt *AStmt) {
5816 ASTContext &Ctx = getASTContext();
5818 // Extract the common elements of ForStmt and CXXForRangeStmt:
5819 // Loop variable, repeat condition, increment
5820 Expr *Cond, *Inc;
5821 VarDecl *LIVDecl, *LUVDecl;
5822 if (auto *For = dyn_cast<ForStmt>(AStmt)) {
5823 Stmt *Init = For->getInit();
5824 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) {
5825 // For statement declares loop variable.
5826 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5827 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) {
5828 // For statement reuses variable.
5829 assert(LCAssign->getOpcode() == BO_Assign &&
5830 "init part must be a loop variable assignment");
5831 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5832 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5833 } else
5834 llvm_unreachable("Cannot determine loop variable");
5835 LUVDecl = LIVDecl;
5837 Cond = For->getCond();
5838 Inc = For->getInc();
5839 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5840 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5841 LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl());
5842 LUVDecl = RangeFor->getLoopVariable();
5844 Cond = RangeFor->getCond();
5845 Inc = RangeFor->getInc();
5846 } else
5847 llvm_unreachable("unhandled kind of loop");
5849 QualType CounterTy = LIVDecl->getType();
5850 QualType LVTy = LUVDecl->getType();
5852 // Analyze the loop condition.
5853 Expr *LHS, *RHS;
5854 BinaryOperator::Opcode CondRel;
5855 Cond = Cond->IgnoreImplicit();
5856 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5857 LHS = CondBinExpr->getLHS();
5858 RHS = CondBinExpr->getRHS();
5859 CondRel = CondBinExpr->getOpcode();
5860 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5861 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5862 LHS = CondCXXOp->getArg(0);
5863 RHS = CondCXXOp->getArg(1);
5864 switch (CondCXXOp->getOperator()) {
5865 case OO_ExclaimEqual:
5866 CondRel = BO_NE;
5867 break;
5868 case OO_Less:
5869 CondRel = BO_LT;
5870 break;
5871 case OO_LessEqual:
5872 CondRel = BO_LE;
5873 break;
5874 case OO_Greater:
5875 CondRel = BO_GT;
5876 break;
5877 case OO_GreaterEqual:
5878 CondRel = BO_GE;
5879 break;
5880 default:
5881 llvm_unreachable("unexpected iterator operator");
5883 } else
5884 llvm_unreachable("unexpected loop condition");
5886 // Normalize such that the loop counter is on the LHS.
5887 if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) ||
5888 cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5889 std::swap(LHS, RHS);
5890 CondRel = BinaryOperator::reverseComparisonOp(CondRel);
5892 auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit());
5894 // Decide the bit width for the logical iteration counter. By default use the
5895 // unsigned ptrdiff_t integer size (for iterators and pointers).
5896 // TODO: For iterators, use iterator::difference_type,
5897 // std::iterator_traits<>::difference_type or decltype(it - end).
5898 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5899 if (CounterTy->isIntegerType()) {
5900 unsigned BitWidth = Ctx.getIntWidth(CounterTy);
5901 LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false);
5904 // Analyze the loop increment.
5905 Expr *Step;
5906 if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5907 int Direction;
5908 switch (IncUn->getOpcode()) {
5909 case UO_PreInc:
5910 case UO_PostInc:
5911 Direction = 1;
5912 break;
5913 case UO_PreDec:
5914 case UO_PostDec:
5915 Direction = -1;
5916 break;
5917 default:
5918 llvm_unreachable("unhandled unary increment operator");
5920 Step = IntegerLiteral::Create(
5921 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction), LogicalTy, {});
5922 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5923 if (IncBin->getOpcode() == BO_AddAssign) {
5924 Step = IncBin->getRHS();
5925 } else if (IncBin->getOpcode() == BO_SubAssign) {
5926 Step =
5927 AssertSuccess(BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS()));
5928 } else
5929 llvm_unreachable("unhandled binary increment operator");
5930 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5931 switch (CondCXXOp->getOperator()) {
5932 case OO_PlusPlus:
5933 Step = IntegerLiteral::Create(
5934 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5935 break;
5936 case OO_MinusMinus:
5937 Step = IntegerLiteral::Create(
5938 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
5939 break;
5940 case OO_PlusEqual:
5941 Step = CondCXXOp->getArg(1);
5942 break;
5943 case OO_MinusEqual:
5944 Step = AssertSuccess(
5945 BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5946 break;
5947 default:
5948 llvm_unreachable("unhandled overloaded increment operator");
5950 } else
5951 llvm_unreachable("unknown increment expression");
5953 CapturedStmt *DistanceFunc =
5954 buildDistanceFunc(*this, LogicalTy, CondRel, LHS, RHS, Step);
5955 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
5956 *this, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
5957 DeclRefExpr *LVRef = BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue,
5958 {}, nullptr, nullptr, {}, nullptr);
5959 return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc,
5960 LoopVarFunc, LVRef);
5963 StmtResult Sema::ActOnOpenMPLoopnest(Stmt *AStmt) {
5964 // Handle a literal loop.
5965 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
5966 return ActOnOpenMPCanonicalLoop(AStmt);
5968 // If not a literal loop, it must be the result of a loop transformation.
5969 OMPExecutableDirective *LoopTransform = cast<OMPExecutableDirective>(AStmt);
5970 assert(
5971 isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) &&
5972 "Loop transformation directive expected");
5973 return LoopTransform;
5976 static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
5977 CXXScopeSpec &MapperIdScopeSpec,
5978 const DeclarationNameInfo &MapperId,
5979 QualType Type,
5980 Expr *UnresolvedMapper);
5982 /// Perform DFS through the structure/class data members trying to find
5983 /// member(s) with user-defined 'default' mapper and generate implicit map
5984 /// clauses for such members with the found 'default' mapper.
5985 static void
5986 processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack,
5987 SmallVectorImpl<OMPClause *> &Clauses) {
5988 // Check for the deault mapper for data members.
5989 if (S.getLangOpts().OpenMP < 50)
5990 return;
5991 SmallVector<OMPClause *, 4> ImplicitMaps;
5992 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
5993 auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
5994 if (!C)
5995 continue;
5996 SmallVector<Expr *, 4> SubExprs;
5997 auto *MI = C->mapperlist_begin();
5998 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
5999 ++I, ++MI) {
6000 // Expression is mapped using mapper - skip it.
6001 if (*MI)
6002 continue;
6003 Expr *E = *I;
6004 // Expression is dependent - skip it, build the mapper when it gets
6005 // instantiated.
6006 if (E->isTypeDependent() || E->isValueDependent() ||
6007 E->containsUnexpandedParameterPack())
6008 continue;
6009 // Array section - need to check for the mapping of the array section
6010 // element.
6011 QualType CanonType = E->getType().getCanonicalType();
6012 if (CanonType->isSpecificBuiltinType(BuiltinType::OMPArraySection)) {
6013 const auto *OASE = cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts());
6014 QualType BaseType =
6015 OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
6016 QualType ElemType;
6017 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
6018 ElemType = ATy->getElementType();
6019 else
6020 ElemType = BaseType->getPointeeType();
6021 CanonType = ElemType;
6024 // DFS over data members in structures/classes.
6025 SmallVector<std::pair<QualType, FieldDecl *>, 4> Types(
6026 1, {CanonType, nullptr});
6027 llvm::DenseMap<const Type *, Expr *> Visited;
6028 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(
6029 1, {nullptr, 1});
6030 while (!Types.empty()) {
6031 QualType BaseType;
6032 FieldDecl *CurFD;
6033 std::tie(BaseType, CurFD) = Types.pop_back_val();
6034 while (ParentChain.back().second == 0)
6035 ParentChain.pop_back();
6036 --ParentChain.back().second;
6037 if (BaseType.isNull())
6038 continue;
6039 // Only structs/classes are allowed to have mappers.
6040 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
6041 if (!RD)
6042 continue;
6043 auto It = Visited.find(BaseType.getTypePtr());
6044 if (It == Visited.end()) {
6045 // Try to find the associated user-defined mapper.
6046 CXXScopeSpec MapperIdScopeSpec;
6047 DeclarationNameInfo DefaultMapperId;
6048 DefaultMapperId.setName(S.Context.DeclarationNames.getIdentifier(
6049 &S.Context.Idents.get("default")));
6050 DefaultMapperId.setLoc(E->getExprLoc());
6051 ExprResult ER = buildUserDefinedMapperRef(
6052 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
6053 BaseType, /*UnresolvedMapper=*/nullptr);
6054 if (ER.isInvalid())
6055 continue;
6056 It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first;
6058 // Found default mapper.
6059 if (It->second) {
6060 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
6061 VK_LValue, OK_Ordinary, E);
6062 OE->setIsUnique(/*V=*/true);
6063 Expr *BaseExpr = OE;
6064 for (const auto &P : ParentChain) {
6065 if (P.first) {
6066 BaseExpr = S.BuildMemberExpr(
6067 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6068 NestedNameSpecifierLoc(), SourceLocation(), P.first,
6069 DeclAccessPair::make(P.first, P.first->getAccess()),
6070 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6071 P.first->getType(), VK_LValue, OK_Ordinary);
6072 BaseExpr = S.DefaultLvalueConversion(BaseExpr).get();
6075 if (CurFD)
6076 BaseExpr = S.BuildMemberExpr(
6077 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6078 NestedNameSpecifierLoc(), SourceLocation(), CurFD,
6079 DeclAccessPair::make(CurFD, CurFD->getAccess()),
6080 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6081 CurFD->getType(), VK_LValue, OK_Ordinary);
6082 SubExprs.push_back(BaseExpr);
6083 continue;
6085 // Check for the "default" mapper for data members.
6086 bool FirstIter = true;
6087 for (FieldDecl *FD : RD->fields()) {
6088 if (!FD)
6089 continue;
6090 QualType FieldTy = FD->getType();
6091 if (FieldTy.isNull() ||
6092 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
6093 continue;
6094 if (FirstIter) {
6095 FirstIter = false;
6096 ParentChain.emplace_back(CurFD, 1);
6097 } else {
6098 ++ParentChain.back().second;
6100 Types.emplace_back(FieldTy, FD);
6104 if (SubExprs.empty())
6105 continue;
6106 CXXScopeSpec MapperIdScopeSpec;
6107 DeclarationNameInfo MapperId;
6108 if (OMPClause *NewClause = S.ActOnOpenMPMapClause(
6109 nullptr, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(),
6110 MapperIdScopeSpec, MapperId, C->getMapType(),
6111 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6112 SubExprs, OMPVarListLocTy()))
6113 Clauses.push_back(NewClause);
6117 bool Sema::mapLoopConstruct(llvm::SmallVector<OMPClause *> &ClausesWithoutBind,
6118 ArrayRef<OMPClause *> Clauses,
6119 OpenMPBindClauseKind BindKind,
6120 OpenMPDirectiveKind &Kind,
6121 OpenMPDirectiveKind &PrevMappedDirective) {
6123 bool UseClausesWithoutBind = false;
6125 // Restricting to "#pragma omp loop bind"
6126 if (getLangOpts().OpenMP >= 50 && Kind == OMPD_loop) {
6127 if (BindKind == OMPC_BIND_unknown) {
6128 // Setting the enclosing teams or parallel construct for the loop
6129 // directive without bind clause.
6130 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
6132 const OpenMPDirectiveKind ParentDirective =
6133 DSAStack->getParentDirective();
6134 if (ParentDirective == OMPD_unknown) {
6135 Diag(DSAStack->getDefaultDSALocation(),
6136 diag::err_omp_bind_required_on_loop);
6137 } else if (ParentDirective == OMPD_parallel ||
6138 ParentDirective == OMPD_target_parallel) {
6139 BindKind = OMPC_BIND_parallel;
6140 } else if (ParentDirective == OMPD_teams ||
6141 ParentDirective == OMPD_target_teams) {
6142 BindKind = OMPC_BIND_teams;
6144 } else {
6145 // bind clause is present, so we should set flag indicating to only
6146 // use the clauses that aren't the bind clause for the new directive that
6147 // loop is lowered to.
6148 UseClausesWithoutBind = true;
6151 for (OMPClause *C : Clauses) {
6152 // Spec restriction : bind(teams) and reduction not permitted.
6153 if (BindKind == OMPC_BIND_teams &&
6154 C->getClauseKind() == llvm::omp::Clause::OMPC_reduction)
6155 Diag(DSAStack->getDefaultDSALocation(),
6156 diag::err_omp_loop_reduction_clause);
6158 // A new Vector ClausesWithoutBind, which does not contain the bind
6159 // clause, for passing to new directive.
6160 if (C->getClauseKind() != llvm::omp::Clause::OMPC_bind)
6161 ClausesWithoutBind.push_back(C);
6164 switch (BindKind) {
6165 case OMPC_BIND_parallel:
6166 Kind = OMPD_for;
6167 DSAStack->setCurrentDirective(OMPD_for);
6168 DSAStack->setMappedDirective(OMPD_loop);
6169 PrevMappedDirective = OMPD_loop;
6170 break;
6171 case OMPC_BIND_teams:
6172 Kind = OMPD_distribute;
6173 DSAStack->setCurrentDirective(OMPD_distribute);
6174 DSAStack->setMappedDirective(OMPD_loop);
6175 PrevMappedDirective = OMPD_loop;
6176 break;
6177 case OMPC_BIND_thread:
6178 Kind = OMPD_simd;
6179 DSAStack->setCurrentDirective(OMPD_simd);
6180 DSAStack->setMappedDirective(OMPD_loop);
6181 PrevMappedDirective = OMPD_loop;
6182 break;
6183 case OMPC_BIND_unknown:
6184 break;
6186 } else if (PrevMappedDirective == OMPD_loop) {
6187 /// An initial pass after recognizing all the statements is done in the
6188 /// Parser when the directive OMPD_loop is mapped to OMPD_for,
6189 /// OMPD_distribute or OMPD_simd. A second transform pass with call from
6190 /// clang::TreeTransform::TransformOMPExecutableDirective() is done
6191 /// with the Directive as one of the above mapped directive without
6192 /// the bind clause. Then "PrevMappedDirective" stored in the
6193 /// OMPExecutableDirective is accessed and hence this else statement.
6195 DSAStack->setMappedDirective(OMPD_loop);
6198 return UseClausesWithoutBind;
6201 StmtResult Sema::ActOnOpenMPExecutableDirective(
6202 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6203 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
6204 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc,
6205 OpenMPDirectiveKind PrevMappedDirective) {
6206 StmtResult Res = StmtError();
6207 OpenMPBindClauseKind BindKind = OMPC_BIND_unknown;
6208 if (const OMPBindClause *BC =
6209 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6210 BindKind = BC->getBindKind();
6211 // First check CancelRegion which is then used in checkNestingOfRegions.
6212 if (checkCancelRegion(*this, Kind, CancelRegion, StartLoc) ||
6213 checkNestingOfRegions(*this, DSAStack, Kind, DirName, CancelRegion,
6214 BindKind, StartLoc))
6215 return StmtError();
6217 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6218 if (getLangOpts().HIP && (isOpenMPTargetExecutionDirective(Kind) ||
6219 isOpenMPTargetDataManagementDirective(Kind)))
6220 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6222 llvm::SmallVector<OMPClause *> ClausesWithoutBind;
6223 bool UseClausesWithoutBind = false;
6225 UseClausesWithoutBind = mapLoopConstruct(ClausesWithoutBind, Clauses,
6226 BindKind, Kind, PrevMappedDirective);
6228 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
6229 VarsWithInheritedDSAType VarsWithInheritedDSA;
6230 bool ErrorFound = false;
6231 if (getLangOpts().OpenMP >= 50 && UseClausesWithoutBind) {
6232 ClausesWithImplicit.append(ClausesWithoutBind.begin(),
6233 ClausesWithoutBind.end());
6234 } else {
6235 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6237 if (AStmt && !CurContext->isDependentContext() && Kind != OMPD_atomic &&
6238 Kind != OMPD_critical && Kind != OMPD_section && Kind != OMPD_master &&
6239 Kind != OMPD_masked && !isOpenMPLoopTransformationDirective(Kind)) {
6240 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6242 // Check default data sharing attributes for referenced variables.
6243 DSAAttrChecker DSAChecker(DSAStack, *this, cast<CapturedStmt>(AStmt));
6244 int ThisCaptureLevel = getOpenMPCaptureLevels(Kind);
6245 Stmt *S = AStmt;
6246 while (--ThisCaptureLevel >= 0)
6247 S = cast<CapturedStmt>(S)->getCapturedStmt();
6248 DSAChecker.Visit(S);
6249 if (!isOpenMPTargetDataManagementDirective(Kind) &&
6250 !isOpenMPTaskingDirective(Kind)) {
6251 // Visit subcaptures to generate implicit clauses for captured vars.
6252 auto *CS = cast<CapturedStmt>(AStmt);
6253 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
6254 getOpenMPCaptureRegions(CaptureRegions, Kind);
6255 // Ignore outer tasking regions for target directives.
6256 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6257 CS = cast<CapturedStmt>(CS->getCapturedStmt());
6258 DSAChecker.visitSubCaptures(CS);
6260 if (DSAChecker.isErrorFound())
6261 return StmtError();
6262 // Generate list of implicitly defined firstprivate variables.
6263 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6265 SmallVector<Expr *, 4> ImplicitFirstprivates(
6266 DSAChecker.getImplicitFirstprivate().begin(),
6267 DSAChecker.getImplicitFirstprivate().end());
6268 SmallVector<Expr *, 4> ImplicitPrivates(
6269 DSAChecker.getImplicitPrivate().begin(),
6270 DSAChecker.getImplicitPrivate().end());
6271 const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_pointer + 1;
6272 SmallVector<Expr *, 4> ImplicitMaps[DefaultmapKindNum][OMPC_MAP_delete];
6273 SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
6274 ImplicitMapModifiers[DefaultmapKindNum];
6275 SmallVector<SourceLocation, NumberOfOMPMapClauseModifiers>
6276 ImplicitMapModifiersLoc[DefaultmapKindNum];
6277 // Get the original location of present modifier from Defaultmap clause.
6278 SourceLocation PresentModifierLocs[DefaultmapKindNum];
6279 for (OMPClause *C : Clauses) {
6280 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C))
6281 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6282 PresentModifierLocs[DMC->getDefaultmapKind()] =
6283 DMC->getDefaultmapModifierLoc();
6285 for (unsigned VC = 0; VC < DefaultmapKindNum; ++VC) {
6286 auto Kind = static_cast<OpenMPDefaultmapClauseKind>(VC);
6287 for (unsigned I = 0; I < OMPC_MAP_delete; ++I) {
6288 ArrayRef<Expr *> ImplicitMap = DSAChecker.getImplicitMap(
6289 Kind, static_cast<OpenMPMapClauseKind>(I));
6290 ImplicitMaps[VC][I].append(ImplicitMap.begin(), ImplicitMap.end());
6292 ArrayRef<OpenMPMapModifierKind> ImplicitModifier =
6293 DSAChecker.getImplicitMapModifier(Kind);
6294 ImplicitMapModifiers[VC].append(ImplicitModifier.begin(),
6295 ImplicitModifier.end());
6296 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[VC]),
6297 ImplicitModifier.size(), PresentModifierLocs[VC]);
6299 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6300 for (OMPClause *C : Clauses) {
6301 if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
6302 for (Expr *E : IRC->taskgroup_descriptors())
6303 if (E)
6304 ImplicitFirstprivates.emplace_back(E);
6306 // OpenMP 5.0, 2.10.1 task Construct
6307 // [detach clause]... The event-handle will be considered as if it was
6308 // specified on a firstprivate clause.
6309 if (auto *DC = dyn_cast<OMPDetachClause>(C))
6310 ImplicitFirstprivates.push_back(DC->getEventHandler());
6312 if (!ImplicitFirstprivates.empty()) {
6313 if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause(
6314 ImplicitFirstprivates, SourceLocation(), SourceLocation(),
6315 SourceLocation())) {
6316 ClausesWithImplicit.push_back(Implicit);
6317 ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
6318 ImplicitFirstprivates.size();
6319 } else {
6320 ErrorFound = true;
6323 if (!ImplicitPrivates.empty()) {
6324 if (OMPClause *Implicit =
6325 ActOnOpenMPPrivateClause(ImplicitPrivates, SourceLocation(),
6326 SourceLocation(), SourceLocation())) {
6327 ClausesWithImplicit.push_back(Implicit);
6328 ErrorFound = cast<OMPPrivateClause>(Implicit)->varlist_size() !=
6329 ImplicitPrivates.size();
6330 } else {
6331 ErrorFound = true;
6334 // OpenMP 5.0 [2.19.7]
6335 // If a list item appears in a reduction, lastprivate or linear
6336 // clause on a combined target construct then it is treated as
6337 // if it also appears in a map clause with a map-type of tofrom
6338 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6339 isOpenMPTargetExecutionDirective(Kind)) {
6340 SmallVector<Expr *, 4> ImplicitExprs;
6341 for (OMPClause *C : Clauses) {
6342 if (auto *RC = dyn_cast<OMPReductionClause>(C))
6343 for (Expr *E : RC->varlists())
6344 if (!isa<DeclRefExpr>(E->IgnoreParenImpCasts()))
6345 ImplicitExprs.emplace_back(E);
6347 if (!ImplicitExprs.empty()) {
6348 ArrayRef<Expr *> Exprs = ImplicitExprs;
6349 CXXScopeSpec MapperIdScopeSpec;
6350 DeclarationNameInfo MapperId;
6351 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6352 nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(),
6353 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6354 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6355 Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true))
6356 ClausesWithImplicit.emplace_back(Implicit);
6359 for (unsigned I = 0, E = DefaultmapKindNum; I < E; ++I) {
6360 int ClauseKindCnt = -1;
6361 for (ArrayRef<Expr *> ImplicitMap : ImplicitMaps[I]) {
6362 ++ClauseKindCnt;
6363 if (ImplicitMap.empty())
6364 continue;
6365 CXXScopeSpec MapperIdScopeSpec;
6366 DeclarationNameInfo MapperId;
6367 auto Kind = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6368 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6369 nullptr, ImplicitMapModifiers[I], ImplicitMapModifiersLoc[I],
6370 MapperIdScopeSpec, MapperId, Kind, /*IsMapTypeImplicit=*/true,
6371 SourceLocation(), SourceLocation(), ImplicitMap,
6372 OMPVarListLocTy())) {
6373 ClausesWithImplicit.emplace_back(Implicit);
6374 ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() !=
6375 ImplicitMap.size();
6376 } else {
6377 ErrorFound = true;
6381 // Build expressions for implicit maps of data members with 'default'
6382 // mappers.
6383 if (LangOpts.OpenMP >= 50)
6384 processImplicitMapsWithDefaultMappers(*this, DSAStack,
6385 ClausesWithImplicit);
6388 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6389 switch (Kind) {
6390 case OMPD_parallel:
6391 Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
6392 EndLoc);
6393 AllowedNameModifiers.push_back(OMPD_parallel);
6394 break;
6395 case OMPD_simd:
6396 Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6397 VarsWithInheritedDSA);
6398 if (LangOpts.OpenMP >= 50)
6399 AllowedNameModifiers.push_back(OMPD_simd);
6400 break;
6401 case OMPD_tile:
6402 Res =
6403 ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6404 break;
6405 case OMPD_unroll:
6406 Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc,
6407 EndLoc);
6408 break;
6409 case OMPD_for:
6410 Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6411 VarsWithInheritedDSA);
6412 break;
6413 case OMPD_for_simd:
6414 Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6415 EndLoc, VarsWithInheritedDSA);
6416 if (LangOpts.OpenMP >= 50)
6417 AllowedNameModifiers.push_back(OMPD_simd);
6418 break;
6419 case OMPD_sections:
6420 Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc,
6421 EndLoc);
6422 break;
6423 case OMPD_section:
6424 assert(ClausesWithImplicit.empty() &&
6425 "No clauses are allowed for 'omp section' directive");
6426 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6427 break;
6428 case OMPD_single:
6429 Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc,
6430 EndLoc);
6431 break;
6432 case OMPD_master:
6433 assert(ClausesWithImplicit.empty() &&
6434 "No clauses are allowed for 'omp master' directive");
6435 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6436 break;
6437 case OMPD_masked:
6438 Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc,
6439 EndLoc);
6440 break;
6441 case OMPD_critical:
6442 Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
6443 StartLoc, EndLoc);
6444 break;
6445 case OMPD_parallel_for:
6446 Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
6447 EndLoc, VarsWithInheritedDSA);
6448 AllowedNameModifiers.push_back(OMPD_parallel);
6449 break;
6450 case OMPD_parallel_for_simd:
6451 Res = ActOnOpenMPParallelForSimdDirective(
6452 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6453 AllowedNameModifiers.push_back(OMPD_parallel);
6454 if (LangOpts.OpenMP >= 50)
6455 AllowedNameModifiers.push_back(OMPD_simd);
6456 break;
6457 case OMPD_scope:
6458 Res =
6459 ActOnOpenMPScopeDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6460 break;
6461 case OMPD_parallel_master:
6462 Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt,
6463 StartLoc, EndLoc);
6464 AllowedNameModifiers.push_back(OMPD_parallel);
6465 break;
6466 case OMPD_parallel_masked:
6467 Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt,
6468 StartLoc, EndLoc);
6469 AllowedNameModifiers.push_back(OMPD_parallel);
6470 break;
6471 case OMPD_parallel_sections:
6472 Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
6473 StartLoc, EndLoc);
6474 AllowedNameModifiers.push_back(OMPD_parallel);
6475 break;
6476 case OMPD_task:
6477 Res =
6478 ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6479 AllowedNameModifiers.push_back(OMPD_task);
6480 break;
6481 case OMPD_taskyield:
6482 assert(ClausesWithImplicit.empty() &&
6483 "No clauses are allowed for 'omp taskyield' directive");
6484 assert(AStmt == nullptr &&
6485 "No associated statement allowed for 'omp taskyield' directive");
6486 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6487 break;
6488 case OMPD_error:
6489 assert(AStmt == nullptr &&
6490 "No associated statement allowed for 'omp error' directive");
6491 Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc);
6492 break;
6493 case OMPD_barrier:
6494 assert(ClausesWithImplicit.empty() &&
6495 "No clauses are allowed for 'omp barrier' directive");
6496 assert(AStmt == nullptr &&
6497 "No associated statement allowed for 'omp barrier' directive");
6498 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6499 break;
6500 case OMPD_taskwait:
6501 assert(AStmt == nullptr &&
6502 "No associated statement allowed for 'omp taskwait' directive");
6503 Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc);
6504 break;
6505 case OMPD_taskgroup:
6506 Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc,
6507 EndLoc);
6508 break;
6509 case OMPD_flush:
6510 assert(AStmt == nullptr &&
6511 "No associated statement allowed for 'omp flush' directive");
6512 Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
6513 break;
6514 case OMPD_depobj:
6515 assert(AStmt == nullptr &&
6516 "No associated statement allowed for 'omp depobj' directive");
6517 Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc);
6518 break;
6519 case OMPD_scan:
6520 assert(AStmt == nullptr &&
6521 "No associated statement allowed for 'omp scan' directive");
6522 Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc);
6523 break;
6524 case OMPD_ordered:
6525 Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
6526 EndLoc);
6527 break;
6528 case OMPD_atomic:
6529 Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
6530 EndLoc);
6531 break;
6532 case OMPD_teams:
6533 Res =
6534 ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6535 break;
6536 case OMPD_target:
6537 Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
6538 EndLoc);
6539 AllowedNameModifiers.push_back(OMPD_target);
6540 break;
6541 case OMPD_target_parallel:
6542 Res = ActOnOpenMPTargetParallelDirective(ClausesWithImplicit, AStmt,
6543 StartLoc, EndLoc);
6544 AllowedNameModifiers.push_back(OMPD_target);
6545 AllowedNameModifiers.push_back(OMPD_parallel);
6546 break;
6547 case OMPD_target_parallel_for:
6548 Res = ActOnOpenMPTargetParallelForDirective(
6549 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6550 AllowedNameModifiers.push_back(OMPD_target);
6551 AllowedNameModifiers.push_back(OMPD_parallel);
6552 break;
6553 case OMPD_cancellation_point:
6554 assert(ClausesWithImplicit.empty() &&
6555 "No clauses are allowed for 'omp cancellation point' directive");
6556 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6557 "cancellation point' directive");
6558 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6559 break;
6560 case OMPD_cancel:
6561 assert(AStmt == nullptr &&
6562 "No associated statement allowed for 'omp cancel' directive");
6563 Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
6564 CancelRegion);
6565 AllowedNameModifiers.push_back(OMPD_cancel);
6566 break;
6567 case OMPD_target_data:
6568 Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
6569 EndLoc);
6570 AllowedNameModifiers.push_back(OMPD_target_data);
6571 break;
6572 case OMPD_target_enter_data:
6573 Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc,
6574 EndLoc, AStmt);
6575 AllowedNameModifiers.push_back(OMPD_target_enter_data);
6576 break;
6577 case OMPD_target_exit_data:
6578 Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc,
6579 EndLoc, AStmt);
6580 AllowedNameModifiers.push_back(OMPD_target_exit_data);
6581 break;
6582 case OMPD_taskloop:
6583 Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6584 EndLoc, VarsWithInheritedDSA);
6585 AllowedNameModifiers.push_back(OMPD_taskloop);
6586 break;
6587 case OMPD_taskloop_simd:
6588 Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6589 EndLoc, VarsWithInheritedDSA);
6590 AllowedNameModifiers.push_back(OMPD_taskloop);
6591 if (LangOpts.OpenMP >= 50)
6592 AllowedNameModifiers.push_back(OMPD_simd);
6593 break;
6594 case OMPD_master_taskloop:
6595 Res = ActOnOpenMPMasterTaskLoopDirective(
6596 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6597 AllowedNameModifiers.push_back(OMPD_taskloop);
6598 break;
6599 case OMPD_masked_taskloop:
6600 Res = ActOnOpenMPMaskedTaskLoopDirective(
6601 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6602 AllowedNameModifiers.push_back(OMPD_taskloop);
6603 break;
6604 case OMPD_master_taskloop_simd:
6605 Res = ActOnOpenMPMasterTaskLoopSimdDirective(
6606 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6607 AllowedNameModifiers.push_back(OMPD_taskloop);
6608 if (LangOpts.OpenMP >= 50)
6609 AllowedNameModifiers.push_back(OMPD_simd);
6610 break;
6611 case OMPD_masked_taskloop_simd:
6612 Res = ActOnOpenMPMaskedTaskLoopSimdDirective(
6613 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6614 if (LangOpts.OpenMP >= 51) {
6615 AllowedNameModifiers.push_back(OMPD_taskloop);
6616 AllowedNameModifiers.push_back(OMPD_simd);
6618 break;
6619 case OMPD_parallel_master_taskloop:
6620 Res = ActOnOpenMPParallelMasterTaskLoopDirective(
6621 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6622 AllowedNameModifiers.push_back(OMPD_taskloop);
6623 AllowedNameModifiers.push_back(OMPD_parallel);
6624 break;
6625 case OMPD_parallel_masked_taskloop:
6626 Res = ActOnOpenMPParallelMaskedTaskLoopDirective(
6627 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6628 if (LangOpts.OpenMP >= 51) {
6629 AllowedNameModifiers.push_back(OMPD_taskloop);
6630 AllowedNameModifiers.push_back(OMPD_parallel);
6632 break;
6633 case OMPD_parallel_master_taskloop_simd:
6634 Res = ActOnOpenMPParallelMasterTaskLoopSimdDirective(
6635 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6636 AllowedNameModifiers.push_back(OMPD_taskloop);
6637 AllowedNameModifiers.push_back(OMPD_parallel);
6638 if (LangOpts.OpenMP >= 50)
6639 AllowedNameModifiers.push_back(OMPD_simd);
6640 break;
6641 case OMPD_parallel_masked_taskloop_simd:
6642 Res = ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
6643 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6644 if (LangOpts.OpenMP >= 51) {
6645 AllowedNameModifiers.push_back(OMPD_taskloop);
6646 AllowedNameModifiers.push_back(OMPD_parallel);
6647 AllowedNameModifiers.push_back(OMPD_simd);
6649 break;
6650 case OMPD_distribute:
6651 Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc,
6652 EndLoc, VarsWithInheritedDSA);
6653 break;
6654 case OMPD_target_update:
6655 Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc,
6656 EndLoc, AStmt);
6657 AllowedNameModifiers.push_back(OMPD_target_update);
6658 break;
6659 case OMPD_distribute_parallel_for:
6660 Res = ActOnOpenMPDistributeParallelForDirective(
6661 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6662 AllowedNameModifiers.push_back(OMPD_parallel);
6663 break;
6664 case OMPD_distribute_parallel_for_simd:
6665 Res = ActOnOpenMPDistributeParallelForSimdDirective(
6666 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6667 AllowedNameModifiers.push_back(OMPD_parallel);
6668 if (LangOpts.OpenMP >= 50)
6669 AllowedNameModifiers.push_back(OMPD_simd);
6670 break;
6671 case OMPD_distribute_simd:
6672 Res = ActOnOpenMPDistributeSimdDirective(
6673 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6674 if (LangOpts.OpenMP >= 50)
6675 AllowedNameModifiers.push_back(OMPD_simd);
6676 break;
6677 case OMPD_target_parallel_for_simd:
6678 Res = ActOnOpenMPTargetParallelForSimdDirective(
6679 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6680 AllowedNameModifiers.push_back(OMPD_target);
6681 AllowedNameModifiers.push_back(OMPD_parallel);
6682 if (LangOpts.OpenMP >= 50)
6683 AllowedNameModifiers.push_back(OMPD_simd);
6684 break;
6685 case OMPD_target_simd:
6686 Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6687 EndLoc, VarsWithInheritedDSA);
6688 AllowedNameModifiers.push_back(OMPD_target);
6689 if (LangOpts.OpenMP >= 50)
6690 AllowedNameModifiers.push_back(OMPD_simd);
6691 break;
6692 case OMPD_teams_distribute:
6693 Res = ActOnOpenMPTeamsDistributeDirective(
6694 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6695 break;
6696 case OMPD_teams_distribute_simd:
6697 Res = ActOnOpenMPTeamsDistributeSimdDirective(
6698 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6699 if (LangOpts.OpenMP >= 50)
6700 AllowedNameModifiers.push_back(OMPD_simd);
6701 break;
6702 case OMPD_teams_distribute_parallel_for_simd:
6703 Res = ActOnOpenMPTeamsDistributeParallelForSimdDirective(
6704 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6705 AllowedNameModifiers.push_back(OMPD_parallel);
6706 if (LangOpts.OpenMP >= 50)
6707 AllowedNameModifiers.push_back(OMPD_simd);
6708 break;
6709 case OMPD_teams_distribute_parallel_for:
6710 Res = ActOnOpenMPTeamsDistributeParallelForDirective(
6711 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6712 AllowedNameModifiers.push_back(OMPD_parallel);
6713 break;
6714 case OMPD_target_teams:
6715 Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc,
6716 EndLoc);
6717 AllowedNameModifiers.push_back(OMPD_target);
6718 break;
6719 case OMPD_target_teams_distribute:
6720 Res = ActOnOpenMPTargetTeamsDistributeDirective(
6721 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6722 AllowedNameModifiers.push_back(OMPD_target);
6723 break;
6724 case OMPD_target_teams_distribute_parallel_for:
6725 Res = ActOnOpenMPTargetTeamsDistributeParallelForDirective(
6726 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6727 AllowedNameModifiers.push_back(OMPD_target);
6728 AllowedNameModifiers.push_back(OMPD_parallel);
6729 break;
6730 case OMPD_target_teams_distribute_parallel_for_simd:
6731 Res = ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
6732 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6733 AllowedNameModifiers.push_back(OMPD_target);
6734 AllowedNameModifiers.push_back(OMPD_parallel);
6735 if (LangOpts.OpenMP >= 50)
6736 AllowedNameModifiers.push_back(OMPD_simd);
6737 break;
6738 case OMPD_target_teams_distribute_simd:
6739 Res = ActOnOpenMPTargetTeamsDistributeSimdDirective(
6740 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6741 AllowedNameModifiers.push_back(OMPD_target);
6742 if (LangOpts.OpenMP >= 50)
6743 AllowedNameModifiers.push_back(OMPD_simd);
6744 break;
6745 case OMPD_interop:
6746 assert(AStmt == nullptr &&
6747 "No associated statement allowed for 'omp interop' directive");
6748 Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc);
6749 break;
6750 case OMPD_dispatch:
6751 Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc,
6752 EndLoc);
6753 break;
6754 case OMPD_loop:
6755 Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6756 EndLoc, VarsWithInheritedDSA);
6757 break;
6758 case OMPD_teams_loop:
6759 Res = ActOnOpenMPTeamsGenericLoopDirective(
6760 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6761 break;
6762 case OMPD_target_teams_loop:
6763 Res = ActOnOpenMPTargetTeamsGenericLoopDirective(
6764 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6765 AllowedNameModifiers.push_back(OMPD_target);
6766 break;
6767 case OMPD_parallel_loop:
6768 Res = ActOnOpenMPParallelGenericLoopDirective(
6769 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6770 break;
6771 case OMPD_target_parallel_loop:
6772 Res = ActOnOpenMPTargetParallelGenericLoopDirective(
6773 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6774 break;
6775 case OMPD_declare_target:
6776 case OMPD_end_declare_target:
6777 case OMPD_threadprivate:
6778 case OMPD_allocate:
6779 case OMPD_declare_reduction:
6780 case OMPD_declare_mapper:
6781 case OMPD_declare_simd:
6782 case OMPD_requires:
6783 case OMPD_declare_variant:
6784 case OMPD_begin_declare_variant:
6785 case OMPD_end_declare_variant:
6786 llvm_unreachable("OpenMP Directive is not allowed");
6787 case OMPD_unknown:
6788 default:
6789 llvm_unreachable("Unknown OpenMP directive");
6792 ErrorFound = Res.isInvalid() || ErrorFound;
6794 // Check variables in the clauses if default(none) or
6795 // default(firstprivate) was specified.
6796 if (DSAStack->getDefaultDSA() == DSA_none ||
6797 DSAStack->getDefaultDSA() == DSA_private ||
6798 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6799 DSAAttrChecker DSAChecker(DSAStack, *this, nullptr);
6800 for (OMPClause *C : Clauses) {
6801 switch (C->getClauseKind()) {
6802 case OMPC_num_threads:
6803 case OMPC_dist_schedule:
6804 // Do not analyse if no parent teams directive.
6805 if (isOpenMPTeamsDirective(Kind))
6806 break;
6807 continue;
6808 case OMPC_if:
6809 if (isOpenMPTeamsDirective(Kind) &&
6810 cast<OMPIfClause>(C)->getNameModifier() != OMPD_target)
6811 break;
6812 if (isOpenMPParallelDirective(Kind) &&
6813 isOpenMPTaskLoopDirective(Kind) &&
6814 cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel)
6815 break;
6816 continue;
6817 case OMPC_schedule:
6818 case OMPC_detach:
6819 break;
6820 case OMPC_grainsize:
6821 case OMPC_num_tasks:
6822 case OMPC_final:
6823 case OMPC_priority:
6824 case OMPC_novariants:
6825 case OMPC_nocontext:
6826 // Do not analyze if no parent parallel directive.
6827 if (isOpenMPParallelDirective(Kind))
6828 break;
6829 continue;
6830 case OMPC_ordered:
6831 case OMPC_device:
6832 case OMPC_num_teams:
6833 case OMPC_thread_limit:
6834 case OMPC_hint:
6835 case OMPC_collapse:
6836 case OMPC_safelen:
6837 case OMPC_simdlen:
6838 case OMPC_sizes:
6839 case OMPC_default:
6840 case OMPC_proc_bind:
6841 case OMPC_private:
6842 case OMPC_firstprivate:
6843 case OMPC_lastprivate:
6844 case OMPC_shared:
6845 case OMPC_reduction:
6846 case OMPC_task_reduction:
6847 case OMPC_in_reduction:
6848 case OMPC_linear:
6849 case OMPC_aligned:
6850 case OMPC_copyin:
6851 case OMPC_copyprivate:
6852 case OMPC_nowait:
6853 case OMPC_untied:
6854 case OMPC_mergeable:
6855 case OMPC_allocate:
6856 case OMPC_read:
6857 case OMPC_write:
6858 case OMPC_update:
6859 case OMPC_capture:
6860 case OMPC_compare:
6861 case OMPC_seq_cst:
6862 case OMPC_acq_rel:
6863 case OMPC_acquire:
6864 case OMPC_release:
6865 case OMPC_relaxed:
6866 case OMPC_depend:
6867 case OMPC_threads:
6868 case OMPC_simd:
6869 case OMPC_map:
6870 case OMPC_nogroup:
6871 case OMPC_defaultmap:
6872 case OMPC_to:
6873 case OMPC_from:
6874 case OMPC_use_device_ptr:
6875 case OMPC_use_device_addr:
6876 case OMPC_is_device_ptr:
6877 case OMPC_has_device_addr:
6878 case OMPC_nontemporal:
6879 case OMPC_order:
6880 case OMPC_destroy:
6881 case OMPC_inclusive:
6882 case OMPC_exclusive:
6883 case OMPC_uses_allocators:
6884 case OMPC_affinity:
6885 case OMPC_bind:
6886 case OMPC_filter:
6887 continue;
6888 case OMPC_allocator:
6889 case OMPC_flush:
6890 case OMPC_depobj:
6891 case OMPC_threadprivate:
6892 case OMPC_uniform:
6893 case OMPC_unknown:
6894 case OMPC_unified_address:
6895 case OMPC_unified_shared_memory:
6896 case OMPC_reverse_offload:
6897 case OMPC_dynamic_allocators:
6898 case OMPC_atomic_default_mem_order:
6899 case OMPC_device_type:
6900 case OMPC_match:
6901 case OMPC_when:
6902 case OMPC_at:
6903 case OMPC_severity:
6904 case OMPC_message:
6905 default:
6906 llvm_unreachable("Unexpected clause");
6908 for (Stmt *CC : C->children()) {
6909 if (CC)
6910 DSAChecker.Visit(CC);
6913 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6914 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6916 for (const auto &P : VarsWithInheritedDSA) {
6917 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst()))
6918 continue;
6919 ErrorFound = true;
6920 if (DSAStack->getDefaultDSA() == DSA_none ||
6921 DSAStack->getDefaultDSA() == DSA_private ||
6922 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6923 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6924 << P.first << P.second->getSourceRange();
6925 Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6926 } else if (getLangOpts().OpenMP >= 50) {
6927 Diag(P.second->getExprLoc(),
6928 diag::err_omp_defaultmap_no_attr_for_variable)
6929 << P.first << P.second->getSourceRange();
6930 Diag(DSAStack->getDefaultDSALocation(),
6931 diag::note_omp_defaultmap_attr_none);
6935 if (!AllowedNameModifiers.empty())
6936 ErrorFound = checkIfClauses(*this, Kind, Clauses, AllowedNameModifiers) ||
6937 ErrorFound;
6939 if (ErrorFound)
6940 return StmtError();
6942 if (!CurContext->isDependentContext() &&
6943 isOpenMPTargetExecutionDirective(Kind) &&
6944 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6945 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6946 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6947 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6948 // Register target to DSA Stack.
6949 DSAStack->addTargetDirLocation(StartLoc);
6952 return Res;
6955 Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective(
6956 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6957 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6958 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6959 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6960 assert(Aligneds.size() == Alignments.size());
6961 assert(Linears.size() == LinModifiers.size());
6962 assert(Linears.size() == Steps.size());
6963 if (!DG || DG.get().isNull())
6964 return DeclGroupPtrTy();
6966 const int SimdId = 0;
6967 if (!DG.get().isSingleDecl()) {
6968 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6969 << SimdId;
6970 return DG;
6972 Decl *ADecl = DG.get().getSingleDecl();
6973 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6974 ADecl = FTD->getTemplatedDecl();
6976 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6977 if (!FD) {
6978 Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
6979 return DeclGroupPtrTy();
6982 // OpenMP [2.8.2, declare simd construct, Description]
6983 // The parameter of the simdlen clause must be a constant positive integer
6984 // expression.
6985 ExprResult SL;
6986 if (Simdlen)
6987 SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen);
6988 // OpenMP [2.8.2, declare simd construct, Description]
6989 // The special this pointer can be used as if was one of the arguments to the
6990 // function in any of the linear, aligned, or uniform clauses.
6991 // The uniform clause declares one or more arguments to have an invariant
6992 // value for all concurrent invocations of the function in the execution of a
6993 // single SIMD loop.
6994 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6995 const Expr *UniformedLinearThis = nullptr;
6996 for (const Expr *E : Uniforms) {
6997 E = E->IgnoreParenImpCasts();
6998 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6999 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
7000 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7001 FD->getParamDecl(PVD->getFunctionScopeIndex())
7002 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
7003 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
7004 continue;
7006 if (isa<CXXThisExpr>(E)) {
7007 UniformedLinearThis = E;
7008 continue;
7010 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7011 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7013 // OpenMP [2.8.2, declare simd construct, Description]
7014 // The aligned clause declares that the object to which each list item points
7015 // is aligned to the number of bytes expressed in the optional parameter of
7016 // the aligned clause.
7017 // The special this pointer can be used as if was one of the arguments to the
7018 // function in any of the linear, aligned, or uniform clauses.
7019 // The type of list items appearing in the aligned clause must be array,
7020 // pointer, reference to array, or reference to pointer.
7021 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
7022 const Expr *AlignedThis = nullptr;
7023 for (const Expr *E : Aligneds) {
7024 E = E->IgnoreParenImpCasts();
7025 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
7026 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7027 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7028 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7029 FD->getParamDecl(PVD->getFunctionScopeIndex())
7030 ->getCanonicalDecl() == CanonPVD) {
7031 // OpenMP [2.8.1, simd construct, Restrictions]
7032 // A list-item cannot appear in more than one aligned clause.
7033 if (AlignedArgs.count(CanonPVD) > 0) {
7034 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
7035 << 1 << getOpenMPClauseName(OMPC_aligned)
7036 << E->getSourceRange();
7037 Diag(AlignedArgs[CanonPVD]->getExprLoc(),
7038 diag::note_omp_explicit_dsa)
7039 << getOpenMPClauseName(OMPC_aligned);
7040 continue;
7042 AlignedArgs[CanonPVD] = E;
7043 QualType QTy = PVD->getType()
7044 .getNonReferenceType()
7045 .getUnqualifiedType()
7046 .getCanonicalType();
7047 const Type *Ty = QTy.getTypePtrOrNull();
7048 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
7049 Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
7050 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
7051 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
7053 continue;
7056 if (isa<CXXThisExpr>(E)) {
7057 if (AlignedThis) {
7058 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
7059 << 2 << getOpenMPClauseName(OMPC_aligned) << E->getSourceRange();
7060 Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
7061 << getOpenMPClauseName(OMPC_aligned);
7063 AlignedThis = E;
7064 continue;
7066 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7067 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7069 // The optional parameter of the aligned clause, alignment, must be a constant
7070 // positive integer expression. If no optional parameter is specified,
7071 // implementation-defined default alignments for SIMD instructions on the
7072 // target platforms are assumed.
7073 SmallVector<const Expr *, 4> NewAligns;
7074 for (Expr *E : Alignments) {
7075 ExprResult Align;
7076 if (E)
7077 Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
7078 NewAligns.push_back(Align.get());
7080 // OpenMP [2.8.2, declare simd construct, Description]
7081 // The linear clause declares one or more list items to be private to a SIMD
7082 // lane and to have a linear relationship with respect to the iteration space
7083 // of a loop.
7084 // The special this pointer can be used as if was one of the arguments to the
7085 // function in any of the linear, aligned, or uniform clauses.
7086 // When a linear-step expression is specified in a linear clause it must be
7087 // either a constant integer expression or an integer-typed parameter that is
7088 // specified in a uniform clause on the directive.
7089 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
7090 const bool IsUniformedThis = UniformedLinearThis != nullptr;
7091 auto MI = LinModifiers.begin();
7092 for (const Expr *E : Linears) {
7093 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
7094 ++MI;
7095 E = E->IgnoreParenImpCasts();
7096 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
7097 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7098 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7099 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7100 FD->getParamDecl(PVD->getFunctionScopeIndex())
7101 ->getCanonicalDecl() == CanonPVD) {
7102 // OpenMP [2.15.3.7, linear Clause, Restrictions]
7103 // A list-item cannot appear in more than one linear clause.
7104 if (LinearArgs.count(CanonPVD) > 0) {
7105 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7106 << getOpenMPClauseName(OMPC_linear)
7107 << getOpenMPClauseName(OMPC_linear) << E->getSourceRange();
7108 Diag(LinearArgs[CanonPVD]->getExprLoc(),
7109 diag::note_omp_explicit_dsa)
7110 << getOpenMPClauseName(OMPC_linear);
7111 continue;
7113 // Each argument can appear in at most one uniform or linear clause.
7114 if (UniformedArgs.count(CanonPVD) > 0) {
7115 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7116 << getOpenMPClauseName(OMPC_linear)
7117 << getOpenMPClauseName(OMPC_uniform) << E->getSourceRange();
7118 Diag(UniformedArgs[CanonPVD]->getExprLoc(),
7119 diag::note_omp_explicit_dsa)
7120 << getOpenMPClauseName(OMPC_uniform);
7121 continue;
7123 LinearArgs[CanonPVD] = E;
7124 if (E->isValueDependent() || E->isTypeDependent() ||
7125 E->isInstantiationDependent() ||
7126 E->containsUnexpandedParameterPack())
7127 continue;
7128 (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind,
7129 PVD->getOriginalType(),
7130 /*IsDeclareSimd=*/true);
7131 continue;
7134 if (isa<CXXThisExpr>(E)) {
7135 if (UniformedLinearThis) {
7136 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7137 << getOpenMPClauseName(OMPC_linear)
7138 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform : OMPC_linear)
7139 << E->getSourceRange();
7140 Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa)
7141 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform
7142 : OMPC_linear);
7143 continue;
7145 UniformedLinearThis = E;
7146 if (E->isValueDependent() || E->isTypeDependent() ||
7147 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
7148 continue;
7149 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind,
7150 E->getType(), /*IsDeclareSimd=*/true);
7151 continue;
7153 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7154 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7156 Expr *Step = nullptr;
7157 Expr *NewStep = nullptr;
7158 SmallVector<Expr *, 4> NewSteps;
7159 for (Expr *E : Steps) {
7160 // Skip the same step expression, it was checked already.
7161 if (Step == E || !E) {
7162 NewSteps.push_back(E ? NewStep : nullptr);
7163 continue;
7165 Step = E;
7166 if (const auto *DRE = dyn_cast<DeclRefExpr>(Step))
7167 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7168 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7169 if (UniformedArgs.count(CanonPVD) == 0) {
7170 Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
7171 << Step->getSourceRange();
7172 } else if (E->isValueDependent() || E->isTypeDependent() ||
7173 E->isInstantiationDependent() ||
7174 E->containsUnexpandedParameterPack() ||
7175 CanonPVD->getType()->hasIntegerRepresentation()) {
7176 NewSteps.push_back(Step);
7177 } else {
7178 Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
7179 << Step->getSourceRange();
7181 continue;
7183 NewStep = Step;
7184 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
7185 !Step->isInstantiationDependent() &&
7186 !Step->containsUnexpandedParameterPack()) {
7187 NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step)
7188 .get();
7189 if (NewStep)
7190 NewStep =
7191 VerifyIntegerConstantExpression(NewStep, /*FIXME*/ AllowFold).get();
7193 NewSteps.push_back(NewStep);
7195 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7196 Context, BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
7197 Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
7198 const_cast<Expr **>(NewAligns.data()), NewAligns.size(),
7199 const_cast<Expr **>(Linears.data()), Linears.size(),
7200 const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(),
7201 NewSteps.data(), NewSteps.size(), SR);
7202 ADecl->addAttr(NewAttr);
7203 return DG;
7206 static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
7207 QualType NewType) {
7208 assert(NewType->isFunctionProtoType() &&
7209 "Expected function type with prototype.");
7210 assert(FD->getType()->isFunctionNoProtoType() &&
7211 "Expected function with type with no prototype.");
7212 assert(FDWithProto->getType()->isFunctionProtoType() &&
7213 "Expected function with prototype.");
7214 // Synthesize parameters with the same types.
7215 FD->setType(NewType);
7216 SmallVector<ParmVarDecl *, 16> Params;
7217 for (const ParmVarDecl *P : FDWithProto->parameters()) {
7218 auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(),
7219 SourceLocation(), nullptr, P->getType(),
7220 /*TInfo=*/nullptr, SC_None, nullptr);
7221 Param->setScopeInfo(0, Params.size());
7222 Param->setImplicit();
7223 Params.push_back(Param);
7226 FD->setParams(Params);
7229 void Sema::ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D) {
7230 if (D->isInvalidDecl())
7231 return;
7232 FunctionDecl *FD = nullptr;
7233 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7234 FD = UTemplDecl->getTemplatedDecl();
7235 else
7236 FD = cast<FunctionDecl>(D);
7237 assert(FD && "Expected a function declaration!");
7239 // If we are instantiating templates we do *not* apply scoped assumptions but
7240 // only global ones. We apply scoped assumption to the template definition
7241 // though.
7242 if (!inTemplateInstantiation()) {
7243 for (AssumptionAttr *AA : OMPAssumeScoped)
7244 FD->addAttr(AA);
7246 for (AssumptionAttr *AA : OMPAssumeGlobal)
7247 FD->addAttr(AA);
7250 Sema::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7251 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7253 void Sema::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(
7254 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7255 SmallVectorImpl<FunctionDecl *> &Bases) {
7256 if (!D.getIdentifier())
7257 return;
7259 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7261 // Template specialization is an extension, check if we do it.
7262 bool IsTemplated = !TemplateParamLists.empty();
7263 if (IsTemplated &
7264 !DVScope.TI->isExtensionActive(
7265 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7266 return;
7268 IdentifierInfo *BaseII = D.getIdentifier();
7269 LookupResult Lookup(*this, DeclarationName(BaseII), D.getIdentifierLoc(),
7270 LookupOrdinaryName);
7271 LookupParsedName(Lookup, S, &D.getCXXScopeSpec());
7273 TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
7274 QualType FType = TInfo->getType();
7276 bool IsConstexpr =
7277 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr;
7278 bool IsConsteval =
7279 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Consteval;
7281 for (auto *Candidate : Lookup) {
7282 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7283 FunctionDecl *UDecl = nullptr;
7284 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7285 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7286 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7287 UDecl = FTD->getTemplatedDecl();
7288 } else if (!IsTemplated)
7289 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7290 if (!UDecl)
7291 continue;
7293 // Don't specialize constexpr/consteval functions with
7294 // non-constexpr/consteval functions.
7295 if (UDecl->isConstexpr() && !IsConstexpr)
7296 continue;
7297 if (UDecl->isConsteval() && !IsConsteval)
7298 continue;
7300 QualType UDeclTy = UDecl->getType();
7301 if (!UDeclTy->isDependentType()) {
7302 QualType NewType = Context.mergeFunctionTypes(
7303 FType, UDeclTy, /* OfBlockPointer */ false,
7304 /* Unqualified */ false, /* AllowCXX */ true);
7305 if (NewType.isNull())
7306 continue;
7309 // Found a base!
7310 Bases.push_back(UDecl);
7313 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7314 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7315 // If no base was found we create a declaration that we use as base.
7316 if (Bases.empty() && UseImplicitBase) {
7317 D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration);
7318 Decl *BaseD = HandleDeclarator(S, D, TemplateParamLists);
7319 BaseD->setImplicit(true);
7320 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7321 Bases.push_back(BaseTemplD->getTemplatedDecl());
7322 else
7323 Bases.push_back(cast<FunctionDecl>(BaseD));
7326 std::string MangledName;
7327 MangledName += D.getIdentifier()->getName();
7328 MangledName += getOpenMPVariantManglingSeparatorStr();
7329 MangledName += DVScope.NameSuffix;
7330 IdentifierInfo &VariantII = Context.Idents.get(MangledName);
7332 VariantII.setMangledOpenMPVariantName(true);
7333 D.SetIdentifier(&VariantII, D.getBeginLoc());
7336 void Sema::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
7337 Decl *D, SmallVectorImpl<FunctionDecl *> &Bases) {
7338 // Do not mark function as is used to prevent its emission if this is the
7339 // only place where it is used.
7340 EnterExpressionEvaluationContext Unevaluated(
7341 *this, Sema::ExpressionEvaluationContext::Unevaluated);
7343 FunctionDecl *FD = nullptr;
7344 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7345 FD = UTemplDecl->getTemplatedDecl();
7346 else
7347 FD = cast<FunctionDecl>(D);
7348 auto *VariantFuncRef = DeclRefExpr::Create(
7349 Context, NestedNameSpecifierLoc(), SourceLocation(), FD,
7350 /* RefersToEnclosingVariableOrCapture */ false,
7351 /* NameLoc */ FD->getLocation(), FD->getType(),
7352 ExprValueKind::VK_PRValue);
7354 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7355 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7356 Context, VariantFuncRef, DVScope.TI,
7357 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7358 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7359 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7360 for (FunctionDecl *BaseFD : Bases)
7361 BaseFD->addAttr(OMPDeclareVariantA);
7364 ExprResult Sema::ActOnOpenMPCall(ExprResult Call, Scope *Scope,
7365 SourceLocation LParenLoc,
7366 MultiExprArg ArgExprs,
7367 SourceLocation RParenLoc, Expr *ExecConfig) {
7368 // The common case is a regular call we do not want to specialize at all. Try
7369 // to make that case fast by bailing early.
7370 CallExpr *CE = dyn_cast<CallExpr>(Call.get());
7371 if (!CE)
7372 return Call;
7374 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7375 if (!CalleeFnDecl)
7376 return Call;
7378 if (LangOpts.OpenMP >= 51 && CalleeFnDecl->getIdentifier() &&
7379 CalleeFnDecl->getName().starts_with_insensitive("omp_")) {
7380 // checking for any calls inside an Order region
7381 if (Scope && Scope->isOpenMPOrderClauseScope())
7382 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7385 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7386 return Call;
7388 ASTContext &Context = getASTContext();
7389 std::function<void(StringRef)> DiagUnknownTrait = [this,
7390 CE](StringRef ISATrait) {
7391 // TODO Track the selector locations in a way that is accessible here to
7392 // improve the diagnostic location.
7393 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7394 << ISATrait;
7396 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7397 getCurFunctionDecl(), DSAStack->getConstructTraits());
7399 QualType CalleeFnType = CalleeFnDecl->getType();
7401 SmallVector<Expr *, 4> Exprs;
7402 SmallVector<VariantMatchInfo, 4> VMIs;
7403 while (CalleeFnDecl) {
7404 for (OMPDeclareVariantAttr *A :
7405 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7406 Expr *VariantRef = A->getVariantFuncRef();
7408 VariantMatchInfo VMI;
7409 OMPTraitInfo &TI = A->getTraitInfo();
7410 TI.getAsVariantMatchInfo(Context, VMI);
7411 if (!isVariantApplicableInContext(VMI, OMPCtx,
7412 /* DeviceSetOnly */ false))
7413 continue;
7415 VMIs.push_back(VMI);
7416 Exprs.push_back(VariantRef);
7419 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7422 ExprResult NewCall;
7423 do {
7424 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7425 if (BestIdx < 0)
7426 return Call;
7427 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7428 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7431 // Try to build a (member) call expression for the current best applicable
7432 // variant expression. We allow this to fail in which case we continue
7433 // with the next best variant expression. The fail case is part of the
7434 // implementation defined behavior in the OpenMP standard when it talks
7435 // about what differences in the function prototypes: "Any differences
7436 // that the specific OpenMP context requires in the prototype of the
7437 // variant from the base function prototype are implementation defined."
7438 // This wording is there to allow the specialized variant to have a
7439 // different type than the base function. This is intended and OK but if
7440 // we cannot create a call the difference is not in the "implementation
7441 // defined range" we allow.
7442 Sema::TentativeAnalysisScope Trap(*this);
7444 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7445 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7446 BestExpr = MemberExpr::CreateImplicit(
7447 Context, MemberCall->getImplicitObjectArgument(),
7448 /* IsArrow */ false, SpecializedMethod, Context.BoundMemberTy,
7449 MemberCall->getValueKind(), MemberCall->getObjectKind());
7451 NewCall = BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs, RParenLoc,
7452 ExecConfig);
7453 if (NewCall.isUsable()) {
7454 if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) {
7455 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7456 QualType NewType = Context.mergeFunctionTypes(
7457 CalleeFnType, NewCalleeFnDecl->getType(),
7458 /* OfBlockPointer */ false,
7459 /* Unqualified */ false, /* AllowCXX */ true);
7460 if (!NewType.isNull())
7461 break;
7462 // Don't use the call if the function type was not compatible.
7463 NewCall = nullptr;
7468 VMIs.erase(VMIs.begin() + BestIdx);
7469 Exprs.erase(Exprs.begin() + BestIdx);
7470 } while (!VMIs.empty());
7472 if (!NewCall.isUsable())
7473 return Call;
7474 return PseudoObjectExpr::Create(Context, CE, {NewCall.get()}, 0);
7477 std::optional<std::pair<FunctionDecl *, Expr *>>
7478 Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG,
7479 Expr *VariantRef, OMPTraitInfo &TI,
7480 unsigned NumAppendArgs,
7481 SourceRange SR) {
7482 if (!DG || DG.get().isNull())
7483 return std::nullopt;
7485 const int VariantId = 1;
7486 // Must be applied only to single decl.
7487 if (!DG.get().isSingleDecl()) {
7488 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7489 << VariantId << SR;
7490 return std::nullopt;
7492 Decl *ADecl = DG.get().getSingleDecl();
7493 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7494 ADecl = FTD->getTemplatedDecl();
7496 // Decl must be a function.
7497 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7498 if (!FD) {
7499 Diag(ADecl->getLocation(), diag::err_omp_function_expected)
7500 << VariantId << SR;
7501 return std::nullopt;
7504 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7505 // The 'target' attribute needs to be separately checked because it does
7506 // not always signify a multiversion function declaration.
7507 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7509 // OpenMP is not compatible with multiversion function attributes.
7510 if (HasMultiVersionAttributes(FD)) {
7511 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7512 << SR;
7513 return std::nullopt;
7516 // Allow #pragma omp declare variant only if the function is not used.
7517 if (FD->isUsed(false))
7518 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
7519 << FD->getLocation();
7521 // Check if the function was emitted already.
7522 const FunctionDecl *Definition;
7523 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7524 (LangOpts.EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
7525 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
7526 << FD->getLocation();
7528 // The VariantRef must point to function.
7529 if (!VariantRef) {
7530 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
7531 return std::nullopt;
7534 auto ShouldDelayChecks = [](Expr *&E, bool) {
7535 return E && (E->isTypeDependent() || E->isValueDependent() ||
7536 E->containsUnexpandedParameterPack() ||
7537 E->isInstantiationDependent());
7539 // Do not check templates, wait until instantiation.
7540 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7541 TI.anyScoreOrCondition(ShouldDelayChecks))
7542 return std::make_pair(FD, VariantRef);
7544 // Deal with non-constant score and user condition expressions.
7545 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7546 bool IsScore) -> bool {
7547 if (!E || E->isIntegerConstantExpr(Context))
7548 return false;
7550 if (IsScore) {
7551 // We warn on non-constant scores and pretend they were not present.
7552 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7553 << E;
7554 E = nullptr;
7555 } else {
7556 // We could replace a non-constant user condition with "false" but we
7557 // will soon need to handle these anyway for the dynamic version of
7558 // OpenMP context selectors.
7559 Diag(E->getExprLoc(),
7560 diag::err_omp_declare_variant_user_condition_not_constant)
7561 << E;
7563 return true;
7565 if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions))
7566 return std::nullopt;
7568 QualType AdjustedFnType = FD->getType();
7569 if (NumAppendArgs) {
7570 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7571 if (!PTy) {
7572 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
7573 << SR;
7574 return std::nullopt;
7576 // Adjust the function type to account for an extra omp_interop_t for each
7577 // specified in the append_args clause.
7578 const TypeDecl *TD = nullptr;
7579 LookupResult Result(*this, &Context.Idents.get("omp_interop_t"),
7580 SR.getBegin(), Sema::LookupOrdinaryName);
7581 if (LookupName(Result, getCurScope())) {
7582 NamedDecl *ND = Result.getFoundDecl();
7583 TD = dyn_cast_or_null<TypeDecl>(ND);
7585 if (!TD) {
7586 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
7587 return std::nullopt;
7589 QualType InteropType = Context.getTypeDeclType(TD);
7590 if (PTy->isVariadic()) {
7591 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7592 return std::nullopt;
7594 llvm::SmallVector<QualType, 8> Params;
7595 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7596 Params.insert(Params.end(), NumAppendArgs, InteropType);
7597 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7598 PTy->getExtProtoInfo());
7601 // Convert VariantRef expression to the type of the original function to
7602 // resolve possible conflicts.
7603 ExprResult VariantRefCast = VariantRef;
7604 if (LangOpts.CPlusPlus) {
7605 QualType FnPtrType;
7606 auto *Method = dyn_cast<CXXMethodDecl>(FD);
7607 if (Method && !Method->isStatic()) {
7608 const Type *ClassType =
7609 Context.getTypeDeclType(Method->getParent()).getTypePtr();
7610 FnPtrType = Context.getMemberPointerType(AdjustedFnType, ClassType);
7611 ExprResult ER;
7613 // Build adrr_of unary op to correctly handle type checks for member
7614 // functions.
7615 Sema::TentativeAnalysisScope Trap(*this);
7616 ER = CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf,
7617 VariantRef);
7619 if (!ER.isUsable()) {
7620 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7621 << VariantId << VariantRef->getSourceRange();
7622 return std::nullopt;
7624 VariantRef = ER.get();
7625 } else {
7626 FnPtrType = Context.getPointerType(AdjustedFnType);
7628 QualType VarianPtrType = Context.getPointerType(VariantRef->getType());
7629 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7630 ImplicitConversionSequence ICS = TryImplicitConversion(
7631 VariantRef, FnPtrType.getUnqualifiedType(),
7632 /*SuppressUserConversions=*/false, AllowedExplicit::None,
7633 /*InOverloadResolution=*/false,
7634 /*CStyle=*/false,
7635 /*AllowObjCWritebackConversion=*/false);
7636 if (ICS.isFailure()) {
7637 Diag(VariantRef->getExprLoc(),
7638 diag::err_omp_declare_variant_incompat_types)
7639 << VariantRef->getType()
7640 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7641 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7642 return std::nullopt;
7644 VariantRefCast = PerformImplicitConversion(
7645 VariantRef, FnPtrType.getUnqualifiedType(), AA_Converting);
7646 if (!VariantRefCast.isUsable())
7647 return std::nullopt;
7649 // Drop previously built artificial addr_of unary op for member functions.
7650 if (Method && !Method->isStatic()) {
7651 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7652 if (auto *UO = dyn_cast<UnaryOperator>(
7653 PossibleAddrOfVariantRef->IgnoreImplicit()))
7654 VariantRefCast = UO->getSubExpr();
7658 ExprResult ER = CheckPlaceholderExpr(VariantRefCast.get());
7659 if (!ER.isUsable() ||
7660 !ER.get()->IgnoreParenImpCasts()->getType()->isFunctionType()) {
7661 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7662 << VariantId << VariantRef->getSourceRange();
7663 return std::nullopt;
7666 // The VariantRef must point to function.
7667 auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts());
7668 if (!DRE) {
7669 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7670 << VariantId << VariantRef->getSourceRange();
7671 return std::nullopt;
7673 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7674 if (!NewFD) {
7675 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7676 << VariantId << VariantRef->getSourceRange();
7677 return std::nullopt;
7680 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7681 Diag(VariantRef->getExprLoc(),
7682 diag::err_omp_declare_variant_same_base_function)
7683 << VariantRef->getSourceRange();
7684 return std::nullopt;
7687 // Check if function types are compatible in C.
7688 if (!LangOpts.CPlusPlus) {
7689 QualType NewType =
7690 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7691 if (NewType.isNull()) {
7692 Diag(VariantRef->getExprLoc(),
7693 diag::err_omp_declare_variant_incompat_types)
7694 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7695 << VariantRef->getSourceRange();
7696 return std::nullopt;
7698 if (NewType->isFunctionProtoType()) {
7699 if (FD->getType()->isFunctionNoProtoType())
7700 setPrototype(*this, FD, NewFD, NewType);
7701 else if (NewFD->getType()->isFunctionNoProtoType())
7702 setPrototype(*this, NewFD, FD, NewType);
7706 // Check if variant function is not marked with declare variant directive.
7707 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7708 Diag(VariantRef->getExprLoc(),
7709 diag::warn_omp_declare_variant_marked_as_declare_variant)
7710 << VariantRef->getSourceRange();
7711 SourceRange SR =
7712 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7713 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7714 return std::nullopt;
7717 enum DoesntSupport {
7718 VirtFuncs = 1,
7719 Constructors = 3,
7720 Destructors = 4,
7721 DeletedFuncs = 5,
7722 DefaultedFuncs = 6,
7723 ConstexprFuncs = 7,
7724 ConstevalFuncs = 8,
7726 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7727 if (CXXFD->isVirtual()) {
7728 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7729 << VirtFuncs;
7730 return std::nullopt;
7733 if (isa<CXXConstructorDecl>(FD)) {
7734 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7735 << Constructors;
7736 return std::nullopt;
7739 if (isa<CXXDestructorDecl>(FD)) {
7740 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7741 << Destructors;
7742 return std::nullopt;
7746 if (FD->isDeleted()) {
7747 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7748 << DeletedFuncs;
7749 return std::nullopt;
7752 if (FD->isDefaulted()) {
7753 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7754 << DefaultedFuncs;
7755 return std::nullopt;
7758 if (FD->isConstexpr()) {
7759 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7760 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7761 return std::nullopt;
7764 // Check general compatibility.
7765 if (areMultiversionVariantFunctionsCompatible(
7766 FD, NewFD, PartialDiagnostic::NullDiagnostic(),
7767 PartialDiagnosticAt(SourceLocation(),
7768 PartialDiagnostic::NullDiagnostic()),
7769 PartialDiagnosticAt(
7770 VariantRef->getExprLoc(),
7771 PDiag(diag::err_omp_declare_variant_doesnt_support)),
7772 PartialDiagnosticAt(VariantRef->getExprLoc(),
7773 PDiag(diag::err_omp_declare_variant_diff)
7774 << FD->getLocation()),
7775 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7776 /*CLinkageMayDiffer=*/true))
7777 return std::nullopt;
7778 return std::make_pair(FD, cast<Expr>(DRE));
7781 void Sema::ActOnOpenMPDeclareVariantDirective(
7782 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7783 ArrayRef<Expr *> AdjustArgsNothing,
7784 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7785 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7786 SourceLocation AppendArgsLoc, SourceRange SR) {
7788 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7789 // An adjust_args clause or append_args clause can only be specified if the
7790 // dispatch selector of the construct selector set appears in the match
7791 // clause.
7793 SmallVector<Expr *, 8> AllAdjustArgs;
7794 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7795 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7797 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7798 VariantMatchInfo VMI;
7799 TI.getAsVariantMatchInfo(Context, VMI);
7800 if (!llvm::is_contained(
7801 VMI.ConstructTraits,
7802 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7803 if (!AllAdjustArgs.empty())
7804 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7805 << getOpenMPClauseName(OMPC_adjust_args);
7806 if (!AppendArgs.empty())
7807 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7808 << getOpenMPClauseName(OMPC_append_args);
7809 return;
7813 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7814 // Each argument can only appear in a single adjust_args clause for each
7815 // declare variant directive.
7816 llvm::SmallPtrSet<const VarDecl *, 4> AdjustVars;
7818 for (Expr *E : AllAdjustArgs) {
7819 E = E->IgnoreParenImpCasts();
7820 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7821 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7822 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7823 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7824 FD->getParamDecl(PVD->getFunctionScopeIndex())
7825 ->getCanonicalDecl() == CanonPVD) {
7826 // It's a parameter of the function, check duplicates.
7827 if (!AdjustVars.insert(CanonPVD).second) {
7828 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7829 << PVD;
7830 return;
7832 continue;
7836 // Anything that is not a function parameter is an error.
7837 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7838 return;
7841 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7842 Context, VariantRef, &TI, const_cast<Expr **>(AdjustArgsNothing.data()),
7843 AdjustArgsNothing.size(),
7844 const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7845 AdjustArgsNeedDevicePtr.size(),
7846 const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR);
7847 FD->addAttr(NewAttr);
7850 StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
7851 Stmt *AStmt,
7852 SourceLocation StartLoc,
7853 SourceLocation EndLoc) {
7854 if (!AStmt)
7855 return StmtError();
7857 auto *CS = cast<CapturedStmt>(AStmt);
7858 // 1.2.2 OpenMP Language Terminology
7859 // Structured block - An executable statement with a single entry at the
7860 // top and a single exit at the bottom.
7861 // The point of exit cannot be a branch out of the structured block.
7862 // longjmp() and throw() must not violate the entry/exit criteria.
7863 CS->getCapturedDecl()->setNothrow();
7865 setFunctionHasBranchProtectedScope();
7867 return OMPParallelDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
7868 DSAStack->getTaskgroupReductionRef(),
7869 DSAStack->isCancelRegion());
7872 namespace {
7873 /// Iteration space of a single for loop.
7874 struct LoopIterationSpace final {
7875 /// True if the condition operator is the strict compare operator (<, > or
7876 /// !=).
7877 bool IsStrictCompare = false;
7878 /// Condition of the loop.
7879 Expr *PreCond = nullptr;
7880 /// This expression calculates the number of iterations in the loop.
7881 /// It is always possible to calculate it before starting the loop.
7882 Expr *NumIterations = nullptr;
7883 /// The loop counter variable.
7884 Expr *CounterVar = nullptr;
7885 /// Private loop counter variable.
7886 Expr *PrivateCounterVar = nullptr;
7887 /// This is initializer for the initial value of #CounterVar.
7888 Expr *CounterInit = nullptr;
7889 /// This is step for the #CounterVar used to generate its update:
7890 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7891 Expr *CounterStep = nullptr;
7892 /// Should step be subtracted?
7893 bool Subtract = false;
7894 /// Source range of the loop init.
7895 SourceRange InitSrcRange;
7896 /// Source range of the loop condition.
7897 SourceRange CondSrcRange;
7898 /// Source range of the loop increment.
7899 SourceRange IncSrcRange;
7900 /// Minimum value that can have the loop control variable. Used to support
7901 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
7902 /// since only such variables can be used in non-loop invariant expressions.
7903 Expr *MinValue = nullptr;
7904 /// Maximum value that can have the loop control variable. Used to support
7905 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
7906 /// since only such variables can be used in non-loop invariant expressions.
7907 Expr *MaxValue = nullptr;
7908 /// true, if the lower bound depends on the outer loop control var.
7909 bool IsNonRectangularLB = false;
7910 /// true, if the upper bound depends on the outer loop control var.
7911 bool IsNonRectangularUB = false;
7912 /// Index of the loop this loop depends on and forms non-rectangular loop
7913 /// nest.
7914 unsigned LoopDependentIdx = 0;
7915 /// Final condition for the non-rectangular loop nest support. It is used to
7916 /// check that the number of iterations for this particular counter must be
7917 /// finished.
7918 Expr *FinalCondition = nullptr;
7921 /// Helper class for checking canonical form of the OpenMP loops and
7922 /// extracting iteration space of each loop in the loop nest, that will be used
7923 /// for IR generation.
7924 class OpenMPIterationSpaceChecker {
7925 /// Reference to Sema.
7926 Sema &SemaRef;
7927 /// Does the loop associated directive support non-rectangular loops?
7928 bool SupportsNonRectangular;
7929 /// Data-sharing stack.
7930 DSAStackTy &Stack;
7931 /// A location for diagnostics (when there is no some better location).
7932 SourceLocation DefaultLoc;
7933 /// A location for diagnostics (when increment is not compatible).
7934 SourceLocation ConditionLoc;
7935 /// A source location for referring to loop init later.
7936 SourceRange InitSrcRange;
7937 /// A source location for referring to condition later.
7938 SourceRange ConditionSrcRange;
7939 /// A source location for referring to increment later.
7940 SourceRange IncrementSrcRange;
7941 /// Loop variable.
7942 ValueDecl *LCDecl = nullptr;
7943 /// Reference to loop variable.
7944 Expr *LCRef = nullptr;
7945 /// Lower bound (initializer for the var).
7946 Expr *LB = nullptr;
7947 /// Upper bound.
7948 Expr *UB = nullptr;
7949 /// Loop step (increment).
7950 Expr *Step = nullptr;
7951 /// This flag is true when condition is one of:
7952 /// Var < UB
7953 /// Var <= UB
7954 /// UB > Var
7955 /// UB >= Var
7956 /// This will have no value when the condition is !=
7957 std::optional<bool> TestIsLessOp;
7958 /// This flag is true when condition is strict ( < or > ).
7959 bool TestIsStrictOp = false;
7960 /// This flag is true when step is subtracted on each iteration.
7961 bool SubtractStep = false;
7962 /// The outer loop counter this loop depends on (if any).
7963 const ValueDecl *DepDecl = nullptr;
7964 /// Contains number of loop (starts from 1) on which loop counter init
7965 /// expression of this loop depends on.
7966 std::optional<unsigned> InitDependOnLC;
7967 /// Contains number of loop (starts from 1) on which loop counter condition
7968 /// expression of this loop depends on.
7969 std::optional<unsigned> CondDependOnLC;
7970 /// Checks if the provide statement depends on the loop counter.
7971 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
7972 bool IsInitializer);
7973 /// Original condition required for checking of the exit condition for
7974 /// non-rectangular loop.
7975 Expr *Condition = nullptr;
7977 public:
7978 OpenMPIterationSpaceChecker(Sema &SemaRef, bool SupportsNonRectangular,
7979 DSAStackTy &Stack, SourceLocation DefaultLoc)
7980 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
7981 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc) {}
7982 /// Check init-expr for canonical loop form and save loop counter
7983 /// variable - #Var and its initialization value - #LB.
7984 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
7985 /// Check test-expr for canonical form, save upper-bound (#UB), flags
7986 /// for less/greater and for strict/non-strict comparison.
7987 bool checkAndSetCond(Expr *S);
7988 /// Check incr-expr for canonical loop form and return true if it
7989 /// does not conform, otherwise save loop step (#Step).
7990 bool checkAndSetInc(Expr *S);
7991 /// Return the loop counter variable.
7992 ValueDecl *getLoopDecl() const { return LCDecl; }
7993 /// Return the reference expression to loop counter variable.
7994 Expr *getLoopDeclRefExpr() const { return LCRef; }
7995 /// Source range of the loop init.
7996 SourceRange getInitSrcRange() const { return InitSrcRange; }
7997 /// Source range of the loop condition.
7998 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
7999 /// Source range of the loop increment.
8000 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
8001 /// True if the step should be subtracted.
8002 bool shouldSubtractStep() const { return SubtractStep; }
8003 /// True, if the compare operator is strict (<, > or !=).
8004 bool isStrictTestOp() const { return TestIsStrictOp; }
8005 /// Build the expression to calculate the number of iterations.
8006 Expr *buildNumIterations(
8007 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8008 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8009 /// Build the precondition expression for the loops.
8010 Expr *
8011 buildPreCond(Scope *S, Expr *Cond,
8012 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8013 /// Build reference expression to the counter be used for codegen.
8014 DeclRefExpr *
8015 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8016 DSAStackTy &DSA) const;
8017 /// Build reference expression to the private counter be used for
8018 /// codegen.
8019 Expr *buildPrivateCounterVar() const;
8020 /// Build initialization of the counter be used for codegen.
8021 Expr *buildCounterInit() const;
8022 /// Build step of the counter be used for codegen.
8023 Expr *buildCounterStep() const;
8024 /// Build loop data with counter value for depend clauses in ordered
8025 /// directives.
8026 Expr *
8027 buildOrderedLoopData(Scope *S, Expr *Counter,
8028 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8029 SourceLocation Loc, Expr *Inc = nullptr,
8030 OverloadedOperatorKind OOK = OO_Amp);
8031 /// Builds the minimum value for the loop counter.
8032 std::pair<Expr *, Expr *> buildMinMaxValues(
8033 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8034 /// Builds final condition for the non-rectangular loops.
8035 Expr *buildFinalCondition(Scope *S) const;
8036 /// Return true if any expression is dependent.
8037 bool dependent() const;
8038 /// Returns true if the initializer forms non-rectangular loop.
8039 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
8040 /// Returns true if the condition forms non-rectangular loop.
8041 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
8042 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
8043 unsigned getLoopDependentIdx() const {
8044 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
8047 private:
8048 /// Check the right-hand side of an assignment in the increment
8049 /// expression.
8050 bool checkAndSetIncRHS(Expr *RHS);
8051 /// Helper to set loop counter variable and its initializer.
8052 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
8053 bool EmitDiags);
8054 /// Helper to set upper bound.
8055 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
8056 SourceRange SR, SourceLocation SL);
8057 /// Helper to set loop increment.
8058 bool setStep(Expr *NewStep, bool Subtract);
8061 bool OpenMPIterationSpaceChecker::dependent() const {
8062 if (!LCDecl) {
8063 assert(!LB && !UB && !Step);
8064 return false;
8066 return LCDecl->getType()->isDependentType() ||
8067 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
8068 (Step && Step->isValueDependent());
8071 bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
8072 Expr *NewLCRefExpr,
8073 Expr *NewLB, bool EmitDiags) {
8074 // State consistency checking to ensure correct usage.
8075 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
8076 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8077 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
8078 return true;
8079 LCDecl = getCanonicalDecl(NewLCDecl);
8080 LCRef = NewLCRefExpr;
8081 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
8082 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8083 if ((Ctor->isCopyOrMoveConstructor() ||
8084 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8085 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8086 NewLB = CE->getArg(0)->IgnoreParenImpCasts();
8087 LB = NewLB;
8088 if (EmitDiags)
8089 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
8090 return false;
8093 bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
8094 bool StrictOp, SourceRange SR,
8095 SourceLocation SL) {
8096 // State consistency checking to ensure correct usage.
8097 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
8098 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8099 if (!NewUB || NewUB->containsErrors())
8100 return true;
8101 UB = NewUB;
8102 if (LessOp)
8103 TestIsLessOp = LessOp;
8104 TestIsStrictOp = StrictOp;
8105 ConditionSrcRange = SR;
8106 ConditionLoc = SL;
8107 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
8108 return false;
8111 bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
8112 // State consistency checking to ensure correct usage.
8113 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
8114 if (!NewStep || NewStep->containsErrors())
8115 return true;
8116 if (!NewStep->isValueDependent()) {
8117 // Check that the step is integer expression.
8118 SourceLocation StepLoc = NewStep->getBeginLoc();
8119 ExprResult Val = SemaRef.PerformOpenMPImplicitIntegerConversion(
8120 StepLoc, getExprAsWritten(NewStep));
8121 if (Val.isInvalid())
8122 return true;
8123 NewStep = Val.get();
8125 // OpenMP [2.6, Canonical Loop Form, Restrictions]
8126 // If test-expr is of form var relational-op b and relational-op is < or
8127 // <= then incr-expr must cause var to increase on each iteration of the
8128 // loop. If test-expr is of form var relational-op b and relational-op is
8129 // > or >= then incr-expr must cause var to decrease on each iteration of
8130 // the loop.
8131 // If test-expr is of form b relational-op var and relational-op is < or
8132 // <= then incr-expr must cause var to decrease on each iteration of the
8133 // loop. If test-expr is of form b relational-op var and relational-op is
8134 // > or >= then incr-expr must cause var to increase on each iteration of
8135 // the loop.
8136 std::optional<llvm::APSInt> Result =
8137 NewStep->getIntegerConstantExpr(SemaRef.Context);
8138 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
8139 bool IsConstNeg =
8140 Result && Result->isSigned() && (Subtract != Result->isNegative());
8141 bool IsConstPos =
8142 Result && Result->isSigned() && (Subtract == Result->isNegative());
8143 bool IsConstZero = Result && !Result->getBoolValue();
8145 // != with increment is treated as <; != with decrement is treated as >
8146 if (!TestIsLessOp)
8147 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8148 if (UB && (IsConstZero ||
8149 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8150 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8151 SemaRef.Diag(NewStep->getExprLoc(),
8152 diag::err_omp_loop_incr_not_compatible)
8153 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
8154 SemaRef.Diag(ConditionLoc,
8155 diag::note_omp_loop_cond_requres_compatible_incr)
8156 << *TestIsLessOp << ConditionSrcRange;
8157 return true;
8159 if (*TestIsLessOp == Subtract) {
8160 NewStep =
8161 SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
8162 .get();
8163 Subtract = !Subtract;
8167 Step = NewStep;
8168 SubtractStep = Subtract;
8169 return false;
8172 namespace {
8173 /// Checker for the non-rectangular loops. Checks if the initializer or
8174 /// condition expression references loop counter variable.
8175 class LoopCounterRefChecker final
8176 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
8177 Sema &SemaRef;
8178 DSAStackTy &Stack;
8179 const ValueDecl *CurLCDecl = nullptr;
8180 const ValueDecl *DepDecl = nullptr;
8181 const ValueDecl *PrevDepDecl = nullptr;
8182 bool IsInitializer = true;
8183 bool SupportsNonRectangular;
8184 unsigned BaseLoopId = 0;
8185 bool checkDecl(const Expr *E, const ValueDecl *VD) {
8186 if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
8187 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8188 << (IsInitializer ? 0 : 1);
8189 return false;
8191 const auto &&Data = Stack.isLoopControlVariable(VD);
8192 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8193 // The type of the loop iterator on which we depend may not have a random
8194 // access iterator type.
8195 if (Data.first && VD->getType()->isRecordType()) {
8196 SmallString<128> Name;
8197 llvm::raw_svector_ostream OS(Name);
8198 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8199 /*Qualified=*/true);
8200 SemaRef.Diag(E->getExprLoc(),
8201 diag::err_omp_wrong_dependency_iterator_type)
8202 << OS.str();
8203 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
8204 return false;
8206 if (Data.first && !SupportsNonRectangular) {
8207 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
8208 return false;
8210 if (Data.first &&
8211 (DepDecl || (PrevDepDecl &&
8212 getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
8213 if (!DepDecl && PrevDepDecl)
8214 DepDecl = PrevDepDecl;
8215 SmallString<128> Name;
8216 llvm::raw_svector_ostream OS(Name);
8217 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8218 /*Qualified=*/true);
8219 SemaRef.Diag(E->getExprLoc(),
8220 diag::err_omp_invariant_or_linear_dependency)
8221 << OS.str();
8222 return false;
8224 if (Data.first) {
8225 DepDecl = VD;
8226 BaseLoopId = Data.first;
8228 return Data.first;
8231 public:
8232 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8233 const ValueDecl *VD = E->getDecl();
8234 if (isa<VarDecl>(VD))
8235 return checkDecl(E, VD);
8236 return false;
8238 bool VisitMemberExpr(const MemberExpr *E) {
8239 if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
8240 const ValueDecl *VD = E->getMemberDecl();
8241 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8242 return checkDecl(E, VD);
8244 return false;
8246 bool VisitStmt(const Stmt *S) {
8247 bool Res = false;
8248 for (const Stmt *Child : S->children())
8249 Res = (Child && Visit(Child)) || Res;
8250 return Res;
8252 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8253 const ValueDecl *CurLCDecl, bool IsInitializer,
8254 const ValueDecl *PrevDepDecl = nullptr,
8255 bool SupportsNonRectangular = true)
8256 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8257 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8258 SupportsNonRectangular(SupportsNonRectangular) {}
8259 unsigned getBaseLoopId() const {
8260 assert(CurLCDecl && "Expected loop dependency.");
8261 return BaseLoopId;
8263 const ValueDecl *getDepDecl() const {
8264 assert(CurLCDecl && "Expected loop dependency.");
8265 return DepDecl;
8268 } // namespace
8270 std::optional<unsigned>
8271 OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8272 bool IsInitializer) {
8273 // Check for the non-rectangular loops.
8274 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8275 DepDecl, SupportsNonRectangular);
8276 if (LoopStmtChecker.Visit(S)) {
8277 DepDecl = LoopStmtChecker.getDepDecl();
8278 return LoopStmtChecker.getBaseLoopId();
8280 return std::nullopt;
8283 bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8284 // Check init-expr for canonical loop form and save loop counter
8285 // variable - #Var and its initialization value - #LB.
8286 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8287 // var = lb
8288 // integer-type var = lb
8289 // random-access-iterator-type var = lb
8290 // pointer-type var = lb
8292 if (!S) {
8293 if (EmitDiags) {
8294 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8296 return true;
8298 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8299 if (!ExprTemp->cleanupsHaveSideEffects())
8300 S = ExprTemp->getSubExpr();
8302 InitSrcRange = S->getSourceRange();
8303 if (Expr *E = dyn_cast<Expr>(S))
8304 S = E->IgnoreParens();
8305 if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8306 if (BO->getOpcode() == BO_Assign) {
8307 Expr *LHS = BO->getLHS()->IgnoreParens();
8308 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8309 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8310 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8311 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8312 EmitDiags);
8313 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8315 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8316 if (ME->isArrow() &&
8317 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8318 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8319 EmitDiags);
8322 } else if (auto *DS = dyn_cast<DeclStmt>(S)) {
8323 if (DS->isSingleDecl()) {
8324 if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8325 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8326 // Accept non-canonical init form here but emit ext. warning.
8327 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8328 SemaRef.Diag(S->getBeginLoc(),
8329 diag::ext_omp_loop_not_canonical_init)
8330 << S->getSourceRange();
8331 return setLCDeclAndLB(
8332 Var,
8333 buildDeclRefExpr(SemaRef, Var,
8334 Var->getType().getNonReferenceType(),
8335 DS->getBeginLoc()),
8336 Var->getInit(), EmitDiags);
8340 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8341 if (CE->getOperator() == OO_Equal) {
8342 Expr *LHS = CE->getArg(0);
8343 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8344 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8345 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8346 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8347 EmitDiags);
8348 return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags);
8350 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8351 if (ME->isArrow() &&
8352 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8353 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8354 EmitDiags);
8359 if (dependent() || SemaRef.CurContext->isDependentContext())
8360 return false;
8361 if (EmitDiags) {
8362 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8363 << S->getSourceRange();
8365 return true;
8368 /// Ignore parenthesizes, implicit casts, copy constructor and return the
8369 /// variable (which may be the loop variable) if possible.
8370 static const ValueDecl *getInitLCDecl(const Expr *E) {
8371 if (!E)
8372 return nullptr;
8373 E = getExprAsWritten(E);
8374 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8375 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8376 if ((Ctor->isCopyOrMoveConstructor() ||
8377 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8378 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8379 E = CE->getArg(0)->IgnoreParenImpCasts();
8380 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8381 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
8382 return getCanonicalDecl(VD);
8384 if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8385 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8386 return getCanonicalDecl(ME->getMemberDecl());
8387 return nullptr;
8390 bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8391 // Check test-expr for canonical form, save upper-bound UB, flags for
8392 // less/greater and for strict/non-strict comparison.
8393 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8394 // var relational-op b
8395 // b relational-op var
8397 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8398 if (!S) {
8399 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8400 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8401 return true;
8403 Condition = S;
8404 S = getExprAsWritten(S);
8405 SourceLocation CondLoc = S->getBeginLoc();
8406 auto &&CheckAndSetCond =
8407 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8408 const Expr *RHS, SourceRange SR,
8409 SourceLocation OpLoc) -> std::optional<bool> {
8410 if (BinaryOperator::isRelationalOp(Opcode)) {
8411 if (getInitLCDecl(LHS) == LCDecl)
8412 return setUB(const_cast<Expr *>(RHS),
8413 (Opcode == BO_LT || Opcode == BO_LE),
8414 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8415 if (getInitLCDecl(RHS) == LCDecl)
8416 return setUB(const_cast<Expr *>(LHS),
8417 (Opcode == BO_GT || Opcode == BO_GE),
8418 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8419 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8420 return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8421 /*LessOp=*/std::nullopt,
8422 /*StrictOp=*/true, SR, OpLoc);
8424 return std::nullopt;
8426 std::optional<bool> Res;
8427 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8428 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8429 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8430 RBO->getOperatorLoc());
8431 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8432 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8433 BO->getSourceRange(), BO->getOperatorLoc());
8434 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8435 if (CE->getNumArgs() == 2) {
8436 Res = CheckAndSetCond(
8437 BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0),
8438 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8441 if (Res)
8442 return *Res;
8443 if (dependent() || SemaRef.CurContext->isDependentContext())
8444 return false;
8445 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8446 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8447 return true;
8450 bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8451 // RHS of canonical loop form increment can be:
8452 // var + incr
8453 // incr + var
8454 // var - incr
8456 RHS = RHS->IgnoreParenImpCasts();
8457 if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8458 if (BO->isAdditiveOp()) {
8459 bool IsAdd = BO->getOpcode() == BO_Add;
8460 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8461 return setStep(BO->getRHS(), !IsAdd);
8462 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8463 return setStep(BO->getLHS(), /*Subtract=*/false);
8465 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8466 bool IsAdd = CE->getOperator() == OO_Plus;
8467 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8468 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8469 return setStep(CE->getArg(1), !IsAdd);
8470 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8471 return setStep(CE->getArg(0), /*Subtract=*/false);
8474 if (dependent() || SemaRef.CurContext->isDependentContext())
8475 return false;
8476 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8477 << RHS->getSourceRange() << LCDecl;
8478 return true;
8481 bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8482 // Check incr-expr for canonical loop form and return true if it
8483 // does not conform.
8484 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8485 // ++var
8486 // var++
8487 // --var
8488 // var--
8489 // var += incr
8490 // var -= incr
8491 // var = var + incr
8492 // var = incr + var
8493 // var = var - incr
8495 if (!S) {
8496 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8497 return true;
8499 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8500 if (!ExprTemp->cleanupsHaveSideEffects())
8501 S = ExprTemp->getSubExpr();
8503 IncrementSrcRange = S->getSourceRange();
8504 S = S->IgnoreParens();
8505 if (auto *UO = dyn_cast<UnaryOperator>(S)) {
8506 if (UO->isIncrementDecrementOp() &&
8507 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8508 return setStep(SemaRef
8509 .ActOnIntegerConstant(UO->getBeginLoc(),
8510 (UO->isDecrementOp() ? -1 : 1))
8511 .get(),
8512 /*Subtract=*/false);
8513 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8514 switch (BO->getOpcode()) {
8515 case BO_AddAssign:
8516 case BO_SubAssign:
8517 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8518 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8519 break;
8520 case BO_Assign:
8521 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8522 return checkAndSetIncRHS(BO->getRHS());
8523 break;
8524 default:
8525 break;
8527 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8528 switch (CE->getOperator()) {
8529 case OO_PlusPlus:
8530 case OO_MinusMinus:
8531 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8532 return setStep(SemaRef
8533 .ActOnIntegerConstant(
8534 CE->getBeginLoc(),
8535 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8536 .get(),
8537 /*Subtract=*/false);
8538 break;
8539 case OO_PlusEqual:
8540 case OO_MinusEqual:
8541 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8542 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8543 break;
8544 case OO_Equal:
8545 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8546 return checkAndSetIncRHS(CE->getArg(1));
8547 break;
8548 default:
8549 break;
8552 if (dependent() || SemaRef.CurContext->isDependentContext())
8553 return false;
8554 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8555 << S->getSourceRange() << LCDecl;
8556 return true;
8559 static ExprResult
8560 tryBuildCapture(Sema &SemaRef, Expr *Capture,
8561 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8562 StringRef Name = ".capture_expr.") {
8563 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8564 return Capture;
8565 if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects))
8566 return SemaRef.PerformImplicitConversion(
8567 Capture->IgnoreImpCasts(), Capture->getType(), Sema::AA_Converting,
8568 /*AllowExplicit=*/true);
8569 auto I = Captures.find(Capture);
8570 if (I != Captures.end())
8571 return buildCapture(SemaRef, Capture, I->second, Name);
8572 DeclRefExpr *Ref = nullptr;
8573 ExprResult Res = buildCapture(SemaRef, Capture, Ref, Name);
8574 Captures[Capture] = Ref;
8575 return Res;
8578 /// Calculate number of iterations, transforming to unsigned, if number of
8579 /// iterations may be larger than the original type.
8580 static Expr *
8581 calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8582 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8583 bool TestIsStrictOp, bool RoundToStep,
8584 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8585 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8586 if (!NewStep.isUsable())
8587 return nullptr;
8588 llvm::APSInt LRes, SRes;
8589 bool IsLowerConst = false, IsStepConst = false;
8590 if (std::optional<llvm::APSInt> Res =
8591 Lower->getIntegerConstantExpr(SemaRef.Context)) {
8592 LRes = *Res;
8593 IsLowerConst = true;
8595 if (std::optional<llvm::APSInt> Res =
8596 Step->getIntegerConstantExpr(SemaRef.Context)) {
8597 SRes = *Res;
8598 IsStepConst = true;
8600 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8601 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8602 (TestIsStrictOp && LRes.isStrictlyPositive()));
8603 bool NeedToReorganize = false;
8604 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8605 if (!NoNeedToConvert && IsLowerConst &&
8606 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8607 NoNeedToConvert = true;
8608 if (RoundToStep) {
8609 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8610 ? LRes.getBitWidth()
8611 : SRes.getBitWidth();
8612 LRes = LRes.extend(BW + 1);
8613 LRes.setIsSigned(true);
8614 SRes = SRes.extend(BW + 1);
8615 SRes.setIsSigned(true);
8616 LRes -= SRes;
8617 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8618 LRes = LRes.trunc(BW);
8620 if (TestIsStrictOp) {
8621 unsigned BW = LRes.getBitWidth();
8622 LRes = LRes.extend(BW + 1);
8623 LRes.setIsSigned(true);
8624 ++LRes;
8625 NoNeedToConvert =
8626 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8627 // truncate to the original bitwidth.
8628 LRes = LRes.trunc(BW);
8630 NeedToReorganize = NoNeedToConvert;
8632 llvm::APSInt URes;
8633 bool IsUpperConst = false;
8634 if (std::optional<llvm::APSInt> Res =
8635 Upper->getIntegerConstantExpr(SemaRef.Context)) {
8636 URes = *Res;
8637 IsUpperConst = true;
8639 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8640 (!RoundToStep || IsStepConst)) {
8641 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8642 : URes.getBitWidth();
8643 LRes = LRes.extend(BW + 1);
8644 LRes.setIsSigned(true);
8645 URes = URes.extend(BW + 1);
8646 URes.setIsSigned(true);
8647 URes -= LRes;
8648 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8649 NeedToReorganize = NoNeedToConvert;
8651 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8652 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8653 // unsigned.
8654 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8655 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8656 QualType LowerTy = Lower->getType();
8657 QualType UpperTy = Upper->getType();
8658 uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy);
8659 uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy);
8660 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8661 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8662 QualType CastType = SemaRef.Context.getIntTypeForBitwidth(
8663 LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8664 Upper =
8665 SemaRef
8666 .PerformImplicitConversion(
8667 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8668 CastType, Sema::AA_Converting)
8669 .get();
8670 Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get();
8671 NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get());
8674 if (!Lower || !Upper || NewStep.isInvalid())
8675 return nullptr;
8677 ExprResult Diff;
8678 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8679 // 1]).
8680 if (NeedToReorganize) {
8681 Diff = Lower;
8683 if (RoundToStep) {
8684 // Lower - Step
8685 Diff =
8686 SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get());
8687 if (!Diff.isUsable())
8688 return nullptr;
8691 // Lower - Step [+ 1]
8692 if (TestIsStrictOp)
8693 Diff = SemaRef.BuildBinOp(
8694 S, DefaultLoc, BO_Add, Diff.get(),
8695 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8696 if (!Diff.isUsable())
8697 return nullptr;
8699 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8700 if (!Diff.isUsable())
8701 return nullptr;
8703 // Upper - (Lower - Step [+ 1]).
8704 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get());
8705 if (!Diff.isUsable())
8706 return nullptr;
8707 } else {
8708 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8710 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8711 // BuildBinOp already emitted error, this one is to point user to upper
8712 // and lower bound, and to tell what is passed to 'operator-'.
8713 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
8714 << Upper->getSourceRange() << Lower->getSourceRange();
8715 return nullptr;
8718 if (!Diff.isUsable())
8719 return nullptr;
8721 // Upper - Lower [- 1]
8722 if (TestIsStrictOp)
8723 Diff = SemaRef.BuildBinOp(
8724 S, DefaultLoc, BO_Sub, Diff.get(),
8725 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8726 if (!Diff.isUsable())
8727 return nullptr;
8729 if (RoundToStep) {
8730 // Upper - Lower [- 1] + Step
8731 Diff =
8732 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
8733 if (!Diff.isUsable())
8734 return nullptr;
8738 // Parentheses (for dumping/debugging purposes only).
8739 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8740 if (!Diff.isUsable())
8741 return nullptr;
8743 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8744 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
8745 if (!Diff.isUsable())
8746 return nullptr;
8748 return Diff.get();
8751 /// Build the expression to calculate the number of iterations.
8752 Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8753 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8754 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8755 QualType VarType = LCDecl->getType().getNonReferenceType();
8756 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8757 !SemaRef.getLangOpts().CPlusPlus)
8758 return nullptr;
8759 Expr *LBVal = LB;
8760 Expr *UBVal = UB;
8761 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8762 // max(LB(MinVal), LB(MaxVal)))
8763 if (InitDependOnLC) {
8764 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8765 if (!IS.MinValue || !IS.MaxValue)
8766 return nullptr;
8767 // OuterVar = Min
8768 ExprResult MinValue =
8769 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8770 if (!MinValue.isUsable())
8771 return nullptr;
8773 ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8774 IS.CounterVar, MinValue.get());
8775 if (!LBMinVal.isUsable())
8776 return nullptr;
8777 // OuterVar = Min, LBVal
8778 LBMinVal =
8779 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal);
8780 if (!LBMinVal.isUsable())
8781 return nullptr;
8782 // (OuterVar = Min, LBVal)
8783 LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get());
8784 if (!LBMinVal.isUsable())
8785 return nullptr;
8787 // OuterVar = Max
8788 ExprResult MaxValue =
8789 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8790 if (!MaxValue.isUsable())
8791 return nullptr;
8793 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8794 IS.CounterVar, MaxValue.get());
8795 if (!LBMaxVal.isUsable())
8796 return nullptr;
8797 // OuterVar = Max, LBVal
8798 LBMaxVal =
8799 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal);
8800 if (!LBMaxVal.isUsable())
8801 return nullptr;
8802 // (OuterVar = Max, LBVal)
8803 LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get());
8804 if (!LBMaxVal.isUsable())
8805 return nullptr;
8807 Expr *LBMin =
8808 tryBuildCapture(SemaRef, LBMinVal.get(), Captures, ".lb_min").get();
8809 Expr *LBMax =
8810 tryBuildCapture(SemaRef, LBMaxVal.get(), Captures, ".lb_max").get();
8811 if (!LBMin || !LBMax)
8812 return nullptr;
8813 // LB(MinVal) < LB(MaxVal)
8814 ExprResult MinLessMaxRes =
8815 SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8816 if (!MinLessMaxRes.isUsable())
8817 return nullptr;
8818 Expr *MinLessMax =
8819 tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures, ".min_less_max")
8820 .get();
8821 if (!MinLessMax)
8822 return nullptr;
8823 if (*TestIsLessOp) {
8824 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8825 // LB(MaxVal))
8826 ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8827 MinLessMax, LBMin, LBMax);
8828 if (!MinLB.isUsable())
8829 return nullptr;
8830 LBVal = MinLB.get();
8831 } else {
8832 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8833 // LB(MaxVal))
8834 ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8835 MinLessMax, LBMax, LBMin);
8836 if (!MaxLB.isUsable())
8837 return nullptr;
8838 LBVal = MaxLB.get();
8840 // OuterVar = LB
8841 LBMinVal =
8842 SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8843 if (!LBMinVal.isUsable())
8844 return nullptr;
8845 LBVal = LBMinVal.get();
8847 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8848 // min(UB(MinVal), UB(MaxVal))
8849 if (CondDependOnLC) {
8850 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8851 if (!IS.MinValue || !IS.MaxValue)
8852 return nullptr;
8853 // OuterVar = Min
8854 ExprResult MinValue =
8855 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8856 if (!MinValue.isUsable())
8857 return nullptr;
8859 ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8860 IS.CounterVar, MinValue.get());
8861 if (!UBMinVal.isUsable())
8862 return nullptr;
8863 // OuterVar = Min, UBVal
8864 UBMinVal =
8865 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal);
8866 if (!UBMinVal.isUsable())
8867 return nullptr;
8868 // (OuterVar = Min, UBVal)
8869 UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get());
8870 if (!UBMinVal.isUsable())
8871 return nullptr;
8873 // OuterVar = Max
8874 ExprResult MaxValue =
8875 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8876 if (!MaxValue.isUsable())
8877 return nullptr;
8879 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8880 IS.CounterVar, MaxValue.get());
8881 if (!UBMaxVal.isUsable())
8882 return nullptr;
8883 // OuterVar = Max, UBVal
8884 UBMaxVal =
8885 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal);
8886 if (!UBMaxVal.isUsable())
8887 return nullptr;
8888 // (OuterVar = Max, UBVal)
8889 UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get());
8890 if (!UBMaxVal.isUsable())
8891 return nullptr;
8893 Expr *UBMin =
8894 tryBuildCapture(SemaRef, UBMinVal.get(), Captures, ".ub_min").get();
8895 Expr *UBMax =
8896 tryBuildCapture(SemaRef, UBMaxVal.get(), Captures, ".ub_max").get();
8897 if (!UBMin || !UBMax)
8898 return nullptr;
8899 // UB(MinVal) > UB(MaxVal)
8900 ExprResult MinGreaterMaxRes =
8901 SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
8902 if (!MinGreaterMaxRes.isUsable())
8903 return nullptr;
8904 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.get(),
8905 Captures, ".min_greater_max")
8906 .get();
8907 if (!MinGreaterMax)
8908 return nullptr;
8909 if (*TestIsLessOp) {
8910 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
8911 // UB(MaxVal))
8912 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
8913 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
8914 if (!MaxUB.isUsable())
8915 return nullptr;
8916 UBVal = MaxUB.get();
8917 } else {
8918 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
8919 // UB(MaxVal))
8920 ExprResult MinUB = SemaRef.ActOnConditionalOp(
8921 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
8922 if (!MinUB.isUsable())
8923 return nullptr;
8924 UBVal = MinUB.get();
8927 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
8928 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
8929 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures, ".upper").get();
8930 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures, ".lower").get();
8931 if (!Upper || !Lower)
8932 return nullptr;
8934 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8935 Step, VarType, TestIsStrictOp,
8936 /*RoundToStep=*/true, Captures);
8937 if (!Diff.isUsable())
8938 return nullptr;
8940 // OpenMP runtime requires 32-bit or 64-bit loop variables.
8941 QualType Type = Diff.get()->getType();
8942 ASTContext &C = SemaRef.Context;
8943 bool UseVarType = VarType->hasIntegerRepresentation() &&
8944 C.getTypeSize(Type) > C.getTypeSize(VarType);
8945 if (!Type->isIntegerType() || UseVarType) {
8946 unsigned NewSize =
8947 UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type);
8948 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
8949 : Type->hasSignedIntegerRepresentation();
8950 Type = C.getIntTypeForBitwidth(NewSize, IsSigned);
8951 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) {
8952 Diff = SemaRef.PerformImplicitConversion(
8953 Diff.get(), Type, Sema::AA_Converting, /*AllowExplicit=*/true);
8954 if (!Diff.isUsable())
8955 return nullptr;
8958 if (LimitedType) {
8959 unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
8960 if (NewSize != C.getTypeSize(Type)) {
8961 if (NewSize < C.getTypeSize(Type)) {
8962 assert(NewSize == 64 && "incorrect loop var size");
8963 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
8964 << InitSrcRange << ConditionSrcRange;
8966 QualType NewType = C.getIntTypeForBitwidth(
8967 NewSize, Type->hasSignedIntegerRepresentation() ||
8968 C.getTypeSize(Type) < NewSize);
8969 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) {
8970 Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
8971 Sema::AA_Converting, true);
8972 if (!Diff.isUsable())
8973 return nullptr;
8978 return Diff.get();
8981 std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
8982 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8983 // Do not build for iterators, they cannot be used in non-rectangular loop
8984 // nests.
8985 if (LCDecl->getType()->isRecordType())
8986 return std::make_pair(nullptr, nullptr);
8987 // If we subtract, the min is in the condition, otherwise the min is in the
8988 // init value.
8989 Expr *MinExpr = nullptr;
8990 Expr *MaxExpr = nullptr;
8991 Expr *LBExpr = *TestIsLessOp ? LB : UB;
8992 Expr *UBExpr = *TestIsLessOp ? UB : LB;
8993 bool LBNonRect =
8994 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
8995 bool UBNonRect =
8996 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
8997 Expr *Lower =
8998 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
8999 Expr *Upper =
9000 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
9001 if (!Upper || !Lower)
9002 return std::make_pair(nullptr, nullptr);
9004 if (*TestIsLessOp)
9005 MinExpr = Lower;
9006 else
9007 MaxExpr = Upper;
9009 // Build minimum/maximum value based on number of iterations.
9010 QualType VarType = LCDecl->getType().getNonReferenceType();
9012 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9013 Step, VarType, TestIsStrictOp,
9014 /*RoundToStep=*/false, Captures);
9015 if (!Diff.isUsable())
9016 return std::make_pair(nullptr, nullptr);
9018 // ((Upper - Lower [- 1]) / Step) * Step
9019 // Parentheses (for dumping/debugging purposes only).
9020 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9021 if (!Diff.isUsable())
9022 return std::make_pair(nullptr, nullptr);
9024 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
9025 if (!NewStep.isUsable())
9026 return std::make_pair(nullptr, nullptr);
9027 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get());
9028 if (!Diff.isUsable())
9029 return std::make_pair(nullptr, nullptr);
9031 // Parentheses (for dumping/debugging purposes only).
9032 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9033 if (!Diff.isUsable())
9034 return std::make_pair(nullptr, nullptr);
9036 // Convert to the ptrdiff_t, if original type is pointer.
9037 if (VarType->isAnyPointerType() &&
9038 !SemaRef.Context.hasSameType(
9039 Diff.get()->getType(),
9040 SemaRef.Context.getUnsignedPointerDiffType())) {
9041 Diff = SemaRef.PerformImplicitConversion(
9042 Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(),
9043 Sema::AA_Converting, /*AllowExplicit=*/true);
9045 if (!Diff.isUsable())
9046 return std::make_pair(nullptr, nullptr);
9048 if (*TestIsLessOp) {
9049 // MinExpr = Lower;
9050 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
9051 Diff = SemaRef.BuildBinOp(
9052 S, DefaultLoc, BO_Add,
9053 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(),
9054 Diff.get());
9055 if (!Diff.isUsable())
9056 return std::make_pair(nullptr, nullptr);
9057 } else {
9058 // MaxExpr = Upper;
9059 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
9060 Diff = SemaRef.BuildBinOp(
9061 S, DefaultLoc, BO_Sub,
9062 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
9063 Diff.get());
9064 if (!Diff.isUsable())
9065 return std::make_pair(nullptr, nullptr);
9068 // Convert to the original type.
9069 if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType))
9070 Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType,
9071 Sema::AA_Converting,
9072 /*AllowExplicit=*/true);
9073 if (!Diff.isUsable())
9074 return std::make_pair(nullptr, nullptr);
9076 Sema::TentativeAnalysisScope Trap(SemaRef);
9077 Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false);
9078 if (!Diff.isUsable())
9079 return std::make_pair(nullptr, nullptr);
9081 if (*TestIsLessOp)
9082 MaxExpr = Diff.get();
9083 else
9084 MinExpr = Diff.get();
9086 return std::make_pair(MinExpr, MaxExpr);
9089 Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
9090 if (InitDependOnLC || CondDependOnLC)
9091 return Condition;
9092 return nullptr;
9095 Expr *OpenMPIterationSpaceChecker::buildPreCond(
9096 Scope *S, Expr *Cond,
9097 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9098 // Do not build a precondition when the condition/initialization is dependent
9099 // to prevent pessimistic early loop exit.
9100 // TODO: this can be improved by calculating min/max values but not sure that
9101 // it will be very effective.
9102 if (CondDependOnLC || InitDependOnLC)
9103 return SemaRef
9104 .PerformImplicitConversion(
9105 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(),
9106 SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
9107 /*AllowExplicit=*/true)
9108 .get();
9110 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
9111 Sema::TentativeAnalysisScope Trap(SemaRef);
9113 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
9114 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
9115 if (!NewLB.isUsable() || !NewUB.isUsable())
9116 return nullptr;
9118 ExprResult CondExpr =
9119 SemaRef.BuildBinOp(S, DefaultLoc,
9120 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
9121 : (TestIsStrictOp ? BO_GT : BO_GE),
9122 NewLB.get(), NewUB.get());
9123 if (CondExpr.isUsable()) {
9124 if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
9125 SemaRef.Context.BoolTy))
9126 CondExpr = SemaRef.PerformImplicitConversion(
9127 CondExpr.get(), SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
9128 /*AllowExplicit=*/true);
9131 // Otherwise use original loop condition and evaluate it in runtime.
9132 return CondExpr.isUsable() ? CondExpr.get() : Cond;
9135 /// Build reference expression to the counter be used for codegen.
9136 DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9137 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9138 DSAStackTy &DSA) const {
9139 auto *VD = dyn_cast<VarDecl>(LCDecl);
9140 if (!VD) {
9141 VD = SemaRef.isOpenMPCapturedDecl(LCDecl);
9142 DeclRefExpr *Ref = buildDeclRefExpr(
9143 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
9144 const DSAStackTy::DSAVarData Data =
9145 DSA.getTopDSA(LCDecl, /*FromParent=*/false);
9146 // If the loop control decl is explicitly marked as private, do not mark it
9147 // as captured again.
9148 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
9149 Captures.insert(std::make_pair(LCRef, Ref));
9150 return Ref;
9152 return cast<DeclRefExpr>(LCRef);
9155 Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9156 if (LCDecl && !LCDecl->isInvalidDecl()) {
9157 QualType Type = LCDecl->getType().getNonReferenceType();
9158 VarDecl *PrivateVar = buildVarDecl(
9159 SemaRef, DefaultLoc, Type, LCDecl->getName(),
9160 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9161 isa<VarDecl>(LCDecl)
9162 ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
9163 : nullptr);
9164 if (PrivateVar->isInvalidDecl())
9165 return nullptr;
9166 return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
9168 return nullptr;
9171 /// Build initialization of the counter to be used for codegen.
9172 Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9174 /// Build step of the counter be used for codegen.
9175 Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9177 Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9178 Scope *S, Expr *Counter,
9179 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9180 Expr *Inc, OverloadedOperatorKind OOK) {
9181 Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
9182 if (!Cnt)
9183 return nullptr;
9184 if (Inc) {
9185 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9186 "Expected only + or - operations for depend clauses.");
9187 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9188 Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
9189 if (!Cnt)
9190 return nullptr;
9192 QualType VarType = LCDecl->getType().getNonReferenceType();
9193 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9194 !SemaRef.getLangOpts().CPlusPlus)
9195 return nullptr;
9196 // Upper - Lower
9197 Expr *Upper =
9198 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9199 Expr *Lower =
9200 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9201 if (!Upper || !Lower)
9202 return nullptr;
9204 ExprResult Diff = calculateNumIters(
9205 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9206 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures);
9207 if (!Diff.isUsable())
9208 return nullptr;
9210 return Diff.get();
9212 } // namespace
9214 void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) {
9215 assert(getLangOpts().OpenMP && "OpenMP is not active.");
9216 assert(Init && "Expected loop in canonical form.");
9217 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9218 if (AssociatedLoops > 0 &&
9219 isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
9220 DSAStack->loopStart();
9221 OpenMPIterationSpaceChecker ISC(*this, /*SupportsNonRectangular=*/true,
9222 *DSAStack, ForLoc);
9223 if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
9224 if (ValueDecl *D = ISC.getLoopDecl()) {
9225 auto *VD = dyn_cast<VarDecl>(D);
9226 DeclRefExpr *PrivateRef = nullptr;
9227 if (!VD) {
9228 if (VarDecl *Private = isOpenMPCapturedDecl(D)) {
9229 VD = Private;
9230 } else {
9231 PrivateRef = buildCapture(*this, D, ISC.getLoopDeclRefExpr(),
9232 /*WithInit=*/false);
9233 VD = cast<VarDecl>(PrivateRef->getDecl());
9236 DSAStack->addLoopControlVariable(D, VD);
9237 const Decl *LD = DSAStack->getPossiblyLoopCunter();
9238 if (LD != D->getCanonicalDecl()) {
9239 DSAStack->resetPossibleLoopCounter();
9240 if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
9241 MarkDeclarationsReferencedInExpr(
9242 buildDeclRefExpr(*this, const_cast<VarDecl *>(Var),
9243 Var->getType().getNonLValueExprType(Context),
9244 ForLoc, /*RefersToCapture=*/true));
9246 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9247 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9248 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9249 // associated for-loop of a simd construct with just one associated
9250 // for-loop may be listed in a linear clause with a constant-linear-step
9251 // that is the increment of the associated for-loop. The loop iteration
9252 // variable(s) in the associated for-loop(s) of a for or parallel for
9253 // construct may be listed in a private or lastprivate clause.
9254 DSAStackTy::DSAVarData DVar =
9255 DSAStack->getTopDSA(D, /*FromParent=*/false);
9256 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9257 // is declared in the loop and it is predetermined as a private.
9258 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9259 OpenMPClauseKind PredeterminedCKind =
9260 isOpenMPSimdDirective(DKind)
9261 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9262 : OMPC_private;
9263 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9264 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9265 (LangOpts.OpenMP <= 45 || (DVar.CKind != OMPC_lastprivate &&
9266 DVar.CKind != OMPC_private))) ||
9267 ((isOpenMPWorksharingDirective(DKind) || DKind == OMPD_taskloop ||
9268 DKind == OMPD_master_taskloop || DKind == OMPD_masked_taskloop ||
9269 DKind == OMPD_parallel_master_taskloop ||
9270 DKind == OMPD_parallel_masked_taskloop ||
9271 isOpenMPDistributeDirective(DKind)) &&
9272 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9273 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9274 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9275 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9276 << getOpenMPClauseName(DVar.CKind)
9277 << getOpenMPDirectiveName(DKind)
9278 << getOpenMPClauseName(PredeterminedCKind);
9279 if (DVar.RefExpr == nullptr)
9280 DVar.CKind = PredeterminedCKind;
9281 reportOriginalDsa(*this, DSAStack, D, DVar,
9282 /*IsLoopIterVar=*/true);
9283 } else if (LoopDeclRefExpr) {
9284 // Make the loop iteration variable private (for worksharing
9285 // constructs), linear (for simd directives with the only one
9286 // associated loop) or lastprivate (for simd directives with several
9287 // collapsed or ordered loops).
9288 if (DVar.CKind == OMPC_unknown)
9289 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind,
9290 PrivateRef);
9294 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9298 namespace {
9299 // Utility for openmp doacross clause kind
9300 class OMPDoacrossKind {
9301 public:
9302 bool isSource(const OMPDoacrossClause *C) {
9303 return C->getDependenceType() == OMPC_DOACROSS_source ||
9304 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9306 bool isSink(const OMPDoacrossClause *C) {
9307 return C->getDependenceType() == OMPC_DOACROSS_sink;
9309 bool isSinkIter(const OMPDoacrossClause *C) {
9310 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9313 } // namespace
9314 /// Called on a for stmt to check and extract its iteration space
9315 /// for further processing (such as collapsing).
9316 static bool checkOpenMPIterationSpace(
9317 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9318 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9319 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9320 Expr *OrderedLoopCountExpr,
9321 Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9322 llvm::MutableArrayRef<LoopIterationSpace> ResultIterSpaces,
9323 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9324 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9325 // OpenMP [2.9.1, Canonical Loop Form]
9326 // for (init-expr; test-expr; incr-expr) structured-block
9327 // for (range-decl: range-expr) structured-block
9328 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9329 S = CanonLoop->getLoopStmt();
9330 auto *For = dyn_cast_or_null<ForStmt>(S);
9331 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9332 // Ranged for is supported only in OpenMP 5.0.
9333 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9334 OpenMPDirectiveKind DK = (SemaRef.getLangOpts().OpenMP < 50 ||
9335 DSA.getMappedDirective() == OMPD_unknown)
9336 ? DKind
9337 : DSA.getMappedDirective();
9338 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
9339 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9340 << getOpenMPDirectiveName(DK) << TotalNestedLoopCount
9341 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9342 if (TotalNestedLoopCount > 1) {
9343 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9344 SemaRef.Diag(DSA.getConstructLoc(),
9345 diag::note_omp_collapse_ordered_expr)
9346 << 2 << CollapseLoopCountExpr->getSourceRange()
9347 << OrderedLoopCountExpr->getSourceRange();
9348 else if (CollapseLoopCountExpr)
9349 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9350 diag::note_omp_collapse_ordered_expr)
9351 << 0 << CollapseLoopCountExpr->getSourceRange();
9352 else
9353 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9354 diag::note_omp_collapse_ordered_expr)
9355 << 1 << OrderedLoopCountExpr->getSourceRange();
9357 return true;
9359 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9360 "No loop body.");
9361 // Postpone analysis in dependent contexts for ranged for loops.
9362 if (CXXFor && SemaRef.CurContext->isDependentContext())
9363 return false;
9365 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9366 For ? For->getForLoc() : CXXFor->getForLoc());
9368 // Check init.
9369 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9370 if (ISC.checkAndSetInit(Init))
9371 return true;
9373 bool HasErrors = false;
9375 // Check loop variable's type.
9376 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9377 // OpenMP [2.6, Canonical Loop Form]
9378 // Var is one of the following:
9379 // A variable of signed or unsigned integer type.
9380 // For C++, a variable of a random access iterator type.
9381 // For C, a variable of a pointer type.
9382 QualType VarType = LCDecl->getType().getNonReferenceType();
9383 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9384 !VarType->isPointerType() &&
9385 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9386 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9387 << SemaRef.getLangOpts().CPlusPlus;
9388 HasErrors = true;
9391 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9392 // a Construct
9393 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9394 // parallel for construct is (are) private.
9395 // The loop iteration variable in the associated for-loop of a simd
9396 // construct with just one associated for-loop is linear with a
9397 // constant-linear-step that is the increment of the associated for-loop.
9398 // Exclude loop var from the list of variables with implicitly defined data
9399 // sharing attributes.
9400 VarsWithImplicitDSA.erase(LCDecl);
9402 assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
9404 // Check test-expr.
9405 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9407 // Check incr-expr.
9408 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9411 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9412 return HasErrors;
9414 // Build the loop's iteration space representation.
9415 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9416 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9417 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9418 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9419 (isOpenMPWorksharingDirective(DKind) ||
9420 isOpenMPGenericLoopDirective(DKind) ||
9421 isOpenMPTaskLoopDirective(DKind) ||
9422 isOpenMPDistributeDirective(DKind) ||
9423 isOpenMPLoopTransformationDirective(DKind)),
9424 Captures);
9425 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9426 ISC.buildCounterVar(Captures, DSA);
9427 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9428 ISC.buildPrivateCounterVar();
9429 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9430 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9431 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9432 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9433 ISC.getConditionSrcRange();
9434 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9435 ISC.getIncrementSrcRange();
9436 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9437 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9438 ISC.isStrictTestOp();
9439 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9440 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9441 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9442 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9443 ISC.buildFinalCondition(DSA.getCurScope());
9444 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9445 ISC.doesInitDependOnLC();
9446 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9447 ISC.doesCondDependOnLC();
9448 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9449 ISC.getLoopDependentIdx();
9451 HasErrors |=
9452 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9453 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9454 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9455 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9456 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9457 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9458 if (!HasErrors && DSA.isOrderedRegion()) {
9459 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9460 if (CurrentNestedLoopCount <
9461 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9462 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9463 CurrentNestedLoopCount,
9464 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9465 DSA.getOrderedRegionParam().second->setLoopCounter(
9466 CurrentNestedLoopCount,
9467 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9470 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9471 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9472 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9473 unsigned NumLoops =
9474 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9475 if (CurrentNestedLoopCount >= NumLoops) {
9476 // Erroneous case - clause has some problems.
9477 continue;
9479 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9480 Pair.second.size() <= CurrentNestedLoopCount) {
9481 // Erroneous case - clause has some problems.
9482 DependC->setLoopData(CurrentNestedLoopCount, nullptr);
9483 continue;
9485 OMPDoacrossKind ODK;
9486 if (DoacrossC && ODK.isSink(DoacrossC) &&
9487 Pair.second.size() <= CurrentNestedLoopCount) {
9488 // Erroneous case - clause has some problems.
9489 DoacrossC->setLoopData(CurrentNestedLoopCount, nullptr);
9490 continue;
9492 Expr *CntValue;
9493 SourceLocation DepLoc =
9494 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9495 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9496 (DoacrossC && ODK.isSource(DoacrossC)))
9497 CntValue = ISC.buildOrderedLoopData(
9498 DSA.getCurScope(),
9499 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9500 DepLoc);
9501 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9502 Expr *Cnt = SemaRef
9503 .DefaultLvalueConversion(
9504 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9505 .get();
9506 if (!Cnt)
9507 continue;
9508 // build CounterVar - 1
9509 Expr *Inc =
9510 SemaRef.ActOnIntegerConstant(DoacrossC->getColonLoc(), /*Val=*/1)
9511 .get();
9512 CntValue = ISC.buildOrderedLoopData(
9513 DSA.getCurScope(),
9514 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9515 DepLoc, Inc, clang::OO_Minus);
9516 } else
9517 CntValue = ISC.buildOrderedLoopData(
9518 DSA.getCurScope(),
9519 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9520 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9521 Pair.second[CurrentNestedLoopCount].second);
9522 if (DependC)
9523 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9524 else
9525 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9529 return HasErrors;
9532 /// Build 'VarRef = Start.
9533 static ExprResult
9534 buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9535 ExprResult Start, bool IsNonRectangularLB,
9536 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9537 // Build 'VarRef = Start.
9538 ExprResult NewStart = IsNonRectangularLB
9539 ? Start.get()
9540 : tryBuildCapture(SemaRef, Start.get(), Captures);
9541 if (!NewStart.isUsable())
9542 return ExprError();
9543 if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
9544 VarRef.get()->getType())) {
9545 NewStart = SemaRef.PerformImplicitConversion(
9546 NewStart.get(), VarRef.get()->getType(), Sema::AA_Converting,
9547 /*AllowExplicit=*/true);
9548 if (!NewStart.isUsable())
9549 return ExprError();
9552 ExprResult Init =
9553 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9554 return Init;
9557 /// Build 'VarRef = Start + Iter * Step'.
9558 static ExprResult buildCounterUpdate(
9559 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9560 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9561 bool IsNonRectangularLB,
9562 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9563 // Add parentheses (for debugging purposes only).
9564 Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
9565 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9566 !Step.isUsable())
9567 return ExprError();
9569 ExprResult NewStep = Step;
9570 if (Captures)
9571 NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures);
9572 if (NewStep.isInvalid())
9573 return ExprError();
9574 ExprResult Update =
9575 SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get());
9576 if (!Update.isUsable())
9577 return ExprError();
9579 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9580 // 'VarRef = Start (+|-) Iter * Step'.
9581 if (!Start.isUsable())
9582 return ExprError();
9583 ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get());
9584 if (!NewStart.isUsable())
9585 return ExprError();
9586 if (Captures && !IsNonRectangularLB)
9587 NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures);
9588 if (NewStart.isInvalid())
9589 return ExprError();
9591 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9592 ExprResult SavedUpdate = Update;
9593 ExprResult UpdateVal;
9594 if (VarRef.get()->getType()->isOverloadableType() ||
9595 NewStart.get()->getType()->isOverloadableType() ||
9596 Update.get()->getType()->isOverloadableType()) {
9597 Sema::TentativeAnalysisScope Trap(SemaRef);
9599 Update =
9600 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9601 if (Update.isUsable()) {
9602 UpdateVal =
9603 SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9604 VarRef.get(), SavedUpdate.get());
9605 if (UpdateVal.isUsable()) {
9606 Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(),
9607 UpdateVal.get());
9612 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9613 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9614 Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add,
9615 NewStart.get(), SavedUpdate.get());
9616 if (!Update.isUsable())
9617 return ExprError();
9619 if (!SemaRef.Context.hasSameType(Update.get()->getType(),
9620 VarRef.get()->getType())) {
9621 Update = SemaRef.PerformImplicitConversion(
9622 Update.get(), VarRef.get()->getType(), Sema::AA_Converting, true);
9623 if (!Update.isUsable())
9624 return ExprError();
9627 Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
9629 return Update;
9632 /// Convert integer expression \a E to make it have at least \a Bits
9633 /// bits.
9634 static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9635 if (E == nullptr)
9636 return ExprError();
9637 ASTContext &C = SemaRef.Context;
9638 QualType OldType = E->getType();
9639 unsigned HasBits = C.getTypeSize(OldType);
9640 if (HasBits >= Bits)
9641 return ExprResult(E);
9642 // OK to convert to signed, because new type has more bits than old.
9643 QualType NewType = C.getIntTypeForBitwidth(Bits, /* Signed */ true);
9644 return SemaRef.PerformImplicitConversion(E, NewType, Sema::AA_Converting,
9645 true);
9648 /// Check if the given expression \a E is a constant integer that fits
9649 /// into \a Bits bits.
9650 static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9651 if (E == nullptr)
9652 return false;
9653 if (std::optional<llvm::APSInt> Result =
9654 E->getIntegerConstantExpr(SemaRef.Context))
9655 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9656 return false;
9659 /// Build preinits statement for the given declarations.
9660 static Stmt *buildPreInits(ASTContext &Context,
9661 MutableArrayRef<Decl *> PreInits) {
9662 if (!PreInits.empty()) {
9663 return new (Context) DeclStmt(
9664 DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()),
9665 SourceLocation(), SourceLocation());
9667 return nullptr;
9670 /// Build preinits statement for the given declarations.
9671 static Stmt *
9672 buildPreInits(ASTContext &Context,
9673 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9674 if (!Captures.empty()) {
9675 SmallVector<Decl *, 16> PreInits;
9676 for (const auto &Pair : Captures)
9677 PreInits.push_back(Pair.second->getDecl());
9678 return buildPreInits(Context, PreInits);
9680 return nullptr;
9683 /// Build postupdate expression for the given list of postupdates expressions.
9684 static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9685 Expr *PostUpdate = nullptr;
9686 if (!PostUpdates.empty()) {
9687 for (Expr *E : PostUpdates) {
9688 Expr *ConvE = S.BuildCStyleCastExpr(
9689 E->getExprLoc(),
9690 S.Context.getTrivialTypeSourceInfo(S.Context.VoidTy),
9691 E->getExprLoc(), E)
9692 .get();
9693 PostUpdate = PostUpdate
9694 ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma,
9695 PostUpdate, ConvE)
9696 .get()
9697 : ConvE;
9700 return PostUpdate;
9703 /// Called on a for stmt to check itself and nested loops (if any).
9704 /// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9705 /// number of collapsed loops otherwise.
9706 static unsigned
9707 checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9708 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
9709 DSAStackTy &DSA,
9710 Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9711 OMPLoopBasedDirective::HelperExprs &Built) {
9712 unsigned NestedLoopCount = 1;
9713 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9714 !isOpenMPLoopTransformationDirective(DKind);
9716 if (CollapseLoopCountExpr) {
9717 // Found 'collapse' clause - calculate collapse number.
9718 Expr::EvalResult Result;
9719 if (!CollapseLoopCountExpr->isValueDependent() &&
9720 CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
9721 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9722 } else {
9723 Built.clear(/*Size=*/1);
9724 return 1;
9727 unsigned OrderedLoopCount = 1;
9728 if (OrderedLoopCountExpr) {
9729 // Found 'ordered' clause - calculate collapse number.
9730 Expr::EvalResult EVResult;
9731 if (!OrderedLoopCountExpr->isValueDependent() &&
9732 OrderedLoopCountExpr->EvaluateAsInt(EVResult,
9733 SemaRef.getASTContext())) {
9734 llvm::APSInt Result = EVResult.Val.getInt();
9735 if (Result.getLimitedValue() < NestedLoopCount) {
9736 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9737 diag::err_omp_wrong_ordered_loop_count)
9738 << OrderedLoopCountExpr->getSourceRange();
9739 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9740 diag::note_collapse_loop_count)
9741 << CollapseLoopCountExpr->getSourceRange();
9743 OrderedLoopCount = Result.getLimitedValue();
9744 } else {
9745 Built.clear(/*Size=*/1);
9746 return 1;
9749 // This is helper routine for loop directives (e.g., 'for', 'simd',
9750 // 'for simd', etc.).
9751 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9752 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9753 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
9754 if (!OMPLoopBasedDirective::doForAllLoops(
9755 AStmt->IgnoreContainers(!isOpenMPLoopTransformationDirective(DKind)),
9756 SupportsNonPerfectlyNested, NumLoops,
9757 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9758 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9759 &IterSpaces, &Captures](unsigned Cnt, Stmt *CurStmt) {
9760 if (checkOpenMPIterationSpace(
9761 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9762 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9763 VarsWithImplicitDSA, IterSpaces, Captures))
9764 return true;
9765 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9766 IterSpaces[Cnt].CounterVar) {
9767 // Handle initialization of captured loop iterator variables.
9768 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9769 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
9770 Captures[DRE] = DRE;
9773 return false;
9775 [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
9776 Stmt *DependentPreInits = Transform->getPreInits();
9777 if (!DependentPreInits)
9778 return;
9779 for (Decl *C : cast<DeclStmt>(DependentPreInits)->getDeclGroup()) {
9780 auto *D = cast<VarDecl>(C);
9781 DeclRefExpr *Ref = buildDeclRefExpr(SemaRef, D, D->getType(),
9782 Transform->getBeginLoc());
9783 Captures[Ref] = Ref;
9786 return 0;
9788 Built.clear(/* size */ NestedLoopCount);
9790 if (SemaRef.CurContext->isDependentContext())
9791 return NestedLoopCount;
9793 // An example of what is generated for the following code:
9795 // #pragma omp simd collapse(2) ordered(2)
9796 // for (i = 0; i < NI; ++i)
9797 // for (k = 0; k < NK; ++k)
9798 // for (j = J0; j < NJ; j+=2) {
9799 // <loop body>
9800 // }
9802 // We generate the code below.
9803 // Note: the loop body may be outlined in CodeGen.
9804 // Note: some counters may be C++ classes, operator- is used to find number of
9805 // iterations and operator+= to calculate counter value.
9806 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
9807 // or i64 is currently supported).
9809 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
9810 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
9811 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
9812 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
9813 // // similar updates for vars in clauses (e.g. 'linear')
9814 // <loop body (using local i and j)>
9815 // }
9816 // i = NI; // assign final values of counters
9817 // j = NJ;
9820 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
9821 // the iteration counts of the collapsed for loops.
9822 // Precondition tests if there is at least one iteration (all conditions are
9823 // true).
9824 auto PreCond = ExprResult(IterSpaces[0].PreCond);
9825 Expr *N0 = IterSpaces[0].NumIterations;
9826 ExprResult LastIteration32 =
9827 widenIterationCount(/*Bits=*/32,
9828 SemaRef
9829 .PerformImplicitConversion(
9830 N0->IgnoreImpCasts(), N0->getType(),
9831 Sema::AA_Converting, /*AllowExplicit=*/true)
9832 .get(),
9833 SemaRef);
9834 ExprResult LastIteration64 = widenIterationCount(
9835 /*Bits=*/64,
9836 SemaRef
9837 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
9838 Sema::AA_Converting,
9839 /*AllowExplicit=*/true)
9840 .get(),
9841 SemaRef);
9843 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
9844 return NestedLoopCount;
9846 ASTContext &C = SemaRef.Context;
9847 bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
9849 Scope *CurScope = DSA.getCurScope();
9850 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
9851 if (PreCond.isUsable()) {
9852 PreCond =
9853 SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
9854 PreCond.get(), IterSpaces[Cnt].PreCond);
9856 Expr *N = IterSpaces[Cnt].NumIterations;
9857 SourceLocation Loc = N->getExprLoc();
9858 AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
9859 if (LastIteration32.isUsable())
9860 LastIteration32 = SemaRef.BuildBinOp(
9861 CurScope, Loc, BO_Mul, LastIteration32.get(),
9862 SemaRef
9863 .PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(),
9864 Sema::AA_Converting,
9865 /*AllowExplicit=*/true)
9866 .get());
9867 if (LastIteration64.isUsable())
9868 LastIteration64 = SemaRef.BuildBinOp(
9869 CurScope, Loc, BO_Mul, LastIteration64.get(),
9870 SemaRef
9871 .PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(),
9872 Sema::AA_Converting,
9873 /*AllowExplicit=*/true)
9874 .get());
9877 // Choose either the 32-bit or 64-bit version.
9878 ExprResult LastIteration = LastIteration64;
9879 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
9880 (LastIteration32.isUsable() &&
9881 C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
9882 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
9883 fitsInto(
9884 /*Bits=*/32,
9885 LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
9886 LastIteration64.get(), SemaRef))))
9887 LastIteration = LastIteration32;
9888 QualType VType = LastIteration.get()->getType();
9889 QualType RealVType = VType;
9890 QualType StrideVType = VType;
9891 if (isOpenMPTaskLoopDirective(DKind)) {
9892 VType =
9893 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
9894 StrideVType =
9895 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
9898 if (!LastIteration.isUsable())
9899 return 0;
9901 // Save the number of iterations.
9902 ExprResult NumIterations = LastIteration;
9904 LastIteration = SemaRef.BuildBinOp(
9905 CurScope, LastIteration.get()->getExprLoc(), BO_Sub,
9906 LastIteration.get(),
9907 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9908 if (!LastIteration.isUsable())
9909 return 0;
9912 // Calculate the last iteration number beforehand instead of doing this on
9913 // each iteration. Do not do this if the number of iterations may be kfold-ed.
9914 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context);
9915 ExprResult CalcLastIteration;
9916 if (!IsConstant) {
9917 ExprResult SaveRef =
9918 tryBuildCapture(SemaRef, LastIteration.get(), Captures);
9919 LastIteration = SaveRef;
9921 // Prepare SaveRef + 1.
9922 NumIterations = SemaRef.BuildBinOp(
9923 CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(),
9924 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9925 if (!NumIterations.isUsable())
9926 return 0;
9929 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
9931 // Build variables passed into runtime, necessary for worksharing directives.
9932 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
9933 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
9934 isOpenMPDistributeDirective(DKind) ||
9935 isOpenMPGenericLoopDirective(DKind) ||
9936 isOpenMPLoopTransformationDirective(DKind)) {
9937 // Lower bound variable, initialized with zero.
9938 VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
9939 LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
9940 SemaRef.AddInitializerToDecl(LBDecl,
9941 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9942 /*DirectInit*/ false);
9944 // Upper bound variable, initialized with last iteration number.
9945 VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
9946 UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
9947 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
9948 /*DirectInit*/ false);
9950 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
9951 // This will be used to implement clause 'lastprivate'.
9952 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
9953 VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
9954 IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
9955 SemaRef.AddInitializerToDecl(ILDecl,
9956 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9957 /*DirectInit*/ false);
9959 // Stride variable returned by runtime (we initialize it to 1 by default).
9960 VarDecl *STDecl =
9961 buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride");
9962 ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc);
9963 SemaRef.AddInitializerToDecl(STDecl,
9964 SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
9965 /*DirectInit*/ false);
9967 // Build expression: UB = min(UB, LastIteration)
9968 // It is necessary for CodeGen of directives with static scheduling.
9969 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
9970 UB.get(), LastIteration.get());
9971 ExprResult CondOp = SemaRef.ActOnConditionalOp(
9972 LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
9973 LastIteration.get(), UB.get());
9974 EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
9975 CondOp.get());
9976 EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue*/ false);
9978 // If we have a combined directive that combines 'distribute', 'for' or
9979 // 'simd' we need to be able to access the bounds of the schedule of the
9980 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
9981 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
9982 if (isOpenMPLoopBoundSharingDirective(DKind)) {
9983 // Lower bound variable, initialized with zero.
9984 VarDecl *CombLBDecl =
9985 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
9986 CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc);
9987 SemaRef.AddInitializerToDecl(
9988 CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9989 /*DirectInit*/ false);
9991 // Upper bound variable, initialized with last iteration number.
9992 VarDecl *CombUBDecl =
9993 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub");
9994 CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc);
9995 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
9996 /*DirectInit*/ false);
9998 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
9999 CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get());
10000 ExprResult CombCondOp =
10001 SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(),
10002 LastIteration.get(), CombUB.get());
10003 CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
10004 CombCondOp.get());
10005 CombEUB =
10006 SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue*/ false);
10008 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
10009 // We expect to have at least 2 more parameters than the 'parallel'
10010 // directive does - the lower and upper bounds of the previous schedule.
10011 assert(CD->getNumParams() >= 4 &&
10012 "Unexpected number of parameters in loop combined directive");
10014 // Set the proper type for the bounds given what we learned from the
10015 // enclosed loops.
10016 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
10017 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
10019 // Previous lower and upper bounds are obtained from the region
10020 // parameters.
10021 PrevLB =
10022 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
10023 PrevUB =
10024 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
10028 // Build the iteration variable and its initialization before loop.
10029 ExprResult IV;
10030 ExprResult Init, CombInit;
10032 VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
10033 IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
10034 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
10035 isOpenMPGenericLoopDirective(DKind) ||
10036 isOpenMPTaskLoopDirective(DKind) ||
10037 isOpenMPDistributeDirective(DKind) ||
10038 isOpenMPLoopTransformationDirective(DKind))
10039 ? LB.get()
10040 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10041 Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
10042 Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false);
10044 if (isOpenMPLoopBoundSharingDirective(DKind)) {
10045 Expr *CombRHS =
10046 (isOpenMPWorksharingDirective(DKind) ||
10047 isOpenMPGenericLoopDirective(DKind) ||
10048 isOpenMPTaskLoopDirective(DKind) ||
10049 isOpenMPDistributeDirective(DKind))
10050 ? CombLB.get()
10051 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10052 CombInit =
10053 SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
10054 CombInit =
10055 SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue*/ false);
10059 bool UseStrictCompare =
10060 RealVType->hasUnsignedIntegerRepresentation() &&
10061 llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) {
10062 return LIS.IsStrictCompare;
10064 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
10065 // unsigned IV)) for worksharing loops.
10066 SourceLocation CondLoc = AStmt->getBeginLoc();
10067 Expr *BoundUB = UB.get();
10068 if (UseStrictCompare) {
10069 BoundUB =
10070 SemaRef
10071 .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
10072 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10073 .get();
10074 BoundUB =
10075 SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue*/ false).get();
10077 ExprResult Cond =
10078 (isOpenMPWorksharingDirective(DKind) ||
10079 isOpenMPGenericLoopDirective(DKind) ||
10080 isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind) ||
10081 isOpenMPLoopTransformationDirective(DKind))
10082 ? SemaRef.BuildBinOp(CurScope, CondLoc,
10083 UseStrictCompare ? BO_LT : BO_LE, IV.get(),
10084 BoundUB)
10085 : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10086 NumIterations.get());
10087 ExprResult CombDistCond;
10088 if (isOpenMPLoopBoundSharingDirective(DKind)) {
10089 CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10090 NumIterations.get());
10093 ExprResult CombCond;
10094 if (isOpenMPLoopBoundSharingDirective(DKind)) {
10095 Expr *BoundCombUB = CombUB.get();
10096 if (UseStrictCompare) {
10097 BoundCombUB =
10098 SemaRef
10099 .BuildBinOp(
10100 CurScope, CondLoc, BO_Add, BoundCombUB,
10101 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10102 .get();
10103 BoundCombUB =
10104 SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue*/ false)
10105 .get();
10107 CombCond =
10108 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10109 IV.get(), BoundCombUB);
10111 // Loop increment (IV = IV + 1)
10112 SourceLocation IncLoc = AStmt->getBeginLoc();
10113 ExprResult Inc =
10114 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
10115 SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
10116 if (!Inc.isUsable())
10117 return 0;
10118 Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
10119 Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue*/ false);
10120 if (!Inc.isUsable())
10121 return 0;
10123 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
10124 // Used for directives with static scheduling.
10125 // In combined construct, add combined version that use CombLB and CombUB
10126 // base variables for the update
10127 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10128 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
10129 isOpenMPGenericLoopDirective(DKind) ||
10130 isOpenMPDistributeDirective(DKind) ||
10131 isOpenMPLoopTransformationDirective(DKind)) {
10132 // LB + ST
10133 NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
10134 if (!NextLB.isUsable())
10135 return 0;
10136 // LB = LB + ST
10137 NextLB =
10138 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
10139 NextLB =
10140 SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue*/ false);
10141 if (!NextLB.isUsable())
10142 return 0;
10143 // UB + ST
10144 NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get());
10145 if (!NextUB.isUsable())
10146 return 0;
10147 // UB = UB + ST
10148 NextUB =
10149 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
10150 NextUB =
10151 SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue*/ false);
10152 if (!NextUB.isUsable())
10153 return 0;
10154 if (isOpenMPLoopBoundSharingDirective(DKind)) {
10155 CombNextLB =
10156 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get());
10157 if (!NextLB.isUsable())
10158 return 0;
10159 // LB = LB + ST
10160 CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
10161 CombNextLB.get());
10162 CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
10163 /*DiscardedValue*/ false);
10164 if (!CombNextLB.isUsable())
10165 return 0;
10166 // UB + ST
10167 CombNextUB =
10168 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get());
10169 if (!CombNextUB.isUsable())
10170 return 0;
10171 // UB = UB + ST
10172 CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
10173 CombNextUB.get());
10174 CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
10175 /*DiscardedValue*/ false);
10176 if (!CombNextUB.isUsable())
10177 return 0;
10181 // Create increment expression for distribute loop when combined in a same
10182 // directive with for as IV = IV + ST; ensure upper bound expression based
10183 // on PrevUB instead of NumIterations - used to implement 'for' when found
10184 // in combination with 'distribute', like in 'distribute parallel for'
10185 SourceLocation DistIncLoc = AStmt->getBeginLoc();
10186 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10187 if (isOpenMPLoopBoundSharingDirective(DKind)) {
10188 DistCond = SemaRef.BuildBinOp(
10189 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB);
10190 assert(DistCond.isUsable() && "distribute cond expr was not built");
10192 DistInc =
10193 SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get());
10194 assert(DistInc.isUsable() && "distribute inc expr was not built");
10195 DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
10196 DistInc.get());
10197 DistInc =
10198 SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue*/ false);
10199 assert(DistInc.isUsable() && "distribute inc expr was not built");
10201 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10202 // construct
10203 ExprResult NewPrevUB = PrevUB;
10204 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10205 if (!SemaRef.Context.hasSameType(UB.get()->getType(),
10206 PrevUB.get()->getType())) {
10207 NewPrevUB = SemaRef.BuildCStyleCastExpr(
10208 DistEUBLoc,
10209 SemaRef.Context.getTrivialTypeSourceInfo(UB.get()->getType()),
10210 DistEUBLoc, NewPrevUB.get());
10211 if (!NewPrevUB.isUsable())
10212 return 0;
10214 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT,
10215 UB.get(), NewPrevUB.get());
10216 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10217 DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get());
10218 PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
10219 CondOp.get());
10220 PrevEUB =
10221 SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue*/ false);
10223 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10224 // parallel for is in combination with a distribute directive with
10225 // schedule(static, 1)
10226 Expr *BoundPrevUB = PrevUB.get();
10227 if (UseStrictCompare) {
10228 BoundPrevUB =
10229 SemaRef
10230 .BuildBinOp(
10231 CurScope, CondLoc, BO_Add, BoundPrevUB,
10232 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10233 .get();
10234 BoundPrevUB =
10235 SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue*/ false)
10236 .get();
10238 ParForInDistCond =
10239 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10240 IV.get(), BoundPrevUB);
10243 // Build updates and final values of the loop counters.
10244 bool HasErrors = false;
10245 Built.Counters.resize(NestedLoopCount);
10246 Built.Inits.resize(NestedLoopCount);
10247 Built.Updates.resize(NestedLoopCount);
10248 Built.Finals.resize(NestedLoopCount);
10249 Built.DependentCounters.resize(NestedLoopCount);
10250 Built.DependentInits.resize(NestedLoopCount);
10251 Built.FinalsConditions.resize(NestedLoopCount);
10253 // We implement the following algorithm for obtaining the
10254 // original loop iteration variable values based on the
10255 // value of the collapsed loop iteration variable IV.
10257 // Let n+1 be the number of collapsed loops in the nest.
10258 // Iteration variables (I0, I1, .... In)
10259 // Iteration counts (N0, N1, ... Nn)
10261 // Acc = IV;
10263 // To compute Ik for loop k, 0 <= k <= n, generate:
10264 // Prod = N(k+1) * N(k+2) * ... * Nn;
10265 // Ik = Acc / Prod;
10266 // Acc -= Ik * Prod;
10268 ExprResult Acc = IV;
10269 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10270 LoopIterationSpace &IS = IterSpaces[Cnt];
10271 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10272 ExprResult Iter;
10274 // Compute prod
10275 ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
10276 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10277 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(),
10278 IterSpaces[K].NumIterations);
10280 // Iter = Acc / Prod
10281 // If there is at least one more inner loop to avoid
10282 // multiplication by 1.
10283 if (Cnt + 1 < NestedLoopCount)
10284 Iter =
10285 SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get());
10286 else
10287 Iter = Acc;
10288 if (!Iter.isUsable()) {
10289 HasErrors = true;
10290 break;
10293 // Update Acc:
10294 // Acc -= Iter * Prod
10295 // Check if there is at least one more inner loop to avoid
10296 // multiplication by 1.
10297 if (Cnt + 1 < NestedLoopCount)
10298 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(),
10299 Prod.get());
10300 else
10301 Prod = Iter;
10302 Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get());
10304 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10305 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10306 DeclRefExpr *CounterVar = buildDeclRefExpr(
10307 SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
10308 /*RefersToCapture=*/true);
10309 ExprResult Init =
10310 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
10311 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10312 if (!Init.isUsable()) {
10313 HasErrors = true;
10314 break;
10316 ExprResult Update = buildCounterUpdate(
10317 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10318 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10319 if (!Update.isUsable()) {
10320 HasErrors = true;
10321 break;
10324 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10325 ExprResult Final =
10326 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
10327 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10328 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10329 if (!Final.isUsable()) {
10330 HasErrors = true;
10331 break;
10334 if (!Update.isUsable() || !Final.isUsable()) {
10335 HasErrors = true;
10336 break;
10338 // Save results
10339 Built.Counters[Cnt] = IS.CounterVar;
10340 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10341 Built.Inits[Cnt] = Init.get();
10342 Built.Updates[Cnt] = Update.get();
10343 Built.Finals[Cnt] = Final.get();
10344 Built.DependentCounters[Cnt] = nullptr;
10345 Built.DependentInits[Cnt] = nullptr;
10346 Built.FinalsConditions[Cnt] = nullptr;
10347 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10348 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10349 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10350 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10355 if (HasErrors)
10356 return 0;
10358 // Save results
10359 Built.IterationVarRef = IV.get();
10360 Built.LastIteration = LastIteration.get();
10361 Built.NumIterations = NumIterations.get();
10362 Built.CalcLastIteration = SemaRef
10363 .ActOnFinishFullExpr(CalcLastIteration.get(),
10364 /*DiscardedValue=*/false)
10365 .get();
10366 Built.PreCond = PreCond.get();
10367 Built.PreInits = buildPreInits(C, Captures);
10368 Built.Cond = Cond.get();
10369 Built.Init = Init.get();
10370 Built.Inc = Inc.get();
10371 Built.LB = LB.get();
10372 Built.UB = UB.get();
10373 Built.IL = IL.get();
10374 Built.ST = ST.get();
10375 Built.EUB = EUB.get();
10376 Built.NLB = NextLB.get();
10377 Built.NUB = NextUB.get();
10378 Built.PrevLB = PrevLB.get();
10379 Built.PrevUB = PrevUB.get();
10380 Built.DistInc = DistInc.get();
10381 Built.PrevEUB = PrevEUB.get();
10382 Built.DistCombinedFields.LB = CombLB.get();
10383 Built.DistCombinedFields.UB = CombUB.get();
10384 Built.DistCombinedFields.EUB = CombEUB.get();
10385 Built.DistCombinedFields.Init = CombInit.get();
10386 Built.DistCombinedFields.Cond = CombCond.get();
10387 Built.DistCombinedFields.NLB = CombNextLB.get();
10388 Built.DistCombinedFields.NUB = CombNextUB.get();
10389 Built.DistCombinedFields.DistCond = CombDistCond.get();
10390 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10392 return NestedLoopCount;
10395 static Expr *getCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) {
10396 auto CollapseClauses =
10397 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10398 if (CollapseClauses.begin() != CollapseClauses.end())
10399 return (*CollapseClauses.begin())->getNumForLoops();
10400 return nullptr;
10403 static Expr *getOrderedNumberExpr(ArrayRef<OMPClause *> Clauses) {
10404 auto OrderedClauses =
10405 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10406 if (OrderedClauses.begin() != OrderedClauses.end())
10407 return (*OrderedClauses.begin())->getNumForLoops();
10408 return nullptr;
10411 static bool checkSimdlenSafelenSpecified(Sema &S,
10412 const ArrayRef<OMPClause *> Clauses) {
10413 const OMPSafelenClause *Safelen = nullptr;
10414 const OMPSimdlenClause *Simdlen = nullptr;
10416 for (const OMPClause *Clause : Clauses) {
10417 if (Clause->getClauseKind() == OMPC_safelen)
10418 Safelen = cast<OMPSafelenClause>(Clause);
10419 else if (Clause->getClauseKind() == OMPC_simdlen)
10420 Simdlen = cast<OMPSimdlenClause>(Clause);
10421 if (Safelen && Simdlen)
10422 break;
10425 if (Simdlen && Safelen) {
10426 const Expr *SimdlenLength = Simdlen->getSimdlen();
10427 const Expr *SafelenLength = Safelen->getSafelen();
10428 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10429 SimdlenLength->isInstantiationDependent() ||
10430 SimdlenLength->containsUnexpandedParameterPack())
10431 return false;
10432 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10433 SafelenLength->isInstantiationDependent() ||
10434 SafelenLength->containsUnexpandedParameterPack())
10435 return false;
10436 Expr::EvalResult SimdlenResult, SafelenResult;
10437 SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
10438 SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
10439 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10440 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10441 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10442 // If both simdlen and safelen clauses are specified, the value of the
10443 // simdlen parameter must be less than or equal to the value of the safelen
10444 // parameter.
10445 if (SimdlenRes > SafelenRes) {
10446 S.Diag(SimdlenLength->getExprLoc(),
10447 diag::err_omp_wrong_simdlen_safelen_values)
10448 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10449 return true;
10452 return false;
10455 static bool checkGenericLoopLastprivate(Sema &S, ArrayRef<OMPClause *> Clauses,
10456 OpenMPDirectiveKind K,
10457 DSAStackTy *Stack);
10459 bool Sema::checkLastPrivateForMappedDirectives(ArrayRef<OMPClause *> Clauses) {
10461 // Check for syntax of lastprivate
10462 // Param of the lastprivate have different meanings in the mapped directives
10463 // e.g. "omp loop" Only loop iteration vars are allowed in lastprivate clause
10464 // "omp for" lastprivate vars must be shared
10465 if (getLangOpts().OpenMP >= 50 &&
10466 DSAStack->getMappedDirective() == OMPD_loop &&
10467 checkGenericLoopLastprivate(*this, Clauses, OMPD_loop, DSAStack)) {
10468 return false;
10470 return true;
10473 StmtResult
10474 Sema::ActOnOpenMPSimdDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt,
10475 SourceLocation StartLoc, SourceLocation EndLoc,
10476 VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10477 if (!AStmt)
10478 return StmtError();
10480 if (!checkLastPrivateForMappedDirectives(Clauses))
10481 return StmtError();
10483 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10484 OMPLoopBasedDirective::HelperExprs B;
10485 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10486 // define the nested loops number.
10487 unsigned NestedLoopCount = checkOpenMPLoop(
10488 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10489 AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
10490 if (NestedLoopCount == 0)
10491 return StmtError();
10493 assert((CurContext->isDependentContext() || B.builtAll()) &&
10494 "omp simd loop exprs were not built");
10496 if (!CurContext->isDependentContext()) {
10497 // Finalize the clauses that need pre-built expressions for CodeGen.
10498 for (OMPClause *C : Clauses) {
10499 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10500 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10501 B.NumIterations, *this, CurScope,
10502 DSAStack))
10503 return StmtError();
10507 if (checkSimdlenSafelenSpecified(*this, Clauses))
10508 return StmtError();
10510 setFunctionHasBranchProtectedScope();
10511 auto *SimdDirective = OMPSimdDirective::Create(
10512 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10513 DSAStack->getMappedDirective());
10514 return SimdDirective;
10517 StmtResult
10518 Sema::ActOnOpenMPForDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt,
10519 SourceLocation StartLoc, SourceLocation EndLoc,
10520 VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10521 if (!AStmt)
10522 return StmtError();
10524 if (!checkLastPrivateForMappedDirectives(Clauses))
10525 return StmtError();
10527 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10528 OMPLoopBasedDirective::HelperExprs B;
10529 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10530 // define the nested loops number.
10531 unsigned NestedLoopCount = checkOpenMPLoop(
10532 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10533 AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
10534 if (NestedLoopCount == 0)
10535 return StmtError();
10537 assert((CurContext->isDependentContext() || B.builtAll()) &&
10538 "omp for loop exprs were not built");
10540 if (!CurContext->isDependentContext()) {
10541 // Finalize the clauses that need pre-built expressions for CodeGen.
10542 for (OMPClause *C : Clauses) {
10543 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10544 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10545 B.NumIterations, *this, CurScope,
10546 DSAStack))
10547 return StmtError();
10551 auto *ForDirective = OMPForDirective::Create(
10552 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10553 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion(),
10554 DSAStack->getMappedDirective());
10555 return ForDirective;
10558 StmtResult Sema::ActOnOpenMPForSimdDirective(
10559 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10560 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10561 if (!AStmt)
10562 return StmtError();
10564 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10565 OMPLoopBasedDirective::HelperExprs B;
10566 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10567 // define the nested loops number.
10568 unsigned NestedLoopCount =
10569 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
10570 getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
10571 VarsWithImplicitDSA, B);
10572 if (NestedLoopCount == 0)
10573 return StmtError();
10575 assert((CurContext->isDependentContext() || B.builtAll()) &&
10576 "omp for simd loop exprs were not built");
10578 if (!CurContext->isDependentContext()) {
10579 // Finalize the clauses that need pre-built expressions for CodeGen.
10580 for (OMPClause *C : Clauses) {
10581 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10582 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10583 B.NumIterations, *this, CurScope,
10584 DSAStack))
10585 return StmtError();
10589 if (checkSimdlenSafelenSpecified(*this, Clauses))
10590 return StmtError();
10592 setFunctionHasBranchProtectedScope();
10593 return OMPForSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
10594 Clauses, AStmt, B);
10597 StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
10598 Stmt *AStmt,
10599 SourceLocation StartLoc,
10600 SourceLocation EndLoc) {
10601 if (!AStmt)
10602 return StmtError();
10604 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10605 auto BaseStmt = AStmt;
10606 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10607 BaseStmt = CS->getCapturedStmt();
10608 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10609 auto S = C->children();
10610 if (S.begin() == S.end())
10611 return StmtError();
10612 // All associated statements must be '#pragma omp section' except for
10613 // the first one.
10614 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
10615 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10616 if (SectionStmt)
10617 Diag(SectionStmt->getBeginLoc(),
10618 diag::err_omp_sections_substmt_not_section);
10619 return StmtError();
10621 cast<OMPSectionDirective>(SectionStmt)
10622 ->setHasCancel(DSAStack->isCancelRegion());
10624 } else {
10625 Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt);
10626 return StmtError();
10629 setFunctionHasBranchProtectedScope();
10631 return OMPSectionsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
10632 DSAStack->getTaskgroupReductionRef(),
10633 DSAStack->isCancelRegion());
10636 StmtResult Sema::ActOnOpenMPSectionDirective(Stmt *AStmt,
10637 SourceLocation StartLoc,
10638 SourceLocation EndLoc) {
10639 if (!AStmt)
10640 return StmtError();
10642 setFunctionHasBranchProtectedScope();
10643 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10645 return OMPSectionDirective::Create(Context, StartLoc, EndLoc, AStmt,
10646 DSAStack->isCancelRegion());
10649 static Expr *getDirectCallExpr(Expr *E) {
10650 E = E->IgnoreParenCasts()->IgnoreImplicit();
10651 if (auto *CE = dyn_cast<CallExpr>(E))
10652 if (CE->getDirectCallee())
10653 return E;
10654 return nullptr;
10657 StmtResult Sema::ActOnOpenMPDispatchDirective(ArrayRef<OMPClause *> Clauses,
10658 Stmt *AStmt,
10659 SourceLocation StartLoc,
10660 SourceLocation EndLoc) {
10661 if (!AStmt)
10662 return StmtError();
10664 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10666 // 5.1 OpenMP
10667 // expression-stmt : an expression statement with one of the following forms:
10668 // expression = target-call ( [expression-list] );
10669 // target-call ( [expression-list] );
10671 SourceLocation TargetCallLoc;
10673 if (!CurContext->isDependentContext()) {
10674 Expr *TargetCall = nullptr;
10676 auto *E = dyn_cast<Expr>(S);
10677 if (!E) {
10678 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10679 return StmtError();
10682 E = E->IgnoreParenCasts()->IgnoreImplicit();
10684 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
10685 if (BO->getOpcode() == BO_Assign)
10686 TargetCall = getDirectCallExpr(BO->getRHS());
10687 } else {
10688 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10689 if (COCE->getOperator() == OO_Equal)
10690 TargetCall = getDirectCallExpr(COCE->getArg(1));
10691 if (!TargetCall)
10692 TargetCall = getDirectCallExpr(E);
10694 if (!TargetCall) {
10695 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10696 return StmtError();
10698 TargetCallLoc = TargetCall->getExprLoc();
10701 setFunctionHasBranchProtectedScope();
10703 return OMPDispatchDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
10704 TargetCallLoc);
10707 static bool checkGenericLoopLastprivate(Sema &S, ArrayRef<OMPClause *> Clauses,
10708 OpenMPDirectiveKind K,
10709 DSAStackTy *Stack) {
10710 bool ErrorFound = false;
10711 for (OMPClause *C : Clauses) {
10712 if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) {
10713 for (Expr *RefExpr : LPC->varlists()) {
10714 SourceLocation ELoc;
10715 SourceRange ERange;
10716 Expr *SimpleRefExpr = RefExpr;
10717 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
10718 if (ValueDecl *D = Res.first) {
10719 auto &&Info = Stack->isLoopControlVariable(D);
10720 if (!Info.first) {
10721 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10722 << getOpenMPDirectiveName(K);
10723 ErrorFound = true;
10729 return ErrorFound;
10732 StmtResult Sema::ActOnOpenMPGenericLoopDirective(
10733 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10734 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10735 if (!AStmt)
10736 return StmtError();
10738 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10739 // A list item may not appear in a lastprivate clause unless it is the
10740 // loop iteration variable of a loop that is associated with the construct.
10741 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_loop, DSAStack))
10742 return StmtError();
10744 auto *CS = cast<CapturedStmt>(AStmt);
10745 // 1.2.2 OpenMP Language Terminology
10746 // Structured block - An executable statement with a single entry at the
10747 // top and a single exit at the bottom.
10748 // The point of exit cannot be a branch out of the structured block.
10749 // longjmp() and throw() must not violate the entry/exit criteria.
10750 CS->getCapturedDecl()->setNothrow();
10752 OMPLoopDirective::HelperExprs B;
10753 // In presence of clause 'collapse', it will define the nested loops number.
10754 unsigned NestedLoopCount = checkOpenMPLoop(
10755 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10756 AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
10757 if (NestedLoopCount == 0)
10758 return StmtError();
10760 assert((CurContext->isDependentContext() || B.builtAll()) &&
10761 "omp loop exprs were not built");
10763 setFunctionHasBranchProtectedScope();
10764 return OMPGenericLoopDirective::Create(Context, StartLoc, EndLoc,
10765 NestedLoopCount, Clauses, AStmt, B);
10768 StmtResult Sema::ActOnOpenMPTeamsGenericLoopDirective(
10769 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10770 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10771 if (!AStmt)
10772 return StmtError();
10774 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10775 // A list item may not appear in a lastprivate clause unless it is the
10776 // loop iteration variable of a loop that is associated with the construct.
10777 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_teams_loop, DSAStack))
10778 return StmtError();
10780 auto *CS = cast<CapturedStmt>(AStmt);
10781 // 1.2.2 OpenMP Language Terminology
10782 // Structured block - An executable statement with a single entry at the
10783 // top and a single exit at the bottom.
10784 // The point of exit cannot be a branch out of the structured block.
10785 // longjmp() and throw() must not violate the entry/exit criteria.
10786 CS->getCapturedDecl()->setNothrow();
10787 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_teams_loop);
10788 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10789 CS = cast<CapturedStmt>(CS->getCapturedStmt());
10790 // 1.2.2 OpenMP Language Terminology
10791 // Structured block - An executable statement with a single entry at the
10792 // top and a single exit at the bottom.
10793 // The point of exit cannot be a branch out of the structured block.
10794 // longjmp() and throw() must not violate the entry/exit criteria.
10795 CS->getCapturedDecl()->setNothrow();
10798 OMPLoopDirective::HelperExprs B;
10799 // In presence of clause 'collapse', it will define the nested loops number.
10800 unsigned NestedLoopCount =
10801 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
10802 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10803 VarsWithImplicitDSA, B);
10804 if (NestedLoopCount == 0)
10805 return StmtError();
10807 assert((CurContext->isDependentContext() || B.builtAll()) &&
10808 "omp loop exprs were not built");
10810 setFunctionHasBranchProtectedScope();
10811 DSAStack->setParentTeamsRegionLoc(StartLoc);
10813 return OMPTeamsGenericLoopDirective::Create(
10814 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10817 StmtResult Sema::ActOnOpenMPTargetTeamsGenericLoopDirective(
10818 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10819 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10820 if (!AStmt)
10821 return StmtError();
10823 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10824 // A list item may not appear in a lastprivate clause unless it is the
10825 // loop iteration variable of a loop that is associated with the construct.
10826 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_target_teams_loop,
10827 DSAStack))
10828 return StmtError();
10830 auto *CS = cast<CapturedStmt>(AStmt);
10831 // 1.2.2 OpenMP Language Terminology
10832 // Structured block - An executable statement with a single entry at the
10833 // top and a single exit at the bottom.
10834 // The point of exit cannot be a branch out of the structured block.
10835 // longjmp() and throw() must not violate the entry/exit criteria.
10836 CS->getCapturedDecl()->setNothrow();
10837 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_teams_loop);
10838 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10839 CS = cast<CapturedStmt>(CS->getCapturedStmt());
10840 // 1.2.2 OpenMP Language Terminology
10841 // Structured block - An executable statement with a single entry at the
10842 // top and a single exit at the bottom.
10843 // The point of exit cannot be a branch out of the structured block.
10844 // longjmp() and throw() must not violate the entry/exit criteria.
10845 CS->getCapturedDecl()->setNothrow();
10848 OMPLoopDirective::HelperExprs B;
10849 // In presence of clause 'collapse', it will define the nested loops number.
10850 unsigned NestedLoopCount =
10851 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
10852 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10853 VarsWithImplicitDSA, B);
10854 if (NestedLoopCount == 0)
10855 return StmtError();
10857 assert((CurContext->isDependentContext() || B.builtAll()) &&
10858 "omp loop exprs were not built");
10860 setFunctionHasBranchProtectedScope();
10862 return OMPTargetTeamsGenericLoopDirective::Create(
10863 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10866 StmtResult Sema::ActOnOpenMPParallelGenericLoopDirective(
10867 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10868 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10869 if (!AStmt)
10870 return StmtError();
10872 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10873 // A list item may not appear in a lastprivate clause unless it is the
10874 // loop iteration variable of a loop that is associated with the construct.
10875 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_parallel_loop, DSAStack))
10876 return StmtError();
10878 auto *CS = cast<CapturedStmt>(AStmt);
10879 // 1.2.2 OpenMP Language Terminology
10880 // Structured block - An executable statement with a single entry at the
10881 // top and a single exit at the bottom.
10882 // The point of exit cannot be a branch out of the structured block.
10883 // longjmp() and throw() must not violate the entry/exit criteria.
10884 CS->getCapturedDecl()->setNothrow();
10885 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_parallel_loop);
10886 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10887 CS = cast<CapturedStmt>(CS->getCapturedStmt());
10888 // 1.2.2 OpenMP Language Terminology
10889 // Structured block - An executable statement with a single entry at the
10890 // top and a single exit at the bottom.
10891 // The point of exit cannot be a branch out of the structured block.
10892 // longjmp() and throw() must not violate the entry/exit criteria.
10893 CS->getCapturedDecl()->setNothrow();
10896 OMPLoopDirective::HelperExprs B;
10897 // In presence of clause 'collapse', it will define the nested loops number.
10898 unsigned NestedLoopCount =
10899 checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses),
10900 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10901 VarsWithImplicitDSA, B);
10902 if (NestedLoopCount == 0)
10903 return StmtError();
10905 assert((CurContext->isDependentContext() || B.builtAll()) &&
10906 "omp loop exprs were not built");
10908 setFunctionHasBranchProtectedScope();
10910 return OMPParallelGenericLoopDirective::Create(
10911 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10914 StmtResult Sema::ActOnOpenMPTargetParallelGenericLoopDirective(
10915 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10916 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10917 if (!AStmt)
10918 return StmtError();
10920 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10921 // A list item may not appear in a lastprivate clause unless it is the
10922 // loop iteration variable of a loop that is associated with the construct.
10923 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_target_parallel_loop,
10924 DSAStack))
10925 return StmtError();
10927 auto *CS = cast<CapturedStmt>(AStmt);
10928 // 1.2.2 OpenMP Language Terminology
10929 // Structured block - An executable statement with a single entry at the
10930 // top and a single exit at the bottom.
10931 // The point of exit cannot be a branch out of the structured block.
10932 // longjmp() and throw() must not violate the entry/exit criteria.
10933 CS->getCapturedDecl()->setNothrow();
10934 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_loop);
10935 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10936 CS = cast<CapturedStmt>(CS->getCapturedStmt());
10937 // 1.2.2 OpenMP Language Terminology
10938 // Structured block - An executable statement with a single entry at the
10939 // top and a single exit at the bottom.
10940 // The point of exit cannot be a branch out of the structured block.
10941 // longjmp() and throw() must not violate the entry/exit criteria.
10942 CS->getCapturedDecl()->setNothrow();
10945 OMPLoopDirective::HelperExprs B;
10946 // In presence of clause 'collapse', it will define the nested loops number.
10947 unsigned NestedLoopCount =
10948 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses),
10949 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10950 VarsWithImplicitDSA, B);
10951 if (NestedLoopCount == 0)
10952 return StmtError();
10954 assert((CurContext->isDependentContext() || B.builtAll()) &&
10955 "omp loop exprs were not built");
10957 setFunctionHasBranchProtectedScope();
10959 return OMPTargetParallelGenericLoopDirective::Create(
10960 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10963 StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
10964 Stmt *AStmt,
10965 SourceLocation StartLoc,
10966 SourceLocation EndLoc) {
10967 if (!AStmt)
10968 return StmtError();
10970 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10972 setFunctionHasBranchProtectedScope();
10974 // OpenMP [2.7.3, single Construct, Restrictions]
10975 // The copyprivate clause must not be used with the nowait clause.
10976 const OMPClause *Nowait = nullptr;
10977 const OMPClause *Copyprivate = nullptr;
10978 for (const OMPClause *Clause : Clauses) {
10979 if (Clause->getClauseKind() == OMPC_nowait)
10980 Nowait = Clause;
10981 else if (Clause->getClauseKind() == OMPC_copyprivate)
10982 Copyprivate = Clause;
10983 if (Copyprivate && Nowait) {
10984 Diag(Copyprivate->getBeginLoc(),
10985 diag::err_omp_single_copyprivate_with_nowait);
10986 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
10987 return StmtError();
10991 return OMPSingleDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
10994 StmtResult Sema::ActOnOpenMPMasterDirective(Stmt *AStmt,
10995 SourceLocation StartLoc,
10996 SourceLocation EndLoc) {
10997 if (!AStmt)
10998 return StmtError();
11000 setFunctionHasBranchProtectedScope();
11002 return OMPMasterDirective::Create(Context, StartLoc, EndLoc, AStmt);
11005 StmtResult Sema::ActOnOpenMPMaskedDirective(ArrayRef<OMPClause *> Clauses,
11006 Stmt *AStmt,
11007 SourceLocation StartLoc,
11008 SourceLocation EndLoc) {
11009 if (!AStmt)
11010 return StmtError();
11012 setFunctionHasBranchProtectedScope();
11014 return OMPMaskedDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
11017 StmtResult Sema::ActOnOpenMPCriticalDirective(
11018 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
11019 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
11020 if (!AStmt)
11021 return StmtError();
11023 bool ErrorFound = false;
11024 llvm::APSInt Hint;
11025 SourceLocation HintLoc;
11026 bool DependentHint = false;
11027 for (const OMPClause *C : Clauses) {
11028 if (C->getClauseKind() == OMPC_hint) {
11029 if (!DirName.getName()) {
11030 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
11031 ErrorFound = true;
11033 Expr *E = cast<OMPHintClause>(C)->getHint();
11034 if (E->isTypeDependent() || E->isValueDependent() ||
11035 E->isInstantiationDependent()) {
11036 DependentHint = true;
11037 } else {
11038 Hint = E->EvaluateKnownConstInt(Context);
11039 HintLoc = C->getBeginLoc();
11043 if (ErrorFound)
11044 return StmtError();
11045 const auto Pair = DSAStack->getCriticalWithHint(DirName);
11046 if (Pair.first && DirName.getName() && !DependentHint) {
11047 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
11048 Diag(StartLoc, diag::err_omp_critical_with_hint);
11049 if (HintLoc.isValid())
11050 Diag(HintLoc, diag::note_omp_critical_hint_here)
11051 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
11052 else
11053 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
11054 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
11055 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
11056 << 1
11057 << toString(C->getHint()->EvaluateKnownConstInt(Context),
11058 /*Radix=*/10, /*Signed=*/false);
11059 } else {
11060 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
11065 setFunctionHasBranchProtectedScope();
11067 auto *Dir = OMPCriticalDirective::Create(Context, DirName, StartLoc, EndLoc,
11068 Clauses, AStmt);
11069 if (!Pair.first && DirName.getName() && !DependentHint)
11070 DSAStack->addCriticalWithHint(Dir, Hint);
11071 return Dir;
11074 StmtResult Sema::ActOnOpenMPParallelForDirective(
11075 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11076 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11077 if (!AStmt)
11078 return StmtError();
11080 auto *CS = cast<CapturedStmt>(AStmt);
11081 // 1.2.2 OpenMP Language Terminology
11082 // Structured block - An executable statement with a single entry at the
11083 // top and a single exit at the bottom.
11084 // The point of exit cannot be a branch out of the structured block.
11085 // longjmp() and throw() must not violate the entry/exit criteria.
11086 CS->getCapturedDecl()->setNothrow();
11088 OMPLoopBasedDirective::HelperExprs B;
11089 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11090 // define the nested loops number.
11091 unsigned NestedLoopCount =
11092 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
11093 getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
11094 VarsWithImplicitDSA, B);
11095 if (NestedLoopCount == 0)
11096 return StmtError();
11098 assert((CurContext->isDependentContext() || B.builtAll()) &&
11099 "omp parallel for loop exprs were not built");
11101 if (!CurContext->isDependentContext()) {
11102 // Finalize the clauses that need pre-built expressions for CodeGen.
11103 for (OMPClause *C : Clauses) {
11104 if (auto *LC = dyn_cast<OMPLinearClause>(C))
11105 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
11106 B.NumIterations, *this, CurScope,
11107 DSAStack))
11108 return StmtError();
11112 setFunctionHasBranchProtectedScope();
11113 return OMPParallelForDirective::Create(
11114 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11115 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11118 StmtResult Sema::ActOnOpenMPParallelForSimdDirective(
11119 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11120 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11121 if (!AStmt)
11122 return StmtError();
11124 auto *CS = cast<CapturedStmt>(AStmt);
11125 // 1.2.2 OpenMP Language Terminology
11126 // Structured block - An executable statement with a single entry at the
11127 // top and a single exit at the bottom.
11128 // The point of exit cannot be a branch out of the structured block.
11129 // longjmp() and throw() must not violate the entry/exit criteria.
11130 CS->getCapturedDecl()->setNothrow();
11132 OMPLoopBasedDirective::HelperExprs B;
11133 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11134 // define the nested loops number.
11135 unsigned NestedLoopCount =
11136 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
11137 getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
11138 VarsWithImplicitDSA, B);
11139 if (NestedLoopCount == 0)
11140 return StmtError();
11142 if (!CurContext->isDependentContext()) {
11143 // Finalize the clauses that need pre-built expressions for CodeGen.
11144 for (OMPClause *C : Clauses) {
11145 if (auto *LC = dyn_cast<OMPLinearClause>(C))
11146 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
11147 B.NumIterations, *this, CurScope,
11148 DSAStack))
11149 return StmtError();
11153 if (checkSimdlenSafelenSpecified(*this, Clauses))
11154 return StmtError();
11156 setFunctionHasBranchProtectedScope();
11157 return OMPParallelForSimdDirective::Create(
11158 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11161 StmtResult
11162 Sema::ActOnOpenMPParallelMasterDirective(ArrayRef<OMPClause *> Clauses,
11163 Stmt *AStmt, SourceLocation StartLoc,
11164 SourceLocation EndLoc) {
11165 if (!AStmt)
11166 return StmtError();
11168 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11169 auto *CS = cast<CapturedStmt>(AStmt);
11170 // 1.2.2 OpenMP Language Terminology
11171 // Structured block - An executable statement with a single entry at the
11172 // top and a single exit at the bottom.
11173 // The point of exit cannot be a branch out of the structured block.
11174 // longjmp() and throw() must not violate the entry/exit criteria.
11175 CS->getCapturedDecl()->setNothrow();
11177 setFunctionHasBranchProtectedScope();
11179 return OMPParallelMasterDirective::Create(
11180 Context, StartLoc, EndLoc, Clauses, AStmt,
11181 DSAStack->getTaskgroupReductionRef());
11184 StmtResult
11185 Sema::ActOnOpenMPParallelMaskedDirective(ArrayRef<OMPClause *> Clauses,
11186 Stmt *AStmt, SourceLocation StartLoc,
11187 SourceLocation EndLoc) {
11188 if (!AStmt)
11189 return StmtError();
11191 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11192 auto *CS = cast<CapturedStmt>(AStmt);
11193 // 1.2.2 OpenMP Language Terminology
11194 // Structured block - An executable statement with a single entry at the
11195 // top and a single exit at the bottom.
11196 // The point of exit cannot be a branch out of the structured block.
11197 // longjmp() and throw() must not violate the entry/exit criteria.
11198 CS->getCapturedDecl()->setNothrow();
11200 setFunctionHasBranchProtectedScope();
11202 return OMPParallelMaskedDirective::Create(
11203 Context, StartLoc, EndLoc, Clauses, AStmt,
11204 DSAStack->getTaskgroupReductionRef());
11207 StmtResult
11208 Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
11209 Stmt *AStmt, SourceLocation StartLoc,
11210 SourceLocation EndLoc) {
11211 if (!AStmt)
11212 return StmtError();
11214 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11215 auto BaseStmt = AStmt;
11216 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
11217 BaseStmt = CS->getCapturedStmt();
11218 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
11219 auto S = C->children();
11220 if (S.begin() == S.end())
11221 return StmtError();
11222 // All associated statements must be '#pragma omp section' except for
11223 // the first one.
11224 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
11225 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
11226 if (SectionStmt)
11227 Diag(SectionStmt->getBeginLoc(),
11228 diag::err_omp_parallel_sections_substmt_not_section);
11229 return StmtError();
11231 cast<OMPSectionDirective>(SectionStmt)
11232 ->setHasCancel(DSAStack->isCancelRegion());
11234 } else {
11235 Diag(AStmt->getBeginLoc(),
11236 diag::err_omp_parallel_sections_not_compound_stmt);
11237 return StmtError();
11240 setFunctionHasBranchProtectedScope();
11242 return OMPParallelSectionsDirective::Create(
11243 Context, StartLoc, EndLoc, Clauses, AStmt,
11244 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11247 /// Find and diagnose mutually exclusive clause kinds.
11248 static bool checkMutuallyExclusiveClauses(
11249 Sema &S, ArrayRef<OMPClause *> Clauses,
11250 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
11251 const OMPClause *PrevClause = nullptr;
11252 bool ErrorFound = false;
11253 for (const OMPClause *C : Clauses) {
11254 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
11255 if (!PrevClause) {
11256 PrevClause = C;
11257 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
11258 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
11259 << getOpenMPClauseName(C->getClauseKind())
11260 << getOpenMPClauseName(PrevClause->getClauseKind());
11261 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
11262 << getOpenMPClauseName(PrevClause->getClauseKind());
11263 ErrorFound = true;
11267 return ErrorFound;
11270 StmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
11271 Stmt *AStmt, SourceLocation StartLoc,
11272 SourceLocation EndLoc) {
11273 if (!AStmt)
11274 return StmtError();
11276 // OpenMP 5.0, 2.10.1 task Construct
11277 // If a detach clause appears on the directive, then a mergeable clause cannot
11278 // appear on the same directive.
11279 if (checkMutuallyExclusiveClauses(*this, Clauses,
11280 {OMPC_detach, OMPC_mergeable}))
11281 return StmtError();
11283 auto *CS = cast<CapturedStmt>(AStmt);
11284 // 1.2.2 OpenMP Language Terminology
11285 // Structured block - An executable statement with a single entry at the
11286 // top and a single exit at the bottom.
11287 // The point of exit cannot be a branch out of the structured block.
11288 // longjmp() and throw() must not violate the entry/exit criteria.
11289 CS->getCapturedDecl()->setNothrow();
11291 setFunctionHasBranchProtectedScope();
11293 return OMPTaskDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
11294 DSAStack->isCancelRegion());
11297 StmtResult Sema::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc,
11298 SourceLocation EndLoc) {
11299 return OMPTaskyieldDirective::Create(Context, StartLoc, EndLoc);
11302 StmtResult Sema::ActOnOpenMPBarrierDirective(SourceLocation StartLoc,
11303 SourceLocation EndLoc) {
11304 return OMPBarrierDirective::Create(Context, StartLoc, EndLoc);
11307 StmtResult Sema::ActOnOpenMPErrorDirective(ArrayRef<OMPClause *> Clauses,
11308 SourceLocation StartLoc,
11309 SourceLocation EndLoc,
11310 bool InExContext) {
11311 const OMPAtClause *AtC =
11312 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11314 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11315 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
11316 return StmtError();
11319 const OMPSeverityClause *SeverityC =
11320 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11321 const OMPMessageClause *MessageC =
11322 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11323 Expr *ME = MessageC ? MessageC->getMessageString() : nullptr;
11325 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11326 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11327 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
11328 << (ME ? cast<StringLiteral>(ME)->getString() : "WARNING");
11329 else
11330 Diag(StartLoc, diag::err_diagnose_if_succeeded)
11331 << (ME ? cast<StringLiteral>(ME)->getString() : "ERROR");
11332 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11333 return StmtError();
11335 return OMPErrorDirective::Create(Context, StartLoc, EndLoc, Clauses);
11338 StmtResult Sema::ActOnOpenMPTaskwaitDirective(ArrayRef<OMPClause *> Clauses,
11339 SourceLocation StartLoc,
11340 SourceLocation EndLoc) {
11341 const OMPNowaitClause *NowaitC =
11342 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11343 bool HasDependC =
11344 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11345 .empty();
11346 if (NowaitC && !HasDependC) {
11347 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11348 return StmtError();
11351 return OMPTaskwaitDirective::Create(Context, StartLoc, EndLoc, Clauses);
11354 StmtResult Sema::ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause *> Clauses,
11355 Stmt *AStmt,
11356 SourceLocation StartLoc,
11357 SourceLocation EndLoc) {
11358 if (!AStmt)
11359 return StmtError();
11361 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11363 setFunctionHasBranchProtectedScope();
11365 return OMPTaskgroupDirective::Create(Context, StartLoc, EndLoc, Clauses,
11366 AStmt,
11367 DSAStack->getTaskgroupReductionRef());
11370 StmtResult Sema::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
11371 SourceLocation StartLoc,
11372 SourceLocation EndLoc) {
11373 OMPFlushClause *FC = nullptr;
11374 OMPClause *OrderClause = nullptr;
11375 for (OMPClause *C : Clauses) {
11376 if (C->getClauseKind() == OMPC_flush)
11377 FC = cast<OMPFlushClause>(C);
11378 else
11379 OrderClause = C;
11381 OpenMPClauseKind MemOrderKind = OMPC_unknown;
11382 SourceLocation MemOrderLoc;
11383 for (const OMPClause *C : Clauses) {
11384 if (C->getClauseKind() == OMPC_acq_rel ||
11385 C->getClauseKind() == OMPC_acquire ||
11386 C->getClauseKind() == OMPC_release) {
11387 if (MemOrderKind != OMPC_unknown) {
11388 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11389 << getOpenMPDirectiveName(OMPD_flush) << 1
11390 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11391 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11392 << getOpenMPClauseName(MemOrderKind);
11393 } else {
11394 MemOrderKind = C->getClauseKind();
11395 MemOrderLoc = C->getBeginLoc();
11399 if (FC && OrderClause) {
11400 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11401 << getOpenMPClauseName(OrderClause->getClauseKind());
11402 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
11403 << getOpenMPClauseName(OrderClause->getClauseKind());
11404 return StmtError();
11406 return OMPFlushDirective::Create(Context, StartLoc, EndLoc, Clauses);
11409 StmtResult Sema::ActOnOpenMPDepobjDirective(ArrayRef<OMPClause *> Clauses,
11410 SourceLocation StartLoc,
11411 SourceLocation EndLoc) {
11412 if (Clauses.empty()) {
11413 Diag(StartLoc, diag::err_omp_depobj_expected);
11414 return StmtError();
11415 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11416 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11417 return StmtError();
11419 // Only depobj expression and another single clause is allowed.
11420 if (Clauses.size() > 2) {
11421 Diag(Clauses[2]->getBeginLoc(),
11422 diag::err_omp_depobj_single_clause_expected);
11423 return StmtError();
11424 } else if (Clauses.size() < 1) {
11425 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11426 return StmtError();
11428 return OMPDepobjDirective::Create(Context, StartLoc, EndLoc, Clauses);
11431 StmtResult Sema::ActOnOpenMPScanDirective(ArrayRef<OMPClause *> Clauses,
11432 SourceLocation StartLoc,
11433 SourceLocation EndLoc) {
11434 // Check that exactly one clause is specified.
11435 if (Clauses.size() != 1) {
11436 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11437 diag::err_omp_scan_single_clause_expected);
11438 return StmtError();
11440 // Check that scan directive is used in the scopeof the OpenMP loop body.
11441 if (Scope *S = DSAStack->getCurScope()) {
11442 Scope *ParentS = S->getParent();
11443 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11444 !ParentS->getBreakParent()->isOpenMPLoopScope())
11445 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11446 << getOpenMPDirectiveName(OMPD_scan) << 5);
11448 // Check that only one instance of scan directives is used in the same outer
11449 // region.
11450 if (DSAStack->doesParentHasScanDirective()) {
11451 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
11452 Diag(DSAStack->getParentScanDirectiveLoc(),
11453 diag::note_omp_previous_directive)
11454 << "scan";
11455 return StmtError();
11457 DSAStack->setParentHasScanDirective(StartLoc);
11458 return OMPScanDirective::Create(Context, StartLoc, EndLoc, Clauses);
11461 StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
11462 Stmt *AStmt,
11463 SourceLocation StartLoc,
11464 SourceLocation EndLoc) {
11465 const OMPClause *DependFound = nullptr;
11466 const OMPClause *DependSourceClause = nullptr;
11467 const OMPClause *DependSinkClause = nullptr;
11468 const OMPClause *DoacrossFound = nullptr;
11469 const OMPClause *DoacrossSourceClause = nullptr;
11470 const OMPClause *DoacrossSinkClause = nullptr;
11471 bool ErrorFound = false;
11472 const OMPThreadsClause *TC = nullptr;
11473 const OMPSIMDClause *SC = nullptr;
11474 for (const OMPClause *C : Clauses) {
11475 auto DOC = dyn_cast<OMPDoacrossClause>(C);
11476 auto DC = dyn_cast<OMPDependClause>(C);
11477 if (DC || DOC) {
11478 DependFound = DC ? C : nullptr;
11479 DoacrossFound = DOC ? C : nullptr;
11480 OMPDoacrossKind ODK;
11481 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11482 (DOC && (ODK.isSource(DOC)))) {
11483 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11484 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
11485 << getOpenMPDirectiveName(OMPD_ordered)
11486 << getOpenMPClauseName(DC ? OMPC_depend : OMPC_doacross) << 2;
11487 ErrorFound = true;
11488 } else {
11489 if (DC)
11490 DependSourceClause = C;
11491 else
11492 DoacrossSourceClause = C;
11494 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11495 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11496 << (DC ? "depend" : "doacross") << 0;
11497 ErrorFound = true;
11499 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11500 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11501 if (DependSourceClause || DoacrossSourceClause) {
11502 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11503 << (DC ? "depend" : "doacross") << 1;
11504 ErrorFound = true;
11506 if (DC)
11507 DependSinkClause = C;
11508 else
11509 DoacrossSinkClause = C;
11511 } else if (C->getClauseKind() == OMPC_threads) {
11512 TC = cast<OMPThreadsClause>(C);
11513 } else if (C->getClauseKind() == OMPC_simd) {
11514 SC = cast<OMPSIMDClause>(C);
11517 if (!ErrorFound && !SC &&
11518 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11519 // OpenMP [2.8.1,simd Construct, Restrictions]
11520 // An ordered construct with the simd clause is the only OpenMP construct
11521 // that can appear in the simd region.
11522 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11523 << (LangOpts.OpenMP >= 50 ? 1 : 0);
11524 ErrorFound = true;
11525 } else if ((DependFound || DoacrossFound) && (TC || SC)) {
11526 SourceLocation Loc =
11527 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11528 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11529 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross)
11530 << getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind());
11531 ErrorFound = true;
11532 } else if ((DependFound || DoacrossFound) &&
11533 !DSAStack->getParentOrderedRegionParam().first) {
11534 SourceLocation Loc =
11535 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11536 Diag(Loc, diag::err_omp_ordered_directive_without_param)
11537 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross);
11538 ErrorFound = true;
11539 } else if (TC || Clauses.empty()) {
11540 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11541 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11542 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11543 << (TC != nullptr);
11544 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11545 ErrorFound = true;
11548 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11549 return StmtError();
11551 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11552 // During execution of an iteration of a worksharing-loop or a loop nest
11553 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11554 // must not execute more than one ordered region corresponding to an ordered
11555 // construct without a depend clause.
11556 if (!DependFound && !DoacrossFound) {
11557 if (DSAStack->doesParentHasOrderedDirective()) {
11558 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
11559 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11560 diag::note_omp_previous_directive)
11561 << "ordered";
11562 return StmtError();
11564 DSAStack->setParentHasOrderedDirective(StartLoc);
11567 if (AStmt) {
11568 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11570 setFunctionHasBranchProtectedScope();
11573 return OMPOrderedDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
11576 namespace {
11577 /// Helper class for checking expression in 'omp atomic [update]'
11578 /// construct.
11579 class OpenMPAtomicUpdateChecker {
11580 /// Error results for atomic update expressions.
11581 enum ExprAnalysisErrorCode {
11582 /// A statement is not an expression statement.
11583 NotAnExpression,
11584 /// Expression is not builtin binary or unary operation.
11585 NotABinaryOrUnaryExpression,
11586 /// Unary operation is not post-/pre- increment/decrement operation.
11587 NotAnUnaryIncDecExpression,
11588 /// An expression is not of scalar type.
11589 NotAScalarType,
11590 /// A binary operation is not an assignment operation.
11591 NotAnAssignmentOp,
11592 /// RHS part of the binary operation is not a binary expression.
11593 NotABinaryExpression,
11594 /// RHS part is not additive/multiplicative/shift/biwise binary
11595 /// expression.
11596 NotABinaryOperator,
11597 /// RHS binary operation does not have reference to the updated LHS
11598 /// part.
11599 NotAnUpdateExpression,
11600 /// No errors is found.
11601 NoError
11603 /// Reference to Sema.
11604 Sema &SemaRef;
11605 /// A location for note diagnostics (when error is found).
11606 SourceLocation NoteLoc;
11607 /// 'x' lvalue part of the source atomic expression.
11608 Expr *X;
11609 /// 'expr' rvalue part of the source atomic expression.
11610 Expr *E;
11611 /// Helper expression of the form
11612 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11613 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11614 Expr *UpdateExpr;
11615 /// Is 'x' a LHS in a RHS part of full update expression. It is
11616 /// important for non-associative operations.
11617 bool IsXLHSInRHSPart;
11618 BinaryOperatorKind Op;
11619 SourceLocation OpLoc;
11620 /// true if the source expression is a postfix unary operation, false
11621 /// if it is a prefix unary operation.
11622 bool IsPostfixUpdate;
11624 public:
11625 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11626 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11627 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11628 /// Check specified statement that it is suitable for 'atomic update'
11629 /// constructs and extract 'x', 'expr' and Operation from the original
11630 /// expression. If DiagId and NoteId == 0, then only check is performed
11631 /// without error notification.
11632 /// \param DiagId Diagnostic which should be emitted if error is found.
11633 /// \param NoteId Diagnostic note for the main error message.
11634 /// \return true if statement is not an update expression, false otherwise.
11635 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11636 /// Return the 'x' lvalue part of the source atomic expression.
11637 Expr *getX() const { return X; }
11638 /// Return the 'expr' rvalue part of the source atomic expression.
11639 Expr *getExpr() const { return E; }
11640 /// Return the update expression used in calculation of the updated
11641 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11642 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11643 Expr *getUpdateExpr() const { return UpdateExpr; }
11644 /// Return true if 'x' is LHS in RHS part of full update expression,
11645 /// false otherwise.
11646 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11648 /// true if the source expression is a postfix unary operation, false
11649 /// if it is a prefix unary operation.
11650 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11652 private:
11653 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11654 unsigned NoteId = 0);
11657 bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11658 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11659 ExprAnalysisErrorCode ErrorFound = NoError;
11660 SourceLocation ErrorLoc, NoteLoc;
11661 SourceRange ErrorRange, NoteRange;
11662 // Allowed constructs are:
11663 // x = x binop expr;
11664 // x = expr binop x;
11665 if (AtomicBinOp->getOpcode() == BO_Assign) {
11666 X = AtomicBinOp->getLHS();
11667 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11668 AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11669 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11670 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11671 AtomicInnerBinOp->isBitwiseOp()) {
11672 Op = AtomicInnerBinOp->getOpcode();
11673 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11674 Expr *LHS = AtomicInnerBinOp->getLHS();
11675 Expr *RHS = AtomicInnerBinOp->getRHS();
11676 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11677 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11678 /*Canonical=*/true);
11679 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11680 /*Canonical=*/true);
11681 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11682 /*Canonical=*/true);
11683 if (XId == LHSId) {
11684 E = RHS;
11685 IsXLHSInRHSPart = true;
11686 } else if (XId == RHSId) {
11687 E = LHS;
11688 IsXLHSInRHSPart = false;
11689 } else {
11690 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11691 ErrorRange = AtomicInnerBinOp->getSourceRange();
11692 NoteLoc = X->getExprLoc();
11693 NoteRange = X->getSourceRange();
11694 ErrorFound = NotAnUpdateExpression;
11696 } else {
11697 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11698 ErrorRange = AtomicInnerBinOp->getSourceRange();
11699 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11700 NoteRange = SourceRange(NoteLoc, NoteLoc);
11701 ErrorFound = NotABinaryOperator;
11703 } else {
11704 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11705 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11706 ErrorFound = NotABinaryExpression;
11708 } else {
11709 ErrorLoc = AtomicBinOp->getExprLoc();
11710 ErrorRange = AtomicBinOp->getSourceRange();
11711 NoteLoc = AtomicBinOp->getOperatorLoc();
11712 NoteRange = SourceRange(NoteLoc, NoteLoc);
11713 ErrorFound = NotAnAssignmentOp;
11715 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11716 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11717 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11718 return true;
11720 if (SemaRef.CurContext->isDependentContext())
11721 E = X = UpdateExpr = nullptr;
11722 return ErrorFound != NoError;
11725 bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11726 unsigned NoteId) {
11727 ExprAnalysisErrorCode ErrorFound = NoError;
11728 SourceLocation ErrorLoc, NoteLoc;
11729 SourceRange ErrorRange, NoteRange;
11730 // Allowed constructs are:
11731 // x++;
11732 // x--;
11733 // ++x;
11734 // --x;
11735 // x binop= expr;
11736 // x = x binop expr;
11737 // x = expr binop x;
11738 if (auto *AtomicBody = dyn_cast<Expr>(S)) {
11739 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11740 if (AtomicBody->getType()->isScalarType() ||
11741 AtomicBody->isInstantiationDependent()) {
11742 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11743 AtomicBody->IgnoreParenImpCasts())) {
11744 // Check for Compound Assignment Operation
11745 Op = BinaryOperator::getOpForCompoundAssignment(
11746 AtomicCompAssignOp->getOpcode());
11747 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11748 E = AtomicCompAssignOp->getRHS();
11749 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11750 IsXLHSInRHSPart = true;
11751 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11752 AtomicBody->IgnoreParenImpCasts())) {
11753 // Check for Binary Operation
11754 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11755 return true;
11756 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11757 AtomicBody->IgnoreParenImpCasts())) {
11758 // Check for Unary Operation
11759 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11760 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11761 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11762 OpLoc = AtomicUnaryOp->getOperatorLoc();
11763 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11764 E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
11765 IsXLHSInRHSPart = true;
11766 } else {
11767 ErrorFound = NotAnUnaryIncDecExpression;
11768 ErrorLoc = AtomicUnaryOp->getExprLoc();
11769 ErrorRange = AtomicUnaryOp->getSourceRange();
11770 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11771 NoteRange = SourceRange(NoteLoc, NoteLoc);
11773 } else if (!AtomicBody->isInstantiationDependent()) {
11774 ErrorFound = NotABinaryOrUnaryExpression;
11775 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11776 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11778 } else {
11779 ErrorFound = NotAScalarType;
11780 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11781 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11783 } else {
11784 ErrorFound = NotAnExpression;
11785 NoteLoc = ErrorLoc = S->getBeginLoc();
11786 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11788 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11789 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11790 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11791 return true;
11793 if (SemaRef.CurContext->isDependentContext())
11794 E = X = UpdateExpr = nullptr;
11795 if (ErrorFound == NoError && E && X) {
11796 // Build an update expression of form 'OpaqueValueExpr(x) binop
11797 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11798 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11799 auto *OVEX = new (SemaRef.getASTContext())
11800 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11801 auto *OVEExpr = new (SemaRef.getASTContext())
11802 OpaqueValueExpr(E->getExprLoc(), E->getType(), VK_PRValue);
11803 ExprResult Update =
11804 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11805 IsXLHSInRHSPart ? OVEExpr : OVEX);
11806 if (Update.isInvalid())
11807 return true;
11808 Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
11809 Sema::AA_Casting);
11810 if (Update.isInvalid())
11811 return true;
11812 UpdateExpr = Update.get();
11814 return ErrorFound != NoError;
11817 /// Get the node id of the fixed point of an expression \a S.
11818 llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11819 llvm::FoldingSetNodeID Id;
11820 S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11821 return Id;
11824 /// Check if two expressions are same.
11825 bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11826 const Expr *RHS) {
11827 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11830 class OpenMPAtomicCompareChecker {
11831 public:
11832 /// All kinds of errors that can occur in `atomic compare`
11833 enum ErrorTy {
11834 /// Empty compound statement.
11835 NoStmt = 0,
11836 /// More than one statement in a compound statement.
11837 MoreThanOneStmt,
11838 /// Not an assignment binary operator.
11839 NotAnAssignment,
11840 /// Not a conditional operator.
11841 NotCondOp,
11842 /// Wrong false expr. According to the spec, 'x' should be at the false
11843 /// expression of a conditional expression.
11844 WrongFalseExpr,
11845 /// The condition of a conditional expression is not a binary operator.
11846 NotABinaryOp,
11847 /// Invalid binary operator (not <, >, or ==).
11848 InvalidBinaryOp,
11849 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11850 InvalidComparison,
11851 /// X is not a lvalue.
11852 XNotLValue,
11853 /// Not a scalar.
11854 NotScalar,
11855 /// Not an integer.
11856 NotInteger,
11857 /// 'else' statement is not expected.
11858 UnexpectedElse,
11859 /// Not an equality operator.
11860 NotEQ,
11861 /// Invalid assignment (not v == x).
11862 InvalidAssignment,
11863 /// Not if statement
11864 NotIfStmt,
11865 /// More than two statements in a compund statement.
11866 MoreThanTwoStmts,
11867 /// Not a compound statement.
11868 NotCompoundStmt,
11869 /// No else statement.
11870 NoElse,
11871 /// Not 'if (r)'.
11872 InvalidCondition,
11873 /// No error.
11874 NoError,
11877 struct ErrorInfoTy {
11878 ErrorTy Error;
11879 SourceLocation ErrorLoc;
11880 SourceRange ErrorRange;
11881 SourceLocation NoteLoc;
11882 SourceRange NoteRange;
11885 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11887 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11888 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11890 Expr *getX() const { return X; }
11891 Expr *getE() const { return E; }
11892 Expr *getD() const { return D; }
11893 Expr *getCond() const { return C; }
11894 bool isXBinopExpr() const { return IsXBinopExpr; }
11896 protected:
11897 /// Reference to ASTContext
11898 ASTContext &ContextRef;
11899 /// 'x' lvalue part of the source atomic expression.
11900 Expr *X = nullptr;
11901 /// 'expr' or 'e' rvalue part of the source atomic expression.
11902 Expr *E = nullptr;
11903 /// 'd' rvalue part of the source atomic expression.
11904 Expr *D = nullptr;
11905 /// 'cond' part of the source atomic expression. It is in one of the following
11906 /// forms:
11907 /// expr ordop x
11908 /// x ordop expr
11909 /// x == e
11910 /// e == x
11911 Expr *C = nullptr;
11912 /// True if the cond expr is in the form of 'x ordop expr'.
11913 bool IsXBinopExpr = true;
11915 /// Check if it is a valid conditional update statement (cond-update-stmt).
11916 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11918 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11919 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11921 /// Check if all captured values have right type.
11922 bool checkType(ErrorInfoTy &ErrorInfo) const;
11924 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
11925 bool ShouldBeLValue, bool ShouldBeInteger = false) {
11926 if (E->isInstantiationDependent())
11927 return true;
11929 if (ShouldBeLValue && !E->isLValue()) {
11930 ErrorInfo.Error = ErrorTy::XNotLValue;
11931 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11932 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11933 return false;
11936 QualType QTy = E->getType();
11937 if (!QTy->isScalarType()) {
11938 ErrorInfo.Error = ErrorTy::NotScalar;
11939 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11940 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11941 return false;
11943 if (ShouldBeInteger && !QTy->isIntegerType()) {
11944 ErrorInfo.Error = ErrorTy::NotInteger;
11945 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11946 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11947 return false;
11950 return true;
11954 bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
11955 ErrorInfoTy &ErrorInfo) {
11956 auto *Then = S->getThen();
11957 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11958 if (CS->body_empty()) {
11959 ErrorInfo.Error = ErrorTy::NoStmt;
11960 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11961 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11962 return false;
11964 if (CS->size() > 1) {
11965 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11966 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11967 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11968 return false;
11970 Then = CS->body_front();
11973 auto *BO = dyn_cast<BinaryOperator>(Then);
11974 if (!BO) {
11975 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11976 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11977 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11978 return false;
11980 if (BO->getOpcode() != BO_Assign) {
11981 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11982 ErrorInfo.ErrorLoc = BO->getExprLoc();
11983 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11984 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11985 return false;
11988 X = BO->getLHS();
11990 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11991 if (!Cond) {
11992 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11993 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11994 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11995 return false;
11998 switch (Cond->getOpcode()) {
11999 case BO_EQ: {
12000 C = Cond;
12001 D = BO->getRHS();
12002 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
12003 E = Cond->getRHS();
12004 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12005 E = Cond->getLHS();
12006 } else {
12007 ErrorInfo.Error = ErrorTy::InvalidComparison;
12008 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12009 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12010 return false;
12012 break;
12014 case BO_LT:
12015 case BO_GT: {
12016 E = BO->getRHS();
12017 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
12018 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
12019 C = Cond;
12020 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
12021 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12022 C = Cond;
12023 IsXBinopExpr = false;
12024 } else {
12025 ErrorInfo.Error = ErrorTy::InvalidComparison;
12026 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12027 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12028 return false;
12030 break;
12032 default:
12033 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12034 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12035 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12036 return false;
12039 if (S->getElse()) {
12040 ErrorInfo.Error = ErrorTy::UnexpectedElse;
12041 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
12042 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
12043 return false;
12046 return true;
12049 bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
12050 ErrorInfoTy &ErrorInfo) {
12051 auto *BO = dyn_cast<BinaryOperator>(S);
12052 if (!BO) {
12053 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12054 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12055 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12056 return false;
12058 if (BO->getOpcode() != BO_Assign) {
12059 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12060 ErrorInfo.ErrorLoc = BO->getExprLoc();
12061 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12062 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12063 return false;
12066 X = BO->getLHS();
12068 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
12069 if (!CO) {
12070 ErrorInfo.Error = ErrorTy::NotCondOp;
12071 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
12072 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
12073 return false;
12076 if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
12077 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
12078 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
12079 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12080 CO->getFalseExpr()->getSourceRange();
12081 return false;
12084 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
12085 if (!Cond) {
12086 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12087 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12088 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12089 CO->getCond()->getSourceRange();
12090 return false;
12093 switch (Cond->getOpcode()) {
12094 case BO_EQ: {
12095 C = Cond;
12096 D = CO->getTrueExpr();
12097 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
12098 E = Cond->getRHS();
12099 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12100 E = Cond->getLHS();
12101 } else {
12102 ErrorInfo.Error = ErrorTy::InvalidComparison;
12103 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12104 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12105 return false;
12107 break;
12109 case BO_LT:
12110 case BO_GT: {
12111 E = CO->getTrueExpr();
12112 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
12113 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
12114 C = Cond;
12115 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
12116 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12117 C = Cond;
12118 IsXBinopExpr = false;
12119 } else {
12120 ErrorInfo.Error = ErrorTy::InvalidComparison;
12121 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12122 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12123 return false;
12125 break;
12127 default:
12128 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12129 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12130 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12131 return false;
12134 return true;
12137 bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
12138 // 'x' and 'e' cannot be nullptr
12139 assert(X && E && "X and E cannot be nullptr");
12141 if (!CheckValue(X, ErrorInfo, true))
12142 return false;
12144 if (!CheckValue(E, ErrorInfo, false))
12145 return false;
12147 if (D && !CheckValue(D, ErrorInfo, false))
12148 return false;
12150 return true;
12153 bool OpenMPAtomicCompareChecker::checkStmt(
12154 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
12155 auto *CS = dyn_cast<CompoundStmt>(S);
12156 if (CS) {
12157 if (CS->body_empty()) {
12158 ErrorInfo.Error = ErrorTy::NoStmt;
12159 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12160 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12161 return false;
12164 if (CS->size() != 1) {
12165 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12166 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12167 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12168 return false;
12170 S = CS->body_front();
12173 auto Res = false;
12175 if (auto *IS = dyn_cast<IfStmt>(S)) {
12176 // Check if the statement is in one of the following forms
12177 // (cond-update-stmt):
12178 // if (expr ordop x) { x = expr; }
12179 // if (x ordop expr) { x = expr; }
12180 // if (x == e) { x = d; }
12181 Res = checkCondUpdateStmt(IS, ErrorInfo);
12182 } else {
12183 // Check if the statement is in one of the following forms (cond-expr-stmt):
12184 // x = expr ordop x ? expr : x;
12185 // x = x ordop expr ? expr : x;
12186 // x = x == e ? d : x;
12187 Res = checkCondExprStmt(S, ErrorInfo);
12190 if (!Res)
12191 return false;
12193 return checkType(ErrorInfo);
12196 class OpenMPAtomicCompareCaptureChecker final
12197 : public OpenMPAtomicCompareChecker {
12198 public:
12199 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
12201 Expr *getV() const { return V; }
12202 Expr *getR() const { return R; }
12203 bool isFailOnly() const { return IsFailOnly; }
12204 bool isPostfixUpdate() const { return IsPostfixUpdate; }
12206 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
12207 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12209 private:
12210 bool checkType(ErrorInfoTy &ErrorInfo);
12212 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
12213 // form of 'conditional-update-capture-atomic' structured block on the v5.2
12214 // spec p.p. 82:
12215 // (1) { v = x; cond-update-stmt }
12216 // (2) { cond-update-stmt v = x; }
12217 // (3) if(x == e) { x = d; } else { v = x; }
12218 // (4) { r = x == e; if(r) { x = d; } }
12219 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
12221 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
12222 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12224 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
12225 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
12226 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12228 /// 'v' lvalue part of the source atomic expression.
12229 Expr *V = nullptr;
12230 /// 'r' lvalue part of the source atomic expression.
12231 Expr *R = nullptr;
12232 /// If 'v' is only updated when the comparison fails.
12233 bool IsFailOnly = false;
12234 /// If original value of 'x' must be stored in 'v', not an updated one.
12235 bool IsPostfixUpdate = false;
12238 bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12239 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12240 return false;
12242 if (V && !CheckValue(V, ErrorInfo, true))
12243 return false;
12245 if (R && !CheckValue(R, ErrorInfo, true, true))
12246 return false;
12248 return true;
12251 bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
12252 ErrorInfoTy &ErrorInfo) {
12253 IsFailOnly = true;
12255 auto *Then = S->getThen();
12256 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
12257 if (CS->body_empty()) {
12258 ErrorInfo.Error = ErrorTy::NoStmt;
12259 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12260 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12261 return false;
12263 if (CS->size() > 1) {
12264 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12265 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12266 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12267 return false;
12269 Then = CS->body_front();
12272 auto *BO = dyn_cast<BinaryOperator>(Then);
12273 if (!BO) {
12274 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12275 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12276 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12277 return false;
12279 if (BO->getOpcode() != BO_Assign) {
12280 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12281 ErrorInfo.ErrorLoc = BO->getExprLoc();
12282 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12283 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12284 return false;
12287 X = BO->getLHS();
12288 D = BO->getRHS();
12290 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12291 if (!Cond) {
12292 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12293 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12294 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12295 return false;
12297 if (Cond->getOpcode() != BO_EQ) {
12298 ErrorInfo.Error = ErrorTy::NotEQ;
12299 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12300 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12301 return false;
12304 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
12305 E = Cond->getRHS();
12306 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12307 E = Cond->getLHS();
12308 } else {
12309 ErrorInfo.Error = ErrorTy::InvalidComparison;
12310 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12311 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12312 return false;
12315 C = Cond;
12317 if (!S->getElse()) {
12318 ErrorInfo.Error = ErrorTy::NoElse;
12319 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12320 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12321 return false;
12324 auto *Else = S->getElse();
12325 if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
12326 if (CS->body_empty()) {
12327 ErrorInfo.Error = ErrorTy::NoStmt;
12328 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12329 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12330 return false;
12332 if (CS->size() > 1) {
12333 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12334 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12335 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12336 return false;
12338 Else = CS->body_front();
12341 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12342 if (!ElseBO) {
12343 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12344 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12345 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12346 return false;
12348 if (ElseBO->getOpcode() != BO_Assign) {
12349 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12350 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12351 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12352 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12353 return false;
12356 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12357 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12358 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12359 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12360 ElseBO->getRHS()->getSourceRange();
12361 return false;
12364 V = ElseBO->getLHS();
12366 return checkType(ErrorInfo);
12369 bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12370 ErrorInfoTy &ErrorInfo) {
12371 // We don't check here as they should be already done before call this
12372 // function.
12373 auto *CS = cast<CompoundStmt>(S);
12374 assert(CS->size() == 2 && "CompoundStmt size is not expected");
12375 auto *S1 = cast<BinaryOperator>(CS->body_front());
12376 auto *S2 = cast<IfStmt>(CS->body_back());
12377 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12379 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12380 ErrorInfo.Error = ErrorTy::InvalidCondition;
12381 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12382 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12383 return false;
12386 R = S1->getLHS();
12388 auto *Then = S2->getThen();
12389 if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12390 if (ThenCS->body_empty()) {
12391 ErrorInfo.Error = ErrorTy::NoStmt;
12392 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12393 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12394 return false;
12396 if (ThenCS->size() > 1) {
12397 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12398 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12399 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12400 return false;
12402 Then = ThenCS->body_front();
12405 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12406 if (!ThenBO) {
12407 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12408 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12409 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12410 return false;
12412 if (ThenBO->getOpcode() != BO_Assign) {
12413 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12414 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12415 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12416 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12417 return false;
12420 X = ThenBO->getLHS();
12421 D = ThenBO->getRHS();
12423 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12424 if (BO->getOpcode() != BO_EQ) {
12425 ErrorInfo.Error = ErrorTy::NotEQ;
12426 ErrorInfo.ErrorLoc = BO->getExprLoc();
12427 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12428 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12429 return false;
12432 C = BO;
12434 if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) {
12435 E = BO->getRHS();
12436 } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) {
12437 E = BO->getLHS();
12438 } else {
12439 ErrorInfo.Error = ErrorTy::InvalidComparison;
12440 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12441 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12442 return false;
12445 if (S2->getElse()) {
12446 IsFailOnly = true;
12448 auto *Else = S2->getElse();
12449 if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12450 if (ElseCS->body_empty()) {
12451 ErrorInfo.Error = ErrorTy::NoStmt;
12452 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12453 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12454 return false;
12456 if (ElseCS->size() > 1) {
12457 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12458 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12459 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12460 return false;
12462 Else = ElseCS->body_front();
12465 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12466 if (!ElseBO) {
12467 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12468 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12469 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12470 return false;
12472 if (ElseBO->getOpcode() != BO_Assign) {
12473 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12474 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12475 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12476 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12477 return false;
12479 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12480 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12481 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12482 ErrorInfo.NoteLoc = X->getExprLoc();
12483 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12484 ErrorInfo.NoteRange = X->getSourceRange();
12485 return false;
12488 V = ElseBO->getLHS();
12491 return checkType(ErrorInfo);
12494 bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12495 ErrorInfoTy &ErrorInfo) {
12496 // if(x == e) { x = d; } else { v = x; }
12497 if (auto *IS = dyn_cast<IfStmt>(S))
12498 return checkForm3(IS, ErrorInfo);
12500 auto *CS = dyn_cast<CompoundStmt>(S);
12501 if (!CS) {
12502 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12503 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12504 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12505 return false;
12507 if (CS->body_empty()) {
12508 ErrorInfo.Error = ErrorTy::NoStmt;
12509 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12510 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12511 return false;
12514 // { if(x == e) { x = d; } else { v = x; } }
12515 if (CS->size() == 1) {
12516 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12517 if (!IS) {
12518 ErrorInfo.Error = ErrorTy::NotIfStmt;
12519 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12520 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12521 CS->body_front()->getSourceRange();
12522 return false;
12525 return checkForm3(IS, ErrorInfo);
12526 } else if (CS->size() == 2) {
12527 auto *S1 = CS->body_front();
12528 auto *S2 = CS->body_back();
12530 Stmt *UpdateStmt = nullptr;
12531 Stmt *CondUpdateStmt = nullptr;
12532 Stmt *CondExprStmt = nullptr;
12534 if (auto *BO = dyn_cast<BinaryOperator>(S1)) {
12535 // It could be one of the following cases:
12536 // { v = x; cond-update-stmt }
12537 // { v = x; cond-expr-stmt }
12538 // { cond-expr-stmt; v = x; }
12539 // form 45
12540 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12541 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12542 // check if form 45
12543 if (isa<IfStmt>(S2))
12544 return checkForm45(CS, ErrorInfo);
12545 // { cond-expr-stmt; v = x; }
12546 CondExprStmt = S1;
12547 UpdateStmt = S2;
12548 } else {
12549 IsPostfixUpdate = true;
12550 UpdateStmt = S1;
12551 if (isa<IfStmt>(S2)) {
12552 // { v = x; cond-update-stmt }
12553 CondUpdateStmt = S2;
12554 } else {
12555 // { v = x; cond-expr-stmt }
12556 CondExprStmt = S2;
12559 } else {
12560 // { cond-update-stmt v = x; }
12561 UpdateStmt = S2;
12562 CondUpdateStmt = S1;
12565 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12566 auto *IS = dyn_cast<IfStmt>(CUS);
12567 if (!IS) {
12568 ErrorInfo.Error = ErrorTy::NotIfStmt;
12569 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12570 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12571 return false;
12574 return checkCondUpdateStmt(IS, ErrorInfo);
12577 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12578 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12579 auto *BO = dyn_cast<BinaryOperator>(US);
12580 if (!BO) {
12581 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12582 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12583 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12584 return false;
12586 if (BO->getOpcode() != BO_Assign) {
12587 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12588 ErrorInfo.ErrorLoc = BO->getExprLoc();
12589 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12590 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12591 return false;
12593 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12594 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12595 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12596 ErrorInfo.NoteLoc = this->X->getExprLoc();
12597 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12598 ErrorInfo.NoteRange = this->X->getSourceRange();
12599 return false;
12602 this->V = BO->getLHS();
12604 return true;
12607 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12608 return false;
12609 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12610 return false;
12611 if (!CheckUpdateStmt(UpdateStmt))
12612 return false;
12613 } else {
12614 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12615 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12616 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12617 return false;
12620 return checkType(ErrorInfo);
12622 } // namespace
12624 StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
12625 Stmt *AStmt,
12626 SourceLocation StartLoc,
12627 SourceLocation EndLoc) {
12628 // Register location of the first atomic directive.
12629 DSAStack->addAtomicDirectiveLoc(StartLoc);
12630 if (!AStmt)
12631 return StmtError();
12633 // 1.2.2 OpenMP Language Terminology
12634 // Structured block - An executable statement with a single entry at the
12635 // top and a single exit at the bottom.
12636 // The point of exit cannot be a branch out of the structured block.
12637 // longjmp() and throw() must not violate the entry/exit criteria.
12638 OpenMPClauseKind AtomicKind = OMPC_unknown;
12639 SourceLocation AtomicKindLoc;
12640 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12641 SourceLocation MemOrderLoc;
12642 bool MutexClauseEncountered = false;
12643 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12644 for (const OMPClause *C : Clauses) {
12645 switch (C->getClauseKind()) {
12646 case OMPC_read:
12647 case OMPC_write:
12648 case OMPC_update:
12649 MutexClauseEncountered = true;
12650 [[fallthrough]];
12651 case OMPC_capture:
12652 case OMPC_compare: {
12653 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12654 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12655 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12656 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12657 << getOpenMPClauseName(AtomicKind);
12658 } else {
12659 AtomicKind = C->getClauseKind();
12660 AtomicKindLoc = C->getBeginLoc();
12661 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12662 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12663 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12664 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12665 << getOpenMPClauseName(AtomicKind);
12668 break;
12670 case OMPC_seq_cst:
12671 case OMPC_acq_rel:
12672 case OMPC_acquire:
12673 case OMPC_release:
12674 case OMPC_relaxed: {
12675 if (MemOrderKind != OMPC_unknown) {
12676 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12677 << getOpenMPDirectiveName(OMPD_atomic) << 0
12678 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12679 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12680 << getOpenMPClauseName(MemOrderKind);
12681 } else {
12682 MemOrderKind = C->getClauseKind();
12683 MemOrderLoc = C->getBeginLoc();
12685 break;
12687 // The following clauses are allowed, but we don't need to do anything here.
12688 case OMPC_hint:
12689 break;
12690 default:
12691 llvm_unreachable("unknown clause is encountered");
12694 bool IsCompareCapture = false;
12695 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12696 EncounteredAtomicKinds.contains(OMPC_capture)) {
12697 IsCompareCapture = true;
12698 AtomicKind = OMPC_compare;
12700 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12701 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12702 // release.
12703 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12704 // acquire.
12705 // If atomic-clause is update or not present then memory-order-clause must not
12706 // be acq_rel or acquire.
12707 if ((AtomicKind == OMPC_read &&
12708 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12709 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12710 AtomicKind == OMPC_unknown) &&
12711 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12712 SourceLocation Loc = AtomicKindLoc;
12713 if (AtomicKind == OMPC_unknown)
12714 Loc = StartLoc;
12715 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12716 << getOpenMPClauseName(AtomicKind)
12717 << (AtomicKind == OMPC_unknown ? 1 : 0)
12718 << getOpenMPClauseName(MemOrderKind);
12719 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12720 << getOpenMPClauseName(MemOrderKind);
12723 Stmt *Body = AStmt;
12724 if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12725 Body = EWC->getSubExpr();
12727 Expr *X = nullptr;
12728 Expr *V = nullptr;
12729 Expr *E = nullptr;
12730 Expr *UE = nullptr;
12731 Expr *D = nullptr;
12732 Expr *CE = nullptr;
12733 Expr *R = nullptr;
12734 bool IsXLHSInRHSPart = false;
12735 bool IsPostfixUpdate = false;
12736 bool IsFailOnly = false;
12737 // OpenMP [2.12.6, atomic Construct]
12738 // In the next expressions:
12739 // * x and v (as applicable) are both l-value expressions with scalar type.
12740 // * During the execution of an atomic region, multiple syntactic
12741 // occurrences of x must designate the same storage location.
12742 // * Neither of v and expr (as applicable) may access the storage location
12743 // designated by x.
12744 // * Neither of x and expr (as applicable) may access the storage location
12745 // designated by v.
12746 // * expr is an expression with scalar type.
12747 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12748 // * binop, binop=, ++, and -- are not overloaded operators.
12749 // * The expression x binop expr must be numerically equivalent to x binop
12750 // (expr). This requirement is satisfied if the operators in expr have
12751 // precedence greater than binop, or by using parentheses around expr or
12752 // subexpressions of expr.
12753 // * The expression expr binop x must be numerically equivalent to (expr)
12754 // binop x. This requirement is satisfied if the operators in expr have
12755 // precedence equal to or greater than binop, or by using parentheses around
12756 // expr or subexpressions of expr.
12757 // * For forms that allow multiple occurrences of x, the number of times
12758 // that x is evaluated is unspecified.
12759 if (AtomicKind == OMPC_read) {
12760 enum {
12761 NotAnExpression,
12762 NotAnAssignmentOp,
12763 NotAScalarType,
12764 NotAnLValue,
12765 NoError
12766 } ErrorFound = NoError;
12767 SourceLocation ErrorLoc, NoteLoc;
12768 SourceRange ErrorRange, NoteRange;
12769 // If clause is read:
12770 // v = x;
12771 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12772 const auto *AtomicBinOp =
12773 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12774 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12775 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12776 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12777 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12778 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12779 if (!X->isLValue() || !V->isLValue()) {
12780 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12781 ErrorFound = NotAnLValue;
12782 ErrorLoc = AtomicBinOp->getExprLoc();
12783 ErrorRange = AtomicBinOp->getSourceRange();
12784 NoteLoc = NotLValueExpr->getExprLoc();
12785 NoteRange = NotLValueExpr->getSourceRange();
12787 } else if (!X->isInstantiationDependent() ||
12788 !V->isInstantiationDependent()) {
12789 const Expr *NotScalarExpr =
12790 (X->isInstantiationDependent() || X->getType()->isScalarType())
12792 : X;
12793 ErrorFound = NotAScalarType;
12794 ErrorLoc = AtomicBinOp->getExprLoc();
12795 ErrorRange = AtomicBinOp->getSourceRange();
12796 NoteLoc = NotScalarExpr->getExprLoc();
12797 NoteRange = NotScalarExpr->getSourceRange();
12799 } else if (!AtomicBody->isInstantiationDependent()) {
12800 ErrorFound = NotAnAssignmentOp;
12801 ErrorLoc = AtomicBody->getExprLoc();
12802 ErrorRange = AtomicBody->getSourceRange();
12803 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12804 : AtomicBody->getExprLoc();
12805 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12806 : AtomicBody->getSourceRange();
12808 } else {
12809 ErrorFound = NotAnExpression;
12810 NoteLoc = ErrorLoc = Body->getBeginLoc();
12811 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12813 if (ErrorFound != NoError) {
12814 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12815 << ErrorRange;
12816 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12817 << ErrorFound << NoteRange;
12818 return StmtError();
12820 if (CurContext->isDependentContext())
12821 V = X = nullptr;
12822 } else if (AtomicKind == OMPC_write) {
12823 enum {
12824 NotAnExpression,
12825 NotAnAssignmentOp,
12826 NotAScalarType,
12827 NotAnLValue,
12828 NoError
12829 } ErrorFound = NoError;
12830 SourceLocation ErrorLoc, NoteLoc;
12831 SourceRange ErrorRange, NoteRange;
12832 // If clause is write:
12833 // x = expr;
12834 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12835 const auto *AtomicBinOp =
12836 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12837 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12838 X = AtomicBinOp->getLHS();
12839 E = AtomicBinOp->getRHS();
12840 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12841 (E->isInstantiationDependent() || E->getType()->isScalarType())) {
12842 if (!X->isLValue()) {
12843 ErrorFound = NotAnLValue;
12844 ErrorLoc = AtomicBinOp->getExprLoc();
12845 ErrorRange = AtomicBinOp->getSourceRange();
12846 NoteLoc = X->getExprLoc();
12847 NoteRange = X->getSourceRange();
12849 } else if (!X->isInstantiationDependent() ||
12850 !E->isInstantiationDependent()) {
12851 const Expr *NotScalarExpr =
12852 (X->isInstantiationDependent() || X->getType()->isScalarType())
12854 : X;
12855 ErrorFound = NotAScalarType;
12856 ErrorLoc = AtomicBinOp->getExprLoc();
12857 ErrorRange = AtomicBinOp->getSourceRange();
12858 NoteLoc = NotScalarExpr->getExprLoc();
12859 NoteRange = NotScalarExpr->getSourceRange();
12861 } else if (!AtomicBody->isInstantiationDependent()) {
12862 ErrorFound = NotAnAssignmentOp;
12863 ErrorLoc = AtomicBody->getExprLoc();
12864 ErrorRange = AtomicBody->getSourceRange();
12865 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12866 : AtomicBody->getExprLoc();
12867 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12868 : AtomicBody->getSourceRange();
12870 } else {
12871 ErrorFound = NotAnExpression;
12872 NoteLoc = ErrorLoc = Body->getBeginLoc();
12873 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12875 if (ErrorFound != NoError) {
12876 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12877 << ErrorRange;
12878 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12879 << ErrorFound << NoteRange;
12880 return StmtError();
12882 if (CurContext->isDependentContext())
12883 E = X = nullptr;
12884 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12885 // If clause is update:
12886 // x++;
12887 // x--;
12888 // ++x;
12889 // --x;
12890 // x binop= expr;
12891 // x = x binop expr;
12892 // x = expr binop x;
12893 OpenMPAtomicUpdateChecker Checker(*this);
12894 if (Checker.checkStatement(
12895 Body,
12896 (AtomicKind == OMPC_update)
12897 ? diag::err_omp_atomic_update_not_expression_statement
12898 : diag::err_omp_atomic_not_expression_statement,
12899 diag::note_omp_atomic_update))
12900 return StmtError();
12901 if (!CurContext->isDependentContext()) {
12902 E = Checker.getExpr();
12903 X = Checker.getX();
12904 UE = Checker.getUpdateExpr();
12905 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12907 } else if (AtomicKind == OMPC_capture) {
12908 enum {
12909 NotAnAssignmentOp,
12910 NotACompoundStatement,
12911 NotTwoSubstatements,
12912 NotASpecificExpression,
12913 NoError
12914 } ErrorFound = NoError;
12915 SourceLocation ErrorLoc, NoteLoc;
12916 SourceRange ErrorRange, NoteRange;
12917 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12918 // If clause is a capture:
12919 // v = x++;
12920 // v = x--;
12921 // v = ++x;
12922 // v = --x;
12923 // v = x binop= expr;
12924 // v = x = x binop expr;
12925 // v = x = expr binop x;
12926 const auto *AtomicBinOp =
12927 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12928 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12929 V = AtomicBinOp->getLHS();
12930 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12931 OpenMPAtomicUpdateChecker Checker(*this);
12932 if (Checker.checkStatement(
12933 Body, diag::err_omp_atomic_capture_not_expression_statement,
12934 diag::note_omp_atomic_update))
12935 return StmtError();
12936 E = Checker.getExpr();
12937 X = Checker.getX();
12938 UE = Checker.getUpdateExpr();
12939 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12940 IsPostfixUpdate = Checker.isPostfixUpdate();
12941 } else if (!AtomicBody->isInstantiationDependent()) {
12942 ErrorLoc = AtomicBody->getExprLoc();
12943 ErrorRange = AtomicBody->getSourceRange();
12944 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12945 : AtomicBody->getExprLoc();
12946 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12947 : AtomicBody->getSourceRange();
12948 ErrorFound = NotAnAssignmentOp;
12950 if (ErrorFound != NoError) {
12951 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
12952 << ErrorRange;
12953 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12954 return StmtError();
12956 if (CurContext->isDependentContext())
12957 UE = V = E = X = nullptr;
12958 } else {
12959 // If clause is a capture:
12960 // { v = x; x = expr; }
12961 // { v = x; x++; }
12962 // { v = x; x--; }
12963 // { v = x; ++x; }
12964 // { v = x; --x; }
12965 // { v = x; x binop= expr; }
12966 // { v = x; x = x binop expr; }
12967 // { v = x; x = expr binop x; }
12968 // { x++; v = x; }
12969 // { x--; v = x; }
12970 // { ++x; v = x; }
12971 // { --x; v = x; }
12972 // { x binop= expr; v = x; }
12973 // { x = x binop expr; v = x; }
12974 // { x = expr binop x; v = x; }
12975 if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
12976 // Check that this is { expr1; expr2; }
12977 if (CS->size() == 2) {
12978 Stmt *First = CS->body_front();
12979 Stmt *Second = CS->body_back();
12980 if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
12981 First = EWC->getSubExpr()->IgnoreParenImpCasts();
12982 if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
12983 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
12984 // Need to find what subexpression is 'v' and what is 'x'.
12985 OpenMPAtomicUpdateChecker Checker(*this);
12986 bool IsUpdateExprFound = !Checker.checkStatement(Second);
12987 BinaryOperator *BinOp = nullptr;
12988 if (IsUpdateExprFound) {
12989 BinOp = dyn_cast<BinaryOperator>(First);
12990 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12992 if (IsUpdateExprFound && !CurContext->isDependentContext()) {
12993 // { v = x; x++; }
12994 // { v = x; x--; }
12995 // { v = x; ++x; }
12996 // { v = x; --x; }
12997 // { v = x; x binop= expr; }
12998 // { v = x; x = x binop expr; }
12999 // { v = x; x = expr binop x; }
13000 // Check that the first expression has form v = x.
13001 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13002 llvm::FoldingSetNodeID XId, PossibleXId;
13003 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13004 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13005 IsUpdateExprFound = XId == PossibleXId;
13006 if (IsUpdateExprFound) {
13007 V = BinOp->getLHS();
13008 X = Checker.getX();
13009 E = Checker.getExpr();
13010 UE = Checker.getUpdateExpr();
13011 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13012 IsPostfixUpdate = true;
13015 if (!IsUpdateExprFound) {
13016 IsUpdateExprFound = !Checker.checkStatement(First);
13017 BinOp = nullptr;
13018 if (IsUpdateExprFound) {
13019 BinOp = dyn_cast<BinaryOperator>(Second);
13020 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13022 if (IsUpdateExprFound && !CurContext->isDependentContext()) {
13023 // { x++; v = x; }
13024 // { x--; v = x; }
13025 // { ++x; v = x; }
13026 // { --x; v = x; }
13027 // { x binop= expr; v = x; }
13028 // { x = x binop expr; v = x; }
13029 // { x = expr binop x; v = x; }
13030 // Check that the second expression has form v = x.
13031 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13032 llvm::FoldingSetNodeID XId, PossibleXId;
13033 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13034 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13035 IsUpdateExprFound = XId == PossibleXId;
13036 if (IsUpdateExprFound) {
13037 V = BinOp->getLHS();
13038 X = Checker.getX();
13039 E = Checker.getExpr();
13040 UE = Checker.getUpdateExpr();
13041 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13042 IsPostfixUpdate = false;
13046 if (!IsUpdateExprFound) {
13047 // { v = x; x = expr; }
13048 auto *FirstExpr = dyn_cast<Expr>(First);
13049 auto *SecondExpr = dyn_cast<Expr>(Second);
13050 if (!FirstExpr || !SecondExpr ||
13051 !(FirstExpr->isInstantiationDependent() ||
13052 SecondExpr->isInstantiationDependent())) {
13053 auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
13054 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
13055 ErrorFound = NotAnAssignmentOp;
13056 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
13057 : First->getBeginLoc();
13058 NoteRange = ErrorRange = FirstBinOp
13059 ? FirstBinOp->getSourceRange()
13060 : SourceRange(ErrorLoc, ErrorLoc);
13061 } else {
13062 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
13063 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
13064 ErrorFound = NotAnAssignmentOp;
13065 NoteLoc = ErrorLoc = SecondBinOp
13066 ? SecondBinOp->getOperatorLoc()
13067 : Second->getBeginLoc();
13068 NoteRange = ErrorRange =
13069 SecondBinOp ? SecondBinOp->getSourceRange()
13070 : SourceRange(ErrorLoc, ErrorLoc);
13071 } else {
13072 Expr *PossibleXRHSInFirst =
13073 FirstBinOp->getRHS()->IgnoreParenImpCasts();
13074 Expr *PossibleXLHSInSecond =
13075 SecondBinOp->getLHS()->IgnoreParenImpCasts();
13076 llvm::FoldingSetNodeID X1Id, X2Id;
13077 PossibleXRHSInFirst->Profile(X1Id, Context,
13078 /*Canonical=*/true);
13079 PossibleXLHSInSecond->Profile(X2Id, Context,
13080 /*Canonical=*/true);
13081 IsUpdateExprFound = X1Id == X2Id;
13082 if (IsUpdateExprFound) {
13083 V = FirstBinOp->getLHS();
13084 X = SecondBinOp->getLHS();
13085 E = SecondBinOp->getRHS();
13086 UE = nullptr;
13087 IsXLHSInRHSPart = false;
13088 IsPostfixUpdate = true;
13089 } else {
13090 ErrorFound = NotASpecificExpression;
13091 ErrorLoc = FirstBinOp->getExprLoc();
13092 ErrorRange = FirstBinOp->getSourceRange();
13093 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
13094 NoteRange = SecondBinOp->getRHS()->getSourceRange();
13100 } else {
13101 NoteLoc = ErrorLoc = Body->getBeginLoc();
13102 NoteRange = ErrorRange =
13103 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13104 ErrorFound = NotTwoSubstatements;
13106 } else {
13107 NoteLoc = ErrorLoc = Body->getBeginLoc();
13108 NoteRange = ErrorRange =
13109 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13110 ErrorFound = NotACompoundStatement;
13113 if (ErrorFound != NoError) {
13114 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
13115 << ErrorRange;
13116 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13117 return StmtError();
13119 if (CurContext->isDependentContext())
13120 UE = V = E = X = nullptr;
13121 } else if (AtomicKind == OMPC_compare) {
13122 if (IsCompareCapture) {
13123 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
13124 OpenMPAtomicCompareCaptureChecker Checker(*this);
13125 if (!Checker.checkStmt(Body, ErrorInfo)) {
13126 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
13127 << ErrorInfo.ErrorRange;
13128 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13129 << ErrorInfo.Error << ErrorInfo.NoteRange;
13130 return StmtError();
13132 X = Checker.getX();
13133 E = Checker.getE();
13134 D = Checker.getD();
13135 CE = Checker.getCond();
13136 V = Checker.getV();
13137 R = Checker.getR();
13138 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13139 IsXLHSInRHSPart = Checker.isXBinopExpr();
13140 IsFailOnly = Checker.isFailOnly();
13141 IsPostfixUpdate = Checker.isPostfixUpdate();
13142 } else {
13143 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
13144 OpenMPAtomicCompareChecker Checker(*this);
13145 if (!Checker.checkStmt(Body, ErrorInfo)) {
13146 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
13147 << ErrorInfo.ErrorRange;
13148 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13149 << ErrorInfo.Error << ErrorInfo.NoteRange;
13150 return StmtError();
13152 X = Checker.getX();
13153 E = Checker.getE();
13154 D = Checker.getD();
13155 CE = Checker.getCond();
13156 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13157 IsXLHSInRHSPart = Checker.isXBinopExpr();
13161 setFunctionHasBranchProtectedScope();
13163 return OMPAtomicDirective::Create(
13164 Context, StartLoc, EndLoc, Clauses, AStmt,
13165 {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
13168 StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
13169 Stmt *AStmt,
13170 SourceLocation StartLoc,
13171 SourceLocation EndLoc) {
13172 if (!AStmt)
13173 return StmtError();
13175 auto *CS = cast<CapturedStmt>(AStmt);
13176 // 1.2.2 OpenMP Language Terminology
13177 // Structured block - An executable statement with a single entry at the
13178 // top and a single exit at the bottom.
13179 // The point of exit cannot be a branch out of the structured block.
13180 // longjmp() and throw() must not violate the entry/exit criteria.
13181 CS->getCapturedDecl()->setNothrow();
13182 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target);
13183 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13184 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13185 // 1.2.2 OpenMP Language Terminology
13186 // Structured block - An executable statement with a single entry at the
13187 // top and a single exit at the bottom.
13188 // The point of exit cannot be a branch out of the structured block.
13189 // longjmp() and throw() must not violate the entry/exit criteria.
13190 CS->getCapturedDecl()->setNothrow();
13193 // OpenMP [2.16, Nesting of Regions]
13194 // If specified, a teams construct must be contained within a target
13195 // construct. That target construct must contain no statements or directives
13196 // outside of the teams construct.
13197 if (DSAStack->hasInnerTeamsRegion()) {
13198 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
13199 bool OMPTeamsFound = true;
13200 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
13201 auto I = CS->body_begin();
13202 while (I != CS->body_end()) {
13203 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
13204 if (!OED || !isOpenMPTeamsDirective(OED->getDirectiveKind()) ||
13205 OMPTeamsFound) {
13207 OMPTeamsFound = false;
13208 break;
13210 ++I;
13212 assert(I != CS->body_end() && "Not found statement");
13213 S = *I;
13214 } else {
13215 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
13216 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13218 if (!OMPTeamsFound) {
13219 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
13220 Diag(DSAStack->getInnerTeamsRegionLoc(),
13221 diag::note_omp_nested_teams_construct_here);
13222 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
13223 << isa<OMPExecutableDirective>(S);
13224 return StmtError();
13228 setFunctionHasBranchProtectedScope();
13230 return OMPTargetDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
13233 StmtResult
13234 Sema::ActOnOpenMPTargetParallelDirective(ArrayRef<OMPClause *> Clauses,
13235 Stmt *AStmt, SourceLocation StartLoc,
13236 SourceLocation EndLoc) {
13237 if (!AStmt)
13238 return StmtError();
13240 auto *CS = cast<CapturedStmt>(AStmt);
13241 // 1.2.2 OpenMP Language Terminology
13242 // Structured block - An executable statement with a single entry at the
13243 // top and a single exit at the bottom.
13244 // The point of exit cannot be a branch out of the structured block.
13245 // longjmp() and throw() must not violate the entry/exit criteria.
13246 CS->getCapturedDecl()->setNothrow();
13247 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel);
13248 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13249 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13250 // 1.2.2 OpenMP Language Terminology
13251 // Structured block - An executable statement with a single entry at the
13252 // top and a single exit at the bottom.
13253 // The point of exit cannot be a branch out of the structured block.
13254 // longjmp() and throw() must not violate the entry/exit criteria.
13255 CS->getCapturedDecl()->setNothrow();
13258 setFunctionHasBranchProtectedScope();
13260 return OMPTargetParallelDirective::Create(
13261 Context, StartLoc, EndLoc, Clauses, AStmt,
13262 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13265 StmtResult Sema::ActOnOpenMPTargetParallelForDirective(
13266 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13267 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13268 if (!AStmt)
13269 return StmtError();
13271 auto *CS = cast<CapturedStmt>(AStmt);
13272 // 1.2.2 OpenMP Language Terminology
13273 // Structured block - An executable statement with a single entry at the
13274 // top and a single exit at the bottom.
13275 // The point of exit cannot be a branch out of the structured block.
13276 // longjmp() and throw() must not violate the entry/exit criteria.
13277 CS->getCapturedDecl()->setNothrow();
13278 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_for);
13279 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13280 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13281 // 1.2.2 OpenMP Language Terminology
13282 // Structured block - An executable statement with a single entry at the
13283 // top and a single exit at the bottom.
13284 // The point of exit cannot be a branch out of the structured block.
13285 // longjmp() and throw() must not violate the entry/exit criteria.
13286 CS->getCapturedDecl()->setNothrow();
13289 OMPLoopBasedDirective::HelperExprs B;
13290 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13291 // define the nested loops number.
13292 unsigned NestedLoopCount =
13293 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
13294 getOrderedNumberExpr(Clauses), CS, *this, *DSAStack,
13295 VarsWithImplicitDSA, B);
13296 if (NestedLoopCount == 0)
13297 return StmtError();
13299 assert((CurContext->isDependentContext() || B.builtAll()) &&
13300 "omp target parallel for loop exprs were not built");
13302 if (!CurContext->isDependentContext()) {
13303 // Finalize the clauses that need pre-built expressions for CodeGen.
13304 for (OMPClause *C : Clauses) {
13305 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13306 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13307 B.NumIterations, *this, CurScope,
13308 DSAStack))
13309 return StmtError();
13313 setFunctionHasBranchProtectedScope();
13314 return OMPTargetParallelForDirective::Create(
13315 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13316 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13319 /// Check for existence of a map clause in the list of clauses.
13320 static bool hasClauses(ArrayRef<OMPClause *> Clauses,
13321 const OpenMPClauseKind K) {
13322 return llvm::any_of(
13323 Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
13326 template <typename... Params>
13327 static bool hasClauses(ArrayRef<OMPClause *> Clauses, const OpenMPClauseKind K,
13328 const Params... ClauseTypes) {
13329 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13332 /// Check if the variables in the mapping clause are externally visible.
13333 static bool isClauseMappable(ArrayRef<OMPClause *> Clauses) {
13334 for (const OMPClause *C : Clauses) {
13335 if (auto *TC = dyn_cast<OMPToClause>(C))
13336 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
13337 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13338 (VD->isExternallyVisible() &&
13339 VD->getVisibility() != HiddenVisibility);
13341 else if (auto *FC = dyn_cast<OMPFromClause>(C))
13342 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
13343 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13344 (VD->isExternallyVisible() &&
13345 VD->getVisibility() != HiddenVisibility);
13349 return true;
13352 StmtResult Sema::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
13353 Stmt *AStmt,
13354 SourceLocation StartLoc,
13355 SourceLocation EndLoc) {
13356 if (!AStmt)
13357 return StmtError();
13359 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13361 // OpenMP [2.12.2, target data Construct, Restrictions]
13362 // At least one map, use_device_addr or use_device_ptr clause must appear on
13363 // the directive.
13364 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13365 (LangOpts.OpenMP < 50 || !hasClauses(Clauses, OMPC_use_device_addr))) {
13366 StringRef Expected;
13367 if (LangOpts.OpenMP < 50)
13368 Expected = "'map' or 'use_device_ptr'";
13369 else
13370 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13371 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13372 << Expected << getOpenMPDirectiveName(OMPD_target_data);
13373 return StmtError();
13376 setFunctionHasBranchProtectedScope();
13378 return OMPTargetDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
13379 AStmt);
13382 StmtResult
13383 Sema::ActOnOpenMPTargetEnterDataDirective(ArrayRef<OMPClause *> Clauses,
13384 SourceLocation StartLoc,
13385 SourceLocation EndLoc, Stmt *AStmt) {
13386 if (!AStmt)
13387 return StmtError();
13389 auto *CS = cast<CapturedStmt>(AStmt);
13390 // 1.2.2 OpenMP Language Terminology
13391 // Structured block - An executable statement with a single entry at the
13392 // top and a single exit at the bottom.
13393 // The point of exit cannot be a branch out of the structured block.
13394 // longjmp() and throw() must not violate the entry/exit criteria.
13395 CS->getCapturedDecl()->setNothrow();
13396 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_enter_data);
13397 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13398 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13399 // 1.2.2 OpenMP Language Terminology
13400 // Structured block - An executable statement with a single entry at the
13401 // top and a single exit at the bottom.
13402 // The point of exit cannot be a branch out of the structured block.
13403 // longjmp() and throw() must not violate the entry/exit criteria.
13404 CS->getCapturedDecl()->setNothrow();
13407 // OpenMP [2.10.2, Restrictions, p. 99]
13408 // At least one map clause must appear on the directive.
13409 if (!hasClauses(Clauses, OMPC_map)) {
13410 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13411 << "'map'" << getOpenMPDirectiveName(OMPD_target_enter_data);
13412 return StmtError();
13415 return OMPTargetEnterDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
13416 AStmt);
13419 StmtResult
13420 Sema::ActOnOpenMPTargetExitDataDirective(ArrayRef<OMPClause *> Clauses,
13421 SourceLocation StartLoc,
13422 SourceLocation EndLoc, Stmt *AStmt) {
13423 if (!AStmt)
13424 return StmtError();
13426 auto *CS = cast<CapturedStmt>(AStmt);
13427 // 1.2.2 OpenMP Language Terminology
13428 // Structured block - An executable statement with a single entry at the
13429 // top and a single exit at the bottom.
13430 // The point of exit cannot be a branch out of the structured block.
13431 // longjmp() and throw() must not violate the entry/exit criteria.
13432 CS->getCapturedDecl()->setNothrow();
13433 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_exit_data);
13434 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13435 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13436 // 1.2.2 OpenMP Language Terminology
13437 // Structured block - An executable statement with a single entry at the
13438 // top and a single exit at the bottom.
13439 // The point of exit cannot be a branch out of the structured block.
13440 // longjmp() and throw() must not violate the entry/exit criteria.
13441 CS->getCapturedDecl()->setNothrow();
13444 // OpenMP [2.10.3, Restrictions, p. 102]
13445 // At least one map clause must appear on the directive.
13446 if (!hasClauses(Clauses, OMPC_map)) {
13447 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13448 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data);
13449 return StmtError();
13452 return OMPTargetExitDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
13453 AStmt);
13456 StmtResult Sema::ActOnOpenMPTargetUpdateDirective(ArrayRef<OMPClause *> Clauses,
13457 SourceLocation StartLoc,
13458 SourceLocation EndLoc,
13459 Stmt *AStmt) {
13460 if (!AStmt)
13461 return StmtError();
13463 auto *CS = cast<CapturedStmt>(AStmt);
13464 // 1.2.2 OpenMP Language Terminology
13465 // Structured block - An executable statement with a single entry at the
13466 // top and a single exit at the bottom.
13467 // The point of exit cannot be a branch out of the structured block.
13468 // longjmp() and throw() must not violate the entry/exit criteria.
13469 CS->getCapturedDecl()->setNothrow();
13470 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_update);
13471 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13472 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13473 // 1.2.2 OpenMP Language Terminology
13474 // Structured block - An executable statement with a single entry at the
13475 // top and a single exit at the bottom.
13476 // The point of exit cannot be a branch out of the structured block.
13477 // longjmp() and throw() must not violate the entry/exit criteria.
13478 CS->getCapturedDecl()->setNothrow();
13481 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
13482 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13483 return StmtError();
13486 if (!isClauseMappable(Clauses)) {
13487 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13488 return StmtError();
13491 return OMPTargetUpdateDirective::Create(Context, StartLoc, EndLoc, Clauses,
13492 AStmt);
13495 StmtResult Sema::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
13496 Stmt *AStmt, SourceLocation StartLoc,
13497 SourceLocation EndLoc) {
13498 if (!AStmt)
13499 return StmtError();
13501 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13502 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13503 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13505 auto *CS = cast<CapturedStmt>(AStmt);
13506 // 1.2.2 OpenMP Language Terminology
13507 // Structured block - An executable statement with a single entry at the
13508 // top and a single exit at the bottom.
13509 // The point of exit cannot be a branch out of the structured block.
13510 // longjmp() and throw() must not violate the entry/exit criteria.
13511 CS->getCapturedDecl()->setNothrow();
13513 setFunctionHasBranchProtectedScope();
13515 DSAStack->setParentTeamsRegionLoc(StartLoc);
13517 return OMPTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
13520 StmtResult
13521 Sema::ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc,
13522 SourceLocation EndLoc,
13523 OpenMPDirectiveKind CancelRegion) {
13524 if (DSAStack->isParentNowaitRegion()) {
13525 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13526 return StmtError();
13528 if (DSAStack->isParentOrderedRegion()) {
13529 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13530 return StmtError();
13532 return OMPCancellationPointDirective::Create(Context, StartLoc, EndLoc,
13533 CancelRegion);
13536 StmtResult Sema::ActOnOpenMPCancelDirective(ArrayRef<OMPClause *> Clauses,
13537 SourceLocation StartLoc,
13538 SourceLocation EndLoc,
13539 OpenMPDirectiveKind CancelRegion) {
13540 if (DSAStack->isParentNowaitRegion()) {
13541 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13542 return StmtError();
13544 if (DSAStack->isParentOrderedRegion()) {
13545 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13546 return StmtError();
13548 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13549 return OMPCancelDirective::Create(Context, StartLoc, EndLoc, Clauses,
13550 CancelRegion);
13553 static bool checkReductionClauseWithNogroup(Sema &S,
13554 ArrayRef<OMPClause *> Clauses) {
13555 const OMPClause *ReductionClause = nullptr;
13556 const OMPClause *NogroupClause = nullptr;
13557 for (const OMPClause *C : Clauses) {
13558 if (C->getClauseKind() == OMPC_reduction) {
13559 ReductionClause = C;
13560 if (NogroupClause)
13561 break;
13562 continue;
13564 if (C->getClauseKind() == OMPC_nogroup) {
13565 NogroupClause = C;
13566 if (ReductionClause)
13567 break;
13568 continue;
13571 if (ReductionClause && NogroupClause) {
13572 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13573 << SourceRange(NogroupClause->getBeginLoc(),
13574 NogroupClause->getEndLoc());
13575 return true;
13577 return false;
13580 StmtResult Sema::ActOnOpenMPTaskLoopDirective(
13581 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13582 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13583 if (!AStmt)
13584 return StmtError();
13586 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13587 OMPLoopBasedDirective::HelperExprs B;
13588 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13589 // define the nested loops number.
13590 unsigned NestedLoopCount =
13591 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13592 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13593 VarsWithImplicitDSA, B);
13594 if (NestedLoopCount == 0)
13595 return StmtError();
13597 assert((CurContext->isDependentContext() || B.builtAll()) &&
13598 "omp for loop exprs were not built");
13600 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13601 // The grainsize clause and num_tasks clause are mutually exclusive and may
13602 // not appear on the same taskloop directive.
13603 if (checkMutuallyExclusiveClauses(*this, Clauses,
13604 {OMPC_grainsize, OMPC_num_tasks}))
13605 return StmtError();
13606 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13607 // If a reduction clause is present on the taskloop directive, the nogroup
13608 // clause must not be specified.
13609 if (checkReductionClauseWithNogroup(*this, Clauses))
13610 return StmtError();
13612 setFunctionHasBranchProtectedScope();
13613 return OMPTaskLoopDirective::Create(Context, StartLoc, EndLoc,
13614 NestedLoopCount, Clauses, AStmt, B,
13615 DSAStack->isCancelRegion());
13618 StmtResult Sema::ActOnOpenMPTaskLoopSimdDirective(
13619 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13620 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13621 if (!AStmt)
13622 return StmtError();
13624 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13625 OMPLoopBasedDirective::HelperExprs B;
13626 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13627 // define the nested loops number.
13628 unsigned NestedLoopCount =
13629 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13630 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13631 VarsWithImplicitDSA, B);
13632 if (NestedLoopCount == 0)
13633 return StmtError();
13635 assert((CurContext->isDependentContext() || B.builtAll()) &&
13636 "omp for loop exprs were not built");
13638 if (!CurContext->isDependentContext()) {
13639 // Finalize the clauses that need pre-built expressions for CodeGen.
13640 for (OMPClause *C : Clauses) {
13641 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13642 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13643 B.NumIterations, *this, CurScope,
13644 DSAStack))
13645 return StmtError();
13649 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13650 // The grainsize clause and num_tasks clause are mutually exclusive and may
13651 // not appear on the same taskloop directive.
13652 if (checkMutuallyExclusiveClauses(*this, Clauses,
13653 {OMPC_grainsize, OMPC_num_tasks}))
13654 return StmtError();
13655 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13656 // If a reduction clause is present on the taskloop directive, the nogroup
13657 // clause must not be specified.
13658 if (checkReductionClauseWithNogroup(*this, Clauses))
13659 return StmtError();
13660 if (checkSimdlenSafelenSpecified(*this, Clauses))
13661 return StmtError();
13663 setFunctionHasBranchProtectedScope();
13664 return OMPTaskLoopSimdDirective::Create(Context, StartLoc, EndLoc,
13665 NestedLoopCount, Clauses, AStmt, B);
13668 StmtResult Sema::ActOnOpenMPMasterTaskLoopDirective(
13669 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13670 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13671 if (!AStmt)
13672 return StmtError();
13674 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13675 OMPLoopBasedDirective::HelperExprs B;
13676 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13677 // define the nested loops number.
13678 unsigned NestedLoopCount =
13679 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13680 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13681 VarsWithImplicitDSA, B);
13682 if (NestedLoopCount == 0)
13683 return StmtError();
13685 assert((CurContext->isDependentContext() || B.builtAll()) &&
13686 "omp for loop exprs were not built");
13688 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13689 // The grainsize clause and num_tasks clause are mutually exclusive and may
13690 // not appear on the same taskloop directive.
13691 if (checkMutuallyExclusiveClauses(*this, Clauses,
13692 {OMPC_grainsize, OMPC_num_tasks}))
13693 return StmtError();
13694 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13695 // If a reduction clause is present on the taskloop directive, the nogroup
13696 // clause must not be specified.
13697 if (checkReductionClauseWithNogroup(*this, Clauses))
13698 return StmtError();
13700 setFunctionHasBranchProtectedScope();
13701 return OMPMasterTaskLoopDirective::Create(Context, StartLoc, EndLoc,
13702 NestedLoopCount, Clauses, AStmt, B,
13703 DSAStack->isCancelRegion());
13706 StmtResult Sema::ActOnOpenMPMaskedTaskLoopDirective(
13707 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13708 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13709 if (!AStmt)
13710 return StmtError();
13712 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13713 OMPLoopBasedDirective::HelperExprs B;
13714 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13715 // define the nested loops number.
13716 unsigned NestedLoopCount =
13717 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13718 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13719 VarsWithImplicitDSA, B);
13720 if (NestedLoopCount == 0)
13721 return StmtError();
13723 assert((CurContext->isDependentContext() || B.builtAll()) &&
13724 "omp for loop exprs were not built");
13726 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13727 // The grainsize clause and num_tasks clause are mutually exclusive and may
13728 // not appear on the same taskloop directive.
13729 if (checkMutuallyExclusiveClauses(*this, Clauses,
13730 {OMPC_grainsize, OMPC_num_tasks}))
13731 return StmtError();
13732 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13733 // If a reduction clause is present on the taskloop directive, the nogroup
13734 // clause must not be specified.
13735 if (checkReductionClauseWithNogroup(*this, Clauses))
13736 return StmtError();
13738 setFunctionHasBranchProtectedScope();
13739 return OMPMaskedTaskLoopDirective::Create(Context, StartLoc, EndLoc,
13740 NestedLoopCount, Clauses, AStmt, B,
13741 DSAStack->isCancelRegion());
13744 StmtResult Sema::ActOnOpenMPMasterTaskLoopSimdDirective(
13745 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13746 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13747 if (!AStmt)
13748 return StmtError();
13750 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13751 OMPLoopBasedDirective::HelperExprs B;
13752 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13753 // define the nested loops number.
13754 unsigned NestedLoopCount =
13755 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13756 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13757 VarsWithImplicitDSA, B);
13758 if (NestedLoopCount == 0)
13759 return StmtError();
13761 assert((CurContext->isDependentContext() || B.builtAll()) &&
13762 "omp for loop exprs were not built");
13764 if (!CurContext->isDependentContext()) {
13765 // Finalize the clauses that need pre-built expressions for CodeGen.
13766 for (OMPClause *C : Clauses) {
13767 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13768 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13769 B.NumIterations, *this, CurScope,
13770 DSAStack))
13771 return StmtError();
13775 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13776 // The grainsize clause and num_tasks clause are mutually exclusive and may
13777 // not appear on the same taskloop directive.
13778 if (checkMutuallyExclusiveClauses(*this, Clauses,
13779 {OMPC_grainsize, OMPC_num_tasks}))
13780 return StmtError();
13781 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13782 // If a reduction clause is present on the taskloop directive, the nogroup
13783 // clause must not be specified.
13784 if (checkReductionClauseWithNogroup(*this, Clauses))
13785 return StmtError();
13786 if (checkSimdlenSafelenSpecified(*this, Clauses))
13787 return StmtError();
13789 setFunctionHasBranchProtectedScope();
13790 return OMPMasterTaskLoopSimdDirective::Create(
13791 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13794 StmtResult Sema::ActOnOpenMPMaskedTaskLoopSimdDirective(
13795 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13796 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13797 if (!AStmt)
13798 return StmtError();
13800 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13801 OMPLoopBasedDirective::HelperExprs B;
13802 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13803 // define the nested loops number.
13804 unsigned NestedLoopCount =
13805 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13806 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13807 VarsWithImplicitDSA, B);
13808 if (NestedLoopCount == 0)
13809 return StmtError();
13811 assert((CurContext->isDependentContext() || B.builtAll()) &&
13812 "omp for loop exprs were not built");
13814 if (!CurContext->isDependentContext()) {
13815 // Finalize the clauses that need pre-built expressions for CodeGen.
13816 for (OMPClause *C : Clauses) {
13817 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13818 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13819 B.NumIterations, *this, CurScope,
13820 DSAStack))
13821 return StmtError();
13825 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13826 // The grainsize clause and num_tasks clause are mutually exclusive and may
13827 // not appear on the same taskloop directive.
13828 if (checkMutuallyExclusiveClauses(*this, Clauses,
13829 {OMPC_grainsize, OMPC_num_tasks}))
13830 return StmtError();
13831 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13832 // If a reduction clause is present on the taskloop directive, the nogroup
13833 // clause must not be specified.
13834 if (checkReductionClauseWithNogroup(*this, Clauses))
13835 return StmtError();
13836 if (checkSimdlenSafelenSpecified(*this, Clauses))
13837 return StmtError();
13839 setFunctionHasBranchProtectedScope();
13840 return OMPMaskedTaskLoopSimdDirective::Create(
13841 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13844 StmtResult Sema::ActOnOpenMPParallelMasterTaskLoopDirective(
13845 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13846 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13847 if (!AStmt)
13848 return StmtError();
13850 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13851 auto *CS = cast<CapturedStmt>(AStmt);
13852 // 1.2.2 OpenMP Language Terminology
13853 // Structured block - An executable statement with a single entry at the
13854 // top and a single exit at the bottom.
13855 // The point of exit cannot be a branch out of the structured block.
13856 // longjmp() and throw() must not violate the entry/exit criteria.
13857 CS->getCapturedDecl()->setNothrow();
13858 for (int ThisCaptureLevel =
13859 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop);
13860 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13861 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13862 // 1.2.2 OpenMP Language Terminology
13863 // Structured block - An executable statement with a single entry at the
13864 // top and a single exit at the bottom.
13865 // The point of exit cannot be a branch out of the structured block.
13866 // longjmp() and throw() must not violate the entry/exit criteria.
13867 CS->getCapturedDecl()->setNothrow();
13870 OMPLoopBasedDirective::HelperExprs B;
13871 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13872 // define the nested loops number.
13873 unsigned NestedLoopCount = checkOpenMPLoop(
13874 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
13875 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
13876 VarsWithImplicitDSA, B);
13877 if (NestedLoopCount == 0)
13878 return StmtError();
13880 assert((CurContext->isDependentContext() || B.builtAll()) &&
13881 "omp for loop exprs were not built");
13883 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13884 // The grainsize clause and num_tasks clause are mutually exclusive and may
13885 // not appear on the same taskloop directive.
13886 if (checkMutuallyExclusiveClauses(*this, Clauses,
13887 {OMPC_grainsize, OMPC_num_tasks}))
13888 return StmtError();
13889 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13890 // If a reduction clause is present on the taskloop directive, the nogroup
13891 // clause must not be specified.
13892 if (checkReductionClauseWithNogroup(*this, Clauses))
13893 return StmtError();
13895 setFunctionHasBranchProtectedScope();
13896 return OMPParallelMasterTaskLoopDirective::Create(
13897 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13898 DSAStack->isCancelRegion());
13901 StmtResult Sema::ActOnOpenMPParallelMaskedTaskLoopDirective(
13902 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13903 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13904 if (!AStmt)
13905 return StmtError();
13907 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13908 auto *CS = cast<CapturedStmt>(AStmt);
13909 // 1.2.2 OpenMP Language Terminology
13910 // Structured block - An executable statement with a single entry at the
13911 // top and a single exit at the bottom.
13912 // The point of exit cannot be a branch out of the structured block.
13913 // longjmp() and throw() must not violate the entry/exit criteria.
13914 CS->getCapturedDecl()->setNothrow();
13915 for (int ThisCaptureLevel =
13916 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop);
13917 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13918 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13919 // 1.2.2 OpenMP Language Terminology
13920 // Structured block - An executable statement with a single entry at the
13921 // top and a single exit at the bottom.
13922 // The point of exit cannot be a branch out of the structured block.
13923 // longjmp() and throw() must not violate the entry/exit criteria.
13924 CS->getCapturedDecl()->setNothrow();
13927 OMPLoopBasedDirective::HelperExprs B;
13928 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13929 // define the nested loops number.
13930 unsigned NestedLoopCount = checkOpenMPLoop(
13931 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
13932 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
13933 VarsWithImplicitDSA, B);
13934 if (NestedLoopCount == 0)
13935 return StmtError();
13937 assert((CurContext->isDependentContext() || B.builtAll()) &&
13938 "omp for loop exprs were not built");
13940 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13941 // The grainsize clause and num_tasks clause are mutually exclusive and may
13942 // not appear on the same taskloop directive.
13943 if (checkMutuallyExclusiveClauses(*this, Clauses,
13944 {OMPC_grainsize, OMPC_num_tasks}))
13945 return StmtError();
13946 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13947 // If a reduction clause is present on the taskloop directive, the nogroup
13948 // clause must not be specified.
13949 if (checkReductionClauseWithNogroup(*this, Clauses))
13950 return StmtError();
13952 setFunctionHasBranchProtectedScope();
13953 return OMPParallelMaskedTaskLoopDirective::Create(
13954 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13955 DSAStack->isCancelRegion());
13958 StmtResult Sema::ActOnOpenMPParallelMasterTaskLoopSimdDirective(
13959 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13960 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13961 if (!AStmt)
13962 return StmtError();
13964 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13965 auto *CS = cast<CapturedStmt>(AStmt);
13966 // 1.2.2 OpenMP Language Terminology
13967 // Structured block - An executable statement with a single entry at the
13968 // top and a single exit at the bottom.
13969 // The point of exit cannot be a branch out of the structured block.
13970 // longjmp() and throw() must not violate the entry/exit criteria.
13971 CS->getCapturedDecl()->setNothrow();
13972 for (int ThisCaptureLevel =
13973 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop_simd);
13974 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13975 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13976 // 1.2.2 OpenMP Language Terminology
13977 // Structured block - An executable statement with a single entry at the
13978 // top and a single exit at the bottom.
13979 // The point of exit cannot be a branch out of the structured block.
13980 // longjmp() and throw() must not violate the entry/exit criteria.
13981 CS->getCapturedDecl()->setNothrow();
13984 OMPLoopBasedDirective::HelperExprs B;
13985 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13986 // define the nested loops number.
13987 unsigned NestedLoopCount = checkOpenMPLoop(
13988 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13989 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
13990 VarsWithImplicitDSA, B);
13991 if (NestedLoopCount == 0)
13992 return StmtError();
13994 assert((CurContext->isDependentContext() || B.builtAll()) &&
13995 "omp for loop exprs were not built");
13997 if (!CurContext->isDependentContext()) {
13998 // Finalize the clauses that need pre-built expressions for CodeGen.
13999 for (OMPClause *C : Clauses) {
14000 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14001 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14002 B.NumIterations, *this, CurScope,
14003 DSAStack))
14004 return StmtError();
14008 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14009 // The grainsize clause and num_tasks clause are mutually exclusive and may
14010 // not appear on the same taskloop directive.
14011 if (checkMutuallyExclusiveClauses(*this, Clauses,
14012 {OMPC_grainsize, OMPC_num_tasks}))
14013 return StmtError();
14014 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14015 // If a reduction clause is present on the taskloop directive, the nogroup
14016 // clause must not be specified.
14017 if (checkReductionClauseWithNogroup(*this, Clauses))
14018 return StmtError();
14019 if (checkSimdlenSafelenSpecified(*this, Clauses))
14020 return StmtError();
14022 setFunctionHasBranchProtectedScope();
14023 return OMPParallelMasterTaskLoopSimdDirective::Create(
14024 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14027 StmtResult Sema::ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
14028 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14029 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14030 if (!AStmt)
14031 return StmtError();
14033 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14034 auto *CS = cast<CapturedStmt>(AStmt);
14035 // 1.2.2 OpenMP Language Terminology
14036 // Structured block - An executable statement with a single entry at the
14037 // top and a single exit at the bottom.
14038 // The point of exit cannot be a branch out of the structured block.
14039 // longjmp() and throw() must not violate the entry/exit criteria.
14040 CS->getCapturedDecl()->setNothrow();
14041 for (int ThisCaptureLevel =
14042 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop_simd);
14043 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14044 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14045 // 1.2.2 OpenMP Language Terminology
14046 // Structured block - An executable statement with a single entry at the
14047 // top and a single exit at the bottom.
14048 // The point of exit cannot be a branch out of the structured block.
14049 // longjmp() and throw() must not violate the entry/exit criteria.
14050 CS->getCapturedDecl()->setNothrow();
14053 OMPLoopBasedDirective::HelperExprs B;
14054 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14055 // define the nested loops number.
14056 unsigned NestedLoopCount = checkOpenMPLoop(
14057 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
14058 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
14059 VarsWithImplicitDSA, B);
14060 if (NestedLoopCount == 0)
14061 return StmtError();
14063 assert((CurContext->isDependentContext() || B.builtAll()) &&
14064 "omp for loop exprs were not built");
14066 if (!CurContext->isDependentContext()) {
14067 // Finalize the clauses that need pre-built expressions for CodeGen.
14068 for (OMPClause *C : Clauses) {
14069 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14070 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14071 B.NumIterations, *this, CurScope,
14072 DSAStack))
14073 return StmtError();
14077 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14078 // The grainsize clause and num_tasks clause are mutually exclusive and may
14079 // not appear on the same taskloop directive.
14080 if (checkMutuallyExclusiveClauses(*this, Clauses,
14081 {OMPC_grainsize, OMPC_num_tasks}))
14082 return StmtError();
14083 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14084 // If a reduction clause is present on the taskloop directive, the nogroup
14085 // clause must not be specified.
14086 if (checkReductionClauseWithNogroup(*this, Clauses))
14087 return StmtError();
14088 if (checkSimdlenSafelenSpecified(*this, Clauses))
14089 return StmtError();
14091 setFunctionHasBranchProtectedScope();
14092 return OMPParallelMaskedTaskLoopSimdDirective::Create(
14093 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14096 StmtResult Sema::ActOnOpenMPDistributeDirective(
14097 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14098 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14099 if (!AStmt)
14100 return StmtError();
14102 if (!checkLastPrivateForMappedDirectives(Clauses))
14103 return StmtError();
14105 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14106 OMPLoopBasedDirective::HelperExprs B;
14107 // In presence of clause 'collapse' with number of loops, it will
14108 // define the nested loops number.
14109 unsigned NestedLoopCount =
14110 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
14111 nullptr /*ordered not a clause on distribute*/, AStmt,
14112 *this, *DSAStack, VarsWithImplicitDSA, B);
14113 if (NestedLoopCount == 0)
14114 return StmtError();
14116 assert((CurContext->isDependentContext() || B.builtAll()) &&
14117 "omp for loop exprs were not built");
14119 setFunctionHasBranchProtectedScope();
14120 auto *DistributeDirective = OMPDistributeDirective::Create(
14121 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14122 DSAStack->getMappedDirective());
14123 return DistributeDirective;
14126 StmtResult Sema::ActOnOpenMPDistributeParallelForDirective(
14127 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14128 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14129 if (!AStmt)
14130 return StmtError();
14132 auto *CS = cast<CapturedStmt>(AStmt);
14133 // 1.2.2 OpenMP Language Terminology
14134 // Structured block - An executable statement with a single entry at the
14135 // top and a single exit at the bottom.
14136 // The point of exit cannot be a branch out of the structured block.
14137 // longjmp() and throw() must not violate the entry/exit criteria.
14138 CS->getCapturedDecl()->setNothrow();
14139 for (int ThisCaptureLevel =
14140 getOpenMPCaptureLevels(OMPD_distribute_parallel_for);
14141 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14142 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14143 // 1.2.2 OpenMP Language Terminology
14144 // Structured block - An executable statement with a single entry at the
14145 // top and a single exit at the bottom.
14146 // The point of exit cannot be a branch out of the structured block.
14147 // longjmp() and throw() must not violate the entry/exit criteria.
14148 CS->getCapturedDecl()->setNothrow();
14151 OMPLoopBasedDirective::HelperExprs B;
14152 // In presence of clause 'collapse' with number of loops, it will
14153 // define the nested loops number.
14154 unsigned NestedLoopCount = checkOpenMPLoop(
14155 OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14156 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14157 VarsWithImplicitDSA, B);
14158 if (NestedLoopCount == 0)
14159 return StmtError();
14161 assert((CurContext->isDependentContext() || B.builtAll()) &&
14162 "omp for loop exprs were not built");
14164 setFunctionHasBranchProtectedScope();
14165 return OMPDistributeParallelForDirective::Create(
14166 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14167 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14170 StmtResult Sema::ActOnOpenMPDistributeParallelForSimdDirective(
14171 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14172 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14173 if (!AStmt)
14174 return StmtError();
14176 auto *CS = cast<CapturedStmt>(AStmt);
14177 // 1.2.2 OpenMP Language Terminology
14178 // Structured block - An executable statement with a single entry at the
14179 // top and a single exit at the bottom.
14180 // The point of exit cannot be a branch out of the structured block.
14181 // longjmp() and throw() must not violate the entry/exit criteria.
14182 CS->getCapturedDecl()->setNothrow();
14183 for (int ThisCaptureLevel =
14184 getOpenMPCaptureLevels(OMPD_distribute_parallel_for_simd);
14185 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14186 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14187 // 1.2.2 OpenMP Language Terminology
14188 // Structured block - An executable statement with a single entry at the
14189 // top and a single exit at the bottom.
14190 // The point of exit cannot be a branch out of the structured block.
14191 // longjmp() and throw() must not violate the entry/exit criteria.
14192 CS->getCapturedDecl()->setNothrow();
14195 OMPLoopBasedDirective::HelperExprs B;
14196 // In presence of clause 'collapse' with number of loops, it will
14197 // define the nested loops number.
14198 unsigned NestedLoopCount = checkOpenMPLoop(
14199 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14200 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14201 VarsWithImplicitDSA, B);
14202 if (NestedLoopCount == 0)
14203 return StmtError();
14205 assert((CurContext->isDependentContext() || B.builtAll()) &&
14206 "omp for loop exprs were not built");
14208 if (!CurContext->isDependentContext()) {
14209 // Finalize the clauses that need pre-built expressions for CodeGen.
14210 for (OMPClause *C : Clauses) {
14211 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14212 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14213 B.NumIterations, *this, CurScope,
14214 DSAStack))
14215 return StmtError();
14219 if (checkSimdlenSafelenSpecified(*this, Clauses))
14220 return StmtError();
14222 setFunctionHasBranchProtectedScope();
14223 return OMPDistributeParallelForSimdDirective::Create(
14224 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14227 StmtResult Sema::ActOnOpenMPDistributeSimdDirective(
14228 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14229 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14230 if (!AStmt)
14231 return StmtError();
14233 auto *CS = cast<CapturedStmt>(AStmt);
14234 // 1.2.2 OpenMP Language Terminology
14235 // Structured block - An executable statement with a single entry at the
14236 // top and a single exit at the bottom.
14237 // The point of exit cannot be a branch out of the structured block.
14238 // longjmp() and throw() must not violate the entry/exit criteria.
14239 CS->getCapturedDecl()->setNothrow();
14240 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_distribute_simd);
14241 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14242 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14243 // 1.2.2 OpenMP Language Terminology
14244 // Structured block - An executable statement with a single entry at the
14245 // top and a single exit at the bottom.
14246 // The point of exit cannot be a branch out of the structured block.
14247 // longjmp() and throw() must not violate the entry/exit criteria.
14248 CS->getCapturedDecl()->setNothrow();
14251 OMPLoopBasedDirective::HelperExprs B;
14252 // In presence of clause 'collapse' with number of loops, it will
14253 // define the nested loops number.
14254 unsigned NestedLoopCount =
14255 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
14256 nullptr /*ordered not a clause on distribute*/, CS, *this,
14257 *DSAStack, VarsWithImplicitDSA, B);
14258 if (NestedLoopCount == 0)
14259 return StmtError();
14261 assert((CurContext->isDependentContext() || B.builtAll()) &&
14262 "omp for loop exprs were not built");
14264 if (!CurContext->isDependentContext()) {
14265 // Finalize the clauses that need pre-built expressions for CodeGen.
14266 for (OMPClause *C : Clauses) {
14267 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14268 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14269 B.NumIterations, *this, CurScope,
14270 DSAStack))
14271 return StmtError();
14275 if (checkSimdlenSafelenSpecified(*this, Clauses))
14276 return StmtError();
14278 setFunctionHasBranchProtectedScope();
14279 return OMPDistributeSimdDirective::Create(Context, StartLoc, EndLoc,
14280 NestedLoopCount, Clauses, AStmt, B);
14283 StmtResult Sema::ActOnOpenMPTargetParallelForSimdDirective(
14284 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14285 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14286 if (!AStmt)
14287 return StmtError();
14289 auto *CS = cast<CapturedStmt>(AStmt);
14290 // 1.2.2 OpenMP Language Terminology
14291 // Structured block - An executable statement with a single entry at the
14292 // top and a single exit at the bottom.
14293 // The point of exit cannot be a branch out of the structured block.
14294 // longjmp() and throw() must not violate the entry/exit criteria.
14295 CS->getCapturedDecl()->setNothrow();
14296 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_for);
14297 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14298 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14299 // 1.2.2 OpenMP Language Terminology
14300 // Structured block - An executable statement with a single entry at the
14301 // top and a single exit at the bottom.
14302 // The point of exit cannot be a branch out of the structured block.
14303 // longjmp() and throw() must not violate the entry/exit criteria.
14304 CS->getCapturedDecl()->setNothrow();
14307 OMPLoopBasedDirective::HelperExprs B;
14308 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14309 // define the nested loops number.
14310 unsigned NestedLoopCount = checkOpenMPLoop(
14311 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
14312 getOrderedNumberExpr(Clauses), CS, *this, *DSAStack, VarsWithImplicitDSA,
14314 if (NestedLoopCount == 0)
14315 return StmtError();
14317 assert((CurContext->isDependentContext() || B.builtAll()) &&
14318 "omp target parallel for simd loop exprs were not built");
14320 if (!CurContext->isDependentContext()) {
14321 // Finalize the clauses that need pre-built expressions for CodeGen.
14322 for (OMPClause *C : Clauses) {
14323 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14324 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14325 B.NumIterations, *this, CurScope,
14326 DSAStack))
14327 return StmtError();
14330 if (checkSimdlenSafelenSpecified(*this, Clauses))
14331 return StmtError();
14333 setFunctionHasBranchProtectedScope();
14334 return OMPTargetParallelForSimdDirective::Create(
14335 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14338 StmtResult Sema::ActOnOpenMPTargetSimdDirective(
14339 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14340 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14341 if (!AStmt)
14342 return StmtError();
14344 auto *CS = cast<CapturedStmt>(AStmt);
14345 // 1.2.2 OpenMP Language Terminology
14346 // Structured block - An executable statement with a single entry at the
14347 // top and a single exit at the bottom.
14348 // The point of exit cannot be a branch out of the structured block.
14349 // longjmp() and throw() must not violate the entry/exit criteria.
14350 CS->getCapturedDecl()->setNothrow();
14351 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_simd);
14352 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14353 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14354 // 1.2.2 OpenMP Language Terminology
14355 // Structured block - An executable statement with a single entry at the
14356 // top and a single exit at the bottom.
14357 // The point of exit cannot be a branch out of the structured block.
14358 // longjmp() and throw() must not violate the entry/exit criteria.
14359 CS->getCapturedDecl()->setNothrow();
14362 OMPLoopBasedDirective::HelperExprs B;
14363 // In presence of clause 'collapse' with number of loops, it will define the
14364 // nested loops number.
14365 unsigned NestedLoopCount =
14366 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
14367 getOrderedNumberExpr(Clauses), CS, *this, *DSAStack,
14368 VarsWithImplicitDSA, B);
14369 if (NestedLoopCount == 0)
14370 return StmtError();
14372 assert((CurContext->isDependentContext() || B.builtAll()) &&
14373 "omp target simd loop exprs were not built");
14375 if (!CurContext->isDependentContext()) {
14376 // Finalize the clauses that need pre-built expressions for CodeGen.
14377 for (OMPClause *C : Clauses) {
14378 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14379 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14380 B.NumIterations, *this, CurScope,
14381 DSAStack))
14382 return StmtError();
14386 if (checkSimdlenSafelenSpecified(*this, Clauses))
14387 return StmtError();
14389 setFunctionHasBranchProtectedScope();
14390 return OMPTargetSimdDirective::Create(Context, StartLoc, EndLoc,
14391 NestedLoopCount, Clauses, AStmt, B);
14394 StmtResult Sema::ActOnOpenMPTeamsDistributeDirective(
14395 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14396 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14397 if (!AStmt)
14398 return StmtError();
14400 auto *CS = cast<CapturedStmt>(AStmt);
14401 // 1.2.2 OpenMP Language Terminology
14402 // Structured block - An executable statement with a single entry at the
14403 // top and a single exit at the bottom.
14404 // The point of exit cannot be a branch out of the structured block.
14405 // longjmp() and throw() must not violate the entry/exit criteria.
14406 CS->getCapturedDecl()->setNothrow();
14407 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_teams_distribute);
14408 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14409 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14410 // 1.2.2 OpenMP Language Terminology
14411 // Structured block - An executable statement with a single entry at the
14412 // top and a single exit at the bottom.
14413 // The point of exit cannot be a branch out of the structured block.
14414 // longjmp() and throw() must not violate the entry/exit criteria.
14415 CS->getCapturedDecl()->setNothrow();
14418 OMPLoopBasedDirective::HelperExprs B;
14419 // In presence of clause 'collapse' with number of loops, it will
14420 // define the nested loops number.
14421 unsigned NestedLoopCount =
14422 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
14423 nullptr /*ordered not a clause on distribute*/, CS, *this,
14424 *DSAStack, VarsWithImplicitDSA, B);
14425 if (NestedLoopCount == 0)
14426 return StmtError();
14428 assert((CurContext->isDependentContext() || B.builtAll()) &&
14429 "omp teams distribute loop exprs were not built");
14431 setFunctionHasBranchProtectedScope();
14433 DSAStack->setParentTeamsRegionLoc(StartLoc);
14435 return OMPTeamsDistributeDirective::Create(
14436 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14439 StmtResult Sema::ActOnOpenMPTeamsDistributeSimdDirective(
14440 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14441 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14442 if (!AStmt)
14443 return StmtError();
14445 auto *CS = cast<CapturedStmt>(AStmt);
14446 // 1.2.2 OpenMP Language Terminology
14447 // Structured block - An executable statement with a single entry at the
14448 // top and a single exit at the bottom.
14449 // The point of exit cannot be a branch out of the structured block.
14450 // longjmp() and throw() must not violate the entry/exit criteria.
14451 CS->getCapturedDecl()->setNothrow();
14452 for (int ThisCaptureLevel =
14453 getOpenMPCaptureLevels(OMPD_teams_distribute_simd);
14454 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14455 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14456 // 1.2.2 OpenMP Language Terminology
14457 // Structured block - An executable statement with a single entry at the
14458 // top and a single exit at the bottom.
14459 // The point of exit cannot be a branch out of the structured block.
14460 // longjmp() and throw() must not violate the entry/exit criteria.
14461 CS->getCapturedDecl()->setNothrow();
14464 OMPLoopBasedDirective::HelperExprs B;
14465 // In presence of clause 'collapse' with number of loops, it will
14466 // define the nested loops number.
14467 unsigned NestedLoopCount = checkOpenMPLoop(
14468 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14469 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14470 VarsWithImplicitDSA, B);
14472 if (NestedLoopCount == 0)
14473 return StmtError();
14475 assert((CurContext->isDependentContext() || B.builtAll()) &&
14476 "omp teams distribute simd loop exprs were not built");
14478 if (!CurContext->isDependentContext()) {
14479 // Finalize the clauses that need pre-built expressions for CodeGen.
14480 for (OMPClause *C : Clauses) {
14481 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14482 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14483 B.NumIterations, *this, CurScope,
14484 DSAStack))
14485 return StmtError();
14489 if (checkSimdlenSafelenSpecified(*this, Clauses))
14490 return StmtError();
14492 setFunctionHasBranchProtectedScope();
14494 DSAStack->setParentTeamsRegionLoc(StartLoc);
14496 return OMPTeamsDistributeSimdDirective::Create(
14497 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14500 StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
14501 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14502 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14503 if (!AStmt)
14504 return StmtError();
14506 auto *CS = cast<CapturedStmt>(AStmt);
14507 // 1.2.2 OpenMP Language Terminology
14508 // Structured block - An executable statement with a single entry at the
14509 // top and a single exit at the bottom.
14510 // The point of exit cannot be a branch out of the structured block.
14511 // longjmp() and throw() must not violate the entry/exit criteria.
14512 CS->getCapturedDecl()->setNothrow();
14514 for (int ThisCaptureLevel =
14515 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for_simd);
14516 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14517 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14518 // 1.2.2 OpenMP Language Terminology
14519 // Structured block - An executable statement with a single entry at the
14520 // top and a single exit at the bottom.
14521 // The point of exit cannot be a branch out of the structured block.
14522 // longjmp() and throw() must not violate the entry/exit criteria.
14523 CS->getCapturedDecl()->setNothrow();
14526 OMPLoopBasedDirective::HelperExprs B;
14527 // In presence of clause 'collapse' with number of loops, it will
14528 // define the nested loops number.
14529 unsigned NestedLoopCount = checkOpenMPLoop(
14530 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14531 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14532 VarsWithImplicitDSA, B);
14534 if (NestedLoopCount == 0)
14535 return StmtError();
14537 assert((CurContext->isDependentContext() || B.builtAll()) &&
14538 "omp for loop exprs were not built");
14540 if (!CurContext->isDependentContext()) {
14541 // Finalize the clauses that need pre-built expressions for CodeGen.
14542 for (OMPClause *C : Clauses) {
14543 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14544 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14545 B.NumIterations, *this, CurScope,
14546 DSAStack))
14547 return StmtError();
14551 if (checkSimdlenSafelenSpecified(*this, Clauses))
14552 return StmtError();
14554 setFunctionHasBranchProtectedScope();
14556 DSAStack->setParentTeamsRegionLoc(StartLoc);
14558 return OMPTeamsDistributeParallelForSimdDirective::Create(
14559 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14562 StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForDirective(
14563 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14564 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14565 if (!AStmt)
14566 return StmtError();
14568 auto *CS = cast<CapturedStmt>(AStmt);
14569 // 1.2.2 OpenMP Language Terminology
14570 // Structured block - An executable statement with a single entry at the
14571 // top and a single exit at the bottom.
14572 // The point of exit cannot be a branch out of the structured block.
14573 // longjmp() and throw() must not violate the entry/exit criteria.
14574 CS->getCapturedDecl()->setNothrow();
14576 for (int ThisCaptureLevel =
14577 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for);
14578 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14579 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14580 // 1.2.2 OpenMP Language Terminology
14581 // Structured block - An executable statement with a single entry at the
14582 // top and a single exit at the bottom.
14583 // The point of exit cannot be a branch out of the structured block.
14584 // longjmp() and throw() must not violate the entry/exit criteria.
14585 CS->getCapturedDecl()->setNothrow();
14588 OMPLoopBasedDirective::HelperExprs B;
14589 // In presence of clause 'collapse' with number of loops, it will
14590 // define the nested loops number.
14591 unsigned NestedLoopCount = checkOpenMPLoop(
14592 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14593 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14594 VarsWithImplicitDSA, B);
14596 if (NestedLoopCount == 0)
14597 return StmtError();
14599 assert((CurContext->isDependentContext() || B.builtAll()) &&
14600 "omp for loop exprs were not built");
14602 setFunctionHasBranchProtectedScope();
14604 DSAStack->setParentTeamsRegionLoc(StartLoc);
14606 return OMPTeamsDistributeParallelForDirective::Create(
14607 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14608 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14611 StmtResult Sema::ActOnOpenMPTargetTeamsDirective(ArrayRef<OMPClause *> Clauses,
14612 Stmt *AStmt,
14613 SourceLocation StartLoc,
14614 SourceLocation EndLoc) {
14615 if (!AStmt)
14616 return StmtError();
14618 auto *CS = cast<CapturedStmt>(AStmt);
14619 // 1.2.2 OpenMP Language Terminology
14620 // Structured block - An executable statement with a single entry at the
14621 // top and a single exit at the bottom.
14622 // The point of exit cannot be a branch out of the structured block.
14623 // longjmp() and throw() must not violate the entry/exit criteria.
14624 CS->getCapturedDecl()->setNothrow();
14626 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_teams);
14627 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14628 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14629 // 1.2.2 OpenMP Language Terminology
14630 // Structured block - An executable statement with a single entry at the
14631 // top and a single exit at the bottom.
14632 // The point of exit cannot be a branch out of the structured block.
14633 // longjmp() and throw() must not violate the entry/exit criteria.
14634 CS->getCapturedDecl()->setNothrow();
14636 setFunctionHasBranchProtectedScope();
14638 return OMPTargetTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses,
14639 AStmt);
14642 StmtResult Sema::ActOnOpenMPTargetTeamsDistributeDirective(
14643 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14644 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14645 if (!AStmt)
14646 return StmtError();
14648 auto *CS = cast<CapturedStmt>(AStmt);
14649 // 1.2.2 OpenMP Language Terminology
14650 // Structured block - An executable statement with a single entry at the
14651 // top and a single exit at the bottom.
14652 // The point of exit cannot be a branch out of the structured block.
14653 // longjmp() and throw() must not violate the entry/exit criteria.
14654 CS->getCapturedDecl()->setNothrow();
14655 for (int ThisCaptureLevel =
14656 getOpenMPCaptureLevels(OMPD_target_teams_distribute);
14657 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14658 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14659 // 1.2.2 OpenMP Language Terminology
14660 // Structured block - An executable statement with a single entry at the
14661 // top and a single exit at the bottom.
14662 // The point of exit cannot be a branch out of the structured block.
14663 // longjmp() and throw() must not violate the entry/exit criteria.
14664 CS->getCapturedDecl()->setNothrow();
14667 OMPLoopBasedDirective::HelperExprs B;
14668 // In presence of clause 'collapse' with number of loops, it will
14669 // define the nested loops number.
14670 unsigned NestedLoopCount = checkOpenMPLoop(
14671 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
14672 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14673 VarsWithImplicitDSA, B);
14674 if (NestedLoopCount == 0)
14675 return StmtError();
14677 assert((CurContext->isDependentContext() || B.builtAll()) &&
14678 "omp target teams distribute loop exprs were not built");
14680 setFunctionHasBranchProtectedScope();
14681 return OMPTargetTeamsDistributeDirective::Create(
14682 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14685 StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForDirective(
14686 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14687 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14688 if (!AStmt)
14689 return StmtError();
14691 auto *CS = cast<CapturedStmt>(AStmt);
14692 // 1.2.2 OpenMP Language Terminology
14693 // Structured block - An executable statement with a single entry at the
14694 // top and a single exit at the bottom.
14695 // The point of exit cannot be a branch out of the structured block.
14696 // longjmp() and throw() must not violate the entry/exit criteria.
14697 CS->getCapturedDecl()->setNothrow();
14698 for (int ThisCaptureLevel =
14699 getOpenMPCaptureLevels(OMPD_target_teams_distribute_parallel_for);
14700 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14701 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14702 // 1.2.2 OpenMP Language Terminology
14703 // Structured block - An executable statement with a single entry at the
14704 // top and a single exit at the bottom.
14705 // The point of exit cannot be a branch out of the structured block.
14706 // longjmp() and throw() must not violate the entry/exit criteria.
14707 CS->getCapturedDecl()->setNothrow();
14710 OMPLoopBasedDirective::HelperExprs B;
14711 // In presence of clause 'collapse' with number of loops, it will
14712 // define the nested loops number.
14713 unsigned NestedLoopCount = checkOpenMPLoop(
14714 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14715 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14716 VarsWithImplicitDSA, B);
14717 if (NestedLoopCount == 0)
14718 return StmtError();
14720 assert((CurContext->isDependentContext() || B.builtAll()) &&
14721 "omp target teams distribute parallel for loop exprs were not built");
14723 if (!CurContext->isDependentContext()) {
14724 // Finalize the clauses that need pre-built expressions for CodeGen.
14725 for (OMPClause *C : Clauses) {
14726 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14727 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14728 B.NumIterations, *this, CurScope,
14729 DSAStack))
14730 return StmtError();
14734 setFunctionHasBranchProtectedScope();
14735 return OMPTargetTeamsDistributeParallelForDirective::Create(
14736 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14737 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14740 StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
14741 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14742 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14743 if (!AStmt)
14744 return StmtError();
14746 auto *CS = cast<CapturedStmt>(AStmt);
14747 // 1.2.2 OpenMP Language Terminology
14748 // Structured block - An executable statement with a single entry at the
14749 // top and a single exit at the bottom.
14750 // The point of exit cannot be a branch out of the structured block.
14751 // longjmp() and throw() must not violate the entry/exit criteria.
14752 CS->getCapturedDecl()->setNothrow();
14753 for (int ThisCaptureLevel = getOpenMPCaptureLevels(
14754 OMPD_target_teams_distribute_parallel_for_simd);
14755 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14756 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14757 // 1.2.2 OpenMP Language Terminology
14758 // Structured block - An executable statement with a single entry at the
14759 // top and a single exit at the bottom.
14760 // The point of exit cannot be a branch out of the structured block.
14761 // longjmp() and throw() must not violate the entry/exit criteria.
14762 CS->getCapturedDecl()->setNothrow();
14765 OMPLoopBasedDirective::HelperExprs B;
14766 // In presence of clause 'collapse' with number of loops, it will
14767 // define the nested loops number.
14768 unsigned NestedLoopCount =
14769 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
14770 getCollapseNumberExpr(Clauses),
14771 nullptr /*ordered not a clause on distribute*/, CS, *this,
14772 *DSAStack, VarsWithImplicitDSA, B);
14773 if (NestedLoopCount == 0)
14774 return StmtError();
14776 assert((CurContext->isDependentContext() || B.builtAll()) &&
14777 "omp target teams distribute parallel for simd loop exprs were not "
14778 "built");
14780 if (!CurContext->isDependentContext()) {
14781 // Finalize the clauses that need pre-built expressions for CodeGen.
14782 for (OMPClause *C : Clauses) {
14783 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14784 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14785 B.NumIterations, *this, CurScope,
14786 DSAStack))
14787 return StmtError();
14791 if (checkSimdlenSafelenSpecified(*this, Clauses))
14792 return StmtError();
14794 setFunctionHasBranchProtectedScope();
14795 return OMPTargetTeamsDistributeParallelForSimdDirective::Create(
14796 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14799 StmtResult Sema::ActOnOpenMPTargetTeamsDistributeSimdDirective(
14800 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14801 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14802 if (!AStmt)
14803 return StmtError();
14805 auto *CS = cast<CapturedStmt>(AStmt);
14806 // 1.2.2 OpenMP Language Terminology
14807 // Structured block - An executable statement with a single entry at the
14808 // top and a single exit at the bottom.
14809 // The point of exit cannot be a branch out of the structured block.
14810 // longjmp() and throw() must not violate the entry/exit criteria.
14811 CS->getCapturedDecl()->setNothrow();
14812 for (int ThisCaptureLevel =
14813 getOpenMPCaptureLevels(OMPD_target_teams_distribute_simd);
14814 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14815 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14816 // 1.2.2 OpenMP Language Terminology
14817 // Structured block - An executable statement with a single entry at the
14818 // top and a single exit at the bottom.
14819 // The point of exit cannot be a branch out of the structured block.
14820 // longjmp() and throw() must not violate the entry/exit criteria.
14821 CS->getCapturedDecl()->setNothrow();
14824 OMPLoopBasedDirective::HelperExprs B;
14825 // In presence of clause 'collapse' with number of loops, it will
14826 // define the nested loops number.
14827 unsigned NestedLoopCount = checkOpenMPLoop(
14828 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14829 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14830 VarsWithImplicitDSA, B);
14831 if (NestedLoopCount == 0)
14832 return StmtError();
14834 assert((CurContext->isDependentContext() || B.builtAll()) &&
14835 "omp target teams distribute simd loop exprs were not built");
14837 if (!CurContext->isDependentContext()) {
14838 // Finalize the clauses that need pre-built expressions for CodeGen.
14839 for (OMPClause *C : Clauses) {
14840 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14841 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14842 B.NumIterations, *this, CurScope,
14843 DSAStack))
14844 return StmtError();
14848 if (checkSimdlenSafelenSpecified(*this, Clauses))
14849 return StmtError();
14851 setFunctionHasBranchProtectedScope();
14852 return OMPTargetTeamsDistributeSimdDirective::Create(
14853 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14856 bool Sema::checkTransformableLoopNest(
14857 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14858 SmallVectorImpl<OMPLoopBasedDirective::HelperExprs> &LoopHelpers,
14859 Stmt *&Body,
14860 SmallVectorImpl<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>>
14861 &OriginalInits) {
14862 OriginalInits.emplace_back();
14863 bool Result = OMPLoopBasedDirective::doForAllLoops(
14864 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14865 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14866 Stmt *CurStmt) {
14867 VarsWithInheritedDSAType TmpDSA;
14868 unsigned SingleNumLoops =
14869 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, *this, *DSAStack,
14870 TmpDSA, LoopHelpers[Cnt]);
14871 if (SingleNumLoops == 0)
14872 return true;
14873 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14874 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14875 OriginalInits.back().push_back(For->getInit());
14876 Body = For->getBody();
14877 } else {
14878 assert(isa<CXXForRangeStmt>(CurStmt) &&
14879 "Expected canonical for or range-based for loops.");
14880 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14881 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14882 Body = CXXFor->getBody();
14884 OriginalInits.emplace_back();
14885 return false;
14887 [&OriginalInits](OMPLoopBasedDirective *Transform) {
14888 Stmt *DependentPreInits;
14889 if (auto *Dir = dyn_cast<OMPTileDirective>(Transform))
14890 DependentPreInits = Dir->getPreInits();
14891 else if (auto *Dir = dyn_cast<OMPUnrollDirective>(Transform))
14892 DependentPreInits = Dir->getPreInits();
14893 else
14894 llvm_unreachable("Unhandled loop transformation");
14895 if (!DependentPreInits)
14896 return;
14897 llvm::append_range(OriginalInits.back(),
14898 cast<DeclStmt>(DependentPreInits)->getDeclGroup());
14900 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14901 OriginalInits.pop_back();
14902 return Result;
14905 StmtResult Sema::ActOnOpenMPTileDirective(ArrayRef<OMPClause *> Clauses,
14906 Stmt *AStmt, SourceLocation StartLoc,
14907 SourceLocation EndLoc) {
14908 auto SizesClauses =
14909 OMPExecutableDirective::getClausesOfKind<OMPSizesClause>(Clauses);
14910 if (SizesClauses.empty()) {
14911 // A missing 'sizes' clause is already reported by the parser.
14912 return StmtError();
14914 const OMPSizesClause *SizesClause = *SizesClauses.begin();
14915 unsigned NumLoops = SizesClause->getNumSizes();
14917 // Empty statement should only be possible if there already was an error.
14918 if (!AStmt)
14919 return StmtError();
14921 // Verify and diagnose loop nest.
14922 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
14923 Stmt *Body = nullptr;
14924 SmallVector<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>, 4>
14925 OriginalInits;
14926 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14927 OriginalInits))
14928 return StmtError();
14930 // Delay tiling to when template is completely instantiated.
14931 if (CurContext->isDependentContext())
14932 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
14933 NumLoops, AStmt, nullptr, nullptr);
14935 SmallVector<Decl *, 4> PreInits;
14937 // Create iteration variables for the generated loops.
14938 SmallVector<VarDecl *, 4> FloorIndVars;
14939 SmallVector<VarDecl *, 4> TileIndVars;
14940 FloorIndVars.resize(NumLoops);
14941 TileIndVars.resize(NumLoops);
14942 for (unsigned I = 0; I < NumLoops; ++I) {
14943 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14945 assert(LoopHelper.Counters.size() == 1 &&
14946 "Expect single-dimensional loop iteration space");
14947 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14948 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14949 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14950 QualType CntTy = IterVarRef->getType();
14952 // Iteration variable for the floor (i.e. outer) loop.
14954 std::string FloorCntName =
14955 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14956 VarDecl *FloorCntDecl =
14957 buildVarDecl(*this, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
14958 FloorIndVars[I] = FloorCntDecl;
14961 // Iteration variable for the tile (i.e. inner) loop.
14963 std::string TileCntName =
14964 (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14966 // Reuse the iteration variable created by checkOpenMPLoop. It is also
14967 // used by the expressions to derive the original iteration variable's
14968 // value from the logical iteration number.
14969 auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
14970 TileCntDecl->setDeclName(&PP.getIdentifierTable().get(TileCntName));
14971 TileIndVars[I] = TileCntDecl;
14973 for (auto &P : OriginalInits[I]) {
14974 if (auto *D = P.dyn_cast<Decl *>())
14975 PreInits.push_back(D);
14976 else if (auto *PI = dyn_cast_or_null<DeclStmt>(P.dyn_cast<Stmt *>()))
14977 PreInits.append(PI->decl_begin(), PI->decl_end());
14979 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits))
14980 PreInits.append(PI->decl_begin(), PI->decl_end());
14981 // Gather declarations for the data members used as counters.
14982 for (Expr *CounterRef : LoopHelper.Counters) {
14983 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14984 if (isa<OMPCapturedExprDecl>(CounterDecl))
14985 PreInits.push_back(CounterDecl);
14989 // Once the original iteration values are set, append the innermost body.
14990 Stmt *Inner = Body;
14992 // Create tile loops from the inside to the outside.
14993 for (int I = NumLoops - 1; I >= 0; --I) {
14994 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14995 Expr *NumIterations = LoopHelper.NumIterations;
14996 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14997 QualType CntTy = OrigCntVar->getType();
14998 Expr *DimTileSize = SizesClause->getSizesRefs()[I];
14999 Scope *CurScope = getCurScope();
15001 // Commonly used variables.
15002 DeclRefExpr *TileIV = buildDeclRefExpr(*this, TileIndVars[I], CntTy,
15003 OrigCntVar->getExprLoc());
15004 DeclRefExpr *FloorIV = buildDeclRefExpr(*this, FloorIndVars[I], CntTy,
15005 OrigCntVar->getExprLoc());
15007 // For init-statement: auto .tile.iv = .floor.iv
15008 AddInitializerToDecl(TileIndVars[I], DefaultLvalueConversion(FloorIV).get(),
15009 /*DirectInit=*/false);
15010 Decl *CounterDecl = TileIndVars[I];
15011 StmtResult InitStmt = new (Context)
15012 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15013 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15014 if (!InitStmt.isUsable())
15015 return StmtError();
15017 // For cond-expression: .tile.iv < min(.floor.iv + DimTileSize,
15018 // NumIterations)
15019 ExprResult EndOfTile = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
15020 BO_Add, FloorIV, DimTileSize);
15021 if (!EndOfTile.isUsable())
15022 return StmtError();
15023 ExprResult IsPartialTile =
15024 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15025 NumIterations, EndOfTile.get());
15026 if (!IsPartialTile.isUsable())
15027 return StmtError();
15028 ExprResult MinTileAndIterSpace = ActOnConditionalOp(
15029 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
15030 IsPartialTile.get(), NumIterations, EndOfTile.get());
15031 if (!MinTileAndIterSpace.isUsable())
15032 return StmtError();
15033 ExprResult CondExpr = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
15034 BO_LT, TileIV, MinTileAndIterSpace.get());
15035 if (!CondExpr.isUsable())
15036 return StmtError();
15038 // For incr-statement: ++.tile.iv
15039 ExprResult IncrStmt =
15040 BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, TileIV);
15041 if (!IncrStmt.isUsable())
15042 return StmtError();
15044 // Statements to set the original iteration variable's value from the
15045 // logical iteration number.
15046 // Generated for loop is:
15047 // Original_for_init;
15048 // for (auto .tile.iv = .floor.iv; .tile.iv < min(.floor.iv + DimTileSize,
15049 // NumIterations); ++.tile.iv) {
15050 // Original_Body;
15051 // Original_counter_update;
15052 // }
15053 // FIXME: If the innermost body is an loop itself, inserting these
15054 // statements stops it being recognized as a perfectly nested loop (e.g.
15055 // for applying tiling again). If this is the case, sink the expressions
15056 // further into the inner loop.
15057 SmallVector<Stmt *, 4> BodyParts;
15058 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15059 BodyParts.push_back(Inner);
15060 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15061 Inner->getBeginLoc(), Inner->getEndLoc());
15062 Inner = new (Context)
15063 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15064 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15065 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15068 // Create floor loops from the inside to the outside.
15069 for (int I = NumLoops - 1; I >= 0; --I) {
15070 auto &LoopHelper = LoopHelpers[I];
15071 Expr *NumIterations = LoopHelper.NumIterations;
15072 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15073 QualType CntTy = OrigCntVar->getType();
15074 Expr *DimTileSize = SizesClause->getSizesRefs()[I];
15075 Scope *CurScope = getCurScope();
15077 // Commonly used variables.
15078 DeclRefExpr *FloorIV = buildDeclRefExpr(*this, FloorIndVars[I], CntTy,
15079 OrigCntVar->getExprLoc());
15081 // For init-statement: auto .floor.iv = 0
15082 AddInitializerToDecl(
15083 FloorIndVars[I],
15084 ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15085 /*DirectInit=*/false);
15086 Decl *CounterDecl = FloorIndVars[I];
15087 StmtResult InitStmt = new (Context)
15088 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15089 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15090 if (!InitStmt.isUsable())
15091 return StmtError();
15093 // For cond-expression: .floor.iv < NumIterations
15094 ExprResult CondExpr = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
15095 BO_LT, FloorIV, NumIterations);
15096 if (!CondExpr.isUsable())
15097 return StmtError();
15099 // For incr-statement: .floor.iv += DimTileSize
15100 ExprResult IncrStmt = BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(),
15101 BO_AddAssign, FloorIV, DimTileSize);
15102 if (!IncrStmt.isUsable())
15103 return StmtError();
15105 Inner = new (Context)
15106 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15107 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15108 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15111 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
15112 AStmt, Inner,
15113 buildPreInits(Context, PreInits));
15116 StmtResult Sema::ActOnOpenMPUnrollDirective(ArrayRef<OMPClause *> Clauses,
15117 Stmt *AStmt,
15118 SourceLocation StartLoc,
15119 SourceLocation EndLoc) {
15120 // Empty statement should only be possible if there already was an error.
15121 if (!AStmt)
15122 return StmtError();
15124 if (checkMutuallyExclusiveClauses(*this, Clauses, {OMPC_partial, OMPC_full}))
15125 return StmtError();
15127 const OMPFullClause *FullClause =
15128 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
15129 const OMPPartialClause *PartialClause =
15130 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
15131 assert(!(FullClause && PartialClause) &&
15132 "mutual exclusivity must have been checked before");
15134 constexpr unsigned NumLoops = 1;
15135 Stmt *Body = nullptr;
15136 SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
15137 NumLoops);
15138 SmallVector<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>, NumLoops + 1>
15139 OriginalInits;
15140 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
15141 Body, OriginalInits))
15142 return StmtError();
15144 unsigned NumGeneratedLoops = PartialClause ? 1 : 0;
15146 // Delay unrolling to when template is completely instantiated.
15147 if (CurContext->isDependentContext())
15148 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15149 NumGeneratedLoops, nullptr, nullptr);
15151 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15153 if (FullClause) {
15154 if (!VerifyPositiveIntegerConstantInClause(
15155 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
15156 /*SuppressExprDiags=*/true)
15157 .isUsable()) {
15158 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
15159 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
15160 << "#pragma omp unroll full";
15161 return StmtError();
15165 // The generated loop may only be passed to other loop-associated directive
15166 // when a partial clause is specified. Without the requirement it is
15167 // sufficient to generate loop unroll metadata at code-generation.
15168 if (NumGeneratedLoops == 0)
15169 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15170 NumGeneratedLoops, nullptr, nullptr);
15172 // Otherwise, we need to provide a de-sugared/transformed AST that can be
15173 // associated with another loop directive.
15175 // The canonical loop analysis return by checkTransformableLoopNest assumes
15176 // the following structure to be the same loop without transformations or
15177 // directives applied: \code OriginalInits; LoopHelper.PreInits;
15178 // LoopHelper.Counters;
15179 // for (; IV < LoopHelper.NumIterations; ++IV) {
15180 // LoopHelper.Updates;
15181 // Body;
15182 // }
15183 // \endcode
15184 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
15185 // and referenced by LoopHelper.IterationVarRef.
15187 // The unrolling directive transforms this into the following loop:
15188 // \code
15189 // OriginalInits; \
15190 // LoopHelper.PreInits; > NewPreInits
15191 // LoopHelper.Counters; /
15192 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
15193 // #pragma clang loop unroll_count(Factor)
15194 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
15195 // {
15196 // LoopHelper.Updates;
15197 // Body;
15198 // }
15199 // }
15200 // \endcode
15201 // where UIV is a new logical iteration counter. IV must be the same VarDecl
15202 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
15203 // references it. If the partially unrolled loop is associated with another
15204 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
15205 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
15206 // OpenMP canonical loop. The inner loop is not an associable canonical loop
15207 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
15208 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
15209 // property of the OMPLoopBasedDirective instead of statements in
15210 // CompoundStatement. This is to allow the loop to become a non-outermost loop
15211 // of a canonical loop nest where these PreInits are emitted before the
15212 // outermost directive.
15214 // Determine the PreInit declarations.
15215 SmallVector<Decl *, 4> PreInits;
15216 assert(OriginalInits.size() == 1 &&
15217 "Expecting a single-dimensional loop iteration space");
15218 for (auto &P : OriginalInits[0]) {
15219 if (auto *D = P.dyn_cast<Decl *>())
15220 PreInits.push_back(D);
15221 else if (auto *PI = dyn_cast_or_null<DeclStmt>(P.dyn_cast<Stmt *>()))
15222 PreInits.append(PI->decl_begin(), PI->decl_end());
15224 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits))
15225 PreInits.append(PI->decl_begin(), PI->decl_end());
15226 // Gather declarations for the data members used as counters.
15227 for (Expr *CounterRef : LoopHelper.Counters) {
15228 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
15229 if (isa<OMPCapturedExprDecl>(CounterDecl))
15230 PreInits.push_back(CounterDecl);
15233 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15234 QualType IVTy = IterationVarRef->getType();
15235 assert(LoopHelper.Counters.size() == 1 &&
15236 "Expecting a single-dimensional loop iteration space");
15237 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15239 // Determine the unroll factor.
15240 uint64_t Factor;
15241 SourceLocation FactorLoc;
15242 if (Expr *FactorVal = PartialClause->getFactor()) {
15243 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
15244 FactorLoc = FactorVal->getExprLoc();
15245 } else {
15246 // TODO: Use a better profitability model.
15247 Factor = 2;
15249 assert(Factor > 0 && "Expected positive unroll factor");
15250 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
15251 return IntegerLiteral::Create(
15252 Context, llvm::APInt(Context.getIntWidth(IVTy), Factor), IVTy,
15253 FactorLoc);
15256 // Iteration variable SourceLocations.
15257 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15258 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15259 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15261 // Internal variable names.
15262 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15263 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
15264 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
15265 std::string InnerTripCountName =
15266 (Twine(".unroll_inner.tripcount.") + OrigVarName).str();
15268 // Create the iteration variable for the unrolled loop.
15269 VarDecl *OuterIVDecl =
15270 buildVarDecl(*this, {}, IVTy, OuterIVName, nullptr, OrigVar);
15271 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
15272 return buildDeclRefExpr(*this, OuterIVDecl, IVTy, OrigVarLoc);
15275 // Iteration variable for the inner loop: Reuse the iteration variable created
15276 // by checkOpenMPLoop.
15277 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15278 InnerIVDecl->setDeclName(&PP.getIdentifierTable().get(InnerIVName));
15279 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
15280 return buildDeclRefExpr(*this, InnerIVDecl, IVTy, OrigVarLoc);
15283 // Make a copy of the NumIterations expression for each use: By the AST
15284 // constraints, every expression object in a DeclContext must be unique.
15285 CaptureVars CopyTransformer(*this);
15286 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15287 return AssertSuccess(
15288 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15291 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
15292 ExprResult LValueConv = DefaultLvalueConversion(MakeOuterRef());
15293 AddInitializerToDecl(InnerIVDecl, LValueConv.get(), /*DirectInit=*/false);
15294 StmtResult InnerInit = new (Context)
15295 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15296 if (!InnerInit.isUsable())
15297 return StmtError();
15299 // Inner For cond-expression:
15300 // \code
15301 // .unroll_inner.iv < .unrolled.iv + Factor &&
15302 // .unroll_inner.iv < NumIterations
15303 // \endcode
15304 // This conjunction of two conditions allows ScalarEvolution to derive the
15305 // maximum trip count of the inner loop.
15306 ExprResult EndOfTile = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
15307 BO_Add, MakeOuterRef(), MakeFactorExpr());
15308 if (!EndOfTile.isUsable())
15309 return StmtError();
15310 ExprResult InnerCond1 = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
15311 BO_LT, MakeInnerRef(), EndOfTile.get());
15312 if (!InnerCond1.isUsable())
15313 return StmtError();
15314 ExprResult InnerCond2 =
15315 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, MakeInnerRef(),
15316 MakeNumIterations());
15317 if (!InnerCond2.isUsable())
15318 return StmtError();
15319 ExprResult InnerCond =
15320 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
15321 InnerCond1.get(), InnerCond2.get());
15322 if (!InnerCond.isUsable())
15323 return StmtError();
15325 // Inner For incr-statement: ++.unroll_inner.iv
15326 ExprResult InnerIncr = BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(),
15327 UO_PreInc, MakeInnerRef());
15328 if (!InnerIncr.isUsable())
15329 return StmtError();
15331 // Inner For statement.
15332 SmallVector<Stmt *> InnerBodyStmts;
15333 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15334 InnerBodyStmts.push_back(Body);
15335 CompoundStmt *InnerBody =
15336 CompoundStmt::Create(Context, InnerBodyStmts, FPOptionsOverride(),
15337 Body->getBeginLoc(), Body->getEndLoc());
15338 ForStmt *InnerFor = new (Context)
15339 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
15340 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
15341 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15343 // Unroll metadata for the inner loop.
15344 // This needs to take into account the remainder portion of the unrolled loop,
15345 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
15346 // supports multiple loop exits. Instead, unroll using a factor equivalent to
15347 // the maximum trip count, which will also generate a remainder loop. Just
15348 // `unroll(enable)` (which could have been useful if the user has not
15349 // specified a concrete factor; even though the outer loop cannot be
15350 // influenced anymore, would avoid more code bloat than necessary) will refuse
15351 // the loop because "Won't unroll; remainder loop could not be generated when
15352 // assuming runtime trip count". Even if it did work, it must not choose a
15353 // larger unroll factor than the maximum loop length, or it would always just
15354 // execute the remainder loop.
15355 LoopHintAttr *UnrollHintAttr =
15356 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
15357 LoopHintAttr::Numeric, MakeFactorExpr());
15358 AttributedStmt *InnerUnrolled =
15359 AttributedStmt::Create(Context, StartLoc, {UnrollHintAttr}, InnerFor);
15361 // Outer For init-statement: auto .unrolled.iv = 0
15362 AddInitializerToDecl(
15363 OuterIVDecl, ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15364 /*DirectInit=*/false);
15365 StmtResult OuterInit = new (Context)
15366 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15367 if (!OuterInit.isUsable())
15368 return StmtError();
15370 // Outer For cond-expression: .unrolled.iv < NumIterations
15371 ExprResult OuterConde =
15372 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, MakeOuterRef(),
15373 MakeNumIterations());
15374 if (!OuterConde.isUsable())
15375 return StmtError();
15377 // Outer For incr-statement: .unrolled.iv += Factor
15378 ExprResult OuterIncr =
15379 BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15380 MakeOuterRef(), MakeFactorExpr());
15381 if (!OuterIncr.isUsable())
15382 return StmtError();
15384 // Outer For statement.
15385 ForStmt *OuterFor = new (Context)
15386 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
15387 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
15388 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15390 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15391 NumGeneratedLoops, OuterFor,
15392 buildPreInits(Context, PreInits));
15395 OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
15396 SourceLocation StartLoc,
15397 SourceLocation LParenLoc,
15398 SourceLocation EndLoc) {
15399 OMPClause *Res = nullptr;
15400 switch (Kind) {
15401 case OMPC_final:
15402 Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
15403 break;
15404 case OMPC_num_threads:
15405 Res = ActOnOpenMPNumThreadsClause(Expr, StartLoc, LParenLoc, EndLoc);
15406 break;
15407 case OMPC_safelen:
15408 Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
15409 break;
15410 case OMPC_simdlen:
15411 Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
15412 break;
15413 case OMPC_allocator:
15414 Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
15415 break;
15416 case OMPC_collapse:
15417 Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
15418 break;
15419 case OMPC_ordered:
15420 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
15421 break;
15422 case OMPC_num_teams:
15423 Res = ActOnOpenMPNumTeamsClause(Expr, StartLoc, LParenLoc, EndLoc);
15424 break;
15425 case OMPC_thread_limit:
15426 Res = ActOnOpenMPThreadLimitClause(Expr, StartLoc, LParenLoc, EndLoc);
15427 break;
15428 case OMPC_priority:
15429 Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
15430 break;
15431 case OMPC_hint:
15432 Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
15433 break;
15434 case OMPC_depobj:
15435 Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
15436 break;
15437 case OMPC_detach:
15438 Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
15439 break;
15440 case OMPC_novariants:
15441 Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
15442 break;
15443 case OMPC_nocontext:
15444 Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
15445 break;
15446 case OMPC_filter:
15447 Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
15448 break;
15449 case OMPC_partial:
15450 Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
15451 break;
15452 case OMPC_message:
15453 Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc);
15454 break;
15455 case OMPC_align:
15456 Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
15457 break;
15458 case OMPC_ompx_dyn_cgroup_mem:
15459 Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc);
15460 break;
15461 case OMPC_grainsize:
15462 case OMPC_num_tasks:
15463 case OMPC_device:
15464 case OMPC_if:
15465 case OMPC_default:
15466 case OMPC_proc_bind:
15467 case OMPC_schedule:
15468 case OMPC_private:
15469 case OMPC_firstprivate:
15470 case OMPC_lastprivate:
15471 case OMPC_shared:
15472 case OMPC_reduction:
15473 case OMPC_task_reduction:
15474 case OMPC_in_reduction:
15475 case OMPC_linear:
15476 case OMPC_aligned:
15477 case OMPC_copyin:
15478 case OMPC_copyprivate:
15479 case OMPC_nowait:
15480 case OMPC_untied:
15481 case OMPC_mergeable:
15482 case OMPC_threadprivate:
15483 case OMPC_sizes:
15484 case OMPC_allocate:
15485 case OMPC_flush:
15486 case OMPC_read:
15487 case OMPC_write:
15488 case OMPC_update:
15489 case OMPC_capture:
15490 case OMPC_compare:
15491 case OMPC_seq_cst:
15492 case OMPC_acq_rel:
15493 case OMPC_acquire:
15494 case OMPC_release:
15495 case OMPC_relaxed:
15496 case OMPC_depend:
15497 case OMPC_threads:
15498 case OMPC_simd:
15499 case OMPC_map:
15500 case OMPC_nogroup:
15501 case OMPC_dist_schedule:
15502 case OMPC_defaultmap:
15503 case OMPC_unknown:
15504 case OMPC_uniform:
15505 case OMPC_to:
15506 case OMPC_from:
15507 case OMPC_use_device_ptr:
15508 case OMPC_use_device_addr:
15509 case OMPC_is_device_ptr:
15510 case OMPC_unified_address:
15511 case OMPC_unified_shared_memory:
15512 case OMPC_reverse_offload:
15513 case OMPC_dynamic_allocators:
15514 case OMPC_atomic_default_mem_order:
15515 case OMPC_device_type:
15516 case OMPC_match:
15517 case OMPC_nontemporal:
15518 case OMPC_order:
15519 case OMPC_at:
15520 case OMPC_severity:
15521 case OMPC_destroy:
15522 case OMPC_inclusive:
15523 case OMPC_exclusive:
15524 case OMPC_uses_allocators:
15525 case OMPC_affinity:
15526 case OMPC_when:
15527 case OMPC_bind:
15528 default:
15529 llvm_unreachable("Clause is not allowed.");
15531 return Res;
15534 // An OpenMP directive such as 'target parallel' has two captured regions:
15535 // for the 'target' and 'parallel' respectively. This function returns
15536 // the region in which to capture expressions associated with a clause.
15537 // A return value of OMPD_unknown signifies that the expression should not
15538 // be captured.
15539 static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
15540 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
15541 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
15542 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15543 switch (CKind) {
15544 case OMPC_if:
15545 switch (DKind) {
15546 case OMPD_target_parallel_for_simd:
15547 if (OpenMPVersion >= 50 &&
15548 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15549 CaptureRegion = OMPD_parallel;
15550 break;
15552 [[fallthrough]];
15553 case OMPD_target_parallel:
15554 case OMPD_target_parallel_for:
15555 case OMPD_target_parallel_loop:
15556 // If this clause applies to the nested 'parallel' region, capture within
15557 // the 'target' region, otherwise do not capture.
15558 if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel)
15559 CaptureRegion = OMPD_target;
15560 break;
15561 case OMPD_target_teams_distribute_parallel_for_simd:
15562 if (OpenMPVersion >= 50 &&
15563 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15564 CaptureRegion = OMPD_parallel;
15565 break;
15567 [[fallthrough]];
15568 case OMPD_target_teams_loop:
15569 case OMPD_target_teams_distribute_parallel_for:
15570 // If this clause applies to the nested 'parallel' region, capture within
15571 // the 'teams' region, otherwise do not capture.
15572 if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel)
15573 CaptureRegion = OMPD_teams;
15574 break;
15575 case OMPD_teams_distribute_parallel_for_simd:
15576 if (OpenMPVersion >= 50 &&
15577 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15578 CaptureRegion = OMPD_parallel;
15579 break;
15581 [[fallthrough]];
15582 case OMPD_teams_distribute_parallel_for:
15583 CaptureRegion = OMPD_teams;
15584 break;
15585 case OMPD_target_update:
15586 case OMPD_target_enter_data:
15587 case OMPD_target_exit_data:
15588 CaptureRegion = OMPD_task;
15589 break;
15590 case OMPD_parallel_masked_taskloop:
15591 if (NameModifier == OMPD_unknown || NameModifier == OMPD_taskloop)
15592 CaptureRegion = OMPD_parallel;
15593 break;
15594 case OMPD_parallel_master_taskloop:
15595 if (NameModifier == OMPD_unknown || NameModifier == OMPD_taskloop)
15596 CaptureRegion = OMPD_parallel;
15597 break;
15598 case OMPD_parallel_masked_taskloop_simd:
15599 if ((OpenMPVersion <= 45 && NameModifier == OMPD_unknown) ||
15600 NameModifier == OMPD_taskloop) {
15601 CaptureRegion = OMPD_parallel;
15602 break;
15604 if (OpenMPVersion <= 45)
15605 break;
15606 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15607 CaptureRegion = OMPD_taskloop;
15608 break;
15609 case OMPD_parallel_master_taskloop_simd:
15610 if ((OpenMPVersion <= 45 && NameModifier == OMPD_unknown) ||
15611 NameModifier == OMPD_taskloop) {
15612 CaptureRegion = OMPD_parallel;
15613 break;
15615 if (OpenMPVersion <= 45)
15616 break;
15617 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15618 CaptureRegion = OMPD_taskloop;
15619 break;
15620 case OMPD_parallel_for_simd:
15621 if (OpenMPVersion <= 45)
15622 break;
15623 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15624 CaptureRegion = OMPD_parallel;
15625 break;
15626 case OMPD_taskloop_simd:
15627 case OMPD_master_taskloop_simd:
15628 case OMPD_masked_taskloop_simd:
15629 if (OpenMPVersion <= 45)
15630 break;
15631 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15632 CaptureRegion = OMPD_taskloop;
15633 break;
15634 case OMPD_distribute_parallel_for_simd:
15635 if (OpenMPVersion <= 45)
15636 break;
15637 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15638 CaptureRegion = OMPD_parallel;
15639 break;
15640 case OMPD_target_simd:
15641 if (OpenMPVersion >= 50 &&
15642 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd))
15643 CaptureRegion = OMPD_target;
15644 break;
15645 case OMPD_teams_distribute_simd:
15646 case OMPD_target_teams_distribute_simd:
15647 if (OpenMPVersion >= 50 &&
15648 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd))
15649 CaptureRegion = OMPD_teams;
15650 break;
15651 case OMPD_cancel:
15652 case OMPD_parallel:
15653 case OMPD_parallel_master:
15654 case OMPD_parallel_masked:
15655 case OMPD_parallel_sections:
15656 case OMPD_parallel_for:
15657 case OMPD_parallel_loop:
15658 case OMPD_target:
15659 case OMPD_target_teams:
15660 case OMPD_target_teams_distribute:
15661 case OMPD_distribute_parallel_for:
15662 case OMPD_task:
15663 case OMPD_taskloop:
15664 case OMPD_master_taskloop:
15665 case OMPD_masked_taskloop:
15666 case OMPD_target_data:
15667 case OMPD_simd:
15668 case OMPD_for_simd:
15669 case OMPD_distribute_simd:
15670 // Do not capture if-clause expressions.
15671 break;
15672 case OMPD_threadprivate:
15673 case OMPD_allocate:
15674 case OMPD_taskyield:
15675 case OMPD_error:
15676 case OMPD_barrier:
15677 case OMPD_taskwait:
15678 case OMPD_cancellation_point:
15679 case OMPD_flush:
15680 case OMPD_depobj:
15681 case OMPD_scan:
15682 case OMPD_declare_reduction:
15683 case OMPD_declare_mapper:
15684 case OMPD_declare_simd:
15685 case OMPD_declare_variant:
15686 case OMPD_begin_declare_variant:
15687 case OMPD_end_declare_variant:
15688 case OMPD_declare_target:
15689 case OMPD_end_declare_target:
15690 case OMPD_loop:
15691 case OMPD_teams_loop:
15692 case OMPD_teams:
15693 case OMPD_tile:
15694 case OMPD_unroll:
15695 case OMPD_for:
15696 case OMPD_sections:
15697 case OMPD_section:
15698 case OMPD_single:
15699 case OMPD_master:
15700 case OMPD_masked:
15701 case OMPD_critical:
15702 case OMPD_taskgroup:
15703 case OMPD_distribute:
15704 case OMPD_ordered:
15705 case OMPD_atomic:
15706 case OMPD_teams_distribute:
15707 case OMPD_requires:
15708 case OMPD_metadirective:
15709 llvm_unreachable("Unexpected OpenMP directive with if-clause");
15710 case OMPD_unknown:
15711 default:
15712 llvm_unreachable("Unknown OpenMP directive");
15714 break;
15715 case OMPC_num_threads:
15716 switch (DKind) {
15717 case OMPD_target_parallel:
15718 case OMPD_target_parallel_for:
15719 case OMPD_target_parallel_for_simd:
15720 case OMPD_target_parallel_loop:
15721 CaptureRegion = OMPD_target;
15722 break;
15723 case OMPD_teams_distribute_parallel_for:
15724 case OMPD_teams_distribute_parallel_for_simd:
15725 case OMPD_target_teams_distribute_parallel_for:
15726 case OMPD_target_teams_distribute_parallel_for_simd:
15727 CaptureRegion = OMPD_teams;
15728 break;
15729 case OMPD_parallel:
15730 case OMPD_parallel_master:
15731 case OMPD_parallel_masked:
15732 case OMPD_parallel_sections:
15733 case OMPD_parallel_for:
15734 case OMPD_parallel_for_simd:
15735 case OMPD_parallel_loop:
15736 case OMPD_distribute_parallel_for:
15737 case OMPD_distribute_parallel_for_simd:
15738 case OMPD_parallel_master_taskloop:
15739 case OMPD_parallel_masked_taskloop:
15740 case OMPD_parallel_master_taskloop_simd:
15741 case OMPD_parallel_masked_taskloop_simd:
15742 // Do not capture num_threads-clause expressions.
15743 break;
15744 case OMPD_target_data:
15745 case OMPD_target_enter_data:
15746 case OMPD_target_exit_data:
15747 case OMPD_target_update:
15748 case OMPD_target:
15749 case OMPD_target_simd:
15750 case OMPD_target_teams:
15751 case OMPD_target_teams_distribute:
15752 case OMPD_target_teams_distribute_simd:
15753 case OMPD_cancel:
15754 case OMPD_task:
15755 case OMPD_taskloop:
15756 case OMPD_taskloop_simd:
15757 case OMPD_master_taskloop:
15758 case OMPD_masked_taskloop:
15759 case OMPD_master_taskloop_simd:
15760 case OMPD_masked_taskloop_simd:
15761 case OMPD_threadprivate:
15762 case OMPD_allocate:
15763 case OMPD_taskyield:
15764 case OMPD_error:
15765 case OMPD_barrier:
15766 case OMPD_taskwait:
15767 case OMPD_cancellation_point:
15768 case OMPD_flush:
15769 case OMPD_depobj:
15770 case OMPD_scan:
15771 case OMPD_declare_reduction:
15772 case OMPD_declare_mapper:
15773 case OMPD_declare_simd:
15774 case OMPD_declare_variant:
15775 case OMPD_begin_declare_variant:
15776 case OMPD_end_declare_variant:
15777 case OMPD_declare_target:
15778 case OMPD_end_declare_target:
15779 case OMPD_loop:
15780 case OMPD_teams_loop:
15781 case OMPD_target_teams_loop:
15782 case OMPD_teams:
15783 case OMPD_simd:
15784 case OMPD_tile:
15785 case OMPD_unroll:
15786 case OMPD_for:
15787 case OMPD_for_simd:
15788 case OMPD_sections:
15789 case OMPD_section:
15790 case OMPD_single:
15791 case OMPD_master:
15792 case OMPD_masked:
15793 case OMPD_critical:
15794 case OMPD_taskgroup:
15795 case OMPD_distribute:
15796 case OMPD_ordered:
15797 case OMPD_atomic:
15798 case OMPD_distribute_simd:
15799 case OMPD_teams_distribute:
15800 case OMPD_teams_distribute_simd:
15801 case OMPD_requires:
15802 case OMPD_metadirective:
15803 llvm_unreachable("Unexpected OpenMP directive with num_threads-clause");
15804 case OMPD_unknown:
15805 default:
15806 llvm_unreachable("Unknown OpenMP directive");
15808 break;
15809 case OMPC_num_teams:
15810 switch (DKind) {
15811 case OMPD_target_teams:
15812 case OMPD_target_teams_distribute:
15813 case OMPD_target_teams_distribute_simd:
15814 case OMPD_target_teams_distribute_parallel_for:
15815 case OMPD_target_teams_distribute_parallel_for_simd:
15816 case OMPD_target_teams_loop:
15817 CaptureRegion = OMPD_target;
15818 break;
15819 case OMPD_teams_distribute_parallel_for:
15820 case OMPD_teams_distribute_parallel_for_simd:
15821 case OMPD_teams:
15822 case OMPD_teams_distribute:
15823 case OMPD_teams_distribute_simd:
15824 case OMPD_teams_loop:
15825 // Do not capture num_teams-clause expressions.
15826 break;
15827 case OMPD_distribute_parallel_for:
15828 case OMPD_distribute_parallel_for_simd:
15829 case OMPD_task:
15830 case OMPD_taskloop:
15831 case OMPD_taskloop_simd:
15832 case OMPD_master_taskloop:
15833 case OMPD_masked_taskloop:
15834 case OMPD_master_taskloop_simd:
15835 case OMPD_masked_taskloop_simd:
15836 case OMPD_parallel_master_taskloop:
15837 case OMPD_parallel_masked_taskloop:
15838 case OMPD_parallel_master_taskloop_simd:
15839 case OMPD_parallel_masked_taskloop_simd:
15840 case OMPD_target_data:
15841 case OMPD_target_enter_data:
15842 case OMPD_target_exit_data:
15843 case OMPD_target_update:
15844 case OMPD_cancel:
15845 case OMPD_parallel:
15846 case OMPD_parallel_master:
15847 case OMPD_parallel_masked:
15848 case OMPD_parallel_sections:
15849 case OMPD_parallel_for:
15850 case OMPD_parallel_for_simd:
15851 case OMPD_parallel_loop:
15852 case OMPD_target:
15853 case OMPD_target_simd:
15854 case OMPD_target_parallel:
15855 case OMPD_target_parallel_for:
15856 case OMPD_target_parallel_for_simd:
15857 case OMPD_target_parallel_loop:
15858 case OMPD_threadprivate:
15859 case OMPD_allocate:
15860 case OMPD_taskyield:
15861 case OMPD_error:
15862 case OMPD_barrier:
15863 case OMPD_taskwait:
15864 case OMPD_cancellation_point:
15865 case OMPD_flush:
15866 case OMPD_depobj:
15867 case OMPD_scan:
15868 case OMPD_declare_reduction:
15869 case OMPD_declare_mapper:
15870 case OMPD_declare_simd:
15871 case OMPD_declare_variant:
15872 case OMPD_begin_declare_variant:
15873 case OMPD_end_declare_variant:
15874 case OMPD_declare_target:
15875 case OMPD_end_declare_target:
15876 case OMPD_loop:
15877 case OMPD_simd:
15878 case OMPD_tile:
15879 case OMPD_unroll:
15880 case OMPD_for:
15881 case OMPD_for_simd:
15882 case OMPD_sections:
15883 case OMPD_section:
15884 case OMPD_single:
15885 case OMPD_master:
15886 case OMPD_masked:
15887 case OMPD_critical:
15888 case OMPD_taskgroup:
15889 case OMPD_distribute:
15890 case OMPD_ordered:
15891 case OMPD_atomic:
15892 case OMPD_distribute_simd:
15893 case OMPD_requires:
15894 case OMPD_metadirective:
15895 llvm_unreachable("Unexpected OpenMP directive with num_teams-clause");
15896 case OMPD_unknown:
15897 default:
15898 llvm_unreachable("Unknown OpenMP directive");
15900 break;
15901 case OMPC_thread_limit:
15902 switch (DKind) {
15903 case OMPD_target:
15904 case OMPD_target_teams:
15905 case OMPD_target_teams_distribute:
15906 case OMPD_target_teams_distribute_simd:
15907 case OMPD_target_teams_distribute_parallel_for:
15908 case OMPD_target_teams_distribute_parallel_for_simd:
15909 case OMPD_target_teams_loop:
15910 CaptureRegion = OMPD_target;
15911 break;
15912 case OMPD_teams_distribute_parallel_for:
15913 case OMPD_teams_distribute_parallel_for_simd:
15914 case OMPD_teams:
15915 case OMPD_teams_distribute:
15916 case OMPD_teams_distribute_simd:
15917 case OMPD_teams_loop:
15918 // Do not capture thread_limit-clause expressions.
15919 break;
15920 case OMPD_distribute_parallel_for:
15921 case OMPD_distribute_parallel_for_simd:
15922 case OMPD_task:
15923 case OMPD_taskloop:
15924 case OMPD_taskloop_simd:
15925 case OMPD_master_taskloop:
15926 case OMPD_masked_taskloop:
15927 case OMPD_master_taskloop_simd:
15928 case OMPD_masked_taskloop_simd:
15929 case OMPD_parallel_master_taskloop:
15930 case OMPD_parallel_masked_taskloop:
15931 case OMPD_parallel_master_taskloop_simd:
15932 case OMPD_parallel_masked_taskloop_simd:
15933 case OMPD_target_data:
15934 case OMPD_target_enter_data:
15935 case OMPD_target_exit_data:
15936 case OMPD_target_update:
15937 case OMPD_cancel:
15938 case OMPD_parallel:
15939 case OMPD_parallel_master:
15940 case OMPD_parallel_masked:
15941 case OMPD_parallel_sections:
15942 case OMPD_parallel_for:
15943 case OMPD_parallel_for_simd:
15944 case OMPD_parallel_loop:
15945 case OMPD_target_simd:
15946 case OMPD_target_parallel:
15947 case OMPD_target_parallel_for:
15948 case OMPD_target_parallel_for_simd:
15949 case OMPD_target_parallel_loop:
15950 case OMPD_threadprivate:
15951 case OMPD_allocate:
15952 case OMPD_taskyield:
15953 case OMPD_error:
15954 case OMPD_barrier:
15955 case OMPD_taskwait:
15956 case OMPD_cancellation_point:
15957 case OMPD_flush:
15958 case OMPD_depobj:
15959 case OMPD_scan:
15960 case OMPD_declare_reduction:
15961 case OMPD_declare_mapper:
15962 case OMPD_declare_simd:
15963 case OMPD_declare_variant:
15964 case OMPD_begin_declare_variant:
15965 case OMPD_end_declare_variant:
15966 case OMPD_declare_target:
15967 case OMPD_end_declare_target:
15968 case OMPD_loop:
15969 case OMPD_simd:
15970 case OMPD_tile:
15971 case OMPD_unroll:
15972 case OMPD_for:
15973 case OMPD_for_simd:
15974 case OMPD_sections:
15975 case OMPD_section:
15976 case OMPD_single:
15977 case OMPD_master:
15978 case OMPD_masked:
15979 case OMPD_critical:
15980 case OMPD_taskgroup:
15981 case OMPD_distribute:
15982 case OMPD_ordered:
15983 case OMPD_atomic:
15984 case OMPD_distribute_simd:
15985 case OMPD_requires:
15986 case OMPD_metadirective:
15987 llvm_unreachable("Unexpected OpenMP directive with thread_limit-clause");
15988 case OMPD_unknown:
15989 default:
15990 llvm_unreachable("Unknown OpenMP directive");
15992 break;
15993 case OMPC_schedule:
15994 switch (DKind) {
15995 case OMPD_parallel_for:
15996 case OMPD_parallel_for_simd:
15997 case OMPD_distribute_parallel_for:
15998 case OMPD_distribute_parallel_for_simd:
15999 case OMPD_teams_distribute_parallel_for:
16000 case OMPD_teams_distribute_parallel_for_simd:
16001 case OMPD_target_parallel_for:
16002 case OMPD_target_parallel_for_simd:
16003 case OMPD_target_teams_distribute_parallel_for:
16004 case OMPD_target_teams_distribute_parallel_for_simd:
16005 CaptureRegion = OMPD_parallel;
16006 break;
16007 case OMPD_for:
16008 case OMPD_for_simd:
16009 // Do not capture schedule-clause expressions.
16010 break;
16011 case OMPD_task:
16012 case OMPD_taskloop:
16013 case OMPD_taskloop_simd:
16014 case OMPD_master_taskloop:
16015 case OMPD_masked_taskloop:
16016 case OMPD_master_taskloop_simd:
16017 case OMPD_masked_taskloop_simd:
16018 case OMPD_parallel_master_taskloop:
16019 case OMPD_parallel_masked_taskloop:
16020 case OMPD_parallel_master_taskloop_simd:
16021 case OMPD_parallel_masked_taskloop_simd:
16022 case OMPD_target_data:
16023 case OMPD_target_enter_data:
16024 case OMPD_target_exit_data:
16025 case OMPD_target_update:
16026 case OMPD_teams:
16027 case OMPD_teams_distribute:
16028 case OMPD_teams_distribute_simd:
16029 case OMPD_target_teams_distribute:
16030 case OMPD_target_teams_distribute_simd:
16031 case OMPD_target:
16032 case OMPD_target_simd:
16033 case OMPD_target_parallel:
16034 case OMPD_cancel:
16035 case OMPD_parallel:
16036 case OMPD_parallel_master:
16037 case OMPD_parallel_masked:
16038 case OMPD_parallel_sections:
16039 case OMPD_threadprivate:
16040 case OMPD_allocate:
16041 case OMPD_taskyield:
16042 case OMPD_error:
16043 case OMPD_barrier:
16044 case OMPD_taskwait:
16045 case OMPD_cancellation_point:
16046 case OMPD_flush:
16047 case OMPD_depobj:
16048 case OMPD_scan:
16049 case OMPD_declare_reduction:
16050 case OMPD_declare_mapper:
16051 case OMPD_declare_simd:
16052 case OMPD_declare_variant:
16053 case OMPD_begin_declare_variant:
16054 case OMPD_end_declare_variant:
16055 case OMPD_declare_target:
16056 case OMPD_end_declare_target:
16057 case OMPD_loop:
16058 case OMPD_teams_loop:
16059 case OMPD_target_teams_loop:
16060 case OMPD_parallel_loop:
16061 case OMPD_target_parallel_loop:
16062 case OMPD_simd:
16063 case OMPD_tile:
16064 case OMPD_unroll:
16065 case OMPD_sections:
16066 case OMPD_section:
16067 case OMPD_single:
16068 case OMPD_master:
16069 case OMPD_masked:
16070 case OMPD_critical:
16071 case OMPD_taskgroup:
16072 case OMPD_distribute:
16073 case OMPD_ordered:
16074 case OMPD_atomic:
16075 case OMPD_distribute_simd:
16076 case OMPD_target_teams:
16077 case OMPD_requires:
16078 case OMPD_metadirective:
16079 llvm_unreachable("Unexpected OpenMP directive with schedule clause");
16080 case OMPD_unknown:
16081 default:
16082 llvm_unreachable("Unknown OpenMP directive");
16084 break;
16085 case OMPC_dist_schedule:
16086 switch (DKind) {
16087 case OMPD_teams_distribute_parallel_for:
16088 case OMPD_teams_distribute_parallel_for_simd:
16089 case OMPD_teams_distribute:
16090 case OMPD_teams_distribute_simd:
16091 case OMPD_target_teams_distribute_parallel_for:
16092 case OMPD_target_teams_distribute_parallel_for_simd:
16093 case OMPD_target_teams_distribute:
16094 case OMPD_target_teams_distribute_simd:
16095 CaptureRegion = OMPD_teams;
16096 break;
16097 case OMPD_distribute_parallel_for:
16098 case OMPD_distribute_parallel_for_simd:
16099 case OMPD_distribute:
16100 case OMPD_distribute_simd:
16101 // Do not capture dist_schedule-clause expressions.
16102 break;
16103 case OMPD_parallel_for:
16104 case OMPD_parallel_for_simd:
16105 case OMPD_target_parallel_for_simd:
16106 case OMPD_target_parallel_for:
16107 case OMPD_task:
16108 case OMPD_taskloop:
16109 case OMPD_taskloop_simd:
16110 case OMPD_master_taskloop:
16111 case OMPD_masked_taskloop:
16112 case OMPD_master_taskloop_simd:
16113 case OMPD_masked_taskloop_simd:
16114 case OMPD_parallel_master_taskloop:
16115 case OMPD_parallel_masked_taskloop:
16116 case OMPD_parallel_master_taskloop_simd:
16117 case OMPD_parallel_masked_taskloop_simd:
16118 case OMPD_target_data:
16119 case OMPD_target_enter_data:
16120 case OMPD_target_exit_data:
16121 case OMPD_target_update:
16122 case OMPD_teams:
16123 case OMPD_target:
16124 case OMPD_target_simd:
16125 case OMPD_target_parallel:
16126 case OMPD_cancel:
16127 case OMPD_parallel:
16128 case OMPD_parallel_master:
16129 case OMPD_parallel_masked:
16130 case OMPD_parallel_sections:
16131 case OMPD_threadprivate:
16132 case OMPD_allocate:
16133 case OMPD_taskyield:
16134 case OMPD_error:
16135 case OMPD_barrier:
16136 case OMPD_taskwait:
16137 case OMPD_cancellation_point:
16138 case OMPD_flush:
16139 case OMPD_depobj:
16140 case OMPD_scan:
16141 case OMPD_declare_reduction:
16142 case OMPD_declare_mapper:
16143 case OMPD_declare_simd:
16144 case OMPD_declare_variant:
16145 case OMPD_begin_declare_variant:
16146 case OMPD_end_declare_variant:
16147 case OMPD_declare_target:
16148 case OMPD_end_declare_target:
16149 case OMPD_loop:
16150 case OMPD_teams_loop:
16151 case OMPD_target_teams_loop:
16152 case OMPD_parallel_loop:
16153 case OMPD_target_parallel_loop:
16154 case OMPD_simd:
16155 case OMPD_tile:
16156 case OMPD_unroll:
16157 case OMPD_for:
16158 case OMPD_for_simd:
16159 case OMPD_sections:
16160 case OMPD_section:
16161 case OMPD_single:
16162 case OMPD_master:
16163 case OMPD_masked:
16164 case OMPD_critical:
16165 case OMPD_taskgroup:
16166 case OMPD_ordered:
16167 case OMPD_atomic:
16168 case OMPD_target_teams:
16169 case OMPD_requires:
16170 case OMPD_metadirective:
16171 llvm_unreachable("Unexpected OpenMP directive with dist_schedule clause");
16172 case OMPD_unknown:
16173 default:
16174 llvm_unreachable("Unknown OpenMP directive");
16176 break;
16177 case OMPC_ompx_dyn_cgroup_mem:
16178 switch (DKind) {
16179 case OMPD_target:
16180 case OMPD_target_simd:
16181 case OMPD_target_teams:
16182 case OMPD_target_parallel:
16183 case OMPD_target_teams_distribute:
16184 case OMPD_target_teams_distribute_simd:
16185 case OMPD_target_parallel_for:
16186 case OMPD_target_parallel_for_simd:
16187 case OMPD_target_parallel_loop:
16188 case OMPD_target_teams_distribute_parallel_for:
16189 case OMPD_target_teams_distribute_parallel_for_simd:
16190 case OMPD_target_teams_loop:
16191 CaptureRegion = OMPD_target;
16192 break;
16193 default:
16194 llvm_unreachable("Unknown OpenMP directive");
16196 break;
16197 case OMPC_device:
16198 switch (DKind) {
16199 case OMPD_target_update:
16200 case OMPD_target_enter_data:
16201 case OMPD_target_exit_data:
16202 case OMPD_target:
16203 case OMPD_target_simd:
16204 case OMPD_target_teams:
16205 case OMPD_target_parallel:
16206 case OMPD_target_teams_distribute:
16207 case OMPD_target_teams_distribute_simd:
16208 case OMPD_target_parallel_for:
16209 case OMPD_target_parallel_for_simd:
16210 case OMPD_target_parallel_loop:
16211 case OMPD_target_teams_distribute_parallel_for:
16212 case OMPD_target_teams_distribute_parallel_for_simd:
16213 case OMPD_target_teams_loop:
16214 case OMPD_dispatch:
16215 CaptureRegion = OMPD_task;
16216 break;
16217 case OMPD_target_data:
16218 case OMPD_interop:
16219 // Do not capture device-clause expressions.
16220 break;
16221 case OMPD_teams_distribute_parallel_for:
16222 case OMPD_teams_distribute_parallel_for_simd:
16223 case OMPD_teams:
16224 case OMPD_teams_distribute:
16225 case OMPD_teams_distribute_simd:
16226 case OMPD_distribute_parallel_for:
16227 case OMPD_distribute_parallel_for_simd:
16228 case OMPD_task:
16229 case OMPD_taskloop:
16230 case OMPD_taskloop_simd:
16231 case OMPD_master_taskloop:
16232 case OMPD_masked_taskloop:
16233 case OMPD_master_taskloop_simd:
16234 case OMPD_masked_taskloop_simd:
16235 case OMPD_parallel_master_taskloop:
16236 case OMPD_parallel_masked_taskloop:
16237 case OMPD_parallel_master_taskloop_simd:
16238 case OMPD_parallel_masked_taskloop_simd:
16239 case OMPD_cancel:
16240 case OMPD_parallel:
16241 case OMPD_parallel_master:
16242 case OMPD_parallel_masked:
16243 case OMPD_parallel_sections:
16244 case OMPD_parallel_for:
16245 case OMPD_parallel_for_simd:
16246 case OMPD_threadprivate:
16247 case OMPD_allocate:
16248 case OMPD_taskyield:
16249 case OMPD_error:
16250 case OMPD_barrier:
16251 case OMPD_taskwait:
16252 case OMPD_cancellation_point:
16253 case OMPD_flush:
16254 case OMPD_depobj:
16255 case OMPD_scan:
16256 case OMPD_declare_reduction:
16257 case OMPD_declare_mapper:
16258 case OMPD_declare_simd:
16259 case OMPD_declare_variant:
16260 case OMPD_begin_declare_variant:
16261 case OMPD_end_declare_variant:
16262 case OMPD_declare_target:
16263 case OMPD_end_declare_target:
16264 case OMPD_loop:
16265 case OMPD_teams_loop:
16266 case OMPD_parallel_loop:
16267 case OMPD_simd:
16268 case OMPD_tile:
16269 case OMPD_unroll:
16270 case OMPD_for:
16271 case OMPD_for_simd:
16272 case OMPD_sections:
16273 case OMPD_section:
16274 case OMPD_single:
16275 case OMPD_master:
16276 case OMPD_masked:
16277 case OMPD_critical:
16278 case OMPD_taskgroup:
16279 case OMPD_distribute:
16280 case OMPD_ordered:
16281 case OMPD_atomic:
16282 case OMPD_distribute_simd:
16283 case OMPD_requires:
16284 case OMPD_metadirective:
16285 llvm_unreachable("Unexpected OpenMP directive with device-clause");
16286 case OMPD_unknown:
16287 default:
16288 llvm_unreachable("Unknown OpenMP directive");
16290 break;
16291 case OMPC_grainsize:
16292 case OMPC_num_tasks:
16293 case OMPC_final:
16294 case OMPC_priority:
16295 switch (DKind) {
16296 case OMPD_task:
16297 case OMPD_taskloop:
16298 case OMPD_taskloop_simd:
16299 case OMPD_master_taskloop:
16300 case OMPD_masked_taskloop:
16301 case OMPD_master_taskloop_simd:
16302 case OMPD_masked_taskloop_simd:
16303 break;
16304 case OMPD_parallel_masked_taskloop:
16305 case OMPD_parallel_masked_taskloop_simd:
16306 case OMPD_parallel_master_taskloop:
16307 case OMPD_parallel_master_taskloop_simd:
16308 CaptureRegion = OMPD_parallel;
16309 break;
16310 case OMPD_target_update:
16311 case OMPD_target_enter_data:
16312 case OMPD_target_exit_data:
16313 case OMPD_target:
16314 case OMPD_target_simd:
16315 case OMPD_target_teams:
16316 case OMPD_target_parallel:
16317 case OMPD_target_teams_distribute:
16318 case OMPD_target_teams_distribute_simd:
16319 case OMPD_target_parallel_for:
16320 case OMPD_target_parallel_for_simd:
16321 case OMPD_target_teams_distribute_parallel_for:
16322 case OMPD_target_teams_distribute_parallel_for_simd:
16323 case OMPD_target_data:
16324 case OMPD_teams_distribute_parallel_for:
16325 case OMPD_teams_distribute_parallel_for_simd:
16326 case OMPD_teams:
16327 case OMPD_teams_distribute:
16328 case OMPD_teams_distribute_simd:
16329 case OMPD_distribute_parallel_for:
16330 case OMPD_distribute_parallel_for_simd:
16331 case OMPD_cancel:
16332 case OMPD_parallel:
16333 case OMPD_parallel_master:
16334 case OMPD_parallel_masked:
16335 case OMPD_parallel_sections:
16336 case OMPD_parallel_for:
16337 case OMPD_parallel_for_simd:
16338 case OMPD_threadprivate:
16339 case OMPD_allocate:
16340 case OMPD_taskyield:
16341 case OMPD_error:
16342 case OMPD_barrier:
16343 case OMPD_taskwait:
16344 case OMPD_cancellation_point:
16345 case OMPD_flush:
16346 case OMPD_depobj:
16347 case OMPD_scan:
16348 case OMPD_declare_reduction:
16349 case OMPD_declare_mapper:
16350 case OMPD_declare_simd:
16351 case OMPD_declare_variant:
16352 case OMPD_begin_declare_variant:
16353 case OMPD_end_declare_variant:
16354 case OMPD_declare_target:
16355 case OMPD_end_declare_target:
16356 case OMPD_loop:
16357 case OMPD_teams_loop:
16358 case OMPD_target_teams_loop:
16359 case OMPD_parallel_loop:
16360 case OMPD_target_parallel_loop:
16361 case OMPD_simd:
16362 case OMPD_tile:
16363 case OMPD_unroll:
16364 case OMPD_for:
16365 case OMPD_for_simd:
16366 case OMPD_sections:
16367 case OMPD_section:
16368 case OMPD_single:
16369 case OMPD_master:
16370 case OMPD_masked:
16371 case OMPD_critical:
16372 case OMPD_taskgroup:
16373 case OMPD_distribute:
16374 case OMPD_ordered:
16375 case OMPD_atomic:
16376 case OMPD_distribute_simd:
16377 case OMPD_requires:
16378 case OMPD_metadirective:
16379 llvm_unreachable("Unexpected OpenMP directive with grainsize-clause");
16380 case OMPD_unknown:
16381 default:
16382 llvm_unreachable("Unknown OpenMP directive");
16384 break;
16385 case OMPC_novariants:
16386 case OMPC_nocontext:
16387 switch (DKind) {
16388 case OMPD_dispatch:
16389 CaptureRegion = OMPD_task;
16390 break;
16391 default:
16392 llvm_unreachable("Unexpected OpenMP directive");
16394 break;
16395 case OMPC_filter:
16396 // Do not capture filter-clause expressions.
16397 break;
16398 case OMPC_when:
16399 if (DKind == OMPD_metadirective) {
16400 CaptureRegion = OMPD_metadirective;
16401 } else if (DKind == OMPD_unknown) {
16402 llvm_unreachable("Unknown OpenMP directive");
16403 } else {
16404 llvm_unreachable("Unexpected OpenMP directive with when clause");
16406 break;
16407 case OMPC_firstprivate:
16408 case OMPC_lastprivate:
16409 case OMPC_reduction:
16410 case OMPC_task_reduction:
16411 case OMPC_in_reduction:
16412 case OMPC_linear:
16413 case OMPC_default:
16414 case OMPC_proc_bind:
16415 case OMPC_safelen:
16416 case OMPC_simdlen:
16417 case OMPC_sizes:
16418 case OMPC_allocator:
16419 case OMPC_collapse:
16420 case OMPC_private:
16421 case OMPC_shared:
16422 case OMPC_aligned:
16423 case OMPC_copyin:
16424 case OMPC_copyprivate:
16425 case OMPC_ordered:
16426 case OMPC_nowait:
16427 case OMPC_untied:
16428 case OMPC_mergeable:
16429 case OMPC_threadprivate:
16430 case OMPC_allocate:
16431 case OMPC_flush:
16432 case OMPC_depobj:
16433 case OMPC_read:
16434 case OMPC_write:
16435 case OMPC_update:
16436 case OMPC_capture:
16437 case OMPC_compare:
16438 case OMPC_seq_cst:
16439 case OMPC_acq_rel:
16440 case OMPC_acquire:
16441 case OMPC_release:
16442 case OMPC_relaxed:
16443 case OMPC_depend:
16444 case OMPC_threads:
16445 case OMPC_simd:
16446 case OMPC_map:
16447 case OMPC_nogroup:
16448 case OMPC_hint:
16449 case OMPC_defaultmap:
16450 case OMPC_unknown:
16451 case OMPC_uniform:
16452 case OMPC_to:
16453 case OMPC_from:
16454 case OMPC_use_device_ptr:
16455 case OMPC_use_device_addr:
16456 case OMPC_is_device_ptr:
16457 case OMPC_unified_address:
16458 case OMPC_unified_shared_memory:
16459 case OMPC_reverse_offload:
16460 case OMPC_dynamic_allocators:
16461 case OMPC_atomic_default_mem_order:
16462 case OMPC_device_type:
16463 case OMPC_match:
16464 case OMPC_nontemporal:
16465 case OMPC_order:
16466 case OMPC_at:
16467 case OMPC_severity:
16468 case OMPC_message:
16469 case OMPC_destroy:
16470 case OMPC_detach:
16471 case OMPC_inclusive:
16472 case OMPC_exclusive:
16473 case OMPC_uses_allocators:
16474 case OMPC_affinity:
16475 case OMPC_bind:
16476 default:
16477 llvm_unreachable("Unexpected OpenMP clause.");
16479 return CaptureRegion;
16482 OMPClause *Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier,
16483 Expr *Condition, SourceLocation StartLoc,
16484 SourceLocation LParenLoc,
16485 SourceLocation NameModifierLoc,
16486 SourceLocation ColonLoc,
16487 SourceLocation EndLoc) {
16488 Expr *ValExpr = Condition;
16489 Stmt *HelperValStmt = nullptr;
16490 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16491 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16492 !Condition->isInstantiationDependent() &&
16493 !Condition->containsUnexpandedParameterPack()) {
16494 ExprResult Val = CheckBooleanCondition(StartLoc, Condition);
16495 if (Val.isInvalid())
16496 return nullptr;
16498 ValExpr = Val.get();
16500 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16501 CaptureRegion = getOpenMPCaptureRegionForClause(
16502 DKind, OMPC_if, LangOpts.OpenMP, NameModifier);
16503 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
16504 ValExpr = MakeFullExpr(ValExpr).get();
16505 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16506 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
16507 HelperValStmt = buildPreInits(Context, Captures);
16511 return new (Context)
16512 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
16513 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
16516 OMPClause *Sema::ActOnOpenMPFinalClause(Expr *Condition,
16517 SourceLocation StartLoc,
16518 SourceLocation LParenLoc,
16519 SourceLocation EndLoc) {
16520 Expr *ValExpr = Condition;
16521 Stmt *HelperValStmt = nullptr;
16522 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16523 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16524 !Condition->isInstantiationDependent() &&
16525 !Condition->containsUnexpandedParameterPack()) {
16526 ExprResult Val = CheckBooleanCondition(StartLoc, Condition);
16527 if (Val.isInvalid())
16528 return nullptr;
16530 ValExpr = MakeFullExpr(Val.get()).get();
16532 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16533 CaptureRegion =
16534 getOpenMPCaptureRegionForClause(DKind, OMPC_final, LangOpts.OpenMP);
16535 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
16536 ValExpr = MakeFullExpr(ValExpr).get();
16537 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16538 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
16539 HelperValStmt = buildPreInits(Context, Captures);
16543 return new (Context) OMPFinalClause(ValExpr, HelperValStmt, CaptureRegion,
16544 StartLoc, LParenLoc, EndLoc);
16547 ExprResult Sema::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc,
16548 Expr *Op) {
16549 if (!Op)
16550 return ExprError();
16552 class IntConvertDiagnoser : public ICEConvertDiagnoser {
16553 public:
16554 IntConvertDiagnoser()
16555 : ICEConvertDiagnoser(/*AllowScopedEnumerations*/ false, false, true) {}
16556 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
16557 QualType T) override {
16558 return S.Diag(Loc, diag::err_omp_not_integral) << T;
16560 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
16561 QualType T) override {
16562 return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
16564 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
16565 QualType T,
16566 QualType ConvTy) override {
16567 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
16569 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
16570 QualType ConvTy) override {
16571 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16572 << ConvTy->isEnumeralType() << ConvTy;
16574 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
16575 QualType T) override {
16576 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
16578 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
16579 QualType ConvTy) override {
16580 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16581 << ConvTy->isEnumeralType() << ConvTy;
16583 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
16584 QualType) override {
16585 llvm_unreachable("conversion functions are permitted");
16587 } ConvertDiagnoser;
16588 return PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
16591 static bool
16592 isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind,
16593 bool StrictlyPositive, bool BuildCapture = false,
16594 OpenMPDirectiveKind DKind = OMPD_unknown,
16595 OpenMPDirectiveKind *CaptureRegion = nullptr,
16596 Stmt **HelperValStmt = nullptr) {
16597 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
16598 !ValExpr->isInstantiationDependent()) {
16599 SourceLocation Loc = ValExpr->getExprLoc();
16600 ExprResult Value =
16601 SemaRef.PerformOpenMPImplicitIntegerConversion(Loc, ValExpr);
16602 if (Value.isInvalid())
16603 return false;
16605 ValExpr = Value.get();
16606 // The expression must evaluate to a non-negative integer value.
16607 if (std::optional<llvm::APSInt> Result =
16608 ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
16609 if (Result->isSigned() &&
16610 !((!StrictlyPositive && Result->isNonNegative()) ||
16611 (StrictlyPositive && Result->isStrictlyPositive()))) {
16612 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
16613 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
16614 << ValExpr->getSourceRange();
16615 return false;
16618 if (!BuildCapture)
16619 return true;
16620 *CaptureRegion =
16621 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
16622 if (*CaptureRegion != OMPD_unknown &&
16623 !SemaRef.CurContext->isDependentContext()) {
16624 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16625 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16626 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16627 *HelperValStmt = buildPreInits(SemaRef.Context, Captures);
16630 return true;
16633 OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads,
16634 SourceLocation StartLoc,
16635 SourceLocation LParenLoc,
16636 SourceLocation EndLoc) {
16637 Expr *ValExpr = NumThreads;
16638 Stmt *HelperValStmt = nullptr;
16640 // OpenMP [2.5, Restrictions]
16641 // The num_threads expression must evaluate to a positive integer value.
16642 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_num_threads,
16643 /*StrictlyPositive=*/true))
16644 return nullptr;
16646 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16647 OpenMPDirectiveKind CaptureRegion =
16648 getOpenMPCaptureRegionForClause(DKind, OMPC_num_threads, LangOpts.OpenMP);
16649 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
16650 ValExpr = MakeFullExpr(ValExpr).get();
16651 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16652 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
16653 HelperValStmt = buildPreInits(Context, Captures);
16656 return new (Context) OMPNumThreadsClause(
16657 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16660 ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,
16661 OpenMPClauseKind CKind,
16662 bool StrictlyPositive,
16663 bool SuppressExprDiags) {
16664 if (!E)
16665 return ExprError();
16666 if (E->isValueDependent() || E->isTypeDependent() ||
16667 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
16668 return E;
16670 llvm::APSInt Result;
16671 ExprResult ICE;
16672 if (SuppressExprDiags) {
16673 // Use a custom diagnoser that suppresses 'note' diagnostics about the
16674 // expression.
16675 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
16676 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
16677 Sema::SemaDiagnosticBuilder diagnoseNotICE(Sema &S,
16678 SourceLocation Loc) override {
16679 llvm_unreachable("Diagnostic suppressed");
16681 } Diagnoser;
16682 ICE = VerifyIntegerConstantExpression(E, &Result, Diagnoser, AllowFold);
16683 } else {
16684 ICE = VerifyIntegerConstantExpression(E, &Result, /*FIXME*/ AllowFold);
16686 if (ICE.isInvalid())
16687 return ExprError();
16689 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
16690 (!StrictlyPositive && !Result.isNonNegative())) {
16691 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
16692 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
16693 << E->getSourceRange();
16694 return ExprError();
16696 if ((CKind == OMPC_aligned || CKind == OMPC_align) && !Result.isPowerOf2()) {
16697 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
16698 << E->getSourceRange();
16699 return ExprError();
16701 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
16702 DSAStack->setAssociatedLoops(Result.getExtValue());
16703 else if (CKind == OMPC_ordered)
16704 DSAStack->setAssociatedLoops(Result.getExtValue());
16705 return ICE;
16708 OMPClause *Sema::ActOnOpenMPSafelenClause(Expr *Len, SourceLocation StartLoc,
16709 SourceLocation LParenLoc,
16710 SourceLocation EndLoc) {
16711 // OpenMP [2.8.1, simd construct, Description]
16712 // The parameter of the safelen clause must be a constant
16713 // positive integer expression.
16714 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
16715 if (Safelen.isInvalid())
16716 return nullptr;
16717 return new (Context)
16718 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
16721 OMPClause *Sema::ActOnOpenMPSimdlenClause(Expr *Len, SourceLocation StartLoc,
16722 SourceLocation LParenLoc,
16723 SourceLocation EndLoc) {
16724 // OpenMP [2.8.1, simd construct, Description]
16725 // The parameter of the simdlen clause must be a constant
16726 // positive integer expression.
16727 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
16728 if (Simdlen.isInvalid())
16729 return nullptr;
16730 return new (Context)
16731 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
16734 /// Tries to find omp_allocator_handle_t type.
16735 static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc,
16736 DSAStackTy *Stack) {
16737 if (!Stack->getOMPAllocatorHandleT().isNull())
16738 return true;
16740 // Set the allocator handle type.
16741 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t");
16742 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
16743 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
16744 S.Diag(Loc, diag::err_omp_implied_type_not_found)
16745 << "omp_allocator_handle_t";
16746 return false;
16748 QualType AllocatorHandleEnumTy = PT.get();
16749 AllocatorHandleEnumTy.addConst();
16750 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
16752 // Fill the predefined allocator map.
16753 bool ErrorFound = false;
16754 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
16755 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
16756 StringRef Allocator =
16757 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
16758 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
16759 auto *VD = dyn_cast_or_null<ValueDecl>(
16760 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
16761 if (!VD) {
16762 ErrorFound = true;
16763 break;
16765 QualType AllocatorType =
16766 VD->getType().getNonLValueExprType(S.getASTContext());
16767 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
16768 if (!Res.isUsable()) {
16769 ErrorFound = true;
16770 break;
16772 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
16773 Sema::AA_Initializing,
16774 /* AllowExplicit */ true);
16775 if (!Res.isUsable()) {
16776 ErrorFound = true;
16777 break;
16779 Stack->setAllocator(AllocatorKind, Res.get());
16781 if (ErrorFound) {
16782 S.Diag(Loc, diag::err_omp_implied_type_not_found)
16783 << "omp_allocator_handle_t";
16784 return false;
16787 return true;
16790 OMPClause *Sema::ActOnOpenMPAllocatorClause(Expr *A, SourceLocation StartLoc,
16791 SourceLocation LParenLoc,
16792 SourceLocation EndLoc) {
16793 // OpenMP [2.11.3, allocate Directive, Description]
16794 // allocator is an expression of omp_allocator_handle_t type.
16795 if (!findOMPAllocatorHandleT(*this, A->getExprLoc(), DSAStack))
16796 return nullptr;
16798 ExprResult Allocator = DefaultLvalueConversion(A);
16799 if (Allocator.isInvalid())
16800 return nullptr;
16801 Allocator = PerformImplicitConversion(Allocator.get(),
16802 DSAStack->getOMPAllocatorHandleT(),
16803 Sema::AA_Initializing,
16804 /*AllowExplicit=*/true);
16805 if (Allocator.isInvalid())
16806 return nullptr;
16807 return new (Context)
16808 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
16811 OMPClause *Sema::ActOnOpenMPCollapseClause(Expr *NumForLoops,
16812 SourceLocation StartLoc,
16813 SourceLocation LParenLoc,
16814 SourceLocation EndLoc) {
16815 // OpenMP [2.7.1, loop construct, Description]
16816 // OpenMP [2.8.1, simd construct, Description]
16817 // OpenMP [2.9.6, distribute construct, Description]
16818 // The parameter of the collapse clause must be a constant
16819 // positive integer expression.
16820 ExprResult NumForLoopsResult =
16821 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
16822 if (NumForLoopsResult.isInvalid())
16823 return nullptr;
16824 return new (Context)
16825 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
16828 OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc,
16829 SourceLocation EndLoc,
16830 SourceLocation LParenLoc,
16831 Expr *NumForLoops) {
16832 // OpenMP [2.7.1, loop construct, Description]
16833 // OpenMP [2.8.1, simd construct, Description]
16834 // OpenMP [2.9.6, distribute construct, Description]
16835 // The parameter of the ordered clause must be a constant
16836 // positive integer expression if any.
16837 if (NumForLoops && LParenLoc.isValid()) {
16838 ExprResult NumForLoopsResult =
16839 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
16840 if (NumForLoopsResult.isInvalid())
16841 return nullptr;
16842 NumForLoops = NumForLoopsResult.get();
16843 } else {
16844 NumForLoops = nullptr;
16846 auto *Clause = OMPOrderedClause::Create(
16847 Context, NumForLoops, NumForLoops ? DSAStack->getAssociatedLoops() : 0,
16848 StartLoc, LParenLoc, EndLoc);
16849 DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
16850 return Clause;
16853 OMPClause *Sema::ActOnOpenMPSimpleClause(
16854 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
16855 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
16856 OMPClause *Res = nullptr;
16857 switch (Kind) {
16858 case OMPC_default:
16859 Res = ActOnOpenMPDefaultClause(static_cast<DefaultKind>(Argument),
16860 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16861 break;
16862 case OMPC_proc_bind:
16863 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
16864 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16865 break;
16866 case OMPC_atomic_default_mem_order:
16867 Res = ActOnOpenMPAtomicDefaultMemOrderClause(
16868 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
16869 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16870 break;
16871 case OMPC_update:
16872 Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument),
16873 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16874 break;
16875 case OMPC_bind:
16876 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
16877 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16878 break;
16879 case OMPC_at:
16880 Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
16881 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16882 break;
16883 case OMPC_severity:
16884 Res = ActOnOpenMPSeverityClause(
16885 static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc,
16886 LParenLoc, EndLoc);
16887 break;
16888 case OMPC_if:
16889 case OMPC_final:
16890 case OMPC_num_threads:
16891 case OMPC_safelen:
16892 case OMPC_simdlen:
16893 case OMPC_sizes:
16894 case OMPC_allocator:
16895 case OMPC_collapse:
16896 case OMPC_schedule:
16897 case OMPC_private:
16898 case OMPC_firstprivate:
16899 case OMPC_lastprivate:
16900 case OMPC_shared:
16901 case OMPC_reduction:
16902 case OMPC_task_reduction:
16903 case OMPC_in_reduction:
16904 case OMPC_linear:
16905 case OMPC_aligned:
16906 case OMPC_copyin:
16907 case OMPC_copyprivate:
16908 case OMPC_ordered:
16909 case OMPC_nowait:
16910 case OMPC_untied:
16911 case OMPC_mergeable:
16912 case OMPC_threadprivate:
16913 case OMPC_allocate:
16914 case OMPC_flush:
16915 case OMPC_depobj:
16916 case OMPC_read:
16917 case OMPC_write:
16918 case OMPC_capture:
16919 case OMPC_compare:
16920 case OMPC_seq_cst:
16921 case OMPC_acq_rel:
16922 case OMPC_acquire:
16923 case OMPC_release:
16924 case OMPC_relaxed:
16925 case OMPC_depend:
16926 case OMPC_device:
16927 case OMPC_threads:
16928 case OMPC_simd:
16929 case OMPC_map:
16930 case OMPC_num_teams:
16931 case OMPC_thread_limit:
16932 case OMPC_priority:
16933 case OMPC_grainsize:
16934 case OMPC_nogroup:
16935 case OMPC_num_tasks:
16936 case OMPC_hint:
16937 case OMPC_dist_schedule:
16938 case OMPC_defaultmap:
16939 case OMPC_unknown:
16940 case OMPC_uniform:
16941 case OMPC_to:
16942 case OMPC_from:
16943 case OMPC_use_device_ptr:
16944 case OMPC_use_device_addr:
16945 case OMPC_is_device_ptr:
16946 case OMPC_has_device_addr:
16947 case OMPC_unified_address:
16948 case OMPC_unified_shared_memory:
16949 case OMPC_reverse_offload:
16950 case OMPC_dynamic_allocators:
16951 case OMPC_device_type:
16952 case OMPC_match:
16953 case OMPC_nontemporal:
16954 case OMPC_destroy:
16955 case OMPC_novariants:
16956 case OMPC_nocontext:
16957 case OMPC_detach:
16958 case OMPC_inclusive:
16959 case OMPC_exclusive:
16960 case OMPC_uses_allocators:
16961 case OMPC_affinity:
16962 case OMPC_when:
16963 case OMPC_message:
16964 default:
16965 llvm_unreachable("Clause is not allowed.");
16967 return Res;
16970 static std::string
16971 getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last,
16972 ArrayRef<unsigned> Exclude = std::nullopt) {
16973 SmallString<256> Buffer;
16974 llvm::raw_svector_ostream Out(Buffer);
16975 unsigned Skipped = Exclude.size();
16976 for (unsigned I = First; I < Last; ++I) {
16977 if (llvm::is_contained(Exclude, I)) {
16978 --Skipped;
16979 continue;
16981 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
16982 if (I + Skipped + 2 == Last)
16983 Out << " or ";
16984 else if (I + Skipped + 1 != Last)
16985 Out << ", ";
16987 return std::string(Out.str());
16990 OMPClause *Sema::ActOnOpenMPDefaultClause(DefaultKind Kind,
16991 SourceLocation KindKwLoc,
16992 SourceLocation StartLoc,
16993 SourceLocation LParenLoc,
16994 SourceLocation EndLoc) {
16995 if (Kind == OMP_DEFAULT_unknown) {
16996 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16997 << getListOfPossibleValues(OMPC_default, /*First=*/0,
16998 /*Last=*/unsigned(OMP_DEFAULT_unknown))
16999 << getOpenMPClauseName(OMPC_default);
17000 return nullptr;
17003 switch (Kind) {
17004 case OMP_DEFAULT_none:
17005 DSAStack->setDefaultDSANone(KindKwLoc);
17006 break;
17007 case OMP_DEFAULT_shared:
17008 DSAStack->setDefaultDSAShared(KindKwLoc);
17009 break;
17010 case OMP_DEFAULT_firstprivate:
17011 DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
17012 break;
17013 case OMP_DEFAULT_private:
17014 DSAStack->setDefaultDSAPrivate(KindKwLoc);
17015 break;
17016 default:
17017 llvm_unreachable("DSA unexpected in OpenMP default clause");
17020 return new (Context)
17021 OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17024 OMPClause *Sema::ActOnOpenMPProcBindClause(ProcBindKind Kind,
17025 SourceLocation KindKwLoc,
17026 SourceLocation StartLoc,
17027 SourceLocation LParenLoc,
17028 SourceLocation EndLoc) {
17029 if (Kind == OMP_PROC_BIND_unknown) {
17030 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17031 << getListOfPossibleValues(OMPC_proc_bind,
17032 /*First=*/unsigned(OMP_PROC_BIND_master),
17033 /*Last=*/
17034 unsigned(LangOpts.OpenMP > 50
17035 ? OMP_PROC_BIND_primary
17036 : OMP_PROC_BIND_spread) +
17038 << getOpenMPClauseName(OMPC_proc_bind);
17039 return nullptr;
17041 if (Kind == OMP_PROC_BIND_primary && LangOpts.OpenMP < 51)
17042 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17043 << getListOfPossibleValues(OMPC_proc_bind,
17044 /*First=*/unsigned(OMP_PROC_BIND_master),
17045 /*Last=*/
17046 unsigned(OMP_PROC_BIND_spread) + 1)
17047 << getOpenMPClauseName(OMPC_proc_bind);
17048 return new (Context)
17049 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17052 OMPClause *Sema::ActOnOpenMPAtomicDefaultMemOrderClause(
17053 OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindKwLoc,
17054 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17055 if (Kind == OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown) {
17056 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17057 << getListOfPossibleValues(
17058 OMPC_atomic_default_mem_order, /*First=*/0,
17059 /*Last=*/OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown)
17060 << getOpenMPClauseName(OMPC_atomic_default_mem_order);
17061 return nullptr;
17063 return new (Context) OMPAtomicDefaultMemOrderClause(Kind, KindKwLoc, StartLoc,
17064 LParenLoc, EndLoc);
17067 OMPClause *Sema::ActOnOpenMPAtClause(OpenMPAtClauseKind Kind,
17068 SourceLocation KindKwLoc,
17069 SourceLocation StartLoc,
17070 SourceLocation LParenLoc,
17071 SourceLocation EndLoc) {
17072 if (Kind == OMPC_AT_unknown) {
17073 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17074 << getListOfPossibleValues(OMPC_at, /*First=*/0,
17075 /*Last=*/OMPC_AT_unknown)
17076 << getOpenMPClauseName(OMPC_at);
17077 return nullptr;
17079 return new (Context)
17080 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17083 OMPClause *Sema::ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind,
17084 SourceLocation KindKwLoc,
17085 SourceLocation StartLoc,
17086 SourceLocation LParenLoc,
17087 SourceLocation EndLoc) {
17088 if (Kind == OMPC_SEVERITY_unknown) {
17089 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17090 << getListOfPossibleValues(OMPC_severity, /*First=*/0,
17091 /*Last=*/OMPC_SEVERITY_unknown)
17092 << getOpenMPClauseName(OMPC_severity);
17093 return nullptr;
17095 return new (Context)
17096 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17099 OMPClause *Sema::ActOnOpenMPMessageClause(Expr *ME, SourceLocation StartLoc,
17100 SourceLocation LParenLoc,
17101 SourceLocation EndLoc) {
17102 assert(ME && "NULL expr in Message clause");
17103 if (!isa<StringLiteral>(ME)) {
17104 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
17105 << getOpenMPClauseName(OMPC_message);
17106 return nullptr;
17108 return new (Context) OMPMessageClause(ME, StartLoc, LParenLoc, EndLoc);
17111 OMPClause *Sema::ActOnOpenMPOrderClause(
17112 OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind,
17113 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
17114 SourceLocation KindLoc, SourceLocation EndLoc) {
17115 if (Kind != OMPC_ORDER_concurrent ||
17116 (LangOpts.OpenMP < 51 && MLoc.isValid())) {
17117 // Kind should be concurrent,
17118 // Modifiers introduced in OpenMP 5.1
17119 static_assert(OMPC_ORDER_unknown > 0,
17120 "OMPC_ORDER_unknown not greater than 0");
17122 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17123 << getListOfPossibleValues(OMPC_order,
17124 /*First=*/0,
17125 /*Last=*/OMPC_ORDER_unknown)
17126 << getOpenMPClauseName(OMPC_order);
17127 return nullptr;
17129 if (LangOpts.OpenMP >= 51) {
17130 if (Modifier == OMPC_ORDER_MODIFIER_unknown && MLoc.isValid()) {
17131 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17132 << getListOfPossibleValues(OMPC_order,
17133 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
17134 /*Last=*/OMPC_ORDER_MODIFIER_last)
17135 << getOpenMPClauseName(OMPC_order);
17136 } else {
17137 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
17138 if (DSAStack->getCurScope()) {
17139 // mark the current scope with 'order' flag
17140 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
17141 DSAStack->getCurScope()->setFlags(existingFlags |
17142 Scope::OpenMPOrderClauseScope);
17146 return new (Context) OMPOrderClause(Kind, KindLoc, StartLoc, LParenLoc,
17147 EndLoc, Modifier, MLoc);
17150 OMPClause *Sema::ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind,
17151 SourceLocation KindKwLoc,
17152 SourceLocation StartLoc,
17153 SourceLocation LParenLoc,
17154 SourceLocation EndLoc) {
17155 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
17156 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
17157 SmallVector<unsigned> Except = {
17158 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
17159 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
17160 if (LangOpts.OpenMP < 51)
17161 Except.push_back(OMPC_DEPEND_inoutset);
17162 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17163 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
17164 /*Last=*/OMPC_DEPEND_unknown, Except)
17165 << getOpenMPClauseName(OMPC_update);
17166 return nullptr;
17168 return OMPUpdateClause::Create(Context, StartLoc, LParenLoc, KindKwLoc, Kind,
17169 EndLoc);
17172 OMPClause *Sema::ActOnOpenMPSizesClause(ArrayRef<Expr *> SizeExprs,
17173 SourceLocation StartLoc,
17174 SourceLocation LParenLoc,
17175 SourceLocation EndLoc) {
17176 for (Expr *SizeExpr : SizeExprs) {
17177 ExprResult NumForLoopsResult = VerifyPositiveIntegerConstantInClause(
17178 SizeExpr, OMPC_sizes, /*StrictlyPositive=*/true);
17179 if (!NumForLoopsResult.isUsable())
17180 return nullptr;
17183 DSAStack->setAssociatedLoops(SizeExprs.size());
17184 return OMPSizesClause::Create(Context, StartLoc, LParenLoc, EndLoc,
17185 SizeExprs);
17188 OMPClause *Sema::ActOnOpenMPFullClause(SourceLocation StartLoc,
17189 SourceLocation EndLoc) {
17190 return OMPFullClause::Create(Context, StartLoc, EndLoc);
17193 OMPClause *Sema::ActOnOpenMPPartialClause(Expr *FactorExpr,
17194 SourceLocation StartLoc,
17195 SourceLocation LParenLoc,
17196 SourceLocation EndLoc) {
17197 if (FactorExpr) {
17198 // If an argument is specified, it must be a constant (or an unevaluated
17199 // template expression).
17200 ExprResult FactorResult = VerifyPositiveIntegerConstantInClause(
17201 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
17202 if (FactorResult.isInvalid())
17203 return nullptr;
17204 FactorExpr = FactorResult.get();
17207 return OMPPartialClause::Create(Context, StartLoc, LParenLoc, EndLoc,
17208 FactorExpr);
17211 OMPClause *Sema::ActOnOpenMPAlignClause(Expr *A, SourceLocation StartLoc,
17212 SourceLocation LParenLoc,
17213 SourceLocation EndLoc) {
17214 ExprResult AlignVal;
17215 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
17216 if (AlignVal.isInvalid())
17217 return nullptr;
17218 return OMPAlignClause::Create(Context, AlignVal.get(), StartLoc, LParenLoc,
17219 EndLoc);
17222 OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
17223 OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr,
17224 SourceLocation StartLoc, SourceLocation LParenLoc,
17225 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
17226 SourceLocation EndLoc) {
17227 OMPClause *Res = nullptr;
17228 switch (Kind) {
17229 case OMPC_schedule:
17230 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
17231 assert(Argument.size() == NumberOfElements &&
17232 ArgumentLoc.size() == NumberOfElements);
17233 Res = ActOnOpenMPScheduleClause(
17234 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
17235 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
17236 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
17237 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
17238 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
17239 break;
17240 case OMPC_if:
17241 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17242 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
17243 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
17244 DelimLoc, EndLoc);
17245 break;
17246 case OMPC_dist_schedule:
17247 Res = ActOnOpenMPDistScheduleClause(
17248 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
17249 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
17250 break;
17251 case OMPC_defaultmap:
17252 enum { Modifier, DefaultmapKind };
17253 Res = ActOnOpenMPDefaultmapClause(
17254 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
17255 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
17256 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
17257 EndLoc);
17258 break;
17259 case OMPC_order:
17260 enum { OrderModifier, OrderKind };
17261 Res = ActOnOpenMPOrderClause(
17262 static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
17263 static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
17264 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
17265 break;
17266 case OMPC_device:
17267 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17268 Res = ActOnOpenMPDeviceClause(
17269 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
17270 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17271 break;
17272 case OMPC_grainsize:
17273 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17274 "Modifier for grainsize clause and its location are expected.");
17275 Res = ActOnOpenMPGrainsizeClause(
17276 static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr,
17277 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17278 break;
17279 case OMPC_num_tasks:
17280 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17281 "Modifier for num_tasks clause and its location are expected.");
17282 Res = ActOnOpenMPNumTasksClause(
17283 static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
17284 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17285 break;
17286 case OMPC_final:
17287 case OMPC_num_threads:
17288 case OMPC_safelen:
17289 case OMPC_simdlen:
17290 case OMPC_sizes:
17291 case OMPC_allocator:
17292 case OMPC_collapse:
17293 case OMPC_default:
17294 case OMPC_proc_bind:
17295 case OMPC_private:
17296 case OMPC_firstprivate:
17297 case OMPC_lastprivate:
17298 case OMPC_shared:
17299 case OMPC_reduction:
17300 case OMPC_task_reduction:
17301 case OMPC_in_reduction:
17302 case OMPC_linear:
17303 case OMPC_aligned:
17304 case OMPC_copyin:
17305 case OMPC_copyprivate:
17306 case OMPC_ordered:
17307 case OMPC_nowait:
17308 case OMPC_untied:
17309 case OMPC_mergeable:
17310 case OMPC_threadprivate:
17311 case OMPC_allocate:
17312 case OMPC_flush:
17313 case OMPC_depobj:
17314 case OMPC_read:
17315 case OMPC_write:
17316 case OMPC_update:
17317 case OMPC_capture:
17318 case OMPC_compare:
17319 case OMPC_seq_cst:
17320 case OMPC_acq_rel:
17321 case OMPC_acquire:
17322 case OMPC_release:
17323 case OMPC_relaxed:
17324 case OMPC_depend:
17325 case OMPC_threads:
17326 case OMPC_simd:
17327 case OMPC_map:
17328 case OMPC_num_teams:
17329 case OMPC_thread_limit:
17330 case OMPC_priority:
17331 case OMPC_nogroup:
17332 case OMPC_hint:
17333 case OMPC_unknown:
17334 case OMPC_uniform:
17335 case OMPC_to:
17336 case OMPC_from:
17337 case OMPC_use_device_ptr:
17338 case OMPC_use_device_addr:
17339 case OMPC_is_device_ptr:
17340 case OMPC_has_device_addr:
17341 case OMPC_unified_address:
17342 case OMPC_unified_shared_memory:
17343 case OMPC_reverse_offload:
17344 case OMPC_dynamic_allocators:
17345 case OMPC_atomic_default_mem_order:
17346 case OMPC_device_type:
17347 case OMPC_match:
17348 case OMPC_nontemporal:
17349 case OMPC_at:
17350 case OMPC_severity:
17351 case OMPC_message:
17352 case OMPC_destroy:
17353 case OMPC_novariants:
17354 case OMPC_nocontext:
17355 case OMPC_detach:
17356 case OMPC_inclusive:
17357 case OMPC_exclusive:
17358 case OMPC_uses_allocators:
17359 case OMPC_affinity:
17360 case OMPC_when:
17361 case OMPC_bind:
17362 default:
17363 llvm_unreachable("Clause is not allowed.");
17365 return Res;
17368 static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1,
17369 OpenMPScheduleClauseModifier M2,
17370 SourceLocation M1Loc, SourceLocation M2Loc) {
17371 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
17372 SmallVector<unsigned, 2> Excluded;
17373 if (M2 != OMPC_SCHEDULE_MODIFIER_unknown)
17374 Excluded.push_back(M2);
17375 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
17376 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
17377 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
17378 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
17379 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
17380 << getListOfPossibleValues(OMPC_schedule,
17381 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
17382 /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
17383 Excluded)
17384 << getOpenMPClauseName(OMPC_schedule);
17385 return true;
17387 return false;
17390 OMPClause *Sema::ActOnOpenMPScheduleClause(
17391 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
17392 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
17393 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
17394 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
17395 if (checkScheduleModifiers(*this, M1, M2, M1Loc, M2Loc) ||
17396 checkScheduleModifiers(*this, M2, M1, M2Loc, M1Loc))
17397 return nullptr;
17398 // OpenMP, 2.7.1, Loop Construct, Restrictions
17399 // Either the monotonic modifier or the nonmonotonic modifier can be specified
17400 // but not both.
17401 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
17402 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
17403 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
17404 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
17405 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
17406 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
17407 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
17408 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
17409 return nullptr;
17411 if (Kind == OMPC_SCHEDULE_unknown) {
17412 std::string Values;
17413 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
17414 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
17415 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
17416 /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
17417 Exclude);
17418 } else {
17419 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
17420 /*Last=*/OMPC_SCHEDULE_unknown);
17422 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17423 << Values << getOpenMPClauseName(OMPC_schedule);
17424 return nullptr;
17426 // OpenMP, 2.7.1, Loop Construct, Restrictions
17427 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
17428 // schedule(guided).
17429 // OpenMP 5.0 does not have this restriction.
17430 if (LangOpts.OpenMP < 50 &&
17431 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
17432 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
17433 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
17434 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
17435 diag::err_omp_schedule_nonmonotonic_static);
17436 return nullptr;
17438 Expr *ValExpr = ChunkSize;
17439 Stmt *HelperValStmt = nullptr;
17440 if (ChunkSize) {
17441 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
17442 !ChunkSize->isInstantiationDependent() &&
17443 !ChunkSize->containsUnexpandedParameterPack()) {
17444 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
17445 ExprResult Val =
17446 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
17447 if (Val.isInvalid())
17448 return nullptr;
17450 ValExpr = Val.get();
17452 // OpenMP [2.7.1, Restrictions]
17453 // chunk_size must be a loop invariant integer expression with a positive
17454 // value.
17455 if (std::optional<llvm::APSInt> Result =
17456 ValExpr->getIntegerConstantExpr(Context)) {
17457 if (Result->isSigned() && !Result->isStrictlyPositive()) {
17458 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
17459 << "schedule" << 1 << ChunkSize->getSourceRange();
17460 return nullptr;
17462 } else if (getOpenMPCaptureRegionForClause(
17463 DSAStack->getCurrentDirective(), OMPC_schedule,
17464 LangOpts.OpenMP) != OMPD_unknown &&
17465 !CurContext->isDependentContext()) {
17466 ValExpr = MakeFullExpr(ValExpr).get();
17467 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17468 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
17469 HelperValStmt = buildPreInits(Context, Captures);
17474 return new (Context)
17475 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
17476 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
17479 OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
17480 SourceLocation StartLoc,
17481 SourceLocation EndLoc) {
17482 OMPClause *Res = nullptr;
17483 switch (Kind) {
17484 case OMPC_ordered:
17485 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
17486 break;
17487 case OMPC_nowait:
17488 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc);
17489 break;
17490 case OMPC_untied:
17491 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
17492 break;
17493 case OMPC_mergeable:
17494 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
17495 break;
17496 case OMPC_read:
17497 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
17498 break;
17499 case OMPC_write:
17500 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
17501 break;
17502 case OMPC_update:
17503 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
17504 break;
17505 case OMPC_capture:
17506 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
17507 break;
17508 case OMPC_compare:
17509 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
17510 break;
17511 case OMPC_seq_cst:
17512 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
17513 break;
17514 case OMPC_acq_rel:
17515 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
17516 break;
17517 case OMPC_acquire:
17518 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
17519 break;
17520 case OMPC_release:
17521 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
17522 break;
17523 case OMPC_relaxed:
17524 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
17525 break;
17526 case OMPC_threads:
17527 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
17528 break;
17529 case OMPC_simd:
17530 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
17531 break;
17532 case OMPC_nogroup:
17533 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
17534 break;
17535 case OMPC_unified_address:
17536 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
17537 break;
17538 case OMPC_unified_shared_memory:
17539 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
17540 break;
17541 case OMPC_reverse_offload:
17542 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
17543 break;
17544 case OMPC_dynamic_allocators:
17545 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
17546 break;
17547 case OMPC_destroy:
17548 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
17549 /*LParenLoc=*/SourceLocation(),
17550 /*VarLoc=*/SourceLocation(), EndLoc);
17551 break;
17552 case OMPC_full:
17553 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
17554 break;
17555 case OMPC_partial:
17556 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
17557 break;
17558 case OMPC_if:
17559 case OMPC_final:
17560 case OMPC_num_threads:
17561 case OMPC_safelen:
17562 case OMPC_simdlen:
17563 case OMPC_sizes:
17564 case OMPC_allocator:
17565 case OMPC_collapse:
17566 case OMPC_schedule:
17567 case OMPC_private:
17568 case OMPC_firstprivate:
17569 case OMPC_lastprivate:
17570 case OMPC_shared:
17571 case OMPC_reduction:
17572 case OMPC_task_reduction:
17573 case OMPC_in_reduction:
17574 case OMPC_linear:
17575 case OMPC_aligned:
17576 case OMPC_copyin:
17577 case OMPC_copyprivate:
17578 case OMPC_default:
17579 case OMPC_proc_bind:
17580 case OMPC_threadprivate:
17581 case OMPC_allocate:
17582 case OMPC_flush:
17583 case OMPC_depobj:
17584 case OMPC_depend:
17585 case OMPC_device:
17586 case OMPC_map:
17587 case OMPC_num_teams:
17588 case OMPC_thread_limit:
17589 case OMPC_priority:
17590 case OMPC_grainsize:
17591 case OMPC_num_tasks:
17592 case OMPC_hint:
17593 case OMPC_dist_schedule:
17594 case OMPC_defaultmap:
17595 case OMPC_unknown:
17596 case OMPC_uniform:
17597 case OMPC_to:
17598 case OMPC_from:
17599 case OMPC_use_device_ptr:
17600 case OMPC_use_device_addr:
17601 case OMPC_is_device_ptr:
17602 case OMPC_has_device_addr:
17603 case OMPC_atomic_default_mem_order:
17604 case OMPC_device_type:
17605 case OMPC_match:
17606 case OMPC_nontemporal:
17607 case OMPC_order:
17608 case OMPC_at:
17609 case OMPC_severity:
17610 case OMPC_message:
17611 case OMPC_novariants:
17612 case OMPC_nocontext:
17613 case OMPC_detach:
17614 case OMPC_inclusive:
17615 case OMPC_exclusive:
17616 case OMPC_uses_allocators:
17617 case OMPC_affinity:
17618 case OMPC_when:
17619 case OMPC_ompx_dyn_cgroup_mem:
17620 default:
17621 llvm_unreachable("Clause is not allowed.");
17623 return Res;
17626 OMPClause *Sema::ActOnOpenMPNowaitClause(SourceLocation StartLoc,
17627 SourceLocation EndLoc) {
17628 DSAStack->setNowaitRegion();
17629 return new (Context) OMPNowaitClause(StartLoc, EndLoc);
17632 OMPClause *Sema::ActOnOpenMPUntiedClause(SourceLocation StartLoc,
17633 SourceLocation EndLoc) {
17634 DSAStack->setUntiedRegion();
17635 return new (Context) OMPUntiedClause(StartLoc, EndLoc);
17638 OMPClause *Sema::ActOnOpenMPMergeableClause(SourceLocation StartLoc,
17639 SourceLocation EndLoc) {
17640 return new (Context) OMPMergeableClause(StartLoc, EndLoc);
17643 OMPClause *Sema::ActOnOpenMPReadClause(SourceLocation StartLoc,
17644 SourceLocation EndLoc) {
17645 return new (Context) OMPReadClause(StartLoc, EndLoc);
17648 OMPClause *Sema::ActOnOpenMPWriteClause(SourceLocation StartLoc,
17649 SourceLocation EndLoc) {
17650 return new (Context) OMPWriteClause(StartLoc, EndLoc);
17653 OMPClause *Sema::ActOnOpenMPUpdateClause(SourceLocation StartLoc,
17654 SourceLocation EndLoc) {
17655 return OMPUpdateClause::Create(Context, StartLoc, EndLoc);
17658 OMPClause *Sema::ActOnOpenMPCaptureClause(SourceLocation StartLoc,
17659 SourceLocation EndLoc) {
17660 return new (Context) OMPCaptureClause(StartLoc, EndLoc);
17663 OMPClause *Sema::ActOnOpenMPCompareClause(SourceLocation StartLoc,
17664 SourceLocation EndLoc) {
17665 return new (Context) OMPCompareClause(StartLoc, EndLoc);
17668 OMPClause *Sema::ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
17669 SourceLocation EndLoc) {
17670 return new (Context) OMPSeqCstClause(StartLoc, EndLoc);
17673 OMPClause *Sema::ActOnOpenMPAcqRelClause(SourceLocation StartLoc,
17674 SourceLocation EndLoc) {
17675 return new (Context) OMPAcqRelClause(StartLoc, EndLoc);
17678 OMPClause *Sema::ActOnOpenMPAcquireClause(SourceLocation StartLoc,
17679 SourceLocation EndLoc) {
17680 return new (Context) OMPAcquireClause(StartLoc, EndLoc);
17683 OMPClause *Sema::ActOnOpenMPReleaseClause(SourceLocation StartLoc,
17684 SourceLocation EndLoc) {
17685 return new (Context) OMPReleaseClause(StartLoc, EndLoc);
17688 OMPClause *Sema::ActOnOpenMPRelaxedClause(SourceLocation StartLoc,
17689 SourceLocation EndLoc) {
17690 return new (Context) OMPRelaxedClause(StartLoc, EndLoc);
17693 OMPClause *Sema::ActOnOpenMPThreadsClause(SourceLocation StartLoc,
17694 SourceLocation EndLoc) {
17695 return new (Context) OMPThreadsClause(StartLoc, EndLoc);
17698 OMPClause *Sema::ActOnOpenMPSIMDClause(SourceLocation StartLoc,
17699 SourceLocation EndLoc) {
17700 return new (Context) OMPSIMDClause(StartLoc, EndLoc);
17703 OMPClause *Sema::ActOnOpenMPNogroupClause(SourceLocation StartLoc,
17704 SourceLocation EndLoc) {
17705 return new (Context) OMPNogroupClause(StartLoc, EndLoc);
17708 OMPClause *Sema::ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc,
17709 SourceLocation EndLoc) {
17710 return new (Context) OMPUnifiedAddressClause(StartLoc, EndLoc);
17713 OMPClause *Sema::ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc,
17714 SourceLocation EndLoc) {
17715 return new (Context) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
17718 OMPClause *Sema::ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc,
17719 SourceLocation EndLoc) {
17720 return new (Context) OMPReverseOffloadClause(StartLoc, EndLoc);
17723 OMPClause *Sema::ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc,
17724 SourceLocation EndLoc) {
17725 return new (Context) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
17728 StmtResult Sema::ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses,
17729 SourceLocation StartLoc,
17730 SourceLocation EndLoc) {
17732 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17733 // At least one action-clause must appear on a directive.
17734 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
17735 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
17736 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
17737 << Expected << getOpenMPDirectiveName(OMPD_interop);
17738 return StmtError();
17741 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17742 // A depend clause can only appear on the directive if a targetsync
17743 // interop-type is present or the interop-var was initialized with
17744 // the targetsync interop-type.
17746 // If there is any 'init' clause diagnose if there is no 'init' clause with
17747 // interop-type of 'targetsync'. Cases involving other directives cannot be
17748 // diagnosed.
17749 const OMPDependClause *DependClause = nullptr;
17750 bool HasInitClause = false;
17751 bool IsTargetSync = false;
17752 for (const OMPClause *C : Clauses) {
17753 if (IsTargetSync)
17754 break;
17755 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
17756 HasInitClause = true;
17757 if (InitClause->getIsTargetSync())
17758 IsTargetSync = true;
17759 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
17760 DependClause = DC;
17763 if (DependClause && HasInitClause && !IsTargetSync) {
17764 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
17765 return StmtError();
17768 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17769 // Each interop-var may be specified for at most one action-clause of each
17770 // interop construct.
17771 llvm::SmallPtrSet<const ValueDecl *, 4> InteropVars;
17772 for (OMPClause *C : Clauses) {
17773 OpenMPClauseKind ClauseKind = C->getClauseKind();
17774 std::pair<ValueDecl *, bool> DeclResult;
17775 SourceLocation ELoc;
17776 SourceRange ERange;
17778 if (ClauseKind == OMPC_init) {
17779 auto *E = cast<OMPInitClause>(C)->getInteropVar();
17780 DeclResult = getPrivateItem(*this, E, ELoc, ERange);
17781 } else if (ClauseKind == OMPC_use) {
17782 auto *E = cast<OMPUseClause>(C)->getInteropVar();
17783 DeclResult = getPrivateItem(*this, E, ELoc, ERange);
17784 } else if (ClauseKind == OMPC_destroy) {
17785 auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
17786 DeclResult = getPrivateItem(*this, E, ELoc, ERange);
17789 if (DeclResult.first) {
17790 if (!InteropVars.insert(DeclResult.first).second) {
17791 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
17792 << DeclResult.first;
17793 return StmtError();
17798 return OMPInteropDirective::Create(Context, StartLoc, EndLoc, Clauses);
17801 static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
17802 SourceLocation VarLoc,
17803 OpenMPClauseKind Kind) {
17804 SourceLocation ELoc;
17805 SourceRange ERange;
17806 Expr *RefExpr = InteropVarExpr;
17807 auto Res =
17808 getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
17809 /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t");
17811 if (Res.second) {
17812 // It will be analyzed later.
17813 return true;
17816 if (!Res.first)
17817 return false;
17819 // Interop variable should be of type omp_interop_t.
17820 bool HasError = false;
17821 QualType InteropType;
17822 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
17823 VarLoc, Sema::LookupOrdinaryName);
17824 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
17825 NamedDecl *ND = Result.getFoundDecl();
17826 if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
17827 InteropType = QualType(TD->getTypeForDecl(), 0);
17828 } else {
17829 HasError = true;
17831 } else {
17832 HasError = true;
17835 if (HasError) {
17836 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
17837 << "omp_interop_t";
17838 return false;
17841 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
17842 if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
17843 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
17844 return false;
17847 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17848 // The interop-var passed to init or destroy must be non-const.
17849 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
17850 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
17851 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
17852 << /*non-const*/ 1;
17853 return false;
17855 return true;
17858 OMPClause *
17859 Sema::ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo,
17860 SourceLocation StartLoc, SourceLocation LParenLoc,
17861 SourceLocation VarLoc, SourceLocation EndLoc) {
17863 if (!isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_init))
17864 return nullptr;
17866 // Check prefer_type values. These foreign-runtime-id values are either
17867 // string literals or constant integral expressions.
17868 for (const Expr *E : InteropInfo.PreferTypes) {
17869 if (E->isValueDependent() || E->isTypeDependent() ||
17870 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
17871 continue;
17872 if (E->isIntegerConstantExpr(Context))
17873 continue;
17874 if (isa<StringLiteral>(E))
17875 continue;
17876 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
17877 return nullptr;
17880 return OMPInitClause::Create(Context, InteropVar, InteropInfo, StartLoc,
17881 LParenLoc, VarLoc, EndLoc);
17884 OMPClause *Sema::ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc,
17885 SourceLocation LParenLoc,
17886 SourceLocation VarLoc,
17887 SourceLocation EndLoc) {
17889 if (!isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_use))
17890 return nullptr;
17892 return new (Context)
17893 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
17896 OMPClause *Sema::ActOnOpenMPDestroyClause(Expr *InteropVar,
17897 SourceLocation StartLoc,
17898 SourceLocation LParenLoc,
17899 SourceLocation VarLoc,
17900 SourceLocation EndLoc) {
17901 if (!InteropVar && LangOpts.OpenMP >= 52 &&
17902 DSAStack->getCurrentDirective() == OMPD_depobj) {
17903 Diag(StartLoc, diag::err_omp_expected_clause_argument)
17904 << getOpenMPClauseName(OMPC_destroy)
17905 << getOpenMPDirectiveName(OMPD_depobj);
17906 return nullptr;
17908 if (InteropVar &&
17909 !isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_destroy))
17910 return nullptr;
17912 return new (Context)
17913 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
17916 OMPClause *Sema::ActOnOpenMPNovariantsClause(Expr *Condition,
17917 SourceLocation StartLoc,
17918 SourceLocation LParenLoc,
17919 SourceLocation EndLoc) {
17920 Expr *ValExpr = Condition;
17921 Stmt *HelperValStmt = nullptr;
17922 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17923 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17924 !Condition->isInstantiationDependent() &&
17925 !Condition->containsUnexpandedParameterPack()) {
17926 ExprResult Val = CheckBooleanCondition(StartLoc, Condition);
17927 if (Val.isInvalid())
17928 return nullptr;
17930 ValExpr = MakeFullExpr(Val.get()).get();
17932 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17933 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
17934 LangOpts.OpenMP);
17935 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
17936 ValExpr = MakeFullExpr(ValExpr).get();
17937 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17938 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
17939 HelperValStmt = buildPreInits(Context, Captures);
17943 return new (Context) OMPNovariantsClause(
17944 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17947 OMPClause *Sema::ActOnOpenMPNocontextClause(Expr *Condition,
17948 SourceLocation StartLoc,
17949 SourceLocation LParenLoc,
17950 SourceLocation EndLoc) {
17951 Expr *ValExpr = Condition;
17952 Stmt *HelperValStmt = nullptr;
17953 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17954 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17955 !Condition->isInstantiationDependent() &&
17956 !Condition->containsUnexpandedParameterPack()) {
17957 ExprResult Val = CheckBooleanCondition(StartLoc, Condition);
17958 if (Val.isInvalid())
17959 return nullptr;
17961 ValExpr = MakeFullExpr(Val.get()).get();
17963 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17964 CaptureRegion =
17965 getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext, LangOpts.OpenMP);
17966 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
17967 ValExpr = MakeFullExpr(ValExpr).get();
17968 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17969 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
17970 HelperValStmt = buildPreInits(Context, Captures);
17974 return new (Context) OMPNocontextClause(ValExpr, HelperValStmt, CaptureRegion,
17975 StartLoc, LParenLoc, EndLoc);
17978 OMPClause *Sema::ActOnOpenMPFilterClause(Expr *ThreadID,
17979 SourceLocation StartLoc,
17980 SourceLocation LParenLoc,
17981 SourceLocation EndLoc) {
17982 Expr *ValExpr = ThreadID;
17983 Stmt *HelperValStmt = nullptr;
17985 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17986 OpenMPDirectiveKind CaptureRegion =
17987 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, LangOpts.OpenMP);
17988 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
17989 ValExpr = MakeFullExpr(ValExpr).get();
17990 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17991 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
17992 HelperValStmt = buildPreInits(Context, Captures);
17995 return new (Context) OMPFilterClause(ValExpr, HelperValStmt, CaptureRegion,
17996 StartLoc, LParenLoc, EndLoc);
17999 OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
18000 ArrayRef<Expr *> VarList,
18001 const OMPVarListLocTy &Locs,
18002 OpenMPVarListDataTy &Data) {
18003 SourceLocation StartLoc = Locs.StartLoc;
18004 SourceLocation LParenLoc = Locs.LParenLoc;
18005 SourceLocation EndLoc = Locs.EndLoc;
18006 OMPClause *Res = nullptr;
18007 int ExtraModifier = Data.ExtraModifier;
18008 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
18009 SourceLocation ColonLoc = Data.ColonLoc;
18010 switch (Kind) {
18011 case OMPC_private:
18012 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18013 break;
18014 case OMPC_firstprivate:
18015 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18016 break;
18017 case OMPC_lastprivate:
18018 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
18019 "Unexpected lastprivate modifier.");
18020 Res = ActOnOpenMPLastprivateClause(
18021 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
18022 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
18023 break;
18024 case OMPC_shared:
18025 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
18026 break;
18027 case OMPC_reduction:
18028 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
18029 "Unexpected lastprivate modifier.");
18030 Res = ActOnOpenMPReductionClause(
18031 VarList, static_cast<OpenMPReductionClauseModifier>(ExtraModifier),
18032 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
18033 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18034 break;
18035 case OMPC_task_reduction:
18036 Res = ActOnOpenMPTaskReductionClause(
18037 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18038 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18039 break;
18040 case OMPC_in_reduction:
18041 Res = ActOnOpenMPInReductionClause(
18042 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18043 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18044 break;
18045 case OMPC_linear:
18046 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
18047 "Unexpected linear modifier.");
18048 Res = ActOnOpenMPLinearClause(
18049 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
18050 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
18051 ColonLoc, EndLoc);
18052 break;
18053 case OMPC_aligned:
18054 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
18055 LParenLoc, ColonLoc, EndLoc);
18056 break;
18057 case OMPC_copyin:
18058 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
18059 break;
18060 case OMPC_copyprivate:
18061 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18062 break;
18063 case OMPC_flush:
18064 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
18065 break;
18066 case OMPC_depend:
18067 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
18068 "Unexpected depend modifier.");
18069 Res = ActOnOpenMPDependClause(
18070 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
18071 ColonLoc, Data.OmpAllMemoryLoc},
18072 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
18073 break;
18074 case OMPC_map:
18075 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
18076 "Unexpected map modifier.");
18077 Res = ActOnOpenMPMapClause(
18078 Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
18079 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
18080 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
18081 ExtraModifierLoc, ColonLoc, VarList, Locs);
18082 break;
18083 case OMPC_to:
18084 Res =
18085 ActOnOpenMPToClause(Data.MotionModifiers, Data.MotionModifiersLoc,
18086 Data.ReductionOrMapperIdScopeSpec,
18087 Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
18088 break;
18089 case OMPC_from:
18090 Res = ActOnOpenMPFromClause(Data.MotionModifiers, Data.MotionModifiersLoc,
18091 Data.ReductionOrMapperIdScopeSpec,
18092 Data.ReductionOrMapperId, ColonLoc, VarList,
18093 Locs);
18094 break;
18095 case OMPC_use_device_ptr:
18096 Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
18097 break;
18098 case OMPC_use_device_addr:
18099 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
18100 break;
18101 case OMPC_is_device_ptr:
18102 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
18103 break;
18104 case OMPC_has_device_addr:
18105 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
18106 break;
18107 case OMPC_allocate:
18108 Res = ActOnOpenMPAllocateClause(Data.DepModOrTailExpr, VarList, StartLoc,
18109 LParenLoc, ColonLoc, EndLoc);
18110 break;
18111 case OMPC_nontemporal:
18112 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
18113 break;
18114 case OMPC_inclusive:
18115 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
18116 break;
18117 case OMPC_exclusive:
18118 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
18119 break;
18120 case OMPC_affinity:
18121 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
18122 Data.DepModOrTailExpr, VarList);
18123 break;
18124 case OMPC_doacross:
18125 Res = ActOnOpenMPDoacrossClause(
18126 static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
18127 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
18128 break;
18129 case OMPC_if:
18130 case OMPC_depobj:
18131 case OMPC_final:
18132 case OMPC_num_threads:
18133 case OMPC_safelen:
18134 case OMPC_simdlen:
18135 case OMPC_sizes:
18136 case OMPC_allocator:
18137 case OMPC_collapse:
18138 case OMPC_default:
18139 case OMPC_proc_bind:
18140 case OMPC_schedule:
18141 case OMPC_ordered:
18142 case OMPC_nowait:
18143 case OMPC_untied:
18144 case OMPC_mergeable:
18145 case OMPC_threadprivate:
18146 case OMPC_read:
18147 case OMPC_write:
18148 case OMPC_update:
18149 case OMPC_capture:
18150 case OMPC_compare:
18151 case OMPC_seq_cst:
18152 case OMPC_acq_rel:
18153 case OMPC_acquire:
18154 case OMPC_release:
18155 case OMPC_relaxed:
18156 case OMPC_device:
18157 case OMPC_threads:
18158 case OMPC_simd:
18159 case OMPC_num_teams:
18160 case OMPC_thread_limit:
18161 case OMPC_priority:
18162 case OMPC_grainsize:
18163 case OMPC_nogroup:
18164 case OMPC_num_tasks:
18165 case OMPC_hint:
18166 case OMPC_dist_schedule:
18167 case OMPC_defaultmap:
18168 case OMPC_unknown:
18169 case OMPC_uniform:
18170 case OMPC_unified_address:
18171 case OMPC_unified_shared_memory:
18172 case OMPC_reverse_offload:
18173 case OMPC_dynamic_allocators:
18174 case OMPC_atomic_default_mem_order:
18175 case OMPC_device_type:
18176 case OMPC_match:
18177 case OMPC_order:
18178 case OMPC_at:
18179 case OMPC_severity:
18180 case OMPC_message:
18181 case OMPC_destroy:
18182 case OMPC_novariants:
18183 case OMPC_nocontext:
18184 case OMPC_detach:
18185 case OMPC_uses_allocators:
18186 case OMPC_when:
18187 case OMPC_bind:
18188 default:
18189 llvm_unreachable("Clause is not allowed.");
18191 return Res;
18194 ExprResult Sema::getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
18195 ExprObjectKind OK, SourceLocation Loc) {
18196 ExprResult Res = BuildDeclRefExpr(
18197 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
18198 if (!Res.isUsable())
18199 return ExprError();
18200 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
18201 Res = CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
18202 if (!Res.isUsable())
18203 return ExprError();
18205 if (VK != VK_LValue && Res.get()->isGLValue()) {
18206 Res = DefaultLvalueConversion(Res.get());
18207 if (!Res.isUsable())
18208 return ExprError();
18210 return Res;
18213 OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
18214 SourceLocation StartLoc,
18215 SourceLocation LParenLoc,
18216 SourceLocation EndLoc) {
18217 SmallVector<Expr *, 8> Vars;
18218 SmallVector<Expr *, 8> PrivateCopies;
18219 bool IsImplicitClause =
18220 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
18221 for (Expr *RefExpr : VarList) {
18222 assert(RefExpr && "NULL expr in OpenMP private clause.");
18223 SourceLocation ELoc;
18224 SourceRange ERange;
18225 Expr *SimpleRefExpr = RefExpr;
18226 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
18227 if (Res.second) {
18228 // It will be analyzed later.
18229 Vars.push_back(RefExpr);
18230 PrivateCopies.push_back(nullptr);
18232 ValueDecl *D = Res.first;
18233 if (!D)
18234 continue;
18236 QualType Type = D->getType();
18237 auto *VD = dyn_cast<VarDecl>(D);
18239 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18240 // A variable that appears in a private clause must not have an incomplete
18241 // type or a reference type.
18242 if (RequireCompleteType(ELoc, Type, diag::err_omp_private_incomplete_type))
18243 continue;
18244 Type = Type.getNonReferenceType();
18246 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18247 // A variable that is privatized must not have a const-qualified type
18248 // unless it is of class type with a mutable member. This restriction does
18249 // not apply to the firstprivate clause.
18251 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
18252 // A variable that appears in a private clause must not have a
18253 // const-qualified type unless it is of class type with a mutable member.
18254 if (rejectConstNotMutableType(*this, D, Type, OMPC_private, ELoc))
18255 continue;
18257 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18258 // in a Construct]
18259 // Variables with the predetermined data-sharing attributes may not be
18260 // listed in data-sharing attributes clauses, except for the cases
18261 // listed below. For these exceptions only, listing a predetermined
18262 // variable in a data-sharing attribute clause is allowed and overrides
18263 // the variable's predetermined data-sharing attributes.
18264 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18265 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
18266 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
18267 << getOpenMPClauseName(OMPC_private);
18268 reportOriginalDsa(*this, DSAStack, D, DVar);
18269 continue;
18272 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18273 // Variably modified types are not supported for tasks.
18274 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
18275 isOpenMPTaskingDirective(CurrDir)) {
18276 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18277 << getOpenMPClauseName(OMPC_private) << Type
18278 << getOpenMPDirectiveName(CurrDir);
18279 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18280 VarDecl::DeclarationOnly;
18281 Diag(D->getLocation(),
18282 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18283 << D;
18284 continue;
18287 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18288 // A list item cannot appear in both a map clause and a data-sharing
18289 // attribute clause on the same construct
18291 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18292 // A list item cannot appear in both a map clause and a data-sharing
18293 // attribute clause on the same construct unless the construct is a
18294 // combined construct.
18295 if ((LangOpts.OpenMP <= 45 && isOpenMPTargetExecutionDirective(CurrDir)) ||
18296 CurrDir == OMPD_target) {
18297 OpenMPClauseKind ConflictKind;
18298 if (DSAStack->checkMappableExprComponentListsForDecl(
18299 VD, /*CurrentRegionOnly=*/true,
18300 [&](OMPClauseMappableExprCommon::MappableExprComponentListRef,
18301 OpenMPClauseKind WhereFoundClauseKind) -> bool {
18302 ConflictKind = WhereFoundClauseKind;
18303 return true;
18304 })) {
18305 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18306 << getOpenMPClauseName(OMPC_private)
18307 << getOpenMPClauseName(ConflictKind)
18308 << getOpenMPDirectiveName(CurrDir);
18309 reportOriginalDsa(*this, DSAStack, D, DVar);
18310 continue;
18314 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
18315 // A variable of class type (or array thereof) that appears in a private
18316 // clause requires an accessible, unambiguous default constructor for the
18317 // class type.
18318 // Generate helper private variable and initialize it with the default
18319 // value. The address of the original variable is replaced by the address of
18320 // the new private variable in CodeGen. This new variable is not added to
18321 // IdResolver, so the code in the OpenMP region uses original variable for
18322 // proper diagnostics.
18323 Type = Type.getUnqualifiedType();
18324 VarDecl *VDPrivate =
18325 buildVarDecl(*this, ELoc, Type, D->getName(),
18326 D->hasAttrs() ? &D->getAttrs() : nullptr,
18327 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18328 ActOnUninitializedDecl(VDPrivate);
18329 if (VDPrivate->isInvalidDecl())
18330 continue;
18331 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18332 *this, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
18334 DeclRefExpr *Ref = nullptr;
18335 if (!VD && !CurContext->isDependentContext()) {
18336 auto *FD = dyn_cast<FieldDecl>(D);
18337 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
18338 if (VD)
18339 Ref = buildDeclRefExpr(*this, VD, VD->getType().getNonReferenceType(),
18340 RefExpr->getExprLoc());
18341 else
18342 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
18344 if (!IsImplicitClause)
18345 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
18346 Vars.push_back((VD || CurContext->isDependentContext())
18347 ? RefExpr->IgnoreParens()
18348 : Ref);
18349 PrivateCopies.push_back(VDPrivateRefExpr);
18352 if (Vars.empty())
18353 return nullptr;
18355 return OMPPrivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars,
18356 PrivateCopies);
18359 OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
18360 SourceLocation StartLoc,
18361 SourceLocation LParenLoc,
18362 SourceLocation EndLoc) {
18363 SmallVector<Expr *, 8> Vars;
18364 SmallVector<Expr *, 8> PrivateCopies;
18365 SmallVector<Expr *, 8> Inits;
18366 SmallVector<Decl *, 4> ExprCaptures;
18367 bool IsImplicitClause =
18368 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
18369 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
18371 for (Expr *RefExpr : VarList) {
18372 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
18373 SourceLocation ELoc;
18374 SourceRange ERange;
18375 Expr *SimpleRefExpr = RefExpr;
18376 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
18377 if (Res.second) {
18378 // It will be analyzed later.
18379 Vars.push_back(RefExpr);
18380 PrivateCopies.push_back(nullptr);
18381 Inits.push_back(nullptr);
18383 ValueDecl *D = Res.first;
18384 if (!D)
18385 continue;
18387 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
18388 QualType Type = D->getType();
18389 auto *VD = dyn_cast<VarDecl>(D);
18391 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18392 // A variable that appears in a private clause must not have an incomplete
18393 // type or a reference type.
18394 if (RequireCompleteType(ELoc, Type,
18395 diag::err_omp_firstprivate_incomplete_type))
18396 continue;
18397 Type = Type.getNonReferenceType();
18399 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
18400 // A variable of class type (or array thereof) that appears in a private
18401 // clause requires an accessible, unambiguous copy constructor for the
18402 // class type.
18403 QualType ElemType = Context.getBaseElementType(Type).getNonReferenceType();
18405 // If an implicit firstprivate variable found it was checked already.
18406 DSAStackTy::DSAVarData TopDVar;
18407 if (!IsImplicitClause) {
18408 DSAStackTy::DSAVarData DVar =
18409 DSAStack->getTopDSA(D, /*FromParent=*/false);
18410 TopDVar = DVar;
18411 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18412 bool IsConstant = ElemType.isConstant(Context);
18413 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
18414 // A list item that specifies a given variable may not appear in more
18415 // than one clause on the same directive, except that a variable may be
18416 // specified in both firstprivate and lastprivate clauses.
18417 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18418 // A list item may appear in a firstprivate or lastprivate clause but not
18419 // both.
18420 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
18421 (isOpenMPDistributeDirective(CurrDir) ||
18422 DVar.CKind != OMPC_lastprivate) &&
18423 DVar.RefExpr) {
18424 Diag(ELoc, diag::err_omp_wrong_dsa)
18425 << getOpenMPClauseName(DVar.CKind)
18426 << getOpenMPClauseName(OMPC_firstprivate);
18427 reportOriginalDsa(*this, DSAStack, D, DVar);
18428 continue;
18431 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18432 // in a Construct]
18433 // Variables with the predetermined data-sharing attributes may not be
18434 // listed in data-sharing attributes clauses, except for the cases
18435 // listed below. For these exceptions only, listing a predetermined
18436 // variable in a data-sharing attribute clause is allowed and overrides
18437 // the variable's predetermined data-sharing attributes.
18438 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18439 // in a Construct, C/C++, p.2]
18440 // Variables with const-qualified type having no mutable member may be
18441 // listed in a firstprivate clause, even if they are static data members.
18442 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
18443 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
18444 Diag(ELoc, diag::err_omp_wrong_dsa)
18445 << getOpenMPClauseName(DVar.CKind)
18446 << getOpenMPClauseName(OMPC_firstprivate);
18447 reportOriginalDsa(*this, DSAStack, D, DVar);
18448 continue;
18451 // OpenMP [2.9.3.4, Restrictions, p.2]
18452 // A list item that is private within a parallel region must not appear
18453 // in a firstprivate clause on a worksharing construct if any of the
18454 // worksharing regions arising from the worksharing construct ever bind
18455 // to any of the parallel regions arising from the parallel construct.
18456 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18457 // A list item that is private within a teams region must not appear in a
18458 // firstprivate clause on a distribute construct if any of the distribute
18459 // regions arising from the distribute construct ever bind to any of the
18460 // teams regions arising from the teams construct.
18461 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18462 // A list item that appears in a reduction clause of a teams construct
18463 // must not appear in a firstprivate clause on a distribute construct if
18464 // any of the distribute regions arising from the distribute construct
18465 // ever bind to any of the teams regions arising from the teams construct.
18466 if ((isOpenMPWorksharingDirective(CurrDir) ||
18467 isOpenMPDistributeDirective(CurrDir)) &&
18468 !isOpenMPParallelDirective(CurrDir) &&
18469 !isOpenMPTeamsDirective(CurrDir)) {
18470 DVar = DSAStack->getImplicitDSA(D, true);
18471 if (DVar.CKind != OMPC_shared &&
18472 (isOpenMPParallelDirective(DVar.DKind) ||
18473 isOpenMPTeamsDirective(DVar.DKind) ||
18474 DVar.DKind == OMPD_unknown)) {
18475 Diag(ELoc, diag::err_omp_required_access)
18476 << getOpenMPClauseName(OMPC_firstprivate)
18477 << getOpenMPClauseName(OMPC_shared);
18478 reportOriginalDsa(*this, DSAStack, D, DVar);
18479 continue;
18482 // OpenMP [2.9.3.4, Restrictions, p.3]
18483 // A list item that appears in a reduction clause of a parallel construct
18484 // must not appear in a firstprivate clause on a worksharing or task
18485 // construct if any of the worksharing or task regions arising from the
18486 // worksharing or task construct ever bind to any of the parallel regions
18487 // arising from the parallel construct.
18488 // OpenMP [2.9.3.4, Restrictions, p.4]
18489 // A list item that appears in a reduction clause in worksharing
18490 // construct must not appear in a firstprivate clause in a task construct
18491 // encountered during execution of any of the worksharing regions arising
18492 // from the worksharing construct.
18493 if (isOpenMPTaskingDirective(CurrDir)) {
18494 DVar = DSAStack->hasInnermostDSA(
18496 [](OpenMPClauseKind C, bool AppliedToPointee) {
18497 return C == OMPC_reduction && !AppliedToPointee;
18499 [](OpenMPDirectiveKind K) {
18500 return isOpenMPParallelDirective(K) ||
18501 isOpenMPWorksharingDirective(K) ||
18502 isOpenMPTeamsDirective(K);
18504 /*FromParent=*/true);
18505 if (DVar.CKind == OMPC_reduction &&
18506 (isOpenMPParallelDirective(DVar.DKind) ||
18507 isOpenMPWorksharingDirective(DVar.DKind) ||
18508 isOpenMPTeamsDirective(DVar.DKind))) {
18509 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
18510 << getOpenMPDirectiveName(DVar.DKind);
18511 reportOriginalDsa(*this, DSAStack, D, DVar);
18512 continue;
18516 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18517 // A list item cannot appear in both a map clause and a data-sharing
18518 // attribute clause on the same construct
18520 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18521 // A list item cannot appear in both a map clause and a data-sharing
18522 // attribute clause on the same construct unless the construct is a
18523 // combined construct.
18524 if ((LangOpts.OpenMP <= 45 &&
18525 isOpenMPTargetExecutionDirective(CurrDir)) ||
18526 CurrDir == OMPD_target) {
18527 OpenMPClauseKind ConflictKind;
18528 if (DSAStack->checkMappableExprComponentListsForDecl(
18529 VD, /*CurrentRegionOnly=*/true,
18530 [&ConflictKind](
18531 OMPClauseMappableExprCommon::MappableExprComponentListRef,
18532 OpenMPClauseKind WhereFoundClauseKind) {
18533 ConflictKind = WhereFoundClauseKind;
18534 return true;
18535 })) {
18536 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18537 << getOpenMPClauseName(OMPC_firstprivate)
18538 << getOpenMPClauseName(ConflictKind)
18539 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
18540 reportOriginalDsa(*this, DSAStack, D, DVar);
18541 continue;
18546 // Variably modified types are not supported for tasks.
18547 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
18548 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
18549 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18550 << getOpenMPClauseName(OMPC_firstprivate) << Type
18551 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
18552 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18553 VarDecl::DeclarationOnly;
18554 Diag(D->getLocation(),
18555 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18556 << D;
18557 continue;
18560 Type = Type.getUnqualifiedType();
18561 VarDecl *VDPrivate =
18562 buildVarDecl(*this, ELoc, Type, D->getName(),
18563 D->hasAttrs() ? &D->getAttrs() : nullptr,
18564 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18565 // Generate helper private variable and initialize it with the value of the
18566 // original variable. The address of the original variable is replaced by
18567 // the address of the new private variable in the CodeGen. This new variable
18568 // is not added to IdResolver, so the code in the OpenMP region uses
18569 // original variable for proper diagnostics and variable capturing.
18570 Expr *VDInitRefExpr = nullptr;
18571 // For arrays generate initializer for single element and replace it by the
18572 // original array element in CodeGen.
18573 if (Type->isArrayType()) {
18574 VarDecl *VDInit =
18575 buildVarDecl(*this, RefExpr->getExprLoc(), ElemType, D->getName());
18576 VDInitRefExpr = buildDeclRefExpr(*this, VDInit, ElemType, ELoc);
18577 Expr *Init = DefaultLvalueConversion(VDInitRefExpr).get();
18578 ElemType = ElemType.getUnqualifiedType();
18579 VarDecl *VDInitTemp = buildVarDecl(*this, RefExpr->getExprLoc(), ElemType,
18580 ".firstprivate.temp");
18581 InitializedEntity Entity =
18582 InitializedEntity::InitializeVariable(VDInitTemp);
18583 InitializationKind Kind = InitializationKind::CreateCopy(ELoc, ELoc);
18585 InitializationSequence InitSeq(*this, Entity, Kind, Init);
18586 ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Init);
18587 if (Result.isInvalid())
18588 VDPrivate->setInvalidDecl();
18589 else
18590 VDPrivate->setInit(Result.getAs<Expr>());
18591 // Remove temp variable declaration.
18592 Context.Deallocate(VDInitTemp);
18593 } else {
18594 VarDecl *VDInit = buildVarDecl(*this, RefExpr->getExprLoc(), Type,
18595 ".firstprivate.temp");
18596 VDInitRefExpr = buildDeclRefExpr(*this, VDInit, RefExpr->getType(),
18597 RefExpr->getExprLoc());
18598 AddInitializerToDecl(VDPrivate,
18599 DefaultLvalueConversion(VDInitRefExpr).get(),
18600 /*DirectInit=*/false);
18602 if (VDPrivate->isInvalidDecl()) {
18603 if (IsImplicitClause) {
18604 Diag(RefExpr->getExprLoc(),
18605 diag::note_omp_task_predetermined_firstprivate_here);
18607 continue;
18609 CurContext->addDecl(VDPrivate);
18610 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18611 *this, VDPrivate, RefExpr->getType().getUnqualifiedType(),
18612 RefExpr->getExprLoc());
18613 DeclRefExpr *Ref = nullptr;
18614 if (!VD && !CurContext->isDependentContext()) {
18615 if (TopDVar.CKind == OMPC_lastprivate) {
18616 Ref = TopDVar.PrivateCopy;
18617 } else {
18618 auto *FD = dyn_cast<FieldDecl>(D);
18619 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
18620 if (VD)
18621 Ref = buildDeclRefExpr(*this, VD, VD->getType().getNonReferenceType(),
18622 RefExpr->getExprLoc());
18623 else
18624 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
18625 if (VD || !isOpenMPCapturedDecl(D))
18626 ExprCaptures.push_back(Ref->getDecl());
18629 if (!IsImplicitClause)
18630 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
18631 Vars.push_back((VD || CurContext->isDependentContext())
18632 ? RefExpr->IgnoreParens()
18633 : Ref);
18634 PrivateCopies.push_back(VDPrivateRefExpr);
18635 Inits.push_back(VDInitRefExpr);
18638 if (Vars.empty())
18639 return nullptr;
18641 return OMPFirstprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
18642 Vars, PrivateCopies, Inits,
18643 buildPreInits(Context, ExprCaptures));
18646 OMPClause *Sema::ActOnOpenMPLastprivateClause(
18647 ArrayRef<Expr *> VarList, OpenMPLastprivateModifier LPKind,
18648 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
18649 SourceLocation LParenLoc, SourceLocation EndLoc) {
18650 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
18651 assert(ColonLoc.isValid() && "Colon location must be valid.");
18652 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
18653 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
18654 /*Last=*/OMPC_LASTPRIVATE_unknown)
18655 << getOpenMPClauseName(OMPC_lastprivate);
18656 return nullptr;
18659 SmallVector<Expr *, 8> Vars;
18660 SmallVector<Expr *, 8> SrcExprs;
18661 SmallVector<Expr *, 8> DstExprs;
18662 SmallVector<Expr *, 8> AssignmentOps;
18663 SmallVector<Decl *, 4> ExprCaptures;
18664 SmallVector<Expr *, 4> ExprPostUpdates;
18665 for (Expr *RefExpr : VarList) {
18666 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
18667 SourceLocation ELoc;
18668 SourceRange ERange;
18669 Expr *SimpleRefExpr = RefExpr;
18670 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
18671 if (Res.second) {
18672 // It will be analyzed later.
18673 Vars.push_back(RefExpr);
18674 SrcExprs.push_back(nullptr);
18675 DstExprs.push_back(nullptr);
18676 AssignmentOps.push_back(nullptr);
18678 ValueDecl *D = Res.first;
18679 if (!D)
18680 continue;
18682 QualType Type = D->getType();
18683 auto *VD = dyn_cast<VarDecl>(D);
18685 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
18686 // A variable that appears in a lastprivate clause must not have an
18687 // incomplete type or a reference type.
18688 if (RequireCompleteType(ELoc, Type,
18689 diag::err_omp_lastprivate_incomplete_type))
18690 continue;
18691 Type = Type.getNonReferenceType();
18693 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18694 // A variable that is privatized must not have a const-qualified type
18695 // unless it is of class type with a mutable member. This restriction does
18696 // not apply to the firstprivate clause.
18698 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
18699 // A variable that appears in a lastprivate clause must not have a
18700 // const-qualified type unless it is of class type with a mutable member.
18701 if (rejectConstNotMutableType(*this, D, Type, OMPC_lastprivate, ELoc))
18702 continue;
18704 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
18705 // A list item that appears in a lastprivate clause with the conditional
18706 // modifier must be a scalar variable.
18707 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
18708 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
18709 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18710 VarDecl::DeclarationOnly;
18711 Diag(D->getLocation(),
18712 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18713 << D;
18714 continue;
18717 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18718 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
18719 // in a Construct]
18720 // Variables with the predetermined data-sharing attributes may not be
18721 // listed in data-sharing attributes clauses, except for the cases
18722 // listed below.
18723 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18724 // A list item may appear in a firstprivate or lastprivate clause but not
18725 // both.
18726 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18727 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
18728 (isOpenMPDistributeDirective(CurrDir) ||
18729 DVar.CKind != OMPC_firstprivate) &&
18730 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
18731 Diag(ELoc, diag::err_omp_wrong_dsa)
18732 << getOpenMPClauseName(DVar.CKind)
18733 << getOpenMPClauseName(OMPC_lastprivate);
18734 reportOriginalDsa(*this, DSAStack, D, DVar);
18735 continue;
18738 // OpenMP [2.14.3.5, Restrictions, p.2]
18739 // A list item that is private within a parallel region, or that appears in
18740 // the reduction clause of a parallel construct, must not appear in a
18741 // lastprivate clause on a worksharing construct if any of the corresponding
18742 // worksharing regions ever binds to any of the corresponding parallel
18743 // regions.
18744 DSAStackTy::DSAVarData TopDVar = DVar;
18745 if (isOpenMPWorksharingDirective(CurrDir) &&
18746 !isOpenMPParallelDirective(CurrDir) &&
18747 !isOpenMPTeamsDirective(CurrDir)) {
18748 DVar = DSAStack->getImplicitDSA(D, true);
18749 if (DVar.CKind != OMPC_shared) {
18750 Diag(ELoc, diag::err_omp_required_access)
18751 << getOpenMPClauseName(OMPC_lastprivate)
18752 << getOpenMPClauseName(OMPC_shared);
18753 reportOriginalDsa(*this, DSAStack, D, DVar);
18754 continue;
18758 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
18759 // A variable of class type (or array thereof) that appears in a
18760 // lastprivate clause requires an accessible, unambiguous default
18761 // constructor for the class type, unless the list item is also specified
18762 // in a firstprivate clause.
18763 // A variable of class type (or array thereof) that appears in a
18764 // lastprivate clause requires an accessible, unambiguous copy assignment
18765 // operator for the class type.
18766 Type = Context.getBaseElementType(Type).getNonReferenceType();
18767 VarDecl *SrcVD = buildVarDecl(*this, ERange.getBegin(),
18768 Type.getUnqualifiedType(), ".lastprivate.src",
18769 D->hasAttrs() ? &D->getAttrs() : nullptr);
18770 DeclRefExpr *PseudoSrcExpr =
18771 buildDeclRefExpr(*this, SrcVD, Type.getUnqualifiedType(), ELoc);
18772 VarDecl *DstVD =
18773 buildVarDecl(*this, ERange.getBegin(), Type, ".lastprivate.dst",
18774 D->hasAttrs() ? &D->getAttrs() : nullptr);
18775 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc);
18776 // For arrays generate assignment operation for single element and replace
18777 // it by the original array element in CodeGen.
18778 ExprResult AssignmentOp = BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
18779 PseudoDstExpr, PseudoSrcExpr);
18780 if (AssignmentOp.isInvalid())
18781 continue;
18782 AssignmentOp =
18783 ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false);
18784 if (AssignmentOp.isInvalid())
18785 continue;
18787 DeclRefExpr *Ref = nullptr;
18788 if (!VD && !CurContext->isDependentContext()) {
18789 if (TopDVar.CKind == OMPC_firstprivate) {
18790 Ref = TopDVar.PrivateCopy;
18791 } else {
18792 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
18793 if (!isOpenMPCapturedDecl(D))
18794 ExprCaptures.push_back(Ref->getDecl());
18796 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
18797 (!isOpenMPCapturedDecl(D) &&
18798 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
18799 ExprResult RefRes = DefaultLvalueConversion(Ref);
18800 if (!RefRes.isUsable())
18801 continue;
18802 ExprResult PostUpdateRes =
18803 BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
18804 RefRes.get());
18805 if (!PostUpdateRes.isUsable())
18806 continue;
18807 ExprPostUpdates.push_back(
18808 IgnoredValueConversions(PostUpdateRes.get()).get());
18811 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
18812 Vars.push_back((VD || CurContext->isDependentContext())
18813 ? RefExpr->IgnoreParens()
18814 : Ref);
18815 SrcExprs.push_back(PseudoSrcExpr);
18816 DstExprs.push_back(PseudoDstExpr);
18817 AssignmentOps.push_back(AssignmentOp.get());
18820 if (Vars.empty())
18821 return nullptr;
18823 return OMPLastprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
18824 Vars, SrcExprs, DstExprs, AssignmentOps,
18825 LPKind, LPKindLoc, ColonLoc,
18826 buildPreInits(Context, ExprCaptures),
18827 buildPostUpdate(*this, ExprPostUpdates));
18830 OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
18831 SourceLocation StartLoc,
18832 SourceLocation LParenLoc,
18833 SourceLocation EndLoc) {
18834 SmallVector<Expr *, 8> Vars;
18835 for (Expr *RefExpr : VarList) {
18836 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
18837 SourceLocation ELoc;
18838 SourceRange ERange;
18839 Expr *SimpleRefExpr = RefExpr;
18840 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
18841 if (Res.second) {
18842 // It will be analyzed later.
18843 Vars.push_back(RefExpr);
18845 ValueDecl *D = Res.first;
18846 if (!D)
18847 continue;
18849 auto *VD = dyn_cast<VarDecl>(D);
18850 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18851 // in a Construct]
18852 // Variables with the predetermined data-sharing attributes may not be
18853 // listed in data-sharing attributes clauses, except for the cases
18854 // listed below. For these exceptions only, listing a predetermined
18855 // variable in a data-sharing attribute clause is allowed and overrides
18856 // the variable's predetermined data-sharing attributes.
18857 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18858 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
18859 DVar.RefExpr) {
18860 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
18861 << getOpenMPClauseName(OMPC_shared);
18862 reportOriginalDsa(*this, DSAStack, D, DVar);
18863 continue;
18866 DeclRefExpr *Ref = nullptr;
18867 if (!VD && isOpenMPCapturedDecl(D) && !CurContext->isDependentContext())
18868 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
18869 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
18870 Vars.push_back((VD || !Ref || CurContext->isDependentContext())
18871 ? RefExpr->IgnoreParens()
18872 : Ref);
18875 if (Vars.empty())
18876 return nullptr;
18878 return OMPSharedClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
18881 namespace {
18882 class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
18883 DSAStackTy *Stack;
18885 public:
18886 bool VisitDeclRefExpr(DeclRefExpr *E) {
18887 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
18888 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
18889 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
18890 return false;
18891 if (DVar.CKind != OMPC_unknown)
18892 return true;
18893 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
18895 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
18896 return isOpenMPPrivate(C) && !AppliedToPointee;
18898 [](OpenMPDirectiveKind) { return true; },
18899 /*FromParent=*/true);
18900 return DVarPrivate.CKind != OMPC_unknown;
18902 return false;
18904 bool VisitStmt(Stmt *S) {
18905 for (Stmt *Child : S->children()) {
18906 if (Child && Visit(Child))
18907 return true;
18909 return false;
18911 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
18913 } // namespace
18915 namespace {
18916 // Transform MemberExpression for specified FieldDecl of current class to
18917 // DeclRefExpr to specified OMPCapturedExprDecl.
18918 class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
18919 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
18920 ValueDecl *Field = nullptr;
18921 DeclRefExpr *CapturedExpr = nullptr;
18923 public:
18924 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
18925 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
18927 ExprResult TransformMemberExpr(MemberExpr *E) {
18928 if (isa<CXXThisExpr>(E->getBase()->IgnoreParenImpCasts()) &&
18929 E->getMemberDecl() == Field) {
18930 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
18931 return CapturedExpr;
18933 return BaseTransform::TransformMemberExpr(E);
18935 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
18937 } // namespace
18939 template <typename T, typename U>
18940 static T filterLookupForUDReductionAndMapper(
18941 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
18942 for (U &Set : Lookups) {
18943 for (auto *D : Set) {
18944 if (T Res = Gen(cast<ValueDecl>(D)))
18945 return Res;
18948 return T();
18951 static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
18952 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
18954 for (auto *RD : D->redecls()) {
18955 // Don't bother with extra checks if we already know this one isn't visible.
18956 if (RD == D)
18957 continue;
18959 auto ND = cast<NamedDecl>(RD);
18960 if (LookupResult::isVisible(SemaRef, ND))
18961 return ND;
18964 return nullptr;
18967 static void
18968 argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id,
18969 SourceLocation Loc, QualType Ty,
18970 SmallVectorImpl<UnresolvedSet<8>> &Lookups) {
18971 // Find all of the associated namespaces and classes based on the
18972 // arguments we have.
18973 Sema::AssociatedNamespaceSet AssociatedNamespaces;
18974 Sema::AssociatedClassSet AssociatedClasses;
18975 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
18976 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
18977 AssociatedClasses);
18979 // C++ [basic.lookup.argdep]p3:
18980 // Let X be the lookup set produced by unqualified lookup (3.4.1)
18981 // and let Y be the lookup set produced by argument dependent
18982 // lookup (defined as follows). If X contains [...] then Y is
18983 // empty. Otherwise Y is the set of declarations found in the
18984 // namespaces associated with the argument types as described
18985 // below. The set of declarations found by the lookup of the name
18986 // is the union of X and Y.
18988 // Here, we compute Y and add its members to the overloaded
18989 // candidate set.
18990 for (auto *NS : AssociatedNamespaces) {
18991 // When considering an associated namespace, the lookup is the
18992 // same as the lookup performed when the associated namespace is
18993 // used as a qualifier (3.4.3.2) except that:
18995 // -- Any using-directives in the associated namespace are
18996 // ignored.
18998 // -- Any namespace-scope friend functions declared in
18999 // associated classes are visible within their respective
19000 // namespaces even if they are not visible during an ordinary
19001 // lookup (11.4).
19002 DeclContext::lookup_result R = NS->lookup(Id.getName());
19003 for (auto *D : R) {
19004 auto *Underlying = D;
19005 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
19006 Underlying = USD->getTargetDecl();
19008 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
19009 !isa<OMPDeclareMapperDecl>(Underlying))
19010 continue;
19012 if (!SemaRef.isVisible(D)) {
19013 D = findAcceptableDecl(SemaRef, D);
19014 if (!D)
19015 continue;
19016 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
19017 Underlying = USD->getTargetDecl();
19019 Lookups.emplace_back();
19020 Lookups.back().addDecl(Underlying);
19025 static ExprResult
19026 buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
19027 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
19028 const DeclarationNameInfo &ReductionId, QualType Ty,
19029 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
19030 if (ReductionIdScopeSpec.isInvalid())
19031 return ExprError();
19032 SmallVector<UnresolvedSet<8>, 4> Lookups;
19033 if (S) {
19034 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
19035 Lookup.suppressDiagnostics();
19036 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec)) {
19037 NamedDecl *D = Lookup.getRepresentativeDecl();
19038 do {
19039 S = S->getParent();
19040 } while (S && !S->isDeclScope(D));
19041 if (S)
19042 S = S->getParent();
19043 Lookups.emplace_back();
19044 Lookups.back().append(Lookup.begin(), Lookup.end());
19045 Lookup.clear();
19047 } else if (auto *ULE =
19048 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
19049 Lookups.push_back(UnresolvedSet<8>());
19050 Decl *PrevD = nullptr;
19051 for (NamedDecl *D : ULE->decls()) {
19052 if (D == PrevD)
19053 Lookups.push_back(UnresolvedSet<8>());
19054 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
19055 Lookups.back().addDecl(DRD);
19056 PrevD = D;
19059 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
19060 Ty->isInstantiationDependentType() ||
19061 Ty->containsUnexpandedParameterPack() ||
19062 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
19063 return !D->isInvalidDecl() &&
19064 (D->getType()->isDependentType() ||
19065 D->getType()->isInstantiationDependentType() ||
19066 D->getType()->containsUnexpandedParameterPack());
19067 })) {
19068 UnresolvedSet<8> ResSet;
19069 for (const UnresolvedSet<8> &Set : Lookups) {
19070 if (Set.empty())
19071 continue;
19072 ResSet.append(Set.begin(), Set.end());
19073 // The last item marks the end of all declarations at the specified scope.
19074 ResSet.addDecl(Set[Set.size() - 1]);
19076 return UnresolvedLookupExpr::Create(
19077 SemaRef.Context, /*NamingClass=*/nullptr,
19078 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
19079 /*ADL=*/true, /*Overloaded=*/true, ResSet.begin(), ResSet.end());
19081 // Lookup inside the classes.
19082 // C++ [over.match.oper]p3:
19083 // For a unary operator @ with an operand of a type whose
19084 // cv-unqualified version is T1, and for a binary operator @ with
19085 // a left operand of a type whose cv-unqualified version is T1 and
19086 // a right operand of a type whose cv-unqualified version is T2,
19087 // three sets of candidate functions, designated member
19088 // candidates, non-member candidates and built-in candidates, are
19089 // constructed as follows:
19090 // -- If T1 is a complete class type or a class currently being
19091 // defined, the set of member candidates is the result of the
19092 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
19093 // the set of member candidates is empty.
19094 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
19095 Lookup.suppressDiagnostics();
19096 if (const auto *TyRec = Ty->getAs<RecordType>()) {
19097 // Complete the type if it can be completed.
19098 // If the type is neither complete nor being defined, bail out now.
19099 if (SemaRef.isCompleteType(Loc, Ty) || TyRec->isBeingDefined() ||
19100 TyRec->getDecl()->getDefinition()) {
19101 Lookup.clear();
19102 SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl());
19103 if (Lookup.empty()) {
19104 Lookups.emplace_back();
19105 Lookups.back().append(Lookup.begin(), Lookup.end());
19109 // Perform ADL.
19110 if (SemaRef.getLangOpts().CPlusPlus)
19111 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
19112 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
19113 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
19114 if (!D->isInvalidDecl() &&
19115 SemaRef.Context.hasSameType(D->getType(), Ty))
19116 return D;
19117 return nullptr;
19119 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
19120 VK_LValue, Loc);
19121 if (SemaRef.getLangOpts().CPlusPlus) {
19122 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
19123 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
19124 if (!D->isInvalidDecl() &&
19125 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
19126 !Ty.isMoreQualifiedThan(D->getType()))
19127 return D;
19128 return nullptr;
19129 })) {
19130 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
19131 /*DetectVirtual=*/false);
19132 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
19133 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
19134 VD->getType().getUnqualifiedType()))) {
19135 if (SemaRef.CheckBaseClassAccess(
19136 Loc, VD->getType(), Ty, Paths.front(),
19137 /*DiagID=*/0) != Sema::AR_inaccessible) {
19138 SemaRef.BuildBasePathArray(Paths, BasePath);
19139 return SemaRef.BuildDeclRefExpr(
19140 VD, VD->getType().getNonReferenceType(), VK_LValue, Loc);
19146 if (ReductionIdScopeSpec.isSet()) {
19147 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
19148 << Ty << Range;
19149 return ExprError();
19151 return ExprEmpty();
19154 namespace {
19155 /// Data for the reduction-based clauses.
19156 struct ReductionData {
19157 /// List of original reduction items.
19158 SmallVector<Expr *, 8> Vars;
19159 /// List of private copies of the reduction items.
19160 SmallVector<Expr *, 8> Privates;
19161 /// LHS expressions for the reduction_op expressions.
19162 SmallVector<Expr *, 8> LHSs;
19163 /// RHS expressions for the reduction_op expressions.
19164 SmallVector<Expr *, 8> RHSs;
19165 /// Reduction operation expression.
19166 SmallVector<Expr *, 8> ReductionOps;
19167 /// inscan copy operation expressions.
19168 SmallVector<Expr *, 8> InscanCopyOps;
19169 /// inscan copy temp array expressions for prefix sums.
19170 SmallVector<Expr *, 8> InscanCopyArrayTemps;
19171 /// inscan copy temp array element expressions for prefix sums.
19172 SmallVector<Expr *, 8> InscanCopyArrayElems;
19173 /// Taskgroup descriptors for the corresponding reduction items in
19174 /// in_reduction clauses.
19175 SmallVector<Expr *, 8> TaskgroupDescriptors;
19176 /// List of captures for clause.
19177 SmallVector<Decl *, 4> ExprCaptures;
19178 /// List of postupdate expressions.
19179 SmallVector<Expr *, 4> ExprPostUpdates;
19180 /// Reduction modifier.
19181 unsigned RedModifier = 0;
19182 ReductionData() = delete;
19183 /// Reserves required memory for the reduction data.
19184 ReductionData(unsigned Size, unsigned Modifier = 0) : RedModifier(Modifier) {
19185 Vars.reserve(Size);
19186 Privates.reserve(Size);
19187 LHSs.reserve(Size);
19188 RHSs.reserve(Size);
19189 ReductionOps.reserve(Size);
19190 if (RedModifier == OMPC_REDUCTION_inscan) {
19191 InscanCopyOps.reserve(Size);
19192 InscanCopyArrayTemps.reserve(Size);
19193 InscanCopyArrayElems.reserve(Size);
19195 TaskgroupDescriptors.reserve(Size);
19196 ExprCaptures.reserve(Size);
19197 ExprPostUpdates.reserve(Size);
19199 /// Stores reduction item and reduction operation only (required for dependent
19200 /// reduction item).
19201 void push(Expr *Item, Expr *ReductionOp) {
19202 Vars.emplace_back(Item);
19203 Privates.emplace_back(nullptr);
19204 LHSs.emplace_back(nullptr);
19205 RHSs.emplace_back(nullptr);
19206 ReductionOps.emplace_back(ReductionOp);
19207 TaskgroupDescriptors.emplace_back(nullptr);
19208 if (RedModifier == OMPC_REDUCTION_inscan) {
19209 InscanCopyOps.push_back(nullptr);
19210 InscanCopyArrayTemps.push_back(nullptr);
19211 InscanCopyArrayElems.push_back(nullptr);
19214 /// Stores reduction data.
19215 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
19216 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
19217 Expr *CopyArrayElem) {
19218 Vars.emplace_back(Item);
19219 Privates.emplace_back(Private);
19220 LHSs.emplace_back(LHS);
19221 RHSs.emplace_back(RHS);
19222 ReductionOps.emplace_back(ReductionOp);
19223 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
19224 if (RedModifier == OMPC_REDUCTION_inscan) {
19225 InscanCopyOps.push_back(CopyOp);
19226 InscanCopyArrayTemps.push_back(CopyArrayTemp);
19227 InscanCopyArrayElems.push_back(CopyArrayElem);
19228 } else {
19229 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
19230 CopyArrayElem == nullptr &&
19231 "Copy operation must be used for inscan reductions only.");
19235 } // namespace
19237 static bool checkOMPArraySectionConstantForReduction(
19238 ASTContext &Context, const OMPArraySectionExpr *OASE, bool &SingleElement,
19239 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
19240 const Expr *Length = OASE->getLength();
19241 if (Length == nullptr) {
19242 // For array sections of the form [1:] or [:], we would need to analyze
19243 // the lower bound...
19244 if (OASE->getColonLocFirst().isValid())
19245 return false;
19247 // This is an array subscript which has implicit length 1!
19248 SingleElement = true;
19249 ArraySizes.push_back(llvm::APSInt::get(1));
19250 } else {
19251 Expr::EvalResult Result;
19252 if (!Length->EvaluateAsInt(Result, Context))
19253 return false;
19255 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19256 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
19257 ArraySizes.push_back(ConstantLengthValue);
19260 // Get the base of this array section and walk up from there.
19261 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
19263 // We require length = 1 for all array sections except the right-most to
19264 // guarantee that the memory region is contiguous and has no holes in it.
19265 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) {
19266 Length = TempOASE->getLength();
19267 if (Length == nullptr) {
19268 // For array sections of the form [1:] or [:], we would need to analyze
19269 // the lower bound...
19270 if (OASE->getColonLocFirst().isValid())
19271 return false;
19273 // This is an array subscript which has implicit length 1!
19274 ArraySizes.push_back(llvm::APSInt::get(1));
19275 } else {
19276 Expr::EvalResult Result;
19277 if (!Length->EvaluateAsInt(Result, Context))
19278 return false;
19280 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19281 if (ConstantLengthValue.getSExtValue() != 1)
19282 return false;
19284 ArraySizes.push_back(ConstantLengthValue);
19286 Base = TempOASE->getBase()->IgnoreParenImpCasts();
19289 // If we have a single element, we don't need to add the implicit lengths.
19290 if (!SingleElement) {
19291 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
19292 // Has implicit length 1!
19293 ArraySizes.push_back(llvm::APSInt::get(1));
19294 Base = TempASE->getBase()->IgnoreParenImpCasts();
19298 // This array section can be privatized as a single value or as a constant
19299 // sized array.
19300 return true;
19303 static BinaryOperatorKind
19304 getRelatedCompoundReductionOp(BinaryOperatorKind BOK) {
19305 if (BOK == BO_Add)
19306 return BO_AddAssign;
19307 if (BOK == BO_Mul)
19308 return BO_MulAssign;
19309 if (BOK == BO_And)
19310 return BO_AndAssign;
19311 if (BOK == BO_Or)
19312 return BO_OrAssign;
19313 if (BOK == BO_Xor)
19314 return BO_XorAssign;
19315 return BOK;
19318 static bool actOnOMPReductionKindClause(
19319 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
19320 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19321 SourceLocation ColonLoc, SourceLocation EndLoc,
19322 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19323 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
19324 DeclarationName DN = ReductionId.getName();
19325 OverloadedOperatorKind OOK = DN.getCXXOverloadedOperator();
19326 BinaryOperatorKind BOK = BO_Comma;
19328 ASTContext &Context = S.Context;
19329 // OpenMP [2.14.3.6, reduction clause]
19330 // C
19331 // reduction-identifier is either an identifier or one of the following
19332 // operators: +, -, *, &, |, ^, && and ||
19333 // C++
19334 // reduction-identifier is either an id-expression or one of the following
19335 // operators: +, -, *, &, |, ^, && and ||
19336 switch (OOK) {
19337 case OO_Plus:
19338 BOK = BO_Add;
19339 break;
19340 case OO_Minus:
19341 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
19342 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
19343 // reduction identifier.
19344 if (S.LangOpts.OpenMP > 52)
19345 BOK = BO_Comma;
19346 else
19347 BOK = BO_Add;
19348 break;
19349 case OO_Star:
19350 BOK = BO_Mul;
19351 break;
19352 case OO_Amp:
19353 BOK = BO_And;
19354 break;
19355 case OO_Pipe:
19356 BOK = BO_Or;
19357 break;
19358 case OO_Caret:
19359 BOK = BO_Xor;
19360 break;
19361 case OO_AmpAmp:
19362 BOK = BO_LAnd;
19363 break;
19364 case OO_PipePipe:
19365 BOK = BO_LOr;
19366 break;
19367 case OO_New:
19368 case OO_Delete:
19369 case OO_Array_New:
19370 case OO_Array_Delete:
19371 case OO_Slash:
19372 case OO_Percent:
19373 case OO_Tilde:
19374 case OO_Exclaim:
19375 case OO_Equal:
19376 case OO_Less:
19377 case OO_Greater:
19378 case OO_LessEqual:
19379 case OO_GreaterEqual:
19380 case OO_PlusEqual:
19381 case OO_MinusEqual:
19382 case OO_StarEqual:
19383 case OO_SlashEqual:
19384 case OO_PercentEqual:
19385 case OO_CaretEqual:
19386 case OO_AmpEqual:
19387 case OO_PipeEqual:
19388 case OO_LessLess:
19389 case OO_GreaterGreater:
19390 case OO_LessLessEqual:
19391 case OO_GreaterGreaterEqual:
19392 case OO_EqualEqual:
19393 case OO_ExclaimEqual:
19394 case OO_Spaceship:
19395 case OO_PlusPlus:
19396 case OO_MinusMinus:
19397 case OO_Comma:
19398 case OO_ArrowStar:
19399 case OO_Arrow:
19400 case OO_Call:
19401 case OO_Subscript:
19402 case OO_Conditional:
19403 case OO_Coawait:
19404 case NUM_OVERLOADED_OPERATORS:
19405 llvm_unreachable("Unexpected reduction identifier");
19406 case OO_None:
19407 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
19408 if (II->isStr("max"))
19409 BOK = BO_GT;
19410 else if (II->isStr("min"))
19411 BOK = BO_LT;
19413 break;
19416 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
19417 // A reduction clause with the minus (-) operator was deprecated
19418 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
19419 S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
19421 SourceRange ReductionIdRange;
19422 if (ReductionIdScopeSpec.isValid())
19423 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
19424 else
19425 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
19426 ReductionIdRange.setEnd(ReductionId.getEndLoc());
19428 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
19429 bool FirstIter = true;
19430 for (Expr *RefExpr : VarList) {
19431 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
19432 // OpenMP [2.1, C/C++]
19433 // A list item is a variable or array section, subject to the restrictions
19434 // specified in Section 2.4 on page 42 and in each of the sections
19435 // describing clauses and directives for which a list appears.
19436 // OpenMP [2.14.3.3, Restrictions, p.1]
19437 // A variable that is part of another variable (as an array or
19438 // structure element) cannot appear in a private clause.
19439 if (!FirstIter && IR != ER)
19440 ++IR;
19441 FirstIter = false;
19442 SourceLocation ELoc;
19443 SourceRange ERange;
19444 Expr *SimpleRefExpr = RefExpr;
19445 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
19446 /*AllowArraySection=*/true);
19447 if (Res.second) {
19448 // Try to find 'declare reduction' corresponding construct before using
19449 // builtin/overloaded operators.
19450 QualType Type = Context.DependentTy;
19451 CXXCastPath BasePath;
19452 ExprResult DeclareReductionRef = buildDeclareReductionRef(
19453 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
19454 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
19455 Expr *ReductionOp = nullptr;
19456 if (S.CurContext->isDependentContext() &&
19457 (DeclareReductionRef.isUnset() ||
19458 isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
19459 ReductionOp = DeclareReductionRef.get();
19460 // It will be analyzed later.
19461 RD.push(RefExpr, ReductionOp);
19463 ValueDecl *D = Res.first;
19464 if (!D)
19465 continue;
19467 Expr *TaskgroupDescriptor = nullptr;
19468 QualType Type;
19469 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
19470 auto *OASE = dyn_cast<OMPArraySectionExpr>(RefExpr->IgnoreParens());
19471 if (ASE) {
19472 Type = ASE->getType().getNonReferenceType();
19473 } else if (OASE) {
19474 QualType BaseType =
19475 OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
19476 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
19477 Type = ATy->getElementType();
19478 else
19479 Type = BaseType->getPointeeType();
19480 Type = Type.getNonReferenceType();
19481 } else {
19482 Type = Context.getBaseElementType(D->getType().getNonReferenceType());
19484 auto *VD = dyn_cast<VarDecl>(D);
19486 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19487 // A variable that appears in a private clause must not have an incomplete
19488 // type or a reference type.
19489 if (S.RequireCompleteType(ELoc, D->getType(),
19490 diag::err_omp_reduction_incomplete_type))
19491 continue;
19492 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19493 // A list item that appears in a reduction clause must not be
19494 // const-qualified.
19495 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
19496 /*AcceptIfMutable*/ false, ASE || OASE))
19497 continue;
19499 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
19500 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
19501 // If a list-item is a reference type then it must bind to the same object
19502 // for all threads of the team.
19503 if (!ASE && !OASE) {
19504 if (VD) {
19505 VarDecl *VDDef = VD->getDefinition();
19506 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
19507 DSARefChecker Check(Stack);
19508 if (Check.Visit(VDDef->getInit())) {
19509 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
19510 << getOpenMPClauseName(ClauseKind) << ERange;
19511 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
19512 continue;
19517 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
19518 // in a Construct]
19519 // Variables with the predetermined data-sharing attributes may not be
19520 // listed in data-sharing attributes clauses, except for the cases
19521 // listed below. For these exceptions only, listing a predetermined
19522 // variable in a data-sharing attribute clause is allowed and overrides
19523 // the variable's predetermined data-sharing attributes.
19524 // OpenMP [2.14.3.6, Restrictions, p.3]
19525 // Any number of reduction clauses can be specified on the directive,
19526 // but a list item can appear only once in the reduction clauses for that
19527 // directive.
19528 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19529 if (DVar.CKind == OMPC_reduction) {
19530 S.Diag(ELoc, diag::err_omp_once_referenced)
19531 << getOpenMPClauseName(ClauseKind);
19532 if (DVar.RefExpr)
19533 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
19534 continue;
19536 if (DVar.CKind != OMPC_unknown) {
19537 S.Diag(ELoc, diag::err_omp_wrong_dsa)
19538 << getOpenMPClauseName(DVar.CKind)
19539 << getOpenMPClauseName(OMPC_reduction);
19540 reportOriginalDsa(S, Stack, D, DVar);
19541 continue;
19544 // OpenMP [2.14.3.6, Restrictions, p.1]
19545 // A list item that appears in a reduction clause of a worksharing
19546 // construct must be shared in the parallel regions to which any of the
19547 // worksharing regions arising from the worksharing construct bind.
19548 if (isOpenMPWorksharingDirective(CurrDir) &&
19549 !isOpenMPParallelDirective(CurrDir) &&
19550 !isOpenMPTeamsDirective(CurrDir)) {
19551 DVar = Stack->getImplicitDSA(D, true);
19552 if (DVar.CKind != OMPC_shared) {
19553 S.Diag(ELoc, diag::err_omp_required_access)
19554 << getOpenMPClauseName(OMPC_reduction)
19555 << getOpenMPClauseName(OMPC_shared);
19556 reportOriginalDsa(S, Stack, D, DVar);
19557 continue;
19560 } else {
19561 // Threadprivates cannot be shared between threads, so dignose if the base
19562 // is a threadprivate variable.
19563 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19564 if (DVar.CKind == OMPC_threadprivate) {
19565 S.Diag(ELoc, diag::err_omp_wrong_dsa)
19566 << getOpenMPClauseName(DVar.CKind)
19567 << getOpenMPClauseName(OMPC_reduction);
19568 reportOriginalDsa(S, Stack, D, DVar);
19569 continue;
19573 // Try to find 'declare reduction' corresponding construct before using
19574 // builtin/overloaded operators.
19575 CXXCastPath BasePath;
19576 ExprResult DeclareReductionRef = buildDeclareReductionRef(
19577 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
19578 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
19579 if (DeclareReductionRef.isInvalid())
19580 continue;
19581 if (S.CurContext->isDependentContext() &&
19582 (DeclareReductionRef.isUnset() ||
19583 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
19584 RD.push(RefExpr, DeclareReductionRef.get());
19585 continue;
19587 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
19588 // Not allowed reduction identifier is found.
19589 if (S.LangOpts.OpenMP > 52)
19590 S.Diag(ReductionId.getBeginLoc(),
19591 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
19592 << Type << ReductionIdRange;
19593 else
19594 S.Diag(ReductionId.getBeginLoc(),
19595 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
19596 << Type << ReductionIdRange;
19597 continue;
19600 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19601 // The type of a list item that appears in a reduction clause must be valid
19602 // for the reduction-identifier. For a max or min reduction in C, the type
19603 // of the list item must be an allowed arithmetic data type: char, int,
19604 // float, double, or _Bool, possibly modified with long, short, signed, or
19605 // unsigned. For a max or min reduction in C++, the type of the list item
19606 // must be an allowed arithmetic data type: char, wchar_t, int, float,
19607 // double, or bool, possibly modified with long, short, signed, or unsigned.
19608 if (DeclareReductionRef.isUnset()) {
19609 if ((BOK == BO_GT || BOK == BO_LT) &&
19610 !(Type->isScalarType() ||
19611 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
19612 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
19613 << getOpenMPClauseName(ClauseKind) << S.getLangOpts().CPlusPlus;
19614 if (!ASE && !OASE) {
19615 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19616 VarDecl::DeclarationOnly;
19617 S.Diag(D->getLocation(),
19618 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19619 << D;
19621 continue;
19623 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
19624 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
19625 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
19626 << getOpenMPClauseName(ClauseKind);
19627 if (!ASE && !OASE) {
19628 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19629 VarDecl::DeclarationOnly;
19630 S.Diag(D->getLocation(),
19631 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19632 << D;
19634 continue;
19638 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
19639 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
19640 D->hasAttrs() ? &D->getAttrs() : nullptr);
19641 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
19642 D->hasAttrs() ? &D->getAttrs() : nullptr);
19643 QualType PrivateTy = Type;
19645 // Try if we can determine constant lengths for all array sections and avoid
19646 // the VLA.
19647 bool ConstantLengthOASE = false;
19648 if (OASE) {
19649 bool SingleElement;
19650 llvm::SmallVector<llvm::APSInt, 4> ArraySizes;
19651 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
19652 Context, OASE, SingleElement, ArraySizes);
19654 // If we don't have a single element, we must emit a constant array type.
19655 if (ConstantLengthOASE && !SingleElement) {
19656 for (llvm::APSInt &Size : ArraySizes)
19657 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
19658 ArrayType::Normal,
19659 /*IndexTypeQuals=*/0);
19663 if ((OASE && !ConstantLengthOASE) ||
19664 (!OASE && !ASE &&
19665 D->getType().getNonReferenceType()->isVariablyModifiedType())) {
19666 if (!Context.getTargetInfo().isVLASupported()) {
19667 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
19668 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19669 S.Diag(ELoc, diag::note_vla_unsupported);
19670 continue;
19671 } else {
19672 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19673 S.targetDiag(ELoc, diag::note_vla_unsupported);
19676 // For arrays/array sections only:
19677 // Create pseudo array type for private copy. The size for this array will
19678 // be generated during codegen.
19679 // For array subscripts or single variables Private Ty is the same as Type
19680 // (type of the variable or single array element).
19681 PrivateTy = Context.getVariableArrayType(
19682 Type,
19683 new (Context)
19684 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
19685 ArrayType::Normal, /*IndexTypeQuals=*/0, SourceRange());
19686 } else if (!ASE && !OASE &&
19687 Context.getAsArrayType(D->getType().getNonReferenceType())) {
19688 PrivateTy = D->getType().getNonReferenceType();
19690 // Private copy.
19691 VarDecl *PrivateVD =
19692 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
19693 D->hasAttrs() ? &D->getAttrs() : nullptr,
19694 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19695 // Add initializer for private variable.
19696 Expr *Init = nullptr;
19697 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
19698 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
19699 if (DeclareReductionRef.isUsable()) {
19700 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
19701 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
19702 if (DRD->getInitializer()) {
19703 Init = DRDRef;
19704 RHSVD->setInit(DRDRef);
19705 RHSVD->setInitStyle(VarDecl::CallInit);
19707 } else {
19708 switch (BOK) {
19709 case BO_Add:
19710 case BO_Xor:
19711 case BO_Or:
19712 case BO_LOr:
19713 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
19714 if (Type->isScalarType() || Type->isAnyComplexType())
19715 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
19716 break;
19717 case BO_Mul:
19718 case BO_LAnd:
19719 if (Type->isScalarType() || Type->isAnyComplexType()) {
19720 // '*' and '&&' reduction ops - initializer is '1'.
19721 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
19723 break;
19724 case BO_And: {
19725 // '&' reduction op - initializer is '~0'.
19726 QualType OrigType = Type;
19727 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
19728 Type = ComplexTy->getElementType();
19729 if (Type->isRealFloatingType()) {
19730 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
19731 Context.getFloatTypeSemantics(Type));
19732 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
19733 Type, ELoc);
19734 } else if (Type->isScalarType()) {
19735 uint64_t Size = Context.getTypeSize(Type);
19736 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
19737 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
19738 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
19740 if (Init && OrigType->isAnyComplexType()) {
19741 // Init = 0xFFFF + 0xFFFFi;
19742 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
19743 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
19745 Type = OrigType;
19746 break;
19748 case BO_LT:
19749 case BO_GT: {
19750 // 'min' reduction op - initializer is 'Largest representable number in
19751 // the reduction list item type'.
19752 // 'max' reduction op - initializer is 'Least representable number in
19753 // the reduction list item type'.
19754 if (Type->isIntegerType() || Type->isPointerType()) {
19755 bool IsSigned = Type->hasSignedIntegerRepresentation();
19756 uint64_t Size = Context.getTypeSize(Type);
19757 QualType IntTy =
19758 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
19759 llvm::APInt InitValue =
19760 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
19761 : llvm::APInt::getMinValue(Size)
19762 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
19763 : llvm::APInt::getMaxValue(Size);
19764 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
19765 if (Type->isPointerType()) {
19766 // Cast to pointer type.
19767 ExprResult CastExpr = S.BuildCStyleCastExpr(
19768 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
19769 if (CastExpr.isInvalid())
19770 continue;
19771 Init = CastExpr.get();
19773 } else if (Type->isRealFloatingType()) {
19774 llvm::APFloat InitValue = llvm::APFloat::getLargest(
19775 Context.getFloatTypeSemantics(Type), BOK != BO_LT);
19776 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
19777 Type, ELoc);
19779 break;
19781 case BO_PtrMemD:
19782 case BO_PtrMemI:
19783 case BO_MulAssign:
19784 case BO_Div:
19785 case BO_Rem:
19786 case BO_Sub:
19787 case BO_Shl:
19788 case BO_Shr:
19789 case BO_LE:
19790 case BO_GE:
19791 case BO_EQ:
19792 case BO_NE:
19793 case BO_Cmp:
19794 case BO_AndAssign:
19795 case BO_XorAssign:
19796 case BO_OrAssign:
19797 case BO_Assign:
19798 case BO_AddAssign:
19799 case BO_SubAssign:
19800 case BO_DivAssign:
19801 case BO_RemAssign:
19802 case BO_ShlAssign:
19803 case BO_ShrAssign:
19804 case BO_Comma:
19805 llvm_unreachable("Unexpected reduction operation");
19808 if (Init && DeclareReductionRef.isUnset()) {
19809 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
19810 // Store initializer for single element in private copy. Will be used
19811 // during codegen.
19812 PrivateVD->setInit(RHSVD->getInit());
19813 PrivateVD->setInitStyle(RHSVD->getInitStyle());
19814 } else if (!Init) {
19815 S.ActOnUninitializedDecl(RHSVD);
19816 // Store initializer for single element in private copy. Will be used
19817 // during codegen.
19818 PrivateVD->setInit(RHSVD->getInit());
19819 PrivateVD->setInitStyle(RHSVD->getInitStyle());
19821 if (RHSVD->isInvalidDecl())
19822 continue;
19823 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
19824 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
19825 << Type << ReductionIdRange;
19826 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19827 VarDecl::DeclarationOnly;
19828 S.Diag(D->getLocation(),
19829 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19830 << D;
19831 continue;
19833 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
19834 ExprResult ReductionOp;
19835 if (DeclareReductionRef.isUsable()) {
19836 QualType RedTy = DeclareReductionRef.get()->getType();
19837 QualType PtrRedTy = Context.getPointerType(RedTy);
19838 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
19839 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
19840 if (!BasePath.empty()) {
19841 LHS = S.DefaultLvalueConversion(LHS.get());
19842 RHS = S.DefaultLvalueConversion(RHS.get());
19843 LHS = ImplicitCastExpr::Create(
19844 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
19845 LHS.get()->getValueKind(), FPOptionsOverride());
19846 RHS = ImplicitCastExpr::Create(
19847 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
19848 RHS.get()->getValueKind(), FPOptionsOverride());
19850 FunctionProtoType::ExtProtoInfo EPI;
19851 QualType Params[] = {PtrRedTy, PtrRedTy};
19852 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
19853 auto *OVE = new (Context) OpaqueValueExpr(
19854 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
19855 S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
19856 Expr *Args[] = {LHS.get(), RHS.get()};
19857 ReductionOp =
19858 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
19859 S.CurFPFeatureOverrides());
19860 } else {
19861 BinaryOperatorKind CombBOK = getRelatedCompoundReductionOp(BOK);
19862 if (Type->isRecordType() && CombBOK != BOK) {
19863 Sema::TentativeAnalysisScope Trap(S);
19864 ReductionOp =
19865 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19866 CombBOK, LHSDRE, RHSDRE);
19868 if (!ReductionOp.isUsable()) {
19869 ReductionOp =
19870 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
19871 LHSDRE, RHSDRE);
19872 if (ReductionOp.isUsable()) {
19873 if (BOK != BO_LT && BOK != BO_GT) {
19874 ReductionOp =
19875 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19876 BO_Assign, LHSDRE, ReductionOp.get());
19877 } else {
19878 auto *ConditionalOp = new (Context)
19879 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
19880 RHSDRE, Type, VK_LValue, OK_Ordinary);
19881 ReductionOp =
19882 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19883 BO_Assign, LHSDRE, ConditionalOp);
19887 if (ReductionOp.isUsable())
19888 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
19889 /*DiscardedValue*/ false);
19890 if (!ReductionOp.isUsable())
19891 continue;
19894 // Add copy operations for inscan reductions.
19895 // LHS = RHS;
19896 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
19897 if (ClauseKind == OMPC_reduction &&
19898 RD.RedModifier == OMPC_REDUCTION_inscan) {
19899 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
19900 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
19901 RHS.get());
19902 if (!CopyOpRes.isUsable())
19903 continue;
19904 CopyOpRes =
19905 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
19906 if (!CopyOpRes.isUsable())
19907 continue;
19908 // For simd directive and simd-based directives in simd mode no need to
19909 // construct temp array, need just a single temp element.
19910 if (Stack->getCurrentDirective() == OMPD_simd ||
19911 (S.getLangOpts().OpenMPSimd &&
19912 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
19913 VarDecl *TempArrayVD =
19914 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
19915 D->hasAttrs() ? &D->getAttrs() : nullptr);
19916 // Add a constructor to the temp decl.
19917 S.ActOnUninitializedDecl(TempArrayVD);
19918 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
19919 } else {
19920 // Build temp array for prefix sum.
19921 auto *Dim = new (S.Context)
19922 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
19923 QualType ArrayTy =
19924 S.Context.getVariableArrayType(PrivateTy, Dim, ArrayType::Normal,
19925 /*IndexTypeQuals=*/0, {ELoc, ELoc});
19926 VarDecl *TempArrayVD =
19927 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
19928 D->hasAttrs() ? &D->getAttrs() : nullptr);
19929 // Add a constructor to the temp decl.
19930 S.ActOnUninitializedDecl(TempArrayVD);
19931 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
19932 TempArrayElem =
19933 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
19934 auto *Idx = new (S.Context)
19935 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
19936 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
19937 ELoc, Idx, ELoc);
19941 // OpenMP [2.15.4.6, Restrictions, p.2]
19942 // A list item that appears in an in_reduction clause of a task construct
19943 // must appear in a task_reduction clause of a construct associated with a
19944 // taskgroup region that includes the participating task in its taskgroup
19945 // set. The construct associated with the innermost region that meets this
19946 // condition must specify the same reduction-identifier as the in_reduction
19947 // clause.
19948 if (ClauseKind == OMPC_in_reduction) {
19949 SourceRange ParentSR;
19950 BinaryOperatorKind ParentBOK;
19951 const Expr *ParentReductionOp = nullptr;
19952 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
19953 DSAStackTy::DSAVarData ParentBOKDSA =
19954 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
19955 ParentBOKTD);
19956 DSAStackTy::DSAVarData ParentReductionOpDSA =
19957 Stack->getTopMostTaskgroupReductionData(
19958 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
19959 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
19960 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
19961 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
19962 (DeclareReductionRef.isUsable() && IsParentBOK) ||
19963 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
19964 bool EmitError = true;
19965 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
19966 llvm::FoldingSetNodeID RedId, ParentRedId;
19967 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
19968 DeclareReductionRef.get()->Profile(RedId, Context,
19969 /*Canonical=*/true);
19970 EmitError = RedId != ParentRedId;
19972 if (EmitError) {
19973 S.Diag(ReductionId.getBeginLoc(),
19974 diag::err_omp_reduction_identifier_mismatch)
19975 << ReductionIdRange << RefExpr->getSourceRange();
19976 S.Diag(ParentSR.getBegin(),
19977 diag::note_omp_previous_reduction_identifier)
19978 << ParentSR
19979 << (IsParentBOK ? ParentBOKDSA.RefExpr
19980 : ParentReductionOpDSA.RefExpr)
19981 ->getSourceRange();
19982 continue;
19985 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
19988 DeclRefExpr *Ref = nullptr;
19989 Expr *VarsExpr = RefExpr->IgnoreParens();
19990 if (!VD && !S.CurContext->isDependentContext()) {
19991 if (ASE || OASE) {
19992 TransformExprToCaptures RebuildToCapture(S, D);
19993 VarsExpr =
19994 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
19995 Ref = RebuildToCapture.getCapturedExpr();
19996 } else {
19997 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
19999 if (!S.isOpenMPCapturedDecl(D)) {
20000 RD.ExprCaptures.emplace_back(Ref->getDecl());
20001 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
20002 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
20003 if (!RefRes.isUsable())
20004 continue;
20005 ExprResult PostUpdateRes =
20006 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
20007 RefRes.get());
20008 if (!PostUpdateRes.isUsable())
20009 continue;
20010 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
20011 Stack->getCurrentDirective() == OMPD_taskgroup) {
20012 S.Diag(RefExpr->getExprLoc(),
20013 diag::err_omp_reduction_non_addressable_expression)
20014 << RefExpr->getSourceRange();
20015 continue;
20017 RD.ExprPostUpdates.emplace_back(
20018 S.IgnoredValueConversions(PostUpdateRes.get()).get());
20022 // All reduction items are still marked as reduction (to do not increase
20023 // code base size).
20024 unsigned Modifier = RD.RedModifier;
20025 // Consider task_reductions as reductions with task modifier. Required for
20026 // correct analysis of in_reduction clauses.
20027 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
20028 Modifier = OMPC_REDUCTION_task;
20029 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
20030 ASE || OASE);
20031 if (Modifier == OMPC_REDUCTION_task &&
20032 (CurrDir == OMPD_taskgroup ||
20033 ((isOpenMPParallelDirective(CurrDir) ||
20034 isOpenMPWorksharingDirective(CurrDir)) &&
20035 !isOpenMPSimdDirective(CurrDir)))) {
20036 if (DeclareReductionRef.isUsable())
20037 Stack->addTaskgroupReductionData(D, ReductionIdRange,
20038 DeclareReductionRef.get());
20039 else
20040 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
20042 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
20043 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
20044 TempArrayElem.get());
20046 return RD.Vars.empty();
20049 OMPClause *Sema::ActOnOpenMPReductionClause(
20050 ArrayRef<Expr *> VarList, OpenMPReductionClauseModifier Modifier,
20051 SourceLocation StartLoc, SourceLocation LParenLoc,
20052 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
20053 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20054 ArrayRef<Expr *> UnresolvedReductions) {
20055 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
20056 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
20057 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
20058 /*Last=*/OMPC_REDUCTION_unknown)
20059 << getOpenMPClauseName(OMPC_reduction);
20060 return nullptr;
20062 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
20063 // A reduction clause with the inscan reduction-modifier may only appear on a
20064 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
20065 // construct, a parallel worksharing-loop construct or a parallel
20066 // worksharing-loop SIMD construct.
20067 if (Modifier == OMPC_REDUCTION_inscan &&
20068 (DSAStack->getCurrentDirective() != OMPD_for &&
20069 DSAStack->getCurrentDirective() != OMPD_for_simd &&
20070 DSAStack->getCurrentDirective() != OMPD_simd &&
20071 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
20072 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
20073 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
20074 return nullptr;
20077 ReductionData RD(VarList.size(), Modifier);
20078 if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_reduction, VarList,
20079 StartLoc, LParenLoc, ColonLoc, EndLoc,
20080 ReductionIdScopeSpec, ReductionId,
20081 UnresolvedReductions, RD))
20082 return nullptr;
20084 return OMPReductionClause::Create(
20085 Context, StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc, Modifier,
20086 RD.Vars, ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId,
20087 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
20088 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
20089 buildPreInits(Context, RD.ExprCaptures),
20090 buildPostUpdate(*this, RD.ExprPostUpdates));
20093 OMPClause *Sema::ActOnOpenMPTaskReductionClause(
20094 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20095 SourceLocation ColonLoc, SourceLocation EndLoc,
20096 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20097 ArrayRef<Expr *> UnresolvedReductions) {
20098 ReductionData RD(VarList.size());
20099 if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_task_reduction, VarList,
20100 StartLoc, LParenLoc, ColonLoc, EndLoc,
20101 ReductionIdScopeSpec, ReductionId,
20102 UnresolvedReductions, RD))
20103 return nullptr;
20105 return OMPTaskReductionClause::Create(
20106 Context, StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20107 ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId,
20108 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
20109 buildPreInits(Context, RD.ExprCaptures),
20110 buildPostUpdate(*this, RD.ExprPostUpdates));
20113 OMPClause *Sema::ActOnOpenMPInReductionClause(
20114 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20115 SourceLocation ColonLoc, SourceLocation EndLoc,
20116 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20117 ArrayRef<Expr *> UnresolvedReductions) {
20118 ReductionData RD(VarList.size());
20119 if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_in_reduction, VarList,
20120 StartLoc, LParenLoc, ColonLoc, EndLoc,
20121 ReductionIdScopeSpec, ReductionId,
20122 UnresolvedReductions, RD))
20123 return nullptr;
20125 return OMPInReductionClause::Create(
20126 Context, StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20127 ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId,
20128 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
20129 buildPreInits(Context, RD.ExprCaptures),
20130 buildPostUpdate(*this, RD.ExprPostUpdates));
20133 bool Sema::CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
20134 SourceLocation LinLoc) {
20135 if ((!LangOpts.CPlusPlus && LinKind != OMPC_LINEAR_val) ||
20136 LinKind == OMPC_LINEAR_unknown) {
20137 Diag(LinLoc, diag::err_omp_wrong_linear_modifier) << LangOpts.CPlusPlus;
20138 return true;
20140 return false;
20143 bool Sema::CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc,
20144 OpenMPLinearClauseKind LinKind, QualType Type,
20145 bool IsDeclareSimd) {
20146 const auto *VD = dyn_cast_or_null<VarDecl>(D);
20147 // A variable must not have an incomplete type or a reference type.
20148 if (RequireCompleteType(ELoc, Type, diag::err_omp_linear_incomplete_type))
20149 return true;
20150 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
20151 !Type->isReferenceType()) {
20152 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
20153 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
20154 return true;
20156 Type = Type.getNonReferenceType();
20158 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
20159 // A variable that is privatized must not have a const-qualified type
20160 // unless it is of class type with a mutable member. This restriction does
20161 // not apply to the firstprivate clause, nor to the linear clause on
20162 // declarative directives (like declare simd).
20163 if (!IsDeclareSimd &&
20164 rejectConstNotMutableType(*this, D, Type, OMPC_linear, ELoc))
20165 return true;
20167 // A list item must be of integral or pointer type.
20168 Type = Type.getUnqualifiedType().getCanonicalType();
20169 const auto *Ty = Type.getTypePtrOrNull();
20170 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
20171 !Ty->isIntegralType(Context) && !Ty->isPointerType())) {
20172 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
20173 if (D) {
20174 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20175 VarDecl::DeclarationOnly;
20176 Diag(D->getLocation(),
20177 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20178 << D;
20180 return true;
20182 return false;
20185 OMPClause *Sema::ActOnOpenMPLinearClause(
20186 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
20187 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
20188 SourceLocation LinLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
20189 SmallVector<Expr *, 8> Vars;
20190 SmallVector<Expr *, 8> Privates;
20191 SmallVector<Expr *, 8> Inits;
20192 SmallVector<Decl *, 4> ExprCaptures;
20193 SmallVector<Expr *, 4> ExprPostUpdates;
20194 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
20195 LinKind = OMPC_LINEAR_val;
20196 for (Expr *RefExpr : VarList) {
20197 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20198 SourceLocation ELoc;
20199 SourceRange ERange;
20200 Expr *SimpleRefExpr = RefExpr;
20201 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
20202 if (Res.second) {
20203 // It will be analyzed later.
20204 Vars.push_back(RefExpr);
20205 Privates.push_back(nullptr);
20206 Inits.push_back(nullptr);
20208 ValueDecl *D = Res.first;
20209 if (!D)
20210 continue;
20212 QualType Type = D->getType();
20213 auto *VD = dyn_cast<VarDecl>(D);
20215 // OpenMP [2.14.3.7, linear clause]
20216 // A list-item cannot appear in more than one linear clause.
20217 // A list-item that appears in a linear clause cannot appear in any
20218 // other data-sharing attribute clause.
20219 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
20220 if (DVar.RefExpr) {
20221 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
20222 << getOpenMPClauseName(OMPC_linear);
20223 reportOriginalDsa(*this, DSAStack, D, DVar);
20224 continue;
20227 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
20228 continue;
20229 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20231 // Build private copy of original var.
20232 VarDecl *Private =
20233 buildVarDecl(*this, ELoc, Type, D->getName(),
20234 D->hasAttrs() ? &D->getAttrs() : nullptr,
20235 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
20236 DeclRefExpr *PrivateRef = buildDeclRefExpr(*this, Private, Type, ELoc);
20237 // Build var to save initial value.
20238 VarDecl *Init = buildVarDecl(*this, ELoc, Type, ".linear.start");
20239 Expr *InitExpr;
20240 DeclRefExpr *Ref = nullptr;
20241 if (!VD && !CurContext->isDependentContext()) {
20242 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
20243 if (!isOpenMPCapturedDecl(D)) {
20244 ExprCaptures.push_back(Ref->getDecl());
20245 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
20246 ExprResult RefRes = DefaultLvalueConversion(Ref);
20247 if (!RefRes.isUsable())
20248 continue;
20249 ExprResult PostUpdateRes =
20250 BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
20251 SimpleRefExpr, RefRes.get());
20252 if (!PostUpdateRes.isUsable())
20253 continue;
20254 ExprPostUpdates.push_back(
20255 IgnoredValueConversions(PostUpdateRes.get()).get());
20259 if (LinKind == OMPC_LINEAR_uval)
20260 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
20261 else
20262 InitExpr = VD ? SimpleRefExpr : Ref;
20263 AddInitializerToDecl(Init, DefaultLvalueConversion(InitExpr).get(),
20264 /*DirectInit=*/false);
20265 DeclRefExpr *InitRef = buildDeclRefExpr(*this, Init, Type, ELoc);
20267 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
20268 Vars.push_back((VD || CurContext->isDependentContext())
20269 ? RefExpr->IgnoreParens()
20270 : Ref);
20271 Privates.push_back(PrivateRef);
20272 Inits.push_back(InitRef);
20275 if (Vars.empty())
20276 return nullptr;
20278 Expr *StepExpr = Step;
20279 Expr *CalcStepExpr = nullptr;
20280 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
20281 !Step->isInstantiationDependent() &&
20282 !Step->containsUnexpandedParameterPack()) {
20283 SourceLocation StepLoc = Step->getBeginLoc();
20284 ExprResult Val = PerformOpenMPImplicitIntegerConversion(StepLoc, Step);
20285 if (Val.isInvalid())
20286 return nullptr;
20287 StepExpr = Val.get();
20289 // Build var to save the step value.
20290 VarDecl *SaveVar =
20291 buildVarDecl(*this, StepLoc, StepExpr->getType(), ".linear.step");
20292 ExprResult SaveRef =
20293 buildDeclRefExpr(*this, SaveVar, StepExpr->getType(), StepLoc);
20294 ExprResult CalcStep =
20295 BuildBinOp(CurScope, StepLoc, BO_Assign, SaveRef.get(), StepExpr);
20296 CalcStep = ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue*/ false);
20298 // Warn about zero linear step (it would be probably better specified as
20299 // making corresponding variables 'const').
20300 if (std::optional<llvm::APSInt> Result =
20301 StepExpr->getIntegerConstantExpr(Context)) {
20302 if (!Result->isNegative() && !Result->isStrictlyPositive())
20303 Diag(StepLoc, diag::warn_omp_linear_step_zero)
20304 << Vars[0] << (Vars.size() > 1);
20305 } else if (CalcStep.isUsable()) {
20306 // Calculate the step beforehand instead of doing this on each iteration.
20307 // (This is not used if the number of iterations may be kfold-ed).
20308 CalcStepExpr = CalcStep.get();
20312 return OMPLinearClause::Create(Context, StartLoc, LParenLoc, LinKind, LinLoc,
20313 ColonLoc, EndLoc, Vars, Privates, Inits,
20314 StepExpr, CalcStepExpr,
20315 buildPreInits(Context, ExprCaptures),
20316 buildPostUpdate(*this, ExprPostUpdates));
20319 static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
20320 Expr *NumIterations, Sema &SemaRef,
20321 Scope *S, DSAStackTy *Stack) {
20322 // Walk the vars and build update/final expressions for the CodeGen.
20323 SmallVector<Expr *, 8> Updates;
20324 SmallVector<Expr *, 8> Finals;
20325 SmallVector<Expr *, 8> UsedExprs;
20326 Expr *Step = Clause.getStep();
20327 Expr *CalcStep = Clause.getCalcStep();
20328 // OpenMP [2.14.3.7, linear clause]
20329 // If linear-step is not specified it is assumed to be 1.
20330 if (!Step)
20331 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
20332 else if (CalcStep)
20333 Step = cast<BinaryOperator>(CalcStep)->getLHS();
20334 bool HasErrors = false;
20335 auto CurInit = Clause.inits().begin();
20336 auto CurPrivate = Clause.privates().begin();
20337 OpenMPLinearClauseKind LinKind = Clause.getModifier();
20338 for (Expr *RefExpr : Clause.varlists()) {
20339 SourceLocation ELoc;
20340 SourceRange ERange;
20341 Expr *SimpleRefExpr = RefExpr;
20342 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20343 ValueDecl *D = Res.first;
20344 if (Res.second || !D) {
20345 Updates.push_back(nullptr);
20346 Finals.push_back(nullptr);
20347 HasErrors = true;
20348 continue;
20350 auto &&Info = Stack->isLoopControlVariable(D);
20351 // OpenMP [2.15.11, distribute simd Construct]
20352 // A list item may not appear in a linear clause, unless it is the loop
20353 // iteration variable.
20354 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
20355 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
20356 SemaRef.Diag(ELoc,
20357 diag::err_omp_linear_distribute_var_non_loop_iteration);
20358 Updates.push_back(nullptr);
20359 Finals.push_back(nullptr);
20360 HasErrors = true;
20361 continue;
20363 Expr *InitExpr = *CurInit;
20365 // Build privatized reference to the current linear var.
20366 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
20367 Expr *CapturedRef;
20368 if (LinKind == OMPC_LINEAR_uval)
20369 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
20370 else
20371 CapturedRef =
20372 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
20373 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
20374 /*RefersToCapture=*/true);
20376 // Build update: Var = InitExpr + IV * Step
20377 ExprResult Update;
20378 if (!Info.first)
20379 Update = buildCounterUpdate(
20380 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
20381 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
20382 else
20383 Update = *CurPrivate;
20384 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
20385 /*DiscardedValue*/ false);
20387 // Build final: Var = PrivCopy;
20388 ExprResult Final;
20389 if (!Info.first)
20390 Final = SemaRef.BuildBinOp(
20391 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
20392 SemaRef.DefaultLvalueConversion(*CurPrivate).get());
20393 else
20394 Final = *CurPrivate;
20395 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
20396 /*DiscardedValue*/ false);
20398 if (!Update.isUsable() || !Final.isUsable()) {
20399 Updates.push_back(nullptr);
20400 Finals.push_back(nullptr);
20401 UsedExprs.push_back(nullptr);
20402 HasErrors = true;
20403 } else {
20404 Updates.push_back(Update.get());
20405 Finals.push_back(Final.get());
20406 if (!Info.first)
20407 UsedExprs.push_back(SimpleRefExpr);
20409 ++CurInit;
20410 ++CurPrivate;
20412 if (Expr *S = Clause.getStep())
20413 UsedExprs.push_back(S);
20414 // Fill the remaining part with the nullptr.
20415 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
20416 Clause.setUpdates(Updates);
20417 Clause.setFinals(Finals);
20418 Clause.setUsedExprs(UsedExprs);
20419 return HasErrors;
20422 OMPClause *Sema::ActOnOpenMPAlignedClause(
20423 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
20424 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
20425 SmallVector<Expr *, 8> Vars;
20426 for (Expr *RefExpr : VarList) {
20427 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20428 SourceLocation ELoc;
20429 SourceRange ERange;
20430 Expr *SimpleRefExpr = RefExpr;
20431 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
20432 if (Res.second) {
20433 // It will be analyzed later.
20434 Vars.push_back(RefExpr);
20436 ValueDecl *D = Res.first;
20437 if (!D)
20438 continue;
20440 QualType QType = D->getType();
20441 auto *VD = dyn_cast<VarDecl>(D);
20443 // OpenMP [2.8.1, simd construct, Restrictions]
20444 // The type of list items appearing in the aligned clause must be
20445 // array, pointer, reference to array, or reference to pointer.
20446 QType = QType.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20447 const Type *Ty = QType.getTypePtrOrNull();
20448 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
20449 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
20450 << QType << getLangOpts().CPlusPlus << ERange;
20451 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20452 VarDecl::DeclarationOnly;
20453 Diag(D->getLocation(),
20454 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20455 << D;
20456 continue;
20459 // OpenMP [2.8.1, simd construct, Restrictions]
20460 // A list-item cannot appear in more than one aligned clause.
20461 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
20462 Diag(ELoc, diag::err_omp_used_in_clause_twice)
20463 << 0 << getOpenMPClauseName(OMPC_aligned) << ERange;
20464 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
20465 << getOpenMPClauseName(OMPC_aligned);
20466 continue;
20469 DeclRefExpr *Ref = nullptr;
20470 if (!VD && isOpenMPCapturedDecl(D))
20471 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
20472 Vars.push_back(DefaultFunctionArrayConversion(
20473 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
20474 .get());
20477 // OpenMP [2.8.1, simd construct, Description]
20478 // The parameter of the aligned clause, alignment, must be a constant
20479 // positive integer expression.
20480 // If no optional parameter is specified, implementation-defined default
20481 // alignments for SIMD instructions on the target platforms are assumed.
20482 if (Alignment != nullptr) {
20483 ExprResult AlignResult =
20484 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
20485 if (AlignResult.isInvalid())
20486 return nullptr;
20487 Alignment = AlignResult.get();
20489 if (Vars.empty())
20490 return nullptr;
20492 return OMPAlignedClause::Create(Context, StartLoc, LParenLoc, ColonLoc,
20493 EndLoc, Vars, Alignment);
20496 OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
20497 SourceLocation StartLoc,
20498 SourceLocation LParenLoc,
20499 SourceLocation EndLoc) {
20500 SmallVector<Expr *, 8> Vars;
20501 SmallVector<Expr *, 8> SrcExprs;
20502 SmallVector<Expr *, 8> DstExprs;
20503 SmallVector<Expr *, 8> AssignmentOps;
20504 for (Expr *RefExpr : VarList) {
20505 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
20506 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20507 // It will be analyzed later.
20508 Vars.push_back(RefExpr);
20509 SrcExprs.push_back(nullptr);
20510 DstExprs.push_back(nullptr);
20511 AssignmentOps.push_back(nullptr);
20512 continue;
20515 SourceLocation ELoc = RefExpr->getExprLoc();
20516 // OpenMP [2.1, C/C++]
20517 // A list item is a variable name.
20518 // OpenMP [2.14.4.1, Restrictions, p.1]
20519 // A list item that appears in a copyin clause must be threadprivate.
20520 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
20521 if (!DE || !isa<VarDecl>(DE->getDecl())) {
20522 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
20523 << 0 << RefExpr->getSourceRange();
20524 continue;
20527 Decl *D = DE->getDecl();
20528 auto *VD = cast<VarDecl>(D);
20530 QualType Type = VD->getType();
20531 if (Type->isDependentType() || Type->isInstantiationDependentType()) {
20532 // It will be analyzed later.
20533 Vars.push_back(DE);
20534 SrcExprs.push_back(nullptr);
20535 DstExprs.push_back(nullptr);
20536 AssignmentOps.push_back(nullptr);
20537 continue;
20540 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
20541 // A list item that appears in a copyin clause must be threadprivate.
20542 if (!DSAStack->isThreadPrivate(VD)) {
20543 Diag(ELoc, diag::err_omp_required_access)
20544 << getOpenMPClauseName(OMPC_copyin)
20545 << getOpenMPDirectiveName(OMPD_threadprivate);
20546 continue;
20549 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20550 // A variable of class type (or array thereof) that appears in a
20551 // copyin clause requires an accessible, unambiguous copy assignment
20552 // operator for the class type.
20553 QualType ElemType = Context.getBaseElementType(Type).getNonReferenceType();
20554 VarDecl *SrcVD =
20555 buildVarDecl(*this, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
20556 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20557 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
20558 *this, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
20559 VarDecl *DstVD =
20560 buildVarDecl(*this, DE->getBeginLoc(), ElemType, ".copyin.dst",
20561 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20562 DeclRefExpr *PseudoDstExpr =
20563 buildDeclRefExpr(*this, DstVD, ElemType, DE->getExprLoc());
20564 // For arrays generate assignment operation for single element and replace
20565 // it by the original array element in CodeGen.
20566 ExprResult AssignmentOp =
20567 BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign, PseudoDstExpr,
20568 PseudoSrcExpr);
20569 if (AssignmentOp.isInvalid())
20570 continue;
20571 AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
20572 /*DiscardedValue*/ false);
20573 if (AssignmentOp.isInvalid())
20574 continue;
20576 DSAStack->addDSA(VD, DE, OMPC_copyin);
20577 Vars.push_back(DE);
20578 SrcExprs.push_back(PseudoSrcExpr);
20579 DstExprs.push_back(PseudoDstExpr);
20580 AssignmentOps.push_back(AssignmentOp.get());
20583 if (Vars.empty())
20584 return nullptr;
20586 return OMPCopyinClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars,
20587 SrcExprs, DstExprs, AssignmentOps);
20590 OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
20591 SourceLocation StartLoc,
20592 SourceLocation LParenLoc,
20593 SourceLocation EndLoc) {
20594 SmallVector<Expr *, 8> Vars;
20595 SmallVector<Expr *, 8> SrcExprs;
20596 SmallVector<Expr *, 8> DstExprs;
20597 SmallVector<Expr *, 8> AssignmentOps;
20598 for (Expr *RefExpr : VarList) {
20599 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20600 SourceLocation ELoc;
20601 SourceRange ERange;
20602 Expr *SimpleRefExpr = RefExpr;
20603 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
20604 if (Res.second) {
20605 // It will be analyzed later.
20606 Vars.push_back(RefExpr);
20607 SrcExprs.push_back(nullptr);
20608 DstExprs.push_back(nullptr);
20609 AssignmentOps.push_back(nullptr);
20611 ValueDecl *D = Res.first;
20612 if (!D)
20613 continue;
20615 QualType Type = D->getType();
20616 auto *VD = dyn_cast<VarDecl>(D);
20618 // OpenMP [2.14.4.2, Restrictions, p.2]
20619 // A list item that appears in a copyprivate clause may not appear in a
20620 // private or firstprivate clause on the single construct.
20621 if (!VD || !DSAStack->isThreadPrivate(VD)) {
20622 DSAStackTy::DSAVarData DVar =
20623 DSAStack->getTopDSA(D, /*FromParent=*/false);
20624 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
20625 DVar.RefExpr) {
20626 Diag(ELoc, diag::err_omp_wrong_dsa)
20627 << getOpenMPClauseName(DVar.CKind)
20628 << getOpenMPClauseName(OMPC_copyprivate);
20629 reportOriginalDsa(*this, DSAStack, D, DVar);
20630 continue;
20633 // OpenMP [2.11.4.2, Restrictions, p.1]
20634 // All list items that appear in a copyprivate clause must be either
20635 // threadprivate or private in the enclosing context.
20636 if (DVar.CKind == OMPC_unknown) {
20637 DVar = DSAStack->getImplicitDSA(D, false);
20638 if (DVar.CKind == OMPC_shared) {
20639 Diag(ELoc, diag::err_omp_required_access)
20640 << getOpenMPClauseName(OMPC_copyprivate)
20641 << "threadprivate or private in the enclosing context";
20642 reportOriginalDsa(*this, DSAStack, D, DVar);
20643 continue;
20648 // Variably modified types are not supported.
20649 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType()) {
20650 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
20651 << getOpenMPClauseName(OMPC_copyprivate) << Type
20652 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
20653 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20654 VarDecl::DeclarationOnly;
20655 Diag(D->getLocation(),
20656 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20657 << D;
20658 continue;
20661 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20662 // A variable of class type (or array thereof) that appears in a
20663 // copyin clause requires an accessible, unambiguous copy assignment
20664 // operator for the class type.
20665 Type = Context.getBaseElementType(Type.getNonReferenceType())
20666 .getUnqualifiedType();
20667 VarDecl *SrcVD =
20668 buildVarDecl(*this, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
20669 D->hasAttrs() ? &D->getAttrs() : nullptr);
20670 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(*this, SrcVD, Type, ELoc);
20671 VarDecl *DstVD =
20672 buildVarDecl(*this, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
20673 D->hasAttrs() ? &D->getAttrs() : nullptr);
20674 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc);
20675 ExprResult AssignmentOp = BuildBinOp(
20676 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
20677 if (AssignmentOp.isInvalid())
20678 continue;
20679 AssignmentOp =
20680 ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false);
20681 if (AssignmentOp.isInvalid())
20682 continue;
20684 // No need to mark vars as copyprivate, they are already threadprivate or
20685 // implicitly private.
20686 assert(VD || isOpenMPCapturedDecl(D));
20687 Vars.push_back(
20688 VD ? RefExpr->IgnoreParens()
20689 : buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false));
20690 SrcExprs.push_back(PseudoSrcExpr);
20691 DstExprs.push_back(PseudoDstExpr);
20692 AssignmentOps.push_back(AssignmentOp.get());
20695 if (Vars.empty())
20696 return nullptr;
20698 return OMPCopyprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
20699 Vars, SrcExprs, DstExprs, AssignmentOps);
20702 OMPClause *Sema::ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList,
20703 SourceLocation StartLoc,
20704 SourceLocation LParenLoc,
20705 SourceLocation EndLoc) {
20706 if (VarList.empty())
20707 return nullptr;
20709 return OMPFlushClause::Create(Context, StartLoc, LParenLoc, EndLoc, VarList);
20712 /// Tries to find omp_depend_t. type.
20713 static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
20714 bool Diagnose = true) {
20715 QualType OMPDependT = Stack->getOMPDependT();
20716 if (!OMPDependT.isNull())
20717 return true;
20718 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
20719 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
20720 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
20721 if (Diagnose)
20722 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
20723 return false;
20725 Stack->setOMPDependT(PT.get());
20726 return true;
20729 OMPClause *Sema::ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc,
20730 SourceLocation LParenLoc,
20731 SourceLocation EndLoc) {
20732 if (!Depobj)
20733 return nullptr;
20735 bool OMPDependTFound = findOMPDependT(*this, StartLoc, DSAStack);
20737 // OpenMP 5.0, 2.17.10.1 depobj Construct
20738 // depobj is an lvalue expression of type omp_depend_t.
20739 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
20740 !Depobj->isInstantiationDependent() &&
20741 !Depobj->containsUnexpandedParameterPack() &&
20742 (OMPDependTFound &&
20743 !Context.typesAreCompatible(DSAStack->getOMPDependT(), Depobj->getType(),
20744 /*CompareUnqualified=*/true))) {
20745 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20746 << 0 << Depobj->getType() << Depobj->getSourceRange();
20749 if (!Depobj->isLValue()) {
20750 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20751 << 1 << Depobj->getSourceRange();
20754 return OMPDepobjClause::Create(Context, StartLoc, LParenLoc, EndLoc, Depobj);
20757 namespace {
20758 // Utility struct that gathers the related info for doacross clause.
20759 struct DoacrossDataInfoTy {
20760 // The list of expressions.
20761 SmallVector<Expr *, 8> Vars;
20762 // The OperatorOffset for doacross loop.
20763 DSAStackTy::OperatorOffsetTy OpsOffs;
20764 // The depended loop count.
20765 llvm::APSInt TotalDepCount;
20767 } // namespace
20768 static DoacrossDataInfoTy
20769 ProcessOpenMPDoacrossClauseCommon(Sema &SemaRef, bool IsSource,
20770 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
20771 SourceLocation EndLoc) {
20773 SmallVector<Expr *, 8> Vars;
20774 DSAStackTy::OperatorOffsetTy OpsOffs;
20775 llvm::APSInt DepCounter(/*BitWidth=*/32);
20776 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
20778 if (const Expr *OrderedCountExpr =
20779 Stack->getParentOrderedRegionParam().first) {
20780 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.Context);
20781 TotalDepCount.setIsUnsigned(/*Val=*/true);
20784 for (Expr *RefExpr : VarList) {
20785 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
20786 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20787 // It will be analyzed later.
20788 Vars.push_back(RefExpr);
20789 continue;
20792 SourceLocation ELoc = RefExpr->getExprLoc();
20793 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
20794 if (!IsSource) {
20795 if (Stack->getParentOrderedRegionParam().first &&
20796 DepCounter >= TotalDepCount) {
20797 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
20798 continue;
20800 ++DepCounter;
20801 // OpenMP [2.13.9, Summary]
20802 // depend(dependence-type : vec), where dependence-type is:
20803 // 'sink' and where vec is the iteration vector, which has the form:
20804 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
20805 // where n is the value specified by the ordered clause in the loop
20806 // directive, xi denotes the loop iteration variable of the i-th nested
20807 // loop associated with the loop directive, and di is a constant
20808 // non-negative integer.
20809 if (SemaRef.CurContext->isDependentContext()) {
20810 // It will be analyzed later.
20811 Vars.push_back(RefExpr);
20812 continue;
20814 SimpleExpr = SimpleExpr->IgnoreImplicit();
20815 OverloadedOperatorKind OOK = OO_None;
20816 SourceLocation OOLoc;
20817 Expr *LHS = SimpleExpr;
20818 Expr *RHS = nullptr;
20819 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
20820 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
20821 OOLoc = BO->getOperatorLoc();
20822 LHS = BO->getLHS()->IgnoreParenImpCasts();
20823 RHS = BO->getRHS()->IgnoreParenImpCasts();
20824 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
20825 OOK = OCE->getOperator();
20826 OOLoc = OCE->getOperatorLoc();
20827 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20828 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
20829 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
20830 OOK = MCE->getMethodDecl()
20831 ->getNameInfo()
20832 .getName()
20833 .getCXXOverloadedOperator();
20834 OOLoc = MCE->getCallee()->getExprLoc();
20835 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
20836 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20838 SourceLocation ELoc;
20839 SourceRange ERange;
20840 auto Res = getPrivateItem(SemaRef, LHS, ELoc, ERange);
20841 if (Res.second) {
20842 // It will be analyzed later.
20843 Vars.push_back(RefExpr);
20845 ValueDecl *D = Res.first;
20846 if (!D)
20847 continue;
20849 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
20850 SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
20851 continue;
20853 if (RHS) {
20854 ExprResult RHSRes = SemaRef.VerifyPositiveIntegerConstantInClause(
20855 RHS, OMPC_depend, /*StrictlyPositive=*/false);
20856 if (RHSRes.isInvalid())
20857 continue;
20859 if (!SemaRef.CurContext->isDependentContext() &&
20860 Stack->getParentOrderedRegionParam().first &&
20861 DepCounter != Stack->isParentLoopControlVariable(D).first) {
20862 const ValueDecl *VD =
20863 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
20864 if (VD)
20865 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
20866 << 1 << VD;
20867 else
20868 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
20869 << 0;
20870 continue;
20872 OpsOffs.emplace_back(RHS, OOK);
20874 Vars.push_back(RefExpr->IgnoreParenImpCasts());
20876 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
20877 TotalDepCount > VarList.size() &&
20878 Stack->getParentOrderedRegionParam().first &&
20879 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
20880 SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
20881 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
20883 return {Vars, OpsOffs, TotalDepCount};
20886 OMPClause *
20887 Sema::ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data,
20888 Expr *DepModifier, ArrayRef<Expr *> VarList,
20889 SourceLocation StartLoc, SourceLocation LParenLoc,
20890 SourceLocation EndLoc) {
20891 OpenMPDependClauseKind DepKind = Data.DepKind;
20892 SourceLocation DepLoc = Data.DepLoc;
20893 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
20894 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
20895 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20896 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
20897 return nullptr;
20899 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
20900 DepKind == OMPC_DEPEND_mutexinoutset) {
20901 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
20902 return nullptr;
20904 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
20905 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20906 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
20907 DepKind == OMPC_DEPEND_sink ||
20908 ((LangOpts.OpenMP < 50 ||
20909 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20910 DepKind == OMPC_DEPEND_depobj))) {
20911 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
20912 OMPC_DEPEND_outallmemory,
20913 OMPC_DEPEND_inoutallmemory};
20914 if (LangOpts.OpenMP < 50 || DSAStack->getCurrentDirective() == OMPD_depobj)
20915 Except.push_back(OMPC_DEPEND_depobj);
20916 if (LangOpts.OpenMP < 51)
20917 Except.push_back(OMPC_DEPEND_inoutset);
20918 std::string Expected = (LangOpts.OpenMP >= 50 && !DepModifier)
20919 ? "depend modifier(iterator) or "
20920 : "";
20921 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20922 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
20923 /*Last=*/OMPC_DEPEND_unknown,
20924 Except)
20925 << getOpenMPClauseName(OMPC_depend);
20926 return nullptr;
20928 if (DepModifier &&
20929 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
20930 Diag(DepModifier->getExprLoc(),
20931 diag::err_omp_depend_sink_source_with_modifier);
20932 return nullptr;
20934 if (DepModifier &&
20935 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
20936 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
20938 SmallVector<Expr *, 8> Vars;
20939 DSAStackTy::OperatorOffsetTy OpsOffs;
20940 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
20942 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
20943 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
20944 *this, DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
20945 Vars = VarOffset.Vars;
20946 OpsOffs = VarOffset.OpsOffs;
20947 TotalDepCount = VarOffset.TotalDepCount;
20948 } else {
20949 for (Expr *RefExpr : VarList) {
20950 assert(RefExpr && "NULL expr in OpenMP shared clause.");
20951 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20952 // It will be analyzed later.
20953 Vars.push_back(RefExpr);
20954 continue;
20957 SourceLocation ELoc = RefExpr->getExprLoc();
20958 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
20959 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
20960 bool OMPDependTFound = LangOpts.OpenMP >= 50;
20961 if (OMPDependTFound)
20962 OMPDependTFound = findOMPDependT(*this, StartLoc, DSAStack,
20963 DepKind == OMPC_DEPEND_depobj);
20964 if (DepKind == OMPC_DEPEND_depobj) {
20965 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20966 // List items used in depend clauses with the depobj dependence type
20967 // must be expressions of the omp_depend_t type.
20968 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20969 !RefExpr->isInstantiationDependent() &&
20970 !RefExpr->containsUnexpandedParameterPack() &&
20971 (OMPDependTFound &&
20972 !Context.hasSameUnqualifiedType(DSAStack->getOMPDependT(),
20973 RefExpr->getType()))) {
20974 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20975 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
20976 continue;
20978 if (!RefExpr->isLValue()) {
20979 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20980 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
20981 continue;
20983 } else {
20984 // OpenMP 5.0 [2.17.11, Restrictions]
20985 // List items used in depend clauses cannot be zero-length array
20986 // sections.
20987 QualType ExprTy = RefExpr->getType().getNonReferenceType();
20988 const auto *OASE = dyn_cast<OMPArraySectionExpr>(SimpleExpr);
20989 if (OASE) {
20990 QualType BaseType =
20991 OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
20992 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20993 ExprTy = ATy->getElementType();
20994 else
20995 ExprTy = BaseType->getPointeeType();
20996 ExprTy = ExprTy.getNonReferenceType();
20997 const Expr *Length = OASE->getLength();
20998 Expr::EvalResult Result;
20999 if (Length && !Length->isValueDependent() &&
21000 Length->EvaluateAsInt(Result, Context) &&
21001 Result.Val.getInt().isZero()) {
21002 Diag(ELoc,
21003 diag::err_omp_depend_zero_length_array_section_not_allowed)
21004 << SimpleExpr->getSourceRange();
21005 continue;
21009 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21010 // List items used in depend clauses with the in, out, inout,
21011 // inoutset, or mutexinoutset dependence types cannot be
21012 // expressions of the omp_depend_t type.
21013 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21014 !RefExpr->isInstantiationDependent() &&
21015 !RefExpr->containsUnexpandedParameterPack() &&
21016 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
21017 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
21018 ExprTy.getTypePtr()))) {
21019 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21020 << (LangOpts.OpenMP >= 50 ? 1 : 0)
21021 << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
21022 continue;
21025 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
21026 if (ASE && !ASE->getBase()->isTypeDependent() &&
21027 !ASE->getBase()
21028 ->getType()
21029 .getNonReferenceType()
21030 ->isPointerType() &&
21031 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
21032 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21033 << (LangOpts.OpenMP >= 50 ? 1 : 0)
21034 << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
21035 continue;
21038 ExprResult Res;
21040 Sema::TentativeAnalysisScope Trap(*this);
21041 Res = CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
21042 RefExpr->IgnoreParenImpCasts());
21044 if (!Res.isUsable() && !isa<OMPArraySectionExpr>(SimpleExpr) &&
21045 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
21046 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21047 << (LangOpts.OpenMP >= 50 ? 1 : 0)
21048 << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
21049 continue;
21053 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21057 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
21058 DepKind != OMPC_DEPEND_outallmemory &&
21059 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
21060 return nullptr;
21062 auto *C = OMPDependClause::Create(
21063 Context, StartLoc, LParenLoc, EndLoc,
21064 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
21065 TotalDepCount.getZExtValue());
21066 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
21067 DSAStack->isParentOrderedRegion())
21068 DSAStack->addDoacrossDependClause(C, OpsOffs);
21069 return C;
21072 OMPClause *Sema::ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier,
21073 Expr *Device, SourceLocation StartLoc,
21074 SourceLocation LParenLoc,
21075 SourceLocation ModifierLoc,
21076 SourceLocation EndLoc) {
21077 assert((ModifierLoc.isInvalid() || LangOpts.OpenMP >= 50) &&
21078 "Unexpected device modifier in OpenMP < 50.");
21080 bool ErrorFound = false;
21081 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
21082 std::string Values =
21083 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
21084 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
21085 << Values << getOpenMPClauseName(OMPC_device);
21086 ErrorFound = true;
21089 Expr *ValExpr = Device;
21090 Stmt *HelperValStmt = nullptr;
21092 // OpenMP [2.9.1, Restrictions]
21093 // The device expression must evaluate to a non-negative integer value.
21094 ErrorFound = !isNonNegativeIntegerValue(ValExpr, *this, OMPC_device,
21095 /*StrictlyPositive=*/false) ||
21096 ErrorFound;
21097 if (ErrorFound)
21098 return nullptr;
21100 // OpenMP 5.0 [2.12.5, Restrictions]
21101 // In case of ancestor device-modifier, a requires directive with
21102 // the reverse_offload clause must be specified.
21103 if (Modifier == OMPC_DEVICE_ancestor) {
21104 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
21105 targetDiag(
21106 StartLoc,
21107 diag::err_omp_device_ancestor_without_requires_reverse_offload);
21108 ErrorFound = true;
21112 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
21113 OpenMPDirectiveKind CaptureRegion =
21114 getOpenMPCaptureRegionForClause(DKind, OMPC_device, LangOpts.OpenMP);
21115 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
21116 ValExpr = MakeFullExpr(ValExpr).get();
21117 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21118 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
21119 HelperValStmt = buildPreInits(Context, Captures);
21122 return new (Context)
21123 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
21124 LParenLoc, ModifierLoc, EndLoc);
21127 static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef,
21128 DSAStackTy *Stack, QualType QTy,
21129 bool FullCheck = true) {
21130 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
21131 return false;
21132 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
21133 !QTy.isTriviallyCopyableType(SemaRef.Context))
21134 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
21135 return true;
21138 /// Return true if it can be proven that the provided array expression
21139 /// (array section or array subscript) does NOT specify the whole size of the
21140 /// array whose base type is \a BaseQTy.
21141 static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
21142 const Expr *E,
21143 QualType BaseQTy) {
21144 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
21146 // If this is an array subscript, it refers to the whole size if the size of
21147 // the dimension is constant and equals 1. Also, an array section assumes the
21148 // format of an array subscript if no colon is used.
21149 if (isa<ArraySubscriptExpr>(E) ||
21150 (OASE && OASE->getColonLocFirst().isInvalid())) {
21151 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
21152 return ATy->getSize().getSExtValue() != 1;
21153 // Size can't be evaluated statically.
21154 return false;
21157 assert(OASE && "Expecting array section if not an array subscript.");
21158 const Expr *LowerBound = OASE->getLowerBound();
21159 const Expr *Length = OASE->getLength();
21161 // If there is a lower bound that does not evaluates to zero, we are not
21162 // covering the whole dimension.
21163 if (LowerBound) {
21164 Expr::EvalResult Result;
21165 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
21166 return false; // Can't get the integer value as a constant.
21168 llvm::APSInt ConstLowerBound = Result.Val.getInt();
21169 if (ConstLowerBound.getSExtValue())
21170 return true;
21173 // If we don't have a length we covering the whole dimension.
21174 if (!Length)
21175 return false;
21177 // If the base is a pointer, we don't have a way to get the size of the
21178 // pointee.
21179 if (BaseQTy->isPointerType())
21180 return false;
21182 // We can only check if the length is the same as the size of the dimension
21183 // if we have a constant array.
21184 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
21185 if (!CATy)
21186 return false;
21188 Expr::EvalResult Result;
21189 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
21190 return false; // Can't get the integer value as a constant.
21192 llvm::APSInt ConstLength = Result.Val.getInt();
21193 return CATy->getSize().getSExtValue() != ConstLength.getSExtValue();
21196 // Return true if it can be proven that the provided array expression (array
21197 // section or array subscript) does NOT specify a single element of the array
21198 // whose base type is \a BaseQTy.
21199 static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
21200 const Expr *E,
21201 QualType BaseQTy) {
21202 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
21204 // An array subscript always refer to a single element. Also, an array section
21205 // assumes the format of an array subscript if no colon is used.
21206 if (isa<ArraySubscriptExpr>(E) ||
21207 (OASE && OASE->getColonLocFirst().isInvalid()))
21208 return false;
21210 assert(OASE && "Expecting array section if not an array subscript.");
21211 const Expr *Length = OASE->getLength();
21213 // If we don't have a length we have to check if the array has unitary size
21214 // for this dimension. Also, we should always expect a length if the base type
21215 // is pointer.
21216 if (!Length) {
21217 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
21218 return ATy->getSize().getSExtValue() != 1;
21219 // We cannot assume anything.
21220 return false;
21223 // Check if the length evaluates to 1.
21224 Expr::EvalResult Result;
21225 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
21226 return false; // Can't get the integer value as a constant.
21228 llvm::APSInt ConstLength = Result.Val.getInt();
21229 return ConstLength.getSExtValue() != 1;
21232 // The base of elements of list in a map clause have to be either:
21233 // - a reference to variable or field.
21234 // - a member expression.
21235 // - an array expression.
21237 // E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
21238 // reference to 'r'.
21240 // If we have:
21242 // struct SS {
21243 // Bla S;
21244 // foo() {
21245 // #pragma omp target map (S.Arr[:12]);
21246 // }
21247 // }
21249 // We want to retrieve the member expression 'this->S';
21251 // OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
21252 // If a list item is an array section, it must specify contiguous storage.
21254 // For this restriction it is sufficient that we make sure only references
21255 // to variables or fields and array expressions, and that no array sections
21256 // exist except in the rightmost expression (unless they cover the whole
21257 // dimension of the array). E.g. these would be invalid:
21259 // r.ArrS[3:5].Arr[6:7]
21261 // r.ArrS[3:5].x
21263 // but these would be valid:
21264 // r.ArrS[3].Arr[6:7]
21266 // r.ArrS[3].x
21267 namespace {
21268 class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
21269 Sema &SemaRef;
21270 OpenMPClauseKind CKind = OMPC_unknown;
21271 OpenMPDirectiveKind DKind = OMPD_unknown;
21272 OMPClauseMappableExprCommon::MappableExprComponentList &Components;
21273 bool IsNonContiguous = false;
21274 bool NoDiagnose = false;
21275 const Expr *RelevantExpr = nullptr;
21276 bool AllowUnitySizeArraySection = true;
21277 bool AllowWholeSizeArraySection = true;
21278 bool AllowAnotherPtr = true;
21279 SourceLocation ELoc;
21280 SourceRange ERange;
21282 void emitErrorMsg() {
21283 // If nothing else worked, this is not a valid map clause expression.
21284 if (SemaRef.getLangOpts().OpenMP < 50) {
21285 SemaRef.Diag(ELoc,
21286 diag::err_omp_expected_named_var_member_or_array_expression)
21287 << ERange;
21288 } else {
21289 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21290 << getOpenMPClauseName(CKind) << ERange;
21294 public:
21295 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
21296 if (!isa<VarDecl>(DRE->getDecl())) {
21297 emitErrorMsg();
21298 return false;
21300 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21301 RelevantExpr = DRE;
21302 // Record the component.
21303 Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
21304 return true;
21307 bool VisitMemberExpr(MemberExpr *ME) {
21308 Expr *E = ME;
21309 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
21311 if (isa<CXXThisExpr>(BaseE)) {
21312 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21313 // We found a base expression: this->Val.
21314 RelevantExpr = ME;
21315 } else {
21316 E = BaseE;
21319 if (!isa<FieldDecl>(ME->getMemberDecl())) {
21320 if (!NoDiagnose) {
21321 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
21322 << ME->getSourceRange();
21323 return false;
21325 if (RelevantExpr)
21326 return false;
21327 return Visit(E);
21330 auto *FD = cast<FieldDecl>(ME->getMemberDecl());
21332 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
21333 // A bit-field cannot appear in a map clause.
21335 if (FD->isBitField()) {
21336 if (!NoDiagnose) {
21337 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
21338 << ME->getSourceRange() << getOpenMPClauseName(CKind);
21339 return false;
21341 if (RelevantExpr)
21342 return false;
21343 return Visit(E);
21346 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21347 // If the type of a list item is a reference to a type T then the type
21348 // will be considered to be T for all purposes of this clause.
21349 QualType CurType = BaseE->getType().getNonReferenceType();
21351 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
21352 // A list item cannot be a variable that is a member of a structure with
21353 // a union type.
21355 if (CurType->isUnionType()) {
21356 if (!NoDiagnose) {
21357 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
21358 << ME->getSourceRange();
21359 return false;
21361 return RelevantExpr || Visit(E);
21364 // If we got a member expression, we should not expect any array section
21365 // before that:
21367 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
21368 // If a list item is an element of a structure, only the rightmost symbol
21369 // of the variable reference can be an array section.
21371 AllowUnitySizeArraySection = false;
21372 AllowWholeSizeArraySection = false;
21374 // Record the component.
21375 Components.emplace_back(ME, FD, IsNonContiguous);
21376 return RelevantExpr || Visit(E);
21379 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
21380 Expr *E = AE->getBase()->IgnoreParenImpCasts();
21382 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
21383 if (!NoDiagnose) {
21384 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21385 << 0 << AE->getSourceRange();
21386 return false;
21388 return RelevantExpr || Visit(E);
21391 // If we got an array subscript that express the whole dimension we
21392 // can have any array expressions before. If it only expressing part of
21393 // the dimension, we can only have unitary-size array expressions.
21394 if (checkArrayExpressionDoesNotReferToWholeSize(SemaRef, AE, E->getType()))
21395 AllowWholeSizeArraySection = false;
21397 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
21398 Expr::EvalResult Result;
21399 if (!AE->getIdx()->isValueDependent() &&
21400 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
21401 !Result.Val.getInt().isZero()) {
21402 SemaRef.Diag(AE->getIdx()->getExprLoc(),
21403 diag::err_omp_invalid_map_this_expr);
21404 SemaRef.Diag(AE->getIdx()->getExprLoc(),
21405 diag::note_omp_invalid_subscript_on_this_ptr_map);
21407 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21408 RelevantExpr = TE;
21411 // Record the component - we don't have any declaration associated.
21412 Components.emplace_back(AE, nullptr, IsNonContiguous);
21414 return RelevantExpr || Visit(E);
21417 bool VisitOMPArraySectionExpr(OMPArraySectionExpr *OASE) {
21418 // After OMP 5.0 Array section in reduction clause will be implicitly
21419 // mapped
21420 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
21421 "Array sections cannot be implicitly mapped.");
21422 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21423 QualType CurType =
21424 OMPArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
21426 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21427 // If the type of a list item is a reference to a type T then the type
21428 // will be considered to be T for all purposes of this clause.
21429 if (CurType->isReferenceType())
21430 CurType = CurType->getPointeeType();
21432 bool IsPointer = CurType->isAnyPointerType();
21434 if (!IsPointer && !CurType->isArrayType()) {
21435 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21436 << 0 << OASE->getSourceRange();
21437 return false;
21440 bool NotWhole =
21441 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
21442 bool NotUnity =
21443 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
21445 if (AllowWholeSizeArraySection) {
21446 // Any array section is currently allowed. Allowing a whole size array
21447 // section implies allowing a unity array section as well.
21449 // If this array section refers to the whole dimension we can still
21450 // accept other array sections before this one, except if the base is a
21451 // pointer. Otherwise, only unitary sections are accepted.
21452 if (NotWhole || IsPointer)
21453 AllowWholeSizeArraySection = false;
21454 } else if (DKind == OMPD_target_update &&
21455 SemaRef.getLangOpts().OpenMP >= 50) {
21456 if (IsPointer && !AllowAnotherPtr)
21457 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
21458 << /*array of unknown bound */ 1;
21459 else
21460 IsNonContiguous = true;
21461 } else if (AllowUnitySizeArraySection && NotUnity) {
21462 // A unity or whole array section is not allowed and that is not
21463 // compatible with the properties of the current array section.
21464 if (NoDiagnose)
21465 return false;
21466 SemaRef.Diag(ELoc,
21467 diag::err_array_section_does_not_specify_contiguous_storage)
21468 << OASE->getSourceRange();
21469 return false;
21472 if (IsPointer)
21473 AllowAnotherPtr = false;
21475 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
21476 Expr::EvalResult ResultR;
21477 Expr::EvalResult ResultL;
21478 if (!OASE->getLength()->isValueDependent() &&
21479 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
21480 !ResultR.Val.getInt().isOne()) {
21481 SemaRef.Diag(OASE->getLength()->getExprLoc(),
21482 diag::err_omp_invalid_map_this_expr);
21483 SemaRef.Diag(OASE->getLength()->getExprLoc(),
21484 diag::note_omp_invalid_length_on_this_ptr_mapping);
21486 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
21487 OASE->getLowerBound()->EvaluateAsInt(ResultL,
21488 SemaRef.getASTContext()) &&
21489 !ResultL.Val.getInt().isZero()) {
21490 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
21491 diag::err_omp_invalid_map_this_expr);
21492 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
21493 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
21495 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21496 RelevantExpr = TE;
21499 // Record the component - we don't have any declaration associated.
21500 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
21501 return RelevantExpr || Visit(E);
21503 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
21504 Expr *Base = E->getBase();
21506 // Record the component - we don't have any declaration associated.
21507 Components.emplace_back(E, nullptr, IsNonContiguous);
21509 return Visit(Base->IgnoreParenImpCasts());
21512 bool VisitUnaryOperator(UnaryOperator *UO) {
21513 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
21514 UO->getOpcode() != UO_Deref) {
21515 emitErrorMsg();
21516 return false;
21518 if (!RelevantExpr) {
21519 // Record the component if haven't found base decl.
21520 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
21522 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
21524 bool VisitBinaryOperator(BinaryOperator *BO) {
21525 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
21526 emitErrorMsg();
21527 return false;
21530 // Pointer arithmetic is the only thing we expect to happen here so after we
21531 // make sure the binary operator is a pointer type, the only thing we need
21532 // to do is to visit the subtree that has the same type as root (so that we
21533 // know the other subtree is just an offset)
21534 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
21535 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
21536 Components.emplace_back(BO, nullptr, false);
21537 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
21538 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
21539 "Either LHS or RHS have base decl inside");
21540 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
21541 return RelevantExpr || Visit(LE);
21542 return RelevantExpr || Visit(RE);
21544 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
21545 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21546 RelevantExpr = CTE;
21547 Components.emplace_back(CTE, nullptr, IsNonContiguous);
21548 return true;
21550 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
21551 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21552 Components.emplace_back(COCE, nullptr, IsNonContiguous);
21553 return true;
21555 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
21556 Expr *Source = E->getSourceExpr();
21557 if (!Source) {
21558 emitErrorMsg();
21559 return false;
21561 return Visit(Source);
21563 bool VisitStmt(Stmt *) {
21564 emitErrorMsg();
21565 return false;
21567 const Expr *getFoundBase() const { return RelevantExpr; }
21568 explicit MapBaseChecker(
21569 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
21570 OMPClauseMappableExprCommon::MappableExprComponentList &Components,
21571 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
21572 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
21573 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
21575 } // namespace
21577 /// Return the expression of the base of the mappable expression or null if it
21578 /// cannot be determined and do all the necessary checks to see if the
21579 /// expression is valid as a standalone mappable expression. In the process,
21580 /// record all the components of the expression.
21581 static const Expr *checkMapClauseExpressionBase(
21582 Sema &SemaRef, Expr *E,
21583 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
21584 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
21585 SourceLocation ELoc = E->getExprLoc();
21586 SourceRange ERange = E->getSourceRange();
21587 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
21588 ERange);
21589 if (Checker.Visit(E->IgnoreParens())) {
21590 // Check if the highest dimension array section has length specified
21591 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
21592 (CKind == OMPC_to || CKind == OMPC_from)) {
21593 auto CI = CurComponents.rbegin();
21594 auto CE = CurComponents.rend();
21595 for (; CI != CE; ++CI) {
21596 const auto *OASE =
21597 dyn_cast<OMPArraySectionExpr>(CI->getAssociatedExpression());
21598 if (!OASE)
21599 continue;
21600 if (OASE && OASE->getLength())
21601 break;
21602 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
21603 << ERange;
21606 return Checker.getFoundBase();
21608 return nullptr;
21611 // Return true if expression E associated with value VD has conflicts with other
21612 // map information.
21613 static bool checkMapConflicts(
21614 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
21615 bool CurrentRegionOnly,
21616 OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents,
21617 OpenMPClauseKind CKind) {
21618 assert(VD && E);
21619 SourceLocation ELoc = E->getExprLoc();
21620 SourceRange ERange = E->getSourceRange();
21622 // In order to easily check the conflicts we need to match each component of
21623 // the expression under test with the components of the expressions that are
21624 // already in the stack.
21626 assert(!CurComponents.empty() && "Map clause expression with no components!");
21627 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
21628 "Map clause expression with unexpected base!");
21630 // Variables to help detecting enclosing problems in data environment nests.
21631 bool IsEnclosedByDataEnvironmentExpr = false;
21632 const Expr *EnclosingExpr = nullptr;
21634 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
21635 VD, CurrentRegionOnly,
21636 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
21637 ERange, CKind, &EnclosingExpr,
21638 CurComponents](OMPClauseMappableExprCommon::MappableExprComponentListRef
21639 StackComponents,
21640 OpenMPClauseKind Kind) {
21641 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
21642 return false;
21643 assert(!StackComponents.empty() &&
21644 "Map clause expression with no components!");
21645 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
21646 "Map clause expression with unexpected base!");
21647 (void)VD;
21649 // The whole expression in the stack.
21650 const Expr *RE = StackComponents.front().getAssociatedExpression();
21652 // Expressions must start from the same base. Here we detect at which
21653 // point both expressions diverge from each other and see if we can
21654 // detect if the memory referred to both expressions is contiguous and
21655 // do not overlap.
21656 auto CI = CurComponents.rbegin();
21657 auto CE = CurComponents.rend();
21658 auto SI = StackComponents.rbegin();
21659 auto SE = StackComponents.rend();
21660 for (; CI != CE && SI != SE; ++CI, ++SI) {
21662 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
21663 // At most one list item can be an array item derived from a given
21664 // variable in map clauses of the same construct.
21665 if (CurrentRegionOnly &&
21666 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
21667 isa<OMPArraySectionExpr>(CI->getAssociatedExpression()) ||
21668 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
21669 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
21670 isa<OMPArraySectionExpr>(SI->getAssociatedExpression()) ||
21671 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
21672 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
21673 diag::err_omp_multiple_array_items_in_map_clause)
21674 << CI->getAssociatedExpression()->getSourceRange();
21675 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
21676 diag::note_used_here)
21677 << SI->getAssociatedExpression()->getSourceRange();
21678 return true;
21681 // Do both expressions have the same kind?
21682 if (CI->getAssociatedExpression()->getStmtClass() !=
21683 SI->getAssociatedExpression()->getStmtClass())
21684 break;
21686 // Are we dealing with different variables/fields?
21687 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
21688 break;
21690 // Check if the extra components of the expressions in the enclosing
21691 // data environment are redundant for the current base declaration.
21692 // If they are, the maps completely overlap, which is legal.
21693 for (; SI != SE; ++SI) {
21694 QualType Type;
21695 if (const auto *ASE =
21696 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
21697 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
21698 } else if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(
21699 SI->getAssociatedExpression())) {
21700 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21701 Type =
21702 OMPArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
21703 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
21704 SI->getAssociatedExpression())) {
21705 Type = OASE->getBase()->getType()->getPointeeType();
21707 if (Type.isNull() || Type->isAnyPointerType() ||
21708 checkArrayExpressionDoesNotReferToWholeSize(
21709 SemaRef, SI->getAssociatedExpression(), Type))
21710 break;
21713 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21714 // List items of map clauses in the same construct must not share
21715 // original storage.
21717 // If the expressions are exactly the same or one is a subset of the
21718 // other, it means they are sharing storage.
21719 if (CI == CE && SI == SE) {
21720 if (CurrentRegionOnly) {
21721 if (CKind == OMPC_map) {
21722 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21723 } else {
21724 assert(CKind == OMPC_to || CKind == OMPC_from);
21725 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21726 << ERange;
21728 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21729 << RE->getSourceRange();
21730 return true;
21732 // If we find the same expression in the enclosing data environment,
21733 // that is legal.
21734 IsEnclosedByDataEnvironmentExpr = true;
21735 return false;
21738 QualType DerivedType =
21739 std::prev(CI)->getAssociatedDeclaration()->getType();
21740 SourceLocation DerivedLoc =
21741 std::prev(CI)->getAssociatedExpression()->getExprLoc();
21743 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21744 // If the type of a list item is a reference to a type T then the type
21745 // will be considered to be T for all purposes of this clause.
21746 DerivedType = DerivedType.getNonReferenceType();
21748 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
21749 // A variable for which the type is pointer and an array section
21750 // derived from that variable must not appear as list items of map
21751 // clauses of the same construct.
21753 // Also, cover one of the cases in:
21754 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21755 // If any part of the original storage of a list item has corresponding
21756 // storage in the device data environment, all of the original storage
21757 // must have corresponding storage in the device data environment.
21759 if (DerivedType->isAnyPointerType()) {
21760 if (CI == CE || SI == SE) {
21761 SemaRef.Diag(
21762 DerivedLoc,
21763 diag::err_omp_pointer_mapped_along_with_derived_section)
21764 << DerivedLoc;
21765 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21766 << RE->getSourceRange();
21767 return true;
21769 if (CI->getAssociatedExpression()->getStmtClass() !=
21770 SI->getAssociatedExpression()->getStmtClass() ||
21771 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
21772 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
21773 assert(CI != CE && SI != SE);
21774 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
21775 << DerivedLoc;
21776 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21777 << RE->getSourceRange();
21778 return true;
21782 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21783 // List items of map clauses in the same construct must not share
21784 // original storage.
21786 // An expression is a subset of the other.
21787 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
21788 if (CKind == OMPC_map) {
21789 if (CI != CE || SI != SE) {
21790 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
21791 // a pointer.
21792 auto Begin =
21793 CI != CE ? CurComponents.begin() : StackComponents.begin();
21794 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
21795 auto It = Begin;
21796 while (It != End && !It->getAssociatedDeclaration())
21797 std::advance(It, 1);
21798 assert(It != End &&
21799 "Expected at least one component with the declaration.");
21800 if (It != Begin && It->getAssociatedDeclaration()
21801 ->getType()
21802 .getCanonicalType()
21803 ->isAnyPointerType()) {
21804 IsEnclosedByDataEnvironmentExpr = false;
21805 EnclosingExpr = nullptr;
21806 return false;
21809 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21810 } else {
21811 assert(CKind == OMPC_to || CKind == OMPC_from);
21812 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21813 << ERange;
21815 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21816 << RE->getSourceRange();
21817 return true;
21820 // The current expression uses the same base as other expression in the
21821 // data environment but does not contain it completely.
21822 if (!CurrentRegionOnly && SI != SE)
21823 EnclosingExpr = RE;
21825 // The current expression is a subset of the expression in the data
21826 // environment.
21827 IsEnclosedByDataEnvironmentExpr |=
21828 (!CurrentRegionOnly && CI != CE && SI == SE);
21830 return false;
21833 if (CurrentRegionOnly)
21834 return FoundError;
21836 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21837 // If any part of the original storage of a list item has corresponding
21838 // storage in the device data environment, all of the original storage must
21839 // have corresponding storage in the device data environment.
21840 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
21841 // If a list item is an element of a structure, and a different element of
21842 // the structure has a corresponding list item in the device data environment
21843 // prior to a task encountering the construct associated with the map clause,
21844 // then the list item must also have a corresponding list item in the device
21845 // data environment prior to the task encountering the construct.
21847 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
21848 SemaRef.Diag(ELoc,
21849 diag::err_omp_original_storage_is_shared_and_does_not_contain)
21850 << ERange;
21851 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
21852 << EnclosingExpr->getSourceRange();
21853 return true;
21856 return FoundError;
21859 // Look up the user-defined mapper given the mapper name and mapped type, and
21860 // build a reference to it.
21861 static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
21862 CXXScopeSpec &MapperIdScopeSpec,
21863 const DeclarationNameInfo &MapperId,
21864 QualType Type,
21865 Expr *UnresolvedMapper) {
21866 if (MapperIdScopeSpec.isInvalid())
21867 return ExprError();
21868 // Get the actual type for the array type.
21869 if (Type->isArrayType()) {
21870 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
21871 Type = Type->getAsArrayTypeUnsafe()->getElementType().getCanonicalType();
21873 // Find all user-defined mappers with the given MapperId.
21874 SmallVector<UnresolvedSet<8>, 4> Lookups;
21875 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
21876 Lookup.suppressDiagnostics();
21877 if (S) {
21878 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec)) {
21879 NamedDecl *D = Lookup.getRepresentativeDecl();
21880 while (S && !S->isDeclScope(D))
21881 S = S->getParent();
21882 if (S)
21883 S = S->getParent();
21884 Lookups.emplace_back();
21885 Lookups.back().append(Lookup.begin(), Lookup.end());
21886 Lookup.clear();
21888 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
21889 // Extract the user-defined mappers with the given MapperId.
21890 Lookups.push_back(UnresolvedSet<8>());
21891 for (NamedDecl *D : ULE->decls()) {
21892 auto *DMD = cast<OMPDeclareMapperDecl>(D);
21893 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
21894 Lookups.back().addDecl(DMD);
21897 // Defer the lookup for dependent types. The results will be passed through
21898 // UnresolvedMapper on instantiation.
21899 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
21900 Type->isInstantiationDependentType() ||
21901 Type->containsUnexpandedParameterPack() ||
21902 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
21903 return !D->isInvalidDecl() &&
21904 (D->getType()->isDependentType() ||
21905 D->getType()->isInstantiationDependentType() ||
21906 D->getType()->containsUnexpandedParameterPack());
21907 })) {
21908 UnresolvedSet<8> URS;
21909 for (const UnresolvedSet<8> &Set : Lookups) {
21910 if (Set.empty())
21911 continue;
21912 URS.append(Set.begin(), Set.end());
21914 return UnresolvedLookupExpr::Create(
21915 SemaRef.Context, /*NamingClass=*/nullptr,
21916 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
21917 /*ADL=*/false, /*Overloaded=*/true, URS.begin(), URS.end());
21919 SourceLocation Loc = MapperId.getLoc();
21920 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21921 // The type must be of struct, union or class type in C and C++
21922 if (!Type->isStructureOrClassType() && !Type->isUnionType() &&
21923 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
21924 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
21925 return ExprError();
21927 // Perform argument dependent lookup.
21928 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
21929 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
21930 // Return the first user-defined mapper with the desired type.
21931 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21932 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
21933 if (!D->isInvalidDecl() &&
21934 SemaRef.Context.hasSameType(D->getType(), Type))
21935 return D;
21936 return nullptr;
21938 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
21939 // Find the first user-defined mapper with a type derived from the desired
21940 // type.
21941 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21942 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
21943 if (!D->isInvalidDecl() &&
21944 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
21945 !Type.isMoreQualifiedThan(D->getType()))
21946 return D;
21947 return nullptr;
21948 })) {
21949 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
21950 /*DetectVirtual=*/false);
21951 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
21952 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
21953 VD->getType().getUnqualifiedType()))) {
21954 if (SemaRef.CheckBaseClassAccess(
21955 Loc, VD->getType(), Type, Paths.front(),
21956 /*DiagID=*/0) != Sema::AR_inaccessible) {
21957 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
21962 // Report error if a mapper is specified, but cannot be found.
21963 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
21964 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
21965 << Type << MapperId.getName();
21966 return ExprError();
21968 return ExprEmpty();
21971 namespace {
21972 // Utility struct that gathers all the related lists associated with a mappable
21973 // expression.
21974 struct MappableVarListInfo {
21975 // The list of expressions.
21976 ArrayRef<Expr *> VarList;
21977 // The list of processed expressions.
21978 SmallVector<Expr *, 16> ProcessedVarList;
21979 // The mappble components for each expression.
21980 OMPClauseMappableExprCommon::MappableExprComponentLists VarComponents;
21981 // The base declaration of the variable.
21982 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
21983 // The reference to the user-defined mapper associated with every expression.
21984 SmallVector<Expr *, 16> UDMapperList;
21986 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
21987 // We have a list of components and base declarations for each entry in the
21988 // variable list.
21989 VarComponents.reserve(VarList.size());
21990 VarBaseDeclarations.reserve(VarList.size());
21993 } // namespace
21995 // Check the validity of the provided variable list for the provided clause kind
21996 // \a CKind. In the check process the valid expressions, mappable expression
21997 // components, variables, and user-defined mappers are extracted and used to
21998 // fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
21999 // UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
22000 // and \a MapperId are expected to be valid if the clause kind is 'map'.
22001 static void checkMappableExpressionList(
22002 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
22003 MappableVarListInfo &MVLI, SourceLocation StartLoc,
22004 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
22005 ArrayRef<Expr *> UnresolvedMappers,
22006 OpenMPMapClauseKind MapType = OMPC_MAP_unknown,
22007 ArrayRef<OpenMPMapModifierKind> Modifiers = std::nullopt,
22008 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
22009 // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
22010 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
22011 "Unexpected clause kind with mappable expressions!");
22013 // If the identifier of user-defined mapper is not specified, it is "default".
22014 // We do not change the actual name in this clause to distinguish whether a
22015 // mapper is specified explicitly, i.e., it is not explicitly specified when
22016 // MapperId.getName() is empty.
22017 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
22018 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
22019 MapperId.setName(DeclNames.getIdentifier(
22020 &SemaRef.getASTContext().Idents.get("default")));
22021 MapperId.setLoc(StartLoc);
22024 // Iterators to find the current unresolved mapper expression.
22025 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
22026 bool UpdateUMIt = false;
22027 Expr *UnresolvedMapper = nullptr;
22029 bool HasHoldModifier =
22030 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
22032 // Keep track of the mappable components and base declarations in this clause.
22033 // Each entry in the list is going to have a list of components associated. We
22034 // record each set of the components so that we can build the clause later on.
22035 // In the end we should have the same amount of declarations and component
22036 // lists.
22038 for (Expr *RE : MVLI.VarList) {
22039 assert(RE && "Null expr in omp to/from/map clause");
22040 SourceLocation ELoc = RE->getExprLoc();
22042 // Find the current unresolved mapper expression.
22043 if (UpdateUMIt && UMIt != UMEnd) {
22044 UMIt++;
22045 assert(
22046 UMIt != UMEnd &&
22047 "Expect the size of UnresolvedMappers to match with that of VarList");
22049 UpdateUMIt = true;
22050 if (UMIt != UMEnd)
22051 UnresolvedMapper = *UMIt;
22053 const Expr *VE = RE->IgnoreParenLValueCasts();
22055 if (VE->isValueDependent() || VE->isTypeDependent() ||
22056 VE->isInstantiationDependent() ||
22057 VE->containsUnexpandedParameterPack()) {
22058 // Try to find the associated user-defined mapper.
22059 ExprResult ER = buildUserDefinedMapperRef(
22060 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22061 VE->getType().getCanonicalType(), UnresolvedMapper);
22062 if (ER.isInvalid())
22063 continue;
22064 MVLI.UDMapperList.push_back(ER.get());
22065 // We can only analyze this information once the missing information is
22066 // resolved.
22067 MVLI.ProcessedVarList.push_back(RE);
22068 continue;
22071 Expr *SimpleExpr = RE->IgnoreParenCasts();
22073 if (!RE->isLValue()) {
22074 if (SemaRef.getLangOpts().OpenMP < 50) {
22075 SemaRef.Diag(
22076 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
22077 << RE->getSourceRange();
22078 } else {
22079 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
22080 << getOpenMPClauseName(CKind) << RE->getSourceRange();
22082 continue;
22085 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
22086 ValueDecl *CurDeclaration = nullptr;
22088 // Obtain the array or member expression bases if required. Also, fill the
22089 // components array with all the components identified in the process.
22090 const Expr *BE =
22091 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
22092 DSAS->getCurrentDirective(), NoDiagnose);
22093 if (!BE)
22094 continue;
22096 assert(!CurComponents.empty() &&
22097 "Invalid mappable expression information.");
22099 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
22100 // Add store "this" pointer to class in DSAStackTy for future checking
22101 DSAS->addMappedClassesQualTypes(TE->getType());
22102 // Try to find the associated user-defined mapper.
22103 ExprResult ER = buildUserDefinedMapperRef(
22104 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22105 VE->getType().getCanonicalType(), UnresolvedMapper);
22106 if (ER.isInvalid())
22107 continue;
22108 MVLI.UDMapperList.push_back(ER.get());
22109 // Skip restriction checking for variable or field declarations
22110 MVLI.ProcessedVarList.push_back(RE);
22111 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22112 MVLI.VarComponents.back().append(CurComponents.begin(),
22113 CurComponents.end());
22114 MVLI.VarBaseDeclarations.push_back(nullptr);
22115 continue;
22118 // For the following checks, we rely on the base declaration which is
22119 // expected to be associated with the last component. The declaration is
22120 // expected to be a variable or a field (if 'this' is being mapped).
22121 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
22122 assert(CurDeclaration && "Null decl on map clause.");
22123 assert(
22124 CurDeclaration->isCanonicalDecl() &&
22125 "Expecting components to have associated only canonical declarations.");
22127 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
22128 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
22130 assert((VD || FD) && "Only variables or fields are expected here!");
22131 (void)FD;
22133 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
22134 // threadprivate variables cannot appear in a map clause.
22135 // OpenMP 4.5 [2.10.5, target update Construct]
22136 // threadprivate variables cannot appear in a from clause.
22137 if (VD && DSAS->isThreadPrivate(VD)) {
22138 if (NoDiagnose)
22139 continue;
22140 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
22141 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
22142 << getOpenMPClauseName(CKind);
22143 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
22144 continue;
22147 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
22148 // A list item cannot appear in both a map clause and a data-sharing
22149 // attribute clause on the same construct.
22151 // Check conflicts with other map clause expressions. We check the conflicts
22152 // with the current construct separately from the enclosing data
22153 // environment, because the restrictions are different. We only have to
22154 // check conflicts across regions for the map clauses.
22155 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
22156 /*CurrentRegionOnly=*/true, CurComponents, CKind))
22157 break;
22158 if (CKind == OMPC_map &&
22159 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
22160 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
22161 /*CurrentRegionOnly=*/false, CurComponents, CKind))
22162 break;
22164 // OpenMP 4.5 [2.10.5, target update Construct]
22165 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22166 // If the type of a list item is a reference to a type T then the type will
22167 // be considered to be T for all purposes of this clause.
22168 auto I = llvm::find_if(
22169 CurComponents,
22170 [](const OMPClauseMappableExprCommon::MappableComponent &MC) {
22171 return MC.getAssociatedDeclaration();
22173 assert(I != CurComponents.end() && "Null decl on map clause.");
22174 (void)I;
22175 QualType Type;
22176 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
22177 auto *OASE = dyn_cast<OMPArraySectionExpr>(VE->IgnoreParens());
22178 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
22179 if (ASE) {
22180 Type = ASE->getType().getNonReferenceType();
22181 } else if (OASE) {
22182 QualType BaseType =
22183 OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
22184 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
22185 Type = ATy->getElementType();
22186 else
22187 Type = BaseType->getPointeeType();
22188 Type = Type.getNonReferenceType();
22189 } else if (OAShE) {
22190 Type = OAShE->getBase()->getType()->getPointeeType();
22191 } else {
22192 Type = VE->getType();
22195 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
22196 // A list item in a to or from clause must have a mappable type.
22197 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
22198 // A list item must have a mappable type.
22199 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
22200 DSAS, Type, /*FullCheck=*/true))
22201 continue;
22203 if (CKind == OMPC_map) {
22204 // target enter data
22205 // OpenMP [2.10.2, Restrictions, p. 99]
22206 // A map-type must be specified in all map clauses and must be either
22207 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
22208 // no map type is present.
22209 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
22210 if (DKind == OMPD_target_enter_data &&
22211 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
22212 SemaRef.getLangOpts().OpenMP >= 52)) {
22213 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22214 << (IsMapTypeImplicit ? 1 : 0)
22215 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22216 << getOpenMPDirectiveName(DKind);
22217 continue;
22220 // target exit_data
22221 // OpenMP [2.10.3, Restrictions, p. 102]
22222 // A map-type must be specified in all map clauses and must be either
22223 // from, release, or delete. Starting with OpenMP 5.2 the default map
22224 // type is `from` if no map type is present.
22225 if (DKind == OMPD_target_exit_data &&
22226 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
22227 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
22228 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22229 << (IsMapTypeImplicit ? 1 : 0)
22230 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22231 << getOpenMPDirectiveName(DKind);
22232 continue;
22235 // The 'ompx_hold' modifier is specifically intended to be used on a
22236 // 'target' or 'target data' directive to prevent data from being unmapped
22237 // during the associated statement. It is not permitted on a 'target
22238 // enter data' or 'target exit data' directive, which have no associated
22239 // statement.
22240 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
22241 HasHoldModifier) {
22242 SemaRef.Diag(StartLoc,
22243 diag::err_omp_invalid_map_type_modifier_for_directive)
22244 << getOpenMPSimpleClauseTypeName(OMPC_map,
22245 OMPC_MAP_MODIFIER_ompx_hold)
22246 << getOpenMPDirectiveName(DKind);
22247 continue;
22250 // target, target data
22251 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
22252 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
22253 // A map-type in a map clause must be to, from, tofrom or alloc
22254 if ((DKind == OMPD_target_data ||
22255 isOpenMPTargetExecutionDirective(DKind)) &&
22256 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
22257 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
22258 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22259 << (IsMapTypeImplicit ? 1 : 0)
22260 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22261 << getOpenMPDirectiveName(DKind);
22262 continue;
22265 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
22266 // A list item cannot appear in both a map clause and a data-sharing
22267 // attribute clause on the same construct
22269 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
22270 // A list item cannot appear in both a map clause and a data-sharing
22271 // attribute clause on the same construct unless the construct is a
22272 // combined construct.
22273 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
22274 isOpenMPTargetExecutionDirective(DKind)) ||
22275 DKind == OMPD_target)) {
22276 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
22277 if (isOpenMPPrivate(DVar.CKind)) {
22278 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
22279 << getOpenMPClauseName(DVar.CKind)
22280 << getOpenMPClauseName(OMPC_map)
22281 << getOpenMPDirectiveName(DSAS->getCurrentDirective());
22282 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
22283 continue;
22288 // Try to find the associated user-defined mapper.
22289 ExprResult ER = buildUserDefinedMapperRef(
22290 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22291 Type.getCanonicalType(), UnresolvedMapper);
22292 if (ER.isInvalid())
22293 continue;
22294 MVLI.UDMapperList.push_back(ER.get());
22296 // Save the current expression.
22297 MVLI.ProcessedVarList.push_back(RE);
22299 // Store the components in the stack so that they can be used to check
22300 // against other clauses later on.
22301 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
22302 /*WhereFoundClauseKind=*/OMPC_map);
22304 // Save the components and declaration to create the clause. For purposes of
22305 // the clause creation, any component list that has base 'this' uses
22306 // null as base declaration.
22307 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22308 MVLI.VarComponents.back().append(CurComponents.begin(),
22309 CurComponents.end());
22310 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
22311 : CurDeclaration);
22315 OMPClause *Sema::ActOnOpenMPMapClause(
22316 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
22317 ArrayRef<SourceLocation> MapTypeModifiersLoc,
22318 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22319 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
22320 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22321 const OMPVarListLocTy &Locs, bool NoDiagnose,
22322 ArrayRef<Expr *> UnresolvedMappers) {
22323 OpenMPMapModifierKind Modifiers[] = {
22324 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
22325 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
22326 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown};
22327 SourceLocation ModifiersLoc[NumberOfOMPMapClauseModifiers];
22329 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
22330 BuiltinType::OMPIterator))
22331 Diag(IteratorModifier->getExprLoc(),
22332 diag::err_omp_map_modifier_not_iterator);
22334 // Process map-type-modifiers, flag errors for duplicate modifiers.
22335 unsigned Count = 0;
22336 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
22337 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
22338 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
22339 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
22340 continue;
22342 assert(Count < NumberOfOMPMapClauseModifiers &&
22343 "Modifiers exceed the allowed number of map type modifiers");
22344 Modifiers[Count] = MapTypeModifiers[I];
22345 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
22346 ++Count;
22349 MappableVarListInfo MVLI(VarList);
22350 checkMappableExpressionList(*this, DSAStack, OMPC_map, MVLI, Locs.StartLoc,
22351 MapperIdScopeSpec, MapperId, UnresolvedMappers,
22352 MapType, Modifiers, IsMapTypeImplicit,
22353 NoDiagnose);
22355 // We need to produce a map clause even if we don't have variables so that
22356 // other diagnostics related with non-existing map clauses are accurate.
22357 return OMPMapClause::Create(
22358 Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22359 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
22360 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(Context), MapperId,
22361 MapType, IsMapTypeImplicit, MapLoc);
22364 QualType Sema::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc,
22365 TypeResult ParsedType) {
22366 assert(ParsedType.isUsable());
22368 QualType ReductionType = GetTypeFromParser(ParsedType.get());
22369 if (ReductionType.isNull())
22370 return QualType();
22372 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
22373 // A type name in a declare reduction directive cannot be a function type, an
22374 // array type, a reference type, or a type qualified with const, volatile or
22375 // restrict.
22376 if (ReductionType.hasQualifiers()) {
22377 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
22378 return QualType();
22381 if (ReductionType->isFunctionType()) {
22382 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
22383 return QualType();
22385 if (ReductionType->isReferenceType()) {
22386 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
22387 return QualType();
22389 if (ReductionType->isArrayType()) {
22390 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
22391 return QualType();
22393 return ReductionType;
22396 Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareReductionDirectiveStart(
22397 Scope *S, DeclContext *DC, DeclarationName Name,
22398 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
22399 AccessSpecifier AS, Decl *PrevDeclInScope) {
22400 SmallVector<Decl *, 8> Decls;
22401 Decls.reserve(ReductionTypes.size());
22403 LookupResult Lookup(*this, Name, SourceLocation(), LookupOMPReductionName,
22404 forRedeclarationInCurContext());
22405 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
22406 // A reduction-identifier may not be re-declared in the current scope for the
22407 // same type or for a type that is compatible according to the base language
22408 // rules.
22409 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22410 OMPDeclareReductionDecl *PrevDRD = nullptr;
22411 bool InCompoundScope = true;
22412 if (S != nullptr) {
22413 // Find previous declaration with the same name not referenced in other
22414 // declarations.
22415 FunctionScopeInfo *ParentFn = getEnclosingFunction();
22416 InCompoundScope =
22417 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22418 LookupName(Lookup, S);
22419 FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
22420 /*AllowInlineNamespace=*/false);
22421 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
22422 LookupResult::Filter Filter = Lookup.makeFilter();
22423 while (Filter.hasNext()) {
22424 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
22425 if (InCompoundScope) {
22426 auto I = UsedAsPrevious.find(PrevDecl);
22427 if (I == UsedAsPrevious.end())
22428 UsedAsPrevious[PrevDecl] = false;
22429 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
22430 UsedAsPrevious[D] = true;
22432 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22433 PrevDecl->getLocation();
22435 Filter.done();
22436 if (InCompoundScope) {
22437 for (const auto &PrevData : UsedAsPrevious) {
22438 if (!PrevData.second) {
22439 PrevDRD = PrevData.first;
22440 break;
22444 } else if (PrevDeclInScope != nullptr) {
22445 auto *PrevDRDInScope = PrevDRD =
22446 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
22447 do {
22448 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
22449 PrevDRDInScope->getLocation();
22450 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
22451 } while (PrevDRDInScope != nullptr);
22453 for (const auto &TyData : ReductionTypes) {
22454 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
22455 bool Invalid = false;
22456 if (I != PreviousRedeclTypes.end()) {
22457 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
22458 << TyData.first;
22459 Diag(I->second, diag::note_previous_definition);
22460 Invalid = true;
22462 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
22463 auto *DRD = OMPDeclareReductionDecl::Create(Context, DC, TyData.second,
22464 Name, TyData.first, PrevDRD);
22465 DC->addDecl(DRD);
22466 DRD->setAccess(AS);
22467 Decls.push_back(DRD);
22468 if (Invalid)
22469 DRD->setInvalidDecl();
22470 else
22471 PrevDRD = DRD;
22474 return DeclGroupPtrTy::make(
22475 DeclGroupRef::Create(Context, Decls.begin(), Decls.size()));
22478 void Sema::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) {
22479 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22481 // Enter new function scope.
22482 PushFunctionScope();
22483 setFunctionHasBranchProtectedScope();
22484 getCurFunction()->setHasOMPDeclareReductionCombiner();
22486 if (S != nullptr)
22487 PushDeclContext(S, DRD);
22488 else
22489 CurContext = DRD;
22491 PushExpressionEvaluationContext(
22492 ExpressionEvaluationContext::PotentiallyEvaluated);
22494 QualType ReductionType = DRD->getType();
22495 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
22496 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
22497 // uses semantics of argument handles by value, but it should be passed by
22498 // reference. C lang does not support references, so pass all parameters as
22499 // pointers.
22500 // Create 'T omp_in;' variable.
22501 VarDecl *OmpInParm =
22502 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_in");
22503 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
22504 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
22505 // uses semantics of argument handles by value, but it should be passed by
22506 // reference. C lang does not support references, so pass all parameters as
22507 // pointers.
22508 // Create 'T omp_out;' variable.
22509 VarDecl *OmpOutParm =
22510 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_out");
22511 if (S != nullptr) {
22512 PushOnScopeChains(OmpInParm, S);
22513 PushOnScopeChains(OmpOutParm, S);
22514 } else {
22515 DRD->addDecl(OmpInParm);
22516 DRD->addDecl(OmpOutParm);
22518 Expr *InE =
22519 ::buildDeclRefExpr(*this, OmpInParm, ReductionType, D->getLocation());
22520 Expr *OutE =
22521 ::buildDeclRefExpr(*this, OmpOutParm, ReductionType, D->getLocation());
22522 DRD->setCombinerData(InE, OutE);
22525 void Sema::ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner) {
22526 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22527 DiscardCleanupsInEvaluationContext();
22528 PopExpressionEvaluationContext();
22530 PopDeclContext();
22531 PopFunctionScopeInfo();
22533 if (Combiner != nullptr)
22534 DRD->setCombiner(Combiner);
22535 else
22536 DRD->setInvalidDecl();
22539 VarDecl *Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D) {
22540 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22542 // Enter new function scope.
22543 PushFunctionScope();
22544 setFunctionHasBranchProtectedScope();
22546 if (S != nullptr)
22547 PushDeclContext(S, DRD);
22548 else
22549 CurContext = DRD;
22551 PushExpressionEvaluationContext(
22552 ExpressionEvaluationContext::PotentiallyEvaluated);
22554 QualType ReductionType = DRD->getType();
22555 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
22556 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
22557 // uses semantics of argument handles by value, but it should be passed by
22558 // reference. C lang does not support references, so pass all parameters as
22559 // pointers.
22560 // Create 'T omp_priv;' variable.
22561 VarDecl *OmpPrivParm =
22562 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_priv");
22563 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
22564 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
22565 // uses semantics of argument handles by value, but it should be passed by
22566 // reference. C lang does not support references, so pass all parameters as
22567 // pointers.
22568 // Create 'T omp_orig;' variable.
22569 VarDecl *OmpOrigParm =
22570 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_orig");
22571 if (S != nullptr) {
22572 PushOnScopeChains(OmpPrivParm, S);
22573 PushOnScopeChains(OmpOrigParm, S);
22574 } else {
22575 DRD->addDecl(OmpPrivParm);
22576 DRD->addDecl(OmpOrigParm);
22578 Expr *OrigE =
22579 ::buildDeclRefExpr(*this, OmpOrigParm, ReductionType, D->getLocation());
22580 Expr *PrivE =
22581 ::buildDeclRefExpr(*this, OmpPrivParm, ReductionType, D->getLocation());
22582 DRD->setInitializerData(OrigE, PrivE);
22583 return OmpPrivParm;
22586 void Sema::ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer,
22587 VarDecl *OmpPrivParm) {
22588 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22589 DiscardCleanupsInEvaluationContext();
22590 PopExpressionEvaluationContext();
22592 PopDeclContext();
22593 PopFunctionScopeInfo();
22595 if (Initializer != nullptr) {
22596 DRD->setInitializer(Initializer, OMPDeclareReductionDecl::CallInit);
22597 } else if (OmpPrivParm->hasInit()) {
22598 DRD->setInitializer(OmpPrivParm->getInit(),
22599 OmpPrivParm->isDirectInit()
22600 ? OMPDeclareReductionDecl::DirectInit
22601 : OMPDeclareReductionDecl::CopyInit);
22602 } else {
22603 DRD->setInvalidDecl();
22607 Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareReductionDirectiveEnd(
22608 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
22609 for (Decl *D : DeclReductions.get()) {
22610 if (IsValid) {
22611 if (S)
22612 PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
22613 /*AddToContext=*/false);
22614 } else {
22615 D->setInvalidDecl();
22618 return DeclReductions;
22621 TypeResult Sema::ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D) {
22622 TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
22623 QualType T = TInfo->getType();
22624 if (D.isInvalidType())
22625 return true;
22627 if (getLangOpts().CPlusPlus) {
22628 // Check that there are no default arguments (C++ only).
22629 CheckExtraCXXDefaultArguments(D);
22632 return CreateParsedType(T, TInfo);
22635 QualType Sema::ActOnOpenMPDeclareMapperType(SourceLocation TyLoc,
22636 TypeResult ParsedType) {
22637 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
22639 QualType MapperType = GetTypeFromParser(ParsedType.get());
22640 assert(!MapperType.isNull() && "Expect valid mapper type");
22642 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22643 // The type must be of struct, union or class type in C and C++
22644 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
22645 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
22646 return QualType();
22648 return MapperType;
22651 Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareMapperDirective(
22652 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
22653 SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS,
22654 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
22655 LookupResult Lookup(*this, Name, SourceLocation(), LookupOMPMapperName,
22656 forRedeclarationInCurContext());
22657 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22658 // A mapper-identifier may not be redeclared in the current scope for the
22659 // same type or for a type that is compatible according to the base language
22660 // rules.
22661 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22662 OMPDeclareMapperDecl *PrevDMD = nullptr;
22663 bool InCompoundScope = true;
22664 if (S != nullptr) {
22665 // Find previous declaration with the same name not referenced in other
22666 // declarations.
22667 FunctionScopeInfo *ParentFn = getEnclosingFunction();
22668 InCompoundScope =
22669 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22670 LookupName(Lookup, S);
22671 FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
22672 /*AllowInlineNamespace=*/false);
22673 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
22674 LookupResult::Filter Filter = Lookup.makeFilter();
22675 while (Filter.hasNext()) {
22676 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
22677 if (InCompoundScope) {
22678 auto I = UsedAsPrevious.find(PrevDecl);
22679 if (I == UsedAsPrevious.end())
22680 UsedAsPrevious[PrevDecl] = false;
22681 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
22682 UsedAsPrevious[D] = true;
22684 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22685 PrevDecl->getLocation();
22687 Filter.done();
22688 if (InCompoundScope) {
22689 for (const auto &PrevData : UsedAsPrevious) {
22690 if (!PrevData.second) {
22691 PrevDMD = PrevData.first;
22692 break;
22696 } else if (PrevDeclInScope) {
22697 auto *PrevDMDInScope = PrevDMD =
22698 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
22699 do {
22700 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
22701 PrevDMDInScope->getLocation();
22702 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
22703 } while (PrevDMDInScope != nullptr);
22705 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
22706 bool Invalid = false;
22707 if (I != PreviousRedeclTypes.end()) {
22708 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
22709 << MapperType << Name;
22710 Diag(I->second, diag::note_previous_definition);
22711 Invalid = true;
22713 // Build expressions for implicit maps of data members with 'default'
22714 // mappers.
22715 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses.begin(),
22716 Clauses.end());
22717 if (LangOpts.OpenMP >= 50)
22718 processImplicitMapsWithDefaultMappers(*this, DSAStack, ClausesWithImplicit);
22719 auto *DMD =
22720 OMPDeclareMapperDecl::Create(Context, DC, StartLoc, Name, MapperType, VN,
22721 ClausesWithImplicit, PrevDMD);
22722 if (S)
22723 PushOnScopeChains(DMD, S);
22724 else
22725 DC->addDecl(DMD);
22726 DMD->setAccess(AS);
22727 if (Invalid)
22728 DMD->setInvalidDecl();
22730 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
22731 VD->setDeclContext(DMD);
22732 VD->setLexicalDeclContext(DMD);
22733 DMD->addDecl(VD);
22734 DMD->setMapperVarRef(MapperVarRef);
22736 return DeclGroupPtrTy::make(DeclGroupRef(DMD));
22739 ExprResult
22740 Sema::ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType,
22741 SourceLocation StartLoc,
22742 DeclarationName VN) {
22743 TypeSourceInfo *TInfo =
22744 Context.getTrivialTypeSourceInfo(MapperType, StartLoc);
22745 auto *VD = VarDecl::Create(Context, Context.getTranslationUnitDecl(),
22746 StartLoc, StartLoc, VN.getAsIdentifierInfo(),
22747 MapperType, TInfo, SC_None);
22748 if (S)
22749 PushOnScopeChains(VD, S, /*AddToContext=*/false);
22750 Expr *E = buildDeclRefExpr(*this, VD, MapperType, StartLoc);
22751 DSAStack->addDeclareMapperVarRef(E);
22752 return E;
22755 void Sema::ActOnOpenMPIteratorVarDecl(VarDecl *VD) {
22756 if (DSAStack->getDeclareMapperVarRef())
22757 DSAStack->addIteratorVarDecl(VD);
22760 bool Sema::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const {
22761 assert(LangOpts.OpenMP && "Expected OpenMP mode.");
22762 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
22763 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
22764 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
22765 return true;
22766 if (VD->isUsableInConstantExpressions(Context))
22767 return true;
22768 if (LangOpts.OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
22769 return true;
22770 return false;
22772 return true;
22775 const ValueDecl *Sema::getOpenMPDeclareMapperVarName() const {
22776 assert(LangOpts.OpenMP && "Expected OpenMP mode.");
22777 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
22780 OMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams,
22781 SourceLocation StartLoc,
22782 SourceLocation LParenLoc,
22783 SourceLocation EndLoc) {
22784 Expr *ValExpr = NumTeams;
22785 Stmt *HelperValStmt = nullptr;
22787 // OpenMP [teams Constrcut, Restrictions]
22788 // The num_teams expression must evaluate to a positive integer value.
22789 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_num_teams,
22790 /*StrictlyPositive=*/true))
22791 return nullptr;
22793 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22794 OpenMPDirectiveKind CaptureRegion =
22795 getOpenMPCaptureRegionForClause(DKind, OMPC_num_teams, LangOpts.OpenMP);
22796 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
22797 ValExpr = MakeFullExpr(ValExpr).get();
22798 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22799 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
22800 HelperValStmt = buildPreInits(Context, Captures);
22803 return new (Context) OMPNumTeamsClause(ValExpr, HelperValStmt, CaptureRegion,
22804 StartLoc, LParenLoc, EndLoc);
22807 OMPClause *Sema::ActOnOpenMPThreadLimitClause(Expr *ThreadLimit,
22808 SourceLocation StartLoc,
22809 SourceLocation LParenLoc,
22810 SourceLocation EndLoc) {
22811 Expr *ValExpr = ThreadLimit;
22812 Stmt *HelperValStmt = nullptr;
22814 // OpenMP [teams Constrcut, Restrictions]
22815 // The thread_limit expression must evaluate to a positive integer value.
22816 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_thread_limit,
22817 /*StrictlyPositive=*/true))
22818 return nullptr;
22820 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22821 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
22822 DKind, OMPC_thread_limit, LangOpts.OpenMP);
22823 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
22824 ValExpr = MakeFullExpr(ValExpr).get();
22825 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22826 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
22827 HelperValStmt = buildPreInits(Context, Captures);
22830 return new (Context) OMPThreadLimitClause(
22831 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
22834 OMPClause *Sema::ActOnOpenMPPriorityClause(Expr *Priority,
22835 SourceLocation StartLoc,
22836 SourceLocation LParenLoc,
22837 SourceLocation EndLoc) {
22838 Expr *ValExpr = Priority;
22839 Stmt *HelperValStmt = nullptr;
22840 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22842 // OpenMP [2.9.1, task Constrcut]
22843 // The priority-value is a non-negative numerical scalar expression.
22844 if (!isNonNegativeIntegerValue(
22845 ValExpr, *this, OMPC_priority,
22846 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
22847 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22848 return nullptr;
22850 return new (Context) OMPPriorityClause(ValExpr, HelperValStmt, CaptureRegion,
22851 StartLoc, LParenLoc, EndLoc);
22854 OMPClause *Sema::ActOnOpenMPGrainsizeClause(
22855 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
22856 SourceLocation StartLoc, SourceLocation LParenLoc,
22857 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22858 assert((ModifierLoc.isInvalid() || LangOpts.OpenMP >= 51) &&
22859 "Unexpected grainsize modifier in OpenMP < 51.");
22861 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
22862 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
22863 OMPC_GRAINSIZE_unknown);
22864 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22865 << Values << getOpenMPClauseName(OMPC_grainsize);
22866 return nullptr;
22869 Expr *ValExpr = Grainsize;
22870 Stmt *HelperValStmt = nullptr;
22871 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22873 // OpenMP [2.9.2, taskloop Constrcut]
22874 // The parameter of the grainsize clause must be a positive integer
22875 // expression.
22876 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_grainsize,
22877 /*StrictlyPositive=*/true,
22878 /*BuildCapture=*/true,
22879 DSAStack->getCurrentDirective(),
22880 &CaptureRegion, &HelperValStmt))
22881 return nullptr;
22883 return new (Context)
22884 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22885 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22888 OMPClause *Sema::ActOnOpenMPNumTasksClause(
22889 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
22890 SourceLocation StartLoc, SourceLocation LParenLoc,
22891 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22892 assert((ModifierLoc.isInvalid() || LangOpts.OpenMP >= 51) &&
22893 "Unexpected num_tasks modifier in OpenMP < 51.");
22895 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
22896 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
22897 OMPC_NUMTASKS_unknown);
22898 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22899 << Values << getOpenMPClauseName(OMPC_num_tasks);
22900 return nullptr;
22903 Expr *ValExpr = NumTasks;
22904 Stmt *HelperValStmt = nullptr;
22905 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22907 // OpenMP [2.9.2, taskloop Constrcut]
22908 // The parameter of the num_tasks clause must be a positive integer
22909 // expression.
22910 if (!isNonNegativeIntegerValue(
22911 ValExpr, *this, OMPC_num_tasks,
22912 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
22913 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22914 return nullptr;
22916 return new (Context)
22917 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22918 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22921 OMPClause *Sema::ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc,
22922 SourceLocation LParenLoc,
22923 SourceLocation EndLoc) {
22924 // OpenMP [2.13.2, critical construct, Description]
22925 // ... where hint-expression is an integer constant expression that evaluates
22926 // to a valid lock hint.
22927 ExprResult HintExpr =
22928 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
22929 if (HintExpr.isInvalid())
22930 return nullptr;
22931 return new (Context)
22932 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
22935 /// Tries to find omp_event_handle_t type.
22936 static bool findOMPEventHandleT(Sema &S, SourceLocation Loc,
22937 DSAStackTy *Stack) {
22938 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
22939 if (!OMPEventHandleT.isNull())
22940 return true;
22941 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
22942 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
22943 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
22944 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
22945 return false;
22947 Stack->setOMPEventHandleT(PT.get());
22948 return true;
22951 OMPClause *Sema::ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc,
22952 SourceLocation LParenLoc,
22953 SourceLocation EndLoc) {
22954 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
22955 !Evt->isInstantiationDependent() &&
22956 !Evt->containsUnexpandedParameterPack()) {
22957 if (!findOMPEventHandleT(*this, Evt->getExprLoc(), DSAStack))
22958 return nullptr;
22959 // OpenMP 5.0, 2.10.1 task Construct.
22960 // event-handle is a variable of the omp_event_handle_t type.
22961 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
22962 if (!Ref) {
22963 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22964 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22965 return nullptr;
22967 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
22968 if (!VD) {
22969 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22970 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22971 return nullptr;
22973 if (!Context.hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
22974 VD->getType()) ||
22975 VD->getType().isConstant(Context)) {
22976 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22977 << "omp_event_handle_t" << 1 << VD->getType()
22978 << Evt->getSourceRange();
22979 return nullptr;
22981 // OpenMP 5.0, 2.10.1 task Construct
22982 // [detach clause]... The event-handle will be considered as if it was
22983 // specified on a firstprivate clause.
22984 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
22985 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
22986 DVar.RefExpr) {
22987 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
22988 << getOpenMPClauseName(DVar.CKind)
22989 << getOpenMPClauseName(OMPC_firstprivate);
22990 reportOriginalDsa(*this, DSAStack, VD, DVar);
22991 return nullptr;
22995 return new (Context) OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
22998 OMPClause *Sema::ActOnOpenMPDistScheduleClause(
22999 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
23000 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
23001 SourceLocation EndLoc) {
23002 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
23003 std::string Values;
23004 Values += "'";
23005 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
23006 Values += "'";
23007 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23008 << Values << getOpenMPClauseName(OMPC_dist_schedule);
23009 return nullptr;
23011 Expr *ValExpr = ChunkSize;
23012 Stmt *HelperValStmt = nullptr;
23013 if (ChunkSize) {
23014 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
23015 !ChunkSize->isInstantiationDependent() &&
23016 !ChunkSize->containsUnexpandedParameterPack()) {
23017 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
23018 ExprResult Val =
23019 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
23020 if (Val.isInvalid())
23021 return nullptr;
23023 ValExpr = Val.get();
23025 // OpenMP [2.7.1, Restrictions]
23026 // chunk_size must be a loop invariant integer expression with a positive
23027 // value.
23028 if (std::optional<llvm::APSInt> Result =
23029 ValExpr->getIntegerConstantExpr(Context)) {
23030 if (Result->isSigned() && !Result->isStrictlyPositive()) {
23031 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
23032 << "dist_schedule" << ChunkSize->getSourceRange();
23033 return nullptr;
23035 } else if (getOpenMPCaptureRegionForClause(
23036 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
23037 LangOpts.OpenMP) != OMPD_unknown &&
23038 !CurContext->isDependentContext()) {
23039 ValExpr = MakeFullExpr(ValExpr).get();
23040 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23041 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
23042 HelperValStmt = buildPreInits(Context, Captures);
23047 return new (Context)
23048 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
23049 Kind, ValExpr, HelperValStmt);
23052 OMPClause *Sema::ActOnOpenMPDefaultmapClause(
23053 OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind,
23054 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
23055 SourceLocation KindLoc, SourceLocation EndLoc) {
23056 if (getLangOpts().OpenMP < 50) {
23057 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
23058 Kind != OMPC_DEFAULTMAP_scalar) {
23059 std::string Value;
23060 SourceLocation Loc;
23061 Value += "'";
23062 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
23063 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
23064 OMPC_DEFAULTMAP_MODIFIER_tofrom);
23065 Loc = MLoc;
23066 } else {
23067 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
23068 OMPC_DEFAULTMAP_scalar);
23069 Loc = KindLoc;
23071 Value += "'";
23072 Diag(Loc, diag::err_omp_unexpected_clause_value)
23073 << Value << getOpenMPClauseName(OMPC_defaultmap);
23074 return nullptr;
23076 } else {
23077 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
23078 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
23079 (LangOpts.OpenMP >= 50 && KindLoc.isInvalid());
23080 if (!isDefaultmapKind || !isDefaultmapModifier) {
23081 StringRef KindValue = "'scalar', 'aggregate', 'pointer'";
23082 if (LangOpts.OpenMP == 50) {
23083 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
23084 "'firstprivate', 'none', 'default'";
23085 if (!isDefaultmapKind && isDefaultmapModifier) {
23086 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23087 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23088 } else if (isDefaultmapKind && !isDefaultmapModifier) {
23089 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23090 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23091 } else {
23092 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23093 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23094 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23095 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23097 } else {
23098 StringRef ModifierValue =
23099 "'alloc', 'from', 'to', 'tofrom', "
23100 "'firstprivate', 'none', 'default', 'present'";
23101 if (!isDefaultmapKind && isDefaultmapModifier) {
23102 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23103 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23104 } else if (isDefaultmapKind && !isDefaultmapModifier) {
23105 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23106 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23107 } else {
23108 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23109 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23110 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23111 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23114 return nullptr;
23117 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
23118 // At most one defaultmap clause for each category can appear on the
23119 // directive.
23120 if (DSAStack->checkDefaultmapCategory(Kind)) {
23121 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
23122 return nullptr;
23125 if (Kind == OMPC_DEFAULTMAP_unknown) {
23126 // Variable category is not specified - mark all categories.
23127 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
23128 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
23129 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
23130 } else {
23131 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
23134 return new (Context)
23135 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
23138 bool Sema::ActOnStartOpenMPDeclareTargetContext(
23139 DeclareTargetContextInfo &DTCI) {
23140 DeclContext *CurLexicalContext = getCurLexicalContext();
23141 if (!CurLexicalContext->isFileContext() &&
23142 !CurLexicalContext->isExternCContext() &&
23143 !CurLexicalContext->isExternCXXContext() &&
23144 !isa<CXXRecordDecl>(CurLexicalContext) &&
23145 !isa<ClassTemplateDecl>(CurLexicalContext) &&
23146 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
23147 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
23148 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
23149 return false;
23152 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
23153 if (getLangOpts().HIP)
23154 Diag(DTCI.Loc, diag::warn_hip_omp_target_directives);
23156 DeclareTargetNesting.push_back(DTCI);
23157 return true;
23160 const Sema::DeclareTargetContextInfo
23161 Sema::ActOnOpenMPEndDeclareTargetDirective() {
23162 assert(!DeclareTargetNesting.empty() &&
23163 "check isInOpenMPDeclareTargetContext() first!");
23164 return DeclareTargetNesting.pop_back_val();
23167 void Sema::ActOnFinishedOpenMPDeclareTargetContext(
23168 DeclareTargetContextInfo &DTCI) {
23169 for (auto &It : DTCI.ExplicitlyMapped)
23170 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
23173 void Sema::DiagnoseUnterminatedOpenMPDeclareTarget() {
23174 if (DeclareTargetNesting.empty())
23175 return;
23176 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
23177 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
23178 << getOpenMPDirectiveName(DTCI.Kind);
23181 NamedDecl *Sema::lookupOpenMPDeclareTargetName(Scope *CurScope,
23182 CXXScopeSpec &ScopeSpec,
23183 const DeclarationNameInfo &Id) {
23184 LookupResult Lookup(*this, Id, LookupOrdinaryName);
23185 LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
23187 if (Lookup.isAmbiguous())
23188 return nullptr;
23189 Lookup.suppressDiagnostics();
23191 if (!Lookup.isSingleResult()) {
23192 VarOrFuncDeclFilterCCC CCC(*this);
23193 if (TypoCorrection Corrected =
23194 CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr, CCC,
23195 CTK_ErrorRecovery)) {
23196 diagnoseTypo(Corrected, PDiag(diag::err_undeclared_var_use_suggest)
23197 << Id.getName());
23198 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
23199 return nullptr;
23202 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
23203 return nullptr;
23206 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
23207 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
23208 !isa<FunctionTemplateDecl>(ND)) {
23209 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
23210 return nullptr;
23212 return ND;
23215 void Sema::ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc,
23216 OMPDeclareTargetDeclAttr::MapTypeTy MT,
23217 DeclareTargetContextInfo &DTCI) {
23218 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
23219 isa<FunctionTemplateDecl>(ND)) &&
23220 "Expected variable, function or function template.");
23222 // Diagnose marking after use as it may lead to incorrect diagnosis and
23223 // codegen.
23224 if (LangOpts.OpenMP >= 50 &&
23225 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
23226 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
23228 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
23229 if (getLangOpts().HIP)
23230 Diag(Loc, diag::warn_hip_omp_target_directives);
23232 // Explicit declare target lists have precedence.
23233 const unsigned Level = -1;
23235 auto *VD = cast<ValueDecl>(ND);
23236 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23237 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23238 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
23239 (*ActiveAttr)->getLevel() == Level) {
23240 Diag(Loc, diag::err_omp_device_type_mismatch)
23241 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
23242 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
23243 (*ActiveAttr)->getDevType());
23244 return;
23246 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
23247 (*ActiveAttr)->getLevel() == Level) {
23248 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
23249 return;
23252 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
23253 return;
23255 Expr *IndirectE = nullptr;
23256 bool IsIndirect = false;
23257 if (DTCI.Indirect) {
23258 IndirectE = *DTCI.Indirect;
23259 if (!IndirectE)
23260 IsIndirect = true;
23262 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23263 Context, MT, DTCI.DT, IndirectE, IsIndirect, Level,
23264 SourceRange(Loc, Loc));
23265 ND->addAttr(A);
23266 if (ASTMutationListener *ML = Context.getASTMutationListener())
23267 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
23268 checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Loc);
23269 if (auto *VD = dyn_cast<VarDecl>(ND);
23270 LangOpts.OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
23271 VD->hasGlobalStorage())
23272 ActOnOpenMPDeclareTargetInitializer(ND);
23275 static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
23276 Sema &SemaRef, Decl *D) {
23277 if (!D || !isa<VarDecl>(D))
23278 return;
23279 auto *VD = cast<VarDecl>(D);
23280 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
23281 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
23282 if (SemaRef.LangOpts.OpenMP >= 50 &&
23283 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
23284 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
23285 VD->hasGlobalStorage()) {
23286 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
23287 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
23288 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
23289 // If a lambda declaration and definition appears between a
23290 // declare target directive and the matching end declare target
23291 // directive, all variables that are captured by the lambda
23292 // expression must also appear in a to clause.
23293 SemaRef.Diag(VD->getLocation(),
23294 diag::err_omp_lambda_capture_in_declare_target_not_to);
23295 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
23296 << VD << 0 << SR;
23297 return;
23300 if (MapTy)
23301 return;
23302 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
23303 SemaRef.Diag(SL, diag::note_used_here) << SR;
23306 static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR,
23307 Sema &SemaRef, DSAStackTy *Stack,
23308 ValueDecl *VD) {
23309 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
23310 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
23311 /*FullCheck=*/false);
23314 void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
23315 SourceLocation IdLoc) {
23316 if (!D || D->isInvalidDecl())
23317 return;
23318 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
23319 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
23320 if (auto *VD = dyn_cast<VarDecl>(D)) {
23321 // Only global variables can be marked as declare target.
23322 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
23323 !VD->isStaticDataMember())
23324 return;
23325 // 2.10.6: threadprivate variable cannot appear in a declare target
23326 // directive.
23327 if (DSAStack->isThreadPrivate(VD)) {
23328 Diag(SL, diag::err_omp_threadprivate_in_target);
23329 reportOriginalDsa(*this, DSAStack, VD, DSAStack->getTopDSA(VD, false));
23330 return;
23333 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
23334 D = FTD->getTemplatedDecl();
23335 if (auto *FD = dyn_cast<FunctionDecl>(D)) {
23336 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
23337 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
23338 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
23339 Diag(IdLoc, diag::err_omp_function_in_link_clause);
23340 Diag(FD->getLocation(), diag::note_defined_here) << FD;
23341 return;
23344 if (auto *VD = dyn_cast<ValueDecl>(D)) {
23345 // Problem if any with var declared with incomplete type will be reported
23346 // as normal, so no need to check it here.
23347 if ((E || !VD->getType()->isIncompleteType()) &&
23348 !checkValueDeclInTarget(SL, SR, *this, DSAStack, VD))
23349 return;
23350 if (!E && isInOpenMPDeclareTargetContext()) {
23351 // Checking declaration inside declare target region.
23352 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
23353 isa<FunctionTemplateDecl>(D)) {
23354 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23355 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23356 unsigned Level = DeclareTargetNesting.size();
23357 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
23358 return;
23359 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
23360 Expr *IndirectE = nullptr;
23361 bool IsIndirect = false;
23362 if (DTCI.Indirect) {
23363 IndirectE = *DTCI.Indirect;
23364 if (!IndirectE)
23365 IsIndirect = true;
23367 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23368 Context,
23369 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
23370 : OMPDeclareTargetDeclAttr::MT_To,
23371 DTCI.DT, IndirectE, IsIndirect, Level,
23372 SourceRange(DTCI.Loc, DTCI.Loc));
23373 D->addAttr(A);
23374 if (ASTMutationListener *ML = Context.getASTMutationListener())
23375 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
23377 return;
23380 if (!E)
23381 return;
23382 checkDeclInTargetContext(E->getExprLoc(), E->getSourceRange(), *this, D);
23385 /// This class visits every VarDecl that the initializer references and adds
23386 /// OMPDeclareTargetDeclAttr to each of them.
23387 class GlobalDeclRefChecker final
23388 : public StmtVisitor<GlobalDeclRefChecker> {
23389 SmallVector<VarDecl *> DeclVector;
23390 Attr *A;
23392 public:
23393 /// A StmtVisitor class function that visits all DeclRefExpr and adds
23394 /// OMPDeclareTargetDeclAttr to them.
23395 void VisitDeclRefExpr(DeclRefExpr *Node) {
23396 if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) {
23397 VD->addAttr(A);
23398 DeclVector.push_back(VD);
23401 /// A function that iterates across each of the Expr's children.
23402 void VisitExpr(Expr *Ex) {
23403 for (auto *Child : Ex->children()) {
23404 Visit(Child);
23407 /// A function that keeps a record of all the Decls that are variables, has
23408 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
23409 /// each Decl one at a time and use the inherited 'visit' functions to look
23410 /// for DeclRefExpr.
23411 void declareTargetInitializer(Decl *TD) {
23412 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
23413 DeclVector.push_back(cast<VarDecl>(TD));
23414 while (!DeclVector.empty()) {
23415 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
23416 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
23417 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
23418 if (Expr *Ex = TargetVarDecl->getInit())
23419 Visit(Ex);
23425 /// Adding OMPDeclareTargetDeclAttr to variables with static storage
23426 /// duration that are referenced in the initializer expression list of
23427 /// variables with static storage duration in declare target directive.
23428 void Sema::ActOnOpenMPDeclareTargetInitializer(Decl *TargetDecl) {
23429 GlobalDeclRefChecker Checker;
23430 if (isa<VarDecl>(TargetDecl))
23431 Checker.declareTargetInitializer(TargetDecl);
23434 OMPClause *Sema::ActOnOpenMPToClause(
23435 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23436 ArrayRef<SourceLocation> MotionModifiersLoc,
23437 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23438 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23439 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23440 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
23441 OMPC_MOTION_MODIFIER_unknown};
23442 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
23444 // Process motion-modifiers, flag errors for duplicate modifiers.
23445 unsigned Count = 0;
23446 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23447 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23448 llvm::is_contained(Modifiers, MotionModifiers[I])) {
23449 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23450 continue;
23452 assert(Count < NumberOfOMPMotionModifiers &&
23453 "Modifiers exceed the allowed number of motion modifiers");
23454 Modifiers[Count] = MotionModifiers[I];
23455 ModifiersLoc[Count] = MotionModifiersLoc[I];
23456 ++Count;
23459 MappableVarListInfo MVLI(VarList);
23460 checkMappableExpressionList(*this, DSAStack, OMPC_to, MVLI, Locs.StartLoc,
23461 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23462 if (MVLI.ProcessedVarList.empty())
23463 return nullptr;
23465 return OMPToClause::Create(
23466 Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23467 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23468 MapperIdScopeSpec.getWithLocInContext(Context), MapperId);
23471 OMPClause *Sema::ActOnOpenMPFromClause(
23472 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23473 ArrayRef<SourceLocation> MotionModifiersLoc,
23474 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23475 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23476 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23477 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
23478 OMPC_MOTION_MODIFIER_unknown};
23479 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
23481 // Process motion-modifiers, flag errors for duplicate modifiers.
23482 unsigned Count = 0;
23483 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23484 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23485 llvm::is_contained(Modifiers, MotionModifiers[I])) {
23486 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23487 continue;
23489 assert(Count < NumberOfOMPMotionModifiers &&
23490 "Modifiers exceed the allowed number of motion modifiers");
23491 Modifiers[Count] = MotionModifiers[I];
23492 ModifiersLoc[Count] = MotionModifiersLoc[I];
23493 ++Count;
23496 MappableVarListInfo MVLI(VarList);
23497 checkMappableExpressionList(*this, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
23498 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23499 if (MVLI.ProcessedVarList.empty())
23500 return nullptr;
23502 return OMPFromClause::Create(
23503 Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23504 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23505 MapperIdScopeSpec.getWithLocInContext(Context), MapperId);
23508 OMPClause *Sema::ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList,
23509 const OMPVarListLocTy &Locs) {
23510 MappableVarListInfo MVLI(VarList);
23511 SmallVector<Expr *, 8> PrivateCopies;
23512 SmallVector<Expr *, 8> Inits;
23514 for (Expr *RefExpr : VarList) {
23515 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
23516 SourceLocation ELoc;
23517 SourceRange ERange;
23518 Expr *SimpleRefExpr = RefExpr;
23519 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
23520 if (Res.second) {
23521 // It will be analyzed later.
23522 MVLI.ProcessedVarList.push_back(RefExpr);
23523 PrivateCopies.push_back(nullptr);
23524 Inits.push_back(nullptr);
23526 ValueDecl *D = Res.first;
23527 if (!D)
23528 continue;
23530 QualType Type = D->getType();
23531 Type = Type.getNonReferenceType().getUnqualifiedType();
23533 auto *VD = dyn_cast<VarDecl>(D);
23535 // Item should be a pointer or reference to pointer.
23536 if (!Type->isPointerType()) {
23537 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
23538 << 0 << RefExpr->getSourceRange();
23539 continue;
23542 // Build the private variable and the expression that refers to it.
23543 auto VDPrivate =
23544 buildVarDecl(*this, ELoc, Type, D->getName(),
23545 D->hasAttrs() ? &D->getAttrs() : nullptr,
23546 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
23547 if (VDPrivate->isInvalidDecl())
23548 continue;
23550 CurContext->addDecl(VDPrivate);
23551 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
23552 *this, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
23554 // Add temporary variable to initialize the private copy of the pointer.
23555 VarDecl *VDInit =
23556 buildVarDecl(*this, RefExpr->getExprLoc(), Type, ".devptr.temp");
23557 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
23558 *this, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
23559 AddInitializerToDecl(VDPrivate,
23560 DefaultLvalueConversion(VDInitRefExpr).get(),
23561 /*DirectInit=*/false);
23563 // If required, build a capture to implement the privatization initialized
23564 // with the current list item value.
23565 DeclRefExpr *Ref = nullptr;
23566 if (!VD)
23567 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
23568 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
23569 PrivateCopies.push_back(VDPrivateRefExpr);
23570 Inits.push_back(VDInitRefExpr);
23572 // We need to add a data sharing attribute for this variable to make sure it
23573 // is correctly captured. A variable that shows up in a use_device_ptr has
23574 // similar properties of a first private variable.
23575 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23577 // Create a mappable component for the list item. List items in this clause
23578 // only need a component.
23579 MVLI.VarBaseDeclarations.push_back(D);
23580 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23581 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
23582 /*IsNonContiguous=*/false);
23585 if (MVLI.ProcessedVarList.empty())
23586 return nullptr;
23588 return OMPUseDevicePtrClause::Create(
23589 Context, Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
23590 MVLI.VarBaseDeclarations, MVLI.VarComponents);
23593 OMPClause *Sema::ActOnOpenMPUseDeviceAddrClause(ArrayRef<Expr *> VarList,
23594 const OMPVarListLocTy &Locs) {
23595 MappableVarListInfo MVLI(VarList);
23597 for (Expr *RefExpr : VarList) {
23598 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
23599 SourceLocation ELoc;
23600 SourceRange ERange;
23601 Expr *SimpleRefExpr = RefExpr;
23602 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
23603 /*AllowArraySection=*/true);
23604 if (Res.second) {
23605 // It will be analyzed later.
23606 MVLI.ProcessedVarList.push_back(RefExpr);
23608 ValueDecl *D = Res.first;
23609 if (!D)
23610 continue;
23611 auto *VD = dyn_cast<VarDecl>(D);
23613 // If required, build a capture to implement the privatization initialized
23614 // with the current list item value.
23615 DeclRefExpr *Ref = nullptr;
23616 if (!VD)
23617 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
23618 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
23620 // We need to add a data sharing attribute for this variable to make sure it
23621 // is correctly captured. A variable that shows up in a use_device_addr has
23622 // similar properties of a first private variable.
23623 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23625 // Create a mappable component for the list item. List items in this clause
23626 // only need a component.
23627 MVLI.VarBaseDeclarations.push_back(D);
23628 MVLI.VarComponents.emplace_back();
23629 Expr *Component = SimpleRefExpr;
23630 if (VD && (isa<OMPArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23631 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23632 Component = DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
23633 MVLI.VarComponents.back().emplace_back(Component, D,
23634 /*IsNonContiguous=*/false);
23637 if (MVLI.ProcessedVarList.empty())
23638 return nullptr;
23640 return OMPUseDeviceAddrClause::Create(Context, Locs, MVLI.ProcessedVarList,
23641 MVLI.VarBaseDeclarations,
23642 MVLI.VarComponents);
23645 OMPClause *Sema::ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList,
23646 const OMPVarListLocTy &Locs) {
23647 MappableVarListInfo MVLI(VarList);
23648 for (Expr *RefExpr : VarList) {
23649 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
23650 SourceLocation ELoc;
23651 SourceRange ERange;
23652 Expr *SimpleRefExpr = RefExpr;
23653 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
23654 if (Res.second) {
23655 // It will be analyzed later.
23656 MVLI.ProcessedVarList.push_back(RefExpr);
23658 ValueDecl *D = Res.first;
23659 if (!D)
23660 continue;
23662 QualType Type = D->getType();
23663 // item should be a pointer or array or reference to pointer or array
23664 if (!Type.getNonReferenceType()->isPointerType() &&
23665 !Type.getNonReferenceType()->isArrayType()) {
23666 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
23667 << 0 << RefExpr->getSourceRange();
23668 continue;
23671 // Check if the declaration in the clause does not show up in any data
23672 // sharing attribute.
23673 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23674 if (isOpenMPPrivate(DVar.CKind)) {
23675 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23676 << getOpenMPClauseName(DVar.CKind)
23677 << getOpenMPClauseName(OMPC_is_device_ptr)
23678 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
23679 reportOriginalDsa(*this, DSAStack, D, DVar);
23680 continue;
23683 const Expr *ConflictExpr;
23684 if (DSAStack->checkMappableExprComponentListsForDecl(
23685 D, /*CurrentRegionOnly=*/true,
23686 [&ConflictExpr](
23687 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
23688 OpenMPClauseKind) -> bool {
23689 ConflictExpr = R.front().getAssociatedExpression();
23690 return true;
23691 })) {
23692 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23693 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23694 << ConflictExpr->getSourceRange();
23695 continue;
23698 // Store the components in the stack so that they can be used to check
23699 // against other clauses later on.
23700 OMPClauseMappableExprCommon::MappableComponent MC(
23701 SimpleRefExpr, D, /*IsNonContiguous=*/false);
23702 DSAStack->addMappableExpressionComponents(
23703 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
23705 // Record the expression we've just processed.
23706 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
23708 // Create a mappable component for the list item. List items in this clause
23709 // only need a component. We use a null declaration to signal fields in
23710 // 'this'.
23711 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23712 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23713 "Unexpected device pointer expression!");
23714 MVLI.VarBaseDeclarations.push_back(
23715 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23716 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23717 MVLI.VarComponents.back().push_back(MC);
23720 if (MVLI.ProcessedVarList.empty())
23721 return nullptr;
23723 return OMPIsDevicePtrClause::Create(Context, Locs, MVLI.ProcessedVarList,
23724 MVLI.VarBaseDeclarations,
23725 MVLI.VarComponents);
23728 OMPClause *Sema::ActOnOpenMPHasDeviceAddrClause(ArrayRef<Expr *> VarList,
23729 const OMPVarListLocTy &Locs) {
23730 MappableVarListInfo MVLI(VarList);
23731 for (Expr *RefExpr : VarList) {
23732 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
23733 SourceLocation ELoc;
23734 SourceRange ERange;
23735 Expr *SimpleRefExpr = RefExpr;
23736 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
23737 /*AllowArraySection=*/true);
23738 if (Res.second) {
23739 // It will be analyzed later.
23740 MVLI.ProcessedVarList.push_back(RefExpr);
23742 ValueDecl *D = Res.first;
23743 if (!D)
23744 continue;
23746 // Check if the declaration in the clause does not show up in any data
23747 // sharing attribute.
23748 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23749 if (isOpenMPPrivate(DVar.CKind)) {
23750 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23751 << getOpenMPClauseName(DVar.CKind)
23752 << getOpenMPClauseName(OMPC_has_device_addr)
23753 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
23754 reportOriginalDsa(*this, DSAStack, D, DVar);
23755 continue;
23758 const Expr *ConflictExpr;
23759 if (DSAStack->checkMappableExprComponentListsForDecl(
23760 D, /*CurrentRegionOnly=*/true,
23761 [&ConflictExpr](
23762 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
23763 OpenMPClauseKind) -> bool {
23764 ConflictExpr = R.front().getAssociatedExpression();
23765 return true;
23766 })) {
23767 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23768 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23769 << ConflictExpr->getSourceRange();
23770 continue;
23773 // Store the components in the stack so that they can be used to check
23774 // against other clauses later on.
23775 Expr *Component = SimpleRefExpr;
23776 auto *VD = dyn_cast<VarDecl>(D);
23777 if (VD && (isa<OMPArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23778 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23779 Component = DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
23780 OMPClauseMappableExprCommon::MappableComponent MC(
23781 Component, D, /*IsNonContiguous=*/false);
23782 DSAStack->addMappableExpressionComponents(
23783 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
23785 // Record the expression we've just processed.
23786 if (!VD && !CurContext->isDependentContext()) {
23787 DeclRefExpr *Ref =
23788 buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
23789 assert(Ref && "has_device_addr capture failed");
23790 MVLI.ProcessedVarList.push_back(Ref);
23791 } else
23792 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
23794 // Create a mappable component for the list item. List items in this clause
23795 // only need a component. We use a null declaration to signal fields in
23796 // 'this'.
23797 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23798 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23799 "Unexpected device pointer expression!");
23800 MVLI.VarBaseDeclarations.push_back(
23801 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23802 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23803 MVLI.VarComponents.back().push_back(MC);
23806 if (MVLI.ProcessedVarList.empty())
23807 return nullptr;
23809 return OMPHasDeviceAddrClause::Create(Context, Locs, MVLI.ProcessedVarList,
23810 MVLI.VarBaseDeclarations,
23811 MVLI.VarComponents);
23814 OMPClause *Sema::ActOnOpenMPAllocateClause(
23815 Expr *Allocator, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
23816 SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
23817 if (Allocator) {
23818 // OpenMP [2.11.4 allocate Clause, Description]
23819 // allocator is an expression of omp_allocator_handle_t type.
23820 if (!findOMPAllocatorHandleT(*this, Allocator->getExprLoc(), DSAStack))
23821 return nullptr;
23823 ExprResult AllocatorRes = DefaultLvalueConversion(Allocator);
23824 if (AllocatorRes.isInvalid())
23825 return nullptr;
23826 AllocatorRes = PerformImplicitConversion(AllocatorRes.get(),
23827 DSAStack->getOMPAllocatorHandleT(),
23828 Sema::AA_Initializing,
23829 /*AllowExplicit=*/true);
23830 if (AllocatorRes.isInvalid())
23831 return nullptr;
23832 Allocator = AllocatorRes.get();
23833 } else {
23834 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
23835 // allocate clauses that appear on a target construct or on constructs in a
23836 // target region must specify an allocator expression unless a requires
23837 // directive with the dynamic_allocators clause is present in the same
23838 // compilation unit.
23839 if (LangOpts.OpenMPIsTargetDevice &&
23840 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
23841 targetDiag(StartLoc, diag::err_expected_allocator_expression);
23843 // Analyze and build list of variables.
23844 SmallVector<Expr *, 8> Vars;
23845 for (Expr *RefExpr : VarList) {
23846 assert(RefExpr && "NULL expr in OpenMP private clause.");
23847 SourceLocation ELoc;
23848 SourceRange ERange;
23849 Expr *SimpleRefExpr = RefExpr;
23850 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
23851 if (Res.second) {
23852 // It will be analyzed later.
23853 Vars.push_back(RefExpr);
23855 ValueDecl *D = Res.first;
23856 if (!D)
23857 continue;
23859 auto *VD = dyn_cast<VarDecl>(D);
23860 DeclRefExpr *Ref = nullptr;
23861 if (!VD && !CurContext->isDependentContext())
23862 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
23863 Vars.push_back((VD || CurContext->isDependentContext())
23864 ? RefExpr->IgnoreParens()
23865 : Ref);
23868 if (Vars.empty())
23869 return nullptr;
23871 if (Allocator)
23872 DSAStack->addInnerAllocatorExpr(Allocator);
23873 return OMPAllocateClause::Create(Context, StartLoc, LParenLoc, Allocator,
23874 ColonLoc, EndLoc, Vars);
23877 OMPClause *Sema::ActOnOpenMPNontemporalClause(ArrayRef<Expr *> VarList,
23878 SourceLocation StartLoc,
23879 SourceLocation LParenLoc,
23880 SourceLocation EndLoc) {
23881 SmallVector<Expr *, 8> Vars;
23882 for (Expr *RefExpr : VarList) {
23883 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23884 SourceLocation ELoc;
23885 SourceRange ERange;
23886 Expr *SimpleRefExpr = RefExpr;
23887 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
23888 if (Res.second)
23889 // It will be analyzed later.
23890 Vars.push_back(RefExpr);
23891 ValueDecl *D = Res.first;
23892 if (!D)
23893 continue;
23895 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
23896 // A list-item cannot appear in more than one nontemporal clause.
23897 if (const Expr *PrevRef =
23898 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
23899 Diag(ELoc, diag::err_omp_used_in_clause_twice)
23900 << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange;
23901 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
23902 << getOpenMPClauseName(OMPC_nontemporal);
23903 continue;
23906 Vars.push_back(RefExpr);
23909 if (Vars.empty())
23910 return nullptr;
23912 return OMPNontemporalClause::Create(Context, StartLoc, LParenLoc, EndLoc,
23913 Vars);
23916 StmtResult Sema::ActOnOpenMPScopeDirective(ArrayRef<OMPClause *> Clauses,
23917 Stmt *AStmt, SourceLocation StartLoc,
23918 SourceLocation EndLoc) {
23919 if (!AStmt)
23920 return StmtError();
23922 setFunctionHasBranchProtectedScope();
23924 return OMPScopeDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
23927 OMPClause *Sema::ActOnOpenMPInclusiveClause(ArrayRef<Expr *> VarList,
23928 SourceLocation StartLoc,
23929 SourceLocation LParenLoc,
23930 SourceLocation EndLoc) {
23931 SmallVector<Expr *, 8> Vars;
23932 for (Expr *RefExpr : VarList) {
23933 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23934 SourceLocation ELoc;
23935 SourceRange ERange;
23936 Expr *SimpleRefExpr = RefExpr;
23937 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
23938 /*AllowArraySection=*/true);
23939 if (Res.second)
23940 // It will be analyzed later.
23941 Vars.push_back(RefExpr);
23942 ValueDecl *D = Res.first;
23943 if (!D)
23944 continue;
23946 const DSAStackTy::DSAVarData DVar =
23947 DSAStack->getTopDSA(D, /*FromParent=*/true);
23948 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23949 // A list item that appears in the inclusive or exclusive clause must appear
23950 // in a reduction clause with the inscan modifier on the enclosing
23951 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23952 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
23953 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23954 << RefExpr->getSourceRange();
23956 if (DSAStack->getParentDirective() != OMPD_unknown)
23957 DSAStack->markDeclAsUsedInScanDirective(D);
23958 Vars.push_back(RefExpr);
23961 if (Vars.empty())
23962 return nullptr;
23964 return OMPInclusiveClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
23967 OMPClause *Sema::ActOnOpenMPExclusiveClause(ArrayRef<Expr *> VarList,
23968 SourceLocation StartLoc,
23969 SourceLocation LParenLoc,
23970 SourceLocation EndLoc) {
23971 SmallVector<Expr *, 8> Vars;
23972 for (Expr *RefExpr : VarList) {
23973 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23974 SourceLocation ELoc;
23975 SourceRange ERange;
23976 Expr *SimpleRefExpr = RefExpr;
23977 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
23978 /*AllowArraySection=*/true);
23979 if (Res.second)
23980 // It will be analyzed later.
23981 Vars.push_back(RefExpr);
23982 ValueDecl *D = Res.first;
23983 if (!D)
23984 continue;
23986 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
23987 DSAStackTy::DSAVarData DVar;
23988 if (ParentDirective != OMPD_unknown)
23989 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
23990 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23991 // A list item that appears in the inclusive or exclusive clause must appear
23992 // in a reduction clause with the inscan modifier on the enclosing
23993 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23994 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
23995 DVar.Modifier != OMPC_REDUCTION_inscan) {
23996 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23997 << RefExpr->getSourceRange();
23998 } else {
23999 DSAStack->markDeclAsUsedInScanDirective(D);
24001 Vars.push_back(RefExpr);
24004 if (Vars.empty())
24005 return nullptr;
24007 return OMPExclusiveClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
24010 /// Tries to find omp_alloctrait_t type.
24011 static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
24012 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
24013 if (!OMPAlloctraitT.isNull())
24014 return true;
24015 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
24016 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
24017 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
24018 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
24019 return false;
24021 Stack->setOMPAlloctraitT(PT.get());
24022 return true;
24025 OMPClause *Sema::ActOnOpenMPUsesAllocatorClause(
24026 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
24027 ArrayRef<UsesAllocatorsData> Data) {
24028 // OpenMP [2.12.5, target Construct]
24029 // allocator is an identifier of omp_allocator_handle_t type.
24030 if (!findOMPAllocatorHandleT(*this, StartLoc, DSAStack))
24031 return nullptr;
24032 // OpenMP [2.12.5, target Construct]
24033 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
24034 if (llvm::any_of(
24035 Data,
24036 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
24037 !findOMPAlloctraitT(*this, StartLoc, DSAStack))
24038 return nullptr;
24039 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
24040 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
24041 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
24042 StringRef Allocator =
24043 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
24044 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
24045 PredefinedAllocators.insert(LookupSingleName(
24046 TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
24049 SmallVector<OMPUsesAllocatorsClause::Data, 4> NewData;
24050 for (const UsesAllocatorsData &D : Data) {
24051 Expr *AllocatorExpr = nullptr;
24052 // Check allocator expression.
24053 if (D.Allocator->isTypeDependent()) {
24054 AllocatorExpr = D.Allocator;
24055 } else {
24056 // Traits were specified - need to assign new allocator to the specified
24057 // allocator, so it must be an lvalue.
24058 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
24059 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
24060 bool IsPredefinedAllocator = false;
24061 if (DRE) {
24062 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
24063 getAllocatorKind(*this, DSAStack, AllocatorExpr);
24064 IsPredefinedAllocator =
24065 AllocatorTy !=
24066 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
24068 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
24069 QualType AllocatorExprType = AllocatorExpr->getType();
24070 bool IsTypeCompatible = IsPredefinedAllocator;
24071 IsTypeCompatible = IsTypeCompatible ||
24072 Context.hasSameUnqualifiedType(AllocatorExprType,
24073 OMPAllocatorHandleT);
24074 IsTypeCompatible =
24075 IsTypeCompatible ||
24076 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
24077 bool IsNonConstantLValue =
24078 !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue();
24079 if (!DRE || !IsTypeCompatible ||
24080 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
24081 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
24082 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
24083 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
24084 continue;
24086 // OpenMP [2.12.5, target Construct]
24087 // Predefined allocators appearing in a uses_allocators clause cannot have
24088 // traits specified.
24089 if (IsPredefinedAllocator && D.AllocatorTraits) {
24090 Diag(D.AllocatorTraits->getExprLoc(),
24091 diag::err_omp_predefined_allocator_with_traits)
24092 << D.AllocatorTraits->getSourceRange();
24093 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
24094 << cast<NamedDecl>(DRE->getDecl())->getName()
24095 << D.Allocator->getSourceRange();
24096 continue;
24098 // OpenMP [2.12.5, target Construct]
24099 // Non-predefined allocators appearing in a uses_allocators clause must
24100 // have traits specified.
24101 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
24102 Diag(D.Allocator->getExprLoc(),
24103 diag::err_omp_nonpredefined_allocator_without_traits);
24104 continue;
24106 // No allocator traits - just convert it to rvalue.
24107 if (!D.AllocatorTraits)
24108 AllocatorExpr = DefaultLvalueConversion(AllocatorExpr).get();
24109 DSAStack->addUsesAllocatorsDecl(
24110 DRE->getDecl(),
24111 IsPredefinedAllocator
24112 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
24113 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
24115 Expr *AllocatorTraitsExpr = nullptr;
24116 if (D.AllocatorTraits) {
24117 if (D.AllocatorTraits->isTypeDependent()) {
24118 AllocatorTraitsExpr = D.AllocatorTraits;
24119 } else {
24120 // OpenMP [2.12.5, target Construct]
24121 // Arrays that contain allocator traits that appear in a uses_allocators
24122 // clause must be constant arrays, have constant values and be defined
24123 // in the same scope as the construct in which the clause appears.
24124 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
24125 // Check that traits expr is a constant array.
24126 QualType TraitTy;
24127 if (const ArrayType *Ty =
24128 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
24129 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
24130 TraitTy = ConstArrayTy->getElementType();
24131 if (TraitTy.isNull() ||
24132 !(Context.hasSameUnqualifiedType(TraitTy,
24133 DSAStack->getOMPAlloctraitT()) ||
24134 Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
24135 /*CompareUnqualified=*/true))) {
24136 Diag(D.AllocatorTraits->getExprLoc(),
24137 diag::err_omp_expected_array_alloctraits)
24138 << AllocatorTraitsExpr->getType();
24139 continue;
24141 // Do not map by default allocator traits if it is a standalone
24142 // variable.
24143 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
24144 DSAStack->addUsesAllocatorsDecl(
24145 DRE->getDecl(),
24146 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
24149 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
24150 NewD.Allocator = AllocatorExpr;
24151 NewD.AllocatorTraits = AllocatorTraitsExpr;
24152 NewD.LParenLoc = D.LParenLoc;
24153 NewD.RParenLoc = D.RParenLoc;
24155 return OMPUsesAllocatorsClause::Create(Context, StartLoc, LParenLoc, EndLoc,
24156 NewData);
24159 OMPClause *Sema::ActOnOpenMPAffinityClause(
24160 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
24161 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
24162 SmallVector<Expr *, 8> Vars;
24163 for (Expr *RefExpr : Locators) {
24164 assert(RefExpr && "NULL expr in OpenMP shared clause.");
24165 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
24166 // It will be analyzed later.
24167 Vars.push_back(RefExpr);
24168 continue;
24171 SourceLocation ELoc = RefExpr->getExprLoc();
24172 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
24174 if (!SimpleExpr->isLValue()) {
24175 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24176 << 1 << 0 << RefExpr->getSourceRange();
24177 continue;
24180 ExprResult Res;
24182 Sema::TentativeAnalysisScope Trap(*this);
24183 Res = CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
24185 if (!Res.isUsable() && !isa<OMPArraySectionExpr>(SimpleExpr) &&
24186 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
24187 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24188 << 1 << 0 << RefExpr->getSourceRange();
24189 continue;
24191 Vars.push_back(SimpleExpr);
24194 return OMPAffinityClause::Create(Context, StartLoc, LParenLoc, ColonLoc,
24195 EndLoc, Modifier, Vars);
24198 OMPClause *Sema::ActOnOpenMPBindClause(OpenMPBindClauseKind Kind,
24199 SourceLocation KindLoc,
24200 SourceLocation StartLoc,
24201 SourceLocation LParenLoc,
24202 SourceLocation EndLoc) {
24203 if (Kind == OMPC_BIND_unknown) {
24204 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24205 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
24206 /*Last=*/unsigned(OMPC_BIND_unknown))
24207 << getOpenMPClauseName(OMPC_bind);
24208 return nullptr;
24211 return OMPBindClause::Create(Context, Kind, KindLoc, StartLoc, LParenLoc,
24212 EndLoc);
24215 OMPClause *Sema::ActOnOpenMPXDynCGroupMemClause(Expr *Size,
24216 SourceLocation StartLoc,
24217 SourceLocation LParenLoc,
24218 SourceLocation EndLoc) {
24219 Expr *ValExpr = Size;
24220 Stmt *HelperValStmt = nullptr;
24222 // OpenMP [2.5, Restrictions]
24223 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
24224 // value.
24225 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_ompx_dyn_cgroup_mem,
24226 /*StrictlyPositive=*/false))
24227 return nullptr;
24229 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
24230 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
24231 DKind, OMPC_ompx_dyn_cgroup_mem, LangOpts.OpenMP);
24232 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
24233 ValExpr = MakeFullExpr(ValExpr).get();
24234 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24235 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
24236 HelperValStmt = buildPreInits(Context, Captures);
24239 return new (Context) OMPXDynCGroupMemClause(
24240 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
24243 OMPClause *Sema::ActOnOpenMPDoacrossClause(
24244 OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc,
24245 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
24246 SourceLocation LParenLoc, SourceLocation EndLoc) {
24248 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
24249 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
24250 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
24251 DepType != OMPC_DOACROSS_source_omp_cur_iteration &&
24252 DepType != OMPC_DOACROSS_source) {
24253 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
24254 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_doacross);
24255 return nullptr;
24258 SmallVector<Expr *, 8> Vars;
24259 DSAStackTy::OperatorOffsetTy OpsOffs;
24260 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
24261 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
24262 *this,
24263 DepType == OMPC_DOACROSS_source ||
24264 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
24265 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
24266 VarList, DSAStack, EndLoc);
24267 Vars = VarOffset.Vars;
24268 OpsOffs = VarOffset.OpsOffs;
24269 TotalDepCount = VarOffset.TotalDepCount;
24270 auto *C = OMPDoacrossClause::Create(Context, StartLoc, LParenLoc, EndLoc,
24271 DepType, DepLoc, ColonLoc, Vars,
24272 TotalDepCount.getZExtValue());
24273 if (DSAStack->isParentOrderedRegion())
24274 DSAStack->addDoacrossDependClause(C, OpsOffs);
24275 return C;
24278 OMPClause *Sema::ActOnOpenMPXAttributeClause(ArrayRef<const Attr *> Attrs,
24279 SourceLocation StartLoc,
24280 SourceLocation LParenLoc,
24281 SourceLocation EndLoc) {
24282 return new (Context) OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);