[Flang] remove whole-archive option for AIX linker (#76039)
[llvm-project.git] / clang / lib / Sema / SemaOpenMP.cpp
blob3826994ef2126cee9a93d3f3580e1ea710ad17d2
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 + 1];
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::is_contained(Top->IteratorVarDecls, VD->getCanonicalDecl());
1192 /// get captured field from ImplicitDefaultFirstprivateFDs
1193 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1194 const_iterator I = begin();
1195 const_iterator EndI = end();
1196 size_t StackLevel = getStackSize();
1197 for (; I != EndI; ++I) {
1198 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1199 break;
1200 StackLevel--;
1202 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1203 if (I == EndI)
1204 return nullptr;
1205 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1206 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1207 return IFD.VD;
1208 return nullptr;
1210 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
1211 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1212 const_iterator I = begin();
1213 const_iterator EndI = end();
1214 for (; I != EndI; ++I)
1215 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1216 break;
1217 if (I == EndI)
1218 return false;
1219 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1220 if (IFD.VD == VD)
1221 return true;
1222 return false;
1224 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
1225 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1226 iterator I = begin();
1227 const_iterator EndI = end();
1228 size_t StackLevel = getStackSize();
1229 for (; I != EndI; ++I) {
1230 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1231 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1232 break;
1234 StackLevel--;
1236 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1240 bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1241 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1244 bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1245 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) ||
1246 DKind == OMPD_unknown;
1249 } // namespace
1251 static const Expr *getExprAsWritten(const Expr *E) {
1252 if (const auto *FE = dyn_cast<FullExpr>(E))
1253 E = FE->getSubExpr();
1255 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
1256 E = MTE->getSubExpr();
1258 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
1259 E = Binder->getSubExpr();
1261 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
1262 E = ICE->getSubExprAsWritten();
1263 return E->IgnoreParens();
1266 static Expr *getExprAsWritten(Expr *E) {
1267 return const_cast<Expr *>(getExprAsWritten(const_cast<const Expr *>(E)));
1270 static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1271 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
1272 if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
1273 D = ME->getMemberDecl();
1274 const auto *VD = dyn_cast<VarDecl>(D);
1275 const auto *FD = dyn_cast<FieldDecl>(D);
1276 if (VD != nullptr) {
1277 VD = VD->getCanonicalDecl();
1278 D = VD;
1279 } else {
1280 assert(FD);
1281 FD = FD->getCanonicalDecl();
1282 D = FD;
1284 return D;
1287 static ValueDecl *getCanonicalDecl(ValueDecl *D) {
1288 return const_cast<ValueDecl *>(
1289 getCanonicalDecl(const_cast<const ValueDecl *>(D)));
1292 DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1293 ValueDecl *D) const {
1294 D = getCanonicalDecl(D);
1295 auto *VD = dyn_cast<VarDecl>(D);
1296 const auto *FD = dyn_cast<FieldDecl>(D);
1297 DSAVarData DVar;
1298 if (Iter == end()) {
1299 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1300 // in a region but not in construct]
1301 // File-scope or namespace-scope variables referenced in called routines
1302 // in the region are shared unless they appear in a threadprivate
1303 // directive.
1304 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD))
1305 DVar.CKind = OMPC_shared;
1307 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1308 // in a region but not in construct]
1309 // Variables with static storage duration that are declared in called
1310 // routines in the region are shared.
1311 if (VD && VD->hasGlobalStorage())
1312 DVar.CKind = OMPC_shared;
1314 // Non-static data members are shared by default.
1315 if (FD)
1316 DVar.CKind = OMPC_shared;
1318 return DVar;
1321 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1322 // in a Construct, C/C++, predetermined, p.1]
1323 // Variables with automatic storage duration that are declared in a scope
1324 // inside the construct are private.
1325 if (VD && isOpenMPLocal(VD, Iter) && VD->isLocalVarDecl() &&
1326 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1327 DVar.CKind = OMPC_private;
1328 return DVar;
1331 DVar.DKind = Iter->Directive;
1332 // Explicitly specified attributes and local variables with predetermined
1333 // attributes.
1334 if (Iter->SharingMap.count(D)) {
1335 const DSAInfo &Data = Iter->SharingMap.lookup(D);
1336 DVar.RefExpr = Data.RefExpr.getPointer();
1337 DVar.PrivateCopy = Data.PrivateCopy;
1338 DVar.CKind = Data.Attributes;
1339 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1340 DVar.Modifier = Data.Modifier;
1341 DVar.AppliedToPointee = Data.AppliedToPointee;
1342 return DVar;
1345 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1346 // in a Construct, C/C++, implicitly determined, p.1]
1347 // In a parallel or task construct, the data-sharing attributes of these
1348 // variables are determined by the default clause, if present.
1349 switch (Iter->DefaultAttr) {
1350 case DSA_shared:
1351 DVar.CKind = OMPC_shared;
1352 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1353 return DVar;
1354 case DSA_none:
1355 return DVar;
1356 case DSA_firstprivate:
1357 if (VD && VD->getStorageDuration() == SD_Static &&
1358 VD->getDeclContext()->isFileContext()) {
1359 DVar.CKind = OMPC_unknown;
1360 } else {
1361 DVar.CKind = OMPC_firstprivate;
1363 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1364 return DVar;
1365 case DSA_private:
1366 // each variable with static storage duration that is declared
1367 // in a namespace or global scope and referenced in the construct,
1368 // and that does not have a predetermined data-sharing attribute
1369 if (VD && VD->getStorageDuration() == SD_Static &&
1370 VD->getDeclContext()->isFileContext()) {
1371 DVar.CKind = OMPC_unknown;
1372 } else {
1373 DVar.CKind = OMPC_private;
1375 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1376 return DVar;
1377 case DSA_unspecified:
1378 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1379 // in a Construct, implicitly determined, p.2]
1380 // In a parallel construct, if no default clause is present, these
1381 // variables are shared.
1382 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1383 if ((isOpenMPParallelDirective(DVar.DKind) &&
1384 !isOpenMPTaskLoopDirective(DVar.DKind)) ||
1385 isOpenMPTeamsDirective(DVar.DKind)) {
1386 DVar.CKind = OMPC_shared;
1387 return DVar;
1390 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1391 // in a Construct, implicitly determined, p.4]
1392 // In a task construct, if no default clause is present, a variable that in
1393 // the enclosing context is determined to be shared by all implicit tasks
1394 // bound to the current team is shared.
1395 if (isOpenMPTaskingDirective(DVar.DKind)) {
1396 DSAVarData DVarTemp;
1397 const_iterator I = Iter, E = end();
1398 do {
1399 ++I;
1400 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1401 // Referenced in a Construct, implicitly determined, p.6]
1402 // In a task construct, if no default clause is present, a variable
1403 // whose data-sharing attribute is not determined by the rules above is
1404 // firstprivate.
1405 DVarTemp = getDSA(I, D);
1406 if (DVarTemp.CKind != OMPC_shared) {
1407 DVar.RefExpr = nullptr;
1408 DVar.CKind = OMPC_firstprivate;
1409 return DVar;
1411 } while (I != E && !isImplicitTaskingRegion(I->Directive));
1412 DVar.CKind =
1413 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1414 return DVar;
1417 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1418 // in a Construct, implicitly determined, p.3]
1419 // For constructs other than task, if no default clause is present, these
1420 // variables inherit their data-sharing attributes from the enclosing
1421 // context.
1422 return getDSA(++Iter, D);
1425 const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1426 const Expr *NewDE) {
1427 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1428 D = getCanonicalDecl(D);
1429 SharingMapTy &StackElem = getTopOfStack();
1430 auto It = StackElem.AlignedMap.find(D);
1431 if (It == StackElem.AlignedMap.end()) {
1432 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1433 StackElem.AlignedMap[D] = NewDE;
1434 return nullptr;
1436 assert(It->second && "Unexpected nullptr expr in the aligned map");
1437 return It->second;
1440 const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1441 const Expr *NewDE) {
1442 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1443 D = getCanonicalDecl(D);
1444 SharingMapTy &StackElem = getTopOfStack();
1445 auto It = StackElem.NontemporalMap.find(D);
1446 if (It == StackElem.NontemporalMap.end()) {
1447 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1448 StackElem.NontemporalMap[D] = NewDE;
1449 return nullptr;
1451 assert(It->second && "Unexpected nullptr expr in the aligned map");
1452 return It->second;
1455 void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1456 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1457 D = getCanonicalDecl(D);
1458 SharingMapTy &StackElem = getTopOfStack();
1459 StackElem.LCVMap.try_emplace(
1460 D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1463 const DSAStackTy::LCDeclInfo
1464 DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1465 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1466 D = getCanonicalDecl(D);
1467 const SharingMapTy &StackElem = getTopOfStack();
1468 auto It = StackElem.LCVMap.find(D);
1469 if (It != StackElem.LCVMap.end())
1470 return It->second;
1471 return {0, nullptr};
1474 const DSAStackTy::LCDeclInfo
1475 DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1476 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1477 D = getCanonicalDecl(D);
1478 for (unsigned I = Level + 1; I > 0; --I) {
1479 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1480 auto It = StackElem.LCVMap.find(D);
1481 if (It != StackElem.LCVMap.end())
1482 return It->second;
1484 return {0, nullptr};
1487 const DSAStackTy::LCDeclInfo
1488 DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1489 const SharingMapTy *Parent = getSecondOnStackOrNull();
1490 assert(Parent && "Data-sharing attributes stack is empty");
1491 D = getCanonicalDecl(D);
1492 auto It = Parent->LCVMap.find(D);
1493 if (It != Parent->LCVMap.end())
1494 return It->second;
1495 return {0, nullptr};
1498 const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1499 const SharingMapTy *Parent = getSecondOnStackOrNull();
1500 assert(Parent && "Data-sharing attributes stack is empty");
1501 if (Parent->LCVMap.size() < I)
1502 return nullptr;
1503 for (const auto &Pair : Parent->LCVMap)
1504 if (Pair.second.first == I)
1505 return Pair.first;
1506 return nullptr;
1509 void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1510 DeclRefExpr *PrivateCopy, unsigned Modifier,
1511 bool AppliedToPointee) {
1512 D = getCanonicalDecl(D);
1513 if (A == OMPC_threadprivate) {
1514 DSAInfo &Data = Threadprivates[D];
1515 Data.Attributes = A;
1516 Data.RefExpr.setPointer(E);
1517 Data.PrivateCopy = nullptr;
1518 Data.Modifier = Modifier;
1519 } else {
1520 DSAInfo &Data = getTopOfStack().SharingMap[D];
1521 assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1522 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1523 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1524 (isLoopControlVariable(D).first && A == OMPC_private));
1525 Data.Modifier = Modifier;
1526 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1527 Data.RefExpr.setInt(/*IntVal=*/true);
1528 return;
1530 const bool IsLastprivate =
1531 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1532 Data.Attributes = A;
1533 Data.RefExpr.setPointerAndInt(E, IsLastprivate);
1534 Data.PrivateCopy = PrivateCopy;
1535 Data.AppliedToPointee = AppliedToPointee;
1536 if (PrivateCopy) {
1537 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1538 Data.Modifier = Modifier;
1539 Data.Attributes = A;
1540 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1541 Data.PrivateCopy = nullptr;
1542 Data.AppliedToPointee = AppliedToPointee;
1547 /// Build a variable declaration for OpenMP loop iteration variable.
1548 static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type,
1549 StringRef Name, const AttrVec *Attrs = nullptr,
1550 DeclRefExpr *OrigRef = nullptr) {
1551 DeclContext *DC = SemaRef.CurContext;
1552 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1553 TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
1554 auto *Decl =
1555 VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
1556 if (Attrs) {
1557 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1558 I != E; ++I)
1559 Decl->addAttr(*I);
1561 Decl->setImplicit();
1562 if (OrigRef) {
1563 Decl->addAttr(
1564 OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef));
1566 return Decl;
1569 static DeclRefExpr *buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty,
1570 SourceLocation Loc,
1571 bool RefersToCapture = false) {
1572 D->setReferenced();
1573 D->markUsed(S.Context);
1574 return DeclRefExpr::Create(S.getASTContext(), NestedNameSpecifierLoc(),
1575 SourceLocation(), D, RefersToCapture, Loc, Ty,
1576 VK_LValue);
1579 void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1580 BinaryOperatorKind BOK) {
1581 D = getCanonicalDecl(D);
1582 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1583 assert(
1584 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1585 "Additional reduction info may be specified only for reduction items.");
1586 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1587 assert(ReductionData.ReductionRange.isInvalid() &&
1588 (getTopOfStack().Directive == OMPD_taskgroup ||
1589 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1590 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1591 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1592 "Additional reduction info may be specified only once for reduction "
1593 "items.");
1594 ReductionData.set(BOK, SR);
1595 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1596 if (!TaskgroupReductionRef) {
1597 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1598 SemaRef.Context.VoidPtrTy, ".task_red.");
1599 TaskgroupReductionRef =
1600 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1604 void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1605 const Expr *ReductionRef) {
1606 D = getCanonicalDecl(D);
1607 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1608 assert(
1609 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1610 "Additional reduction info may be specified only for reduction items.");
1611 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1612 assert(ReductionData.ReductionRange.isInvalid() &&
1613 (getTopOfStack().Directive == OMPD_taskgroup ||
1614 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1615 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1616 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1617 "Additional reduction info may be specified only once for reduction "
1618 "items.");
1619 ReductionData.set(ReductionRef, SR);
1620 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1621 if (!TaskgroupReductionRef) {
1622 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1623 SemaRef.Context.VoidPtrTy, ".task_red.");
1624 TaskgroupReductionRef =
1625 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1629 const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1630 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1631 Expr *&TaskgroupDescriptor) const {
1632 D = getCanonicalDecl(D);
1633 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1634 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1635 const DSAInfo &Data = I->SharingMap.lookup(D);
1636 if (Data.Attributes != OMPC_reduction ||
1637 Data.Modifier != OMPC_REDUCTION_task)
1638 continue;
1639 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1640 if (!ReductionData.ReductionOp ||
1641 ReductionData.ReductionOp.is<const Expr *>())
1642 return DSAVarData();
1643 SR = ReductionData.ReductionRange;
1644 BOK = ReductionData.ReductionOp.get<ReductionData::BOKPtrType>();
1645 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1646 "expression for the descriptor is not "
1647 "set.");
1648 TaskgroupDescriptor = I->TaskgroupReductionRef;
1649 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1650 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1651 /*AppliedToPointee=*/false);
1653 return DSAVarData();
1656 const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1657 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1658 Expr *&TaskgroupDescriptor) const {
1659 D = getCanonicalDecl(D);
1660 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1661 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1662 const DSAInfo &Data = I->SharingMap.lookup(D);
1663 if (Data.Attributes != OMPC_reduction ||
1664 Data.Modifier != OMPC_REDUCTION_task)
1665 continue;
1666 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1667 if (!ReductionData.ReductionOp ||
1668 !ReductionData.ReductionOp.is<const Expr *>())
1669 return DSAVarData();
1670 SR = ReductionData.ReductionRange;
1671 ReductionRef = ReductionData.ReductionOp.get<const Expr *>();
1672 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1673 "expression for the descriptor is not "
1674 "set.");
1675 TaskgroupDescriptor = I->TaskgroupReductionRef;
1676 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1677 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1678 /*AppliedToPointee=*/false);
1680 return DSAVarData();
1683 bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1684 D = D->getCanonicalDecl();
1685 for (const_iterator E = end(); I != E; ++I) {
1686 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1687 isOpenMPTargetExecutionDirective(I->Directive)) {
1688 if (I->CurScope) {
1689 Scope *TopScope = I->CurScope->getParent();
1690 Scope *CurScope = getCurScope();
1691 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1692 CurScope = CurScope->getParent();
1693 return CurScope != TopScope;
1695 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1696 if (I->Context == DC)
1697 return true;
1698 return false;
1701 return false;
1704 static bool isConstNotMutableType(Sema &SemaRef, QualType Type,
1705 bool AcceptIfMutable = true,
1706 bool *IsClassType = nullptr) {
1707 ASTContext &Context = SemaRef.getASTContext();
1708 Type = Type.getNonReferenceType().getCanonicalType();
1709 bool IsConstant = Type.isConstant(Context);
1710 Type = Context.getBaseElementType(Type);
1711 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1712 ? Type->getAsCXXRecordDecl()
1713 : nullptr;
1714 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1715 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1716 RD = CTD->getTemplatedDecl();
1717 if (IsClassType)
1718 *IsClassType = RD;
1719 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1720 RD->hasDefinition() && RD->hasMutableFields());
1723 static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1724 QualType Type, OpenMPClauseKind CKind,
1725 SourceLocation ELoc,
1726 bool AcceptIfMutable = true,
1727 bool ListItemNotVar = false) {
1728 ASTContext &Context = SemaRef.getASTContext();
1729 bool IsClassType;
1730 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, &IsClassType)) {
1731 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1732 : IsClassType ? diag::err_omp_const_not_mutable_variable
1733 : diag::err_omp_const_variable;
1734 SemaRef.Diag(ELoc, Diag) << getOpenMPClauseName(CKind);
1735 if (!ListItemNotVar && D) {
1736 const VarDecl *VD = dyn_cast<VarDecl>(D);
1737 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1738 VarDecl::DeclarationOnly;
1739 SemaRef.Diag(D->getLocation(),
1740 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1741 << D;
1743 return true;
1745 return false;
1748 const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1749 bool FromParent) {
1750 D = getCanonicalDecl(D);
1751 DSAVarData DVar;
1753 auto *VD = dyn_cast<VarDecl>(D);
1754 auto TI = Threadprivates.find(D);
1755 if (TI != Threadprivates.end()) {
1756 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1757 DVar.CKind = OMPC_threadprivate;
1758 DVar.Modifier = TI->getSecond().Modifier;
1759 return DVar;
1761 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1762 DVar.RefExpr = buildDeclRefExpr(
1763 SemaRef, VD, D->getType().getNonReferenceType(),
1764 VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1765 DVar.CKind = OMPC_threadprivate;
1766 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1767 return DVar;
1769 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1770 // in a Construct, C/C++, predetermined, p.1]
1771 // Variables appearing in threadprivate directives are threadprivate.
1772 if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1773 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1774 SemaRef.getLangOpts().OpenMPUseTLS &&
1775 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1776 (VD && VD->getStorageClass() == SC_Register &&
1777 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1778 DVar.RefExpr = buildDeclRefExpr(
1779 SemaRef, VD, D->getType().getNonReferenceType(), D->getLocation());
1780 DVar.CKind = OMPC_threadprivate;
1781 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1782 return DVar;
1784 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1785 VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1786 !isLoopControlVariable(D).first) {
1787 const_iterator IterTarget =
1788 std::find_if(begin(), end(), [](const SharingMapTy &Data) {
1789 return isOpenMPTargetExecutionDirective(Data.Directive);
1791 if (IterTarget != end()) {
1792 const_iterator ParentIterTarget = IterTarget + 1;
1793 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1794 if (isOpenMPLocal(VD, Iter)) {
1795 DVar.RefExpr =
1796 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1797 D->getLocation());
1798 DVar.CKind = OMPC_threadprivate;
1799 return DVar;
1802 if (!isClauseParsingMode() || IterTarget != begin()) {
1803 auto DSAIter = IterTarget->SharingMap.find(D);
1804 if (DSAIter != IterTarget->SharingMap.end() &&
1805 isOpenMPPrivate(DSAIter->getSecond().Attributes)) {
1806 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1807 DVar.CKind = OMPC_threadprivate;
1808 return DVar;
1810 const_iterator End = end();
1811 if (!SemaRef.isOpenMPCapturedByRef(D,
1812 std::distance(ParentIterTarget, End),
1813 /*OpenMPCaptureLevel=*/0)) {
1814 DVar.RefExpr =
1815 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1816 IterTarget->ConstructLoc);
1817 DVar.CKind = OMPC_threadprivate;
1818 return DVar;
1824 if (isStackEmpty())
1825 // Not in OpenMP execution region and top scope was already checked.
1826 return DVar;
1828 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1829 // in a Construct, C/C++, predetermined, p.4]
1830 // Static data members are shared.
1831 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1832 // in a Construct, C/C++, predetermined, p.7]
1833 // Variables with static storage duration that are declared in a scope
1834 // inside the construct are shared.
1835 if (VD && VD->isStaticDataMember()) {
1836 // Check for explicitly specified attributes.
1837 const_iterator I = begin();
1838 const_iterator EndI = end();
1839 if (FromParent && I != EndI)
1840 ++I;
1841 if (I != EndI) {
1842 auto It = I->SharingMap.find(D);
1843 if (It != I->SharingMap.end()) {
1844 const DSAInfo &Data = It->getSecond();
1845 DVar.RefExpr = Data.RefExpr.getPointer();
1846 DVar.PrivateCopy = Data.PrivateCopy;
1847 DVar.CKind = Data.Attributes;
1848 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1849 DVar.DKind = I->Directive;
1850 DVar.Modifier = Data.Modifier;
1851 DVar.AppliedToPointee = Data.AppliedToPointee;
1852 return DVar;
1856 DVar.CKind = OMPC_shared;
1857 return DVar;
1860 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1861 // The predetermined shared attribute for const-qualified types having no
1862 // mutable members was removed after OpenMP 3.1.
1863 if (SemaRef.LangOpts.OpenMP <= 31) {
1864 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1865 // in a Construct, C/C++, predetermined, p.6]
1866 // Variables with const qualified type having no mutable member are
1867 // shared.
1868 if (isConstNotMutableType(SemaRef, D->getType())) {
1869 // Variables with const-qualified type having no mutable member may be
1870 // listed in a firstprivate clause, even if they are static data members.
1871 DSAVarData DVarTemp = hasInnermostDSA(
1873 [](OpenMPClauseKind C, bool) {
1874 return C == OMPC_firstprivate || C == OMPC_shared;
1876 MatchesAlways, FromParent);
1877 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1878 return DVarTemp;
1880 DVar.CKind = OMPC_shared;
1881 return DVar;
1885 // Explicitly specified attributes and local variables with predetermined
1886 // attributes.
1887 const_iterator I = begin();
1888 const_iterator EndI = end();
1889 if (FromParent && I != EndI)
1890 ++I;
1891 if (I == EndI)
1892 return DVar;
1893 auto It = I->SharingMap.find(D);
1894 if (It != I->SharingMap.end()) {
1895 const DSAInfo &Data = It->getSecond();
1896 DVar.RefExpr = Data.RefExpr.getPointer();
1897 DVar.PrivateCopy = Data.PrivateCopy;
1898 DVar.CKind = Data.Attributes;
1899 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1900 DVar.DKind = I->Directive;
1901 DVar.Modifier = Data.Modifier;
1902 DVar.AppliedToPointee = Data.AppliedToPointee;
1905 return DVar;
1908 const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1909 bool FromParent) const {
1910 if (isStackEmpty()) {
1911 const_iterator I;
1912 return getDSA(I, D);
1914 D = getCanonicalDecl(D);
1915 const_iterator StartI = begin();
1916 const_iterator EndI = end();
1917 if (FromParent && StartI != EndI)
1918 ++StartI;
1919 return getDSA(StartI, D);
1922 const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1923 unsigned Level) const {
1924 if (getStackSize() <= Level)
1925 return DSAVarData();
1926 D = getCanonicalDecl(D);
1927 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
1928 return getDSA(StartI, D);
1931 const DSAStackTy::DSAVarData
1932 DSAStackTy::hasDSA(ValueDecl *D,
1933 const llvm::function_ref<bool(OpenMPClauseKind, bool,
1934 DefaultDataSharingAttributes)>
1935 CPred,
1936 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1937 bool FromParent) const {
1938 if (isStackEmpty())
1939 return {};
1940 D = getCanonicalDecl(D);
1941 const_iterator I = begin();
1942 const_iterator EndI = end();
1943 if (FromParent && I != EndI)
1944 ++I;
1945 for (; I != EndI; ++I) {
1946 if (!DPred(I->Directive) &&
1947 !isImplicitOrExplicitTaskingRegion(I->Directive))
1948 continue;
1949 const_iterator NewI = I;
1950 DSAVarData DVar = getDSA(NewI, D);
1951 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1952 return DVar;
1954 return {};
1957 const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1958 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1959 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1960 bool FromParent) const {
1961 if (isStackEmpty())
1962 return {};
1963 D = getCanonicalDecl(D);
1964 const_iterator StartI = begin();
1965 const_iterator EndI = end();
1966 if (FromParent && StartI != EndI)
1967 ++StartI;
1968 if (StartI == EndI || !DPred(StartI->Directive))
1969 return {};
1970 const_iterator NewI = StartI;
1971 DSAVarData DVar = getDSA(NewI, D);
1972 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
1973 ? DVar
1974 : DSAVarData();
1977 bool DSAStackTy::hasExplicitDSA(
1978 const ValueDecl *D,
1979 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1980 unsigned Level, bool NotLastprivate) const {
1981 if (getStackSize() <= Level)
1982 return false;
1983 D = getCanonicalDecl(D);
1984 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1985 auto I = StackElem.SharingMap.find(D);
1986 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
1987 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
1988 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
1989 return true;
1990 // Check predetermined rules for the loop control variables.
1991 auto LI = StackElem.LCVMap.find(D);
1992 if (LI != StackElem.LCVMap.end())
1993 return CPred(OMPC_private, /*AppliedToPointee=*/false);
1994 return false;
1997 bool DSAStackTy::hasExplicitDirective(
1998 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1999 unsigned Level) const {
2000 if (getStackSize() <= Level)
2001 return false;
2002 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2003 return DPred(StackElem.Directive);
2006 bool DSAStackTy::hasDirective(
2007 const llvm::function_ref<bool(OpenMPDirectiveKind,
2008 const DeclarationNameInfo &, SourceLocation)>
2009 DPred,
2010 bool FromParent) const {
2011 // We look only in the enclosing region.
2012 size_t Skip = FromParent ? 2 : 1;
2013 for (const_iterator I = begin() + std::min(Skip, getStackSize()), E = end();
2014 I != E; ++I) {
2015 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
2016 return true;
2018 return false;
2021 void Sema::InitDataSharingAttributesStack() {
2022 VarDataSharingAttributesStack = new DSAStackTy(*this);
2025 #define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2027 void Sema::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); }
2029 void Sema::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
2030 DSAStack->popFunction(OldFSI);
2033 static bool isOpenMPDeviceDelayedContext(Sema &S) {
2034 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsTargetDevice &&
2035 "Expected OpenMP device compilation.");
2036 return !S.isInOpenMPTargetExecutionDirective();
2039 namespace {
2040 /// Status of the function emission on the host/device.
2041 enum class FunctionEmissionStatus {
2042 Emitted,
2043 Discarded,
2044 Unknown,
2046 } // anonymous namespace
2048 Sema::SemaDiagnosticBuilder
2049 Sema::diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID,
2050 const FunctionDecl *FD) {
2051 assert(LangOpts.OpenMP && LangOpts.OpenMPIsTargetDevice &&
2052 "Expected OpenMP device compilation.");
2054 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2055 if (FD) {
2056 FunctionEmissionStatus FES = getEmissionStatus(FD);
2057 switch (FES) {
2058 case FunctionEmissionStatus::Emitted:
2059 Kind = SemaDiagnosticBuilder::K_Immediate;
2060 break;
2061 case FunctionEmissionStatus::Unknown:
2062 // TODO: We should always delay diagnostics here in case a target
2063 // region is in a function we do not emit. However, as the
2064 // current diagnostics are associated with the function containing
2065 // the target region and we do not emit that one, we would miss out
2066 // on diagnostics for the target region itself. We need to anchor
2067 // the diagnostics with the new generated function *or* ensure we
2068 // emit diagnostics associated with the surrounding function.
2069 Kind = isOpenMPDeviceDelayedContext(*this)
2070 ? SemaDiagnosticBuilder::K_Deferred
2071 : SemaDiagnosticBuilder::K_Immediate;
2072 break;
2073 case FunctionEmissionStatus::TemplateDiscarded:
2074 case FunctionEmissionStatus::OMPDiscarded:
2075 Kind = SemaDiagnosticBuilder::K_Nop;
2076 break;
2077 case FunctionEmissionStatus::CUDADiscarded:
2078 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2079 break;
2083 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, *this);
2086 Sema::SemaDiagnosticBuilder Sema::diagIfOpenMPHostCode(SourceLocation Loc,
2087 unsigned DiagID,
2088 const FunctionDecl *FD) {
2089 assert(LangOpts.OpenMP && !LangOpts.OpenMPIsTargetDevice &&
2090 "Expected OpenMP host compilation.");
2092 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2093 if (FD) {
2094 FunctionEmissionStatus FES = getEmissionStatus(FD);
2095 switch (FES) {
2096 case FunctionEmissionStatus::Emitted:
2097 Kind = SemaDiagnosticBuilder::K_Immediate;
2098 break;
2099 case FunctionEmissionStatus::Unknown:
2100 Kind = SemaDiagnosticBuilder::K_Deferred;
2101 break;
2102 case FunctionEmissionStatus::TemplateDiscarded:
2103 case FunctionEmissionStatus::OMPDiscarded:
2104 case FunctionEmissionStatus::CUDADiscarded:
2105 Kind = SemaDiagnosticBuilder::K_Nop;
2106 break;
2110 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, *this);
2113 static OpenMPDefaultmapClauseKind
2114 getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD) {
2115 if (LO.OpenMP <= 45) {
2116 if (VD->getType().getNonReferenceType()->isScalarType())
2117 return OMPC_DEFAULTMAP_scalar;
2118 return OMPC_DEFAULTMAP_aggregate;
2120 if (VD->getType().getNonReferenceType()->isAnyPointerType())
2121 return OMPC_DEFAULTMAP_pointer;
2122 if (VD->getType().getNonReferenceType()->isScalarType())
2123 return OMPC_DEFAULTMAP_scalar;
2124 return OMPC_DEFAULTMAP_aggregate;
2127 bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
2128 unsigned OpenMPCaptureLevel) const {
2129 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2131 ASTContext &Ctx = getASTContext();
2132 bool IsByRef = true;
2134 // Find the directive that is associated with the provided scope.
2135 D = cast<ValueDecl>(D->getCanonicalDecl());
2136 QualType Ty = D->getType();
2138 bool IsVariableUsedInMapClause = false;
2139 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) {
2140 // This table summarizes how a given variable should be passed to the device
2141 // given its type and the clauses where it appears. This table is based on
2142 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2143 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2145 // =========================================================================
2146 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2147 // | |(tofrom:scalar)| | pvt | |has_dv_adr| |
2148 // =========================================================================
2149 // | scl | | | | - | | bycopy|
2150 // | scl | | - | x | - | - | bycopy|
2151 // | scl | | x | - | - | - | null |
2152 // | scl | x | | | - | | byref |
2153 // | scl | x | - | x | - | - | bycopy|
2154 // | scl | x | x | - | - | - | null |
2155 // | scl | | - | - | - | x | byref |
2156 // | scl | x | - | - | - | x | byref |
2158 // | agg | n.a. | | | - | | byref |
2159 // | agg | n.a. | - | x | - | - | byref |
2160 // | agg | n.a. | x | - | - | - | null |
2161 // | agg | n.a. | - | - | - | x | byref |
2162 // | agg | n.a. | - | - | - | x[] | byref |
2164 // | ptr | n.a. | | | - | | bycopy|
2165 // | ptr | n.a. | - | x | - | - | bycopy|
2166 // | ptr | n.a. | x | - | - | - | null |
2167 // | ptr | n.a. | - | - | - | x | byref |
2168 // | ptr | n.a. | - | - | - | x[] | bycopy|
2169 // | ptr | n.a. | - | - | x | | bycopy|
2170 // | ptr | n.a. | - | - | x | x | bycopy|
2171 // | ptr | n.a. | - | - | x | x[] | bycopy|
2172 // =========================================================================
2173 // Legend:
2174 // scl - scalar
2175 // ptr - pointer
2176 // agg - aggregate
2177 // x - applies
2178 // - - invalid in this combination
2179 // [] - mapped with an array section
2180 // byref - should be mapped by reference
2181 // byval - should be mapped by value
2182 // null - initialize a local variable to null on the device
2184 // Observations:
2185 // - All scalar declarations that show up in a map clause have to be passed
2186 // by reference, because they may have been mapped in the enclosing data
2187 // environment.
2188 // - If the scalar value does not fit the size of uintptr, it has to be
2189 // passed by reference, regardless the result in the table above.
2190 // - For pointers mapped by value that have either an implicit map or an
2191 // array section, the runtime library may pass the NULL value to the
2192 // device instead of the value passed to it by the compiler.
2194 if (Ty->isReferenceType())
2195 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2197 // Locate map clauses and see if the variable being captured is referred to
2198 // in any of those clauses. Here we only care about variables, not fields,
2199 // because fields are part of aggregates.
2200 bool IsVariableAssociatedWithSection = false;
2202 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2203 D, Level,
2204 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2205 D](OMPClauseMappableExprCommon::MappableExprComponentListRef
2206 MapExprComponents,
2207 OpenMPClauseKind WhereFoundClauseKind) {
2208 // Both map and has_device_addr clauses information influences how a
2209 // variable is captured. E.g. is_device_ptr does not require changing
2210 // the default behavior.
2211 if (WhereFoundClauseKind != OMPC_map &&
2212 WhereFoundClauseKind != OMPC_has_device_addr)
2213 return false;
2215 auto EI = MapExprComponents.rbegin();
2216 auto EE = MapExprComponents.rend();
2218 assert(EI != EE && "Invalid map expression!");
2220 if (isa<DeclRefExpr>(EI->getAssociatedExpression()))
2221 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D;
2223 ++EI;
2224 if (EI == EE)
2225 return false;
2226 auto Last = std::prev(EE);
2227 const auto *UO =
2228 dyn_cast<UnaryOperator>(Last->getAssociatedExpression());
2229 if ((UO && UO->getOpcode() == UO_Deref) ||
2230 isa<ArraySubscriptExpr>(Last->getAssociatedExpression()) ||
2231 isa<OMPArraySectionExpr>(Last->getAssociatedExpression()) ||
2232 isa<MemberExpr>(EI->getAssociatedExpression()) ||
2233 isa<OMPArrayShapingExpr>(Last->getAssociatedExpression())) {
2234 IsVariableAssociatedWithSection = true;
2235 // There is nothing more we need to know about this variable.
2236 return true;
2239 // Keep looking for more map info.
2240 return false;
2243 if (IsVariableUsedInMapClause) {
2244 // If variable is identified in a map clause it is always captured by
2245 // reference except if it is a pointer that is dereferenced somehow.
2246 IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2247 } else {
2248 // By default, all the data that has a scalar type is mapped by copy
2249 // (except for reduction variables).
2250 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2251 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2252 !Ty->isAnyPointerType()) ||
2253 !Ty->isScalarType() ||
2254 DSAStack->isDefaultmapCapturedByRef(
2255 Level, getVariableCategoryFromDecl(LangOpts, D)) ||
2256 DSAStack->hasExplicitDSA(
2258 [](OpenMPClauseKind K, bool AppliedToPointee) {
2259 return K == OMPC_reduction && !AppliedToPointee;
2261 Level);
2265 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2266 IsByRef =
2267 ((IsVariableUsedInMapClause &&
2268 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2269 OMPD_target) ||
2270 !(DSAStack->hasExplicitDSA(
2272 [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2273 return K == OMPC_firstprivate ||
2274 (K == OMPC_reduction && AppliedToPointee);
2276 Level, /*NotLastprivate=*/true) ||
2277 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2278 // If the variable is artificial and must be captured by value - try to
2279 // capture by value.
2280 !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2281 !cast<OMPCapturedExprDecl>(D)->getInit()->isGLValue()) &&
2282 // If the variable is implicitly firstprivate and scalar - capture by
2283 // copy
2284 !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2285 DSAStack->getDefaultDSA() == DSA_private) &&
2286 !DSAStack->hasExplicitDSA(
2287 D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2288 Level) &&
2289 !DSAStack->isLoopControlVariable(D, Level).first);
2292 // When passing data by copy, we need to make sure it fits the uintptr size
2293 // and alignment, because the runtime library only deals with uintptr types.
2294 // If it does not fit the uintptr size, we need to pass the data by reference
2295 // instead.
2296 if (!IsByRef && (Ctx.getTypeSizeInChars(Ty) >
2297 Ctx.getTypeSizeInChars(Ctx.getUIntPtrType()) ||
2298 Ctx.getAlignOfGlobalVarInChars(Ty) >
2299 Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) {
2300 IsByRef = true;
2303 return IsByRef;
2306 unsigned Sema::getOpenMPNestingLevel() const {
2307 assert(getLangOpts().OpenMP);
2308 return DSAStack->getNestingLevel();
2311 bool Sema::isInOpenMPTaskUntiedContext() const {
2312 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2313 DSAStack->isUntiedRegion();
2316 bool Sema::isInOpenMPTargetExecutionDirective() const {
2317 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2318 !DSAStack->isClauseParsingMode()) ||
2319 DSAStack->hasDirective(
2320 [](OpenMPDirectiveKind K, const DeclarationNameInfo &,
2321 SourceLocation) -> bool {
2322 return isOpenMPTargetExecutionDirective(K);
2324 false);
2327 bool Sema::isOpenMPRebuildMemberExpr(ValueDecl *D) {
2328 // Only rebuild for Field.
2329 if (!dyn_cast<FieldDecl>(D))
2330 return false;
2331 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2333 [](OpenMPClauseKind C, bool AppliedToPointee,
2334 DefaultDataSharingAttributes DefaultAttr) {
2335 return isOpenMPPrivate(C) && !AppliedToPointee &&
2336 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2338 [](OpenMPDirectiveKind) { return true; },
2339 DSAStack->isClauseParsingMode());
2340 if (DVarPrivate.CKind != OMPC_unknown)
2341 return true;
2342 return false;
2345 static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
2346 Expr *CaptureExpr, bool WithInit,
2347 DeclContext *CurContext,
2348 bool AsExpression);
2350 VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo,
2351 unsigned StopAt) {
2352 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2353 D = getCanonicalDecl(D);
2355 auto *VD = dyn_cast<VarDecl>(D);
2356 // Do not capture constexpr variables.
2357 if (VD && VD->isConstexpr())
2358 return nullptr;
2360 // If we want to determine whether the variable should be captured from the
2361 // perspective of the current capturing scope, and we've already left all the
2362 // capturing scopes of the top directive on the stack, check from the
2363 // perspective of its parent directive (if any) instead.
2364 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2365 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2367 // If we are attempting to capture a global variable in a directive with
2368 // 'target' we return true so that this global is also mapped to the device.
2370 if (VD && !VD->hasLocalStorage() &&
2371 (getCurCapturedRegion() || getCurBlock() || getCurLambda())) {
2372 if (isInOpenMPTargetExecutionDirective()) {
2373 DSAStackTy::DSAVarData DVarTop =
2374 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2375 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2376 return VD;
2377 // If the declaration is enclosed in a 'declare target' directive,
2378 // then it should not be captured.
2380 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2381 return nullptr;
2382 CapturedRegionScopeInfo *CSI = nullptr;
2383 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2384 llvm::reverse(FunctionScopes),
2385 CheckScopeInfo ? (FunctionScopes.size() - (StopAt + 1)) : 0)) {
2386 if (!isa<CapturingScopeInfo>(FSI))
2387 return nullptr;
2388 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2389 if (RSI->CapRegionKind == CR_OpenMP) {
2390 CSI = RSI;
2391 break;
2394 assert(CSI && "Failed to find CapturedRegionScopeInfo");
2395 SmallVector<OpenMPDirectiveKind, 4> Regions;
2396 getOpenMPCaptureRegions(Regions,
2397 DSAStack->getDirective(CSI->OpenMPLevel));
2398 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2399 return VD;
2401 if (isInOpenMPDeclareTargetContext()) {
2402 // Try to mark variable as declare target if it is used in capturing
2403 // regions.
2404 if (LangOpts.OpenMP <= 45 &&
2405 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2406 checkDeclIsAllowedInOpenMPTarget(nullptr, VD);
2407 return nullptr;
2411 if (CheckScopeInfo) {
2412 bool OpenMPFound = false;
2413 for (unsigned I = StopAt + 1; I > 0; --I) {
2414 FunctionScopeInfo *FSI = FunctionScopes[I - 1];
2415 if (!isa<CapturingScopeInfo>(FSI))
2416 return nullptr;
2417 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2418 if (RSI->CapRegionKind == CR_OpenMP) {
2419 OpenMPFound = true;
2420 break;
2423 if (!OpenMPFound)
2424 return nullptr;
2427 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2428 (!DSAStack->isClauseParsingMode() ||
2429 DSAStack->getParentDirective() != OMPD_unknown)) {
2430 auto &&Info = DSAStack->isLoopControlVariable(D);
2431 if (Info.first ||
2432 (VD && VD->hasLocalStorage() &&
2433 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2434 (VD && DSAStack->isForceVarCapturing()))
2435 return VD ? VD : Info.second;
2436 DSAStackTy::DSAVarData DVarTop =
2437 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2438 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) &&
2439 (!VD || VD->hasLocalStorage() || !DVarTop.AppliedToPointee))
2440 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2441 // Threadprivate variables must not be captured.
2442 if (isOpenMPThreadPrivate(DVarTop.CKind))
2443 return nullptr;
2444 // The variable is not private or it is the variable in the directive with
2445 // default(none) clause and not used in any clause.
2446 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2448 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2449 return isOpenMPPrivate(C) && !AppliedToPointee;
2451 [](OpenMPDirectiveKind) { return true; },
2452 DSAStack->isClauseParsingMode());
2453 // Global shared must not be captured.
2454 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2455 ((DSAStack->getDefaultDSA() != DSA_none &&
2456 DSAStack->getDefaultDSA() != DSA_private &&
2457 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2458 DVarTop.CKind == OMPC_shared))
2459 return nullptr;
2460 auto *FD = dyn_cast<FieldDecl>(D);
2461 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2462 !DVarPrivate.PrivateCopy) {
2463 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2465 [](OpenMPClauseKind C, bool AppliedToPointee,
2466 DefaultDataSharingAttributes DefaultAttr) {
2467 return isOpenMPPrivate(C) && !AppliedToPointee &&
2468 (DefaultAttr == DSA_firstprivate ||
2469 DefaultAttr == DSA_private);
2471 [](OpenMPDirectiveKind) { return true; },
2472 DSAStack->isClauseParsingMode());
2473 if (DVarPrivate.CKind == OMPC_unknown)
2474 return nullptr;
2476 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2477 if (VD)
2478 return VD;
2479 if (getCurrentThisType().isNull())
2480 return nullptr;
2481 Expr *ThisExpr = BuildCXXThisExpr(SourceLocation(), getCurrentThisType(),
2482 /*IsImplicit=*/true);
2483 const CXXScopeSpec CS = CXXScopeSpec();
2484 Expr *ME = BuildMemberExpr(ThisExpr, /*IsArrow=*/true, SourceLocation(),
2485 NestedNameSpecifierLoc(), SourceLocation(), FD,
2486 DeclAccessPair::make(FD, FD->getAccess()),
2487 /*HadMultipleCandidates=*/false,
2488 DeclarationNameInfo(), FD->getType(),
2489 VK_LValue, OK_Ordinary);
2490 OMPCapturedExprDecl *CD = buildCaptureDecl(
2491 *this, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private,
2492 CurContext->getParent(), /*AsExpression=*/false);
2493 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2494 *this, CD, CD->getType().getNonReferenceType(), SourceLocation());
2495 VD = cast<VarDecl>(VDPrivateRefExpr->getDecl());
2496 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2497 return VD;
2499 if (DVarPrivate.CKind != OMPC_unknown ||
2500 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2501 DSAStack->getDefaultDSA() == DSA_private ||
2502 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2503 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2505 return nullptr;
2508 void Sema::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2509 unsigned Level) const {
2510 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2513 void Sema::startOpenMPLoop() {
2514 assert(LangOpts.OpenMP && "OpenMP must be enabled.");
2515 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2516 DSAStack->loopInit();
2519 void Sema::startOpenMPCXXRangeFor() {
2520 assert(LangOpts.OpenMP && "OpenMP must be enabled.");
2521 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2522 DSAStack->resetPossibleLoopCounter();
2523 DSAStack->loopStart();
2527 OpenMPClauseKind Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level,
2528 unsigned CapLevel) const {
2529 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2530 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2531 (!DSAStack->isClauseParsingMode() ||
2532 DSAStack->getParentDirective() != OMPD_unknown)) {
2533 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2535 [](OpenMPClauseKind C, bool AppliedToPointee,
2536 DefaultDataSharingAttributes DefaultAttr) {
2537 return isOpenMPPrivate(C) && !AppliedToPointee &&
2538 DefaultAttr == DSA_private;
2540 [](OpenMPDirectiveKind) { return true; },
2541 DSAStack->isClauseParsingMode());
2542 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) &&
2543 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) &&
2544 !DSAStack->isLoopControlVariable(D).first)
2545 return OMPC_private;
2547 if (DSAStack->hasExplicitDirective(isOpenMPTaskingDirective, Level)) {
2548 bool IsTriviallyCopyable =
2549 D->getType().getNonReferenceType().isTriviallyCopyableType(Context) &&
2550 !D->getType()
2551 .getNonReferenceType()
2552 .getCanonicalType()
2553 ->getAsCXXRecordDecl();
2554 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2555 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
2556 getOpenMPCaptureRegions(CaptureRegions, DKind);
2557 if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) &&
2558 (IsTriviallyCopyable ||
2559 !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) {
2560 if (DSAStack->hasExplicitDSA(
2562 [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2563 Level, /*NotLastprivate=*/true))
2564 return OMPC_firstprivate;
2565 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2566 if (DVar.CKind != OMPC_shared &&
2567 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2568 DSAStack->addImplicitTaskFirstprivate(Level, D);
2569 return OMPC_firstprivate;
2573 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) &&
2574 !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) {
2575 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2576 DSAStack->resetPossibleLoopCounter(D);
2577 DSAStack->loopStart();
2578 return OMPC_private;
2580 if ((DSAStack->getPossiblyLoopCunter() == D->getCanonicalDecl() ||
2581 DSAStack->isLoopControlVariable(D).first) &&
2582 !DSAStack->hasExplicitDSA(
2583 D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2584 Level) &&
2585 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2586 return OMPC_private;
2588 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2589 if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
2590 DSAStack->isForceVarCapturing() &&
2591 !DSAStack->hasExplicitDSA(
2592 D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2593 Level))
2594 return OMPC_private;
2596 // User-defined allocators are private since they must be defined in the
2597 // context of target region.
2598 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) &&
2599 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2600 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2601 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2602 return OMPC_private;
2603 return (DSAStack->hasExplicitDSA(
2604 D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2605 Level) ||
2606 (DSAStack->isClauseParsingMode() &&
2607 DSAStack->getClauseParsingMode() == OMPC_private) ||
2608 // Consider taskgroup reduction descriptor variable a private
2609 // to avoid possible capture in the region.
2610 (DSAStack->hasExplicitDirective(
2611 [](OpenMPDirectiveKind K) {
2612 return K == OMPD_taskgroup ||
2613 ((isOpenMPParallelDirective(K) ||
2614 isOpenMPWorksharingDirective(K)) &&
2615 !isOpenMPSimdDirective(K));
2617 Level) &&
2618 DSAStack->isTaskgroupReductionRef(D, Level)))
2619 ? OMPC_private
2620 : OMPC_unknown;
2623 void Sema::setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D,
2624 unsigned Level) {
2625 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2626 D = getCanonicalDecl(D);
2627 OpenMPClauseKind OMPC = OMPC_unknown;
2628 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2629 const unsigned NewLevel = I - 1;
2630 if (DSAStack->hasExplicitDSA(
2632 [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2633 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2634 OMPC = K;
2635 return true;
2637 return false;
2639 NewLevel))
2640 break;
2641 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2642 D, NewLevel,
2643 [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
2644 OpenMPClauseKind) { return true; })) {
2645 OMPC = OMPC_map;
2646 break;
2648 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2649 NewLevel)) {
2650 OMPC = OMPC_map;
2651 if (DSAStack->mustBeFirstprivateAtLevel(
2652 NewLevel, getVariableCategoryFromDecl(LangOpts, D)))
2653 OMPC = OMPC_firstprivate;
2654 break;
2657 if (OMPC != OMPC_unknown)
2658 FD->addAttr(OMPCaptureKindAttr::CreateImplicit(Context, unsigned(OMPC)));
2661 bool Sema::isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level,
2662 unsigned CaptureLevel) const {
2663 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2664 // Return true if the current level is no longer enclosed in a target region.
2666 SmallVector<OpenMPDirectiveKind, 4> Regions;
2667 getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level));
2668 const auto *VD = dyn_cast<VarDecl>(D);
2669 return VD && !VD->hasLocalStorage() &&
2670 DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2671 Level) &&
2672 Regions[CaptureLevel] != OMPD_task;
2675 bool Sema::isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level,
2676 unsigned CaptureLevel) const {
2677 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2678 // Return true if the current level is no longer enclosed in a target region.
2680 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2681 if (!VD->hasLocalStorage()) {
2682 if (isInOpenMPTargetExecutionDirective())
2683 return true;
2684 DSAStackTy::DSAVarData TopDVar =
2685 DSAStack->getTopDSA(D, /*FromParent=*/false);
2686 unsigned NumLevels =
2687 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2688 if (Level == 0)
2689 // non-file scope static variale with default(firstprivate)
2690 // should be gloabal captured.
2691 return (NumLevels == CaptureLevel + 1 &&
2692 (TopDVar.CKind != OMPC_shared ||
2693 DSAStack->getDefaultDSA() == DSA_firstprivate));
2694 do {
2695 --Level;
2696 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2697 if (DVar.CKind != OMPC_shared)
2698 return true;
2699 } while (Level > 0);
2702 return true;
2705 void Sema::DestroyDataSharingAttributesStack() { delete DSAStack; }
2707 void Sema::ActOnOpenMPBeginDeclareVariant(SourceLocation Loc,
2708 OMPTraitInfo &TI) {
2709 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2712 void Sema::ActOnOpenMPEndDeclareVariant() {
2713 assert(isInOpenMPDeclareVariantScope() &&
2714 "Not in OpenMP declare variant scope!");
2716 OMPDeclareVariantScopes.pop_back();
2719 void Sema::finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller,
2720 const FunctionDecl *Callee,
2721 SourceLocation Loc) {
2722 assert(LangOpts.OpenMP && "Expected OpenMP compilation mode.");
2723 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2724 OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
2725 // Ignore host functions during device analyzis.
2726 if (LangOpts.OpenMPIsTargetDevice &&
2727 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2728 return;
2729 // Ignore nohost functions during host analyzis.
2730 if (!LangOpts.OpenMPIsTargetDevice && DevTy &&
2731 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2732 return;
2733 const FunctionDecl *FD = Callee->getMostRecentDecl();
2734 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2735 if (LangOpts.OpenMPIsTargetDevice && DevTy &&
2736 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2737 // Diagnose host function called during device codegen.
2738 StringRef HostDevTy =
2739 getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
2740 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2741 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2742 diag::note_omp_marked_device_type_here)
2743 << HostDevTy;
2744 return;
2746 if (!LangOpts.OpenMPIsTargetDevice && !LangOpts.OpenMPOffloadMandatory &&
2747 DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2748 // In OpenMP 5.2 or later, if the function has a host variant then allow
2749 // that to be called instead
2750 auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2751 for (OMPDeclareVariantAttr *A :
2752 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2753 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2754 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2755 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2756 OMPDeclareTargetDeclAttr::getDeviceType(
2757 VariantFD->getMostRecentDecl());
2758 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2759 return true;
2761 return false;
2763 if (getLangOpts().OpenMP >= 52 &&
2764 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2765 return;
2766 // Diagnose nohost function called during host codegen.
2767 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2768 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2769 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2770 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2771 diag::note_omp_marked_device_type_here)
2772 << NoHostDevTy;
2776 void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
2777 const DeclarationNameInfo &DirName,
2778 Scope *CurScope, SourceLocation Loc) {
2779 DSAStack->push(DKind, DirName, CurScope, Loc);
2780 PushExpressionEvaluationContext(
2781 ExpressionEvaluationContext::PotentiallyEvaluated);
2784 void Sema::StartOpenMPClause(OpenMPClauseKind K) {
2785 DSAStack->setClauseParsingMode(K);
2788 void Sema::EndOpenMPClause() {
2789 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2790 CleanupVarDeclMarking();
2793 static std::pair<ValueDecl *, bool>
2794 getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2795 SourceRange &ERange, bool AllowArraySection = false,
2796 StringRef DiagType = "");
2798 /// Check consistency of the reduction clauses.
2799 static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2800 ArrayRef<OMPClause *> Clauses) {
2801 bool InscanFound = false;
2802 SourceLocation InscanLoc;
2803 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2804 // A reduction clause without the inscan reduction-modifier may not appear on
2805 // a construct on which a reduction clause with the inscan reduction-modifier
2806 // appears.
2807 for (OMPClause *C : Clauses) {
2808 if (C->getClauseKind() != OMPC_reduction)
2809 continue;
2810 auto *RC = cast<OMPReductionClause>(C);
2811 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2812 InscanFound = true;
2813 InscanLoc = RC->getModifierLoc();
2814 continue;
2816 if (RC->getModifier() == OMPC_REDUCTION_task) {
2817 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2818 // A reduction clause with the task reduction-modifier may only appear on
2819 // a parallel construct, a worksharing construct or a combined or
2820 // composite construct for which any of the aforementioned constructs is a
2821 // constituent construct and simd or loop are not constituent constructs.
2822 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2823 if (!(isOpenMPParallelDirective(CurDir) ||
2824 isOpenMPWorksharingDirective(CurDir)) ||
2825 isOpenMPSimdDirective(CurDir))
2826 S.Diag(RC->getModifierLoc(),
2827 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2828 continue;
2831 if (InscanFound) {
2832 for (OMPClause *C : Clauses) {
2833 if (C->getClauseKind() != OMPC_reduction)
2834 continue;
2835 auto *RC = cast<OMPReductionClause>(C);
2836 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2837 S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2838 ? RC->getBeginLoc()
2839 : RC->getModifierLoc(),
2840 diag::err_omp_inscan_reduction_expected);
2841 S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2842 continue;
2844 for (Expr *Ref : RC->varlists()) {
2845 assert(Ref && "NULL expr in OpenMP nontemporal clause.");
2846 SourceLocation ELoc;
2847 SourceRange ERange;
2848 Expr *SimpleRefExpr = Ref;
2849 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2850 /*AllowArraySection=*/true);
2851 ValueDecl *D = Res.first;
2852 if (!D)
2853 continue;
2854 if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2855 S.Diag(Ref->getExprLoc(),
2856 diag::err_omp_reduction_not_inclusive_exclusive)
2857 << Ref->getSourceRange();
2864 static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2865 ArrayRef<OMPClause *> Clauses);
2866 static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2867 bool WithInit);
2869 static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2870 const ValueDecl *D,
2871 const DSAStackTy::DSAVarData &DVar,
2872 bool IsLoopIterVar = false);
2874 void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
2875 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2876 // A variable of class type (or array thereof) that appears in a lastprivate
2877 // clause requires an accessible, unambiguous default constructor for the
2878 // class type, unless the list item is also specified in a firstprivate
2879 // clause.
2880 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
2881 for (OMPClause *C : D->clauses()) {
2882 if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
2883 SmallVector<Expr *, 8> PrivateCopies;
2884 for (Expr *DE : Clause->varlists()) {
2885 if (DE->isValueDependent() || DE->isTypeDependent()) {
2886 PrivateCopies.push_back(nullptr);
2887 continue;
2889 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2890 auto *VD = cast<VarDecl>(DRE->getDecl());
2891 QualType Type = VD->getType().getNonReferenceType();
2892 const DSAStackTy::DSAVarData DVar =
2893 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2894 if (DVar.CKind == OMPC_lastprivate) {
2895 // Generate helper private variable and initialize it with the
2896 // default value. The address of the original variable is replaced
2897 // by the address of the new private variable in CodeGen. This new
2898 // variable is not added to IdResolver, so the code in the OpenMP
2899 // region uses original variable for proper diagnostics.
2900 VarDecl *VDPrivate = buildVarDecl(
2901 *this, DE->getExprLoc(), Type.getUnqualifiedType(),
2902 VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
2903 ActOnUninitializedDecl(VDPrivate);
2904 if (VDPrivate->isInvalidDecl()) {
2905 PrivateCopies.push_back(nullptr);
2906 continue;
2908 PrivateCopies.push_back(buildDeclRefExpr(
2909 *this, VDPrivate, DE->getType(), DE->getExprLoc()));
2910 } else {
2911 // The variable is also a firstprivate, so initialization sequence
2912 // for private copy is generated already.
2913 PrivateCopies.push_back(nullptr);
2916 Clause->setPrivateCopies(PrivateCopies);
2917 continue;
2919 // Finalize nontemporal clause by handling private copies, if any.
2920 if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) {
2921 SmallVector<Expr *, 8> PrivateRefs;
2922 for (Expr *RefExpr : Clause->varlists()) {
2923 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
2924 SourceLocation ELoc;
2925 SourceRange ERange;
2926 Expr *SimpleRefExpr = RefExpr;
2927 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
2928 if (Res.second)
2929 // It will be analyzed later.
2930 PrivateRefs.push_back(RefExpr);
2931 ValueDecl *D = Res.first;
2932 if (!D)
2933 continue;
2935 const DSAStackTy::DSAVarData DVar =
2936 DSAStack->getTopDSA(D, /*FromParent=*/false);
2937 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2938 : SimpleRefExpr);
2940 Clause->setPrivateRefs(PrivateRefs);
2941 continue;
2943 if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) {
2944 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
2945 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
2946 auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts());
2947 if (!DRE)
2948 continue;
2949 ValueDecl *VD = DRE->getDecl();
2950 if (!VD || !isa<VarDecl>(VD))
2951 continue;
2952 DSAStackTy::DSAVarData DVar =
2953 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2954 // OpenMP [2.12.5, target Construct]
2955 // Memory allocators that appear in a uses_allocators clause cannot
2956 // appear in other data-sharing attribute clauses or data-mapping
2957 // attribute clauses in the same construct.
2958 Expr *MapExpr = nullptr;
2959 if (DVar.RefExpr ||
2960 DSAStack->checkMappableExprComponentListsForDecl(
2961 VD, /*CurrentRegionOnly=*/true,
2962 [VD, &MapExpr](
2963 OMPClauseMappableExprCommon::MappableExprComponentListRef
2964 MapExprComponents,
2965 OpenMPClauseKind C) {
2966 auto MI = MapExprComponents.rbegin();
2967 auto ME = MapExprComponents.rend();
2968 if (MI != ME &&
2969 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
2970 VD->getCanonicalDecl()) {
2971 MapExpr = MI->getAssociatedExpression();
2972 return true;
2974 return false;
2975 })) {
2976 Diag(D.Allocator->getExprLoc(),
2977 diag::err_omp_allocator_used_in_clauses)
2978 << D.Allocator->getSourceRange();
2979 if (DVar.RefExpr)
2980 reportOriginalDsa(*this, DSAStack, VD, DVar);
2981 else
2982 Diag(MapExpr->getExprLoc(), diag::note_used_here)
2983 << MapExpr->getSourceRange();
2986 continue;
2989 // Check allocate clauses.
2990 if (!CurContext->isDependentContext())
2991 checkAllocateClauses(*this, DSAStack, D->clauses());
2992 checkReductionClauses(*this, DSAStack, D->clauses());
2995 DSAStack->pop();
2996 DiscardCleanupsInEvaluationContext();
2997 PopExpressionEvaluationContext();
3000 static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
3001 Expr *NumIterations, Sema &SemaRef,
3002 Scope *S, DSAStackTy *Stack);
3004 namespace {
3006 class VarDeclFilterCCC final : public CorrectionCandidateCallback {
3007 private:
3008 Sema &SemaRef;
3010 public:
3011 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3012 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3013 NamedDecl *ND = Candidate.getCorrectionDecl();
3014 if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3015 return VD->hasGlobalStorage() &&
3016 SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3017 SemaRef.getCurScope());
3019 return false;
3022 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3023 return std::make_unique<VarDeclFilterCCC>(*this);
3027 class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3028 private:
3029 Sema &SemaRef;
3031 public:
3032 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3033 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3034 NamedDecl *ND = Candidate.getCorrectionDecl();
3035 if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
3036 isa<FunctionDecl>(ND))) {
3037 return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3038 SemaRef.getCurScope());
3040 return false;
3043 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3044 return std::make_unique<VarOrFuncDeclFilterCCC>(*this);
3048 } // namespace
3050 ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
3051 CXXScopeSpec &ScopeSpec,
3052 const DeclarationNameInfo &Id,
3053 OpenMPDirectiveKind Kind) {
3054 LookupResult Lookup(*this, Id, LookupOrdinaryName);
3055 LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
3057 if (Lookup.isAmbiguous())
3058 return ExprError();
3060 VarDecl *VD;
3061 if (!Lookup.isSingleResult()) {
3062 VarDeclFilterCCC CCC(*this);
3063 if (TypoCorrection Corrected =
3064 CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr, CCC,
3065 CTK_ErrorRecovery)) {
3066 diagnoseTypo(Corrected,
3067 PDiag(Lookup.empty()
3068 ? diag::err_undeclared_var_use_suggest
3069 : diag::err_omp_expected_var_arg_suggest)
3070 << Id.getName());
3071 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3072 } else {
3073 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
3074 : diag::err_omp_expected_var_arg)
3075 << Id.getName();
3076 return ExprError();
3078 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3079 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3080 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3081 return ExprError();
3083 Lookup.suppressDiagnostics();
3085 // OpenMP [2.9.2, Syntax, C/C++]
3086 // Variables must be file-scope, namespace-scope, or static block-scope.
3087 if (Kind == OMPD_threadprivate && !VD->hasGlobalStorage()) {
3088 Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3089 << getOpenMPDirectiveName(Kind) << !VD->isStaticLocal();
3090 bool IsDecl =
3091 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3092 Diag(VD->getLocation(),
3093 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3094 << VD;
3095 return ExprError();
3098 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3099 NamedDecl *ND = CanonicalVD;
3100 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3101 // A threadprivate directive for file-scope variables must appear outside
3102 // any definition or declaration.
3103 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3104 !getCurLexicalContext()->isTranslationUnit()) {
3105 Diag(Id.getLoc(), diag::err_omp_var_scope)
3106 << getOpenMPDirectiveName(Kind) << VD;
3107 bool IsDecl =
3108 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3109 Diag(VD->getLocation(),
3110 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3111 << VD;
3112 return ExprError();
3114 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3115 // A threadprivate directive for static class member variables must appear
3116 // in the class definition, in the same scope in which the member
3117 // variables are declared.
3118 if (CanonicalVD->isStaticDataMember() &&
3119 !CanonicalVD->getDeclContext()->Equals(getCurLexicalContext())) {
3120 Diag(Id.getLoc(), diag::err_omp_var_scope)
3121 << getOpenMPDirectiveName(Kind) << VD;
3122 bool IsDecl =
3123 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3124 Diag(VD->getLocation(),
3125 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3126 << VD;
3127 return ExprError();
3129 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3130 // A threadprivate directive for namespace-scope variables must appear
3131 // outside any definition or declaration other than the namespace
3132 // definition itself.
3133 if (CanonicalVD->getDeclContext()->isNamespace() &&
3134 (!getCurLexicalContext()->isFileContext() ||
3135 !getCurLexicalContext()->Encloses(CanonicalVD->getDeclContext()))) {
3136 Diag(Id.getLoc(), diag::err_omp_var_scope)
3137 << getOpenMPDirectiveName(Kind) << VD;
3138 bool IsDecl =
3139 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3140 Diag(VD->getLocation(),
3141 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3142 << VD;
3143 return ExprError();
3145 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3146 // A threadprivate directive for static block-scope variables must appear
3147 // in the scope of the variable and not in a nested scope.
3148 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3149 !isDeclInScope(ND, getCurLexicalContext(), CurScope)) {
3150 Diag(Id.getLoc(), diag::err_omp_var_scope)
3151 << getOpenMPDirectiveName(Kind) << VD;
3152 bool IsDecl =
3153 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3154 Diag(VD->getLocation(),
3155 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3156 << VD;
3157 return ExprError();
3160 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3161 // A threadprivate directive must lexically precede all references to any
3162 // of the variables in its list.
3163 if (Kind == OMPD_threadprivate && VD->isUsed() &&
3164 !DSAStack->isThreadPrivate(VD)) {
3165 Diag(Id.getLoc(), diag::err_omp_var_used)
3166 << getOpenMPDirectiveName(Kind) << VD;
3167 return ExprError();
3170 QualType ExprType = VD->getType().getNonReferenceType();
3171 return DeclRefExpr::Create(Context, NestedNameSpecifierLoc(),
3172 SourceLocation(), VD,
3173 /*RefersToEnclosingVariableOrCapture=*/false,
3174 Id.getLoc(), ExprType, VK_LValue);
3177 Sema::DeclGroupPtrTy
3178 Sema::ActOnOpenMPThreadprivateDirective(SourceLocation Loc,
3179 ArrayRef<Expr *> VarList) {
3180 if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
3181 CurContext->addDecl(D);
3182 return DeclGroupPtrTy::make(DeclGroupRef(D));
3184 return nullptr;
3187 namespace {
3188 class LocalVarRefChecker final
3189 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3190 Sema &SemaRef;
3192 public:
3193 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3194 if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3195 if (VD->hasLocalStorage()) {
3196 SemaRef.Diag(E->getBeginLoc(),
3197 diag::err_omp_local_var_in_threadprivate_init)
3198 << E->getSourceRange();
3199 SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3200 << VD << VD->getSourceRange();
3201 return true;
3204 return false;
3206 bool VisitStmt(const Stmt *S) {
3207 for (const Stmt *Child : S->children()) {
3208 if (Child && Visit(Child))
3209 return true;
3211 return false;
3213 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3215 } // namespace
3217 OMPThreadPrivateDecl *
3218 Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) {
3219 SmallVector<Expr *, 8> Vars;
3220 for (Expr *RefExpr : VarList) {
3221 auto *DE = cast<DeclRefExpr>(RefExpr);
3222 auto *VD = cast<VarDecl>(DE->getDecl());
3223 SourceLocation ILoc = DE->getExprLoc();
3225 // Mark variable as used.
3226 VD->setReferenced();
3227 VD->markUsed(Context);
3229 QualType QType = VD->getType();
3230 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3231 // It will be analyzed later.
3232 Vars.push_back(DE);
3233 continue;
3236 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3237 // A threadprivate variable must not have an incomplete type.
3238 if (RequireCompleteType(ILoc, VD->getType(),
3239 diag::err_omp_threadprivate_incomplete_type)) {
3240 continue;
3243 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3244 // A threadprivate variable must not have a reference type.
3245 if (VD->getType()->isReferenceType()) {
3246 Diag(ILoc, diag::err_omp_ref_type_arg)
3247 << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType();
3248 bool IsDecl =
3249 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3250 Diag(VD->getLocation(),
3251 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3252 << VD;
3253 continue;
3256 // Check if this is a TLS variable. If TLS is not being supported, produce
3257 // the corresponding diagnostic.
3258 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3259 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3260 getLangOpts().OpenMPUseTLS &&
3261 getASTContext().getTargetInfo().isTLSSupported())) ||
3262 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3263 !VD->isLocalVarDecl())) {
3264 Diag(ILoc, diag::err_omp_var_thread_local)
3265 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3266 bool IsDecl =
3267 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3268 Diag(VD->getLocation(),
3269 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3270 << VD;
3271 continue;
3274 // Check if initial value of threadprivate variable reference variable with
3275 // local storage (it is not supported by runtime).
3276 if (const Expr *Init = VD->getAnyInitializer()) {
3277 LocalVarRefChecker Checker(*this);
3278 if (Checker.Visit(Init))
3279 continue;
3282 Vars.push_back(RefExpr);
3283 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3284 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3285 Context, SourceRange(Loc, Loc)));
3286 if (ASTMutationListener *ML = Context.getASTMutationListener())
3287 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3289 OMPThreadPrivateDecl *D = nullptr;
3290 if (!Vars.empty()) {
3291 D = OMPThreadPrivateDecl::Create(Context, getCurLexicalContext(), Loc,
3292 Vars);
3293 D->setAccess(AS_public);
3295 return D;
3298 static OMPAllocateDeclAttr::AllocatorTypeTy
3299 getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3300 if (!Allocator)
3301 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3302 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3303 Allocator->isInstantiationDependent() ||
3304 Allocator->containsUnexpandedParameterPack())
3305 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3306 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3307 llvm::FoldingSetNodeID AEId;
3308 const Expr *AE = Allocator->IgnoreParenImpCasts();
3309 AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3310 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3311 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3312 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3313 llvm::FoldingSetNodeID DAEId;
3314 DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(),
3315 /*Canonical=*/true);
3316 if (AEId == DAEId) {
3317 AllocatorKindRes = AllocatorKind;
3318 break;
3321 return AllocatorKindRes;
3324 static bool checkPreviousOMPAllocateAttribute(
3325 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3326 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3327 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3328 return false;
3329 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3330 Expr *PrevAllocator = A->getAllocator();
3331 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3332 getAllocatorKind(S, Stack, PrevAllocator);
3333 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3334 if (AllocatorsMatch &&
3335 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3336 Allocator && PrevAllocator) {
3337 const Expr *AE = Allocator->IgnoreParenImpCasts();
3338 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3339 llvm::FoldingSetNodeID AEId, PAEId;
3340 AE->Profile(AEId, S.Context, /*Canonical=*/true);
3341 PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3342 AllocatorsMatch = AEId == PAEId;
3344 if (!AllocatorsMatch) {
3345 SmallString<256> AllocatorBuffer;
3346 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3347 if (Allocator)
3348 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3349 SmallString<256> PrevAllocatorBuffer;
3350 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3351 if (PrevAllocator)
3352 PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3353 S.getPrintingPolicy());
3355 SourceLocation AllocatorLoc =
3356 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3357 SourceRange AllocatorRange =
3358 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3359 SourceLocation PrevAllocatorLoc =
3360 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3361 SourceRange PrevAllocatorRange =
3362 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3363 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3364 << (Allocator ? 1 : 0) << AllocatorStream.str()
3365 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3366 << AllocatorRange;
3367 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3368 << PrevAllocatorRange;
3369 return true;
3371 return false;
3374 static void
3375 applyOMPAllocateAttribute(Sema &S, VarDecl *VD,
3376 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3377 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3378 if (VD->hasAttr<OMPAllocateDeclAttr>())
3379 return;
3380 if (Alignment &&
3381 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3382 Alignment->isInstantiationDependent() ||
3383 Alignment->containsUnexpandedParameterPack()))
3384 // Apply later when we have a usable value.
3385 return;
3386 if (Allocator &&
3387 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3388 Allocator->isInstantiationDependent() ||
3389 Allocator->containsUnexpandedParameterPack()))
3390 return;
3391 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3392 Allocator, Alignment, SR);
3393 VD->addAttr(A);
3394 if (ASTMutationListener *ML = S.Context.getASTMutationListener())
3395 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3398 Sema::DeclGroupPtrTy
3399 Sema::ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef<Expr *> VarList,
3400 ArrayRef<OMPClause *> Clauses,
3401 DeclContext *Owner) {
3402 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3403 Expr *Alignment = nullptr;
3404 Expr *Allocator = nullptr;
3405 if (Clauses.empty()) {
3406 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3407 // allocate directives that appear in a target region must specify an
3408 // allocator clause unless a requires directive with the dynamic_allocators
3409 // clause is present in the same compilation unit.
3410 if (LangOpts.OpenMPIsTargetDevice &&
3411 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3412 targetDiag(Loc, diag::err_expected_allocator_clause);
3413 } else {
3414 for (const OMPClause *C : Clauses)
3415 if (const auto *AC = dyn_cast<OMPAllocatorClause>(C))
3416 Allocator = AC->getAllocator();
3417 else if (const auto *AC = dyn_cast<OMPAlignClause>(C))
3418 Alignment = AC->getAlignment();
3419 else
3420 llvm_unreachable("Unexpected clause on allocate directive");
3422 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3423 getAllocatorKind(*this, DSAStack, Allocator);
3424 SmallVector<Expr *, 8> Vars;
3425 for (Expr *RefExpr : VarList) {
3426 auto *DE = cast<DeclRefExpr>(RefExpr);
3427 auto *VD = cast<VarDecl>(DE->getDecl());
3429 // Check if this is a TLS variable or global register.
3430 if (VD->getTLSKind() != VarDecl::TLS_None ||
3431 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3432 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3433 !VD->isLocalVarDecl()))
3434 continue;
3436 // If the used several times in the allocate directive, the same allocator
3437 // must be used.
3438 if (checkPreviousOMPAllocateAttribute(*this, DSAStack, RefExpr, VD,
3439 AllocatorKind, Allocator))
3440 continue;
3442 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3443 // If a list item has a static storage type, the allocator expression in the
3444 // allocator clause must be a constant expression that evaluates to one of
3445 // the predefined memory allocator values.
3446 if (Allocator && VD->hasGlobalStorage()) {
3447 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3448 Diag(Allocator->getExprLoc(),
3449 diag::err_omp_expected_predefined_allocator)
3450 << Allocator->getSourceRange();
3451 bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
3452 VarDecl::DeclarationOnly;
3453 Diag(VD->getLocation(),
3454 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3455 << VD;
3456 continue;
3460 Vars.push_back(RefExpr);
3461 applyOMPAllocateAttribute(*this, VD, AllocatorKind, Allocator, Alignment,
3462 DE->getSourceRange());
3464 if (Vars.empty())
3465 return nullptr;
3466 if (!Owner)
3467 Owner = getCurLexicalContext();
3468 auto *D = OMPAllocateDecl::Create(Context, Owner, Loc, Vars, Clauses);
3469 D->setAccess(AS_public);
3470 Owner->addDecl(D);
3471 return DeclGroupPtrTy::make(DeclGroupRef(D));
3474 Sema::DeclGroupPtrTy
3475 Sema::ActOnOpenMPRequiresDirective(SourceLocation Loc,
3476 ArrayRef<OMPClause *> ClauseList) {
3477 OMPRequiresDecl *D = nullptr;
3478 if (!CurContext->isFileContext()) {
3479 Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3480 } else {
3481 D = CheckOMPRequiresDecl(Loc, ClauseList);
3482 if (D) {
3483 CurContext->addDecl(D);
3484 DSAStack->addRequiresDecl(D);
3487 return DeclGroupPtrTy::make(DeclGroupRef(D));
3490 void Sema::ActOnOpenMPAssumesDirective(SourceLocation Loc,
3491 OpenMPDirectiveKind DKind,
3492 ArrayRef<std::string> Assumptions,
3493 bool SkippedClauses) {
3494 if (!SkippedClauses && Assumptions.empty())
3495 Diag(Loc, diag::err_omp_no_clause_for_directive)
3496 << llvm::omp::getAllAssumeClauseOptions()
3497 << llvm::omp::getOpenMPDirectiveName(DKind);
3499 auto *AA = AssumptionAttr::Create(Context, llvm::join(Assumptions, ","), Loc);
3500 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3501 OMPAssumeScoped.push_back(AA);
3502 return;
3505 // Global assumes without assumption clauses are ignored.
3506 if (Assumptions.empty())
3507 return;
3509 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3510 "Unexpected omp assumption directive!");
3511 OMPAssumeGlobal.push_back(AA);
3513 // The OMPAssumeGlobal scope above will take care of new declarations but
3514 // we also want to apply the assumption to existing ones, e.g., to
3515 // declarations in included headers. To this end, we traverse all existing
3516 // declaration contexts and annotate function declarations here.
3517 SmallVector<DeclContext *, 8> DeclContexts;
3518 auto *Ctx = CurContext;
3519 while (Ctx->getLexicalParent())
3520 Ctx = Ctx->getLexicalParent();
3521 DeclContexts.push_back(Ctx);
3522 while (!DeclContexts.empty()) {
3523 DeclContext *DC = DeclContexts.pop_back_val();
3524 for (auto *SubDC : DC->decls()) {
3525 if (SubDC->isInvalidDecl())
3526 continue;
3527 if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3528 DeclContexts.push_back(CTD->getTemplatedDecl());
3529 llvm::append_range(DeclContexts, CTD->specializations());
3530 continue;
3532 if (auto *DC = dyn_cast<DeclContext>(SubDC))
3533 DeclContexts.push_back(DC);
3534 if (auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3535 F->addAttr(AA);
3536 continue;
3542 void Sema::ActOnOpenMPEndAssumesDirective() {
3543 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3544 OMPAssumeScoped.pop_back();
3547 OMPRequiresDecl *Sema::CheckOMPRequiresDecl(SourceLocation Loc,
3548 ArrayRef<OMPClause *> ClauseList) {
3549 /// For target specific clauses, the requires directive cannot be
3550 /// specified after the handling of any of the target regions in the
3551 /// current compilation unit.
3552 ArrayRef<SourceLocation> TargetLocations =
3553 DSAStack->getEncounteredTargetLocs();
3554 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3555 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3556 for (const OMPClause *CNew : ClauseList) {
3557 // Check if any of the requires clauses affect target regions.
3558 if (isa<OMPUnifiedSharedMemoryClause>(CNew) ||
3559 isa<OMPUnifiedAddressClause>(CNew) ||
3560 isa<OMPReverseOffloadClause>(CNew) ||
3561 isa<OMPDynamicAllocatorsClause>(CNew)) {
3562 Diag(Loc, diag::err_omp_directive_before_requires)
3563 << "target" << getOpenMPClauseName(CNew->getClauseKind());
3564 for (SourceLocation TargetLoc : TargetLocations) {
3565 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3566 << "target";
3568 } else if (!AtomicLoc.isInvalid() &&
3569 isa<OMPAtomicDefaultMemOrderClause>(CNew)) {
3570 Diag(Loc, diag::err_omp_directive_before_requires)
3571 << "atomic" << getOpenMPClauseName(CNew->getClauseKind());
3572 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3573 << "atomic";
3578 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3579 return OMPRequiresDecl::Create(Context, getCurLexicalContext(), Loc,
3580 ClauseList);
3581 return nullptr;
3584 static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3585 const ValueDecl *D,
3586 const DSAStackTy::DSAVarData &DVar,
3587 bool IsLoopIterVar) {
3588 if (DVar.RefExpr) {
3589 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3590 << getOpenMPClauseName(DVar.CKind);
3591 return;
3593 enum {
3594 PDSA_StaticMemberShared,
3595 PDSA_StaticLocalVarShared,
3596 PDSA_LoopIterVarPrivate,
3597 PDSA_LoopIterVarLinear,
3598 PDSA_LoopIterVarLastprivate,
3599 PDSA_ConstVarShared,
3600 PDSA_GlobalVarShared,
3601 PDSA_TaskVarFirstprivate,
3602 PDSA_LocalVarPrivate,
3603 PDSA_Implicit
3604 } Reason = PDSA_Implicit;
3605 bool ReportHint = false;
3606 auto ReportLoc = D->getLocation();
3607 auto *VD = dyn_cast<VarDecl>(D);
3608 if (IsLoopIterVar) {
3609 if (DVar.CKind == OMPC_private)
3610 Reason = PDSA_LoopIterVarPrivate;
3611 else if (DVar.CKind == OMPC_lastprivate)
3612 Reason = PDSA_LoopIterVarLastprivate;
3613 else
3614 Reason = PDSA_LoopIterVarLinear;
3615 } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3616 DVar.CKind == OMPC_firstprivate) {
3617 Reason = PDSA_TaskVarFirstprivate;
3618 ReportLoc = DVar.ImplicitDSALoc;
3619 } else if (VD && VD->isStaticLocal())
3620 Reason = PDSA_StaticLocalVarShared;
3621 else if (VD && VD->isStaticDataMember())
3622 Reason = PDSA_StaticMemberShared;
3623 else if (VD && VD->isFileVarDecl())
3624 Reason = PDSA_GlobalVarShared;
3625 else if (D->getType().isConstant(SemaRef.getASTContext()))
3626 Reason = PDSA_ConstVarShared;
3627 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3628 ReportHint = true;
3629 Reason = PDSA_LocalVarPrivate;
3631 if (Reason != PDSA_Implicit) {
3632 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3633 << Reason << ReportHint
3634 << getOpenMPDirectiveName(Stack->getCurrentDirective());
3635 } else if (DVar.ImplicitDSALoc.isValid()) {
3636 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3637 << getOpenMPClauseName(DVar.CKind);
3641 static OpenMPMapClauseKind
3642 getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M,
3643 bool IsAggregateOrDeclareTarget) {
3644 OpenMPMapClauseKind Kind = OMPC_MAP_unknown;
3645 switch (M) {
3646 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3647 Kind = OMPC_MAP_alloc;
3648 break;
3649 case OMPC_DEFAULTMAP_MODIFIER_to:
3650 Kind = OMPC_MAP_to;
3651 break;
3652 case OMPC_DEFAULTMAP_MODIFIER_from:
3653 Kind = OMPC_MAP_from;
3654 break;
3655 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3656 Kind = OMPC_MAP_tofrom;
3657 break;
3658 case OMPC_DEFAULTMAP_MODIFIER_present:
3659 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3660 // If implicit-behavior is present, each variable referenced in the
3661 // construct in the category specified by variable-category is treated as if
3662 // it had been listed in a map clause with the map-type of alloc and
3663 // map-type-modifier of present.
3664 Kind = OMPC_MAP_alloc;
3665 break;
3666 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3667 case OMPC_DEFAULTMAP_MODIFIER_last:
3668 llvm_unreachable("Unexpected defaultmap implicit behavior");
3669 case OMPC_DEFAULTMAP_MODIFIER_none:
3670 case OMPC_DEFAULTMAP_MODIFIER_default:
3671 case OMPC_DEFAULTMAP_MODIFIER_unknown:
3672 // IsAggregateOrDeclareTarget could be true if:
3673 // 1. the implicit behavior for aggregate is tofrom
3674 // 2. it's a declare target link
3675 if (IsAggregateOrDeclareTarget) {
3676 Kind = OMPC_MAP_tofrom;
3677 break;
3679 llvm_unreachable("Unexpected defaultmap implicit behavior");
3681 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3682 return Kind;
3685 namespace {
3686 class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3687 DSAStackTy *Stack;
3688 Sema &SemaRef;
3689 bool ErrorFound = false;
3690 bool TryCaptureCXXThisMembers = false;
3691 CapturedStmt *CS = nullptr;
3692 const static unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
3693 llvm::SmallVector<Expr *, 4> ImplicitFirstprivate;
3694 llvm::SmallVector<Expr *, 4> ImplicitPrivate;
3695 llvm::SmallVector<Expr *, 4> ImplicitMap[DefaultmapKindNum][OMPC_MAP_delete];
3696 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
3697 ImplicitMapModifier[DefaultmapKindNum];
3698 Sema::VarsWithInheritedDSAType VarsWithInheritedDSA;
3699 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3701 void VisitSubCaptures(OMPExecutableDirective *S) {
3702 // Check implicitly captured variables.
3703 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3704 return;
3705 if (S->getDirectiveKind() == OMPD_atomic ||
3706 S->getDirectiveKind() == OMPD_critical ||
3707 S->getDirectiveKind() == OMPD_section ||
3708 S->getDirectiveKind() == OMPD_master ||
3709 S->getDirectiveKind() == OMPD_masked ||
3710 S->getDirectiveKind() == OMPD_scope ||
3711 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
3712 Visit(S->getAssociatedStmt());
3713 return;
3715 visitSubCaptures(S->getInnermostCapturedStmt());
3716 // Try to capture inner this->member references to generate correct mappings
3717 // and diagnostics.
3718 if (TryCaptureCXXThisMembers ||
3719 (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
3720 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3721 [](const CapturedStmt::Capture &C) {
3722 return C.capturesThis();
3723 }))) {
3724 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3725 TryCaptureCXXThisMembers = true;
3726 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3727 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3729 // In tasks firstprivates are not captured anymore, need to analyze them
3730 // explicitly.
3731 if (isOpenMPTaskingDirective(S->getDirectiveKind()) &&
3732 !isOpenMPTaskLoopDirective(S->getDirectiveKind())) {
3733 for (OMPClause *C : S->clauses())
3734 if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) {
3735 for (Expr *Ref : FC->varlists())
3736 Visit(Ref);
3741 public:
3742 void VisitDeclRefExpr(DeclRefExpr *E) {
3743 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
3744 E->isValueDependent() || E->containsUnexpandedParameterPack() ||
3745 E->isInstantiationDependent())
3746 return;
3747 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3748 // Check the datasharing rules for the expressions in the clauses.
3749 if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) &&
3750 !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr &&
3751 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3752 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3753 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3754 Visit(CED->getInit());
3755 return;
3757 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD))
3758 // Do not analyze internal variables and do not enclose them into
3759 // implicit clauses.
3760 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3761 return;
3762 VD = VD->getCanonicalDecl();
3763 // Skip internally declared variables.
3764 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) &&
3765 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3766 !Stack->isImplicitTaskFirstprivate(VD))
3767 return;
3768 // Skip allocators in uses_allocators clauses.
3769 if (Stack->isUsesAllocatorsDecl(VD))
3770 return;
3772 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
3773 // Check if the variable has explicit DSA set and stop analysis if it so.
3774 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3775 return;
3777 // Skip internally declared static variables.
3778 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3779 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3780 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
3781 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
3782 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3783 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3784 !Stack->isImplicitTaskFirstprivate(VD))
3785 return;
3787 SourceLocation ELoc = E->getExprLoc();
3788 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3789 // The default(none) clause requires that each variable that is referenced
3790 // in the construct, and does not have a predetermined data-sharing
3791 // attribute, must have its data-sharing attribute explicitly determined
3792 // by being listed in a data-sharing attribute clause.
3793 if (DVar.CKind == OMPC_unknown &&
3794 (Stack->getDefaultDSA() == DSA_none ||
3795 Stack->getDefaultDSA() == DSA_private ||
3796 Stack->getDefaultDSA() == DSA_firstprivate) &&
3797 isImplicitOrExplicitTaskingRegion(DKind) &&
3798 VarsWithInheritedDSA.count(VD) == 0) {
3799 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
3800 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
3801 Stack->getDefaultDSA() == DSA_private)) {
3802 DSAStackTy::DSAVarData DVar =
3803 Stack->getImplicitDSA(VD, /*FromParent=*/false);
3804 InheritedDSA = DVar.CKind == OMPC_unknown;
3806 if (InheritedDSA)
3807 VarsWithInheritedDSA[VD] = E;
3808 if (Stack->getDefaultDSA() == DSA_none)
3809 return;
3812 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
3813 // If implicit-behavior is none, each variable referenced in the
3814 // construct that does not have a predetermined data-sharing attribute
3815 // and does not appear in a to or link clause on a declare target
3816 // directive must be listed in a data-mapping attribute clause, a
3817 // data-sharing attribute clause (including a data-sharing attribute
3818 // clause on a combined construct where target. is one of the
3819 // constituent constructs), or an is_device_ptr clause.
3820 OpenMPDefaultmapClauseKind ClauseKind =
3821 getVariableCategoryFromDecl(SemaRef.getLangOpts(), VD);
3822 if (SemaRef.getLangOpts().OpenMP >= 50) {
3823 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
3824 OMPC_DEFAULTMAP_MODIFIER_none;
3825 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
3826 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
3827 // Only check for data-mapping attribute and is_device_ptr here
3828 // since we have already make sure that the declaration does not
3829 // have a data-sharing attribute above
3830 if (!Stack->checkMappableExprComponentListsForDecl(
3831 VD, /*CurrentRegionOnly=*/true,
3832 [VD](OMPClauseMappableExprCommon::MappableExprComponentListRef
3833 MapExprComponents,
3834 OpenMPClauseKind) {
3835 auto MI = MapExprComponents.rbegin();
3836 auto ME = MapExprComponents.rend();
3837 return MI != ME && MI->getAssociatedDeclaration() == VD;
3838 })) {
3839 VarsWithInheritedDSA[VD] = E;
3840 return;
3844 if (SemaRef.getLangOpts().OpenMP > 50) {
3845 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
3846 OMPC_DEFAULTMAP_MODIFIER_present;
3847 if (IsModifierPresent) {
3848 if (!llvm::is_contained(ImplicitMapModifier[ClauseKind],
3849 OMPC_MAP_MODIFIER_present)) {
3850 ImplicitMapModifier[ClauseKind].push_back(
3851 OMPC_MAP_MODIFIER_present);
3856 if (isOpenMPTargetExecutionDirective(DKind) &&
3857 !Stack->isLoopControlVariable(VD).first) {
3858 if (!Stack->checkMappableExprComponentListsForDecl(
3859 VD, /*CurrentRegionOnly=*/true,
3860 [this](OMPClauseMappableExprCommon::MappableExprComponentListRef
3861 StackComponents,
3862 OpenMPClauseKind) {
3863 if (SemaRef.LangOpts.OpenMP >= 50)
3864 return !StackComponents.empty();
3865 // Variable is used if it has been marked as an array, array
3866 // section, array shaping or the variable iself.
3867 return StackComponents.size() == 1 ||
3868 llvm::all_of(
3869 llvm::drop_begin(llvm::reverse(StackComponents)),
3870 [](const OMPClauseMappableExprCommon::
3871 MappableComponent &MC) {
3872 return MC.getAssociatedDeclaration() ==
3873 nullptr &&
3874 (isa<OMPArraySectionExpr>(
3875 MC.getAssociatedExpression()) ||
3876 isa<OMPArrayShapingExpr>(
3877 MC.getAssociatedExpression()) ||
3878 isa<ArraySubscriptExpr>(
3879 MC.getAssociatedExpression()));
3881 })) {
3882 bool IsFirstprivate = false;
3883 // By default lambdas are captured as firstprivates.
3884 if (const auto *RD =
3885 VD->getType().getNonReferenceType()->getAsCXXRecordDecl())
3886 IsFirstprivate = RD->isLambda();
3887 IsFirstprivate =
3888 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
3889 if (IsFirstprivate) {
3890 ImplicitFirstprivate.emplace_back(E);
3891 } else {
3892 OpenMPDefaultmapClauseModifier M =
3893 Stack->getDefaultmapModifier(ClauseKind);
3894 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
3895 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
3896 ImplicitMap[ClauseKind][Kind].emplace_back(E);
3898 return;
3902 // OpenMP [2.9.3.6, Restrictions, p.2]
3903 // A list item that appears in a reduction clause of the innermost
3904 // enclosing worksharing or parallel construct may not be accessed in an
3905 // explicit task.
3906 DVar = Stack->hasInnermostDSA(
3908 [](OpenMPClauseKind C, bool AppliedToPointee) {
3909 return C == OMPC_reduction && !AppliedToPointee;
3911 [](OpenMPDirectiveKind K) {
3912 return isOpenMPParallelDirective(K) ||
3913 isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K);
3915 /*FromParent=*/true);
3916 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
3917 ErrorFound = true;
3918 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
3919 reportOriginalDsa(SemaRef, Stack, VD, DVar);
3920 return;
3923 // Define implicit data-sharing attributes for task.
3924 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
3925 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
3926 (((Stack->getDefaultDSA() == DSA_firstprivate &&
3927 DVar.CKind == OMPC_firstprivate) ||
3928 (Stack->getDefaultDSA() == DSA_private &&
3929 DVar.CKind == OMPC_private)) &&
3930 !DVar.RefExpr)) &&
3931 !Stack->isLoopControlVariable(VD).first) {
3932 if (Stack->getDefaultDSA() == DSA_private)
3933 ImplicitPrivate.push_back(E);
3934 else
3935 ImplicitFirstprivate.push_back(E);
3936 return;
3939 // Store implicitly used globals with declare target link for parent
3940 // target.
3941 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
3942 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
3943 Stack->addToParentTargetRegionLinkGlobals(E);
3944 return;
3948 void VisitMemberExpr(MemberExpr *E) {
3949 if (E->isTypeDependent() || E->isValueDependent() ||
3950 E->containsUnexpandedParameterPack() || E->isInstantiationDependent())
3951 return;
3952 auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
3953 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3954 if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) {
3955 if (!FD)
3956 return;
3957 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
3958 // Check if the variable has explicit DSA set and stop analysis if it
3959 // so.
3960 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
3961 return;
3963 if (isOpenMPTargetExecutionDirective(DKind) &&
3964 !Stack->isLoopControlVariable(FD).first &&
3965 !Stack->checkMappableExprComponentListsForDecl(
3966 FD, /*CurrentRegionOnly=*/true,
3967 [](OMPClauseMappableExprCommon::MappableExprComponentListRef
3968 StackComponents,
3969 OpenMPClauseKind) {
3970 return isa<CXXThisExpr>(
3971 cast<MemberExpr>(
3972 StackComponents.back().getAssociatedExpression())
3973 ->getBase()
3974 ->IgnoreParens());
3975 })) {
3976 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
3977 // A bit-field cannot appear in a map clause.
3979 if (FD->isBitField())
3980 return;
3982 // Check to see if the member expression is referencing a class that
3983 // has already been explicitly mapped
3984 if (Stack->isClassPreviouslyMapped(TE->getType()))
3985 return;
3987 OpenMPDefaultmapClauseModifier Modifier =
3988 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
3989 OpenMPDefaultmapClauseKind ClauseKind =
3990 getVariableCategoryFromDecl(SemaRef.getLangOpts(), FD);
3991 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
3992 Modifier, /*IsAggregateOrDeclareTarget*/ true);
3993 ImplicitMap[ClauseKind][Kind].emplace_back(E);
3994 return;
3997 SourceLocation ELoc = E->getExprLoc();
3998 // OpenMP [2.9.3.6, Restrictions, p.2]
3999 // A list item that appears in a reduction clause of the innermost
4000 // enclosing worksharing or parallel construct may not be accessed in
4001 // an explicit task.
4002 DVar = Stack->hasInnermostDSA(
4004 [](OpenMPClauseKind C, bool AppliedToPointee) {
4005 return C == OMPC_reduction && !AppliedToPointee;
4007 [](OpenMPDirectiveKind K) {
4008 return isOpenMPParallelDirective(K) ||
4009 isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K);
4011 /*FromParent=*/true);
4012 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4013 ErrorFound = true;
4014 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4015 reportOriginalDsa(SemaRef, Stack, FD, DVar);
4016 return;
4019 // Define implicit data-sharing attributes for task.
4020 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
4021 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
4022 !Stack->isLoopControlVariable(FD).first) {
4023 // Check if there is a captured expression for the current field in the
4024 // region. Do not mark it as firstprivate unless there is no captured
4025 // expression.
4026 // TODO: try to make it firstprivate.
4027 if (DVar.CKind != OMPC_unknown)
4028 ImplicitFirstprivate.push_back(E);
4030 return;
4032 if (isOpenMPTargetExecutionDirective(DKind)) {
4033 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
4034 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
4035 Stack->getCurrentDirective(),
4036 /*NoDiagnose=*/true))
4037 return;
4038 const auto *VD = cast<ValueDecl>(
4039 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4040 if (!Stack->checkMappableExprComponentListsForDecl(
4041 VD, /*CurrentRegionOnly=*/true,
4042 [&CurComponents](
4043 OMPClauseMappableExprCommon::MappableExprComponentListRef
4044 StackComponents,
4045 OpenMPClauseKind) {
4046 auto CCI = CurComponents.rbegin();
4047 auto CCE = CurComponents.rend();
4048 for (const auto &SC : llvm::reverse(StackComponents)) {
4049 // Do both expressions have the same kind?
4050 if (CCI->getAssociatedExpression()->getStmtClass() !=
4051 SC.getAssociatedExpression()->getStmtClass())
4052 if (!((isa<OMPArraySectionExpr>(
4053 SC.getAssociatedExpression()) ||
4054 isa<OMPArrayShapingExpr>(
4055 SC.getAssociatedExpression())) &&
4056 isa<ArraySubscriptExpr>(
4057 CCI->getAssociatedExpression())))
4058 return false;
4060 const Decl *CCD = CCI->getAssociatedDeclaration();
4061 const Decl *SCD = SC.getAssociatedDeclaration();
4062 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4063 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4064 if (SCD != CCD)
4065 return false;
4066 std::advance(CCI, 1);
4067 if (CCI == CCE)
4068 break;
4070 return true;
4071 })) {
4072 Visit(E->getBase());
4074 } else if (!TryCaptureCXXThisMembers) {
4075 Visit(E->getBase());
4078 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4079 for (OMPClause *C : S->clauses()) {
4080 // Skip analysis of arguments of private clauses for task|target
4081 // directives.
4082 if (isa_and_nonnull<OMPPrivateClause>(C))
4083 continue;
4084 // Skip analysis of arguments of implicitly defined firstprivate clause
4085 // for task|target directives.
4086 // Skip analysis of arguments of implicitly defined map clause for target
4087 // directives.
4088 if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) &&
4089 C->isImplicit() &&
4090 !isOpenMPTaskingDirective(Stack->getCurrentDirective()))) {
4091 for (Stmt *CC : C->children()) {
4092 if (CC)
4093 Visit(CC);
4097 // Check implicitly captured variables.
4098 VisitSubCaptures(S);
4101 void VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective *S) {
4102 // Loop transformation directives do not introduce data sharing
4103 VisitStmt(S);
4106 void VisitCallExpr(CallExpr *S) {
4107 for (Stmt *C : S->arguments()) {
4108 if (C) {
4109 // Check implicitly captured variables in the task-based directives to
4110 // check if they must be firstprivatized.
4111 Visit(C);
4114 if (Expr *Callee = S->getCallee()) {
4115 auto *CI = Callee->IgnoreParenImpCasts();
4116 if (auto *CE = dyn_cast<MemberExpr>(CI))
4117 Visit(CE->getBase());
4118 else if (auto *CE = dyn_cast<DeclRefExpr>(CI))
4119 Visit(CE);
4122 void VisitStmt(Stmt *S) {
4123 for (Stmt *C : S->children()) {
4124 if (C) {
4125 // Check implicitly captured variables in the task-based directives to
4126 // check if they must be firstprivatized.
4127 Visit(C);
4132 void visitSubCaptures(CapturedStmt *S) {
4133 for (const CapturedStmt::Capture &Cap : S->captures()) {
4134 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4135 continue;
4136 VarDecl *VD = Cap.getCapturedVar();
4137 // Do not try to map the variable if it or its sub-component was mapped
4138 // already.
4139 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
4140 Stack->checkMappableExprComponentListsForDecl(
4141 VD, /*CurrentRegionOnly=*/true,
4142 [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
4143 OpenMPClauseKind) { return true; }))
4144 continue;
4145 DeclRefExpr *DRE = buildDeclRefExpr(
4146 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4147 Cap.getLocation(), /*RefersToCapture=*/true);
4148 Visit(DRE);
4151 bool isErrorFound() const { return ErrorFound; }
4152 ArrayRef<Expr *> getImplicitFirstprivate() const {
4153 return ImplicitFirstprivate;
4155 ArrayRef<Expr *> getImplicitPrivate() const { return ImplicitPrivate; }
4156 ArrayRef<Expr *> getImplicitMap(OpenMPDefaultmapClauseKind DK,
4157 OpenMPMapClauseKind MK) const {
4158 return ImplicitMap[DK][MK];
4160 ArrayRef<OpenMPMapModifierKind>
4161 getImplicitMapModifier(OpenMPDefaultmapClauseKind Kind) const {
4162 return ImplicitMapModifier[Kind];
4164 const Sema::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4165 return VarsWithInheritedDSA;
4168 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4169 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4170 // Process declare target link variables for the target directives.
4171 if (isOpenMPTargetExecutionDirective(S->getCurrentDirective())) {
4172 for (DeclRefExpr *E : Stack->getLinkGlobals())
4173 Visit(E);
4177 } // namespace
4179 static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4180 OpenMPDirectiveKind DKind,
4181 bool ScopeEntry) {
4182 SmallVector<llvm::omp::TraitProperty, 8> Traits;
4183 if (isOpenMPTargetExecutionDirective(DKind))
4184 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4185 if (isOpenMPTeamsDirective(DKind))
4186 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4187 if (isOpenMPParallelDirective(DKind))
4188 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4189 if (isOpenMPWorksharingDirective(DKind))
4190 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4191 if (isOpenMPSimdDirective(DKind))
4192 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4193 Stack->handleConstructTrait(Traits, ScopeEntry);
4196 void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
4197 switch (DKind) {
4198 case OMPD_parallel:
4199 case OMPD_parallel_for:
4200 case OMPD_parallel_for_simd:
4201 case OMPD_parallel_sections:
4202 case OMPD_parallel_master:
4203 case OMPD_parallel_masked:
4204 case OMPD_parallel_loop:
4205 case OMPD_teams:
4206 case OMPD_teams_distribute:
4207 case OMPD_teams_distribute_simd: {
4208 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4209 QualType KmpInt32PtrTy =
4210 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4211 Sema::CapturedParamNameType Params[] = {
4212 std::make_pair(".global_tid.", KmpInt32PtrTy),
4213 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4214 std::make_pair(StringRef(), QualType()) // __context with shared vars
4216 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4217 Params);
4218 break;
4220 case OMPD_target_teams:
4221 case OMPD_target_parallel:
4222 case OMPD_target_parallel_for:
4223 case OMPD_target_parallel_for_simd:
4224 case OMPD_target_parallel_loop:
4225 case OMPD_target_teams_distribute:
4226 case OMPD_target_teams_distribute_simd: {
4227 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4228 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4229 QualType KmpInt32PtrTy =
4230 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4231 QualType Args[] = {VoidPtrTy};
4232 FunctionProtoType::ExtProtoInfo EPI;
4233 EPI.Variadic = true;
4234 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4235 Sema::CapturedParamNameType Params[] = {
4236 std::make_pair(".global_tid.", KmpInt32Ty),
4237 std::make_pair(".part_id.", KmpInt32PtrTy),
4238 std::make_pair(".privates.", VoidPtrTy),
4239 std::make_pair(
4240 ".copy_fn.",
4241 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4242 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4243 std::make_pair(StringRef(), QualType()) // __context with shared vars
4245 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4246 Params, /*OpenMPCaptureLevel=*/0);
4247 // Mark this captured region as inlined, because we don't use outlined
4248 // function directly.
4249 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4250 AlwaysInlineAttr::CreateImplicit(
4251 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4252 SmallVector<Sema::CapturedParamNameType, 2> ParamsTarget;
4253 if (getLangOpts().OpenMPIsTargetDevice)
4254 ParamsTarget.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4255 ParamsTarget.push_back(
4256 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,
4260 /*OpenMPCaptureLevel=*/1);
4261 Sema::CapturedParamNameType ParamsTeamsOrParallel[] = {
4262 std::make_pair(".global_tid.", KmpInt32PtrTy),
4263 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4264 std::make_pair(StringRef(), QualType()) // __context with shared vars
4266 // Start a captured region for 'teams' or 'parallel'. Both regions have
4267 // the same implicit parameters.
4268 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4269 ParamsTeamsOrParallel, /*OpenMPCaptureLevel=*/2);
4270 break;
4272 case OMPD_target:
4273 case OMPD_target_simd: {
4274 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4275 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4276 QualType KmpInt32PtrTy =
4277 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4278 QualType Args[] = {VoidPtrTy};
4279 FunctionProtoType::ExtProtoInfo EPI;
4280 EPI.Variadic = true;
4281 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4282 Sema::CapturedParamNameType Params[] = {
4283 std::make_pair(".global_tid.", KmpInt32Ty),
4284 std::make_pair(".part_id.", KmpInt32PtrTy),
4285 std::make_pair(".privates.", VoidPtrTy),
4286 std::make_pair(
4287 ".copy_fn.",
4288 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4289 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4290 std::make_pair(StringRef(), QualType()) // __context with shared vars
4292 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4293 Params, /*OpenMPCaptureLevel=*/0);
4294 // Mark this captured region as inlined, because we don't use outlined
4295 // function directly.
4296 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4297 AlwaysInlineAttr::CreateImplicit(
4298 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4299 SmallVector<Sema::CapturedParamNameType, 2> ParamsTarget;
4300 if (getLangOpts().OpenMPIsTargetDevice)
4301 ParamsTarget.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4302 ParamsTarget.push_back(
4303 std::make_pair(StringRef(), QualType())); // __context with shared vars;
4304 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4305 ParamsTarget,
4306 /*OpenMPCaptureLevel=*/1);
4307 break;
4309 case OMPD_atomic:
4310 case OMPD_critical:
4311 case OMPD_section:
4312 case OMPD_master:
4313 case OMPD_masked:
4314 case OMPD_tile:
4315 case OMPD_unroll:
4316 break;
4317 case OMPD_loop:
4318 // TODO: 'loop' may require additional parameters depending on the binding.
4319 // Treat similar to OMPD_simd/OMPD_for for now.
4320 case OMPD_simd:
4321 case OMPD_for:
4322 case OMPD_for_simd:
4323 case OMPD_sections:
4324 case OMPD_single:
4325 case OMPD_taskgroup:
4326 case OMPD_distribute:
4327 case OMPD_distribute_simd:
4328 case OMPD_ordered:
4329 case OMPD_scope:
4330 case OMPD_target_data:
4331 case OMPD_dispatch: {
4332 Sema::CapturedParamNameType Params[] = {
4333 std::make_pair(StringRef(), QualType()) // __context with shared vars
4335 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4336 Params);
4337 break;
4339 case OMPD_task: {
4340 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4341 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4342 QualType KmpInt32PtrTy =
4343 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4344 QualType Args[] = {VoidPtrTy};
4345 FunctionProtoType::ExtProtoInfo EPI;
4346 EPI.Variadic = true;
4347 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4348 Sema::CapturedParamNameType Params[] = {
4349 std::make_pair(".global_tid.", KmpInt32Ty),
4350 std::make_pair(".part_id.", KmpInt32PtrTy),
4351 std::make_pair(".privates.", VoidPtrTy),
4352 std::make_pair(
4353 ".copy_fn.",
4354 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4355 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4356 std::make_pair(StringRef(), QualType()) // __context with shared vars
4358 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4359 Params);
4360 // Mark this captured region as inlined, because we don't use outlined
4361 // function directly.
4362 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4363 AlwaysInlineAttr::CreateImplicit(
4364 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4365 break;
4367 case OMPD_taskloop:
4368 case OMPD_taskloop_simd:
4369 case OMPD_master_taskloop:
4370 case OMPD_masked_taskloop:
4371 case OMPD_masked_taskloop_simd:
4372 case OMPD_master_taskloop_simd: {
4373 QualType KmpInt32Ty =
4374 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
4375 .withConst();
4376 QualType KmpUInt64Ty =
4377 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
4378 .withConst();
4379 QualType KmpInt64Ty =
4380 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
4381 .withConst();
4382 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4383 QualType KmpInt32PtrTy =
4384 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4385 QualType Args[] = {VoidPtrTy};
4386 FunctionProtoType::ExtProtoInfo EPI;
4387 EPI.Variadic = true;
4388 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4389 Sema::CapturedParamNameType Params[] = {
4390 std::make_pair(".global_tid.", KmpInt32Ty),
4391 std::make_pair(".part_id.", KmpInt32PtrTy),
4392 std::make_pair(".privates.", VoidPtrTy),
4393 std::make_pair(
4394 ".copy_fn.",
4395 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4396 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4397 std::make_pair(".lb.", KmpUInt64Ty),
4398 std::make_pair(".ub.", KmpUInt64Ty),
4399 std::make_pair(".st.", KmpInt64Ty),
4400 std::make_pair(".liter.", KmpInt32Ty),
4401 std::make_pair(".reductions.", VoidPtrTy),
4402 std::make_pair(StringRef(), QualType()) // __context with shared vars
4404 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4405 Params);
4406 // Mark this captured region as inlined, because we don't use outlined
4407 // function directly.
4408 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4409 AlwaysInlineAttr::CreateImplicit(
4410 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4411 break;
4413 case OMPD_parallel_masked_taskloop:
4414 case OMPD_parallel_masked_taskloop_simd:
4415 case OMPD_parallel_master_taskloop:
4416 case OMPD_parallel_master_taskloop_simd: {
4417 QualType KmpInt32Ty =
4418 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
4419 .withConst();
4420 QualType KmpUInt64Ty =
4421 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
4422 .withConst();
4423 QualType KmpInt64Ty =
4424 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
4425 .withConst();
4426 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4427 QualType KmpInt32PtrTy =
4428 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4429 Sema::CapturedParamNameType ParamsParallel[] = {
4430 std::make_pair(".global_tid.", KmpInt32PtrTy),
4431 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4432 std::make_pair(StringRef(), QualType()) // __context with shared vars
4434 // Start a captured region for 'parallel'.
4435 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4436 ParamsParallel, /*OpenMPCaptureLevel=*/0);
4437 QualType Args[] = {VoidPtrTy};
4438 FunctionProtoType::ExtProtoInfo EPI;
4439 EPI.Variadic = true;
4440 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4441 Sema::CapturedParamNameType Params[] = {
4442 std::make_pair(".global_tid.", KmpInt32Ty),
4443 std::make_pair(".part_id.", KmpInt32PtrTy),
4444 std::make_pair(".privates.", VoidPtrTy),
4445 std::make_pair(
4446 ".copy_fn.",
4447 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4448 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4449 std::make_pair(".lb.", KmpUInt64Ty),
4450 std::make_pair(".ub.", KmpUInt64Ty),
4451 std::make_pair(".st.", KmpInt64Ty),
4452 std::make_pair(".liter.", KmpInt32Ty),
4453 std::make_pair(".reductions.", VoidPtrTy),
4454 std::make_pair(StringRef(), QualType()) // __context with shared vars
4456 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4457 Params, /*OpenMPCaptureLevel=*/1);
4458 // Mark this captured region as inlined, because we don't use outlined
4459 // function directly.
4460 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4461 AlwaysInlineAttr::CreateImplicit(
4462 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4463 break;
4465 case OMPD_distribute_parallel_for_simd:
4466 case OMPD_distribute_parallel_for: {
4467 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4468 QualType KmpInt32PtrTy =
4469 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4470 Sema::CapturedParamNameType Params[] = {
4471 std::make_pair(".global_tid.", KmpInt32PtrTy),
4472 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4473 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4474 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4475 std::make_pair(StringRef(), QualType()) // __context with shared vars
4477 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4478 Params);
4479 break;
4481 case OMPD_target_teams_loop:
4482 case OMPD_target_teams_distribute_parallel_for:
4483 case OMPD_target_teams_distribute_parallel_for_simd: {
4484 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4485 QualType KmpInt32PtrTy =
4486 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4487 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4489 QualType Args[] = {VoidPtrTy};
4490 FunctionProtoType::ExtProtoInfo EPI;
4491 EPI.Variadic = true;
4492 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4493 Sema::CapturedParamNameType Params[] = {
4494 std::make_pair(".global_tid.", KmpInt32Ty),
4495 std::make_pair(".part_id.", KmpInt32PtrTy),
4496 std::make_pair(".privates.", VoidPtrTy),
4497 std::make_pair(
4498 ".copy_fn.",
4499 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4500 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4501 std::make_pair(StringRef(), QualType()) // __context with shared vars
4503 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4504 Params, /*OpenMPCaptureLevel=*/0);
4505 // Mark this captured region as inlined, because we don't use outlined
4506 // function directly.
4507 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4508 AlwaysInlineAttr::CreateImplicit(
4509 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4510 SmallVector<Sema::CapturedParamNameType, 2> ParamsTarget;
4511 if (getLangOpts().OpenMPIsTargetDevice)
4512 ParamsTarget.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4513 ParamsTarget.push_back(
4514 std::make_pair(StringRef(), QualType())); // __context with shared vars;
4515 // Start a captured region for 'target' with no implicit parameters.
4516 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4517 ParamsTarget, /*OpenMPCaptureLevel=*/1);
4519 Sema::CapturedParamNameType ParamsTeams[] = {
4520 std::make_pair(".global_tid.", KmpInt32PtrTy),
4521 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4522 std::make_pair(StringRef(), QualType()) // __context with shared vars
4524 // Start a captured region for 'target' with no implicit parameters.
4525 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4526 ParamsTeams, /*OpenMPCaptureLevel=*/2);
4528 Sema::CapturedParamNameType ParamsParallel[] = {
4529 std::make_pair(".global_tid.", KmpInt32PtrTy),
4530 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4531 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4532 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4533 std::make_pair(StringRef(), QualType()) // __context with shared vars
4535 // Start a captured region for 'teams' or 'parallel'. Both regions have
4536 // the same implicit parameters.
4537 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4538 ParamsParallel, /*OpenMPCaptureLevel=*/3);
4539 break;
4542 case OMPD_teams_loop:
4543 case OMPD_teams_distribute_parallel_for:
4544 case OMPD_teams_distribute_parallel_for_simd: {
4545 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4546 QualType KmpInt32PtrTy =
4547 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4549 Sema::CapturedParamNameType ParamsTeams[] = {
4550 std::make_pair(".global_tid.", KmpInt32PtrTy),
4551 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4552 std::make_pair(StringRef(), QualType()) // __context with shared vars
4554 // Start a captured region for 'target' with no implicit parameters.
4555 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4556 ParamsTeams, /*OpenMPCaptureLevel=*/0);
4558 Sema::CapturedParamNameType ParamsParallel[] = {
4559 std::make_pair(".global_tid.", KmpInt32PtrTy),
4560 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4561 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4562 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4563 std::make_pair(StringRef(), QualType()) // __context with shared vars
4565 // Start a captured region for 'teams' or 'parallel'. Both regions have
4566 // the same implicit parameters.
4567 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4568 ParamsParallel, /*OpenMPCaptureLevel=*/1);
4569 break;
4571 case OMPD_target_update:
4572 case OMPD_target_enter_data:
4573 case OMPD_target_exit_data: {
4574 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4575 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4576 QualType KmpInt32PtrTy =
4577 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4578 QualType Args[] = {VoidPtrTy};
4579 FunctionProtoType::ExtProtoInfo EPI;
4580 EPI.Variadic = true;
4581 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4582 Sema::CapturedParamNameType Params[] = {
4583 std::make_pair(".global_tid.", KmpInt32Ty),
4584 std::make_pair(".part_id.", KmpInt32PtrTy),
4585 std::make_pair(".privates.", VoidPtrTy),
4586 std::make_pair(
4587 ".copy_fn.",
4588 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4589 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4590 std::make_pair(StringRef(), QualType()) // __context with shared vars
4592 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4593 Params);
4594 // Mark this captured region as inlined, because we don't use outlined
4595 // function directly.
4596 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4597 AlwaysInlineAttr::CreateImplicit(
4598 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4599 break;
4601 case OMPD_threadprivate:
4602 case OMPD_allocate:
4603 case OMPD_taskyield:
4604 case OMPD_error:
4605 case OMPD_barrier:
4606 case OMPD_taskwait:
4607 case OMPD_cancellation_point:
4608 case OMPD_cancel:
4609 case OMPD_flush:
4610 case OMPD_depobj:
4611 case OMPD_scan:
4612 case OMPD_declare_reduction:
4613 case OMPD_declare_mapper:
4614 case OMPD_declare_simd:
4615 case OMPD_declare_target:
4616 case OMPD_end_declare_target:
4617 case OMPD_requires:
4618 case OMPD_declare_variant:
4619 case OMPD_begin_declare_variant:
4620 case OMPD_end_declare_variant:
4621 case OMPD_metadirective:
4622 llvm_unreachable("OpenMP Directive is not allowed");
4623 case OMPD_unknown:
4624 default:
4625 llvm_unreachable("Unknown OpenMP directive");
4627 DSAStack->setContext(CurContext);
4628 handleDeclareVariantConstructTrait(DSAStack, DKind, /* ScopeEntry */ true);
4631 int Sema::getNumberOfConstructScopes(unsigned Level) const {
4632 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4635 int Sema::getOpenMPCaptureLevels(OpenMPDirectiveKind DKind) {
4636 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4637 getOpenMPCaptureRegions(CaptureRegions, DKind);
4638 return CaptureRegions.size();
4641 static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
4642 Expr *CaptureExpr, bool WithInit,
4643 DeclContext *CurContext,
4644 bool AsExpression) {
4645 assert(CaptureExpr);
4646 ASTContext &C = S.getASTContext();
4647 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4648 QualType Ty = Init->getType();
4649 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4650 if (S.getLangOpts().CPlusPlus) {
4651 Ty = C.getLValueReferenceType(Ty);
4652 } else {
4653 Ty = C.getPointerType(Ty);
4654 ExprResult Res =
4655 S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init);
4656 if (!Res.isUsable())
4657 return nullptr;
4658 Init = Res.get();
4660 WithInit = true;
4662 auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty,
4663 CaptureExpr->getBeginLoc());
4664 if (!WithInit)
4665 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
4666 CurContext->addHiddenDecl(CED);
4667 Sema::TentativeAnalysisScope Trap(S);
4668 S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
4669 return CED;
4672 static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4673 bool WithInit) {
4674 OMPCapturedExprDecl *CD;
4675 if (VarDecl *VD = S.isOpenMPCapturedDecl(D))
4676 CD = cast<OMPCapturedExprDecl>(VD);
4677 else
4678 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
4679 S.CurContext,
4680 /*AsExpression=*/false);
4681 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4682 CaptureExpr->getExprLoc());
4685 static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
4686 StringRef Name) {
4687 CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get();
4688 if (!Ref) {
4689 OMPCapturedExprDecl *CD = buildCaptureDecl(
4690 S, &S.getASTContext().Idents.get(Name), CaptureExpr,
4691 /*WithInit=*/true, S.CurContext, /*AsExpression=*/true);
4692 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4693 CaptureExpr->getExprLoc());
4695 ExprResult Res = Ref;
4696 if (!S.getLangOpts().CPlusPlus &&
4697 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4698 Ref->getType()->isPointerType()) {
4699 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
4700 if (!Res.isUsable())
4701 return ExprError();
4703 return S.DefaultLvalueConversion(Res.get());
4706 namespace {
4707 // OpenMP directives parsed in this section are represented as a
4708 // CapturedStatement with an associated statement. If a syntax error
4709 // is detected during the parsing of the associated statement, the
4710 // compiler must abort processing and close the CapturedStatement.
4712 // Combined directives such as 'target parallel' have more than one
4713 // nested CapturedStatements. This RAII ensures that we unwind out
4714 // of all the nested CapturedStatements when an error is found.
4715 class CaptureRegionUnwinderRAII {
4716 private:
4717 Sema &S;
4718 bool &ErrorFound;
4719 OpenMPDirectiveKind DKind = OMPD_unknown;
4721 public:
4722 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4723 OpenMPDirectiveKind DKind)
4724 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4725 ~CaptureRegionUnwinderRAII() {
4726 if (ErrorFound) {
4727 int ThisCaptureLevel = S.getOpenMPCaptureLevels(DKind);
4728 while (--ThisCaptureLevel >= 0)
4729 S.ActOnCapturedRegionError();
4733 } // namespace
4735 void Sema::tryCaptureOpenMPLambdas(ValueDecl *V) {
4736 // Capture variables captured by reference in lambdas for target-based
4737 // directives.
4738 if (!CurContext->isDependentContext() &&
4739 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4740 isOpenMPTargetDataManagementDirective(
4741 DSAStack->getCurrentDirective()))) {
4742 QualType Type = V->getType();
4743 if (const auto *RD = Type.getCanonicalType()
4744 .getNonReferenceType()
4745 ->getAsCXXRecordDecl()) {
4746 bool SavedForceCaptureByReferenceInTargetExecutable =
4747 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4748 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4749 /*V=*/true);
4750 if (RD->isLambda()) {
4751 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4752 FieldDecl *ThisCapture;
4753 RD->getCaptureFields(Captures, ThisCapture);
4754 for (const LambdaCapture &LC : RD->captures()) {
4755 if (LC.getCaptureKind() == LCK_ByRef) {
4756 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4757 DeclContext *VDC = VD->getDeclContext();
4758 if (!VDC->Encloses(CurContext))
4759 continue;
4760 MarkVariableReferenced(LC.getLocation(), VD);
4761 } else if (LC.getCaptureKind() == LCK_This) {
4762 QualType ThisTy = getCurrentThisType();
4763 if (!ThisTy.isNull() &&
4764 Context.typesAreCompatible(ThisTy, ThisCapture->getType()))
4765 CheckCXXThisCapture(LC.getLocation());
4769 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4770 SavedForceCaptureByReferenceInTargetExecutable);
4775 static bool checkOrderedOrderSpecified(Sema &S,
4776 const ArrayRef<OMPClause *> Clauses) {
4777 const OMPOrderedClause *Ordered = nullptr;
4778 const OMPOrderClause *Order = nullptr;
4780 for (const OMPClause *Clause : Clauses) {
4781 if (Clause->getClauseKind() == OMPC_ordered)
4782 Ordered = cast<OMPOrderedClause>(Clause);
4783 else if (Clause->getClauseKind() == OMPC_order) {
4784 Order = cast<OMPOrderClause>(Clause);
4785 if (Order->getKind() != OMPC_ORDER_concurrent)
4786 Order = nullptr;
4788 if (Ordered && Order)
4789 break;
4792 if (Ordered && Order) {
4793 S.Diag(Order->getKindKwLoc(),
4794 diag::err_omp_simple_clause_incompatible_with_ordered)
4795 << getOpenMPClauseName(OMPC_order)
4796 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
4797 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4798 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4799 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4800 return true;
4802 return false;
4805 StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
4806 ArrayRef<OMPClause *> Clauses) {
4807 handleDeclareVariantConstructTrait(DSAStack, DSAStack->getCurrentDirective(),
4808 /* ScopeEntry */ false);
4809 if (DSAStack->getCurrentDirective() == OMPD_atomic ||
4810 DSAStack->getCurrentDirective() == OMPD_critical ||
4811 DSAStack->getCurrentDirective() == OMPD_section ||
4812 DSAStack->getCurrentDirective() == OMPD_master ||
4813 DSAStack->getCurrentDirective() == OMPD_masked)
4814 return S;
4816 bool ErrorFound = false;
4817 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4818 *this, ErrorFound, DSAStack->getCurrentDirective());
4819 if (!S.isUsable()) {
4820 ErrorFound = true;
4821 return StmtError();
4824 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4825 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4826 OMPOrderedClause *OC = nullptr;
4827 OMPScheduleClause *SC = nullptr;
4828 SmallVector<const OMPLinearClause *, 4> LCs;
4829 SmallVector<const OMPClauseWithPreInit *, 4> PICs;
4830 // This is required for proper codegen.
4831 for (OMPClause *Clause : Clauses) {
4832 if (!LangOpts.OpenMPSimd &&
4833 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4834 DSAStack->getCurrentDirective() == OMPD_target) &&
4835 Clause->getClauseKind() == OMPC_in_reduction) {
4836 // Capture taskgroup task_reduction descriptors inside the tasking regions
4837 // with the corresponding in_reduction items.
4838 auto *IRC = cast<OMPInReductionClause>(Clause);
4839 for (Expr *E : IRC->taskgroup_descriptors())
4840 if (E)
4841 MarkDeclarationsReferencedInExpr(E);
4843 if (isOpenMPPrivate(Clause->getClauseKind()) ||
4844 Clause->getClauseKind() == OMPC_copyprivate ||
4845 (getLangOpts().OpenMPUseTLS &&
4846 getASTContext().getTargetInfo().isTLSSupported() &&
4847 Clause->getClauseKind() == OMPC_copyin)) {
4848 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4849 // Mark all variables in private list clauses as used in inner region.
4850 for (Stmt *VarRef : Clause->children()) {
4851 if (auto *E = cast_or_null<Expr>(VarRef)) {
4852 MarkDeclarationsReferencedInExpr(E);
4855 DSAStack->setForceVarCapturing(/*V=*/false);
4856 } else if (isOpenMPLoopTransformationDirective(
4857 DSAStack->getCurrentDirective())) {
4858 assert(CaptureRegions.empty() &&
4859 "No captured regions in loop transformation directives.");
4860 } else if (CaptureRegions.size() > 1 ||
4861 CaptureRegions.back() != OMPD_unknown) {
4862 if (auto *C = OMPClauseWithPreInit::get(Clause))
4863 PICs.push_back(C);
4864 if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
4865 if (Expr *E = C->getPostUpdateExpr())
4866 MarkDeclarationsReferencedInExpr(E);
4869 if (Clause->getClauseKind() == OMPC_schedule)
4870 SC = cast<OMPScheduleClause>(Clause);
4871 else if (Clause->getClauseKind() == OMPC_ordered)
4872 OC = cast<OMPOrderedClause>(Clause);
4873 else if (Clause->getClauseKind() == OMPC_linear)
4874 LCs.push_back(cast<OMPLinearClause>(Clause));
4876 // Capture allocator expressions if used.
4877 for (Expr *E : DSAStack->getInnerAllocators())
4878 MarkDeclarationsReferencedInExpr(E);
4879 // OpenMP, 2.7.1 Loop Construct, Restrictions
4880 // The nonmonotonic modifier cannot be specified if an ordered clause is
4881 // specified.
4882 if (SC &&
4883 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4884 SC->getSecondScheduleModifier() ==
4885 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4886 OC) {
4887 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4888 ? SC->getFirstScheduleModifierLoc()
4889 : SC->getSecondScheduleModifierLoc(),
4890 diag::err_omp_simple_clause_incompatible_with_ordered)
4891 << getOpenMPClauseName(OMPC_schedule)
4892 << getOpenMPSimpleClauseTypeName(OMPC_schedule,
4893 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4894 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4895 ErrorFound = true;
4897 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4898 // If an order(concurrent) clause is present, an ordered clause may not appear
4899 // on the same directive.
4900 if (checkOrderedOrderSpecified(*this, Clauses))
4901 ErrorFound = true;
4902 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4903 for (const OMPLinearClause *C : LCs) {
4904 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
4905 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4907 ErrorFound = true;
4909 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4910 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4911 OC->getNumForLoops()) {
4912 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4913 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
4914 ErrorFound = true;
4916 if (ErrorFound) {
4917 return StmtError();
4919 StmtResult SR = S;
4920 unsigned CompletedRegions = 0;
4921 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
4922 // Mark all variables in private list clauses as used in inner region.
4923 // Required for proper codegen of combined directives.
4924 // TODO: add processing for other clauses.
4925 if (ThisCaptureRegion != OMPD_unknown) {
4926 for (const clang::OMPClauseWithPreInit *C : PICs) {
4927 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4928 // Find the particular capture region for the clause if the
4929 // directive is a combined one with multiple capture regions.
4930 // If the directive is not a combined one, the capture region
4931 // associated with the clause is OMPD_unknown and is generated
4932 // only once.
4933 if (CaptureRegion == ThisCaptureRegion ||
4934 CaptureRegion == OMPD_unknown) {
4935 if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
4936 for (Decl *D : DS->decls())
4937 MarkVariableReferenced(D->getLocation(), cast<VarDecl>(D));
4942 if (ThisCaptureRegion == OMPD_target) {
4943 // Capture allocator traits in the target region. They are used implicitly
4944 // and, thus, are not captured by default.
4945 for (OMPClause *C : Clauses) {
4946 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) {
4947 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4948 ++I) {
4949 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4950 if (Expr *E = D.AllocatorTraits)
4951 MarkDeclarationsReferencedInExpr(E);
4953 continue;
4957 if (ThisCaptureRegion == OMPD_parallel) {
4958 // Capture temp arrays for inscan reductions and locals in aligned
4959 // clauses.
4960 for (OMPClause *C : Clauses) {
4961 if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
4962 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4963 continue;
4964 for (Expr *E : RC->copy_array_temps())
4965 MarkDeclarationsReferencedInExpr(E);
4967 if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
4968 for (Expr *E : AC->varlists())
4969 MarkDeclarationsReferencedInExpr(E);
4973 if (++CompletedRegions == CaptureRegions.size())
4974 DSAStack->setBodyComplete();
4975 SR = ActOnCapturedRegionEnd(SR.get());
4977 return SR;
4980 static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4981 OpenMPDirectiveKind CancelRegion,
4982 SourceLocation StartLoc) {
4983 // CancelRegion is only needed for cancel and cancellation_point.
4984 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4985 return false;
4987 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4988 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4989 return false;
4991 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4992 << getOpenMPDirectiveName(CancelRegion);
4993 return true;
4996 static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
4997 OpenMPDirectiveKind CurrentRegion,
4998 const DeclarationNameInfo &CurrentName,
4999 OpenMPDirectiveKind CancelRegion,
5000 OpenMPBindClauseKind BindKind,
5001 SourceLocation StartLoc) {
5002 if (Stack->getCurScope()) {
5003 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
5004 OpenMPDirectiveKind OffendingRegion = ParentRegion;
5005 bool NestingProhibited = false;
5006 bool CloseNesting = true;
5007 bool OrphanSeen = false;
5008 enum {
5009 NoRecommend,
5010 ShouldBeInParallelRegion,
5011 ShouldBeInOrderedRegion,
5012 ShouldBeInTargetRegion,
5013 ShouldBeInTeamsRegion,
5014 ShouldBeInLoopSimdRegion,
5015 } Recommend = NoRecommend;
5016 if (SemaRef.LangOpts.OpenMP >= 51 && Stack->isParentOrderConcurrent() &&
5017 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_loop &&
5018 CurrentRegion != OMPD_parallel &&
5019 !isOpenMPCombinedParallelADirective(CurrentRegion)) {
5020 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order)
5021 << getOpenMPDirectiveName(CurrentRegion);
5022 return true;
5024 if (isOpenMPSimdDirective(ParentRegion) &&
5025 ((SemaRef.LangOpts.OpenMP <= 45 && CurrentRegion != OMPD_ordered) ||
5026 (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion != OMPD_ordered &&
5027 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
5028 CurrentRegion != OMPD_scan))) {
5029 // OpenMP [2.16, Nesting of Regions]
5030 // OpenMP constructs may not be nested inside a simd region.
5031 // OpenMP [2.8.1,simd Construct, Restrictions]
5032 // An ordered construct with the simd clause is the only OpenMP
5033 // construct that can appear in the simd region.
5034 // Allowing a SIMD construct nested in another SIMD construct is an
5035 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
5036 // message.
5037 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
5038 // The only OpenMP constructs that can be encountered during execution of
5039 // a simd region are the atomic construct, the loop construct, the simd
5040 // construct and the ordered construct with the simd clause.
5041 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
5042 ? diag::err_omp_prohibited_region_simd
5043 : diag::warn_omp_nesting_simd)
5044 << (SemaRef.LangOpts.OpenMP >= 50 ? 1 : 0);
5045 return CurrentRegion != OMPD_simd;
5047 if (ParentRegion == OMPD_atomic) {
5048 // OpenMP [2.16, Nesting of Regions]
5049 // OpenMP constructs may not be nested inside an atomic region.
5050 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
5051 return true;
5053 if (CurrentRegion == OMPD_section) {
5054 // OpenMP [2.7.2, sections Construct, Restrictions]
5055 // Orphaned section directives are prohibited. That is, the section
5056 // directives must appear within the sections construct and must not be
5057 // encountered elsewhere in the sections region.
5058 if (ParentRegion != OMPD_sections &&
5059 ParentRegion != OMPD_parallel_sections) {
5060 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
5061 << (ParentRegion != OMPD_unknown)
5062 << getOpenMPDirectiveName(ParentRegion);
5063 return true;
5065 return false;
5067 // Allow some constructs (except teams and cancellation constructs) to be
5068 // orphaned (they could be used in functions, called from OpenMP regions
5069 // with the required preconditions).
5070 if (ParentRegion == OMPD_unknown &&
5071 !isOpenMPNestingTeamsDirective(CurrentRegion) &&
5072 CurrentRegion != OMPD_cancellation_point &&
5073 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
5074 return false;
5075 if (CurrentRegion == OMPD_cancellation_point ||
5076 CurrentRegion == OMPD_cancel) {
5077 // OpenMP [2.16, Nesting of Regions]
5078 // A cancellation point construct for which construct-type-clause is
5079 // taskgroup must be nested inside a task construct. A cancellation
5080 // point construct for which construct-type-clause is not taskgroup must
5081 // be closely nested inside an OpenMP construct that matches the type
5082 // specified in construct-type-clause.
5083 // A cancel construct for which construct-type-clause is taskgroup must be
5084 // nested inside a task construct. A cancel construct for which
5085 // construct-type-clause is not taskgroup must be closely nested inside an
5086 // OpenMP construct that matches the type specified in
5087 // construct-type-clause.
5088 NestingProhibited =
5089 !((CancelRegion == OMPD_parallel &&
5090 (ParentRegion == OMPD_parallel ||
5091 ParentRegion == OMPD_target_parallel)) ||
5092 (CancelRegion == OMPD_for &&
5093 (ParentRegion == OMPD_for || ParentRegion == OMPD_parallel_for ||
5094 ParentRegion == OMPD_target_parallel_for ||
5095 ParentRegion == OMPD_distribute_parallel_for ||
5096 ParentRegion == OMPD_teams_distribute_parallel_for ||
5097 ParentRegion == OMPD_target_teams_distribute_parallel_for)) ||
5098 (CancelRegion == OMPD_taskgroup &&
5099 (ParentRegion == OMPD_task ||
5100 (SemaRef.getLangOpts().OpenMP >= 50 &&
5101 (ParentRegion == OMPD_taskloop ||
5102 ParentRegion == OMPD_master_taskloop ||
5103 ParentRegion == OMPD_masked_taskloop ||
5104 ParentRegion == OMPD_parallel_masked_taskloop ||
5105 ParentRegion == OMPD_parallel_master_taskloop)))) ||
5106 (CancelRegion == OMPD_sections &&
5107 (ParentRegion == OMPD_section || ParentRegion == OMPD_sections ||
5108 ParentRegion == OMPD_parallel_sections)));
5109 OrphanSeen = ParentRegion == OMPD_unknown;
5110 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5111 // OpenMP 5.1 [2.22, Nesting of Regions]
5112 // A masked region may not be closely nested inside a worksharing, loop,
5113 // atomic, task, or taskloop region.
5114 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5115 isOpenMPGenericLoopDirective(ParentRegion) ||
5116 isOpenMPTaskingDirective(ParentRegion);
5117 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
5118 // OpenMP [2.16, Nesting of Regions]
5119 // A critical region may not be nested (closely or otherwise) inside a
5120 // critical region with the same name. Note that this restriction is not
5121 // sufficient to prevent deadlock.
5122 SourceLocation PreviousCriticalLoc;
5123 bool DeadLock = Stack->hasDirective(
5124 [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
5125 const DeclarationNameInfo &DNI,
5126 SourceLocation Loc) {
5127 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
5128 PreviousCriticalLoc = Loc;
5129 return true;
5131 return false;
5133 false /* skip top directive */);
5134 if (DeadLock) {
5135 SemaRef.Diag(StartLoc,
5136 diag::err_omp_prohibited_region_critical_same_name)
5137 << CurrentName.getName();
5138 if (PreviousCriticalLoc.isValid())
5139 SemaRef.Diag(PreviousCriticalLoc,
5140 diag::note_omp_previous_critical_region);
5141 return true;
5143 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
5144 // OpenMP 5.1 [2.22, Nesting of Regions]
5145 // A scope region may not be closely nested inside a worksharing, loop,
5146 // task, taskloop, critical, ordered, atomic, or masked region.
5147 // OpenMP 5.1 [2.22, Nesting of Regions]
5148 // A barrier region may not be closely nested inside a worksharing, loop,
5149 // task, taskloop, critical, ordered, atomic, or masked region.
5150 NestingProhibited =
5151 isOpenMPWorksharingDirective(ParentRegion) ||
5152 isOpenMPGenericLoopDirective(ParentRegion) ||
5153 isOpenMPTaskingDirective(ParentRegion) ||
5154 ParentRegion == OMPD_master || ParentRegion == OMPD_masked ||
5155 ParentRegion == OMPD_parallel_master ||
5156 ParentRegion == OMPD_parallel_masked ||
5157 ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
5158 } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
5159 !isOpenMPParallelDirective(CurrentRegion) &&
5160 !isOpenMPTeamsDirective(CurrentRegion)) {
5161 // OpenMP 5.1 [2.22, Nesting of Regions]
5162 // A loop region that binds to a parallel region or a worksharing region
5163 // may not be closely nested inside a worksharing, loop, task, taskloop,
5164 // critical, ordered, atomic, or masked region.
5165 NestingProhibited =
5166 isOpenMPWorksharingDirective(ParentRegion) ||
5167 isOpenMPGenericLoopDirective(ParentRegion) ||
5168 isOpenMPTaskingDirective(ParentRegion) ||
5169 ParentRegion == OMPD_master || ParentRegion == OMPD_masked ||
5170 ParentRegion == OMPD_parallel_master ||
5171 ParentRegion == OMPD_parallel_masked ||
5172 ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
5173 Recommend = ShouldBeInParallelRegion;
5174 } else if (CurrentRegion == OMPD_ordered) {
5175 // OpenMP [2.16, Nesting of Regions]
5176 // An ordered region may not be closely nested inside a critical,
5177 // atomic, or explicit task region.
5178 // An ordered region must be closely nested inside a loop region (or
5179 // parallel loop region) with an ordered clause.
5180 // OpenMP [2.8.1,simd Construct, Restrictions]
5181 // An ordered construct with the simd clause is the only OpenMP construct
5182 // that can appear in the simd region.
5183 NestingProhibited = ParentRegion == OMPD_critical ||
5184 isOpenMPTaskingDirective(ParentRegion) ||
5185 !(isOpenMPSimdDirective(ParentRegion) ||
5186 Stack->isParentOrderedRegion());
5187 Recommend = ShouldBeInOrderedRegion;
5188 } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
5189 // OpenMP [2.16, Nesting of Regions]
5190 // If specified, a teams construct must be contained within a target
5191 // construct.
5192 NestingProhibited =
5193 (SemaRef.LangOpts.OpenMP <= 45 && ParentRegion != OMPD_target) ||
5194 (SemaRef.LangOpts.OpenMP >= 50 && ParentRegion != OMPD_unknown &&
5195 ParentRegion != OMPD_target);
5196 OrphanSeen = ParentRegion == OMPD_unknown;
5197 Recommend = ShouldBeInTargetRegion;
5198 } else if (CurrentRegion == OMPD_scan) {
5199 // OpenMP [2.16, Nesting of Regions]
5200 // If specified, a teams construct must be contained within a target
5201 // construct.
5202 NestingProhibited =
5203 SemaRef.LangOpts.OpenMP < 50 ||
5204 (ParentRegion != OMPD_simd && ParentRegion != OMPD_for &&
5205 ParentRegion != OMPD_for_simd && ParentRegion != OMPD_parallel_for &&
5206 ParentRegion != OMPD_parallel_for_simd);
5207 OrphanSeen = ParentRegion == OMPD_unknown;
5208 Recommend = ShouldBeInLoopSimdRegion;
5210 if (!NestingProhibited &&
5211 !isOpenMPTargetExecutionDirective(CurrentRegion) &&
5212 !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
5213 (ParentRegion == OMPD_teams || ParentRegion == OMPD_target_teams)) {
5214 // OpenMP [5.1, 2.22, Nesting of Regions]
5215 // distribute, distribute simd, distribute parallel worksharing-loop,
5216 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5217 // including any parallel regions arising from combined constructs,
5218 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5219 // only OpenMP regions that may be strictly nested inside the teams
5220 // region.
5222 // As an extension, we permit atomic within teams as well.
5223 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
5224 !isOpenMPDistributeDirective(CurrentRegion) &&
5225 CurrentRegion != OMPD_loop &&
5226 !(SemaRef.getLangOpts().OpenMPExtensions &&
5227 CurrentRegion == OMPD_atomic);
5228 Recommend = ShouldBeInParallelRegion;
5230 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5231 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5232 // If the bind clause is present on the loop construct and binding is
5233 // teams then the corresponding loop region must be strictly nested inside
5234 // a teams region.
5235 NestingProhibited = BindKind == OMPC_BIND_teams &&
5236 ParentRegion != OMPD_teams &&
5237 ParentRegion != OMPD_target_teams;
5238 Recommend = ShouldBeInTeamsRegion;
5240 if (!NestingProhibited &&
5241 isOpenMPNestingDistributeDirective(CurrentRegion)) {
5242 // OpenMP 4.5 [2.17 Nesting of Regions]
5243 // The region associated with the distribute construct must be strictly
5244 // nested inside a teams region
5245 NestingProhibited =
5246 (ParentRegion != OMPD_teams && ParentRegion != OMPD_target_teams);
5247 Recommend = ShouldBeInTeamsRegion;
5249 if (!NestingProhibited &&
5250 (isOpenMPTargetExecutionDirective(CurrentRegion) ||
5251 isOpenMPTargetDataManagementDirective(CurrentRegion))) {
5252 // OpenMP 4.5 [2.17 Nesting of Regions]
5253 // If a target, target update, target data, target enter data, or
5254 // target exit data construct is encountered during execution of a
5255 // target region, the behavior is unspecified.
5256 NestingProhibited = Stack->hasDirective(
5257 [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5258 SourceLocation) {
5259 if (isOpenMPTargetExecutionDirective(K)) {
5260 OffendingRegion = K;
5261 return true;
5263 return false;
5265 false /* don't skip top directive */);
5266 CloseNesting = false;
5268 if (NestingProhibited) {
5269 if (OrphanSeen) {
5270 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5271 << getOpenMPDirectiveName(CurrentRegion) << Recommend;
5272 } else {
5273 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5274 << CloseNesting << getOpenMPDirectiveName(OffendingRegion)
5275 << Recommend << getOpenMPDirectiveName(CurrentRegion);
5277 return true;
5280 return false;
5283 struct Kind2Unsigned {
5284 using argument_type = OpenMPDirectiveKind;
5285 unsigned operator()(argument_type DK) { return unsigned(DK); }
5287 static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind,
5288 ArrayRef<OMPClause *> Clauses,
5289 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5290 bool ErrorFound = false;
5291 unsigned NamedModifiersNumber = 0;
5292 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5293 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5294 SmallVector<SourceLocation, 4> NameModifierLoc;
5295 for (const OMPClause *C : Clauses) {
5296 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
5297 // At most one if clause without a directive-name-modifier can appear on
5298 // the directive.
5299 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5300 if (FoundNameModifiers[CurNM]) {
5301 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5302 << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if)
5303 << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM);
5304 ErrorFound = true;
5305 } else if (CurNM != OMPD_unknown) {
5306 NameModifierLoc.push_back(IC->getNameModifierLoc());
5307 ++NamedModifiersNumber;
5309 FoundNameModifiers[CurNM] = IC;
5310 if (CurNM == OMPD_unknown)
5311 continue;
5312 // Check if the specified name modifier is allowed for the current
5313 // directive.
5314 // At most one if clause with the particular directive-name-modifier can
5315 // appear on the directive.
5316 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5317 S.Diag(IC->getNameModifierLoc(),
5318 diag::err_omp_wrong_if_directive_name_modifier)
5319 << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind);
5320 ErrorFound = true;
5324 // If any if clause on the directive includes a directive-name-modifier then
5325 // all if clauses on the directive must include a directive-name-modifier.
5326 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5327 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5328 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5329 diag::err_omp_no_more_if_clause);
5330 } else {
5331 std::string Values;
5332 std::string Sep(", ");
5333 unsigned AllowedCnt = 0;
5334 unsigned TotalAllowedNum =
5335 AllowedNameModifiers.size() - NamedModifiersNumber;
5336 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5337 ++Cnt) {
5338 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5339 if (!FoundNameModifiers[NM]) {
5340 Values += "'";
5341 Values += getOpenMPDirectiveName(NM);
5342 Values += "'";
5343 if (AllowedCnt + 2 == TotalAllowedNum)
5344 Values += " or ";
5345 else if (AllowedCnt + 1 != TotalAllowedNum)
5346 Values += Sep;
5347 ++AllowedCnt;
5350 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5351 diag::err_omp_unnamed_if_clause)
5352 << (TotalAllowedNum > 1) << Values;
5354 for (SourceLocation Loc : NameModifierLoc) {
5355 S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5357 ErrorFound = true;
5359 return ErrorFound;
5362 static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr,
5363 SourceLocation &ELoc,
5364 SourceRange &ERange,
5365 bool AllowArraySection,
5366 StringRef DiagType) {
5367 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5368 RefExpr->containsUnexpandedParameterPack())
5369 return std::make_pair(nullptr, true);
5371 // OpenMP [3.1, C/C++]
5372 // A list item is a variable name.
5373 // OpenMP [2.9.3.3, Restrictions, p.1]
5374 // A variable that is part of another variable (as an array or
5375 // structure element) cannot appear in a private clause.
5376 RefExpr = RefExpr->IgnoreParens();
5377 enum {
5378 NoArrayExpr = -1,
5379 ArraySubscript = 0,
5380 OMPArraySection = 1
5381 } IsArrayExpr = NoArrayExpr;
5382 if (AllowArraySection) {
5383 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5384 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5385 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5386 Base = TempASE->getBase()->IgnoreParenImpCasts();
5387 RefExpr = Base;
5388 IsArrayExpr = ArraySubscript;
5389 } else if (auto *OASE = dyn_cast_or_null<OMPArraySectionExpr>(RefExpr)) {
5390 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5391 while (auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
5392 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5393 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5394 Base = TempASE->getBase()->IgnoreParenImpCasts();
5395 RefExpr = Base;
5396 IsArrayExpr = OMPArraySection;
5399 ELoc = RefExpr->getExprLoc();
5400 ERange = RefExpr->getSourceRange();
5401 RefExpr = RefExpr->IgnoreParenImpCasts();
5402 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5403 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5404 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5405 (S.getCurrentThisType().isNull() || !ME ||
5406 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5407 !isa<FieldDecl>(ME->getMemberDecl()))) {
5408 if (IsArrayExpr != NoArrayExpr) {
5409 S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5410 << IsArrayExpr << ERange;
5411 } else if (!DiagType.empty()) {
5412 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5413 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5414 : 0;
5415 S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5416 << DiagSelect << DiagType << ERange;
5417 } else {
5418 S.Diag(ELoc,
5419 AllowArraySection
5420 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5421 : diag::err_omp_expected_var_name_member_expr)
5422 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5424 return std::make_pair(nullptr, false);
5426 return std::make_pair(
5427 getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
5430 namespace {
5431 /// Checks if the allocator is used in uses_allocators clause to be allowed in
5432 /// target regions.
5433 class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5434 DSAStackTy *S = nullptr;
5436 public:
5437 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5438 return S->isUsesAllocatorsDecl(E->getDecl())
5439 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5440 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5442 bool VisitStmt(const Stmt *S) {
5443 for (const Stmt *Child : S->children()) {
5444 if (Child && Visit(Child))
5445 return true;
5447 return false;
5449 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5451 } // namespace
5453 static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5454 ArrayRef<OMPClause *> Clauses) {
5455 assert(!S.CurContext->isDependentContext() &&
5456 "Expected non-dependent context.");
5457 auto AllocateRange =
5458 llvm::make_filter_range(Clauses, OMPAllocateClause::classof);
5459 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5460 auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) {
5461 return isOpenMPPrivate(C->getClauseKind());
5463 for (OMPClause *Cl : PrivateRange) {
5464 MutableArrayRef<Expr *>::iterator I, It, Et;
5465 if (Cl->getClauseKind() == OMPC_private) {
5466 auto *PC = cast<OMPPrivateClause>(Cl);
5467 I = PC->private_copies().begin();
5468 It = PC->varlist_begin();
5469 Et = PC->varlist_end();
5470 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5471 auto *PC = cast<OMPFirstprivateClause>(Cl);
5472 I = PC->private_copies().begin();
5473 It = PC->varlist_begin();
5474 Et = PC->varlist_end();
5475 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5476 auto *PC = cast<OMPLastprivateClause>(Cl);
5477 I = PC->private_copies().begin();
5478 It = PC->varlist_begin();
5479 Et = PC->varlist_end();
5480 } else if (Cl->getClauseKind() == OMPC_linear) {
5481 auto *PC = cast<OMPLinearClause>(Cl);
5482 I = PC->privates().begin();
5483 It = PC->varlist_begin();
5484 Et = PC->varlist_end();
5485 } else if (Cl->getClauseKind() == OMPC_reduction) {
5486 auto *PC = cast<OMPReductionClause>(Cl);
5487 I = PC->privates().begin();
5488 It = PC->varlist_begin();
5489 Et = PC->varlist_end();
5490 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5491 auto *PC = cast<OMPTaskReductionClause>(Cl);
5492 I = PC->privates().begin();
5493 It = PC->varlist_begin();
5494 Et = PC->varlist_end();
5495 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5496 auto *PC = cast<OMPInReductionClause>(Cl);
5497 I = PC->privates().begin();
5498 It = PC->varlist_begin();
5499 Et = PC->varlist_end();
5500 } else {
5501 llvm_unreachable("Expected private clause.");
5503 for (Expr *E : llvm::make_range(It, Et)) {
5504 if (!*I) {
5505 ++I;
5506 continue;
5508 SourceLocation ELoc;
5509 SourceRange ERange;
5510 Expr *SimpleRefExpr = E;
5511 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
5512 /*AllowArraySection=*/true);
5513 DeclToCopy.try_emplace(Res.first,
5514 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5515 ++I;
5518 for (OMPClause *C : AllocateRange) {
5519 auto *AC = cast<OMPAllocateClause>(C);
5520 if (S.getLangOpts().OpenMP >= 50 &&
5521 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5522 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
5523 AC->getAllocator()) {
5524 Expr *Allocator = AC->getAllocator();
5525 // OpenMP, 2.12.5 target Construct
5526 // Memory allocators that do not appear in a uses_allocators clause cannot
5527 // appear as an allocator in an allocate clause or be used in the target
5528 // region unless a requires directive with the dynamic_allocators clause
5529 // is present in the same compilation unit.
5530 AllocatorChecker Checker(Stack);
5531 if (Checker.Visit(Allocator))
5532 S.Diag(Allocator->getExprLoc(),
5533 diag::err_omp_allocator_not_in_uses_allocators)
5534 << Allocator->getSourceRange();
5536 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5537 getAllocatorKind(S, Stack, AC->getAllocator());
5538 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5539 // For task, taskloop or target directives, allocation requests to memory
5540 // allocators with the trait access set to thread result in unspecified
5541 // behavior.
5542 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5543 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
5544 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
5545 S.Diag(AC->getAllocator()->getExprLoc(),
5546 diag::warn_omp_allocate_thread_on_task_target_directive)
5547 << getOpenMPDirectiveName(Stack->getCurrentDirective());
5549 for (Expr *E : AC->varlists()) {
5550 SourceLocation ELoc;
5551 SourceRange ERange;
5552 Expr *SimpleRefExpr = E;
5553 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
5554 ValueDecl *VD = Res.first;
5555 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
5556 if (!isOpenMPPrivate(Data.CKind)) {
5557 S.Diag(E->getExprLoc(),
5558 diag::err_omp_expected_private_copy_for_allocate);
5559 continue;
5561 VarDecl *PrivateVD = DeclToCopy[VD];
5562 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5563 AllocatorKind, AC->getAllocator()))
5564 continue;
5565 // Placeholder until allocate clause supports align modifier.
5566 Expr *Alignment = nullptr;
5567 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5568 Alignment, E->getSourceRange());
5573 namespace {
5574 /// Rewrite statements and expressions for Sema \p Actions CurContext.
5576 /// Used to wrap already parsed statements/expressions into a new CapturedStmt
5577 /// context. DeclRefExpr used inside the new context are changed to refer to the
5578 /// captured variable instead.
5579 class CaptureVars : public TreeTransform<CaptureVars> {
5580 using BaseTransform = TreeTransform<CaptureVars>;
5582 public:
5583 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5585 bool AlwaysRebuild() { return true; }
5587 } // namespace
5589 static VarDecl *precomputeExpr(Sema &Actions,
5590 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5591 StringRef Name) {
5592 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
5593 VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
5594 dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
5595 auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
5596 Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
5597 Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
5598 BodyStmts.push_back(NewDeclStmt);
5599 return NewVar;
5602 /// Create a closure that computes the number of iterations of a loop.
5604 /// \param Actions The Sema object.
5605 /// \param LogicalTy Type for the logical iteration number.
5606 /// \param Rel Comparison operator of the loop condition.
5607 /// \param StartExpr Value of the loop counter at the first iteration.
5608 /// \param StopExpr Expression the loop counter is compared against in the loop
5609 /// condition. \param StepExpr Amount of increment after each iteration.
5611 /// \return Closure (CapturedStmt) of the distance calculation.
5612 static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5613 BinaryOperator::Opcode Rel,
5614 Expr *StartExpr, Expr *StopExpr,
5615 Expr *StepExpr) {
5616 ASTContext &Ctx = Actions.getASTContext();
5617 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
5619 // Captured regions currently don't support return values, we use an
5620 // out-parameter instead. All inputs are implicit captures.
5621 // TODO: Instead of capturing each DeclRefExpr occurring in
5622 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5623 QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
5624 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5625 {StringRef(), QualType()}};
5626 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5628 Stmt *Body;
5630 Sema::CompoundScopeRAII CompoundScope(Actions);
5631 CapturedDecl *CS = cast<CapturedDecl>(Actions.CurContext);
5633 // Get the LValue expression for the result.
5634 ImplicitParamDecl *DistParam = CS->getParam(0);
5635 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5636 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5638 SmallVector<Stmt *, 4> BodyStmts;
5640 // Capture all referenced variable references.
5641 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5642 // CapturedStmt, we could compute them before and capture the result, to be
5643 // used jointly with the LoopVar function.
5644 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
5645 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
5646 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
5647 auto BuildVarRef = [&](VarDecl *VD) {
5648 return buildDeclRefExpr(Actions, VD, VD->getType(), {});
5651 IntegerLiteral *Zero = IntegerLiteral::Create(
5652 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
5653 IntegerLiteral *One = IntegerLiteral::Create(
5654 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5655 Expr *Dist;
5656 if (Rel == BO_NE) {
5657 // When using a != comparison, the increment can be +1 or -1. This can be
5658 // dynamic at runtime, so we need to check for the direction.
5659 Expr *IsNegStep = AssertSuccess(
5660 Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5662 // Positive increment.
5663 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
5664 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5665 ForwardRange = AssertSuccess(
5666 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
5667 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
5668 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5670 // Negative increment.
5671 Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
5672 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5673 BackwardRange = AssertSuccess(
5674 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange));
5675 Expr *NegIncAmount = AssertSuccess(
5676 Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5677 Expr *BackwardDist = AssertSuccess(
5678 Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5680 // Use the appropriate case.
5681 Dist = AssertSuccess(Actions.ActOnConditionalOp(
5682 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5683 } else {
5684 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5685 "Expected one of these relational operators");
5687 // We can derive the direction from any other comparison operator. It is
5688 // non well-formed OpenMP if Step increments/decrements in the other
5689 // directions. Whether at least the first iteration passes the loop
5690 // condition.
5691 Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
5692 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5694 // Compute the range between first and last counter value.
5695 Expr *Range;
5696 if (Rel == BO_GE || Rel == BO_GT)
5697 Range = AssertSuccess(Actions.BuildBinOp(
5698 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5699 else
5700 Range = AssertSuccess(Actions.BuildBinOp(
5701 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5703 // Ensure unsigned range space.
5704 Range =
5705 AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range));
5707 if (Rel == BO_LE || Rel == BO_GE) {
5708 // Add one to the range if the relational operator is inclusive.
5709 Range =
5710 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One));
5713 // Divide by the absolute step amount. If the range is not a multiple of
5714 // the step size, rounding-up the effective upper bound ensures that the
5715 // last iteration is included.
5716 // Note that the rounding-up may cause an overflow in a temporry that
5717 // could be avoided, but would have occurred in a C-style for-loop as
5718 // well.
5719 Expr *Divisor = BuildVarRef(NewStep);
5720 if (Rel == BO_GE || Rel == BO_GT)
5721 Divisor =
5722 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor));
5723 Expr *DivisorMinusOne =
5724 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One));
5725 Expr *RangeRoundUp = AssertSuccess(
5726 Actions.BuildBinOp(nullptr, {}, BO_Add, Range, DivisorMinusOne));
5727 Dist = AssertSuccess(
5728 Actions.BuildBinOp(nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5730 // If there is not at least one iteration, the range contains garbage. Fix
5731 // to zero in this case.
5732 Dist = AssertSuccess(
5733 Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
5736 // Assign the result to the out-parameter.
5737 Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp(
5738 Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
5739 BodyStmts.push_back(ResultAssign);
5741 Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false));
5744 return cast<CapturedStmt>(
5745 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5748 /// Create a closure that computes the loop variable from the logical iteration
5749 /// number.
5751 /// \param Actions The Sema object.
5752 /// \param LoopVarTy Type for the loop variable used for result value.
5753 /// \param LogicalTy Type for the logical iteration number.
5754 /// \param StartExpr Value of the loop counter at the first iteration.
5755 /// \param Step Amount of increment after each iteration.
5756 /// \param Deref Whether the loop variable is a dereference of the loop
5757 /// counter variable.
5759 /// \return Closure (CapturedStmt) of the loop value calculation.
5760 static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5761 QualType LogicalTy,
5762 DeclRefExpr *StartExpr, Expr *Step,
5763 bool Deref) {
5764 ASTContext &Ctx = Actions.getASTContext();
5766 // Pass the result as an out-parameter. Passing as return value would require
5767 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5768 // invoke a copy constructor.
5769 QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy);
5770 Sema::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5771 {"Logical", LogicalTy},
5772 {StringRef(), QualType()}};
5773 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5775 // Capture the initial iterator which represents the LoopVar value at the
5776 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5777 // it in every iteration, capture it by value before it is modified.
5778 VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl());
5779 bool Invalid = Actions.tryCaptureVariable(StartVar, {},
5780 Sema::TryCapture_ExplicitByVal, {});
5781 (void)Invalid;
5782 assert(!Invalid && "Expecting capture-by-value to work.");
5784 Expr *Body;
5786 Sema::CompoundScopeRAII CompoundScope(Actions);
5787 auto *CS = cast<CapturedDecl>(Actions.CurContext);
5789 ImplicitParamDecl *TargetParam = CS->getParam(0);
5790 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5791 TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5792 ImplicitParamDecl *IndvarParam = CS->getParam(1);
5793 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5794 IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5796 // Capture the Start expression.
5797 CaptureVars Recap(Actions);
5798 Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
5799 Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
5801 Expr *Skip = AssertSuccess(
5802 Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
5803 // TODO: Explicitly cast to the iterator's difference_type instead of
5804 // relying on implicit conversion.
5805 Expr *Advanced =
5806 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip));
5808 if (Deref) {
5809 // For range-based for-loops convert the loop counter value to a concrete
5810 // loop variable value by dereferencing the iterator.
5811 Advanced =
5812 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced));
5815 // Assign the result to the output parameter.
5816 Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {},
5817 BO_Assign, TargetRef, Advanced));
5819 return cast<CapturedStmt>(
5820 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5823 StmtResult Sema::ActOnOpenMPCanonicalLoop(Stmt *AStmt) {
5824 ASTContext &Ctx = getASTContext();
5826 // Extract the common elements of ForStmt and CXXForRangeStmt:
5827 // Loop variable, repeat condition, increment
5828 Expr *Cond, *Inc;
5829 VarDecl *LIVDecl, *LUVDecl;
5830 if (auto *For = dyn_cast<ForStmt>(AStmt)) {
5831 Stmt *Init = For->getInit();
5832 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) {
5833 // For statement declares loop variable.
5834 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5835 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) {
5836 // For statement reuses variable.
5837 assert(LCAssign->getOpcode() == BO_Assign &&
5838 "init part must be a loop variable assignment");
5839 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5840 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5841 } else
5842 llvm_unreachable("Cannot determine loop variable");
5843 LUVDecl = LIVDecl;
5845 Cond = For->getCond();
5846 Inc = For->getInc();
5847 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5848 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5849 LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl());
5850 LUVDecl = RangeFor->getLoopVariable();
5852 Cond = RangeFor->getCond();
5853 Inc = RangeFor->getInc();
5854 } else
5855 llvm_unreachable("unhandled kind of loop");
5857 QualType CounterTy = LIVDecl->getType();
5858 QualType LVTy = LUVDecl->getType();
5860 // Analyze the loop condition.
5861 Expr *LHS, *RHS;
5862 BinaryOperator::Opcode CondRel;
5863 Cond = Cond->IgnoreImplicit();
5864 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5865 LHS = CondBinExpr->getLHS();
5866 RHS = CondBinExpr->getRHS();
5867 CondRel = CondBinExpr->getOpcode();
5868 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5869 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5870 LHS = CondCXXOp->getArg(0);
5871 RHS = CondCXXOp->getArg(1);
5872 switch (CondCXXOp->getOperator()) {
5873 case OO_ExclaimEqual:
5874 CondRel = BO_NE;
5875 break;
5876 case OO_Less:
5877 CondRel = BO_LT;
5878 break;
5879 case OO_LessEqual:
5880 CondRel = BO_LE;
5881 break;
5882 case OO_Greater:
5883 CondRel = BO_GT;
5884 break;
5885 case OO_GreaterEqual:
5886 CondRel = BO_GE;
5887 break;
5888 default:
5889 llvm_unreachable("unexpected iterator operator");
5891 } else
5892 llvm_unreachable("unexpected loop condition");
5894 // Normalize such that the loop counter is on the LHS.
5895 if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) ||
5896 cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5897 std::swap(LHS, RHS);
5898 CondRel = BinaryOperator::reverseComparisonOp(CondRel);
5900 auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit());
5902 // Decide the bit width for the logical iteration counter. By default use the
5903 // unsigned ptrdiff_t integer size (for iterators and pointers).
5904 // TODO: For iterators, use iterator::difference_type,
5905 // std::iterator_traits<>::difference_type or decltype(it - end).
5906 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5907 if (CounterTy->isIntegerType()) {
5908 unsigned BitWidth = Ctx.getIntWidth(CounterTy);
5909 LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false);
5912 // Analyze the loop increment.
5913 Expr *Step;
5914 if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5915 int Direction;
5916 switch (IncUn->getOpcode()) {
5917 case UO_PreInc:
5918 case UO_PostInc:
5919 Direction = 1;
5920 break;
5921 case UO_PreDec:
5922 case UO_PostDec:
5923 Direction = -1;
5924 break;
5925 default:
5926 llvm_unreachable("unhandled unary increment operator");
5928 Step = IntegerLiteral::Create(
5929 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction), LogicalTy, {});
5930 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5931 if (IncBin->getOpcode() == BO_AddAssign) {
5932 Step = IncBin->getRHS();
5933 } else if (IncBin->getOpcode() == BO_SubAssign) {
5934 Step =
5935 AssertSuccess(BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS()));
5936 } else
5937 llvm_unreachable("unhandled binary increment operator");
5938 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5939 switch (CondCXXOp->getOperator()) {
5940 case OO_PlusPlus:
5941 Step = IntegerLiteral::Create(
5942 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5943 break;
5944 case OO_MinusMinus:
5945 Step = IntegerLiteral::Create(
5946 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
5947 break;
5948 case OO_PlusEqual:
5949 Step = CondCXXOp->getArg(1);
5950 break;
5951 case OO_MinusEqual:
5952 Step = AssertSuccess(
5953 BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5954 break;
5955 default:
5956 llvm_unreachable("unhandled overloaded increment operator");
5958 } else
5959 llvm_unreachable("unknown increment expression");
5961 CapturedStmt *DistanceFunc =
5962 buildDistanceFunc(*this, LogicalTy, CondRel, LHS, RHS, Step);
5963 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
5964 *this, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
5965 DeclRefExpr *LVRef = BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue,
5966 {}, nullptr, nullptr, {}, nullptr);
5967 return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc,
5968 LoopVarFunc, LVRef);
5971 StmtResult Sema::ActOnOpenMPLoopnest(Stmt *AStmt) {
5972 // Handle a literal loop.
5973 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
5974 return ActOnOpenMPCanonicalLoop(AStmt);
5976 // If not a literal loop, it must be the result of a loop transformation.
5977 OMPExecutableDirective *LoopTransform = cast<OMPExecutableDirective>(AStmt);
5978 assert(
5979 isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) &&
5980 "Loop transformation directive expected");
5981 return LoopTransform;
5984 static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
5985 CXXScopeSpec &MapperIdScopeSpec,
5986 const DeclarationNameInfo &MapperId,
5987 QualType Type,
5988 Expr *UnresolvedMapper);
5990 /// Perform DFS through the structure/class data members trying to find
5991 /// member(s) with user-defined 'default' mapper and generate implicit map
5992 /// clauses for such members with the found 'default' mapper.
5993 static void
5994 processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack,
5995 SmallVectorImpl<OMPClause *> &Clauses) {
5996 // Check for the deault mapper for data members.
5997 if (S.getLangOpts().OpenMP < 50)
5998 return;
5999 SmallVector<OMPClause *, 4> ImplicitMaps;
6000 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
6001 auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
6002 if (!C)
6003 continue;
6004 SmallVector<Expr *, 4> SubExprs;
6005 auto *MI = C->mapperlist_begin();
6006 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
6007 ++I, ++MI) {
6008 // Expression is mapped using mapper - skip it.
6009 if (*MI)
6010 continue;
6011 Expr *E = *I;
6012 // Expression is dependent - skip it, build the mapper when it gets
6013 // instantiated.
6014 if (E->isTypeDependent() || E->isValueDependent() ||
6015 E->containsUnexpandedParameterPack())
6016 continue;
6017 // Array section - need to check for the mapping of the array section
6018 // element.
6019 QualType CanonType = E->getType().getCanonicalType();
6020 if (CanonType->isSpecificBuiltinType(BuiltinType::OMPArraySection)) {
6021 const auto *OASE = cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts());
6022 QualType BaseType =
6023 OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
6024 QualType ElemType;
6025 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
6026 ElemType = ATy->getElementType();
6027 else
6028 ElemType = BaseType->getPointeeType();
6029 CanonType = ElemType;
6032 // DFS over data members in structures/classes.
6033 SmallVector<std::pair<QualType, FieldDecl *>, 4> Types(
6034 1, {CanonType, nullptr});
6035 llvm::DenseMap<const Type *, Expr *> Visited;
6036 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(
6037 1, {nullptr, 1});
6038 while (!Types.empty()) {
6039 QualType BaseType;
6040 FieldDecl *CurFD;
6041 std::tie(BaseType, CurFD) = Types.pop_back_val();
6042 while (ParentChain.back().second == 0)
6043 ParentChain.pop_back();
6044 --ParentChain.back().second;
6045 if (BaseType.isNull())
6046 continue;
6047 // Only structs/classes are allowed to have mappers.
6048 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
6049 if (!RD)
6050 continue;
6051 auto It = Visited.find(BaseType.getTypePtr());
6052 if (It == Visited.end()) {
6053 // Try to find the associated user-defined mapper.
6054 CXXScopeSpec MapperIdScopeSpec;
6055 DeclarationNameInfo DefaultMapperId;
6056 DefaultMapperId.setName(S.Context.DeclarationNames.getIdentifier(
6057 &S.Context.Idents.get("default")));
6058 DefaultMapperId.setLoc(E->getExprLoc());
6059 ExprResult ER = buildUserDefinedMapperRef(
6060 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
6061 BaseType, /*UnresolvedMapper=*/nullptr);
6062 if (ER.isInvalid())
6063 continue;
6064 It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first;
6066 // Found default mapper.
6067 if (It->second) {
6068 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
6069 VK_LValue, OK_Ordinary, E);
6070 OE->setIsUnique(/*V=*/true);
6071 Expr *BaseExpr = OE;
6072 for (const auto &P : ParentChain) {
6073 if (P.first) {
6074 BaseExpr = S.BuildMemberExpr(
6075 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6076 NestedNameSpecifierLoc(), SourceLocation(), P.first,
6077 DeclAccessPair::make(P.first, P.first->getAccess()),
6078 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6079 P.first->getType(), VK_LValue, OK_Ordinary);
6080 BaseExpr = S.DefaultLvalueConversion(BaseExpr).get();
6083 if (CurFD)
6084 BaseExpr = S.BuildMemberExpr(
6085 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6086 NestedNameSpecifierLoc(), SourceLocation(), CurFD,
6087 DeclAccessPair::make(CurFD, CurFD->getAccess()),
6088 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6089 CurFD->getType(), VK_LValue, OK_Ordinary);
6090 SubExprs.push_back(BaseExpr);
6091 continue;
6093 // Check for the "default" mapper for data members.
6094 bool FirstIter = true;
6095 for (FieldDecl *FD : RD->fields()) {
6096 if (!FD)
6097 continue;
6098 QualType FieldTy = FD->getType();
6099 if (FieldTy.isNull() ||
6100 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
6101 continue;
6102 if (FirstIter) {
6103 FirstIter = false;
6104 ParentChain.emplace_back(CurFD, 1);
6105 } else {
6106 ++ParentChain.back().second;
6108 Types.emplace_back(FieldTy, FD);
6112 if (SubExprs.empty())
6113 continue;
6114 CXXScopeSpec MapperIdScopeSpec;
6115 DeclarationNameInfo MapperId;
6116 if (OMPClause *NewClause = S.ActOnOpenMPMapClause(
6117 nullptr, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(),
6118 MapperIdScopeSpec, MapperId, C->getMapType(),
6119 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6120 SubExprs, OMPVarListLocTy()))
6121 Clauses.push_back(NewClause);
6125 bool Sema::mapLoopConstruct(llvm::SmallVector<OMPClause *> &ClausesWithoutBind,
6126 ArrayRef<OMPClause *> Clauses,
6127 OpenMPBindClauseKind BindKind,
6128 OpenMPDirectiveKind &Kind,
6129 OpenMPDirectiveKind &PrevMappedDirective) {
6131 bool UseClausesWithoutBind = false;
6133 // Restricting to "#pragma omp loop bind"
6134 if (getLangOpts().OpenMP >= 50 && Kind == OMPD_loop) {
6135 if (BindKind == OMPC_BIND_unknown) {
6136 // Setting the enclosing teams or parallel construct for the loop
6137 // directive without bind clause.
6138 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
6140 const OpenMPDirectiveKind ParentDirective =
6141 DSAStack->getParentDirective();
6142 if (ParentDirective == OMPD_unknown) {
6143 Diag(DSAStack->getDefaultDSALocation(),
6144 diag::err_omp_bind_required_on_loop);
6145 } else if (ParentDirective == OMPD_parallel ||
6146 ParentDirective == OMPD_target_parallel) {
6147 BindKind = OMPC_BIND_parallel;
6148 } else if (ParentDirective == OMPD_teams ||
6149 ParentDirective == OMPD_target_teams) {
6150 BindKind = OMPC_BIND_teams;
6152 } else {
6153 // bind clause is present, so we should set flag indicating to only
6154 // use the clauses that aren't the bind clause for the new directive that
6155 // loop is lowered to.
6156 UseClausesWithoutBind = true;
6159 for (OMPClause *C : Clauses) {
6160 // Spec restriction : bind(teams) and reduction not permitted.
6161 if (BindKind == OMPC_BIND_teams &&
6162 C->getClauseKind() == llvm::omp::Clause::OMPC_reduction)
6163 Diag(DSAStack->getDefaultDSALocation(),
6164 diag::err_omp_loop_reduction_clause);
6166 // A new Vector ClausesWithoutBind, which does not contain the bind
6167 // clause, for passing to new directive.
6168 if (C->getClauseKind() != llvm::omp::Clause::OMPC_bind)
6169 ClausesWithoutBind.push_back(C);
6172 switch (BindKind) {
6173 case OMPC_BIND_parallel:
6174 Kind = OMPD_for;
6175 DSAStack->setCurrentDirective(OMPD_for);
6176 DSAStack->setMappedDirective(OMPD_loop);
6177 PrevMappedDirective = OMPD_loop;
6178 break;
6179 case OMPC_BIND_teams:
6180 Kind = OMPD_distribute;
6181 DSAStack->setCurrentDirective(OMPD_distribute);
6182 DSAStack->setMappedDirective(OMPD_loop);
6183 PrevMappedDirective = OMPD_loop;
6184 break;
6185 case OMPC_BIND_thread:
6186 Kind = OMPD_simd;
6187 DSAStack->setCurrentDirective(OMPD_simd);
6188 DSAStack->setMappedDirective(OMPD_loop);
6189 PrevMappedDirective = OMPD_loop;
6190 break;
6191 case OMPC_BIND_unknown:
6192 break;
6194 } else if (PrevMappedDirective == OMPD_loop) {
6195 /// An initial pass after recognizing all the statements is done in the
6196 /// Parser when the directive OMPD_loop is mapped to OMPD_for,
6197 /// OMPD_distribute or OMPD_simd. A second transform pass with call from
6198 /// clang::TreeTransform::TransformOMPExecutableDirective() is done
6199 /// with the Directive as one of the above mapped directive without
6200 /// the bind clause. Then "PrevMappedDirective" stored in the
6201 /// OMPExecutableDirective is accessed and hence this else statement.
6203 DSAStack->setMappedDirective(OMPD_loop);
6206 return UseClausesWithoutBind;
6209 StmtResult Sema::ActOnOpenMPExecutableDirective(
6210 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6211 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
6212 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc,
6213 OpenMPDirectiveKind PrevMappedDirective) {
6214 StmtResult Res = StmtError();
6215 OpenMPBindClauseKind BindKind = OMPC_BIND_unknown;
6216 if (const OMPBindClause *BC =
6217 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6218 BindKind = BC->getBindKind();
6219 // First check CancelRegion which is then used in checkNestingOfRegions.
6220 if (checkCancelRegion(*this, Kind, CancelRegion, StartLoc) ||
6221 checkNestingOfRegions(*this, DSAStack, Kind, DirName, CancelRegion,
6222 BindKind, StartLoc))
6223 return StmtError();
6225 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6226 if (getLangOpts().HIP && (isOpenMPTargetExecutionDirective(Kind) ||
6227 isOpenMPTargetDataManagementDirective(Kind)))
6228 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6230 llvm::SmallVector<OMPClause *> ClausesWithoutBind;
6231 bool UseClausesWithoutBind = false;
6233 UseClausesWithoutBind = mapLoopConstruct(ClausesWithoutBind, Clauses,
6234 BindKind, Kind, PrevMappedDirective);
6236 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
6237 VarsWithInheritedDSAType VarsWithInheritedDSA;
6238 bool ErrorFound = false;
6239 if (getLangOpts().OpenMP >= 50 && UseClausesWithoutBind) {
6240 ClausesWithImplicit.append(ClausesWithoutBind.begin(),
6241 ClausesWithoutBind.end());
6242 } else {
6243 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6245 if (AStmt && !CurContext->isDependentContext() && Kind != OMPD_atomic &&
6246 Kind != OMPD_critical && Kind != OMPD_section && Kind != OMPD_master &&
6247 Kind != OMPD_masked && !isOpenMPLoopTransformationDirective(Kind)) {
6248 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6250 // Check default data sharing attributes for referenced variables.
6251 DSAAttrChecker DSAChecker(DSAStack, *this, cast<CapturedStmt>(AStmt));
6252 int ThisCaptureLevel = getOpenMPCaptureLevels(Kind);
6253 Stmt *S = AStmt;
6254 while (--ThisCaptureLevel >= 0)
6255 S = cast<CapturedStmt>(S)->getCapturedStmt();
6256 DSAChecker.Visit(S);
6257 if (!isOpenMPTargetDataManagementDirective(Kind) &&
6258 !isOpenMPTaskingDirective(Kind)) {
6259 // Visit subcaptures to generate implicit clauses for captured vars.
6260 auto *CS = cast<CapturedStmt>(AStmt);
6261 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
6262 getOpenMPCaptureRegions(CaptureRegions, Kind);
6263 // Ignore outer tasking regions for target directives.
6264 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6265 CS = cast<CapturedStmt>(CS->getCapturedStmt());
6266 DSAChecker.visitSubCaptures(CS);
6268 if (DSAChecker.isErrorFound())
6269 return StmtError();
6270 // Generate list of implicitly defined firstprivate variables.
6271 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6273 SmallVector<Expr *, 4> ImplicitFirstprivates(
6274 DSAChecker.getImplicitFirstprivate().begin(),
6275 DSAChecker.getImplicitFirstprivate().end());
6276 SmallVector<Expr *, 4> ImplicitPrivates(
6277 DSAChecker.getImplicitPrivate().begin(),
6278 DSAChecker.getImplicitPrivate().end());
6279 const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
6280 SmallVector<Expr *, 4> ImplicitMaps[DefaultmapKindNum][OMPC_MAP_delete];
6281 SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
6282 ImplicitMapModifiers[DefaultmapKindNum];
6283 SmallVector<SourceLocation, NumberOfOMPMapClauseModifiers>
6284 ImplicitMapModifiersLoc[DefaultmapKindNum];
6285 // Get the original location of present modifier from Defaultmap clause.
6286 SourceLocation PresentModifierLocs[DefaultmapKindNum];
6287 for (OMPClause *C : Clauses) {
6288 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C))
6289 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6290 PresentModifierLocs[DMC->getDefaultmapKind()] =
6291 DMC->getDefaultmapModifierLoc();
6293 for (unsigned VC = 0; VC < DefaultmapKindNum; ++VC) {
6294 auto Kind = static_cast<OpenMPDefaultmapClauseKind>(VC);
6295 for (unsigned I = 0; I < OMPC_MAP_delete; ++I) {
6296 ArrayRef<Expr *> ImplicitMap = DSAChecker.getImplicitMap(
6297 Kind, static_cast<OpenMPMapClauseKind>(I));
6298 ImplicitMaps[VC][I].append(ImplicitMap.begin(), ImplicitMap.end());
6300 ArrayRef<OpenMPMapModifierKind> ImplicitModifier =
6301 DSAChecker.getImplicitMapModifier(Kind);
6302 ImplicitMapModifiers[VC].append(ImplicitModifier.begin(),
6303 ImplicitModifier.end());
6304 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[VC]),
6305 ImplicitModifier.size(), PresentModifierLocs[VC]);
6307 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6308 for (OMPClause *C : Clauses) {
6309 if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
6310 for (Expr *E : IRC->taskgroup_descriptors())
6311 if (E)
6312 ImplicitFirstprivates.emplace_back(E);
6314 // OpenMP 5.0, 2.10.1 task Construct
6315 // [detach clause]... The event-handle will be considered as if it was
6316 // specified on a firstprivate clause.
6317 if (auto *DC = dyn_cast<OMPDetachClause>(C))
6318 ImplicitFirstprivates.push_back(DC->getEventHandler());
6320 if (!ImplicitFirstprivates.empty()) {
6321 if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause(
6322 ImplicitFirstprivates, SourceLocation(), SourceLocation(),
6323 SourceLocation())) {
6324 ClausesWithImplicit.push_back(Implicit);
6325 ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
6326 ImplicitFirstprivates.size();
6327 } else {
6328 ErrorFound = true;
6331 if (!ImplicitPrivates.empty()) {
6332 if (OMPClause *Implicit =
6333 ActOnOpenMPPrivateClause(ImplicitPrivates, SourceLocation(),
6334 SourceLocation(), SourceLocation())) {
6335 ClausesWithImplicit.push_back(Implicit);
6336 ErrorFound = cast<OMPPrivateClause>(Implicit)->varlist_size() !=
6337 ImplicitPrivates.size();
6338 } else {
6339 ErrorFound = true;
6342 // OpenMP 5.0 [2.19.7]
6343 // If a list item appears in a reduction, lastprivate or linear
6344 // clause on a combined target construct then it is treated as
6345 // if it also appears in a map clause with a map-type of tofrom
6346 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6347 isOpenMPTargetExecutionDirective(Kind)) {
6348 SmallVector<Expr *, 4> ImplicitExprs;
6349 for (OMPClause *C : Clauses) {
6350 if (auto *RC = dyn_cast<OMPReductionClause>(C))
6351 for (Expr *E : RC->varlists())
6352 if (!isa<DeclRefExpr>(E->IgnoreParenImpCasts()))
6353 ImplicitExprs.emplace_back(E);
6355 if (!ImplicitExprs.empty()) {
6356 ArrayRef<Expr *> Exprs = ImplicitExprs;
6357 CXXScopeSpec MapperIdScopeSpec;
6358 DeclarationNameInfo MapperId;
6359 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6360 nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(),
6361 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6362 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6363 Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true))
6364 ClausesWithImplicit.emplace_back(Implicit);
6367 for (unsigned I = 0, E = DefaultmapKindNum; I < E; ++I) {
6368 int ClauseKindCnt = -1;
6369 for (ArrayRef<Expr *> ImplicitMap : ImplicitMaps[I]) {
6370 ++ClauseKindCnt;
6371 if (ImplicitMap.empty())
6372 continue;
6373 CXXScopeSpec MapperIdScopeSpec;
6374 DeclarationNameInfo MapperId;
6375 auto Kind = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6376 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6377 nullptr, ImplicitMapModifiers[I], ImplicitMapModifiersLoc[I],
6378 MapperIdScopeSpec, MapperId, Kind, /*IsMapTypeImplicit=*/true,
6379 SourceLocation(), SourceLocation(), ImplicitMap,
6380 OMPVarListLocTy())) {
6381 ClausesWithImplicit.emplace_back(Implicit);
6382 ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() !=
6383 ImplicitMap.size();
6384 } else {
6385 ErrorFound = true;
6389 // Build expressions for implicit maps of data members with 'default'
6390 // mappers.
6391 if (LangOpts.OpenMP >= 50)
6392 processImplicitMapsWithDefaultMappers(*this, DSAStack,
6393 ClausesWithImplicit);
6396 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6397 switch (Kind) {
6398 case OMPD_parallel:
6399 Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
6400 EndLoc);
6401 AllowedNameModifiers.push_back(OMPD_parallel);
6402 break;
6403 case OMPD_simd:
6404 Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6405 VarsWithInheritedDSA);
6406 if (LangOpts.OpenMP >= 50)
6407 AllowedNameModifiers.push_back(OMPD_simd);
6408 break;
6409 case OMPD_tile:
6410 Res =
6411 ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6412 break;
6413 case OMPD_unroll:
6414 Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc,
6415 EndLoc);
6416 break;
6417 case OMPD_for:
6418 Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6419 VarsWithInheritedDSA);
6420 break;
6421 case OMPD_for_simd:
6422 Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6423 EndLoc, VarsWithInheritedDSA);
6424 if (LangOpts.OpenMP >= 50)
6425 AllowedNameModifiers.push_back(OMPD_simd);
6426 break;
6427 case OMPD_sections:
6428 Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc,
6429 EndLoc);
6430 break;
6431 case OMPD_section:
6432 assert(ClausesWithImplicit.empty() &&
6433 "No clauses are allowed for 'omp section' directive");
6434 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6435 break;
6436 case OMPD_single:
6437 Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc,
6438 EndLoc);
6439 break;
6440 case OMPD_master:
6441 assert(ClausesWithImplicit.empty() &&
6442 "No clauses are allowed for 'omp master' directive");
6443 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6444 break;
6445 case OMPD_masked:
6446 Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc,
6447 EndLoc);
6448 break;
6449 case OMPD_critical:
6450 Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
6451 StartLoc, EndLoc);
6452 break;
6453 case OMPD_parallel_for:
6454 Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
6455 EndLoc, VarsWithInheritedDSA);
6456 AllowedNameModifiers.push_back(OMPD_parallel);
6457 break;
6458 case OMPD_parallel_for_simd:
6459 Res = ActOnOpenMPParallelForSimdDirective(
6460 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6461 AllowedNameModifiers.push_back(OMPD_parallel);
6462 if (LangOpts.OpenMP >= 50)
6463 AllowedNameModifiers.push_back(OMPD_simd);
6464 break;
6465 case OMPD_scope:
6466 Res =
6467 ActOnOpenMPScopeDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6468 break;
6469 case OMPD_parallel_master:
6470 Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt,
6471 StartLoc, EndLoc);
6472 AllowedNameModifiers.push_back(OMPD_parallel);
6473 break;
6474 case OMPD_parallel_masked:
6475 Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt,
6476 StartLoc, EndLoc);
6477 AllowedNameModifiers.push_back(OMPD_parallel);
6478 break;
6479 case OMPD_parallel_sections:
6480 Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
6481 StartLoc, EndLoc);
6482 AllowedNameModifiers.push_back(OMPD_parallel);
6483 break;
6484 case OMPD_task:
6485 Res =
6486 ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6487 AllowedNameModifiers.push_back(OMPD_task);
6488 break;
6489 case OMPD_taskyield:
6490 assert(ClausesWithImplicit.empty() &&
6491 "No clauses are allowed for 'omp taskyield' directive");
6492 assert(AStmt == nullptr &&
6493 "No associated statement allowed for 'omp taskyield' directive");
6494 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6495 break;
6496 case OMPD_error:
6497 assert(AStmt == nullptr &&
6498 "No associated statement allowed for 'omp error' directive");
6499 Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc);
6500 break;
6501 case OMPD_barrier:
6502 assert(ClausesWithImplicit.empty() &&
6503 "No clauses are allowed for 'omp barrier' directive");
6504 assert(AStmt == nullptr &&
6505 "No associated statement allowed for 'omp barrier' directive");
6506 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6507 break;
6508 case OMPD_taskwait:
6509 assert(AStmt == nullptr &&
6510 "No associated statement allowed for 'omp taskwait' directive");
6511 Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc);
6512 break;
6513 case OMPD_taskgroup:
6514 Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc,
6515 EndLoc);
6516 break;
6517 case OMPD_flush:
6518 assert(AStmt == nullptr &&
6519 "No associated statement allowed for 'omp flush' directive");
6520 Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
6521 break;
6522 case OMPD_depobj:
6523 assert(AStmt == nullptr &&
6524 "No associated statement allowed for 'omp depobj' directive");
6525 Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc);
6526 break;
6527 case OMPD_scan:
6528 assert(AStmt == nullptr &&
6529 "No associated statement allowed for 'omp scan' directive");
6530 Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc);
6531 break;
6532 case OMPD_ordered:
6533 Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
6534 EndLoc);
6535 break;
6536 case OMPD_atomic:
6537 Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
6538 EndLoc);
6539 break;
6540 case OMPD_teams:
6541 Res =
6542 ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6543 break;
6544 case OMPD_target:
6545 Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
6546 EndLoc);
6547 AllowedNameModifiers.push_back(OMPD_target);
6548 break;
6549 case OMPD_target_parallel:
6550 Res = ActOnOpenMPTargetParallelDirective(ClausesWithImplicit, AStmt,
6551 StartLoc, EndLoc);
6552 AllowedNameModifiers.push_back(OMPD_target);
6553 AllowedNameModifiers.push_back(OMPD_parallel);
6554 break;
6555 case OMPD_target_parallel_for:
6556 Res = ActOnOpenMPTargetParallelForDirective(
6557 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6558 AllowedNameModifiers.push_back(OMPD_target);
6559 AllowedNameModifiers.push_back(OMPD_parallel);
6560 break;
6561 case OMPD_cancellation_point:
6562 assert(ClausesWithImplicit.empty() &&
6563 "No clauses are allowed for 'omp cancellation point' directive");
6564 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6565 "cancellation point' directive");
6566 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6567 break;
6568 case OMPD_cancel:
6569 assert(AStmt == nullptr &&
6570 "No associated statement allowed for 'omp cancel' directive");
6571 Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
6572 CancelRegion);
6573 AllowedNameModifiers.push_back(OMPD_cancel);
6574 break;
6575 case OMPD_target_data:
6576 Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
6577 EndLoc);
6578 AllowedNameModifiers.push_back(OMPD_target_data);
6579 break;
6580 case OMPD_target_enter_data:
6581 Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc,
6582 EndLoc, AStmt);
6583 AllowedNameModifiers.push_back(OMPD_target_enter_data);
6584 break;
6585 case OMPD_target_exit_data:
6586 Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc,
6587 EndLoc, AStmt);
6588 AllowedNameModifiers.push_back(OMPD_target_exit_data);
6589 break;
6590 case OMPD_taskloop:
6591 Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6592 EndLoc, VarsWithInheritedDSA);
6593 AllowedNameModifiers.push_back(OMPD_taskloop);
6594 break;
6595 case OMPD_taskloop_simd:
6596 Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6597 EndLoc, VarsWithInheritedDSA);
6598 AllowedNameModifiers.push_back(OMPD_taskloop);
6599 if (LangOpts.OpenMP >= 50)
6600 AllowedNameModifiers.push_back(OMPD_simd);
6601 break;
6602 case OMPD_master_taskloop:
6603 Res = ActOnOpenMPMasterTaskLoopDirective(
6604 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6605 AllowedNameModifiers.push_back(OMPD_taskloop);
6606 break;
6607 case OMPD_masked_taskloop:
6608 Res = ActOnOpenMPMaskedTaskLoopDirective(
6609 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6610 AllowedNameModifiers.push_back(OMPD_taskloop);
6611 break;
6612 case OMPD_master_taskloop_simd:
6613 Res = ActOnOpenMPMasterTaskLoopSimdDirective(
6614 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6615 AllowedNameModifiers.push_back(OMPD_taskloop);
6616 if (LangOpts.OpenMP >= 50)
6617 AllowedNameModifiers.push_back(OMPD_simd);
6618 break;
6619 case OMPD_masked_taskloop_simd:
6620 Res = ActOnOpenMPMaskedTaskLoopSimdDirective(
6621 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6622 if (LangOpts.OpenMP >= 51) {
6623 AllowedNameModifiers.push_back(OMPD_taskloop);
6624 AllowedNameModifiers.push_back(OMPD_simd);
6626 break;
6627 case OMPD_parallel_master_taskloop:
6628 Res = ActOnOpenMPParallelMasterTaskLoopDirective(
6629 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6630 AllowedNameModifiers.push_back(OMPD_taskloop);
6631 AllowedNameModifiers.push_back(OMPD_parallel);
6632 break;
6633 case OMPD_parallel_masked_taskloop:
6634 Res = ActOnOpenMPParallelMaskedTaskLoopDirective(
6635 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6636 if (LangOpts.OpenMP >= 51) {
6637 AllowedNameModifiers.push_back(OMPD_taskloop);
6638 AllowedNameModifiers.push_back(OMPD_parallel);
6640 break;
6641 case OMPD_parallel_master_taskloop_simd:
6642 Res = ActOnOpenMPParallelMasterTaskLoopSimdDirective(
6643 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6644 AllowedNameModifiers.push_back(OMPD_taskloop);
6645 AllowedNameModifiers.push_back(OMPD_parallel);
6646 if (LangOpts.OpenMP >= 50)
6647 AllowedNameModifiers.push_back(OMPD_simd);
6648 break;
6649 case OMPD_parallel_masked_taskloop_simd:
6650 Res = ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
6651 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6652 if (LangOpts.OpenMP >= 51) {
6653 AllowedNameModifiers.push_back(OMPD_taskloop);
6654 AllowedNameModifiers.push_back(OMPD_parallel);
6655 AllowedNameModifiers.push_back(OMPD_simd);
6657 break;
6658 case OMPD_distribute:
6659 Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc,
6660 EndLoc, VarsWithInheritedDSA);
6661 break;
6662 case OMPD_target_update:
6663 Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc,
6664 EndLoc, AStmt);
6665 AllowedNameModifiers.push_back(OMPD_target_update);
6666 break;
6667 case OMPD_distribute_parallel_for:
6668 Res = ActOnOpenMPDistributeParallelForDirective(
6669 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6670 AllowedNameModifiers.push_back(OMPD_parallel);
6671 break;
6672 case OMPD_distribute_parallel_for_simd:
6673 Res = ActOnOpenMPDistributeParallelForSimdDirective(
6674 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6675 AllowedNameModifiers.push_back(OMPD_parallel);
6676 if (LangOpts.OpenMP >= 50)
6677 AllowedNameModifiers.push_back(OMPD_simd);
6678 break;
6679 case OMPD_distribute_simd:
6680 Res = ActOnOpenMPDistributeSimdDirective(
6681 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6682 if (LangOpts.OpenMP >= 50)
6683 AllowedNameModifiers.push_back(OMPD_simd);
6684 break;
6685 case OMPD_target_parallel_for_simd:
6686 Res = ActOnOpenMPTargetParallelForSimdDirective(
6687 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6688 AllowedNameModifiers.push_back(OMPD_target);
6689 AllowedNameModifiers.push_back(OMPD_parallel);
6690 if (LangOpts.OpenMP >= 50)
6691 AllowedNameModifiers.push_back(OMPD_simd);
6692 break;
6693 case OMPD_target_simd:
6694 Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6695 EndLoc, VarsWithInheritedDSA);
6696 AllowedNameModifiers.push_back(OMPD_target);
6697 if (LangOpts.OpenMP >= 50)
6698 AllowedNameModifiers.push_back(OMPD_simd);
6699 break;
6700 case OMPD_teams_distribute:
6701 Res = ActOnOpenMPTeamsDistributeDirective(
6702 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6703 break;
6704 case OMPD_teams_distribute_simd:
6705 Res = ActOnOpenMPTeamsDistributeSimdDirective(
6706 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6707 if (LangOpts.OpenMP >= 50)
6708 AllowedNameModifiers.push_back(OMPD_simd);
6709 break;
6710 case OMPD_teams_distribute_parallel_for_simd:
6711 Res = ActOnOpenMPTeamsDistributeParallelForSimdDirective(
6712 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6713 AllowedNameModifiers.push_back(OMPD_parallel);
6714 if (LangOpts.OpenMP >= 50)
6715 AllowedNameModifiers.push_back(OMPD_simd);
6716 break;
6717 case OMPD_teams_distribute_parallel_for:
6718 Res = ActOnOpenMPTeamsDistributeParallelForDirective(
6719 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6720 AllowedNameModifiers.push_back(OMPD_parallel);
6721 break;
6722 case OMPD_target_teams:
6723 Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc,
6724 EndLoc);
6725 AllowedNameModifiers.push_back(OMPD_target);
6726 break;
6727 case OMPD_target_teams_distribute:
6728 Res = ActOnOpenMPTargetTeamsDistributeDirective(
6729 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6730 AllowedNameModifiers.push_back(OMPD_target);
6731 break;
6732 case OMPD_target_teams_distribute_parallel_for:
6733 Res = ActOnOpenMPTargetTeamsDistributeParallelForDirective(
6734 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6735 AllowedNameModifiers.push_back(OMPD_target);
6736 AllowedNameModifiers.push_back(OMPD_parallel);
6737 break;
6738 case OMPD_target_teams_distribute_parallel_for_simd:
6739 Res = ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
6740 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6741 AllowedNameModifiers.push_back(OMPD_target);
6742 AllowedNameModifiers.push_back(OMPD_parallel);
6743 if (LangOpts.OpenMP >= 50)
6744 AllowedNameModifiers.push_back(OMPD_simd);
6745 break;
6746 case OMPD_target_teams_distribute_simd:
6747 Res = ActOnOpenMPTargetTeamsDistributeSimdDirective(
6748 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6749 AllowedNameModifiers.push_back(OMPD_target);
6750 if (LangOpts.OpenMP >= 50)
6751 AllowedNameModifiers.push_back(OMPD_simd);
6752 break;
6753 case OMPD_interop:
6754 assert(AStmt == nullptr &&
6755 "No associated statement allowed for 'omp interop' directive");
6756 Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc);
6757 break;
6758 case OMPD_dispatch:
6759 Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc,
6760 EndLoc);
6761 break;
6762 case OMPD_loop:
6763 Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6764 EndLoc, VarsWithInheritedDSA);
6765 break;
6766 case OMPD_teams_loop:
6767 Res = ActOnOpenMPTeamsGenericLoopDirective(
6768 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6769 break;
6770 case OMPD_target_teams_loop:
6771 Res = ActOnOpenMPTargetTeamsGenericLoopDirective(
6772 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6773 AllowedNameModifiers.push_back(OMPD_target);
6774 break;
6775 case OMPD_parallel_loop:
6776 Res = ActOnOpenMPParallelGenericLoopDirective(
6777 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6778 break;
6779 case OMPD_target_parallel_loop:
6780 Res = ActOnOpenMPTargetParallelGenericLoopDirective(
6781 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6782 break;
6783 case OMPD_declare_target:
6784 case OMPD_end_declare_target:
6785 case OMPD_threadprivate:
6786 case OMPD_allocate:
6787 case OMPD_declare_reduction:
6788 case OMPD_declare_mapper:
6789 case OMPD_declare_simd:
6790 case OMPD_requires:
6791 case OMPD_declare_variant:
6792 case OMPD_begin_declare_variant:
6793 case OMPD_end_declare_variant:
6794 llvm_unreachable("OpenMP Directive is not allowed");
6795 case OMPD_unknown:
6796 default:
6797 llvm_unreachable("Unknown OpenMP directive");
6800 ErrorFound = Res.isInvalid() || ErrorFound;
6802 // Check variables in the clauses if default(none) or
6803 // default(firstprivate) was specified.
6804 if (DSAStack->getDefaultDSA() == DSA_none ||
6805 DSAStack->getDefaultDSA() == DSA_private ||
6806 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6807 DSAAttrChecker DSAChecker(DSAStack, *this, nullptr);
6808 for (OMPClause *C : Clauses) {
6809 switch (C->getClauseKind()) {
6810 case OMPC_num_threads:
6811 case OMPC_dist_schedule:
6812 // Do not analyse if no parent teams directive.
6813 if (isOpenMPTeamsDirective(Kind))
6814 break;
6815 continue;
6816 case OMPC_if:
6817 if (isOpenMPTeamsDirective(Kind) &&
6818 cast<OMPIfClause>(C)->getNameModifier() != OMPD_target)
6819 break;
6820 if (isOpenMPParallelDirective(Kind) &&
6821 isOpenMPTaskLoopDirective(Kind) &&
6822 cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel)
6823 break;
6824 continue;
6825 case OMPC_schedule:
6826 case OMPC_detach:
6827 break;
6828 case OMPC_grainsize:
6829 case OMPC_num_tasks:
6830 case OMPC_final:
6831 case OMPC_priority:
6832 case OMPC_novariants:
6833 case OMPC_nocontext:
6834 // Do not analyze if no parent parallel directive.
6835 if (isOpenMPParallelDirective(Kind))
6836 break;
6837 continue;
6838 case OMPC_ordered:
6839 case OMPC_device:
6840 case OMPC_num_teams:
6841 case OMPC_thread_limit:
6842 case OMPC_hint:
6843 case OMPC_collapse:
6844 case OMPC_safelen:
6845 case OMPC_simdlen:
6846 case OMPC_sizes:
6847 case OMPC_default:
6848 case OMPC_proc_bind:
6849 case OMPC_private:
6850 case OMPC_firstprivate:
6851 case OMPC_lastprivate:
6852 case OMPC_shared:
6853 case OMPC_reduction:
6854 case OMPC_task_reduction:
6855 case OMPC_in_reduction:
6856 case OMPC_linear:
6857 case OMPC_aligned:
6858 case OMPC_copyin:
6859 case OMPC_copyprivate:
6860 case OMPC_nowait:
6861 case OMPC_untied:
6862 case OMPC_mergeable:
6863 case OMPC_allocate:
6864 case OMPC_read:
6865 case OMPC_write:
6866 case OMPC_update:
6867 case OMPC_capture:
6868 case OMPC_compare:
6869 case OMPC_seq_cst:
6870 case OMPC_acq_rel:
6871 case OMPC_acquire:
6872 case OMPC_release:
6873 case OMPC_relaxed:
6874 case OMPC_depend:
6875 case OMPC_threads:
6876 case OMPC_simd:
6877 case OMPC_map:
6878 case OMPC_nogroup:
6879 case OMPC_defaultmap:
6880 case OMPC_to:
6881 case OMPC_from:
6882 case OMPC_use_device_ptr:
6883 case OMPC_use_device_addr:
6884 case OMPC_is_device_ptr:
6885 case OMPC_has_device_addr:
6886 case OMPC_nontemporal:
6887 case OMPC_order:
6888 case OMPC_destroy:
6889 case OMPC_inclusive:
6890 case OMPC_exclusive:
6891 case OMPC_uses_allocators:
6892 case OMPC_affinity:
6893 case OMPC_bind:
6894 case OMPC_filter:
6895 continue;
6896 case OMPC_allocator:
6897 case OMPC_flush:
6898 case OMPC_depobj:
6899 case OMPC_threadprivate:
6900 case OMPC_uniform:
6901 case OMPC_unknown:
6902 case OMPC_unified_address:
6903 case OMPC_unified_shared_memory:
6904 case OMPC_reverse_offload:
6905 case OMPC_dynamic_allocators:
6906 case OMPC_atomic_default_mem_order:
6907 case OMPC_device_type:
6908 case OMPC_match:
6909 case OMPC_when:
6910 case OMPC_at:
6911 case OMPC_severity:
6912 case OMPC_message:
6913 default:
6914 llvm_unreachable("Unexpected clause");
6916 for (Stmt *CC : C->children()) {
6917 if (CC)
6918 DSAChecker.Visit(CC);
6921 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6922 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6924 for (const auto &P : VarsWithInheritedDSA) {
6925 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst()))
6926 continue;
6927 ErrorFound = true;
6928 if (DSAStack->getDefaultDSA() == DSA_none ||
6929 DSAStack->getDefaultDSA() == DSA_private ||
6930 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6931 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6932 << P.first << P.second->getSourceRange();
6933 Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6934 } else if (getLangOpts().OpenMP >= 50) {
6935 Diag(P.second->getExprLoc(),
6936 diag::err_omp_defaultmap_no_attr_for_variable)
6937 << P.first << P.second->getSourceRange();
6938 Diag(DSAStack->getDefaultDSALocation(),
6939 diag::note_omp_defaultmap_attr_none);
6943 if (!AllowedNameModifiers.empty())
6944 ErrorFound = checkIfClauses(*this, Kind, Clauses, AllowedNameModifiers) ||
6945 ErrorFound;
6947 if (ErrorFound)
6948 return StmtError();
6950 if (!CurContext->isDependentContext() &&
6951 isOpenMPTargetExecutionDirective(Kind) &&
6952 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6953 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6954 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6955 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6956 // Register target to DSA Stack.
6957 DSAStack->addTargetDirLocation(StartLoc);
6960 return Res;
6963 Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective(
6964 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6965 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6966 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6967 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6968 assert(Aligneds.size() == Alignments.size());
6969 assert(Linears.size() == LinModifiers.size());
6970 assert(Linears.size() == Steps.size());
6971 if (!DG || DG.get().isNull())
6972 return DeclGroupPtrTy();
6974 const int SimdId = 0;
6975 if (!DG.get().isSingleDecl()) {
6976 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6977 << SimdId;
6978 return DG;
6980 Decl *ADecl = DG.get().getSingleDecl();
6981 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6982 ADecl = FTD->getTemplatedDecl();
6984 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6985 if (!FD) {
6986 Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
6987 return DeclGroupPtrTy();
6990 // OpenMP [2.8.2, declare simd construct, Description]
6991 // The parameter of the simdlen clause must be a constant positive integer
6992 // expression.
6993 ExprResult SL;
6994 if (Simdlen)
6995 SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen);
6996 // OpenMP [2.8.2, declare simd construct, Description]
6997 // The special this pointer can be used as if was one of the arguments to the
6998 // function in any of the linear, aligned, or uniform clauses.
6999 // The uniform clause declares one or more arguments to have an invariant
7000 // value for all concurrent invocations of the function in the execution of a
7001 // single SIMD loop.
7002 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
7003 const Expr *UniformedLinearThis = nullptr;
7004 for (const Expr *E : Uniforms) {
7005 E = E->IgnoreParenImpCasts();
7006 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
7007 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
7008 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7009 FD->getParamDecl(PVD->getFunctionScopeIndex())
7010 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
7011 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
7012 continue;
7014 if (isa<CXXThisExpr>(E)) {
7015 UniformedLinearThis = E;
7016 continue;
7018 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7019 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7021 // OpenMP [2.8.2, declare simd construct, Description]
7022 // The aligned clause declares that the object to which each list item points
7023 // is aligned to the number of bytes expressed in the optional parameter of
7024 // the aligned clause.
7025 // The special this pointer can be used as if was one of the arguments to the
7026 // function in any of the linear, aligned, or uniform clauses.
7027 // The type of list items appearing in the aligned clause must be array,
7028 // pointer, reference to array, or reference to pointer.
7029 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
7030 const Expr *AlignedThis = nullptr;
7031 for (const Expr *E : Aligneds) {
7032 E = E->IgnoreParenImpCasts();
7033 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
7034 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7035 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7036 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7037 FD->getParamDecl(PVD->getFunctionScopeIndex())
7038 ->getCanonicalDecl() == CanonPVD) {
7039 // OpenMP [2.8.1, simd construct, Restrictions]
7040 // A list-item cannot appear in more than one aligned clause.
7041 if (AlignedArgs.count(CanonPVD) > 0) {
7042 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
7043 << 1 << getOpenMPClauseName(OMPC_aligned)
7044 << E->getSourceRange();
7045 Diag(AlignedArgs[CanonPVD]->getExprLoc(),
7046 diag::note_omp_explicit_dsa)
7047 << getOpenMPClauseName(OMPC_aligned);
7048 continue;
7050 AlignedArgs[CanonPVD] = E;
7051 QualType QTy = PVD->getType()
7052 .getNonReferenceType()
7053 .getUnqualifiedType()
7054 .getCanonicalType();
7055 const Type *Ty = QTy.getTypePtrOrNull();
7056 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
7057 Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
7058 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
7059 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
7061 continue;
7064 if (isa<CXXThisExpr>(E)) {
7065 if (AlignedThis) {
7066 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
7067 << 2 << getOpenMPClauseName(OMPC_aligned) << E->getSourceRange();
7068 Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
7069 << getOpenMPClauseName(OMPC_aligned);
7071 AlignedThis = E;
7072 continue;
7074 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7075 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7077 // The optional parameter of the aligned clause, alignment, must be a constant
7078 // positive integer expression. If no optional parameter is specified,
7079 // implementation-defined default alignments for SIMD instructions on the
7080 // target platforms are assumed.
7081 SmallVector<const Expr *, 4> NewAligns;
7082 for (Expr *E : Alignments) {
7083 ExprResult Align;
7084 if (E)
7085 Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
7086 NewAligns.push_back(Align.get());
7088 // OpenMP [2.8.2, declare simd construct, Description]
7089 // The linear clause declares one or more list items to be private to a SIMD
7090 // lane and to have a linear relationship with respect to the iteration space
7091 // of a loop.
7092 // The special this pointer can be used as if was one of the arguments to the
7093 // function in any of the linear, aligned, or uniform clauses.
7094 // When a linear-step expression is specified in a linear clause it must be
7095 // either a constant integer expression or an integer-typed parameter that is
7096 // specified in a uniform clause on the directive.
7097 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
7098 const bool IsUniformedThis = UniformedLinearThis != nullptr;
7099 auto MI = LinModifiers.begin();
7100 for (const Expr *E : Linears) {
7101 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
7102 ++MI;
7103 E = E->IgnoreParenImpCasts();
7104 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
7105 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7106 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7107 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7108 FD->getParamDecl(PVD->getFunctionScopeIndex())
7109 ->getCanonicalDecl() == CanonPVD) {
7110 // OpenMP [2.15.3.7, linear Clause, Restrictions]
7111 // A list-item cannot appear in more than one linear clause.
7112 if (LinearArgs.count(CanonPVD) > 0) {
7113 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7114 << getOpenMPClauseName(OMPC_linear)
7115 << getOpenMPClauseName(OMPC_linear) << E->getSourceRange();
7116 Diag(LinearArgs[CanonPVD]->getExprLoc(),
7117 diag::note_omp_explicit_dsa)
7118 << getOpenMPClauseName(OMPC_linear);
7119 continue;
7121 // Each argument can appear in at most one uniform or linear clause.
7122 if (UniformedArgs.count(CanonPVD) > 0) {
7123 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7124 << getOpenMPClauseName(OMPC_linear)
7125 << getOpenMPClauseName(OMPC_uniform) << E->getSourceRange();
7126 Diag(UniformedArgs[CanonPVD]->getExprLoc(),
7127 diag::note_omp_explicit_dsa)
7128 << getOpenMPClauseName(OMPC_uniform);
7129 continue;
7131 LinearArgs[CanonPVD] = E;
7132 if (E->isValueDependent() || E->isTypeDependent() ||
7133 E->isInstantiationDependent() ||
7134 E->containsUnexpandedParameterPack())
7135 continue;
7136 (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind,
7137 PVD->getOriginalType(),
7138 /*IsDeclareSimd=*/true);
7139 continue;
7142 if (isa<CXXThisExpr>(E)) {
7143 if (UniformedLinearThis) {
7144 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7145 << getOpenMPClauseName(OMPC_linear)
7146 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform : OMPC_linear)
7147 << E->getSourceRange();
7148 Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa)
7149 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform
7150 : OMPC_linear);
7151 continue;
7153 UniformedLinearThis = E;
7154 if (E->isValueDependent() || E->isTypeDependent() ||
7155 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
7156 continue;
7157 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind,
7158 E->getType(), /*IsDeclareSimd=*/true);
7159 continue;
7161 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7162 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7164 Expr *Step = nullptr;
7165 Expr *NewStep = nullptr;
7166 SmallVector<Expr *, 4> NewSteps;
7167 for (Expr *E : Steps) {
7168 // Skip the same step expression, it was checked already.
7169 if (Step == E || !E) {
7170 NewSteps.push_back(E ? NewStep : nullptr);
7171 continue;
7173 Step = E;
7174 if (const auto *DRE = dyn_cast<DeclRefExpr>(Step))
7175 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7176 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7177 if (UniformedArgs.count(CanonPVD) == 0) {
7178 Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
7179 << Step->getSourceRange();
7180 } else if (E->isValueDependent() || E->isTypeDependent() ||
7181 E->isInstantiationDependent() ||
7182 E->containsUnexpandedParameterPack() ||
7183 CanonPVD->getType()->hasIntegerRepresentation()) {
7184 NewSteps.push_back(Step);
7185 } else {
7186 Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
7187 << Step->getSourceRange();
7189 continue;
7191 NewStep = Step;
7192 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
7193 !Step->isInstantiationDependent() &&
7194 !Step->containsUnexpandedParameterPack()) {
7195 NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step)
7196 .get();
7197 if (NewStep)
7198 NewStep =
7199 VerifyIntegerConstantExpression(NewStep, /*FIXME*/ AllowFold).get();
7201 NewSteps.push_back(NewStep);
7203 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7204 Context, BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
7205 Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
7206 const_cast<Expr **>(NewAligns.data()), NewAligns.size(),
7207 const_cast<Expr **>(Linears.data()), Linears.size(),
7208 const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(),
7209 NewSteps.data(), NewSteps.size(), SR);
7210 ADecl->addAttr(NewAttr);
7211 return DG;
7214 static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
7215 QualType NewType) {
7216 assert(NewType->isFunctionProtoType() &&
7217 "Expected function type with prototype.");
7218 assert(FD->getType()->isFunctionNoProtoType() &&
7219 "Expected function with type with no prototype.");
7220 assert(FDWithProto->getType()->isFunctionProtoType() &&
7221 "Expected function with prototype.");
7222 // Synthesize parameters with the same types.
7223 FD->setType(NewType);
7224 SmallVector<ParmVarDecl *, 16> Params;
7225 for (const ParmVarDecl *P : FDWithProto->parameters()) {
7226 auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(),
7227 SourceLocation(), nullptr, P->getType(),
7228 /*TInfo=*/nullptr, SC_None, nullptr);
7229 Param->setScopeInfo(0, Params.size());
7230 Param->setImplicit();
7231 Params.push_back(Param);
7234 FD->setParams(Params);
7237 void Sema::ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D) {
7238 if (D->isInvalidDecl())
7239 return;
7240 FunctionDecl *FD = nullptr;
7241 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7242 FD = UTemplDecl->getTemplatedDecl();
7243 else
7244 FD = cast<FunctionDecl>(D);
7245 assert(FD && "Expected a function declaration!");
7247 // If we are instantiating templates we do *not* apply scoped assumptions but
7248 // only global ones. We apply scoped assumption to the template definition
7249 // though.
7250 if (!inTemplateInstantiation()) {
7251 for (AssumptionAttr *AA : OMPAssumeScoped)
7252 FD->addAttr(AA);
7254 for (AssumptionAttr *AA : OMPAssumeGlobal)
7255 FD->addAttr(AA);
7258 Sema::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7259 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7261 void Sema::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(
7262 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7263 SmallVectorImpl<FunctionDecl *> &Bases) {
7264 if (!D.getIdentifier())
7265 return;
7267 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7269 // Template specialization is an extension, check if we do it.
7270 bool IsTemplated = !TemplateParamLists.empty();
7271 if (IsTemplated &
7272 !DVScope.TI->isExtensionActive(
7273 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7274 return;
7276 IdentifierInfo *BaseII = D.getIdentifier();
7277 LookupResult Lookup(*this, DeclarationName(BaseII), D.getIdentifierLoc(),
7278 LookupOrdinaryName);
7279 LookupParsedName(Lookup, S, &D.getCXXScopeSpec());
7281 TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
7282 QualType FType = TInfo->getType();
7284 bool IsConstexpr =
7285 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr;
7286 bool IsConsteval =
7287 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Consteval;
7289 for (auto *Candidate : Lookup) {
7290 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7291 FunctionDecl *UDecl = nullptr;
7292 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7293 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7294 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7295 UDecl = FTD->getTemplatedDecl();
7296 } else if (!IsTemplated)
7297 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7298 if (!UDecl)
7299 continue;
7301 // Don't specialize constexpr/consteval functions with
7302 // non-constexpr/consteval functions.
7303 if (UDecl->isConstexpr() && !IsConstexpr)
7304 continue;
7305 if (UDecl->isConsteval() && !IsConsteval)
7306 continue;
7308 QualType UDeclTy = UDecl->getType();
7309 if (!UDeclTy->isDependentType()) {
7310 QualType NewType = Context.mergeFunctionTypes(
7311 FType, UDeclTy, /* OfBlockPointer */ false,
7312 /* Unqualified */ false, /* AllowCXX */ true);
7313 if (NewType.isNull())
7314 continue;
7317 // Found a base!
7318 Bases.push_back(UDecl);
7321 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7322 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7323 // If no base was found we create a declaration that we use as base.
7324 if (Bases.empty() && UseImplicitBase) {
7325 D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration);
7326 Decl *BaseD = HandleDeclarator(S, D, TemplateParamLists);
7327 BaseD->setImplicit(true);
7328 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7329 Bases.push_back(BaseTemplD->getTemplatedDecl());
7330 else
7331 Bases.push_back(cast<FunctionDecl>(BaseD));
7334 std::string MangledName;
7335 MangledName += D.getIdentifier()->getName();
7336 MangledName += getOpenMPVariantManglingSeparatorStr();
7337 MangledName += DVScope.NameSuffix;
7338 IdentifierInfo &VariantII = Context.Idents.get(MangledName);
7340 VariantII.setMangledOpenMPVariantName(true);
7341 D.SetIdentifier(&VariantII, D.getBeginLoc());
7344 void Sema::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
7345 Decl *D, SmallVectorImpl<FunctionDecl *> &Bases) {
7346 // Do not mark function as is used to prevent its emission if this is the
7347 // only place where it is used.
7348 EnterExpressionEvaluationContext Unevaluated(
7349 *this, Sema::ExpressionEvaluationContext::Unevaluated);
7351 FunctionDecl *FD = nullptr;
7352 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7353 FD = UTemplDecl->getTemplatedDecl();
7354 else
7355 FD = cast<FunctionDecl>(D);
7356 auto *VariantFuncRef = DeclRefExpr::Create(
7357 Context, NestedNameSpecifierLoc(), SourceLocation(), FD,
7358 /* RefersToEnclosingVariableOrCapture */ false,
7359 /* NameLoc */ FD->getLocation(), FD->getType(),
7360 ExprValueKind::VK_PRValue);
7362 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7363 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7364 Context, VariantFuncRef, DVScope.TI,
7365 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7366 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7367 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7368 for (FunctionDecl *BaseFD : Bases)
7369 BaseFD->addAttr(OMPDeclareVariantA);
7372 ExprResult Sema::ActOnOpenMPCall(ExprResult Call, Scope *Scope,
7373 SourceLocation LParenLoc,
7374 MultiExprArg ArgExprs,
7375 SourceLocation RParenLoc, Expr *ExecConfig) {
7376 // The common case is a regular call we do not want to specialize at all. Try
7377 // to make that case fast by bailing early.
7378 CallExpr *CE = dyn_cast<CallExpr>(Call.get());
7379 if (!CE)
7380 return Call;
7382 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7383 if (!CalleeFnDecl)
7384 return Call;
7386 if (LangOpts.OpenMP >= 51 && CalleeFnDecl->getIdentifier() &&
7387 CalleeFnDecl->getName().starts_with_insensitive("omp_")) {
7388 // checking for any calls inside an Order region
7389 if (Scope && Scope->isOpenMPOrderClauseScope())
7390 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7393 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7394 return Call;
7396 ASTContext &Context = getASTContext();
7397 std::function<void(StringRef)> DiagUnknownTrait = [this,
7398 CE](StringRef ISATrait) {
7399 // TODO Track the selector locations in a way that is accessible here to
7400 // improve the diagnostic location.
7401 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7402 << ISATrait;
7404 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7405 getCurFunctionDecl(), DSAStack->getConstructTraits());
7407 QualType CalleeFnType = CalleeFnDecl->getType();
7409 SmallVector<Expr *, 4> Exprs;
7410 SmallVector<VariantMatchInfo, 4> VMIs;
7411 while (CalleeFnDecl) {
7412 for (OMPDeclareVariantAttr *A :
7413 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7414 Expr *VariantRef = A->getVariantFuncRef();
7416 VariantMatchInfo VMI;
7417 OMPTraitInfo &TI = A->getTraitInfo();
7418 TI.getAsVariantMatchInfo(Context, VMI);
7419 if (!isVariantApplicableInContext(VMI, OMPCtx,
7420 /* DeviceSetOnly */ false))
7421 continue;
7423 VMIs.push_back(VMI);
7424 Exprs.push_back(VariantRef);
7427 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7430 ExprResult NewCall;
7431 do {
7432 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7433 if (BestIdx < 0)
7434 return Call;
7435 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7436 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7439 // Try to build a (member) call expression for the current best applicable
7440 // variant expression. We allow this to fail in which case we continue
7441 // with the next best variant expression. The fail case is part of the
7442 // implementation defined behavior in the OpenMP standard when it talks
7443 // about what differences in the function prototypes: "Any differences
7444 // that the specific OpenMP context requires in the prototype of the
7445 // variant from the base function prototype are implementation defined."
7446 // This wording is there to allow the specialized variant to have a
7447 // different type than the base function. This is intended and OK but if
7448 // we cannot create a call the difference is not in the "implementation
7449 // defined range" we allow.
7450 Sema::TentativeAnalysisScope Trap(*this);
7452 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7453 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7454 BestExpr = MemberExpr::CreateImplicit(
7455 Context, MemberCall->getImplicitObjectArgument(),
7456 /* IsArrow */ false, SpecializedMethod, Context.BoundMemberTy,
7457 MemberCall->getValueKind(), MemberCall->getObjectKind());
7459 NewCall = BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs, RParenLoc,
7460 ExecConfig);
7461 if (NewCall.isUsable()) {
7462 if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) {
7463 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7464 QualType NewType = Context.mergeFunctionTypes(
7465 CalleeFnType, NewCalleeFnDecl->getType(),
7466 /* OfBlockPointer */ false,
7467 /* Unqualified */ false, /* AllowCXX */ true);
7468 if (!NewType.isNull())
7469 break;
7470 // Don't use the call if the function type was not compatible.
7471 NewCall = nullptr;
7476 VMIs.erase(VMIs.begin() + BestIdx);
7477 Exprs.erase(Exprs.begin() + BestIdx);
7478 } while (!VMIs.empty());
7480 if (!NewCall.isUsable())
7481 return Call;
7482 return PseudoObjectExpr::Create(Context, CE, {NewCall.get()}, 0);
7485 std::optional<std::pair<FunctionDecl *, Expr *>>
7486 Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG,
7487 Expr *VariantRef, OMPTraitInfo &TI,
7488 unsigned NumAppendArgs,
7489 SourceRange SR) {
7490 if (!DG || DG.get().isNull())
7491 return std::nullopt;
7493 const int VariantId = 1;
7494 // Must be applied only to single decl.
7495 if (!DG.get().isSingleDecl()) {
7496 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7497 << VariantId << SR;
7498 return std::nullopt;
7500 Decl *ADecl = DG.get().getSingleDecl();
7501 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7502 ADecl = FTD->getTemplatedDecl();
7504 // Decl must be a function.
7505 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7506 if (!FD) {
7507 Diag(ADecl->getLocation(), diag::err_omp_function_expected)
7508 << VariantId << SR;
7509 return std::nullopt;
7512 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7513 // The 'target' attribute needs to be separately checked because it does
7514 // not always signify a multiversion function declaration.
7515 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7517 // OpenMP is not compatible with multiversion function attributes.
7518 if (HasMultiVersionAttributes(FD)) {
7519 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7520 << SR;
7521 return std::nullopt;
7524 // Allow #pragma omp declare variant only if the function is not used.
7525 if (FD->isUsed(false))
7526 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
7527 << FD->getLocation();
7529 // Check if the function was emitted already.
7530 const FunctionDecl *Definition;
7531 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7532 (LangOpts.EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
7533 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
7534 << FD->getLocation();
7536 // The VariantRef must point to function.
7537 if (!VariantRef) {
7538 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
7539 return std::nullopt;
7542 auto ShouldDelayChecks = [](Expr *&E, bool) {
7543 return E && (E->isTypeDependent() || E->isValueDependent() ||
7544 E->containsUnexpandedParameterPack() ||
7545 E->isInstantiationDependent());
7547 // Do not check templates, wait until instantiation.
7548 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7549 TI.anyScoreOrCondition(ShouldDelayChecks))
7550 return std::make_pair(FD, VariantRef);
7552 // Deal with non-constant score and user condition expressions.
7553 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7554 bool IsScore) -> bool {
7555 if (!E || E->isIntegerConstantExpr(Context))
7556 return false;
7558 if (IsScore) {
7559 // We warn on non-constant scores and pretend they were not present.
7560 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7561 << E;
7562 E = nullptr;
7563 } else {
7564 // We could replace a non-constant user condition with "false" but we
7565 // will soon need to handle these anyway for the dynamic version of
7566 // OpenMP context selectors.
7567 Diag(E->getExprLoc(),
7568 diag::err_omp_declare_variant_user_condition_not_constant)
7569 << E;
7571 return true;
7573 if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions))
7574 return std::nullopt;
7576 QualType AdjustedFnType = FD->getType();
7577 if (NumAppendArgs) {
7578 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7579 if (!PTy) {
7580 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
7581 << SR;
7582 return std::nullopt;
7584 // Adjust the function type to account for an extra omp_interop_t for each
7585 // specified in the append_args clause.
7586 const TypeDecl *TD = nullptr;
7587 LookupResult Result(*this, &Context.Idents.get("omp_interop_t"),
7588 SR.getBegin(), Sema::LookupOrdinaryName);
7589 if (LookupName(Result, getCurScope())) {
7590 NamedDecl *ND = Result.getFoundDecl();
7591 TD = dyn_cast_or_null<TypeDecl>(ND);
7593 if (!TD) {
7594 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
7595 return std::nullopt;
7597 QualType InteropType = Context.getTypeDeclType(TD);
7598 if (PTy->isVariadic()) {
7599 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7600 return std::nullopt;
7602 llvm::SmallVector<QualType, 8> Params;
7603 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7604 Params.insert(Params.end(), NumAppendArgs, InteropType);
7605 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7606 PTy->getExtProtoInfo());
7609 // Convert VariantRef expression to the type of the original function to
7610 // resolve possible conflicts.
7611 ExprResult VariantRefCast = VariantRef;
7612 if (LangOpts.CPlusPlus) {
7613 QualType FnPtrType;
7614 auto *Method = dyn_cast<CXXMethodDecl>(FD);
7615 if (Method && !Method->isStatic()) {
7616 const Type *ClassType =
7617 Context.getTypeDeclType(Method->getParent()).getTypePtr();
7618 FnPtrType = Context.getMemberPointerType(AdjustedFnType, ClassType);
7619 ExprResult ER;
7621 // Build adrr_of unary op to correctly handle type checks for member
7622 // functions.
7623 Sema::TentativeAnalysisScope Trap(*this);
7624 ER = CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf,
7625 VariantRef);
7627 if (!ER.isUsable()) {
7628 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7629 << VariantId << VariantRef->getSourceRange();
7630 return std::nullopt;
7632 VariantRef = ER.get();
7633 } else {
7634 FnPtrType = Context.getPointerType(AdjustedFnType);
7636 QualType VarianPtrType = Context.getPointerType(VariantRef->getType());
7637 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7638 ImplicitConversionSequence ICS = TryImplicitConversion(
7639 VariantRef, FnPtrType.getUnqualifiedType(),
7640 /*SuppressUserConversions=*/false, AllowedExplicit::None,
7641 /*InOverloadResolution=*/false,
7642 /*CStyle=*/false,
7643 /*AllowObjCWritebackConversion=*/false);
7644 if (ICS.isFailure()) {
7645 Diag(VariantRef->getExprLoc(),
7646 diag::err_omp_declare_variant_incompat_types)
7647 << VariantRef->getType()
7648 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7649 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7650 return std::nullopt;
7652 VariantRefCast = PerformImplicitConversion(
7653 VariantRef, FnPtrType.getUnqualifiedType(), AA_Converting);
7654 if (!VariantRefCast.isUsable())
7655 return std::nullopt;
7657 // Drop previously built artificial addr_of unary op for member functions.
7658 if (Method && !Method->isStatic()) {
7659 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7660 if (auto *UO = dyn_cast<UnaryOperator>(
7661 PossibleAddrOfVariantRef->IgnoreImplicit()))
7662 VariantRefCast = UO->getSubExpr();
7666 ExprResult ER = CheckPlaceholderExpr(VariantRefCast.get());
7667 if (!ER.isUsable() ||
7668 !ER.get()->IgnoreParenImpCasts()->getType()->isFunctionType()) {
7669 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7670 << VariantId << VariantRef->getSourceRange();
7671 return std::nullopt;
7674 // The VariantRef must point to function.
7675 auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts());
7676 if (!DRE) {
7677 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7678 << VariantId << VariantRef->getSourceRange();
7679 return std::nullopt;
7681 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7682 if (!NewFD) {
7683 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7684 << VariantId << VariantRef->getSourceRange();
7685 return std::nullopt;
7688 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7689 Diag(VariantRef->getExprLoc(),
7690 diag::err_omp_declare_variant_same_base_function)
7691 << VariantRef->getSourceRange();
7692 return std::nullopt;
7695 // Check if function types are compatible in C.
7696 if (!LangOpts.CPlusPlus) {
7697 QualType NewType =
7698 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7699 if (NewType.isNull()) {
7700 Diag(VariantRef->getExprLoc(),
7701 diag::err_omp_declare_variant_incompat_types)
7702 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7703 << VariantRef->getSourceRange();
7704 return std::nullopt;
7706 if (NewType->isFunctionProtoType()) {
7707 if (FD->getType()->isFunctionNoProtoType())
7708 setPrototype(*this, FD, NewFD, NewType);
7709 else if (NewFD->getType()->isFunctionNoProtoType())
7710 setPrototype(*this, NewFD, FD, NewType);
7714 // Check if variant function is not marked with declare variant directive.
7715 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7716 Diag(VariantRef->getExprLoc(),
7717 diag::warn_omp_declare_variant_marked_as_declare_variant)
7718 << VariantRef->getSourceRange();
7719 SourceRange SR =
7720 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7721 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7722 return std::nullopt;
7725 enum DoesntSupport {
7726 VirtFuncs = 1,
7727 Constructors = 3,
7728 Destructors = 4,
7729 DeletedFuncs = 5,
7730 DefaultedFuncs = 6,
7731 ConstexprFuncs = 7,
7732 ConstevalFuncs = 8,
7734 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7735 if (CXXFD->isVirtual()) {
7736 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7737 << VirtFuncs;
7738 return std::nullopt;
7741 if (isa<CXXConstructorDecl>(FD)) {
7742 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7743 << Constructors;
7744 return std::nullopt;
7747 if (isa<CXXDestructorDecl>(FD)) {
7748 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7749 << Destructors;
7750 return std::nullopt;
7754 if (FD->isDeleted()) {
7755 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7756 << DeletedFuncs;
7757 return std::nullopt;
7760 if (FD->isDefaulted()) {
7761 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7762 << DefaultedFuncs;
7763 return std::nullopt;
7766 if (FD->isConstexpr()) {
7767 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7768 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7769 return std::nullopt;
7772 // Check general compatibility.
7773 if (areMultiversionVariantFunctionsCompatible(
7774 FD, NewFD, PartialDiagnostic::NullDiagnostic(),
7775 PartialDiagnosticAt(SourceLocation(),
7776 PartialDiagnostic::NullDiagnostic()),
7777 PartialDiagnosticAt(
7778 VariantRef->getExprLoc(),
7779 PDiag(diag::err_omp_declare_variant_doesnt_support)),
7780 PartialDiagnosticAt(VariantRef->getExprLoc(),
7781 PDiag(diag::err_omp_declare_variant_diff)
7782 << FD->getLocation()),
7783 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7784 /*CLinkageMayDiffer=*/true))
7785 return std::nullopt;
7786 return std::make_pair(FD, cast<Expr>(DRE));
7789 void Sema::ActOnOpenMPDeclareVariantDirective(
7790 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7791 ArrayRef<Expr *> AdjustArgsNothing,
7792 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7793 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7794 SourceLocation AppendArgsLoc, SourceRange SR) {
7796 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7797 // An adjust_args clause or append_args clause can only be specified if the
7798 // dispatch selector of the construct selector set appears in the match
7799 // clause.
7801 SmallVector<Expr *, 8> AllAdjustArgs;
7802 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7803 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7805 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7806 VariantMatchInfo VMI;
7807 TI.getAsVariantMatchInfo(Context, VMI);
7808 if (!llvm::is_contained(
7809 VMI.ConstructTraits,
7810 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7811 if (!AllAdjustArgs.empty())
7812 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7813 << getOpenMPClauseName(OMPC_adjust_args);
7814 if (!AppendArgs.empty())
7815 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7816 << getOpenMPClauseName(OMPC_append_args);
7817 return;
7821 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7822 // Each argument can only appear in a single adjust_args clause for each
7823 // declare variant directive.
7824 llvm::SmallPtrSet<const VarDecl *, 4> AdjustVars;
7826 for (Expr *E : AllAdjustArgs) {
7827 E = E->IgnoreParenImpCasts();
7828 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7829 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7830 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7831 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7832 FD->getParamDecl(PVD->getFunctionScopeIndex())
7833 ->getCanonicalDecl() == CanonPVD) {
7834 // It's a parameter of the function, check duplicates.
7835 if (!AdjustVars.insert(CanonPVD).second) {
7836 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7837 << PVD;
7838 return;
7840 continue;
7844 // Anything that is not a function parameter is an error.
7845 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7846 return;
7849 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7850 Context, VariantRef, &TI, const_cast<Expr **>(AdjustArgsNothing.data()),
7851 AdjustArgsNothing.size(),
7852 const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7853 AdjustArgsNeedDevicePtr.size(),
7854 const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR);
7855 FD->addAttr(NewAttr);
7858 StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
7859 Stmt *AStmt,
7860 SourceLocation StartLoc,
7861 SourceLocation EndLoc) {
7862 if (!AStmt)
7863 return StmtError();
7865 auto *CS = cast<CapturedStmt>(AStmt);
7866 // 1.2.2 OpenMP Language Terminology
7867 // Structured block - An executable statement with a single entry at the
7868 // top and a single exit at the bottom.
7869 // The point of exit cannot be a branch out of the structured block.
7870 // longjmp() and throw() must not violate the entry/exit criteria.
7871 CS->getCapturedDecl()->setNothrow();
7873 setFunctionHasBranchProtectedScope();
7875 return OMPParallelDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
7876 DSAStack->getTaskgroupReductionRef(),
7877 DSAStack->isCancelRegion());
7880 namespace {
7881 /// Iteration space of a single for loop.
7882 struct LoopIterationSpace final {
7883 /// True if the condition operator is the strict compare operator (<, > or
7884 /// !=).
7885 bool IsStrictCompare = false;
7886 /// Condition of the loop.
7887 Expr *PreCond = nullptr;
7888 /// This expression calculates the number of iterations in the loop.
7889 /// It is always possible to calculate it before starting the loop.
7890 Expr *NumIterations = nullptr;
7891 /// The loop counter variable.
7892 Expr *CounterVar = nullptr;
7893 /// Private loop counter variable.
7894 Expr *PrivateCounterVar = nullptr;
7895 /// This is initializer for the initial value of #CounterVar.
7896 Expr *CounterInit = nullptr;
7897 /// This is step for the #CounterVar used to generate its update:
7898 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7899 Expr *CounterStep = nullptr;
7900 /// Should step be subtracted?
7901 bool Subtract = false;
7902 /// Source range of the loop init.
7903 SourceRange InitSrcRange;
7904 /// Source range of the loop condition.
7905 SourceRange CondSrcRange;
7906 /// Source range of the loop increment.
7907 SourceRange IncSrcRange;
7908 /// Minimum value that can have the loop control variable. Used to support
7909 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
7910 /// since only such variables can be used in non-loop invariant expressions.
7911 Expr *MinValue = nullptr;
7912 /// Maximum value that can have the loop control variable. Used to support
7913 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
7914 /// since only such variables can be used in non-loop invariant expressions.
7915 Expr *MaxValue = nullptr;
7916 /// true, if the lower bound depends on the outer loop control var.
7917 bool IsNonRectangularLB = false;
7918 /// true, if the upper bound depends on the outer loop control var.
7919 bool IsNonRectangularUB = false;
7920 /// Index of the loop this loop depends on and forms non-rectangular loop
7921 /// nest.
7922 unsigned LoopDependentIdx = 0;
7923 /// Final condition for the non-rectangular loop nest support. It is used to
7924 /// check that the number of iterations for this particular counter must be
7925 /// finished.
7926 Expr *FinalCondition = nullptr;
7929 /// Helper class for checking canonical form of the OpenMP loops and
7930 /// extracting iteration space of each loop in the loop nest, that will be used
7931 /// for IR generation.
7932 class OpenMPIterationSpaceChecker {
7933 /// Reference to Sema.
7934 Sema &SemaRef;
7935 /// Does the loop associated directive support non-rectangular loops?
7936 bool SupportsNonRectangular;
7937 /// Data-sharing stack.
7938 DSAStackTy &Stack;
7939 /// A location for diagnostics (when there is no some better location).
7940 SourceLocation DefaultLoc;
7941 /// A location for diagnostics (when increment is not compatible).
7942 SourceLocation ConditionLoc;
7943 /// A source location for referring to loop init later.
7944 SourceRange InitSrcRange;
7945 /// A source location for referring to condition later.
7946 SourceRange ConditionSrcRange;
7947 /// A source location for referring to increment later.
7948 SourceRange IncrementSrcRange;
7949 /// Loop variable.
7950 ValueDecl *LCDecl = nullptr;
7951 /// Reference to loop variable.
7952 Expr *LCRef = nullptr;
7953 /// Lower bound (initializer for the var).
7954 Expr *LB = nullptr;
7955 /// Upper bound.
7956 Expr *UB = nullptr;
7957 /// Loop step (increment).
7958 Expr *Step = nullptr;
7959 /// This flag is true when condition is one of:
7960 /// Var < UB
7961 /// Var <= UB
7962 /// UB > Var
7963 /// UB >= Var
7964 /// This will have no value when the condition is !=
7965 std::optional<bool> TestIsLessOp;
7966 /// This flag is true when condition is strict ( < or > ).
7967 bool TestIsStrictOp = false;
7968 /// This flag is true when step is subtracted on each iteration.
7969 bool SubtractStep = false;
7970 /// The outer loop counter this loop depends on (if any).
7971 const ValueDecl *DepDecl = nullptr;
7972 /// Contains number of loop (starts from 1) on which loop counter init
7973 /// expression of this loop depends on.
7974 std::optional<unsigned> InitDependOnLC;
7975 /// Contains number of loop (starts from 1) on which loop counter condition
7976 /// expression of this loop depends on.
7977 std::optional<unsigned> CondDependOnLC;
7978 /// Checks if the provide statement depends on the loop counter.
7979 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
7980 bool IsInitializer);
7981 /// Original condition required for checking of the exit condition for
7982 /// non-rectangular loop.
7983 Expr *Condition = nullptr;
7985 public:
7986 OpenMPIterationSpaceChecker(Sema &SemaRef, bool SupportsNonRectangular,
7987 DSAStackTy &Stack, SourceLocation DefaultLoc)
7988 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
7989 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc) {}
7990 /// Check init-expr for canonical loop form and save loop counter
7991 /// variable - #Var and its initialization value - #LB.
7992 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
7993 /// Check test-expr for canonical form, save upper-bound (#UB), flags
7994 /// for less/greater and for strict/non-strict comparison.
7995 bool checkAndSetCond(Expr *S);
7996 /// Check incr-expr for canonical loop form and return true if it
7997 /// does not conform, otherwise save loop step (#Step).
7998 bool checkAndSetInc(Expr *S);
7999 /// Return the loop counter variable.
8000 ValueDecl *getLoopDecl() const { return LCDecl; }
8001 /// Return the reference expression to loop counter variable.
8002 Expr *getLoopDeclRefExpr() const { return LCRef; }
8003 /// Source range of the loop init.
8004 SourceRange getInitSrcRange() const { return InitSrcRange; }
8005 /// Source range of the loop condition.
8006 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
8007 /// Source range of the loop increment.
8008 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
8009 /// True if the step should be subtracted.
8010 bool shouldSubtractStep() const { return SubtractStep; }
8011 /// True, if the compare operator is strict (<, > or !=).
8012 bool isStrictTestOp() const { return TestIsStrictOp; }
8013 /// Build the expression to calculate the number of iterations.
8014 Expr *buildNumIterations(
8015 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8016 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8017 /// Build the precondition expression for the loops.
8018 Expr *
8019 buildPreCond(Scope *S, Expr *Cond,
8020 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8021 /// Build reference expression to the counter be used for codegen.
8022 DeclRefExpr *
8023 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8024 DSAStackTy &DSA) const;
8025 /// Build reference expression to the private counter be used for
8026 /// codegen.
8027 Expr *buildPrivateCounterVar() const;
8028 /// Build initialization of the counter be used for codegen.
8029 Expr *buildCounterInit() const;
8030 /// Build step of the counter be used for codegen.
8031 Expr *buildCounterStep() const;
8032 /// Build loop data with counter value for depend clauses in ordered
8033 /// directives.
8034 Expr *
8035 buildOrderedLoopData(Scope *S, Expr *Counter,
8036 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8037 SourceLocation Loc, Expr *Inc = nullptr,
8038 OverloadedOperatorKind OOK = OO_Amp);
8039 /// Builds the minimum value for the loop counter.
8040 std::pair<Expr *, Expr *> buildMinMaxValues(
8041 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8042 /// Builds final condition for the non-rectangular loops.
8043 Expr *buildFinalCondition(Scope *S) const;
8044 /// Return true if any expression is dependent.
8045 bool dependent() const;
8046 /// Returns true if the initializer forms non-rectangular loop.
8047 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
8048 /// Returns true if the condition forms non-rectangular loop.
8049 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
8050 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
8051 unsigned getLoopDependentIdx() const {
8052 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
8055 private:
8056 /// Check the right-hand side of an assignment in the increment
8057 /// expression.
8058 bool checkAndSetIncRHS(Expr *RHS);
8059 /// Helper to set loop counter variable and its initializer.
8060 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
8061 bool EmitDiags);
8062 /// Helper to set upper bound.
8063 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
8064 SourceRange SR, SourceLocation SL);
8065 /// Helper to set loop increment.
8066 bool setStep(Expr *NewStep, bool Subtract);
8069 bool OpenMPIterationSpaceChecker::dependent() const {
8070 if (!LCDecl) {
8071 assert(!LB && !UB && !Step);
8072 return false;
8074 return LCDecl->getType()->isDependentType() ||
8075 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
8076 (Step && Step->isValueDependent());
8079 bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
8080 Expr *NewLCRefExpr,
8081 Expr *NewLB, bool EmitDiags) {
8082 // State consistency checking to ensure correct usage.
8083 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
8084 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8085 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
8086 return true;
8087 LCDecl = getCanonicalDecl(NewLCDecl);
8088 LCRef = NewLCRefExpr;
8089 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
8090 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8091 if ((Ctor->isCopyOrMoveConstructor() ||
8092 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8093 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8094 NewLB = CE->getArg(0)->IgnoreParenImpCasts();
8095 LB = NewLB;
8096 if (EmitDiags)
8097 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
8098 return false;
8101 bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
8102 bool StrictOp, SourceRange SR,
8103 SourceLocation SL) {
8104 // State consistency checking to ensure correct usage.
8105 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
8106 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8107 if (!NewUB || NewUB->containsErrors())
8108 return true;
8109 UB = NewUB;
8110 if (LessOp)
8111 TestIsLessOp = LessOp;
8112 TestIsStrictOp = StrictOp;
8113 ConditionSrcRange = SR;
8114 ConditionLoc = SL;
8115 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
8116 return false;
8119 bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
8120 // State consistency checking to ensure correct usage.
8121 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
8122 if (!NewStep || NewStep->containsErrors())
8123 return true;
8124 if (!NewStep->isValueDependent()) {
8125 // Check that the step is integer expression.
8126 SourceLocation StepLoc = NewStep->getBeginLoc();
8127 ExprResult Val = SemaRef.PerformOpenMPImplicitIntegerConversion(
8128 StepLoc, getExprAsWritten(NewStep));
8129 if (Val.isInvalid())
8130 return true;
8131 NewStep = Val.get();
8133 // OpenMP [2.6, Canonical Loop Form, Restrictions]
8134 // If test-expr is of form var relational-op b and relational-op is < or
8135 // <= then incr-expr must cause var to increase on each iteration of the
8136 // loop. If test-expr is of form var relational-op b and relational-op is
8137 // > or >= then incr-expr must cause var to decrease on each iteration of
8138 // the loop.
8139 // If test-expr is of form b relational-op var and relational-op is < or
8140 // <= then incr-expr must cause var to decrease on each iteration of the
8141 // loop. If test-expr is of form b relational-op var and relational-op is
8142 // > or >= then incr-expr must cause var to increase on each iteration of
8143 // the loop.
8144 std::optional<llvm::APSInt> Result =
8145 NewStep->getIntegerConstantExpr(SemaRef.Context);
8146 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
8147 bool IsConstNeg =
8148 Result && Result->isSigned() && (Subtract != Result->isNegative());
8149 bool IsConstPos =
8150 Result && Result->isSigned() && (Subtract == Result->isNegative());
8151 bool IsConstZero = Result && !Result->getBoolValue();
8153 // != with increment is treated as <; != with decrement is treated as >
8154 if (!TestIsLessOp)
8155 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8156 if (UB && (IsConstZero ||
8157 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8158 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8159 SemaRef.Diag(NewStep->getExprLoc(),
8160 diag::err_omp_loop_incr_not_compatible)
8161 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
8162 SemaRef.Diag(ConditionLoc,
8163 diag::note_omp_loop_cond_requres_compatible_incr)
8164 << *TestIsLessOp << ConditionSrcRange;
8165 return true;
8167 if (*TestIsLessOp == Subtract) {
8168 NewStep =
8169 SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
8170 .get();
8171 Subtract = !Subtract;
8175 Step = NewStep;
8176 SubtractStep = Subtract;
8177 return false;
8180 namespace {
8181 /// Checker for the non-rectangular loops. Checks if the initializer or
8182 /// condition expression references loop counter variable.
8183 class LoopCounterRefChecker final
8184 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
8185 Sema &SemaRef;
8186 DSAStackTy &Stack;
8187 const ValueDecl *CurLCDecl = nullptr;
8188 const ValueDecl *DepDecl = nullptr;
8189 const ValueDecl *PrevDepDecl = nullptr;
8190 bool IsInitializer = true;
8191 bool SupportsNonRectangular;
8192 unsigned BaseLoopId = 0;
8193 bool checkDecl(const Expr *E, const ValueDecl *VD) {
8194 if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
8195 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8196 << (IsInitializer ? 0 : 1);
8197 return false;
8199 const auto &&Data = Stack.isLoopControlVariable(VD);
8200 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8201 // The type of the loop iterator on which we depend may not have a random
8202 // access iterator type.
8203 if (Data.first && VD->getType()->isRecordType()) {
8204 SmallString<128> Name;
8205 llvm::raw_svector_ostream OS(Name);
8206 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8207 /*Qualified=*/true);
8208 SemaRef.Diag(E->getExprLoc(),
8209 diag::err_omp_wrong_dependency_iterator_type)
8210 << OS.str();
8211 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
8212 return false;
8214 if (Data.first && !SupportsNonRectangular) {
8215 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
8216 return false;
8218 if (Data.first &&
8219 (DepDecl || (PrevDepDecl &&
8220 getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
8221 if (!DepDecl && PrevDepDecl)
8222 DepDecl = PrevDepDecl;
8223 SmallString<128> Name;
8224 llvm::raw_svector_ostream OS(Name);
8225 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8226 /*Qualified=*/true);
8227 SemaRef.Diag(E->getExprLoc(),
8228 diag::err_omp_invariant_or_linear_dependency)
8229 << OS.str();
8230 return false;
8232 if (Data.first) {
8233 DepDecl = VD;
8234 BaseLoopId = Data.first;
8236 return Data.first;
8239 public:
8240 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8241 const ValueDecl *VD = E->getDecl();
8242 if (isa<VarDecl>(VD))
8243 return checkDecl(E, VD);
8244 return false;
8246 bool VisitMemberExpr(const MemberExpr *E) {
8247 if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
8248 const ValueDecl *VD = E->getMemberDecl();
8249 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8250 return checkDecl(E, VD);
8252 return false;
8254 bool VisitStmt(const Stmt *S) {
8255 bool Res = false;
8256 for (const Stmt *Child : S->children())
8257 Res = (Child && Visit(Child)) || Res;
8258 return Res;
8260 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8261 const ValueDecl *CurLCDecl, bool IsInitializer,
8262 const ValueDecl *PrevDepDecl = nullptr,
8263 bool SupportsNonRectangular = true)
8264 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8265 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8266 SupportsNonRectangular(SupportsNonRectangular) {}
8267 unsigned getBaseLoopId() const {
8268 assert(CurLCDecl && "Expected loop dependency.");
8269 return BaseLoopId;
8271 const ValueDecl *getDepDecl() const {
8272 assert(CurLCDecl && "Expected loop dependency.");
8273 return DepDecl;
8276 } // namespace
8278 std::optional<unsigned>
8279 OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8280 bool IsInitializer) {
8281 // Check for the non-rectangular loops.
8282 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8283 DepDecl, SupportsNonRectangular);
8284 if (LoopStmtChecker.Visit(S)) {
8285 DepDecl = LoopStmtChecker.getDepDecl();
8286 return LoopStmtChecker.getBaseLoopId();
8288 return std::nullopt;
8291 bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8292 // Check init-expr for canonical loop form and save loop counter
8293 // variable - #Var and its initialization value - #LB.
8294 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8295 // var = lb
8296 // integer-type var = lb
8297 // random-access-iterator-type var = lb
8298 // pointer-type var = lb
8300 if (!S) {
8301 if (EmitDiags) {
8302 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8304 return true;
8306 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8307 if (!ExprTemp->cleanupsHaveSideEffects())
8308 S = ExprTemp->getSubExpr();
8310 InitSrcRange = S->getSourceRange();
8311 if (Expr *E = dyn_cast<Expr>(S))
8312 S = E->IgnoreParens();
8313 if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8314 if (BO->getOpcode() == BO_Assign) {
8315 Expr *LHS = BO->getLHS()->IgnoreParens();
8316 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8317 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8318 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8319 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8320 EmitDiags);
8321 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8323 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8324 if (ME->isArrow() &&
8325 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8326 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8327 EmitDiags);
8330 } else if (auto *DS = dyn_cast<DeclStmt>(S)) {
8331 if (DS->isSingleDecl()) {
8332 if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8333 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8334 // Accept non-canonical init form here but emit ext. warning.
8335 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8336 SemaRef.Diag(S->getBeginLoc(),
8337 diag::ext_omp_loop_not_canonical_init)
8338 << S->getSourceRange();
8339 return setLCDeclAndLB(
8340 Var,
8341 buildDeclRefExpr(SemaRef, Var,
8342 Var->getType().getNonReferenceType(),
8343 DS->getBeginLoc()),
8344 Var->getInit(), EmitDiags);
8348 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8349 if (CE->getOperator() == OO_Equal) {
8350 Expr *LHS = CE->getArg(0);
8351 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8352 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8353 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8354 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8355 EmitDiags);
8356 return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags);
8358 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8359 if (ME->isArrow() &&
8360 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8361 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8362 EmitDiags);
8367 if (dependent() || SemaRef.CurContext->isDependentContext())
8368 return false;
8369 if (EmitDiags) {
8370 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8371 << S->getSourceRange();
8373 return true;
8376 /// Ignore parenthesizes, implicit casts, copy constructor and return the
8377 /// variable (which may be the loop variable) if possible.
8378 static const ValueDecl *getInitLCDecl(const Expr *E) {
8379 if (!E)
8380 return nullptr;
8381 E = getExprAsWritten(E);
8382 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8383 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8384 if ((Ctor->isCopyOrMoveConstructor() ||
8385 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8386 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8387 E = CE->getArg(0)->IgnoreParenImpCasts();
8388 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8389 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
8390 return getCanonicalDecl(VD);
8392 if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8393 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8394 return getCanonicalDecl(ME->getMemberDecl());
8395 return nullptr;
8398 bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8399 // Check test-expr for canonical form, save upper-bound UB, flags for
8400 // less/greater and for strict/non-strict comparison.
8401 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8402 // var relational-op b
8403 // b relational-op var
8405 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8406 if (!S) {
8407 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8408 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8409 return true;
8411 Condition = S;
8412 S = getExprAsWritten(S);
8413 SourceLocation CondLoc = S->getBeginLoc();
8414 auto &&CheckAndSetCond =
8415 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8416 const Expr *RHS, SourceRange SR,
8417 SourceLocation OpLoc) -> std::optional<bool> {
8418 if (BinaryOperator::isRelationalOp(Opcode)) {
8419 if (getInitLCDecl(LHS) == LCDecl)
8420 return setUB(const_cast<Expr *>(RHS),
8421 (Opcode == BO_LT || Opcode == BO_LE),
8422 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8423 if (getInitLCDecl(RHS) == LCDecl)
8424 return setUB(const_cast<Expr *>(LHS),
8425 (Opcode == BO_GT || Opcode == BO_GE),
8426 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8427 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8428 return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8429 /*LessOp=*/std::nullopt,
8430 /*StrictOp=*/true, SR, OpLoc);
8432 return std::nullopt;
8434 std::optional<bool> Res;
8435 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8436 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8437 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8438 RBO->getOperatorLoc());
8439 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8440 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8441 BO->getSourceRange(), BO->getOperatorLoc());
8442 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8443 if (CE->getNumArgs() == 2) {
8444 Res = CheckAndSetCond(
8445 BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0),
8446 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8449 if (Res)
8450 return *Res;
8451 if (dependent() || SemaRef.CurContext->isDependentContext())
8452 return false;
8453 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8454 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8455 return true;
8458 bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8459 // RHS of canonical loop form increment can be:
8460 // var + incr
8461 // incr + var
8462 // var - incr
8464 RHS = RHS->IgnoreParenImpCasts();
8465 if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8466 if (BO->isAdditiveOp()) {
8467 bool IsAdd = BO->getOpcode() == BO_Add;
8468 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8469 return setStep(BO->getRHS(), !IsAdd);
8470 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8471 return setStep(BO->getLHS(), /*Subtract=*/false);
8473 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8474 bool IsAdd = CE->getOperator() == OO_Plus;
8475 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8476 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8477 return setStep(CE->getArg(1), !IsAdd);
8478 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8479 return setStep(CE->getArg(0), /*Subtract=*/false);
8482 if (dependent() || SemaRef.CurContext->isDependentContext())
8483 return false;
8484 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8485 << RHS->getSourceRange() << LCDecl;
8486 return true;
8489 bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8490 // Check incr-expr for canonical loop form and return true if it
8491 // does not conform.
8492 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8493 // ++var
8494 // var++
8495 // --var
8496 // var--
8497 // var += incr
8498 // var -= incr
8499 // var = var + incr
8500 // var = incr + var
8501 // var = var - incr
8503 if (!S) {
8504 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8505 return true;
8507 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8508 if (!ExprTemp->cleanupsHaveSideEffects())
8509 S = ExprTemp->getSubExpr();
8511 IncrementSrcRange = S->getSourceRange();
8512 S = S->IgnoreParens();
8513 if (auto *UO = dyn_cast<UnaryOperator>(S)) {
8514 if (UO->isIncrementDecrementOp() &&
8515 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8516 return setStep(SemaRef
8517 .ActOnIntegerConstant(UO->getBeginLoc(),
8518 (UO->isDecrementOp() ? -1 : 1))
8519 .get(),
8520 /*Subtract=*/false);
8521 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8522 switch (BO->getOpcode()) {
8523 case BO_AddAssign:
8524 case BO_SubAssign:
8525 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8526 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8527 break;
8528 case BO_Assign:
8529 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8530 return checkAndSetIncRHS(BO->getRHS());
8531 break;
8532 default:
8533 break;
8535 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8536 switch (CE->getOperator()) {
8537 case OO_PlusPlus:
8538 case OO_MinusMinus:
8539 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8540 return setStep(SemaRef
8541 .ActOnIntegerConstant(
8542 CE->getBeginLoc(),
8543 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8544 .get(),
8545 /*Subtract=*/false);
8546 break;
8547 case OO_PlusEqual:
8548 case OO_MinusEqual:
8549 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8550 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8551 break;
8552 case OO_Equal:
8553 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8554 return checkAndSetIncRHS(CE->getArg(1));
8555 break;
8556 default:
8557 break;
8560 if (dependent() || SemaRef.CurContext->isDependentContext())
8561 return false;
8562 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8563 << S->getSourceRange() << LCDecl;
8564 return true;
8567 static ExprResult
8568 tryBuildCapture(Sema &SemaRef, Expr *Capture,
8569 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8570 StringRef Name = ".capture_expr.") {
8571 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8572 return Capture;
8573 if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects))
8574 return SemaRef.PerformImplicitConversion(
8575 Capture->IgnoreImpCasts(), Capture->getType(), Sema::AA_Converting,
8576 /*AllowExplicit=*/true);
8577 auto I = Captures.find(Capture);
8578 if (I != Captures.end())
8579 return buildCapture(SemaRef, Capture, I->second, Name);
8580 DeclRefExpr *Ref = nullptr;
8581 ExprResult Res = buildCapture(SemaRef, Capture, Ref, Name);
8582 Captures[Capture] = Ref;
8583 return Res;
8586 /// Calculate number of iterations, transforming to unsigned, if number of
8587 /// iterations may be larger than the original type.
8588 static Expr *
8589 calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8590 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8591 bool TestIsStrictOp, bool RoundToStep,
8592 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8593 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8594 if (!NewStep.isUsable())
8595 return nullptr;
8596 llvm::APSInt LRes, SRes;
8597 bool IsLowerConst = false, IsStepConst = false;
8598 if (std::optional<llvm::APSInt> Res =
8599 Lower->getIntegerConstantExpr(SemaRef.Context)) {
8600 LRes = *Res;
8601 IsLowerConst = true;
8603 if (std::optional<llvm::APSInt> Res =
8604 Step->getIntegerConstantExpr(SemaRef.Context)) {
8605 SRes = *Res;
8606 IsStepConst = true;
8608 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8609 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8610 (TestIsStrictOp && LRes.isStrictlyPositive()));
8611 bool NeedToReorganize = false;
8612 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8613 if (!NoNeedToConvert && IsLowerConst &&
8614 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8615 NoNeedToConvert = true;
8616 if (RoundToStep) {
8617 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8618 ? LRes.getBitWidth()
8619 : SRes.getBitWidth();
8620 LRes = LRes.extend(BW + 1);
8621 LRes.setIsSigned(true);
8622 SRes = SRes.extend(BW + 1);
8623 SRes.setIsSigned(true);
8624 LRes -= SRes;
8625 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8626 LRes = LRes.trunc(BW);
8628 if (TestIsStrictOp) {
8629 unsigned BW = LRes.getBitWidth();
8630 LRes = LRes.extend(BW + 1);
8631 LRes.setIsSigned(true);
8632 ++LRes;
8633 NoNeedToConvert =
8634 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8635 // truncate to the original bitwidth.
8636 LRes = LRes.trunc(BW);
8638 NeedToReorganize = NoNeedToConvert;
8640 llvm::APSInt URes;
8641 bool IsUpperConst = false;
8642 if (std::optional<llvm::APSInt> Res =
8643 Upper->getIntegerConstantExpr(SemaRef.Context)) {
8644 URes = *Res;
8645 IsUpperConst = true;
8647 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8648 (!RoundToStep || IsStepConst)) {
8649 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8650 : URes.getBitWidth();
8651 LRes = LRes.extend(BW + 1);
8652 LRes.setIsSigned(true);
8653 URes = URes.extend(BW + 1);
8654 URes.setIsSigned(true);
8655 URes -= LRes;
8656 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8657 NeedToReorganize = NoNeedToConvert;
8659 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8660 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8661 // unsigned.
8662 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8663 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8664 QualType LowerTy = Lower->getType();
8665 QualType UpperTy = Upper->getType();
8666 uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy);
8667 uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy);
8668 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8669 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8670 QualType CastType = SemaRef.Context.getIntTypeForBitwidth(
8671 LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8672 Upper =
8673 SemaRef
8674 .PerformImplicitConversion(
8675 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8676 CastType, Sema::AA_Converting)
8677 .get();
8678 Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get();
8679 NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get());
8682 if (!Lower || !Upper || NewStep.isInvalid())
8683 return nullptr;
8685 ExprResult Diff;
8686 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8687 // 1]).
8688 if (NeedToReorganize) {
8689 Diff = Lower;
8691 if (RoundToStep) {
8692 // Lower - Step
8693 Diff =
8694 SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get());
8695 if (!Diff.isUsable())
8696 return nullptr;
8699 // Lower - Step [+ 1]
8700 if (TestIsStrictOp)
8701 Diff = SemaRef.BuildBinOp(
8702 S, DefaultLoc, BO_Add, Diff.get(),
8703 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8704 if (!Diff.isUsable())
8705 return nullptr;
8707 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8708 if (!Diff.isUsable())
8709 return nullptr;
8711 // Upper - (Lower - Step [+ 1]).
8712 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get());
8713 if (!Diff.isUsable())
8714 return nullptr;
8715 } else {
8716 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8718 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8719 // BuildBinOp already emitted error, this one is to point user to upper
8720 // and lower bound, and to tell what is passed to 'operator-'.
8721 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
8722 << Upper->getSourceRange() << Lower->getSourceRange();
8723 return nullptr;
8726 if (!Diff.isUsable())
8727 return nullptr;
8729 // Upper - Lower [- 1]
8730 if (TestIsStrictOp)
8731 Diff = SemaRef.BuildBinOp(
8732 S, DefaultLoc, BO_Sub, Diff.get(),
8733 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8734 if (!Diff.isUsable())
8735 return nullptr;
8737 if (RoundToStep) {
8738 // Upper - Lower [- 1] + Step
8739 Diff =
8740 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
8741 if (!Diff.isUsable())
8742 return nullptr;
8746 // Parentheses (for dumping/debugging purposes only).
8747 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8748 if (!Diff.isUsable())
8749 return nullptr;
8751 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8752 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
8753 if (!Diff.isUsable())
8754 return nullptr;
8756 return Diff.get();
8759 /// Build the expression to calculate the number of iterations.
8760 Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8761 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8762 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8763 QualType VarType = LCDecl->getType().getNonReferenceType();
8764 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8765 !SemaRef.getLangOpts().CPlusPlus)
8766 return nullptr;
8767 Expr *LBVal = LB;
8768 Expr *UBVal = UB;
8769 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8770 // max(LB(MinVal), LB(MaxVal)))
8771 if (InitDependOnLC) {
8772 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8773 if (!IS.MinValue || !IS.MaxValue)
8774 return nullptr;
8775 // OuterVar = Min
8776 ExprResult MinValue =
8777 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8778 if (!MinValue.isUsable())
8779 return nullptr;
8781 ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8782 IS.CounterVar, MinValue.get());
8783 if (!LBMinVal.isUsable())
8784 return nullptr;
8785 // OuterVar = Min, LBVal
8786 LBMinVal =
8787 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal);
8788 if (!LBMinVal.isUsable())
8789 return nullptr;
8790 // (OuterVar = Min, LBVal)
8791 LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get());
8792 if (!LBMinVal.isUsable())
8793 return nullptr;
8795 // OuterVar = Max
8796 ExprResult MaxValue =
8797 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8798 if (!MaxValue.isUsable())
8799 return nullptr;
8801 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8802 IS.CounterVar, MaxValue.get());
8803 if (!LBMaxVal.isUsable())
8804 return nullptr;
8805 // OuterVar = Max, LBVal
8806 LBMaxVal =
8807 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal);
8808 if (!LBMaxVal.isUsable())
8809 return nullptr;
8810 // (OuterVar = Max, LBVal)
8811 LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get());
8812 if (!LBMaxVal.isUsable())
8813 return nullptr;
8815 Expr *LBMin =
8816 tryBuildCapture(SemaRef, LBMinVal.get(), Captures, ".lb_min").get();
8817 Expr *LBMax =
8818 tryBuildCapture(SemaRef, LBMaxVal.get(), Captures, ".lb_max").get();
8819 if (!LBMin || !LBMax)
8820 return nullptr;
8821 // LB(MinVal) < LB(MaxVal)
8822 ExprResult MinLessMaxRes =
8823 SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8824 if (!MinLessMaxRes.isUsable())
8825 return nullptr;
8826 Expr *MinLessMax =
8827 tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures, ".min_less_max")
8828 .get();
8829 if (!MinLessMax)
8830 return nullptr;
8831 if (*TestIsLessOp) {
8832 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8833 // LB(MaxVal))
8834 ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8835 MinLessMax, LBMin, LBMax);
8836 if (!MinLB.isUsable())
8837 return nullptr;
8838 LBVal = MinLB.get();
8839 } else {
8840 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8841 // LB(MaxVal))
8842 ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8843 MinLessMax, LBMax, LBMin);
8844 if (!MaxLB.isUsable())
8845 return nullptr;
8846 LBVal = MaxLB.get();
8848 // OuterVar = LB
8849 LBMinVal =
8850 SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8851 if (!LBMinVal.isUsable())
8852 return nullptr;
8853 LBVal = LBMinVal.get();
8855 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8856 // min(UB(MinVal), UB(MaxVal))
8857 if (CondDependOnLC) {
8858 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8859 if (!IS.MinValue || !IS.MaxValue)
8860 return nullptr;
8861 // OuterVar = Min
8862 ExprResult MinValue =
8863 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8864 if (!MinValue.isUsable())
8865 return nullptr;
8867 ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8868 IS.CounterVar, MinValue.get());
8869 if (!UBMinVal.isUsable())
8870 return nullptr;
8871 // OuterVar = Min, UBVal
8872 UBMinVal =
8873 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal);
8874 if (!UBMinVal.isUsable())
8875 return nullptr;
8876 // (OuterVar = Min, UBVal)
8877 UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get());
8878 if (!UBMinVal.isUsable())
8879 return nullptr;
8881 // OuterVar = Max
8882 ExprResult MaxValue =
8883 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8884 if (!MaxValue.isUsable())
8885 return nullptr;
8887 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8888 IS.CounterVar, MaxValue.get());
8889 if (!UBMaxVal.isUsable())
8890 return nullptr;
8891 // OuterVar = Max, UBVal
8892 UBMaxVal =
8893 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal);
8894 if (!UBMaxVal.isUsable())
8895 return nullptr;
8896 // (OuterVar = Max, UBVal)
8897 UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get());
8898 if (!UBMaxVal.isUsable())
8899 return nullptr;
8901 Expr *UBMin =
8902 tryBuildCapture(SemaRef, UBMinVal.get(), Captures, ".ub_min").get();
8903 Expr *UBMax =
8904 tryBuildCapture(SemaRef, UBMaxVal.get(), Captures, ".ub_max").get();
8905 if (!UBMin || !UBMax)
8906 return nullptr;
8907 // UB(MinVal) > UB(MaxVal)
8908 ExprResult MinGreaterMaxRes =
8909 SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
8910 if (!MinGreaterMaxRes.isUsable())
8911 return nullptr;
8912 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.get(),
8913 Captures, ".min_greater_max")
8914 .get();
8915 if (!MinGreaterMax)
8916 return nullptr;
8917 if (*TestIsLessOp) {
8918 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
8919 // UB(MaxVal))
8920 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
8921 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
8922 if (!MaxUB.isUsable())
8923 return nullptr;
8924 UBVal = MaxUB.get();
8925 } else {
8926 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
8927 // UB(MaxVal))
8928 ExprResult MinUB = SemaRef.ActOnConditionalOp(
8929 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
8930 if (!MinUB.isUsable())
8931 return nullptr;
8932 UBVal = MinUB.get();
8935 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
8936 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
8937 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures, ".upper").get();
8938 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures, ".lower").get();
8939 if (!Upper || !Lower)
8940 return nullptr;
8942 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8943 Step, VarType, TestIsStrictOp,
8944 /*RoundToStep=*/true, Captures);
8945 if (!Diff.isUsable())
8946 return nullptr;
8948 // OpenMP runtime requires 32-bit or 64-bit loop variables.
8949 QualType Type = Diff.get()->getType();
8950 ASTContext &C = SemaRef.Context;
8951 bool UseVarType = VarType->hasIntegerRepresentation() &&
8952 C.getTypeSize(Type) > C.getTypeSize(VarType);
8953 if (!Type->isIntegerType() || UseVarType) {
8954 unsigned NewSize =
8955 UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type);
8956 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
8957 : Type->hasSignedIntegerRepresentation();
8958 Type = C.getIntTypeForBitwidth(NewSize, IsSigned);
8959 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) {
8960 Diff = SemaRef.PerformImplicitConversion(
8961 Diff.get(), Type, Sema::AA_Converting, /*AllowExplicit=*/true);
8962 if (!Diff.isUsable())
8963 return nullptr;
8966 if (LimitedType) {
8967 unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
8968 if (NewSize != C.getTypeSize(Type)) {
8969 if (NewSize < C.getTypeSize(Type)) {
8970 assert(NewSize == 64 && "incorrect loop var size");
8971 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
8972 << InitSrcRange << ConditionSrcRange;
8974 QualType NewType = C.getIntTypeForBitwidth(
8975 NewSize, Type->hasSignedIntegerRepresentation() ||
8976 C.getTypeSize(Type) < NewSize);
8977 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) {
8978 Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
8979 Sema::AA_Converting, true);
8980 if (!Diff.isUsable())
8981 return nullptr;
8986 return Diff.get();
8989 std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
8990 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8991 // Do not build for iterators, they cannot be used in non-rectangular loop
8992 // nests.
8993 if (LCDecl->getType()->isRecordType())
8994 return std::make_pair(nullptr, nullptr);
8995 // If we subtract, the min is in the condition, otherwise the min is in the
8996 // init value.
8997 Expr *MinExpr = nullptr;
8998 Expr *MaxExpr = nullptr;
8999 Expr *LBExpr = *TestIsLessOp ? LB : UB;
9000 Expr *UBExpr = *TestIsLessOp ? UB : LB;
9001 bool LBNonRect =
9002 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
9003 bool UBNonRect =
9004 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
9005 Expr *Lower =
9006 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
9007 Expr *Upper =
9008 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
9009 if (!Upper || !Lower)
9010 return std::make_pair(nullptr, nullptr);
9012 if (*TestIsLessOp)
9013 MinExpr = Lower;
9014 else
9015 MaxExpr = Upper;
9017 // Build minimum/maximum value based on number of iterations.
9018 QualType VarType = LCDecl->getType().getNonReferenceType();
9020 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9021 Step, VarType, TestIsStrictOp,
9022 /*RoundToStep=*/false, Captures);
9023 if (!Diff.isUsable())
9024 return std::make_pair(nullptr, nullptr);
9026 // ((Upper - Lower [- 1]) / Step) * Step
9027 // Parentheses (for dumping/debugging purposes only).
9028 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9029 if (!Diff.isUsable())
9030 return std::make_pair(nullptr, nullptr);
9032 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
9033 if (!NewStep.isUsable())
9034 return std::make_pair(nullptr, nullptr);
9035 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get());
9036 if (!Diff.isUsable())
9037 return std::make_pair(nullptr, nullptr);
9039 // Parentheses (for dumping/debugging purposes only).
9040 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9041 if (!Diff.isUsable())
9042 return std::make_pair(nullptr, nullptr);
9044 // Convert to the ptrdiff_t, if original type is pointer.
9045 if (VarType->isAnyPointerType() &&
9046 !SemaRef.Context.hasSameType(
9047 Diff.get()->getType(),
9048 SemaRef.Context.getUnsignedPointerDiffType())) {
9049 Diff = SemaRef.PerformImplicitConversion(
9050 Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(),
9051 Sema::AA_Converting, /*AllowExplicit=*/true);
9053 if (!Diff.isUsable())
9054 return std::make_pair(nullptr, nullptr);
9056 if (*TestIsLessOp) {
9057 // MinExpr = Lower;
9058 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
9059 Diff = SemaRef.BuildBinOp(
9060 S, DefaultLoc, BO_Add,
9061 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(),
9062 Diff.get());
9063 if (!Diff.isUsable())
9064 return std::make_pair(nullptr, nullptr);
9065 } else {
9066 // MaxExpr = Upper;
9067 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
9068 Diff = SemaRef.BuildBinOp(
9069 S, DefaultLoc, BO_Sub,
9070 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
9071 Diff.get());
9072 if (!Diff.isUsable())
9073 return std::make_pair(nullptr, nullptr);
9076 // Convert to the original type.
9077 if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType))
9078 Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType,
9079 Sema::AA_Converting,
9080 /*AllowExplicit=*/true);
9081 if (!Diff.isUsable())
9082 return std::make_pair(nullptr, nullptr);
9084 Sema::TentativeAnalysisScope Trap(SemaRef);
9085 Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false);
9086 if (!Diff.isUsable())
9087 return std::make_pair(nullptr, nullptr);
9089 if (*TestIsLessOp)
9090 MaxExpr = Diff.get();
9091 else
9092 MinExpr = Diff.get();
9094 return std::make_pair(MinExpr, MaxExpr);
9097 Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
9098 if (InitDependOnLC || CondDependOnLC)
9099 return Condition;
9100 return nullptr;
9103 Expr *OpenMPIterationSpaceChecker::buildPreCond(
9104 Scope *S, Expr *Cond,
9105 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9106 // Do not build a precondition when the condition/initialization is dependent
9107 // to prevent pessimistic early loop exit.
9108 // TODO: this can be improved by calculating min/max values but not sure that
9109 // it will be very effective.
9110 if (CondDependOnLC || InitDependOnLC)
9111 return SemaRef
9112 .PerformImplicitConversion(
9113 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(),
9114 SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
9115 /*AllowExplicit=*/true)
9116 .get();
9118 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
9119 Sema::TentativeAnalysisScope Trap(SemaRef);
9121 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
9122 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
9123 if (!NewLB.isUsable() || !NewUB.isUsable())
9124 return nullptr;
9126 ExprResult CondExpr =
9127 SemaRef.BuildBinOp(S, DefaultLoc,
9128 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
9129 : (TestIsStrictOp ? BO_GT : BO_GE),
9130 NewLB.get(), NewUB.get());
9131 if (CondExpr.isUsable()) {
9132 if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
9133 SemaRef.Context.BoolTy))
9134 CondExpr = SemaRef.PerformImplicitConversion(
9135 CondExpr.get(), SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
9136 /*AllowExplicit=*/true);
9139 // Otherwise use original loop condition and evaluate it in runtime.
9140 return CondExpr.isUsable() ? CondExpr.get() : Cond;
9143 /// Build reference expression to the counter be used for codegen.
9144 DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9145 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9146 DSAStackTy &DSA) const {
9147 auto *VD = dyn_cast<VarDecl>(LCDecl);
9148 if (!VD) {
9149 VD = SemaRef.isOpenMPCapturedDecl(LCDecl);
9150 DeclRefExpr *Ref = buildDeclRefExpr(
9151 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
9152 const DSAStackTy::DSAVarData Data =
9153 DSA.getTopDSA(LCDecl, /*FromParent=*/false);
9154 // If the loop control decl is explicitly marked as private, do not mark it
9155 // as captured again.
9156 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
9157 Captures.insert(std::make_pair(LCRef, Ref));
9158 return Ref;
9160 return cast<DeclRefExpr>(LCRef);
9163 Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9164 if (LCDecl && !LCDecl->isInvalidDecl()) {
9165 QualType Type = LCDecl->getType().getNonReferenceType();
9166 VarDecl *PrivateVar = buildVarDecl(
9167 SemaRef, DefaultLoc, Type, LCDecl->getName(),
9168 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9169 isa<VarDecl>(LCDecl)
9170 ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
9171 : nullptr);
9172 if (PrivateVar->isInvalidDecl())
9173 return nullptr;
9174 return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
9176 return nullptr;
9179 /// Build initialization of the counter to be used for codegen.
9180 Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9182 /// Build step of the counter be used for codegen.
9183 Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9185 Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9186 Scope *S, Expr *Counter,
9187 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9188 Expr *Inc, OverloadedOperatorKind OOK) {
9189 Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
9190 if (!Cnt)
9191 return nullptr;
9192 if (Inc) {
9193 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9194 "Expected only + or - operations for depend clauses.");
9195 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9196 Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
9197 if (!Cnt)
9198 return nullptr;
9200 QualType VarType = LCDecl->getType().getNonReferenceType();
9201 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9202 !SemaRef.getLangOpts().CPlusPlus)
9203 return nullptr;
9204 // Upper - Lower
9205 Expr *Upper =
9206 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9207 Expr *Lower =
9208 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9209 if (!Upper || !Lower)
9210 return nullptr;
9212 ExprResult Diff = calculateNumIters(
9213 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9214 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures);
9215 if (!Diff.isUsable())
9216 return nullptr;
9218 return Diff.get();
9220 } // namespace
9222 void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) {
9223 assert(getLangOpts().OpenMP && "OpenMP is not active.");
9224 assert(Init && "Expected loop in canonical form.");
9225 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9226 if (AssociatedLoops > 0 &&
9227 isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
9228 DSAStack->loopStart();
9229 OpenMPIterationSpaceChecker ISC(*this, /*SupportsNonRectangular=*/true,
9230 *DSAStack, ForLoc);
9231 if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
9232 if (ValueDecl *D = ISC.getLoopDecl()) {
9233 auto *VD = dyn_cast<VarDecl>(D);
9234 DeclRefExpr *PrivateRef = nullptr;
9235 if (!VD) {
9236 if (VarDecl *Private = isOpenMPCapturedDecl(D)) {
9237 VD = Private;
9238 } else {
9239 PrivateRef = buildCapture(*this, D, ISC.getLoopDeclRefExpr(),
9240 /*WithInit=*/false);
9241 VD = cast<VarDecl>(PrivateRef->getDecl());
9244 DSAStack->addLoopControlVariable(D, VD);
9245 const Decl *LD = DSAStack->getPossiblyLoopCunter();
9246 if (LD != D->getCanonicalDecl()) {
9247 DSAStack->resetPossibleLoopCounter();
9248 if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
9249 MarkDeclarationsReferencedInExpr(
9250 buildDeclRefExpr(*this, const_cast<VarDecl *>(Var),
9251 Var->getType().getNonLValueExprType(Context),
9252 ForLoc, /*RefersToCapture=*/true));
9254 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9255 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9256 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9257 // associated for-loop of a simd construct with just one associated
9258 // for-loop may be listed in a linear clause with a constant-linear-step
9259 // that is the increment of the associated for-loop. The loop iteration
9260 // variable(s) in the associated for-loop(s) of a for or parallel for
9261 // construct may be listed in a private or lastprivate clause.
9262 DSAStackTy::DSAVarData DVar =
9263 DSAStack->getTopDSA(D, /*FromParent=*/false);
9264 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9265 // is declared in the loop and it is predetermined as a private.
9266 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9267 OpenMPClauseKind PredeterminedCKind =
9268 isOpenMPSimdDirective(DKind)
9269 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9270 : OMPC_private;
9271 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9272 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9273 (LangOpts.OpenMP <= 45 || (DVar.CKind != OMPC_lastprivate &&
9274 DVar.CKind != OMPC_private))) ||
9275 ((isOpenMPWorksharingDirective(DKind) || DKind == OMPD_taskloop ||
9276 DKind == OMPD_master_taskloop || DKind == OMPD_masked_taskloop ||
9277 DKind == OMPD_parallel_master_taskloop ||
9278 DKind == OMPD_parallel_masked_taskloop ||
9279 isOpenMPDistributeDirective(DKind)) &&
9280 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9281 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9282 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9283 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9284 << getOpenMPClauseName(DVar.CKind)
9285 << getOpenMPDirectiveName(DKind)
9286 << getOpenMPClauseName(PredeterminedCKind);
9287 if (DVar.RefExpr == nullptr)
9288 DVar.CKind = PredeterminedCKind;
9289 reportOriginalDsa(*this, DSAStack, D, DVar,
9290 /*IsLoopIterVar=*/true);
9291 } else if (LoopDeclRefExpr) {
9292 // Make the loop iteration variable private (for worksharing
9293 // constructs), linear (for simd directives with the only one
9294 // associated loop) or lastprivate (for simd directives with several
9295 // collapsed or ordered loops).
9296 if (DVar.CKind == OMPC_unknown)
9297 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind,
9298 PrivateRef);
9302 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9306 namespace {
9307 // Utility for openmp doacross clause kind
9308 class OMPDoacrossKind {
9309 public:
9310 bool isSource(const OMPDoacrossClause *C) {
9311 return C->getDependenceType() == OMPC_DOACROSS_source ||
9312 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9314 bool isSink(const OMPDoacrossClause *C) {
9315 return C->getDependenceType() == OMPC_DOACROSS_sink;
9317 bool isSinkIter(const OMPDoacrossClause *C) {
9318 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9321 } // namespace
9322 /// Called on a for stmt to check and extract its iteration space
9323 /// for further processing (such as collapsing).
9324 static bool checkOpenMPIterationSpace(
9325 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9326 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9327 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9328 Expr *OrderedLoopCountExpr,
9329 Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9330 llvm::MutableArrayRef<LoopIterationSpace> ResultIterSpaces,
9331 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9332 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9333 // OpenMP [2.9.1, Canonical Loop Form]
9334 // for (init-expr; test-expr; incr-expr) structured-block
9335 // for (range-decl: range-expr) structured-block
9336 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9337 S = CanonLoop->getLoopStmt();
9338 auto *For = dyn_cast_or_null<ForStmt>(S);
9339 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9340 // Ranged for is supported only in OpenMP 5.0.
9341 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9342 OpenMPDirectiveKind DK = (SemaRef.getLangOpts().OpenMP < 50 ||
9343 DSA.getMappedDirective() == OMPD_unknown)
9344 ? DKind
9345 : DSA.getMappedDirective();
9346 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
9347 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9348 << getOpenMPDirectiveName(DK) << TotalNestedLoopCount
9349 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9350 if (TotalNestedLoopCount > 1) {
9351 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9352 SemaRef.Diag(DSA.getConstructLoc(),
9353 diag::note_omp_collapse_ordered_expr)
9354 << 2 << CollapseLoopCountExpr->getSourceRange()
9355 << OrderedLoopCountExpr->getSourceRange();
9356 else if (CollapseLoopCountExpr)
9357 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9358 diag::note_omp_collapse_ordered_expr)
9359 << 0 << CollapseLoopCountExpr->getSourceRange();
9360 else
9361 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9362 diag::note_omp_collapse_ordered_expr)
9363 << 1 << OrderedLoopCountExpr->getSourceRange();
9365 return true;
9367 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9368 "No loop body.");
9369 // Postpone analysis in dependent contexts for ranged for loops.
9370 if (CXXFor && SemaRef.CurContext->isDependentContext())
9371 return false;
9373 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9374 For ? For->getForLoc() : CXXFor->getForLoc());
9376 // Check init.
9377 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9378 if (ISC.checkAndSetInit(Init))
9379 return true;
9381 bool HasErrors = false;
9383 // Check loop variable's type.
9384 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9385 // OpenMP [2.6, Canonical Loop Form]
9386 // Var is one of the following:
9387 // A variable of signed or unsigned integer type.
9388 // For C++, a variable of a random access iterator type.
9389 // For C, a variable of a pointer type.
9390 QualType VarType = LCDecl->getType().getNonReferenceType();
9391 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9392 !VarType->isPointerType() &&
9393 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9394 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9395 << SemaRef.getLangOpts().CPlusPlus;
9396 HasErrors = true;
9399 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9400 // a Construct
9401 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9402 // parallel for construct is (are) private.
9403 // The loop iteration variable in the associated for-loop of a simd
9404 // construct with just one associated for-loop is linear with a
9405 // constant-linear-step that is the increment of the associated for-loop.
9406 // Exclude loop var from the list of variables with implicitly defined data
9407 // sharing attributes.
9408 VarsWithImplicitDSA.erase(LCDecl);
9410 assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
9412 // Check test-expr.
9413 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9415 // Check incr-expr.
9416 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9419 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9420 return HasErrors;
9422 // Build the loop's iteration space representation.
9423 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9424 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9425 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9426 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9427 (isOpenMPWorksharingDirective(DKind) ||
9428 isOpenMPGenericLoopDirective(DKind) ||
9429 isOpenMPTaskLoopDirective(DKind) ||
9430 isOpenMPDistributeDirective(DKind) ||
9431 isOpenMPLoopTransformationDirective(DKind)),
9432 Captures);
9433 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9434 ISC.buildCounterVar(Captures, DSA);
9435 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9436 ISC.buildPrivateCounterVar();
9437 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9438 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9439 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9440 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9441 ISC.getConditionSrcRange();
9442 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9443 ISC.getIncrementSrcRange();
9444 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9445 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9446 ISC.isStrictTestOp();
9447 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9448 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9449 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9450 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9451 ISC.buildFinalCondition(DSA.getCurScope());
9452 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9453 ISC.doesInitDependOnLC();
9454 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9455 ISC.doesCondDependOnLC();
9456 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9457 ISC.getLoopDependentIdx();
9459 HasErrors |=
9460 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9461 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9462 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9463 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9464 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9465 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9466 if (!HasErrors && DSA.isOrderedRegion()) {
9467 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9468 if (CurrentNestedLoopCount <
9469 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9470 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9471 CurrentNestedLoopCount,
9472 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9473 DSA.getOrderedRegionParam().second->setLoopCounter(
9474 CurrentNestedLoopCount,
9475 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9478 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9479 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9480 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9481 unsigned NumLoops =
9482 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9483 if (CurrentNestedLoopCount >= NumLoops) {
9484 // Erroneous case - clause has some problems.
9485 continue;
9487 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9488 Pair.second.size() <= CurrentNestedLoopCount) {
9489 // Erroneous case - clause has some problems.
9490 DependC->setLoopData(CurrentNestedLoopCount, nullptr);
9491 continue;
9493 OMPDoacrossKind ODK;
9494 if (DoacrossC && ODK.isSink(DoacrossC) &&
9495 Pair.second.size() <= CurrentNestedLoopCount) {
9496 // Erroneous case - clause has some problems.
9497 DoacrossC->setLoopData(CurrentNestedLoopCount, nullptr);
9498 continue;
9500 Expr *CntValue;
9501 SourceLocation DepLoc =
9502 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9503 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9504 (DoacrossC && ODK.isSource(DoacrossC)))
9505 CntValue = ISC.buildOrderedLoopData(
9506 DSA.getCurScope(),
9507 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9508 DepLoc);
9509 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9510 Expr *Cnt = SemaRef
9511 .DefaultLvalueConversion(
9512 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9513 .get();
9514 if (!Cnt)
9515 continue;
9516 // build CounterVar - 1
9517 Expr *Inc =
9518 SemaRef.ActOnIntegerConstant(DoacrossC->getColonLoc(), /*Val=*/1)
9519 .get();
9520 CntValue = ISC.buildOrderedLoopData(
9521 DSA.getCurScope(),
9522 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9523 DepLoc, Inc, clang::OO_Minus);
9524 } else
9525 CntValue = ISC.buildOrderedLoopData(
9526 DSA.getCurScope(),
9527 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9528 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9529 Pair.second[CurrentNestedLoopCount].second);
9530 if (DependC)
9531 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9532 else
9533 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9537 return HasErrors;
9540 /// Build 'VarRef = Start.
9541 static ExprResult
9542 buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9543 ExprResult Start, bool IsNonRectangularLB,
9544 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9545 // Build 'VarRef = Start.
9546 ExprResult NewStart = IsNonRectangularLB
9547 ? Start.get()
9548 : tryBuildCapture(SemaRef, Start.get(), Captures);
9549 if (!NewStart.isUsable())
9550 return ExprError();
9551 if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
9552 VarRef.get()->getType())) {
9553 NewStart = SemaRef.PerformImplicitConversion(
9554 NewStart.get(), VarRef.get()->getType(), Sema::AA_Converting,
9555 /*AllowExplicit=*/true);
9556 if (!NewStart.isUsable())
9557 return ExprError();
9560 ExprResult Init =
9561 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9562 return Init;
9565 /// Build 'VarRef = Start + Iter * Step'.
9566 static ExprResult buildCounterUpdate(
9567 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9568 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9569 bool IsNonRectangularLB,
9570 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9571 // Add parentheses (for debugging purposes only).
9572 Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
9573 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9574 !Step.isUsable())
9575 return ExprError();
9577 ExprResult NewStep = Step;
9578 if (Captures)
9579 NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures);
9580 if (NewStep.isInvalid())
9581 return ExprError();
9582 ExprResult Update =
9583 SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get());
9584 if (!Update.isUsable())
9585 return ExprError();
9587 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9588 // 'VarRef = Start (+|-) Iter * Step'.
9589 if (!Start.isUsable())
9590 return ExprError();
9591 ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get());
9592 if (!NewStart.isUsable())
9593 return ExprError();
9594 if (Captures && !IsNonRectangularLB)
9595 NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures);
9596 if (NewStart.isInvalid())
9597 return ExprError();
9599 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9600 ExprResult SavedUpdate = Update;
9601 ExprResult UpdateVal;
9602 if (VarRef.get()->getType()->isOverloadableType() ||
9603 NewStart.get()->getType()->isOverloadableType() ||
9604 Update.get()->getType()->isOverloadableType()) {
9605 Sema::TentativeAnalysisScope Trap(SemaRef);
9607 Update =
9608 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9609 if (Update.isUsable()) {
9610 UpdateVal =
9611 SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9612 VarRef.get(), SavedUpdate.get());
9613 if (UpdateVal.isUsable()) {
9614 Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(),
9615 UpdateVal.get());
9620 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9621 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9622 Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add,
9623 NewStart.get(), SavedUpdate.get());
9624 if (!Update.isUsable())
9625 return ExprError();
9627 if (!SemaRef.Context.hasSameType(Update.get()->getType(),
9628 VarRef.get()->getType())) {
9629 Update = SemaRef.PerformImplicitConversion(
9630 Update.get(), VarRef.get()->getType(), Sema::AA_Converting, true);
9631 if (!Update.isUsable())
9632 return ExprError();
9635 Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
9637 return Update;
9640 /// Convert integer expression \a E to make it have at least \a Bits
9641 /// bits.
9642 static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9643 if (E == nullptr)
9644 return ExprError();
9645 ASTContext &C = SemaRef.Context;
9646 QualType OldType = E->getType();
9647 unsigned HasBits = C.getTypeSize(OldType);
9648 if (HasBits >= Bits)
9649 return ExprResult(E);
9650 // OK to convert to signed, because new type has more bits than old.
9651 QualType NewType = C.getIntTypeForBitwidth(Bits, /* Signed */ true);
9652 return SemaRef.PerformImplicitConversion(E, NewType, Sema::AA_Converting,
9653 true);
9656 /// Check if the given expression \a E is a constant integer that fits
9657 /// into \a Bits bits.
9658 static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9659 if (E == nullptr)
9660 return false;
9661 if (std::optional<llvm::APSInt> Result =
9662 E->getIntegerConstantExpr(SemaRef.Context))
9663 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9664 return false;
9667 /// Build preinits statement for the given declarations.
9668 static Stmt *buildPreInits(ASTContext &Context,
9669 MutableArrayRef<Decl *> PreInits) {
9670 if (!PreInits.empty()) {
9671 return new (Context) DeclStmt(
9672 DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()),
9673 SourceLocation(), SourceLocation());
9675 return nullptr;
9678 /// Build preinits statement for the given declarations.
9679 static Stmt *
9680 buildPreInits(ASTContext &Context,
9681 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9682 if (!Captures.empty()) {
9683 SmallVector<Decl *, 16> PreInits;
9684 for (const auto &Pair : Captures)
9685 PreInits.push_back(Pair.second->getDecl());
9686 return buildPreInits(Context, PreInits);
9688 return nullptr;
9691 /// Build postupdate expression for the given list of postupdates expressions.
9692 static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9693 Expr *PostUpdate = nullptr;
9694 if (!PostUpdates.empty()) {
9695 for (Expr *E : PostUpdates) {
9696 Expr *ConvE = S.BuildCStyleCastExpr(
9697 E->getExprLoc(),
9698 S.Context.getTrivialTypeSourceInfo(S.Context.VoidTy),
9699 E->getExprLoc(), E)
9700 .get();
9701 PostUpdate = PostUpdate
9702 ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma,
9703 PostUpdate, ConvE)
9704 .get()
9705 : ConvE;
9708 return PostUpdate;
9711 /// Called on a for stmt to check itself and nested loops (if any).
9712 /// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9713 /// number of collapsed loops otherwise.
9714 static unsigned
9715 checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9716 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
9717 DSAStackTy &DSA,
9718 Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9719 OMPLoopBasedDirective::HelperExprs &Built) {
9720 unsigned NestedLoopCount = 1;
9721 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9722 !isOpenMPLoopTransformationDirective(DKind);
9724 if (CollapseLoopCountExpr) {
9725 // Found 'collapse' clause - calculate collapse number.
9726 Expr::EvalResult Result;
9727 if (!CollapseLoopCountExpr->isValueDependent() &&
9728 CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
9729 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9730 } else {
9731 Built.clear(/*Size=*/1);
9732 return 1;
9735 unsigned OrderedLoopCount = 1;
9736 if (OrderedLoopCountExpr) {
9737 // Found 'ordered' clause - calculate collapse number.
9738 Expr::EvalResult EVResult;
9739 if (!OrderedLoopCountExpr->isValueDependent() &&
9740 OrderedLoopCountExpr->EvaluateAsInt(EVResult,
9741 SemaRef.getASTContext())) {
9742 llvm::APSInt Result = EVResult.Val.getInt();
9743 if (Result.getLimitedValue() < NestedLoopCount) {
9744 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9745 diag::err_omp_wrong_ordered_loop_count)
9746 << OrderedLoopCountExpr->getSourceRange();
9747 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9748 diag::note_collapse_loop_count)
9749 << CollapseLoopCountExpr->getSourceRange();
9751 OrderedLoopCount = Result.getLimitedValue();
9752 } else {
9753 Built.clear(/*Size=*/1);
9754 return 1;
9757 // This is helper routine for loop directives (e.g., 'for', 'simd',
9758 // 'for simd', etc.).
9759 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9760 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9761 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
9762 if (!OMPLoopBasedDirective::doForAllLoops(
9763 AStmt->IgnoreContainers(!isOpenMPLoopTransformationDirective(DKind)),
9764 SupportsNonPerfectlyNested, NumLoops,
9765 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9766 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9767 &IterSpaces, &Captures](unsigned Cnt, Stmt *CurStmt) {
9768 if (checkOpenMPIterationSpace(
9769 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9770 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9771 VarsWithImplicitDSA, IterSpaces, Captures))
9772 return true;
9773 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9774 IterSpaces[Cnt].CounterVar) {
9775 // Handle initialization of captured loop iterator variables.
9776 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9777 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
9778 Captures[DRE] = DRE;
9781 return false;
9783 [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
9784 Stmt *DependentPreInits = Transform->getPreInits();
9785 if (!DependentPreInits)
9786 return;
9787 for (Decl *C : cast<DeclStmt>(DependentPreInits)->getDeclGroup()) {
9788 auto *D = cast<VarDecl>(C);
9789 DeclRefExpr *Ref = buildDeclRefExpr(SemaRef, D, D->getType(),
9790 Transform->getBeginLoc());
9791 Captures[Ref] = Ref;
9794 return 0;
9796 Built.clear(/* size */ NestedLoopCount);
9798 if (SemaRef.CurContext->isDependentContext())
9799 return NestedLoopCount;
9801 // An example of what is generated for the following code:
9803 // #pragma omp simd collapse(2) ordered(2)
9804 // for (i = 0; i < NI; ++i)
9805 // for (k = 0; k < NK; ++k)
9806 // for (j = J0; j < NJ; j+=2) {
9807 // <loop body>
9808 // }
9810 // We generate the code below.
9811 // Note: the loop body may be outlined in CodeGen.
9812 // Note: some counters may be C++ classes, operator- is used to find number of
9813 // iterations and operator+= to calculate counter value.
9814 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
9815 // or i64 is currently supported).
9817 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
9818 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
9819 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
9820 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
9821 // // similar updates for vars in clauses (e.g. 'linear')
9822 // <loop body (using local i and j)>
9823 // }
9824 // i = NI; // assign final values of counters
9825 // j = NJ;
9828 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
9829 // the iteration counts of the collapsed for loops.
9830 // Precondition tests if there is at least one iteration (all conditions are
9831 // true).
9832 auto PreCond = ExprResult(IterSpaces[0].PreCond);
9833 Expr *N0 = IterSpaces[0].NumIterations;
9834 ExprResult LastIteration32 =
9835 widenIterationCount(/*Bits=*/32,
9836 SemaRef
9837 .PerformImplicitConversion(
9838 N0->IgnoreImpCasts(), N0->getType(),
9839 Sema::AA_Converting, /*AllowExplicit=*/true)
9840 .get(),
9841 SemaRef);
9842 ExprResult LastIteration64 = widenIterationCount(
9843 /*Bits=*/64,
9844 SemaRef
9845 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
9846 Sema::AA_Converting,
9847 /*AllowExplicit=*/true)
9848 .get(),
9849 SemaRef);
9851 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
9852 return NestedLoopCount;
9854 ASTContext &C = SemaRef.Context;
9855 bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
9857 Scope *CurScope = DSA.getCurScope();
9858 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
9859 if (PreCond.isUsable()) {
9860 PreCond =
9861 SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
9862 PreCond.get(), IterSpaces[Cnt].PreCond);
9864 Expr *N = IterSpaces[Cnt].NumIterations;
9865 SourceLocation Loc = N->getExprLoc();
9866 AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
9867 if (LastIteration32.isUsable())
9868 LastIteration32 = SemaRef.BuildBinOp(
9869 CurScope, Loc, BO_Mul, LastIteration32.get(),
9870 SemaRef
9871 .PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(),
9872 Sema::AA_Converting,
9873 /*AllowExplicit=*/true)
9874 .get());
9875 if (LastIteration64.isUsable())
9876 LastIteration64 = SemaRef.BuildBinOp(
9877 CurScope, Loc, BO_Mul, LastIteration64.get(),
9878 SemaRef
9879 .PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(),
9880 Sema::AA_Converting,
9881 /*AllowExplicit=*/true)
9882 .get());
9885 // Choose either the 32-bit or 64-bit version.
9886 ExprResult LastIteration = LastIteration64;
9887 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
9888 (LastIteration32.isUsable() &&
9889 C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
9890 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
9891 fitsInto(
9892 /*Bits=*/32,
9893 LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
9894 LastIteration64.get(), SemaRef))))
9895 LastIteration = LastIteration32;
9896 QualType VType = LastIteration.get()->getType();
9897 QualType RealVType = VType;
9898 QualType StrideVType = VType;
9899 if (isOpenMPTaskLoopDirective(DKind)) {
9900 VType =
9901 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
9902 StrideVType =
9903 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
9906 if (!LastIteration.isUsable())
9907 return 0;
9909 // Save the number of iterations.
9910 ExprResult NumIterations = LastIteration;
9912 LastIteration = SemaRef.BuildBinOp(
9913 CurScope, LastIteration.get()->getExprLoc(), BO_Sub,
9914 LastIteration.get(),
9915 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9916 if (!LastIteration.isUsable())
9917 return 0;
9920 // Calculate the last iteration number beforehand instead of doing this on
9921 // each iteration. Do not do this if the number of iterations may be kfold-ed.
9922 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context);
9923 ExprResult CalcLastIteration;
9924 if (!IsConstant) {
9925 ExprResult SaveRef =
9926 tryBuildCapture(SemaRef, LastIteration.get(), Captures);
9927 LastIteration = SaveRef;
9929 // Prepare SaveRef + 1.
9930 NumIterations = SemaRef.BuildBinOp(
9931 CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(),
9932 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9933 if (!NumIterations.isUsable())
9934 return 0;
9937 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
9939 // Build variables passed into runtime, necessary for worksharing directives.
9940 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
9941 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
9942 isOpenMPDistributeDirective(DKind) ||
9943 isOpenMPGenericLoopDirective(DKind) ||
9944 isOpenMPLoopTransformationDirective(DKind)) {
9945 // Lower bound variable, initialized with zero.
9946 VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
9947 LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
9948 SemaRef.AddInitializerToDecl(LBDecl,
9949 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9950 /*DirectInit*/ false);
9952 // Upper bound variable, initialized with last iteration number.
9953 VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
9954 UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
9955 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
9956 /*DirectInit*/ false);
9958 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
9959 // This will be used to implement clause 'lastprivate'.
9960 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
9961 VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
9962 IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
9963 SemaRef.AddInitializerToDecl(ILDecl,
9964 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9965 /*DirectInit*/ false);
9967 // Stride variable returned by runtime (we initialize it to 1 by default).
9968 VarDecl *STDecl =
9969 buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride");
9970 ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc);
9971 SemaRef.AddInitializerToDecl(STDecl,
9972 SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
9973 /*DirectInit*/ false);
9975 // Build expression: UB = min(UB, LastIteration)
9976 // It is necessary for CodeGen of directives with static scheduling.
9977 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
9978 UB.get(), LastIteration.get());
9979 ExprResult CondOp = SemaRef.ActOnConditionalOp(
9980 LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
9981 LastIteration.get(), UB.get());
9982 EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
9983 CondOp.get());
9984 EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue*/ false);
9986 // If we have a combined directive that combines 'distribute', 'for' or
9987 // 'simd' we need to be able to access the bounds of the schedule of the
9988 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
9989 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
9990 if (isOpenMPLoopBoundSharingDirective(DKind)) {
9991 // Lower bound variable, initialized with zero.
9992 VarDecl *CombLBDecl =
9993 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
9994 CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc);
9995 SemaRef.AddInitializerToDecl(
9996 CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9997 /*DirectInit*/ false);
9999 // Upper bound variable, initialized with last iteration number.
10000 VarDecl *CombUBDecl =
10001 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub");
10002 CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc);
10003 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
10004 /*DirectInit*/ false);
10006 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
10007 CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get());
10008 ExprResult CombCondOp =
10009 SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(),
10010 LastIteration.get(), CombUB.get());
10011 CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
10012 CombCondOp.get());
10013 CombEUB =
10014 SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue*/ false);
10016 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
10017 // We expect to have at least 2 more parameters than the 'parallel'
10018 // directive does - the lower and upper bounds of the previous schedule.
10019 assert(CD->getNumParams() >= 4 &&
10020 "Unexpected number of parameters in loop combined directive");
10022 // Set the proper type for the bounds given what we learned from the
10023 // enclosed loops.
10024 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
10025 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
10027 // Previous lower and upper bounds are obtained from the region
10028 // parameters.
10029 PrevLB =
10030 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
10031 PrevUB =
10032 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
10036 // Build the iteration variable and its initialization before loop.
10037 ExprResult IV;
10038 ExprResult Init, CombInit;
10040 VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
10041 IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
10042 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
10043 isOpenMPGenericLoopDirective(DKind) ||
10044 isOpenMPTaskLoopDirective(DKind) ||
10045 isOpenMPDistributeDirective(DKind) ||
10046 isOpenMPLoopTransformationDirective(DKind))
10047 ? LB.get()
10048 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10049 Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
10050 Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false);
10052 if (isOpenMPLoopBoundSharingDirective(DKind)) {
10053 Expr *CombRHS =
10054 (isOpenMPWorksharingDirective(DKind) ||
10055 isOpenMPGenericLoopDirective(DKind) ||
10056 isOpenMPTaskLoopDirective(DKind) ||
10057 isOpenMPDistributeDirective(DKind))
10058 ? CombLB.get()
10059 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10060 CombInit =
10061 SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
10062 CombInit =
10063 SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue*/ false);
10067 bool UseStrictCompare =
10068 RealVType->hasUnsignedIntegerRepresentation() &&
10069 llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) {
10070 return LIS.IsStrictCompare;
10072 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
10073 // unsigned IV)) for worksharing loops.
10074 SourceLocation CondLoc = AStmt->getBeginLoc();
10075 Expr *BoundUB = UB.get();
10076 if (UseStrictCompare) {
10077 BoundUB =
10078 SemaRef
10079 .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
10080 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10081 .get();
10082 BoundUB =
10083 SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue*/ false).get();
10085 ExprResult Cond =
10086 (isOpenMPWorksharingDirective(DKind) ||
10087 isOpenMPGenericLoopDirective(DKind) ||
10088 isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind) ||
10089 isOpenMPLoopTransformationDirective(DKind))
10090 ? SemaRef.BuildBinOp(CurScope, CondLoc,
10091 UseStrictCompare ? BO_LT : BO_LE, IV.get(),
10092 BoundUB)
10093 : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10094 NumIterations.get());
10095 ExprResult CombDistCond;
10096 if (isOpenMPLoopBoundSharingDirective(DKind)) {
10097 CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10098 NumIterations.get());
10101 ExprResult CombCond;
10102 if (isOpenMPLoopBoundSharingDirective(DKind)) {
10103 Expr *BoundCombUB = CombUB.get();
10104 if (UseStrictCompare) {
10105 BoundCombUB =
10106 SemaRef
10107 .BuildBinOp(
10108 CurScope, CondLoc, BO_Add, BoundCombUB,
10109 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10110 .get();
10111 BoundCombUB =
10112 SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue*/ false)
10113 .get();
10115 CombCond =
10116 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10117 IV.get(), BoundCombUB);
10119 // Loop increment (IV = IV + 1)
10120 SourceLocation IncLoc = AStmt->getBeginLoc();
10121 ExprResult Inc =
10122 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
10123 SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
10124 if (!Inc.isUsable())
10125 return 0;
10126 Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
10127 Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue*/ false);
10128 if (!Inc.isUsable())
10129 return 0;
10131 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
10132 // Used for directives with static scheduling.
10133 // In combined construct, add combined version that use CombLB and CombUB
10134 // base variables for the update
10135 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10136 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
10137 isOpenMPGenericLoopDirective(DKind) ||
10138 isOpenMPDistributeDirective(DKind) ||
10139 isOpenMPLoopTransformationDirective(DKind)) {
10140 // LB + ST
10141 NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
10142 if (!NextLB.isUsable())
10143 return 0;
10144 // LB = LB + ST
10145 NextLB =
10146 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
10147 NextLB =
10148 SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue*/ false);
10149 if (!NextLB.isUsable())
10150 return 0;
10151 // UB + ST
10152 NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get());
10153 if (!NextUB.isUsable())
10154 return 0;
10155 // UB = UB + ST
10156 NextUB =
10157 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
10158 NextUB =
10159 SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue*/ false);
10160 if (!NextUB.isUsable())
10161 return 0;
10162 if (isOpenMPLoopBoundSharingDirective(DKind)) {
10163 CombNextLB =
10164 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get());
10165 if (!NextLB.isUsable())
10166 return 0;
10167 // LB = LB + ST
10168 CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
10169 CombNextLB.get());
10170 CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
10171 /*DiscardedValue*/ false);
10172 if (!CombNextLB.isUsable())
10173 return 0;
10174 // UB + ST
10175 CombNextUB =
10176 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get());
10177 if (!CombNextUB.isUsable())
10178 return 0;
10179 // UB = UB + ST
10180 CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
10181 CombNextUB.get());
10182 CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
10183 /*DiscardedValue*/ false);
10184 if (!CombNextUB.isUsable())
10185 return 0;
10189 // Create increment expression for distribute loop when combined in a same
10190 // directive with for as IV = IV + ST; ensure upper bound expression based
10191 // on PrevUB instead of NumIterations - used to implement 'for' when found
10192 // in combination with 'distribute', like in 'distribute parallel for'
10193 SourceLocation DistIncLoc = AStmt->getBeginLoc();
10194 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10195 if (isOpenMPLoopBoundSharingDirective(DKind)) {
10196 DistCond = SemaRef.BuildBinOp(
10197 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB);
10198 assert(DistCond.isUsable() && "distribute cond expr was not built");
10200 DistInc =
10201 SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get());
10202 assert(DistInc.isUsable() && "distribute inc expr was not built");
10203 DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
10204 DistInc.get());
10205 DistInc =
10206 SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue*/ false);
10207 assert(DistInc.isUsable() && "distribute inc expr was not built");
10209 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10210 // construct
10211 ExprResult NewPrevUB = PrevUB;
10212 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10213 if (!SemaRef.Context.hasSameType(UB.get()->getType(),
10214 PrevUB.get()->getType())) {
10215 NewPrevUB = SemaRef.BuildCStyleCastExpr(
10216 DistEUBLoc,
10217 SemaRef.Context.getTrivialTypeSourceInfo(UB.get()->getType()),
10218 DistEUBLoc, NewPrevUB.get());
10219 if (!NewPrevUB.isUsable())
10220 return 0;
10222 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT,
10223 UB.get(), NewPrevUB.get());
10224 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10225 DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get());
10226 PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
10227 CondOp.get());
10228 PrevEUB =
10229 SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue*/ false);
10231 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10232 // parallel for is in combination with a distribute directive with
10233 // schedule(static, 1)
10234 Expr *BoundPrevUB = PrevUB.get();
10235 if (UseStrictCompare) {
10236 BoundPrevUB =
10237 SemaRef
10238 .BuildBinOp(
10239 CurScope, CondLoc, BO_Add, BoundPrevUB,
10240 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10241 .get();
10242 BoundPrevUB =
10243 SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue*/ false)
10244 .get();
10246 ParForInDistCond =
10247 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10248 IV.get(), BoundPrevUB);
10251 // Build updates and final values of the loop counters.
10252 bool HasErrors = false;
10253 Built.Counters.resize(NestedLoopCount);
10254 Built.Inits.resize(NestedLoopCount);
10255 Built.Updates.resize(NestedLoopCount);
10256 Built.Finals.resize(NestedLoopCount);
10257 Built.DependentCounters.resize(NestedLoopCount);
10258 Built.DependentInits.resize(NestedLoopCount);
10259 Built.FinalsConditions.resize(NestedLoopCount);
10261 // We implement the following algorithm for obtaining the
10262 // original loop iteration variable values based on the
10263 // value of the collapsed loop iteration variable IV.
10265 // Let n+1 be the number of collapsed loops in the nest.
10266 // Iteration variables (I0, I1, .... In)
10267 // Iteration counts (N0, N1, ... Nn)
10269 // Acc = IV;
10271 // To compute Ik for loop k, 0 <= k <= n, generate:
10272 // Prod = N(k+1) * N(k+2) * ... * Nn;
10273 // Ik = Acc / Prod;
10274 // Acc -= Ik * Prod;
10276 ExprResult Acc = IV;
10277 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10278 LoopIterationSpace &IS = IterSpaces[Cnt];
10279 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10280 ExprResult Iter;
10282 // Compute prod
10283 ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
10284 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10285 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(),
10286 IterSpaces[K].NumIterations);
10288 // Iter = Acc / Prod
10289 // If there is at least one more inner loop to avoid
10290 // multiplication by 1.
10291 if (Cnt + 1 < NestedLoopCount)
10292 Iter =
10293 SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get());
10294 else
10295 Iter = Acc;
10296 if (!Iter.isUsable()) {
10297 HasErrors = true;
10298 break;
10301 // Update Acc:
10302 // Acc -= Iter * Prod
10303 // Check if there is at least one more inner loop to avoid
10304 // multiplication by 1.
10305 if (Cnt + 1 < NestedLoopCount)
10306 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(),
10307 Prod.get());
10308 else
10309 Prod = Iter;
10310 Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get());
10312 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10313 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10314 DeclRefExpr *CounterVar = buildDeclRefExpr(
10315 SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
10316 /*RefersToCapture=*/true);
10317 ExprResult Init =
10318 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
10319 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10320 if (!Init.isUsable()) {
10321 HasErrors = true;
10322 break;
10324 ExprResult Update = buildCounterUpdate(
10325 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10326 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10327 if (!Update.isUsable()) {
10328 HasErrors = true;
10329 break;
10332 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10333 ExprResult Final =
10334 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
10335 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10336 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10337 if (!Final.isUsable()) {
10338 HasErrors = true;
10339 break;
10342 if (!Update.isUsable() || !Final.isUsable()) {
10343 HasErrors = true;
10344 break;
10346 // Save results
10347 Built.Counters[Cnt] = IS.CounterVar;
10348 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10349 Built.Inits[Cnt] = Init.get();
10350 Built.Updates[Cnt] = Update.get();
10351 Built.Finals[Cnt] = Final.get();
10352 Built.DependentCounters[Cnt] = nullptr;
10353 Built.DependentInits[Cnt] = nullptr;
10354 Built.FinalsConditions[Cnt] = nullptr;
10355 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10356 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10357 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10358 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10363 if (HasErrors)
10364 return 0;
10366 // Save results
10367 Built.IterationVarRef = IV.get();
10368 Built.LastIteration = LastIteration.get();
10369 Built.NumIterations = NumIterations.get();
10370 Built.CalcLastIteration = SemaRef
10371 .ActOnFinishFullExpr(CalcLastIteration.get(),
10372 /*DiscardedValue=*/false)
10373 .get();
10374 Built.PreCond = PreCond.get();
10375 Built.PreInits = buildPreInits(C, Captures);
10376 Built.Cond = Cond.get();
10377 Built.Init = Init.get();
10378 Built.Inc = Inc.get();
10379 Built.LB = LB.get();
10380 Built.UB = UB.get();
10381 Built.IL = IL.get();
10382 Built.ST = ST.get();
10383 Built.EUB = EUB.get();
10384 Built.NLB = NextLB.get();
10385 Built.NUB = NextUB.get();
10386 Built.PrevLB = PrevLB.get();
10387 Built.PrevUB = PrevUB.get();
10388 Built.DistInc = DistInc.get();
10389 Built.PrevEUB = PrevEUB.get();
10390 Built.DistCombinedFields.LB = CombLB.get();
10391 Built.DistCombinedFields.UB = CombUB.get();
10392 Built.DistCombinedFields.EUB = CombEUB.get();
10393 Built.DistCombinedFields.Init = CombInit.get();
10394 Built.DistCombinedFields.Cond = CombCond.get();
10395 Built.DistCombinedFields.NLB = CombNextLB.get();
10396 Built.DistCombinedFields.NUB = CombNextUB.get();
10397 Built.DistCombinedFields.DistCond = CombDistCond.get();
10398 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10400 return NestedLoopCount;
10403 static Expr *getCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) {
10404 auto CollapseClauses =
10405 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10406 if (CollapseClauses.begin() != CollapseClauses.end())
10407 return (*CollapseClauses.begin())->getNumForLoops();
10408 return nullptr;
10411 static Expr *getOrderedNumberExpr(ArrayRef<OMPClause *> Clauses) {
10412 auto OrderedClauses =
10413 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10414 if (OrderedClauses.begin() != OrderedClauses.end())
10415 return (*OrderedClauses.begin())->getNumForLoops();
10416 return nullptr;
10419 static bool checkSimdlenSafelenSpecified(Sema &S,
10420 const ArrayRef<OMPClause *> Clauses) {
10421 const OMPSafelenClause *Safelen = nullptr;
10422 const OMPSimdlenClause *Simdlen = nullptr;
10424 for (const OMPClause *Clause : Clauses) {
10425 if (Clause->getClauseKind() == OMPC_safelen)
10426 Safelen = cast<OMPSafelenClause>(Clause);
10427 else if (Clause->getClauseKind() == OMPC_simdlen)
10428 Simdlen = cast<OMPSimdlenClause>(Clause);
10429 if (Safelen && Simdlen)
10430 break;
10433 if (Simdlen && Safelen) {
10434 const Expr *SimdlenLength = Simdlen->getSimdlen();
10435 const Expr *SafelenLength = Safelen->getSafelen();
10436 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10437 SimdlenLength->isInstantiationDependent() ||
10438 SimdlenLength->containsUnexpandedParameterPack())
10439 return false;
10440 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10441 SafelenLength->isInstantiationDependent() ||
10442 SafelenLength->containsUnexpandedParameterPack())
10443 return false;
10444 Expr::EvalResult SimdlenResult, SafelenResult;
10445 SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
10446 SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
10447 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10448 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10449 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10450 // If both simdlen and safelen clauses are specified, the value of the
10451 // simdlen parameter must be less than or equal to the value of the safelen
10452 // parameter.
10453 if (SimdlenRes > SafelenRes) {
10454 S.Diag(SimdlenLength->getExprLoc(),
10455 diag::err_omp_wrong_simdlen_safelen_values)
10456 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10457 return true;
10460 return false;
10463 static bool checkGenericLoopLastprivate(Sema &S, ArrayRef<OMPClause *> Clauses,
10464 OpenMPDirectiveKind K,
10465 DSAStackTy *Stack);
10467 bool Sema::checkLastPrivateForMappedDirectives(ArrayRef<OMPClause *> Clauses) {
10469 // Check for syntax of lastprivate
10470 // Param of the lastprivate have different meanings in the mapped directives
10471 // e.g. "omp loop" Only loop iteration vars are allowed in lastprivate clause
10472 // "omp for" lastprivate vars must be shared
10473 if (getLangOpts().OpenMP >= 50 &&
10474 DSAStack->getMappedDirective() == OMPD_loop &&
10475 checkGenericLoopLastprivate(*this, Clauses, OMPD_loop, DSAStack)) {
10476 return false;
10478 return true;
10481 StmtResult
10482 Sema::ActOnOpenMPSimdDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt,
10483 SourceLocation StartLoc, SourceLocation EndLoc,
10484 VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10485 if (!AStmt)
10486 return StmtError();
10488 if (!checkLastPrivateForMappedDirectives(Clauses))
10489 return StmtError();
10491 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10492 OMPLoopBasedDirective::HelperExprs B;
10493 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10494 // define the nested loops number.
10495 unsigned NestedLoopCount = checkOpenMPLoop(
10496 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10497 AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
10498 if (NestedLoopCount == 0)
10499 return StmtError();
10501 assert((CurContext->isDependentContext() || B.builtAll()) &&
10502 "omp simd loop exprs were not built");
10504 if (!CurContext->isDependentContext()) {
10505 // Finalize the clauses that need pre-built expressions for CodeGen.
10506 for (OMPClause *C : Clauses) {
10507 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10508 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10509 B.NumIterations, *this, CurScope,
10510 DSAStack))
10511 return StmtError();
10515 if (checkSimdlenSafelenSpecified(*this, Clauses))
10516 return StmtError();
10518 setFunctionHasBranchProtectedScope();
10519 auto *SimdDirective = OMPSimdDirective::Create(
10520 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10521 DSAStack->getMappedDirective());
10522 return SimdDirective;
10525 StmtResult
10526 Sema::ActOnOpenMPForDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt,
10527 SourceLocation StartLoc, SourceLocation EndLoc,
10528 VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10529 if (!AStmt)
10530 return StmtError();
10532 if (!checkLastPrivateForMappedDirectives(Clauses))
10533 return StmtError();
10535 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10536 OMPLoopBasedDirective::HelperExprs B;
10537 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10538 // define the nested loops number.
10539 unsigned NestedLoopCount = checkOpenMPLoop(
10540 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10541 AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
10542 if (NestedLoopCount == 0)
10543 return StmtError();
10545 assert((CurContext->isDependentContext() || B.builtAll()) &&
10546 "omp for loop exprs were not built");
10548 if (!CurContext->isDependentContext()) {
10549 // Finalize the clauses that need pre-built expressions for CodeGen.
10550 for (OMPClause *C : Clauses) {
10551 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10552 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10553 B.NumIterations, *this, CurScope,
10554 DSAStack))
10555 return StmtError();
10559 auto *ForDirective = OMPForDirective::Create(
10560 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10561 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion(),
10562 DSAStack->getMappedDirective());
10563 return ForDirective;
10566 StmtResult Sema::ActOnOpenMPForSimdDirective(
10567 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10568 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10569 if (!AStmt)
10570 return StmtError();
10572 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10573 OMPLoopBasedDirective::HelperExprs B;
10574 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10575 // define the nested loops number.
10576 unsigned NestedLoopCount =
10577 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
10578 getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
10579 VarsWithImplicitDSA, B);
10580 if (NestedLoopCount == 0)
10581 return StmtError();
10583 assert((CurContext->isDependentContext() || B.builtAll()) &&
10584 "omp for simd loop exprs were not built");
10586 if (!CurContext->isDependentContext()) {
10587 // Finalize the clauses that need pre-built expressions for CodeGen.
10588 for (OMPClause *C : Clauses) {
10589 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10590 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10591 B.NumIterations, *this, CurScope,
10592 DSAStack))
10593 return StmtError();
10597 if (checkSimdlenSafelenSpecified(*this, Clauses))
10598 return StmtError();
10600 setFunctionHasBranchProtectedScope();
10601 return OMPForSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
10602 Clauses, AStmt, B);
10605 StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
10606 Stmt *AStmt,
10607 SourceLocation StartLoc,
10608 SourceLocation EndLoc) {
10609 if (!AStmt)
10610 return StmtError();
10612 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10613 auto BaseStmt = AStmt;
10614 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10615 BaseStmt = CS->getCapturedStmt();
10616 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10617 auto S = C->children();
10618 if (S.begin() == S.end())
10619 return StmtError();
10620 // All associated statements must be '#pragma omp section' except for
10621 // the first one.
10622 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
10623 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10624 if (SectionStmt)
10625 Diag(SectionStmt->getBeginLoc(),
10626 diag::err_omp_sections_substmt_not_section);
10627 return StmtError();
10629 cast<OMPSectionDirective>(SectionStmt)
10630 ->setHasCancel(DSAStack->isCancelRegion());
10632 } else {
10633 Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt);
10634 return StmtError();
10637 setFunctionHasBranchProtectedScope();
10639 return OMPSectionsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
10640 DSAStack->getTaskgroupReductionRef(),
10641 DSAStack->isCancelRegion());
10644 StmtResult Sema::ActOnOpenMPSectionDirective(Stmt *AStmt,
10645 SourceLocation StartLoc,
10646 SourceLocation EndLoc) {
10647 if (!AStmt)
10648 return StmtError();
10650 setFunctionHasBranchProtectedScope();
10651 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10653 return OMPSectionDirective::Create(Context, StartLoc, EndLoc, AStmt,
10654 DSAStack->isCancelRegion());
10657 static Expr *getDirectCallExpr(Expr *E) {
10658 E = E->IgnoreParenCasts()->IgnoreImplicit();
10659 if (auto *CE = dyn_cast<CallExpr>(E))
10660 if (CE->getDirectCallee())
10661 return E;
10662 return nullptr;
10665 StmtResult Sema::ActOnOpenMPDispatchDirective(ArrayRef<OMPClause *> Clauses,
10666 Stmt *AStmt,
10667 SourceLocation StartLoc,
10668 SourceLocation EndLoc) {
10669 if (!AStmt)
10670 return StmtError();
10672 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10674 // 5.1 OpenMP
10675 // expression-stmt : an expression statement with one of the following forms:
10676 // expression = target-call ( [expression-list] );
10677 // target-call ( [expression-list] );
10679 SourceLocation TargetCallLoc;
10681 if (!CurContext->isDependentContext()) {
10682 Expr *TargetCall = nullptr;
10684 auto *E = dyn_cast<Expr>(S);
10685 if (!E) {
10686 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10687 return StmtError();
10690 E = E->IgnoreParenCasts()->IgnoreImplicit();
10692 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
10693 if (BO->getOpcode() == BO_Assign)
10694 TargetCall = getDirectCallExpr(BO->getRHS());
10695 } else {
10696 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10697 if (COCE->getOperator() == OO_Equal)
10698 TargetCall = getDirectCallExpr(COCE->getArg(1));
10699 if (!TargetCall)
10700 TargetCall = getDirectCallExpr(E);
10702 if (!TargetCall) {
10703 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10704 return StmtError();
10706 TargetCallLoc = TargetCall->getExprLoc();
10709 setFunctionHasBranchProtectedScope();
10711 return OMPDispatchDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
10712 TargetCallLoc);
10715 static bool checkGenericLoopLastprivate(Sema &S, ArrayRef<OMPClause *> Clauses,
10716 OpenMPDirectiveKind K,
10717 DSAStackTy *Stack) {
10718 bool ErrorFound = false;
10719 for (OMPClause *C : Clauses) {
10720 if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) {
10721 for (Expr *RefExpr : LPC->varlists()) {
10722 SourceLocation ELoc;
10723 SourceRange ERange;
10724 Expr *SimpleRefExpr = RefExpr;
10725 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
10726 if (ValueDecl *D = Res.first) {
10727 auto &&Info = Stack->isLoopControlVariable(D);
10728 if (!Info.first) {
10729 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10730 << getOpenMPDirectiveName(K);
10731 ErrorFound = true;
10737 return ErrorFound;
10740 StmtResult Sema::ActOnOpenMPGenericLoopDirective(
10741 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10742 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10743 if (!AStmt)
10744 return StmtError();
10746 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10747 // A list item may not appear in a lastprivate clause unless it is the
10748 // loop iteration variable of a loop that is associated with the construct.
10749 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_loop, DSAStack))
10750 return StmtError();
10752 auto *CS = cast<CapturedStmt>(AStmt);
10753 // 1.2.2 OpenMP Language Terminology
10754 // Structured block - An executable statement with a single entry at the
10755 // top and a single exit at the bottom.
10756 // The point of exit cannot be a branch out of the structured block.
10757 // longjmp() and throw() must not violate the entry/exit criteria.
10758 CS->getCapturedDecl()->setNothrow();
10760 OMPLoopDirective::HelperExprs B;
10761 // In presence of clause 'collapse', it will define the nested loops number.
10762 unsigned NestedLoopCount = checkOpenMPLoop(
10763 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10764 AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
10765 if (NestedLoopCount == 0)
10766 return StmtError();
10768 assert((CurContext->isDependentContext() || B.builtAll()) &&
10769 "omp loop exprs were not built");
10771 setFunctionHasBranchProtectedScope();
10772 return OMPGenericLoopDirective::Create(Context, StartLoc, EndLoc,
10773 NestedLoopCount, Clauses, AStmt, B);
10776 StmtResult Sema::ActOnOpenMPTeamsGenericLoopDirective(
10777 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10778 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10779 if (!AStmt)
10780 return StmtError();
10782 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10783 // A list item may not appear in a lastprivate clause unless it is the
10784 // loop iteration variable of a loop that is associated with the construct.
10785 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_teams_loop, DSAStack))
10786 return StmtError();
10788 auto *CS = cast<CapturedStmt>(AStmt);
10789 // 1.2.2 OpenMP Language Terminology
10790 // Structured block - An executable statement with a single entry at the
10791 // top and a single exit at the bottom.
10792 // The point of exit cannot be a branch out of the structured block.
10793 // longjmp() and throw() must not violate the entry/exit criteria.
10794 CS->getCapturedDecl()->setNothrow();
10795 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_teams_loop);
10796 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10797 CS = cast<CapturedStmt>(CS->getCapturedStmt());
10798 // 1.2.2 OpenMP Language Terminology
10799 // Structured block - An executable statement with a single entry at the
10800 // top and a single exit at the bottom.
10801 // The point of exit cannot be a branch out of the structured block.
10802 // longjmp() and throw() must not violate the entry/exit criteria.
10803 CS->getCapturedDecl()->setNothrow();
10806 OMPLoopDirective::HelperExprs B;
10807 // In presence of clause 'collapse', it will define the nested loops number.
10808 unsigned NestedLoopCount =
10809 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
10810 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10811 VarsWithImplicitDSA, B);
10812 if (NestedLoopCount == 0)
10813 return StmtError();
10815 assert((CurContext->isDependentContext() || B.builtAll()) &&
10816 "omp loop exprs were not built");
10818 setFunctionHasBranchProtectedScope();
10819 DSAStack->setParentTeamsRegionLoc(StartLoc);
10821 return OMPTeamsGenericLoopDirective::Create(
10822 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10825 StmtResult Sema::ActOnOpenMPTargetTeamsGenericLoopDirective(
10826 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10827 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10828 if (!AStmt)
10829 return StmtError();
10831 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10832 // A list item may not appear in a lastprivate clause unless it is the
10833 // loop iteration variable of a loop that is associated with the construct.
10834 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_target_teams_loop,
10835 DSAStack))
10836 return StmtError();
10838 auto *CS = cast<CapturedStmt>(AStmt);
10839 // 1.2.2 OpenMP Language Terminology
10840 // Structured block - An executable statement with a single entry at the
10841 // top and a single exit at the bottom.
10842 // The point of exit cannot be a branch out of the structured block.
10843 // longjmp() and throw() must not violate the entry/exit criteria.
10844 CS->getCapturedDecl()->setNothrow();
10845 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_teams_loop);
10846 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10847 CS = cast<CapturedStmt>(CS->getCapturedStmt());
10848 // 1.2.2 OpenMP Language Terminology
10849 // Structured block - An executable statement with a single entry at the
10850 // top and a single exit at the bottom.
10851 // The point of exit cannot be a branch out of the structured block.
10852 // longjmp() and throw() must not violate the entry/exit criteria.
10853 CS->getCapturedDecl()->setNothrow();
10856 OMPLoopDirective::HelperExprs B;
10857 // In presence of clause 'collapse', it will define the nested loops number.
10858 unsigned NestedLoopCount =
10859 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
10860 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10861 VarsWithImplicitDSA, B);
10862 if (NestedLoopCount == 0)
10863 return StmtError();
10865 assert((CurContext->isDependentContext() || B.builtAll()) &&
10866 "omp loop exprs were not built");
10868 setFunctionHasBranchProtectedScope();
10870 return OMPTargetTeamsGenericLoopDirective::Create(
10871 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10874 StmtResult Sema::ActOnOpenMPParallelGenericLoopDirective(
10875 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10876 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10877 if (!AStmt)
10878 return StmtError();
10880 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10881 // A list item may not appear in a lastprivate clause unless it is the
10882 // loop iteration variable of a loop that is associated with the construct.
10883 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_parallel_loop, DSAStack))
10884 return StmtError();
10886 auto *CS = cast<CapturedStmt>(AStmt);
10887 // 1.2.2 OpenMP Language Terminology
10888 // Structured block - An executable statement with a single entry at the
10889 // top and a single exit at the bottom.
10890 // The point of exit cannot be a branch out of the structured block.
10891 // longjmp() and throw() must not violate the entry/exit criteria.
10892 CS->getCapturedDecl()->setNothrow();
10893 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_parallel_loop);
10894 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10895 CS = cast<CapturedStmt>(CS->getCapturedStmt());
10896 // 1.2.2 OpenMP Language Terminology
10897 // Structured block - An executable statement with a single entry at the
10898 // top and a single exit at the bottom.
10899 // The point of exit cannot be a branch out of the structured block.
10900 // longjmp() and throw() must not violate the entry/exit criteria.
10901 CS->getCapturedDecl()->setNothrow();
10904 OMPLoopDirective::HelperExprs B;
10905 // In presence of clause 'collapse', it will define the nested loops number.
10906 unsigned NestedLoopCount =
10907 checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses),
10908 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10909 VarsWithImplicitDSA, B);
10910 if (NestedLoopCount == 0)
10911 return StmtError();
10913 assert((CurContext->isDependentContext() || B.builtAll()) &&
10914 "omp loop exprs were not built");
10916 setFunctionHasBranchProtectedScope();
10918 return OMPParallelGenericLoopDirective::Create(
10919 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10922 StmtResult Sema::ActOnOpenMPTargetParallelGenericLoopDirective(
10923 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10924 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10925 if (!AStmt)
10926 return StmtError();
10928 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10929 // A list item may not appear in a lastprivate clause unless it is the
10930 // loop iteration variable of a loop that is associated with the construct.
10931 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_target_parallel_loop,
10932 DSAStack))
10933 return StmtError();
10935 auto *CS = cast<CapturedStmt>(AStmt);
10936 // 1.2.2 OpenMP Language Terminology
10937 // Structured block - An executable statement with a single entry at the
10938 // top and a single exit at the bottom.
10939 // The point of exit cannot be a branch out of the structured block.
10940 // longjmp() and throw() must not violate the entry/exit criteria.
10941 CS->getCapturedDecl()->setNothrow();
10942 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_loop);
10943 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10944 CS = cast<CapturedStmt>(CS->getCapturedStmt());
10945 // 1.2.2 OpenMP Language Terminology
10946 // Structured block - An executable statement with a single entry at the
10947 // top and a single exit at the bottom.
10948 // The point of exit cannot be a branch out of the structured block.
10949 // longjmp() and throw() must not violate the entry/exit criteria.
10950 CS->getCapturedDecl()->setNothrow();
10953 OMPLoopDirective::HelperExprs B;
10954 // In presence of clause 'collapse', it will define the nested loops number.
10955 unsigned NestedLoopCount =
10956 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses),
10957 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10958 VarsWithImplicitDSA, B);
10959 if (NestedLoopCount == 0)
10960 return StmtError();
10962 assert((CurContext->isDependentContext() || B.builtAll()) &&
10963 "omp loop exprs were not built");
10965 setFunctionHasBranchProtectedScope();
10967 return OMPTargetParallelGenericLoopDirective::Create(
10968 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10971 StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
10972 Stmt *AStmt,
10973 SourceLocation StartLoc,
10974 SourceLocation EndLoc) {
10975 if (!AStmt)
10976 return StmtError();
10978 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10980 setFunctionHasBranchProtectedScope();
10982 // OpenMP [2.7.3, single Construct, Restrictions]
10983 // The copyprivate clause must not be used with the nowait clause.
10984 const OMPClause *Nowait = nullptr;
10985 const OMPClause *Copyprivate = nullptr;
10986 for (const OMPClause *Clause : Clauses) {
10987 if (Clause->getClauseKind() == OMPC_nowait)
10988 Nowait = Clause;
10989 else if (Clause->getClauseKind() == OMPC_copyprivate)
10990 Copyprivate = Clause;
10991 if (Copyprivate && Nowait) {
10992 Diag(Copyprivate->getBeginLoc(),
10993 diag::err_omp_single_copyprivate_with_nowait);
10994 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
10995 return StmtError();
10999 return OMPSingleDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
11002 StmtResult Sema::ActOnOpenMPMasterDirective(Stmt *AStmt,
11003 SourceLocation StartLoc,
11004 SourceLocation EndLoc) {
11005 if (!AStmt)
11006 return StmtError();
11008 setFunctionHasBranchProtectedScope();
11010 return OMPMasterDirective::Create(Context, StartLoc, EndLoc, AStmt);
11013 StmtResult Sema::ActOnOpenMPMaskedDirective(ArrayRef<OMPClause *> Clauses,
11014 Stmt *AStmt,
11015 SourceLocation StartLoc,
11016 SourceLocation EndLoc) {
11017 if (!AStmt)
11018 return StmtError();
11020 setFunctionHasBranchProtectedScope();
11022 return OMPMaskedDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
11025 StmtResult Sema::ActOnOpenMPCriticalDirective(
11026 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
11027 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
11028 if (!AStmt)
11029 return StmtError();
11031 bool ErrorFound = false;
11032 llvm::APSInt Hint;
11033 SourceLocation HintLoc;
11034 bool DependentHint = false;
11035 for (const OMPClause *C : Clauses) {
11036 if (C->getClauseKind() == OMPC_hint) {
11037 if (!DirName.getName()) {
11038 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
11039 ErrorFound = true;
11041 Expr *E = cast<OMPHintClause>(C)->getHint();
11042 if (E->isTypeDependent() || E->isValueDependent() ||
11043 E->isInstantiationDependent()) {
11044 DependentHint = true;
11045 } else {
11046 Hint = E->EvaluateKnownConstInt(Context);
11047 HintLoc = C->getBeginLoc();
11051 if (ErrorFound)
11052 return StmtError();
11053 const auto Pair = DSAStack->getCriticalWithHint(DirName);
11054 if (Pair.first && DirName.getName() && !DependentHint) {
11055 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
11056 Diag(StartLoc, diag::err_omp_critical_with_hint);
11057 if (HintLoc.isValid())
11058 Diag(HintLoc, diag::note_omp_critical_hint_here)
11059 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
11060 else
11061 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
11062 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
11063 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
11064 << 1
11065 << toString(C->getHint()->EvaluateKnownConstInt(Context),
11066 /*Radix=*/10, /*Signed=*/false);
11067 } else {
11068 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
11073 setFunctionHasBranchProtectedScope();
11075 auto *Dir = OMPCriticalDirective::Create(Context, DirName, StartLoc, EndLoc,
11076 Clauses, AStmt);
11077 if (!Pair.first && DirName.getName() && !DependentHint)
11078 DSAStack->addCriticalWithHint(Dir, Hint);
11079 return Dir;
11082 StmtResult Sema::ActOnOpenMPParallelForDirective(
11083 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11084 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11085 if (!AStmt)
11086 return StmtError();
11088 auto *CS = cast<CapturedStmt>(AStmt);
11089 // 1.2.2 OpenMP Language Terminology
11090 // Structured block - An executable statement with a single entry at the
11091 // top and a single exit at the bottom.
11092 // The point of exit cannot be a branch out of the structured block.
11093 // longjmp() and throw() must not violate the entry/exit criteria.
11094 CS->getCapturedDecl()->setNothrow();
11096 OMPLoopBasedDirective::HelperExprs B;
11097 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11098 // define the nested loops number.
11099 unsigned NestedLoopCount =
11100 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
11101 getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
11102 VarsWithImplicitDSA, B);
11103 if (NestedLoopCount == 0)
11104 return StmtError();
11106 assert((CurContext->isDependentContext() || B.builtAll()) &&
11107 "omp parallel for loop exprs were not built");
11109 if (!CurContext->isDependentContext()) {
11110 // Finalize the clauses that need pre-built expressions for CodeGen.
11111 for (OMPClause *C : Clauses) {
11112 if (auto *LC = dyn_cast<OMPLinearClause>(C))
11113 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
11114 B.NumIterations, *this, CurScope,
11115 DSAStack))
11116 return StmtError();
11120 setFunctionHasBranchProtectedScope();
11121 return OMPParallelForDirective::Create(
11122 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11123 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11126 StmtResult Sema::ActOnOpenMPParallelForSimdDirective(
11127 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11128 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11129 if (!AStmt)
11130 return StmtError();
11132 auto *CS = cast<CapturedStmt>(AStmt);
11133 // 1.2.2 OpenMP Language Terminology
11134 // Structured block - An executable statement with a single entry at the
11135 // top and a single exit at the bottom.
11136 // The point of exit cannot be a branch out of the structured block.
11137 // longjmp() and throw() must not violate the entry/exit criteria.
11138 CS->getCapturedDecl()->setNothrow();
11140 OMPLoopBasedDirective::HelperExprs B;
11141 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11142 // define the nested loops number.
11143 unsigned NestedLoopCount =
11144 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
11145 getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
11146 VarsWithImplicitDSA, B);
11147 if (NestedLoopCount == 0)
11148 return StmtError();
11150 if (!CurContext->isDependentContext()) {
11151 // Finalize the clauses that need pre-built expressions for CodeGen.
11152 for (OMPClause *C : Clauses) {
11153 if (auto *LC = dyn_cast<OMPLinearClause>(C))
11154 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
11155 B.NumIterations, *this, CurScope,
11156 DSAStack))
11157 return StmtError();
11161 if (checkSimdlenSafelenSpecified(*this, Clauses))
11162 return StmtError();
11164 setFunctionHasBranchProtectedScope();
11165 return OMPParallelForSimdDirective::Create(
11166 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11169 StmtResult
11170 Sema::ActOnOpenMPParallelMasterDirective(ArrayRef<OMPClause *> Clauses,
11171 Stmt *AStmt, SourceLocation StartLoc,
11172 SourceLocation EndLoc) {
11173 if (!AStmt)
11174 return StmtError();
11176 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11177 auto *CS = cast<CapturedStmt>(AStmt);
11178 // 1.2.2 OpenMP Language Terminology
11179 // Structured block - An executable statement with a single entry at the
11180 // top and a single exit at the bottom.
11181 // The point of exit cannot be a branch out of the structured block.
11182 // longjmp() and throw() must not violate the entry/exit criteria.
11183 CS->getCapturedDecl()->setNothrow();
11185 setFunctionHasBranchProtectedScope();
11187 return OMPParallelMasterDirective::Create(
11188 Context, StartLoc, EndLoc, Clauses, AStmt,
11189 DSAStack->getTaskgroupReductionRef());
11192 StmtResult
11193 Sema::ActOnOpenMPParallelMaskedDirective(ArrayRef<OMPClause *> Clauses,
11194 Stmt *AStmt, SourceLocation StartLoc,
11195 SourceLocation EndLoc) {
11196 if (!AStmt)
11197 return StmtError();
11199 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11200 auto *CS = cast<CapturedStmt>(AStmt);
11201 // 1.2.2 OpenMP Language Terminology
11202 // Structured block - An executable statement with a single entry at the
11203 // top and a single exit at the bottom.
11204 // The point of exit cannot be a branch out of the structured block.
11205 // longjmp() and throw() must not violate the entry/exit criteria.
11206 CS->getCapturedDecl()->setNothrow();
11208 setFunctionHasBranchProtectedScope();
11210 return OMPParallelMaskedDirective::Create(
11211 Context, StartLoc, EndLoc, Clauses, AStmt,
11212 DSAStack->getTaskgroupReductionRef());
11215 StmtResult
11216 Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
11217 Stmt *AStmt, SourceLocation StartLoc,
11218 SourceLocation EndLoc) {
11219 if (!AStmt)
11220 return StmtError();
11222 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11223 auto BaseStmt = AStmt;
11224 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
11225 BaseStmt = CS->getCapturedStmt();
11226 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
11227 auto S = C->children();
11228 if (S.begin() == S.end())
11229 return StmtError();
11230 // All associated statements must be '#pragma omp section' except for
11231 // the first one.
11232 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
11233 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
11234 if (SectionStmt)
11235 Diag(SectionStmt->getBeginLoc(),
11236 diag::err_omp_parallel_sections_substmt_not_section);
11237 return StmtError();
11239 cast<OMPSectionDirective>(SectionStmt)
11240 ->setHasCancel(DSAStack->isCancelRegion());
11242 } else {
11243 Diag(AStmt->getBeginLoc(),
11244 diag::err_omp_parallel_sections_not_compound_stmt);
11245 return StmtError();
11248 setFunctionHasBranchProtectedScope();
11250 return OMPParallelSectionsDirective::Create(
11251 Context, StartLoc, EndLoc, Clauses, AStmt,
11252 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11255 /// Find and diagnose mutually exclusive clause kinds.
11256 static bool checkMutuallyExclusiveClauses(
11257 Sema &S, ArrayRef<OMPClause *> Clauses,
11258 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
11259 const OMPClause *PrevClause = nullptr;
11260 bool ErrorFound = false;
11261 for (const OMPClause *C : Clauses) {
11262 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
11263 if (!PrevClause) {
11264 PrevClause = C;
11265 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
11266 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
11267 << getOpenMPClauseName(C->getClauseKind())
11268 << getOpenMPClauseName(PrevClause->getClauseKind());
11269 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
11270 << getOpenMPClauseName(PrevClause->getClauseKind());
11271 ErrorFound = true;
11275 return ErrorFound;
11278 StmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
11279 Stmt *AStmt, SourceLocation StartLoc,
11280 SourceLocation EndLoc) {
11281 if (!AStmt)
11282 return StmtError();
11284 // OpenMP 5.0, 2.10.1 task Construct
11285 // If a detach clause appears on the directive, then a mergeable clause cannot
11286 // appear on the same directive.
11287 if (checkMutuallyExclusiveClauses(*this, Clauses,
11288 {OMPC_detach, OMPC_mergeable}))
11289 return StmtError();
11291 auto *CS = cast<CapturedStmt>(AStmt);
11292 // 1.2.2 OpenMP Language Terminology
11293 // Structured block - An executable statement with a single entry at the
11294 // top and a single exit at the bottom.
11295 // The point of exit cannot be a branch out of the structured block.
11296 // longjmp() and throw() must not violate the entry/exit criteria.
11297 CS->getCapturedDecl()->setNothrow();
11299 setFunctionHasBranchProtectedScope();
11301 return OMPTaskDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
11302 DSAStack->isCancelRegion());
11305 StmtResult Sema::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc,
11306 SourceLocation EndLoc) {
11307 return OMPTaskyieldDirective::Create(Context, StartLoc, EndLoc);
11310 StmtResult Sema::ActOnOpenMPBarrierDirective(SourceLocation StartLoc,
11311 SourceLocation EndLoc) {
11312 return OMPBarrierDirective::Create(Context, StartLoc, EndLoc);
11315 StmtResult Sema::ActOnOpenMPErrorDirective(ArrayRef<OMPClause *> Clauses,
11316 SourceLocation StartLoc,
11317 SourceLocation EndLoc,
11318 bool InExContext) {
11319 const OMPAtClause *AtC =
11320 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11322 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11323 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
11324 return StmtError();
11327 const OMPSeverityClause *SeverityC =
11328 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11329 const OMPMessageClause *MessageC =
11330 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11331 Expr *ME = MessageC ? MessageC->getMessageString() : nullptr;
11333 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11334 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11335 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
11336 << (ME ? cast<StringLiteral>(ME)->getString() : "WARNING");
11337 else
11338 Diag(StartLoc, diag::err_diagnose_if_succeeded)
11339 << (ME ? cast<StringLiteral>(ME)->getString() : "ERROR");
11340 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11341 return StmtError();
11343 return OMPErrorDirective::Create(Context, StartLoc, EndLoc, Clauses);
11346 StmtResult Sema::ActOnOpenMPTaskwaitDirective(ArrayRef<OMPClause *> Clauses,
11347 SourceLocation StartLoc,
11348 SourceLocation EndLoc) {
11349 const OMPNowaitClause *NowaitC =
11350 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11351 bool HasDependC =
11352 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11353 .empty();
11354 if (NowaitC && !HasDependC) {
11355 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11356 return StmtError();
11359 return OMPTaskwaitDirective::Create(Context, StartLoc, EndLoc, Clauses);
11362 StmtResult Sema::ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause *> Clauses,
11363 Stmt *AStmt,
11364 SourceLocation StartLoc,
11365 SourceLocation EndLoc) {
11366 if (!AStmt)
11367 return StmtError();
11369 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11371 setFunctionHasBranchProtectedScope();
11373 return OMPTaskgroupDirective::Create(Context, StartLoc, EndLoc, Clauses,
11374 AStmt,
11375 DSAStack->getTaskgroupReductionRef());
11378 StmtResult Sema::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
11379 SourceLocation StartLoc,
11380 SourceLocation EndLoc) {
11381 OMPFlushClause *FC = nullptr;
11382 OMPClause *OrderClause = nullptr;
11383 for (OMPClause *C : Clauses) {
11384 if (C->getClauseKind() == OMPC_flush)
11385 FC = cast<OMPFlushClause>(C);
11386 else
11387 OrderClause = C;
11389 OpenMPClauseKind MemOrderKind = OMPC_unknown;
11390 SourceLocation MemOrderLoc;
11391 for (const OMPClause *C : Clauses) {
11392 if (C->getClauseKind() == OMPC_acq_rel ||
11393 C->getClauseKind() == OMPC_acquire ||
11394 C->getClauseKind() == OMPC_release) {
11395 if (MemOrderKind != OMPC_unknown) {
11396 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11397 << getOpenMPDirectiveName(OMPD_flush) << 1
11398 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11399 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11400 << getOpenMPClauseName(MemOrderKind);
11401 } else {
11402 MemOrderKind = C->getClauseKind();
11403 MemOrderLoc = C->getBeginLoc();
11407 if (FC && OrderClause) {
11408 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11409 << getOpenMPClauseName(OrderClause->getClauseKind());
11410 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
11411 << getOpenMPClauseName(OrderClause->getClauseKind());
11412 return StmtError();
11414 return OMPFlushDirective::Create(Context, StartLoc, EndLoc, Clauses);
11417 StmtResult Sema::ActOnOpenMPDepobjDirective(ArrayRef<OMPClause *> Clauses,
11418 SourceLocation StartLoc,
11419 SourceLocation EndLoc) {
11420 if (Clauses.empty()) {
11421 Diag(StartLoc, diag::err_omp_depobj_expected);
11422 return StmtError();
11423 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11424 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11425 return StmtError();
11427 // Only depobj expression and another single clause is allowed.
11428 if (Clauses.size() > 2) {
11429 Diag(Clauses[2]->getBeginLoc(),
11430 diag::err_omp_depobj_single_clause_expected);
11431 return StmtError();
11432 } else if (Clauses.size() < 1) {
11433 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11434 return StmtError();
11436 return OMPDepobjDirective::Create(Context, StartLoc, EndLoc, Clauses);
11439 StmtResult Sema::ActOnOpenMPScanDirective(ArrayRef<OMPClause *> Clauses,
11440 SourceLocation StartLoc,
11441 SourceLocation EndLoc) {
11442 // Check that exactly one clause is specified.
11443 if (Clauses.size() != 1) {
11444 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11445 diag::err_omp_scan_single_clause_expected);
11446 return StmtError();
11448 // Check that scan directive is used in the scopeof the OpenMP loop body.
11449 if (Scope *S = DSAStack->getCurScope()) {
11450 Scope *ParentS = S->getParent();
11451 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11452 !ParentS->getBreakParent()->isOpenMPLoopScope())
11453 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11454 << getOpenMPDirectiveName(OMPD_scan) << 5);
11456 // Check that only one instance of scan directives is used in the same outer
11457 // region.
11458 if (DSAStack->doesParentHasScanDirective()) {
11459 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
11460 Diag(DSAStack->getParentScanDirectiveLoc(),
11461 diag::note_omp_previous_directive)
11462 << "scan";
11463 return StmtError();
11465 DSAStack->setParentHasScanDirective(StartLoc);
11466 return OMPScanDirective::Create(Context, StartLoc, EndLoc, Clauses);
11469 StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
11470 Stmt *AStmt,
11471 SourceLocation StartLoc,
11472 SourceLocation EndLoc) {
11473 const OMPClause *DependFound = nullptr;
11474 const OMPClause *DependSourceClause = nullptr;
11475 const OMPClause *DependSinkClause = nullptr;
11476 const OMPClause *DoacrossFound = nullptr;
11477 const OMPClause *DoacrossSourceClause = nullptr;
11478 const OMPClause *DoacrossSinkClause = nullptr;
11479 bool ErrorFound = false;
11480 const OMPThreadsClause *TC = nullptr;
11481 const OMPSIMDClause *SC = nullptr;
11482 for (const OMPClause *C : Clauses) {
11483 auto DOC = dyn_cast<OMPDoacrossClause>(C);
11484 auto DC = dyn_cast<OMPDependClause>(C);
11485 if (DC || DOC) {
11486 DependFound = DC ? C : nullptr;
11487 DoacrossFound = DOC ? C : nullptr;
11488 OMPDoacrossKind ODK;
11489 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11490 (DOC && (ODK.isSource(DOC)))) {
11491 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11492 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
11493 << getOpenMPDirectiveName(OMPD_ordered)
11494 << getOpenMPClauseName(DC ? OMPC_depend : OMPC_doacross) << 2;
11495 ErrorFound = true;
11496 } else {
11497 if (DC)
11498 DependSourceClause = C;
11499 else
11500 DoacrossSourceClause = C;
11502 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11503 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11504 << (DC ? "depend" : "doacross") << 0;
11505 ErrorFound = true;
11507 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11508 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11509 if (DependSourceClause || DoacrossSourceClause) {
11510 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11511 << (DC ? "depend" : "doacross") << 1;
11512 ErrorFound = true;
11514 if (DC)
11515 DependSinkClause = C;
11516 else
11517 DoacrossSinkClause = C;
11519 } else if (C->getClauseKind() == OMPC_threads) {
11520 TC = cast<OMPThreadsClause>(C);
11521 } else if (C->getClauseKind() == OMPC_simd) {
11522 SC = cast<OMPSIMDClause>(C);
11525 if (!ErrorFound && !SC &&
11526 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11527 // OpenMP [2.8.1,simd Construct, Restrictions]
11528 // An ordered construct with the simd clause is the only OpenMP construct
11529 // that can appear in the simd region.
11530 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11531 << (LangOpts.OpenMP >= 50 ? 1 : 0);
11532 ErrorFound = true;
11533 } else if ((DependFound || DoacrossFound) && (TC || SC)) {
11534 SourceLocation Loc =
11535 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11536 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11537 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross)
11538 << getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind());
11539 ErrorFound = true;
11540 } else if ((DependFound || DoacrossFound) &&
11541 !DSAStack->getParentOrderedRegionParam().first) {
11542 SourceLocation Loc =
11543 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11544 Diag(Loc, diag::err_omp_ordered_directive_without_param)
11545 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross);
11546 ErrorFound = true;
11547 } else if (TC || Clauses.empty()) {
11548 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11549 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11550 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11551 << (TC != nullptr);
11552 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11553 ErrorFound = true;
11556 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11557 return StmtError();
11559 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11560 // During execution of an iteration of a worksharing-loop or a loop nest
11561 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11562 // must not execute more than one ordered region corresponding to an ordered
11563 // construct without a depend clause.
11564 if (!DependFound && !DoacrossFound) {
11565 if (DSAStack->doesParentHasOrderedDirective()) {
11566 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
11567 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11568 diag::note_omp_previous_directive)
11569 << "ordered";
11570 return StmtError();
11572 DSAStack->setParentHasOrderedDirective(StartLoc);
11575 if (AStmt) {
11576 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11578 setFunctionHasBranchProtectedScope();
11581 return OMPOrderedDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
11584 namespace {
11585 /// Helper class for checking expression in 'omp atomic [update]'
11586 /// construct.
11587 class OpenMPAtomicUpdateChecker {
11588 /// Error results for atomic update expressions.
11589 enum ExprAnalysisErrorCode {
11590 /// A statement is not an expression statement.
11591 NotAnExpression,
11592 /// Expression is not builtin binary or unary operation.
11593 NotABinaryOrUnaryExpression,
11594 /// Unary operation is not post-/pre- increment/decrement operation.
11595 NotAnUnaryIncDecExpression,
11596 /// An expression is not of scalar type.
11597 NotAScalarType,
11598 /// A binary operation is not an assignment operation.
11599 NotAnAssignmentOp,
11600 /// RHS part of the binary operation is not a binary expression.
11601 NotABinaryExpression,
11602 /// RHS part is not additive/multiplicative/shift/biwise binary
11603 /// expression.
11604 NotABinaryOperator,
11605 /// RHS binary operation does not have reference to the updated LHS
11606 /// part.
11607 NotAnUpdateExpression,
11608 /// An expression contains semantical error not related to
11609 /// 'omp atomic [update]'
11610 NotAValidExpression,
11611 /// No errors is found.
11612 NoError
11614 /// Reference to Sema.
11615 Sema &SemaRef;
11616 /// A location for note diagnostics (when error is found).
11617 SourceLocation NoteLoc;
11618 /// 'x' lvalue part of the source atomic expression.
11619 Expr *X;
11620 /// 'expr' rvalue part of the source atomic expression.
11621 Expr *E;
11622 /// Helper expression of the form
11623 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11624 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11625 Expr *UpdateExpr;
11626 /// Is 'x' a LHS in a RHS part of full update expression. It is
11627 /// important for non-associative operations.
11628 bool IsXLHSInRHSPart;
11629 BinaryOperatorKind Op;
11630 SourceLocation OpLoc;
11631 /// true if the source expression is a postfix unary operation, false
11632 /// if it is a prefix unary operation.
11633 bool IsPostfixUpdate;
11635 public:
11636 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11637 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11638 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11639 /// Check specified statement that it is suitable for 'atomic update'
11640 /// constructs and extract 'x', 'expr' and Operation from the original
11641 /// expression. If DiagId and NoteId == 0, then only check is performed
11642 /// without error notification.
11643 /// \param DiagId Diagnostic which should be emitted if error is found.
11644 /// \param NoteId Diagnostic note for the main error message.
11645 /// \return true if statement is not an update expression, false otherwise.
11646 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11647 /// Return the 'x' lvalue part of the source atomic expression.
11648 Expr *getX() const { return X; }
11649 /// Return the 'expr' rvalue part of the source atomic expression.
11650 Expr *getExpr() const { return E; }
11651 /// Return the update expression used in calculation of the updated
11652 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11653 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11654 Expr *getUpdateExpr() const { return UpdateExpr; }
11655 /// Return true if 'x' is LHS in RHS part of full update expression,
11656 /// false otherwise.
11657 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11659 /// true if the source expression is a postfix unary operation, false
11660 /// if it is a prefix unary operation.
11661 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11663 private:
11664 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11665 unsigned NoteId = 0);
11668 bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11669 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11670 ExprAnalysisErrorCode ErrorFound = NoError;
11671 SourceLocation ErrorLoc, NoteLoc;
11672 SourceRange ErrorRange, NoteRange;
11673 // Allowed constructs are:
11674 // x = x binop expr;
11675 // x = expr binop x;
11676 if (AtomicBinOp->getOpcode() == BO_Assign) {
11677 X = AtomicBinOp->getLHS();
11678 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11679 AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11680 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11681 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11682 AtomicInnerBinOp->isBitwiseOp()) {
11683 Op = AtomicInnerBinOp->getOpcode();
11684 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11685 Expr *LHS = AtomicInnerBinOp->getLHS();
11686 Expr *RHS = AtomicInnerBinOp->getRHS();
11687 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11688 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11689 /*Canonical=*/true);
11690 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11691 /*Canonical=*/true);
11692 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11693 /*Canonical=*/true);
11694 if (XId == LHSId) {
11695 E = RHS;
11696 IsXLHSInRHSPart = true;
11697 } else if (XId == RHSId) {
11698 E = LHS;
11699 IsXLHSInRHSPart = false;
11700 } else {
11701 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11702 ErrorRange = AtomicInnerBinOp->getSourceRange();
11703 NoteLoc = X->getExprLoc();
11704 NoteRange = X->getSourceRange();
11705 ErrorFound = NotAnUpdateExpression;
11707 } else {
11708 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11709 ErrorRange = AtomicInnerBinOp->getSourceRange();
11710 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11711 NoteRange = SourceRange(NoteLoc, NoteLoc);
11712 ErrorFound = NotABinaryOperator;
11714 } else {
11715 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11716 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11717 ErrorFound = NotABinaryExpression;
11719 } else {
11720 ErrorLoc = AtomicBinOp->getExprLoc();
11721 ErrorRange = AtomicBinOp->getSourceRange();
11722 NoteLoc = AtomicBinOp->getOperatorLoc();
11723 NoteRange = SourceRange(NoteLoc, NoteLoc);
11724 ErrorFound = NotAnAssignmentOp;
11726 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11727 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11728 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11729 return true;
11731 if (SemaRef.CurContext->isDependentContext())
11732 E = X = UpdateExpr = nullptr;
11733 return ErrorFound != NoError;
11736 bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11737 unsigned NoteId) {
11738 ExprAnalysisErrorCode ErrorFound = NoError;
11739 SourceLocation ErrorLoc, NoteLoc;
11740 SourceRange ErrorRange, NoteRange;
11741 // Allowed constructs are:
11742 // x++;
11743 // x--;
11744 // ++x;
11745 // --x;
11746 // x binop= expr;
11747 // x = x binop expr;
11748 // x = expr binop x;
11749 if (auto *AtomicBody = dyn_cast<Expr>(S)) {
11750 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11751 if (AtomicBody->getType()->isScalarType() ||
11752 AtomicBody->isInstantiationDependent()) {
11753 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11754 AtomicBody->IgnoreParenImpCasts())) {
11755 // Check for Compound Assignment Operation
11756 Op = BinaryOperator::getOpForCompoundAssignment(
11757 AtomicCompAssignOp->getOpcode());
11758 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11759 E = AtomicCompAssignOp->getRHS();
11760 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11761 IsXLHSInRHSPart = true;
11762 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11763 AtomicBody->IgnoreParenImpCasts())) {
11764 // Check for Binary Operation
11765 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11766 return true;
11767 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11768 AtomicBody->IgnoreParenImpCasts())) {
11769 // Check for Unary Operation
11770 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11771 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11772 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11773 OpLoc = AtomicUnaryOp->getOperatorLoc();
11774 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11775 E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
11776 IsXLHSInRHSPart = true;
11777 } else {
11778 ErrorFound = NotAnUnaryIncDecExpression;
11779 ErrorLoc = AtomicUnaryOp->getExprLoc();
11780 ErrorRange = AtomicUnaryOp->getSourceRange();
11781 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11782 NoteRange = SourceRange(NoteLoc, NoteLoc);
11784 } else if (!AtomicBody->isInstantiationDependent()) {
11785 ErrorFound = NotABinaryOrUnaryExpression;
11786 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11787 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11788 } else if (AtomicBody->containsErrors()) {
11789 ErrorFound = NotAValidExpression;
11790 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11791 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11793 } else {
11794 ErrorFound = NotAScalarType;
11795 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11796 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11798 } else {
11799 ErrorFound = NotAnExpression;
11800 NoteLoc = ErrorLoc = S->getBeginLoc();
11801 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11803 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11804 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11805 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11806 return true;
11808 if (SemaRef.CurContext->isDependentContext())
11809 E = X = UpdateExpr = nullptr;
11810 if (ErrorFound == NoError && E && X) {
11811 // Build an update expression of form 'OpaqueValueExpr(x) binop
11812 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11813 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11814 auto *OVEX = new (SemaRef.getASTContext())
11815 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11816 auto *OVEExpr = new (SemaRef.getASTContext())
11817 OpaqueValueExpr(E->getExprLoc(), E->getType(), VK_PRValue);
11818 ExprResult Update =
11819 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11820 IsXLHSInRHSPart ? OVEExpr : OVEX);
11821 if (Update.isInvalid())
11822 return true;
11823 Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
11824 Sema::AA_Casting);
11825 if (Update.isInvalid())
11826 return true;
11827 UpdateExpr = Update.get();
11829 return ErrorFound != NoError;
11832 /// Get the node id of the fixed point of an expression \a S.
11833 llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11834 llvm::FoldingSetNodeID Id;
11835 S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11836 return Id;
11839 /// Check if two expressions are same.
11840 bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11841 const Expr *RHS) {
11842 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11845 class OpenMPAtomicCompareChecker {
11846 public:
11847 /// All kinds of errors that can occur in `atomic compare`
11848 enum ErrorTy {
11849 /// Empty compound statement.
11850 NoStmt = 0,
11851 /// More than one statement in a compound statement.
11852 MoreThanOneStmt,
11853 /// Not an assignment binary operator.
11854 NotAnAssignment,
11855 /// Not a conditional operator.
11856 NotCondOp,
11857 /// Wrong false expr. According to the spec, 'x' should be at the false
11858 /// expression of a conditional expression.
11859 WrongFalseExpr,
11860 /// The condition of a conditional expression is not a binary operator.
11861 NotABinaryOp,
11862 /// Invalid binary operator (not <, >, or ==).
11863 InvalidBinaryOp,
11864 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11865 InvalidComparison,
11866 /// X is not a lvalue.
11867 XNotLValue,
11868 /// Not a scalar.
11869 NotScalar,
11870 /// Not an integer.
11871 NotInteger,
11872 /// 'else' statement is not expected.
11873 UnexpectedElse,
11874 /// Not an equality operator.
11875 NotEQ,
11876 /// Invalid assignment (not v == x).
11877 InvalidAssignment,
11878 /// Not if statement
11879 NotIfStmt,
11880 /// More than two statements in a compund statement.
11881 MoreThanTwoStmts,
11882 /// Not a compound statement.
11883 NotCompoundStmt,
11884 /// No else statement.
11885 NoElse,
11886 /// Not 'if (r)'.
11887 InvalidCondition,
11888 /// No error.
11889 NoError,
11892 struct ErrorInfoTy {
11893 ErrorTy Error;
11894 SourceLocation ErrorLoc;
11895 SourceRange ErrorRange;
11896 SourceLocation NoteLoc;
11897 SourceRange NoteRange;
11900 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11902 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11903 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11905 Expr *getX() const { return X; }
11906 Expr *getE() const { return E; }
11907 Expr *getD() const { return D; }
11908 Expr *getCond() const { return C; }
11909 bool isXBinopExpr() const { return IsXBinopExpr; }
11911 protected:
11912 /// Reference to ASTContext
11913 ASTContext &ContextRef;
11914 /// 'x' lvalue part of the source atomic expression.
11915 Expr *X = nullptr;
11916 /// 'expr' or 'e' rvalue part of the source atomic expression.
11917 Expr *E = nullptr;
11918 /// 'd' rvalue part of the source atomic expression.
11919 Expr *D = nullptr;
11920 /// 'cond' part of the source atomic expression. It is in one of the following
11921 /// forms:
11922 /// expr ordop x
11923 /// x ordop expr
11924 /// x == e
11925 /// e == x
11926 Expr *C = nullptr;
11927 /// True if the cond expr is in the form of 'x ordop expr'.
11928 bool IsXBinopExpr = true;
11930 /// Check if it is a valid conditional update statement (cond-update-stmt).
11931 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11933 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11934 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11936 /// Check if all captured values have right type.
11937 bool checkType(ErrorInfoTy &ErrorInfo) const;
11939 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
11940 bool ShouldBeLValue, bool ShouldBeInteger = false) {
11941 if (E->isInstantiationDependent())
11942 return true;
11944 if (ShouldBeLValue && !E->isLValue()) {
11945 ErrorInfo.Error = ErrorTy::XNotLValue;
11946 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11947 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11948 return false;
11951 QualType QTy = E->getType();
11952 if (!QTy->isScalarType()) {
11953 ErrorInfo.Error = ErrorTy::NotScalar;
11954 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11955 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11956 return false;
11958 if (ShouldBeInteger && !QTy->isIntegerType()) {
11959 ErrorInfo.Error = ErrorTy::NotInteger;
11960 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11961 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11962 return false;
11965 return true;
11969 bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
11970 ErrorInfoTy &ErrorInfo) {
11971 auto *Then = S->getThen();
11972 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11973 if (CS->body_empty()) {
11974 ErrorInfo.Error = ErrorTy::NoStmt;
11975 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11976 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11977 return false;
11979 if (CS->size() > 1) {
11980 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11981 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11982 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11983 return false;
11985 Then = CS->body_front();
11988 auto *BO = dyn_cast<BinaryOperator>(Then);
11989 if (!BO) {
11990 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11991 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11992 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11993 return false;
11995 if (BO->getOpcode() != BO_Assign) {
11996 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11997 ErrorInfo.ErrorLoc = BO->getExprLoc();
11998 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11999 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12000 return false;
12003 X = BO->getLHS();
12005 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12006 if (!Cond) {
12007 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12008 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12009 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12010 return false;
12013 switch (Cond->getOpcode()) {
12014 case BO_EQ: {
12015 C = Cond;
12016 D = BO->getRHS();
12017 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
12018 E = Cond->getRHS();
12019 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12020 E = Cond->getLHS();
12021 } else {
12022 ErrorInfo.Error = ErrorTy::InvalidComparison;
12023 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12024 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12025 return false;
12027 break;
12029 case BO_LT:
12030 case BO_GT: {
12031 E = BO->getRHS();
12032 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
12033 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
12034 C = Cond;
12035 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
12036 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12037 C = Cond;
12038 IsXBinopExpr = false;
12039 } else {
12040 ErrorInfo.Error = ErrorTy::InvalidComparison;
12041 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12042 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12043 return false;
12045 break;
12047 default:
12048 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12049 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12050 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12051 return false;
12054 if (S->getElse()) {
12055 ErrorInfo.Error = ErrorTy::UnexpectedElse;
12056 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
12057 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
12058 return false;
12061 return true;
12064 bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
12065 ErrorInfoTy &ErrorInfo) {
12066 auto *BO = dyn_cast<BinaryOperator>(S);
12067 if (!BO) {
12068 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12069 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12070 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12071 return false;
12073 if (BO->getOpcode() != BO_Assign) {
12074 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12075 ErrorInfo.ErrorLoc = BO->getExprLoc();
12076 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12077 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12078 return false;
12081 X = BO->getLHS();
12083 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
12084 if (!CO) {
12085 ErrorInfo.Error = ErrorTy::NotCondOp;
12086 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
12087 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
12088 return false;
12091 if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
12092 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
12093 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
12094 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12095 CO->getFalseExpr()->getSourceRange();
12096 return false;
12099 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
12100 if (!Cond) {
12101 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12102 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12103 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12104 CO->getCond()->getSourceRange();
12105 return false;
12108 switch (Cond->getOpcode()) {
12109 case BO_EQ: {
12110 C = Cond;
12111 D = CO->getTrueExpr();
12112 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
12113 E = Cond->getRHS();
12114 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12115 E = Cond->getLHS();
12116 } else {
12117 ErrorInfo.Error = ErrorTy::InvalidComparison;
12118 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12119 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12120 return false;
12122 break;
12124 case BO_LT:
12125 case BO_GT: {
12126 E = CO->getTrueExpr();
12127 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
12128 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
12129 C = Cond;
12130 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
12131 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12132 C = Cond;
12133 IsXBinopExpr = false;
12134 } else {
12135 ErrorInfo.Error = ErrorTy::InvalidComparison;
12136 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12137 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12138 return false;
12140 break;
12142 default:
12143 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12144 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12145 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12146 return false;
12149 return true;
12152 bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
12153 // 'x' and 'e' cannot be nullptr
12154 assert(X && E && "X and E cannot be nullptr");
12156 if (!CheckValue(X, ErrorInfo, true))
12157 return false;
12159 if (!CheckValue(E, ErrorInfo, false))
12160 return false;
12162 if (D && !CheckValue(D, ErrorInfo, false))
12163 return false;
12165 return true;
12168 bool OpenMPAtomicCompareChecker::checkStmt(
12169 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
12170 auto *CS = dyn_cast<CompoundStmt>(S);
12171 if (CS) {
12172 if (CS->body_empty()) {
12173 ErrorInfo.Error = ErrorTy::NoStmt;
12174 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12175 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12176 return false;
12179 if (CS->size() != 1) {
12180 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12181 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12182 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12183 return false;
12185 S = CS->body_front();
12188 auto Res = false;
12190 if (auto *IS = dyn_cast<IfStmt>(S)) {
12191 // Check if the statement is in one of the following forms
12192 // (cond-update-stmt):
12193 // if (expr ordop x) { x = expr; }
12194 // if (x ordop expr) { x = expr; }
12195 // if (x == e) { x = d; }
12196 Res = checkCondUpdateStmt(IS, ErrorInfo);
12197 } else {
12198 // Check if the statement is in one of the following forms (cond-expr-stmt):
12199 // x = expr ordop x ? expr : x;
12200 // x = x ordop expr ? expr : x;
12201 // x = x == e ? d : x;
12202 Res = checkCondExprStmt(S, ErrorInfo);
12205 if (!Res)
12206 return false;
12208 return checkType(ErrorInfo);
12211 class OpenMPAtomicCompareCaptureChecker final
12212 : public OpenMPAtomicCompareChecker {
12213 public:
12214 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
12216 Expr *getV() const { return V; }
12217 Expr *getR() const { return R; }
12218 bool isFailOnly() const { return IsFailOnly; }
12219 bool isPostfixUpdate() const { return IsPostfixUpdate; }
12221 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
12222 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12224 private:
12225 bool checkType(ErrorInfoTy &ErrorInfo);
12227 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
12228 // form of 'conditional-update-capture-atomic' structured block on the v5.2
12229 // spec p.p. 82:
12230 // (1) { v = x; cond-update-stmt }
12231 // (2) { cond-update-stmt v = x; }
12232 // (3) if(x == e) { x = d; } else { v = x; }
12233 // (4) { r = x == e; if(r) { x = d; } }
12234 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
12236 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
12237 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12239 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
12240 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
12241 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12243 /// 'v' lvalue part of the source atomic expression.
12244 Expr *V = nullptr;
12245 /// 'r' lvalue part of the source atomic expression.
12246 Expr *R = nullptr;
12247 /// If 'v' is only updated when the comparison fails.
12248 bool IsFailOnly = false;
12249 /// If original value of 'x' must be stored in 'v', not an updated one.
12250 bool IsPostfixUpdate = false;
12253 bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12254 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12255 return false;
12257 if (V && !CheckValue(V, ErrorInfo, true))
12258 return false;
12260 if (R && !CheckValue(R, ErrorInfo, true, true))
12261 return false;
12263 return true;
12266 bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
12267 ErrorInfoTy &ErrorInfo) {
12268 IsFailOnly = true;
12270 auto *Then = S->getThen();
12271 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
12272 if (CS->body_empty()) {
12273 ErrorInfo.Error = ErrorTy::NoStmt;
12274 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12275 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12276 return false;
12278 if (CS->size() > 1) {
12279 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12280 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12281 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12282 return false;
12284 Then = CS->body_front();
12287 auto *BO = dyn_cast<BinaryOperator>(Then);
12288 if (!BO) {
12289 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12290 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12291 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12292 return false;
12294 if (BO->getOpcode() != BO_Assign) {
12295 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12296 ErrorInfo.ErrorLoc = BO->getExprLoc();
12297 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12298 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12299 return false;
12302 X = BO->getLHS();
12303 D = BO->getRHS();
12305 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12306 if (!Cond) {
12307 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12308 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12309 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12310 return false;
12312 if (Cond->getOpcode() != BO_EQ) {
12313 ErrorInfo.Error = ErrorTy::NotEQ;
12314 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12315 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12316 return false;
12319 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
12320 E = Cond->getRHS();
12321 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12322 E = Cond->getLHS();
12323 } else {
12324 ErrorInfo.Error = ErrorTy::InvalidComparison;
12325 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12326 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12327 return false;
12330 C = Cond;
12332 if (!S->getElse()) {
12333 ErrorInfo.Error = ErrorTy::NoElse;
12334 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12335 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12336 return false;
12339 auto *Else = S->getElse();
12340 if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
12341 if (CS->body_empty()) {
12342 ErrorInfo.Error = ErrorTy::NoStmt;
12343 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12344 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12345 return false;
12347 if (CS->size() > 1) {
12348 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12349 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12350 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12351 return false;
12353 Else = CS->body_front();
12356 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12357 if (!ElseBO) {
12358 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12359 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12360 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12361 return false;
12363 if (ElseBO->getOpcode() != BO_Assign) {
12364 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12365 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12366 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12367 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12368 return false;
12371 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12372 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12373 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12374 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12375 ElseBO->getRHS()->getSourceRange();
12376 return false;
12379 V = ElseBO->getLHS();
12381 return checkType(ErrorInfo);
12384 bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12385 ErrorInfoTy &ErrorInfo) {
12386 // We don't check here as they should be already done before call this
12387 // function.
12388 auto *CS = cast<CompoundStmt>(S);
12389 assert(CS->size() == 2 && "CompoundStmt size is not expected");
12390 auto *S1 = cast<BinaryOperator>(CS->body_front());
12391 auto *S2 = cast<IfStmt>(CS->body_back());
12392 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12394 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12395 ErrorInfo.Error = ErrorTy::InvalidCondition;
12396 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12397 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12398 return false;
12401 R = S1->getLHS();
12403 auto *Then = S2->getThen();
12404 if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12405 if (ThenCS->body_empty()) {
12406 ErrorInfo.Error = ErrorTy::NoStmt;
12407 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12408 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12409 return false;
12411 if (ThenCS->size() > 1) {
12412 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12413 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12414 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12415 return false;
12417 Then = ThenCS->body_front();
12420 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12421 if (!ThenBO) {
12422 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12423 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12424 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12425 return false;
12427 if (ThenBO->getOpcode() != BO_Assign) {
12428 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12429 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12430 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12431 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12432 return false;
12435 X = ThenBO->getLHS();
12436 D = ThenBO->getRHS();
12438 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12439 if (BO->getOpcode() != BO_EQ) {
12440 ErrorInfo.Error = ErrorTy::NotEQ;
12441 ErrorInfo.ErrorLoc = BO->getExprLoc();
12442 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12443 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12444 return false;
12447 C = BO;
12449 if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) {
12450 E = BO->getRHS();
12451 } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) {
12452 E = BO->getLHS();
12453 } else {
12454 ErrorInfo.Error = ErrorTy::InvalidComparison;
12455 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12456 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12457 return false;
12460 if (S2->getElse()) {
12461 IsFailOnly = true;
12463 auto *Else = S2->getElse();
12464 if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12465 if (ElseCS->body_empty()) {
12466 ErrorInfo.Error = ErrorTy::NoStmt;
12467 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12468 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12469 return false;
12471 if (ElseCS->size() > 1) {
12472 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12473 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12474 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12475 return false;
12477 Else = ElseCS->body_front();
12480 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12481 if (!ElseBO) {
12482 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12483 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12484 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12485 return false;
12487 if (ElseBO->getOpcode() != BO_Assign) {
12488 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12489 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12490 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12491 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12492 return false;
12494 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12495 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12496 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12497 ErrorInfo.NoteLoc = X->getExprLoc();
12498 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12499 ErrorInfo.NoteRange = X->getSourceRange();
12500 return false;
12503 V = ElseBO->getLHS();
12506 return checkType(ErrorInfo);
12509 bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12510 ErrorInfoTy &ErrorInfo) {
12511 // if(x == e) { x = d; } else { v = x; }
12512 if (auto *IS = dyn_cast<IfStmt>(S))
12513 return checkForm3(IS, ErrorInfo);
12515 auto *CS = dyn_cast<CompoundStmt>(S);
12516 if (!CS) {
12517 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12518 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12519 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12520 return false;
12522 if (CS->body_empty()) {
12523 ErrorInfo.Error = ErrorTy::NoStmt;
12524 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12525 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12526 return false;
12529 // { if(x == e) { x = d; } else { v = x; } }
12530 if (CS->size() == 1) {
12531 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12532 if (!IS) {
12533 ErrorInfo.Error = ErrorTy::NotIfStmt;
12534 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12535 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12536 CS->body_front()->getSourceRange();
12537 return false;
12540 return checkForm3(IS, ErrorInfo);
12541 } else if (CS->size() == 2) {
12542 auto *S1 = CS->body_front();
12543 auto *S2 = CS->body_back();
12545 Stmt *UpdateStmt = nullptr;
12546 Stmt *CondUpdateStmt = nullptr;
12547 Stmt *CondExprStmt = nullptr;
12549 if (auto *BO = dyn_cast<BinaryOperator>(S1)) {
12550 // It could be one of the following cases:
12551 // { v = x; cond-update-stmt }
12552 // { v = x; cond-expr-stmt }
12553 // { cond-expr-stmt; v = x; }
12554 // form 45
12555 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12556 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12557 // check if form 45
12558 if (isa<IfStmt>(S2))
12559 return checkForm45(CS, ErrorInfo);
12560 // { cond-expr-stmt; v = x; }
12561 CondExprStmt = S1;
12562 UpdateStmt = S2;
12563 } else {
12564 IsPostfixUpdate = true;
12565 UpdateStmt = S1;
12566 if (isa<IfStmt>(S2)) {
12567 // { v = x; cond-update-stmt }
12568 CondUpdateStmt = S2;
12569 } else {
12570 // { v = x; cond-expr-stmt }
12571 CondExprStmt = S2;
12574 } else {
12575 // { cond-update-stmt v = x; }
12576 UpdateStmt = S2;
12577 CondUpdateStmt = S1;
12580 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12581 auto *IS = dyn_cast<IfStmt>(CUS);
12582 if (!IS) {
12583 ErrorInfo.Error = ErrorTy::NotIfStmt;
12584 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12585 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12586 return false;
12589 return checkCondUpdateStmt(IS, ErrorInfo);
12592 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12593 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12594 auto *BO = dyn_cast<BinaryOperator>(US);
12595 if (!BO) {
12596 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12597 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12598 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12599 return false;
12601 if (BO->getOpcode() != BO_Assign) {
12602 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12603 ErrorInfo.ErrorLoc = BO->getExprLoc();
12604 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12605 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12606 return false;
12608 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12609 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12610 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12611 ErrorInfo.NoteLoc = this->X->getExprLoc();
12612 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12613 ErrorInfo.NoteRange = this->X->getSourceRange();
12614 return false;
12617 this->V = BO->getLHS();
12619 return true;
12622 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12623 return false;
12624 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12625 return false;
12626 if (!CheckUpdateStmt(UpdateStmt))
12627 return false;
12628 } else {
12629 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12630 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12631 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12632 return false;
12635 return checkType(ErrorInfo);
12637 } // namespace
12639 StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
12640 Stmt *AStmt,
12641 SourceLocation StartLoc,
12642 SourceLocation EndLoc) {
12643 // Register location of the first atomic directive.
12644 DSAStack->addAtomicDirectiveLoc(StartLoc);
12645 if (!AStmt)
12646 return StmtError();
12648 // 1.2.2 OpenMP Language Terminology
12649 // Structured block - An executable statement with a single entry at the
12650 // top and a single exit at the bottom.
12651 // The point of exit cannot be a branch out of the structured block.
12652 // longjmp() and throw() must not violate the entry/exit criteria.
12653 OpenMPClauseKind AtomicKind = OMPC_unknown;
12654 SourceLocation AtomicKindLoc;
12655 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12656 SourceLocation MemOrderLoc;
12657 bool MutexClauseEncountered = false;
12658 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12659 for (const OMPClause *C : Clauses) {
12660 switch (C->getClauseKind()) {
12661 case OMPC_read:
12662 case OMPC_write:
12663 case OMPC_update:
12664 MutexClauseEncountered = true;
12665 [[fallthrough]];
12666 case OMPC_capture:
12667 case OMPC_compare: {
12668 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12669 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12670 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12671 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12672 << getOpenMPClauseName(AtomicKind);
12673 } else {
12674 AtomicKind = C->getClauseKind();
12675 AtomicKindLoc = C->getBeginLoc();
12676 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12677 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12678 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12679 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12680 << getOpenMPClauseName(AtomicKind);
12683 break;
12685 case OMPC_fail: {
12686 if (AtomicKind != OMPC_compare) {
12687 Diag(C->getBeginLoc(), diag::err_omp_atomic_fail_no_compare)
12688 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12689 return StmtError();
12691 break;
12693 case OMPC_seq_cst:
12694 case OMPC_acq_rel:
12695 case OMPC_acquire:
12696 case OMPC_release:
12697 case OMPC_relaxed: {
12698 if (MemOrderKind != OMPC_unknown) {
12699 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12700 << getOpenMPDirectiveName(OMPD_atomic) << 0
12701 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12702 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12703 << getOpenMPClauseName(MemOrderKind);
12704 } else {
12705 MemOrderKind = C->getClauseKind();
12706 MemOrderLoc = C->getBeginLoc();
12708 break;
12710 // The following clauses are allowed, but we don't need to do anything here.
12711 case OMPC_hint:
12712 break;
12713 default:
12714 llvm_unreachable("unknown clause is encountered");
12717 bool IsCompareCapture = false;
12718 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12719 EncounteredAtomicKinds.contains(OMPC_capture)) {
12720 IsCompareCapture = true;
12721 AtomicKind = OMPC_compare;
12723 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12724 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12725 // release.
12726 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12727 // acquire.
12728 // If atomic-clause is update or not present then memory-order-clause must not
12729 // be acq_rel or acquire.
12730 if ((AtomicKind == OMPC_read &&
12731 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12732 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12733 AtomicKind == OMPC_unknown) &&
12734 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12735 SourceLocation Loc = AtomicKindLoc;
12736 if (AtomicKind == OMPC_unknown)
12737 Loc = StartLoc;
12738 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12739 << getOpenMPClauseName(AtomicKind)
12740 << (AtomicKind == OMPC_unknown ? 1 : 0)
12741 << getOpenMPClauseName(MemOrderKind);
12742 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12743 << getOpenMPClauseName(MemOrderKind);
12746 Stmt *Body = AStmt;
12747 if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12748 Body = EWC->getSubExpr();
12750 Expr *X = nullptr;
12751 Expr *V = nullptr;
12752 Expr *E = nullptr;
12753 Expr *UE = nullptr;
12754 Expr *D = nullptr;
12755 Expr *CE = nullptr;
12756 Expr *R = nullptr;
12757 bool IsXLHSInRHSPart = false;
12758 bool IsPostfixUpdate = false;
12759 bool IsFailOnly = false;
12760 // OpenMP [2.12.6, atomic Construct]
12761 // In the next expressions:
12762 // * x and v (as applicable) are both l-value expressions with scalar type.
12763 // * During the execution of an atomic region, multiple syntactic
12764 // occurrences of x must designate the same storage location.
12765 // * Neither of v and expr (as applicable) may access the storage location
12766 // designated by x.
12767 // * Neither of x and expr (as applicable) may access the storage location
12768 // designated by v.
12769 // * expr is an expression with scalar type.
12770 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12771 // * binop, binop=, ++, and -- are not overloaded operators.
12772 // * The expression x binop expr must be numerically equivalent to x binop
12773 // (expr). This requirement is satisfied if the operators in expr have
12774 // precedence greater than binop, or by using parentheses around expr or
12775 // subexpressions of expr.
12776 // * The expression expr binop x must be numerically equivalent to (expr)
12777 // binop x. This requirement is satisfied if the operators in expr have
12778 // precedence equal to or greater than binop, or by using parentheses around
12779 // expr or subexpressions of expr.
12780 // * For forms that allow multiple occurrences of x, the number of times
12781 // that x is evaluated is unspecified.
12782 if (AtomicKind == OMPC_read) {
12783 enum {
12784 NotAnExpression,
12785 NotAnAssignmentOp,
12786 NotAScalarType,
12787 NotAnLValue,
12788 NoError
12789 } ErrorFound = NoError;
12790 SourceLocation ErrorLoc, NoteLoc;
12791 SourceRange ErrorRange, NoteRange;
12792 // If clause is read:
12793 // v = x;
12794 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12795 const auto *AtomicBinOp =
12796 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12797 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12798 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12799 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12800 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12801 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12802 if (!X->isLValue() || !V->isLValue()) {
12803 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12804 ErrorFound = NotAnLValue;
12805 ErrorLoc = AtomicBinOp->getExprLoc();
12806 ErrorRange = AtomicBinOp->getSourceRange();
12807 NoteLoc = NotLValueExpr->getExprLoc();
12808 NoteRange = NotLValueExpr->getSourceRange();
12810 } else if (!X->isInstantiationDependent() ||
12811 !V->isInstantiationDependent()) {
12812 const Expr *NotScalarExpr =
12813 (X->isInstantiationDependent() || X->getType()->isScalarType())
12815 : X;
12816 ErrorFound = NotAScalarType;
12817 ErrorLoc = AtomicBinOp->getExprLoc();
12818 ErrorRange = AtomicBinOp->getSourceRange();
12819 NoteLoc = NotScalarExpr->getExprLoc();
12820 NoteRange = NotScalarExpr->getSourceRange();
12822 } else if (!AtomicBody->isInstantiationDependent()) {
12823 ErrorFound = NotAnAssignmentOp;
12824 ErrorLoc = AtomicBody->getExprLoc();
12825 ErrorRange = AtomicBody->getSourceRange();
12826 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12827 : AtomicBody->getExprLoc();
12828 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12829 : AtomicBody->getSourceRange();
12831 } else {
12832 ErrorFound = NotAnExpression;
12833 NoteLoc = ErrorLoc = Body->getBeginLoc();
12834 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12836 if (ErrorFound != NoError) {
12837 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12838 << ErrorRange;
12839 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12840 << ErrorFound << NoteRange;
12841 return StmtError();
12843 if (CurContext->isDependentContext())
12844 V = X = nullptr;
12845 } else if (AtomicKind == OMPC_write) {
12846 enum {
12847 NotAnExpression,
12848 NotAnAssignmentOp,
12849 NotAScalarType,
12850 NotAnLValue,
12851 NoError
12852 } ErrorFound = NoError;
12853 SourceLocation ErrorLoc, NoteLoc;
12854 SourceRange ErrorRange, NoteRange;
12855 // If clause is write:
12856 // x = expr;
12857 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12858 const auto *AtomicBinOp =
12859 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12860 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12861 X = AtomicBinOp->getLHS();
12862 E = AtomicBinOp->getRHS();
12863 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12864 (E->isInstantiationDependent() || E->getType()->isScalarType())) {
12865 if (!X->isLValue()) {
12866 ErrorFound = NotAnLValue;
12867 ErrorLoc = AtomicBinOp->getExprLoc();
12868 ErrorRange = AtomicBinOp->getSourceRange();
12869 NoteLoc = X->getExprLoc();
12870 NoteRange = X->getSourceRange();
12872 } else if (!X->isInstantiationDependent() ||
12873 !E->isInstantiationDependent()) {
12874 const Expr *NotScalarExpr =
12875 (X->isInstantiationDependent() || X->getType()->isScalarType())
12877 : X;
12878 ErrorFound = NotAScalarType;
12879 ErrorLoc = AtomicBinOp->getExprLoc();
12880 ErrorRange = AtomicBinOp->getSourceRange();
12881 NoteLoc = NotScalarExpr->getExprLoc();
12882 NoteRange = NotScalarExpr->getSourceRange();
12884 } else if (!AtomicBody->isInstantiationDependent()) {
12885 ErrorFound = NotAnAssignmentOp;
12886 ErrorLoc = AtomicBody->getExprLoc();
12887 ErrorRange = AtomicBody->getSourceRange();
12888 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12889 : AtomicBody->getExprLoc();
12890 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12891 : AtomicBody->getSourceRange();
12893 } else {
12894 ErrorFound = NotAnExpression;
12895 NoteLoc = ErrorLoc = Body->getBeginLoc();
12896 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12898 if (ErrorFound != NoError) {
12899 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12900 << ErrorRange;
12901 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12902 << ErrorFound << NoteRange;
12903 return StmtError();
12905 if (CurContext->isDependentContext())
12906 E = X = nullptr;
12907 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12908 // If clause is update:
12909 // x++;
12910 // x--;
12911 // ++x;
12912 // --x;
12913 // x binop= expr;
12914 // x = x binop expr;
12915 // x = expr binop x;
12916 OpenMPAtomicUpdateChecker Checker(*this);
12917 if (Checker.checkStatement(
12918 Body,
12919 (AtomicKind == OMPC_update)
12920 ? diag::err_omp_atomic_update_not_expression_statement
12921 : diag::err_omp_atomic_not_expression_statement,
12922 diag::note_omp_atomic_update))
12923 return StmtError();
12924 if (!CurContext->isDependentContext()) {
12925 E = Checker.getExpr();
12926 X = Checker.getX();
12927 UE = Checker.getUpdateExpr();
12928 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12930 } else if (AtomicKind == OMPC_capture) {
12931 enum {
12932 NotAnAssignmentOp,
12933 NotACompoundStatement,
12934 NotTwoSubstatements,
12935 NotASpecificExpression,
12936 NoError
12937 } ErrorFound = NoError;
12938 SourceLocation ErrorLoc, NoteLoc;
12939 SourceRange ErrorRange, NoteRange;
12940 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12941 // If clause is a capture:
12942 // v = x++;
12943 // v = x--;
12944 // v = ++x;
12945 // v = --x;
12946 // v = x binop= expr;
12947 // v = x = x binop expr;
12948 // v = x = expr binop x;
12949 const auto *AtomicBinOp =
12950 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12951 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12952 V = AtomicBinOp->getLHS();
12953 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12954 OpenMPAtomicUpdateChecker Checker(*this);
12955 if (Checker.checkStatement(
12956 Body, diag::err_omp_atomic_capture_not_expression_statement,
12957 diag::note_omp_atomic_update))
12958 return StmtError();
12959 E = Checker.getExpr();
12960 X = Checker.getX();
12961 UE = Checker.getUpdateExpr();
12962 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12963 IsPostfixUpdate = Checker.isPostfixUpdate();
12964 } else if (!AtomicBody->isInstantiationDependent()) {
12965 ErrorLoc = AtomicBody->getExprLoc();
12966 ErrorRange = AtomicBody->getSourceRange();
12967 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12968 : AtomicBody->getExprLoc();
12969 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12970 : AtomicBody->getSourceRange();
12971 ErrorFound = NotAnAssignmentOp;
12973 if (ErrorFound != NoError) {
12974 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
12975 << ErrorRange;
12976 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12977 return StmtError();
12979 if (CurContext->isDependentContext())
12980 UE = V = E = X = nullptr;
12981 } else {
12982 // If clause is a capture:
12983 // { v = x; x = expr; }
12984 // { v = x; x++; }
12985 // { v = x; x--; }
12986 // { v = x; ++x; }
12987 // { v = x; --x; }
12988 // { v = x; x binop= expr; }
12989 // { v = x; x = x binop expr; }
12990 // { v = x; x = expr binop x; }
12991 // { x++; v = x; }
12992 // { x--; v = x; }
12993 // { ++x; v = x; }
12994 // { --x; v = x; }
12995 // { x binop= expr; v = x; }
12996 // { x = x binop expr; v = x; }
12997 // { x = expr binop x; v = x; }
12998 if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
12999 // Check that this is { expr1; expr2; }
13000 if (CS->size() == 2) {
13001 Stmt *First = CS->body_front();
13002 Stmt *Second = CS->body_back();
13003 if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
13004 First = EWC->getSubExpr()->IgnoreParenImpCasts();
13005 if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
13006 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
13007 // Need to find what subexpression is 'v' and what is 'x'.
13008 OpenMPAtomicUpdateChecker Checker(*this);
13009 bool IsUpdateExprFound = !Checker.checkStatement(Second);
13010 BinaryOperator *BinOp = nullptr;
13011 if (IsUpdateExprFound) {
13012 BinOp = dyn_cast<BinaryOperator>(First);
13013 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13015 if (IsUpdateExprFound && !CurContext->isDependentContext()) {
13016 // { v = x; x++; }
13017 // { v = x; x--; }
13018 // { v = x; ++x; }
13019 // { v = x; --x; }
13020 // { v = x; x binop= expr; }
13021 // { v = x; x = x binop expr; }
13022 // { v = x; x = expr binop x; }
13023 // Check that the first expression has form v = x.
13024 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13025 llvm::FoldingSetNodeID XId, PossibleXId;
13026 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13027 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13028 IsUpdateExprFound = XId == PossibleXId;
13029 if (IsUpdateExprFound) {
13030 V = BinOp->getLHS();
13031 X = Checker.getX();
13032 E = Checker.getExpr();
13033 UE = Checker.getUpdateExpr();
13034 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13035 IsPostfixUpdate = true;
13038 if (!IsUpdateExprFound) {
13039 IsUpdateExprFound = !Checker.checkStatement(First);
13040 BinOp = nullptr;
13041 if (IsUpdateExprFound) {
13042 BinOp = dyn_cast<BinaryOperator>(Second);
13043 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13045 if (IsUpdateExprFound && !CurContext->isDependentContext()) {
13046 // { x++; v = x; }
13047 // { x--; v = x; }
13048 // { ++x; v = x; }
13049 // { --x; v = x; }
13050 // { x binop= expr; v = x; }
13051 // { x = x binop expr; v = x; }
13052 // { x = expr binop x; v = x; }
13053 // Check that the second expression has form v = x.
13054 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13055 llvm::FoldingSetNodeID XId, PossibleXId;
13056 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13057 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13058 IsUpdateExprFound = XId == PossibleXId;
13059 if (IsUpdateExprFound) {
13060 V = BinOp->getLHS();
13061 X = Checker.getX();
13062 E = Checker.getExpr();
13063 UE = Checker.getUpdateExpr();
13064 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13065 IsPostfixUpdate = false;
13069 if (!IsUpdateExprFound) {
13070 // { v = x; x = expr; }
13071 auto *FirstExpr = dyn_cast<Expr>(First);
13072 auto *SecondExpr = dyn_cast<Expr>(Second);
13073 if (!FirstExpr || !SecondExpr ||
13074 !(FirstExpr->isInstantiationDependent() ||
13075 SecondExpr->isInstantiationDependent())) {
13076 auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
13077 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
13078 ErrorFound = NotAnAssignmentOp;
13079 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
13080 : First->getBeginLoc();
13081 NoteRange = ErrorRange = FirstBinOp
13082 ? FirstBinOp->getSourceRange()
13083 : SourceRange(ErrorLoc, ErrorLoc);
13084 } else {
13085 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
13086 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
13087 ErrorFound = NotAnAssignmentOp;
13088 NoteLoc = ErrorLoc = SecondBinOp
13089 ? SecondBinOp->getOperatorLoc()
13090 : Second->getBeginLoc();
13091 NoteRange = ErrorRange =
13092 SecondBinOp ? SecondBinOp->getSourceRange()
13093 : SourceRange(ErrorLoc, ErrorLoc);
13094 } else {
13095 Expr *PossibleXRHSInFirst =
13096 FirstBinOp->getRHS()->IgnoreParenImpCasts();
13097 Expr *PossibleXLHSInSecond =
13098 SecondBinOp->getLHS()->IgnoreParenImpCasts();
13099 llvm::FoldingSetNodeID X1Id, X2Id;
13100 PossibleXRHSInFirst->Profile(X1Id, Context,
13101 /*Canonical=*/true);
13102 PossibleXLHSInSecond->Profile(X2Id, Context,
13103 /*Canonical=*/true);
13104 IsUpdateExprFound = X1Id == X2Id;
13105 if (IsUpdateExprFound) {
13106 V = FirstBinOp->getLHS();
13107 X = SecondBinOp->getLHS();
13108 E = SecondBinOp->getRHS();
13109 UE = nullptr;
13110 IsXLHSInRHSPart = false;
13111 IsPostfixUpdate = true;
13112 } else {
13113 ErrorFound = NotASpecificExpression;
13114 ErrorLoc = FirstBinOp->getExprLoc();
13115 ErrorRange = FirstBinOp->getSourceRange();
13116 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
13117 NoteRange = SecondBinOp->getRHS()->getSourceRange();
13123 } else {
13124 NoteLoc = ErrorLoc = Body->getBeginLoc();
13125 NoteRange = ErrorRange =
13126 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13127 ErrorFound = NotTwoSubstatements;
13129 } else {
13130 NoteLoc = ErrorLoc = Body->getBeginLoc();
13131 NoteRange = ErrorRange =
13132 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13133 ErrorFound = NotACompoundStatement;
13136 if (ErrorFound != NoError) {
13137 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
13138 << ErrorRange;
13139 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13140 return StmtError();
13142 if (CurContext->isDependentContext())
13143 UE = V = E = X = nullptr;
13144 } else if (AtomicKind == OMPC_compare) {
13145 if (IsCompareCapture) {
13146 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
13147 OpenMPAtomicCompareCaptureChecker Checker(*this);
13148 if (!Checker.checkStmt(Body, ErrorInfo)) {
13149 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
13150 << ErrorInfo.ErrorRange;
13151 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13152 << ErrorInfo.Error << ErrorInfo.NoteRange;
13153 return StmtError();
13155 X = Checker.getX();
13156 E = Checker.getE();
13157 D = Checker.getD();
13158 CE = Checker.getCond();
13159 V = Checker.getV();
13160 R = Checker.getR();
13161 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13162 IsXLHSInRHSPart = Checker.isXBinopExpr();
13163 IsFailOnly = Checker.isFailOnly();
13164 IsPostfixUpdate = Checker.isPostfixUpdate();
13165 } else {
13166 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
13167 OpenMPAtomicCompareChecker Checker(*this);
13168 if (!Checker.checkStmt(Body, ErrorInfo)) {
13169 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
13170 << ErrorInfo.ErrorRange;
13171 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13172 << ErrorInfo.Error << ErrorInfo.NoteRange;
13173 return StmtError();
13175 X = Checker.getX();
13176 E = Checker.getE();
13177 D = Checker.getD();
13178 CE = Checker.getCond();
13179 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13180 IsXLHSInRHSPart = Checker.isXBinopExpr();
13184 setFunctionHasBranchProtectedScope();
13186 return OMPAtomicDirective::Create(
13187 Context, StartLoc, EndLoc, Clauses, AStmt,
13188 {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
13191 StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
13192 Stmt *AStmt,
13193 SourceLocation StartLoc,
13194 SourceLocation EndLoc) {
13195 if (!AStmt)
13196 return StmtError();
13198 auto *CS = cast<CapturedStmt>(AStmt);
13199 // 1.2.2 OpenMP Language Terminology
13200 // Structured block - An executable statement with a single entry at the
13201 // top and a single exit at the bottom.
13202 // The point of exit cannot be a branch out of the structured block.
13203 // longjmp() and throw() must not violate the entry/exit criteria.
13204 CS->getCapturedDecl()->setNothrow();
13205 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target);
13206 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13207 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13208 // 1.2.2 OpenMP Language Terminology
13209 // Structured block - An executable statement with a single entry at the
13210 // top and a single exit at the bottom.
13211 // The point of exit cannot be a branch out of the structured block.
13212 // longjmp() and throw() must not violate the entry/exit criteria.
13213 CS->getCapturedDecl()->setNothrow();
13216 // OpenMP [2.16, Nesting of Regions]
13217 // If specified, a teams construct must be contained within a target
13218 // construct. That target construct must contain no statements or directives
13219 // outside of the teams construct.
13220 if (DSAStack->hasInnerTeamsRegion()) {
13221 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
13222 bool OMPTeamsFound = true;
13223 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
13224 auto I = CS->body_begin();
13225 while (I != CS->body_end()) {
13226 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
13227 if (!OED || !isOpenMPTeamsDirective(OED->getDirectiveKind()) ||
13228 OMPTeamsFound) {
13230 OMPTeamsFound = false;
13231 break;
13233 ++I;
13235 assert(I != CS->body_end() && "Not found statement");
13236 S = *I;
13237 } else {
13238 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
13239 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13241 if (!OMPTeamsFound) {
13242 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
13243 Diag(DSAStack->getInnerTeamsRegionLoc(),
13244 diag::note_omp_nested_teams_construct_here);
13245 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
13246 << isa<OMPExecutableDirective>(S);
13247 return StmtError();
13251 setFunctionHasBranchProtectedScope();
13253 return OMPTargetDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
13256 StmtResult
13257 Sema::ActOnOpenMPTargetParallelDirective(ArrayRef<OMPClause *> Clauses,
13258 Stmt *AStmt, SourceLocation StartLoc,
13259 SourceLocation EndLoc) {
13260 if (!AStmt)
13261 return StmtError();
13263 auto *CS = cast<CapturedStmt>(AStmt);
13264 // 1.2.2 OpenMP Language Terminology
13265 // Structured block - An executable statement with a single entry at the
13266 // top and a single exit at the bottom.
13267 // The point of exit cannot be a branch out of the structured block.
13268 // longjmp() and throw() must not violate the entry/exit criteria.
13269 CS->getCapturedDecl()->setNothrow();
13270 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel);
13271 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13272 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13273 // 1.2.2 OpenMP Language Terminology
13274 // Structured block - An executable statement with a single entry at the
13275 // top and a single exit at the bottom.
13276 // The point of exit cannot be a branch out of the structured block.
13277 // longjmp() and throw() must not violate the entry/exit criteria.
13278 CS->getCapturedDecl()->setNothrow();
13281 setFunctionHasBranchProtectedScope();
13283 return OMPTargetParallelDirective::Create(
13284 Context, StartLoc, EndLoc, Clauses, AStmt,
13285 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13288 StmtResult Sema::ActOnOpenMPTargetParallelForDirective(
13289 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13290 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13291 if (!AStmt)
13292 return StmtError();
13294 auto *CS = cast<CapturedStmt>(AStmt);
13295 // 1.2.2 OpenMP Language Terminology
13296 // Structured block - An executable statement with a single entry at the
13297 // top and a single exit at the bottom.
13298 // The point of exit cannot be a branch out of the structured block.
13299 // longjmp() and throw() must not violate the entry/exit criteria.
13300 CS->getCapturedDecl()->setNothrow();
13301 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_for);
13302 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13303 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13304 // 1.2.2 OpenMP Language Terminology
13305 // Structured block - An executable statement with a single entry at the
13306 // top and a single exit at the bottom.
13307 // The point of exit cannot be a branch out of the structured block.
13308 // longjmp() and throw() must not violate the entry/exit criteria.
13309 CS->getCapturedDecl()->setNothrow();
13312 OMPLoopBasedDirective::HelperExprs B;
13313 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13314 // define the nested loops number.
13315 unsigned NestedLoopCount =
13316 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
13317 getOrderedNumberExpr(Clauses), CS, *this, *DSAStack,
13318 VarsWithImplicitDSA, B);
13319 if (NestedLoopCount == 0)
13320 return StmtError();
13322 assert((CurContext->isDependentContext() || B.builtAll()) &&
13323 "omp target parallel for loop exprs were not built");
13325 if (!CurContext->isDependentContext()) {
13326 // Finalize the clauses that need pre-built expressions for CodeGen.
13327 for (OMPClause *C : Clauses) {
13328 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13329 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13330 B.NumIterations, *this, CurScope,
13331 DSAStack))
13332 return StmtError();
13336 setFunctionHasBranchProtectedScope();
13337 return OMPTargetParallelForDirective::Create(
13338 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13339 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13342 /// Check for existence of a map clause in the list of clauses.
13343 static bool hasClauses(ArrayRef<OMPClause *> Clauses,
13344 const OpenMPClauseKind K) {
13345 return llvm::any_of(
13346 Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
13349 template <typename... Params>
13350 static bool hasClauses(ArrayRef<OMPClause *> Clauses, const OpenMPClauseKind K,
13351 const Params... ClauseTypes) {
13352 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13355 /// Check if the variables in the mapping clause are externally visible.
13356 static bool isClauseMappable(ArrayRef<OMPClause *> Clauses) {
13357 for (const OMPClause *C : Clauses) {
13358 if (auto *TC = dyn_cast<OMPToClause>(C))
13359 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
13360 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13361 (VD->isExternallyVisible() &&
13362 VD->getVisibility() != HiddenVisibility);
13364 else if (auto *FC = dyn_cast<OMPFromClause>(C))
13365 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
13366 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13367 (VD->isExternallyVisible() &&
13368 VD->getVisibility() != HiddenVisibility);
13372 return true;
13375 StmtResult Sema::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
13376 Stmt *AStmt,
13377 SourceLocation StartLoc,
13378 SourceLocation EndLoc) {
13379 if (!AStmt)
13380 return StmtError();
13382 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13384 // OpenMP [2.12.2, target data Construct, Restrictions]
13385 // At least one map, use_device_addr or use_device_ptr clause must appear on
13386 // the directive.
13387 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13388 (LangOpts.OpenMP < 50 || !hasClauses(Clauses, OMPC_use_device_addr))) {
13389 StringRef Expected;
13390 if (LangOpts.OpenMP < 50)
13391 Expected = "'map' or 'use_device_ptr'";
13392 else
13393 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13394 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13395 << Expected << getOpenMPDirectiveName(OMPD_target_data);
13396 return StmtError();
13399 setFunctionHasBranchProtectedScope();
13401 return OMPTargetDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
13402 AStmt);
13405 StmtResult
13406 Sema::ActOnOpenMPTargetEnterDataDirective(ArrayRef<OMPClause *> Clauses,
13407 SourceLocation StartLoc,
13408 SourceLocation EndLoc, Stmt *AStmt) {
13409 if (!AStmt)
13410 return StmtError();
13412 auto *CS = cast<CapturedStmt>(AStmt);
13413 // 1.2.2 OpenMP Language Terminology
13414 // Structured block - An executable statement with a single entry at the
13415 // top and a single exit at the bottom.
13416 // The point of exit cannot be a branch out of the structured block.
13417 // longjmp() and throw() must not violate the entry/exit criteria.
13418 CS->getCapturedDecl()->setNothrow();
13419 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_enter_data);
13420 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13421 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13422 // 1.2.2 OpenMP Language Terminology
13423 // Structured block - An executable statement with a single entry at the
13424 // top and a single exit at the bottom.
13425 // The point of exit cannot be a branch out of the structured block.
13426 // longjmp() and throw() must not violate the entry/exit criteria.
13427 CS->getCapturedDecl()->setNothrow();
13430 // OpenMP [2.10.2, Restrictions, p. 99]
13431 // At least one map clause must appear on the directive.
13432 if (!hasClauses(Clauses, OMPC_map)) {
13433 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13434 << "'map'" << getOpenMPDirectiveName(OMPD_target_enter_data);
13435 return StmtError();
13438 return OMPTargetEnterDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
13439 AStmt);
13442 StmtResult
13443 Sema::ActOnOpenMPTargetExitDataDirective(ArrayRef<OMPClause *> Clauses,
13444 SourceLocation StartLoc,
13445 SourceLocation EndLoc, Stmt *AStmt) {
13446 if (!AStmt)
13447 return StmtError();
13449 auto *CS = cast<CapturedStmt>(AStmt);
13450 // 1.2.2 OpenMP Language Terminology
13451 // Structured block - An executable statement with a single entry at the
13452 // top and a single exit at the bottom.
13453 // The point of exit cannot be a branch out of the structured block.
13454 // longjmp() and throw() must not violate the entry/exit criteria.
13455 CS->getCapturedDecl()->setNothrow();
13456 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_exit_data);
13457 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13458 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13459 // 1.2.2 OpenMP Language Terminology
13460 // Structured block - An executable statement with a single entry at the
13461 // top and a single exit at the bottom.
13462 // The point of exit cannot be a branch out of the structured block.
13463 // longjmp() and throw() must not violate the entry/exit criteria.
13464 CS->getCapturedDecl()->setNothrow();
13467 // OpenMP [2.10.3, Restrictions, p. 102]
13468 // At least one map clause must appear on the directive.
13469 if (!hasClauses(Clauses, OMPC_map)) {
13470 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13471 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data);
13472 return StmtError();
13475 return OMPTargetExitDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
13476 AStmt);
13479 StmtResult Sema::ActOnOpenMPTargetUpdateDirective(ArrayRef<OMPClause *> Clauses,
13480 SourceLocation StartLoc,
13481 SourceLocation EndLoc,
13482 Stmt *AStmt) {
13483 if (!AStmt)
13484 return StmtError();
13486 auto *CS = cast<CapturedStmt>(AStmt);
13487 // 1.2.2 OpenMP Language Terminology
13488 // Structured block - An executable statement with a single entry at the
13489 // top and a single exit at the bottom.
13490 // The point of exit cannot be a branch out of the structured block.
13491 // longjmp() and throw() must not violate the entry/exit criteria.
13492 CS->getCapturedDecl()->setNothrow();
13493 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_update);
13494 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13495 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13496 // 1.2.2 OpenMP Language Terminology
13497 // Structured block - An executable statement with a single entry at the
13498 // top and a single exit at the bottom.
13499 // The point of exit cannot be a branch out of the structured block.
13500 // longjmp() and throw() must not violate the entry/exit criteria.
13501 CS->getCapturedDecl()->setNothrow();
13504 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
13505 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13506 return StmtError();
13509 if (!isClauseMappable(Clauses)) {
13510 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13511 return StmtError();
13514 return OMPTargetUpdateDirective::Create(Context, StartLoc, EndLoc, Clauses,
13515 AStmt);
13518 StmtResult Sema::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
13519 Stmt *AStmt, SourceLocation StartLoc,
13520 SourceLocation EndLoc) {
13521 if (!AStmt)
13522 return StmtError();
13524 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13525 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13526 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13528 auto *CS = cast<CapturedStmt>(AStmt);
13529 // 1.2.2 OpenMP Language Terminology
13530 // Structured block - An executable statement with a single entry at the
13531 // top and a single exit at the bottom.
13532 // The point of exit cannot be a branch out of the structured block.
13533 // longjmp() and throw() must not violate the entry/exit criteria.
13534 CS->getCapturedDecl()->setNothrow();
13536 setFunctionHasBranchProtectedScope();
13538 DSAStack->setParentTeamsRegionLoc(StartLoc);
13540 return OMPTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
13543 StmtResult
13544 Sema::ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc,
13545 SourceLocation EndLoc,
13546 OpenMPDirectiveKind CancelRegion) {
13547 if (DSAStack->isParentNowaitRegion()) {
13548 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13549 return StmtError();
13551 if (DSAStack->isParentOrderedRegion()) {
13552 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13553 return StmtError();
13555 return OMPCancellationPointDirective::Create(Context, StartLoc, EndLoc,
13556 CancelRegion);
13559 StmtResult Sema::ActOnOpenMPCancelDirective(ArrayRef<OMPClause *> Clauses,
13560 SourceLocation StartLoc,
13561 SourceLocation EndLoc,
13562 OpenMPDirectiveKind CancelRegion) {
13563 if (DSAStack->isParentNowaitRegion()) {
13564 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13565 return StmtError();
13567 if (DSAStack->isParentOrderedRegion()) {
13568 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13569 return StmtError();
13571 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13572 return OMPCancelDirective::Create(Context, StartLoc, EndLoc, Clauses,
13573 CancelRegion);
13576 static bool checkReductionClauseWithNogroup(Sema &S,
13577 ArrayRef<OMPClause *> Clauses) {
13578 const OMPClause *ReductionClause = nullptr;
13579 const OMPClause *NogroupClause = nullptr;
13580 for (const OMPClause *C : Clauses) {
13581 if (C->getClauseKind() == OMPC_reduction) {
13582 ReductionClause = C;
13583 if (NogroupClause)
13584 break;
13585 continue;
13587 if (C->getClauseKind() == OMPC_nogroup) {
13588 NogroupClause = C;
13589 if (ReductionClause)
13590 break;
13591 continue;
13594 if (ReductionClause && NogroupClause) {
13595 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13596 << SourceRange(NogroupClause->getBeginLoc(),
13597 NogroupClause->getEndLoc());
13598 return true;
13600 return false;
13603 StmtResult Sema::ActOnOpenMPTaskLoopDirective(
13604 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13605 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13606 if (!AStmt)
13607 return StmtError();
13609 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13610 OMPLoopBasedDirective::HelperExprs B;
13611 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13612 // define the nested loops number.
13613 unsigned NestedLoopCount =
13614 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13615 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13616 VarsWithImplicitDSA, B);
13617 if (NestedLoopCount == 0)
13618 return StmtError();
13620 assert((CurContext->isDependentContext() || B.builtAll()) &&
13621 "omp for loop exprs were not built");
13623 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13624 // The grainsize clause and num_tasks clause are mutually exclusive and may
13625 // not appear on the same taskloop directive.
13626 if (checkMutuallyExclusiveClauses(*this, Clauses,
13627 {OMPC_grainsize, OMPC_num_tasks}))
13628 return StmtError();
13629 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13630 // If a reduction clause is present on the taskloop directive, the nogroup
13631 // clause must not be specified.
13632 if (checkReductionClauseWithNogroup(*this, Clauses))
13633 return StmtError();
13635 setFunctionHasBranchProtectedScope();
13636 return OMPTaskLoopDirective::Create(Context, StartLoc, EndLoc,
13637 NestedLoopCount, Clauses, AStmt, B,
13638 DSAStack->isCancelRegion());
13641 StmtResult Sema::ActOnOpenMPTaskLoopSimdDirective(
13642 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13643 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13644 if (!AStmt)
13645 return StmtError();
13647 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13648 OMPLoopBasedDirective::HelperExprs B;
13649 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13650 // define the nested loops number.
13651 unsigned NestedLoopCount =
13652 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13653 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13654 VarsWithImplicitDSA, B);
13655 if (NestedLoopCount == 0)
13656 return StmtError();
13658 assert((CurContext->isDependentContext() || B.builtAll()) &&
13659 "omp for loop exprs were not built");
13661 if (!CurContext->isDependentContext()) {
13662 // Finalize the clauses that need pre-built expressions for CodeGen.
13663 for (OMPClause *C : Clauses) {
13664 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13665 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13666 B.NumIterations, *this, CurScope,
13667 DSAStack))
13668 return StmtError();
13672 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13673 // The grainsize clause and num_tasks clause are mutually exclusive and may
13674 // not appear on the same taskloop directive.
13675 if (checkMutuallyExclusiveClauses(*this, Clauses,
13676 {OMPC_grainsize, OMPC_num_tasks}))
13677 return StmtError();
13678 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13679 // If a reduction clause is present on the taskloop directive, the nogroup
13680 // clause must not be specified.
13681 if (checkReductionClauseWithNogroup(*this, Clauses))
13682 return StmtError();
13683 if (checkSimdlenSafelenSpecified(*this, Clauses))
13684 return StmtError();
13686 setFunctionHasBranchProtectedScope();
13687 return OMPTaskLoopSimdDirective::Create(Context, StartLoc, EndLoc,
13688 NestedLoopCount, Clauses, AStmt, B);
13691 StmtResult Sema::ActOnOpenMPMasterTaskLoopDirective(
13692 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13693 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13694 if (!AStmt)
13695 return StmtError();
13697 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13698 OMPLoopBasedDirective::HelperExprs B;
13699 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13700 // define the nested loops number.
13701 unsigned NestedLoopCount =
13702 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13703 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13704 VarsWithImplicitDSA, B);
13705 if (NestedLoopCount == 0)
13706 return StmtError();
13708 assert((CurContext->isDependentContext() || B.builtAll()) &&
13709 "omp for loop exprs were not built");
13711 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13712 // The grainsize clause and num_tasks clause are mutually exclusive and may
13713 // not appear on the same taskloop directive.
13714 if (checkMutuallyExclusiveClauses(*this, Clauses,
13715 {OMPC_grainsize, OMPC_num_tasks}))
13716 return StmtError();
13717 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13718 // If a reduction clause is present on the taskloop directive, the nogroup
13719 // clause must not be specified.
13720 if (checkReductionClauseWithNogroup(*this, Clauses))
13721 return StmtError();
13723 setFunctionHasBranchProtectedScope();
13724 return OMPMasterTaskLoopDirective::Create(Context, StartLoc, EndLoc,
13725 NestedLoopCount, Clauses, AStmt, B,
13726 DSAStack->isCancelRegion());
13729 StmtResult Sema::ActOnOpenMPMaskedTaskLoopDirective(
13730 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13731 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13732 if (!AStmt)
13733 return StmtError();
13735 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13736 OMPLoopBasedDirective::HelperExprs B;
13737 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13738 // define the nested loops number.
13739 unsigned NestedLoopCount =
13740 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13741 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13742 VarsWithImplicitDSA, B);
13743 if (NestedLoopCount == 0)
13744 return StmtError();
13746 assert((CurContext->isDependentContext() || B.builtAll()) &&
13747 "omp for loop exprs were not built");
13749 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13750 // The grainsize clause and num_tasks clause are mutually exclusive and may
13751 // not appear on the same taskloop directive.
13752 if (checkMutuallyExclusiveClauses(*this, Clauses,
13753 {OMPC_grainsize, OMPC_num_tasks}))
13754 return StmtError();
13755 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13756 // If a reduction clause is present on the taskloop directive, the nogroup
13757 // clause must not be specified.
13758 if (checkReductionClauseWithNogroup(*this, Clauses))
13759 return StmtError();
13761 setFunctionHasBranchProtectedScope();
13762 return OMPMaskedTaskLoopDirective::Create(Context, StartLoc, EndLoc,
13763 NestedLoopCount, Clauses, AStmt, B,
13764 DSAStack->isCancelRegion());
13767 StmtResult Sema::ActOnOpenMPMasterTaskLoopSimdDirective(
13768 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13769 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13770 if (!AStmt)
13771 return StmtError();
13773 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13774 OMPLoopBasedDirective::HelperExprs B;
13775 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13776 // define the nested loops number.
13777 unsigned NestedLoopCount =
13778 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13779 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13780 VarsWithImplicitDSA, B);
13781 if (NestedLoopCount == 0)
13782 return StmtError();
13784 assert((CurContext->isDependentContext() || B.builtAll()) &&
13785 "omp for loop exprs were not built");
13787 if (!CurContext->isDependentContext()) {
13788 // Finalize the clauses that need pre-built expressions for CodeGen.
13789 for (OMPClause *C : Clauses) {
13790 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13791 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13792 B.NumIterations, *this, CurScope,
13793 DSAStack))
13794 return StmtError();
13798 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13799 // The grainsize clause and num_tasks clause are mutually exclusive and may
13800 // not appear on the same taskloop directive.
13801 if (checkMutuallyExclusiveClauses(*this, Clauses,
13802 {OMPC_grainsize, OMPC_num_tasks}))
13803 return StmtError();
13804 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13805 // If a reduction clause is present on the taskloop directive, the nogroup
13806 // clause must not be specified.
13807 if (checkReductionClauseWithNogroup(*this, Clauses))
13808 return StmtError();
13809 if (checkSimdlenSafelenSpecified(*this, Clauses))
13810 return StmtError();
13812 setFunctionHasBranchProtectedScope();
13813 return OMPMasterTaskLoopSimdDirective::Create(
13814 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13817 StmtResult Sema::ActOnOpenMPMaskedTaskLoopSimdDirective(
13818 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13819 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13820 if (!AStmt)
13821 return StmtError();
13823 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13824 OMPLoopBasedDirective::HelperExprs B;
13825 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13826 // define the nested loops number.
13827 unsigned NestedLoopCount =
13828 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13829 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13830 VarsWithImplicitDSA, B);
13831 if (NestedLoopCount == 0)
13832 return StmtError();
13834 assert((CurContext->isDependentContext() || B.builtAll()) &&
13835 "omp for loop exprs were not built");
13837 if (!CurContext->isDependentContext()) {
13838 // Finalize the clauses that need pre-built expressions for CodeGen.
13839 for (OMPClause *C : Clauses) {
13840 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13841 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13842 B.NumIterations, *this, CurScope,
13843 DSAStack))
13844 return StmtError();
13848 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13849 // The grainsize clause and num_tasks clause are mutually exclusive and may
13850 // not appear on the same taskloop directive.
13851 if (checkMutuallyExclusiveClauses(*this, Clauses,
13852 {OMPC_grainsize, OMPC_num_tasks}))
13853 return StmtError();
13854 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13855 // If a reduction clause is present on the taskloop directive, the nogroup
13856 // clause must not be specified.
13857 if (checkReductionClauseWithNogroup(*this, Clauses))
13858 return StmtError();
13859 if (checkSimdlenSafelenSpecified(*this, Clauses))
13860 return StmtError();
13862 setFunctionHasBranchProtectedScope();
13863 return OMPMaskedTaskLoopSimdDirective::Create(
13864 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13867 StmtResult Sema::ActOnOpenMPParallelMasterTaskLoopDirective(
13868 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13869 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13870 if (!AStmt)
13871 return StmtError();
13873 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13874 auto *CS = cast<CapturedStmt>(AStmt);
13875 // 1.2.2 OpenMP Language Terminology
13876 // Structured block - An executable statement with a single entry at the
13877 // top and a single exit at the bottom.
13878 // The point of exit cannot be a branch out of the structured block.
13879 // longjmp() and throw() must not violate the entry/exit criteria.
13880 CS->getCapturedDecl()->setNothrow();
13881 for (int ThisCaptureLevel =
13882 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop);
13883 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13884 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13885 // 1.2.2 OpenMP Language Terminology
13886 // Structured block - An executable statement with a single entry at the
13887 // top and a single exit at the bottom.
13888 // The point of exit cannot be a branch out of the structured block.
13889 // longjmp() and throw() must not violate the entry/exit criteria.
13890 CS->getCapturedDecl()->setNothrow();
13893 OMPLoopBasedDirective::HelperExprs B;
13894 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13895 // define the nested loops number.
13896 unsigned NestedLoopCount = checkOpenMPLoop(
13897 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
13898 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
13899 VarsWithImplicitDSA, B);
13900 if (NestedLoopCount == 0)
13901 return StmtError();
13903 assert((CurContext->isDependentContext() || B.builtAll()) &&
13904 "omp for loop exprs were not built");
13906 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13907 // The grainsize clause and num_tasks clause are mutually exclusive and may
13908 // not appear on the same taskloop directive.
13909 if (checkMutuallyExclusiveClauses(*this, Clauses,
13910 {OMPC_grainsize, OMPC_num_tasks}))
13911 return StmtError();
13912 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13913 // If a reduction clause is present on the taskloop directive, the nogroup
13914 // clause must not be specified.
13915 if (checkReductionClauseWithNogroup(*this, Clauses))
13916 return StmtError();
13918 setFunctionHasBranchProtectedScope();
13919 return OMPParallelMasterTaskLoopDirective::Create(
13920 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13921 DSAStack->isCancelRegion());
13924 StmtResult Sema::ActOnOpenMPParallelMaskedTaskLoopDirective(
13925 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13926 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13927 if (!AStmt)
13928 return StmtError();
13930 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13931 auto *CS = cast<CapturedStmt>(AStmt);
13932 // 1.2.2 OpenMP Language Terminology
13933 // Structured block - An executable statement with a single entry at the
13934 // top and a single exit at the bottom.
13935 // The point of exit cannot be a branch out of the structured block.
13936 // longjmp() and throw() must not violate the entry/exit criteria.
13937 CS->getCapturedDecl()->setNothrow();
13938 for (int ThisCaptureLevel =
13939 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop);
13940 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13941 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13942 // 1.2.2 OpenMP Language Terminology
13943 // Structured block - An executable statement with a single entry at the
13944 // top and a single exit at the bottom.
13945 // The point of exit cannot be a branch out of the structured block.
13946 // longjmp() and throw() must not violate the entry/exit criteria.
13947 CS->getCapturedDecl()->setNothrow();
13950 OMPLoopBasedDirective::HelperExprs B;
13951 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13952 // define the nested loops number.
13953 unsigned NestedLoopCount = checkOpenMPLoop(
13954 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
13955 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
13956 VarsWithImplicitDSA, B);
13957 if (NestedLoopCount == 0)
13958 return StmtError();
13960 assert((CurContext->isDependentContext() || B.builtAll()) &&
13961 "omp for loop exprs were not built");
13963 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13964 // The grainsize clause and num_tasks clause are mutually exclusive and may
13965 // not appear on the same taskloop directive.
13966 if (checkMutuallyExclusiveClauses(*this, Clauses,
13967 {OMPC_grainsize, OMPC_num_tasks}))
13968 return StmtError();
13969 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13970 // If a reduction clause is present on the taskloop directive, the nogroup
13971 // clause must not be specified.
13972 if (checkReductionClauseWithNogroup(*this, Clauses))
13973 return StmtError();
13975 setFunctionHasBranchProtectedScope();
13976 return OMPParallelMaskedTaskLoopDirective::Create(
13977 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13978 DSAStack->isCancelRegion());
13981 StmtResult Sema::ActOnOpenMPParallelMasterTaskLoopSimdDirective(
13982 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13983 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13984 if (!AStmt)
13985 return StmtError();
13987 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13988 auto *CS = cast<CapturedStmt>(AStmt);
13989 // 1.2.2 OpenMP Language Terminology
13990 // Structured block - An executable statement with a single entry at the
13991 // top and a single exit at the bottom.
13992 // The point of exit cannot be a branch out of the structured block.
13993 // longjmp() and throw() must not violate the entry/exit criteria.
13994 CS->getCapturedDecl()->setNothrow();
13995 for (int ThisCaptureLevel =
13996 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop_simd);
13997 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13998 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13999 // 1.2.2 OpenMP Language Terminology
14000 // Structured block - An executable statement with a single entry at the
14001 // top and a single exit at the bottom.
14002 // The point of exit cannot be a branch out of the structured block.
14003 // longjmp() and throw() must not violate the entry/exit criteria.
14004 CS->getCapturedDecl()->setNothrow();
14007 OMPLoopBasedDirective::HelperExprs B;
14008 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14009 // define the nested loops number.
14010 unsigned NestedLoopCount = checkOpenMPLoop(
14011 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
14012 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
14013 VarsWithImplicitDSA, B);
14014 if (NestedLoopCount == 0)
14015 return StmtError();
14017 assert((CurContext->isDependentContext() || B.builtAll()) &&
14018 "omp for loop exprs were not built");
14020 if (!CurContext->isDependentContext()) {
14021 // Finalize the clauses that need pre-built expressions for CodeGen.
14022 for (OMPClause *C : Clauses) {
14023 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14024 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14025 B.NumIterations, *this, CurScope,
14026 DSAStack))
14027 return StmtError();
14031 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14032 // The grainsize clause and num_tasks clause are mutually exclusive and may
14033 // not appear on the same taskloop directive.
14034 if (checkMutuallyExclusiveClauses(*this, Clauses,
14035 {OMPC_grainsize, OMPC_num_tasks}))
14036 return StmtError();
14037 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14038 // If a reduction clause is present on the taskloop directive, the nogroup
14039 // clause must not be specified.
14040 if (checkReductionClauseWithNogroup(*this, Clauses))
14041 return StmtError();
14042 if (checkSimdlenSafelenSpecified(*this, Clauses))
14043 return StmtError();
14045 setFunctionHasBranchProtectedScope();
14046 return OMPParallelMasterTaskLoopSimdDirective::Create(
14047 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14050 StmtResult Sema::ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
14051 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14052 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14053 if (!AStmt)
14054 return StmtError();
14056 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14057 auto *CS = cast<CapturedStmt>(AStmt);
14058 // 1.2.2 OpenMP Language Terminology
14059 // Structured block - An executable statement with a single entry at the
14060 // top and a single exit at the bottom.
14061 // The point of exit cannot be a branch out of the structured block.
14062 // longjmp() and throw() must not violate the entry/exit criteria.
14063 CS->getCapturedDecl()->setNothrow();
14064 for (int ThisCaptureLevel =
14065 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop_simd);
14066 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14067 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14068 // 1.2.2 OpenMP Language Terminology
14069 // Structured block - An executable statement with a single entry at the
14070 // top and a single exit at the bottom.
14071 // The point of exit cannot be a branch out of the structured block.
14072 // longjmp() and throw() must not violate the entry/exit criteria.
14073 CS->getCapturedDecl()->setNothrow();
14076 OMPLoopBasedDirective::HelperExprs B;
14077 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14078 // define the nested loops number.
14079 unsigned NestedLoopCount = checkOpenMPLoop(
14080 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
14081 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
14082 VarsWithImplicitDSA, B);
14083 if (NestedLoopCount == 0)
14084 return StmtError();
14086 assert((CurContext->isDependentContext() || B.builtAll()) &&
14087 "omp for loop exprs were not built");
14089 if (!CurContext->isDependentContext()) {
14090 // Finalize the clauses that need pre-built expressions for CodeGen.
14091 for (OMPClause *C : Clauses) {
14092 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14093 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14094 B.NumIterations, *this, CurScope,
14095 DSAStack))
14096 return StmtError();
14100 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14101 // The grainsize clause and num_tasks clause are mutually exclusive and may
14102 // not appear on the same taskloop directive.
14103 if (checkMutuallyExclusiveClauses(*this, Clauses,
14104 {OMPC_grainsize, OMPC_num_tasks}))
14105 return StmtError();
14106 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14107 // If a reduction clause is present on the taskloop directive, the nogroup
14108 // clause must not be specified.
14109 if (checkReductionClauseWithNogroup(*this, Clauses))
14110 return StmtError();
14111 if (checkSimdlenSafelenSpecified(*this, Clauses))
14112 return StmtError();
14114 setFunctionHasBranchProtectedScope();
14115 return OMPParallelMaskedTaskLoopSimdDirective::Create(
14116 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14119 StmtResult Sema::ActOnOpenMPDistributeDirective(
14120 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14121 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14122 if (!AStmt)
14123 return StmtError();
14125 if (!checkLastPrivateForMappedDirectives(Clauses))
14126 return StmtError();
14128 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14129 OMPLoopBasedDirective::HelperExprs B;
14130 // In presence of clause 'collapse' with number of loops, it will
14131 // define the nested loops number.
14132 unsigned NestedLoopCount =
14133 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
14134 nullptr /*ordered not a clause on distribute*/, AStmt,
14135 *this, *DSAStack, VarsWithImplicitDSA, B);
14136 if (NestedLoopCount == 0)
14137 return StmtError();
14139 assert((CurContext->isDependentContext() || B.builtAll()) &&
14140 "omp for loop exprs were not built");
14142 setFunctionHasBranchProtectedScope();
14143 auto *DistributeDirective = OMPDistributeDirective::Create(
14144 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14145 DSAStack->getMappedDirective());
14146 return DistributeDirective;
14149 StmtResult Sema::ActOnOpenMPDistributeParallelForDirective(
14150 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14151 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14152 if (!AStmt)
14153 return StmtError();
14155 auto *CS = cast<CapturedStmt>(AStmt);
14156 // 1.2.2 OpenMP Language Terminology
14157 // Structured block - An executable statement with a single entry at the
14158 // top and a single exit at the bottom.
14159 // The point of exit cannot be a branch out of the structured block.
14160 // longjmp() and throw() must not violate the entry/exit criteria.
14161 CS->getCapturedDecl()->setNothrow();
14162 for (int ThisCaptureLevel =
14163 getOpenMPCaptureLevels(OMPD_distribute_parallel_for);
14164 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14165 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14166 // 1.2.2 OpenMP Language Terminology
14167 // Structured block - An executable statement with a single entry at the
14168 // top and a single exit at the bottom.
14169 // The point of exit cannot be a branch out of the structured block.
14170 // longjmp() and throw() must not violate the entry/exit criteria.
14171 CS->getCapturedDecl()->setNothrow();
14174 OMPLoopBasedDirective::HelperExprs B;
14175 // In presence of clause 'collapse' with number of loops, it will
14176 // define the nested loops number.
14177 unsigned NestedLoopCount = checkOpenMPLoop(
14178 OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14179 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14180 VarsWithImplicitDSA, B);
14181 if (NestedLoopCount == 0)
14182 return StmtError();
14184 assert((CurContext->isDependentContext() || B.builtAll()) &&
14185 "omp for loop exprs were not built");
14187 setFunctionHasBranchProtectedScope();
14188 return OMPDistributeParallelForDirective::Create(
14189 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14190 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14193 StmtResult Sema::ActOnOpenMPDistributeParallelForSimdDirective(
14194 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14195 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14196 if (!AStmt)
14197 return StmtError();
14199 auto *CS = cast<CapturedStmt>(AStmt);
14200 // 1.2.2 OpenMP Language Terminology
14201 // Structured block - An executable statement with a single entry at the
14202 // top and a single exit at the bottom.
14203 // The point of exit cannot be a branch out of the structured block.
14204 // longjmp() and throw() must not violate the entry/exit criteria.
14205 CS->getCapturedDecl()->setNothrow();
14206 for (int ThisCaptureLevel =
14207 getOpenMPCaptureLevels(OMPD_distribute_parallel_for_simd);
14208 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14209 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14210 // 1.2.2 OpenMP Language Terminology
14211 // Structured block - An executable statement with a single entry at the
14212 // top and a single exit at the bottom.
14213 // The point of exit cannot be a branch out of the structured block.
14214 // longjmp() and throw() must not violate the entry/exit criteria.
14215 CS->getCapturedDecl()->setNothrow();
14218 OMPLoopBasedDirective::HelperExprs B;
14219 // In presence of clause 'collapse' with number of loops, it will
14220 // define the nested loops number.
14221 unsigned NestedLoopCount = checkOpenMPLoop(
14222 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14223 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14224 VarsWithImplicitDSA, B);
14225 if (NestedLoopCount == 0)
14226 return StmtError();
14228 assert((CurContext->isDependentContext() || B.builtAll()) &&
14229 "omp for loop exprs were not built");
14231 if (!CurContext->isDependentContext()) {
14232 // Finalize the clauses that need pre-built expressions for CodeGen.
14233 for (OMPClause *C : Clauses) {
14234 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14235 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14236 B.NumIterations, *this, CurScope,
14237 DSAStack))
14238 return StmtError();
14242 if (checkSimdlenSafelenSpecified(*this, Clauses))
14243 return StmtError();
14245 setFunctionHasBranchProtectedScope();
14246 return OMPDistributeParallelForSimdDirective::Create(
14247 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14250 StmtResult Sema::ActOnOpenMPDistributeSimdDirective(
14251 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14252 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14253 if (!AStmt)
14254 return StmtError();
14256 auto *CS = cast<CapturedStmt>(AStmt);
14257 // 1.2.2 OpenMP Language Terminology
14258 // Structured block - An executable statement with a single entry at the
14259 // top and a single exit at the bottom.
14260 // The point of exit cannot be a branch out of the structured block.
14261 // longjmp() and throw() must not violate the entry/exit criteria.
14262 CS->getCapturedDecl()->setNothrow();
14263 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_distribute_simd);
14264 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14265 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14266 // 1.2.2 OpenMP Language Terminology
14267 // Structured block - An executable statement with a single entry at the
14268 // top and a single exit at the bottom.
14269 // The point of exit cannot be a branch out of the structured block.
14270 // longjmp() and throw() must not violate the entry/exit criteria.
14271 CS->getCapturedDecl()->setNothrow();
14274 OMPLoopBasedDirective::HelperExprs B;
14275 // In presence of clause 'collapse' with number of loops, it will
14276 // define the nested loops number.
14277 unsigned NestedLoopCount =
14278 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
14279 nullptr /*ordered not a clause on distribute*/, CS, *this,
14280 *DSAStack, VarsWithImplicitDSA, B);
14281 if (NestedLoopCount == 0)
14282 return StmtError();
14284 assert((CurContext->isDependentContext() || B.builtAll()) &&
14285 "omp for loop exprs were not built");
14287 if (!CurContext->isDependentContext()) {
14288 // Finalize the clauses that need pre-built expressions for CodeGen.
14289 for (OMPClause *C : Clauses) {
14290 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14291 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14292 B.NumIterations, *this, CurScope,
14293 DSAStack))
14294 return StmtError();
14298 if (checkSimdlenSafelenSpecified(*this, Clauses))
14299 return StmtError();
14301 setFunctionHasBranchProtectedScope();
14302 return OMPDistributeSimdDirective::Create(Context, StartLoc, EndLoc,
14303 NestedLoopCount, Clauses, AStmt, B);
14306 StmtResult Sema::ActOnOpenMPTargetParallelForSimdDirective(
14307 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14308 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14309 if (!AStmt)
14310 return StmtError();
14312 auto *CS = cast<CapturedStmt>(AStmt);
14313 // 1.2.2 OpenMP Language Terminology
14314 // Structured block - An executable statement with a single entry at the
14315 // top and a single exit at the bottom.
14316 // The point of exit cannot be a branch out of the structured block.
14317 // longjmp() and throw() must not violate the entry/exit criteria.
14318 CS->getCapturedDecl()->setNothrow();
14319 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_for);
14320 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14321 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14322 // 1.2.2 OpenMP Language Terminology
14323 // Structured block - An executable statement with a single entry at the
14324 // top and a single exit at the bottom.
14325 // The point of exit cannot be a branch out of the structured block.
14326 // longjmp() and throw() must not violate the entry/exit criteria.
14327 CS->getCapturedDecl()->setNothrow();
14330 OMPLoopBasedDirective::HelperExprs B;
14331 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14332 // define the nested loops number.
14333 unsigned NestedLoopCount = checkOpenMPLoop(
14334 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
14335 getOrderedNumberExpr(Clauses), CS, *this, *DSAStack, VarsWithImplicitDSA,
14337 if (NestedLoopCount == 0)
14338 return StmtError();
14340 assert((CurContext->isDependentContext() || B.builtAll()) &&
14341 "omp target parallel for simd loop exprs were not built");
14343 if (!CurContext->isDependentContext()) {
14344 // Finalize the clauses that need pre-built expressions for CodeGen.
14345 for (OMPClause *C : Clauses) {
14346 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14347 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14348 B.NumIterations, *this, CurScope,
14349 DSAStack))
14350 return StmtError();
14353 if (checkSimdlenSafelenSpecified(*this, Clauses))
14354 return StmtError();
14356 setFunctionHasBranchProtectedScope();
14357 return OMPTargetParallelForSimdDirective::Create(
14358 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14361 StmtResult Sema::ActOnOpenMPTargetSimdDirective(
14362 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14363 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14364 if (!AStmt)
14365 return StmtError();
14367 auto *CS = cast<CapturedStmt>(AStmt);
14368 // 1.2.2 OpenMP Language Terminology
14369 // Structured block - An executable statement with a single entry at the
14370 // top and a single exit at the bottom.
14371 // The point of exit cannot be a branch out of the structured block.
14372 // longjmp() and throw() must not violate the entry/exit criteria.
14373 CS->getCapturedDecl()->setNothrow();
14374 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_simd);
14375 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14376 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14377 // 1.2.2 OpenMP Language Terminology
14378 // Structured block - An executable statement with a single entry at the
14379 // top and a single exit at the bottom.
14380 // The point of exit cannot be a branch out of the structured block.
14381 // longjmp() and throw() must not violate the entry/exit criteria.
14382 CS->getCapturedDecl()->setNothrow();
14385 OMPLoopBasedDirective::HelperExprs B;
14386 // In presence of clause 'collapse' with number of loops, it will define the
14387 // nested loops number.
14388 unsigned NestedLoopCount =
14389 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
14390 getOrderedNumberExpr(Clauses), CS, *this, *DSAStack,
14391 VarsWithImplicitDSA, B);
14392 if (NestedLoopCount == 0)
14393 return StmtError();
14395 assert((CurContext->isDependentContext() || B.builtAll()) &&
14396 "omp target simd loop exprs were not built");
14398 if (!CurContext->isDependentContext()) {
14399 // Finalize the clauses that need pre-built expressions for CodeGen.
14400 for (OMPClause *C : Clauses) {
14401 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14402 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14403 B.NumIterations, *this, CurScope,
14404 DSAStack))
14405 return StmtError();
14409 if (checkSimdlenSafelenSpecified(*this, Clauses))
14410 return StmtError();
14412 setFunctionHasBranchProtectedScope();
14413 return OMPTargetSimdDirective::Create(Context, StartLoc, EndLoc,
14414 NestedLoopCount, Clauses, AStmt, B);
14417 StmtResult Sema::ActOnOpenMPTeamsDistributeDirective(
14418 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14419 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14420 if (!AStmt)
14421 return StmtError();
14423 auto *CS = cast<CapturedStmt>(AStmt);
14424 // 1.2.2 OpenMP Language Terminology
14425 // Structured block - An executable statement with a single entry at the
14426 // top and a single exit at the bottom.
14427 // The point of exit cannot be a branch out of the structured block.
14428 // longjmp() and throw() must not violate the entry/exit criteria.
14429 CS->getCapturedDecl()->setNothrow();
14430 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_teams_distribute);
14431 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14432 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14433 // 1.2.2 OpenMP Language Terminology
14434 // Structured block - An executable statement with a single entry at the
14435 // top and a single exit at the bottom.
14436 // The point of exit cannot be a branch out of the structured block.
14437 // longjmp() and throw() must not violate the entry/exit criteria.
14438 CS->getCapturedDecl()->setNothrow();
14441 OMPLoopBasedDirective::HelperExprs B;
14442 // In presence of clause 'collapse' with number of loops, it will
14443 // define the nested loops number.
14444 unsigned NestedLoopCount =
14445 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
14446 nullptr /*ordered not a clause on distribute*/, CS, *this,
14447 *DSAStack, VarsWithImplicitDSA, B);
14448 if (NestedLoopCount == 0)
14449 return StmtError();
14451 assert((CurContext->isDependentContext() || B.builtAll()) &&
14452 "omp teams distribute loop exprs were not built");
14454 setFunctionHasBranchProtectedScope();
14456 DSAStack->setParentTeamsRegionLoc(StartLoc);
14458 return OMPTeamsDistributeDirective::Create(
14459 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14462 StmtResult Sema::ActOnOpenMPTeamsDistributeSimdDirective(
14463 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14464 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14465 if (!AStmt)
14466 return StmtError();
14468 auto *CS = cast<CapturedStmt>(AStmt);
14469 // 1.2.2 OpenMP Language Terminology
14470 // Structured block - An executable statement with a single entry at the
14471 // top and a single exit at the bottom.
14472 // The point of exit cannot be a branch out of the structured block.
14473 // longjmp() and throw() must not violate the entry/exit criteria.
14474 CS->getCapturedDecl()->setNothrow();
14475 for (int ThisCaptureLevel =
14476 getOpenMPCaptureLevels(OMPD_teams_distribute_simd);
14477 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14478 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14479 // 1.2.2 OpenMP Language Terminology
14480 // Structured block - An executable statement with a single entry at the
14481 // top and a single exit at the bottom.
14482 // The point of exit cannot be a branch out of the structured block.
14483 // longjmp() and throw() must not violate the entry/exit criteria.
14484 CS->getCapturedDecl()->setNothrow();
14487 OMPLoopBasedDirective::HelperExprs B;
14488 // In presence of clause 'collapse' with number of loops, it will
14489 // define the nested loops number.
14490 unsigned NestedLoopCount = checkOpenMPLoop(
14491 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14492 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14493 VarsWithImplicitDSA, B);
14495 if (NestedLoopCount == 0)
14496 return StmtError();
14498 assert((CurContext->isDependentContext() || B.builtAll()) &&
14499 "omp teams distribute simd loop exprs were not built");
14501 if (!CurContext->isDependentContext()) {
14502 // Finalize the clauses that need pre-built expressions for CodeGen.
14503 for (OMPClause *C : Clauses) {
14504 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14505 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14506 B.NumIterations, *this, CurScope,
14507 DSAStack))
14508 return StmtError();
14512 if (checkSimdlenSafelenSpecified(*this, Clauses))
14513 return StmtError();
14515 setFunctionHasBranchProtectedScope();
14517 DSAStack->setParentTeamsRegionLoc(StartLoc);
14519 return OMPTeamsDistributeSimdDirective::Create(
14520 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14523 StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
14524 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14525 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14526 if (!AStmt)
14527 return StmtError();
14529 auto *CS = cast<CapturedStmt>(AStmt);
14530 // 1.2.2 OpenMP Language Terminology
14531 // Structured block - An executable statement with a single entry at the
14532 // top and a single exit at the bottom.
14533 // The point of exit cannot be a branch out of the structured block.
14534 // longjmp() and throw() must not violate the entry/exit criteria.
14535 CS->getCapturedDecl()->setNothrow();
14537 for (int ThisCaptureLevel =
14538 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for_simd);
14539 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14540 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14541 // 1.2.2 OpenMP Language Terminology
14542 // Structured block - An executable statement with a single entry at the
14543 // top and a single exit at the bottom.
14544 // The point of exit cannot be a branch out of the structured block.
14545 // longjmp() and throw() must not violate the entry/exit criteria.
14546 CS->getCapturedDecl()->setNothrow();
14549 OMPLoopBasedDirective::HelperExprs B;
14550 // In presence of clause 'collapse' with number of loops, it will
14551 // define the nested loops number.
14552 unsigned NestedLoopCount = checkOpenMPLoop(
14553 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14554 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14555 VarsWithImplicitDSA, B);
14557 if (NestedLoopCount == 0)
14558 return StmtError();
14560 assert((CurContext->isDependentContext() || B.builtAll()) &&
14561 "omp for loop exprs were not built");
14563 if (!CurContext->isDependentContext()) {
14564 // Finalize the clauses that need pre-built expressions for CodeGen.
14565 for (OMPClause *C : Clauses) {
14566 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14567 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14568 B.NumIterations, *this, CurScope,
14569 DSAStack))
14570 return StmtError();
14574 if (checkSimdlenSafelenSpecified(*this, Clauses))
14575 return StmtError();
14577 setFunctionHasBranchProtectedScope();
14579 DSAStack->setParentTeamsRegionLoc(StartLoc);
14581 return OMPTeamsDistributeParallelForSimdDirective::Create(
14582 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14585 StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForDirective(
14586 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14587 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14588 if (!AStmt)
14589 return StmtError();
14591 auto *CS = cast<CapturedStmt>(AStmt);
14592 // 1.2.2 OpenMP Language Terminology
14593 // Structured block - An executable statement with a single entry at the
14594 // top and a single exit at the bottom.
14595 // The point of exit cannot be a branch out of the structured block.
14596 // longjmp() and throw() must not violate the entry/exit criteria.
14597 CS->getCapturedDecl()->setNothrow();
14599 for (int ThisCaptureLevel =
14600 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for);
14601 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14602 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14603 // 1.2.2 OpenMP Language Terminology
14604 // Structured block - An executable statement with a single entry at the
14605 // top and a single exit at the bottom.
14606 // The point of exit cannot be a branch out of the structured block.
14607 // longjmp() and throw() must not violate the entry/exit criteria.
14608 CS->getCapturedDecl()->setNothrow();
14611 OMPLoopBasedDirective::HelperExprs B;
14612 // In presence of clause 'collapse' with number of loops, it will
14613 // define the nested loops number.
14614 unsigned NestedLoopCount = checkOpenMPLoop(
14615 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14616 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14617 VarsWithImplicitDSA, B);
14619 if (NestedLoopCount == 0)
14620 return StmtError();
14622 assert((CurContext->isDependentContext() || B.builtAll()) &&
14623 "omp for loop exprs were not built");
14625 setFunctionHasBranchProtectedScope();
14627 DSAStack->setParentTeamsRegionLoc(StartLoc);
14629 return OMPTeamsDistributeParallelForDirective::Create(
14630 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14631 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14634 StmtResult Sema::ActOnOpenMPTargetTeamsDirective(ArrayRef<OMPClause *> Clauses,
14635 Stmt *AStmt,
14636 SourceLocation StartLoc,
14637 SourceLocation EndLoc) {
14638 if (!AStmt)
14639 return StmtError();
14641 auto *CS = cast<CapturedStmt>(AStmt);
14642 // 1.2.2 OpenMP Language Terminology
14643 // Structured block - An executable statement with a single entry at the
14644 // top and a single exit at the bottom.
14645 // The point of exit cannot be a branch out of the structured block.
14646 // longjmp() and throw() must not violate the entry/exit criteria.
14647 CS->getCapturedDecl()->setNothrow();
14649 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_teams);
14650 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14651 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14652 // 1.2.2 OpenMP Language Terminology
14653 // Structured block - An executable statement with a single entry at the
14654 // top and a single exit at the bottom.
14655 // The point of exit cannot be a branch out of the structured block.
14656 // longjmp() and throw() must not violate the entry/exit criteria.
14657 CS->getCapturedDecl()->setNothrow();
14659 setFunctionHasBranchProtectedScope();
14661 const OMPClause *BareClause = nullptr;
14662 bool HasThreadLimitAndNumTeamsClause = hasClauses(Clauses, OMPC_num_teams) &&
14663 hasClauses(Clauses, OMPC_thread_limit);
14664 bool HasBareClause = llvm::any_of(Clauses, [&](const OMPClause *C) {
14665 BareClause = C;
14666 return C->getClauseKind() == OMPC_ompx_bare;
14669 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
14670 Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid);
14671 return StmtError();
14674 return OMPTargetTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses,
14675 AStmt);
14678 StmtResult Sema::ActOnOpenMPTargetTeamsDistributeDirective(
14679 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14680 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14681 if (!AStmt)
14682 return StmtError();
14684 auto *CS = cast<CapturedStmt>(AStmt);
14685 // 1.2.2 OpenMP Language Terminology
14686 // Structured block - An executable statement with a single entry at the
14687 // top and a single exit at the bottom.
14688 // The point of exit cannot be a branch out of the structured block.
14689 // longjmp() and throw() must not violate the entry/exit criteria.
14690 CS->getCapturedDecl()->setNothrow();
14691 for (int ThisCaptureLevel =
14692 getOpenMPCaptureLevels(OMPD_target_teams_distribute);
14693 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14694 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14695 // 1.2.2 OpenMP Language Terminology
14696 // Structured block - An executable statement with a single entry at the
14697 // top and a single exit at the bottom.
14698 // The point of exit cannot be a branch out of the structured block.
14699 // longjmp() and throw() must not violate the entry/exit criteria.
14700 CS->getCapturedDecl()->setNothrow();
14703 OMPLoopBasedDirective::HelperExprs B;
14704 // In presence of clause 'collapse' with number of loops, it will
14705 // define the nested loops number.
14706 unsigned NestedLoopCount = checkOpenMPLoop(
14707 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
14708 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14709 VarsWithImplicitDSA, B);
14710 if (NestedLoopCount == 0)
14711 return StmtError();
14713 assert((CurContext->isDependentContext() || B.builtAll()) &&
14714 "omp target teams distribute loop exprs were not built");
14716 setFunctionHasBranchProtectedScope();
14717 return OMPTargetTeamsDistributeDirective::Create(
14718 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14721 StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForDirective(
14722 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14723 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14724 if (!AStmt)
14725 return StmtError();
14727 auto *CS = cast<CapturedStmt>(AStmt);
14728 // 1.2.2 OpenMP Language Terminology
14729 // Structured block - An executable statement with a single entry at the
14730 // top and a single exit at the bottom.
14731 // The point of exit cannot be a branch out of the structured block.
14732 // longjmp() and throw() must not violate the entry/exit criteria.
14733 CS->getCapturedDecl()->setNothrow();
14734 for (int ThisCaptureLevel =
14735 getOpenMPCaptureLevels(OMPD_target_teams_distribute_parallel_for);
14736 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14737 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14738 // 1.2.2 OpenMP Language Terminology
14739 // Structured block - An executable statement with a single entry at the
14740 // top and a single exit at the bottom.
14741 // The point of exit cannot be a branch out of the structured block.
14742 // longjmp() and throw() must not violate the entry/exit criteria.
14743 CS->getCapturedDecl()->setNothrow();
14746 OMPLoopBasedDirective::HelperExprs B;
14747 // In presence of clause 'collapse' with number of loops, it will
14748 // define the nested loops number.
14749 unsigned NestedLoopCount = checkOpenMPLoop(
14750 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14751 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14752 VarsWithImplicitDSA, B);
14753 if (NestedLoopCount == 0)
14754 return StmtError();
14756 assert((CurContext->isDependentContext() || B.builtAll()) &&
14757 "omp target teams distribute parallel for loop exprs were not built");
14759 if (!CurContext->isDependentContext()) {
14760 // Finalize the clauses that need pre-built expressions for CodeGen.
14761 for (OMPClause *C : Clauses) {
14762 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14763 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14764 B.NumIterations, *this, CurScope,
14765 DSAStack))
14766 return StmtError();
14770 setFunctionHasBranchProtectedScope();
14771 return OMPTargetTeamsDistributeParallelForDirective::Create(
14772 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14773 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14776 StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
14777 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14778 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14779 if (!AStmt)
14780 return StmtError();
14782 auto *CS = cast<CapturedStmt>(AStmt);
14783 // 1.2.2 OpenMP Language Terminology
14784 // Structured block - An executable statement with a single entry at the
14785 // top and a single exit at the bottom.
14786 // The point of exit cannot be a branch out of the structured block.
14787 // longjmp() and throw() must not violate the entry/exit criteria.
14788 CS->getCapturedDecl()->setNothrow();
14789 for (int ThisCaptureLevel = getOpenMPCaptureLevels(
14790 OMPD_target_teams_distribute_parallel_for_simd);
14791 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14792 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14793 // 1.2.2 OpenMP Language Terminology
14794 // Structured block - An executable statement with a single entry at the
14795 // top and a single exit at the bottom.
14796 // The point of exit cannot be a branch out of the structured block.
14797 // longjmp() and throw() must not violate the entry/exit criteria.
14798 CS->getCapturedDecl()->setNothrow();
14801 OMPLoopBasedDirective::HelperExprs B;
14802 // In presence of clause 'collapse' with number of loops, it will
14803 // define the nested loops number.
14804 unsigned NestedLoopCount =
14805 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
14806 getCollapseNumberExpr(Clauses),
14807 nullptr /*ordered not a clause on distribute*/, CS, *this,
14808 *DSAStack, VarsWithImplicitDSA, B);
14809 if (NestedLoopCount == 0)
14810 return StmtError();
14812 assert((CurContext->isDependentContext() || B.builtAll()) &&
14813 "omp target teams distribute parallel for simd loop exprs were not "
14814 "built");
14816 if (!CurContext->isDependentContext()) {
14817 // Finalize the clauses that need pre-built expressions for CodeGen.
14818 for (OMPClause *C : Clauses) {
14819 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14820 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14821 B.NumIterations, *this, CurScope,
14822 DSAStack))
14823 return StmtError();
14827 if (checkSimdlenSafelenSpecified(*this, Clauses))
14828 return StmtError();
14830 setFunctionHasBranchProtectedScope();
14831 return OMPTargetTeamsDistributeParallelForSimdDirective::Create(
14832 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14835 StmtResult Sema::ActOnOpenMPTargetTeamsDistributeSimdDirective(
14836 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14837 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14838 if (!AStmt)
14839 return StmtError();
14841 auto *CS = cast<CapturedStmt>(AStmt);
14842 // 1.2.2 OpenMP Language Terminology
14843 // Structured block - An executable statement with a single entry at the
14844 // top and a single exit at the bottom.
14845 // The point of exit cannot be a branch out of the structured block.
14846 // longjmp() and throw() must not violate the entry/exit criteria.
14847 CS->getCapturedDecl()->setNothrow();
14848 for (int ThisCaptureLevel =
14849 getOpenMPCaptureLevels(OMPD_target_teams_distribute_simd);
14850 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14851 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14852 // 1.2.2 OpenMP Language Terminology
14853 // Structured block - An executable statement with a single entry at the
14854 // top and a single exit at the bottom.
14855 // The point of exit cannot be a branch out of the structured block.
14856 // longjmp() and throw() must not violate the entry/exit criteria.
14857 CS->getCapturedDecl()->setNothrow();
14860 OMPLoopBasedDirective::HelperExprs B;
14861 // In presence of clause 'collapse' with number of loops, it will
14862 // define the nested loops number.
14863 unsigned NestedLoopCount = checkOpenMPLoop(
14864 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14865 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14866 VarsWithImplicitDSA, B);
14867 if (NestedLoopCount == 0)
14868 return StmtError();
14870 assert((CurContext->isDependentContext() || B.builtAll()) &&
14871 "omp target teams distribute simd loop exprs were not built");
14873 if (!CurContext->isDependentContext()) {
14874 // Finalize the clauses that need pre-built expressions for CodeGen.
14875 for (OMPClause *C : Clauses) {
14876 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14877 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14878 B.NumIterations, *this, CurScope,
14879 DSAStack))
14880 return StmtError();
14884 if (checkSimdlenSafelenSpecified(*this, Clauses))
14885 return StmtError();
14887 setFunctionHasBranchProtectedScope();
14888 return OMPTargetTeamsDistributeSimdDirective::Create(
14889 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14892 bool Sema::checkTransformableLoopNest(
14893 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14894 SmallVectorImpl<OMPLoopBasedDirective::HelperExprs> &LoopHelpers,
14895 Stmt *&Body,
14896 SmallVectorImpl<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>>
14897 &OriginalInits) {
14898 OriginalInits.emplace_back();
14899 bool Result = OMPLoopBasedDirective::doForAllLoops(
14900 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14901 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14902 Stmt *CurStmt) {
14903 VarsWithInheritedDSAType TmpDSA;
14904 unsigned SingleNumLoops =
14905 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, *this, *DSAStack,
14906 TmpDSA, LoopHelpers[Cnt]);
14907 if (SingleNumLoops == 0)
14908 return true;
14909 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14910 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14911 OriginalInits.back().push_back(For->getInit());
14912 Body = For->getBody();
14913 } else {
14914 assert(isa<CXXForRangeStmt>(CurStmt) &&
14915 "Expected canonical for or range-based for loops.");
14916 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14917 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14918 Body = CXXFor->getBody();
14920 OriginalInits.emplace_back();
14921 return false;
14923 [&OriginalInits](OMPLoopBasedDirective *Transform) {
14924 Stmt *DependentPreInits;
14925 if (auto *Dir = dyn_cast<OMPTileDirective>(Transform))
14926 DependentPreInits = Dir->getPreInits();
14927 else if (auto *Dir = dyn_cast<OMPUnrollDirective>(Transform))
14928 DependentPreInits = Dir->getPreInits();
14929 else
14930 llvm_unreachable("Unhandled loop transformation");
14931 if (!DependentPreInits)
14932 return;
14933 llvm::append_range(OriginalInits.back(),
14934 cast<DeclStmt>(DependentPreInits)->getDeclGroup());
14936 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14937 OriginalInits.pop_back();
14938 return Result;
14941 StmtResult Sema::ActOnOpenMPTileDirective(ArrayRef<OMPClause *> Clauses,
14942 Stmt *AStmt, SourceLocation StartLoc,
14943 SourceLocation EndLoc) {
14944 auto SizesClauses =
14945 OMPExecutableDirective::getClausesOfKind<OMPSizesClause>(Clauses);
14946 if (SizesClauses.empty()) {
14947 // A missing 'sizes' clause is already reported by the parser.
14948 return StmtError();
14950 const OMPSizesClause *SizesClause = *SizesClauses.begin();
14951 unsigned NumLoops = SizesClause->getNumSizes();
14953 // Empty statement should only be possible if there already was an error.
14954 if (!AStmt)
14955 return StmtError();
14957 // Verify and diagnose loop nest.
14958 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
14959 Stmt *Body = nullptr;
14960 SmallVector<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>, 4>
14961 OriginalInits;
14962 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14963 OriginalInits))
14964 return StmtError();
14966 // Delay tiling to when template is completely instantiated.
14967 if (CurContext->isDependentContext())
14968 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
14969 NumLoops, AStmt, nullptr, nullptr);
14971 SmallVector<Decl *, 4> PreInits;
14973 // Create iteration variables for the generated loops.
14974 SmallVector<VarDecl *, 4> FloorIndVars;
14975 SmallVector<VarDecl *, 4> TileIndVars;
14976 FloorIndVars.resize(NumLoops);
14977 TileIndVars.resize(NumLoops);
14978 for (unsigned I = 0; I < NumLoops; ++I) {
14979 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14981 assert(LoopHelper.Counters.size() == 1 &&
14982 "Expect single-dimensional loop iteration space");
14983 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14984 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14985 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14986 QualType CntTy = IterVarRef->getType();
14988 // Iteration variable for the floor (i.e. outer) loop.
14990 std::string FloorCntName =
14991 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14992 VarDecl *FloorCntDecl =
14993 buildVarDecl(*this, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
14994 FloorIndVars[I] = FloorCntDecl;
14997 // Iteration variable for the tile (i.e. inner) loop.
14999 std::string TileCntName =
15000 (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
15002 // Reuse the iteration variable created by checkOpenMPLoop. It is also
15003 // used by the expressions to derive the original iteration variable's
15004 // value from the logical iteration number.
15005 auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
15006 TileCntDecl->setDeclName(&PP.getIdentifierTable().get(TileCntName));
15007 TileIndVars[I] = TileCntDecl;
15009 for (auto &P : OriginalInits[I]) {
15010 if (auto *D = P.dyn_cast<Decl *>())
15011 PreInits.push_back(D);
15012 else if (auto *PI = dyn_cast_or_null<DeclStmt>(P.dyn_cast<Stmt *>()))
15013 PreInits.append(PI->decl_begin(), PI->decl_end());
15015 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits))
15016 PreInits.append(PI->decl_begin(), PI->decl_end());
15017 // Gather declarations for the data members used as counters.
15018 for (Expr *CounterRef : LoopHelper.Counters) {
15019 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
15020 if (isa<OMPCapturedExprDecl>(CounterDecl))
15021 PreInits.push_back(CounterDecl);
15025 // Once the original iteration values are set, append the innermost body.
15026 Stmt *Inner = Body;
15028 // Create tile loops from the inside to the outside.
15029 for (int I = NumLoops - 1; I >= 0; --I) {
15030 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15031 Expr *NumIterations = LoopHelper.NumIterations;
15032 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15033 QualType CntTy = OrigCntVar->getType();
15034 Expr *DimTileSize = SizesClause->getSizesRefs()[I];
15035 Scope *CurScope = getCurScope();
15037 // Commonly used variables.
15038 DeclRefExpr *TileIV = buildDeclRefExpr(*this, TileIndVars[I], CntTy,
15039 OrigCntVar->getExprLoc());
15040 DeclRefExpr *FloorIV = buildDeclRefExpr(*this, FloorIndVars[I], CntTy,
15041 OrigCntVar->getExprLoc());
15043 // For init-statement: auto .tile.iv = .floor.iv
15044 AddInitializerToDecl(TileIndVars[I], DefaultLvalueConversion(FloorIV).get(),
15045 /*DirectInit=*/false);
15046 Decl *CounterDecl = TileIndVars[I];
15047 StmtResult InitStmt = new (Context)
15048 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15049 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15050 if (!InitStmt.isUsable())
15051 return StmtError();
15053 // For cond-expression: .tile.iv < min(.floor.iv + DimTileSize,
15054 // NumIterations)
15055 ExprResult EndOfTile = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
15056 BO_Add, FloorIV, DimTileSize);
15057 if (!EndOfTile.isUsable())
15058 return StmtError();
15059 ExprResult IsPartialTile =
15060 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15061 NumIterations, EndOfTile.get());
15062 if (!IsPartialTile.isUsable())
15063 return StmtError();
15064 ExprResult MinTileAndIterSpace = ActOnConditionalOp(
15065 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
15066 IsPartialTile.get(), NumIterations, EndOfTile.get());
15067 if (!MinTileAndIterSpace.isUsable())
15068 return StmtError();
15069 ExprResult CondExpr = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
15070 BO_LT, TileIV, MinTileAndIterSpace.get());
15071 if (!CondExpr.isUsable())
15072 return StmtError();
15074 // For incr-statement: ++.tile.iv
15075 ExprResult IncrStmt =
15076 BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, TileIV);
15077 if (!IncrStmt.isUsable())
15078 return StmtError();
15080 // Statements to set the original iteration variable's value from the
15081 // logical iteration number.
15082 // Generated for loop is:
15083 // Original_for_init;
15084 // for (auto .tile.iv = .floor.iv; .tile.iv < min(.floor.iv + DimTileSize,
15085 // NumIterations); ++.tile.iv) {
15086 // Original_Body;
15087 // Original_counter_update;
15088 // }
15089 // FIXME: If the innermost body is an loop itself, inserting these
15090 // statements stops it being recognized as a perfectly nested loop (e.g.
15091 // for applying tiling again). If this is the case, sink the expressions
15092 // further into the inner loop.
15093 SmallVector<Stmt *, 4> BodyParts;
15094 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15095 BodyParts.push_back(Inner);
15096 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15097 Inner->getBeginLoc(), Inner->getEndLoc());
15098 Inner = new (Context)
15099 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15100 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15101 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15104 // Create floor loops from the inside to the outside.
15105 for (int I = NumLoops - 1; I >= 0; --I) {
15106 auto &LoopHelper = LoopHelpers[I];
15107 Expr *NumIterations = LoopHelper.NumIterations;
15108 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15109 QualType CntTy = OrigCntVar->getType();
15110 Expr *DimTileSize = SizesClause->getSizesRefs()[I];
15111 Scope *CurScope = getCurScope();
15113 // Commonly used variables.
15114 DeclRefExpr *FloorIV = buildDeclRefExpr(*this, FloorIndVars[I], CntTy,
15115 OrigCntVar->getExprLoc());
15117 // For init-statement: auto .floor.iv = 0
15118 AddInitializerToDecl(
15119 FloorIndVars[I],
15120 ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15121 /*DirectInit=*/false);
15122 Decl *CounterDecl = FloorIndVars[I];
15123 StmtResult InitStmt = new (Context)
15124 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15125 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15126 if (!InitStmt.isUsable())
15127 return StmtError();
15129 // For cond-expression: .floor.iv < NumIterations
15130 ExprResult CondExpr = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
15131 BO_LT, FloorIV, NumIterations);
15132 if (!CondExpr.isUsable())
15133 return StmtError();
15135 // For incr-statement: .floor.iv += DimTileSize
15136 ExprResult IncrStmt = BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(),
15137 BO_AddAssign, FloorIV, DimTileSize);
15138 if (!IncrStmt.isUsable())
15139 return StmtError();
15141 Inner = new (Context)
15142 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15143 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15144 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15147 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
15148 AStmt, Inner,
15149 buildPreInits(Context, PreInits));
15152 StmtResult Sema::ActOnOpenMPUnrollDirective(ArrayRef<OMPClause *> Clauses,
15153 Stmt *AStmt,
15154 SourceLocation StartLoc,
15155 SourceLocation EndLoc) {
15156 // Empty statement should only be possible if there already was an error.
15157 if (!AStmt)
15158 return StmtError();
15160 if (checkMutuallyExclusiveClauses(*this, Clauses, {OMPC_partial, OMPC_full}))
15161 return StmtError();
15163 const OMPFullClause *FullClause =
15164 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
15165 const OMPPartialClause *PartialClause =
15166 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
15167 assert(!(FullClause && PartialClause) &&
15168 "mutual exclusivity must have been checked before");
15170 constexpr unsigned NumLoops = 1;
15171 Stmt *Body = nullptr;
15172 SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
15173 NumLoops);
15174 SmallVector<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>, NumLoops + 1>
15175 OriginalInits;
15176 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
15177 Body, OriginalInits))
15178 return StmtError();
15180 unsigned NumGeneratedLoops = PartialClause ? 1 : 0;
15182 // Delay unrolling to when template is completely instantiated.
15183 if (CurContext->isDependentContext())
15184 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15185 NumGeneratedLoops, nullptr, nullptr);
15187 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15189 if (FullClause) {
15190 if (!VerifyPositiveIntegerConstantInClause(
15191 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
15192 /*SuppressExprDiags=*/true)
15193 .isUsable()) {
15194 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
15195 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
15196 << "#pragma omp unroll full";
15197 return StmtError();
15201 // The generated loop may only be passed to other loop-associated directive
15202 // when a partial clause is specified. Without the requirement it is
15203 // sufficient to generate loop unroll metadata at code-generation.
15204 if (NumGeneratedLoops == 0)
15205 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15206 NumGeneratedLoops, nullptr, nullptr);
15208 // Otherwise, we need to provide a de-sugared/transformed AST that can be
15209 // associated with another loop directive.
15211 // The canonical loop analysis return by checkTransformableLoopNest assumes
15212 // the following structure to be the same loop without transformations or
15213 // directives applied: \code OriginalInits; LoopHelper.PreInits;
15214 // LoopHelper.Counters;
15215 // for (; IV < LoopHelper.NumIterations; ++IV) {
15216 // LoopHelper.Updates;
15217 // Body;
15218 // }
15219 // \endcode
15220 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
15221 // and referenced by LoopHelper.IterationVarRef.
15223 // The unrolling directive transforms this into the following loop:
15224 // \code
15225 // OriginalInits; \
15226 // LoopHelper.PreInits; > NewPreInits
15227 // LoopHelper.Counters; /
15228 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
15229 // #pragma clang loop unroll_count(Factor)
15230 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
15231 // {
15232 // LoopHelper.Updates;
15233 // Body;
15234 // }
15235 // }
15236 // \endcode
15237 // where UIV is a new logical iteration counter. IV must be the same VarDecl
15238 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
15239 // references it. If the partially unrolled loop is associated with another
15240 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
15241 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
15242 // OpenMP canonical loop. The inner loop is not an associable canonical loop
15243 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
15244 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
15245 // property of the OMPLoopBasedDirective instead of statements in
15246 // CompoundStatement. This is to allow the loop to become a non-outermost loop
15247 // of a canonical loop nest where these PreInits are emitted before the
15248 // outermost directive.
15250 // Determine the PreInit declarations.
15251 SmallVector<Decl *, 4> PreInits;
15252 assert(OriginalInits.size() == 1 &&
15253 "Expecting a single-dimensional loop iteration space");
15254 for (auto &P : OriginalInits[0]) {
15255 if (auto *D = P.dyn_cast<Decl *>())
15256 PreInits.push_back(D);
15257 else if (auto *PI = dyn_cast_or_null<DeclStmt>(P.dyn_cast<Stmt *>()))
15258 PreInits.append(PI->decl_begin(), PI->decl_end());
15260 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits))
15261 PreInits.append(PI->decl_begin(), PI->decl_end());
15262 // Gather declarations for the data members used as counters.
15263 for (Expr *CounterRef : LoopHelper.Counters) {
15264 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
15265 if (isa<OMPCapturedExprDecl>(CounterDecl))
15266 PreInits.push_back(CounterDecl);
15269 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15270 QualType IVTy = IterationVarRef->getType();
15271 assert(LoopHelper.Counters.size() == 1 &&
15272 "Expecting a single-dimensional loop iteration space");
15273 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15275 // Determine the unroll factor.
15276 uint64_t Factor;
15277 SourceLocation FactorLoc;
15278 if (Expr *FactorVal = PartialClause->getFactor()) {
15279 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
15280 FactorLoc = FactorVal->getExprLoc();
15281 } else {
15282 // TODO: Use a better profitability model.
15283 Factor = 2;
15285 assert(Factor > 0 && "Expected positive unroll factor");
15286 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
15287 return IntegerLiteral::Create(
15288 Context, llvm::APInt(Context.getIntWidth(IVTy), Factor), IVTy,
15289 FactorLoc);
15292 // Iteration variable SourceLocations.
15293 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15294 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15295 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15297 // Internal variable names.
15298 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15299 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
15300 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
15301 std::string InnerTripCountName =
15302 (Twine(".unroll_inner.tripcount.") + OrigVarName).str();
15304 // Create the iteration variable for the unrolled loop.
15305 VarDecl *OuterIVDecl =
15306 buildVarDecl(*this, {}, IVTy, OuterIVName, nullptr, OrigVar);
15307 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
15308 return buildDeclRefExpr(*this, OuterIVDecl, IVTy, OrigVarLoc);
15311 // Iteration variable for the inner loop: Reuse the iteration variable created
15312 // by checkOpenMPLoop.
15313 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15314 InnerIVDecl->setDeclName(&PP.getIdentifierTable().get(InnerIVName));
15315 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
15316 return buildDeclRefExpr(*this, InnerIVDecl, IVTy, OrigVarLoc);
15319 // Make a copy of the NumIterations expression for each use: By the AST
15320 // constraints, every expression object in a DeclContext must be unique.
15321 CaptureVars CopyTransformer(*this);
15322 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15323 return AssertSuccess(
15324 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15327 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
15328 ExprResult LValueConv = DefaultLvalueConversion(MakeOuterRef());
15329 AddInitializerToDecl(InnerIVDecl, LValueConv.get(), /*DirectInit=*/false);
15330 StmtResult InnerInit = new (Context)
15331 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15332 if (!InnerInit.isUsable())
15333 return StmtError();
15335 // Inner For cond-expression:
15336 // \code
15337 // .unroll_inner.iv < .unrolled.iv + Factor &&
15338 // .unroll_inner.iv < NumIterations
15339 // \endcode
15340 // This conjunction of two conditions allows ScalarEvolution to derive the
15341 // maximum trip count of the inner loop.
15342 ExprResult EndOfTile = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
15343 BO_Add, MakeOuterRef(), MakeFactorExpr());
15344 if (!EndOfTile.isUsable())
15345 return StmtError();
15346 ExprResult InnerCond1 = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
15347 BO_LT, MakeInnerRef(), EndOfTile.get());
15348 if (!InnerCond1.isUsable())
15349 return StmtError();
15350 ExprResult InnerCond2 =
15351 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, MakeInnerRef(),
15352 MakeNumIterations());
15353 if (!InnerCond2.isUsable())
15354 return StmtError();
15355 ExprResult InnerCond =
15356 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
15357 InnerCond1.get(), InnerCond2.get());
15358 if (!InnerCond.isUsable())
15359 return StmtError();
15361 // Inner For incr-statement: ++.unroll_inner.iv
15362 ExprResult InnerIncr = BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(),
15363 UO_PreInc, MakeInnerRef());
15364 if (!InnerIncr.isUsable())
15365 return StmtError();
15367 // Inner For statement.
15368 SmallVector<Stmt *> InnerBodyStmts;
15369 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15370 InnerBodyStmts.push_back(Body);
15371 CompoundStmt *InnerBody =
15372 CompoundStmt::Create(Context, InnerBodyStmts, FPOptionsOverride(),
15373 Body->getBeginLoc(), Body->getEndLoc());
15374 ForStmt *InnerFor = new (Context)
15375 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
15376 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
15377 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15379 // Unroll metadata for the inner loop.
15380 // This needs to take into account the remainder portion of the unrolled loop,
15381 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
15382 // supports multiple loop exits. Instead, unroll using a factor equivalent to
15383 // the maximum trip count, which will also generate a remainder loop. Just
15384 // `unroll(enable)` (which could have been useful if the user has not
15385 // specified a concrete factor; even though the outer loop cannot be
15386 // influenced anymore, would avoid more code bloat than necessary) will refuse
15387 // the loop because "Won't unroll; remainder loop could not be generated when
15388 // assuming runtime trip count". Even if it did work, it must not choose a
15389 // larger unroll factor than the maximum loop length, or it would always just
15390 // execute the remainder loop.
15391 LoopHintAttr *UnrollHintAttr =
15392 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
15393 LoopHintAttr::Numeric, MakeFactorExpr());
15394 AttributedStmt *InnerUnrolled =
15395 AttributedStmt::Create(Context, StartLoc, {UnrollHintAttr}, InnerFor);
15397 // Outer For init-statement: auto .unrolled.iv = 0
15398 AddInitializerToDecl(
15399 OuterIVDecl, ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15400 /*DirectInit=*/false);
15401 StmtResult OuterInit = new (Context)
15402 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15403 if (!OuterInit.isUsable())
15404 return StmtError();
15406 // Outer For cond-expression: .unrolled.iv < NumIterations
15407 ExprResult OuterConde =
15408 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, MakeOuterRef(),
15409 MakeNumIterations());
15410 if (!OuterConde.isUsable())
15411 return StmtError();
15413 // Outer For incr-statement: .unrolled.iv += Factor
15414 ExprResult OuterIncr =
15415 BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15416 MakeOuterRef(), MakeFactorExpr());
15417 if (!OuterIncr.isUsable())
15418 return StmtError();
15420 // Outer For statement.
15421 ForStmt *OuterFor = new (Context)
15422 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
15423 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
15424 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15426 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15427 NumGeneratedLoops, OuterFor,
15428 buildPreInits(Context, PreInits));
15431 OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
15432 SourceLocation StartLoc,
15433 SourceLocation LParenLoc,
15434 SourceLocation EndLoc) {
15435 OMPClause *Res = nullptr;
15436 switch (Kind) {
15437 case OMPC_final:
15438 Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
15439 break;
15440 case OMPC_num_threads:
15441 Res = ActOnOpenMPNumThreadsClause(Expr, StartLoc, LParenLoc, EndLoc);
15442 break;
15443 case OMPC_safelen:
15444 Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
15445 break;
15446 case OMPC_simdlen:
15447 Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
15448 break;
15449 case OMPC_allocator:
15450 Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
15451 break;
15452 case OMPC_collapse:
15453 Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
15454 break;
15455 case OMPC_ordered:
15456 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
15457 break;
15458 case OMPC_num_teams:
15459 Res = ActOnOpenMPNumTeamsClause(Expr, StartLoc, LParenLoc, EndLoc);
15460 break;
15461 case OMPC_thread_limit:
15462 Res = ActOnOpenMPThreadLimitClause(Expr, StartLoc, LParenLoc, EndLoc);
15463 break;
15464 case OMPC_priority:
15465 Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
15466 break;
15467 case OMPC_hint:
15468 Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
15469 break;
15470 case OMPC_depobj:
15471 Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
15472 break;
15473 case OMPC_detach:
15474 Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
15475 break;
15476 case OMPC_novariants:
15477 Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
15478 break;
15479 case OMPC_nocontext:
15480 Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
15481 break;
15482 case OMPC_filter:
15483 Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
15484 break;
15485 case OMPC_partial:
15486 Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
15487 break;
15488 case OMPC_message:
15489 Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc);
15490 break;
15491 case OMPC_align:
15492 Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
15493 break;
15494 case OMPC_ompx_dyn_cgroup_mem:
15495 Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc);
15496 break;
15497 case OMPC_grainsize:
15498 case OMPC_num_tasks:
15499 case OMPC_device:
15500 case OMPC_if:
15501 case OMPC_default:
15502 case OMPC_proc_bind:
15503 case OMPC_schedule:
15504 case OMPC_private:
15505 case OMPC_firstprivate:
15506 case OMPC_lastprivate:
15507 case OMPC_shared:
15508 case OMPC_reduction:
15509 case OMPC_task_reduction:
15510 case OMPC_in_reduction:
15511 case OMPC_linear:
15512 case OMPC_aligned:
15513 case OMPC_copyin:
15514 case OMPC_copyprivate:
15515 case OMPC_nowait:
15516 case OMPC_untied:
15517 case OMPC_mergeable:
15518 case OMPC_threadprivate:
15519 case OMPC_sizes:
15520 case OMPC_allocate:
15521 case OMPC_flush:
15522 case OMPC_read:
15523 case OMPC_write:
15524 case OMPC_update:
15525 case OMPC_capture:
15526 case OMPC_compare:
15527 case OMPC_seq_cst:
15528 case OMPC_acq_rel:
15529 case OMPC_acquire:
15530 case OMPC_release:
15531 case OMPC_relaxed:
15532 case OMPC_depend:
15533 case OMPC_threads:
15534 case OMPC_simd:
15535 case OMPC_map:
15536 case OMPC_nogroup:
15537 case OMPC_dist_schedule:
15538 case OMPC_defaultmap:
15539 case OMPC_unknown:
15540 case OMPC_uniform:
15541 case OMPC_to:
15542 case OMPC_from:
15543 case OMPC_use_device_ptr:
15544 case OMPC_use_device_addr:
15545 case OMPC_is_device_ptr:
15546 case OMPC_unified_address:
15547 case OMPC_unified_shared_memory:
15548 case OMPC_reverse_offload:
15549 case OMPC_dynamic_allocators:
15550 case OMPC_atomic_default_mem_order:
15551 case OMPC_device_type:
15552 case OMPC_match:
15553 case OMPC_nontemporal:
15554 case OMPC_order:
15555 case OMPC_at:
15556 case OMPC_severity:
15557 case OMPC_destroy:
15558 case OMPC_inclusive:
15559 case OMPC_exclusive:
15560 case OMPC_uses_allocators:
15561 case OMPC_affinity:
15562 case OMPC_when:
15563 case OMPC_bind:
15564 default:
15565 llvm_unreachable("Clause is not allowed.");
15567 return Res;
15570 // An OpenMP directive such as 'target parallel' has two captured regions:
15571 // for the 'target' and 'parallel' respectively. This function returns
15572 // the region in which to capture expressions associated with a clause.
15573 // A return value of OMPD_unknown signifies that the expression should not
15574 // be captured.
15575 static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
15576 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
15577 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
15578 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15579 switch (CKind) {
15580 case OMPC_if:
15581 switch (DKind) {
15582 case OMPD_target_parallel_for_simd:
15583 if (OpenMPVersion >= 50 &&
15584 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15585 CaptureRegion = OMPD_parallel;
15586 break;
15588 [[fallthrough]];
15589 case OMPD_target_parallel:
15590 case OMPD_target_parallel_for:
15591 case OMPD_target_parallel_loop:
15592 // If this clause applies to the nested 'parallel' region, capture within
15593 // the 'target' region, otherwise do not capture.
15594 if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel)
15595 CaptureRegion = OMPD_target;
15596 break;
15597 case OMPD_target_teams_distribute_parallel_for_simd:
15598 if (OpenMPVersion >= 50 &&
15599 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15600 CaptureRegion = OMPD_parallel;
15601 break;
15603 [[fallthrough]];
15604 case OMPD_target_teams_loop:
15605 case OMPD_target_teams_distribute_parallel_for:
15606 // If this clause applies to the nested 'parallel' region, capture within
15607 // the 'teams' region, otherwise do not capture.
15608 if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel)
15609 CaptureRegion = OMPD_teams;
15610 break;
15611 case OMPD_teams_distribute_parallel_for_simd:
15612 if (OpenMPVersion >= 50 &&
15613 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15614 CaptureRegion = OMPD_parallel;
15615 break;
15617 [[fallthrough]];
15618 case OMPD_teams_distribute_parallel_for:
15619 CaptureRegion = OMPD_teams;
15620 break;
15621 case OMPD_target_update:
15622 case OMPD_target_enter_data:
15623 case OMPD_target_exit_data:
15624 CaptureRegion = OMPD_task;
15625 break;
15626 case OMPD_parallel_masked_taskloop:
15627 if (NameModifier == OMPD_unknown || NameModifier == OMPD_taskloop)
15628 CaptureRegion = OMPD_parallel;
15629 break;
15630 case OMPD_parallel_master_taskloop:
15631 if (NameModifier == OMPD_unknown || NameModifier == OMPD_taskloop)
15632 CaptureRegion = OMPD_parallel;
15633 break;
15634 case OMPD_parallel_masked_taskloop_simd:
15635 if ((OpenMPVersion <= 45 && NameModifier == OMPD_unknown) ||
15636 NameModifier == OMPD_taskloop) {
15637 CaptureRegion = OMPD_parallel;
15638 break;
15640 if (OpenMPVersion <= 45)
15641 break;
15642 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15643 CaptureRegion = OMPD_taskloop;
15644 break;
15645 case OMPD_parallel_master_taskloop_simd:
15646 if ((OpenMPVersion <= 45 && NameModifier == OMPD_unknown) ||
15647 NameModifier == OMPD_taskloop) {
15648 CaptureRegion = OMPD_parallel;
15649 break;
15651 if (OpenMPVersion <= 45)
15652 break;
15653 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15654 CaptureRegion = OMPD_taskloop;
15655 break;
15656 case OMPD_parallel_for_simd:
15657 if (OpenMPVersion <= 45)
15658 break;
15659 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15660 CaptureRegion = OMPD_parallel;
15661 break;
15662 case OMPD_taskloop_simd:
15663 case OMPD_master_taskloop_simd:
15664 case OMPD_masked_taskloop_simd:
15665 if (OpenMPVersion <= 45)
15666 break;
15667 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15668 CaptureRegion = OMPD_taskloop;
15669 break;
15670 case OMPD_distribute_parallel_for_simd:
15671 if (OpenMPVersion <= 45)
15672 break;
15673 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15674 CaptureRegion = OMPD_parallel;
15675 break;
15676 case OMPD_target_simd:
15677 if (OpenMPVersion >= 50 &&
15678 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd))
15679 CaptureRegion = OMPD_target;
15680 break;
15681 case OMPD_teams_distribute_simd:
15682 case OMPD_target_teams_distribute_simd:
15683 if (OpenMPVersion >= 50 &&
15684 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd))
15685 CaptureRegion = OMPD_teams;
15686 break;
15687 case OMPD_cancel:
15688 case OMPD_parallel:
15689 case OMPD_parallel_master:
15690 case OMPD_parallel_masked:
15691 case OMPD_parallel_sections:
15692 case OMPD_parallel_for:
15693 case OMPD_parallel_loop:
15694 case OMPD_target:
15695 case OMPD_target_teams:
15696 case OMPD_target_teams_distribute:
15697 case OMPD_distribute_parallel_for:
15698 case OMPD_task:
15699 case OMPD_taskloop:
15700 case OMPD_master_taskloop:
15701 case OMPD_masked_taskloop:
15702 case OMPD_target_data:
15703 case OMPD_simd:
15704 case OMPD_for_simd:
15705 case OMPD_distribute_simd:
15706 // Do not capture if-clause expressions.
15707 break;
15708 case OMPD_threadprivate:
15709 case OMPD_allocate:
15710 case OMPD_taskyield:
15711 case OMPD_error:
15712 case OMPD_barrier:
15713 case OMPD_taskwait:
15714 case OMPD_cancellation_point:
15715 case OMPD_flush:
15716 case OMPD_depobj:
15717 case OMPD_scan:
15718 case OMPD_declare_reduction:
15719 case OMPD_declare_mapper:
15720 case OMPD_declare_simd:
15721 case OMPD_declare_variant:
15722 case OMPD_begin_declare_variant:
15723 case OMPD_end_declare_variant:
15724 case OMPD_declare_target:
15725 case OMPD_end_declare_target:
15726 case OMPD_loop:
15727 case OMPD_teams_loop:
15728 case OMPD_teams:
15729 case OMPD_tile:
15730 case OMPD_unroll:
15731 case OMPD_for:
15732 case OMPD_sections:
15733 case OMPD_section:
15734 case OMPD_single:
15735 case OMPD_master:
15736 case OMPD_masked:
15737 case OMPD_critical:
15738 case OMPD_taskgroup:
15739 case OMPD_distribute:
15740 case OMPD_ordered:
15741 case OMPD_atomic:
15742 case OMPD_teams_distribute:
15743 case OMPD_requires:
15744 case OMPD_metadirective:
15745 llvm_unreachable("Unexpected OpenMP directive with if-clause");
15746 case OMPD_unknown:
15747 default:
15748 llvm_unreachable("Unknown OpenMP directive");
15750 break;
15751 case OMPC_num_threads:
15752 switch (DKind) {
15753 case OMPD_target_parallel:
15754 case OMPD_target_parallel_for:
15755 case OMPD_target_parallel_for_simd:
15756 case OMPD_target_parallel_loop:
15757 CaptureRegion = OMPD_target;
15758 break;
15759 case OMPD_teams_distribute_parallel_for:
15760 case OMPD_teams_distribute_parallel_for_simd:
15761 case OMPD_target_teams_distribute_parallel_for:
15762 case OMPD_target_teams_distribute_parallel_for_simd:
15763 CaptureRegion = OMPD_teams;
15764 break;
15765 case OMPD_parallel:
15766 case OMPD_parallel_master:
15767 case OMPD_parallel_masked:
15768 case OMPD_parallel_sections:
15769 case OMPD_parallel_for:
15770 case OMPD_parallel_for_simd:
15771 case OMPD_parallel_loop:
15772 case OMPD_distribute_parallel_for:
15773 case OMPD_distribute_parallel_for_simd:
15774 case OMPD_parallel_master_taskloop:
15775 case OMPD_parallel_masked_taskloop:
15776 case OMPD_parallel_master_taskloop_simd:
15777 case OMPD_parallel_masked_taskloop_simd:
15778 // Do not capture num_threads-clause expressions.
15779 break;
15780 case OMPD_target_data:
15781 case OMPD_target_enter_data:
15782 case OMPD_target_exit_data:
15783 case OMPD_target_update:
15784 case OMPD_target:
15785 case OMPD_target_simd:
15786 case OMPD_target_teams:
15787 case OMPD_target_teams_distribute:
15788 case OMPD_target_teams_distribute_simd:
15789 case OMPD_cancel:
15790 case OMPD_task:
15791 case OMPD_taskloop:
15792 case OMPD_taskloop_simd:
15793 case OMPD_master_taskloop:
15794 case OMPD_masked_taskloop:
15795 case OMPD_master_taskloop_simd:
15796 case OMPD_masked_taskloop_simd:
15797 case OMPD_threadprivate:
15798 case OMPD_allocate:
15799 case OMPD_taskyield:
15800 case OMPD_error:
15801 case OMPD_barrier:
15802 case OMPD_taskwait:
15803 case OMPD_cancellation_point:
15804 case OMPD_flush:
15805 case OMPD_depobj:
15806 case OMPD_scan:
15807 case OMPD_declare_reduction:
15808 case OMPD_declare_mapper:
15809 case OMPD_declare_simd:
15810 case OMPD_declare_variant:
15811 case OMPD_begin_declare_variant:
15812 case OMPD_end_declare_variant:
15813 case OMPD_declare_target:
15814 case OMPD_end_declare_target:
15815 case OMPD_loop:
15816 case OMPD_teams_loop:
15817 case OMPD_target_teams_loop:
15818 case OMPD_teams:
15819 case OMPD_simd:
15820 case OMPD_tile:
15821 case OMPD_unroll:
15822 case OMPD_for:
15823 case OMPD_for_simd:
15824 case OMPD_sections:
15825 case OMPD_section:
15826 case OMPD_single:
15827 case OMPD_master:
15828 case OMPD_masked:
15829 case OMPD_critical:
15830 case OMPD_taskgroup:
15831 case OMPD_distribute:
15832 case OMPD_ordered:
15833 case OMPD_atomic:
15834 case OMPD_distribute_simd:
15835 case OMPD_teams_distribute:
15836 case OMPD_teams_distribute_simd:
15837 case OMPD_requires:
15838 case OMPD_metadirective:
15839 llvm_unreachable("Unexpected OpenMP directive with num_threads-clause");
15840 case OMPD_unknown:
15841 default:
15842 llvm_unreachable("Unknown OpenMP directive");
15844 break;
15845 case OMPC_num_teams:
15846 switch (DKind) {
15847 case OMPD_target_teams:
15848 case OMPD_target_teams_distribute:
15849 case OMPD_target_teams_distribute_simd:
15850 case OMPD_target_teams_distribute_parallel_for:
15851 case OMPD_target_teams_distribute_parallel_for_simd:
15852 case OMPD_target_teams_loop:
15853 CaptureRegion = OMPD_target;
15854 break;
15855 case OMPD_teams_distribute_parallel_for:
15856 case OMPD_teams_distribute_parallel_for_simd:
15857 case OMPD_teams:
15858 case OMPD_teams_distribute:
15859 case OMPD_teams_distribute_simd:
15860 case OMPD_teams_loop:
15861 // Do not capture num_teams-clause expressions.
15862 break;
15863 case OMPD_distribute_parallel_for:
15864 case OMPD_distribute_parallel_for_simd:
15865 case OMPD_task:
15866 case OMPD_taskloop:
15867 case OMPD_taskloop_simd:
15868 case OMPD_master_taskloop:
15869 case OMPD_masked_taskloop:
15870 case OMPD_master_taskloop_simd:
15871 case OMPD_masked_taskloop_simd:
15872 case OMPD_parallel_master_taskloop:
15873 case OMPD_parallel_masked_taskloop:
15874 case OMPD_parallel_master_taskloop_simd:
15875 case OMPD_parallel_masked_taskloop_simd:
15876 case OMPD_target_data:
15877 case OMPD_target_enter_data:
15878 case OMPD_target_exit_data:
15879 case OMPD_target_update:
15880 case OMPD_cancel:
15881 case OMPD_parallel:
15882 case OMPD_parallel_master:
15883 case OMPD_parallel_masked:
15884 case OMPD_parallel_sections:
15885 case OMPD_parallel_for:
15886 case OMPD_parallel_for_simd:
15887 case OMPD_parallel_loop:
15888 case OMPD_target:
15889 case OMPD_target_simd:
15890 case OMPD_target_parallel:
15891 case OMPD_target_parallel_for:
15892 case OMPD_target_parallel_for_simd:
15893 case OMPD_target_parallel_loop:
15894 case OMPD_threadprivate:
15895 case OMPD_allocate:
15896 case OMPD_taskyield:
15897 case OMPD_error:
15898 case OMPD_barrier:
15899 case OMPD_taskwait:
15900 case OMPD_cancellation_point:
15901 case OMPD_flush:
15902 case OMPD_depobj:
15903 case OMPD_scan:
15904 case OMPD_declare_reduction:
15905 case OMPD_declare_mapper:
15906 case OMPD_declare_simd:
15907 case OMPD_declare_variant:
15908 case OMPD_begin_declare_variant:
15909 case OMPD_end_declare_variant:
15910 case OMPD_declare_target:
15911 case OMPD_end_declare_target:
15912 case OMPD_loop:
15913 case OMPD_simd:
15914 case OMPD_tile:
15915 case OMPD_unroll:
15916 case OMPD_for:
15917 case OMPD_for_simd:
15918 case OMPD_sections:
15919 case OMPD_section:
15920 case OMPD_single:
15921 case OMPD_master:
15922 case OMPD_masked:
15923 case OMPD_critical:
15924 case OMPD_taskgroup:
15925 case OMPD_distribute:
15926 case OMPD_ordered:
15927 case OMPD_atomic:
15928 case OMPD_distribute_simd:
15929 case OMPD_requires:
15930 case OMPD_metadirective:
15931 llvm_unreachable("Unexpected OpenMP directive with num_teams-clause");
15932 case OMPD_unknown:
15933 default:
15934 llvm_unreachable("Unknown OpenMP directive");
15936 break;
15937 case OMPC_thread_limit:
15938 switch (DKind) {
15939 case OMPD_target:
15940 case OMPD_target_teams:
15941 case OMPD_target_teams_distribute:
15942 case OMPD_target_teams_distribute_simd:
15943 case OMPD_target_teams_distribute_parallel_for:
15944 case OMPD_target_teams_distribute_parallel_for_simd:
15945 case OMPD_target_teams_loop:
15946 case OMPD_target_simd:
15947 case OMPD_target_parallel:
15948 case OMPD_target_parallel_for:
15949 case OMPD_target_parallel_for_simd:
15950 case OMPD_target_parallel_loop:
15951 CaptureRegion = OMPD_target;
15952 break;
15953 case OMPD_teams_distribute_parallel_for:
15954 case OMPD_teams_distribute_parallel_for_simd:
15955 case OMPD_teams:
15956 case OMPD_teams_distribute:
15957 case OMPD_teams_distribute_simd:
15958 case OMPD_teams_loop:
15959 // Do not capture thread_limit-clause expressions.
15960 break;
15961 case OMPD_distribute_parallel_for:
15962 case OMPD_distribute_parallel_for_simd:
15963 case OMPD_task:
15964 case OMPD_taskloop:
15965 case OMPD_taskloop_simd:
15966 case OMPD_master_taskloop:
15967 case OMPD_masked_taskloop:
15968 case OMPD_master_taskloop_simd:
15969 case OMPD_masked_taskloop_simd:
15970 case OMPD_parallel_master_taskloop:
15971 case OMPD_parallel_masked_taskloop:
15972 case OMPD_parallel_master_taskloop_simd:
15973 case OMPD_parallel_masked_taskloop_simd:
15974 case OMPD_target_data:
15975 case OMPD_target_enter_data:
15976 case OMPD_target_exit_data:
15977 case OMPD_target_update:
15978 case OMPD_cancel:
15979 case OMPD_parallel:
15980 case OMPD_parallel_master:
15981 case OMPD_parallel_masked:
15982 case OMPD_parallel_sections:
15983 case OMPD_parallel_for:
15984 case OMPD_parallel_for_simd:
15985 case OMPD_parallel_loop:
15986 case OMPD_threadprivate:
15987 case OMPD_allocate:
15988 case OMPD_taskyield:
15989 case OMPD_error:
15990 case OMPD_barrier:
15991 case OMPD_taskwait:
15992 case OMPD_cancellation_point:
15993 case OMPD_flush:
15994 case OMPD_depobj:
15995 case OMPD_scan:
15996 case OMPD_declare_reduction:
15997 case OMPD_declare_mapper:
15998 case OMPD_declare_simd:
15999 case OMPD_declare_variant:
16000 case OMPD_begin_declare_variant:
16001 case OMPD_end_declare_variant:
16002 case OMPD_declare_target:
16003 case OMPD_end_declare_target:
16004 case OMPD_loop:
16005 case OMPD_simd:
16006 case OMPD_tile:
16007 case OMPD_unroll:
16008 case OMPD_for:
16009 case OMPD_for_simd:
16010 case OMPD_sections:
16011 case OMPD_section:
16012 case OMPD_single:
16013 case OMPD_master:
16014 case OMPD_masked:
16015 case OMPD_critical:
16016 case OMPD_taskgroup:
16017 case OMPD_distribute:
16018 case OMPD_ordered:
16019 case OMPD_atomic:
16020 case OMPD_distribute_simd:
16021 case OMPD_requires:
16022 case OMPD_metadirective:
16023 llvm_unreachable("Unexpected OpenMP directive with thread_limit-clause");
16024 case OMPD_unknown:
16025 default:
16026 llvm_unreachable("Unknown OpenMP directive");
16028 break;
16029 case OMPC_schedule:
16030 switch (DKind) {
16031 case OMPD_parallel_for:
16032 case OMPD_parallel_for_simd:
16033 case OMPD_distribute_parallel_for:
16034 case OMPD_distribute_parallel_for_simd:
16035 case OMPD_teams_distribute_parallel_for:
16036 case OMPD_teams_distribute_parallel_for_simd:
16037 case OMPD_target_parallel_for:
16038 case OMPD_target_parallel_for_simd:
16039 case OMPD_target_teams_distribute_parallel_for:
16040 case OMPD_target_teams_distribute_parallel_for_simd:
16041 CaptureRegion = OMPD_parallel;
16042 break;
16043 case OMPD_for:
16044 case OMPD_for_simd:
16045 // Do not capture schedule-clause expressions.
16046 break;
16047 case OMPD_task:
16048 case OMPD_taskloop:
16049 case OMPD_taskloop_simd:
16050 case OMPD_master_taskloop:
16051 case OMPD_masked_taskloop:
16052 case OMPD_master_taskloop_simd:
16053 case OMPD_masked_taskloop_simd:
16054 case OMPD_parallel_master_taskloop:
16055 case OMPD_parallel_masked_taskloop:
16056 case OMPD_parallel_master_taskloop_simd:
16057 case OMPD_parallel_masked_taskloop_simd:
16058 case OMPD_target_data:
16059 case OMPD_target_enter_data:
16060 case OMPD_target_exit_data:
16061 case OMPD_target_update:
16062 case OMPD_teams:
16063 case OMPD_teams_distribute:
16064 case OMPD_teams_distribute_simd:
16065 case OMPD_target_teams_distribute:
16066 case OMPD_target_teams_distribute_simd:
16067 case OMPD_target:
16068 case OMPD_target_simd:
16069 case OMPD_target_parallel:
16070 case OMPD_cancel:
16071 case OMPD_parallel:
16072 case OMPD_parallel_master:
16073 case OMPD_parallel_masked:
16074 case OMPD_parallel_sections:
16075 case OMPD_threadprivate:
16076 case OMPD_allocate:
16077 case OMPD_taskyield:
16078 case OMPD_error:
16079 case OMPD_barrier:
16080 case OMPD_taskwait:
16081 case OMPD_cancellation_point:
16082 case OMPD_flush:
16083 case OMPD_depobj:
16084 case OMPD_scan:
16085 case OMPD_declare_reduction:
16086 case OMPD_declare_mapper:
16087 case OMPD_declare_simd:
16088 case OMPD_declare_variant:
16089 case OMPD_begin_declare_variant:
16090 case OMPD_end_declare_variant:
16091 case OMPD_declare_target:
16092 case OMPD_end_declare_target:
16093 case OMPD_loop:
16094 case OMPD_teams_loop:
16095 case OMPD_target_teams_loop:
16096 case OMPD_parallel_loop:
16097 case OMPD_target_parallel_loop:
16098 case OMPD_simd:
16099 case OMPD_tile:
16100 case OMPD_unroll:
16101 case OMPD_sections:
16102 case OMPD_section:
16103 case OMPD_single:
16104 case OMPD_master:
16105 case OMPD_masked:
16106 case OMPD_critical:
16107 case OMPD_taskgroup:
16108 case OMPD_distribute:
16109 case OMPD_ordered:
16110 case OMPD_atomic:
16111 case OMPD_distribute_simd:
16112 case OMPD_target_teams:
16113 case OMPD_requires:
16114 case OMPD_metadirective:
16115 llvm_unreachable("Unexpected OpenMP directive with schedule clause");
16116 case OMPD_unknown:
16117 default:
16118 llvm_unreachable("Unknown OpenMP directive");
16120 break;
16121 case OMPC_dist_schedule:
16122 switch (DKind) {
16123 case OMPD_teams_distribute_parallel_for:
16124 case OMPD_teams_distribute_parallel_for_simd:
16125 case OMPD_teams_distribute:
16126 case OMPD_teams_distribute_simd:
16127 case OMPD_target_teams_distribute_parallel_for:
16128 case OMPD_target_teams_distribute_parallel_for_simd:
16129 case OMPD_target_teams_distribute:
16130 case OMPD_target_teams_distribute_simd:
16131 CaptureRegion = OMPD_teams;
16132 break;
16133 case OMPD_distribute_parallel_for:
16134 case OMPD_distribute_parallel_for_simd:
16135 case OMPD_distribute:
16136 case OMPD_distribute_simd:
16137 // Do not capture dist_schedule-clause expressions.
16138 break;
16139 case OMPD_parallel_for:
16140 case OMPD_parallel_for_simd:
16141 case OMPD_target_parallel_for_simd:
16142 case OMPD_target_parallel_for:
16143 case OMPD_task:
16144 case OMPD_taskloop:
16145 case OMPD_taskloop_simd:
16146 case OMPD_master_taskloop:
16147 case OMPD_masked_taskloop:
16148 case OMPD_master_taskloop_simd:
16149 case OMPD_masked_taskloop_simd:
16150 case OMPD_parallel_master_taskloop:
16151 case OMPD_parallel_masked_taskloop:
16152 case OMPD_parallel_master_taskloop_simd:
16153 case OMPD_parallel_masked_taskloop_simd:
16154 case OMPD_target_data:
16155 case OMPD_target_enter_data:
16156 case OMPD_target_exit_data:
16157 case OMPD_target_update:
16158 case OMPD_teams:
16159 case OMPD_target:
16160 case OMPD_target_simd:
16161 case OMPD_target_parallel:
16162 case OMPD_cancel:
16163 case OMPD_parallel:
16164 case OMPD_parallel_master:
16165 case OMPD_parallel_masked:
16166 case OMPD_parallel_sections:
16167 case OMPD_threadprivate:
16168 case OMPD_allocate:
16169 case OMPD_taskyield:
16170 case OMPD_error:
16171 case OMPD_barrier:
16172 case OMPD_taskwait:
16173 case OMPD_cancellation_point:
16174 case OMPD_flush:
16175 case OMPD_depobj:
16176 case OMPD_scan:
16177 case OMPD_declare_reduction:
16178 case OMPD_declare_mapper:
16179 case OMPD_declare_simd:
16180 case OMPD_declare_variant:
16181 case OMPD_begin_declare_variant:
16182 case OMPD_end_declare_variant:
16183 case OMPD_declare_target:
16184 case OMPD_end_declare_target:
16185 case OMPD_loop:
16186 case OMPD_teams_loop:
16187 case OMPD_target_teams_loop:
16188 case OMPD_parallel_loop:
16189 case OMPD_target_parallel_loop:
16190 case OMPD_simd:
16191 case OMPD_tile:
16192 case OMPD_unroll:
16193 case OMPD_for:
16194 case OMPD_for_simd:
16195 case OMPD_sections:
16196 case OMPD_section:
16197 case OMPD_single:
16198 case OMPD_master:
16199 case OMPD_masked:
16200 case OMPD_critical:
16201 case OMPD_taskgroup:
16202 case OMPD_ordered:
16203 case OMPD_atomic:
16204 case OMPD_target_teams:
16205 case OMPD_requires:
16206 case OMPD_metadirective:
16207 llvm_unreachable("Unexpected OpenMP directive with dist_schedule clause");
16208 case OMPD_unknown:
16209 default:
16210 llvm_unreachable("Unknown OpenMP directive");
16212 break;
16213 case OMPC_ompx_dyn_cgroup_mem:
16214 switch (DKind) {
16215 case OMPD_target:
16216 case OMPD_target_simd:
16217 case OMPD_target_teams:
16218 case OMPD_target_parallel:
16219 case OMPD_target_teams_distribute:
16220 case OMPD_target_teams_distribute_simd:
16221 case OMPD_target_parallel_for:
16222 case OMPD_target_parallel_for_simd:
16223 case OMPD_target_parallel_loop:
16224 case OMPD_target_teams_distribute_parallel_for:
16225 case OMPD_target_teams_distribute_parallel_for_simd:
16226 case OMPD_target_teams_loop:
16227 CaptureRegion = OMPD_target;
16228 break;
16229 default:
16230 llvm_unreachable("Unknown OpenMP directive");
16232 break;
16233 case OMPC_device:
16234 switch (DKind) {
16235 case OMPD_target_update:
16236 case OMPD_target_enter_data:
16237 case OMPD_target_exit_data:
16238 case OMPD_target:
16239 case OMPD_target_simd:
16240 case OMPD_target_teams:
16241 case OMPD_target_parallel:
16242 case OMPD_target_teams_distribute:
16243 case OMPD_target_teams_distribute_simd:
16244 case OMPD_target_parallel_for:
16245 case OMPD_target_parallel_for_simd:
16246 case OMPD_target_parallel_loop:
16247 case OMPD_target_teams_distribute_parallel_for:
16248 case OMPD_target_teams_distribute_parallel_for_simd:
16249 case OMPD_target_teams_loop:
16250 case OMPD_dispatch:
16251 CaptureRegion = OMPD_task;
16252 break;
16253 case OMPD_target_data:
16254 case OMPD_interop:
16255 // Do not capture device-clause expressions.
16256 break;
16257 case OMPD_teams_distribute_parallel_for:
16258 case OMPD_teams_distribute_parallel_for_simd:
16259 case OMPD_teams:
16260 case OMPD_teams_distribute:
16261 case OMPD_teams_distribute_simd:
16262 case OMPD_distribute_parallel_for:
16263 case OMPD_distribute_parallel_for_simd:
16264 case OMPD_task:
16265 case OMPD_taskloop:
16266 case OMPD_taskloop_simd:
16267 case OMPD_master_taskloop:
16268 case OMPD_masked_taskloop:
16269 case OMPD_master_taskloop_simd:
16270 case OMPD_masked_taskloop_simd:
16271 case OMPD_parallel_master_taskloop:
16272 case OMPD_parallel_masked_taskloop:
16273 case OMPD_parallel_master_taskloop_simd:
16274 case OMPD_parallel_masked_taskloop_simd:
16275 case OMPD_cancel:
16276 case OMPD_parallel:
16277 case OMPD_parallel_master:
16278 case OMPD_parallel_masked:
16279 case OMPD_parallel_sections:
16280 case OMPD_parallel_for:
16281 case OMPD_parallel_for_simd:
16282 case OMPD_threadprivate:
16283 case OMPD_allocate:
16284 case OMPD_taskyield:
16285 case OMPD_error:
16286 case OMPD_barrier:
16287 case OMPD_taskwait:
16288 case OMPD_cancellation_point:
16289 case OMPD_flush:
16290 case OMPD_depobj:
16291 case OMPD_scan:
16292 case OMPD_declare_reduction:
16293 case OMPD_declare_mapper:
16294 case OMPD_declare_simd:
16295 case OMPD_declare_variant:
16296 case OMPD_begin_declare_variant:
16297 case OMPD_end_declare_variant:
16298 case OMPD_declare_target:
16299 case OMPD_end_declare_target:
16300 case OMPD_loop:
16301 case OMPD_teams_loop:
16302 case OMPD_parallel_loop:
16303 case OMPD_simd:
16304 case OMPD_tile:
16305 case OMPD_unroll:
16306 case OMPD_for:
16307 case OMPD_for_simd:
16308 case OMPD_sections:
16309 case OMPD_section:
16310 case OMPD_single:
16311 case OMPD_master:
16312 case OMPD_masked:
16313 case OMPD_critical:
16314 case OMPD_taskgroup:
16315 case OMPD_distribute:
16316 case OMPD_ordered:
16317 case OMPD_atomic:
16318 case OMPD_distribute_simd:
16319 case OMPD_requires:
16320 case OMPD_metadirective:
16321 llvm_unreachable("Unexpected OpenMP directive with device-clause");
16322 case OMPD_unknown:
16323 default:
16324 llvm_unreachable("Unknown OpenMP directive");
16326 break;
16327 case OMPC_grainsize:
16328 case OMPC_num_tasks:
16329 case OMPC_final:
16330 case OMPC_priority:
16331 switch (DKind) {
16332 case OMPD_task:
16333 case OMPD_taskloop:
16334 case OMPD_taskloop_simd:
16335 case OMPD_master_taskloop:
16336 case OMPD_masked_taskloop:
16337 case OMPD_master_taskloop_simd:
16338 case OMPD_masked_taskloop_simd:
16339 break;
16340 case OMPD_parallel_masked_taskloop:
16341 case OMPD_parallel_masked_taskloop_simd:
16342 case OMPD_parallel_master_taskloop:
16343 case OMPD_parallel_master_taskloop_simd:
16344 CaptureRegion = OMPD_parallel;
16345 break;
16346 case OMPD_target_update:
16347 case OMPD_target_enter_data:
16348 case OMPD_target_exit_data:
16349 case OMPD_target:
16350 case OMPD_target_simd:
16351 case OMPD_target_teams:
16352 case OMPD_target_parallel:
16353 case OMPD_target_teams_distribute:
16354 case OMPD_target_teams_distribute_simd:
16355 case OMPD_target_parallel_for:
16356 case OMPD_target_parallel_for_simd:
16357 case OMPD_target_teams_distribute_parallel_for:
16358 case OMPD_target_teams_distribute_parallel_for_simd:
16359 case OMPD_target_data:
16360 case OMPD_teams_distribute_parallel_for:
16361 case OMPD_teams_distribute_parallel_for_simd:
16362 case OMPD_teams:
16363 case OMPD_teams_distribute:
16364 case OMPD_teams_distribute_simd:
16365 case OMPD_distribute_parallel_for:
16366 case OMPD_distribute_parallel_for_simd:
16367 case OMPD_cancel:
16368 case OMPD_parallel:
16369 case OMPD_parallel_master:
16370 case OMPD_parallel_masked:
16371 case OMPD_parallel_sections:
16372 case OMPD_parallel_for:
16373 case OMPD_parallel_for_simd:
16374 case OMPD_threadprivate:
16375 case OMPD_allocate:
16376 case OMPD_taskyield:
16377 case OMPD_error:
16378 case OMPD_barrier:
16379 case OMPD_taskwait:
16380 case OMPD_cancellation_point:
16381 case OMPD_flush:
16382 case OMPD_depobj:
16383 case OMPD_scan:
16384 case OMPD_declare_reduction:
16385 case OMPD_declare_mapper:
16386 case OMPD_declare_simd:
16387 case OMPD_declare_variant:
16388 case OMPD_begin_declare_variant:
16389 case OMPD_end_declare_variant:
16390 case OMPD_declare_target:
16391 case OMPD_end_declare_target:
16392 case OMPD_loop:
16393 case OMPD_teams_loop:
16394 case OMPD_target_teams_loop:
16395 case OMPD_parallel_loop:
16396 case OMPD_target_parallel_loop:
16397 case OMPD_simd:
16398 case OMPD_tile:
16399 case OMPD_unroll:
16400 case OMPD_for:
16401 case OMPD_for_simd:
16402 case OMPD_sections:
16403 case OMPD_section:
16404 case OMPD_single:
16405 case OMPD_master:
16406 case OMPD_masked:
16407 case OMPD_critical:
16408 case OMPD_taskgroup:
16409 case OMPD_distribute:
16410 case OMPD_ordered:
16411 case OMPD_atomic:
16412 case OMPD_distribute_simd:
16413 case OMPD_requires:
16414 case OMPD_metadirective:
16415 llvm_unreachable("Unexpected OpenMP directive with grainsize-clause");
16416 case OMPD_unknown:
16417 default:
16418 llvm_unreachable("Unknown OpenMP directive");
16420 break;
16421 case OMPC_novariants:
16422 case OMPC_nocontext:
16423 switch (DKind) {
16424 case OMPD_dispatch:
16425 CaptureRegion = OMPD_task;
16426 break;
16427 default:
16428 llvm_unreachable("Unexpected OpenMP directive");
16430 break;
16431 case OMPC_filter:
16432 // Do not capture filter-clause expressions.
16433 break;
16434 case OMPC_when:
16435 if (DKind == OMPD_metadirective) {
16436 CaptureRegion = OMPD_metadirective;
16437 } else if (DKind == OMPD_unknown) {
16438 llvm_unreachable("Unknown OpenMP directive");
16439 } else {
16440 llvm_unreachable("Unexpected OpenMP directive with when clause");
16442 break;
16443 case OMPC_firstprivate:
16444 case OMPC_lastprivate:
16445 case OMPC_reduction:
16446 case OMPC_task_reduction:
16447 case OMPC_in_reduction:
16448 case OMPC_linear:
16449 case OMPC_default:
16450 case OMPC_proc_bind:
16451 case OMPC_safelen:
16452 case OMPC_simdlen:
16453 case OMPC_sizes:
16454 case OMPC_allocator:
16455 case OMPC_collapse:
16456 case OMPC_private:
16457 case OMPC_shared:
16458 case OMPC_aligned:
16459 case OMPC_copyin:
16460 case OMPC_copyprivate:
16461 case OMPC_ordered:
16462 case OMPC_nowait:
16463 case OMPC_untied:
16464 case OMPC_mergeable:
16465 case OMPC_threadprivate:
16466 case OMPC_allocate:
16467 case OMPC_flush:
16468 case OMPC_depobj:
16469 case OMPC_read:
16470 case OMPC_write:
16471 case OMPC_update:
16472 case OMPC_capture:
16473 case OMPC_compare:
16474 case OMPC_seq_cst:
16475 case OMPC_acq_rel:
16476 case OMPC_acquire:
16477 case OMPC_release:
16478 case OMPC_relaxed:
16479 case OMPC_depend:
16480 case OMPC_threads:
16481 case OMPC_simd:
16482 case OMPC_map:
16483 case OMPC_nogroup:
16484 case OMPC_hint:
16485 case OMPC_defaultmap:
16486 case OMPC_unknown:
16487 case OMPC_uniform:
16488 case OMPC_to:
16489 case OMPC_from:
16490 case OMPC_use_device_ptr:
16491 case OMPC_use_device_addr:
16492 case OMPC_is_device_ptr:
16493 case OMPC_unified_address:
16494 case OMPC_unified_shared_memory:
16495 case OMPC_reverse_offload:
16496 case OMPC_dynamic_allocators:
16497 case OMPC_atomic_default_mem_order:
16498 case OMPC_device_type:
16499 case OMPC_match:
16500 case OMPC_nontemporal:
16501 case OMPC_order:
16502 case OMPC_at:
16503 case OMPC_severity:
16504 case OMPC_message:
16505 case OMPC_destroy:
16506 case OMPC_detach:
16507 case OMPC_inclusive:
16508 case OMPC_exclusive:
16509 case OMPC_uses_allocators:
16510 case OMPC_affinity:
16511 case OMPC_bind:
16512 default:
16513 llvm_unreachable("Unexpected OpenMP clause.");
16515 return CaptureRegion;
16518 OMPClause *Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier,
16519 Expr *Condition, SourceLocation StartLoc,
16520 SourceLocation LParenLoc,
16521 SourceLocation NameModifierLoc,
16522 SourceLocation ColonLoc,
16523 SourceLocation EndLoc) {
16524 Expr *ValExpr = Condition;
16525 Stmt *HelperValStmt = nullptr;
16526 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16527 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16528 !Condition->isInstantiationDependent() &&
16529 !Condition->containsUnexpandedParameterPack()) {
16530 ExprResult Val = CheckBooleanCondition(StartLoc, Condition);
16531 if (Val.isInvalid())
16532 return nullptr;
16534 ValExpr = Val.get();
16536 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16537 CaptureRegion = getOpenMPCaptureRegionForClause(
16538 DKind, OMPC_if, LangOpts.OpenMP, NameModifier);
16539 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
16540 ValExpr = MakeFullExpr(ValExpr).get();
16541 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16542 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
16543 HelperValStmt = buildPreInits(Context, Captures);
16547 return new (Context)
16548 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
16549 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
16552 OMPClause *Sema::ActOnOpenMPFinalClause(Expr *Condition,
16553 SourceLocation StartLoc,
16554 SourceLocation LParenLoc,
16555 SourceLocation EndLoc) {
16556 Expr *ValExpr = Condition;
16557 Stmt *HelperValStmt = nullptr;
16558 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16559 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16560 !Condition->isInstantiationDependent() &&
16561 !Condition->containsUnexpandedParameterPack()) {
16562 ExprResult Val = CheckBooleanCondition(StartLoc, Condition);
16563 if (Val.isInvalid())
16564 return nullptr;
16566 ValExpr = MakeFullExpr(Val.get()).get();
16568 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16569 CaptureRegion =
16570 getOpenMPCaptureRegionForClause(DKind, OMPC_final, LangOpts.OpenMP);
16571 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
16572 ValExpr = MakeFullExpr(ValExpr).get();
16573 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16574 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
16575 HelperValStmt = buildPreInits(Context, Captures);
16579 return new (Context) OMPFinalClause(ValExpr, HelperValStmt, CaptureRegion,
16580 StartLoc, LParenLoc, EndLoc);
16583 ExprResult Sema::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc,
16584 Expr *Op) {
16585 if (!Op)
16586 return ExprError();
16588 class IntConvertDiagnoser : public ICEConvertDiagnoser {
16589 public:
16590 IntConvertDiagnoser()
16591 : ICEConvertDiagnoser(/*AllowScopedEnumerations*/ false, false, true) {}
16592 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
16593 QualType T) override {
16594 return S.Diag(Loc, diag::err_omp_not_integral) << T;
16596 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
16597 QualType T) override {
16598 return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
16600 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
16601 QualType T,
16602 QualType ConvTy) override {
16603 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
16605 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
16606 QualType ConvTy) override {
16607 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16608 << ConvTy->isEnumeralType() << ConvTy;
16610 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
16611 QualType T) override {
16612 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
16614 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
16615 QualType ConvTy) override {
16616 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16617 << ConvTy->isEnumeralType() << ConvTy;
16619 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
16620 QualType) override {
16621 llvm_unreachable("conversion functions are permitted");
16623 } ConvertDiagnoser;
16624 return PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
16627 static bool
16628 isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind,
16629 bool StrictlyPositive, bool BuildCapture = false,
16630 OpenMPDirectiveKind DKind = OMPD_unknown,
16631 OpenMPDirectiveKind *CaptureRegion = nullptr,
16632 Stmt **HelperValStmt = nullptr) {
16633 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
16634 !ValExpr->isInstantiationDependent()) {
16635 SourceLocation Loc = ValExpr->getExprLoc();
16636 ExprResult Value =
16637 SemaRef.PerformOpenMPImplicitIntegerConversion(Loc, ValExpr);
16638 if (Value.isInvalid())
16639 return false;
16641 ValExpr = Value.get();
16642 // The expression must evaluate to a non-negative integer value.
16643 if (std::optional<llvm::APSInt> Result =
16644 ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
16645 if (Result->isSigned() &&
16646 !((!StrictlyPositive && Result->isNonNegative()) ||
16647 (StrictlyPositive && Result->isStrictlyPositive()))) {
16648 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
16649 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
16650 << ValExpr->getSourceRange();
16651 return false;
16654 if (!BuildCapture)
16655 return true;
16656 *CaptureRegion =
16657 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
16658 if (*CaptureRegion != OMPD_unknown &&
16659 !SemaRef.CurContext->isDependentContext()) {
16660 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16661 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16662 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16663 *HelperValStmt = buildPreInits(SemaRef.Context, Captures);
16666 return true;
16669 OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads,
16670 SourceLocation StartLoc,
16671 SourceLocation LParenLoc,
16672 SourceLocation EndLoc) {
16673 Expr *ValExpr = NumThreads;
16674 Stmt *HelperValStmt = nullptr;
16676 // OpenMP [2.5, Restrictions]
16677 // The num_threads expression must evaluate to a positive integer value.
16678 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_num_threads,
16679 /*StrictlyPositive=*/true))
16680 return nullptr;
16682 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16683 OpenMPDirectiveKind CaptureRegion =
16684 getOpenMPCaptureRegionForClause(DKind, OMPC_num_threads, LangOpts.OpenMP);
16685 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
16686 ValExpr = MakeFullExpr(ValExpr).get();
16687 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16688 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
16689 HelperValStmt = buildPreInits(Context, Captures);
16692 return new (Context) OMPNumThreadsClause(
16693 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16696 ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,
16697 OpenMPClauseKind CKind,
16698 bool StrictlyPositive,
16699 bool SuppressExprDiags) {
16700 if (!E)
16701 return ExprError();
16702 if (E->isValueDependent() || E->isTypeDependent() ||
16703 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
16704 return E;
16706 llvm::APSInt Result;
16707 ExprResult ICE;
16708 if (SuppressExprDiags) {
16709 // Use a custom diagnoser that suppresses 'note' diagnostics about the
16710 // expression.
16711 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
16712 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
16713 Sema::SemaDiagnosticBuilder diagnoseNotICE(Sema &S,
16714 SourceLocation Loc) override {
16715 llvm_unreachable("Diagnostic suppressed");
16717 } Diagnoser;
16718 ICE = VerifyIntegerConstantExpression(E, &Result, Diagnoser, AllowFold);
16719 } else {
16720 ICE = VerifyIntegerConstantExpression(E, &Result, /*FIXME*/ AllowFold);
16722 if (ICE.isInvalid())
16723 return ExprError();
16725 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
16726 (!StrictlyPositive && !Result.isNonNegative())) {
16727 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
16728 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
16729 << E->getSourceRange();
16730 return ExprError();
16732 if ((CKind == OMPC_aligned || CKind == OMPC_align) && !Result.isPowerOf2()) {
16733 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
16734 << E->getSourceRange();
16735 return ExprError();
16737 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
16738 DSAStack->setAssociatedLoops(Result.getExtValue());
16739 else if (CKind == OMPC_ordered)
16740 DSAStack->setAssociatedLoops(Result.getExtValue());
16741 return ICE;
16744 OMPClause *Sema::ActOnOpenMPSafelenClause(Expr *Len, SourceLocation StartLoc,
16745 SourceLocation LParenLoc,
16746 SourceLocation EndLoc) {
16747 // OpenMP [2.8.1, simd construct, Description]
16748 // The parameter of the safelen clause must be a constant
16749 // positive integer expression.
16750 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
16751 if (Safelen.isInvalid())
16752 return nullptr;
16753 return new (Context)
16754 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
16757 OMPClause *Sema::ActOnOpenMPSimdlenClause(Expr *Len, SourceLocation StartLoc,
16758 SourceLocation LParenLoc,
16759 SourceLocation EndLoc) {
16760 // OpenMP [2.8.1, simd construct, Description]
16761 // The parameter of the simdlen clause must be a constant
16762 // positive integer expression.
16763 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
16764 if (Simdlen.isInvalid())
16765 return nullptr;
16766 return new (Context)
16767 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
16770 /// Tries to find omp_allocator_handle_t type.
16771 static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc,
16772 DSAStackTy *Stack) {
16773 if (!Stack->getOMPAllocatorHandleT().isNull())
16774 return true;
16776 // Set the allocator handle type.
16777 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t");
16778 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
16779 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
16780 S.Diag(Loc, diag::err_omp_implied_type_not_found)
16781 << "omp_allocator_handle_t";
16782 return false;
16784 QualType AllocatorHandleEnumTy = PT.get();
16785 AllocatorHandleEnumTy.addConst();
16786 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
16788 // Fill the predefined allocator map.
16789 bool ErrorFound = false;
16790 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
16791 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
16792 StringRef Allocator =
16793 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
16794 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
16795 auto *VD = dyn_cast_or_null<ValueDecl>(
16796 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
16797 if (!VD) {
16798 ErrorFound = true;
16799 break;
16801 QualType AllocatorType =
16802 VD->getType().getNonLValueExprType(S.getASTContext());
16803 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
16804 if (!Res.isUsable()) {
16805 ErrorFound = true;
16806 break;
16808 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
16809 Sema::AA_Initializing,
16810 /* AllowExplicit */ true);
16811 if (!Res.isUsable()) {
16812 ErrorFound = true;
16813 break;
16815 Stack->setAllocator(AllocatorKind, Res.get());
16817 if (ErrorFound) {
16818 S.Diag(Loc, diag::err_omp_implied_type_not_found)
16819 << "omp_allocator_handle_t";
16820 return false;
16823 return true;
16826 OMPClause *Sema::ActOnOpenMPAllocatorClause(Expr *A, SourceLocation StartLoc,
16827 SourceLocation LParenLoc,
16828 SourceLocation EndLoc) {
16829 // OpenMP [2.11.3, allocate Directive, Description]
16830 // allocator is an expression of omp_allocator_handle_t type.
16831 if (!findOMPAllocatorHandleT(*this, A->getExprLoc(), DSAStack))
16832 return nullptr;
16834 ExprResult Allocator = DefaultLvalueConversion(A);
16835 if (Allocator.isInvalid())
16836 return nullptr;
16837 Allocator = PerformImplicitConversion(Allocator.get(),
16838 DSAStack->getOMPAllocatorHandleT(),
16839 Sema::AA_Initializing,
16840 /*AllowExplicit=*/true);
16841 if (Allocator.isInvalid())
16842 return nullptr;
16843 return new (Context)
16844 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
16847 OMPClause *Sema::ActOnOpenMPCollapseClause(Expr *NumForLoops,
16848 SourceLocation StartLoc,
16849 SourceLocation LParenLoc,
16850 SourceLocation EndLoc) {
16851 // OpenMP [2.7.1, loop construct, Description]
16852 // OpenMP [2.8.1, simd construct, Description]
16853 // OpenMP [2.9.6, distribute construct, Description]
16854 // The parameter of the collapse clause must be a constant
16855 // positive integer expression.
16856 ExprResult NumForLoopsResult =
16857 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
16858 if (NumForLoopsResult.isInvalid())
16859 return nullptr;
16860 return new (Context)
16861 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
16864 OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc,
16865 SourceLocation EndLoc,
16866 SourceLocation LParenLoc,
16867 Expr *NumForLoops) {
16868 // OpenMP [2.7.1, loop construct, Description]
16869 // OpenMP [2.8.1, simd construct, Description]
16870 // OpenMP [2.9.6, distribute construct, Description]
16871 // The parameter of the ordered clause must be a constant
16872 // positive integer expression if any.
16873 if (NumForLoops && LParenLoc.isValid()) {
16874 ExprResult NumForLoopsResult =
16875 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
16876 if (NumForLoopsResult.isInvalid())
16877 return nullptr;
16878 NumForLoops = NumForLoopsResult.get();
16879 } else {
16880 NumForLoops = nullptr;
16882 auto *Clause = OMPOrderedClause::Create(
16883 Context, NumForLoops, NumForLoops ? DSAStack->getAssociatedLoops() : 0,
16884 StartLoc, LParenLoc, EndLoc);
16885 DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
16886 return Clause;
16889 OMPClause *Sema::ActOnOpenMPSimpleClause(
16890 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
16891 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
16892 OMPClause *Res = nullptr;
16893 switch (Kind) {
16894 case OMPC_default:
16895 Res = ActOnOpenMPDefaultClause(static_cast<DefaultKind>(Argument),
16896 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16897 break;
16898 case OMPC_proc_bind:
16899 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
16900 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16901 break;
16902 case OMPC_atomic_default_mem_order:
16903 Res = ActOnOpenMPAtomicDefaultMemOrderClause(
16904 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
16905 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16906 break;
16907 case OMPC_fail:
16908 Res = ActOnOpenMPFailClause(
16909 static_cast<OpenMPClauseKind>(Argument),
16910 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16911 break;
16912 case OMPC_update:
16913 Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument),
16914 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16915 break;
16916 case OMPC_bind:
16917 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
16918 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16919 break;
16920 case OMPC_at:
16921 Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
16922 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16923 break;
16924 case OMPC_severity:
16925 Res = ActOnOpenMPSeverityClause(
16926 static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc,
16927 LParenLoc, EndLoc);
16928 break;
16929 case OMPC_if:
16930 case OMPC_final:
16931 case OMPC_num_threads:
16932 case OMPC_safelen:
16933 case OMPC_simdlen:
16934 case OMPC_sizes:
16935 case OMPC_allocator:
16936 case OMPC_collapse:
16937 case OMPC_schedule:
16938 case OMPC_private:
16939 case OMPC_firstprivate:
16940 case OMPC_lastprivate:
16941 case OMPC_shared:
16942 case OMPC_reduction:
16943 case OMPC_task_reduction:
16944 case OMPC_in_reduction:
16945 case OMPC_linear:
16946 case OMPC_aligned:
16947 case OMPC_copyin:
16948 case OMPC_copyprivate:
16949 case OMPC_ordered:
16950 case OMPC_nowait:
16951 case OMPC_untied:
16952 case OMPC_mergeable:
16953 case OMPC_threadprivate:
16954 case OMPC_allocate:
16955 case OMPC_flush:
16956 case OMPC_depobj:
16957 case OMPC_read:
16958 case OMPC_write:
16959 case OMPC_capture:
16960 case OMPC_compare:
16961 case OMPC_seq_cst:
16962 case OMPC_acq_rel:
16963 case OMPC_acquire:
16964 case OMPC_release:
16965 case OMPC_relaxed:
16966 case OMPC_depend:
16967 case OMPC_device:
16968 case OMPC_threads:
16969 case OMPC_simd:
16970 case OMPC_map:
16971 case OMPC_num_teams:
16972 case OMPC_thread_limit:
16973 case OMPC_priority:
16974 case OMPC_grainsize:
16975 case OMPC_nogroup:
16976 case OMPC_num_tasks:
16977 case OMPC_hint:
16978 case OMPC_dist_schedule:
16979 case OMPC_defaultmap:
16980 case OMPC_unknown:
16981 case OMPC_uniform:
16982 case OMPC_to:
16983 case OMPC_from:
16984 case OMPC_use_device_ptr:
16985 case OMPC_use_device_addr:
16986 case OMPC_is_device_ptr:
16987 case OMPC_has_device_addr:
16988 case OMPC_unified_address:
16989 case OMPC_unified_shared_memory:
16990 case OMPC_reverse_offload:
16991 case OMPC_dynamic_allocators:
16992 case OMPC_device_type:
16993 case OMPC_match:
16994 case OMPC_nontemporal:
16995 case OMPC_destroy:
16996 case OMPC_novariants:
16997 case OMPC_nocontext:
16998 case OMPC_detach:
16999 case OMPC_inclusive:
17000 case OMPC_exclusive:
17001 case OMPC_uses_allocators:
17002 case OMPC_affinity:
17003 case OMPC_when:
17004 case OMPC_message:
17005 default:
17006 llvm_unreachable("Clause is not allowed.");
17008 return Res;
17011 static std::string
17012 getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last,
17013 ArrayRef<unsigned> Exclude = std::nullopt) {
17014 SmallString<256> Buffer;
17015 llvm::raw_svector_ostream Out(Buffer);
17016 unsigned Skipped = Exclude.size();
17017 for (unsigned I = First; I < Last; ++I) {
17018 if (llvm::is_contained(Exclude, I)) {
17019 --Skipped;
17020 continue;
17022 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
17023 if (I + Skipped + 2 == Last)
17024 Out << " or ";
17025 else if (I + Skipped + 1 != Last)
17026 Out << ", ";
17028 return std::string(Out.str());
17031 OMPClause *Sema::ActOnOpenMPDefaultClause(DefaultKind Kind,
17032 SourceLocation KindKwLoc,
17033 SourceLocation StartLoc,
17034 SourceLocation LParenLoc,
17035 SourceLocation EndLoc) {
17036 if (Kind == OMP_DEFAULT_unknown) {
17037 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17038 << getListOfPossibleValues(OMPC_default, /*First=*/0,
17039 /*Last=*/unsigned(OMP_DEFAULT_unknown))
17040 << getOpenMPClauseName(OMPC_default);
17041 return nullptr;
17044 switch (Kind) {
17045 case OMP_DEFAULT_none:
17046 DSAStack->setDefaultDSANone(KindKwLoc);
17047 break;
17048 case OMP_DEFAULT_shared:
17049 DSAStack->setDefaultDSAShared(KindKwLoc);
17050 break;
17051 case OMP_DEFAULT_firstprivate:
17052 DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
17053 break;
17054 case OMP_DEFAULT_private:
17055 DSAStack->setDefaultDSAPrivate(KindKwLoc);
17056 break;
17057 default:
17058 llvm_unreachable("DSA unexpected in OpenMP default clause");
17061 return new (Context)
17062 OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17065 OMPClause *Sema::ActOnOpenMPProcBindClause(ProcBindKind Kind,
17066 SourceLocation KindKwLoc,
17067 SourceLocation StartLoc,
17068 SourceLocation LParenLoc,
17069 SourceLocation EndLoc) {
17070 if (Kind == OMP_PROC_BIND_unknown) {
17071 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17072 << getListOfPossibleValues(OMPC_proc_bind,
17073 /*First=*/unsigned(OMP_PROC_BIND_master),
17074 /*Last=*/
17075 unsigned(LangOpts.OpenMP > 50
17076 ? OMP_PROC_BIND_primary
17077 : OMP_PROC_BIND_spread) +
17079 << getOpenMPClauseName(OMPC_proc_bind);
17080 return nullptr;
17082 if (Kind == OMP_PROC_BIND_primary && LangOpts.OpenMP < 51)
17083 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17084 << getListOfPossibleValues(OMPC_proc_bind,
17085 /*First=*/unsigned(OMP_PROC_BIND_master),
17086 /*Last=*/
17087 unsigned(OMP_PROC_BIND_spread) + 1)
17088 << getOpenMPClauseName(OMPC_proc_bind);
17089 return new (Context)
17090 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17093 OMPClause *Sema::ActOnOpenMPAtomicDefaultMemOrderClause(
17094 OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindKwLoc,
17095 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17096 if (Kind == OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown) {
17097 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17098 << getListOfPossibleValues(
17099 OMPC_atomic_default_mem_order, /*First=*/0,
17100 /*Last=*/OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown)
17101 << getOpenMPClauseName(OMPC_atomic_default_mem_order);
17102 return nullptr;
17104 return new (Context) OMPAtomicDefaultMemOrderClause(Kind, KindKwLoc, StartLoc,
17105 LParenLoc, EndLoc);
17108 OMPClause *Sema::ActOnOpenMPAtClause(OpenMPAtClauseKind Kind,
17109 SourceLocation KindKwLoc,
17110 SourceLocation StartLoc,
17111 SourceLocation LParenLoc,
17112 SourceLocation EndLoc) {
17113 if (Kind == OMPC_AT_unknown) {
17114 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17115 << getListOfPossibleValues(OMPC_at, /*First=*/0,
17116 /*Last=*/OMPC_AT_unknown)
17117 << getOpenMPClauseName(OMPC_at);
17118 return nullptr;
17120 return new (Context)
17121 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17124 OMPClause *Sema::ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind,
17125 SourceLocation KindKwLoc,
17126 SourceLocation StartLoc,
17127 SourceLocation LParenLoc,
17128 SourceLocation EndLoc) {
17129 if (Kind == OMPC_SEVERITY_unknown) {
17130 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17131 << getListOfPossibleValues(OMPC_severity, /*First=*/0,
17132 /*Last=*/OMPC_SEVERITY_unknown)
17133 << getOpenMPClauseName(OMPC_severity);
17134 return nullptr;
17136 return new (Context)
17137 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17140 OMPClause *Sema::ActOnOpenMPMessageClause(Expr *ME, SourceLocation StartLoc,
17141 SourceLocation LParenLoc,
17142 SourceLocation EndLoc) {
17143 assert(ME && "NULL expr in Message clause");
17144 if (!isa<StringLiteral>(ME)) {
17145 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
17146 << getOpenMPClauseName(OMPC_message);
17147 return nullptr;
17149 return new (Context) OMPMessageClause(ME, StartLoc, LParenLoc, EndLoc);
17152 OMPClause *Sema::ActOnOpenMPOrderClause(
17153 OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind,
17154 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
17155 SourceLocation KindLoc, SourceLocation EndLoc) {
17156 if (Kind != OMPC_ORDER_concurrent ||
17157 (LangOpts.OpenMP < 51 && MLoc.isValid())) {
17158 // Kind should be concurrent,
17159 // Modifiers introduced in OpenMP 5.1
17160 static_assert(OMPC_ORDER_unknown > 0,
17161 "OMPC_ORDER_unknown not greater than 0");
17163 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17164 << getListOfPossibleValues(OMPC_order,
17165 /*First=*/0,
17166 /*Last=*/OMPC_ORDER_unknown)
17167 << getOpenMPClauseName(OMPC_order);
17168 return nullptr;
17170 if (LangOpts.OpenMP >= 51) {
17171 if (Modifier == OMPC_ORDER_MODIFIER_unknown && MLoc.isValid()) {
17172 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17173 << getListOfPossibleValues(OMPC_order,
17174 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
17175 /*Last=*/OMPC_ORDER_MODIFIER_last)
17176 << getOpenMPClauseName(OMPC_order);
17177 } else {
17178 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
17179 if (DSAStack->getCurScope()) {
17180 // mark the current scope with 'order' flag
17181 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
17182 DSAStack->getCurScope()->setFlags(existingFlags |
17183 Scope::OpenMPOrderClauseScope);
17187 return new (Context) OMPOrderClause(Kind, KindLoc, StartLoc, LParenLoc,
17188 EndLoc, Modifier, MLoc);
17191 OMPClause *Sema::ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind,
17192 SourceLocation KindKwLoc,
17193 SourceLocation StartLoc,
17194 SourceLocation LParenLoc,
17195 SourceLocation EndLoc) {
17196 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
17197 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
17198 SmallVector<unsigned> Except = {
17199 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
17200 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
17201 if (LangOpts.OpenMP < 51)
17202 Except.push_back(OMPC_DEPEND_inoutset);
17203 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17204 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
17205 /*Last=*/OMPC_DEPEND_unknown, Except)
17206 << getOpenMPClauseName(OMPC_update);
17207 return nullptr;
17209 return OMPUpdateClause::Create(Context, StartLoc, LParenLoc, KindKwLoc, Kind,
17210 EndLoc);
17213 OMPClause *Sema::ActOnOpenMPSizesClause(ArrayRef<Expr *> SizeExprs,
17214 SourceLocation StartLoc,
17215 SourceLocation LParenLoc,
17216 SourceLocation EndLoc) {
17217 for (Expr *SizeExpr : SizeExprs) {
17218 ExprResult NumForLoopsResult = VerifyPositiveIntegerConstantInClause(
17219 SizeExpr, OMPC_sizes, /*StrictlyPositive=*/true);
17220 if (!NumForLoopsResult.isUsable())
17221 return nullptr;
17224 DSAStack->setAssociatedLoops(SizeExprs.size());
17225 return OMPSizesClause::Create(Context, StartLoc, LParenLoc, EndLoc,
17226 SizeExprs);
17229 OMPClause *Sema::ActOnOpenMPFullClause(SourceLocation StartLoc,
17230 SourceLocation EndLoc) {
17231 return OMPFullClause::Create(Context, StartLoc, EndLoc);
17234 OMPClause *Sema::ActOnOpenMPPartialClause(Expr *FactorExpr,
17235 SourceLocation StartLoc,
17236 SourceLocation LParenLoc,
17237 SourceLocation EndLoc) {
17238 if (FactorExpr) {
17239 // If an argument is specified, it must be a constant (or an unevaluated
17240 // template expression).
17241 ExprResult FactorResult = VerifyPositiveIntegerConstantInClause(
17242 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
17243 if (FactorResult.isInvalid())
17244 return nullptr;
17245 FactorExpr = FactorResult.get();
17248 return OMPPartialClause::Create(Context, StartLoc, LParenLoc, EndLoc,
17249 FactorExpr);
17252 OMPClause *Sema::ActOnOpenMPAlignClause(Expr *A, SourceLocation StartLoc,
17253 SourceLocation LParenLoc,
17254 SourceLocation EndLoc) {
17255 ExprResult AlignVal;
17256 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
17257 if (AlignVal.isInvalid())
17258 return nullptr;
17259 return OMPAlignClause::Create(Context, AlignVal.get(), StartLoc, LParenLoc,
17260 EndLoc);
17263 OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
17264 OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr,
17265 SourceLocation StartLoc, SourceLocation LParenLoc,
17266 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
17267 SourceLocation EndLoc) {
17268 OMPClause *Res = nullptr;
17269 switch (Kind) {
17270 case OMPC_schedule:
17271 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
17272 assert(Argument.size() == NumberOfElements &&
17273 ArgumentLoc.size() == NumberOfElements);
17274 Res = ActOnOpenMPScheduleClause(
17275 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
17276 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
17277 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
17278 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
17279 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
17280 break;
17281 case OMPC_if:
17282 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17283 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
17284 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
17285 DelimLoc, EndLoc);
17286 break;
17287 case OMPC_dist_schedule:
17288 Res = ActOnOpenMPDistScheduleClause(
17289 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
17290 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
17291 break;
17292 case OMPC_defaultmap:
17293 enum { Modifier, DefaultmapKind };
17294 Res = ActOnOpenMPDefaultmapClause(
17295 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
17296 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
17297 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
17298 EndLoc);
17299 break;
17300 case OMPC_order:
17301 enum { OrderModifier, OrderKind };
17302 Res = ActOnOpenMPOrderClause(
17303 static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
17304 static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
17305 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
17306 break;
17307 case OMPC_device:
17308 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17309 Res = ActOnOpenMPDeviceClause(
17310 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
17311 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17312 break;
17313 case OMPC_grainsize:
17314 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17315 "Modifier for grainsize clause and its location are expected.");
17316 Res = ActOnOpenMPGrainsizeClause(
17317 static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr,
17318 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17319 break;
17320 case OMPC_num_tasks:
17321 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17322 "Modifier for num_tasks clause and its location are expected.");
17323 Res = ActOnOpenMPNumTasksClause(
17324 static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
17325 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17326 break;
17327 case OMPC_final:
17328 case OMPC_num_threads:
17329 case OMPC_safelen:
17330 case OMPC_simdlen:
17331 case OMPC_sizes:
17332 case OMPC_allocator:
17333 case OMPC_collapse:
17334 case OMPC_default:
17335 case OMPC_proc_bind:
17336 case OMPC_private:
17337 case OMPC_firstprivate:
17338 case OMPC_lastprivate:
17339 case OMPC_shared:
17340 case OMPC_reduction:
17341 case OMPC_task_reduction:
17342 case OMPC_in_reduction:
17343 case OMPC_linear:
17344 case OMPC_aligned:
17345 case OMPC_copyin:
17346 case OMPC_copyprivate:
17347 case OMPC_ordered:
17348 case OMPC_nowait:
17349 case OMPC_untied:
17350 case OMPC_mergeable:
17351 case OMPC_threadprivate:
17352 case OMPC_allocate:
17353 case OMPC_flush:
17354 case OMPC_depobj:
17355 case OMPC_read:
17356 case OMPC_write:
17357 case OMPC_update:
17358 case OMPC_capture:
17359 case OMPC_compare:
17360 case OMPC_seq_cst:
17361 case OMPC_acq_rel:
17362 case OMPC_acquire:
17363 case OMPC_release:
17364 case OMPC_relaxed:
17365 case OMPC_depend:
17366 case OMPC_threads:
17367 case OMPC_simd:
17368 case OMPC_map:
17369 case OMPC_num_teams:
17370 case OMPC_thread_limit:
17371 case OMPC_priority:
17372 case OMPC_nogroup:
17373 case OMPC_hint:
17374 case OMPC_unknown:
17375 case OMPC_uniform:
17376 case OMPC_to:
17377 case OMPC_from:
17378 case OMPC_use_device_ptr:
17379 case OMPC_use_device_addr:
17380 case OMPC_is_device_ptr:
17381 case OMPC_has_device_addr:
17382 case OMPC_unified_address:
17383 case OMPC_unified_shared_memory:
17384 case OMPC_reverse_offload:
17385 case OMPC_dynamic_allocators:
17386 case OMPC_atomic_default_mem_order:
17387 case OMPC_device_type:
17388 case OMPC_match:
17389 case OMPC_nontemporal:
17390 case OMPC_at:
17391 case OMPC_severity:
17392 case OMPC_message:
17393 case OMPC_destroy:
17394 case OMPC_novariants:
17395 case OMPC_nocontext:
17396 case OMPC_detach:
17397 case OMPC_inclusive:
17398 case OMPC_exclusive:
17399 case OMPC_uses_allocators:
17400 case OMPC_affinity:
17401 case OMPC_when:
17402 case OMPC_bind:
17403 default:
17404 llvm_unreachable("Clause is not allowed.");
17406 return Res;
17409 static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1,
17410 OpenMPScheduleClauseModifier M2,
17411 SourceLocation M1Loc, SourceLocation M2Loc) {
17412 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
17413 SmallVector<unsigned, 2> Excluded;
17414 if (M2 != OMPC_SCHEDULE_MODIFIER_unknown)
17415 Excluded.push_back(M2);
17416 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
17417 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
17418 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
17419 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
17420 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
17421 << getListOfPossibleValues(OMPC_schedule,
17422 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
17423 /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
17424 Excluded)
17425 << getOpenMPClauseName(OMPC_schedule);
17426 return true;
17428 return false;
17431 OMPClause *Sema::ActOnOpenMPScheduleClause(
17432 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
17433 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
17434 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
17435 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
17436 if (checkScheduleModifiers(*this, M1, M2, M1Loc, M2Loc) ||
17437 checkScheduleModifiers(*this, M2, M1, M2Loc, M1Loc))
17438 return nullptr;
17439 // OpenMP, 2.7.1, Loop Construct, Restrictions
17440 // Either the monotonic modifier or the nonmonotonic modifier can be specified
17441 // but not both.
17442 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
17443 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
17444 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
17445 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
17446 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
17447 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
17448 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
17449 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
17450 return nullptr;
17452 if (Kind == OMPC_SCHEDULE_unknown) {
17453 std::string Values;
17454 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
17455 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
17456 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
17457 /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
17458 Exclude);
17459 } else {
17460 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
17461 /*Last=*/OMPC_SCHEDULE_unknown);
17463 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17464 << Values << getOpenMPClauseName(OMPC_schedule);
17465 return nullptr;
17467 // OpenMP, 2.7.1, Loop Construct, Restrictions
17468 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
17469 // schedule(guided).
17470 // OpenMP 5.0 does not have this restriction.
17471 if (LangOpts.OpenMP < 50 &&
17472 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
17473 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
17474 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
17475 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
17476 diag::err_omp_schedule_nonmonotonic_static);
17477 return nullptr;
17479 Expr *ValExpr = ChunkSize;
17480 Stmt *HelperValStmt = nullptr;
17481 if (ChunkSize) {
17482 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
17483 !ChunkSize->isInstantiationDependent() &&
17484 !ChunkSize->containsUnexpandedParameterPack()) {
17485 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
17486 ExprResult Val =
17487 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
17488 if (Val.isInvalid())
17489 return nullptr;
17491 ValExpr = Val.get();
17493 // OpenMP [2.7.1, Restrictions]
17494 // chunk_size must be a loop invariant integer expression with a positive
17495 // value.
17496 if (std::optional<llvm::APSInt> Result =
17497 ValExpr->getIntegerConstantExpr(Context)) {
17498 if (Result->isSigned() && !Result->isStrictlyPositive()) {
17499 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
17500 << "schedule" << 1 << ChunkSize->getSourceRange();
17501 return nullptr;
17503 } else if (getOpenMPCaptureRegionForClause(
17504 DSAStack->getCurrentDirective(), OMPC_schedule,
17505 LangOpts.OpenMP) != OMPD_unknown &&
17506 !CurContext->isDependentContext()) {
17507 ValExpr = MakeFullExpr(ValExpr).get();
17508 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17509 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
17510 HelperValStmt = buildPreInits(Context, Captures);
17515 return new (Context)
17516 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
17517 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
17520 OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
17521 SourceLocation StartLoc,
17522 SourceLocation EndLoc) {
17523 OMPClause *Res = nullptr;
17524 switch (Kind) {
17525 case OMPC_ordered:
17526 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
17527 break;
17528 case OMPC_nowait:
17529 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc);
17530 break;
17531 case OMPC_untied:
17532 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
17533 break;
17534 case OMPC_mergeable:
17535 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
17536 break;
17537 case OMPC_read:
17538 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
17539 break;
17540 case OMPC_write:
17541 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
17542 break;
17543 case OMPC_update:
17544 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
17545 break;
17546 case OMPC_capture:
17547 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
17548 break;
17549 case OMPC_compare:
17550 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
17551 break;
17552 case OMPC_fail:
17553 Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
17554 break;
17555 case OMPC_seq_cst:
17556 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
17557 break;
17558 case OMPC_acq_rel:
17559 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
17560 break;
17561 case OMPC_acquire:
17562 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
17563 break;
17564 case OMPC_release:
17565 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
17566 break;
17567 case OMPC_relaxed:
17568 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
17569 break;
17570 case OMPC_threads:
17571 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
17572 break;
17573 case OMPC_simd:
17574 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
17575 break;
17576 case OMPC_nogroup:
17577 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
17578 break;
17579 case OMPC_unified_address:
17580 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
17581 break;
17582 case OMPC_unified_shared_memory:
17583 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
17584 break;
17585 case OMPC_reverse_offload:
17586 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
17587 break;
17588 case OMPC_dynamic_allocators:
17589 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
17590 break;
17591 case OMPC_destroy:
17592 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
17593 /*LParenLoc=*/SourceLocation(),
17594 /*VarLoc=*/SourceLocation(), EndLoc);
17595 break;
17596 case OMPC_full:
17597 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
17598 break;
17599 case OMPC_partial:
17600 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
17601 break;
17602 case OMPC_ompx_bare:
17603 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
17604 break;
17605 case OMPC_if:
17606 case OMPC_final:
17607 case OMPC_num_threads:
17608 case OMPC_safelen:
17609 case OMPC_simdlen:
17610 case OMPC_sizes:
17611 case OMPC_allocator:
17612 case OMPC_collapse:
17613 case OMPC_schedule:
17614 case OMPC_private:
17615 case OMPC_firstprivate:
17616 case OMPC_lastprivate:
17617 case OMPC_shared:
17618 case OMPC_reduction:
17619 case OMPC_task_reduction:
17620 case OMPC_in_reduction:
17621 case OMPC_linear:
17622 case OMPC_aligned:
17623 case OMPC_copyin:
17624 case OMPC_copyprivate:
17625 case OMPC_default:
17626 case OMPC_proc_bind:
17627 case OMPC_threadprivate:
17628 case OMPC_allocate:
17629 case OMPC_flush:
17630 case OMPC_depobj:
17631 case OMPC_depend:
17632 case OMPC_device:
17633 case OMPC_map:
17634 case OMPC_num_teams:
17635 case OMPC_thread_limit:
17636 case OMPC_priority:
17637 case OMPC_grainsize:
17638 case OMPC_num_tasks:
17639 case OMPC_hint:
17640 case OMPC_dist_schedule:
17641 case OMPC_defaultmap:
17642 case OMPC_unknown:
17643 case OMPC_uniform:
17644 case OMPC_to:
17645 case OMPC_from:
17646 case OMPC_use_device_ptr:
17647 case OMPC_use_device_addr:
17648 case OMPC_is_device_ptr:
17649 case OMPC_has_device_addr:
17650 case OMPC_atomic_default_mem_order:
17651 case OMPC_device_type:
17652 case OMPC_match:
17653 case OMPC_nontemporal:
17654 case OMPC_order:
17655 case OMPC_at:
17656 case OMPC_severity:
17657 case OMPC_message:
17658 case OMPC_novariants:
17659 case OMPC_nocontext:
17660 case OMPC_detach:
17661 case OMPC_inclusive:
17662 case OMPC_exclusive:
17663 case OMPC_uses_allocators:
17664 case OMPC_affinity:
17665 case OMPC_when:
17666 case OMPC_ompx_dyn_cgroup_mem:
17667 default:
17668 llvm_unreachable("Clause is not allowed.");
17670 return Res;
17673 OMPClause *Sema::ActOnOpenMPNowaitClause(SourceLocation StartLoc,
17674 SourceLocation EndLoc) {
17675 DSAStack->setNowaitRegion();
17676 return new (Context) OMPNowaitClause(StartLoc, EndLoc);
17679 OMPClause *Sema::ActOnOpenMPUntiedClause(SourceLocation StartLoc,
17680 SourceLocation EndLoc) {
17681 DSAStack->setUntiedRegion();
17682 return new (Context) OMPUntiedClause(StartLoc, EndLoc);
17685 OMPClause *Sema::ActOnOpenMPMergeableClause(SourceLocation StartLoc,
17686 SourceLocation EndLoc) {
17687 return new (Context) OMPMergeableClause(StartLoc, EndLoc);
17690 OMPClause *Sema::ActOnOpenMPReadClause(SourceLocation StartLoc,
17691 SourceLocation EndLoc) {
17692 return new (Context) OMPReadClause(StartLoc, EndLoc);
17695 OMPClause *Sema::ActOnOpenMPWriteClause(SourceLocation StartLoc,
17696 SourceLocation EndLoc) {
17697 return new (Context) OMPWriteClause(StartLoc, EndLoc);
17700 OMPClause *Sema::ActOnOpenMPUpdateClause(SourceLocation StartLoc,
17701 SourceLocation EndLoc) {
17702 return OMPUpdateClause::Create(Context, StartLoc, EndLoc);
17705 OMPClause *Sema::ActOnOpenMPCaptureClause(SourceLocation StartLoc,
17706 SourceLocation EndLoc) {
17707 return new (Context) OMPCaptureClause(StartLoc, EndLoc);
17710 OMPClause *Sema::ActOnOpenMPCompareClause(SourceLocation StartLoc,
17711 SourceLocation EndLoc) {
17712 return new (Context) OMPCompareClause(StartLoc, EndLoc);
17715 OMPClause *Sema::ActOnOpenMPFailClause(SourceLocation StartLoc,
17716 SourceLocation EndLoc) {
17717 return new (Context) OMPFailClause(StartLoc, EndLoc);
17720 OMPClause *Sema::ActOnOpenMPFailClause(
17721 OpenMPClauseKind Parameter, SourceLocation KindLoc,
17722 SourceLocation StartLoc, SourceLocation LParenLoc,
17723 SourceLocation EndLoc) {
17725 if (!checkFailClauseParameter(Parameter)) {
17726 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
17727 return nullptr;
17729 return new (Context)
17730 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
17733 OMPClause *Sema::ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
17734 SourceLocation EndLoc) {
17735 return new (Context) OMPSeqCstClause(StartLoc, EndLoc);
17738 OMPClause *Sema::ActOnOpenMPAcqRelClause(SourceLocation StartLoc,
17739 SourceLocation EndLoc) {
17740 return new (Context) OMPAcqRelClause(StartLoc, EndLoc);
17743 OMPClause *Sema::ActOnOpenMPAcquireClause(SourceLocation StartLoc,
17744 SourceLocation EndLoc) {
17745 return new (Context) OMPAcquireClause(StartLoc, EndLoc);
17748 OMPClause *Sema::ActOnOpenMPReleaseClause(SourceLocation StartLoc,
17749 SourceLocation EndLoc) {
17750 return new (Context) OMPReleaseClause(StartLoc, EndLoc);
17753 OMPClause *Sema::ActOnOpenMPRelaxedClause(SourceLocation StartLoc,
17754 SourceLocation EndLoc) {
17755 return new (Context) OMPRelaxedClause(StartLoc, EndLoc);
17758 OMPClause *Sema::ActOnOpenMPThreadsClause(SourceLocation StartLoc,
17759 SourceLocation EndLoc) {
17760 return new (Context) OMPThreadsClause(StartLoc, EndLoc);
17763 OMPClause *Sema::ActOnOpenMPSIMDClause(SourceLocation StartLoc,
17764 SourceLocation EndLoc) {
17765 return new (Context) OMPSIMDClause(StartLoc, EndLoc);
17768 OMPClause *Sema::ActOnOpenMPNogroupClause(SourceLocation StartLoc,
17769 SourceLocation EndLoc) {
17770 return new (Context) OMPNogroupClause(StartLoc, EndLoc);
17773 OMPClause *Sema::ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc,
17774 SourceLocation EndLoc) {
17775 return new (Context) OMPUnifiedAddressClause(StartLoc, EndLoc);
17778 OMPClause *Sema::ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc,
17779 SourceLocation EndLoc) {
17780 return new (Context) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
17783 OMPClause *Sema::ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc,
17784 SourceLocation EndLoc) {
17785 return new (Context) OMPReverseOffloadClause(StartLoc, EndLoc);
17788 OMPClause *Sema::ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc,
17789 SourceLocation EndLoc) {
17790 return new (Context) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
17793 StmtResult Sema::ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses,
17794 SourceLocation StartLoc,
17795 SourceLocation EndLoc) {
17797 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17798 // At least one action-clause must appear on a directive.
17799 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
17800 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
17801 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
17802 << Expected << getOpenMPDirectiveName(OMPD_interop);
17803 return StmtError();
17806 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17807 // A depend clause can only appear on the directive if a targetsync
17808 // interop-type is present or the interop-var was initialized with
17809 // the targetsync interop-type.
17811 // If there is any 'init' clause diagnose if there is no 'init' clause with
17812 // interop-type of 'targetsync'. Cases involving other directives cannot be
17813 // diagnosed.
17814 const OMPDependClause *DependClause = nullptr;
17815 bool HasInitClause = false;
17816 bool IsTargetSync = false;
17817 for (const OMPClause *C : Clauses) {
17818 if (IsTargetSync)
17819 break;
17820 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
17821 HasInitClause = true;
17822 if (InitClause->getIsTargetSync())
17823 IsTargetSync = true;
17824 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
17825 DependClause = DC;
17828 if (DependClause && HasInitClause && !IsTargetSync) {
17829 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
17830 return StmtError();
17833 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17834 // Each interop-var may be specified for at most one action-clause of each
17835 // interop construct.
17836 llvm::SmallPtrSet<const ValueDecl *, 4> InteropVars;
17837 for (OMPClause *C : Clauses) {
17838 OpenMPClauseKind ClauseKind = C->getClauseKind();
17839 std::pair<ValueDecl *, bool> DeclResult;
17840 SourceLocation ELoc;
17841 SourceRange ERange;
17843 if (ClauseKind == OMPC_init) {
17844 auto *E = cast<OMPInitClause>(C)->getInteropVar();
17845 DeclResult = getPrivateItem(*this, E, ELoc, ERange);
17846 } else if (ClauseKind == OMPC_use) {
17847 auto *E = cast<OMPUseClause>(C)->getInteropVar();
17848 DeclResult = getPrivateItem(*this, E, ELoc, ERange);
17849 } else if (ClauseKind == OMPC_destroy) {
17850 auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
17851 DeclResult = getPrivateItem(*this, E, ELoc, ERange);
17854 if (DeclResult.first) {
17855 if (!InteropVars.insert(DeclResult.first).second) {
17856 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
17857 << DeclResult.first;
17858 return StmtError();
17863 return OMPInteropDirective::Create(Context, StartLoc, EndLoc, Clauses);
17866 static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
17867 SourceLocation VarLoc,
17868 OpenMPClauseKind Kind) {
17869 SourceLocation ELoc;
17870 SourceRange ERange;
17871 Expr *RefExpr = InteropVarExpr;
17872 auto Res =
17873 getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
17874 /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t");
17876 if (Res.second) {
17877 // It will be analyzed later.
17878 return true;
17881 if (!Res.first)
17882 return false;
17884 // Interop variable should be of type omp_interop_t.
17885 bool HasError = false;
17886 QualType InteropType;
17887 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
17888 VarLoc, Sema::LookupOrdinaryName);
17889 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
17890 NamedDecl *ND = Result.getFoundDecl();
17891 if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
17892 InteropType = QualType(TD->getTypeForDecl(), 0);
17893 } else {
17894 HasError = true;
17896 } else {
17897 HasError = true;
17900 if (HasError) {
17901 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
17902 << "omp_interop_t";
17903 return false;
17906 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
17907 if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
17908 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
17909 return false;
17912 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17913 // The interop-var passed to init or destroy must be non-const.
17914 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
17915 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
17916 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
17917 << /*non-const*/ 1;
17918 return false;
17920 return true;
17923 OMPClause *
17924 Sema::ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo,
17925 SourceLocation StartLoc, SourceLocation LParenLoc,
17926 SourceLocation VarLoc, SourceLocation EndLoc) {
17928 if (!isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_init))
17929 return nullptr;
17931 // Check prefer_type values. These foreign-runtime-id values are either
17932 // string literals or constant integral expressions.
17933 for (const Expr *E : InteropInfo.PreferTypes) {
17934 if (E->isValueDependent() || E->isTypeDependent() ||
17935 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
17936 continue;
17937 if (E->isIntegerConstantExpr(Context))
17938 continue;
17939 if (isa<StringLiteral>(E))
17940 continue;
17941 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
17942 return nullptr;
17945 return OMPInitClause::Create(Context, InteropVar, InteropInfo, StartLoc,
17946 LParenLoc, VarLoc, EndLoc);
17949 OMPClause *Sema::ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc,
17950 SourceLocation LParenLoc,
17951 SourceLocation VarLoc,
17952 SourceLocation EndLoc) {
17954 if (!isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_use))
17955 return nullptr;
17957 return new (Context)
17958 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
17961 OMPClause *Sema::ActOnOpenMPDestroyClause(Expr *InteropVar,
17962 SourceLocation StartLoc,
17963 SourceLocation LParenLoc,
17964 SourceLocation VarLoc,
17965 SourceLocation EndLoc) {
17966 if (!InteropVar && LangOpts.OpenMP >= 52 &&
17967 DSAStack->getCurrentDirective() == OMPD_depobj) {
17968 Diag(StartLoc, diag::err_omp_expected_clause_argument)
17969 << getOpenMPClauseName(OMPC_destroy)
17970 << getOpenMPDirectiveName(OMPD_depobj);
17971 return nullptr;
17973 if (InteropVar &&
17974 !isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_destroy))
17975 return nullptr;
17977 return new (Context)
17978 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
17981 OMPClause *Sema::ActOnOpenMPNovariantsClause(Expr *Condition,
17982 SourceLocation StartLoc,
17983 SourceLocation LParenLoc,
17984 SourceLocation EndLoc) {
17985 Expr *ValExpr = Condition;
17986 Stmt *HelperValStmt = nullptr;
17987 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17988 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17989 !Condition->isInstantiationDependent() &&
17990 !Condition->containsUnexpandedParameterPack()) {
17991 ExprResult Val = CheckBooleanCondition(StartLoc, Condition);
17992 if (Val.isInvalid())
17993 return nullptr;
17995 ValExpr = MakeFullExpr(Val.get()).get();
17997 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17998 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
17999 LangOpts.OpenMP);
18000 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
18001 ValExpr = MakeFullExpr(ValExpr).get();
18002 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18003 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
18004 HelperValStmt = buildPreInits(Context, Captures);
18008 return new (Context) OMPNovariantsClause(
18009 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18012 OMPClause *Sema::ActOnOpenMPNocontextClause(Expr *Condition,
18013 SourceLocation StartLoc,
18014 SourceLocation LParenLoc,
18015 SourceLocation EndLoc) {
18016 Expr *ValExpr = Condition;
18017 Stmt *HelperValStmt = nullptr;
18018 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
18019 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18020 !Condition->isInstantiationDependent() &&
18021 !Condition->containsUnexpandedParameterPack()) {
18022 ExprResult Val = CheckBooleanCondition(StartLoc, Condition);
18023 if (Val.isInvalid())
18024 return nullptr;
18026 ValExpr = MakeFullExpr(Val.get()).get();
18028 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18029 CaptureRegion =
18030 getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext, LangOpts.OpenMP);
18031 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
18032 ValExpr = MakeFullExpr(ValExpr).get();
18033 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18034 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
18035 HelperValStmt = buildPreInits(Context, Captures);
18039 return new (Context) OMPNocontextClause(ValExpr, HelperValStmt, CaptureRegion,
18040 StartLoc, LParenLoc, EndLoc);
18043 OMPClause *Sema::ActOnOpenMPFilterClause(Expr *ThreadID,
18044 SourceLocation StartLoc,
18045 SourceLocation LParenLoc,
18046 SourceLocation EndLoc) {
18047 Expr *ValExpr = ThreadID;
18048 Stmt *HelperValStmt = nullptr;
18050 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18051 OpenMPDirectiveKind CaptureRegion =
18052 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, LangOpts.OpenMP);
18053 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
18054 ValExpr = MakeFullExpr(ValExpr).get();
18055 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18056 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
18057 HelperValStmt = buildPreInits(Context, Captures);
18060 return new (Context) OMPFilterClause(ValExpr, HelperValStmt, CaptureRegion,
18061 StartLoc, LParenLoc, EndLoc);
18064 OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
18065 ArrayRef<Expr *> VarList,
18066 const OMPVarListLocTy &Locs,
18067 OpenMPVarListDataTy &Data) {
18068 SourceLocation StartLoc = Locs.StartLoc;
18069 SourceLocation LParenLoc = Locs.LParenLoc;
18070 SourceLocation EndLoc = Locs.EndLoc;
18071 OMPClause *Res = nullptr;
18072 int ExtraModifier = Data.ExtraModifier;
18073 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
18074 SourceLocation ColonLoc = Data.ColonLoc;
18075 switch (Kind) {
18076 case OMPC_private:
18077 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18078 break;
18079 case OMPC_firstprivate:
18080 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18081 break;
18082 case OMPC_lastprivate:
18083 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
18084 "Unexpected lastprivate modifier.");
18085 Res = ActOnOpenMPLastprivateClause(
18086 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
18087 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
18088 break;
18089 case OMPC_shared:
18090 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
18091 break;
18092 case OMPC_reduction:
18093 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
18094 "Unexpected lastprivate modifier.");
18095 Res = ActOnOpenMPReductionClause(
18096 VarList, static_cast<OpenMPReductionClauseModifier>(ExtraModifier),
18097 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
18098 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18099 break;
18100 case OMPC_task_reduction:
18101 Res = ActOnOpenMPTaskReductionClause(
18102 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18103 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18104 break;
18105 case OMPC_in_reduction:
18106 Res = ActOnOpenMPInReductionClause(
18107 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18108 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18109 break;
18110 case OMPC_linear:
18111 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
18112 "Unexpected linear modifier.");
18113 Res = ActOnOpenMPLinearClause(
18114 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
18115 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
18116 ColonLoc, Data.StepModifierLoc, EndLoc);
18117 break;
18118 case OMPC_aligned:
18119 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
18120 LParenLoc, ColonLoc, EndLoc);
18121 break;
18122 case OMPC_copyin:
18123 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
18124 break;
18125 case OMPC_copyprivate:
18126 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18127 break;
18128 case OMPC_flush:
18129 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
18130 break;
18131 case OMPC_depend:
18132 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
18133 "Unexpected depend modifier.");
18134 Res = ActOnOpenMPDependClause(
18135 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
18136 ColonLoc, Data.OmpAllMemoryLoc},
18137 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
18138 break;
18139 case OMPC_map:
18140 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
18141 "Unexpected map modifier.");
18142 Res = ActOnOpenMPMapClause(
18143 Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
18144 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
18145 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
18146 ExtraModifierLoc, ColonLoc, VarList, Locs);
18147 break;
18148 case OMPC_to:
18149 Res =
18150 ActOnOpenMPToClause(Data.MotionModifiers, Data.MotionModifiersLoc,
18151 Data.ReductionOrMapperIdScopeSpec,
18152 Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
18153 break;
18154 case OMPC_from:
18155 Res = ActOnOpenMPFromClause(Data.MotionModifiers, Data.MotionModifiersLoc,
18156 Data.ReductionOrMapperIdScopeSpec,
18157 Data.ReductionOrMapperId, ColonLoc, VarList,
18158 Locs);
18159 break;
18160 case OMPC_use_device_ptr:
18161 Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
18162 break;
18163 case OMPC_use_device_addr:
18164 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
18165 break;
18166 case OMPC_is_device_ptr:
18167 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
18168 break;
18169 case OMPC_has_device_addr:
18170 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
18171 break;
18172 case OMPC_allocate:
18173 Res = ActOnOpenMPAllocateClause(Data.DepModOrTailExpr, VarList, StartLoc,
18174 LParenLoc, ColonLoc, EndLoc);
18175 break;
18176 case OMPC_nontemporal:
18177 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
18178 break;
18179 case OMPC_inclusive:
18180 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
18181 break;
18182 case OMPC_exclusive:
18183 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
18184 break;
18185 case OMPC_affinity:
18186 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
18187 Data.DepModOrTailExpr, VarList);
18188 break;
18189 case OMPC_doacross:
18190 Res = ActOnOpenMPDoacrossClause(
18191 static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
18192 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
18193 break;
18194 case OMPC_if:
18195 case OMPC_depobj:
18196 case OMPC_final:
18197 case OMPC_num_threads:
18198 case OMPC_safelen:
18199 case OMPC_simdlen:
18200 case OMPC_sizes:
18201 case OMPC_allocator:
18202 case OMPC_collapse:
18203 case OMPC_default:
18204 case OMPC_proc_bind:
18205 case OMPC_schedule:
18206 case OMPC_ordered:
18207 case OMPC_nowait:
18208 case OMPC_untied:
18209 case OMPC_mergeable:
18210 case OMPC_threadprivate:
18211 case OMPC_read:
18212 case OMPC_write:
18213 case OMPC_update:
18214 case OMPC_capture:
18215 case OMPC_compare:
18216 case OMPC_seq_cst:
18217 case OMPC_acq_rel:
18218 case OMPC_acquire:
18219 case OMPC_release:
18220 case OMPC_relaxed:
18221 case OMPC_device:
18222 case OMPC_threads:
18223 case OMPC_simd:
18224 case OMPC_num_teams:
18225 case OMPC_thread_limit:
18226 case OMPC_priority:
18227 case OMPC_grainsize:
18228 case OMPC_nogroup:
18229 case OMPC_num_tasks:
18230 case OMPC_hint:
18231 case OMPC_dist_schedule:
18232 case OMPC_defaultmap:
18233 case OMPC_unknown:
18234 case OMPC_uniform:
18235 case OMPC_unified_address:
18236 case OMPC_unified_shared_memory:
18237 case OMPC_reverse_offload:
18238 case OMPC_dynamic_allocators:
18239 case OMPC_atomic_default_mem_order:
18240 case OMPC_device_type:
18241 case OMPC_match:
18242 case OMPC_order:
18243 case OMPC_at:
18244 case OMPC_severity:
18245 case OMPC_message:
18246 case OMPC_destroy:
18247 case OMPC_novariants:
18248 case OMPC_nocontext:
18249 case OMPC_detach:
18250 case OMPC_uses_allocators:
18251 case OMPC_when:
18252 case OMPC_bind:
18253 default:
18254 llvm_unreachable("Clause is not allowed.");
18256 return Res;
18259 ExprResult Sema::getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
18260 ExprObjectKind OK, SourceLocation Loc) {
18261 ExprResult Res = BuildDeclRefExpr(
18262 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
18263 if (!Res.isUsable())
18264 return ExprError();
18265 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
18266 Res = CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
18267 if (!Res.isUsable())
18268 return ExprError();
18270 if (VK != VK_LValue && Res.get()->isGLValue()) {
18271 Res = DefaultLvalueConversion(Res.get());
18272 if (!Res.isUsable())
18273 return ExprError();
18275 return Res;
18278 OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
18279 SourceLocation StartLoc,
18280 SourceLocation LParenLoc,
18281 SourceLocation EndLoc) {
18282 SmallVector<Expr *, 8> Vars;
18283 SmallVector<Expr *, 8> PrivateCopies;
18284 bool IsImplicitClause =
18285 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
18286 for (Expr *RefExpr : VarList) {
18287 assert(RefExpr && "NULL expr in OpenMP private clause.");
18288 SourceLocation ELoc;
18289 SourceRange ERange;
18290 Expr *SimpleRefExpr = RefExpr;
18291 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
18292 if (Res.second) {
18293 // It will be analyzed later.
18294 Vars.push_back(RefExpr);
18295 PrivateCopies.push_back(nullptr);
18297 ValueDecl *D = Res.first;
18298 if (!D)
18299 continue;
18301 QualType Type = D->getType();
18302 auto *VD = dyn_cast<VarDecl>(D);
18304 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18305 // A variable that appears in a private clause must not have an incomplete
18306 // type or a reference type.
18307 if (RequireCompleteType(ELoc, Type, diag::err_omp_private_incomplete_type))
18308 continue;
18309 Type = Type.getNonReferenceType();
18311 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18312 // A variable that is privatized must not have a const-qualified type
18313 // unless it is of class type with a mutable member. This restriction does
18314 // not apply to the firstprivate clause.
18316 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
18317 // A variable that appears in a private clause must not have a
18318 // const-qualified type unless it is of class type with a mutable member.
18319 if (rejectConstNotMutableType(*this, D, Type, OMPC_private, ELoc))
18320 continue;
18322 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18323 // in a Construct]
18324 // Variables with the predetermined data-sharing attributes may not be
18325 // listed in data-sharing attributes clauses, except for the cases
18326 // listed below. For these exceptions only, listing a predetermined
18327 // variable in a data-sharing attribute clause is allowed and overrides
18328 // the variable's predetermined data-sharing attributes.
18329 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18330 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
18331 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
18332 << getOpenMPClauseName(OMPC_private);
18333 reportOriginalDsa(*this, DSAStack, D, DVar);
18334 continue;
18337 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18338 // Variably modified types are not supported for tasks.
18339 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
18340 isOpenMPTaskingDirective(CurrDir)) {
18341 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18342 << getOpenMPClauseName(OMPC_private) << Type
18343 << getOpenMPDirectiveName(CurrDir);
18344 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18345 VarDecl::DeclarationOnly;
18346 Diag(D->getLocation(),
18347 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18348 << D;
18349 continue;
18352 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18353 // A list item cannot appear in both a map clause and a data-sharing
18354 // attribute clause on the same construct
18356 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18357 // A list item cannot appear in both a map clause and a data-sharing
18358 // attribute clause on the same construct unless the construct is a
18359 // combined construct.
18360 if ((LangOpts.OpenMP <= 45 && isOpenMPTargetExecutionDirective(CurrDir)) ||
18361 CurrDir == OMPD_target) {
18362 OpenMPClauseKind ConflictKind;
18363 if (DSAStack->checkMappableExprComponentListsForDecl(
18364 VD, /*CurrentRegionOnly=*/true,
18365 [&](OMPClauseMappableExprCommon::MappableExprComponentListRef,
18366 OpenMPClauseKind WhereFoundClauseKind) -> bool {
18367 ConflictKind = WhereFoundClauseKind;
18368 return true;
18369 })) {
18370 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18371 << getOpenMPClauseName(OMPC_private)
18372 << getOpenMPClauseName(ConflictKind)
18373 << getOpenMPDirectiveName(CurrDir);
18374 reportOriginalDsa(*this, DSAStack, D, DVar);
18375 continue;
18379 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
18380 // A variable of class type (or array thereof) that appears in a private
18381 // clause requires an accessible, unambiguous default constructor for the
18382 // class type.
18383 // Generate helper private variable and initialize it with the default
18384 // value. The address of the original variable is replaced by the address of
18385 // the new private variable in CodeGen. This new variable is not added to
18386 // IdResolver, so the code in the OpenMP region uses original variable for
18387 // proper diagnostics.
18388 Type = Type.getUnqualifiedType();
18389 VarDecl *VDPrivate =
18390 buildVarDecl(*this, ELoc, Type, D->getName(),
18391 D->hasAttrs() ? &D->getAttrs() : nullptr,
18392 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18393 ActOnUninitializedDecl(VDPrivate);
18394 if (VDPrivate->isInvalidDecl())
18395 continue;
18396 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18397 *this, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
18399 DeclRefExpr *Ref = nullptr;
18400 if (!VD && !CurContext->isDependentContext()) {
18401 auto *FD = dyn_cast<FieldDecl>(D);
18402 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
18403 if (VD)
18404 Ref = buildDeclRefExpr(*this, VD, VD->getType().getNonReferenceType(),
18405 RefExpr->getExprLoc());
18406 else
18407 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
18409 if (!IsImplicitClause)
18410 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
18411 Vars.push_back((VD || CurContext->isDependentContext())
18412 ? RefExpr->IgnoreParens()
18413 : Ref);
18414 PrivateCopies.push_back(VDPrivateRefExpr);
18417 if (Vars.empty())
18418 return nullptr;
18420 return OMPPrivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars,
18421 PrivateCopies);
18424 OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
18425 SourceLocation StartLoc,
18426 SourceLocation LParenLoc,
18427 SourceLocation EndLoc) {
18428 SmallVector<Expr *, 8> Vars;
18429 SmallVector<Expr *, 8> PrivateCopies;
18430 SmallVector<Expr *, 8> Inits;
18431 SmallVector<Decl *, 4> ExprCaptures;
18432 bool IsImplicitClause =
18433 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
18434 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
18436 for (Expr *RefExpr : VarList) {
18437 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
18438 SourceLocation ELoc;
18439 SourceRange ERange;
18440 Expr *SimpleRefExpr = RefExpr;
18441 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
18442 if (Res.second) {
18443 // It will be analyzed later.
18444 Vars.push_back(RefExpr);
18445 PrivateCopies.push_back(nullptr);
18446 Inits.push_back(nullptr);
18448 ValueDecl *D = Res.first;
18449 if (!D)
18450 continue;
18452 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
18453 QualType Type = D->getType();
18454 auto *VD = dyn_cast<VarDecl>(D);
18456 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18457 // A variable that appears in a private clause must not have an incomplete
18458 // type or a reference type.
18459 if (RequireCompleteType(ELoc, Type,
18460 diag::err_omp_firstprivate_incomplete_type))
18461 continue;
18462 Type = Type.getNonReferenceType();
18464 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
18465 // A variable of class type (or array thereof) that appears in a private
18466 // clause requires an accessible, unambiguous copy constructor for the
18467 // class type.
18468 QualType ElemType = Context.getBaseElementType(Type).getNonReferenceType();
18470 // If an implicit firstprivate variable found it was checked already.
18471 DSAStackTy::DSAVarData TopDVar;
18472 if (!IsImplicitClause) {
18473 DSAStackTy::DSAVarData DVar =
18474 DSAStack->getTopDSA(D, /*FromParent=*/false);
18475 TopDVar = DVar;
18476 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18477 bool IsConstant = ElemType.isConstant(Context);
18478 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
18479 // A list item that specifies a given variable may not appear in more
18480 // than one clause on the same directive, except that a variable may be
18481 // specified in both firstprivate and lastprivate clauses.
18482 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18483 // A list item may appear in a firstprivate or lastprivate clause but not
18484 // both.
18485 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
18486 (isOpenMPDistributeDirective(CurrDir) ||
18487 DVar.CKind != OMPC_lastprivate) &&
18488 DVar.RefExpr) {
18489 Diag(ELoc, diag::err_omp_wrong_dsa)
18490 << getOpenMPClauseName(DVar.CKind)
18491 << getOpenMPClauseName(OMPC_firstprivate);
18492 reportOriginalDsa(*this, DSAStack, D, DVar);
18493 continue;
18496 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18497 // in a Construct]
18498 // Variables with the predetermined data-sharing attributes may not be
18499 // listed in data-sharing attributes clauses, except for the cases
18500 // listed below. For these exceptions only, listing a predetermined
18501 // variable in a data-sharing attribute clause is allowed and overrides
18502 // the variable's predetermined data-sharing attributes.
18503 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18504 // in a Construct, C/C++, p.2]
18505 // Variables with const-qualified type having no mutable member may be
18506 // listed in a firstprivate clause, even if they are static data members.
18507 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
18508 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
18509 Diag(ELoc, diag::err_omp_wrong_dsa)
18510 << getOpenMPClauseName(DVar.CKind)
18511 << getOpenMPClauseName(OMPC_firstprivate);
18512 reportOriginalDsa(*this, DSAStack, D, DVar);
18513 continue;
18516 // OpenMP [2.9.3.4, Restrictions, p.2]
18517 // A list item that is private within a parallel region must not appear
18518 // in a firstprivate clause on a worksharing construct if any of the
18519 // worksharing regions arising from the worksharing construct ever bind
18520 // to any of the parallel regions arising from the parallel construct.
18521 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18522 // A list item that is private within a teams region must not appear in a
18523 // firstprivate clause on a distribute construct if any of the distribute
18524 // regions arising from the distribute construct ever bind to any of the
18525 // teams regions arising from the teams construct.
18526 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18527 // A list item that appears in a reduction clause of a teams construct
18528 // must not appear in a firstprivate clause on a distribute construct if
18529 // any of the distribute regions arising from the distribute construct
18530 // ever bind to any of the teams regions arising from the teams construct.
18531 if ((isOpenMPWorksharingDirective(CurrDir) ||
18532 isOpenMPDistributeDirective(CurrDir)) &&
18533 !isOpenMPParallelDirective(CurrDir) &&
18534 !isOpenMPTeamsDirective(CurrDir)) {
18535 DVar = DSAStack->getImplicitDSA(D, true);
18536 if (DVar.CKind != OMPC_shared &&
18537 (isOpenMPParallelDirective(DVar.DKind) ||
18538 isOpenMPTeamsDirective(DVar.DKind) ||
18539 DVar.DKind == OMPD_unknown)) {
18540 Diag(ELoc, diag::err_omp_required_access)
18541 << getOpenMPClauseName(OMPC_firstprivate)
18542 << getOpenMPClauseName(OMPC_shared);
18543 reportOriginalDsa(*this, DSAStack, D, DVar);
18544 continue;
18547 // OpenMP [2.9.3.4, Restrictions, p.3]
18548 // A list item that appears in a reduction clause of a parallel construct
18549 // must not appear in a firstprivate clause on a worksharing or task
18550 // construct if any of the worksharing or task regions arising from the
18551 // worksharing or task construct ever bind to any of the parallel regions
18552 // arising from the parallel construct.
18553 // OpenMP [2.9.3.4, Restrictions, p.4]
18554 // A list item that appears in a reduction clause in worksharing
18555 // construct must not appear in a firstprivate clause in a task construct
18556 // encountered during execution of any of the worksharing regions arising
18557 // from the worksharing construct.
18558 if (isOpenMPTaskingDirective(CurrDir)) {
18559 DVar = DSAStack->hasInnermostDSA(
18561 [](OpenMPClauseKind C, bool AppliedToPointee) {
18562 return C == OMPC_reduction && !AppliedToPointee;
18564 [](OpenMPDirectiveKind K) {
18565 return isOpenMPParallelDirective(K) ||
18566 isOpenMPWorksharingDirective(K) ||
18567 isOpenMPTeamsDirective(K);
18569 /*FromParent=*/true);
18570 if (DVar.CKind == OMPC_reduction &&
18571 (isOpenMPParallelDirective(DVar.DKind) ||
18572 isOpenMPWorksharingDirective(DVar.DKind) ||
18573 isOpenMPTeamsDirective(DVar.DKind))) {
18574 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
18575 << getOpenMPDirectiveName(DVar.DKind);
18576 reportOriginalDsa(*this, DSAStack, D, DVar);
18577 continue;
18581 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18582 // A list item cannot appear in both a map clause and a data-sharing
18583 // attribute clause on the same construct
18585 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18586 // A list item cannot appear in both a map clause and a data-sharing
18587 // attribute clause on the same construct unless the construct is a
18588 // combined construct.
18589 if ((LangOpts.OpenMP <= 45 &&
18590 isOpenMPTargetExecutionDirective(CurrDir)) ||
18591 CurrDir == OMPD_target) {
18592 OpenMPClauseKind ConflictKind;
18593 if (DSAStack->checkMappableExprComponentListsForDecl(
18594 VD, /*CurrentRegionOnly=*/true,
18595 [&ConflictKind](
18596 OMPClauseMappableExprCommon::MappableExprComponentListRef,
18597 OpenMPClauseKind WhereFoundClauseKind) {
18598 ConflictKind = WhereFoundClauseKind;
18599 return true;
18600 })) {
18601 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18602 << getOpenMPClauseName(OMPC_firstprivate)
18603 << getOpenMPClauseName(ConflictKind)
18604 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
18605 reportOriginalDsa(*this, DSAStack, D, DVar);
18606 continue;
18611 // Variably modified types are not supported for tasks.
18612 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
18613 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
18614 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18615 << getOpenMPClauseName(OMPC_firstprivate) << Type
18616 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
18617 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18618 VarDecl::DeclarationOnly;
18619 Diag(D->getLocation(),
18620 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18621 << D;
18622 continue;
18625 Type = Type.getUnqualifiedType();
18626 VarDecl *VDPrivate =
18627 buildVarDecl(*this, ELoc, Type, D->getName(),
18628 D->hasAttrs() ? &D->getAttrs() : nullptr,
18629 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18630 // Generate helper private variable and initialize it with the value of the
18631 // original variable. The address of the original variable is replaced by
18632 // the address of the new private variable in the CodeGen. This new variable
18633 // is not added to IdResolver, so the code in the OpenMP region uses
18634 // original variable for proper diagnostics and variable capturing.
18635 Expr *VDInitRefExpr = nullptr;
18636 // For arrays generate initializer for single element and replace it by the
18637 // original array element in CodeGen.
18638 if (Type->isArrayType()) {
18639 VarDecl *VDInit =
18640 buildVarDecl(*this, RefExpr->getExprLoc(), ElemType, D->getName());
18641 VDInitRefExpr = buildDeclRefExpr(*this, VDInit, ElemType, ELoc);
18642 Expr *Init = DefaultLvalueConversion(VDInitRefExpr).get();
18643 ElemType = ElemType.getUnqualifiedType();
18644 VarDecl *VDInitTemp = buildVarDecl(*this, RefExpr->getExprLoc(), ElemType,
18645 ".firstprivate.temp");
18646 InitializedEntity Entity =
18647 InitializedEntity::InitializeVariable(VDInitTemp);
18648 InitializationKind Kind = InitializationKind::CreateCopy(ELoc, ELoc);
18650 InitializationSequence InitSeq(*this, Entity, Kind, Init);
18651 ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Init);
18652 if (Result.isInvalid())
18653 VDPrivate->setInvalidDecl();
18654 else
18655 VDPrivate->setInit(Result.getAs<Expr>());
18656 // Remove temp variable declaration.
18657 Context.Deallocate(VDInitTemp);
18658 } else {
18659 VarDecl *VDInit = buildVarDecl(*this, RefExpr->getExprLoc(), Type,
18660 ".firstprivate.temp");
18661 VDInitRefExpr = buildDeclRefExpr(*this, VDInit, RefExpr->getType(),
18662 RefExpr->getExprLoc());
18663 AddInitializerToDecl(VDPrivate,
18664 DefaultLvalueConversion(VDInitRefExpr).get(),
18665 /*DirectInit=*/false);
18667 if (VDPrivate->isInvalidDecl()) {
18668 if (IsImplicitClause) {
18669 Diag(RefExpr->getExprLoc(),
18670 diag::note_omp_task_predetermined_firstprivate_here);
18672 continue;
18674 CurContext->addDecl(VDPrivate);
18675 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18676 *this, VDPrivate, RefExpr->getType().getUnqualifiedType(),
18677 RefExpr->getExprLoc());
18678 DeclRefExpr *Ref = nullptr;
18679 if (!VD && !CurContext->isDependentContext()) {
18680 if (TopDVar.CKind == OMPC_lastprivate) {
18681 Ref = TopDVar.PrivateCopy;
18682 } else {
18683 auto *FD = dyn_cast<FieldDecl>(D);
18684 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
18685 if (VD)
18686 Ref = buildDeclRefExpr(*this, VD, VD->getType().getNonReferenceType(),
18687 RefExpr->getExprLoc());
18688 else
18689 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
18690 if (VD || !isOpenMPCapturedDecl(D))
18691 ExprCaptures.push_back(Ref->getDecl());
18694 if (!IsImplicitClause)
18695 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
18696 Vars.push_back((VD || CurContext->isDependentContext())
18697 ? RefExpr->IgnoreParens()
18698 : Ref);
18699 PrivateCopies.push_back(VDPrivateRefExpr);
18700 Inits.push_back(VDInitRefExpr);
18703 if (Vars.empty())
18704 return nullptr;
18706 return OMPFirstprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
18707 Vars, PrivateCopies, Inits,
18708 buildPreInits(Context, ExprCaptures));
18711 OMPClause *Sema::ActOnOpenMPLastprivateClause(
18712 ArrayRef<Expr *> VarList, OpenMPLastprivateModifier LPKind,
18713 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
18714 SourceLocation LParenLoc, SourceLocation EndLoc) {
18715 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
18716 assert(ColonLoc.isValid() && "Colon location must be valid.");
18717 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
18718 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
18719 /*Last=*/OMPC_LASTPRIVATE_unknown)
18720 << getOpenMPClauseName(OMPC_lastprivate);
18721 return nullptr;
18724 SmallVector<Expr *, 8> Vars;
18725 SmallVector<Expr *, 8> SrcExprs;
18726 SmallVector<Expr *, 8> DstExprs;
18727 SmallVector<Expr *, 8> AssignmentOps;
18728 SmallVector<Decl *, 4> ExprCaptures;
18729 SmallVector<Expr *, 4> ExprPostUpdates;
18730 for (Expr *RefExpr : VarList) {
18731 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
18732 SourceLocation ELoc;
18733 SourceRange ERange;
18734 Expr *SimpleRefExpr = RefExpr;
18735 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
18736 if (Res.second) {
18737 // It will be analyzed later.
18738 Vars.push_back(RefExpr);
18739 SrcExprs.push_back(nullptr);
18740 DstExprs.push_back(nullptr);
18741 AssignmentOps.push_back(nullptr);
18743 ValueDecl *D = Res.first;
18744 if (!D)
18745 continue;
18747 QualType Type = D->getType();
18748 auto *VD = dyn_cast<VarDecl>(D);
18750 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
18751 // A variable that appears in a lastprivate clause must not have an
18752 // incomplete type or a reference type.
18753 if (RequireCompleteType(ELoc, Type,
18754 diag::err_omp_lastprivate_incomplete_type))
18755 continue;
18756 Type = Type.getNonReferenceType();
18758 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18759 // A variable that is privatized must not have a const-qualified type
18760 // unless it is of class type with a mutable member. This restriction does
18761 // not apply to the firstprivate clause.
18763 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
18764 // A variable that appears in a lastprivate clause must not have a
18765 // const-qualified type unless it is of class type with a mutable member.
18766 if (rejectConstNotMutableType(*this, D, Type, OMPC_lastprivate, ELoc))
18767 continue;
18769 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
18770 // A list item that appears in a lastprivate clause with the conditional
18771 // modifier must be a scalar variable.
18772 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
18773 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
18774 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18775 VarDecl::DeclarationOnly;
18776 Diag(D->getLocation(),
18777 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18778 << D;
18779 continue;
18782 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18783 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
18784 // in a Construct]
18785 // Variables with the predetermined data-sharing attributes may not be
18786 // listed in data-sharing attributes clauses, except for the cases
18787 // listed below.
18788 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18789 // A list item may appear in a firstprivate or lastprivate clause but not
18790 // both.
18791 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18792 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
18793 (isOpenMPDistributeDirective(CurrDir) ||
18794 DVar.CKind != OMPC_firstprivate) &&
18795 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
18796 Diag(ELoc, diag::err_omp_wrong_dsa)
18797 << getOpenMPClauseName(DVar.CKind)
18798 << getOpenMPClauseName(OMPC_lastprivate);
18799 reportOriginalDsa(*this, DSAStack, D, DVar);
18800 continue;
18803 // OpenMP [2.14.3.5, Restrictions, p.2]
18804 // A list item that is private within a parallel region, or that appears in
18805 // the reduction clause of a parallel construct, must not appear in a
18806 // lastprivate clause on a worksharing construct if any of the corresponding
18807 // worksharing regions ever binds to any of the corresponding parallel
18808 // regions.
18809 DSAStackTy::DSAVarData TopDVar = DVar;
18810 if (isOpenMPWorksharingDirective(CurrDir) &&
18811 !isOpenMPParallelDirective(CurrDir) &&
18812 !isOpenMPTeamsDirective(CurrDir)) {
18813 DVar = DSAStack->getImplicitDSA(D, true);
18814 if (DVar.CKind != OMPC_shared) {
18815 Diag(ELoc, diag::err_omp_required_access)
18816 << getOpenMPClauseName(OMPC_lastprivate)
18817 << getOpenMPClauseName(OMPC_shared);
18818 reportOriginalDsa(*this, DSAStack, D, DVar);
18819 continue;
18823 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
18824 // A variable of class type (or array thereof) that appears in a
18825 // lastprivate clause requires an accessible, unambiguous default
18826 // constructor for the class type, unless the list item is also specified
18827 // in a firstprivate clause.
18828 // A variable of class type (or array thereof) that appears in a
18829 // lastprivate clause requires an accessible, unambiguous copy assignment
18830 // operator for the class type.
18831 Type = Context.getBaseElementType(Type).getNonReferenceType();
18832 VarDecl *SrcVD = buildVarDecl(*this, ERange.getBegin(),
18833 Type.getUnqualifiedType(), ".lastprivate.src",
18834 D->hasAttrs() ? &D->getAttrs() : nullptr);
18835 DeclRefExpr *PseudoSrcExpr =
18836 buildDeclRefExpr(*this, SrcVD, Type.getUnqualifiedType(), ELoc);
18837 VarDecl *DstVD =
18838 buildVarDecl(*this, ERange.getBegin(), Type, ".lastprivate.dst",
18839 D->hasAttrs() ? &D->getAttrs() : nullptr);
18840 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc);
18841 // For arrays generate assignment operation for single element and replace
18842 // it by the original array element in CodeGen.
18843 ExprResult AssignmentOp = BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
18844 PseudoDstExpr, PseudoSrcExpr);
18845 if (AssignmentOp.isInvalid())
18846 continue;
18847 AssignmentOp =
18848 ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false);
18849 if (AssignmentOp.isInvalid())
18850 continue;
18852 DeclRefExpr *Ref = nullptr;
18853 if (!VD && !CurContext->isDependentContext()) {
18854 if (TopDVar.CKind == OMPC_firstprivate) {
18855 Ref = TopDVar.PrivateCopy;
18856 } else {
18857 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
18858 if (!isOpenMPCapturedDecl(D))
18859 ExprCaptures.push_back(Ref->getDecl());
18861 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
18862 (!isOpenMPCapturedDecl(D) &&
18863 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
18864 ExprResult RefRes = DefaultLvalueConversion(Ref);
18865 if (!RefRes.isUsable())
18866 continue;
18867 ExprResult PostUpdateRes =
18868 BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
18869 RefRes.get());
18870 if (!PostUpdateRes.isUsable())
18871 continue;
18872 ExprPostUpdates.push_back(
18873 IgnoredValueConversions(PostUpdateRes.get()).get());
18876 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
18877 Vars.push_back((VD || CurContext->isDependentContext())
18878 ? RefExpr->IgnoreParens()
18879 : Ref);
18880 SrcExprs.push_back(PseudoSrcExpr);
18881 DstExprs.push_back(PseudoDstExpr);
18882 AssignmentOps.push_back(AssignmentOp.get());
18885 if (Vars.empty())
18886 return nullptr;
18888 return OMPLastprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
18889 Vars, SrcExprs, DstExprs, AssignmentOps,
18890 LPKind, LPKindLoc, ColonLoc,
18891 buildPreInits(Context, ExprCaptures),
18892 buildPostUpdate(*this, ExprPostUpdates));
18895 OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
18896 SourceLocation StartLoc,
18897 SourceLocation LParenLoc,
18898 SourceLocation EndLoc) {
18899 SmallVector<Expr *, 8> Vars;
18900 for (Expr *RefExpr : VarList) {
18901 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
18902 SourceLocation ELoc;
18903 SourceRange ERange;
18904 Expr *SimpleRefExpr = RefExpr;
18905 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
18906 if (Res.second) {
18907 // It will be analyzed later.
18908 Vars.push_back(RefExpr);
18910 ValueDecl *D = Res.first;
18911 if (!D)
18912 continue;
18914 auto *VD = dyn_cast<VarDecl>(D);
18915 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18916 // in a Construct]
18917 // Variables with the predetermined data-sharing attributes may not be
18918 // listed in data-sharing attributes clauses, except for the cases
18919 // listed below. For these exceptions only, listing a predetermined
18920 // variable in a data-sharing attribute clause is allowed and overrides
18921 // the variable's predetermined data-sharing attributes.
18922 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18923 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
18924 DVar.RefExpr) {
18925 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
18926 << getOpenMPClauseName(OMPC_shared);
18927 reportOriginalDsa(*this, DSAStack, D, DVar);
18928 continue;
18931 DeclRefExpr *Ref = nullptr;
18932 if (!VD && isOpenMPCapturedDecl(D) && !CurContext->isDependentContext())
18933 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
18934 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
18935 Vars.push_back((VD || !Ref || CurContext->isDependentContext())
18936 ? RefExpr->IgnoreParens()
18937 : Ref);
18940 if (Vars.empty())
18941 return nullptr;
18943 return OMPSharedClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
18946 namespace {
18947 class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
18948 DSAStackTy *Stack;
18950 public:
18951 bool VisitDeclRefExpr(DeclRefExpr *E) {
18952 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
18953 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
18954 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
18955 return false;
18956 if (DVar.CKind != OMPC_unknown)
18957 return true;
18958 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
18960 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
18961 return isOpenMPPrivate(C) && !AppliedToPointee;
18963 [](OpenMPDirectiveKind) { return true; },
18964 /*FromParent=*/true);
18965 return DVarPrivate.CKind != OMPC_unknown;
18967 return false;
18969 bool VisitStmt(Stmt *S) {
18970 for (Stmt *Child : S->children()) {
18971 if (Child && Visit(Child))
18972 return true;
18974 return false;
18976 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
18978 } // namespace
18980 namespace {
18981 // Transform MemberExpression for specified FieldDecl of current class to
18982 // DeclRefExpr to specified OMPCapturedExprDecl.
18983 class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
18984 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
18985 ValueDecl *Field = nullptr;
18986 DeclRefExpr *CapturedExpr = nullptr;
18988 public:
18989 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
18990 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
18992 ExprResult TransformMemberExpr(MemberExpr *E) {
18993 if (isa<CXXThisExpr>(E->getBase()->IgnoreParenImpCasts()) &&
18994 E->getMemberDecl() == Field) {
18995 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
18996 return CapturedExpr;
18998 return BaseTransform::TransformMemberExpr(E);
19000 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
19002 } // namespace
19004 template <typename T, typename U>
19005 static T filterLookupForUDReductionAndMapper(
19006 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
19007 for (U &Set : Lookups) {
19008 for (auto *D : Set) {
19009 if (T Res = Gen(cast<ValueDecl>(D)))
19010 return Res;
19013 return T();
19016 static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
19017 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
19019 for (auto *RD : D->redecls()) {
19020 // Don't bother with extra checks if we already know this one isn't visible.
19021 if (RD == D)
19022 continue;
19024 auto ND = cast<NamedDecl>(RD);
19025 if (LookupResult::isVisible(SemaRef, ND))
19026 return ND;
19029 return nullptr;
19032 static void
19033 argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id,
19034 SourceLocation Loc, QualType Ty,
19035 SmallVectorImpl<UnresolvedSet<8>> &Lookups) {
19036 // Find all of the associated namespaces and classes based on the
19037 // arguments we have.
19038 Sema::AssociatedNamespaceSet AssociatedNamespaces;
19039 Sema::AssociatedClassSet AssociatedClasses;
19040 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
19041 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
19042 AssociatedClasses);
19044 // C++ [basic.lookup.argdep]p3:
19045 // Let X be the lookup set produced by unqualified lookup (3.4.1)
19046 // and let Y be the lookup set produced by argument dependent
19047 // lookup (defined as follows). If X contains [...] then Y is
19048 // empty. Otherwise Y is the set of declarations found in the
19049 // namespaces associated with the argument types as described
19050 // below. The set of declarations found by the lookup of the name
19051 // is the union of X and Y.
19053 // Here, we compute Y and add its members to the overloaded
19054 // candidate set.
19055 for (auto *NS : AssociatedNamespaces) {
19056 // When considering an associated namespace, the lookup is the
19057 // same as the lookup performed when the associated namespace is
19058 // used as a qualifier (3.4.3.2) except that:
19060 // -- Any using-directives in the associated namespace are
19061 // ignored.
19063 // -- Any namespace-scope friend functions declared in
19064 // associated classes are visible within their respective
19065 // namespaces even if they are not visible during an ordinary
19066 // lookup (11.4).
19067 DeclContext::lookup_result R = NS->lookup(Id.getName());
19068 for (auto *D : R) {
19069 auto *Underlying = D;
19070 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
19071 Underlying = USD->getTargetDecl();
19073 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
19074 !isa<OMPDeclareMapperDecl>(Underlying))
19075 continue;
19077 if (!SemaRef.isVisible(D)) {
19078 D = findAcceptableDecl(SemaRef, D);
19079 if (!D)
19080 continue;
19081 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
19082 Underlying = USD->getTargetDecl();
19084 Lookups.emplace_back();
19085 Lookups.back().addDecl(Underlying);
19090 static ExprResult
19091 buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
19092 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
19093 const DeclarationNameInfo &ReductionId, QualType Ty,
19094 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
19095 if (ReductionIdScopeSpec.isInvalid())
19096 return ExprError();
19097 SmallVector<UnresolvedSet<8>, 4> Lookups;
19098 if (S) {
19099 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
19100 Lookup.suppressDiagnostics();
19101 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec)) {
19102 NamedDecl *D = Lookup.getRepresentativeDecl();
19103 do {
19104 S = S->getParent();
19105 } while (S && !S->isDeclScope(D));
19106 if (S)
19107 S = S->getParent();
19108 Lookups.emplace_back();
19109 Lookups.back().append(Lookup.begin(), Lookup.end());
19110 Lookup.clear();
19112 } else if (auto *ULE =
19113 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
19114 Lookups.push_back(UnresolvedSet<8>());
19115 Decl *PrevD = nullptr;
19116 for (NamedDecl *D : ULE->decls()) {
19117 if (D == PrevD)
19118 Lookups.push_back(UnresolvedSet<8>());
19119 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
19120 Lookups.back().addDecl(DRD);
19121 PrevD = D;
19124 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
19125 Ty->isInstantiationDependentType() ||
19126 Ty->containsUnexpandedParameterPack() ||
19127 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
19128 return !D->isInvalidDecl() &&
19129 (D->getType()->isDependentType() ||
19130 D->getType()->isInstantiationDependentType() ||
19131 D->getType()->containsUnexpandedParameterPack());
19132 })) {
19133 UnresolvedSet<8> ResSet;
19134 for (const UnresolvedSet<8> &Set : Lookups) {
19135 if (Set.empty())
19136 continue;
19137 ResSet.append(Set.begin(), Set.end());
19138 // The last item marks the end of all declarations at the specified scope.
19139 ResSet.addDecl(Set[Set.size() - 1]);
19141 return UnresolvedLookupExpr::Create(
19142 SemaRef.Context, /*NamingClass=*/nullptr,
19143 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
19144 /*ADL=*/true, /*Overloaded=*/true, ResSet.begin(), ResSet.end());
19146 // Lookup inside the classes.
19147 // C++ [over.match.oper]p3:
19148 // For a unary operator @ with an operand of a type whose
19149 // cv-unqualified version is T1, and for a binary operator @ with
19150 // a left operand of a type whose cv-unqualified version is T1 and
19151 // a right operand of a type whose cv-unqualified version is T2,
19152 // three sets of candidate functions, designated member
19153 // candidates, non-member candidates and built-in candidates, are
19154 // constructed as follows:
19155 // -- If T1 is a complete class type or a class currently being
19156 // defined, the set of member candidates is the result of the
19157 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
19158 // the set of member candidates is empty.
19159 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
19160 Lookup.suppressDiagnostics();
19161 if (const auto *TyRec = Ty->getAs<RecordType>()) {
19162 // Complete the type if it can be completed.
19163 // If the type is neither complete nor being defined, bail out now.
19164 if (SemaRef.isCompleteType(Loc, Ty) || TyRec->isBeingDefined() ||
19165 TyRec->getDecl()->getDefinition()) {
19166 Lookup.clear();
19167 SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl());
19168 if (Lookup.empty()) {
19169 Lookups.emplace_back();
19170 Lookups.back().append(Lookup.begin(), Lookup.end());
19174 // Perform ADL.
19175 if (SemaRef.getLangOpts().CPlusPlus)
19176 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
19177 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
19178 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
19179 if (!D->isInvalidDecl() &&
19180 SemaRef.Context.hasSameType(D->getType(), Ty))
19181 return D;
19182 return nullptr;
19184 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
19185 VK_LValue, Loc);
19186 if (SemaRef.getLangOpts().CPlusPlus) {
19187 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
19188 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
19189 if (!D->isInvalidDecl() &&
19190 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
19191 !Ty.isMoreQualifiedThan(D->getType()))
19192 return D;
19193 return nullptr;
19194 })) {
19195 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
19196 /*DetectVirtual=*/false);
19197 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
19198 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
19199 VD->getType().getUnqualifiedType()))) {
19200 if (SemaRef.CheckBaseClassAccess(
19201 Loc, VD->getType(), Ty, Paths.front(),
19202 /*DiagID=*/0) != Sema::AR_inaccessible) {
19203 SemaRef.BuildBasePathArray(Paths, BasePath);
19204 return SemaRef.BuildDeclRefExpr(
19205 VD, VD->getType().getNonReferenceType(), VK_LValue, Loc);
19211 if (ReductionIdScopeSpec.isSet()) {
19212 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
19213 << Ty << Range;
19214 return ExprError();
19216 return ExprEmpty();
19219 namespace {
19220 /// Data for the reduction-based clauses.
19221 struct ReductionData {
19222 /// List of original reduction items.
19223 SmallVector<Expr *, 8> Vars;
19224 /// List of private copies of the reduction items.
19225 SmallVector<Expr *, 8> Privates;
19226 /// LHS expressions for the reduction_op expressions.
19227 SmallVector<Expr *, 8> LHSs;
19228 /// RHS expressions for the reduction_op expressions.
19229 SmallVector<Expr *, 8> RHSs;
19230 /// Reduction operation expression.
19231 SmallVector<Expr *, 8> ReductionOps;
19232 /// inscan copy operation expressions.
19233 SmallVector<Expr *, 8> InscanCopyOps;
19234 /// inscan copy temp array expressions for prefix sums.
19235 SmallVector<Expr *, 8> InscanCopyArrayTemps;
19236 /// inscan copy temp array element expressions for prefix sums.
19237 SmallVector<Expr *, 8> InscanCopyArrayElems;
19238 /// Taskgroup descriptors for the corresponding reduction items in
19239 /// in_reduction clauses.
19240 SmallVector<Expr *, 8> TaskgroupDescriptors;
19241 /// List of captures for clause.
19242 SmallVector<Decl *, 4> ExprCaptures;
19243 /// List of postupdate expressions.
19244 SmallVector<Expr *, 4> ExprPostUpdates;
19245 /// Reduction modifier.
19246 unsigned RedModifier = 0;
19247 ReductionData() = delete;
19248 /// Reserves required memory for the reduction data.
19249 ReductionData(unsigned Size, unsigned Modifier = 0) : RedModifier(Modifier) {
19250 Vars.reserve(Size);
19251 Privates.reserve(Size);
19252 LHSs.reserve(Size);
19253 RHSs.reserve(Size);
19254 ReductionOps.reserve(Size);
19255 if (RedModifier == OMPC_REDUCTION_inscan) {
19256 InscanCopyOps.reserve(Size);
19257 InscanCopyArrayTemps.reserve(Size);
19258 InscanCopyArrayElems.reserve(Size);
19260 TaskgroupDescriptors.reserve(Size);
19261 ExprCaptures.reserve(Size);
19262 ExprPostUpdates.reserve(Size);
19264 /// Stores reduction item and reduction operation only (required for dependent
19265 /// reduction item).
19266 void push(Expr *Item, Expr *ReductionOp) {
19267 Vars.emplace_back(Item);
19268 Privates.emplace_back(nullptr);
19269 LHSs.emplace_back(nullptr);
19270 RHSs.emplace_back(nullptr);
19271 ReductionOps.emplace_back(ReductionOp);
19272 TaskgroupDescriptors.emplace_back(nullptr);
19273 if (RedModifier == OMPC_REDUCTION_inscan) {
19274 InscanCopyOps.push_back(nullptr);
19275 InscanCopyArrayTemps.push_back(nullptr);
19276 InscanCopyArrayElems.push_back(nullptr);
19279 /// Stores reduction data.
19280 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
19281 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
19282 Expr *CopyArrayElem) {
19283 Vars.emplace_back(Item);
19284 Privates.emplace_back(Private);
19285 LHSs.emplace_back(LHS);
19286 RHSs.emplace_back(RHS);
19287 ReductionOps.emplace_back(ReductionOp);
19288 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
19289 if (RedModifier == OMPC_REDUCTION_inscan) {
19290 InscanCopyOps.push_back(CopyOp);
19291 InscanCopyArrayTemps.push_back(CopyArrayTemp);
19292 InscanCopyArrayElems.push_back(CopyArrayElem);
19293 } else {
19294 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
19295 CopyArrayElem == nullptr &&
19296 "Copy operation must be used for inscan reductions only.");
19300 } // namespace
19302 static bool checkOMPArraySectionConstantForReduction(
19303 ASTContext &Context, const OMPArraySectionExpr *OASE, bool &SingleElement,
19304 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
19305 const Expr *Length = OASE->getLength();
19306 if (Length == nullptr) {
19307 // For array sections of the form [1:] or [:], we would need to analyze
19308 // the lower bound...
19309 if (OASE->getColonLocFirst().isValid())
19310 return false;
19312 // This is an array subscript which has implicit length 1!
19313 SingleElement = true;
19314 ArraySizes.push_back(llvm::APSInt::get(1));
19315 } else {
19316 Expr::EvalResult Result;
19317 if (!Length->EvaluateAsInt(Result, Context))
19318 return false;
19320 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19321 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
19322 ArraySizes.push_back(ConstantLengthValue);
19325 // Get the base of this array section and walk up from there.
19326 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
19328 // We require length = 1 for all array sections except the right-most to
19329 // guarantee that the memory region is contiguous and has no holes in it.
19330 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) {
19331 Length = TempOASE->getLength();
19332 if (Length == nullptr) {
19333 // For array sections of the form [1:] or [:], we would need to analyze
19334 // the lower bound...
19335 if (OASE->getColonLocFirst().isValid())
19336 return false;
19338 // This is an array subscript which has implicit length 1!
19339 ArraySizes.push_back(llvm::APSInt::get(1));
19340 } else {
19341 Expr::EvalResult Result;
19342 if (!Length->EvaluateAsInt(Result, Context))
19343 return false;
19345 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19346 if (ConstantLengthValue.getSExtValue() != 1)
19347 return false;
19349 ArraySizes.push_back(ConstantLengthValue);
19351 Base = TempOASE->getBase()->IgnoreParenImpCasts();
19354 // If we have a single element, we don't need to add the implicit lengths.
19355 if (!SingleElement) {
19356 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
19357 // Has implicit length 1!
19358 ArraySizes.push_back(llvm::APSInt::get(1));
19359 Base = TempASE->getBase()->IgnoreParenImpCasts();
19363 // This array section can be privatized as a single value or as a constant
19364 // sized array.
19365 return true;
19368 static BinaryOperatorKind
19369 getRelatedCompoundReductionOp(BinaryOperatorKind BOK) {
19370 if (BOK == BO_Add)
19371 return BO_AddAssign;
19372 if (BOK == BO_Mul)
19373 return BO_MulAssign;
19374 if (BOK == BO_And)
19375 return BO_AndAssign;
19376 if (BOK == BO_Or)
19377 return BO_OrAssign;
19378 if (BOK == BO_Xor)
19379 return BO_XorAssign;
19380 return BOK;
19383 static bool actOnOMPReductionKindClause(
19384 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
19385 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19386 SourceLocation ColonLoc, SourceLocation EndLoc,
19387 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19388 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
19389 DeclarationName DN = ReductionId.getName();
19390 OverloadedOperatorKind OOK = DN.getCXXOverloadedOperator();
19391 BinaryOperatorKind BOK = BO_Comma;
19393 ASTContext &Context = S.Context;
19394 // OpenMP [2.14.3.6, reduction clause]
19395 // C
19396 // reduction-identifier is either an identifier or one of the following
19397 // operators: +, -, *, &, |, ^, && and ||
19398 // C++
19399 // reduction-identifier is either an id-expression or one of the following
19400 // operators: +, -, *, &, |, ^, && and ||
19401 switch (OOK) {
19402 case OO_Plus:
19403 BOK = BO_Add;
19404 break;
19405 case OO_Minus:
19406 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
19407 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
19408 // reduction identifier.
19409 if (S.LangOpts.OpenMP > 52)
19410 BOK = BO_Comma;
19411 else
19412 BOK = BO_Add;
19413 break;
19414 case OO_Star:
19415 BOK = BO_Mul;
19416 break;
19417 case OO_Amp:
19418 BOK = BO_And;
19419 break;
19420 case OO_Pipe:
19421 BOK = BO_Or;
19422 break;
19423 case OO_Caret:
19424 BOK = BO_Xor;
19425 break;
19426 case OO_AmpAmp:
19427 BOK = BO_LAnd;
19428 break;
19429 case OO_PipePipe:
19430 BOK = BO_LOr;
19431 break;
19432 case OO_New:
19433 case OO_Delete:
19434 case OO_Array_New:
19435 case OO_Array_Delete:
19436 case OO_Slash:
19437 case OO_Percent:
19438 case OO_Tilde:
19439 case OO_Exclaim:
19440 case OO_Equal:
19441 case OO_Less:
19442 case OO_Greater:
19443 case OO_LessEqual:
19444 case OO_GreaterEqual:
19445 case OO_PlusEqual:
19446 case OO_MinusEqual:
19447 case OO_StarEqual:
19448 case OO_SlashEqual:
19449 case OO_PercentEqual:
19450 case OO_CaretEqual:
19451 case OO_AmpEqual:
19452 case OO_PipeEqual:
19453 case OO_LessLess:
19454 case OO_GreaterGreater:
19455 case OO_LessLessEqual:
19456 case OO_GreaterGreaterEqual:
19457 case OO_EqualEqual:
19458 case OO_ExclaimEqual:
19459 case OO_Spaceship:
19460 case OO_PlusPlus:
19461 case OO_MinusMinus:
19462 case OO_Comma:
19463 case OO_ArrowStar:
19464 case OO_Arrow:
19465 case OO_Call:
19466 case OO_Subscript:
19467 case OO_Conditional:
19468 case OO_Coawait:
19469 case NUM_OVERLOADED_OPERATORS:
19470 llvm_unreachable("Unexpected reduction identifier");
19471 case OO_None:
19472 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
19473 if (II->isStr("max"))
19474 BOK = BO_GT;
19475 else if (II->isStr("min"))
19476 BOK = BO_LT;
19478 break;
19481 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
19482 // A reduction clause with the minus (-) operator was deprecated
19483 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
19484 S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
19486 SourceRange ReductionIdRange;
19487 if (ReductionIdScopeSpec.isValid())
19488 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
19489 else
19490 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
19491 ReductionIdRange.setEnd(ReductionId.getEndLoc());
19493 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
19494 bool FirstIter = true;
19495 for (Expr *RefExpr : VarList) {
19496 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
19497 // OpenMP [2.1, C/C++]
19498 // A list item is a variable or array section, subject to the restrictions
19499 // specified in Section 2.4 on page 42 and in each of the sections
19500 // describing clauses and directives for which a list appears.
19501 // OpenMP [2.14.3.3, Restrictions, p.1]
19502 // A variable that is part of another variable (as an array or
19503 // structure element) cannot appear in a private clause.
19504 if (!FirstIter && IR != ER)
19505 ++IR;
19506 FirstIter = false;
19507 SourceLocation ELoc;
19508 SourceRange ERange;
19509 Expr *SimpleRefExpr = RefExpr;
19510 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
19511 /*AllowArraySection=*/true);
19512 if (Res.second) {
19513 // Try to find 'declare reduction' corresponding construct before using
19514 // builtin/overloaded operators.
19515 QualType Type = Context.DependentTy;
19516 CXXCastPath BasePath;
19517 ExprResult DeclareReductionRef = buildDeclareReductionRef(
19518 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
19519 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
19520 Expr *ReductionOp = nullptr;
19521 if (S.CurContext->isDependentContext() &&
19522 (DeclareReductionRef.isUnset() ||
19523 isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
19524 ReductionOp = DeclareReductionRef.get();
19525 // It will be analyzed later.
19526 RD.push(RefExpr, ReductionOp);
19528 ValueDecl *D = Res.first;
19529 if (!D)
19530 continue;
19532 Expr *TaskgroupDescriptor = nullptr;
19533 QualType Type;
19534 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
19535 auto *OASE = dyn_cast<OMPArraySectionExpr>(RefExpr->IgnoreParens());
19536 if (ASE) {
19537 Type = ASE->getType().getNonReferenceType();
19538 } else if (OASE) {
19539 QualType BaseType =
19540 OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
19541 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
19542 Type = ATy->getElementType();
19543 else
19544 Type = BaseType->getPointeeType();
19545 Type = Type.getNonReferenceType();
19546 } else {
19547 Type = Context.getBaseElementType(D->getType().getNonReferenceType());
19549 auto *VD = dyn_cast<VarDecl>(D);
19551 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19552 // A variable that appears in a private clause must not have an incomplete
19553 // type or a reference type.
19554 if (S.RequireCompleteType(ELoc, D->getType(),
19555 diag::err_omp_reduction_incomplete_type))
19556 continue;
19557 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19558 // A list item that appears in a reduction clause must not be
19559 // const-qualified.
19560 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
19561 /*AcceptIfMutable*/ false, ASE || OASE))
19562 continue;
19564 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
19565 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
19566 // If a list-item is a reference type then it must bind to the same object
19567 // for all threads of the team.
19568 if (!ASE && !OASE) {
19569 if (VD) {
19570 VarDecl *VDDef = VD->getDefinition();
19571 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
19572 DSARefChecker Check(Stack);
19573 if (Check.Visit(VDDef->getInit())) {
19574 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
19575 << getOpenMPClauseName(ClauseKind) << ERange;
19576 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
19577 continue;
19582 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
19583 // in a Construct]
19584 // Variables with the predetermined data-sharing attributes may not be
19585 // listed in data-sharing attributes clauses, except for the cases
19586 // listed below. For these exceptions only, listing a predetermined
19587 // variable in a data-sharing attribute clause is allowed and overrides
19588 // the variable's predetermined data-sharing attributes.
19589 // OpenMP [2.14.3.6, Restrictions, p.3]
19590 // Any number of reduction clauses can be specified on the directive,
19591 // but a list item can appear only once in the reduction clauses for that
19592 // directive.
19593 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19594 if (DVar.CKind == OMPC_reduction) {
19595 S.Diag(ELoc, diag::err_omp_once_referenced)
19596 << getOpenMPClauseName(ClauseKind);
19597 if (DVar.RefExpr)
19598 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
19599 continue;
19601 if (DVar.CKind != OMPC_unknown) {
19602 S.Diag(ELoc, diag::err_omp_wrong_dsa)
19603 << getOpenMPClauseName(DVar.CKind)
19604 << getOpenMPClauseName(OMPC_reduction);
19605 reportOriginalDsa(S, Stack, D, DVar);
19606 continue;
19609 // OpenMP [2.14.3.6, Restrictions, p.1]
19610 // A list item that appears in a reduction clause of a worksharing
19611 // construct must be shared in the parallel regions to which any of the
19612 // worksharing regions arising from the worksharing construct bind.
19613 if (isOpenMPWorksharingDirective(CurrDir) &&
19614 !isOpenMPParallelDirective(CurrDir) &&
19615 !isOpenMPTeamsDirective(CurrDir)) {
19616 DVar = Stack->getImplicitDSA(D, true);
19617 if (DVar.CKind != OMPC_shared) {
19618 S.Diag(ELoc, diag::err_omp_required_access)
19619 << getOpenMPClauseName(OMPC_reduction)
19620 << getOpenMPClauseName(OMPC_shared);
19621 reportOriginalDsa(S, Stack, D, DVar);
19622 continue;
19625 } else {
19626 // Threadprivates cannot be shared between threads, so dignose if the base
19627 // is a threadprivate variable.
19628 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19629 if (DVar.CKind == OMPC_threadprivate) {
19630 S.Diag(ELoc, diag::err_omp_wrong_dsa)
19631 << getOpenMPClauseName(DVar.CKind)
19632 << getOpenMPClauseName(OMPC_reduction);
19633 reportOriginalDsa(S, Stack, D, DVar);
19634 continue;
19638 // Try to find 'declare reduction' corresponding construct before using
19639 // builtin/overloaded operators.
19640 CXXCastPath BasePath;
19641 ExprResult DeclareReductionRef = buildDeclareReductionRef(
19642 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
19643 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
19644 if (DeclareReductionRef.isInvalid())
19645 continue;
19646 if (S.CurContext->isDependentContext() &&
19647 (DeclareReductionRef.isUnset() ||
19648 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
19649 RD.push(RefExpr, DeclareReductionRef.get());
19650 continue;
19652 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
19653 // Not allowed reduction identifier is found.
19654 if (S.LangOpts.OpenMP > 52)
19655 S.Diag(ReductionId.getBeginLoc(),
19656 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
19657 << Type << ReductionIdRange;
19658 else
19659 S.Diag(ReductionId.getBeginLoc(),
19660 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
19661 << Type << ReductionIdRange;
19662 continue;
19665 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19666 // The type of a list item that appears in a reduction clause must be valid
19667 // for the reduction-identifier. For a max or min reduction in C, the type
19668 // of the list item must be an allowed arithmetic data type: char, int,
19669 // float, double, or _Bool, possibly modified with long, short, signed, or
19670 // unsigned. For a max or min reduction in C++, the type of the list item
19671 // must be an allowed arithmetic data type: char, wchar_t, int, float,
19672 // double, or bool, possibly modified with long, short, signed, or unsigned.
19673 if (DeclareReductionRef.isUnset()) {
19674 if ((BOK == BO_GT || BOK == BO_LT) &&
19675 !(Type->isScalarType() ||
19676 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
19677 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
19678 << getOpenMPClauseName(ClauseKind) << S.getLangOpts().CPlusPlus;
19679 if (!ASE && !OASE) {
19680 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19681 VarDecl::DeclarationOnly;
19682 S.Diag(D->getLocation(),
19683 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19684 << D;
19686 continue;
19688 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
19689 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
19690 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
19691 << getOpenMPClauseName(ClauseKind);
19692 if (!ASE && !OASE) {
19693 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19694 VarDecl::DeclarationOnly;
19695 S.Diag(D->getLocation(),
19696 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19697 << D;
19699 continue;
19703 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
19704 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
19705 D->hasAttrs() ? &D->getAttrs() : nullptr);
19706 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
19707 D->hasAttrs() ? &D->getAttrs() : nullptr);
19708 QualType PrivateTy = Type;
19710 // Try if we can determine constant lengths for all array sections and avoid
19711 // the VLA.
19712 bool ConstantLengthOASE = false;
19713 if (OASE) {
19714 bool SingleElement;
19715 llvm::SmallVector<llvm::APSInt, 4> ArraySizes;
19716 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
19717 Context, OASE, SingleElement, ArraySizes);
19719 // If we don't have a single element, we must emit a constant array type.
19720 if (ConstantLengthOASE && !SingleElement) {
19721 for (llvm::APSInt &Size : ArraySizes)
19722 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
19723 ArraySizeModifier::Normal,
19724 /*IndexTypeQuals=*/0);
19728 if ((OASE && !ConstantLengthOASE) ||
19729 (!OASE && !ASE &&
19730 D->getType().getNonReferenceType()->isVariablyModifiedType())) {
19731 if (!Context.getTargetInfo().isVLASupported()) {
19732 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
19733 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19734 S.Diag(ELoc, diag::note_vla_unsupported);
19735 continue;
19736 } else {
19737 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19738 S.targetDiag(ELoc, diag::note_vla_unsupported);
19741 // For arrays/array sections only:
19742 // Create pseudo array type for private copy. The size for this array will
19743 // be generated during codegen.
19744 // For array subscripts or single variables Private Ty is the same as Type
19745 // (type of the variable or single array element).
19746 PrivateTy = Context.getVariableArrayType(
19747 Type,
19748 new (Context)
19749 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
19750 ArraySizeModifier::Normal, /*IndexTypeQuals=*/0, SourceRange());
19751 } else if (!ASE && !OASE &&
19752 Context.getAsArrayType(D->getType().getNonReferenceType())) {
19753 PrivateTy = D->getType().getNonReferenceType();
19755 // Private copy.
19756 VarDecl *PrivateVD =
19757 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
19758 D->hasAttrs() ? &D->getAttrs() : nullptr,
19759 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19760 // Add initializer for private variable.
19761 Expr *Init = nullptr;
19762 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
19763 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
19764 if (DeclareReductionRef.isUsable()) {
19765 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
19766 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
19767 if (DRD->getInitializer()) {
19768 Init = DRDRef;
19769 RHSVD->setInit(DRDRef);
19770 RHSVD->setInitStyle(VarDecl::CallInit);
19772 } else {
19773 switch (BOK) {
19774 case BO_Add:
19775 case BO_Xor:
19776 case BO_Or:
19777 case BO_LOr:
19778 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
19779 if (Type->isScalarType() || Type->isAnyComplexType())
19780 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
19781 break;
19782 case BO_Mul:
19783 case BO_LAnd:
19784 if (Type->isScalarType() || Type->isAnyComplexType()) {
19785 // '*' and '&&' reduction ops - initializer is '1'.
19786 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
19788 break;
19789 case BO_And: {
19790 // '&' reduction op - initializer is '~0'.
19791 QualType OrigType = Type;
19792 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
19793 Type = ComplexTy->getElementType();
19794 if (Type->isRealFloatingType()) {
19795 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
19796 Context.getFloatTypeSemantics(Type));
19797 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
19798 Type, ELoc);
19799 } else if (Type->isScalarType()) {
19800 uint64_t Size = Context.getTypeSize(Type);
19801 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
19802 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
19803 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
19805 if (Init && OrigType->isAnyComplexType()) {
19806 // Init = 0xFFFF + 0xFFFFi;
19807 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
19808 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
19810 Type = OrigType;
19811 break;
19813 case BO_LT:
19814 case BO_GT: {
19815 // 'min' reduction op - initializer is 'Largest representable number in
19816 // the reduction list item type'.
19817 // 'max' reduction op - initializer is 'Least representable number in
19818 // the reduction list item type'.
19819 if (Type->isIntegerType() || Type->isPointerType()) {
19820 bool IsSigned = Type->hasSignedIntegerRepresentation();
19821 uint64_t Size = Context.getTypeSize(Type);
19822 QualType IntTy =
19823 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
19824 llvm::APInt InitValue =
19825 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
19826 : llvm::APInt::getMinValue(Size)
19827 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
19828 : llvm::APInt::getMaxValue(Size);
19829 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
19830 if (Type->isPointerType()) {
19831 // Cast to pointer type.
19832 ExprResult CastExpr = S.BuildCStyleCastExpr(
19833 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
19834 if (CastExpr.isInvalid())
19835 continue;
19836 Init = CastExpr.get();
19838 } else if (Type->isRealFloatingType()) {
19839 llvm::APFloat InitValue = llvm::APFloat::getLargest(
19840 Context.getFloatTypeSemantics(Type), BOK != BO_LT);
19841 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
19842 Type, ELoc);
19844 break;
19846 case BO_PtrMemD:
19847 case BO_PtrMemI:
19848 case BO_MulAssign:
19849 case BO_Div:
19850 case BO_Rem:
19851 case BO_Sub:
19852 case BO_Shl:
19853 case BO_Shr:
19854 case BO_LE:
19855 case BO_GE:
19856 case BO_EQ:
19857 case BO_NE:
19858 case BO_Cmp:
19859 case BO_AndAssign:
19860 case BO_XorAssign:
19861 case BO_OrAssign:
19862 case BO_Assign:
19863 case BO_AddAssign:
19864 case BO_SubAssign:
19865 case BO_DivAssign:
19866 case BO_RemAssign:
19867 case BO_ShlAssign:
19868 case BO_ShrAssign:
19869 case BO_Comma:
19870 llvm_unreachable("Unexpected reduction operation");
19873 if (Init && DeclareReductionRef.isUnset()) {
19874 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
19875 // Store initializer for single element in private copy. Will be used
19876 // during codegen.
19877 PrivateVD->setInit(RHSVD->getInit());
19878 PrivateVD->setInitStyle(RHSVD->getInitStyle());
19879 } else if (!Init) {
19880 S.ActOnUninitializedDecl(RHSVD);
19881 // Store initializer for single element in private copy. Will be used
19882 // during codegen.
19883 PrivateVD->setInit(RHSVD->getInit());
19884 PrivateVD->setInitStyle(RHSVD->getInitStyle());
19886 if (RHSVD->isInvalidDecl())
19887 continue;
19888 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
19889 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
19890 << Type << ReductionIdRange;
19891 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19892 VarDecl::DeclarationOnly;
19893 S.Diag(D->getLocation(),
19894 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19895 << D;
19896 continue;
19898 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
19899 ExprResult ReductionOp;
19900 if (DeclareReductionRef.isUsable()) {
19901 QualType RedTy = DeclareReductionRef.get()->getType();
19902 QualType PtrRedTy = Context.getPointerType(RedTy);
19903 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
19904 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
19905 if (!BasePath.empty()) {
19906 LHS = S.DefaultLvalueConversion(LHS.get());
19907 RHS = S.DefaultLvalueConversion(RHS.get());
19908 LHS = ImplicitCastExpr::Create(
19909 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
19910 LHS.get()->getValueKind(), FPOptionsOverride());
19911 RHS = ImplicitCastExpr::Create(
19912 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
19913 RHS.get()->getValueKind(), FPOptionsOverride());
19915 FunctionProtoType::ExtProtoInfo EPI;
19916 QualType Params[] = {PtrRedTy, PtrRedTy};
19917 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
19918 auto *OVE = new (Context) OpaqueValueExpr(
19919 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
19920 S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
19921 Expr *Args[] = {LHS.get(), RHS.get()};
19922 ReductionOp =
19923 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
19924 S.CurFPFeatureOverrides());
19925 } else {
19926 BinaryOperatorKind CombBOK = getRelatedCompoundReductionOp(BOK);
19927 if (Type->isRecordType() && CombBOK != BOK) {
19928 Sema::TentativeAnalysisScope Trap(S);
19929 ReductionOp =
19930 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19931 CombBOK, LHSDRE, RHSDRE);
19933 if (!ReductionOp.isUsable()) {
19934 ReductionOp =
19935 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
19936 LHSDRE, RHSDRE);
19937 if (ReductionOp.isUsable()) {
19938 if (BOK != BO_LT && BOK != BO_GT) {
19939 ReductionOp =
19940 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19941 BO_Assign, LHSDRE, ReductionOp.get());
19942 } else {
19943 auto *ConditionalOp = new (Context)
19944 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
19945 RHSDRE, Type, VK_LValue, OK_Ordinary);
19946 ReductionOp =
19947 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19948 BO_Assign, LHSDRE, ConditionalOp);
19952 if (ReductionOp.isUsable())
19953 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
19954 /*DiscardedValue*/ false);
19955 if (!ReductionOp.isUsable())
19956 continue;
19959 // Add copy operations for inscan reductions.
19960 // LHS = RHS;
19961 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
19962 if (ClauseKind == OMPC_reduction &&
19963 RD.RedModifier == OMPC_REDUCTION_inscan) {
19964 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
19965 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
19966 RHS.get());
19967 if (!CopyOpRes.isUsable())
19968 continue;
19969 CopyOpRes =
19970 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
19971 if (!CopyOpRes.isUsable())
19972 continue;
19973 // For simd directive and simd-based directives in simd mode no need to
19974 // construct temp array, need just a single temp element.
19975 if (Stack->getCurrentDirective() == OMPD_simd ||
19976 (S.getLangOpts().OpenMPSimd &&
19977 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
19978 VarDecl *TempArrayVD =
19979 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
19980 D->hasAttrs() ? &D->getAttrs() : nullptr);
19981 // Add a constructor to the temp decl.
19982 S.ActOnUninitializedDecl(TempArrayVD);
19983 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
19984 } else {
19985 // Build temp array for prefix sum.
19986 auto *Dim = new (S.Context)
19987 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
19988 QualType ArrayTy = S.Context.getVariableArrayType(
19989 PrivateTy, Dim, ArraySizeModifier::Normal,
19990 /*IndexTypeQuals=*/0, {ELoc, ELoc});
19991 VarDecl *TempArrayVD =
19992 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
19993 D->hasAttrs() ? &D->getAttrs() : nullptr);
19994 // Add a constructor to the temp decl.
19995 S.ActOnUninitializedDecl(TempArrayVD);
19996 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
19997 TempArrayElem =
19998 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
19999 auto *Idx = new (S.Context)
20000 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
20001 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
20002 ELoc, Idx, ELoc);
20006 // OpenMP [2.15.4.6, Restrictions, p.2]
20007 // A list item that appears in an in_reduction clause of a task construct
20008 // must appear in a task_reduction clause of a construct associated with a
20009 // taskgroup region that includes the participating task in its taskgroup
20010 // set. The construct associated with the innermost region that meets this
20011 // condition must specify the same reduction-identifier as the in_reduction
20012 // clause.
20013 if (ClauseKind == OMPC_in_reduction) {
20014 SourceRange ParentSR;
20015 BinaryOperatorKind ParentBOK;
20016 const Expr *ParentReductionOp = nullptr;
20017 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
20018 DSAStackTy::DSAVarData ParentBOKDSA =
20019 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
20020 ParentBOKTD);
20021 DSAStackTy::DSAVarData ParentReductionOpDSA =
20022 Stack->getTopMostTaskgroupReductionData(
20023 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
20024 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
20025 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
20026 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
20027 (DeclareReductionRef.isUsable() && IsParentBOK) ||
20028 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
20029 bool EmitError = true;
20030 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
20031 llvm::FoldingSetNodeID RedId, ParentRedId;
20032 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
20033 DeclareReductionRef.get()->Profile(RedId, Context,
20034 /*Canonical=*/true);
20035 EmitError = RedId != ParentRedId;
20037 if (EmitError) {
20038 S.Diag(ReductionId.getBeginLoc(),
20039 diag::err_omp_reduction_identifier_mismatch)
20040 << ReductionIdRange << RefExpr->getSourceRange();
20041 S.Diag(ParentSR.getBegin(),
20042 diag::note_omp_previous_reduction_identifier)
20043 << ParentSR
20044 << (IsParentBOK ? ParentBOKDSA.RefExpr
20045 : ParentReductionOpDSA.RefExpr)
20046 ->getSourceRange();
20047 continue;
20050 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
20053 DeclRefExpr *Ref = nullptr;
20054 Expr *VarsExpr = RefExpr->IgnoreParens();
20055 if (!VD && !S.CurContext->isDependentContext()) {
20056 if (ASE || OASE) {
20057 TransformExprToCaptures RebuildToCapture(S, D);
20058 VarsExpr =
20059 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
20060 Ref = RebuildToCapture.getCapturedExpr();
20061 } else {
20062 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
20064 if (!S.isOpenMPCapturedDecl(D)) {
20065 RD.ExprCaptures.emplace_back(Ref->getDecl());
20066 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
20067 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
20068 if (!RefRes.isUsable())
20069 continue;
20070 ExprResult PostUpdateRes =
20071 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
20072 RefRes.get());
20073 if (!PostUpdateRes.isUsable())
20074 continue;
20075 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
20076 Stack->getCurrentDirective() == OMPD_taskgroup) {
20077 S.Diag(RefExpr->getExprLoc(),
20078 diag::err_omp_reduction_non_addressable_expression)
20079 << RefExpr->getSourceRange();
20080 continue;
20082 RD.ExprPostUpdates.emplace_back(
20083 S.IgnoredValueConversions(PostUpdateRes.get()).get());
20087 // All reduction items are still marked as reduction (to do not increase
20088 // code base size).
20089 unsigned Modifier = RD.RedModifier;
20090 // Consider task_reductions as reductions with task modifier. Required for
20091 // correct analysis of in_reduction clauses.
20092 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
20093 Modifier = OMPC_REDUCTION_task;
20094 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
20095 ASE || OASE);
20096 if (Modifier == OMPC_REDUCTION_task &&
20097 (CurrDir == OMPD_taskgroup ||
20098 ((isOpenMPParallelDirective(CurrDir) ||
20099 isOpenMPWorksharingDirective(CurrDir)) &&
20100 !isOpenMPSimdDirective(CurrDir)))) {
20101 if (DeclareReductionRef.isUsable())
20102 Stack->addTaskgroupReductionData(D, ReductionIdRange,
20103 DeclareReductionRef.get());
20104 else
20105 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
20107 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
20108 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
20109 TempArrayElem.get());
20111 return RD.Vars.empty();
20114 OMPClause *Sema::ActOnOpenMPReductionClause(
20115 ArrayRef<Expr *> VarList, OpenMPReductionClauseModifier Modifier,
20116 SourceLocation StartLoc, SourceLocation LParenLoc,
20117 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
20118 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20119 ArrayRef<Expr *> UnresolvedReductions) {
20120 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
20121 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
20122 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
20123 /*Last=*/OMPC_REDUCTION_unknown)
20124 << getOpenMPClauseName(OMPC_reduction);
20125 return nullptr;
20127 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
20128 // A reduction clause with the inscan reduction-modifier may only appear on a
20129 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
20130 // construct, a parallel worksharing-loop construct or a parallel
20131 // worksharing-loop SIMD construct.
20132 if (Modifier == OMPC_REDUCTION_inscan &&
20133 (DSAStack->getCurrentDirective() != OMPD_for &&
20134 DSAStack->getCurrentDirective() != OMPD_for_simd &&
20135 DSAStack->getCurrentDirective() != OMPD_simd &&
20136 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
20137 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
20138 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
20139 return nullptr;
20142 ReductionData RD(VarList.size(), Modifier);
20143 if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_reduction, VarList,
20144 StartLoc, LParenLoc, ColonLoc, EndLoc,
20145 ReductionIdScopeSpec, ReductionId,
20146 UnresolvedReductions, RD))
20147 return nullptr;
20149 return OMPReductionClause::Create(
20150 Context, StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc, Modifier,
20151 RD.Vars, ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId,
20152 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
20153 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
20154 buildPreInits(Context, RD.ExprCaptures),
20155 buildPostUpdate(*this, RD.ExprPostUpdates));
20158 OMPClause *Sema::ActOnOpenMPTaskReductionClause(
20159 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20160 SourceLocation ColonLoc, SourceLocation EndLoc,
20161 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20162 ArrayRef<Expr *> UnresolvedReductions) {
20163 ReductionData RD(VarList.size());
20164 if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_task_reduction, VarList,
20165 StartLoc, LParenLoc, ColonLoc, EndLoc,
20166 ReductionIdScopeSpec, ReductionId,
20167 UnresolvedReductions, RD))
20168 return nullptr;
20170 return OMPTaskReductionClause::Create(
20171 Context, StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20172 ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId,
20173 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
20174 buildPreInits(Context, RD.ExprCaptures),
20175 buildPostUpdate(*this, RD.ExprPostUpdates));
20178 OMPClause *Sema::ActOnOpenMPInReductionClause(
20179 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20180 SourceLocation ColonLoc, SourceLocation EndLoc,
20181 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20182 ArrayRef<Expr *> UnresolvedReductions) {
20183 ReductionData RD(VarList.size());
20184 if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_in_reduction, VarList,
20185 StartLoc, LParenLoc, ColonLoc, EndLoc,
20186 ReductionIdScopeSpec, ReductionId,
20187 UnresolvedReductions, RD))
20188 return nullptr;
20190 return OMPInReductionClause::Create(
20191 Context, StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20192 ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId,
20193 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
20194 buildPreInits(Context, RD.ExprCaptures),
20195 buildPostUpdate(*this, RD.ExprPostUpdates));
20198 bool Sema::CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
20199 SourceLocation LinLoc) {
20200 if ((!LangOpts.CPlusPlus && LinKind != OMPC_LINEAR_val) ||
20201 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
20202 Diag(LinLoc, diag::err_omp_wrong_linear_modifier) << LangOpts.CPlusPlus;
20203 return true;
20205 return false;
20208 bool Sema::CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc,
20209 OpenMPLinearClauseKind LinKind, QualType Type,
20210 bool IsDeclareSimd) {
20211 const auto *VD = dyn_cast_or_null<VarDecl>(D);
20212 // A variable must not have an incomplete type or a reference type.
20213 if (RequireCompleteType(ELoc, Type, diag::err_omp_linear_incomplete_type))
20214 return true;
20215 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
20216 !Type->isReferenceType()) {
20217 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
20218 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
20219 return true;
20221 Type = Type.getNonReferenceType();
20223 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
20224 // A variable that is privatized must not have a const-qualified type
20225 // unless it is of class type with a mutable member. This restriction does
20226 // not apply to the firstprivate clause, nor to the linear clause on
20227 // declarative directives (like declare simd).
20228 if (!IsDeclareSimd &&
20229 rejectConstNotMutableType(*this, D, Type, OMPC_linear, ELoc))
20230 return true;
20232 // A list item must be of integral or pointer type.
20233 Type = Type.getUnqualifiedType().getCanonicalType();
20234 const auto *Ty = Type.getTypePtrOrNull();
20235 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
20236 !Ty->isIntegralType(Context) && !Ty->isPointerType())) {
20237 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
20238 if (D) {
20239 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20240 VarDecl::DeclarationOnly;
20241 Diag(D->getLocation(),
20242 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20243 << D;
20245 return true;
20247 return false;
20250 OMPClause *Sema::ActOnOpenMPLinearClause(
20251 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
20252 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
20253 SourceLocation LinLoc, SourceLocation ColonLoc,
20254 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
20255 SmallVector<Expr *, 8> Vars;
20256 SmallVector<Expr *, 8> Privates;
20257 SmallVector<Expr *, 8> Inits;
20258 SmallVector<Decl *, 4> ExprCaptures;
20259 SmallVector<Expr *, 4> ExprPostUpdates;
20260 // OpenMP 5.2 [Section 5.4.6, linear clause]
20261 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
20262 // 'ref'
20263 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
20264 getLangOpts().OpenMP >= 52)
20265 Diag(Step->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
20266 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
20267 LinKind = OMPC_LINEAR_val;
20268 for (Expr *RefExpr : VarList) {
20269 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20270 SourceLocation ELoc;
20271 SourceRange ERange;
20272 Expr *SimpleRefExpr = RefExpr;
20273 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
20274 if (Res.second) {
20275 // It will be analyzed later.
20276 Vars.push_back(RefExpr);
20277 Privates.push_back(nullptr);
20278 Inits.push_back(nullptr);
20280 ValueDecl *D = Res.first;
20281 if (!D)
20282 continue;
20284 QualType Type = D->getType();
20285 auto *VD = dyn_cast<VarDecl>(D);
20287 // OpenMP [2.14.3.7, linear clause]
20288 // A list-item cannot appear in more than one linear clause.
20289 // A list-item that appears in a linear clause cannot appear in any
20290 // other data-sharing attribute clause.
20291 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
20292 if (DVar.RefExpr) {
20293 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
20294 << getOpenMPClauseName(OMPC_linear);
20295 reportOriginalDsa(*this, DSAStack, D, DVar);
20296 continue;
20299 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
20300 continue;
20301 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20303 // Build private copy of original var.
20304 VarDecl *Private =
20305 buildVarDecl(*this, ELoc, Type, D->getName(),
20306 D->hasAttrs() ? &D->getAttrs() : nullptr,
20307 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
20308 DeclRefExpr *PrivateRef = buildDeclRefExpr(*this, Private, Type, ELoc);
20309 // Build var to save initial value.
20310 VarDecl *Init = buildVarDecl(*this, ELoc, Type, ".linear.start");
20311 Expr *InitExpr;
20312 DeclRefExpr *Ref = nullptr;
20313 if (!VD && !CurContext->isDependentContext()) {
20314 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
20315 if (!isOpenMPCapturedDecl(D)) {
20316 ExprCaptures.push_back(Ref->getDecl());
20317 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
20318 ExprResult RefRes = DefaultLvalueConversion(Ref);
20319 if (!RefRes.isUsable())
20320 continue;
20321 ExprResult PostUpdateRes =
20322 BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
20323 SimpleRefExpr, RefRes.get());
20324 if (!PostUpdateRes.isUsable())
20325 continue;
20326 ExprPostUpdates.push_back(
20327 IgnoredValueConversions(PostUpdateRes.get()).get());
20331 if (LinKind == OMPC_LINEAR_uval)
20332 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
20333 else
20334 InitExpr = VD ? SimpleRefExpr : Ref;
20335 AddInitializerToDecl(Init, DefaultLvalueConversion(InitExpr).get(),
20336 /*DirectInit=*/false);
20337 DeclRefExpr *InitRef = buildDeclRefExpr(*this, Init, Type, ELoc);
20339 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
20340 Vars.push_back((VD || CurContext->isDependentContext())
20341 ? RefExpr->IgnoreParens()
20342 : Ref);
20343 Privates.push_back(PrivateRef);
20344 Inits.push_back(InitRef);
20347 if (Vars.empty())
20348 return nullptr;
20350 Expr *StepExpr = Step;
20351 Expr *CalcStepExpr = nullptr;
20352 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
20353 !Step->isInstantiationDependent() &&
20354 !Step->containsUnexpandedParameterPack()) {
20355 SourceLocation StepLoc = Step->getBeginLoc();
20356 ExprResult Val = PerformOpenMPImplicitIntegerConversion(StepLoc, Step);
20357 if (Val.isInvalid())
20358 return nullptr;
20359 StepExpr = Val.get();
20361 // Build var to save the step value.
20362 VarDecl *SaveVar =
20363 buildVarDecl(*this, StepLoc, StepExpr->getType(), ".linear.step");
20364 ExprResult SaveRef =
20365 buildDeclRefExpr(*this, SaveVar, StepExpr->getType(), StepLoc);
20366 ExprResult CalcStep =
20367 BuildBinOp(CurScope, StepLoc, BO_Assign, SaveRef.get(), StepExpr);
20368 CalcStep = ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue*/ false);
20370 // Warn about zero linear step (it would be probably better specified as
20371 // making corresponding variables 'const').
20372 if (std::optional<llvm::APSInt> Result =
20373 StepExpr->getIntegerConstantExpr(Context)) {
20374 if (!Result->isNegative() && !Result->isStrictlyPositive())
20375 Diag(StepLoc, diag::warn_omp_linear_step_zero)
20376 << Vars[0] << (Vars.size() > 1);
20377 } else if (CalcStep.isUsable()) {
20378 // Calculate the step beforehand instead of doing this on each iteration.
20379 // (This is not used if the number of iterations may be kfold-ed).
20380 CalcStepExpr = CalcStep.get();
20384 return OMPLinearClause::Create(Context, StartLoc, LParenLoc, LinKind, LinLoc,
20385 ColonLoc, StepModifierLoc, EndLoc, Vars,
20386 Privates, Inits, StepExpr, CalcStepExpr,
20387 buildPreInits(Context, ExprCaptures),
20388 buildPostUpdate(*this, ExprPostUpdates));
20391 static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
20392 Expr *NumIterations, Sema &SemaRef,
20393 Scope *S, DSAStackTy *Stack) {
20394 // Walk the vars and build update/final expressions for the CodeGen.
20395 SmallVector<Expr *, 8> Updates;
20396 SmallVector<Expr *, 8> Finals;
20397 SmallVector<Expr *, 8> UsedExprs;
20398 Expr *Step = Clause.getStep();
20399 Expr *CalcStep = Clause.getCalcStep();
20400 // OpenMP [2.14.3.7, linear clause]
20401 // If linear-step is not specified it is assumed to be 1.
20402 if (!Step)
20403 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
20404 else if (CalcStep)
20405 Step = cast<BinaryOperator>(CalcStep)->getLHS();
20406 bool HasErrors = false;
20407 auto CurInit = Clause.inits().begin();
20408 auto CurPrivate = Clause.privates().begin();
20409 OpenMPLinearClauseKind LinKind = Clause.getModifier();
20410 for (Expr *RefExpr : Clause.varlists()) {
20411 SourceLocation ELoc;
20412 SourceRange ERange;
20413 Expr *SimpleRefExpr = RefExpr;
20414 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20415 ValueDecl *D = Res.first;
20416 if (Res.second || !D) {
20417 Updates.push_back(nullptr);
20418 Finals.push_back(nullptr);
20419 HasErrors = true;
20420 continue;
20422 auto &&Info = Stack->isLoopControlVariable(D);
20423 // OpenMP [2.15.11, distribute simd Construct]
20424 // A list item may not appear in a linear clause, unless it is the loop
20425 // iteration variable.
20426 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
20427 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
20428 SemaRef.Diag(ELoc,
20429 diag::err_omp_linear_distribute_var_non_loop_iteration);
20430 Updates.push_back(nullptr);
20431 Finals.push_back(nullptr);
20432 HasErrors = true;
20433 continue;
20435 Expr *InitExpr = *CurInit;
20437 // Build privatized reference to the current linear var.
20438 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
20439 Expr *CapturedRef;
20440 if (LinKind == OMPC_LINEAR_uval)
20441 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
20442 else
20443 CapturedRef =
20444 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
20445 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
20446 /*RefersToCapture=*/true);
20448 // Build update: Var = InitExpr + IV * Step
20449 ExprResult Update;
20450 if (!Info.first)
20451 Update = buildCounterUpdate(
20452 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
20453 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
20454 else
20455 Update = *CurPrivate;
20456 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
20457 /*DiscardedValue*/ false);
20459 // Build final: Var = PrivCopy;
20460 ExprResult Final;
20461 if (!Info.first)
20462 Final = SemaRef.BuildBinOp(
20463 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
20464 SemaRef.DefaultLvalueConversion(*CurPrivate).get());
20465 else
20466 Final = *CurPrivate;
20467 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
20468 /*DiscardedValue*/ false);
20470 if (!Update.isUsable() || !Final.isUsable()) {
20471 Updates.push_back(nullptr);
20472 Finals.push_back(nullptr);
20473 UsedExprs.push_back(nullptr);
20474 HasErrors = true;
20475 } else {
20476 Updates.push_back(Update.get());
20477 Finals.push_back(Final.get());
20478 if (!Info.first)
20479 UsedExprs.push_back(SimpleRefExpr);
20481 ++CurInit;
20482 ++CurPrivate;
20484 if (Expr *S = Clause.getStep())
20485 UsedExprs.push_back(S);
20486 // Fill the remaining part with the nullptr.
20487 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
20488 Clause.setUpdates(Updates);
20489 Clause.setFinals(Finals);
20490 Clause.setUsedExprs(UsedExprs);
20491 return HasErrors;
20494 OMPClause *Sema::ActOnOpenMPAlignedClause(
20495 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
20496 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
20497 SmallVector<Expr *, 8> Vars;
20498 for (Expr *RefExpr : VarList) {
20499 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20500 SourceLocation ELoc;
20501 SourceRange ERange;
20502 Expr *SimpleRefExpr = RefExpr;
20503 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
20504 if (Res.second) {
20505 // It will be analyzed later.
20506 Vars.push_back(RefExpr);
20508 ValueDecl *D = Res.first;
20509 if (!D)
20510 continue;
20512 QualType QType = D->getType();
20513 auto *VD = dyn_cast<VarDecl>(D);
20515 // OpenMP [2.8.1, simd construct, Restrictions]
20516 // The type of list items appearing in the aligned clause must be
20517 // array, pointer, reference to array, or reference to pointer.
20518 QType = QType.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20519 const Type *Ty = QType.getTypePtrOrNull();
20520 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
20521 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
20522 << QType << getLangOpts().CPlusPlus << ERange;
20523 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20524 VarDecl::DeclarationOnly;
20525 Diag(D->getLocation(),
20526 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20527 << D;
20528 continue;
20531 // OpenMP [2.8.1, simd construct, Restrictions]
20532 // A list-item cannot appear in more than one aligned clause.
20533 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
20534 Diag(ELoc, diag::err_omp_used_in_clause_twice)
20535 << 0 << getOpenMPClauseName(OMPC_aligned) << ERange;
20536 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
20537 << getOpenMPClauseName(OMPC_aligned);
20538 continue;
20541 DeclRefExpr *Ref = nullptr;
20542 if (!VD && isOpenMPCapturedDecl(D))
20543 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
20544 Vars.push_back(DefaultFunctionArrayConversion(
20545 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
20546 .get());
20549 // OpenMP [2.8.1, simd construct, Description]
20550 // The parameter of the aligned clause, alignment, must be a constant
20551 // positive integer expression.
20552 // If no optional parameter is specified, implementation-defined default
20553 // alignments for SIMD instructions on the target platforms are assumed.
20554 if (Alignment != nullptr) {
20555 ExprResult AlignResult =
20556 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
20557 if (AlignResult.isInvalid())
20558 return nullptr;
20559 Alignment = AlignResult.get();
20561 if (Vars.empty())
20562 return nullptr;
20564 return OMPAlignedClause::Create(Context, StartLoc, LParenLoc, ColonLoc,
20565 EndLoc, Vars, Alignment);
20568 OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
20569 SourceLocation StartLoc,
20570 SourceLocation LParenLoc,
20571 SourceLocation EndLoc) {
20572 SmallVector<Expr *, 8> Vars;
20573 SmallVector<Expr *, 8> SrcExprs;
20574 SmallVector<Expr *, 8> DstExprs;
20575 SmallVector<Expr *, 8> AssignmentOps;
20576 for (Expr *RefExpr : VarList) {
20577 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
20578 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20579 // It will be analyzed later.
20580 Vars.push_back(RefExpr);
20581 SrcExprs.push_back(nullptr);
20582 DstExprs.push_back(nullptr);
20583 AssignmentOps.push_back(nullptr);
20584 continue;
20587 SourceLocation ELoc = RefExpr->getExprLoc();
20588 // OpenMP [2.1, C/C++]
20589 // A list item is a variable name.
20590 // OpenMP [2.14.4.1, Restrictions, p.1]
20591 // A list item that appears in a copyin clause must be threadprivate.
20592 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
20593 if (!DE || !isa<VarDecl>(DE->getDecl())) {
20594 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
20595 << 0 << RefExpr->getSourceRange();
20596 continue;
20599 Decl *D = DE->getDecl();
20600 auto *VD = cast<VarDecl>(D);
20602 QualType Type = VD->getType();
20603 if (Type->isDependentType() || Type->isInstantiationDependentType()) {
20604 // It will be analyzed later.
20605 Vars.push_back(DE);
20606 SrcExprs.push_back(nullptr);
20607 DstExprs.push_back(nullptr);
20608 AssignmentOps.push_back(nullptr);
20609 continue;
20612 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
20613 // A list item that appears in a copyin clause must be threadprivate.
20614 if (!DSAStack->isThreadPrivate(VD)) {
20615 Diag(ELoc, diag::err_omp_required_access)
20616 << getOpenMPClauseName(OMPC_copyin)
20617 << getOpenMPDirectiveName(OMPD_threadprivate);
20618 continue;
20621 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20622 // A variable of class type (or array thereof) that appears in a
20623 // copyin clause requires an accessible, unambiguous copy assignment
20624 // operator for the class type.
20625 QualType ElemType = Context.getBaseElementType(Type).getNonReferenceType();
20626 VarDecl *SrcVD =
20627 buildVarDecl(*this, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
20628 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20629 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
20630 *this, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
20631 VarDecl *DstVD =
20632 buildVarDecl(*this, DE->getBeginLoc(), ElemType, ".copyin.dst",
20633 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20634 DeclRefExpr *PseudoDstExpr =
20635 buildDeclRefExpr(*this, DstVD, ElemType, DE->getExprLoc());
20636 // For arrays generate assignment operation for single element and replace
20637 // it by the original array element in CodeGen.
20638 ExprResult AssignmentOp =
20639 BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign, PseudoDstExpr,
20640 PseudoSrcExpr);
20641 if (AssignmentOp.isInvalid())
20642 continue;
20643 AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
20644 /*DiscardedValue*/ false);
20645 if (AssignmentOp.isInvalid())
20646 continue;
20648 DSAStack->addDSA(VD, DE, OMPC_copyin);
20649 Vars.push_back(DE);
20650 SrcExprs.push_back(PseudoSrcExpr);
20651 DstExprs.push_back(PseudoDstExpr);
20652 AssignmentOps.push_back(AssignmentOp.get());
20655 if (Vars.empty())
20656 return nullptr;
20658 return OMPCopyinClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars,
20659 SrcExprs, DstExprs, AssignmentOps);
20662 OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
20663 SourceLocation StartLoc,
20664 SourceLocation LParenLoc,
20665 SourceLocation EndLoc) {
20666 SmallVector<Expr *, 8> Vars;
20667 SmallVector<Expr *, 8> SrcExprs;
20668 SmallVector<Expr *, 8> DstExprs;
20669 SmallVector<Expr *, 8> AssignmentOps;
20670 for (Expr *RefExpr : VarList) {
20671 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20672 SourceLocation ELoc;
20673 SourceRange ERange;
20674 Expr *SimpleRefExpr = RefExpr;
20675 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
20676 if (Res.second) {
20677 // It will be analyzed later.
20678 Vars.push_back(RefExpr);
20679 SrcExprs.push_back(nullptr);
20680 DstExprs.push_back(nullptr);
20681 AssignmentOps.push_back(nullptr);
20683 ValueDecl *D = Res.first;
20684 if (!D)
20685 continue;
20687 QualType Type = D->getType();
20688 auto *VD = dyn_cast<VarDecl>(D);
20690 // OpenMP [2.14.4.2, Restrictions, p.2]
20691 // A list item that appears in a copyprivate clause may not appear in a
20692 // private or firstprivate clause on the single construct.
20693 if (!VD || !DSAStack->isThreadPrivate(VD)) {
20694 DSAStackTy::DSAVarData DVar =
20695 DSAStack->getTopDSA(D, /*FromParent=*/false);
20696 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
20697 DVar.RefExpr) {
20698 Diag(ELoc, diag::err_omp_wrong_dsa)
20699 << getOpenMPClauseName(DVar.CKind)
20700 << getOpenMPClauseName(OMPC_copyprivate);
20701 reportOriginalDsa(*this, DSAStack, D, DVar);
20702 continue;
20705 // OpenMP [2.11.4.2, Restrictions, p.1]
20706 // All list items that appear in a copyprivate clause must be either
20707 // threadprivate or private in the enclosing context.
20708 if (DVar.CKind == OMPC_unknown) {
20709 DVar = DSAStack->getImplicitDSA(D, false);
20710 if (DVar.CKind == OMPC_shared) {
20711 Diag(ELoc, diag::err_omp_required_access)
20712 << getOpenMPClauseName(OMPC_copyprivate)
20713 << "threadprivate or private in the enclosing context";
20714 reportOriginalDsa(*this, DSAStack, D, DVar);
20715 continue;
20720 // Variably modified types are not supported.
20721 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType()) {
20722 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
20723 << getOpenMPClauseName(OMPC_copyprivate) << Type
20724 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
20725 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20726 VarDecl::DeclarationOnly;
20727 Diag(D->getLocation(),
20728 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20729 << D;
20730 continue;
20733 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20734 // A variable of class type (or array thereof) that appears in a
20735 // copyin clause requires an accessible, unambiguous copy assignment
20736 // operator for the class type.
20737 Type = Context.getBaseElementType(Type.getNonReferenceType())
20738 .getUnqualifiedType();
20739 VarDecl *SrcVD =
20740 buildVarDecl(*this, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
20741 D->hasAttrs() ? &D->getAttrs() : nullptr);
20742 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(*this, SrcVD, Type, ELoc);
20743 VarDecl *DstVD =
20744 buildVarDecl(*this, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
20745 D->hasAttrs() ? &D->getAttrs() : nullptr);
20746 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc);
20747 ExprResult AssignmentOp = BuildBinOp(
20748 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
20749 if (AssignmentOp.isInvalid())
20750 continue;
20751 AssignmentOp =
20752 ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false);
20753 if (AssignmentOp.isInvalid())
20754 continue;
20756 // No need to mark vars as copyprivate, they are already threadprivate or
20757 // implicitly private.
20758 assert(VD || isOpenMPCapturedDecl(D));
20759 Vars.push_back(
20760 VD ? RefExpr->IgnoreParens()
20761 : buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false));
20762 SrcExprs.push_back(PseudoSrcExpr);
20763 DstExprs.push_back(PseudoDstExpr);
20764 AssignmentOps.push_back(AssignmentOp.get());
20767 if (Vars.empty())
20768 return nullptr;
20770 return OMPCopyprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
20771 Vars, SrcExprs, DstExprs, AssignmentOps);
20774 OMPClause *Sema::ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList,
20775 SourceLocation StartLoc,
20776 SourceLocation LParenLoc,
20777 SourceLocation EndLoc) {
20778 if (VarList.empty())
20779 return nullptr;
20781 return OMPFlushClause::Create(Context, StartLoc, LParenLoc, EndLoc, VarList);
20784 /// Tries to find omp_depend_t. type.
20785 static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
20786 bool Diagnose = true) {
20787 QualType OMPDependT = Stack->getOMPDependT();
20788 if (!OMPDependT.isNull())
20789 return true;
20790 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
20791 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
20792 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
20793 if (Diagnose)
20794 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
20795 return false;
20797 Stack->setOMPDependT(PT.get());
20798 return true;
20801 OMPClause *Sema::ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc,
20802 SourceLocation LParenLoc,
20803 SourceLocation EndLoc) {
20804 if (!Depobj)
20805 return nullptr;
20807 bool OMPDependTFound = findOMPDependT(*this, StartLoc, DSAStack);
20809 // OpenMP 5.0, 2.17.10.1 depobj Construct
20810 // depobj is an lvalue expression of type omp_depend_t.
20811 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
20812 !Depobj->isInstantiationDependent() &&
20813 !Depobj->containsUnexpandedParameterPack() &&
20814 (OMPDependTFound &&
20815 !Context.typesAreCompatible(DSAStack->getOMPDependT(), Depobj->getType(),
20816 /*CompareUnqualified=*/true))) {
20817 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20818 << 0 << Depobj->getType() << Depobj->getSourceRange();
20821 if (!Depobj->isLValue()) {
20822 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20823 << 1 << Depobj->getSourceRange();
20826 return OMPDepobjClause::Create(Context, StartLoc, LParenLoc, EndLoc, Depobj);
20829 namespace {
20830 // Utility struct that gathers the related info for doacross clause.
20831 struct DoacrossDataInfoTy {
20832 // The list of expressions.
20833 SmallVector<Expr *, 8> Vars;
20834 // The OperatorOffset for doacross loop.
20835 DSAStackTy::OperatorOffsetTy OpsOffs;
20836 // The depended loop count.
20837 llvm::APSInt TotalDepCount;
20839 } // namespace
20840 static DoacrossDataInfoTy
20841 ProcessOpenMPDoacrossClauseCommon(Sema &SemaRef, bool IsSource,
20842 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
20843 SourceLocation EndLoc) {
20845 SmallVector<Expr *, 8> Vars;
20846 DSAStackTy::OperatorOffsetTy OpsOffs;
20847 llvm::APSInt DepCounter(/*BitWidth=*/32);
20848 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
20850 if (const Expr *OrderedCountExpr =
20851 Stack->getParentOrderedRegionParam().first) {
20852 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.Context);
20853 TotalDepCount.setIsUnsigned(/*Val=*/true);
20856 for (Expr *RefExpr : VarList) {
20857 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
20858 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20859 // It will be analyzed later.
20860 Vars.push_back(RefExpr);
20861 continue;
20864 SourceLocation ELoc = RefExpr->getExprLoc();
20865 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
20866 if (!IsSource) {
20867 if (Stack->getParentOrderedRegionParam().first &&
20868 DepCounter >= TotalDepCount) {
20869 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
20870 continue;
20872 ++DepCounter;
20873 // OpenMP [2.13.9, Summary]
20874 // depend(dependence-type : vec), where dependence-type is:
20875 // 'sink' and where vec is the iteration vector, which has the form:
20876 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
20877 // where n is the value specified by the ordered clause in the loop
20878 // directive, xi denotes the loop iteration variable of the i-th nested
20879 // loop associated with the loop directive, and di is a constant
20880 // non-negative integer.
20881 if (SemaRef.CurContext->isDependentContext()) {
20882 // It will be analyzed later.
20883 Vars.push_back(RefExpr);
20884 continue;
20886 SimpleExpr = SimpleExpr->IgnoreImplicit();
20887 OverloadedOperatorKind OOK = OO_None;
20888 SourceLocation OOLoc;
20889 Expr *LHS = SimpleExpr;
20890 Expr *RHS = nullptr;
20891 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
20892 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
20893 OOLoc = BO->getOperatorLoc();
20894 LHS = BO->getLHS()->IgnoreParenImpCasts();
20895 RHS = BO->getRHS()->IgnoreParenImpCasts();
20896 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
20897 OOK = OCE->getOperator();
20898 OOLoc = OCE->getOperatorLoc();
20899 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20900 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
20901 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
20902 OOK = MCE->getMethodDecl()
20903 ->getNameInfo()
20904 .getName()
20905 .getCXXOverloadedOperator();
20906 OOLoc = MCE->getCallee()->getExprLoc();
20907 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
20908 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20910 SourceLocation ELoc;
20911 SourceRange ERange;
20912 auto Res = getPrivateItem(SemaRef, LHS, ELoc, ERange);
20913 if (Res.second) {
20914 // It will be analyzed later.
20915 Vars.push_back(RefExpr);
20917 ValueDecl *D = Res.first;
20918 if (!D)
20919 continue;
20921 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
20922 SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
20923 continue;
20925 if (RHS) {
20926 ExprResult RHSRes = SemaRef.VerifyPositiveIntegerConstantInClause(
20927 RHS, OMPC_depend, /*StrictlyPositive=*/false);
20928 if (RHSRes.isInvalid())
20929 continue;
20931 if (!SemaRef.CurContext->isDependentContext() &&
20932 Stack->getParentOrderedRegionParam().first &&
20933 DepCounter != Stack->isParentLoopControlVariable(D).first) {
20934 const ValueDecl *VD =
20935 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
20936 if (VD)
20937 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
20938 << 1 << VD;
20939 else
20940 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
20941 << 0;
20942 continue;
20944 OpsOffs.emplace_back(RHS, OOK);
20946 Vars.push_back(RefExpr->IgnoreParenImpCasts());
20948 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
20949 TotalDepCount > VarList.size() &&
20950 Stack->getParentOrderedRegionParam().first &&
20951 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
20952 SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
20953 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
20955 return {Vars, OpsOffs, TotalDepCount};
20958 OMPClause *
20959 Sema::ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data,
20960 Expr *DepModifier, ArrayRef<Expr *> VarList,
20961 SourceLocation StartLoc, SourceLocation LParenLoc,
20962 SourceLocation EndLoc) {
20963 OpenMPDependClauseKind DepKind = Data.DepKind;
20964 SourceLocation DepLoc = Data.DepLoc;
20965 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
20966 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
20967 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20968 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
20969 return nullptr;
20971 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
20972 DepKind == OMPC_DEPEND_mutexinoutset) {
20973 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
20974 return nullptr;
20976 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
20977 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20978 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
20979 DepKind == OMPC_DEPEND_sink ||
20980 ((LangOpts.OpenMP < 50 ||
20981 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20982 DepKind == OMPC_DEPEND_depobj))) {
20983 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
20984 OMPC_DEPEND_outallmemory,
20985 OMPC_DEPEND_inoutallmemory};
20986 if (LangOpts.OpenMP < 50 || DSAStack->getCurrentDirective() == OMPD_depobj)
20987 Except.push_back(OMPC_DEPEND_depobj);
20988 if (LangOpts.OpenMP < 51)
20989 Except.push_back(OMPC_DEPEND_inoutset);
20990 std::string Expected = (LangOpts.OpenMP >= 50 && !DepModifier)
20991 ? "depend modifier(iterator) or "
20992 : "";
20993 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20994 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
20995 /*Last=*/OMPC_DEPEND_unknown,
20996 Except)
20997 << getOpenMPClauseName(OMPC_depend);
20998 return nullptr;
21000 if (DepModifier &&
21001 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
21002 Diag(DepModifier->getExprLoc(),
21003 diag::err_omp_depend_sink_source_with_modifier);
21004 return nullptr;
21006 if (DepModifier &&
21007 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
21008 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
21010 SmallVector<Expr *, 8> Vars;
21011 DSAStackTy::OperatorOffsetTy OpsOffs;
21012 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
21014 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
21015 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
21016 *this, DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
21017 Vars = VarOffset.Vars;
21018 OpsOffs = VarOffset.OpsOffs;
21019 TotalDepCount = VarOffset.TotalDepCount;
21020 } else {
21021 for (Expr *RefExpr : VarList) {
21022 assert(RefExpr && "NULL expr in OpenMP shared clause.");
21023 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
21024 // It will be analyzed later.
21025 Vars.push_back(RefExpr);
21026 continue;
21029 SourceLocation ELoc = RefExpr->getExprLoc();
21030 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
21031 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
21032 bool OMPDependTFound = LangOpts.OpenMP >= 50;
21033 if (OMPDependTFound)
21034 OMPDependTFound = findOMPDependT(*this, StartLoc, DSAStack,
21035 DepKind == OMPC_DEPEND_depobj);
21036 if (DepKind == OMPC_DEPEND_depobj) {
21037 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21038 // List items used in depend clauses with the depobj dependence type
21039 // must be expressions of the omp_depend_t type.
21040 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21041 !RefExpr->isInstantiationDependent() &&
21042 !RefExpr->containsUnexpandedParameterPack() &&
21043 (OMPDependTFound &&
21044 !Context.hasSameUnqualifiedType(DSAStack->getOMPDependT(),
21045 RefExpr->getType()))) {
21046 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21047 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
21048 continue;
21050 if (!RefExpr->isLValue()) {
21051 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21052 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
21053 continue;
21055 } else {
21056 // OpenMP 5.0 [2.17.11, Restrictions]
21057 // List items used in depend clauses cannot be zero-length array
21058 // sections.
21059 QualType ExprTy = RefExpr->getType().getNonReferenceType();
21060 const auto *OASE = dyn_cast<OMPArraySectionExpr>(SimpleExpr);
21061 if (OASE) {
21062 QualType BaseType =
21063 OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
21064 if (BaseType.isNull())
21065 return nullptr;
21066 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21067 ExprTy = ATy->getElementType();
21068 else
21069 ExprTy = BaseType->getPointeeType();
21070 ExprTy = ExprTy.getNonReferenceType();
21071 const Expr *Length = OASE->getLength();
21072 Expr::EvalResult Result;
21073 if (Length && !Length->isValueDependent() &&
21074 Length->EvaluateAsInt(Result, Context) &&
21075 Result.Val.getInt().isZero()) {
21076 Diag(ELoc,
21077 diag::err_omp_depend_zero_length_array_section_not_allowed)
21078 << SimpleExpr->getSourceRange();
21079 continue;
21083 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21084 // List items used in depend clauses with the in, out, inout,
21085 // inoutset, or mutexinoutset dependence types cannot be
21086 // expressions of the omp_depend_t type.
21087 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21088 !RefExpr->isInstantiationDependent() &&
21089 !RefExpr->containsUnexpandedParameterPack() &&
21090 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
21091 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
21092 ExprTy.getTypePtr()))) {
21093 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21094 << (LangOpts.OpenMP >= 50 ? 1 : 0)
21095 << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
21096 continue;
21099 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
21100 if (ASE && !ASE->getBase()->isTypeDependent() &&
21101 !ASE->getBase()
21102 ->getType()
21103 .getNonReferenceType()
21104 ->isPointerType() &&
21105 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
21106 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21107 << (LangOpts.OpenMP >= 50 ? 1 : 0)
21108 << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
21109 continue;
21112 ExprResult Res;
21114 Sema::TentativeAnalysisScope Trap(*this);
21115 Res = CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
21116 RefExpr->IgnoreParenImpCasts());
21118 if (!Res.isUsable() && !isa<OMPArraySectionExpr>(SimpleExpr) &&
21119 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
21120 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21121 << (LangOpts.OpenMP >= 50 ? 1 : 0)
21122 << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
21123 continue;
21127 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21131 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
21132 DepKind != OMPC_DEPEND_outallmemory &&
21133 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
21134 return nullptr;
21136 auto *C = OMPDependClause::Create(
21137 Context, StartLoc, LParenLoc, EndLoc,
21138 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
21139 TotalDepCount.getZExtValue());
21140 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
21141 DSAStack->isParentOrderedRegion())
21142 DSAStack->addDoacrossDependClause(C, OpsOffs);
21143 return C;
21146 OMPClause *Sema::ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier,
21147 Expr *Device, SourceLocation StartLoc,
21148 SourceLocation LParenLoc,
21149 SourceLocation ModifierLoc,
21150 SourceLocation EndLoc) {
21151 assert((ModifierLoc.isInvalid() || LangOpts.OpenMP >= 50) &&
21152 "Unexpected device modifier in OpenMP < 50.");
21154 bool ErrorFound = false;
21155 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
21156 std::string Values =
21157 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
21158 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
21159 << Values << getOpenMPClauseName(OMPC_device);
21160 ErrorFound = true;
21163 Expr *ValExpr = Device;
21164 Stmt *HelperValStmt = nullptr;
21166 // OpenMP [2.9.1, Restrictions]
21167 // The device expression must evaluate to a non-negative integer value.
21168 ErrorFound = !isNonNegativeIntegerValue(ValExpr, *this, OMPC_device,
21169 /*StrictlyPositive=*/false) ||
21170 ErrorFound;
21171 if (ErrorFound)
21172 return nullptr;
21174 // OpenMP 5.0 [2.12.5, Restrictions]
21175 // In case of ancestor device-modifier, a requires directive with
21176 // the reverse_offload clause must be specified.
21177 if (Modifier == OMPC_DEVICE_ancestor) {
21178 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
21179 targetDiag(
21180 StartLoc,
21181 diag::err_omp_device_ancestor_without_requires_reverse_offload);
21182 ErrorFound = true;
21186 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
21187 OpenMPDirectiveKind CaptureRegion =
21188 getOpenMPCaptureRegionForClause(DKind, OMPC_device, LangOpts.OpenMP);
21189 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
21190 ValExpr = MakeFullExpr(ValExpr).get();
21191 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21192 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
21193 HelperValStmt = buildPreInits(Context, Captures);
21196 return new (Context)
21197 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
21198 LParenLoc, ModifierLoc, EndLoc);
21201 static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef,
21202 DSAStackTy *Stack, QualType QTy,
21203 bool FullCheck = true) {
21204 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
21205 return false;
21206 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
21207 !QTy.isTriviallyCopyableType(SemaRef.Context))
21208 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
21209 return true;
21212 /// Return true if it can be proven that the provided array expression
21213 /// (array section or array subscript) does NOT specify the whole size of the
21214 /// array whose base type is \a BaseQTy.
21215 static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
21216 const Expr *E,
21217 QualType BaseQTy) {
21218 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
21220 // If this is an array subscript, it refers to the whole size if the size of
21221 // the dimension is constant and equals 1. Also, an array section assumes the
21222 // format of an array subscript if no colon is used.
21223 if (isa<ArraySubscriptExpr>(E) ||
21224 (OASE && OASE->getColonLocFirst().isInvalid())) {
21225 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
21226 return ATy->getSize().getSExtValue() != 1;
21227 // Size can't be evaluated statically.
21228 return false;
21231 assert(OASE && "Expecting array section if not an array subscript.");
21232 const Expr *LowerBound = OASE->getLowerBound();
21233 const Expr *Length = OASE->getLength();
21235 // If there is a lower bound that does not evaluates to zero, we are not
21236 // covering the whole dimension.
21237 if (LowerBound) {
21238 Expr::EvalResult Result;
21239 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
21240 return false; // Can't get the integer value as a constant.
21242 llvm::APSInt ConstLowerBound = Result.Val.getInt();
21243 if (ConstLowerBound.getSExtValue())
21244 return true;
21247 // If we don't have a length we covering the whole dimension.
21248 if (!Length)
21249 return false;
21251 // If the base is a pointer, we don't have a way to get the size of the
21252 // pointee.
21253 if (BaseQTy->isPointerType())
21254 return false;
21256 // We can only check if the length is the same as the size of the dimension
21257 // if we have a constant array.
21258 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
21259 if (!CATy)
21260 return false;
21262 Expr::EvalResult Result;
21263 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
21264 return false; // Can't get the integer value as a constant.
21266 llvm::APSInt ConstLength = Result.Val.getInt();
21267 return CATy->getSize().getSExtValue() != ConstLength.getSExtValue();
21270 // Return true if it can be proven that the provided array expression (array
21271 // section or array subscript) does NOT specify a single element of the array
21272 // whose base type is \a BaseQTy.
21273 static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
21274 const Expr *E,
21275 QualType BaseQTy) {
21276 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
21278 // An array subscript always refer to a single element. Also, an array section
21279 // assumes the format of an array subscript if no colon is used.
21280 if (isa<ArraySubscriptExpr>(E) ||
21281 (OASE && OASE->getColonLocFirst().isInvalid()))
21282 return false;
21284 assert(OASE && "Expecting array section if not an array subscript.");
21285 const Expr *Length = OASE->getLength();
21287 // If we don't have a length we have to check if the array has unitary size
21288 // for this dimension. Also, we should always expect a length if the base type
21289 // is pointer.
21290 if (!Length) {
21291 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
21292 return ATy->getSize().getSExtValue() != 1;
21293 // We cannot assume anything.
21294 return false;
21297 // Check if the length evaluates to 1.
21298 Expr::EvalResult Result;
21299 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
21300 return false; // Can't get the integer value as a constant.
21302 llvm::APSInt ConstLength = Result.Val.getInt();
21303 return ConstLength.getSExtValue() != 1;
21306 // The base of elements of list in a map clause have to be either:
21307 // - a reference to variable or field.
21308 // - a member expression.
21309 // - an array expression.
21311 // E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
21312 // reference to 'r'.
21314 // If we have:
21316 // struct SS {
21317 // Bla S;
21318 // foo() {
21319 // #pragma omp target map (S.Arr[:12]);
21320 // }
21321 // }
21323 // We want to retrieve the member expression 'this->S';
21325 // OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
21326 // If a list item is an array section, it must specify contiguous storage.
21328 // For this restriction it is sufficient that we make sure only references
21329 // to variables or fields and array expressions, and that no array sections
21330 // exist except in the rightmost expression (unless they cover the whole
21331 // dimension of the array). E.g. these would be invalid:
21333 // r.ArrS[3:5].Arr[6:7]
21335 // r.ArrS[3:5].x
21337 // but these would be valid:
21338 // r.ArrS[3].Arr[6:7]
21340 // r.ArrS[3].x
21341 namespace {
21342 class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
21343 Sema &SemaRef;
21344 OpenMPClauseKind CKind = OMPC_unknown;
21345 OpenMPDirectiveKind DKind = OMPD_unknown;
21346 OMPClauseMappableExprCommon::MappableExprComponentList &Components;
21347 bool IsNonContiguous = false;
21348 bool NoDiagnose = false;
21349 const Expr *RelevantExpr = nullptr;
21350 bool AllowUnitySizeArraySection = true;
21351 bool AllowWholeSizeArraySection = true;
21352 bool AllowAnotherPtr = true;
21353 SourceLocation ELoc;
21354 SourceRange ERange;
21356 void emitErrorMsg() {
21357 // If nothing else worked, this is not a valid map clause expression.
21358 if (SemaRef.getLangOpts().OpenMP < 50) {
21359 SemaRef.Diag(ELoc,
21360 diag::err_omp_expected_named_var_member_or_array_expression)
21361 << ERange;
21362 } else {
21363 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21364 << getOpenMPClauseName(CKind) << ERange;
21368 public:
21369 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
21370 if (!isa<VarDecl>(DRE->getDecl())) {
21371 emitErrorMsg();
21372 return false;
21374 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21375 RelevantExpr = DRE;
21376 // Record the component.
21377 Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
21378 return true;
21381 bool VisitMemberExpr(MemberExpr *ME) {
21382 Expr *E = ME;
21383 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
21385 if (isa<CXXThisExpr>(BaseE)) {
21386 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21387 // We found a base expression: this->Val.
21388 RelevantExpr = ME;
21389 } else {
21390 E = BaseE;
21393 if (!isa<FieldDecl>(ME->getMemberDecl())) {
21394 if (!NoDiagnose) {
21395 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
21396 << ME->getSourceRange();
21397 return false;
21399 if (RelevantExpr)
21400 return false;
21401 return Visit(E);
21404 auto *FD = cast<FieldDecl>(ME->getMemberDecl());
21406 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
21407 // A bit-field cannot appear in a map clause.
21409 if (FD->isBitField()) {
21410 if (!NoDiagnose) {
21411 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
21412 << ME->getSourceRange() << getOpenMPClauseName(CKind);
21413 return false;
21415 if (RelevantExpr)
21416 return false;
21417 return Visit(E);
21420 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21421 // If the type of a list item is a reference to a type T then the type
21422 // will be considered to be T for all purposes of this clause.
21423 QualType CurType = BaseE->getType().getNonReferenceType();
21425 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
21426 // A list item cannot be a variable that is a member of a structure with
21427 // a union type.
21429 if (CurType->isUnionType()) {
21430 if (!NoDiagnose) {
21431 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
21432 << ME->getSourceRange();
21433 return false;
21435 return RelevantExpr || Visit(E);
21438 // If we got a member expression, we should not expect any array section
21439 // before that:
21441 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
21442 // If a list item is an element of a structure, only the rightmost symbol
21443 // of the variable reference can be an array section.
21445 AllowUnitySizeArraySection = false;
21446 AllowWholeSizeArraySection = false;
21448 // Record the component.
21449 Components.emplace_back(ME, FD, IsNonContiguous);
21450 return RelevantExpr || Visit(E);
21453 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
21454 Expr *E = AE->getBase()->IgnoreParenImpCasts();
21456 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
21457 if (!NoDiagnose) {
21458 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21459 << 0 << AE->getSourceRange();
21460 return false;
21462 return RelevantExpr || Visit(E);
21465 // If we got an array subscript that express the whole dimension we
21466 // can have any array expressions before. If it only expressing part of
21467 // the dimension, we can only have unitary-size array expressions.
21468 if (checkArrayExpressionDoesNotReferToWholeSize(SemaRef, AE, E->getType()))
21469 AllowWholeSizeArraySection = false;
21471 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
21472 Expr::EvalResult Result;
21473 if (!AE->getIdx()->isValueDependent() &&
21474 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
21475 !Result.Val.getInt().isZero()) {
21476 SemaRef.Diag(AE->getIdx()->getExprLoc(),
21477 diag::err_omp_invalid_map_this_expr);
21478 SemaRef.Diag(AE->getIdx()->getExprLoc(),
21479 diag::note_omp_invalid_subscript_on_this_ptr_map);
21481 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21482 RelevantExpr = TE;
21485 // Record the component - we don't have any declaration associated.
21486 Components.emplace_back(AE, nullptr, IsNonContiguous);
21488 return RelevantExpr || Visit(E);
21491 bool VisitOMPArraySectionExpr(OMPArraySectionExpr *OASE) {
21492 // After OMP 5.0 Array section in reduction clause will be implicitly
21493 // mapped
21494 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
21495 "Array sections cannot be implicitly mapped.");
21496 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21497 QualType CurType =
21498 OMPArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
21500 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21501 // If the type of a list item is a reference to a type T then the type
21502 // will be considered to be T for all purposes of this clause.
21503 if (CurType->isReferenceType())
21504 CurType = CurType->getPointeeType();
21506 bool IsPointer = CurType->isAnyPointerType();
21508 if (!IsPointer && !CurType->isArrayType()) {
21509 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21510 << 0 << OASE->getSourceRange();
21511 return false;
21514 bool NotWhole =
21515 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
21516 bool NotUnity =
21517 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
21519 if (AllowWholeSizeArraySection) {
21520 // Any array section is currently allowed. Allowing a whole size array
21521 // section implies allowing a unity array section as well.
21523 // If this array section refers to the whole dimension we can still
21524 // accept other array sections before this one, except if the base is a
21525 // pointer. Otherwise, only unitary sections are accepted.
21526 if (NotWhole || IsPointer)
21527 AllowWholeSizeArraySection = false;
21528 } else if (DKind == OMPD_target_update &&
21529 SemaRef.getLangOpts().OpenMP >= 50) {
21530 if (IsPointer && !AllowAnotherPtr)
21531 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
21532 << /*array of unknown bound */ 1;
21533 else
21534 IsNonContiguous = true;
21535 } else if (AllowUnitySizeArraySection && NotUnity) {
21536 // A unity or whole array section is not allowed and that is not
21537 // compatible with the properties of the current array section.
21538 if (NoDiagnose)
21539 return false;
21540 SemaRef.Diag(ELoc,
21541 diag::err_array_section_does_not_specify_contiguous_storage)
21542 << OASE->getSourceRange();
21543 return false;
21546 if (IsPointer)
21547 AllowAnotherPtr = false;
21549 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
21550 Expr::EvalResult ResultR;
21551 Expr::EvalResult ResultL;
21552 if (!OASE->getLength()->isValueDependent() &&
21553 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
21554 !ResultR.Val.getInt().isOne()) {
21555 SemaRef.Diag(OASE->getLength()->getExprLoc(),
21556 diag::err_omp_invalid_map_this_expr);
21557 SemaRef.Diag(OASE->getLength()->getExprLoc(),
21558 diag::note_omp_invalid_length_on_this_ptr_mapping);
21560 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
21561 OASE->getLowerBound()->EvaluateAsInt(ResultL,
21562 SemaRef.getASTContext()) &&
21563 !ResultL.Val.getInt().isZero()) {
21564 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
21565 diag::err_omp_invalid_map_this_expr);
21566 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
21567 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
21569 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21570 RelevantExpr = TE;
21573 // Record the component - we don't have any declaration associated.
21574 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
21575 return RelevantExpr || Visit(E);
21577 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
21578 Expr *Base = E->getBase();
21580 // Record the component - we don't have any declaration associated.
21581 Components.emplace_back(E, nullptr, IsNonContiguous);
21583 return Visit(Base->IgnoreParenImpCasts());
21586 bool VisitUnaryOperator(UnaryOperator *UO) {
21587 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
21588 UO->getOpcode() != UO_Deref) {
21589 emitErrorMsg();
21590 return false;
21592 if (!RelevantExpr) {
21593 // Record the component if haven't found base decl.
21594 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
21596 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
21598 bool VisitBinaryOperator(BinaryOperator *BO) {
21599 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
21600 emitErrorMsg();
21601 return false;
21604 // Pointer arithmetic is the only thing we expect to happen here so after we
21605 // make sure the binary operator is a pointer type, the only thing we need
21606 // to do is to visit the subtree that has the same type as root (so that we
21607 // know the other subtree is just an offset)
21608 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
21609 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
21610 Components.emplace_back(BO, nullptr, false);
21611 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
21612 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
21613 "Either LHS or RHS have base decl inside");
21614 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
21615 return RelevantExpr || Visit(LE);
21616 return RelevantExpr || Visit(RE);
21618 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
21619 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21620 RelevantExpr = CTE;
21621 Components.emplace_back(CTE, nullptr, IsNonContiguous);
21622 return true;
21624 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
21625 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21626 Components.emplace_back(COCE, nullptr, IsNonContiguous);
21627 return true;
21629 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
21630 Expr *Source = E->getSourceExpr();
21631 if (!Source) {
21632 emitErrorMsg();
21633 return false;
21635 return Visit(Source);
21637 bool VisitStmt(Stmt *) {
21638 emitErrorMsg();
21639 return false;
21641 const Expr *getFoundBase() const { return RelevantExpr; }
21642 explicit MapBaseChecker(
21643 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
21644 OMPClauseMappableExprCommon::MappableExprComponentList &Components,
21645 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
21646 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
21647 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
21649 } // namespace
21651 /// Return the expression of the base of the mappable expression or null if it
21652 /// cannot be determined and do all the necessary checks to see if the
21653 /// expression is valid as a standalone mappable expression. In the process,
21654 /// record all the components of the expression.
21655 static const Expr *checkMapClauseExpressionBase(
21656 Sema &SemaRef, Expr *E,
21657 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
21658 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
21659 SourceLocation ELoc = E->getExprLoc();
21660 SourceRange ERange = E->getSourceRange();
21661 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
21662 ERange);
21663 if (Checker.Visit(E->IgnoreParens())) {
21664 // Check if the highest dimension array section has length specified
21665 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
21666 (CKind == OMPC_to || CKind == OMPC_from)) {
21667 auto CI = CurComponents.rbegin();
21668 auto CE = CurComponents.rend();
21669 for (; CI != CE; ++CI) {
21670 const auto *OASE =
21671 dyn_cast<OMPArraySectionExpr>(CI->getAssociatedExpression());
21672 if (!OASE)
21673 continue;
21674 if (OASE && OASE->getLength())
21675 break;
21676 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
21677 << ERange;
21680 return Checker.getFoundBase();
21682 return nullptr;
21685 // Return true if expression E associated with value VD has conflicts with other
21686 // map information.
21687 static bool checkMapConflicts(
21688 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
21689 bool CurrentRegionOnly,
21690 OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents,
21691 OpenMPClauseKind CKind) {
21692 assert(VD && E);
21693 SourceLocation ELoc = E->getExprLoc();
21694 SourceRange ERange = E->getSourceRange();
21696 // In order to easily check the conflicts we need to match each component of
21697 // the expression under test with the components of the expressions that are
21698 // already in the stack.
21700 assert(!CurComponents.empty() && "Map clause expression with no components!");
21701 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
21702 "Map clause expression with unexpected base!");
21704 // Variables to help detecting enclosing problems in data environment nests.
21705 bool IsEnclosedByDataEnvironmentExpr = false;
21706 const Expr *EnclosingExpr = nullptr;
21708 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
21709 VD, CurrentRegionOnly,
21710 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
21711 ERange, CKind, &EnclosingExpr,
21712 CurComponents](OMPClauseMappableExprCommon::MappableExprComponentListRef
21713 StackComponents,
21714 OpenMPClauseKind Kind) {
21715 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
21716 return false;
21717 assert(!StackComponents.empty() &&
21718 "Map clause expression with no components!");
21719 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
21720 "Map clause expression with unexpected base!");
21721 (void)VD;
21723 // The whole expression in the stack.
21724 const Expr *RE = StackComponents.front().getAssociatedExpression();
21726 // Expressions must start from the same base. Here we detect at which
21727 // point both expressions diverge from each other and see if we can
21728 // detect if the memory referred to both expressions is contiguous and
21729 // do not overlap.
21730 auto CI = CurComponents.rbegin();
21731 auto CE = CurComponents.rend();
21732 auto SI = StackComponents.rbegin();
21733 auto SE = StackComponents.rend();
21734 for (; CI != CE && SI != SE; ++CI, ++SI) {
21736 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
21737 // At most one list item can be an array item derived from a given
21738 // variable in map clauses of the same construct.
21739 if (CurrentRegionOnly &&
21740 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
21741 isa<OMPArraySectionExpr>(CI->getAssociatedExpression()) ||
21742 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
21743 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
21744 isa<OMPArraySectionExpr>(SI->getAssociatedExpression()) ||
21745 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
21746 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
21747 diag::err_omp_multiple_array_items_in_map_clause)
21748 << CI->getAssociatedExpression()->getSourceRange();
21749 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
21750 diag::note_used_here)
21751 << SI->getAssociatedExpression()->getSourceRange();
21752 return true;
21755 // Do both expressions have the same kind?
21756 if (CI->getAssociatedExpression()->getStmtClass() !=
21757 SI->getAssociatedExpression()->getStmtClass())
21758 break;
21760 // Are we dealing with different variables/fields?
21761 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
21762 break;
21764 // Check if the extra components of the expressions in the enclosing
21765 // data environment are redundant for the current base declaration.
21766 // If they are, the maps completely overlap, which is legal.
21767 for (; SI != SE; ++SI) {
21768 QualType Type;
21769 if (const auto *ASE =
21770 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
21771 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
21772 } else if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(
21773 SI->getAssociatedExpression())) {
21774 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21775 Type =
21776 OMPArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
21777 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
21778 SI->getAssociatedExpression())) {
21779 Type = OASE->getBase()->getType()->getPointeeType();
21781 if (Type.isNull() || Type->isAnyPointerType() ||
21782 checkArrayExpressionDoesNotReferToWholeSize(
21783 SemaRef, SI->getAssociatedExpression(), Type))
21784 break;
21787 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21788 // List items of map clauses in the same construct must not share
21789 // original storage.
21791 // If the expressions are exactly the same or one is a subset of the
21792 // other, it means they are sharing storage.
21793 if (CI == CE && SI == SE) {
21794 if (CurrentRegionOnly) {
21795 if (CKind == OMPC_map) {
21796 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21797 } else {
21798 assert(CKind == OMPC_to || CKind == OMPC_from);
21799 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21800 << ERange;
21802 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21803 << RE->getSourceRange();
21804 return true;
21806 // If we find the same expression in the enclosing data environment,
21807 // that is legal.
21808 IsEnclosedByDataEnvironmentExpr = true;
21809 return false;
21812 QualType DerivedType =
21813 std::prev(CI)->getAssociatedDeclaration()->getType();
21814 SourceLocation DerivedLoc =
21815 std::prev(CI)->getAssociatedExpression()->getExprLoc();
21817 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21818 // If the type of a list item is a reference to a type T then the type
21819 // will be considered to be T for all purposes of this clause.
21820 DerivedType = DerivedType.getNonReferenceType();
21822 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
21823 // A variable for which the type is pointer and an array section
21824 // derived from that variable must not appear as list items of map
21825 // clauses of the same construct.
21827 // Also, cover one of the cases in:
21828 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21829 // If any part of the original storage of a list item has corresponding
21830 // storage in the device data environment, all of the original storage
21831 // must have corresponding storage in the device data environment.
21833 if (DerivedType->isAnyPointerType()) {
21834 if (CI == CE || SI == SE) {
21835 SemaRef.Diag(
21836 DerivedLoc,
21837 diag::err_omp_pointer_mapped_along_with_derived_section)
21838 << DerivedLoc;
21839 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21840 << RE->getSourceRange();
21841 return true;
21843 if (CI->getAssociatedExpression()->getStmtClass() !=
21844 SI->getAssociatedExpression()->getStmtClass() ||
21845 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
21846 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
21847 assert(CI != CE && SI != SE);
21848 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
21849 << DerivedLoc;
21850 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21851 << RE->getSourceRange();
21852 return true;
21856 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21857 // List items of map clauses in the same construct must not share
21858 // original storage.
21860 // An expression is a subset of the other.
21861 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
21862 if (CKind == OMPC_map) {
21863 if (CI != CE || SI != SE) {
21864 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
21865 // a pointer.
21866 auto Begin =
21867 CI != CE ? CurComponents.begin() : StackComponents.begin();
21868 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
21869 auto It = Begin;
21870 while (It != End && !It->getAssociatedDeclaration())
21871 std::advance(It, 1);
21872 assert(It != End &&
21873 "Expected at least one component with the declaration.");
21874 if (It != Begin && It->getAssociatedDeclaration()
21875 ->getType()
21876 .getCanonicalType()
21877 ->isAnyPointerType()) {
21878 IsEnclosedByDataEnvironmentExpr = false;
21879 EnclosingExpr = nullptr;
21880 return false;
21883 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21884 } else {
21885 assert(CKind == OMPC_to || CKind == OMPC_from);
21886 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21887 << ERange;
21889 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21890 << RE->getSourceRange();
21891 return true;
21894 // The current expression uses the same base as other expression in the
21895 // data environment but does not contain it completely.
21896 if (!CurrentRegionOnly && SI != SE)
21897 EnclosingExpr = RE;
21899 // The current expression is a subset of the expression in the data
21900 // environment.
21901 IsEnclosedByDataEnvironmentExpr |=
21902 (!CurrentRegionOnly && CI != CE && SI == SE);
21904 return false;
21907 if (CurrentRegionOnly)
21908 return FoundError;
21910 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21911 // If any part of the original storage of a list item has corresponding
21912 // storage in the device data environment, all of the original storage must
21913 // have corresponding storage in the device data environment.
21914 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
21915 // If a list item is an element of a structure, and a different element of
21916 // the structure has a corresponding list item in the device data environment
21917 // prior to a task encountering the construct associated with the map clause,
21918 // then the list item must also have a corresponding list item in the device
21919 // data environment prior to the task encountering the construct.
21921 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
21922 SemaRef.Diag(ELoc,
21923 diag::err_omp_original_storage_is_shared_and_does_not_contain)
21924 << ERange;
21925 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
21926 << EnclosingExpr->getSourceRange();
21927 return true;
21930 return FoundError;
21933 // Look up the user-defined mapper given the mapper name and mapped type, and
21934 // build a reference to it.
21935 static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
21936 CXXScopeSpec &MapperIdScopeSpec,
21937 const DeclarationNameInfo &MapperId,
21938 QualType Type,
21939 Expr *UnresolvedMapper) {
21940 if (MapperIdScopeSpec.isInvalid())
21941 return ExprError();
21942 // Get the actual type for the array type.
21943 if (Type->isArrayType()) {
21944 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
21945 Type = Type->getAsArrayTypeUnsafe()->getElementType().getCanonicalType();
21947 // Find all user-defined mappers with the given MapperId.
21948 SmallVector<UnresolvedSet<8>, 4> Lookups;
21949 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
21950 Lookup.suppressDiagnostics();
21951 if (S) {
21952 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec)) {
21953 NamedDecl *D = Lookup.getRepresentativeDecl();
21954 while (S && !S->isDeclScope(D))
21955 S = S->getParent();
21956 if (S)
21957 S = S->getParent();
21958 Lookups.emplace_back();
21959 Lookups.back().append(Lookup.begin(), Lookup.end());
21960 Lookup.clear();
21962 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
21963 // Extract the user-defined mappers with the given MapperId.
21964 Lookups.push_back(UnresolvedSet<8>());
21965 for (NamedDecl *D : ULE->decls()) {
21966 auto *DMD = cast<OMPDeclareMapperDecl>(D);
21967 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
21968 Lookups.back().addDecl(DMD);
21971 // Defer the lookup for dependent types. The results will be passed through
21972 // UnresolvedMapper on instantiation.
21973 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
21974 Type->isInstantiationDependentType() ||
21975 Type->containsUnexpandedParameterPack() ||
21976 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
21977 return !D->isInvalidDecl() &&
21978 (D->getType()->isDependentType() ||
21979 D->getType()->isInstantiationDependentType() ||
21980 D->getType()->containsUnexpandedParameterPack());
21981 })) {
21982 UnresolvedSet<8> URS;
21983 for (const UnresolvedSet<8> &Set : Lookups) {
21984 if (Set.empty())
21985 continue;
21986 URS.append(Set.begin(), Set.end());
21988 return UnresolvedLookupExpr::Create(
21989 SemaRef.Context, /*NamingClass=*/nullptr,
21990 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
21991 /*ADL=*/false, /*Overloaded=*/true, URS.begin(), URS.end());
21993 SourceLocation Loc = MapperId.getLoc();
21994 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21995 // The type must be of struct, union or class type in C and C++
21996 if (!Type->isStructureOrClassType() && !Type->isUnionType() &&
21997 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
21998 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
21999 return ExprError();
22001 // Perform argument dependent lookup.
22002 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
22003 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
22004 // Return the first user-defined mapper with the desired type.
22005 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
22006 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
22007 if (!D->isInvalidDecl() &&
22008 SemaRef.Context.hasSameType(D->getType(), Type))
22009 return D;
22010 return nullptr;
22012 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
22013 // Find the first user-defined mapper with a type derived from the desired
22014 // type.
22015 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
22016 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
22017 if (!D->isInvalidDecl() &&
22018 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
22019 !Type.isMoreQualifiedThan(D->getType()))
22020 return D;
22021 return nullptr;
22022 })) {
22023 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
22024 /*DetectVirtual=*/false);
22025 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
22026 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
22027 VD->getType().getUnqualifiedType()))) {
22028 if (SemaRef.CheckBaseClassAccess(
22029 Loc, VD->getType(), Type, Paths.front(),
22030 /*DiagID=*/0) != Sema::AR_inaccessible) {
22031 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
22036 // Report error if a mapper is specified, but cannot be found.
22037 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
22038 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
22039 << Type << MapperId.getName();
22040 return ExprError();
22042 return ExprEmpty();
22045 namespace {
22046 // Utility struct that gathers all the related lists associated with a mappable
22047 // expression.
22048 struct MappableVarListInfo {
22049 // The list of expressions.
22050 ArrayRef<Expr *> VarList;
22051 // The list of processed expressions.
22052 SmallVector<Expr *, 16> ProcessedVarList;
22053 // The mappble components for each expression.
22054 OMPClauseMappableExprCommon::MappableExprComponentLists VarComponents;
22055 // The base declaration of the variable.
22056 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
22057 // The reference to the user-defined mapper associated with every expression.
22058 SmallVector<Expr *, 16> UDMapperList;
22060 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
22061 // We have a list of components and base declarations for each entry in the
22062 // variable list.
22063 VarComponents.reserve(VarList.size());
22064 VarBaseDeclarations.reserve(VarList.size());
22067 } // namespace
22069 // Check the validity of the provided variable list for the provided clause kind
22070 // \a CKind. In the check process the valid expressions, mappable expression
22071 // components, variables, and user-defined mappers are extracted and used to
22072 // fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
22073 // UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
22074 // and \a MapperId are expected to be valid if the clause kind is 'map'.
22075 static void checkMappableExpressionList(
22076 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
22077 MappableVarListInfo &MVLI, SourceLocation StartLoc,
22078 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
22079 ArrayRef<Expr *> UnresolvedMappers,
22080 OpenMPMapClauseKind MapType = OMPC_MAP_unknown,
22081 ArrayRef<OpenMPMapModifierKind> Modifiers = std::nullopt,
22082 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
22083 // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
22084 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
22085 "Unexpected clause kind with mappable expressions!");
22087 // If the identifier of user-defined mapper is not specified, it is "default".
22088 // We do not change the actual name in this clause to distinguish whether a
22089 // mapper is specified explicitly, i.e., it is not explicitly specified when
22090 // MapperId.getName() is empty.
22091 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
22092 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
22093 MapperId.setName(DeclNames.getIdentifier(
22094 &SemaRef.getASTContext().Idents.get("default")));
22095 MapperId.setLoc(StartLoc);
22098 // Iterators to find the current unresolved mapper expression.
22099 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
22100 bool UpdateUMIt = false;
22101 Expr *UnresolvedMapper = nullptr;
22103 bool HasHoldModifier =
22104 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
22106 // Keep track of the mappable components and base declarations in this clause.
22107 // Each entry in the list is going to have a list of components associated. We
22108 // record each set of the components so that we can build the clause later on.
22109 // In the end we should have the same amount of declarations and component
22110 // lists.
22112 for (Expr *RE : MVLI.VarList) {
22113 assert(RE && "Null expr in omp to/from/map clause");
22114 SourceLocation ELoc = RE->getExprLoc();
22116 // Find the current unresolved mapper expression.
22117 if (UpdateUMIt && UMIt != UMEnd) {
22118 UMIt++;
22119 assert(
22120 UMIt != UMEnd &&
22121 "Expect the size of UnresolvedMappers to match with that of VarList");
22123 UpdateUMIt = true;
22124 if (UMIt != UMEnd)
22125 UnresolvedMapper = *UMIt;
22127 const Expr *VE = RE->IgnoreParenLValueCasts();
22129 if (VE->isValueDependent() || VE->isTypeDependent() ||
22130 VE->isInstantiationDependent() ||
22131 VE->containsUnexpandedParameterPack()) {
22132 // Try to find the associated user-defined mapper.
22133 ExprResult ER = buildUserDefinedMapperRef(
22134 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22135 VE->getType().getCanonicalType(), UnresolvedMapper);
22136 if (ER.isInvalid())
22137 continue;
22138 MVLI.UDMapperList.push_back(ER.get());
22139 // We can only analyze this information once the missing information is
22140 // resolved.
22141 MVLI.ProcessedVarList.push_back(RE);
22142 continue;
22145 Expr *SimpleExpr = RE->IgnoreParenCasts();
22147 if (!RE->isLValue()) {
22148 if (SemaRef.getLangOpts().OpenMP < 50) {
22149 SemaRef.Diag(
22150 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
22151 << RE->getSourceRange();
22152 } else {
22153 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
22154 << getOpenMPClauseName(CKind) << RE->getSourceRange();
22156 continue;
22159 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
22160 ValueDecl *CurDeclaration = nullptr;
22162 // Obtain the array or member expression bases if required. Also, fill the
22163 // components array with all the components identified in the process.
22164 const Expr *BE =
22165 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
22166 DSAS->getCurrentDirective(), NoDiagnose);
22167 if (!BE)
22168 continue;
22170 assert(!CurComponents.empty() &&
22171 "Invalid mappable expression information.");
22173 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
22174 // Add store "this" pointer to class in DSAStackTy for future checking
22175 DSAS->addMappedClassesQualTypes(TE->getType());
22176 // Try to find the associated user-defined mapper.
22177 ExprResult ER = buildUserDefinedMapperRef(
22178 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22179 VE->getType().getCanonicalType(), UnresolvedMapper);
22180 if (ER.isInvalid())
22181 continue;
22182 MVLI.UDMapperList.push_back(ER.get());
22183 // Skip restriction checking for variable or field declarations
22184 MVLI.ProcessedVarList.push_back(RE);
22185 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22186 MVLI.VarComponents.back().append(CurComponents.begin(),
22187 CurComponents.end());
22188 MVLI.VarBaseDeclarations.push_back(nullptr);
22189 continue;
22192 // For the following checks, we rely on the base declaration which is
22193 // expected to be associated with the last component. The declaration is
22194 // expected to be a variable or a field (if 'this' is being mapped).
22195 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
22196 assert(CurDeclaration && "Null decl on map clause.");
22197 assert(
22198 CurDeclaration->isCanonicalDecl() &&
22199 "Expecting components to have associated only canonical declarations.");
22201 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
22202 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
22204 assert((VD || FD) && "Only variables or fields are expected here!");
22205 (void)FD;
22207 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
22208 // threadprivate variables cannot appear in a map clause.
22209 // OpenMP 4.5 [2.10.5, target update Construct]
22210 // threadprivate variables cannot appear in a from clause.
22211 if (VD && DSAS->isThreadPrivate(VD)) {
22212 if (NoDiagnose)
22213 continue;
22214 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
22215 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
22216 << getOpenMPClauseName(CKind);
22217 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
22218 continue;
22221 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
22222 // A list item cannot appear in both a map clause and a data-sharing
22223 // attribute clause on the same construct.
22225 // Check conflicts with other map clause expressions. We check the conflicts
22226 // with the current construct separately from the enclosing data
22227 // environment, because the restrictions are different. We only have to
22228 // check conflicts across regions for the map clauses.
22229 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
22230 /*CurrentRegionOnly=*/true, CurComponents, CKind))
22231 break;
22232 if (CKind == OMPC_map &&
22233 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
22234 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
22235 /*CurrentRegionOnly=*/false, CurComponents, CKind))
22236 break;
22238 // OpenMP 4.5 [2.10.5, target update Construct]
22239 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22240 // If the type of a list item is a reference to a type T then the type will
22241 // be considered to be T for all purposes of this clause.
22242 auto I = llvm::find_if(
22243 CurComponents,
22244 [](const OMPClauseMappableExprCommon::MappableComponent &MC) {
22245 return MC.getAssociatedDeclaration();
22247 assert(I != CurComponents.end() && "Null decl on map clause.");
22248 (void)I;
22249 QualType Type;
22250 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
22251 auto *OASE = dyn_cast<OMPArraySectionExpr>(VE->IgnoreParens());
22252 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
22253 if (ASE) {
22254 Type = ASE->getType().getNonReferenceType();
22255 } else if (OASE) {
22256 QualType BaseType =
22257 OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
22258 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
22259 Type = ATy->getElementType();
22260 else
22261 Type = BaseType->getPointeeType();
22262 Type = Type.getNonReferenceType();
22263 } else if (OAShE) {
22264 Type = OAShE->getBase()->getType()->getPointeeType();
22265 } else {
22266 Type = VE->getType();
22269 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
22270 // A list item in a to or from clause must have a mappable type.
22271 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
22272 // A list item must have a mappable type.
22273 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
22274 DSAS, Type, /*FullCheck=*/true))
22275 continue;
22277 if (CKind == OMPC_map) {
22278 // target enter data
22279 // OpenMP [2.10.2, Restrictions, p. 99]
22280 // A map-type must be specified in all map clauses and must be either
22281 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
22282 // no map type is present.
22283 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
22284 if (DKind == OMPD_target_enter_data &&
22285 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
22286 SemaRef.getLangOpts().OpenMP >= 52)) {
22287 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22288 << (IsMapTypeImplicit ? 1 : 0)
22289 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22290 << getOpenMPDirectiveName(DKind);
22291 continue;
22294 // target exit_data
22295 // OpenMP [2.10.3, Restrictions, p. 102]
22296 // A map-type must be specified in all map clauses and must be either
22297 // from, release, or delete. Starting with OpenMP 5.2 the default map
22298 // type is `from` if no map type is present.
22299 if (DKind == OMPD_target_exit_data &&
22300 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
22301 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
22302 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22303 << (IsMapTypeImplicit ? 1 : 0)
22304 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22305 << getOpenMPDirectiveName(DKind);
22306 continue;
22309 // The 'ompx_hold' modifier is specifically intended to be used on a
22310 // 'target' or 'target data' directive to prevent data from being unmapped
22311 // during the associated statement. It is not permitted on a 'target
22312 // enter data' or 'target exit data' directive, which have no associated
22313 // statement.
22314 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
22315 HasHoldModifier) {
22316 SemaRef.Diag(StartLoc,
22317 diag::err_omp_invalid_map_type_modifier_for_directive)
22318 << getOpenMPSimpleClauseTypeName(OMPC_map,
22319 OMPC_MAP_MODIFIER_ompx_hold)
22320 << getOpenMPDirectiveName(DKind);
22321 continue;
22324 // target, target data
22325 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
22326 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
22327 // A map-type in a map clause must be to, from, tofrom or alloc
22328 if ((DKind == OMPD_target_data ||
22329 isOpenMPTargetExecutionDirective(DKind)) &&
22330 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
22331 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
22332 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22333 << (IsMapTypeImplicit ? 1 : 0)
22334 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22335 << getOpenMPDirectiveName(DKind);
22336 continue;
22339 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
22340 // A list item cannot appear in both a map clause and a data-sharing
22341 // attribute clause on the same construct
22343 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
22344 // A list item cannot appear in both a map clause and a data-sharing
22345 // attribute clause on the same construct unless the construct is a
22346 // combined construct.
22347 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
22348 isOpenMPTargetExecutionDirective(DKind)) ||
22349 DKind == OMPD_target)) {
22350 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
22351 if (isOpenMPPrivate(DVar.CKind)) {
22352 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
22353 << getOpenMPClauseName(DVar.CKind)
22354 << getOpenMPClauseName(OMPC_map)
22355 << getOpenMPDirectiveName(DSAS->getCurrentDirective());
22356 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
22357 continue;
22362 // Try to find the associated user-defined mapper.
22363 ExprResult ER = buildUserDefinedMapperRef(
22364 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22365 Type.getCanonicalType(), UnresolvedMapper);
22366 if (ER.isInvalid())
22367 continue;
22368 MVLI.UDMapperList.push_back(ER.get());
22370 // Save the current expression.
22371 MVLI.ProcessedVarList.push_back(RE);
22373 // Store the components in the stack so that they can be used to check
22374 // against other clauses later on.
22375 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
22376 /*WhereFoundClauseKind=*/OMPC_map);
22378 // Save the components and declaration to create the clause. For purposes of
22379 // the clause creation, any component list that has base 'this' uses
22380 // null as base declaration.
22381 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22382 MVLI.VarComponents.back().append(CurComponents.begin(),
22383 CurComponents.end());
22384 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
22385 : CurDeclaration);
22389 OMPClause *Sema::ActOnOpenMPMapClause(
22390 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
22391 ArrayRef<SourceLocation> MapTypeModifiersLoc,
22392 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22393 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
22394 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22395 const OMPVarListLocTy &Locs, bool NoDiagnose,
22396 ArrayRef<Expr *> UnresolvedMappers) {
22397 OpenMPMapModifierKind Modifiers[] = {
22398 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
22399 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
22400 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown};
22401 SourceLocation ModifiersLoc[NumberOfOMPMapClauseModifiers];
22403 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
22404 BuiltinType::OMPIterator))
22405 Diag(IteratorModifier->getExprLoc(),
22406 diag::err_omp_map_modifier_not_iterator);
22408 // Process map-type-modifiers, flag errors for duplicate modifiers.
22409 unsigned Count = 0;
22410 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
22411 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
22412 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
22413 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
22414 continue;
22416 assert(Count < NumberOfOMPMapClauseModifiers &&
22417 "Modifiers exceed the allowed number of map type modifiers");
22418 Modifiers[Count] = MapTypeModifiers[I];
22419 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
22420 ++Count;
22423 MappableVarListInfo MVLI(VarList);
22424 checkMappableExpressionList(*this, DSAStack, OMPC_map, MVLI, Locs.StartLoc,
22425 MapperIdScopeSpec, MapperId, UnresolvedMappers,
22426 MapType, Modifiers, IsMapTypeImplicit,
22427 NoDiagnose);
22429 // We need to produce a map clause even if we don't have variables so that
22430 // other diagnostics related with non-existing map clauses are accurate.
22431 return OMPMapClause::Create(
22432 Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22433 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
22434 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(Context), MapperId,
22435 MapType, IsMapTypeImplicit, MapLoc);
22438 QualType Sema::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc,
22439 TypeResult ParsedType) {
22440 assert(ParsedType.isUsable());
22442 QualType ReductionType = GetTypeFromParser(ParsedType.get());
22443 if (ReductionType.isNull())
22444 return QualType();
22446 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
22447 // A type name in a declare reduction directive cannot be a function type, an
22448 // array type, a reference type, or a type qualified with const, volatile or
22449 // restrict.
22450 if (ReductionType.hasQualifiers()) {
22451 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
22452 return QualType();
22455 if (ReductionType->isFunctionType()) {
22456 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
22457 return QualType();
22459 if (ReductionType->isReferenceType()) {
22460 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
22461 return QualType();
22463 if (ReductionType->isArrayType()) {
22464 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
22465 return QualType();
22467 return ReductionType;
22470 Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareReductionDirectiveStart(
22471 Scope *S, DeclContext *DC, DeclarationName Name,
22472 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
22473 AccessSpecifier AS, Decl *PrevDeclInScope) {
22474 SmallVector<Decl *, 8> Decls;
22475 Decls.reserve(ReductionTypes.size());
22477 LookupResult Lookup(*this, Name, SourceLocation(), LookupOMPReductionName,
22478 forRedeclarationInCurContext());
22479 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
22480 // A reduction-identifier may not be re-declared in the current scope for the
22481 // same type or for a type that is compatible according to the base language
22482 // rules.
22483 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22484 OMPDeclareReductionDecl *PrevDRD = nullptr;
22485 bool InCompoundScope = true;
22486 if (S != nullptr) {
22487 // Find previous declaration with the same name not referenced in other
22488 // declarations.
22489 FunctionScopeInfo *ParentFn = getEnclosingFunction();
22490 InCompoundScope =
22491 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22492 LookupName(Lookup, S);
22493 FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
22494 /*AllowInlineNamespace=*/false);
22495 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
22496 LookupResult::Filter Filter = Lookup.makeFilter();
22497 while (Filter.hasNext()) {
22498 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
22499 if (InCompoundScope) {
22500 auto I = UsedAsPrevious.find(PrevDecl);
22501 if (I == UsedAsPrevious.end())
22502 UsedAsPrevious[PrevDecl] = false;
22503 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
22504 UsedAsPrevious[D] = true;
22506 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22507 PrevDecl->getLocation();
22509 Filter.done();
22510 if (InCompoundScope) {
22511 for (const auto &PrevData : UsedAsPrevious) {
22512 if (!PrevData.second) {
22513 PrevDRD = PrevData.first;
22514 break;
22518 } else if (PrevDeclInScope != nullptr) {
22519 auto *PrevDRDInScope = PrevDRD =
22520 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
22521 do {
22522 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
22523 PrevDRDInScope->getLocation();
22524 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
22525 } while (PrevDRDInScope != nullptr);
22527 for (const auto &TyData : ReductionTypes) {
22528 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
22529 bool Invalid = false;
22530 if (I != PreviousRedeclTypes.end()) {
22531 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
22532 << TyData.first;
22533 Diag(I->second, diag::note_previous_definition);
22534 Invalid = true;
22536 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
22537 auto *DRD = OMPDeclareReductionDecl::Create(Context, DC, TyData.second,
22538 Name, TyData.first, PrevDRD);
22539 DC->addDecl(DRD);
22540 DRD->setAccess(AS);
22541 Decls.push_back(DRD);
22542 if (Invalid)
22543 DRD->setInvalidDecl();
22544 else
22545 PrevDRD = DRD;
22548 return DeclGroupPtrTy::make(
22549 DeclGroupRef::Create(Context, Decls.begin(), Decls.size()));
22552 void Sema::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) {
22553 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22555 // Enter new function scope.
22556 PushFunctionScope();
22557 setFunctionHasBranchProtectedScope();
22558 getCurFunction()->setHasOMPDeclareReductionCombiner();
22560 if (S != nullptr)
22561 PushDeclContext(S, DRD);
22562 else
22563 CurContext = DRD;
22565 PushExpressionEvaluationContext(
22566 ExpressionEvaluationContext::PotentiallyEvaluated);
22568 QualType ReductionType = DRD->getType();
22569 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
22570 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
22571 // uses semantics of argument handles by value, but it should be passed by
22572 // reference. C lang does not support references, so pass all parameters as
22573 // pointers.
22574 // Create 'T omp_in;' variable.
22575 VarDecl *OmpInParm =
22576 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_in");
22577 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
22578 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
22579 // uses semantics of argument handles by value, but it should be passed by
22580 // reference. C lang does not support references, so pass all parameters as
22581 // pointers.
22582 // Create 'T omp_out;' variable.
22583 VarDecl *OmpOutParm =
22584 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_out");
22585 if (S != nullptr) {
22586 PushOnScopeChains(OmpInParm, S);
22587 PushOnScopeChains(OmpOutParm, S);
22588 } else {
22589 DRD->addDecl(OmpInParm);
22590 DRD->addDecl(OmpOutParm);
22592 Expr *InE =
22593 ::buildDeclRefExpr(*this, OmpInParm, ReductionType, D->getLocation());
22594 Expr *OutE =
22595 ::buildDeclRefExpr(*this, OmpOutParm, ReductionType, D->getLocation());
22596 DRD->setCombinerData(InE, OutE);
22599 void Sema::ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner) {
22600 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22601 DiscardCleanupsInEvaluationContext();
22602 PopExpressionEvaluationContext();
22604 PopDeclContext();
22605 PopFunctionScopeInfo();
22607 if (Combiner != nullptr)
22608 DRD->setCombiner(Combiner);
22609 else
22610 DRD->setInvalidDecl();
22613 VarDecl *Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D) {
22614 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22616 // Enter new function scope.
22617 PushFunctionScope();
22618 setFunctionHasBranchProtectedScope();
22620 if (S != nullptr)
22621 PushDeclContext(S, DRD);
22622 else
22623 CurContext = DRD;
22625 PushExpressionEvaluationContext(
22626 ExpressionEvaluationContext::PotentiallyEvaluated);
22628 QualType ReductionType = DRD->getType();
22629 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
22630 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
22631 // uses semantics of argument handles by value, but it should be passed by
22632 // reference. C lang does not support references, so pass all parameters as
22633 // pointers.
22634 // Create 'T omp_priv;' variable.
22635 VarDecl *OmpPrivParm =
22636 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_priv");
22637 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
22638 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
22639 // uses semantics of argument handles by value, but it should be passed by
22640 // reference. C lang does not support references, so pass all parameters as
22641 // pointers.
22642 // Create 'T omp_orig;' variable.
22643 VarDecl *OmpOrigParm =
22644 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_orig");
22645 if (S != nullptr) {
22646 PushOnScopeChains(OmpPrivParm, S);
22647 PushOnScopeChains(OmpOrigParm, S);
22648 } else {
22649 DRD->addDecl(OmpPrivParm);
22650 DRD->addDecl(OmpOrigParm);
22652 Expr *OrigE =
22653 ::buildDeclRefExpr(*this, OmpOrigParm, ReductionType, D->getLocation());
22654 Expr *PrivE =
22655 ::buildDeclRefExpr(*this, OmpPrivParm, ReductionType, D->getLocation());
22656 DRD->setInitializerData(OrigE, PrivE);
22657 return OmpPrivParm;
22660 void Sema::ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer,
22661 VarDecl *OmpPrivParm) {
22662 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22663 DiscardCleanupsInEvaluationContext();
22664 PopExpressionEvaluationContext();
22666 PopDeclContext();
22667 PopFunctionScopeInfo();
22669 if (Initializer != nullptr) {
22670 DRD->setInitializer(Initializer, OMPDeclareReductionInitKind::Call);
22671 } else if (OmpPrivParm->hasInit()) {
22672 DRD->setInitializer(OmpPrivParm->getInit(),
22673 OmpPrivParm->isDirectInit()
22674 ? OMPDeclareReductionInitKind::Direct
22675 : OMPDeclareReductionInitKind::Copy);
22676 } else {
22677 DRD->setInvalidDecl();
22681 Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareReductionDirectiveEnd(
22682 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
22683 for (Decl *D : DeclReductions.get()) {
22684 if (IsValid) {
22685 if (S)
22686 PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
22687 /*AddToContext=*/false);
22688 } else {
22689 D->setInvalidDecl();
22692 return DeclReductions;
22695 TypeResult Sema::ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D) {
22696 TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
22697 QualType T = TInfo->getType();
22698 if (D.isInvalidType())
22699 return true;
22701 if (getLangOpts().CPlusPlus) {
22702 // Check that there are no default arguments (C++ only).
22703 CheckExtraCXXDefaultArguments(D);
22706 return CreateParsedType(T, TInfo);
22709 QualType Sema::ActOnOpenMPDeclareMapperType(SourceLocation TyLoc,
22710 TypeResult ParsedType) {
22711 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
22713 QualType MapperType = GetTypeFromParser(ParsedType.get());
22714 assert(!MapperType.isNull() && "Expect valid mapper type");
22716 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22717 // The type must be of struct, union or class type in C and C++
22718 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
22719 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
22720 return QualType();
22722 return MapperType;
22725 Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareMapperDirective(
22726 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
22727 SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS,
22728 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
22729 LookupResult Lookup(*this, Name, SourceLocation(), LookupOMPMapperName,
22730 forRedeclarationInCurContext());
22731 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22732 // A mapper-identifier may not be redeclared in the current scope for the
22733 // same type or for a type that is compatible according to the base language
22734 // rules.
22735 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22736 OMPDeclareMapperDecl *PrevDMD = nullptr;
22737 bool InCompoundScope = true;
22738 if (S != nullptr) {
22739 // Find previous declaration with the same name not referenced in other
22740 // declarations.
22741 FunctionScopeInfo *ParentFn = getEnclosingFunction();
22742 InCompoundScope =
22743 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22744 LookupName(Lookup, S);
22745 FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
22746 /*AllowInlineNamespace=*/false);
22747 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
22748 LookupResult::Filter Filter = Lookup.makeFilter();
22749 while (Filter.hasNext()) {
22750 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
22751 if (InCompoundScope) {
22752 auto I = UsedAsPrevious.find(PrevDecl);
22753 if (I == UsedAsPrevious.end())
22754 UsedAsPrevious[PrevDecl] = false;
22755 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
22756 UsedAsPrevious[D] = true;
22758 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22759 PrevDecl->getLocation();
22761 Filter.done();
22762 if (InCompoundScope) {
22763 for (const auto &PrevData : UsedAsPrevious) {
22764 if (!PrevData.second) {
22765 PrevDMD = PrevData.first;
22766 break;
22770 } else if (PrevDeclInScope) {
22771 auto *PrevDMDInScope = PrevDMD =
22772 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
22773 do {
22774 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
22775 PrevDMDInScope->getLocation();
22776 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
22777 } while (PrevDMDInScope != nullptr);
22779 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
22780 bool Invalid = false;
22781 if (I != PreviousRedeclTypes.end()) {
22782 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
22783 << MapperType << Name;
22784 Diag(I->second, diag::note_previous_definition);
22785 Invalid = true;
22787 // Build expressions for implicit maps of data members with 'default'
22788 // mappers.
22789 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses.begin(),
22790 Clauses.end());
22791 if (LangOpts.OpenMP >= 50)
22792 processImplicitMapsWithDefaultMappers(*this, DSAStack, ClausesWithImplicit);
22793 auto *DMD =
22794 OMPDeclareMapperDecl::Create(Context, DC, StartLoc, Name, MapperType, VN,
22795 ClausesWithImplicit, PrevDMD);
22796 if (S)
22797 PushOnScopeChains(DMD, S);
22798 else
22799 DC->addDecl(DMD);
22800 DMD->setAccess(AS);
22801 if (Invalid)
22802 DMD->setInvalidDecl();
22804 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
22805 VD->setDeclContext(DMD);
22806 VD->setLexicalDeclContext(DMD);
22807 DMD->addDecl(VD);
22808 DMD->setMapperVarRef(MapperVarRef);
22810 return DeclGroupPtrTy::make(DeclGroupRef(DMD));
22813 ExprResult
22814 Sema::ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType,
22815 SourceLocation StartLoc,
22816 DeclarationName VN) {
22817 TypeSourceInfo *TInfo =
22818 Context.getTrivialTypeSourceInfo(MapperType, StartLoc);
22819 auto *VD = VarDecl::Create(Context, Context.getTranslationUnitDecl(),
22820 StartLoc, StartLoc, VN.getAsIdentifierInfo(),
22821 MapperType, TInfo, SC_None);
22822 if (S)
22823 PushOnScopeChains(VD, S, /*AddToContext=*/false);
22824 Expr *E = buildDeclRefExpr(*this, VD, MapperType, StartLoc);
22825 DSAStack->addDeclareMapperVarRef(E);
22826 return E;
22829 void Sema::ActOnOpenMPIteratorVarDecl(VarDecl *VD) {
22830 if (DSAStack->getDeclareMapperVarRef())
22831 DSAStack->addIteratorVarDecl(VD);
22834 bool Sema::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const {
22835 assert(LangOpts.OpenMP && "Expected OpenMP mode.");
22836 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
22837 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
22838 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
22839 return true;
22840 if (VD->isUsableInConstantExpressions(Context))
22841 return true;
22842 if (LangOpts.OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
22843 return true;
22844 return false;
22846 return true;
22849 const ValueDecl *Sema::getOpenMPDeclareMapperVarName() const {
22850 assert(LangOpts.OpenMP && "Expected OpenMP mode.");
22851 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
22854 OMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams,
22855 SourceLocation StartLoc,
22856 SourceLocation LParenLoc,
22857 SourceLocation EndLoc) {
22858 Expr *ValExpr = NumTeams;
22859 Stmt *HelperValStmt = nullptr;
22861 // OpenMP [teams Constrcut, Restrictions]
22862 // The num_teams expression must evaluate to a positive integer value.
22863 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_num_teams,
22864 /*StrictlyPositive=*/true))
22865 return nullptr;
22867 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22868 OpenMPDirectiveKind CaptureRegion =
22869 getOpenMPCaptureRegionForClause(DKind, OMPC_num_teams, LangOpts.OpenMP);
22870 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
22871 ValExpr = MakeFullExpr(ValExpr).get();
22872 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22873 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
22874 HelperValStmt = buildPreInits(Context, Captures);
22877 return new (Context) OMPNumTeamsClause(ValExpr, HelperValStmt, CaptureRegion,
22878 StartLoc, LParenLoc, EndLoc);
22881 OMPClause *Sema::ActOnOpenMPThreadLimitClause(Expr *ThreadLimit,
22882 SourceLocation StartLoc,
22883 SourceLocation LParenLoc,
22884 SourceLocation EndLoc) {
22885 Expr *ValExpr = ThreadLimit;
22886 Stmt *HelperValStmt = nullptr;
22888 // OpenMP [teams Constrcut, Restrictions]
22889 // The thread_limit expression must evaluate to a positive integer value.
22890 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_thread_limit,
22891 /*StrictlyPositive=*/true))
22892 return nullptr;
22894 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22895 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
22896 DKind, OMPC_thread_limit, LangOpts.OpenMP);
22897 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
22898 ValExpr = MakeFullExpr(ValExpr).get();
22899 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22900 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
22901 HelperValStmt = buildPreInits(Context, Captures);
22904 return new (Context) OMPThreadLimitClause(
22905 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
22908 OMPClause *Sema::ActOnOpenMPPriorityClause(Expr *Priority,
22909 SourceLocation StartLoc,
22910 SourceLocation LParenLoc,
22911 SourceLocation EndLoc) {
22912 Expr *ValExpr = Priority;
22913 Stmt *HelperValStmt = nullptr;
22914 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22916 // OpenMP [2.9.1, task Constrcut]
22917 // The priority-value is a non-negative numerical scalar expression.
22918 if (!isNonNegativeIntegerValue(
22919 ValExpr, *this, OMPC_priority,
22920 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
22921 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22922 return nullptr;
22924 return new (Context) OMPPriorityClause(ValExpr, HelperValStmt, CaptureRegion,
22925 StartLoc, LParenLoc, EndLoc);
22928 OMPClause *Sema::ActOnOpenMPGrainsizeClause(
22929 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
22930 SourceLocation StartLoc, SourceLocation LParenLoc,
22931 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22932 assert((ModifierLoc.isInvalid() || LangOpts.OpenMP >= 51) &&
22933 "Unexpected grainsize modifier in OpenMP < 51.");
22935 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
22936 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
22937 OMPC_GRAINSIZE_unknown);
22938 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22939 << Values << getOpenMPClauseName(OMPC_grainsize);
22940 return nullptr;
22943 Expr *ValExpr = Grainsize;
22944 Stmt *HelperValStmt = nullptr;
22945 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22947 // OpenMP [2.9.2, taskloop Constrcut]
22948 // The parameter of the grainsize clause must be a positive integer
22949 // expression.
22950 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_grainsize,
22951 /*StrictlyPositive=*/true,
22952 /*BuildCapture=*/true,
22953 DSAStack->getCurrentDirective(),
22954 &CaptureRegion, &HelperValStmt))
22955 return nullptr;
22957 return new (Context)
22958 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22959 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22962 OMPClause *Sema::ActOnOpenMPNumTasksClause(
22963 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
22964 SourceLocation StartLoc, SourceLocation LParenLoc,
22965 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22966 assert((ModifierLoc.isInvalid() || LangOpts.OpenMP >= 51) &&
22967 "Unexpected num_tasks modifier in OpenMP < 51.");
22969 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
22970 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
22971 OMPC_NUMTASKS_unknown);
22972 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22973 << Values << getOpenMPClauseName(OMPC_num_tasks);
22974 return nullptr;
22977 Expr *ValExpr = NumTasks;
22978 Stmt *HelperValStmt = nullptr;
22979 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22981 // OpenMP [2.9.2, taskloop Constrcut]
22982 // The parameter of the num_tasks clause must be a positive integer
22983 // expression.
22984 if (!isNonNegativeIntegerValue(
22985 ValExpr, *this, OMPC_num_tasks,
22986 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
22987 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22988 return nullptr;
22990 return new (Context)
22991 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22992 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22995 OMPClause *Sema::ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc,
22996 SourceLocation LParenLoc,
22997 SourceLocation EndLoc) {
22998 // OpenMP [2.13.2, critical construct, Description]
22999 // ... where hint-expression is an integer constant expression that evaluates
23000 // to a valid lock hint.
23001 ExprResult HintExpr =
23002 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
23003 if (HintExpr.isInvalid())
23004 return nullptr;
23005 return new (Context)
23006 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
23009 /// Tries to find omp_event_handle_t type.
23010 static bool findOMPEventHandleT(Sema &S, SourceLocation Loc,
23011 DSAStackTy *Stack) {
23012 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
23013 if (!OMPEventHandleT.isNull())
23014 return true;
23015 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
23016 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
23017 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
23018 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
23019 return false;
23021 Stack->setOMPEventHandleT(PT.get());
23022 return true;
23025 OMPClause *Sema::ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc,
23026 SourceLocation LParenLoc,
23027 SourceLocation EndLoc) {
23028 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
23029 !Evt->isInstantiationDependent() &&
23030 !Evt->containsUnexpandedParameterPack()) {
23031 if (!findOMPEventHandleT(*this, Evt->getExprLoc(), DSAStack))
23032 return nullptr;
23033 // OpenMP 5.0, 2.10.1 task Construct.
23034 // event-handle is a variable of the omp_event_handle_t type.
23035 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
23036 if (!Ref) {
23037 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
23038 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
23039 return nullptr;
23041 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
23042 if (!VD) {
23043 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
23044 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
23045 return nullptr;
23047 if (!Context.hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
23048 VD->getType()) ||
23049 VD->getType().isConstant(Context)) {
23050 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
23051 << "omp_event_handle_t" << 1 << VD->getType()
23052 << Evt->getSourceRange();
23053 return nullptr;
23055 // OpenMP 5.0, 2.10.1 task Construct
23056 // [detach clause]... The event-handle will be considered as if it was
23057 // specified on a firstprivate clause.
23058 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
23059 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
23060 DVar.RefExpr) {
23061 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
23062 << getOpenMPClauseName(DVar.CKind)
23063 << getOpenMPClauseName(OMPC_firstprivate);
23064 reportOriginalDsa(*this, DSAStack, VD, DVar);
23065 return nullptr;
23069 return new (Context) OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
23072 OMPClause *Sema::ActOnOpenMPDistScheduleClause(
23073 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
23074 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
23075 SourceLocation EndLoc) {
23076 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
23077 std::string Values;
23078 Values += "'";
23079 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
23080 Values += "'";
23081 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23082 << Values << getOpenMPClauseName(OMPC_dist_schedule);
23083 return nullptr;
23085 Expr *ValExpr = ChunkSize;
23086 Stmt *HelperValStmt = nullptr;
23087 if (ChunkSize) {
23088 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
23089 !ChunkSize->isInstantiationDependent() &&
23090 !ChunkSize->containsUnexpandedParameterPack()) {
23091 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
23092 ExprResult Val =
23093 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
23094 if (Val.isInvalid())
23095 return nullptr;
23097 ValExpr = Val.get();
23099 // OpenMP [2.7.1, Restrictions]
23100 // chunk_size must be a loop invariant integer expression with a positive
23101 // value.
23102 if (std::optional<llvm::APSInt> Result =
23103 ValExpr->getIntegerConstantExpr(Context)) {
23104 if (Result->isSigned() && !Result->isStrictlyPositive()) {
23105 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
23106 << "dist_schedule" << ChunkSize->getSourceRange();
23107 return nullptr;
23109 } else if (getOpenMPCaptureRegionForClause(
23110 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
23111 LangOpts.OpenMP) != OMPD_unknown &&
23112 !CurContext->isDependentContext()) {
23113 ValExpr = MakeFullExpr(ValExpr).get();
23114 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23115 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
23116 HelperValStmt = buildPreInits(Context, Captures);
23121 return new (Context)
23122 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
23123 Kind, ValExpr, HelperValStmt);
23126 OMPClause *Sema::ActOnOpenMPDefaultmapClause(
23127 OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind,
23128 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
23129 SourceLocation KindLoc, SourceLocation EndLoc) {
23130 if (getLangOpts().OpenMP < 50) {
23131 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
23132 Kind != OMPC_DEFAULTMAP_scalar) {
23133 std::string Value;
23134 SourceLocation Loc;
23135 Value += "'";
23136 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
23137 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
23138 OMPC_DEFAULTMAP_MODIFIER_tofrom);
23139 Loc = MLoc;
23140 } else {
23141 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
23142 OMPC_DEFAULTMAP_scalar);
23143 Loc = KindLoc;
23145 Value += "'";
23146 Diag(Loc, diag::err_omp_unexpected_clause_value)
23147 << Value << getOpenMPClauseName(OMPC_defaultmap);
23148 return nullptr;
23150 } else {
23151 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
23152 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
23153 (LangOpts.OpenMP >= 50 && KindLoc.isInvalid());
23154 if (!isDefaultmapKind || !isDefaultmapModifier) {
23155 StringRef KindValue = "'scalar', 'aggregate', 'pointer'";
23156 if (LangOpts.OpenMP == 50) {
23157 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
23158 "'firstprivate', 'none', 'default'";
23159 if (!isDefaultmapKind && isDefaultmapModifier) {
23160 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23161 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23162 } else if (isDefaultmapKind && !isDefaultmapModifier) {
23163 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23164 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23165 } else {
23166 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23167 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23168 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23169 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23171 } else {
23172 StringRef ModifierValue =
23173 "'alloc', 'from', 'to', 'tofrom', "
23174 "'firstprivate', 'none', 'default', 'present'";
23175 if (!isDefaultmapKind && isDefaultmapModifier) {
23176 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23177 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23178 } else if (isDefaultmapKind && !isDefaultmapModifier) {
23179 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23180 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23181 } else {
23182 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23183 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23184 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23185 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23188 return nullptr;
23191 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
23192 // At most one defaultmap clause for each category can appear on the
23193 // directive.
23194 if (DSAStack->checkDefaultmapCategory(Kind)) {
23195 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
23196 return nullptr;
23199 if (Kind == OMPC_DEFAULTMAP_unknown) {
23200 // Variable category is not specified - mark all categories.
23201 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
23202 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
23203 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
23204 } else {
23205 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
23208 return new (Context)
23209 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
23212 bool Sema::ActOnStartOpenMPDeclareTargetContext(
23213 DeclareTargetContextInfo &DTCI) {
23214 DeclContext *CurLexicalContext = getCurLexicalContext();
23215 if (!CurLexicalContext->isFileContext() &&
23216 !CurLexicalContext->isExternCContext() &&
23217 !CurLexicalContext->isExternCXXContext() &&
23218 !isa<CXXRecordDecl>(CurLexicalContext) &&
23219 !isa<ClassTemplateDecl>(CurLexicalContext) &&
23220 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
23221 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
23222 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
23223 return false;
23226 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
23227 if (getLangOpts().HIP)
23228 Diag(DTCI.Loc, diag::warn_hip_omp_target_directives);
23230 DeclareTargetNesting.push_back(DTCI);
23231 return true;
23234 const Sema::DeclareTargetContextInfo
23235 Sema::ActOnOpenMPEndDeclareTargetDirective() {
23236 assert(!DeclareTargetNesting.empty() &&
23237 "check isInOpenMPDeclareTargetContext() first!");
23238 return DeclareTargetNesting.pop_back_val();
23241 void Sema::ActOnFinishedOpenMPDeclareTargetContext(
23242 DeclareTargetContextInfo &DTCI) {
23243 for (auto &It : DTCI.ExplicitlyMapped)
23244 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
23247 void Sema::DiagnoseUnterminatedOpenMPDeclareTarget() {
23248 if (DeclareTargetNesting.empty())
23249 return;
23250 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
23251 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
23252 << getOpenMPDirectiveName(DTCI.Kind);
23255 NamedDecl *Sema::lookupOpenMPDeclareTargetName(Scope *CurScope,
23256 CXXScopeSpec &ScopeSpec,
23257 const DeclarationNameInfo &Id) {
23258 LookupResult Lookup(*this, Id, LookupOrdinaryName);
23259 LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
23261 if (Lookup.isAmbiguous())
23262 return nullptr;
23263 Lookup.suppressDiagnostics();
23265 if (!Lookup.isSingleResult()) {
23266 VarOrFuncDeclFilterCCC CCC(*this);
23267 if (TypoCorrection Corrected =
23268 CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr, CCC,
23269 CTK_ErrorRecovery)) {
23270 diagnoseTypo(Corrected, PDiag(diag::err_undeclared_var_use_suggest)
23271 << Id.getName());
23272 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
23273 return nullptr;
23276 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
23277 return nullptr;
23280 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
23281 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
23282 !isa<FunctionTemplateDecl>(ND)) {
23283 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
23284 return nullptr;
23286 return ND;
23289 void Sema::ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc,
23290 OMPDeclareTargetDeclAttr::MapTypeTy MT,
23291 DeclareTargetContextInfo &DTCI) {
23292 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
23293 isa<FunctionTemplateDecl>(ND)) &&
23294 "Expected variable, function or function template.");
23296 // Diagnose marking after use as it may lead to incorrect diagnosis and
23297 // codegen.
23298 if (LangOpts.OpenMP >= 50 &&
23299 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
23300 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
23302 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
23303 if (getLangOpts().HIP)
23304 Diag(Loc, diag::warn_hip_omp_target_directives);
23306 // Explicit declare target lists have precedence.
23307 const unsigned Level = -1;
23309 auto *VD = cast<ValueDecl>(ND);
23310 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23311 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23312 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
23313 (*ActiveAttr)->getLevel() == Level) {
23314 Diag(Loc, diag::err_omp_device_type_mismatch)
23315 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
23316 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
23317 (*ActiveAttr)->getDevType());
23318 return;
23320 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
23321 (*ActiveAttr)->getLevel() == Level) {
23322 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
23323 return;
23326 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
23327 return;
23329 Expr *IndirectE = nullptr;
23330 bool IsIndirect = false;
23331 if (DTCI.Indirect) {
23332 IndirectE = *DTCI.Indirect;
23333 if (!IndirectE)
23334 IsIndirect = true;
23336 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23337 Context, MT, DTCI.DT, IndirectE, IsIndirect, Level,
23338 SourceRange(Loc, Loc));
23339 ND->addAttr(A);
23340 if (ASTMutationListener *ML = Context.getASTMutationListener())
23341 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
23342 checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Loc);
23343 if (auto *VD = dyn_cast<VarDecl>(ND);
23344 LangOpts.OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
23345 VD->hasGlobalStorage())
23346 ActOnOpenMPDeclareTargetInitializer(ND);
23349 static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
23350 Sema &SemaRef, Decl *D) {
23351 if (!D || !isa<VarDecl>(D))
23352 return;
23353 auto *VD = cast<VarDecl>(D);
23354 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
23355 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
23356 if (SemaRef.LangOpts.OpenMP >= 50 &&
23357 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
23358 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
23359 VD->hasGlobalStorage()) {
23360 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
23361 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
23362 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
23363 // If a lambda declaration and definition appears between a
23364 // declare target directive and the matching end declare target
23365 // directive, all variables that are captured by the lambda
23366 // expression must also appear in a to clause.
23367 SemaRef.Diag(VD->getLocation(),
23368 diag::err_omp_lambda_capture_in_declare_target_not_to);
23369 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
23370 << VD << 0 << SR;
23371 return;
23374 if (MapTy)
23375 return;
23376 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
23377 SemaRef.Diag(SL, diag::note_used_here) << SR;
23380 static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR,
23381 Sema &SemaRef, DSAStackTy *Stack,
23382 ValueDecl *VD) {
23383 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
23384 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
23385 /*FullCheck=*/false);
23388 void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
23389 SourceLocation IdLoc) {
23390 if (!D || D->isInvalidDecl())
23391 return;
23392 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
23393 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
23394 if (auto *VD = dyn_cast<VarDecl>(D)) {
23395 // Only global variables can be marked as declare target.
23396 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
23397 !VD->isStaticDataMember())
23398 return;
23399 // 2.10.6: threadprivate variable cannot appear in a declare target
23400 // directive.
23401 if (DSAStack->isThreadPrivate(VD)) {
23402 Diag(SL, diag::err_omp_threadprivate_in_target);
23403 reportOriginalDsa(*this, DSAStack, VD, DSAStack->getTopDSA(VD, false));
23404 return;
23407 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
23408 D = FTD->getTemplatedDecl();
23409 if (auto *FD = dyn_cast<FunctionDecl>(D)) {
23410 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
23411 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
23412 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
23413 Diag(IdLoc, diag::err_omp_function_in_link_clause);
23414 Diag(FD->getLocation(), diag::note_defined_here) << FD;
23415 return;
23418 if (auto *VD = dyn_cast<ValueDecl>(D)) {
23419 // Problem if any with var declared with incomplete type will be reported
23420 // as normal, so no need to check it here.
23421 if ((E || !VD->getType()->isIncompleteType()) &&
23422 !checkValueDeclInTarget(SL, SR, *this, DSAStack, VD))
23423 return;
23424 if (!E && isInOpenMPDeclareTargetContext()) {
23425 // Checking declaration inside declare target region.
23426 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
23427 isa<FunctionTemplateDecl>(D)) {
23428 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23429 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23430 unsigned Level = DeclareTargetNesting.size();
23431 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
23432 return;
23433 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
23434 Expr *IndirectE = nullptr;
23435 bool IsIndirect = false;
23436 if (DTCI.Indirect) {
23437 IndirectE = *DTCI.Indirect;
23438 if (!IndirectE)
23439 IsIndirect = true;
23441 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23442 Context,
23443 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
23444 : OMPDeclareTargetDeclAttr::MT_To,
23445 DTCI.DT, IndirectE, IsIndirect, Level,
23446 SourceRange(DTCI.Loc, DTCI.Loc));
23447 D->addAttr(A);
23448 if (ASTMutationListener *ML = Context.getASTMutationListener())
23449 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
23451 return;
23454 if (!E)
23455 return;
23456 checkDeclInTargetContext(E->getExprLoc(), E->getSourceRange(), *this, D);
23459 /// This class visits every VarDecl that the initializer references and adds
23460 /// OMPDeclareTargetDeclAttr to each of them.
23461 class GlobalDeclRefChecker final
23462 : public StmtVisitor<GlobalDeclRefChecker> {
23463 SmallVector<VarDecl *> DeclVector;
23464 Attr *A;
23466 public:
23467 /// A StmtVisitor class function that visits all DeclRefExpr and adds
23468 /// OMPDeclareTargetDeclAttr to them.
23469 void VisitDeclRefExpr(DeclRefExpr *Node) {
23470 if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) {
23471 VD->addAttr(A);
23472 DeclVector.push_back(VD);
23475 /// A function that iterates across each of the Expr's children.
23476 void VisitExpr(Expr *Ex) {
23477 for (auto *Child : Ex->children()) {
23478 Visit(Child);
23481 /// A function that keeps a record of all the Decls that are variables, has
23482 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
23483 /// each Decl one at a time and use the inherited 'visit' functions to look
23484 /// for DeclRefExpr.
23485 void declareTargetInitializer(Decl *TD) {
23486 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
23487 DeclVector.push_back(cast<VarDecl>(TD));
23488 while (!DeclVector.empty()) {
23489 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
23490 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
23491 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
23492 if (Expr *Ex = TargetVarDecl->getInit())
23493 Visit(Ex);
23499 /// Adding OMPDeclareTargetDeclAttr to variables with static storage
23500 /// duration that are referenced in the initializer expression list of
23501 /// variables with static storage duration in declare target directive.
23502 void Sema::ActOnOpenMPDeclareTargetInitializer(Decl *TargetDecl) {
23503 GlobalDeclRefChecker Checker;
23504 if (isa<VarDecl>(TargetDecl))
23505 Checker.declareTargetInitializer(TargetDecl);
23508 OMPClause *Sema::ActOnOpenMPToClause(
23509 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23510 ArrayRef<SourceLocation> MotionModifiersLoc,
23511 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23512 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23513 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23514 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
23515 OMPC_MOTION_MODIFIER_unknown};
23516 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
23518 // Process motion-modifiers, flag errors for duplicate modifiers.
23519 unsigned Count = 0;
23520 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23521 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23522 llvm::is_contained(Modifiers, MotionModifiers[I])) {
23523 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23524 continue;
23526 assert(Count < NumberOfOMPMotionModifiers &&
23527 "Modifiers exceed the allowed number of motion modifiers");
23528 Modifiers[Count] = MotionModifiers[I];
23529 ModifiersLoc[Count] = MotionModifiersLoc[I];
23530 ++Count;
23533 MappableVarListInfo MVLI(VarList);
23534 checkMappableExpressionList(*this, DSAStack, OMPC_to, MVLI, Locs.StartLoc,
23535 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23536 if (MVLI.ProcessedVarList.empty())
23537 return nullptr;
23539 return OMPToClause::Create(
23540 Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23541 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23542 MapperIdScopeSpec.getWithLocInContext(Context), MapperId);
23545 OMPClause *Sema::ActOnOpenMPFromClause(
23546 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23547 ArrayRef<SourceLocation> MotionModifiersLoc,
23548 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23549 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23550 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23551 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
23552 OMPC_MOTION_MODIFIER_unknown};
23553 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
23555 // Process motion-modifiers, flag errors for duplicate modifiers.
23556 unsigned Count = 0;
23557 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23558 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23559 llvm::is_contained(Modifiers, MotionModifiers[I])) {
23560 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23561 continue;
23563 assert(Count < NumberOfOMPMotionModifiers &&
23564 "Modifiers exceed the allowed number of motion modifiers");
23565 Modifiers[Count] = MotionModifiers[I];
23566 ModifiersLoc[Count] = MotionModifiersLoc[I];
23567 ++Count;
23570 MappableVarListInfo MVLI(VarList);
23571 checkMappableExpressionList(*this, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
23572 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23573 if (MVLI.ProcessedVarList.empty())
23574 return nullptr;
23576 return OMPFromClause::Create(
23577 Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23578 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23579 MapperIdScopeSpec.getWithLocInContext(Context), MapperId);
23582 OMPClause *Sema::ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList,
23583 const OMPVarListLocTy &Locs) {
23584 MappableVarListInfo MVLI(VarList);
23585 SmallVector<Expr *, 8> PrivateCopies;
23586 SmallVector<Expr *, 8> Inits;
23588 for (Expr *RefExpr : VarList) {
23589 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
23590 SourceLocation ELoc;
23591 SourceRange ERange;
23592 Expr *SimpleRefExpr = RefExpr;
23593 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
23594 if (Res.second) {
23595 // It will be analyzed later.
23596 MVLI.ProcessedVarList.push_back(RefExpr);
23597 PrivateCopies.push_back(nullptr);
23598 Inits.push_back(nullptr);
23600 ValueDecl *D = Res.first;
23601 if (!D)
23602 continue;
23604 QualType Type = D->getType();
23605 Type = Type.getNonReferenceType().getUnqualifiedType();
23607 auto *VD = dyn_cast<VarDecl>(D);
23609 // Item should be a pointer or reference to pointer.
23610 if (!Type->isPointerType()) {
23611 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
23612 << 0 << RefExpr->getSourceRange();
23613 continue;
23616 // Build the private variable and the expression that refers to it.
23617 auto VDPrivate =
23618 buildVarDecl(*this, ELoc, Type, D->getName(),
23619 D->hasAttrs() ? &D->getAttrs() : nullptr,
23620 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
23621 if (VDPrivate->isInvalidDecl())
23622 continue;
23624 CurContext->addDecl(VDPrivate);
23625 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
23626 *this, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
23628 // Add temporary variable to initialize the private copy of the pointer.
23629 VarDecl *VDInit =
23630 buildVarDecl(*this, RefExpr->getExprLoc(), Type, ".devptr.temp");
23631 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
23632 *this, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
23633 AddInitializerToDecl(VDPrivate,
23634 DefaultLvalueConversion(VDInitRefExpr).get(),
23635 /*DirectInit=*/false);
23637 // If required, build a capture to implement the privatization initialized
23638 // with the current list item value.
23639 DeclRefExpr *Ref = nullptr;
23640 if (!VD)
23641 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
23642 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
23643 PrivateCopies.push_back(VDPrivateRefExpr);
23644 Inits.push_back(VDInitRefExpr);
23646 // We need to add a data sharing attribute for this variable to make sure it
23647 // is correctly captured. A variable that shows up in a use_device_ptr has
23648 // similar properties of a first private variable.
23649 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23651 // Create a mappable component for the list item. List items in this clause
23652 // only need a component.
23653 MVLI.VarBaseDeclarations.push_back(D);
23654 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23655 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
23656 /*IsNonContiguous=*/false);
23659 if (MVLI.ProcessedVarList.empty())
23660 return nullptr;
23662 return OMPUseDevicePtrClause::Create(
23663 Context, Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
23664 MVLI.VarBaseDeclarations, MVLI.VarComponents);
23667 OMPClause *Sema::ActOnOpenMPUseDeviceAddrClause(ArrayRef<Expr *> VarList,
23668 const OMPVarListLocTy &Locs) {
23669 MappableVarListInfo MVLI(VarList);
23671 for (Expr *RefExpr : VarList) {
23672 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
23673 SourceLocation ELoc;
23674 SourceRange ERange;
23675 Expr *SimpleRefExpr = RefExpr;
23676 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
23677 /*AllowArraySection=*/true);
23678 if (Res.second) {
23679 // It will be analyzed later.
23680 MVLI.ProcessedVarList.push_back(RefExpr);
23682 ValueDecl *D = Res.first;
23683 if (!D)
23684 continue;
23685 auto *VD = dyn_cast<VarDecl>(D);
23687 // If required, build a capture to implement the privatization initialized
23688 // with the current list item value.
23689 DeclRefExpr *Ref = nullptr;
23690 if (!VD)
23691 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
23692 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
23694 // We need to add a data sharing attribute for this variable to make sure it
23695 // is correctly captured. A variable that shows up in a use_device_addr has
23696 // similar properties of a first private variable.
23697 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23699 // Create a mappable component for the list item. List items in this clause
23700 // only need a component.
23701 MVLI.VarBaseDeclarations.push_back(D);
23702 MVLI.VarComponents.emplace_back();
23703 Expr *Component = SimpleRefExpr;
23704 if (VD && (isa<OMPArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23705 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23706 Component = DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
23707 MVLI.VarComponents.back().emplace_back(Component, D,
23708 /*IsNonContiguous=*/false);
23711 if (MVLI.ProcessedVarList.empty())
23712 return nullptr;
23714 return OMPUseDeviceAddrClause::Create(Context, Locs, MVLI.ProcessedVarList,
23715 MVLI.VarBaseDeclarations,
23716 MVLI.VarComponents);
23719 OMPClause *Sema::ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList,
23720 const OMPVarListLocTy &Locs) {
23721 MappableVarListInfo MVLI(VarList);
23722 for (Expr *RefExpr : VarList) {
23723 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
23724 SourceLocation ELoc;
23725 SourceRange ERange;
23726 Expr *SimpleRefExpr = RefExpr;
23727 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
23728 if (Res.second) {
23729 // It will be analyzed later.
23730 MVLI.ProcessedVarList.push_back(RefExpr);
23732 ValueDecl *D = Res.first;
23733 if (!D)
23734 continue;
23736 QualType Type = D->getType();
23737 // item should be a pointer or array or reference to pointer or array
23738 if (!Type.getNonReferenceType()->isPointerType() &&
23739 !Type.getNonReferenceType()->isArrayType()) {
23740 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
23741 << 0 << RefExpr->getSourceRange();
23742 continue;
23745 // Check if the declaration in the clause does not show up in any data
23746 // sharing attribute.
23747 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23748 if (isOpenMPPrivate(DVar.CKind)) {
23749 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23750 << getOpenMPClauseName(DVar.CKind)
23751 << getOpenMPClauseName(OMPC_is_device_ptr)
23752 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
23753 reportOriginalDsa(*this, DSAStack, D, DVar);
23754 continue;
23757 const Expr *ConflictExpr;
23758 if (DSAStack->checkMappableExprComponentListsForDecl(
23759 D, /*CurrentRegionOnly=*/true,
23760 [&ConflictExpr](
23761 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
23762 OpenMPClauseKind) -> bool {
23763 ConflictExpr = R.front().getAssociatedExpression();
23764 return true;
23765 })) {
23766 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23767 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23768 << ConflictExpr->getSourceRange();
23769 continue;
23772 // Store the components in the stack so that they can be used to check
23773 // against other clauses later on.
23774 OMPClauseMappableExprCommon::MappableComponent MC(
23775 SimpleRefExpr, D, /*IsNonContiguous=*/false);
23776 DSAStack->addMappableExpressionComponents(
23777 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
23779 // Record the expression we've just processed.
23780 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
23782 // Create a mappable component for the list item. List items in this clause
23783 // only need a component. We use a null declaration to signal fields in
23784 // 'this'.
23785 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23786 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23787 "Unexpected device pointer expression!");
23788 MVLI.VarBaseDeclarations.push_back(
23789 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23790 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23791 MVLI.VarComponents.back().push_back(MC);
23794 if (MVLI.ProcessedVarList.empty())
23795 return nullptr;
23797 return OMPIsDevicePtrClause::Create(Context, Locs, MVLI.ProcessedVarList,
23798 MVLI.VarBaseDeclarations,
23799 MVLI.VarComponents);
23802 OMPClause *Sema::ActOnOpenMPHasDeviceAddrClause(ArrayRef<Expr *> VarList,
23803 const OMPVarListLocTy &Locs) {
23804 MappableVarListInfo MVLI(VarList);
23805 for (Expr *RefExpr : VarList) {
23806 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
23807 SourceLocation ELoc;
23808 SourceRange ERange;
23809 Expr *SimpleRefExpr = RefExpr;
23810 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
23811 /*AllowArraySection=*/true);
23812 if (Res.second) {
23813 // It will be analyzed later.
23814 MVLI.ProcessedVarList.push_back(RefExpr);
23816 ValueDecl *D = Res.first;
23817 if (!D)
23818 continue;
23820 // Check if the declaration in the clause does not show up in any data
23821 // sharing attribute.
23822 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23823 if (isOpenMPPrivate(DVar.CKind)) {
23824 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23825 << getOpenMPClauseName(DVar.CKind)
23826 << getOpenMPClauseName(OMPC_has_device_addr)
23827 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
23828 reportOriginalDsa(*this, DSAStack, D, DVar);
23829 continue;
23832 const Expr *ConflictExpr;
23833 if (DSAStack->checkMappableExprComponentListsForDecl(
23834 D, /*CurrentRegionOnly=*/true,
23835 [&ConflictExpr](
23836 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
23837 OpenMPClauseKind) -> bool {
23838 ConflictExpr = R.front().getAssociatedExpression();
23839 return true;
23840 })) {
23841 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23842 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23843 << ConflictExpr->getSourceRange();
23844 continue;
23847 // Store the components in the stack so that they can be used to check
23848 // against other clauses later on.
23849 Expr *Component = SimpleRefExpr;
23850 auto *VD = dyn_cast<VarDecl>(D);
23851 if (VD && (isa<OMPArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23852 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23853 Component = DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
23854 OMPClauseMappableExprCommon::MappableComponent MC(
23855 Component, D, /*IsNonContiguous=*/false);
23856 DSAStack->addMappableExpressionComponents(
23857 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
23859 // Record the expression we've just processed.
23860 if (!VD && !CurContext->isDependentContext()) {
23861 DeclRefExpr *Ref =
23862 buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
23863 assert(Ref && "has_device_addr capture failed");
23864 MVLI.ProcessedVarList.push_back(Ref);
23865 } else
23866 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
23868 // Create a mappable component for the list item. List items in this clause
23869 // only need a component. We use a null declaration to signal fields in
23870 // 'this'.
23871 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23872 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23873 "Unexpected device pointer expression!");
23874 MVLI.VarBaseDeclarations.push_back(
23875 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23876 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23877 MVLI.VarComponents.back().push_back(MC);
23880 if (MVLI.ProcessedVarList.empty())
23881 return nullptr;
23883 return OMPHasDeviceAddrClause::Create(Context, Locs, MVLI.ProcessedVarList,
23884 MVLI.VarBaseDeclarations,
23885 MVLI.VarComponents);
23888 OMPClause *Sema::ActOnOpenMPAllocateClause(
23889 Expr *Allocator, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
23890 SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
23891 if (Allocator) {
23892 // OpenMP [2.11.4 allocate Clause, Description]
23893 // allocator is an expression of omp_allocator_handle_t type.
23894 if (!findOMPAllocatorHandleT(*this, Allocator->getExprLoc(), DSAStack))
23895 return nullptr;
23897 ExprResult AllocatorRes = DefaultLvalueConversion(Allocator);
23898 if (AllocatorRes.isInvalid())
23899 return nullptr;
23900 AllocatorRes = PerformImplicitConversion(AllocatorRes.get(),
23901 DSAStack->getOMPAllocatorHandleT(),
23902 Sema::AA_Initializing,
23903 /*AllowExplicit=*/true);
23904 if (AllocatorRes.isInvalid())
23905 return nullptr;
23906 Allocator = AllocatorRes.get();
23907 } else {
23908 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
23909 // allocate clauses that appear on a target construct or on constructs in a
23910 // target region must specify an allocator expression unless a requires
23911 // directive with the dynamic_allocators clause is present in the same
23912 // compilation unit.
23913 if (LangOpts.OpenMPIsTargetDevice &&
23914 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
23915 targetDiag(StartLoc, diag::err_expected_allocator_expression);
23917 // Analyze and build list of variables.
23918 SmallVector<Expr *, 8> Vars;
23919 for (Expr *RefExpr : VarList) {
23920 assert(RefExpr && "NULL expr in OpenMP private clause.");
23921 SourceLocation ELoc;
23922 SourceRange ERange;
23923 Expr *SimpleRefExpr = RefExpr;
23924 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
23925 if (Res.second) {
23926 // It will be analyzed later.
23927 Vars.push_back(RefExpr);
23929 ValueDecl *D = Res.first;
23930 if (!D)
23931 continue;
23933 auto *VD = dyn_cast<VarDecl>(D);
23934 DeclRefExpr *Ref = nullptr;
23935 if (!VD && !CurContext->isDependentContext())
23936 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
23937 Vars.push_back((VD || CurContext->isDependentContext())
23938 ? RefExpr->IgnoreParens()
23939 : Ref);
23942 if (Vars.empty())
23943 return nullptr;
23945 if (Allocator)
23946 DSAStack->addInnerAllocatorExpr(Allocator);
23947 return OMPAllocateClause::Create(Context, StartLoc, LParenLoc, Allocator,
23948 ColonLoc, EndLoc, Vars);
23951 OMPClause *Sema::ActOnOpenMPNontemporalClause(ArrayRef<Expr *> VarList,
23952 SourceLocation StartLoc,
23953 SourceLocation LParenLoc,
23954 SourceLocation EndLoc) {
23955 SmallVector<Expr *, 8> Vars;
23956 for (Expr *RefExpr : VarList) {
23957 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23958 SourceLocation ELoc;
23959 SourceRange ERange;
23960 Expr *SimpleRefExpr = RefExpr;
23961 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
23962 if (Res.second)
23963 // It will be analyzed later.
23964 Vars.push_back(RefExpr);
23965 ValueDecl *D = Res.first;
23966 if (!D)
23967 continue;
23969 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
23970 // A list-item cannot appear in more than one nontemporal clause.
23971 if (const Expr *PrevRef =
23972 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
23973 Diag(ELoc, diag::err_omp_used_in_clause_twice)
23974 << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange;
23975 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
23976 << getOpenMPClauseName(OMPC_nontemporal);
23977 continue;
23980 Vars.push_back(RefExpr);
23983 if (Vars.empty())
23984 return nullptr;
23986 return OMPNontemporalClause::Create(Context, StartLoc, LParenLoc, EndLoc,
23987 Vars);
23990 StmtResult Sema::ActOnOpenMPScopeDirective(ArrayRef<OMPClause *> Clauses,
23991 Stmt *AStmt, SourceLocation StartLoc,
23992 SourceLocation EndLoc) {
23993 if (!AStmt)
23994 return StmtError();
23996 setFunctionHasBranchProtectedScope();
23998 return OMPScopeDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
24001 OMPClause *Sema::ActOnOpenMPInclusiveClause(ArrayRef<Expr *> VarList,
24002 SourceLocation StartLoc,
24003 SourceLocation LParenLoc,
24004 SourceLocation EndLoc) {
24005 SmallVector<Expr *, 8> Vars;
24006 for (Expr *RefExpr : VarList) {
24007 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
24008 SourceLocation ELoc;
24009 SourceRange ERange;
24010 Expr *SimpleRefExpr = RefExpr;
24011 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
24012 /*AllowArraySection=*/true);
24013 if (Res.second)
24014 // It will be analyzed later.
24015 Vars.push_back(RefExpr);
24016 ValueDecl *D = Res.first;
24017 if (!D)
24018 continue;
24020 const DSAStackTy::DSAVarData DVar =
24021 DSAStack->getTopDSA(D, /*FromParent=*/true);
24022 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
24023 // A list item that appears in the inclusive or exclusive clause must appear
24024 // in a reduction clause with the inscan modifier on the enclosing
24025 // worksharing-loop, worksharing-loop SIMD, or simd construct.
24026 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
24027 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
24028 << RefExpr->getSourceRange();
24030 if (DSAStack->getParentDirective() != OMPD_unknown)
24031 DSAStack->markDeclAsUsedInScanDirective(D);
24032 Vars.push_back(RefExpr);
24035 if (Vars.empty())
24036 return nullptr;
24038 return OMPInclusiveClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
24041 OMPClause *Sema::ActOnOpenMPExclusiveClause(ArrayRef<Expr *> VarList,
24042 SourceLocation StartLoc,
24043 SourceLocation LParenLoc,
24044 SourceLocation EndLoc) {
24045 SmallVector<Expr *, 8> Vars;
24046 for (Expr *RefExpr : VarList) {
24047 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
24048 SourceLocation ELoc;
24049 SourceRange ERange;
24050 Expr *SimpleRefExpr = RefExpr;
24051 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
24052 /*AllowArraySection=*/true);
24053 if (Res.second)
24054 // It will be analyzed later.
24055 Vars.push_back(RefExpr);
24056 ValueDecl *D = Res.first;
24057 if (!D)
24058 continue;
24060 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
24061 DSAStackTy::DSAVarData DVar;
24062 if (ParentDirective != OMPD_unknown)
24063 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
24064 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
24065 // A list item that appears in the inclusive or exclusive clause must appear
24066 // in a reduction clause with the inscan modifier on the enclosing
24067 // worksharing-loop, worksharing-loop SIMD, or simd construct.
24068 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
24069 DVar.Modifier != OMPC_REDUCTION_inscan) {
24070 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
24071 << RefExpr->getSourceRange();
24072 } else {
24073 DSAStack->markDeclAsUsedInScanDirective(D);
24075 Vars.push_back(RefExpr);
24078 if (Vars.empty())
24079 return nullptr;
24081 return OMPExclusiveClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
24084 /// Tries to find omp_alloctrait_t type.
24085 static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
24086 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
24087 if (!OMPAlloctraitT.isNull())
24088 return true;
24089 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
24090 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
24091 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
24092 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
24093 return false;
24095 Stack->setOMPAlloctraitT(PT.get());
24096 return true;
24099 OMPClause *Sema::ActOnOpenMPUsesAllocatorClause(
24100 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
24101 ArrayRef<UsesAllocatorsData> Data) {
24102 // OpenMP [2.12.5, target Construct]
24103 // allocator is an identifier of omp_allocator_handle_t type.
24104 if (!findOMPAllocatorHandleT(*this, StartLoc, DSAStack))
24105 return nullptr;
24106 // OpenMP [2.12.5, target Construct]
24107 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
24108 if (llvm::any_of(
24109 Data,
24110 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
24111 !findOMPAlloctraitT(*this, StartLoc, DSAStack))
24112 return nullptr;
24113 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
24114 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
24115 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
24116 StringRef Allocator =
24117 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
24118 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
24119 PredefinedAllocators.insert(LookupSingleName(
24120 TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
24123 SmallVector<OMPUsesAllocatorsClause::Data, 4> NewData;
24124 for (const UsesAllocatorsData &D : Data) {
24125 Expr *AllocatorExpr = nullptr;
24126 // Check allocator expression.
24127 if (D.Allocator->isTypeDependent()) {
24128 AllocatorExpr = D.Allocator;
24129 } else {
24130 // Traits were specified - need to assign new allocator to the specified
24131 // allocator, so it must be an lvalue.
24132 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
24133 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
24134 bool IsPredefinedAllocator = false;
24135 if (DRE) {
24136 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
24137 getAllocatorKind(*this, DSAStack, AllocatorExpr);
24138 IsPredefinedAllocator =
24139 AllocatorTy !=
24140 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
24142 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
24143 QualType AllocatorExprType = AllocatorExpr->getType();
24144 bool IsTypeCompatible = IsPredefinedAllocator;
24145 IsTypeCompatible = IsTypeCompatible ||
24146 Context.hasSameUnqualifiedType(AllocatorExprType,
24147 OMPAllocatorHandleT);
24148 IsTypeCompatible =
24149 IsTypeCompatible ||
24150 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
24151 bool IsNonConstantLValue =
24152 !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue();
24153 if (!DRE || !IsTypeCompatible ||
24154 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
24155 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
24156 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
24157 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
24158 continue;
24160 // OpenMP [2.12.5, target Construct]
24161 // Predefined allocators appearing in a uses_allocators clause cannot have
24162 // traits specified.
24163 if (IsPredefinedAllocator && D.AllocatorTraits) {
24164 Diag(D.AllocatorTraits->getExprLoc(),
24165 diag::err_omp_predefined_allocator_with_traits)
24166 << D.AllocatorTraits->getSourceRange();
24167 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
24168 << cast<NamedDecl>(DRE->getDecl())->getName()
24169 << D.Allocator->getSourceRange();
24170 continue;
24172 // OpenMP [2.12.5, target Construct]
24173 // Non-predefined allocators appearing in a uses_allocators clause must
24174 // have traits specified.
24175 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
24176 Diag(D.Allocator->getExprLoc(),
24177 diag::err_omp_nonpredefined_allocator_without_traits);
24178 continue;
24180 // No allocator traits - just convert it to rvalue.
24181 if (!D.AllocatorTraits)
24182 AllocatorExpr = DefaultLvalueConversion(AllocatorExpr).get();
24183 DSAStack->addUsesAllocatorsDecl(
24184 DRE->getDecl(),
24185 IsPredefinedAllocator
24186 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
24187 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
24189 Expr *AllocatorTraitsExpr = nullptr;
24190 if (D.AllocatorTraits) {
24191 if (D.AllocatorTraits->isTypeDependent()) {
24192 AllocatorTraitsExpr = D.AllocatorTraits;
24193 } else {
24194 // OpenMP [2.12.5, target Construct]
24195 // Arrays that contain allocator traits that appear in a uses_allocators
24196 // clause must be constant arrays, have constant values and be defined
24197 // in the same scope as the construct in which the clause appears.
24198 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
24199 // Check that traits expr is a constant array.
24200 QualType TraitTy;
24201 if (const ArrayType *Ty =
24202 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
24203 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
24204 TraitTy = ConstArrayTy->getElementType();
24205 if (TraitTy.isNull() ||
24206 !(Context.hasSameUnqualifiedType(TraitTy,
24207 DSAStack->getOMPAlloctraitT()) ||
24208 Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
24209 /*CompareUnqualified=*/true))) {
24210 Diag(D.AllocatorTraits->getExprLoc(),
24211 diag::err_omp_expected_array_alloctraits)
24212 << AllocatorTraitsExpr->getType();
24213 continue;
24215 // Do not map by default allocator traits if it is a standalone
24216 // variable.
24217 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
24218 DSAStack->addUsesAllocatorsDecl(
24219 DRE->getDecl(),
24220 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
24223 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
24224 NewD.Allocator = AllocatorExpr;
24225 NewD.AllocatorTraits = AllocatorTraitsExpr;
24226 NewD.LParenLoc = D.LParenLoc;
24227 NewD.RParenLoc = D.RParenLoc;
24229 return OMPUsesAllocatorsClause::Create(Context, StartLoc, LParenLoc, EndLoc,
24230 NewData);
24233 OMPClause *Sema::ActOnOpenMPAffinityClause(
24234 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
24235 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
24236 SmallVector<Expr *, 8> Vars;
24237 for (Expr *RefExpr : Locators) {
24238 assert(RefExpr && "NULL expr in OpenMP shared clause.");
24239 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
24240 // It will be analyzed later.
24241 Vars.push_back(RefExpr);
24242 continue;
24245 SourceLocation ELoc = RefExpr->getExprLoc();
24246 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
24248 if (!SimpleExpr->isLValue()) {
24249 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24250 << 1 << 0 << RefExpr->getSourceRange();
24251 continue;
24254 ExprResult Res;
24256 Sema::TentativeAnalysisScope Trap(*this);
24257 Res = CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
24259 if (!Res.isUsable() && !isa<OMPArraySectionExpr>(SimpleExpr) &&
24260 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
24261 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24262 << 1 << 0 << RefExpr->getSourceRange();
24263 continue;
24265 Vars.push_back(SimpleExpr);
24268 return OMPAffinityClause::Create(Context, StartLoc, LParenLoc, ColonLoc,
24269 EndLoc, Modifier, Vars);
24272 OMPClause *Sema::ActOnOpenMPBindClause(OpenMPBindClauseKind Kind,
24273 SourceLocation KindLoc,
24274 SourceLocation StartLoc,
24275 SourceLocation LParenLoc,
24276 SourceLocation EndLoc) {
24277 if (Kind == OMPC_BIND_unknown) {
24278 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24279 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
24280 /*Last=*/unsigned(OMPC_BIND_unknown))
24281 << getOpenMPClauseName(OMPC_bind);
24282 return nullptr;
24285 return OMPBindClause::Create(Context, Kind, KindLoc, StartLoc, LParenLoc,
24286 EndLoc);
24289 OMPClause *Sema::ActOnOpenMPXDynCGroupMemClause(Expr *Size,
24290 SourceLocation StartLoc,
24291 SourceLocation LParenLoc,
24292 SourceLocation EndLoc) {
24293 Expr *ValExpr = Size;
24294 Stmt *HelperValStmt = nullptr;
24296 // OpenMP [2.5, Restrictions]
24297 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
24298 // value.
24299 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_ompx_dyn_cgroup_mem,
24300 /*StrictlyPositive=*/false))
24301 return nullptr;
24303 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
24304 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
24305 DKind, OMPC_ompx_dyn_cgroup_mem, LangOpts.OpenMP);
24306 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
24307 ValExpr = MakeFullExpr(ValExpr).get();
24308 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24309 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
24310 HelperValStmt = buildPreInits(Context, Captures);
24313 return new (Context) OMPXDynCGroupMemClause(
24314 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
24317 OMPClause *Sema::ActOnOpenMPDoacrossClause(
24318 OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc,
24319 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
24320 SourceLocation LParenLoc, SourceLocation EndLoc) {
24322 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
24323 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
24324 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
24325 DepType != OMPC_DOACROSS_source_omp_cur_iteration &&
24326 DepType != OMPC_DOACROSS_source) {
24327 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
24328 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_doacross);
24329 return nullptr;
24332 SmallVector<Expr *, 8> Vars;
24333 DSAStackTy::OperatorOffsetTy OpsOffs;
24334 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
24335 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
24336 *this,
24337 DepType == OMPC_DOACROSS_source ||
24338 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
24339 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
24340 VarList, DSAStack, EndLoc);
24341 Vars = VarOffset.Vars;
24342 OpsOffs = VarOffset.OpsOffs;
24343 TotalDepCount = VarOffset.TotalDepCount;
24344 auto *C = OMPDoacrossClause::Create(Context, StartLoc, LParenLoc, EndLoc,
24345 DepType, DepLoc, ColonLoc, Vars,
24346 TotalDepCount.getZExtValue());
24347 if (DSAStack->isParentOrderedRegion())
24348 DSAStack->addDoacrossDependClause(C, OpsOffs);
24349 return C;
24352 OMPClause *Sema::ActOnOpenMPXAttributeClause(ArrayRef<const Attr *> Attrs,
24353 SourceLocation StartLoc,
24354 SourceLocation LParenLoc,
24355 SourceLocation EndLoc) {
24356 return new (Context) OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
24359 OMPClause *Sema::ActOnOpenMPXBareClause(SourceLocation StartLoc,
24360 SourceLocation EndLoc) {
24361 return new (Context) OMPXBareClause(StartLoc, EndLoc);