[DFAJumpThreading] Remove incoming StartBlock from all phis when unfolding select...
[llvm-project.git] / clang / lib / Sema / SemaOpenMP.cpp
blob1bd34f73e5f7e00ec7039e5a20d6cd905ce8f259
1 //===--- SemaOpenMP.cpp - Semantic Analysis for OpenMP constructs ---------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 /// This file implements semantic analysis for OpenMP directives and
10 /// clauses.
11 ///
12 //===----------------------------------------------------------------------===//
14 #include "TreeTransform.h"
15 #include "clang/AST/ASTContext.h"
16 #include "clang/AST/ASTMutationListener.h"
17 #include "clang/AST/CXXInheritance.h"
18 #include "clang/AST/Decl.h"
19 #include "clang/AST/DeclCXX.h"
20 #include "clang/AST/DeclOpenMP.h"
21 #include "clang/AST/OpenMPClause.h"
22 #include "clang/AST/StmtCXX.h"
23 #include "clang/AST/StmtOpenMP.h"
24 #include "clang/AST/StmtVisitor.h"
25 #include "clang/AST/TypeOrdering.h"
26 #include "clang/Basic/DiagnosticSema.h"
27 #include "clang/Basic/OpenMPKinds.h"
28 #include "clang/Basic/PartialDiagnostic.h"
29 #include "clang/Basic/TargetInfo.h"
30 #include "clang/Sema/EnterExpressionEvaluationContext.h"
31 #include "clang/Sema/Initialization.h"
32 #include "clang/Sema/Lookup.h"
33 #include "clang/Sema/ParsedAttr.h"
34 #include "clang/Sema/Scope.h"
35 #include "clang/Sema/ScopeInfo.h"
36 #include "clang/Sema/SemaInternal.h"
37 #include "llvm/ADT/IndexedMap.h"
38 #include "llvm/ADT/PointerEmbeddedInt.h"
39 #include "llvm/ADT/STLExtras.h"
40 #include "llvm/ADT/SmallSet.h"
41 #include "llvm/ADT/StringExtras.h"
42 #include "llvm/Frontend/OpenMP/OMPAssume.h"
43 #include "llvm/Frontend/OpenMP/OMPConstants.h"
44 #include <optional>
45 #include <set>
47 using namespace clang;
48 using namespace llvm::omp;
50 //===----------------------------------------------------------------------===//
51 // Stack of data-sharing attributes for variables
52 //===----------------------------------------------------------------------===//
54 static const Expr *checkMapClauseExpressionBase(
55 Sema &SemaRef, Expr *E,
56 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
57 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose);
59 namespace {
60 /// Default data sharing attributes, which can be applied to directive.
61 enum DefaultDataSharingAttributes {
62 DSA_unspecified = 0, /// Data sharing attribute not specified.
63 DSA_none = 1 << 0, /// Default data sharing attribute 'none'.
64 DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
65 DSA_private = 1 << 2, /// Default data sharing attribute 'private'.
66 DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'.
69 /// Stack for tracking declarations used in OpenMP directives and
70 /// clauses and their data-sharing attributes.
71 class DSAStackTy {
72 public:
73 struct DSAVarData {
74 OpenMPDirectiveKind DKind = OMPD_unknown;
75 OpenMPClauseKind CKind = OMPC_unknown;
76 unsigned Modifier = 0;
77 const Expr *RefExpr = nullptr;
78 DeclRefExpr *PrivateCopy = nullptr;
79 SourceLocation ImplicitDSALoc;
80 bool AppliedToPointee = false;
81 DSAVarData() = default;
82 DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
83 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
84 SourceLocation ImplicitDSALoc, unsigned Modifier,
85 bool AppliedToPointee)
86 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
87 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
88 AppliedToPointee(AppliedToPointee) {}
90 using OperatorOffsetTy =
91 llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
92 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
93 /// Kind of the declaration used in the uses_allocators clauses.
94 enum class UsesAllocatorsDeclKind {
95 /// Predefined allocator
96 PredefinedAllocator,
97 /// User-defined allocator
98 UserDefinedAllocator,
99 /// The declaration that represent allocator trait
100 AllocatorTrait,
103 private:
104 struct DSAInfo {
105 OpenMPClauseKind Attributes = OMPC_unknown;
106 unsigned Modifier = 0;
107 /// Pointer to a reference expression and a flag which shows that the
108 /// variable is marked as lastprivate(true) or not (false).
109 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
110 DeclRefExpr *PrivateCopy = nullptr;
111 /// true if the attribute is applied to the pointee, not the variable
112 /// itself.
113 bool AppliedToPointee = false;
115 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
116 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
117 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
118 using LoopControlVariablesMapTy =
119 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
120 /// Struct that associates a component with the clause kind where they are
121 /// found.
122 struct MappedExprComponentTy {
123 OMPClauseMappableExprCommon::MappableExprComponentLists Components;
124 OpenMPClauseKind Kind = OMPC_unknown;
126 using MappedExprComponentsTy =
127 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
128 using CriticalsWithHintsTy =
129 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
130 struct ReductionData {
131 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
132 SourceRange ReductionRange;
133 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
134 ReductionData() = default;
135 void set(BinaryOperatorKind BO, SourceRange RR) {
136 ReductionRange = RR;
137 ReductionOp = BO;
139 void set(const Expr *RefExpr, SourceRange RR) {
140 ReductionRange = RR;
141 ReductionOp = RefExpr;
144 using DeclReductionMapTy =
145 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
146 struct DefaultmapInfo {
147 OpenMPDefaultmapClauseModifier ImplicitBehavior =
148 OMPC_DEFAULTMAP_MODIFIER_unknown;
149 SourceLocation SLoc;
150 DefaultmapInfo() = default;
151 DefaultmapInfo(OpenMPDefaultmapClauseModifier M, SourceLocation Loc)
152 : ImplicitBehavior(M), SLoc(Loc) {}
155 struct SharingMapTy {
156 DeclSAMapTy SharingMap;
157 DeclReductionMapTy ReductionMap;
158 UsedRefMapTy AlignedMap;
159 UsedRefMapTy NontemporalMap;
160 MappedExprComponentsTy MappedExprComponents;
161 LoopControlVariablesMapTy LCVMap;
162 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
163 SourceLocation DefaultAttrLoc;
164 DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown];
165 OpenMPDirectiveKind Directive = OMPD_unknown;
166 /// GenericLoopDirective with bind clause is mapped to other directives,
167 /// like for, distribute and simd. Presently, set MappedDirective to
168 /// OMPLoop. This may also be used in a similar way for other constructs.
169 OpenMPDirectiveKind MappedDirective = OMPD_unknown;
170 DeclarationNameInfo DirectiveName;
171 Scope *CurScope = nullptr;
172 DeclContext *Context = nullptr;
173 SourceLocation ConstructLoc;
174 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
175 /// get the data (loop counters etc.) about enclosing loop-based construct.
176 /// This data is required during codegen.
177 DoacrossClauseMapTy DoacrossDepends;
178 /// First argument (Expr *) contains optional argument of the
179 /// 'ordered' clause, the second one is true if the regions has 'ordered'
180 /// clause, false otherwise.
181 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
182 bool RegionHasOrderConcurrent = false;
183 unsigned AssociatedLoops = 1;
184 bool HasMutipleLoops = false;
185 const Decl *PossiblyLoopCounter = nullptr;
186 bool NowaitRegion = false;
187 bool UntiedRegion = false;
188 bool CancelRegion = false;
189 bool LoopStart = false;
190 bool BodyComplete = false;
191 SourceLocation PrevScanLocation;
192 SourceLocation PrevOrderedLocation;
193 SourceLocation InnerTeamsRegionLoc;
194 /// Reference to the taskgroup task_reduction reference expression.
195 Expr *TaskgroupReductionRef = nullptr;
196 llvm::DenseSet<QualType> MappedClassesQualTypes;
197 SmallVector<Expr *, 4> InnerUsedAllocators;
198 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
199 /// List of globals marked as declare target link in this target region
200 /// (isOpenMPTargetExecutionDirective(Directive) == true).
201 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
202 /// List of decls used in inclusive/exclusive clauses of the scan directive.
203 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
204 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
205 UsesAllocatorsDecls;
206 /// Data is required on creating capture fields for implicit
207 /// default first|private clause.
208 struct ImplicitDefaultFDInfoTy {
209 /// Field decl.
210 const FieldDecl *FD = nullptr;
211 /// Nesting stack level
212 size_t StackLevel = 0;
213 /// Capture variable decl.
214 VarDecl *VD = nullptr;
215 ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel,
216 VarDecl *VD)
217 : FD(FD), StackLevel(StackLevel), VD(VD) {}
219 /// List of captured fields
220 llvm::SmallVector<ImplicitDefaultFDInfoTy, 8>
221 ImplicitDefaultFirstprivateFDs;
222 Expr *DeclareMapperVar = nullptr;
223 SmallVector<VarDecl *, 16> IteratorVarDecls;
224 SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
225 Scope *CurScope, SourceLocation Loc)
226 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
227 ConstructLoc(Loc) {}
228 SharingMapTy() = default;
231 using StackTy = SmallVector<SharingMapTy, 4>;
233 /// Stack of used declaration and their data-sharing attributes.
234 DeclSAMapTy Threadprivates;
235 const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
236 SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack;
237 /// true, if check for DSA must be from parent directive, false, if
238 /// from current directive.
239 OpenMPClauseKind ClauseKindMode = OMPC_unknown;
240 Sema &SemaRef;
241 bool ForceCapturing = false;
242 /// true if all the variables in the target executable directives must be
243 /// captured by reference.
244 bool ForceCaptureByReferenceInTargetExecutable = false;
245 CriticalsWithHintsTy Criticals;
246 unsigned IgnoredStackElements = 0;
248 /// Iterators over the stack iterate in order from innermost to outermost
249 /// directive.
250 using const_iterator = StackTy::const_reverse_iterator;
251 const_iterator begin() const {
252 return Stack.empty() ? const_iterator()
253 : Stack.back().first.rbegin() + IgnoredStackElements;
255 const_iterator end() const {
256 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
258 using iterator = StackTy::reverse_iterator;
259 iterator begin() {
260 return Stack.empty() ? iterator()
261 : Stack.back().first.rbegin() + IgnoredStackElements;
263 iterator end() {
264 return Stack.empty() ? iterator() : Stack.back().first.rend();
267 // Convenience operations to get at the elements of the stack.
269 bool isStackEmpty() const {
270 return Stack.empty() ||
271 Stack.back().second != CurrentNonCapturingFunctionScope ||
272 Stack.back().first.size() <= IgnoredStackElements;
274 size_t getStackSize() const {
275 return isStackEmpty() ? 0
276 : Stack.back().first.size() - IgnoredStackElements;
279 SharingMapTy *getTopOfStackOrNull() {
280 size_t Size = getStackSize();
281 if (Size == 0)
282 return nullptr;
283 return &Stack.back().first[Size - 1];
285 const SharingMapTy *getTopOfStackOrNull() const {
286 return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull();
288 SharingMapTy &getTopOfStack() {
289 assert(!isStackEmpty() && "no current directive");
290 return *getTopOfStackOrNull();
292 const SharingMapTy &getTopOfStack() const {
293 return const_cast<DSAStackTy &>(*this).getTopOfStack();
296 SharingMapTy *getSecondOnStackOrNull() {
297 size_t Size = getStackSize();
298 if (Size <= 1)
299 return nullptr;
300 return &Stack.back().first[Size - 2];
302 const SharingMapTy *getSecondOnStackOrNull() const {
303 return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull();
306 /// Get the stack element at a certain level (previously returned by
307 /// \c getNestingLevel).
309 /// Note that nesting levels count from outermost to innermost, and this is
310 /// the reverse of our iteration order where new inner levels are pushed at
311 /// the front of the stack.
312 SharingMapTy &getStackElemAtLevel(unsigned Level) {
313 assert(Level < getStackSize() && "no such stack element");
314 return Stack.back().first[Level];
316 const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
317 return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level);
320 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
322 /// Checks if the variable is a local for OpenMP region.
323 bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
325 /// Vector of previously declared requires directives
326 SmallVector<const OMPRequiresDecl *, 2> RequiresDecls;
327 /// omp_allocator_handle_t type.
328 QualType OMPAllocatorHandleT;
329 /// omp_depend_t type.
330 QualType OMPDependT;
331 /// omp_event_handle_t type.
332 QualType OMPEventHandleT;
333 /// omp_alloctrait_t type.
334 QualType OMPAlloctraitT;
335 /// Expression for the predefined allocators.
336 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
337 nullptr};
338 /// Vector of previously encountered target directives
339 SmallVector<SourceLocation, 2> TargetLocations;
340 SourceLocation AtomicLocation;
341 /// Vector of declare variant construct traits.
342 SmallVector<llvm::omp::TraitProperty, 8> ConstructTraits;
344 public:
345 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
347 /// Sets omp_allocator_handle_t type.
348 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
349 /// Gets omp_allocator_handle_t type.
350 QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
351 /// Sets omp_alloctrait_t type.
352 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
353 /// Gets omp_alloctrait_t type.
354 QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
355 /// Sets the given default allocator.
356 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
357 Expr *Allocator) {
358 OMPPredefinedAllocators[AllocatorKind] = Allocator;
360 /// Returns the specified default allocator.
361 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
362 return OMPPredefinedAllocators[AllocatorKind];
364 /// Sets omp_depend_t type.
365 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
366 /// Gets omp_depend_t type.
367 QualType getOMPDependT() const { return OMPDependT; }
369 /// Sets omp_event_handle_t type.
370 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
371 /// Gets omp_event_handle_t type.
372 QualType getOMPEventHandleT() const { return OMPEventHandleT; }
374 bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
375 OpenMPClauseKind getClauseParsingMode() const {
376 assert(isClauseParsingMode() && "Must be in clause parsing mode.");
377 return ClauseKindMode;
379 void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
381 bool isBodyComplete() const {
382 const SharingMapTy *Top = getTopOfStackOrNull();
383 return Top && Top->BodyComplete;
385 void setBodyComplete() { getTopOfStack().BodyComplete = true; }
387 bool isForceVarCapturing() const { return ForceCapturing; }
388 void setForceVarCapturing(bool V) { ForceCapturing = V; }
390 void setForceCaptureByReferenceInTargetExecutable(bool V) {
391 ForceCaptureByReferenceInTargetExecutable = V;
393 bool isForceCaptureByReferenceInTargetExecutable() const {
394 return ForceCaptureByReferenceInTargetExecutable;
397 void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
398 Scope *CurScope, SourceLocation Loc) {
399 assert(!IgnoredStackElements &&
400 "cannot change stack while ignoring elements");
401 if (Stack.empty() ||
402 Stack.back().second != CurrentNonCapturingFunctionScope)
403 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
404 Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc);
405 Stack.back().first.back().DefaultAttrLoc = Loc;
408 void pop() {
409 assert(!IgnoredStackElements &&
410 "cannot change stack while ignoring elements");
411 assert(!Stack.back().first.empty() &&
412 "Data-sharing attributes stack is empty!");
413 Stack.back().first.pop_back();
416 /// RAII object to temporarily leave the scope of a directive when we want to
417 /// logically operate in its parent.
418 class ParentDirectiveScope {
419 DSAStackTy &Self;
420 bool Active;
422 public:
423 ParentDirectiveScope(DSAStackTy &Self, bool Activate)
424 : Self(Self), Active(false) {
425 if (Activate)
426 enable();
428 ~ParentDirectiveScope() { disable(); }
429 void disable() {
430 if (Active) {
431 --Self.IgnoredStackElements;
432 Active = false;
435 void enable() {
436 if (!Active) {
437 ++Self.IgnoredStackElements;
438 Active = true;
443 /// Marks that we're started loop parsing.
444 void loopInit() {
445 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
446 "Expected loop-based directive.");
447 getTopOfStack().LoopStart = true;
449 /// Start capturing of the variables in the loop context.
450 void loopStart() {
451 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
452 "Expected loop-based directive.");
453 getTopOfStack().LoopStart = false;
455 /// true, if variables are captured, false otherwise.
456 bool isLoopStarted() const {
457 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
458 "Expected loop-based directive.");
459 return !getTopOfStack().LoopStart;
461 /// Marks (or clears) declaration as possibly loop counter.
462 void resetPossibleLoopCounter(const Decl *D = nullptr) {
463 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
465 /// Gets the possible loop counter decl.
466 const Decl *getPossiblyLoopCunter() const {
467 return getTopOfStack().PossiblyLoopCounter;
469 /// Start new OpenMP region stack in new non-capturing function.
470 void pushFunction() {
471 assert(!IgnoredStackElements &&
472 "cannot change stack while ignoring elements");
473 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
474 assert(!isa<CapturingScopeInfo>(CurFnScope));
475 CurrentNonCapturingFunctionScope = CurFnScope;
477 /// Pop region stack for non-capturing function.
478 void popFunction(const FunctionScopeInfo *OldFSI) {
479 assert(!IgnoredStackElements &&
480 "cannot change stack while ignoring elements");
481 if (!Stack.empty() && Stack.back().second == OldFSI) {
482 assert(Stack.back().first.empty());
483 Stack.pop_back();
485 CurrentNonCapturingFunctionScope = nullptr;
486 for (const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) {
487 if (!isa<CapturingScopeInfo>(FSI)) {
488 CurrentNonCapturingFunctionScope = FSI;
489 break;
494 void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
495 Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint);
497 const std::pair<const OMPCriticalDirective *, llvm::APSInt>
498 getCriticalWithHint(const DeclarationNameInfo &Name) const {
499 auto I = Criticals.find(Name.getAsString());
500 if (I != Criticals.end())
501 return I->second;
502 return std::make_pair(nullptr, llvm::APSInt());
504 /// If 'aligned' declaration for given variable \a D was not seen yet,
505 /// add it and return NULL; otherwise return previous occurrence's expression
506 /// for diagnostics.
507 const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
508 /// If 'nontemporal' declaration for given variable \a D was not seen yet,
509 /// add it and return NULL; otherwise return previous occurrence's expression
510 /// for diagnostics.
511 const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
513 /// Register specified variable as loop control variable.
514 void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
515 /// Check if the specified variable is a loop control variable for
516 /// current region.
517 /// \return The index of the loop control variable in the list of associated
518 /// for-loops (from outer to inner).
519 const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
520 /// Check if the specified variable is a loop control variable for
521 /// parent region.
522 /// \return The index of the loop control variable in the list of associated
523 /// for-loops (from outer to inner).
524 const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const;
525 /// Check if the specified variable is a loop control variable for
526 /// current region.
527 /// \return The index of the loop control variable in the list of associated
528 /// for-loops (from outer to inner).
529 const LCDeclInfo isLoopControlVariable(const ValueDecl *D,
530 unsigned Level) const;
531 /// Get the loop control variable for the I-th loop (or nullptr) in
532 /// parent directive.
533 const ValueDecl *getParentLoopControlVariable(unsigned I) const;
535 /// Marks the specified decl \p D as used in scan directive.
536 void markDeclAsUsedInScanDirective(ValueDecl *D) {
537 if (SharingMapTy *Stack = getSecondOnStackOrNull())
538 Stack->UsedInScanDirective.insert(D);
541 /// Checks if the specified declaration was used in the inner scan directive.
542 bool isUsedInScanDirective(ValueDecl *D) const {
543 if (const SharingMapTy *Stack = getTopOfStackOrNull())
544 return Stack->UsedInScanDirective.contains(D);
545 return false;
548 /// Adds explicit data sharing attribute to the specified declaration.
549 void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
550 DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
551 bool AppliedToPointee = false);
553 /// Adds additional information for the reduction items with the reduction id
554 /// represented as an operator.
555 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
556 BinaryOperatorKind BOK);
557 /// Adds additional information for the reduction items with the reduction id
558 /// represented as reduction identifier.
559 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
560 const Expr *ReductionRef);
561 /// Returns the location and reduction operation from the innermost parent
562 /// region for the given \p D.
563 const DSAVarData
564 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
565 BinaryOperatorKind &BOK,
566 Expr *&TaskgroupDescriptor) const;
567 /// Returns the location and reduction operation from the innermost parent
568 /// region for the given \p D.
569 const DSAVarData
570 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
571 const Expr *&ReductionRef,
572 Expr *&TaskgroupDescriptor) const;
573 /// Return reduction reference expression for the current taskgroup or
574 /// parallel/worksharing directives with task reductions.
575 Expr *getTaskgroupReductionRef() const {
576 assert((getTopOfStack().Directive == OMPD_taskgroup ||
577 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
578 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
579 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
580 "taskgroup reference expression requested for non taskgroup or "
581 "parallel/worksharing directive.");
582 return getTopOfStack().TaskgroupReductionRef;
584 /// Checks if the given \p VD declaration is actually a taskgroup reduction
585 /// descriptor variable at the \p Level of OpenMP regions.
586 bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
587 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
588 cast<DeclRefExpr>(getStackElemAtLevel(Level).TaskgroupReductionRef)
589 ->getDecl() == VD;
592 /// Returns data sharing attributes from top of the stack for the
593 /// specified declaration.
594 const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
595 /// Returns data-sharing attributes for the specified declaration.
596 const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
597 /// Returns data-sharing attributes for the specified declaration.
598 const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const;
599 /// Checks if the specified variables has data-sharing attributes which
600 /// match specified \a CPred predicate in any directive which matches \a DPred
601 /// predicate.
602 const DSAVarData
603 hasDSA(ValueDecl *D,
604 const llvm::function_ref<bool(OpenMPClauseKind, bool,
605 DefaultDataSharingAttributes)>
606 CPred,
607 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
608 bool FromParent) const;
609 /// Checks if the specified variables has data-sharing attributes which
610 /// match specified \a CPred predicate in any innermost directive which
611 /// matches \a DPred predicate.
612 const DSAVarData
613 hasInnermostDSA(ValueDecl *D,
614 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
615 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
616 bool FromParent) const;
617 /// Checks if the specified variables has explicit data-sharing
618 /// attributes which match specified \a CPred predicate at the specified
619 /// OpenMP region.
620 bool
621 hasExplicitDSA(const ValueDecl *D,
622 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
623 unsigned Level, bool NotLastprivate = false) const;
625 /// Returns true if the directive at level \Level matches in the
626 /// specified \a DPred predicate.
627 bool hasExplicitDirective(
628 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
629 unsigned Level) const;
631 /// Finds a directive which matches specified \a DPred predicate.
632 bool hasDirective(
633 const llvm::function_ref<bool(
634 OpenMPDirectiveKind, const DeclarationNameInfo &, SourceLocation)>
635 DPred,
636 bool FromParent) const;
638 /// Returns currently analyzed directive.
639 OpenMPDirectiveKind getCurrentDirective() const {
640 const SharingMapTy *Top = getTopOfStackOrNull();
641 return Top ? Top->Directive : OMPD_unknown;
643 OpenMPDirectiveKind getMappedDirective() const {
644 const SharingMapTy *Top = getTopOfStackOrNull();
645 return Top ? Top->MappedDirective : OMPD_unknown;
647 void setCurrentDirective(OpenMPDirectiveKind NewDK) {
648 SharingMapTy *Top = getTopOfStackOrNull();
649 assert(Top &&
650 "Before calling setCurrentDirective Top of Stack not to be NULL.");
651 // Store the old into MappedDirective & assign argument NewDK to Directive.
652 Top->Directive = NewDK;
654 void setMappedDirective(OpenMPDirectiveKind NewDK) {
655 SharingMapTy *Top = getTopOfStackOrNull();
656 assert(Top &&
657 "Before calling setMappedDirective Top of Stack not to be NULL.");
658 // Store the old into MappedDirective & assign argument NewDK to Directive.
659 Top->MappedDirective = NewDK;
661 /// Returns directive kind at specified level.
662 OpenMPDirectiveKind getDirective(unsigned Level) const {
663 assert(!isStackEmpty() && "No directive at specified level.");
664 return getStackElemAtLevel(Level).Directive;
666 /// Returns the capture region at the specified level.
667 OpenMPDirectiveKind getCaptureRegion(unsigned Level,
668 unsigned OpenMPCaptureLevel) const {
669 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
670 getOpenMPCaptureRegions(CaptureRegions, getDirective(Level));
671 return CaptureRegions[OpenMPCaptureLevel];
673 /// Returns parent directive.
674 OpenMPDirectiveKind getParentDirective() const {
675 const SharingMapTy *Parent = getSecondOnStackOrNull();
676 return Parent ? Parent->Directive : OMPD_unknown;
679 /// Add requires decl to internal vector
680 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
682 /// Checks if the defined 'requires' directive has specified type of clause.
683 template <typename ClauseType> bool hasRequiresDeclWithClause() const {
684 return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
685 return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
686 return isa<ClauseType>(C);
691 /// Checks for a duplicate clause amongst previously declared requires
692 /// directives
693 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
694 bool IsDuplicate = false;
695 for (OMPClause *CNew : ClauseList) {
696 for (const OMPRequiresDecl *D : RequiresDecls) {
697 for (const OMPClause *CPrev : D->clauselists()) {
698 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
699 SemaRef.Diag(CNew->getBeginLoc(),
700 diag::err_omp_requires_clause_redeclaration)
701 << getOpenMPClauseName(CNew->getClauseKind());
702 SemaRef.Diag(CPrev->getBeginLoc(),
703 diag::note_omp_requires_previous_clause)
704 << getOpenMPClauseName(CPrev->getClauseKind());
705 IsDuplicate = true;
710 return IsDuplicate;
713 /// Add location of previously encountered target to internal vector
714 void addTargetDirLocation(SourceLocation LocStart) {
715 TargetLocations.push_back(LocStart);
718 /// Add location for the first encountered atomicc directive.
719 void addAtomicDirectiveLoc(SourceLocation Loc) {
720 if (AtomicLocation.isInvalid())
721 AtomicLocation = Loc;
724 /// Returns the location of the first encountered atomic directive in the
725 /// module.
726 SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; }
728 // Return previously encountered target region locations.
729 ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
730 return TargetLocations;
733 /// Set default data sharing attribute to none.
734 void setDefaultDSANone(SourceLocation Loc) {
735 getTopOfStack().DefaultAttr = DSA_none;
736 getTopOfStack().DefaultAttrLoc = Loc;
738 /// Set default data sharing attribute to shared.
739 void setDefaultDSAShared(SourceLocation Loc) {
740 getTopOfStack().DefaultAttr = DSA_shared;
741 getTopOfStack().DefaultAttrLoc = Loc;
743 /// Set default data sharing attribute to private.
744 void setDefaultDSAPrivate(SourceLocation Loc) {
745 getTopOfStack().DefaultAttr = DSA_private;
746 getTopOfStack().DefaultAttrLoc = Loc;
748 /// Set default data sharing attribute to firstprivate.
749 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
750 getTopOfStack().DefaultAttr = DSA_firstprivate;
751 getTopOfStack().DefaultAttrLoc = Loc;
753 /// Set default data mapping attribute to Modifier:Kind
754 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
755 OpenMPDefaultmapClauseKind Kind, SourceLocation Loc) {
756 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind];
757 DMI.ImplicitBehavior = M;
758 DMI.SLoc = Loc;
760 /// Check whether the implicit-behavior has been set in defaultmap
761 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) {
762 if (VariableCategory == OMPC_DEFAULTMAP_unknown)
763 return getTopOfStack()
764 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
765 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
766 getTopOfStack()
767 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
768 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
769 getTopOfStack()
770 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
771 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown;
772 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
773 OMPC_DEFAULTMAP_MODIFIER_unknown;
776 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
777 return ConstructTraits;
779 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
780 bool ScopeEntry) {
781 if (ScopeEntry)
782 ConstructTraits.append(Traits.begin(), Traits.end());
783 else
784 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
785 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
786 assert(Top == Trait && "Something left a trait on the stack!");
787 (void)Trait;
788 (void)Top;
792 DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const {
793 return getStackSize() <= Level ? DSA_unspecified
794 : getStackElemAtLevel(Level).DefaultAttr;
796 DefaultDataSharingAttributes getDefaultDSA() const {
797 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
799 SourceLocation getDefaultDSALocation() const {
800 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
802 OpenMPDefaultmapClauseModifier
803 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const {
804 return isStackEmpty()
805 ? OMPC_DEFAULTMAP_MODIFIER_unknown
806 : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior;
808 OpenMPDefaultmapClauseModifier
809 getDefaultmapModifierAtLevel(unsigned Level,
810 OpenMPDefaultmapClauseKind Kind) const {
811 return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior;
813 bool isDefaultmapCapturedByRef(unsigned Level,
814 OpenMPDefaultmapClauseKind Kind) const {
815 OpenMPDefaultmapClauseModifier M =
816 getDefaultmapModifierAtLevel(Level, Kind);
817 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
818 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
819 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
820 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
821 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom);
823 return true;
825 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
826 OpenMPDefaultmapClauseKind Kind) {
827 switch (Kind) {
828 case OMPC_DEFAULTMAP_scalar:
829 case OMPC_DEFAULTMAP_pointer:
830 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
831 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
832 (M == OMPC_DEFAULTMAP_MODIFIER_default);
833 case OMPC_DEFAULTMAP_aggregate:
834 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
835 default:
836 break;
838 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum");
840 bool mustBeFirstprivateAtLevel(unsigned Level,
841 OpenMPDefaultmapClauseKind Kind) const {
842 OpenMPDefaultmapClauseModifier M =
843 getDefaultmapModifierAtLevel(Level, Kind);
844 return mustBeFirstprivateBase(M, Kind);
846 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
847 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
848 return mustBeFirstprivateBase(M, Kind);
851 /// Checks if the specified variable is a threadprivate.
852 bool isThreadPrivate(VarDecl *D) {
853 const DSAVarData DVar = getTopDSA(D, false);
854 return isOpenMPThreadPrivate(DVar.CKind);
857 /// Marks current region as ordered (it has an 'ordered' clause).
858 void setOrderedRegion(bool IsOrdered, const Expr *Param,
859 OMPOrderedClause *Clause) {
860 if (IsOrdered)
861 getTopOfStack().OrderedRegion.emplace(Param, Clause);
862 else
863 getTopOfStack().OrderedRegion.reset();
865 /// Returns true, if region is ordered (has associated 'ordered' clause),
866 /// false - otherwise.
867 bool isOrderedRegion() const {
868 if (const SharingMapTy *Top = getTopOfStackOrNull())
869 return Top->OrderedRegion.has_value();
870 return false;
872 /// Returns optional parameter for the ordered region.
873 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
874 if (const SharingMapTy *Top = getTopOfStackOrNull())
875 if (Top->OrderedRegion)
876 return *Top->OrderedRegion;
877 return std::make_pair(nullptr, nullptr);
879 /// Returns true, if parent region is ordered (has associated
880 /// 'ordered' clause), false - otherwise.
881 bool isParentOrderedRegion() const {
882 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
883 return Parent->OrderedRegion.has_value();
884 return false;
886 /// Returns optional parameter for the ordered region.
887 std::pair<const Expr *, OMPOrderedClause *>
888 getParentOrderedRegionParam() const {
889 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
890 if (Parent->OrderedRegion)
891 return *Parent->OrderedRegion;
892 return std::make_pair(nullptr, nullptr);
894 /// Marks current region as having an 'order' clause.
895 void setRegionHasOrderConcurrent(bool HasOrderConcurrent) {
896 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
898 /// Returns true, if parent region is order (has associated
899 /// 'order' clause), false - otherwise.
900 bool isParentOrderConcurrent() const {
901 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
902 return Parent->RegionHasOrderConcurrent;
903 return false;
905 /// Marks current region as nowait (it has a 'nowait' clause).
906 void setNowaitRegion(bool IsNowait = true) {
907 getTopOfStack().NowaitRegion = IsNowait;
909 /// Returns true, if parent region is nowait (has associated
910 /// 'nowait' clause), false - otherwise.
911 bool isParentNowaitRegion() const {
912 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
913 return Parent->NowaitRegion;
914 return false;
916 /// Marks current region as untied (it has a 'untied' clause).
917 void setUntiedRegion(bool IsUntied = true) {
918 getTopOfStack().UntiedRegion = IsUntied;
920 /// Return true if current region is untied.
921 bool isUntiedRegion() const {
922 const SharingMapTy *Top = getTopOfStackOrNull();
923 return Top ? Top->UntiedRegion : false;
925 /// Marks parent region as cancel region.
926 void setParentCancelRegion(bool Cancel = true) {
927 if (SharingMapTy *Parent = getSecondOnStackOrNull())
928 Parent->CancelRegion |= Cancel;
930 /// Return true if current region has inner cancel construct.
931 bool isCancelRegion() const {
932 const SharingMapTy *Top = getTopOfStackOrNull();
933 return Top ? Top->CancelRegion : false;
936 /// Mark that parent region already has scan directive.
937 void setParentHasScanDirective(SourceLocation Loc) {
938 if (SharingMapTy *Parent = getSecondOnStackOrNull())
939 Parent->PrevScanLocation = Loc;
941 /// Return true if current region has inner cancel construct.
942 bool doesParentHasScanDirective() const {
943 const SharingMapTy *Top = getSecondOnStackOrNull();
944 return Top ? Top->PrevScanLocation.isValid() : false;
946 /// Return true if current region has inner cancel construct.
947 SourceLocation getParentScanDirectiveLoc() const {
948 const SharingMapTy *Top = getSecondOnStackOrNull();
949 return Top ? Top->PrevScanLocation : SourceLocation();
951 /// Mark that parent region already has ordered directive.
952 void setParentHasOrderedDirective(SourceLocation Loc) {
953 if (SharingMapTy *Parent = getSecondOnStackOrNull())
954 Parent->PrevOrderedLocation = Loc;
956 /// Return true if current region has inner ordered construct.
957 bool doesParentHasOrderedDirective() const {
958 const SharingMapTy *Top = getSecondOnStackOrNull();
959 return Top ? Top->PrevOrderedLocation.isValid() : false;
961 /// Returns the location of the previously specified ordered directive.
962 SourceLocation getParentOrderedDirectiveLoc() const {
963 const SharingMapTy *Top = getSecondOnStackOrNull();
964 return Top ? Top->PrevOrderedLocation : SourceLocation();
967 /// Set collapse value for the region.
968 void setAssociatedLoops(unsigned Val) {
969 getTopOfStack().AssociatedLoops = Val;
970 if (Val > 1)
971 getTopOfStack().HasMutipleLoops = true;
973 /// Return collapse value for region.
974 unsigned getAssociatedLoops() const {
975 const SharingMapTy *Top = getTopOfStackOrNull();
976 return Top ? Top->AssociatedLoops : 0;
978 /// Returns true if the construct is associated with multiple loops.
979 bool hasMutipleLoops() const {
980 const SharingMapTy *Top = getTopOfStackOrNull();
981 return Top ? Top->HasMutipleLoops : false;
984 /// Marks current target region as one with closely nested teams
985 /// region.
986 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
987 if (SharingMapTy *Parent = getSecondOnStackOrNull())
988 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
990 /// Returns true, if current region has closely nested teams region.
991 bool hasInnerTeamsRegion() const {
992 return getInnerTeamsRegionLoc().isValid();
994 /// Returns location of the nested teams region (if any).
995 SourceLocation getInnerTeamsRegionLoc() const {
996 const SharingMapTy *Top = getTopOfStackOrNull();
997 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
1000 Scope *getCurScope() const {
1001 const SharingMapTy *Top = getTopOfStackOrNull();
1002 return Top ? Top->CurScope : nullptr;
1004 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
1005 SourceLocation getConstructLoc() const {
1006 const SharingMapTy *Top = getTopOfStackOrNull();
1007 return Top ? Top->ConstructLoc : SourceLocation();
1010 /// Do the check specified in \a Check to all component lists and return true
1011 /// if any issue is found.
1012 bool checkMappableExprComponentListsForDecl(
1013 const ValueDecl *VD, bool CurrentRegionOnly,
1014 const llvm::function_ref<
1015 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
1016 OpenMPClauseKind)>
1017 Check) const {
1018 if (isStackEmpty())
1019 return false;
1020 auto SI = begin();
1021 auto SE = end();
1023 if (SI == SE)
1024 return false;
1026 if (CurrentRegionOnly)
1027 SE = std::next(SI);
1028 else
1029 std::advance(SI, 1);
1031 for (; SI != SE; ++SI) {
1032 auto MI = SI->MappedExprComponents.find(VD);
1033 if (MI != SI->MappedExprComponents.end())
1034 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
1035 MI->second.Components)
1036 if (Check(L, MI->second.Kind))
1037 return true;
1039 return false;
1042 /// Do the check specified in \a Check to all component lists at a given level
1043 /// and return true if any issue is found.
1044 bool checkMappableExprComponentListsForDeclAtLevel(
1045 const ValueDecl *VD, unsigned Level,
1046 const llvm::function_ref<
1047 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
1048 OpenMPClauseKind)>
1049 Check) const {
1050 if (getStackSize() <= Level)
1051 return false;
1053 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1054 auto MI = StackElem.MappedExprComponents.find(VD);
1055 if (MI != StackElem.MappedExprComponents.end())
1056 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
1057 MI->second.Components)
1058 if (Check(L, MI->second.Kind))
1059 return true;
1060 return false;
1063 /// Create a new mappable expression component list associated with a given
1064 /// declaration and initialize it with the provided list of components.
1065 void addMappableExpressionComponents(
1066 const ValueDecl *VD,
1067 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
1068 OpenMPClauseKind WhereFoundClauseKind) {
1069 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1070 // Create new entry and append the new components there.
1071 MEC.Components.resize(MEC.Components.size() + 1);
1072 MEC.Components.back().append(Components.begin(), Components.end());
1073 MEC.Kind = WhereFoundClauseKind;
1076 unsigned getNestingLevel() const {
1077 assert(!isStackEmpty());
1078 return getStackSize() - 1;
1080 void addDoacrossDependClause(OMPClause *C, const OperatorOffsetTy &OpsOffs) {
1081 SharingMapTy *Parent = getSecondOnStackOrNull();
1082 assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
1083 Parent->DoacrossDepends.try_emplace(C, OpsOffs);
1085 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1086 getDoacrossDependClauses() const {
1087 const SharingMapTy &StackElem = getTopOfStack();
1088 if (isOpenMPWorksharingDirective(StackElem.Directive)) {
1089 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1090 return llvm::make_range(Ref.begin(), Ref.end());
1092 return llvm::make_range(StackElem.DoacrossDepends.end(),
1093 StackElem.DoacrossDepends.end());
1096 // Store types of classes which have been explicitly mapped
1097 void addMappedClassesQualTypes(QualType QT) {
1098 SharingMapTy &StackElem = getTopOfStack();
1099 StackElem.MappedClassesQualTypes.insert(QT);
1102 // Return set of mapped classes types
1103 bool isClassPreviouslyMapped(QualType QT) const {
1104 const SharingMapTy &StackElem = getTopOfStack();
1105 return StackElem.MappedClassesQualTypes.contains(QT);
1108 /// Adds global declare target to the parent target region.
1109 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1110 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1111 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1112 "Expected declare target link global.");
1113 for (auto &Elem : *this) {
1114 if (isOpenMPTargetExecutionDirective(Elem.Directive)) {
1115 Elem.DeclareTargetLinkVarDecls.push_back(E);
1116 return;
1121 /// Returns the list of globals with declare target link if current directive
1122 /// is target.
1123 ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1124 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
1125 "Expected target executable directive.");
1126 return getTopOfStack().DeclareTargetLinkVarDecls;
1129 /// Adds list of allocators expressions.
1130 void addInnerAllocatorExpr(Expr *E) {
1131 getTopOfStack().InnerUsedAllocators.push_back(E);
1133 /// Return list of used allocators.
1134 ArrayRef<Expr *> getInnerAllocators() const {
1135 return getTopOfStack().InnerUsedAllocators;
1137 /// Marks the declaration as implicitly firstprivate nin the task-based
1138 /// regions.
1139 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1140 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(D);
1142 /// Checks if the decl is implicitly firstprivate in the task-based region.
1143 bool isImplicitTaskFirstprivate(Decl *D) const {
1144 return getTopOfStack().ImplicitTaskFirstprivates.contains(D);
1147 /// Marks decl as used in uses_allocators clause as the allocator.
1148 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1149 getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind);
1151 /// Checks if specified decl is used in uses allocator clause as the
1152 /// allocator.
1153 std::optional<UsesAllocatorsDeclKind>
1154 isUsesAllocatorsDecl(unsigned Level, const Decl *D) const {
1155 const SharingMapTy &StackElem = getTopOfStack();
1156 auto I = StackElem.UsesAllocatorsDecls.find(D);
1157 if (I == StackElem.UsesAllocatorsDecls.end())
1158 return std::nullopt;
1159 return I->getSecond();
1161 std::optional<UsesAllocatorsDeclKind>
1162 isUsesAllocatorsDecl(const Decl *D) const {
1163 const SharingMapTy &StackElem = getTopOfStack();
1164 auto I = StackElem.UsesAllocatorsDecls.find(D);
1165 if (I == StackElem.UsesAllocatorsDecls.end())
1166 return std::nullopt;
1167 return I->getSecond();
1170 void addDeclareMapperVarRef(Expr *Ref) {
1171 SharingMapTy &StackElem = getTopOfStack();
1172 StackElem.DeclareMapperVar = Ref;
1174 const Expr *getDeclareMapperVarRef() const {
1175 const SharingMapTy *Top = getTopOfStackOrNull();
1176 return Top ? Top->DeclareMapperVar : nullptr;
1179 /// Add a new iterator variable.
1180 void addIteratorVarDecl(VarDecl *VD) {
1181 SharingMapTy &StackElem = getTopOfStack();
1182 StackElem.IteratorVarDecls.push_back(VD->getCanonicalDecl());
1184 /// Check if variable declaration is an iterator VarDecl.
1185 bool isIteratorVarDecl(const VarDecl *VD) const {
1186 const SharingMapTy *Top = getTopOfStackOrNull();
1187 if (!Top)
1188 return false;
1190 return llvm::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_pointer + 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_pointer + 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 /// No errors is found.
11609 NoError
11611 /// Reference to Sema.
11612 Sema &SemaRef;
11613 /// A location for note diagnostics (when error is found).
11614 SourceLocation NoteLoc;
11615 /// 'x' lvalue part of the source atomic expression.
11616 Expr *X;
11617 /// 'expr' rvalue part of the source atomic expression.
11618 Expr *E;
11619 /// Helper expression of the form
11620 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11621 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11622 Expr *UpdateExpr;
11623 /// Is 'x' a LHS in a RHS part of full update expression. It is
11624 /// important for non-associative operations.
11625 bool IsXLHSInRHSPart;
11626 BinaryOperatorKind Op;
11627 SourceLocation OpLoc;
11628 /// true if the source expression is a postfix unary operation, false
11629 /// if it is a prefix unary operation.
11630 bool IsPostfixUpdate;
11632 public:
11633 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11634 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11635 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11636 /// Check specified statement that it is suitable for 'atomic update'
11637 /// constructs and extract 'x', 'expr' and Operation from the original
11638 /// expression. If DiagId and NoteId == 0, then only check is performed
11639 /// without error notification.
11640 /// \param DiagId Diagnostic which should be emitted if error is found.
11641 /// \param NoteId Diagnostic note for the main error message.
11642 /// \return true if statement is not an update expression, false otherwise.
11643 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11644 /// Return the 'x' lvalue part of the source atomic expression.
11645 Expr *getX() const { return X; }
11646 /// Return the 'expr' rvalue part of the source atomic expression.
11647 Expr *getExpr() const { return E; }
11648 /// Return the update expression used in calculation of the updated
11649 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11650 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11651 Expr *getUpdateExpr() const { return UpdateExpr; }
11652 /// Return true if 'x' is LHS in RHS part of full update expression,
11653 /// false otherwise.
11654 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11656 /// true if the source expression is a postfix unary operation, false
11657 /// if it is a prefix unary operation.
11658 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11660 private:
11661 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11662 unsigned NoteId = 0);
11665 bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11666 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11667 ExprAnalysisErrorCode ErrorFound = NoError;
11668 SourceLocation ErrorLoc, NoteLoc;
11669 SourceRange ErrorRange, NoteRange;
11670 // Allowed constructs are:
11671 // x = x binop expr;
11672 // x = expr binop x;
11673 if (AtomicBinOp->getOpcode() == BO_Assign) {
11674 X = AtomicBinOp->getLHS();
11675 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11676 AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11677 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11678 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11679 AtomicInnerBinOp->isBitwiseOp()) {
11680 Op = AtomicInnerBinOp->getOpcode();
11681 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11682 Expr *LHS = AtomicInnerBinOp->getLHS();
11683 Expr *RHS = AtomicInnerBinOp->getRHS();
11684 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11685 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11686 /*Canonical=*/true);
11687 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11688 /*Canonical=*/true);
11689 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11690 /*Canonical=*/true);
11691 if (XId == LHSId) {
11692 E = RHS;
11693 IsXLHSInRHSPart = true;
11694 } else if (XId == RHSId) {
11695 E = LHS;
11696 IsXLHSInRHSPart = false;
11697 } else {
11698 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11699 ErrorRange = AtomicInnerBinOp->getSourceRange();
11700 NoteLoc = X->getExprLoc();
11701 NoteRange = X->getSourceRange();
11702 ErrorFound = NotAnUpdateExpression;
11704 } else {
11705 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11706 ErrorRange = AtomicInnerBinOp->getSourceRange();
11707 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11708 NoteRange = SourceRange(NoteLoc, NoteLoc);
11709 ErrorFound = NotABinaryOperator;
11711 } else {
11712 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11713 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11714 ErrorFound = NotABinaryExpression;
11716 } else {
11717 ErrorLoc = AtomicBinOp->getExprLoc();
11718 ErrorRange = AtomicBinOp->getSourceRange();
11719 NoteLoc = AtomicBinOp->getOperatorLoc();
11720 NoteRange = SourceRange(NoteLoc, NoteLoc);
11721 ErrorFound = NotAnAssignmentOp;
11723 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11724 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11725 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11726 return true;
11728 if (SemaRef.CurContext->isDependentContext())
11729 E = X = UpdateExpr = nullptr;
11730 return ErrorFound != NoError;
11733 bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11734 unsigned NoteId) {
11735 ExprAnalysisErrorCode ErrorFound = NoError;
11736 SourceLocation ErrorLoc, NoteLoc;
11737 SourceRange ErrorRange, NoteRange;
11738 // Allowed constructs are:
11739 // x++;
11740 // x--;
11741 // ++x;
11742 // --x;
11743 // x binop= expr;
11744 // x = x binop expr;
11745 // x = expr binop x;
11746 if (auto *AtomicBody = dyn_cast<Expr>(S)) {
11747 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11748 if (AtomicBody->getType()->isScalarType() ||
11749 AtomicBody->isInstantiationDependent()) {
11750 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11751 AtomicBody->IgnoreParenImpCasts())) {
11752 // Check for Compound Assignment Operation
11753 Op = BinaryOperator::getOpForCompoundAssignment(
11754 AtomicCompAssignOp->getOpcode());
11755 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11756 E = AtomicCompAssignOp->getRHS();
11757 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11758 IsXLHSInRHSPart = true;
11759 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11760 AtomicBody->IgnoreParenImpCasts())) {
11761 // Check for Binary Operation
11762 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11763 return true;
11764 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11765 AtomicBody->IgnoreParenImpCasts())) {
11766 // Check for Unary Operation
11767 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11768 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11769 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11770 OpLoc = AtomicUnaryOp->getOperatorLoc();
11771 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11772 E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
11773 IsXLHSInRHSPart = true;
11774 } else {
11775 ErrorFound = NotAnUnaryIncDecExpression;
11776 ErrorLoc = AtomicUnaryOp->getExprLoc();
11777 ErrorRange = AtomicUnaryOp->getSourceRange();
11778 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11779 NoteRange = SourceRange(NoteLoc, NoteLoc);
11781 } else if (!AtomicBody->isInstantiationDependent()) {
11782 ErrorFound = NotABinaryOrUnaryExpression;
11783 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11784 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11786 } else {
11787 ErrorFound = NotAScalarType;
11788 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11789 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11791 } else {
11792 ErrorFound = NotAnExpression;
11793 NoteLoc = ErrorLoc = S->getBeginLoc();
11794 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11796 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11797 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11798 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11799 return true;
11801 if (SemaRef.CurContext->isDependentContext())
11802 E = X = UpdateExpr = nullptr;
11803 if (ErrorFound == NoError && E && X) {
11804 // Build an update expression of form 'OpaqueValueExpr(x) binop
11805 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11806 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11807 auto *OVEX = new (SemaRef.getASTContext())
11808 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11809 auto *OVEExpr = new (SemaRef.getASTContext())
11810 OpaqueValueExpr(E->getExprLoc(), E->getType(), VK_PRValue);
11811 ExprResult Update =
11812 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11813 IsXLHSInRHSPart ? OVEExpr : OVEX);
11814 if (Update.isInvalid())
11815 return true;
11816 Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
11817 Sema::AA_Casting);
11818 if (Update.isInvalid())
11819 return true;
11820 UpdateExpr = Update.get();
11822 return ErrorFound != NoError;
11825 /// Get the node id of the fixed point of an expression \a S.
11826 llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11827 llvm::FoldingSetNodeID Id;
11828 S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11829 return Id;
11832 /// Check if two expressions are same.
11833 bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11834 const Expr *RHS) {
11835 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11838 class OpenMPAtomicCompareChecker {
11839 public:
11840 /// All kinds of errors that can occur in `atomic compare`
11841 enum ErrorTy {
11842 /// Empty compound statement.
11843 NoStmt = 0,
11844 /// More than one statement in a compound statement.
11845 MoreThanOneStmt,
11846 /// Not an assignment binary operator.
11847 NotAnAssignment,
11848 /// Not a conditional operator.
11849 NotCondOp,
11850 /// Wrong false expr. According to the spec, 'x' should be at the false
11851 /// expression of a conditional expression.
11852 WrongFalseExpr,
11853 /// The condition of a conditional expression is not a binary operator.
11854 NotABinaryOp,
11855 /// Invalid binary operator (not <, >, or ==).
11856 InvalidBinaryOp,
11857 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11858 InvalidComparison,
11859 /// X is not a lvalue.
11860 XNotLValue,
11861 /// Not a scalar.
11862 NotScalar,
11863 /// Not an integer.
11864 NotInteger,
11865 /// 'else' statement is not expected.
11866 UnexpectedElse,
11867 /// Not an equality operator.
11868 NotEQ,
11869 /// Invalid assignment (not v == x).
11870 InvalidAssignment,
11871 /// Not if statement
11872 NotIfStmt,
11873 /// More than two statements in a compund statement.
11874 MoreThanTwoStmts,
11875 /// Not a compound statement.
11876 NotCompoundStmt,
11877 /// No else statement.
11878 NoElse,
11879 /// Not 'if (r)'.
11880 InvalidCondition,
11881 /// No error.
11882 NoError,
11885 struct ErrorInfoTy {
11886 ErrorTy Error;
11887 SourceLocation ErrorLoc;
11888 SourceRange ErrorRange;
11889 SourceLocation NoteLoc;
11890 SourceRange NoteRange;
11893 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11895 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11896 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11898 Expr *getX() const { return X; }
11899 Expr *getE() const { return E; }
11900 Expr *getD() const { return D; }
11901 Expr *getCond() const { return C; }
11902 bool isXBinopExpr() const { return IsXBinopExpr; }
11904 protected:
11905 /// Reference to ASTContext
11906 ASTContext &ContextRef;
11907 /// 'x' lvalue part of the source atomic expression.
11908 Expr *X = nullptr;
11909 /// 'expr' or 'e' rvalue part of the source atomic expression.
11910 Expr *E = nullptr;
11911 /// 'd' rvalue part of the source atomic expression.
11912 Expr *D = nullptr;
11913 /// 'cond' part of the source atomic expression. It is in one of the following
11914 /// forms:
11915 /// expr ordop x
11916 /// x ordop expr
11917 /// x == e
11918 /// e == x
11919 Expr *C = nullptr;
11920 /// True if the cond expr is in the form of 'x ordop expr'.
11921 bool IsXBinopExpr = true;
11923 /// Check if it is a valid conditional update statement (cond-update-stmt).
11924 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11926 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11927 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11929 /// Check if all captured values have right type.
11930 bool checkType(ErrorInfoTy &ErrorInfo) const;
11932 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
11933 bool ShouldBeLValue, bool ShouldBeInteger = false) {
11934 if (E->isInstantiationDependent())
11935 return true;
11937 if (ShouldBeLValue && !E->isLValue()) {
11938 ErrorInfo.Error = ErrorTy::XNotLValue;
11939 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11940 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11941 return false;
11944 QualType QTy = E->getType();
11945 if (!QTy->isScalarType()) {
11946 ErrorInfo.Error = ErrorTy::NotScalar;
11947 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11948 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11949 return false;
11951 if (ShouldBeInteger && !QTy->isIntegerType()) {
11952 ErrorInfo.Error = ErrorTy::NotInteger;
11953 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11954 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11955 return false;
11958 return true;
11962 bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
11963 ErrorInfoTy &ErrorInfo) {
11964 auto *Then = S->getThen();
11965 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11966 if (CS->body_empty()) {
11967 ErrorInfo.Error = ErrorTy::NoStmt;
11968 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11969 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11970 return false;
11972 if (CS->size() > 1) {
11973 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11974 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11975 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11976 return false;
11978 Then = CS->body_front();
11981 auto *BO = dyn_cast<BinaryOperator>(Then);
11982 if (!BO) {
11983 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11984 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11985 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11986 return false;
11988 if (BO->getOpcode() != BO_Assign) {
11989 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11990 ErrorInfo.ErrorLoc = BO->getExprLoc();
11991 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11992 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11993 return false;
11996 X = BO->getLHS();
11998 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11999 if (!Cond) {
12000 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12001 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12002 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12003 return false;
12006 switch (Cond->getOpcode()) {
12007 case BO_EQ: {
12008 C = Cond;
12009 D = BO->getRHS();
12010 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
12011 E = Cond->getRHS();
12012 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12013 E = Cond->getLHS();
12014 } else {
12015 ErrorInfo.Error = ErrorTy::InvalidComparison;
12016 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12017 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12018 return false;
12020 break;
12022 case BO_LT:
12023 case BO_GT: {
12024 E = BO->getRHS();
12025 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
12026 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
12027 C = Cond;
12028 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
12029 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12030 C = Cond;
12031 IsXBinopExpr = false;
12032 } else {
12033 ErrorInfo.Error = ErrorTy::InvalidComparison;
12034 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12035 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12036 return false;
12038 break;
12040 default:
12041 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12042 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12043 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12044 return false;
12047 if (S->getElse()) {
12048 ErrorInfo.Error = ErrorTy::UnexpectedElse;
12049 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
12050 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
12051 return false;
12054 return true;
12057 bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
12058 ErrorInfoTy &ErrorInfo) {
12059 auto *BO = dyn_cast<BinaryOperator>(S);
12060 if (!BO) {
12061 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12062 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12063 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12064 return false;
12066 if (BO->getOpcode() != BO_Assign) {
12067 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12068 ErrorInfo.ErrorLoc = BO->getExprLoc();
12069 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12070 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12071 return false;
12074 X = BO->getLHS();
12076 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
12077 if (!CO) {
12078 ErrorInfo.Error = ErrorTy::NotCondOp;
12079 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
12080 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
12081 return false;
12084 if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
12085 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
12086 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
12087 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12088 CO->getFalseExpr()->getSourceRange();
12089 return false;
12092 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
12093 if (!Cond) {
12094 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12095 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12096 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12097 CO->getCond()->getSourceRange();
12098 return false;
12101 switch (Cond->getOpcode()) {
12102 case BO_EQ: {
12103 C = Cond;
12104 D = CO->getTrueExpr();
12105 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
12106 E = Cond->getRHS();
12107 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12108 E = Cond->getLHS();
12109 } else {
12110 ErrorInfo.Error = ErrorTy::InvalidComparison;
12111 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12112 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12113 return false;
12115 break;
12117 case BO_LT:
12118 case BO_GT: {
12119 E = CO->getTrueExpr();
12120 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
12121 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
12122 C = Cond;
12123 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
12124 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12125 C = Cond;
12126 IsXBinopExpr = false;
12127 } else {
12128 ErrorInfo.Error = ErrorTy::InvalidComparison;
12129 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12130 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12131 return false;
12133 break;
12135 default:
12136 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12137 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12138 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12139 return false;
12142 return true;
12145 bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
12146 // 'x' and 'e' cannot be nullptr
12147 assert(X && E && "X and E cannot be nullptr");
12149 if (!CheckValue(X, ErrorInfo, true))
12150 return false;
12152 if (!CheckValue(E, ErrorInfo, false))
12153 return false;
12155 if (D && !CheckValue(D, ErrorInfo, false))
12156 return false;
12158 return true;
12161 bool OpenMPAtomicCompareChecker::checkStmt(
12162 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
12163 auto *CS = dyn_cast<CompoundStmt>(S);
12164 if (CS) {
12165 if (CS->body_empty()) {
12166 ErrorInfo.Error = ErrorTy::NoStmt;
12167 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12168 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12169 return false;
12172 if (CS->size() != 1) {
12173 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12174 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12175 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12176 return false;
12178 S = CS->body_front();
12181 auto Res = false;
12183 if (auto *IS = dyn_cast<IfStmt>(S)) {
12184 // Check if the statement is in one of the following forms
12185 // (cond-update-stmt):
12186 // if (expr ordop x) { x = expr; }
12187 // if (x ordop expr) { x = expr; }
12188 // if (x == e) { x = d; }
12189 Res = checkCondUpdateStmt(IS, ErrorInfo);
12190 } else {
12191 // Check if the statement is in one of the following forms (cond-expr-stmt):
12192 // x = expr ordop x ? expr : x;
12193 // x = x ordop expr ? expr : x;
12194 // x = x == e ? d : x;
12195 Res = checkCondExprStmt(S, ErrorInfo);
12198 if (!Res)
12199 return false;
12201 return checkType(ErrorInfo);
12204 class OpenMPAtomicCompareCaptureChecker final
12205 : public OpenMPAtomicCompareChecker {
12206 public:
12207 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
12209 Expr *getV() const { return V; }
12210 Expr *getR() const { return R; }
12211 bool isFailOnly() const { return IsFailOnly; }
12212 bool isPostfixUpdate() const { return IsPostfixUpdate; }
12214 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
12215 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12217 private:
12218 bool checkType(ErrorInfoTy &ErrorInfo);
12220 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
12221 // form of 'conditional-update-capture-atomic' structured block on the v5.2
12222 // spec p.p. 82:
12223 // (1) { v = x; cond-update-stmt }
12224 // (2) { cond-update-stmt v = x; }
12225 // (3) if(x == e) { x = d; } else { v = x; }
12226 // (4) { r = x == e; if(r) { x = d; } }
12227 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
12229 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
12230 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12232 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
12233 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
12234 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12236 /// 'v' lvalue part of the source atomic expression.
12237 Expr *V = nullptr;
12238 /// 'r' lvalue part of the source atomic expression.
12239 Expr *R = nullptr;
12240 /// If 'v' is only updated when the comparison fails.
12241 bool IsFailOnly = false;
12242 /// If original value of 'x' must be stored in 'v', not an updated one.
12243 bool IsPostfixUpdate = false;
12246 bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12247 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12248 return false;
12250 if (V && !CheckValue(V, ErrorInfo, true))
12251 return false;
12253 if (R && !CheckValue(R, ErrorInfo, true, true))
12254 return false;
12256 return true;
12259 bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
12260 ErrorInfoTy &ErrorInfo) {
12261 IsFailOnly = true;
12263 auto *Then = S->getThen();
12264 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
12265 if (CS->body_empty()) {
12266 ErrorInfo.Error = ErrorTy::NoStmt;
12267 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12268 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12269 return false;
12271 if (CS->size() > 1) {
12272 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12273 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12274 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12275 return false;
12277 Then = CS->body_front();
12280 auto *BO = dyn_cast<BinaryOperator>(Then);
12281 if (!BO) {
12282 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12283 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12284 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12285 return false;
12287 if (BO->getOpcode() != BO_Assign) {
12288 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12289 ErrorInfo.ErrorLoc = BO->getExprLoc();
12290 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12291 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12292 return false;
12295 X = BO->getLHS();
12296 D = BO->getRHS();
12298 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12299 if (!Cond) {
12300 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12301 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12302 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12303 return false;
12305 if (Cond->getOpcode() != BO_EQ) {
12306 ErrorInfo.Error = ErrorTy::NotEQ;
12307 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12308 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12309 return false;
12312 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
12313 E = Cond->getRHS();
12314 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12315 E = Cond->getLHS();
12316 } else {
12317 ErrorInfo.Error = ErrorTy::InvalidComparison;
12318 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12319 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12320 return false;
12323 C = Cond;
12325 if (!S->getElse()) {
12326 ErrorInfo.Error = ErrorTy::NoElse;
12327 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12328 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12329 return false;
12332 auto *Else = S->getElse();
12333 if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
12334 if (CS->body_empty()) {
12335 ErrorInfo.Error = ErrorTy::NoStmt;
12336 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12337 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12338 return false;
12340 if (CS->size() > 1) {
12341 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12342 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12343 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12344 return false;
12346 Else = CS->body_front();
12349 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12350 if (!ElseBO) {
12351 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12352 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12353 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12354 return false;
12356 if (ElseBO->getOpcode() != BO_Assign) {
12357 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12358 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12359 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12360 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12361 return false;
12364 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12365 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12366 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12367 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12368 ElseBO->getRHS()->getSourceRange();
12369 return false;
12372 V = ElseBO->getLHS();
12374 return checkType(ErrorInfo);
12377 bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12378 ErrorInfoTy &ErrorInfo) {
12379 // We don't check here as they should be already done before call this
12380 // function.
12381 auto *CS = cast<CompoundStmt>(S);
12382 assert(CS->size() == 2 && "CompoundStmt size is not expected");
12383 auto *S1 = cast<BinaryOperator>(CS->body_front());
12384 auto *S2 = cast<IfStmt>(CS->body_back());
12385 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12387 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12388 ErrorInfo.Error = ErrorTy::InvalidCondition;
12389 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12390 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12391 return false;
12394 R = S1->getLHS();
12396 auto *Then = S2->getThen();
12397 if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12398 if (ThenCS->body_empty()) {
12399 ErrorInfo.Error = ErrorTy::NoStmt;
12400 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12401 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12402 return false;
12404 if (ThenCS->size() > 1) {
12405 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12406 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12407 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12408 return false;
12410 Then = ThenCS->body_front();
12413 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12414 if (!ThenBO) {
12415 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12416 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12417 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12418 return false;
12420 if (ThenBO->getOpcode() != BO_Assign) {
12421 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12422 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12423 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12424 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12425 return false;
12428 X = ThenBO->getLHS();
12429 D = ThenBO->getRHS();
12431 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12432 if (BO->getOpcode() != BO_EQ) {
12433 ErrorInfo.Error = ErrorTy::NotEQ;
12434 ErrorInfo.ErrorLoc = BO->getExprLoc();
12435 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12436 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12437 return false;
12440 C = BO;
12442 if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) {
12443 E = BO->getRHS();
12444 } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) {
12445 E = BO->getLHS();
12446 } else {
12447 ErrorInfo.Error = ErrorTy::InvalidComparison;
12448 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12449 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12450 return false;
12453 if (S2->getElse()) {
12454 IsFailOnly = true;
12456 auto *Else = S2->getElse();
12457 if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12458 if (ElseCS->body_empty()) {
12459 ErrorInfo.Error = ErrorTy::NoStmt;
12460 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12461 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12462 return false;
12464 if (ElseCS->size() > 1) {
12465 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12466 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12467 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12468 return false;
12470 Else = ElseCS->body_front();
12473 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12474 if (!ElseBO) {
12475 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12476 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12477 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12478 return false;
12480 if (ElseBO->getOpcode() != BO_Assign) {
12481 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12482 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12483 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12484 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12485 return false;
12487 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12488 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12489 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12490 ErrorInfo.NoteLoc = X->getExprLoc();
12491 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12492 ErrorInfo.NoteRange = X->getSourceRange();
12493 return false;
12496 V = ElseBO->getLHS();
12499 return checkType(ErrorInfo);
12502 bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12503 ErrorInfoTy &ErrorInfo) {
12504 // if(x == e) { x = d; } else { v = x; }
12505 if (auto *IS = dyn_cast<IfStmt>(S))
12506 return checkForm3(IS, ErrorInfo);
12508 auto *CS = dyn_cast<CompoundStmt>(S);
12509 if (!CS) {
12510 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12511 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12512 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12513 return false;
12515 if (CS->body_empty()) {
12516 ErrorInfo.Error = ErrorTy::NoStmt;
12517 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12518 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12519 return false;
12522 // { if(x == e) { x = d; } else { v = x; } }
12523 if (CS->size() == 1) {
12524 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12525 if (!IS) {
12526 ErrorInfo.Error = ErrorTy::NotIfStmt;
12527 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12528 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12529 CS->body_front()->getSourceRange();
12530 return false;
12533 return checkForm3(IS, ErrorInfo);
12534 } else if (CS->size() == 2) {
12535 auto *S1 = CS->body_front();
12536 auto *S2 = CS->body_back();
12538 Stmt *UpdateStmt = nullptr;
12539 Stmt *CondUpdateStmt = nullptr;
12540 Stmt *CondExprStmt = nullptr;
12542 if (auto *BO = dyn_cast<BinaryOperator>(S1)) {
12543 // It could be one of the following cases:
12544 // { v = x; cond-update-stmt }
12545 // { v = x; cond-expr-stmt }
12546 // { cond-expr-stmt; v = x; }
12547 // form 45
12548 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12549 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12550 // check if form 45
12551 if (isa<IfStmt>(S2))
12552 return checkForm45(CS, ErrorInfo);
12553 // { cond-expr-stmt; v = x; }
12554 CondExprStmt = S1;
12555 UpdateStmt = S2;
12556 } else {
12557 IsPostfixUpdate = true;
12558 UpdateStmt = S1;
12559 if (isa<IfStmt>(S2)) {
12560 // { v = x; cond-update-stmt }
12561 CondUpdateStmt = S2;
12562 } else {
12563 // { v = x; cond-expr-stmt }
12564 CondExprStmt = S2;
12567 } else {
12568 // { cond-update-stmt v = x; }
12569 UpdateStmt = S2;
12570 CondUpdateStmt = S1;
12573 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12574 auto *IS = dyn_cast<IfStmt>(CUS);
12575 if (!IS) {
12576 ErrorInfo.Error = ErrorTy::NotIfStmt;
12577 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12578 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12579 return false;
12582 return checkCondUpdateStmt(IS, ErrorInfo);
12585 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12586 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12587 auto *BO = dyn_cast<BinaryOperator>(US);
12588 if (!BO) {
12589 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12590 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12591 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12592 return false;
12594 if (BO->getOpcode() != BO_Assign) {
12595 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12596 ErrorInfo.ErrorLoc = BO->getExprLoc();
12597 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12598 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12599 return false;
12601 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12602 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12603 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12604 ErrorInfo.NoteLoc = this->X->getExprLoc();
12605 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12606 ErrorInfo.NoteRange = this->X->getSourceRange();
12607 return false;
12610 this->V = BO->getLHS();
12612 return true;
12615 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12616 return false;
12617 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12618 return false;
12619 if (!CheckUpdateStmt(UpdateStmt))
12620 return false;
12621 } else {
12622 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12623 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12624 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12625 return false;
12628 return checkType(ErrorInfo);
12630 } // namespace
12632 StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
12633 Stmt *AStmt,
12634 SourceLocation StartLoc,
12635 SourceLocation EndLoc) {
12636 // Register location of the first atomic directive.
12637 DSAStack->addAtomicDirectiveLoc(StartLoc);
12638 if (!AStmt)
12639 return StmtError();
12641 // 1.2.2 OpenMP Language Terminology
12642 // Structured block - An executable statement with a single entry at the
12643 // top and a single exit at the bottom.
12644 // The point of exit cannot be a branch out of the structured block.
12645 // longjmp() and throw() must not violate the entry/exit criteria.
12646 OpenMPClauseKind AtomicKind = OMPC_unknown;
12647 SourceLocation AtomicKindLoc;
12648 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12649 SourceLocation MemOrderLoc;
12650 bool MutexClauseEncountered = false;
12651 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12652 for (const OMPClause *C : Clauses) {
12653 switch (C->getClauseKind()) {
12654 case OMPC_read:
12655 case OMPC_write:
12656 case OMPC_update:
12657 MutexClauseEncountered = true;
12658 [[fallthrough]];
12659 case OMPC_capture:
12660 case OMPC_compare: {
12661 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12662 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12663 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12664 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12665 << getOpenMPClauseName(AtomicKind);
12666 } else {
12667 AtomicKind = C->getClauseKind();
12668 AtomicKindLoc = C->getBeginLoc();
12669 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12670 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12671 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12672 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12673 << getOpenMPClauseName(AtomicKind);
12676 break;
12678 case OMPC_seq_cst:
12679 case OMPC_acq_rel:
12680 case OMPC_acquire:
12681 case OMPC_release:
12682 case OMPC_relaxed: {
12683 if (MemOrderKind != OMPC_unknown) {
12684 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12685 << getOpenMPDirectiveName(OMPD_atomic) << 0
12686 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12687 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12688 << getOpenMPClauseName(MemOrderKind);
12689 } else {
12690 MemOrderKind = C->getClauseKind();
12691 MemOrderLoc = C->getBeginLoc();
12693 break;
12695 // The following clauses are allowed, but we don't need to do anything here.
12696 case OMPC_hint:
12697 break;
12698 default:
12699 llvm_unreachable("unknown clause is encountered");
12702 bool IsCompareCapture = false;
12703 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12704 EncounteredAtomicKinds.contains(OMPC_capture)) {
12705 IsCompareCapture = true;
12706 AtomicKind = OMPC_compare;
12708 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12709 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12710 // release.
12711 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12712 // acquire.
12713 // If atomic-clause is update or not present then memory-order-clause must not
12714 // be acq_rel or acquire.
12715 if ((AtomicKind == OMPC_read &&
12716 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12717 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12718 AtomicKind == OMPC_unknown) &&
12719 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12720 SourceLocation Loc = AtomicKindLoc;
12721 if (AtomicKind == OMPC_unknown)
12722 Loc = StartLoc;
12723 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12724 << getOpenMPClauseName(AtomicKind)
12725 << (AtomicKind == OMPC_unknown ? 1 : 0)
12726 << getOpenMPClauseName(MemOrderKind);
12727 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12728 << getOpenMPClauseName(MemOrderKind);
12731 Stmt *Body = AStmt;
12732 if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12733 Body = EWC->getSubExpr();
12735 Expr *X = nullptr;
12736 Expr *V = nullptr;
12737 Expr *E = nullptr;
12738 Expr *UE = nullptr;
12739 Expr *D = nullptr;
12740 Expr *CE = nullptr;
12741 Expr *R = nullptr;
12742 bool IsXLHSInRHSPart = false;
12743 bool IsPostfixUpdate = false;
12744 bool IsFailOnly = false;
12745 // OpenMP [2.12.6, atomic Construct]
12746 // In the next expressions:
12747 // * x and v (as applicable) are both l-value expressions with scalar type.
12748 // * During the execution of an atomic region, multiple syntactic
12749 // occurrences of x must designate the same storage location.
12750 // * Neither of v and expr (as applicable) may access the storage location
12751 // designated by x.
12752 // * Neither of x and expr (as applicable) may access the storage location
12753 // designated by v.
12754 // * expr is an expression with scalar type.
12755 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12756 // * binop, binop=, ++, and -- are not overloaded operators.
12757 // * The expression x binop expr must be numerically equivalent to x binop
12758 // (expr). This requirement is satisfied if the operators in expr have
12759 // precedence greater than binop, or by using parentheses around expr or
12760 // subexpressions of expr.
12761 // * The expression expr binop x must be numerically equivalent to (expr)
12762 // binop x. This requirement is satisfied if the operators in expr have
12763 // precedence equal to or greater than binop, or by using parentheses around
12764 // expr or subexpressions of expr.
12765 // * For forms that allow multiple occurrences of x, the number of times
12766 // that x is evaluated is unspecified.
12767 if (AtomicKind == OMPC_read) {
12768 enum {
12769 NotAnExpression,
12770 NotAnAssignmentOp,
12771 NotAScalarType,
12772 NotAnLValue,
12773 NoError
12774 } ErrorFound = NoError;
12775 SourceLocation ErrorLoc, NoteLoc;
12776 SourceRange ErrorRange, NoteRange;
12777 // If clause is read:
12778 // v = x;
12779 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12780 const auto *AtomicBinOp =
12781 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12782 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12783 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12784 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12785 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12786 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12787 if (!X->isLValue() || !V->isLValue()) {
12788 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12789 ErrorFound = NotAnLValue;
12790 ErrorLoc = AtomicBinOp->getExprLoc();
12791 ErrorRange = AtomicBinOp->getSourceRange();
12792 NoteLoc = NotLValueExpr->getExprLoc();
12793 NoteRange = NotLValueExpr->getSourceRange();
12795 } else if (!X->isInstantiationDependent() ||
12796 !V->isInstantiationDependent()) {
12797 const Expr *NotScalarExpr =
12798 (X->isInstantiationDependent() || X->getType()->isScalarType())
12800 : X;
12801 ErrorFound = NotAScalarType;
12802 ErrorLoc = AtomicBinOp->getExprLoc();
12803 ErrorRange = AtomicBinOp->getSourceRange();
12804 NoteLoc = NotScalarExpr->getExprLoc();
12805 NoteRange = NotScalarExpr->getSourceRange();
12807 } else if (!AtomicBody->isInstantiationDependent()) {
12808 ErrorFound = NotAnAssignmentOp;
12809 ErrorLoc = AtomicBody->getExprLoc();
12810 ErrorRange = AtomicBody->getSourceRange();
12811 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12812 : AtomicBody->getExprLoc();
12813 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12814 : AtomicBody->getSourceRange();
12816 } else {
12817 ErrorFound = NotAnExpression;
12818 NoteLoc = ErrorLoc = Body->getBeginLoc();
12819 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12821 if (ErrorFound != NoError) {
12822 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12823 << ErrorRange;
12824 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12825 << ErrorFound << NoteRange;
12826 return StmtError();
12828 if (CurContext->isDependentContext())
12829 V = X = nullptr;
12830 } else if (AtomicKind == OMPC_write) {
12831 enum {
12832 NotAnExpression,
12833 NotAnAssignmentOp,
12834 NotAScalarType,
12835 NotAnLValue,
12836 NoError
12837 } ErrorFound = NoError;
12838 SourceLocation ErrorLoc, NoteLoc;
12839 SourceRange ErrorRange, NoteRange;
12840 // If clause is write:
12841 // x = expr;
12842 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12843 const auto *AtomicBinOp =
12844 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12845 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12846 X = AtomicBinOp->getLHS();
12847 E = AtomicBinOp->getRHS();
12848 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12849 (E->isInstantiationDependent() || E->getType()->isScalarType())) {
12850 if (!X->isLValue()) {
12851 ErrorFound = NotAnLValue;
12852 ErrorLoc = AtomicBinOp->getExprLoc();
12853 ErrorRange = AtomicBinOp->getSourceRange();
12854 NoteLoc = X->getExprLoc();
12855 NoteRange = X->getSourceRange();
12857 } else if (!X->isInstantiationDependent() ||
12858 !E->isInstantiationDependent()) {
12859 const Expr *NotScalarExpr =
12860 (X->isInstantiationDependent() || X->getType()->isScalarType())
12862 : X;
12863 ErrorFound = NotAScalarType;
12864 ErrorLoc = AtomicBinOp->getExprLoc();
12865 ErrorRange = AtomicBinOp->getSourceRange();
12866 NoteLoc = NotScalarExpr->getExprLoc();
12867 NoteRange = NotScalarExpr->getSourceRange();
12869 } else if (!AtomicBody->isInstantiationDependent()) {
12870 ErrorFound = NotAnAssignmentOp;
12871 ErrorLoc = AtomicBody->getExprLoc();
12872 ErrorRange = AtomicBody->getSourceRange();
12873 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12874 : AtomicBody->getExprLoc();
12875 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12876 : AtomicBody->getSourceRange();
12878 } else {
12879 ErrorFound = NotAnExpression;
12880 NoteLoc = ErrorLoc = Body->getBeginLoc();
12881 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12883 if (ErrorFound != NoError) {
12884 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12885 << ErrorRange;
12886 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12887 << ErrorFound << NoteRange;
12888 return StmtError();
12890 if (CurContext->isDependentContext())
12891 E = X = nullptr;
12892 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12893 // If clause is update:
12894 // x++;
12895 // x--;
12896 // ++x;
12897 // --x;
12898 // x binop= expr;
12899 // x = x binop expr;
12900 // x = expr binop x;
12901 OpenMPAtomicUpdateChecker Checker(*this);
12902 if (Checker.checkStatement(
12903 Body,
12904 (AtomicKind == OMPC_update)
12905 ? diag::err_omp_atomic_update_not_expression_statement
12906 : diag::err_omp_atomic_not_expression_statement,
12907 diag::note_omp_atomic_update))
12908 return StmtError();
12909 if (!CurContext->isDependentContext()) {
12910 E = Checker.getExpr();
12911 X = Checker.getX();
12912 UE = Checker.getUpdateExpr();
12913 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12915 } else if (AtomicKind == OMPC_capture) {
12916 enum {
12917 NotAnAssignmentOp,
12918 NotACompoundStatement,
12919 NotTwoSubstatements,
12920 NotASpecificExpression,
12921 NoError
12922 } ErrorFound = NoError;
12923 SourceLocation ErrorLoc, NoteLoc;
12924 SourceRange ErrorRange, NoteRange;
12925 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12926 // If clause is a capture:
12927 // v = x++;
12928 // v = x--;
12929 // v = ++x;
12930 // v = --x;
12931 // v = x binop= expr;
12932 // v = x = x binop expr;
12933 // v = x = expr binop x;
12934 const auto *AtomicBinOp =
12935 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12936 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12937 V = AtomicBinOp->getLHS();
12938 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12939 OpenMPAtomicUpdateChecker Checker(*this);
12940 if (Checker.checkStatement(
12941 Body, diag::err_omp_atomic_capture_not_expression_statement,
12942 diag::note_omp_atomic_update))
12943 return StmtError();
12944 E = Checker.getExpr();
12945 X = Checker.getX();
12946 UE = Checker.getUpdateExpr();
12947 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12948 IsPostfixUpdate = Checker.isPostfixUpdate();
12949 } else if (!AtomicBody->isInstantiationDependent()) {
12950 ErrorLoc = AtomicBody->getExprLoc();
12951 ErrorRange = AtomicBody->getSourceRange();
12952 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12953 : AtomicBody->getExprLoc();
12954 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12955 : AtomicBody->getSourceRange();
12956 ErrorFound = NotAnAssignmentOp;
12958 if (ErrorFound != NoError) {
12959 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
12960 << ErrorRange;
12961 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12962 return StmtError();
12964 if (CurContext->isDependentContext())
12965 UE = V = E = X = nullptr;
12966 } else {
12967 // If clause is a capture:
12968 // { v = x; x = expr; }
12969 // { v = x; x++; }
12970 // { v = x; x--; }
12971 // { v = x; ++x; }
12972 // { v = x; --x; }
12973 // { v = x; x binop= expr; }
12974 // { v = x; x = x binop expr; }
12975 // { v = x; x = expr binop x; }
12976 // { x++; v = x; }
12977 // { x--; v = x; }
12978 // { ++x; v = x; }
12979 // { --x; v = x; }
12980 // { x binop= expr; v = x; }
12981 // { x = x binop expr; v = x; }
12982 // { x = expr binop x; v = x; }
12983 if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
12984 // Check that this is { expr1; expr2; }
12985 if (CS->size() == 2) {
12986 Stmt *First = CS->body_front();
12987 Stmt *Second = CS->body_back();
12988 if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
12989 First = EWC->getSubExpr()->IgnoreParenImpCasts();
12990 if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
12991 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
12992 // Need to find what subexpression is 'v' and what is 'x'.
12993 OpenMPAtomicUpdateChecker Checker(*this);
12994 bool IsUpdateExprFound = !Checker.checkStatement(Second);
12995 BinaryOperator *BinOp = nullptr;
12996 if (IsUpdateExprFound) {
12997 BinOp = dyn_cast<BinaryOperator>(First);
12998 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13000 if (IsUpdateExprFound && !CurContext->isDependentContext()) {
13001 // { v = x; x++; }
13002 // { v = x; x--; }
13003 // { v = x; ++x; }
13004 // { v = x; --x; }
13005 // { v = x; x binop= expr; }
13006 // { v = x; x = x binop expr; }
13007 // { v = x; x = expr binop x; }
13008 // Check that the first expression has form v = x.
13009 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13010 llvm::FoldingSetNodeID XId, PossibleXId;
13011 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13012 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13013 IsUpdateExprFound = XId == PossibleXId;
13014 if (IsUpdateExprFound) {
13015 V = BinOp->getLHS();
13016 X = Checker.getX();
13017 E = Checker.getExpr();
13018 UE = Checker.getUpdateExpr();
13019 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13020 IsPostfixUpdate = true;
13023 if (!IsUpdateExprFound) {
13024 IsUpdateExprFound = !Checker.checkStatement(First);
13025 BinOp = nullptr;
13026 if (IsUpdateExprFound) {
13027 BinOp = dyn_cast<BinaryOperator>(Second);
13028 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13030 if (IsUpdateExprFound && !CurContext->isDependentContext()) {
13031 // { x++; v = x; }
13032 // { x--; v = x; }
13033 // { ++x; v = x; }
13034 // { --x; v = x; }
13035 // { x binop= expr; v = x; }
13036 // { x = x binop expr; v = x; }
13037 // { x = expr binop x; v = x; }
13038 // Check that the second expression has form v = x.
13039 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13040 llvm::FoldingSetNodeID XId, PossibleXId;
13041 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13042 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13043 IsUpdateExprFound = XId == PossibleXId;
13044 if (IsUpdateExprFound) {
13045 V = BinOp->getLHS();
13046 X = Checker.getX();
13047 E = Checker.getExpr();
13048 UE = Checker.getUpdateExpr();
13049 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13050 IsPostfixUpdate = false;
13054 if (!IsUpdateExprFound) {
13055 // { v = x; x = expr; }
13056 auto *FirstExpr = dyn_cast<Expr>(First);
13057 auto *SecondExpr = dyn_cast<Expr>(Second);
13058 if (!FirstExpr || !SecondExpr ||
13059 !(FirstExpr->isInstantiationDependent() ||
13060 SecondExpr->isInstantiationDependent())) {
13061 auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
13062 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
13063 ErrorFound = NotAnAssignmentOp;
13064 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
13065 : First->getBeginLoc();
13066 NoteRange = ErrorRange = FirstBinOp
13067 ? FirstBinOp->getSourceRange()
13068 : SourceRange(ErrorLoc, ErrorLoc);
13069 } else {
13070 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
13071 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
13072 ErrorFound = NotAnAssignmentOp;
13073 NoteLoc = ErrorLoc = SecondBinOp
13074 ? SecondBinOp->getOperatorLoc()
13075 : Second->getBeginLoc();
13076 NoteRange = ErrorRange =
13077 SecondBinOp ? SecondBinOp->getSourceRange()
13078 : SourceRange(ErrorLoc, ErrorLoc);
13079 } else {
13080 Expr *PossibleXRHSInFirst =
13081 FirstBinOp->getRHS()->IgnoreParenImpCasts();
13082 Expr *PossibleXLHSInSecond =
13083 SecondBinOp->getLHS()->IgnoreParenImpCasts();
13084 llvm::FoldingSetNodeID X1Id, X2Id;
13085 PossibleXRHSInFirst->Profile(X1Id, Context,
13086 /*Canonical=*/true);
13087 PossibleXLHSInSecond->Profile(X2Id, Context,
13088 /*Canonical=*/true);
13089 IsUpdateExprFound = X1Id == X2Id;
13090 if (IsUpdateExprFound) {
13091 V = FirstBinOp->getLHS();
13092 X = SecondBinOp->getLHS();
13093 E = SecondBinOp->getRHS();
13094 UE = nullptr;
13095 IsXLHSInRHSPart = false;
13096 IsPostfixUpdate = true;
13097 } else {
13098 ErrorFound = NotASpecificExpression;
13099 ErrorLoc = FirstBinOp->getExprLoc();
13100 ErrorRange = FirstBinOp->getSourceRange();
13101 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
13102 NoteRange = SecondBinOp->getRHS()->getSourceRange();
13108 } else {
13109 NoteLoc = ErrorLoc = Body->getBeginLoc();
13110 NoteRange = ErrorRange =
13111 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13112 ErrorFound = NotTwoSubstatements;
13114 } else {
13115 NoteLoc = ErrorLoc = Body->getBeginLoc();
13116 NoteRange = ErrorRange =
13117 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13118 ErrorFound = NotACompoundStatement;
13121 if (ErrorFound != NoError) {
13122 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
13123 << ErrorRange;
13124 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13125 return StmtError();
13127 if (CurContext->isDependentContext())
13128 UE = V = E = X = nullptr;
13129 } else if (AtomicKind == OMPC_compare) {
13130 if (IsCompareCapture) {
13131 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
13132 OpenMPAtomicCompareCaptureChecker Checker(*this);
13133 if (!Checker.checkStmt(Body, ErrorInfo)) {
13134 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
13135 << ErrorInfo.ErrorRange;
13136 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13137 << ErrorInfo.Error << ErrorInfo.NoteRange;
13138 return StmtError();
13140 X = Checker.getX();
13141 E = Checker.getE();
13142 D = Checker.getD();
13143 CE = Checker.getCond();
13144 V = Checker.getV();
13145 R = Checker.getR();
13146 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13147 IsXLHSInRHSPart = Checker.isXBinopExpr();
13148 IsFailOnly = Checker.isFailOnly();
13149 IsPostfixUpdate = Checker.isPostfixUpdate();
13150 } else {
13151 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
13152 OpenMPAtomicCompareChecker Checker(*this);
13153 if (!Checker.checkStmt(Body, ErrorInfo)) {
13154 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
13155 << ErrorInfo.ErrorRange;
13156 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13157 << ErrorInfo.Error << ErrorInfo.NoteRange;
13158 return StmtError();
13160 X = Checker.getX();
13161 E = Checker.getE();
13162 D = Checker.getD();
13163 CE = Checker.getCond();
13164 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13165 IsXLHSInRHSPart = Checker.isXBinopExpr();
13169 setFunctionHasBranchProtectedScope();
13171 return OMPAtomicDirective::Create(
13172 Context, StartLoc, EndLoc, Clauses, AStmt,
13173 {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
13176 StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
13177 Stmt *AStmt,
13178 SourceLocation StartLoc,
13179 SourceLocation EndLoc) {
13180 if (!AStmt)
13181 return StmtError();
13183 auto *CS = cast<CapturedStmt>(AStmt);
13184 // 1.2.2 OpenMP Language Terminology
13185 // Structured block - An executable statement with a single entry at the
13186 // top and a single exit at the bottom.
13187 // The point of exit cannot be a branch out of the structured block.
13188 // longjmp() and throw() must not violate the entry/exit criteria.
13189 CS->getCapturedDecl()->setNothrow();
13190 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target);
13191 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13192 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13193 // 1.2.2 OpenMP Language Terminology
13194 // Structured block - An executable statement with a single entry at the
13195 // top and a single exit at the bottom.
13196 // The point of exit cannot be a branch out of the structured block.
13197 // longjmp() and throw() must not violate the entry/exit criteria.
13198 CS->getCapturedDecl()->setNothrow();
13201 // OpenMP [2.16, Nesting of Regions]
13202 // If specified, a teams construct must be contained within a target
13203 // construct. That target construct must contain no statements or directives
13204 // outside of the teams construct.
13205 if (DSAStack->hasInnerTeamsRegion()) {
13206 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
13207 bool OMPTeamsFound = true;
13208 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
13209 auto I = CS->body_begin();
13210 while (I != CS->body_end()) {
13211 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
13212 if (!OED || !isOpenMPTeamsDirective(OED->getDirectiveKind()) ||
13213 OMPTeamsFound) {
13215 OMPTeamsFound = false;
13216 break;
13218 ++I;
13220 assert(I != CS->body_end() && "Not found statement");
13221 S = *I;
13222 } else {
13223 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
13224 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13226 if (!OMPTeamsFound) {
13227 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
13228 Diag(DSAStack->getInnerTeamsRegionLoc(),
13229 diag::note_omp_nested_teams_construct_here);
13230 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
13231 << isa<OMPExecutableDirective>(S);
13232 return StmtError();
13236 setFunctionHasBranchProtectedScope();
13238 return OMPTargetDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
13241 StmtResult
13242 Sema::ActOnOpenMPTargetParallelDirective(ArrayRef<OMPClause *> Clauses,
13243 Stmt *AStmt, SourceLocation StartLoc,
13244 SourceLocation EndLoc) {
13245 if (!AStmt)
13246 return StmtError();
13248 auto *CS = cast<CapturedStmt>(AStmt);
13249 // 1.2.2 OpenMP Language Terminology
13250 // Structured block - An executable statement with a single entry at the
13251 // top and a single exit at the bottom.
13252 // The point of exit cannot be a branch out of the structured block.
13253 // longjmp() and throw() must not violate the entry/exit criteria.
13254 CS->getCapturedDecl()->setNothrow();
13255 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel);
13256 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13257 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13258 // 1.2.2 OpenMP Language Terminology
13259 // Structured block - An executable statement with a single entry at the
13260 // top and a single exit at the bottom.
13261 // The point of exit cannot be a branch out of the structured block.
13262 // longjmp() and throw() must not violate the entry/exit criteria.
13263 CS->getCapturedDecl()->setNothrow();
13266 setFunctionHasBranchProtectedScope();
13268 return OMPTargetParallelDirective::Create(
13269 Context, StartLoc, EndLoc, Clauses, AStmt,
13270 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13273 StmtResult Sema::ActOnOpenMPTargetParallelForDirective(
13274 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13275 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13276 if (!AStmt)
13277 return StmtError();
13279 auto *CS = cast<CapturedStmt>(AStmt);
13280 // 1.2.2 OpenMP Language Terminology
13281 // Structured block - An executable statement with a single entry at the
13282 // top and a single exit at the bottom.
13283 // The point of exit cannot be a branch out of the structured block.
13284 // longjmp() and throw() must not violate the entry/exit criteria.
13285 CS->getCapturedDecl()->setNothrow();
13286 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_for);
13287 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13288 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13289 // 1.2.2 OpenMP Language Terminology
13290 // Structured block - An executable statement with a single entry at the
13291 // top and a single exit at the bottom.
13292 // The point of exit cannot be a branch out of the structured block.
13293 // longjmp() and throw() must not violate the entry/exit criteria.
13294 CS->getCapturedDecl()->setNothrow();
13297 OMPLoopBasedDirective::HelperExprs B;
13298 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13299 // define the nested loops number.
13300 unsigned NestedLoopCount =
13301 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
13302 getOrderedNumberExpr(Clauses), CS, *this, *DSAStack,
13303 VarsWithImplicitDSA, B);
13304 if (NestedLoopCount == 0)
13305 return StmtError();
13307 assert((CurContext->isDependentContext() || B.builtAll()) &&
13308 "omp target parallel for loop exprs were not built");
13310 if (!CurContext->isDependentContext()) {
13311 // Finalize the clauses that need pre-built expressions for CodeGen.
13312 for (OMPClause *C : Clauses) {
13313 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13314 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13315 B.NumIterations, *this, CurScope,
13316 DSAStack))
13317 return StmtError();
13321 setFunctionHasBranchProtectedScope();
13322 return OMPTargetParallelForDirective::Create(
13323 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13324 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13327 /// Check for existence of a map clause in the list of clauses.
13328 static bool hasClauses(ArrayRef<OMPClause *> Clauses,
13329 const OpenMPClauseKind K) {
13330 return llvm::any_of(
13331 Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
13334 template <typename... Params>
13335 static bool hasClauses(ArrayRef<OMPClause *> Clauses, const OpenMPClauseKind K,
13336 const Params... ClauseTypes) {
13337 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13340 /// Check if the variables in the mapping clause are externally visible.
13341 static bool isClauseMappable(ArrayRef<OMPClause *> Clauses) {
13342 for (const OMPClause *C : Clauses) {
13343 if (auto *TC = dyn_cast<OMPToClause>(C))
13344 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
13345 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13346 (VD->isExternallyVisible() &&
13347 VD->getVisibility() != HiddenVisibility);
13349 else if (auto *FC = dyn_cast<OMPFromClause>(C))
13350 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
13351 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13352 (VD->isExternallyVisible() &&
13353 VD->getVisibility() != HiddenVisibility);
13357 return true;
13360 StmtResult Sema::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
13361 Stmt *AStmt,
13362 SourceLocation StartLoc,
13363 SourceLocation EndLoc) {
13364 if (!AStmt)
13365 return StmtError();
13367 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13369 // OpenMP [2.12.2, target data Construct, Restrictions]
13370 // At least one map, use_device_addr or use_device_ptr clause must appear on
13371 // the directive.
13372 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13373 (LangOpts.OpenMP < 50 || !hasClauses(Clauses, OMPC_use_device_addr))) {
13374 StringRef Expected;
13375 if (LangOpts.OpenMP < 50)
13376 Expected = "'map' or 'use_device_ptr'";
13377 else
13378 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13379 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13380 << Expected << getOpenMPDirectiveName(OMPD_target_data);
13381 return StmtError();
13384 setFunctionHasBranchProtectedScope();
13386 return OMPTargetDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
13387 AStmt);
13390 StmtResult
13391 Sema::ActOnOpenMPTargetEnterDataDirective(ArrayRef<OMPClause *> Clauses,
13392 SourceLocation StartLoc,
13393 SourceLocation EndLoc, Stmt *AStmt) {
13394 if (!AStmt)
13395 return StmtError();
13397 auto *CS = cast<CapturedStmt>(AStmt);
13398 // 1.2.2 OpenMP Language Terminology
13399 // Structured block - An executable statement with a single entry at the
13400 // top and a single exit at the bottom.
13401 // The point of exit cannot be a branch out of the structured block.
13402 // longjmp() and throw() must not violate the entry/exit criteria.
13403 CS->getCapturedDecl()->setNothrow();
13404 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_enter_data);
13405 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13406 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13407 // 1.2.2 OpenMP Language Terminology
13408 // Structured block - An executable statement with a single entry at the
13409 // top and a single exit at the bottom.
13410 // The point of exit cannot be a branch out of the structured block.
13411 // longjmp() and throw() must not violate the entry/exit criteria.
13412 CS->getCapturedDecl()->setNothrow();
13415 // OpenMP [2.10.2, Restrictions, p. 99]
13416 // At least one map clause must appear on the directive.
13417 if (!hasClauses(Clauses, OMPC_map)) {
13418 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13419 << "'map'" << getOpenMPDirectiveName(OMPD_target_enter_data);
13420 return StmtError();
13423 return OMPTargetEnterDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
13424 AStmt);
13427 StmtResult
13428 Sema::ActOnOpenMPTargetExitDataDirective(ArrayRef<OMPClause *> Clauses,
13429 SourceLocation StartLoc,
13430 SourceLocation EndLoc, Stmt *AStmt) {
13431 if (!AStmt)
13432 return StmtError();
13434 auto *CS = cast<CapturedStmt>(AStmt);
13435 // 1.2.2 OpenMP Language Terminology
13436 // Structured block - An executable statement with a single entry at the
13437 // top and a single exit at the bottom.
13438 // The point of exit cannot be a branch out of the structured block.
13439 // longjmp() and throw() must not violate the entry/exit criteria.
13440 CS->getCapturedDecl()->setNothrow();
13441 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_exit_data);
13442 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13443 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13444 // 1.2.2 OpenMP Language Terminology
13445 // Structured block - An executable statement with a single entry at the
13446 // top and a single exit at the bottom.
13447 // The point of exit cannot be a branch out of the structured block.
13448 // longjmp() and throw() must not violate the entry/exit criteria.
13449 CS->getCapturedDecl()->setNothrow();
13452 // OpenMP [2.10.3, Restrictions, p. 102]
13453 // At least one map clause must appear on the directive.
13454 if (!hasClauses(Clauses, OMPC_map)) {
13455 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13456 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data);
13457 return StmtError();
13460 return OMPTargetExitDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
13461 AStmt);
13464 StmtResult Sema::ActOnOpenMPTargetUpdateDirective(ArrayRef<OMPClause *> Clauses,
13465 SourceLocation StartLoc,
13466 SourceLocation EndLoc,
13467 Stmt *AStmt) {
13468 if (!AStmt)
13469 return StmtError();
13471 auto *CS = cast<CapturedStmt>(AStmt);
13472 // 1.2.2 OpenMP Language Terminology
13473 // Structured block - An executable statement with a single entry at the
13474 // top and a single exit at the bottom.
13475 // The point of exit cannot be a branch out of the structured block.
13476 // longjmp() and throw() must not violate the entry/exit criteria.
13477 CS->getCapturedDecl()->setNothrow();
13478 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_update);
13479 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13480 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13481 // 1.2.2 OpenMP Language Terminology
13482 // Structured block - An executable statement with a single entry at the
13483 // top and a single exit at the bottom.
13484 // The point of exit cannot be a branch out of the structured block.
13485 // longjmp() and throw() must not violate the entry/exit criteria.
13486 CS->getCapturedDecl()->setNothrow();
13489 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
13490 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13491 return StmtError();
13494 if (!isClauseMappable(Clauses)) {
13495 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13496 return StmtError();
13499 return OMPTargetUpdateDirective::Create(Context, StartLoc, EndLoc, Clauses,
13500 AStmt);
13503 StmtResult Sema::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
13504 Stmt *AStmt, SourceLocation StartLoc,
13505 SourceLocation EndLoc) {
13506 if (!AStmt)
13507 return StmtError();
13509 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13510 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13511 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13513 auto *CS = cast<CapturedStmt>(AStmt);
13514 // 1.2.2 OpenMP Language Terminology
13515 // Structured block - An executable statement with a single entry at the
13516 // top and a single exit at the bottom.
13517 // The point of exit cannot be a branch out of the structured block.
13518 // longjmp() and throw() must not violate the entry/exit criteria.
13519 CS->getCapturedDecl()->setNothrow();
13521 setFunctionHasBranchProtectedScope();
13523 DSAStack->setParentTeamsRegionLoc(StartLoc);
13525 return OMPTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
13528 StmtResult
13529 Sema::ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc,
13530 SourceLocation EndLoc,
13531 OpenMPDirectiveKind CancelRegion) {
13532 if (DSAStack->isParentNowaitRegion()) {
13533 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13534 return StmtError();
13536 if (DSAStack->isParentOrderedRegion()) {
13537 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13538 return StmtError();
13540 return OMPCancellationPointDirective::Create(Context, StartLoc, EndLoc,
13541 CancelRegion);
13544 StmtResult Sema::ActOnOpenMPCancelDirective(ArrayRef<OMPClause *> Clauses,
13545 SourceLocation StartLoc,
13546 SourceLocation EndLoc,
13547 OpenMPDirectiveKind CancelRegion) {
13548 if (DSAStack->isParentNowaitRegion()) {
13549 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13550 return StmtError();
13552 if (DSAStack->isParentOrderedRegion()) {
13553 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13554 return StmtError();
13556 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13557 return OMPCancelDirective::Create(Context, StartLoc, EndLoc, Clauses,
13558 CancelRegion);
13561 static bool checkReductionClauseWithNogroup(Sema &S,
13562 ArrayRef<OMPClause *> Clauses) {
13563 const OMPClause *ReductionClause = nullptr;
13564 const OMPClause *NogroupClause = nullptr;
13565 for (const OMPClause *C : Clauses) {
13566 if (C->getClauseKind() == OMPC_reduction) {
13567 ReductionClause = C;
13568 if (NogroupClause)
13569 break;
13570 continue;
13572 if (C->getClauseKind() == OMPC_nogroup) {
13573 NogroupClause = C;
13574 if (ReductionClause)
13575 break;
13576 continue;
13579 if (ReductionClause && NogroupClause) {
13580 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13581 << SourceRange(NogroupClause->getBeginLoc(),
13582 NogroupClause->getEndLoc());
13583 return true;
13585 return false;
13588 StmtResult Sema::ActOnOpenMPTaskLoopDirective(
13589 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13590 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13591 if (!AStmt)
13592 return StmtError();
13594 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13595 OMPLoopBasedDirective::HelperExprs B;
13596 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13597 // define the nested loops number.
13598 unsigned NestedLoopCount =
13599 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13600 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13601 VarsWithImplicitDSA, B);
13602 if (NestedLoopCount == 0)
13603 return StmtError();
13605 assert((CurContext->isDependentContext() || B.builtAll()) &&
13606 "omp for loop exprs were not built");
13608 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13609 // The grainsize clause and num_tasks clause are mutually exclusive and may
13610 // not appear on the same taskloop directive.
13611 if (checkMutuallyExclusiveClauses(*this, Clauses,
13612 {OMPC_grainsize, OMPC_num_tasks}))
13613 return StmtError();
13614 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13615 // If a reduction clause is present on the taskloop directive, the nogroup
13616 // clause must not be specified.
13617 if (checkReductionClauseWithNogroup(*this, Clauses))
13618 return StmtError();
13620 setFunctionHasBranchProtectedScope();
13621 return OMPTaskLoopDirective::Create(Context, StartLoc, EndLoc,
13622 NestedLoopCount, Clauses, AStmt, B,
13623 DSAStack->isCancelRegion());
13626 StmtResult Sema::ActOnOpenMPTaskLoopSimdDirective(
13627 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13628 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13629 if (!AStmt)
13630 return StmtError();
13632 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13633 OMPLoopBasedDirective::HelperExprs B;
13634 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13635 // define the nested loops number.
13636 unsigned NestedLoopCount =
13637 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13638 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13639 VarsWithImplicitDSA, B);
13640 if (NestedLoopCount == 0)
13641 return StmtError();
13643 assert((CurContext->isDependentContext() || B.builtAll()) &&
13644 "omp for loop exprs were not built");
13646 if (!CurContext->isDependentContext()) {
13647 // Finalize the clauses that need pre-built expressions for CodeGen.
13648 for (OMPClause *C : Clauses) {
13649 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13650 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13651 B.NumIterations, *this, CurScope,
13652 DSAStack))
13653 return StmtError();
13657 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13658 // The grainsize clause and num_tasks clause are mutually exclusive and may
13659 // not appear on the same taskloop directive.
13660 if (checkMutuallyExclusiveClauses(*this, Clauses,
13661 {OMPC_grainsize, OMPC_num_tasks}))
13662 return StmtError();
13663 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13664 // If a reduction clause is present on the taskloop directive, the nogroup
13665 // clause must not be specified.
13666 if (checkReductionClauseWithNogroup(*this, Clauses))
13667 return StmtError();
13668 if (checkSimdlenSafelenSpecified(*this, Clauses))
13669 return StmtError();
13671 setFunctionHasBranchProtectedScope();
13672 return OMPTaskLoopSimdDirective::Create(Context, StartLoc, EndLoc,
13673 NestedLoopCount, Clauses, AStmt, B);
13676 StmtResult Sema::ActOnOpenMPMasterTaskLoopDirective(
13677 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13678 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13679 if (!AStmt)
13680 return StmtError();
13682 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13683 OMPLoopBasedDirective::HelperExprs B;
13684 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13685 // define the nested loops number.
13686 unsigned NestedLoopCount =
13687 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13688 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13689 VarsWithImplicitDSA, B);
13690 if (NestedLoopCount == 0)
13691 return StmtError();
13693 assert((CurContext->isDependentContext() || B.builtAll()) &&
13694 "omp for loop exprs were not built");
13696 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13697 // The grainsize clause and num_tasks clause are mutually exclusive and may
13698 // not appear on the same taskloop directive.
13699 if (checkMutuallyExclusiveClauses(*this, Clauses,
13700 {OMPC_grainsize, OMPC_num_tasks}))
13701 return StmtError();
13702 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13703 // If a reduction clause is present on the taskloop directive, the nogroup
13704 // clause must not be specified.
13705 if (checkReductionClauseWithNogroup(*this, Clauses))
13706 return StmtError();
13708 setFunctionHasBranchProtectedScope();
13709 return OMPMasterTaskLoopDirective::Create(Context, StartLoc, EndLoc,
13710 NestedLoopCount, Clauses, AStmt, B,
13711 DSAStack->isCancelRegion());
13714 StmtResult Sema::ActOnOpenMPMaskedTaskLoopDirective(
13715 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13716 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13717 if (!AStmt)
13718 return StmtError();
13720 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13721 OMPLoopBasedDirective::HelperExprs B;
13722 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13723 // define the nested loops number.
13724 unsigned NestedLoopCount =
13725 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13726 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13727 VarsWithImplicitDSA, B);
13728 if (NestedLoopCount == 0)
13729 return StmtError();
13731 assert((CurContext->isDependentContext() || B.builtAll()) &&
13732 "omp for loop exprs were not built");
13734 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13735 // The grainsize clause and num_tasks clause are mutually exclusive and may
13736 // not appear on the same taskloop directive.
13737 if (checkMutuallyExclusiveClauses(*this, Clauses,
13738 {OMPC_grainsize, OMPC_num_tasks}))
13739 return StmtError();
13740 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13741 // If a reduction clause is present on the taskloop directive, the nogroup
13742 // clause must not be specified.
13743 if (checkReductionClauseWithNogroup(*this, Clauses))
13744 return StmtError();
13746 setFunctionHasBranchProtectedScope();
13747 return OMPMaskedTaskLoopDirective::Create(Context, StartLoc, EndLoc,
13748 NestedLoopCount, Clauses, AStmt, B,
13749 DSAStack->isCancelRegion());
13752 StmtResult Sema::ActOnOpenMPMasterTaskLoopSimdDirective(
13753 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13754 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13755 if (!AStmt)
13756 return StmtError();
13758 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13759 OMPLoopBasedDirective::HelperExprs B;
13760 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13761 // define the nested loops number.
13762 unsigned NestedLoopCount =
13763 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13764 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13765 VarsWithImplicitDSA, B);
13766 if (NestedLoopCount == 0)
13767 return StmtError();
13769 assert((CurContext->isDependentContext() || B.builtAll()) &&
13770 "omp for loop exprs were not built");
13772 if (!CurContext->isDependentContext()) {
13773 // Finalize the clauses that need pre-built expressions for CodeGen.
13774 for (OMPClause *C : Clauses) {
13775 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13776 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13777 B.NumIterations, *this, CurScope,
13778 DSAStack))
13779 return StmtError();
13783 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13784 // The grainsize clause and num_tasks clause are mutually exclusive and may
13785 // not appear on the same taskloop directive.
13786 if (checkMutuallyExclusiveClauses(*this, Clauses,
13787 {OMPC_grainsize, OMPC_num_tasks}))
13788 return StmtError();
13789 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13790 // If a reduction clause is present on the taskloop directive, the nogroup
13791 // clause must not be specified.
13792 if (checkReductionClauseWithNogroup(*this, Clauses))
13793 return StmtError();
13794 if (checkSimdlenSafelenSpecified(*this, Clauses))
13795 return StmtError();
13797 setFunctionHasBranchProtectedScope();
13798 return OMPMasterTaskLoopSimdDirective::Create(
13799 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13802 StmtResult Sema::ActOnOpenMPMaskedTaskLoopSimdDirective(
13803 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13804 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13805 if (!AStmt)
13806 return StmtError();
13808 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13809 OMPLoopBasedDirective::HelperExprs B;
13810 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13811 // define the nested loops number.
13812 unsigned NestedLoopCount =
13813 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13814 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13815 VarsWithImplicitDSA, B);
13816 if (NestedLoopCount == 0)
13817 return StmtError();
13819 assert((CurContext->isDependentContext() || B.builtAll()) &&
13820 "omp for loop exprs were not built");
13822 if (!CurContext->isDependentContext()) {
13823 // Finalize the clauses that need pre-built expressions for CodeGen.
13824 for (OMPClause *C : Clauses) {
13825 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13826 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13827 B.NumIterations, *this, CurScope,
13828 DSAStack))
13829 return StmtError();
13833 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13834 // The grainsize clause and num_tasks clause are mutually exclusive and may
13835 // not appear on the same taskloop directive.
13836 if (checkMutuallyExclusiveClauses(*this, Clauses,
13837 {OMPC_grainsize, OMPC_num_tasks}))
13838 return StmtError();
13839 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13840 // If a reduction clause is present on the taskloop directive, the nogroup
13841 // clause must not be specified.
13842 if (checkReductionClauseWithNogroup(*this, Clauses))
13843 return StmtError();
13844 if (checkSimdlenSafelenSpecified(*this, Clauses))
13845 return StmtError();
13847 setFunctionHasBranchProtectedScope();
13848 return OMPMaskedTaskLoopSimdDirective::Create(
13849 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13852 StmtResult Sema::ActOnOpenMPParallelMasterTaskLoopDirective(
13853 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13854 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13855 if (!AStmt)
13856 return StmtError();
13858 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13859 auto *CS = cast<CapturedStmt>(AStmt);
13860 // 1.2.2 OpenMP Language Terminology
13861 // Structured block - An executable statement with a single entry at the
13862 // top and a single exit at the bottom.
13863 // The point of exit cannot be a branch out of the structured block.
13864 // longjmp() and throw() must not violate the entry/exit criteria.
13865 CS->getCapturedDecl()->setNothrow();
13866 for (int ThisCaptureLevel =
13867 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop);
13868 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13869 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13870 // 1.2.2 OpenMP Language Terminology
13871 // Structured block - An executable statement with a single entry at the
13872 // top and a single exit at the bottom.
13873 // The point of exit cannot be a branch out of the structured block.
13874 // longjmp() and throw() must not violate the entry/exit criteria.
13875 CS->getCapturedDecl()->setNothrow();
13878 OMPLoopBasedDirective::HelperExprs B;
13879 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13880 // define the nested loops number.
13881 unsigned NestedLoopCount = checkOpenMPLoop(
13882 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
13883 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
13884 VarsWithImplicitDSA, B);
13885 if (NestedLoopCount == 0)
13886 return StmtError();
13888 assert((CurContext->isDependentContext() || B.builtAll()) &&
13889 "omp for loop exprs were not built");
13891 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13892 // The grainsize clause and num_tasks clause are mutually exclusive and may
13893 // not appear on the same taskloop directive.
13894 if (checkMutuallyExclusiveClauses(*this, Clauses,
13895 {OMPC_grainsize, OMPC_num_tasks}))
13896 return StmtError();
13897 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13898 // If a reduction clause is present on the taskloop directive, the nogroup
13899 // clause must not be specified.
13900 if (checkReductionClauseWithNogroup(*this, Clauses))
13901 return StmtError();
13903 setFunctionHasBranchProtectedScope();
13904 return OMPParallelMasterTaskLoopDirective::Create(
13905 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13906 DSAStack->isCancelRegion());
13909 StmtResult Sema::ActOnOpenMPParallelMaskedTaskLoopDirective(
13910 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13911 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13912 if (!AStmt)
13913 return StmtError();
13915 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13916 auto *CS = cast<CapturedStmt>(AStmt);
13917 // 1.2.2 OpenMP Language Terminology
13918 // Structured block - An executable statement with a single entry at the
13919 // top and a single exit at the bottom.
13920 // The point of exit cannot be a branch out of the structured block.
13921 // longjmp() and throw() must not violate the entry/exit criteria.
13922 CS->getCapturedDecl()->setNothrow();
13923 for (int ThisCaptureLevel =
13924 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop);
13925 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13926 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13927 // 1.2.2 OpenMP Language Terminology
13928 // Structured block - An executable statement with a single entry at the
13929 // top and a single exit at the bottom.
13930 // The point of exit cannot be a branch out of the structured block.
13931 // longjmp() and throw() must not violate the entry/exit criteria.
13932 CS->getCapturedDecl()->setNothrow();
13935 OMPLoopBasedDirective::HelperExprs B;
13936 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13937 // define the nested loops number.
13938 unsigned NestedLoopCount = checkOpenMPLoop(
13939 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
13940 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
13941 VarsWithImplicitDSA, B);
13942 if (NestedLoopCount == 0)
13943 return StmtError();
13945 assert((CurContext->isDependentContext() || B.builtAll()) &&
13946 "omp for loop exprs were not built");
13948 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13949 // The grainsize clause and num_tasks clause are mutually exclusive and may
13950 // not appear on the same taskloop directive.
13951 if (checkMutuallyExclusiveClauses(*this, Clauses,
13952 {OMPC_grainsize, OMPC_num_tasks}))
13953 return StmtError();
13954 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13955 // If a reduction clause is present on the taskloop directive, the nogroup
13956 // clause must not be specified.
13957 if (checkReductionClauseWithNogroup(*this, Clauses))
13958 return StmtError();
13960 setFunctionHasBranchProtectedScope();
13961 return OMPParallelMaskedTaskLoopDirective::Create(
13962 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13963 DSAStack->isCancelRegion());
13966 StmtResult Sema::ActOnOpenMPParallelMasterTaskLoopSimdDirective(
13967 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13968 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13969 if (!AStmt)
13970 return StmtError();
13972 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13973 auto *CS = cast<CapturedStmt>(AStmt);
13974 // 1.2.2 OpenMP Language Terminology
13975 // Structured block - An executable statement with a single entry at the
13976 // top and a single exit at the bottom.
13977 // The point of exit cannot be a branch out of the structured block.
13978 // longjmp() and throw() must not violate the entry/exit criteria.
13979 CS->getCapturedDecl()->setNothrow();
13980 for (int ThisCaptureLevel =
13981 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop_simd);
13982 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13983 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13984 // 1.2.2 OpenMP Language Terminology
13985 // Structured block - An executable statement with a single entry at the
13986 // top and a single exit at the bottom.
13987 // The point of exit cannot be a branch out of the structured block.
13988 // longjmp() and throw() must not violate the entry/exit criteria.
13989 CS->getCapturedDecl()->setNothrow();
13992 OMPLoopBasedDirective::HelperExprs B;
13993 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13994 // define the nested loops number.
13995 unsigned NestedLoopCount = checkOpenMPLoop(
13996 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13997 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
13998 VarsWithImplicitDSA, B);
13999 if (NestedLoopCount == 0)
14000 return StmtError();
14002 assert((CurContext->isDependentContext() || B.builtAll()) &&
14003 "omp for loop exprs were not built");
14005 if (!CurContext->isDependentContext()) {
14006 // Finalize the clauses that need pre-built expressions for CodeGen.
14007 for (OMPClause *C : Clauses) {
14008 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14009 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14010 B.NumIterations, *this, CurScope,
14011 DSAStack))
14012 return StmtError();
14016 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14017 // The grainsize clause and num_tasks clause are mutually exclusive and may
14018 // not appear on the same taskloop directive.
14019 if (checkMutuallyExclusiveClauses(*this, Clauses,
14020 {OMPC_grainsize, OMPC_num_tasks}))
14021 return StmtError();
14022 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14023 // If a reduction clause is present on the taskloop directive, the nogroup
14024 // clause must not be specified.
14025 if (checkReductionClauseWithNogroup(*this, Clauses))
14026 return StmtError();
14027 if (checkSimdlenSafelenSpecified(*this, Clauses))
14028 return StmtError();
14030 setFunctionHasBranchProtectedScope();
14031 return OMPParallelMasterTaskLoopSimdDirective::Create(
14032 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14035 StmtResult Sema::ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
14036 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14037 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14038 if (!AStmt)
14039 return StmtError();
14041 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14042 auto *CS = cast<CapturedStmt>(AStmt);
14043 // 1.2.2 OpenMP Language Terminology
14044 // Structured block - An executable statement with a single entry at the
14045 // top and a single exit at the bottom.
14046 // The point of exit cannot be a branch out of the structured block.
14047 // longjmp() and throw() must not violate the entry/exit criteria.
14048 CS->getCapturedDecl()->setNothrow();
14049 for (int ThisCaptureLevel =
14050 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop_simd);
14051 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14052 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14053 // 1.2.2 OpenMP Language Terminology
14054 // Structured block - An executable statement with a single entry at the
14055 // top and a single exit at the bottom.
14056 // The point of exit cannot be a branch out of the structured block.
14057 // longjmp() and throw() must not violate the entry/exit criteria.
14058 CS->getCapturedDecl()->setNothrow();
14061 OMPLoopBasedDirective::HelperExprs B;
14062 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14063 // define the nested loops number.
14064 unsigned NestedLoopCount = checkOpenMPLoop(
14065 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
14066 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
14067 VarsWithImplicitDSA, B);
14068 if (NestedLoopCount == 0)
14069 return StmtError();
14071 assert((CurContext->isDependentContext() || B.builtAll()) &&
14072 "omp for loop exprs were not built");
14074 if (!CurContext->isDependentContext()) {
14075 // Finalize the clauses that need pre-built expressions for CodeGen.
14076 for (OMPClause *C : Clauses) {
14077 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14078 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14079 B.NumIterations, *this, CurScope,
14080 DSAStack))
14081 return StmtError();
14085 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14086 // The grainsize clause and num_tasks clause are mutually exclusive and may
14087 // not appear on the same taskloop directive.
14088 if (checkMutuallyExclusiveClauses(*this, Clauses,
14089 {OMPC_grainsize, OMPC_num_tasks}))
14090 return StmtError();
14091 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14092 // If a reduction clause is present on the taskloop directive, the nogroup
14093 // clause must not be specified.
14094 if (checkReductionClauseWithNogroup(*this, Clauses))
14095 return StmtError();
14096 if (checkSimdlenSafelenSpecified(*this, Clauses))
14097 return StmtError();
14099 setFunctionHasBranchProtectedScope();
14100 return OMPParallelMaskedTaskLoopSimdDirective::Create(
14101 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14104 StmtResult Sema::ActOnOpenMPDistributeDirective(
14105 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14106 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14107 if (!AStmt)
14108 return StmtError();
14110 if (!checkLastPrivateForMappedDirectives(Clauses))
14111 return StmtError();
14113 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14114 OMPLoopBasedDirective::HelperExprs B;
14115 // In presence of clause 'collapse' with number of loops, it will
14116 // define the nested loops number.
14117 unsigned NestedLoopCount =
14118 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
14119 nullptr /*ordered not a clause on distribute*/, AStmt,
14120 *this, *DSAStack, VarsWithImplicitDSA, B);
14121 if (NestedLoopCount == 0)
14122 return StmtError();
14124 assert((CurContext->isDependentContext() || B.builtAll()) &&
14125 "omp for loop exprs were not built");
14127 setFunctionHasBranchProtectedScope();
14128 auto *DistributeDirective = OMPDistributeDirective::Create(
14129 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14130 DSAStack->getMappedDirective());
14131 return DistributeDirective;
14134 StmtResult Sema::ActOnOpenMPDistributeParallelForDirective(
14135 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14136 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14137 if (!AStmt)
14138 return StmtError();
14140 auto *CS = cast<CapturedStmt>(AStmt);
14141 // 1.2.2 OpenMP Language Terminology
14142 // Structured block - An executable statement with a single entry at the
14143 // top and a single exit at the bottom.
14144 // The point of exit cannot be a branch out of the structured block.
14145 // longjmp() and throw() must not violate the entry/exit criteria.
14146 CS->getCapturedDecl()->setNothrow();
14147 for (int ThisCaptureLevel =
14148 getOpenMPCaptureLevels(OMPD_distribute_parallel_for);
14149 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14150 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14151 // 1.2.2 OpenMP Language Terminology
14152 // Structured block - An executable statement with a single entry at the
14153 // top and a single exit at the bottom.
14154 // The point of exit cannot be a branch out of the structured block.
14155 // longjmp() and throw() must not violate the entry/exit criteria.
14156 CS->getCapturedDecl()->setNothrow();
14159 OMPLoopBasedDirective::HelperExprs B;
14160 // In presence of clause 'collapse' with number of loops, it will
14161 // define the nested loops number.
14162 unsigned NestedLoopCount = checkOpenMPLoop(
14163 OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14164 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14165 VarsWithImplicitDSA, B);
14166 if (NestedLoopCount == 0)
14167 return StmtError();
14169 assert((CurContext->isDependentContext() || B.builtAll()) &&
14170 "omp for loop exprs were not built");
14172 setFunctionHasBranchProtectedScope();
14173 return OMPDistributeParallelForDirective::Create(
14174 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14175 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14178 StmtResult Sema::ActOnOpenMPDistributeParallelForSimdDirective(
14179 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14180 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14181 if (!AStmt)
14182 return StmtError();
14184 auto *CS = cast<CapturedStmt>(AStmt);
14185 // 1.2.2 OpenMP Language Terminology
14186 // Structured block - An executable statement with a single entry at the
14187 // top and a single exit at the bottom.
14188 // The point of exit cannot be a branch out of the structured block.
14189 // longjmp() and throw() must not violate the entry/exit criteria.
14190 CS->getCapturedDecl()->setNothrow();
14191 for (int ThisCaptureLevel =
14192 getOpenMPCaptureLevels(OMPD_distribute_parallel_for_simd);
14193 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14194 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14195 // 1.2.2 OpenMP Language Terminology
14196 // Structured block - An executable statement with a single entry at the
14197 // top and a single exit at the bottom.
14198 // The point of exit cannot be a branch out of the structured block.
14199 // longjmp() and throw() must not violate the entry/exit criteria.
14200 CS->getCapturedDecl()->setNothrow();
14203 OMPLoopBasedDirective::HelperExprs B;
14204 // In presence of clause 'collapse' with number of loops, it will
14205 // define the nested loops number.
14206 unsigned NestedLoopCount = checkOpenMPLoop(
14207 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14208 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14209 VarsWithImplicitDSA, B);
14210 if (NestedLoopCount == 0)
14211 return StmtError();
14213 assert((CurContext->isDependentContext() || B.builtAll()) &&
14214 "omp for loop exprs were not built");
14216 if (!CurContext->isDependentContext()) {
14217 // Finalize the clauses that need pre-built expressions for CodeGen.
14218 for (OMPClause *C : Clauses) {
14219 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14220 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14221 B.NumIterations, *this, CurScope,
14222 DSAStack))
14223 return StmtError();
14227 if (checkSimdlenSafelenSpecified(*this, Clauses))
14228 return StmtError();
14230 setFunctionHasBranchProtectedScope();
14231 return OMPDistributeParallelForSimdDirective::Create(
14232 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14235 StmtResult Sema::ActOnOpenMPDistributeSimdDirective(
14236 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14237 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14238 if (!AStmt)
14239 return StmtError();
14241 auto *CS = cast<CapturedStmt>(AStmt);
14242 // 1.2.2 OpenMP Language Terminology
14243 // Structured block - An executable statement with a single entry at the
14244 // top and a single exit at the bottom.
14245 // The point of exit cannot be a branch out of the structured block.
14246 // longjmp() and throw() must not violate the entry/exit criteria.
14247 CS->getCapturedDecl()->setNothrow();
14248 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_distribute_simd);
14249 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14250 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14251 // 1.2.2 OpenMP Language Terminology
14252 // Structured block - An executable statement with a single entry at the
14253 // top and a single exit at the bottom.
14254 // The point of exit cannot be a branch out of the structured block.
14255 // longjmp() and throw() must not violate the entry/exit criteria.
14256 CS->getCapturedDecl()->setNothrow();
14259 OMPLoopBasedDirective::HelperExprs B;
14260 // In presence of clause 'collapse' with number of loops, it will
14261 // define the nested loops number.
14262 unsigned NestedLoopCount =
14263 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
14264 nullptr /*ordered not a clause on distribute*/, CS, *this,
14265 *DSAStack, VarsWithImplicitDSA, B);
14266 if (NestedLoopCount == 0)
14267 return StmtError();
14269 assert((CurContext->isDependentContext() || B.builtAll()) &&
14270 "omp for loop exprs were not built");
14272 if (!CurContext->isDependentContext()) {
14273 // Finalize the clauses that need pre-built expressions for CodeGen.
14274 for (OMPClause *C : Clauses) {
14275 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14276 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14277 B.NumIterations, *this, CurScope,
14278 DSAStack))
14279 return StmtError();
14283 if (checkSimdlenSafelenSpecified(*this, Clauses))
14284 return StmtError();
14286 setFunctionHasBranchProtectedScope();
14287 return OMPDistributeSimdDirective::Create(Context, StartLoc, EndLoc,
14288 NestedLoopCount, Clauses, AStmt, B);
14291 StmtResult Sema::ActOnOpenMPTargetParallelForSimdDirective(
14292 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14293 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14294 if (!AStmt)
14295 return StmtError();
14297 auto *CS = cast<CapturedStmt>(AStmt);
14298 // 1.2.2 OpenMP Language Terminology
14299 // Structured block - An executable statement with a single entry at the
14300 // top and a single exit at the bottom.
14301 // The point of exit cannot be a branch out of the structured block.
14302 // longjmp() and throw() must not violate the entry/exit criteria.
14303 CS->getCapturedDecl()->setNothrow();
14304 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_for);
14305 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14306 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14307 // 1.2.2 OpenMP Language Terminology
14308 // Structured block - An executable statement with a single entry at the
14309 // top and a single exit at the bottom.
14310 // The point of exit cannot be a branch out of the structured block.
14311 // longjmp() and throw() must not violate the entry/exit criteria.
14312 CS->getCapturedDecl()->setNothrow();
14315 OMPLoopBasedDirective::HelperExprs B;
14316 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14317 // define the nested loops number.
14318 unsigned NestedLoopCount = checkOpenMPLoop(
14319 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
14320 getOrderedNumberExpr(Clauses), CS, *this, *DSAStack, VarsWithImplicitDSA,
14322 if (NestedLoopCount == 0)
14323 return StmtError();
14325 assert((CurContext->isDependentContext() || B.builtAll()) &&
14326 "omp target parallel for simd loop exprs were not built");
14328 if (!CurContext->isDependentContext()) {
14329 // Finalize the clauses that need pre-built expressions for CodeGen.
14330 for (OMPClause *C : Clauses) {
14331 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14332 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14333 B.NumIterations, *this, CurScope,
14334 DSAStack))
14335 return StmtError();
14338 if (checkSimdlenSafelenSpecified(*this, Clauses))
14339 return StmtError();
14341 setFunctionHasBranchProtectedScope();
14342 return OMPTargetParallelForSimdDirective::Create(
14343 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14346 StmtResult Sema::ActOnOpenMPTargetSimdDirective(
14347 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14348 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14349 if (!AStmt)
14350 return StmtError();
14352 auto *CS = cast<CapturedStmt>(AStmt);
14353 // 1.2.2 OpenMP Language Terminology
14354 // Structured block - An executable statement with a single entry at the
14355 // top and a single exit at the bottom.
14356 // The point of exit cannot be a branch out of the structured block.
14357 // longjmp() and throw() must not violate the entry/exit criteria.
14358 CS->getCapturedDecl()->setNothrow();
14359 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_simd);
14360 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14361 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14362 // 1.2.2 OpenMP Language Terminology
14363 // Structured block - An executable statement with a single entry at the
14364 // top and a single exit at the bottom.
14365 // The point of exit cannot be a branch out of the structured block.
14366 // longjmp() and throw() must not violate the entry/exit criteria.
14367 CS->getCapturedDecl()->setNothrow();
14370 OMPLoopBasedDirective::HelperExprs B;
14371 // In presence of clause 'collapse' with number of loops, it will define the
14372 // nested loops number.
14373 unsigned NestedLoopCount =
14374 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
14375 getOrderedNumberExpr(Clauses), CS, *this, *DSAStack,
14376 VarsWithImplicitDSA, B);
14377 if (NestedLoopCount == 0)
14378 return StmtError();
14380 assert((CurContext->isDependentContext() || B.builtAll()) &&
14381 "omp target simd loop exprs were not built");
14383 if (!CurContext->isDependentContext()) {
14384 // Finalize the clauses that need pre-built expressions for CodeGen.
14385 for (OMPClause *C : Clauses) {
14386 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14387 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14388 B.NumIterations, *this, CurScope,
14389 DSAStack))
14390 return StmtError();
14394 if (checkSimdlenSafelenSpecified(*this, Clauses))
14395 return StmtError();
14397 setFunctionHasBranchProtectedScope();
14398 return OMPTargetSimdDirective::Create(Context, StartLoc, EndLoc,
14399 NestedLoopCount, Clauses, AStmt, B);
14402 StmtResult Sema::ActOnOpenMPTeamsDistributeDirective(
14403 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14404 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14405 if (!AStmt)
14406 return StmtError();
14408 auto *CS = cast<CapturedStmt>(AStmt);
14409 // 1.2.2 OpenMP Language Terminology
14410 // Structured block - An executable statement with a single entry at the
14411 // top and a single exit at the bottom.
14412 // The point of exit cannot be a branch out of the structured block.
14413 // longjmp() and throw() must not violate the entry/exit criteria.
14414 CS->getCapturedDecl()->setNothrow();
14415 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_teams_distribute);
14416 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14417 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14418 // 1.2.2 OpenMP Language Terminology
14419 // Structured block - An executable statement with a single entry at the
14420 // top and a single exit at the bottom.
14421 // The point of exit cannot be a branch out of the structured block.
14422 // longjmp() and throw() must not violate the entry/exit criteria.
14423 CS->getCapturedDecl()->setNothrow();
14426 OMPLoopBasedDirective::HelperExprs B;
14427 // In presence of clause 'collapse' with number of loops, it will
14428 // define the nested loops number.
14429 unsigned NestedLoopCount =
14430 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
14431 nullptr /*ordered not a clause on distribute*/, CS, *this,
14432 *DSAStack, VarsWithImplicitDSA, B);
14433 if (NestedLoopCount == 0)
14434 return StmtError();
14436 assert((CurContext->isDependentContext() || B.builtAll()) &&
14437 "omp teams distribute loop exprs were not built");
14439 setFunctionHasBranchProtectedScope();
14441 DSAStack->setParentTeamsRegionLoc(StartLoc);
14443 return OMPTeamsDistributeDirective::Create(
14444 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14447 StmtResult Sema::ActOnOpenMPTeamsDistributeSimdDirective(
14448 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14449 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14450 if (!AStmt)
14451 return StmtError();
14453 auto *CS = cast<CapturedStmt>(AStmt);
14454 // 1.2.2 OpenMP Language Terminology
14455 // Structured block - An executable statement with a single entry at the
14456 // top and a single exit at the bottom.
14457 // The point of exit cannot be a branch out of the structured block.
14458 // longjmp() and throw() must not violate the entry/exit criteria.
14459 CS->getCapturedDecl()->setNothrow();
14460 for (int ThisCaptureLevel =
14461 getOpenMPCaptureLevels(OMPD_teams_distribute_simd);
14462 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14463 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14464 // 1.2.2 OpenMP Language Terminology
14465 // Structured block - An executable statement with a single entry at the
14466 // top and a single exit at the bottom.
14467 // The point of exit cannot be a branch out of the structured block.
14468 // longjmp() and throw() must not violate the entry/exit criteria.
14469 CS->getCapturedDecl()->setNothrow();
14472 OMPLoopBasedDirective::HelperExprs B;
14473 // In presence of clause 'collapse' with number of loops, it will
14474 // define the nested loops number.
14475 unsigned NestedLoopCount = checkOpenMPLoop(
14476 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14477 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14478 VarsWithImplicitDSA, B);
14480 if (NestedLoopCount == 0)
14481 return StmtError();
14483 assert((CurContext->isDependentContext() || B.builtAll()) &&
14484 "omp teams distribute simd loop exprs were not built");
14486 if (!CurContext->isDependentContext()) {
14487 // Finalize the clauses that need pre-built expressions for CodeGen.
14488 for (OMPClause *C : Clauses) {
14489 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14490 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14491 B.NumIterations, *this, CurScope,
14492 DSAStack))
14493 return StmtError();
14497 if (checkSimdlenSafelenSpecified(*this, Clauses))
14498 return StmtError();
14500 setFunctionHasBranchProtectedScope();
14502 DSAStack->setParentTeamsRegionLoc(StartLoc);
14504 return OMPTeamsDistributeSimdDirective::Create(
14505 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14508 StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
14509 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14510 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14511 if (!AStmt)
14512 return StmtError();
14514 auto *CS = cast<CapturedStmt>(AStmt);
14515 // 1.2.2 OpenMP Language Terminology
14516 // Structured block - An executable statement with a single entry at the
14517 // top and a single exit at the bottom.
14518 // The point of exit cannot be a branch out of the structured block.
14519 // longjmp() and throw() must not violate the entry/exit criteria.
14520 CS->getCapturedDecl()->setNothrow();
14522 for (int ThisCaptureLevel =
14523 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for_simd);
14524 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14525 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14526 // 1.2.2 OpenMP Language Terminology
14527 // Structured block - An executable statement with a single entry at the
14528 // top and a single exit at the bottom.
14529 // The point of exit cannot be a branch out of the structured block.
14530 // longjmp() and throw() must not violate the entry/exit criteria.
14531 CS->getCapturedDecl()->setNothrow();
14534 OMPLoopBasedDirective::HelperExprs B;
14535 // In presence of clause 'collapse' with number of loops, it will
14536 // define the nested loops number.
14537 unsigned NestedLoopCount = checkOpenMPLoop(
14538 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14539 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14540 VarsWithImplicitDSA, B);
14542 if (NestedLoopCount == 0)
14543 return StmtError();
14545 assert((CurContext->isDependentContext() || B.builtAll()) &&
14546 "omp for loop exprs were not built");
14548 if (!CurContext->isDependentContext()) {
14549 // Finalize the clauses that need pre-built expressions for CodeGen.
14550 for (OMPClause *C : Clauses) {
14551 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14552 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14553 B.NumIterations, *this, CurScope,
14554 DSAStack))
14555 return StmtError();
14559 if (checkSimdlenSafelenSpecified(*this, Clauses))
14560 return StmtError();
14562 setFunctionHasBranchProtectedScope();
14564 DSAStack->setParentTeamsRegionLoc(StartLoc);
14566 return OMPTeamsDistributeParallelForSimdDirective::Create(
14567 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14570 StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForDirective(
14571 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14572 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14573 if (!AStmt)
14574 return StmtError();
14576 auto *CS = cast<CapturedStmt>(AStmt);
14577 // 1.2.2 OpenMP Language Terminology
14578 // Structured block - An executable statement with a single entry at the
14579 // top and a single exit at the bottom.
14580 // The point of exit cannot be a branch out of the structured block.
14581 // longjmp() and throw() must not violate the entry/exit criteria.
14582 CS->getCapturedDecl()->setNothrow();
14584 for (int ThisCaptureLevel =
14585 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for);
14586 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14587 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14588 // 1.2.2 OpenMP Language Terminology
14589 // Structured block - An executable statement with a single entry at the
14590 // top and a single exit at the bottom.
14591 // The point of exit cannot be a branch out of the structured block.
14592 // longjmp() and throw() must not violate the entry/exit criteria.
14593 CS->getCapturedDecl()->setNothrow();
14596 OMPLoopBasedDirective::HelperExprs B;
14597 // In presence of clause 'collapse' with number of loops, it will
14598 // define the nested loops number.
14599 unsigned NestedLoopCount = checkOpenMPLoop(
14600 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14601 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14602 VarsWithImplicitDSA, B);
14604 if (NestedLoopCount == 0)
14605 return StmtError();
14607 assert((CurContext->isDependentContext() || B.builtAll()) &&
14608 "omp for loop exprs were not built");
14610 setFunctionHasBranchProtectedScope();
14612 DSAStack->setParentTeamsRegionLoc(StartLoc);
14614 return OMPTeamsDistributeParallelForDirective::Create(
14615 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14616 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14619 StmtResult Sema::ActOnOpenMPTargetTeamsDirective(ArrayRef<OMPClause *> Clauses,
14620 Stmt *AStmt,
14621 SourceLocation StartLoc,
14622 SourceLocation EndLoc) {
14623 if (!AStmt)
14624 return StmtError();
14626 auto *CS = cast<CapturedStmt>(AStmt);
14627 // 1.2.2 OpenMP Language Terminology
14628 // Structured block - An executable statement with a single entry at the
14629 // top and a single exit at the bottom.
14630 // The point of exit cannot be a branch out of the structured block.
14631 // longjmp() and throw() must not violate the entry/exit criteria.
14632 CS->getCapturedDecl()->setNothrow();
14634 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_teams);
14635 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14636 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14637 // 1.2.2 OpenMP Language Terminology
14638 // Structured block - An executable statement with a single entry at the
14639 // top and a single exit at the bottom.
14640 // The point of exit cannot be a branch out of the structured block.
14641 // longjmp() and throw() must not violate the entry/exit criteria.
14642 CS->getCapturedDecl()->setNothrow();
14644 setFunctionHasBranchProtectedScope();
14646 return OMPTargetTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses,
14647 AStmt);
14650 StmtResult Sema::ActOnOpenMPTargetTeamsDistributeDirective(
14651 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14652 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14653 if (!AStmt)
14654 return StmtError();
14656 auto *CS = cast<CapturedStmt>(AStmt);
14657 // 1.2.2 OpenMP Language Terminology
14658 // Structured block - An executable statement with a single entry at the
14659 // top and a single exit at the bottom.
14660 // The point of exit cannot be a branch out of the structured block.
14661 // longjmp() and throw() must not violate the entry/exit criteria.
14662 CS->getCapturedDecl()->setNothrow();
14663 for (int ThisCaptureLevel =
14664 getOpenMPCaptureLevels(OMPD_target_teams_distribute);
14665 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14666 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14667 // 1.2.2 OpenMP Language Terminology
14668 // Structured block - An executable statement with a single entry at the
14669 // top and a single exit at the bottom.
14670 // The point of exit cannot be a branch out of the structured block.
14671 // longjmp() and throw() must not violate the entry/exit criteria.
14672 CS->getCapturedDecl()->setNothrow();
14675 OMPLoopBasedDirective::HelperExprs B;
14676 // In presence of clause 'collapse' with number of loops, it will
14677 // define the nested loops number.
14678 unsigned NestedLoopCount = checkOpenMPLoop(
14679 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
14680 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14681 VarsWithImplicitDSA, B);
14682 if (NestedLoopCount == 0)
14683 return StmtError();
14685 assert((CurContext->isDependentContext() || B.builtAll()) &&
14686 "omp target teams distribute loop exprs were not built");
14688 setFunctionHasBranchProtectedScope();
14689 return OMPTargetTeamsDistributeDirective::Create(
14690 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14693 StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForDirective(
14694 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14695 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14696 if (!AStmt)
14697 return StmtError();
14699 auto *CS = cast<CapturedStmt>(AStmt);
14700 // 1.2.2 OpenMP Language Terminology
14701 // Structured block - An executable statement with a single entry at the
14702 // top and a single exit at the bottom.
14703 // The point of exit cannot be a branch out of the structured block.
14704 // longjmp() and throw() must not violate the entry/exit criteria.
14705 CS->getCapturedDecl()->setNothrow();
14706 for (int ThisCaptureLevel =
14707 getOpenMPCaptureLevels(OMPD_target_teams_distribute_parallel_for);
14708 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14709 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14710 // 1.2.2 OpenMP Language Terminology
14711 // Structured block - An executable statement with a single entry at the
14712 // top and a single exit at the bottom.
14713 // The point of exit cannot be a branch out of the structured block.
14714 // longjmp() and throw() must not violate the entry/exit criteria.
14715 CS->getCapturedDecl()->setNothrow();
14718 OMPLoopBasedDirective::HelperExprs B;
14719 // In presence of clause 'collapse' with number of loops, it will
14720 // define the nested loops number.
14721 unsigned NestedLoopCount = checkOpenMPLoop(
14722 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14723 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14724 VarsWithImplicitDSA, B);
14725 if (NestedLoopCount == 0)
14726 return StmtError();
14728 assert((CurContext->isDependentContext() || B.builtAll()) &&
14729 "omp target teams distribute parallel for loop exprs were not built");
14731 if (!CurContext->isDependentContext()) {
14732 // Finalize the clauses that need pre-built expressions for CodeGen.
14733 for (OMPClause *C : Clauses) {
14734 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14735 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14736 B.NumIterations, *this, CurScope,
14737 DSAStack))
14738 return StmtError();
14742 setFunctionHasBranchProtectedScope();
14743 return OMPTargetTeamsDistributeParallelForDirective::Create(
14744 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14745 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14748 StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
14749 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14750 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14751 if (!AStmt)
14752 return StmtError();
14754 auto *CS = cast<CapturedStmt>(AStmt);
14755 // 1.2.2 OpenMP Language Terminology
14756 // Structured block - An executable statement with a single entry at the
14757 // top and a single exit at the bottom.
14758 // The point of exit cannot be a branch out of the structured block.
14759 // longjmp() and throw() must not violate the entry/exit criteria.
14760 CS->getCapturedDecl()->setNothrow();
14761 for (int ThisCaptureLevel = getOpenMPCaptureLevels(
14762 OMPD_target_teams_distribute_parallel_for_simd);
14763 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14764 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14765 // 1.2.2 OpenMP Language Terminology
14766 // Structured block - An executable statement with a single entry at the
14767 // top and a single exit at the bottom.
14768 // The point of exit cannot be a branch out of the structured block.
14769 // longjmp() and throw() must not violate the entry/exit criteria.
14770 CS->getCapturedDecl()->setNothrow();
14773 OMPLoopBasedDirective::HelperExprs B;
14774 // In presence of clause 'collapse' with number of loops, it will
14775 // define the nested loops number.
14776 unsigned NestedLoopCount =
14777 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
14778 getCollapseNumberExpr(Clauses),
14779 nullptr /*ordered not a clause on distribute*/, CS, *this,
14780 *DSAStack, VarsWithImplicitDSA, B);
14781 if (NestedLoopCount == 0)
14782 return StmtError();
14784 assert((CurContext->isDependentContext() || B.builtAll()) &&
14785 "omp target teams distribute parallel for simd loop exprs were not "
14786 "built");
14788 if (!CurContext->isDependentContext()) {
14789 // Finalize the clauses that need pre-built expressions for CodeGen.
14790 for (OMPClause *C : Clauses) {
14791 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14792 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14793 B.NumIterations, *this, CurScope,
14794 DSAStack))
14795 return StmtError();
14799 if (checkSimdlenSafelenSpecified(*this, Clauses))
14800 return StmtError();
14802 setFunctionHasBranchProtectedScope();
14803 return OMPTargetTeamsDistributeParallelForSimdDirective::Create(
14804 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14807 StmtResult Sema::ActOnOpenMPTargetTeamsDistributeSimdDirective(
14808 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14809 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14810 if (!AStmt)
14811 return StmtError();
14813 auto *CS = cast<CapturedStmt>(AStmt);
14814 // 1.2.2 OpenMP Language Terminology
14815 // Structured block - An executable statement with a single entry at the
14816 // top and a single exit at the bottom.
14817 // The point of exit cannot be a branch out of the structured block.
14818 // longjmp() and throw() must not violate the entry/exit criteria.
14819 CS->getCapturedDecl()->setNothrow();
14820 for (int ThisCaptureLevel =
14821 getOpenMPCaptureLevels(OMPD_target_teams_distribute_simd);
14822 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14823 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14824 // 1.2.2 OpenMP Language Terminology
14825 // Structured block - An executable statement with a single entry at the
14826 // top and a single exit at the bottom.
14827 // The point of exit cannot be a branch out of the structured block.
14828 // longjmp() and throw() must not violate the entry/exit criteria.
14829 CS->getCapturedDecl()->setNothrow();
14832 OMPLoopBasedDirective::HelperExprs B;
14833 // In presence of clause 'collapse' with number of loops, it will
14834 // define the nested loops number.
14835 unsigned NestedLoopCount = checkOpenMPLoop(
14836 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14837 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14838 VarsWithImplicitDSA, B);
14839 if (NestedLoopCount == 0)
14840 return StmtError();
14842 assert((CurContext->isDependentContext() || B.builtAll()) &&
14843 "omp target teams distribute simd loop exprs were not built");
14845 if (!CurContext->isDependentContext()) {
14846 // Finalize the clauses that need pre-built expressions for CodeGen.
14847 for (OMPClause *C : Clauses) {
14848 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14849 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14850 B.NumIterations, *this, CurScope,
14851 DSAStack))
14852 return StmtError();
14856 if (checkSimdlenSafelenSpecified(*this, Clauses))
14857 return StmtError();
14859 setFunctionHasBranchProtectedScope();
14860 return OMPTargetTeamsDistributeSimdDirective::Create(
14861 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14864 bool Sema::checkTransformableLoopNest(
14865 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14866 SmallVectorImpl<OMPLoopBasedDirective::HelperExprs> &LoopHelpers,
14867 Stmt *&Body,
14868 SmallVectorImpl<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>>
14869 &OriginalInits) {
14870 OriginalInits.emplace_back();
14871 bool Result = OMPLoopBasedDirective::doForAllLoops(
14872 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14873 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14874 Stmt *CurStmt) {
14875 VarsWithInheritedDSAType TmpDSA;
14876 unsigned SingleNumLoops =
14877 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, *this, *DSAStack,
14878 TmpDSA, LoopHelpers[Cnt]);
14879 if (SingleNumLoops == 0)
14880 return true;
14881 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14882 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14883 OriginalInits.back().push_back(For->getInit());
14884 Body = For->getBody();
14885 } else {
14886 assert(isa<CXXForRangeStmt>(CurStmt) &&
14887 "Expected canonical for or range-based for loops.");
14888 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14889 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14890 Body = CXXFor->getBody();
14892 OriginalInits.emplace_back();
14893 return false;
14895 [&OriginalInits](OMPLoopBasedDirective *Transform) {
14896 Stmt *DependentPreInits;
14897 if (auto *Dir = dyn_cast<OMPTileDirective>(Transform))
14898 DependentPreInits = Dir->getPreInits();
14899 else if (auto *Dir = dyn_cast<OMPUnrollDirective>(Transform))
14900 DependentPreInits = Dir->getPreInits();
14901 else
14902 llvm_unreachable("Unhandled loop transformation");
14903 if (!DependentPreInits)
14904 return;
14905 llvm::append_range(OriginalInits.back(),
14906 cast<DeclStmt>(DependentPreInits)->getDeclGroup());
14908 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14909 OriginalInits.pop_back();
14910 return Result;
14913 StmtResult Sema::ActOnOpenMPTileDirective(ArrayRef<OMPClause *> Clauses,
14914 Stmt *AStmt, SourceLocation StartLoc,
14915 SourceLocation EndLoc) {
14916 auto SizesClauses =
14917 OMPExecutableDirective::getClausesOfKind<OMPSizesClause>(Clauses);
14918 if (SizesClauses.empty()) {
14919 // A missing 'sizes' clause is already reported by the parser.
14920 return StmtError();
14922 const OMPSizesClause *SizesClause = *SizesClauses.begin();
14923 unsigned NumLoops = SizesClause->getNumSizes();
14925 // Empty statement should only be possible if there already was an error.
14926 if (!AStmt)
14927 return StmtError();
14929 // Verify and diagnose loop nest.
14930 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
14931 Stmt *Body = nullptr;
14932 SmallVector<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>, 4>
14933 OriginalInits;
14934 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14935 OriginalInits))
14936 return StmtError();
14938 // Delay tiling to when template is completely instantiated.
14939 if (CurContext->isDependentContext())
14940 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
14941 NumLoops, AStmt, nullptr, nullptr);
14943 SmallVector<Decl *, 4> PreInits;
14945 // Create iteration variables for the generated loops.
14946 SmallVector<VarDecl *, 4> FloorIndVars;
14947 SmallVector<VarDecl *, 4> TileIndVars;
14948 FloorIndVars.resize(NumLoops);
14949 TileIndVars.resize(NumLoops);
14950 for (unsigned I = 0; I < NumLoops; ++I) {
14951 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14953 assert(LoopHelper.Counters.size() == 1 &&
14954 "Expect single-dimensional loop iteration space");
14955 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14956 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14957 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14958 QualType CntTy = IterVarRef->getType();
14960 // Iteration variable for the floor (i.e. outer) loop.
14962 std::string FloorCntName =
14963 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14964 VarDecl *FloorCntDecl =
14965 buildVarDecl(*this, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
14966 FloorIndVars[I] = FloorCntDecl;
14969 // Iteration variable for the tile (i.e. inner) loop.
14971 std::string TileCntName =
14972 (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14974 // Reuse the iteration variable created by checkOpenMPLoop. It is also
14975 // used by the expressions to derive the original iteration variable's
14976 // value from the logical iteration number.
14977 auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
14978 TileCntDecl->setDeclName(&PP.getIdentifierTable().get(TileCntName));
14979 TileIndVars[I] = TileCntDecl;
14981 for (auto &P : OriginalInits[I]) {
14982 if (auto *D = P.dyn_cast<Decl *>())
14983 PreInits.push_back(D);
14984 else if (auto *PI = dyn_cast_or_null<DeclStmt>(P.dyn_cast<Stmt *>()))
14985 PreInits.append(PI->decl_begin(), PI->decl_end());
14987 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits))
14988 PreInits.append(PI->decl_begin(), PI->decl_end());
14989 // Gather declarations for the data members used as counters.
14990 for (Expr *CounterRef : LoopHelper.Counters) {
14991 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14992 if (isa<OMPCapturedExprDecl>(CounterDecl))
14993 PreInits.push_back(CounterDecl);
14997 // Once the original iteration values are set, append the innermost body.
14998 Stmt *Inner = Body;
15000 // Create tile loops from the inside to the outside.
15001 for (int I = NumLoops - 1; I >= 0; --I) {
15002 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15003 Expr *NumIterations = LoopHelper.NumIterations;
15004 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15005 QualType CntTy = OrigCntVar->getType();
15006 Expr *DimTileSize = SizesClause->getSizesRefs()[I];
15007 Scope *CurScope = getCurScope();
15009 // Commonly used variables.
15010 DeclRefExpr *TileIV = buildDeclRefExpr(*this, TileIndVars[I], CntTy,
15011 OrigCntVar->getExprLoc());
15012 DeclRefExpr *FloorIV = buildDeclRefExpr(*this, FloorIndVars[I], CntTy,
15013 OrigCntVar->getExprLoc());
15015 // For init-statement: auto .tile.iv = .floor.iv
15016 AddInitializerToDecl(TileIndVars[I], DefaultLvalueConversion(FloorIV).get(),
15017 /*DirectInit=*/false);
15018 Decl *CounterDecl = TileIndVars[I];
15019 StmtResult InitStmt = new (Context)
15020 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15021 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15022 if (!InitStmt.isUsable())
15023 return StmtError();
15025 // For cond-expression: .tile.iv < min(.floor.iv + DimTileSize,
15026 // NumIterations)
15027 ExprResult EndOfTile = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
15028 BO_Add, FloorIV, DimTileSize);
15029 if (!EndOfTile.isUsable())
15030 return StmtError();
15031 ExprResult IsPartialTile =
15032 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15033 NumIterations, EndOfTile.get());
15034 if (!IsPartialTile.isUsable())
15035 return StmtError();
15036 ExprResult MinTileAndIterSpace = ActOnConditionalOp(
15037 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
15038 IsPartialTile.get(), NumIterations, EndOfTile.get());
15039 if (!MinTileAndIterSpace.isUsable())
15040 return StmtError();
15041 ExprResult CondExpr = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
15042 BO_LT, TileIV, MinTileAndIterSpace.get());
15043 if (!CondExpr.isUsable())
15044 return StmtError();
15046 // For incr-statement: ++.tile.iv
15047 ExprResult IncrStmt =
15048 BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, TileIV);
15049 if (!IncrStmt.isUsable())
15050 return StmtError();
15052 // Statements to set the original iteration variable's value from the
15053 // logical iteration number.
15054 // Generated for loop is:
15055 // Original_for_init;
15056 // for (auto .tile.iv = .floor.iv; .tile.iv < min(.floor.iv + DimTileSize,
15057 // NumIterations); ++.tile.iv) {
15058 // Original_Body;
15059 // Original_counter_update;
15060 // }
15061 // FIXME: If the innermost body is an loop itself, inserting these
15062 // statements stops it being recognized as a perfectly nested loop (e.g.
15063 // for applying tiling again). If this is the case, sink the expressions
15064 // further into the inner loop.
15065 SmallVector<Stmt *, 4> BodyParts;
15066 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15067 BodyParts.push_back(Inner);
15068 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15069 Inner->getBeginLoc(), Inner->getEndLoc());
15070 Inner = new (Context)
15071 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15072 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15073 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15076 // Create floor loops from the inside to the outside.
15077 for (int I = NumLoops - 1; I >= 0; --I) {
15078 auto &LoopHelper = LoopHelpers[I];
15079 Expr *NumIterations = LoopHelper.NumIterations;
15080 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15081 QualType CntTy = OrigCntVar->getType();
15082 Expr *DimTileSize = SizesClause->getSizesRefs()[I];
15083 Scope *CurScope = getCurScope();
15085 // Commonly used variables.
15086 DeclRefExpr *FloorIV = buildDeclRefExpr(*this, FloorIndVars[I], CntTy,
15087 OrigCntVar->getExprLoc());
15089 // For init-statement: auto .floor.iv = 0
15090 AddInitializerToDecl(
15091 FloorIndVars[I],
15092 ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15093 /*DirectInit=*/false);
15094 Decl *CounterDecl = FloorIndVars[I];
15095 StmtResult InitStmt = new (Context)
15096 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15097 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15098 if (!InitStmt.isUsable())
15099 return StmtError();
15101 // For cond-expression: .floor.iv < NumIterations
15102 ExprResult CondExpr = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
15103 BO_LT, FloorIV, NumIterations);
15104 if (!CondExpr.isUsable())
15105 return StmtError();
15107 // For incr-statement: .floor.iv += DimTileSize
15108 ExprResult IncrStmt = BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(),
15109 BO_AddAssign, FloorIV, DimTileSize);
15110 if (!IncrStmt.isUsable())
15111 return StmtError();
15113 Inner = new (Context)
15114 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15115 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15116 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15119 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
15120 AStmt, Inner,
15121 buildPreInits(Context, PreInits));
15124 StmtResult Sema::ActOnOpenMPUnrollDirective(ArrayRef<OMPClause *> Clauses,
15125 Stmt *AStmt,
15126 SourceLocation StartLoc,
15127 SourceLocation EndLoc) {
15128 // Empty statement should only be possible if there already was an error.
15129 if (!AStmt)
15130 return StmtError();
15132 if (checkMutuallyExclusiveClauses(*this, Clauses, {OMPC_partial, OMPC_full}))
15133 return StmtError();
15135 const OMPFullClause *FullClause =
15136 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
15137 const OMPPartialClause *PartialClause =
15138 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
15139 assert(!(FullClause && PartialClause) &&
15140 "mutual exclusivity must have been checked before");
15142 constexpr unsigned NumLoops = 1;
15143 Stmt *Body = nullptr;
15144 SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
15145 NumLoops);
15146 SmallVector<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>, NumLoops + 1>
15147 OriginalInits;
15148 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
15149 Body, OriginalInits))
15150 return StmtError();
15152 unsigned NumGeneratedLoops = PartialClause ? 1 : 0;
15154 // Delay unrolling to when template is completely instantiated.
15155 if (CurContext->isDependentContext())
15156 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15157 NumGeneratedLoops, nullptr, nullptr);
15159 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15161 if (FullClause) {
15162 if (!VerifyPositiveIntegerConstantInClause(
15163 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
15164 /*SuppressExprDiags=*/true)
15165 .isUsable()) {
15166 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
15167 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
15168 << "#pragma omp unroll full";
15169 return StmtError();
15173 // The generated loop may only be passed to other loop-associated directive
15174 // when a partial clause is specified. Without the requirement it is
15175 // sufficient to generate loop unroll metadata at code-generation.
15176 if (NumGeneratedLoops == 0)
15177 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15178 NumGeneratedLoops, nullptr, nullptr);
15180 // Otherwise, we need to provide a de-sugared/transformed AST that can be
15181 // associated with another loop directive.
15183 // The canonical loop analysis return by checkTransformableLoopNest assumes
15184 // the following structure to be the same loop without transformations or
15185 // directives applied: \code OriginalInits; LoopHelper.PreInits;
15186 // LoopHelper.Counters;
15187 // for (; IV < LoopHelper.NumIterations; ++IV) {
15188 // LoopHelper.Updates;
15189 // Body;
15190 // }
15191 // \endcode
15192 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
15193 // and referenced by LoopHelper.IterationVarRef.
15195 // The unrolling directive transforms this into the following loop:
15196 // \code
15197 // OriginalInits; \
15198 // LoopHelper.PreInits; > NewPreInits
15199 // LoopHelper.Counters; /
15200 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
15201 // #pragma clang loop unroll_count(Factor)
15202 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
15203 // {
15204 // LoopHelper.Updates;
15205 // Body;
15206 // }
15207 // }
15208 // \endcode
15209 // where UIV is a new logical iteration counter. IV must be the same VarDecl
15210 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
15211 // references it. If the partially unrolled loop is associated with another
15212 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
15213 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
15214 // OpenMP canonical loop. The inner loop is not an associable canonical loop
15215 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
15216 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
15217 // property of the OMPLoopBasedDirective instead of statements in
15218 // CompoundStatement. This is to allow the loop to become a non-outermost loop
15219 // of a canonical loop nest where these PreInits are emitted before the
15220 // outermost directive.
15222 // Determine the PreInit declarations.
15223 SmallVector<Decl *, 4> PreInits;
15224 assert(OriginalInits.size() == 1 &&
15225 "Expecting a single-dimensional loop iteration space");
15226 for (auto &P : OriginalInits[0]) {
15227 if (auto *D = P.dyn_cast<Decl *>())
15228 PreInits.push_back(D);
15229 else if (auto *PI = dyn_cast_or_null<DeclStmt>(P.dyn_cast<Stmt *>()))
15230 PreInits.append(PI->decl_begin(), PI->decl_end());
15232 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits))
15233 PreInits.append(PI->decl_begin(), PI->decl_end());
15234 // Gather declarations for the data members used as counters.
15235 for (Expr *CounterRef : LoopHelper.Counters) {
15236 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
15237 if (isa<OMPCapturedExprDecl>(CounterDecl))
15238 PreInits.push_back(CounterDecl);
15241 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15242 QualType IVTy = IterationVarRef->getType();
15243 assert(LoopHelper.Counters.size() == 1 &&
15244 "Expecting a single-dimensional loop iteration space");
15245 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15247 // Determine the unroll factor.
15248 uint64_t Factor;
15249 SourceLocation FactorLoc;
15250 if (Expr *FactorVal = PartialClause->getFactor()) {
15251 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
15252 FactorLoc = FactorVal->getExprLoc();
15253 } else {
15254 // TODO: Use a better profitability model.
15255 Factor = 2;
15257 assert(Factor > 0 && "Expected positive unroll factor");
15258 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
15259 return IntegerLiteral::Create(
15260 Context, llvm::APInt(Context.getIntWidth(IVTy), Factor), IVTy,
15261 FactorLoc);
15264 // Iteration variable SourceLocations.
15265 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15266 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15267 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15269 // Internal variable names.
15270 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15271 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
15272 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
15273 std::string InnerTripCountName =
15274 (Twine(".unroll_inner.tripcount.") + OrigVarName).str();
15276 // Create the iteration variable for the unrolled loop.
15277 VarDecl *OuterIVDecl =
15278 buildVarDecl(*this, {}, IVTy, OuterIVName, nullptr, OrigVar);
15279 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
15280 return buildDeclRefExpr(*this, OuterIVDecl, IVTy, OrigVarLoc);
15283 // Iteration variable for the inner loop: Reuse the iteration variable created
15284 // by checkOpenMPLoop.
15285 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15286 InnerIVDecl->setDeclName(&PP.getIdentifierTable().get(InnerIVName));
15287 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
15288 return buildDeclRefExpr(*this, InnerIVDecl, IVTy, OrigVarLoc);
15291 // Make a copy of the NumIterations expression for each use: By the AST
15292 // constraints, every expression object in a DeclContext must be unique.
15293 CaptureVars CopyTransformer(*this);
15294 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15295 return AssertSuccess(
15296 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15299 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
15300 ExprResult LValueConv = DefaultLvalueConversion(MakeOuterRef());
15301 AddInitializerToDecl(InnerIVDecl, LValueConv.get(), /*DirectInit=*/false);
15302 StmtResult InnerInit = new (Context)
15303 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15304 if (!InnerInit.isUsable())
15305 return StmtError();
15307 // Inner For cond-expression:
15308 // \code
15309 // .unroll_inner.iv < .unrolled.iv + Factor &&
15310 // .unroll_inner.iv < NumIterations
15311 // \endcode
15312 // This conjunction of two conditions allows ScalarEvolution to derive the
15313 // maximum trip count of the inner loop.
15314 ExprResult EndOfTile = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
15315 BO_Add, MakeOuterRef(), MakeFactorExpr());
15316 if (!EndOfTile.isUsable())
15317 return StmtError();
15318 ExprResult InnerCond1 = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
15319 BO_LT, MakeInnerRef(), EndOfTile.get());
15320 if (!InnerCond1.isUsable())
15321 return StmtError();
15322 ExprResult InnerCond2 =
15323 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, MakeInnerRef(),
15324 MakeNumIterations());
15325 if (!InnerCond2.isUsable())
15326 return StmtError();
15327 ExprResult InnerCond =
15328 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
15329 InnerCond1.get(), InnerCond2.get());
15330 if (!InnerCond.isUsable())
15331 return StmtError();
15333 // Inner For incr-statement: ++.unroll_inner.iv
15334 ExprResult InnerIncr = BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(),
15335 UO_PreInc, MakeInnerRef());
15336 if (!InnerIncr.isUsable())
15337 return StmtError();
15339 // Inner For statement.
15340 SmallVector<Stmt *> InnerBodyStmts;
15341 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15342 InnerBodyStmts.push_back(Body);
15343 CompoundStmt *InnerBody =
15344 CompoundStmt::Create(Context, InnerBodyStmts, FPOptionsOverride(),
15345 Body->getBeginLoc(), Body->getEndLoc());
15346 ForStmt *InnerFor = new (Context)
15347 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
15348 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
15349 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15351 // Unroll metadata for the inner loop.
15352 // This needs to take into account the remainder portion of the unrolled loop,
15353 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
15354 // supports multiple loop exits. Instead, unroll using a factor equivalent to
15355 // the maximum trip count, which will also generate a remainder loop. Just
15356 // `unroll(enable)` (which could have been useful if the user has not
15357 // specified a concrete factor; even though the outer loop cannot be
15358 // influenced anymore, would avoid more code bloat than necessary) will refuse
15359 // the loop because "Won't unroll; remainder loop could not be generated when
15360 // assuming runtime trip count". Even if it did work, it must not choose a
15361 // larger unroll factor than the maximum loop length, or it would always just
15362 // execute the remainder loop.
15363 LoopHintAttr *UnrollHintAttr =
15364 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
15365 LoopHintAttr::Numeric, MakeFactorExpr());
15366 AttributedStmt *InnerUnrolled =
15367 AttributedStmt::Create(Context, StartLoc, {UnrollHintAttr}, InnerFor);
15369 // Outer For init-statement: auto .unrolled.iv = 0
15370 AddInitializerToDecl(
15371 OuterIVDecl, ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15372 /*DirectInit=*/false);
15373 StmtResult OuterInit = new (Context)
15374 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15375 if (!OuterInit.isUsable())
15376 return StmtError();
15378 // Outer For cond-expression: .unrolled.iv < NumIterations
15379 ExprResult OuterConde =
15380 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, MakeOuterRef(),
15381 MakeNumIterations());
15382 if (!OuterConde.isUsable())
15383 return StmtError();
15385 // Outer For incr-statement: .unrolled.iv += Factor
15386 ExprResult OuterIncr =
15387 BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15388 MakeOuterRef(), MakeFactorExpr());
15389 if (!OuterIncr.isUsable())
15390 return StmtError();
15392 // Outer For statement.
15393 ForStmt *OuterFor = new (Context)
15394 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
15395 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
15396 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15398 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15399 NumGeneratedLoops, OuterFor,
15400 buildPreInits(Context, PreInits));
15403 OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
15404 SourceLocation StartLoc,
15405 SourceLocation LParenLoc,
15406 SourceLocation EndLoc) {
15407 OMPClause *Res = nullptr;
15408 switch (Kind) {
15409 case OMPC_final:
15410 Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
15411 break;
15412 case OMPC_num_threads:
15413 Res = ActOnOpenMPNumThreadsClause(Expr, StartLoc, LParenLoc, EndLoc);
15414 break;
15415 case OMPC_safelen:
15416 Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
15417 break;
15418 case OMPC_simdlen:
15419 Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
15420 break;
15421 case OMPC_allocator:
15422 Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
15423 break;
15424 case OMPC_collapse:
15425 Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
15426 break;
15427 case OMPC_ordered:
15428 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
15429 break;
15430 case OMPC_num_teams:
15431 Res = ActOnOpenMPNumTeamsClause(Expr, StartLoc, LParenLoc, EndLoc);
15432 break;
15433 case OMPC_thread_limit:
15434 Res = ActOnOpenMPThreadLimitClause(Expr, StartLoc, LParenLoc, EndLoc);
15435 break;
15436 case OMPC_priority:
15437 Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
15438 break;
15439 case OMPC_hint:
15440 Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
15441 break;
15442 case OMPC_depobj:
15443 Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
15444 break;
15445 case OMPC_detach:
15446 Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
15447 break;
15448 case OMPC_novariants:
15449 Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
15450 break;
15451 case OMPC_nocontext:
15452 Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
15453 break;
15454 case OMPC_filter:
15455 Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
15456 break;
15457 case OMPC_partial:
15458 Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
15459 break;
15460 case OMPC_message:
15461 Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc);
15462 break;
15463 case OMPC_align:
15464 Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
15465 break;
15466 case OMPC_ompx_dyn_cgroup_mem:
15467 Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc);
15468 break;
15469 case OMPC_grainsize:
15470 case OMPC_num_tasks:
15471 case OMPC_device:
15472 case OMPC_if:
15473 case OMPC_default:
15474 case OMPC_proc_bind:
15475 case OMPC_schedule:
15476 case OMPC_private:
15477 case OMPC_firstprivate:
15478 case OMPC_lastprivate:
15479 case OMPC_shared:
15480 case OMPC_reduction:
15481 case OMPC_task_reduction:
15482 case OMPC_in_reduction:
15483 case OMPC_linear:
15484 case OMPC_aligned:
15485 case OMPC_copyin:
15486 case OMPC_copyprivate:
15487 case OMPC_nowait:
15488 case OMPC_untied:
15489 case OMPC_mergeable:
15490 case OMPC_threadprivate:
15491 case OMPC_sizes:
15492 case OMPC_allocate:
15493 case OMPC_flush:
15494 case OMPC_read:
15495 case OMPC_write:
15496 case OMPC_update:
15497 case OMPC_capture:
15498 case OMPC_compare:
15499 case OMPC_seq_cst:
15500 case OMPC_acq_rel:
15501 case OMPC_acquire:
15502 case OMPC_release:
15503 case OMPC_relaxed:
15504 case OMPC_depend:
15505 case OMPC_threads:
15506 case OMPC_simd:
15507 case OMPC_map:
15508 case OMPC_nogroup:
15509 case OMPC_dist_schedule:
15510 case OMPC_defaultmap:
15511 case OMPC_unknown:
15512 case OMPC_uniform:
15513 case OMPC_to:
15514 case OMPC_from:
15515 case OMPC_use_device_ptr:
15516 case OMPC_use_device_addr:
15517 case OMPC_is_device_ptr:
15518 case OMPC_unified_address:
15519 case OMPC_unified_shared_memory:
15520 case OMPC_reverse_offload:
15521 case OMPC_dynamic_allocators:
15522 case OMPC_atomic_default_mem_order:
15523 case OMPC_device_type:
15524 case OMPC_match:
15525 case OMPC_nontemporal:
15526 case OMPC_order:
15527 case OMPC_at:
15528 case OMPC_severity:
15529 case OMPC_destroy:
15530 case OMPC_inclusive:
15531 case OMPC_exclusive:
15532 case OMPC_uses_allocators:
15533 case OMPC_affinity:
15534 case OMPC_when:
15535 case OMPC_bind:
15536 default:
15537 llvm_unreachable("Clause is not allowed.");
15539 return Res;
15542 // An OpenMP directive such as 'target parallel' has two captured regions:
15543 // for the 'target' and 'parallel' respectively. This function returns
15544 // the region in which to capture expressions associated with a clause.
15545 // A return value of OMPD_unknown signifies that the expression should not
15546 // be captured.
15547 static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
15548 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
15549 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
15550 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15551 switch (CKind) {
15552 case OMPC_if:
15553 switch (DKind) {
15554 case OMPD_target_parallel_for_simd:
15555 if (OpenMPVersion >= 50 &&
15556 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15557 CaptureRegion = OMPD_parallel;
15558 break;
15560 [[fallthrough]];
15561 case OMPD_target_parallel:
15562 case OMPD_target_parallel_for:
15563 case OMPD_target_parallel_loop:
15564 // If this clause applies to the nested 'parallel' region, capture within
15565 // the 'target' region, otherwise do not capture.
15566 if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel)
15567 CaptureRegion = OMPD_target;
15568 break;
15569 case OMPD_target_teams_distribute_parallel_for_simd:
15570 if (OpenMPVersion >= 50 &&
15571 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15572 CaptureRegion = OMPD_parallel;
15573 break;
15575 [[fallthrough]];
15576 case OMPD_target_teams_loop:
15577 case OMPD_target_teams_distribute_parallel_for:
15578 // If this clause applies to the nested 'parallel' region, capture within
15579 // the 'teams' region, otherwise do not capture.
15580 if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel)
15581 CaptureRegion = OMPD_teams;
15582 break;
15583 case OMPD_teams_distribute_parallel_for_simd:
15584 if (OpenMPVersion >= 50 &&
15585 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15586 CaptureRegion = OMPD_parallel;
15587 break;
15589 [[fallthrough]];
15590 case OMPD_teams_distribute_parallel_for:
15591 CaptureRegion = OMPD_teams;
15592 break;
15593 case OMPD_target_update:
15594 case OMPD_target_enter_data:
15595 case OMPD_target_exit_data:
15596 CaptureRegion = OMPD_task;
15597 break;
15598 case OMPD_parallel_masked_taskloop:
15599 if (NameModifier == OMPD_unknown || NameModifier == OMPD_taskloop)
15600 CaptureRegion = OMPD_parallel;
15601 break;
15602 case OMPD_parallel_master_taskloop:
15603 if (NameModifier == OMPD_unknown || NameModifier == OMPD_taskloop)
15604 CaptureRegion = OMPD_parallel;
15605 break;
15606 case OMPD_parallel_masked_taskloop_simd:
15607 if ((OpenMPVersion <= 45 && NameModifier == OMPD_unknown) ||
15608 NameModifier == OMPD_taskloop) {
15609 CaptureRegion = OMPD_parallel;
15610 break;
15612 if (OpenMPVersion <= 45)
15613 break;
15614 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15615 CaptureRegion = OMPD_taskloop;
15616 break;
15617 case OMPD_parallel_master_taskloop_simd:
15618 if ((OpenMPVersion <= 45 && NameModifier == OMPD_unknown) ||
15619 NameModifier == OMPD_taskloop) {
15620 CaptureRegion = OMPD_parallel;
15621 break;
15623 if (OpenMPVersion <= 45)
15624 break;
15625 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15626 CaptureRegion = OMPD_taskloop;
15627 break;
15628 case OMPD_parallel_for_simd:
15629 if (OpenMPVersion <= 45)
15630 break;
15631 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15632 CaptureRegion = OMPD_parallel;
15633 break;
15634 case OMPD_taskloop_simd:
15635 case OMPD_master_taskloop_simd:
15636 case OMPD_masked_taskloop_simd:
15637 if (OpenMPVersion <= 45)
15638 break;
15639 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15640 CaptureRegion = OMPD_taskloop;
15641 break;
15642 case OMPD_distribute_parallel_for_simd:
15643 if (OpenMPVersion <= 45)
15644 break;
15645 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15646 CaptureRegion = OMPD_parallel;
15647 break;
15648 case OMPD_target_simd:
15649 if (OpenMPVersion >= 50 &&
15650 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd))
15651 CaptureRegion = OMPD_target;
15652 break;
15653 case OMPD_teams_distribute_simd:
15654 case OMPD_target_teams_distribute_simd:
15655 if (OpenMPVersion >= 50 &&
15656 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd))
15657 CaptureRegion = OMPD_teams;
15658 break;
15659 case OMPD_cancel:
15660 case OMPD_parallel:
15661 case OMPD_parallel_master:
15662 case OMPD_parallel_masked:
15663 case OMPD_parallel_sections:
15664 case OMPD_parallel_for:
15665 case OMPD_parallel_loop:
15666 case OMPD_target:
15667 case OMPD_target_teams:
15668 case OMPD_target_teams_distribute:
15669 case OMPD_distribute_parallel_for:
15670 case OMPD_task:
15671 case OMPD_taskloop:
15672 case OMPD_master_taskloop:
15673 case OMPD_masked_taskloop:
15674 case OMPD_target_data:
15675 case OMPD_simd:
15676 case OMPD_for_simd:
15677 case OMPD_distribute_simd:
15678 // Do not capture if-clause expressions.
15679 break;
15680 case OMPD_threadprivate:
15681 case OMPD_allocate:
15682 case OMPD_taskyield:
15683 case OMPD_error:
15684 case OMPD_barrier:
15685 case OMPD_taskwait:
15686 case OMPD_cancellation_point:
15687 case OMPD_flush:
15688 case OMPD_depobj:
15689 case OMPD_scan:
15690 case OMPD_declare_reduction:
15691 case OMPD_declare_mapper:
15692 case OMPD_declare_simd:
15693 case OMPD_declare_variant:
15694 case OMPD_begin_declare_variant:
15695 case OMPD_end_declare_variant:
15696 case OMPD_declare_target:
15697 case OMPD_end_declare_target:
15698 case OMPD_loop:
15699 case OMPD_teams_loop:
15700 case OMPD_teams:
15701 case OMPD_tile:
15702 case OMPD_unroll:
15703 case OMPD_for:
15704 case OMPD_sections:
15705 case OMPD_section:
15706 case OMPD_single:
15707 case OMPD_master:
15708 case OMPD_masked:
15709 case OMPD_critical:
15710 case OMPD_taskgroup:
15711 case OMPD_distribute:
15712 case OMPD_ordered:
15713 case OMPD_atomic:
15714 case OMPD_teams_distribute:
15715 case OMPD_requires:
15716 case OMPD_metadirective:
15717 llvm_unreachable("Unexpected OpenMP directive with if-clause");
15718 case OMPD_unknown:
15719 default:
15720 llvm_unreachable("Unknown OpenMP directive");
15722 break;
15723 case OMPC_num_threads:
15724 switch (DKind) {
15725 case OMPD_target_parallel:
15726 case OMPD_target_parallel_for:
15727 case OMPD_target_parallel_for_simd:
15728 case OMPD_target_parallel_loop:
15729 CaptureRegion = OMPD_target;
15730 break;
15731 case OMPD_teams_distribute_parallel_for:
15732 case OMPD_teams_distribute_parallel_for_simd:
15733 case OMPD_target_teams_distribute_parallel_for:
15734 case OMPD_target_teams_distribute_parallel_for_simd:
15735 CaptureRegion = OMPD_teams;
15736 break;
15737 case OMPD_parallel:
15738 case OMPD_parallel_master:
15739 case OMPD_parallel_masked:
15740 case OMPD_parallel_sections:
15741 case OMPD_parallel_for:
15742 case OMPD_parallel_for_simd:
15743 case OMPD_parallel_loop:
15744 case OMPD_distribute_parallel_for:
15745 case OMPD_distribute_parallel_for_simd:
15746 case OMPD_parallel_master_taskloop:
15747 case OMPD_parallel_masked_taskloop:
15748 case OMPD_parallel_master_taskloop_simd:
15749 case OMPD_parallel_masked_taskloop_simd:
15750 // Do not capture num_threads-clause expressions.
15751 break;
15752 case OMPD_target_data:
15753 case OMPD_target_enter_data:
15754 case OMPD_target_exit_data:
15755 case OMPD_target_update:
15756 case OMPD_target:
15757 case OMPD_target_simd:
15758 case OMPD_target_teams:
15759 case OMPD_target_teams_distribute:
15760 case OMPD_target_teams_distribute_simd:
15761 case OMPD_cancel:
15762 case OMPD_task:
15763 case OMPD_taskloop:
15764 case OMPD_taskloop_simd:
15765 case OMPD_master_taskloop:
15766 case OMPD_masked_taskloop:
15767 case OMPD_master_taskloop_simd:
15768 case OMPD_masked_taskloop_simd:
15769 case OMPD_threadprivate:
15770 case OMPD_allocate:
15771 case OMPD_taskyield:
15772 case OMPD_error:
15773 case OMPD_barrier:
15774 case OMPD_taskwait:
15775 case OMPD_cancellation_point:
15776 case OMPD_flush:
15777 case OMPD_depobj:
15778 case OMPD_scan:
15779 case OMPD_declare_reduction:
15780 case OMPD_declare_mapper:
15781 case OMPD_declare_simd:
15782 case OMPD_declare_variant:
15783 case OMPD_begin_declare_variant:
15784 case OMPD_end_declare_variant:
15785 case OMPD_declare_target:
15786 case OMPD_end_declare_target:
15787 case OMPD_loop:
15788 case OMPD_teams_loop:
15789 case OMPD_target_teams_loop:
15790 case OMPD_teams:
15791 case OMPD_simd:
15792 case OMPD_tile:
15793 case OMPD_unroll:
15794 case OMPD_for:
15795 case OMPD_for_simd:
15796 case OMPD_sections:
15797 case OMPD_section:
15798 case OMPD_single:
15799 case OMPD_master:
15800 case OMPD_masked:
15801 case OMPD_critical:
15802 case OMPD_taskgroup:
15803 case OMPD_distribute:
15804 case OMPD_ordered:
15805 case OMPD_atomic:
15806 case OMPD_distribute_simd:
15807 case OMPD_teams_distribute:
15808 case OMPD_teams_distribute_simd:
15809 case OMPD_requires:
15810 case OMPD_metadirective:
15811 llvm_unreachable("Unexpected OpenMP directive with num_threads-clause");
15812 case OMPD_unknown:
15813 default:
15814 llvm_unreachable("Unknown OpenMP directive");
15816 break;
15817 case OMPC_num_teams:
15818 switch (DKind) {
15819 case OMPD_target_teams:
15820 case OMPD_target_teams_distribute:
15821 case OMPD_target_teams_distribute_simd:
15822 case OMPD_target_teams_distribute_parallel_for:
15823 case OMPD_target_teams_distribute_parallel_for_simd:
15824 case OMPD_target_teams_loop:
15825 CaptureRegion = OMPD_target;
15826 break;
15827 case OMPD_teams_distribute_parallel_for:
15828 case OMPD_teams_distribute_parallel_for_simd:
15829 case OMPD_teams:
15830 case OMPD_teams_distribute:
15831 case OMPD_teams_distribute_simd:
15832 case OMPD_teams_loop:
15833 // Do not capture num_teams-clause expressions.
15834 break;
15835 case OMPD_distribute_parallel_for:
15836 case OMPD_distribute_parallel_for_simd:
15837 case OMPD_task:
15838 case OMPD_taskloop:
15839 case OMPD_taskloop_simd:
15840 case OMPD_master_taskloop:
15841 case OMPD_masked_taskloop:
15842 case OMPD_master_taskloop_simd:
15843 case OMPD_masked_taskloop_simd:
15844 case OMPD_parallel_master_taskloop:
15845 case OMPD_parallel_masked_taskloop:
15846 case OMPD_parallel_master_taskloop_simd:
15847 case OMPD_parallel_masked_taskloop_simd:
15848 case OMPD_target_data:
15849 case OMPD_target_enter_data:
15850 case OMPD_target_exit_data:
15851 case OMPD_target_update:
15852 case OMPD_cancel:
15853 case OMPD_parallel:
15854 case OMPD_parallel_master:
15855 case OMPD_parallel_masked:
15856 case OMPD_parallel_sections:
15857 case OMPD_parallel_for:
15858 case OMPD_parallel_for_simd:
15859 case OMPD_parallel_loop:
15860 case OMPD_target:
15861 case OMPD_target_simd:
15862 case OMPD_target_parallel:
15863 case OMPD_target_parallel_for:
15864 case OMPD_target_parallel_for_simd:
15865 case OMPD_target_parallel_loop:
15866 case OMPD_threadprivate:
15867 case OMPD_allocate:
15868 case OMPD_taskyield:
15869 case OMPD_error:
15870 case OMPD_barrier:
15871 case OMPD_taskwait:
15872 case OMPD_cancellation_point:
15873 case OMPD_flush:
15874 case OMPD_depobj:
15875 case OMPD_scan:
15876 case OMPD_declare_reduction:
15877 case OMPD_declare_mapper:
15878 case OMPD_declare_simd:
15879 case OMPD_declare_variant:
15880 case OMPD_begin_declare_variant:
15881 case OMPD_end_declare_variant:
15882 case OMPD_declare_target:
15883 case OMPD_end_declare_target:
15884 case OMPD_loop:
15885 case OMPD_simd:
15886 case OMPD_tile:
15887 case OMPD_unroll:
15888 case OMPD_for:
15889 case OMPD_for_simd:
15890 case OMPD_sections:
15891 case OMPD_section:
15892 case OMPD_single:
15893 case OMPD_master:
15894 case OMPD_masked:
15895 case OMPD_critical:
15896 case OMPD_taskgroup:
15897 case OMPD_distribute:
15898 case OMPD_ordered:
15899 case OMPD_atomic:
15900 case OMPD_distribute_simd:
15901 case OMPD_requires:
15902 case OMPD_metadirective:
15903 llvm_unreachable("Unexpected OpenMP directive with num_teams-clause");
15904 case OMPD_unknown:
15905 default:
15906 llvm_unreachable("Unknown OpenMP directive");
15908 break;
15909 case OMPC_thread_limit:
15910 switch (DKind) {
15911 case OMPD_target:
15912 case OMPD_target_teams:
15913 case OMPD_target_teams_distribute:
15914 case OMPD_target_teams_distribute_simd:
15915 case OMPD_target_teams_distribute_parallel_for:
15916 case OMPD_target_teams_distribute_parallel_for_simd:
15917 case OMPD_target_teams_loop:
15918 case OMPD_target_simd:
15919 case OMPD_target_parallel:
15920 case OMPD_target_parallel_for:
15921 case OMPD_target_parallel_for_simd:
15922 case OMPD_target_parallel_loop:
15923 CaptureRegion = OMPD_target;
15924 break;
15925 case OMPD_teams_distribute_parallel_for:
15926 case OMPD_teams_distribute_parallel_for_simd:
15927 case OMPD_teams:
15928 case OMPD_teams_distribute:
15929 case OMPD_teams_distribute_simd:
15930 case OMPD_teams_loop:
15931 // Do not capture thread_limit-clause expressions.
15932 break;
15933 case OMPD_distribute_parallel_for:
15934 case OMPD_distribute_parallel_for_simd:
15935 case OMPD_task:
15936 case OMPD_taskloop:
15937 case OMPD_taskloop_simd:
15938 case OMPD_master_taskloop:
15939 case OMPD_masked_taskloop:
15940 case OMPD_master_taskloop_simd:
15941 case OMPD_masked_taskloop_simd:
15942 case OMPD_parallel_master_taskloop:
15943 case OMPD_parallel_masked_taskloop:
15944 case OMPD_parallel_master_taskloop_simd:
15945 case OMPD_parallel_masked_taskloop_simd:
15946 case OMPD_target_data:
15947 case OMPD_target_enter_data:
15948 case OMPD_target_exit_data:
15949 case OMPD_target_update:
15950 case OMPD_cancel:
15951 case OMPD_parallel:
15952 case OMPD_parallel_master:
15953 case OMPD_parallel_masked:
15954 case OMPD_parallel_sections:
15955 case OMPD_parallel_for:
15956 case OMPD_parallel_for_simd:
15957 case OMPD_parallel_loop:
15958 case OMPD_threadprivate:
15959 case OMPD_allocate:
15960 case OMPD_taskyield:
15961 case OMPD_error:
15962 case OMPD_barrier:
15963 case OMPD_taskwait:
15964 case OMPD_cancellation_point:
15965 case OMPD_flush:
15966 case OMPD_depobj:
15967 case OMPD_scan:
15968 case OMPD_declare_reduction:
15969 case OMPD_declare_mapper:
15970 case OMPD_declare_simd:
15971 case OMPD_declare_variant:
15972 case OMPD_begin_declare_variant:
15973 case OMPD_end_declare_variant:
15974 case OMPD_declare_target:
15975 case OMPD_end_declare_target:
15976 case OMPD_loop:
15977 case OMPD_simd:
15978 case OMPD_tile:
15979 case OMPD_unroll:
15980 case OMPD_for:
15981 case OMPD_for_simd:
15982 case OMPD_sections:
15983 case OMPD_section:
15984 case OMPD_single:
15985 case OMPD_master:
15986 case OMPD_masked:
15987 case OMPD_critical:
15988 case OMPD_taskgroup:
15989 case OMPD_distribute:
15990 case OMPD_ordered:
15991 case OMPD_atomic:
15992 case OMPD_distribute_simd:
15993 case OMPD_requires:
15994 case OMPD_metadirective:
15995 llvm_unreachable("Unexpected OpenMP directive with thread_limit-clause");
15996 case OMPD_unknown:
15997 default:
15998 llvm_unreachable("Unknown OpenMP directive");
16000 break;
16001 case OMPC_schedule:
16002 switch (DKind) {
16003 case OMPD_parallel_for:
16004 case OMPD_parallel_for_simd:
16005 case OMPD_distribute_parallel_for:
16006 case OMPD_distribute_parallel_for_simd:
16007 case OMPD_teams_distribute_parallel_for:
16008 case OMPD_teams_distribute_parallel_for_simd:
16009 case OMPD_target_parallel_for:
16010 case OMPD_target_parallel_for_simd:
16011 case OMPD_target_teams_distribute_parallel_for:
16012 case OMPD_target_teams_distribute_parallel_for_simd:
16013 CaptureRegion = OMPD_parallel;
16014 break;
16015 case OMPD_for:
16016 case OMPD_for_simd:
16017 // Do not capture schedule-clause expressions.
16018 break;
16019 case OMPD_task:
16020 case OMPD_taskloop:
16021 case OMPD_taskloop_simd:
16022 case OMPD_master_taskloop:
16023 case OMPD_masked_taskloop:
16024 case OMPD_master_taskloop_simd:
16025 case OMPD_masked_taskloop_simd:
16026 case OMPD_parallel_master_taskloop:
16027 case OMPD_parallel_masked_taskloop:
16028 case OMPD_parallel_master_taskloop_simd:
16029 case OMPD_parallel_masked_taskloop_simd:
16030 case OMPD_target_data:
16031 case OMPD_target_enter_data:
16032 case OMPD_target_exit_data:
16033 case OMPD_target_update:
16034 case OMPD_teams:
16035 case OMPD_teams_distribute:
16036 case OMPD_teams_distribute_simd:
16037 case OMPD_target_teams_distribute:
16038 case OMPD_target_teams_distribute_simd:
16039 case OMPD_target:
16040 case OMPD_target_simd:
16041 case OMPD_target_parallel:
16042 case OMPD_cancel:
16043 case OMPD_parallel:
16044 case OMPD_parallel_master:
16045 case OMPD_parallel_masked:
16046 case OMPD_parallel_sections:
16047 case OMPD_threadprivate:
16048 case OMPD_allocate:
16049 case OMPD_taskyield:
16050 case OMPD_error:
16051 case OMPD_barrier:
16052 case OMPD_taskwait:
16053 case OMPD_cancellation_point:
16054 case OMPD_flush:
16055 case OMPD_depobj:
16056 case OMPD_scan:
16057 case OMPD_declare_reduction:
16058 case OMPD_declare_mapper:
16059 case OMPD_declare_simd:
16060 case OMPD_declare_variant:
16061 case OMPD_begin_declare_variant:
16062 case OMPD_end_declare_variant:
16063 case OMPD_declare_target:
16064 case OMPD_end_declare_target:
16065 case OMPD_loop:
16066 case OMPD_teams_loop:
16067 case OMPD_target_teams_loop:
16068 case OMPD_parallel_loop:
16069 case OMPD_target_parallel_loop:
16070 case OMPD_simd:
16071 case OMPD_tile:
16072 case OMPD_unroll:
16073 case OMPD_sections:
16074 case OMPD_section:
16075 case OMPD_single:
16076 case OMPD_master:
16077 case OMPD_masked:
16078 case OMPD_critical:
16079 case OMPD_taskgroup:
16080 case OMPD_distribute:
16081 case OMPD_ordered:
16082 case OMPD_atomic:
16083 case OMPD_distribute_simd:
16084 case OMPD_target_teams:
16085 case OMPD_requires:
16086 case OMPD_metadirective:
16087 llvm_unreachable("Unexpected OpenMP directive with schedule clause");
16088 case OMPD_unknown:
16089 default:
16090 llvm_unreachable("Unknown OpenMP directive");
16092 break;
16093 case OMPC_dist_schedule:
16094 switch (DKind) {
16095 case OMPD_teams_distribute_parallel_for:
16096 case OMPD_teams_distribute_parallel_for_simd:
16097 case OMPD_teams_distribute:
16098 case OMPD_teams_distribute_simd:
16099 case OMPD_target_teams_distribute_parallel_for:
16100 case OMPD_target_teams_distribute_parallel_for_simd:
16101 case OMPD_target_teams_distribute:
16102 case OMPD_target_teams_distribute_simd:
16103 CaptureRegion = OMPD_teams;
16104 break;
16105 case OMPD_distribute_parallel_for:
16106 case OMPD_distribute_parallel_for_simd:
16107 case OMPD_distribute:
16108 case OMPD_distribute_simd:
16109 // Do not capture dist_schedule-clause expressions.
16110 break;
16111 case OMPD_parallel_for:
16112 case OMPD_parallel_for_simd:
16113 case OMPD_target_parallel_for_simd:
16114 case OMPD_target_parallel_for:
16115 case OMPD_task:
16116 case OMPD_taskloop:
16117 case OMPD_taskloop_simd:
16118 case OMPD_master_taskloop:
16119 case OMPD_masked_taskloop:
16120 case OMPD_master_taskloop_simd:
16121 case OMPD_masked_taskloop_simd:
16122 case OMPD_parallel_master_taskloop:
16123 case OMPD_parallel_masked_taskloop:
16124 case OMPD_parallel_master_taskloop_simd:
16125 case OMPD_parallel_masked_taskloop_simd:
16126 case OMPD_target_data:
16127 case OMPD_target_enter_data:
16128 case OMPD_target_exit_data:
16129 case OMPD_target_update:
16130 case OMPD_teams:
16131 case OMPD_target:
16132 case OMPD_target_simd:
16133 case OMPD_target_parallel:
16134 case OMPD_cancel:
16135 case OMPD_parallel:
16136 case OMPD_parallel_master:
16137 case OMPD_parallel_masked:
16138 case OMPD_parallel_sections:
16139 case OMPD_threadprivate:
16140 case OMPD_allocate:
16141 case OMPD_taskyield:
16142 case OMPD_error:
16143 case OMPD_barrier:
16144 case OMPD_taskwait:
16145 case OMPD_cancellation_point:
16146 case OMPD_flush:
16147 case OMPD_depobj:
16148 case OMPD_scan:
16149 case OMPD_declare_reduction:
16150 case OMPD_declare_mapper:
16151 case OMPD_declare_simd:
16152 case OMPD_declare_variant:
16153 case OMPD_begin_declare_variant:
16154 case OMPD_end_declare_variant:
16155 case OMPD_declare_target:
16156 case OMPD_end_declare_target:
16157 case OMPD_loop:
16158 case OMPD_teams_loop:
16159 case OMPD_target_teams_loop:
16160 case OMPD_parallel_loop:
16161 case OMPD_target_parallel_loop:
16162 case OMPD_simd:
16163 case OMPD_tile:
16164 case OMPD_unroll:
16165 case OMPD_for:
16166 case OMPD_for_simd:
16167 case OMPD_sections:
16168 case OMPD_section:
16169 case OMPD_single:
16170 case OMPD_master:
16171 case OMPD_masked:
16172 case OMPD_critical:
16173 case OMPD_taskgroup:
16174 case OMPD_ordered:
16175 case OMPD_atomic:
16176 case OMPD_target_teams:
16177 case OMPD_requires:
16178 case OMPD_metadirective:
16179 llvm_unreachable("Unexpected OpenMP directive with dist_schedule clause");
16180 case OMPD_unknown:
16181 default:
16182 llvm_unreachable("Unknown OpenMP directive");
16184 break;
16185 case OMPC_ompx_dyn_cgroup_mem:
16186 switch (DKind) {
16187 case OMPD_target:
16188 case OMPD_target_simd:
16189 case OMPD_target_teams:
16190 case OMPD_target_parallel:
16191 case OMPD_target_teams_distribute:
16192 case OMPD_target_teams_distribute_simd:
16193 case OMPD_target_parallel_for:
16194 case OMPD_target_parallel_for_simd:
16195 case OMPD_target_parallel_loop:
16196 case OMPD_target_teams_distribute_parallel_for:
16197 case OMPD_target_teams_distribute_parallel_for_simd:
16198 case OMPD_target_teams_loop:
16199 CaptureRegion = OMPD_target;
16200 break;
16201 default:
16202 llvm_unreachable("Unknown OpenMP directive");
16204 break;
16205 case OMPC_device:
16206 switch (DKind) {
16207 case OMPD_target_update:
16208 case OMPD_target_enter_data:
16209 case OMPD_target_exit_data:
16210 case OMPD_target:
16211 case OMPD_target_simd:
16212 case OMPD_target_teams:
16213 case OMPD_target_parallel:
16214 case OMPD_target_teams_distribute:
16215 case OMPD_target_teams_distribute_simd:
16216 case OMPD_target_parallel_for:
16217 case OMPD_target_parallel_for_simd:
16218 case OMPD_target_parallel_loop:
16219 case OMPD_target_teams_distribute_parallel_for:
16220 case OMPD_target_teams_distribute_parallel_for_simd:
16221 case OMPD_target_teams_loop:
16222 case OMPD_dispatch:
16223 CaptureRegion = OMPD_task;
16224 break;
16225 case OMPD_target_data:
16226 case OMPD_interop:
16227 // Do not capture device-clause expressions.
16228 break;
16229 case OMPD_teams_distribute_parallel_for:
16230 case OMPD_teams_distribute_parallel_for_simd:
16231 case OMPD_teams:
16232 case OMPD_teams_distribute:
16233 case OMPD_teams_distribute_simd:
16234 case OMPD_distribute_parallel_for:
16235 case OMPD_distribute_parallel_for_simd:
16236 case OMPD_task:
16237 case OMPD_taskloop:
16238 case OMPD_taskloop_simd:
16239 case OMPD_master_taskloop:
16240 case OMPD_masked_taskloop:
16241 case OMPD_master_taskloop_simd:
16242 case OMPD_masked_taskloop_simd:
16243 case OMPD_parallel_master_taskloop:
16244 case OMPD_parallel_masked_taskloop:
16245 case OMPD_parallel_master_taskloop_simd:
16246 case OMPD_parallel_masked_taskloop_simd:
16247 case OMPD_cancel:
16248 case OMPD_parallel:
16249 case OMPD_parallel_master:
16250 case OMPD_parallel_masked:
16251 case OMPD_parallel_sections:
16252 case OMPD_parallel_for:
16253 case OMPD_parallel_for_simd:
16254 case OMPD_threadprivate:
16255 case OMPD_allocate:
16256 case OMPD_taskyield:
16257 case OMPD_error:
16258 case OMPD_barrier:
16259 case OMPD_taskwait:
16260 case OMPD_cancellation_point:
16261 case OMPD_flush:
16262 case OMPD_depobj:
16263 case OMPD_scan:
16264 case OMPD_declare_reduction:
16265 case OMPD_declare_mapper:
16266 case OMPD_declare_simd:
16267 case OMPD_declare_variant:
16268 case OMPD_begin_declare_variant:
16269 case OMPD_end_declare_variant:
16270 case OMPD_declare_target:
16271 case OMPD_end_declare_target:
16272 case OMPD_loop:
16273 case OMPD_teams_loop:
16274 case OMPD_parallel_loop:
16275 case OMPD_simd:
16276 case OMPD_tile:
16277 case OMPD_unroll:
16278 case OMPD_for:
16279 case OMPD_for_simd:
16280 case OMPD_sections:
16281 case OMPD_section:
16282 case OMPD_single:
16283 case OMPD_master:
16284 case OMPD_masked:
16285 case OMPD_critical:
16286 case OMPD_taskgroup:
16287 case OMPD_distribute:
16288 case OMPD_ordered:
16289 case OMPD_atomic:
16290 case OMPD_distribute_simd:
16291 case OMPD_requires:
16292 case OMPD_metadirective:
16293 llvm_unreachable("Unexpected OpenMP directive with device-clause");
16294 case OMPD_unknown:
16295 default:
16296 llvm_unreachable("Unknown OpenMP directive");
16298 break;
16299 case OMPC_grainsize:
16300 case OMPC_num_tasks:
16301 case OMPC_final:
16302 case OMPC_priority:
16303 switch (DKind) {
16304 case OMPD_task:
16305 case OMPD_taskloop:
16306 case OMPD_taskloop_simd:
16307 case OMPD_master_taskloop:
16308 case OMPD_masked_taskloop:
16309 case OMPD_master_taskloop_simd:
16310 case OMPD_masked_taskloop_simd:
16311 break;
16312 case OMPD_parallel_masked_taskloop:
16313 case OMPD_parallel_masked_taskloop_simd:
16314 case OMPD_parallel_master_taskloop:
16315 case OMPD_parallel_master_taskloop_simd:
16316 CaptureRegion = OMPD_parallel;
16317 break;
16318 case OMPD_target_update:
16319 case OMPD_target_enter_data:
16320 case OMPD_target_exit_data:
16321 case OMPD_target:
16322 case OMPD_target_simd:
16323 case OMPD_target_teams:
16324 case OMPD_target_parallel:
16325 case OMPD_target_teams_distribute:
16326 case OMPD_target_teams_distribute_simd:
16327 case OMPD_target_parallel_for:
16328 case OMPD_target_parallel_for_simd:
16329 case OMPD_target_teams_distribute_parallel_for:
16330 case OMPD_target_teams_distribute_parallel_for_simd:
16331 case OMPD_target_data:
16332 case OMPD_teams_distribute_parallel_for:
16333 case OMPD_teams_distribute_parallel_for_simd:
16334 case OMPD_teams:
16335 case OMPD_teams_distribute:
16336 case OMPD_teams_distribute_simd:
16337 case OMPD_distribute_parallel_for:
16338 case OMPD_distribute_parallel_for_simd:
16339 case OMPD_cancel:
16340 case OMPD_parallel:
16341 case OMPD_parallel_master:
16342 case OMPD_parallel_masked:
16343 case OMPD_parallel_sections:
16344 case OMPD_parallel_for:
16345 case OMPD_parallel_for_simd:
16346 case OMPD_threadprivate:
16347 case OMPD_allocate:
16348 case OMPD_taskyield:
16349 case OMPD_error:
16350 case OMPD_barrier:
16351 case OMPD_taskwait:
16352 case OMPD_cancellation_point:
16353 case OMPD_flush:
16354 case OMPD_depobj:
16355 case OMPD_scan:
16356 case OMPD_declare_reduction:
16357 case OMPD_declare_mapper:
16358 case OMPD_declare_simd:
16359 case OMPD_declare_variant:
16360 case OMPD_begin_declare_variant:
16361 case OMPD_end_declare_variant:
16362 case OMPD_declare_target:
16363 case OMPD_end_declare_target:
16364 case OMPD_loop:
16365 case OMPD_teams_loop:
16366 case OMPD_target_teams_loop:
16367 case OMPD_parallel_loop:
16368 case OMPD_target_parallel_loop:
16369 case OMPD_simd:
16370 case OMPD_tile:
16371 case OMPD_unroll:
16372 case OMPD_for:
16373 case OMPD_for_simd:
16374 case OMPD_sections:
16375 case OMPD_section:
16376 case OMPD_single:
16377 case OMPD_master:
16378 case OMPD_masked:
16379 case OMPD_critical:
16380 case OMPD_taskgroup:
16381 case OMPD_distribute:
16382 case OMPD_ordered:
16383 case OMPD_atomic:
16384 case OMPD_distribute_simd:
16385 case OMPD_requires:
16386 case OMPD_metadirective:
16387 llvm_unreachable("Unexpected OpenMP directive with grainsize-clause");
16388 case OMPD_unknown:
16389 default:
16390 llvm_unreachable("Unknown OpenMP directive");
16392 break;
16393 case OMPC_novariants:
16394 case OMPC_nocontext:
16395 switch (DKind) {
16396 case OMPD_dispatch:
16397 CaptureRegion = OMPD_task;
16398 break;
16399 default:
16400 llvm_unreachable("Unexpected OpenMP directive");
16402 break;
16403 case OMPC_filter:
16404 // Do not capture filter-clause expressions.
16405 break;
16406 case OMPC_when:
16407 if (DKind == OMPD_metadirective) {
16408 CaptureRegion = OMPD_metadirective;
16409 } else if (DKind == OMPD_unknown) {
16410 llvm_unreachable("Unknown OpenMP directive");
16411 } else {
16412 llvm_unreachable("Unexpected OpenMP directive with when clause");
16414 break;
16415 case OMPC_firstprivate:
16416 case OMPC_lastprivate:
16417 case OMPC_reduction:
16418 case OMPC_task_reduction:
16419 case OMPC_in_reduction:
16420 case OMPC_linear:
16421 case OMPC_default:
16422 case OMPC_proc_bind:
16423 case OMPC_safelen:
16424 case OMPC_simdlen:
16425 case OMPC_sizes:
16426 case OMPC_allocator:
16427 case OMPC_collapse:
16428 case OMPC_private:
16429 case OMPC_shared:
16430 case OMPC_aligned:
16431 case OMPC_copyin:
16432 case OMPC_copyprivate:
16433 case OMPC_ordered:
16434 case OMPC_nowait:
16435 case OMPC_untied:
16436 case OMPC_mergeable:
16437 case OMPC_threadprivate:
16438 case OMPC_allocate:
16439 case OMPC_flush:
16440 case OMPC_depobj:
16441 case OMPC_read:
16442 case OMPC_write:
16443 case OMPC_update:
16444 case OMPC_capture:
16445 case OMPC_compare:
16446 case OMPC_seq_cst:
16447 case OMPC_acq_rel:
16448 case OMPC_acquire:
16449 case OMPC_release:
16450 case OMPC_relaxed:
16451 case OMPC_depend:
16452 case OMPC_threads:
16453 case OMPC_simd:
16454 case OMPC_map:
16455 case OMPC_nogroup:
16456 case OMPC_hint:
16457 case OMPC_defaultmap:
16458 case OMPC_unknown:
16459 case OMPC_uniform:
16460 case OMPC_to:
16461 case OMPC_from:
16462 case OMPC_use_device_ptr:
16463 case OMPC_use_device_addr:
16464 case OMPC_is_device_ptr:
16465 case OMPC_unified_address:
16466 case OMPC_unified_shared_memory:
16467 case OMPC_reverse_offload:
16468 case OMPC_dynamic_allocators:
16469 case OMPC_atomic_default_mem_order:
16470 case OMPC_device_type:
16471 case OMPC_match:
16472 case OMPC_nontemporal:
16473 case OMPC_order:
16474 case OMPC_at:
16475 case OMPC_severity:
16476 case OMPC_message:
16477 case OMPC_destroy:
16478 case OMPC_detach:
16479 case OMPC_inclusive:
16480 case OMPC_exclusive:
16481 case OMPC_uses_allocators:
16482 case OMPC_affinity:
16483 case OMPC_bind:
16484 default:
16485 llvm_unreachable("Unexpected OpenMP clause.");
16487 return CaptureRegion;
16490 OMPClause *Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier,
16491 Expr *Condition, SourceLocation StartLoc,
16492 SourceLocation LParenLoc,
16493 SourceLocation NameModifierLoc,
16494 SourceLocation ColonLoc,
16495 SourceLocation EndLoc) {
16496 Expr *ValExpr = Condition;
16497 Stmt *HelperValStmt = nullptr;
16498 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16499 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16500 !Condition->isInstantiationDependent() &&
16501 !Condition->containsUnexpandedParameterPack()) {
16502 ExprResult Val = CheckBooleanCondition(StartLoc, Condition);
16503 if (Val.isInvalid())
16504 return nullptr;
16506 ValExpr = Val.get();
16508 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16509 CaptureRegion = getOpenMPCaptureRegionForClause(
16510 DKind, OMPC_if, LangOpts.OpenMP, NameModifier);
16511 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
16512 ValExpr = MakeFullExpr(ValExpr).get();
16513 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16514 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
16515 HelperValStmt = buildPreInits(Context, Captures);
16519 return new (Context)
16520 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
16521 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
16524 OMPClause *Sema::ActOnOpenMPFinalClause(Expr *Condition,
16525 SourceLocation StartLoc,
16526 SourceLocation LParenLoc,
16527 SourceLocation EndLoc) {
16528 Expr *ValExpr = Condition;
16529 Stmt *HelperValStmt = nullptr;
16530 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16531 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16532 !Condition->isInstantiationDependent() &&
16533 !Condition->containsUnexpandedParameterPack()) {
16534 ExprResult Val = CheckBooleanCondition(StartLoc, Condition);
16535 if (Val.isInvalid())
16536 return nullptr;
16538 ValExpr = MakeFullExpr(Val.get()).get();
16540 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16541 CaptureRegion =
16542 getOpenMPCaptureRegionForClause(DKind, OMPC_final, LangOpts.OpenMP);
16543 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
16544 ValExpr = MakeFullExpr(ValExpr).get();
16545 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16546 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
16547 HelperValStmt = buildPreInits(Context, Captures);
16551 return new (Context) OMPFinalClause(ValExpr, HelperValStmt, CaptureRegion,
16552 StartLoc, LParenLoc, EndLoc);
16555 ExprResult Sema::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc,
16556 Expr *Op) {
16557 if (!Op)
16558 return ExprError();
16560 class IntConvertDiagnoser : public ICEConvertDiagnoser {
16561 public:
16562 IntConvertDiagnoser()
16563 : ICEConvertDiagnoser(/*AllowScopedEnumerations*/ false, false, true) {}
16564 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
16565 QualType T) override {
16566 return S.Diag(Loc, diag::err_omp_not_integral) << T;
16568 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
16569 QualType T) override {
16570 return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
16572 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
16573 QualType T,
16574 QualType ConvTy) override {
16575 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
16577 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
16578 QualType ConvTy) override {
16579 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16580 << ConvTy->isEnumeralType() << ConvTy;
16582 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
16583 QualType T) override {
16584 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
16586 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
16587 QualType ConvTy) override {
16588 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16589 << ConvTy->isEnumeralType() << ConvTy;
16591 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
16592 QualType) override {
16593 llvm_unreachable("conversion functions are permitted");
16595 } ConvertDiagnoser;
16596 return PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
16599 static bool
16600 isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind,
16601 bool StrictlyPositive, bool BuildCapture = false,
16602 OpenMPDirectiveKind DKind = OMPD_unknown,
16603 OpenMPDirectiveKind *CaptureRegion = nullptr,
16604 Stmt **HelperValStmt = nullptr) {
16605 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
16606 !ValExpr->isInstantiationDependent()) {
16607 SourceLocation Loc = ValExpr->getExprLoc();
16608 ExprResult Value =
16609 SemaRef.PerformOpenMPImplicitIntegerConversion(Loc, ValExpr);
16610 if (Value.isInvalid())
16611 return false;
16613 ValExpr = Value.get();
16614 // The expression must evaluate to a non-negative integer value.
16615 if (std::optional<llvm::APSInt> Result =
16616 ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
16617 if (Result->isSigned() &&
16618 !((!StrictlyPositive && Result->isNonNegative()) ||
16619 (StrictlyPositive && Result->isStrictlyPositive()))) {
16620 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
16621 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
16622 << ValExpr->getSourceRange();
16623 return false;
16626 if (!BuildCapture)
16627 return true;
16628 *CaptureRegion =
16629 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
16630 if (*CaptureRegion != OMPD_unknown &&
16631 !SemaRef.CurContext->isDependentContext()) {
16632 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16633 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16634 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16635 *HelperValStmt = buildPreInits(SemaRef.Context, Captures);
16638 return true;
16641 OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads,
16642 SourceLocation StartLoc,
16643 SourceLocation LParenLoc,
16644 SourceLocation EndLoc) {
16645 Expr *ValExpr = NumThreads;
16646 Stmt *HelperValStmt = nullptr;
16648 // OpenMP [2.5, Restrictions]
16649 // The num_threads expression must evaluate to a positive integer value.
16650 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_num_threads,
16651 /*StrictlyPositive=*/true))
16652 return nullptr;
16654 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16655 OpenMPDirectiveKind CaptureRegion =
16656 getOpenMPCaptureRegionForClause(DKind, OMPC_num_threads, LangOpts.OpenMP);
16657 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
16658 ValExpr = MakeFullExpr(ValExpr).get();
16659 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16660 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
16661 HelperValStmt = buildPreInits(Context, Captures);
16664 return new (Context) OMPNumThreadsClause(
16665 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16668 ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,
16669 OpenMPClauseKind CKind,
16670 bool StrictlyPositive,
16671 bool SuppressExprDiags) {
16672 if (!E)
16673 return ExprError();
16674 if (E->isValueDependent() || E->isTypeDependent() ||
16675 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
16676 return E;
16678 llvm::APSInt Result;
16679 ExprResult ICE;
16680 if (SuppressExprDiags) {
16681 // Use a custom diagnoser that suppresses 'note' diagnostics about the
16682 // expression.
16683 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
16684 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
16685 Sema::SemaDiagnosticBuilder diagnoseNotICE(Sema &S,
16686 SourceLocation Loc) override {
16687 llvm_unreachable("Diagnostic suppressed");
16689 } Diagnoser;
16690 ICE = VerifyIntegerConstantExpression(E, &Result, Diagnoser, AllowFold);
16691 } else {
16692 ICE = VerifyIntegerConstantExpression(E, &Result, /*FIXME*/ AllowFold);
16694 if (ICE.isInvalid())
16695 return ExprError();
16697 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
16698 (!StrictlyPositive && !Result.isNonNegative())) {
16699 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
16700 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
16701 << E->getSourceRange();
16702 return ExprError();
16704 if ((CKind == OMPC_aligned || CKind == OMPC_align) && !Result.isPowerOf2()) {
16705 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
16706 << E->getSourceRange();
16707 return ExprError();
16709 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
16710 DSAStack->setAssociatedLoops(Result.getExtValue());
16711 else if (CKind == OMPC_ordered)
16712 DSAStack->setAssociatedLoops(Result.getExtValue());
16713 return ICE;
16716 OMPClause *Sema::ActOnOpenMPSafelenClause(Expr *Len, SourceLocation StartLoc,
16717 SourceLocation LParenLoc,
16718 SourceLocation EndLoc) {
16719 // OpenMP [2.8.1, simd construct, Description]
16720 // The parameter of the safelen clause must be a constant
16721 // positive integer expression.
16722 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
16723 if (Safelen.isInvalid())
16724 return nullptr;
16725 return new (Context)
16726 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
16729 OMPClause *Sema::ActOnOpenMPSimdlenClause(Expr *Len, SourceLocation StartLoc,
16730 SourceLocation LParenLoc,
16731 SourceLocation EndLoc) {
16732 // OpenMP [2.8.1, simd construct, Description]
16733 // The parameter of the simdlen clause must be a constant
16734 // positive integer expression.
16735 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
16736 if (Simdlen.isInvalid())
16737 return nullptr;
16738 return new (Context)
16739 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
16742 /// Tries to find omp_allocator_handle_t type.
16743 static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc,
16744 DSAStackTy *Stack) {
16745 if (!Stack->getOMPAllocatorHandleT().isNull())
16746 return true;
16748 // Set the allocator handle type.
16749 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t");
16750 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
16751 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
16752 S.Diag(Loc, diag::err_omp_implied_type_not_found)
16753 << "omp_allocator_handle_t";
16754 return false;
16756 QualType AllocatorHandleEnumTy = PT.get();
16757 AllocatorHandleEnumTy.addConst();
16758 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
16760 // Fill the predefined allocator map.
16761 bool ErrorFound = false;
16762 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
16763 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
16764 StringRef Allocator =
16765 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
16766 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
16767 auto *VD = dyn_cast_or_null<ValueDecl>(
16768 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
16769 if (!VD) {
16770 ErrorFound = true;
16771 break;
16773 QualType AllocatorType =
16774 VD->getType().getNonLValueExprType(S.getASTContext());
16775 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
16776 if (!Res.isUsable()) {
16777 ErrorFound = true;
16778 break;
16780 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
16781 Sema::AA_Initializing,
16782 /* AllowExplicit */ true);
16783 if (!Res.isUsable()) {
16784 ErrorFound = true;
16785 break;
16787 Stack->setAllocator(AllocatorKind, Res.get());
16789 if (ErrorFound) {
16790 S.Diag(Loc, diag::err_omp_implied_type_not_found)
16791 << "omp_allocator_handle_t";
16792 return false;
16795 return true;
16798 OMPClause *Sema::ActOnOpenMPAllocatorClause(Expr *A, SourceLocation StartLoc,
16799 SourceLocation LParenLoc,
16800 SourceLocation EndLoc) {
16801 // OpenMP [2.11.3, allocate Directive, Description]
16802 // allocator is an expression of omp_allocator_handle_t type.
16803 if (!findOMPAllocatorHandleT(*this, A->getExprLoc(), DSAStack))
16804 return nullptr;
16806 ExprResult Allocator = DefaultLvalueConversion(A);
16807 if (Allocator.isInvalid())
16808 return nullptr;
16809 Allocator = PerformImplicitConversion(Allocator.get(),
16810 DSAStack->getOMPAllocatorHandleT(),
16811 Sema::AA_Initializing,
16812 /*AllowExplicit=*/true);
16813 if (Allocator.isInvalid())
16814 return nullptr;
16815 return new (Context)
16816 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
16819 OMPClause *Sema::ActOnOpenMPCollapseClause(Expr *NumForLoops,
16820 SourceLocation StartLoc,
16821 SourceLocation LParenLoc,
16822 SourceLocation EndLoc) {
16823 // OpenMP [2.7.1, loop construct, Description]
16824 // OpenMP [2.8.1, simd construct, Description]
16825 // OpenMP [2.9.6, distribute construct, Description]
16826 // The parameter of the collapse clause must be a constant
16827 // positive integer expression.
16828 ExprResult NumForLoopsResult =
16829 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
16830 if (NumForLoopsResult.isInvalid())
16831 return nullptr;
16832 return new (Context)
16833 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
16836 OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc,
16837 SourceLocation EndLoc,
16838 SourceLocation LParenLoc,
16839 Expr *NumForLoops) {
16840 // OpenMP [2.7.1, loop construct, Description]
16841 // OpenMP [2.8.1, simd construct, Description]
16842 // OpenMP [2.9.6, distribute construct, Description]
16843 // The parameter of the ordered clause must be a constant
16844 // positive integer expression if any.
16845 if (NumForLoops && LParenLoc.isValid()) {
16846 ExprResult NumForLoopsResult =
16847 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
16848 if (NumForLoopsResult.isInvalid())
16849 return nullptr;
16850 NumForLoops = NumForLoopsResult.get();
16851 } else {
16852 NumForLoops = nullptr;
16854 auto *Clause = OMPOrderedClause::Create(
16855 Context, NumForLoops, NumForLoops ? DSAStack->getAssociatedLoops() : 0,
16856 StartLoc, LParenLoc, EndLoc);
16857 DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
16858 return Clause;
16861 OMPClause *Sema::ActOnOpenMPSimpleClause(
16862 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
16863 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
16864 OMPClause *Res = nullptr;
16865 switch (Kind) {
16866 case OMPC_default:
16867 Res = ActOnOpenMPDefaultClause(static_cast<DefaultKind>(Argument),
16868 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16869 break;
16870 case OMPC_proc_bind:
16871 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
16872 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16873 break;
16874 case OMPC_atomic_default_mem_order:
16875 Res = ActOnOpenMPAtomicDefaultMemOrderClause(
16876 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
16877 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16878 break;
16879 case OMPC_update:
16880 Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument),
16881 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16882 break;
16883 case OMPC_bind:
16884 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
16885 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16886 break;
16887 case OMPC_at:
16888 Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
16889 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16890 break;
16891 case OMPC_severity:
16892 Res = ActOnOpenMPSeverityClause(
16893 static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc,
16894 LParenLoc, EndLoc);
16895 break;
16896 case OMPC_if:
16897 case OMPC_final:
16898 case OMPC_num_threads:
16899 case OMPC_safelen:
16900 case OMPC_simdlen:
16901 case OMPC_sizes:
16902 case OMPC_allocator:
16903 case OMPC_collapse:
16904 case OMPC_schedule:
16905 case OMPC_private:
16906 case OMPC_firstprivate:
16907 case OMPC_lastprivate:
16908 case OMPC_shared:
16909 case OMPC_reduction:
16910 case OMPC_task_reduction:
16911 case OMPC_in_reduction:
16912 case OMPC_linear:
16913 case OMPC_aligned:
16914 case OMPC_copyin:
16915 case OMPC_copyprivate:
16916 case OMPC_ordered:
16917 case OMPC_nowait:
16918 case OMPC_untied:
16919 case OMPC_mergeable:
16920 case OMPC_threadprivate:
16921 case OMPC_allocate:
16922 case OMPC_flush:
16923 case OMPC_depobj:
16924 case OMPC_read:
16925 case OMPC_write:
16926 case OMPC_capture:
16927 case OMPC_compare:
16928 case OMPC_seq_cst:
16929 case OMPC_acq_rel:
16930 case OMPC_acquire:
16931 case OMPC_release:
16932 case OMPC_relaxed:
16933 case OMPC_depend:
16934 case OMPC_device:
16935 case OMPC_threads:
16936 case OMPC_simd:
16937 case OMPC_map:
16938 case OMPC_num_teams:
16939 case OMPC_thread_limit:
16940 case OMPC_priority:
16941 case OMPC_grainsize:
16942 case OMPC_nogroup:
16943 case OMPC_num_tasks:
16944 case OMPC_hint:
16945 case OMPC_dist_schedule:
16946 case OMPC_defaultmap:
16947 case OMPC_unknown:
16948 case OMPC_uniform:
16949 case OMPC_to:
16950 case OMPC_from:
16951 case OMPC_use_device_ptr:
16952 case OMPC_use_device_addr:
16953 case OMPC_is_device_ptr:
16954 case OMPC_has_device_addr:
16955 case OMPC_unified_address:
16956 case OMPC_unified_shared_memory:
16957 case OMPC_reverse_offload:
16958 case OMPC_dynamic_allocators:
16959 case OMPC_device_type:
16960 case OMPC_match:
16961 case OMPC_nontemporal:
16962 case OMPC_destroy:
16963 case OMPC_novariants:
16964 case OMPC_nocontext:
16965 case OMPC_detach:
16966 case OMPC_inclusive:
16967 case OMPC_exclusive:
16968 case OMPC_uses_allocators:
16969 case OMPC_affinity:
16970 case OMPC_when:
16971 case OMPC_message:
16972 default:
16973 llvm_unreachable("Clause is not allowed.");
16975 return Res;
16978 static std::string
16979 getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last,
16980 ArrayRef<unsigned> Exclude = std::nullopt) {
16981 SmallString<256> Buffer;
16982 llvm::raw_svector_ostream Out(Buffer);
16983 unsigned Skipped = Exclude.size();
16984 for (unsigned I = First; I < Last; ++I) {
16985 if (llvm::is_contained(Exclude, I)) {
16986 --Skipped;
16987 continue;
16989 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
16990 if (I + Skipped + 2 == Last)
16991 Out << " or ";
16992 else if (I + Skipped + 1 != Last)
16993 Out << ", ";
16995 return std::string(Out.str());
16998 OMPClause *Sema::ActOnOpenMPDefaultClause(DefaultKind Kind,
16999 SourceLocation KindKwLoc,
17000 SourceLocation StartLoc,
17001 SourceLocation LParenLoc,
17002 SourceLocation EndLoc) {
17003 if (Kind == OMP_DEFAULT_unknown) {
17004 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17005 << getListOfPossibleValues(OMPC_default, /*First=*/0,
17006 /*Last=*/unsigned(OMP_DEFAULT_unknown))
17007 << getOpenMPClauseName(OMPC_default);
17008 return nullptr;
17011 switch (Kind) {
17012 case OMP_DEFAULT_none:
17013 DSAStack->setDefaultDSANone(KindKwLoc);
17014 break;
17015 case OMP_DEFAULT_shared:
17016 DSAStack->setDefaultDSAShared(KindKwLoc);
17017 break;
17018 case OMP_DEFAULT_firstprivate:
17019 DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
17020 break;
17021 case OMP_DEFAULT_private:
17022 DSAStack->setDefaultDSAPrivate(KindKwLoc);
17023 break;
17024 default:
17025 llvm_unreachable("DSA unexpected in OpenMP default clause");
17028 return new (Context)
17029 OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17032 OMPClause *Sema::ActOnOpenMPProcBindClause(ProcBindKind Kind,
17033 SourceLocation KindKwLoc,
17034 SourceLocation StartLoc,
17035 SourceLocation LParenLoc,
17036 SourceLocation EndLoc) {
17037 if (Kind == OMP_PROC_BIND_unknown) {
17038 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17039 << getListOfPossibleValues(OMPC_proc_bind,
17040 /*First=*/unsigned(OMP_PROC_BIND_master),
17041 /*Last=*/
17042 unsigned(LangOpts.OpenMP > 50
17043 ? OMP_PROC_BIND_primary
17044 : OMP_PROC_BIND_spread) +
17046 << getOpenMPClauseName(OMPC_proc_bind);
17047 return nullptr;
17049 if (Kind == OMP_PROC_BIND_primary && LangOpts.OpenMP < 51)
17050 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17051 << getListOfPossibleValues(OMPC_proc_bind,
17052 /*First=*/unsigned(OMP_PROC_BIND_master),
17053 /*Last=*/
17054 unsigned(OMP_PROC_BIND_spread) + 1)
17055 << getOpenMPClauseName(OMPC_proc_bind);
17056 return new (Context)
17057 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17060 OMPClause *Sema::ActOnOpenMPAtomicDefaultMemOrderClause(
17061 OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindKwLoc,
17062 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17063 if (Kind == OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown) {
17064 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17065 << getListOfPossibleValues(
17066 OMPC_atomic_default_mem_order, /*First=*/0,
17067 /*Last=*/OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown)
17068 << getOpenMPClauseName(OMPC_atomic_default_mem_order);
17069 return nullptr;
17071 return new (Context) OMPAtomicDefaultMemOrderClause(Kind, KindKwLoc, StartLoc,
17072 LParenLoc, EndLoc);
17075 OMPClause *Sema::ActOnOpenMPAtClause(OpenMPAtClauseKind Kind,
17076 SourceLocation KindKwLoc,
17077 SourceLocation StartLoc,
17078 SourceLocation LParenLoc,
17079 SourceLocation EndLoc) {
17080 if (Kind == OMPC_AT_unknown) {
17081 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17082 << getListOfPossibleValues(OMPC_at, /*First=*/0,
17083 /*Last=*/OMPC_AT_unknown)
17084 << getOpenMPClauseName(OMPC_at);
17085 return nullptr;
17087 return new (Context)
17088 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17091 OMPClause *Sema::ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind,
17092 SourceLocation KindKwLoc,
17093 SourceLocation StartLoc,
17094 SourceLocation LParenLoc,
17095 SourceLocation EndLoc) {
17096 if (Kind == OMPC_SEVERITY_unknown) {
17097 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17098 << getListOfPossibleValues(OMPC_severity, /*First=*/0,
17099 /*Last=*/OMPC_SEVERITY_unknown)
17100 << getOpenMPClauseName(OMPC_severity);
17101 return nullptr;
17103 return new (Context)
17104 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17107 OMPClause *Sema::ActOnOpenMPMessageClause(Expr *ME, SourceLocation StartLoc,
17108 SourceLocation LParenLoc,
17109 SourceLocation EndLoc) {
17110 assert(ME && "NULL expr in Message clause");
17111 if (!isa<StringLiteral>(ME)) {
17112 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
17113 << getOpenMPClauseName(OMPC_message);
17114 return nullptr;
17116 return new (Context) OMPMessageClause(ME, StartLoc, LParenLoc, EndLoc);
17119 OMPClause *Sema::ActOnOpenMPOrderClause(
17120 OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind,
17121 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
17122 SourceLocation KindLoc, SourceLocation EndLoc) {
17123 if (Kind != OMPC_ORDER_concurrent ||
17124 (LangOpts.OpenMP < 51 && MLoc.isValid())) {
17125 // Kind should be concurrent,
17126 // Modifiers introduced in OpenMP 5.1
17127 static_assert(OMPC_ORDER_unknown > 0,
17128 "OMPC_ORDER_unknown not greater than 0");
17130 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17131 << getListOfPossibleValues(OMPC_order,
17132 /*First=*/0,
17133 /*Last=*/OMPC_ORDER_unknown)
17134 << getOpenMPClauseName(OMPC_order);
17135 return nullptr;
17137 if (LangOpts.OpenMP >= 51) {
17138 if (Modifier == OMPC_ORDER_MODIFIER_unknown && MLoc.isValid()) {
17139 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17140 << getListOfPossibleValues(OMPC_order,
17141 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
17142 /*Last=*/OMPC_ORDER_MODIFIER_last)
17143 << getOpenMPClauseName(OMPC_order);
17144 } else {
17145 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
17146 if (DSAStack->getCurScope()) {
17147 // mark the current scope with 'order' flag
17148 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
17149 DSAStack->getCurScope()->setFlags(existingFlags |
17150 Scope::OpenMPOrderClauseScope);
17154 return new (Context) OMPOrderClause(Kind, KindLoc, StartLoc, LParenLoc,
17155 EndLoc, Modifier, MLoc);
17158 OMPClause *Sema::ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind,
17159 SourceLocation KindKwLoc,
17160 SourceLocation StartLoc,
17161 SourceLocation LParenLoc,
17162 SourceLocation EndLoc) {
17163 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
17164 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
17165 SmallVector<unsigned> Except = {
17166 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
17167 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
17168 if (LangOpts.OpenMP < 51)
17169 Except.push_back(OMPC_DEPEND_inoutset);
17170 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17171 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
17172 /*Last=*/OMPC_DEPEND_unknown, Except)
17173 << getOpenMPClauseName(OMPC_update);
17174 return nullptr;
17176 return OMPUpdateClause::Create(Context, StartLoc, LParenLoc, KindKwLoc, Kind,
17177 EndLoc);
17180 OMPClause *Sema::ActOnOpenMPSizesClause(ArrayRef<Expr *> SizeExprs,
17181 SourceLocation StartLoc,
17182 SourceLocation LParenLoc,
17183 SourceLocation EndLoc) {
17184 for (Expr *SizeExpr : SizeExprs) {
17185 ExprResult NumForLoopsResult = VerifyPositiveIntegerConstantInClause(
17186 SizeExpr, OMPC_sizes, /*StrictlyPositive=*/true);
17187 if (!NumForLoopsResult.isUsable())
17188 return nullptr;
17191 DSAStack->setAssociatedLoops(SizeExprs.size());
17192 return OMPSizesClause::Create(Context, StartLoc, LParenLoc, EndLoc,
17193 SizeExprs);
17196 OMPClause *Sema::ActOnOpenMPFullClause(SourceLocation StartLoc,
17197 SourceLocation EndLoc) {
17198 return OMPFullClause::Create(Context, StartLoc, EndLoc);
17201 OMPClause *Sema::ActOnOpenMPPartialClause(Expr *FactorExpr,
17202 SourceLocation StartLoc,
17203 SourceLocation LParenLoc,
17204 SourceLocation EndLoc) {
17205 if (FactorExpr) {
17206 // If an argument is specified, it must be a constant (or an unevaluated
17207 // template expression).
17208 ExprResult FactorResult = VerifyPositiveIntegerConstantInClause(
17209 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
17210 if (FactorResult.isInvalid())
17211 return nullptr;
17212 FactorExpr = FactorResult.get();
17215 return OMPPartialClause::Create(Context, StartLoc, LParenLoc, EndLoc,
17216 FactorExpr);
17219 OMPClause *Sema::ActOnOpenMPAlignClause(Expr *A, SourceLocation StartLoc,
17220 SourceLocation LParenLoc,
17221 SourceLocation EndLoc) {
17222 ExprResult AlignVal;
17223 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
17224 if (AlignVal.isInvalid())
17225 return nullptr;
17226 return OMPAlignClause::Create(Context, AlignVal.get(), StartLoc, LParenLoc,
17227 EndLoc);
17230 OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
17231 OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr,
17232 SourceLocation StartLoc, SourceLocation LParenLoc,
17233 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
17234 SourceLocation EndLoc) {
17235 OMPClause *Res = nullptr;
17236 switch (Kind) {
17237 case OMPC_schedule:
17238 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
17239 assert(Argument.size() == NumberOfElements &&
17240 ArgumentLoc.size() == NumberOfElements);
17241 Res = ActOnOpenMPScheduleClause(
17242 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
17243 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
17244 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
17245 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
17246 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
17247 break;
17248 case OMPC_if:
17249 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17250 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
17251 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
17252 DelimLoc, EndLoc);
17253 break;
17254 case OMPC_dist_schedule:
17255 Res = ActOnOpenMPDistScheduleClause(
17256 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
17257 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
17258 break;
17259 case OMPC_defaultmap:
17260 enum { Modifier, DefaultmapKind };
17261 Res = ActOnOpenMPDefaultmapClause(
17262 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
17263 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
17264 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
17265 EndLoc);
17266 break;
17267 case OMPC_order:
17268 enum { OrderModifier, OrderKind };
17269 Res = ActOnOpenMPOrderClause(
17270 static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
17271 static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
17272 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
17273 break;
17274 case OMPC_device:
17275 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17276 Res = ActOnOpenMPDeviceClause(
17277 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
17278 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17279 break;
17280 case OMPC_grainsize:
17281 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17282 "Modifier for grainsize clause and its location are expected.");
17283 Res = ActOnOpenMPGrainsizeClause(
17284 static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr,
17285 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17286 break;
17287 case OMPC_num_tasks:
17288 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17289 "Modifier for num_tasks clause and its location are expected.");
17290 Res = ActOnOpenMPNumTasksClause(
17291 static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
17292 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17293 break;
17294 case OMPC_final:
17295 case OMPC_num_threads:
17296 case OMPC_safelen:
17297 case OMPC_simdlen:
17298 case OMPC_sizes:
17299 case OMPC_allocator:
17300 case OMPC_collapse:
17301 case OMPC_default:
17302 case OMPC_proc_bind:
17303 case OMPC_private:
17304 case OMPC_firstprivate:
17305 case OMPC_lastprivate:
17306 case OMPC_shared:
17307 case OMPC_reduction:
17308 case OMPC_task_reduction:
17309 case OMPC_in_reduction:
17310 case OMPC_linear:
17311 case OMPC_aligned:
17312 case OMPC_copyin:
17313 case OMPC_copyprivate:
17314 case OMPC_ordered:
17315 case OMPC_nowait:
17316 case OMPC_untied:
17317 case OMPC_mergeable:
17318 case OMPC_threadprivate:
17319 case OMPC_allocate:
17320 case OMPC_flush:
17321 case OMPC_depobj:
17322 case OMPC_read:
17323 case OMPC_write:
17324 case OMPC_update:
17325 case OMPC_capture:
17326 case OMPC_compare:
17327 case OMPC_seq_cst:
17328 case OMPC_acq_rel:
17329 case OMPC_acquire:
17330 case OMPC_release:
17331 case OMPC_relaxed:
17332 case OMPC_depend:
17333 case OMPC_threads:
17334 case OMPC_simd:
17335 case OMPC_map:
17336 case OMPC_num_teams:
17337 case OMPC_thread_limit:
17338 case OMPC_priority:
17339 case OMPC_nogroup:
17340 case OMPC_hint:
17341 case OMPC_unknown:
17342 case OMPC_uniform:
17343 case OMPC_to:
17344 case OMPC_from:
17345 case OMPC_use_device_ptr:
17346 case OMPC_use_device_addr:
17347 case OMPC_is_device_ptr:
17348 case OMPC_has_device_addr:
17349 case OMPC_unified_address:
17350 case OMPC_unified_shared_memory:
17351 case OMPC_reverse_offload:
17352 case OMPC_dynamic_allocators:
17353 case OMPC_atomic_default_mem_order:
17354 case OMPC_device_type:
17355 case OMPC_match:
17356 case OMPC_nontemporal:
17357 case OMPC_at:
17358 case OMPC_severity:
17359 case OMPC_message:
17360 case OMPC_destroy:
17361 case OMPC_novariants:
17362 case OMPC_nocontext:
17363 case OMPC_detach:
17364 case OMPC_inclusive:
17365 case OMPC_exclusive:
17366 case OMPC_uses_allocators:
17367 case OMPC_affinity:
17368 case OMPC_when:
17369 case OMPC_bind:
17370 default:
17371 llvm_unreachable("Clause is not allowed.");
17373 return Res;
17376 static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1,
17377 OpenMPScheduleClauseModifier M2,
17378 SourceLocation M1Loc, SourceLocation M2Loc) {
17379 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
17380 SmallVector<unsigned, 2> Excluded;
17381 if (M2 != OMPC_SCHEDULE_MODIFIER_unknown)
17382 Excluded.push_back(M2);
17383 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
17384 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
17385 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
17386 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
17387 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
17388 << getListOfPossibleValues(OMPC_schedule,
17389 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
17390 /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
17391 Excluded)
17392 << getOpenMPClauseName(OMPC_schedule);
17393 return true;
17395 return false;
17398 OMPClause *Sema::ActOnOpenMPScheduleClause(
17399 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
17400 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
17401 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
17402 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
17403 if (checkScheduleModifiers(*this, M1, M2, M1Loc, M2Loc) ||
17404 checkScheduleModifiers(*this, M2, M1, M2Loc, M1Loc))
17405 return nullptr;
17406 // OpenMP, 2.7.1, Loop Construct, Restrictions
17407 // Either the monotonic modifier or the nonmonotonic modifier can be specified
17408 // but not both.
17409 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
17410 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
17411 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
17412 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
17413 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
17414 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
17415 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
17416 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
17417 return nullptr;
17419 if (Kind == OMPC_SCHEDULE_unknown) {
17420 std::string Values;
17421 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
17422 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
17423 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
17424 /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
17425 Exclude);
17426 } else {
17427 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
17428 /*Last=*/OMPC_SCHEDULE_unknown);
17430 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17431 << Values << getOpenMPClauseName(OMPC_schedule);
17432 return nullptr;
17434 // OpenMP, 2.7.1, Loop Construct, Restrictions
17435 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
17436 // schedule(guided).
17437 // OpenMP 5.0 does not have this restriction.
17438 if (LangOpts.OpenMP < 50 &&
17439 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
17440 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
17441 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
17442 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
17443 diag::err_omp_schedule_nonmonotonic_static);
17444 return nullptr;
17446 Expr *ValExpr = ChunkSize;
17447 Stmt *HelperValStmt = nullptr;
17448 if (ChunkSize) {
17449 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
17450 !ChunkSize->isInstantiationDependent() &&
17451 !ChunkSize->containsUnexpandedParameterPack()) {
17452 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
17453 ExprResult Val =
17454 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
17455 if (Val.isInvalid())
17456 return nullptr;
17458 ValExpr = Val.get();
17460 // OpenMP [2.7.1, Restrictions]
17461 // chunk_size must be a loop invariant integer expression with a positive
17462 // value.
17463 if (std::optional<llvm::APSInt> Result =
17464 ValExpr->getIntegerConstantExpr(Context)) {
17465 if (Result->isSigned() && !Result->isStrictlyPositive()) {
17466 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
17467 << "schedule" << 1 << ChunkSize->getSourceRange();
17468 return nullptr;
17470 } else if (getOpenMPCaptureRegionForClause(
17471 DSAStack->getCurrentDirective(), OMPC_schedule,
17472 LangOpts.OpenMP) != OMPD_unknown &&
17473 !CurContext->isDependentContext()) {
17474 ValExpr = MakeFullExpr(ValExpr).get();
17475 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17476 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
17477 HelperValStmt = buildPreInits(Context, Captures);
17482 return new (Context)
17483 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
17484 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
17487 OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
17488 SourceLocation StartLoc,
17489 SourceLocation EndLoc) {
17490 OMPClause *Res = nullptr;
17491 switch (Kind) {
17492 case OMPC_ordered:
17493 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
17494 break;
17495 case OMPC_nowait:
17496 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc);
17497 break;
17498 case OMPC_untied:
17499 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
17500 break;
17501 case OMPC_mergeable:
17502 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
17503 break;
17504 case OMPC_read:
17505 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
17506 break;
17507 case OMPC_write:
17508 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
17509 break;
17510 case OMPC_update:
17511 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
17512 break;
17513 case OMPC_capture:
17514 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
17515 break;
17516 case OMPC_compare:
17517 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
17518 break;
17519 case OMPC_seq_cst:
17520 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
17521 break;
17522 case OMPC_acq_rel:
17523 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
17524 break;
17525 case OMPC_acquire:
17526 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
17527 break;
17528 case OMPC_release:
17529 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
17530 break;
17531 case OMPC_relaxed:
17532 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
17533 break;
17534 case OMPC_threads:
17535 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
17536 break;
17537 case OMPC_simd:
17538 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
17539 break;
17540 case OMPC_nogroup:
17541 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
17542 break;
17543 case OMPC_unified_address:
17544 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
17545 break;
17546 case OMPC_unified_shared_memory:
17547 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
17548 break;
17549 case OMPC_reverse_offload:
17550 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
17551 break;
17552 case OMPC_dynamic_allocators:
17553 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
17554 break;
17555 case OMPC_destroy:
17556 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
17557 /*LParenLoc=*/SourceLocation(),
17558 /*VarLoc=*/SourceLocation(), EndLoc);
17559 break;
17560 case OMPC_full:
17561 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
17562 break;
17563 case OMPC_partial:
17564 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
17565 break;
17566 case OMPC_ompx_bare:
17567 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
17568 break;
17569 case OMPC_if:
17570 case OMPC_final:
17571 case OMPC_num_threads:
17572 case OMPC_safelen:
17573 case OMPC_simdlen:
17574 case OMPC_sizes:
17575 case OMPC_allocator:
17576 case OMPC_collapse:
17577 case OMPC_schedule:
17578 case OMPC_private:
17579 case OMPC_firstprivate:
17580 case OMPC_lastprivate:
17581 case OMPC_shared:
17582 case OMPC_reduction:
17583 case OMPC_task_reduction:
17584 case OMPC_in_reduction:
17585 case OMPC_linear:
17586 case OMPC_aligned:
17587 case OMPC_copyin:
17588 case OMPC_copyprivate:
17589 case OMPC_default:
17590 case OMPC_proc_bind:
17591 case OMPC_threadprivate:
17592 case OMPC_allocate:
17593 case OMPC_flush:
17594 case OMPC_depobj:
17595 case OMPC_depend:
17596 case OMPC_device:
17597 case OMPC_map:
17598 case OMPC_num_teams:
17599 case OMPC_thread_limit:
17600 case OMPC_priority:
17601 case OMPC_grainsize:
17602 case OMPC_num_tasks:
17603 case OMPC_hint:
17604 case OMPC_dist_schedule:
17605 case OMPC_defaultmap:
17606 case OMPC_unknown:
17607 case OMPC_uniform:
17608 case OMPC_to:
17609 case OMPC_from:
17610 case OMPC_use_device_ptr:
17611 case OMPC_use_device_addr:
17612 case OMPC_is_device_ptr:
17613 case OMPC_has_device_addr:
17614 case OMPC_atomic_default_mem_order:
17615 case OMPC_device_type:
17616 case OMPC_match:
17617 case OMPC_nontemporal:
17618 case OMPC_order:
17619 case OMPC_at:
17620 case OMPC_severity:
17621 case OMPC_message:
17622 case OMPC_novariants:
17623 case OMPC_nocontext:
17624 case OMPC_detach:
17625 case OMPC_inclusive:
17626 case OMPC_exclusive:
17627 case OMPC_uses_allocators:
17628 case OMPC_affinity:
17629 case OMPC_when:
17630 case OMPC_ompx_dyn_cgroup_mem:
17631 default:
17632 llvm_unreachable("Clause is not allowed.");
17634 return Res;
17637 OMPClause *Sema::ActOnOpenMPNowaitClause(SourceLocation StartLoc,
17638 SourceLocation EndLoc) {
17639 DSAStack->setNowaitRegion();
17640 return new (Context) OMPNowaitClause(StartLoc, EndLoc);
17643 OMPClause *Sema::ActOnOpenMPUntiedClause(SourceLocation StartLoc,
17644 SourceLocation EndLoc) {
17645 DSAStack->setUntiedRegion();
17646 return new (Context) OMPUntiedClause(StartLoc, EndLoc);
17649 OMPClause *Sema::ActOnOpenMPMergeableClause(SourceLocation StartLoc,
17650 SourceLocation EndLoc) {
17651 return new (Context) OMPMergeableClause(StartLoc, EndLoc);
17654 OMPClause *Sema::ActOnOpenMPReadClause(SourceLocation StartLoc,
17655 SourceLocation EndLoc) {
17656 return new (Context) OMPReadClause(StartLoc, EndLoc);
17659 OMPClause *Sema::ActOnOpenMPWriteClause(SourceLocation StartLoc,
17660 SourceLocation EndLoc) {
17661 return new (Context) OMPWriteClause(StartLoc, EndLoc);
17664 OMPClause *Sema::ActOnOpenMPUpdateClause(SourceLocation StartLoc,
17665 SourceLocation EndLoc) {
17666 return OMPUpdateClause::Create(Context, StartLoc, EndLoc);
17669 OMPClause *Sema::ActOnOpenMPCaptureClause(SourceLocation StartLoc,
17670 SourceLocation EndLoc) {
17671 return new (Context) OMPCaptureClause(StartLoc, EndLoc);
17674 OMPClause *Sema::ActOnOpenMPCompareClause(SourceLocation StartLoc,
17675 SourceLocation EndLoc) {
17676 return new (Context) OMPCompareClause(StartLoc, EndLoc);
17679 OMPClause *Sema::ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
17680 SourceLocation EndLoc) {
17681 return new (Context) OMPSeqCstClause(StartLoc, EndLoc);
17684 OMPClause *Sema::ActOnOpenMPAcqRelClause(SourceLocation StartLoc,
17685 SourceLocation EndLoc) {
17686 return new (Context) OMPAcqRelClause(StartLoc, EndLoc);
17689 OMPClause *Sema::ActOnOpenMPAcquireClause(SourceLocation StartLoc,
17690 SourceLocation EndLoc) {
17691 return new (Context) OMPAcquireClause(StartLoc, EndLoc);
17694 OMPClause *Sema::ActOnOpenMPReleaseClause(SourceLocation StartLoc,
17695 SourceLocation EndLoc) {
17696 return new (Context) OMPReleaseClause(StartLoc, EndLoc);
17699 OMPClause *Sema::ActOnOpenMPRelaxedClause(SourceLocation StartLoc,
17700 SourceLocation EndLoc) {
17701 return new (Context) OMPRelaxedClause(StartLoc, EndLoc);
17704 OMPClause *Sema::ActOnOpenMPThreadsClause(SourceLocation StartLoc,
17705 SourceLocation EndLoc) {
17706 return new (Context) OMPThreadsClause(StartLoc, EndLoc);
17709 OMPClause *Sema::ActOnOpenMPSIMDClause(SourceLocation StartLoc,
17710 SourceLocation EndLoc) {
17711 return new (Context) OMPSIMDClause(StartLoc, EndLoc);
17714 OMPClause *Sema::ActOnOpenMPNogroupClause(SourceLocation StartLoc,
17715 SourceLocation EndLoc) {
17716 return new (Context) OMPNogroupClause(StartLoc, EndLoc);
17719 OMPClause *Sema::ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc,
17720 SourceLocation EndLoc) {
17721 return new (Context) OMPUnifiedAddressClause(StartLoc, EndLoc);
17724 OMPClause *Sema::ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc,
17725 SourceLocation EndLoc) {
17726 return new (Context) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
17729 OMPClause *Sema::ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc,
17730 SourceLocation EndLoc) {
17731 return new (Context) OMPReverseOffloadClause(StartLoc, EndLoc);
17734 OMPClause *Sema::ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc,
17735 SourceLocation EndLoc) {
17736 return new (Context) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
17739 StmtResult Sema::ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses,
17740 SourceLocation StartLoc,
17741 SourceLocation EndLoc) {
17743 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17744 // At least one action-clause must appear on a directive.
17745 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
17746 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
17747 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
17748 << Expected << getOpenMPDirectiveName(OMPD_interop);
17749 return StmtError();
17752 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17753 // A depend clause can only appear on the directive if a targetsync
17754 // interop-type is present or the interop-var was initialized with
17755 // the targetsync interop-type.
17757 // If there is any 'init' clause diagnose if there is no 'init' clause with
17758 // interop-type of 'targetsync'. Cases involving other directives cannot be
17759 // diagnosed.
17760 const OMPDependClause *DependClause = nullptr;
17761 bool HasInitClause = false;
17762 bool IsTargetSync = false;
17763 for (const OMPClause *C : Clauses) {
17764 if (IsTargetSync)
17765 break;
17766 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
17767 HasInitClause = true;
17768 if (InitClause->getIsTargetSync())
17769 IsTargetSync = true;
17770 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
17771 DependClause = DC;
17774 if (DependClause && HasInitClause && !IsTargetSync) {
17775 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
17776 return StmtError();
17779 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17780 // Each interop-var may be specified for at most one action-clause of each
17781 // interop construct.
17782 llvm::SmallPtrSet<const ValueDecl *, 4> InteropVars;
17783 for (OMPClause *C : Clauses) {
17784 OpenMPClauseKind ClauseKind = C->getClauseKind();
17785 std::pair<ValueDecl *, bool> DeclResult;
17786 SourceLocation ELoc;
17787 SourceRange ERange;
17789 if (ClauseKind == OMPC_init) {
17790 auto *E = cast<OMPInitClause>(C)->getInteropVar();
17791 DeclResult = getPrivateItem(*this, E, ELoc, ERange);
17792 } else if (ClauseKind == OMPC_use) {
17793 auto *E = cast<OMPUseClause>(C)->getInteropVar();
17794 DeclResult = getPrivateItem(*this, E, ELoc, ERange);
17795 } else if (ClauseKind == OMPC_destroy) {
17796 auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
17797 DeclResult = getPrivateItem(*this, E, ELoc, ERange);
17800 if (DeclResult.first) {
17801 if (!InteropVars.insert(DeclResult.first).second) {
17802 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
17803 << DeclResult.first;
17804 return StmtError();
17809 return OMPInteropDirective::Create(Context, StartLoc, EndLoc, Clauses);
17812 static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
17813 SourceLocation VarLoc,
17814 OpenMPClauseKind Kind) {
17815 SourceLocation ELoc;
17816 SourceRange ERange;
17817 Expr *RefExpr = InteropVarExpr;
17818 auto Res =
17819 getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
17820 /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t");
17822 if (Res.second) {
17823 // It will be analyzed later.
17824 return true;
17827 if (!Res.first)
17828 return false;
17830 // Interop variable should be of type omp_interop_t.
17831 bool HasError = false;
17832 QualType InteropType;
17833 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
17834 VarLoc, Sema::LookupOrdinaryName);
17835 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
17836 NamedDecl *ND = Result.getFoundDecl();
17837 if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
17838 InteropType = QualType(TD->getTypeForDecl(), 0);
17839 } else {
17840 HasError = true;
17842 } else {
17843 HasError = true;
17846 if (HasError) {
17847 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
17848 << "omp_interop_t";
17849 return false;
17852 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
17853 if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
17854 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
17855 return false;
17858 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17859 // The interop-var passed to init or destroy must be non-const.
17860 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
17861 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
17862 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
17863 << /*non-const*/ 1;
17864 return false;
17866 return true;
17869 OMPClause *
17870 Sema::ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo,
17871 SourceLocation StartLoc, SourceLocation LParenLoc,
17872 SourceLocation VarLoc, SourceLocation EndLoc) {
17874 if (!isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_init))
17875 return nullptr;
17877 // Check prefer_type values. These foreign-runtime-id values are either
17878 // string literals or constant integral expressions.
17879 for (const Expr *E : InteropInfo.PreferTypes) {
17880 if (E->isValueDependent() || E->isTypeDependent() ||
17881 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
17882 continue;
17883 if (E->isIntegerConstantExpr(Context))
17884 continue;
17885 if (isa<StringLiteral>(E))
17886 continue;
17887 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
17888 return nullptr;
17891 return OMPInitClause::Create(Context, InteropVar, InteropInfo, StartLoc,
17892 LParenLoc, VarLoc, EndLoc);
17895 OMPClause *Sema::ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc,
17896 SourceLocation LParenLoc,
17897 SourceLocation VarLoc,
17898 SourceLocation EndLoc) {
17900 if (!isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_use))
17901 return nullptr;
17903 return new (Context)
17904 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
17907 OMPClause *Sema::ActOnOpenMPDestroyClause(Expr *InteropVar,
17908 SourceLocation StartLoc,
17909 SourceLocation LParenLoc,
17910 SourceLocation VarLoc,
17911 SourceLocation EndLoc) {
17912 if (!InteropVar && LangOpts.OpenMP >= 52 &&
17913 DSAStack->getCurrentDirective() == OMPD_depobj) {
17914 Diag(StartLoc, diag::err_omp_expected_clause_argument)
17915 << getOpenMPClauseName(OMPC_destroy)
17916 << getOpenMPDirectiveName(OMPD_depobj);
17917 return nullptr;
17919 if (InteropVar &&
17920 !isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_destroy))
17921 return nullptr;
17923 return new (Context)
17924 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
17927 OMPClause *Sema::ActOnOpenMPNovariantsClause(Expr *Condition,
17928 SourceLocation StartLoc,
17929 SourceLocation LParenLoc,
17930 SourceLocation EndLoc) {
17931 Expr *ValExpr = Condition;
17932 Stmt *HelperValStmt = nullptr;
17933 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17934 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17935 !Condition->isInstantiationDependent() &&
17936 !Condition->containsUnexpandedParameterPack()) {
17937 ExprResult Val = CheckBooleanCondition(StartLoc, Condition);
17938 if (Val.isInvalid())
17939 return nullptr;
17941 ValExpr = MakeFullExpr(Val.get()).get();
17943 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17944 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
17945 LangOpts.OpenMP);
17946 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
17947 ValExpr = MakeFullExpr(ValExpr).get();
17948 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17949 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
17950 HelperValStmt = buildPreInits(Context, Captures);
17954 return new (Context) OMPNovariantsClause(
17955 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17958 OMPClause *Sema::ActOnOpenMPNocontextClause(Expr *Condition,
17959 SourceLocation StartLoc,
17960 SourceLocation LParenLoc,
17961 SourceLocation EndLoc) {
17962 Expr *ValExpr = Condition;
17963 Stmt *HelperValStmt = nullptr;
17964 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17965 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17966 !Condition->isInstantiationDependent() &&
17967 !Condition->containsUnexpandedParameterPack()) {
17968 ExprResult Val = CheckBooleanCondition(StartLoc, Condition);
17969 if (Val.isInvalid())
17970 return nullptr;
17972 ValExpr = MakeFullExpr(Val.get()).get();
17974 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17975 CaptureRegion =
17976 getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext, LangOpts.OpenMP);
17977 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
17978 ValExpr = MakeFullExpr(ValExpr).get();
17979 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17980 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
17981 HelperValStmt = buildPreInits(Context, Captures);
17985 return new (Context) OMPNocontextClause(ValExpr, HelperValStmt, CaptureRegion,
17986 StartLoc, LParenLoc, EndLoc);
17989 OMPClause *Sema::ActOnOpenMPFilterClause(Expr *ThreadID,
17990 SourceLocation StartLoc,
17991 SourceLocation LParenLoc,
17992 SourceLocation EndLoc) {
17993 Expr *ValExpr = ThreadID;
17994 Stmt *HelperValStmt = nullptr;
17996 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17997 OpenMPDirectiveKind CaptureRegion =
17998 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, LangOpts.OpenMP);
17999 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
18000 ValExpr = MakeFullExpr(ValExpr).get();
18001 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18002 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
18003 HelperValStmt = buildPreInits(Context, Captures);
18006 return new (Context) OMPFilterClause(ValExpr, HelperValStmt, CaptureRegion,
18007 StartLoc, LParenLoc, EndLoc);
18010 OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
18011 ArrayRef<Expr *> VarList,
18012 const OMPVarListLocTy &Locs,
18013 OpenMPVarListDataTy &Data) {
18014 SourceLocation StartLoc = Locs.StartLoc;
18015 SourceLocation LParenLoc = Locs.LParenLoc;
18016 SourceLocation EndLoc = Locs.EndLoc;
18017 OMPClause *Res = nullptr;
18018 int ExtraModifier = Data.ExtraModifier;
18019 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
18020 SourceLocation ColonLoc = Data.ColonLoc;
18021 switch (Kind) {
18022 case OMPC_private:
18023 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18024 break;
18025 case OMPC_firstprivate:
18026 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18027 break;
18028 case OMPC_lastprivate:
18029 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
18030 "Unexpected lastprivate modifier.");
18031 Res = ActOnOpenMPLastprivateClause(
18032 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
18033 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
18034 break;
18035 case OMPC_shared:
18036 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
18037 break;
18038 case OMPC_reduction:
18039 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
18040 "Unexpected lastprivate modifier.");
18041 Res = ActOnOpenMPReductionClause(
18042 VarList, static_cast<OpenMPReductionClauseModifier>(ExtraModifier),
18043 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
18044 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18045 break;
18046 case OMPC_task_reduction:
18047 Res = ActOnOpenMPTaskReductionClause(
18048 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18049 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18050 break;
18051 case OMPC_in_reduction:
18052 Res = ActOnOpenMPInReductionClause(
18053 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18054 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18055 break;
18056 case OMPC_linear:
18057 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
18058 "Unexpected linear modifier.");
18059 Res = ActOnOpenMPLinearClause(
18060 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
18061 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
18062 ColonLoc, Data.StepModifierLoc, EndLoc);
18063 break;
18064 case OMPC_aligned:
18065 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
18066 LParenLoc, ColonLoc, EndLoc);
18067 break;
18068 case OMPC_copyin:
18069 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
18070 break;
18071 case OMPC_copyprivate:
18072 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18073 break;
18074 case OMPC_flush:
18075 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
18076 break;
18077 case OMPC_depend:
18078 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
18079 "Unexpected depend modifier.");
18080 Res = ActOnOpenMPDependClause(
18081 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
18082 ColonLoc, Data.OmpAllMemoryLoc},
18083 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
18084 break;
18085 case OMPC_map:
18086 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
18087 "Unexpected map modifier.");
18088 Res = ActOnOpenMPMapClause(
18089 Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
18090 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
18091 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
18092 ExtraModifierLoc, ColonLoc, VarList, Locs);
18093 break;
18094 case OMPC_to:
18095 Res =
18096 ActOnOpenMPToClause(Data.MotionModifiers, Data.MotionModifiersLoc,
18097 Data.ReductionOrMapperIdScopeSpec,
18098 Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
18099 break;
18100 case OMPC_from:
18101 Res = ActOnOpenMPFromClause(Data.MotionModifiers, Data.MotionModifiersLoc,
18102 Data.ReductionOrMapperIdScopeSpec,
18103 Data.ReductionOrMapperId, ColonLoc, VarList,
18104 Locs);
18105 break;
18106 case OMPC_use_device_ptr:
18107 Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
18108 break;
18109 case OMPC_use_device_addr:
18110 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
18111 break;
18112 case OMPC_is_device_ptr:
18113 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
18114 break;
18115 case OMPC_has_device_addr:
18116 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
18117 break;
18118 case OMPC_allocate:
18119 Res = ActOnOpenMPAllocateClause(Data.DepModOrTailExpr, VarList, StartLoc,
18120 LParenLoc, ColonLoc, EndLoc);
18121 break;
18122 case OMPC_nontemporal:
18123 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
18124 break;
18125 case OMPC_inclusive:
18126 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
18127 break;
18128 case OMPC_exclusive:
18129 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
18130 break;
18131 case OMPC_affinity:
18132 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
18133 Data.DepModOrTailExpr, VarList);
18134 break;
18135 case OMPC_doacross:
18136 Res = ActOnOpenMPDoacrossClause(
18137 static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
18138 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
18139 break;
18140 case OMPC_if:
18141 case OMPC_depobj:
18142 case OMPC_final:
18143 case OMPC_num_threads:
18144 case OMPC_safelen:
18145 case OMPC_simdlen:
18146 case OMPC_sizes:
18147 case OMPC_allocator:
18148 case OMPC_collapse:
18149 case OMPC_default:
18150 case OMPC_proc_bind:
18151 case OMPC_schedule:
18152 case OMPC_ordered:
18153 case OMPC_nowait:
18154 case OMPC_untied:
18155 case OMPC_mergeable:
18156 case OMPC_threadprivate:
18157 case OMPC_read:
18158 case OMPC_write:
18159 case OMPC_update:
18160 case OMPC_capture:
18161 case OMPC_compare:
18162 case OMPC_seq_cst:
18163 case OMPC_acq_rel:
18164 case OMPC_acquire:
18165 case OMPC_release:
18166 case OMPC_relaxed:
18167 case OMPC_device:
18168 case OMPC_threads:
18169 case OMPC_simd:
18170 case OMPC_num_teams:
18171 case OMPC_thread_limit:
18172 case OMPC_priority:
18173 case OMPC_grainsize:
18174 case OMPC_nogroup:
18175 case OMPC_num_tasks:
18176 case OMPC_hint:
18177 case OMPC_dist_schedule:
18178 case OMPC_defaultmap:
18179 case OMPC_unknown:
18180 case OMPC_uniform:
18181 case OMPC_unified_address:
18182 case OMPC_unified_shared_memory:
18183 case OMPC_reverse_offload:
18184 case OMPC_dynamic_allocators:
18185 case OMPC_atomic_default_mem_order:
18186 case OMPC_device_type:
18187 case OMPC_match:
18188 case OMPC_order:
18189 case OMPC_at:
18190 case OMPC_severity:
18191 case OMPC_message:
18192 case OMPC_destroy:
18193 case OMPC_novariants:
18194 case OMPC_nocontext:
18195 case OMPC_detach:
18196 case OMPC_uses_allocators:
18197 case OMPC_when:
18198 case OMPC_bind:
18199 default:
18200 llvm_unreachable("Clause is not allowed.");
18202 return Res;
18205 ExprResult Sema::getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
18206 ExprObjectKind OK, SourceLocation Loc) {
18207 ExprResult Res = BuildDeclRefExpr(
18208 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
18209 if (!Res.isUsable())
18210 return ExprError();
18211 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
18212 Res = CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
18213 if (!Res.isUsable())
18214 return ExprError();
18216 if (VK != VK_LValue && Res.get()->isGLValue()) {
18217 Res = DefaultLvalueConversion(Res.get());
18218 if (!Res.isUsable())
18219 return ExprError();
18221 return Res;
18224 OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
18225 SourceLocation StartLoc,
18226 SourceLocation LParenLoc,
18227 SourceLocation EndLoc) {
18228 SmallVector<Expr *, 8> Vars;
18229 SmallVector<Expr *, 8> PrivateCopies;
18230 bool IsImplicitClause =
18231 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
18232 for (Expr *RefExpr : VarList) {
18233 assert(RefExpr && "NULL expr in OpenMP private clause.");
18234 SourceLocation ELoc;
18235 SourceRange ERange;
18236 Expr *SimpleRefExpr = RefExpr;
18237 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
18238 if (Res.second) {
18239 // It will be analyzed later.
18240 Vars.push_back(RefExpr);
18241 PrivateCopies.push_back(nullptr);
18243 ValueDecl *D = Res.first;
18244 if (!D)
18245 continue;
18247 QualType Type = D->getType();
18248 auto *VD = dyn_cast<VarDecl>(D);
18250 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18251 // A variable that appears in a private clause must not have an incomplete
18252 // type or a reference type.
18253 if (RequireCompleteType(ELoc, Type, diag::err_omp_private_incomplete_type))
18254 continue;
18255 Type = Type.getNonReferenceType();
18257 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18258 // A variable that is privatized must not have a const-qualified type
18259 // unless it is of class type with a mutable member. This restriction does
18260 // not apply to the firstprivate clause.
18262 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
18263 // A variable that appears in a private clause must not have a
18264 // const-qualified type unless it is of class type with a mutable member.
18265 if (rejectConstNotMutableType(*this, D, Type, OMPC_private, ELoc))
18266 continue;
18268 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18269 // in a Construct]
18270 // Variables with the predetermined data-sharing attributes may not be
18271 // listed in data-sharing attributes clauses, except for the cases
18272 // listed below. For these exceptions only, listing a predetermined
18273 // variable in a data-sharing attribute clause is allowed and overrides
18274 // the variable's predetermined data-sharing attributes.
18275 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18276 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
18277 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
18278 << getOpenMPClauseName(OMPC_private);
18279 reportOriginalDsa(*this, DSAStack, D, DVar);
18280 continue;
18283 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18284 // Variably modified types are not supported for tasks.
18285 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
18286 isOpenMPTaskingDirective(CurrDir)) {
18287 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18288 << getOpenMPClauseName(OMPC_private) << Type
18289 << getOpenMPDirectiveName(CurrDir);
18290 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18291 VarDecl::DeclarationOnly;
18292 Diag(D->getLocation(),
18293 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18294 << D;
18295 continue;
18298 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18299 // A list item cannot appear in both a map clause and a data-sharing
18300 // attribute clause on the same construct
18302 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18303 // A list item cannot appear in both a map clause and a data-sharing
18304 // attribute clause on the same construct unless the construct is a
18305 // combined construct.
18306 if ((LangOpts.OpenMP <= 45 && isOpenMPTargetExecutionDirective(CurrDir)) ||
18307 CurrDir == OMPD_target) {
18308 OpenMPClauseKind ConflictKind;
18309 if (DSAStack->checkMappableExprComponentListsForDecl(
18310 VD, /*CurrentRegionOnly=*/true,
18311 [&](OMPClauseMappableExprCommon::MappableExprComponentListRef,
18312 OpenMPClauseKind WhereFoundClauseKind) -> bool {
18313 ConflictKind = WhereFoundClauseKind;
18314 return true;
18315 })) {
18316 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18317 << getOpenMPClauseName(OMPC_private)
18318 << getOpenMPClauseName(ConflictKind)
18319 << getOpenMPDirectiveName(CurrDir);
18320 reportOriginalDsa(*this, DSAStack, D, DVar);
18321 continue;
18325 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
18326 // A variable of class type (or array thereof) that appears in a private
18327 // clause requires an accessible, unambiguous default constructor for the
18328 // class type.
18329 // Generate helper private variable and initialize it with the default
18330 // value. The address of the original variable is replaced by the address of
18331 // the new private variable in CodeGen. This new variable is not added to
18332 // IdResolver, so the code in the OpenMP region uses original variable for
18333 // proper diagnostics.
18334 Type = Type.getUnqualifiedType();
18335 VarDecl *VDPrivate =
18336 buildVarDecl(*this, ELoc, Type, D->getName(),
18337 D->hasAttrs() ? &D->getAttrs() : nullptr,
18338 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18339 ActOnUninitializedDecl(VDPrivate);
18340 if (VDPrivate->isInvalidDecl())
18341 continue;
18342 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18343 *this, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
18345 DeclRefExpr *Ref = nullptr;
18346 if (!VD && !CurContext->isDependentContext()) {
18347 auto *FD = dyn_cast<FieldDecl>(D);
18348 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
18349 if (VD)
18350 Ref = buildDeclRefExpr(*this, VD, VD->getType().getNonReferenceType(),
18351 RefExpr->getExprLoc());
18352 else
18353 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
18355 if (!IsImplicitClause)
18356 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
18357 Vars.push_back((VD || CurContext->isDependentContext())
18358 ? RefExpr->IgnoreParens()
18359 : Ref);
18360 PrivateCopies.push_back(VDPrivateRefExpr);
18363 if (Vars.empty())
18364 return nullptr;
18366 return OMPPrivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars,
18367 PrivateCopies);
18370 OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
18371 SourceLocation StartLoc,
18372 SourceLocation LParenLoc,
18373 SourceLocation EndLoc) {
18374 SmallVector<Expr *, 8> Vars;
18375 SmallVector<Expr *, 8> PrivateCopies;
18376 SmallVector<Expr *, 8> Inits;
18377 SmallVector<Decl *, 4> ExprCaptures;
18378 bool IsImplicitClause =
18379 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
18380 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
18382 for (Expr *RefExpr : VarList) {
18383 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
18384 SourceLocation ELoc;
18385 SourceRange ERange;
18386 Expr *SimpleRefExpr = RefExpr;
18387 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
18388 if (Res.second) {
18389 // It will be analyzed later.
18390 Vars.push_back(RefExpr);
18391 PrivateCopies.push_back(nullptr);
18392 Inits.push_back(nullptr);
18394 ValueDecl *D = Res.first;
18395 if (!D)
18396 continue;
18398 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
18399 QualType Type = D->getType();
18400 auto *VD = dyn_cast<VarDecl>(D);
18402 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18403 // A variable that appears in a private clause must not have an incomplete
18404 // type or a reference type.
18405 if (RequireCompleteType(ELoc, Type,
18406 diag::err_omp_firstprivate_incomplete_type))
18407 continue;
18408 Type = Type.getNonReferenceType();
18410 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
18411 // A variable of class type (or array thereof) that appears in a private
18412 // clause requires an accessible, unambiguous copy constructor for the
18413 // class type.
18414 QualType ElemType = Context.getBaseElementType(Type).getNonReferenceType();
18416 // If an implicit firstprivate variable found it was checked already.
18417 DSAStackTy::DSAVarData TopDVar;
18418 if (!IsImplicitClause) {
18419 DSAStackTy::DSAVarData DVar =
18420 DSAStack->getTopDSA(D, /*FromParent=*/false);
18421 TopDVar = DVar;
18422 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18423 bool IsConstant = ElemType.isConstant(Context);
18424 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
18425 // A list item that specifies a given variable may not appear in more
18426 // than one clause on the same directive, except that a variable may be
18427 // specified in both firstprivate and lastprivate clauses.
18428 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18429 // A list item may appear in a firstprivate or lastprivate clause but not
18430 // both.
18431 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
18432 (isOpenMPDistributeDirective(CurrDir) ||
18433 DVar.CKind != OMPC_lastprivate) &&
18434 DVar.RefExpr) {
18435 Diag(ELoc, diag::err_omp_wrong_dsa)
18436 << getOpenMPClauseName(DVar.CKind)
18437 << getOpenMPClauseName(OMPC_firstprivate);
18438 reportOriginalDsa(*this, DSAStack, D, DVar);
18439 continue;
18442 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18443 // in a Construct]
18444 // Variables with the predetermined data-sharing attributes may not be
18445 // listed in data-sharing attributes clauses, except for the cases
18446 // listed below. For these exceptions only, listing a predetermined
18447 // variable in a data-sharing attribute clause is allowed and overrides
18448 // the variable's predetermined data-sharing attributes.
18449 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18450 // in a Construct, C/C++, p.2]
18451 // Variables with const-qualified type having no mutable member may be
18452 // listed in a firstprivate clause, even if they are static data members.
18453 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
18454 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
18455 Diag(ELoc, diag::err_omp_wrong_dsa)
18456 << getOpenMPClauseName(DVar.CKind)
18457 << getOpenMPClauseName(OMPC_firstprivate);
18458 reportOriginalDsa(*this, DSAStack, D, DVar);
18459 continue;
18462 // OpenMP [2.9.3.4, Restrictions, p.2]
18463 // A list item that is private within a parallel region must not appear
18464 // in a firstprivate clause on a worksharing construct if any of the
18465 // worksharing regions arising from the worksharing construct ever bind
18466 // to any of the parallel regions arising from the parallel construct.
18467 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18468 // A list item that is private within a teams region must not appear in a
18469 // firstprivate clause on a distribute construct if any of the distribute
18470 // regions arising from the distribute construct ever bind to any of the
18471 // teams regions arising from the teams construct.
18472 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18473 // A list item that appears in a reduction clause of a teams construct
18474 // must not appear in a firstprivate clause on a distribute construct if
18475 // any of the distribute regions arising from the distribute construct
18476 // ever bind to any of the teams regions arising from the teams construct.
18477 if ((isOpenMPWorksharingDirective(CurrDir) ||
18478 isOpenMPDistributeDirective(CurrDir)) &&
18479 !isOpenMPParallelDirective(CurrDir) &&
18480 !isOpenMPTeamsDirective(CurrDir)) {
18481 DVar = DSAStack->getImplicitDSA(D, true);
18482 if (DVar.CKind != OMPC_shared &&
18483 (isOpenMPParallelDirective(DVar.DKind) ||
18484 isOpenMPTeamsDirective(DVar.DKind) ||
18485 DVar.DKind == OMPD_unknown)) {
18486 Diag(ELoc, diag::err_omp_required_access)
18487 << getOpenMPClauseName(OMPC_firstprivate)
18488 << getOpenMPClauseName(OMPC_shared);
18489 reportOriginalDsa(*this, DSAStack, D, DVar);
18490 continue;
18493 // OpenMP [2.9.3.4, Restrictions, p.3]
18494 // A list item that appears in a reduction clause of a parallel construct
18495 // must not appear in a firstprivate clause on a worksharing or task
18496 // construct if any of the worksharing or task regions arising from the
18497 // worksharing or task construct ever bind to any of the parallel regions
18498 // arising from the parallel construct.
18499 // OpenMP [2.9.3.4, Restrictions, p.4]
18500 // A list item that appears in a reduction clause in worksharing
18501 // construct must not appear in a firstprivate clause in a task construct
18502 // encountered during execution of any of the worksharing regions arising
18503 // from the worksharing construct.
18504 if (isOpenMPTaskingDirective(CurrDir)) {
18505 DVar = DSAStack->hasInnermostDSA(
18507 [](OpenMPClauseKind C, bool AppliedToPointee) {
18508 return C == OMPC_reduction && !AppliedToPointee;
18510 [](OpenMPDirectiveKind K) {
18511 return isOpenMPParallelDirective(K) ||
18512 isOpenMPWorksharingDirective(K) ||
18513 isOpenMPTeamsDirective(K);
18515 /*FromParent=*/true);
18516 if (DVar.CKind == OMPC_reduction &&
18517 (isOpenMPParallelDirective(DVar.DKind) ||
18518 isOpenMPWorksharingDirective(DVar.DKind) ||
18519 isOpenMPTeamsDirective(DVar.DKind))) {
18520 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
18521 << getOpenMPDirectiveName(DVar.DKind);
18522 reportOriginalDsa(*this, DSAStack, D, DVar);
18523 continue;
18527 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18528 // A list item cannot appear in both a map clause and a data-sharing
18529 // attribute clause on the same construct
18531 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18532 // A list item cannot appear in both a map clause and a data-sharing
18533 // attribute clause on the same construct unless the construct is a
18534 // combined construct.
18535 if ((LangOpts.OpenMP <= 45 &&
18536 isOpenMPTargetExecutionDirective(CurrDir)) ||
18537 CurrDir == OMPD_target) {
18538 OpenMPClauseKind ConflictKind;
18539 if (DSAStack->checkMappableExprComponentListsForDecl(
18540 VD, /*CurrentRegionOnly=*/true,
18541 [&ConflictKind](
18542 OMPClauseMappableExprCommon::MappableExprComponentListRef,
18543 OpenMPClauseKind WhereFoundClauseKind) {
18544 ConflictKind = WhereFoundClauseKind;
18545 return true;
18546 })) {
18547 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18548 << getOpenMPClauseName(OMPC_firstprivate)
18549 << getOpenMPClauseName(ConflictKind)
18550 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
18551 reportOriginalDsa(*this, DSAStack, D, DVar);
18552 continue;
18557 // Variably modified types are not supported for tasks.
18558 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
18559 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
18560 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18561 << getOpenMPClauseName(OMPC_firstprivate) << Type
18562 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
18563 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18564 VarDecl::DeclarationOnly;
18565 Diag(D->getLocation(),
18566 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18567 << D;
18568 continue;
18571 Type = Type.getUnqualifiedType();
18572 VarDecl *VDPrivate =
18573 buildVarDecl(*this, ELoc, Type, D->getName(),
18574 D->hasAttrs() ? &D->getAttrs() : nullptr,
18575 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18576 // Generate helper private variable and initialize it with the value of the
18577 // original variable. The address of the original variable is replaced by
18578 // the address of the new private variable in the CodeGen. This new variable
18579 // is not added to IdResolver, so the code in the OpenMP region uses
18580 // original variable for proper diagnostics and variable capturing.
18581 Expr *VDInitRefExpr = nullptr;
18582 // For arrays generate initializer for single element and replace it by the
18583 // original array element in CodeGen.
18584 if (Type->isArrayType()) {
18585 VarDecl *VDInit =
18586 buildVarDecl(*this, RefExpr->getExprLoc(), ElemType, D->getName());
18587 VDInitRefExpr = buildDeclRefExpr(*this, VDInit, ElemType, ELoc);
18588 Expr *Init = DefaultLvalueConversion(VDInitRefExpr).get();
18589 ElemType = ElemType.getUnqualifiedType();
18590 VarDecl *VDInitTemp = buildVarDecl(*this, RefExpr->getExprLoc(), ElemType,
18591 ".firstprivate.temp");
18592 InitializedEntity Entity =
18593 InitializedEntity::InitializeVariable(VDInitTemp);
18594 InitializationKind Kind = InitializationKind::CreateCopy(ELoc, ELoc);
18596 InitializationSequence InitSeq(*this, Entity, Kind, Init);
18597 ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Init);
18598 if (Result.isInvalid())
18599 VDPrivate->setInvalidDecl();
18600 else
18601 VDPrivate->setInit(Result.getAs<Expr>());
18602 // Remove temp variable declaration.
18603 Context.Deallocate(VDInitTemp);
18604 } else {
18605 VarDecl *VDInit = buildVarDecl(*this, RefExpr->getExprLoc(), Type,
18606 ".firstprivate.temp");
18607 VDInitRefExpr = buildDeclRefExpr(*this, VDInit, RefExpr->getType(),
18608 RefExpr->getExprLoc());
18609 AddInitializerToDecl(VDPrivate,
18610 DefaultLvalueConversion(VDInitRefExpr).get(),
18611 /*DirectInit=*/false);
18613 if (VDPrivate->isInvalidDecl()) {
18614 if (IsImplicitClause) {
18615 Diag(RefExpr->getExprLoc(),
18616 diag::note_omp_task_predetermined_firstprivate_here);
18618 continue;
18620 CurContext->addDecl(VDPrivate);
18621 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18622 *this, VDPrivate, RefExpr->getType().getUnqualifiedType(),
18623 RefExpr->getExprLoc());
18624 DeclRefExpr *Ref = nullptr;
18625 if (!VD && !CurContext->isDependentContext()) {
18626 if (TopDVar.CKind == OMPC_lastprivate) {
18627 Ref = TopDVar.PrivateCopy;
18628 } else {
18629 auto *FD = dyn_cast<FieldDecl>(D);
18630 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
18631 if (VD)
18632 Ref = buildDeclRefExpr(*this, VD, VD->getType().getNonReferenceType(),
18633 RefExpr->getExprLoc());
18634 else
18635 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
18636 if (VD || !isOpenMPCapturedDecl(D))
18637 ExprCaptures.push_back(Ref->getDecl());
18640 if (!IsImplicitClause)
18641 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
18642 Vars.push_back((VD || CurContext->isDependentContext())
18643 ? RefExpr->IgnoreParens()
18644 : Ref);
18645 PrivateCopies.push_back(VDPrivateRefExpr);
18646 Inits.push_back(VDInitRefExpr);
18649 if (Vars.empty())
18650 return nullptr;
18652 return OMPFirstprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
18653 Vars, PrivateCopies, Inits,
18654 buildPreInits(Context, ExprCaptures));
18657 OMPClause *Sema::ActOnOpenMPLastprivateClause(
18658 ArrayRef<Expr *> VarList, OpenMPLastprivateModifier LPKind,
18659 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
18660 SourceLocation LParenLoc, SourceLocation EndLoc) {
18661 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
18662 assert(ColonLoc.isValid() && "Colon location must be valid.");
18663 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
18664 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
18665 /*Last=*/OMPC_LASTPRIVATE_unknown)
18666 << getOpenMPClauseName(OMPC_lastprivate);
18667 return nullptr;
18670 SmallVector<Expr *, 8> Vars;
18671 SmallVector<Expr *, 8> SrcExprs;
18672 SmallVector<Expr *, 8> DstExprs;
18673 SmallVector<Expr *, 8> AssignmentOps;
18674 SmallVector<Decl *, 4> ExprCaptures;
18675 SmallVector<Expr *, 4> ExprPostUpdates;
18676 for (Expr *RefExpr : VarList) {
18677 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
18678 SourceLocation ELoc;
18679 SourceRange ERange;
18680 Expr *SimpleRefExpr = RefExpr;
18681 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
18682 if (Res.second) {
18683 // It will be analyzed later.
18684 Vars.push_back(RefExpr);
18685 SrcExprs.push_back(nullptr);
18686 DstExprs.push_back(nullptr);
18687 AssignmentOps.push_back(nullptr);
18689 ValueDecl *D = Res.first;
18690 if (!D)
18691 continue;
18693 QualType Type = D->getType();
18694 auto *VD = dyn_cast<VarDecl>(D);
18696 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
18697 // A variable that appears in a lastprivate clause must not have an
18698 // incomplete type or a reference type.
18699 if (RequireCompleteType(ELoc, Type,
18700 diag::err_omp_lastprivate_incomplete_type))
18701 continue;
18702 Type = Type.getNonReferenceType();
18704 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18705 // A variable that is privatized must not have a const-qualified type
18706 // unless it is of class type with a mutable member. This restriction does
18707 // not apply to the firstprivate clause.
18709 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
18710 // A variable that appears in a lastprivate clause must not have a
18711 // const-qualified type unless it is of class type with a mutable member.
18712 if (rejectConstNotMutableType(*this, D, Type, OMPC_lastprivate, ELoc))
18713 continue;
18715 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
18716 // A list item that appears in a lastprivate clause with the conditional
18717 // modifier must be a scalar variable.
18718 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
18719 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
18720 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18721 VarDecl::DeclarationOnly;
18722 Diag(D->getLocation(),
18723 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18724 << D;
18725 continue;
18728 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18729 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
18730 // in a Construct]
18731 // Variables with the predetermined data-sharing attributes may not be
18732 // listed in data-sharing attributes clauses, except for the cases
18733 // listed below.
18734 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18735 // A list item may appear in a firstprivate or lastprivate clause but not
18736 // both.
18737 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18738 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
18739 (isOpenMPDistributeDirective(CurrDir) ||
18740 DVar.CKind != OMPC_firstprivate) &&
18741 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
18742 Diag(ELoc, diag::err_omp_wrong_dsa)
18743 << getOpenMPClauseName(DVar.CKind)
18744 << getOpenMPClauseName(OMPC_lastprivate);
18745 reportOriginalDsa(*this, DSAStack, D, DVar);
18746 continue;
18749 // OpenMP [2.14.3.5, Restrictions, p.2]
18750 // A list item that is private within a parallel region, or that appears in
18751 // the reduction clause of a parallel construct, must not appear in a
18752 // lastprivate clause on a worksharing construct if any of the corresponding
18753 // worksharing regions ever binds to any of the corresponding parallel
18754 // regions.
18755 DSAStackTy::DSAVarData TopDVar = DVar;
18756 if (isOpenMPWorksharingDirective(CurrDir) &&
18757 !isOpenMPParallelDirective(CurrDir) &&
18758 !isOpenMPTeamsDirective(CurrDir)) {
18759 DVar = DSAStack->getImplicitDSA(D, true);
18760 if (DVar.CKind != OMPC_shared) {
18761 Diag(ELoc, diag::err_omp_required_access)
18762 << getOpenMPClauseName(OMPC_lastprivate)
18763 << getOpenMPClauseName(OMPC_shared);
18764 reportOriginalDsa(*this, DSAStack, D, DVar);
18765 continue;
18769 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
18770 // A variable of class type (or array thereof) that appears in a
18771 // lastprivate clause requires an accessible, unambiguous default
18772 // constructor for the class type, unless the list item is also specified
18773 // in a firstprivate clause.
18774 // A variable of class type (or array thereof) that appears in a
18775 // lastprivate clause requires an accessible, unambiguous copy assignment
18776 // operator for the class type.
18777 Type = Context.getBaseElementType(Type).getNonReferenceType();
18778 VarDecl *SrcVD = buildVarDecl(*this, ERange.getBegin(),
18779 Type.getUnqualifiedType(), ".lastprivate.src",
18780 D->hasAttrs() ? &D->getAttrs() : nullptr);
18781 DeclRefExpr *PseudoSrcExpr =
18782 buildDeclRefExpr(*this, SrcVD, Type.getUnqualifiedType(), ELoc);
18783 VarDecl *DstVD =
18784 buildVarDecl(*this, ERange.getBegin(), Type, ".lastprivate.dst",
18785 D->hasAttrs() ? &D->getAttrs() : nullptr);
18786 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc);
18787 // For arrays generate assignment operation for single element and replace
18788 // it by the original array element in CodeGen.
18789 ExprResult AssignmentOp = BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
18790 PseudoDstExpr, PseudoSrcExpr);
18791 if (AssignmentOp.isInvalid())
18792 continue;
18793 AssignmentOp =
18794 ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false);
18795 if (AssignmentOp.isInvalid())
18796 continue;
18798 DeclRefExpr *Ref = nullptr;
18799 if (!VD && !CurContext->isDependentContext()) {
18800 if (TopDVar.CKind == OMPC_firstprivate) {
18801 Ref = TopDVar.PrivateCopy;
18802 } else {
18803 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
18804 if (!isOpenMPCapturedDecl(D))
18805 ExprCaptures.push_back(Ref->getDecl());
18807 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
18808 (!isOpenMPCapturedDecl(D) &&
18809 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
18810 ExprResult RefRes = DefaultLvalueConversion(Ref);
18811 if (!RefRes.isUsable())
18812 continue;
18813 ExprResult PostUpdateRes =
18814 BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
18815 RefRes.get());
18816 if (!PostUpdateRes.isUsable())
18817 continue;
18818 ExprPostUpdates.push_back(
18819 IgnoredValueConversions(PostUpdateRes.get()).get());
18822 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
18823 Vars.push_back((VD || CurContext->isDependentContext())
18824 ? RefExpr->IgnoreParens()
18825 : Ref);
18826 SrcExprs.push_back(PseudoSrcExpr);
18827 DstExprs.push_back(PseudoDstExpr);
18828 AssignmentOps.push_back(AssignmentOp.get());
18831 if (Vars.empty())
18832 return nullptr;
18834 return OMPLastprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
18835 Vars, SrcExprs, DstExprs, AssignmentOps,
18836 LPKind, LPKindLoc, ColonLoc,
18837 buildPreInits(Context, ExprCaptures),
18838 buildPostUpdate(*this, ExprPostUpdates));
18841 OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
18842 SourceLocation StartLoc,
18843 SourceLocation LParenLoc,
18844 SourceLocation EndLoc) {
18845 SmallVector<Expr *, 8> Vars;
18846 for (Expr *RefExpr : VarList) {
18847 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
18848 SourceLocation ELoc;
18849 SourceRange ERange;
18850 Expr *SimpleRefExpr = RefExpr;
18851 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
18852 if (Res.second) {
18853 // It will be analyzed later.
18854 Vars.push_back(RefExpr);
18856 ValueDecl *D = Res.first;
18857 if (!D)
18858 continue;
18860 auto *VD = dyn_cast<VarDecl>(D);
18861 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18862 // in a Construct]
18863 // Variables with the predetermined data-sharing attributes may not be
18864 // listed in data-sharing attributes clauses, except for the cases
18865 // listed below. For these exceptions only, listing a predetermined
18866 // variable in a data-sharing attribute clause is allowed and overrides
18867 // the variable's predetermined data-sharing attributes.
18868 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18869 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
18870 DVar.RefExpr) {
18871 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
18872 << getOpenMPClauseName(OMPC_shared);
18873 reportOriginalDsa(*this, DSAStack, D, DVar);
18874 continue;
18877 DeclRefExpr *Ref = nullptr;
18878 if (!VD && isOpenMPCapturedDecl(D) && !CurContext->isDependentContext())
18879 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
18880 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
18881 Vars.push_back((VD || !Ref || CurContext->isDependentContext())
18882 ? RefExpr->IgnoreParens()
18883 : Ref);
18886 if (Vars.empty())
18887 return nullptr;
18889 return OMPSharedClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
18892 namespace {
18893 class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
18894 DSAStackTy *Stack;
18896 public:
18897 bool VisitDeclRefExpr(DeclRefExpr *E) {
18898 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
18899 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
18900 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
18901 return false;
18902 if (DVar.CKind != OMPC_unknown)
18903 return true;
18904 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
18906 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
18907 return isOpenMPPrivate(C) && !AppliedToPointee;
18909 [](OpenMPDirectiveKind) { return true; },
18910 /*FromParent=*/true);
18911 return DVarPrivate.CKind != OMPC_unknown;
18913 return false;
18915 bool VisitStmt(Stmt *S) {
18916 for (Stmt *Child : S->children()) {
18917 if (Child && Visit(Child))
18918 return true;
18920 return false;
18922 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
18924 } // namespace
18926 namespace {
18927 // Transform MemberExpression for specified FieldDecl of current class to
18928 // DeclRefExpr to specified OMPCapturedExprDecl.
18929 class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
18930 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
18931 ValueDecl *Field = nullptr;
18932 DeclRefExpr *CapturedExpr = nullptr;
18934 public:
18935 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
18936 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
18938 ExprResult TransformMemberExpr(MemberExpr *E) {
18939 if (isa<CXXThisExpr>(E->getBase()->IgnoreParenImpCasts()) &&
18940 E->getMemberDecl() == Field) {
18941 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
18942 return CapturedExpr;
18944 return BaseTransform::TransformMemberExpr(E);
18946 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
18948 } // namespace
18950 template <typename T, typename U>
18951 static T filterLookupForUDReductionAndMapper(
18952 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
18953 for (U &Set : Lookups) {
18954 for (auto *D : Set) {
18955 if (T Res = Gen(cast<ValueDecl>(D)))
18956 return Res;
18959 return T();
18962 static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
18963 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
18965 for (auto *RD : D->redecls()) {
18966 // Don't bother with extra checks if we already know this one isn't visible.
18967 if (RD == D)
18968 continue;
18970 auto ND = cast<NamedDecl>(RD);
18971 if (LookupResult::isVisible(SemaRef, ND))
18972 return ND;
18975 return nullptr;
18978 static void
18979 argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id,
18980 SourceLocation Loc, QualType Ty,
18981 SmallVectorImpl<UnresolvedSet<8>> &Lookups) {
18982 // Find all of the associated namespaces and classes based on the
18983 // arguments we have.
18984 Sema::AssociatedNamespaceSet AssociatedNamespaces;
18985 Sema::AssociatedClassSet AssociatedClasses;
18986 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
18987 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
18988 AssociatedClasses);
18990 // C++ [basic.lookup.argdep]p3:
18991 // Let X be the lookup set produced by unqualified lookup (3.4.1)
18992 // and let Y be the lookup set produced by argument dependent
18993 // lookup (defined as follows). If X contains [...] then Y is
18994 // empty. Otherwise Y is the set of declarations found in the
18995 // namespaces associated with the argument types as described
18996 // below. The set of declarations found by the lookup of the name
18997 // is the union of X and Y.
18999 // Here, we compute Y and add its members to the overloaded
19000 // candidate set.
19001 for (auto *NS : AssociatedNamespaces) {
19002 // When considering an associated namespace, the lookup is the
19003 // same as the lookup performed when the associated namespace is
19004 // used as a qualifier (3.4.3.2) except that:
19006 // -- Any using-directives in the associated namespace are
19007 // ignored.
19009 // -- Any namespace-scope friend functions declared in
19010 // associated classes are visible within their respective
19011 // namespaces even if they are not visible during an ordinary
19012 // lookup (11.4).
19013 DeclContext::lookup_result R = NS->lookup(Id.getName());
19014 for (auto *D : R) {
19015 auto *Underlying = D;
19016 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
19017 Underlying = USD->getTargetDecl();
19019 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
19020 !isa<OMPDeclareMapperDecl>(Underlying))
19021 continue;
19023 if (!SemaRef.isVisible(D)) {
19024 D = findAcceptableDecl(SemaRef, D);
19025 if (!D)
19026 continue;
19027 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
19028 Underlying = USD->getTargetDecl();
19030 Lookups.emplace_back();
19031 Lookups.back().addDecl(Underlying);
19036 static ExprResult
19037 buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
19038 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
19039 const DeclarationNameInfo &ReductionId, QualType Ty,
19040 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
19041 if (ReductionIdScopeSpec.isInvalid())
19042 return ExprError();
19043 SmallVector<UnresolvedSet<8>, 4> Lookups;
19044 if (S) {
19045 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
19046 Lookup.suppressDiagnostics();
19047 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec)) {
19048 NamedDecl *D = Lookup.getRepresentativeDecl();
19049 do {
19050 S = S->getParent();
19051 } while (S && !S->isDeclScope(D));
19052 if (S)
19053 S = S->getParent();
19054 Lookups.emplace_back();
19055 Lookups.back().append(Lookup.begin(), Lookup.end());
19056 Lookup.clear();
19058 } else if (auto *ULE =
19059 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
19060 Lookups.push_back(UnresolvedSet<8>());
19061 Decl *PrevD = nullptr;
19062 for (NamedDecl *D : ULE->decls()) {
19063 if (D == PrevD)
19064 Lookups.push_back(UnresolvedSet<8>());
19065 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
19066 Lookups.back().addDecl(DRD);
19067 PrevD = D;
19070 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
19071 Ty->isInstantiationDependentType() ||
19072 Ty->containsUnexpandedParameterPack() ||
19073 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
19074 return !D->isInvalidDecl() &&
19075 (D->getType()->isDependentType() ||
19076 D->getType()->isInstantiationDependentType() ||
19077 D->getType()->containsUnexpandedParameterPack());
19078 })) {
19079 UnresolvedSet<8> ResSet;
19080 for (const UnresolvedSet<8> &Set : Lookups) {
19081 if (Set.empty())
19082 continue;
19083 ResSet.append(Set.begin(), Set.end());
19084 // The last item marks the end of all declarations at the specified scope.
19085 ResSet.addDecl(Set[Set.size() - 1]);
19087 return UnresolvedLookupExpr::Create(
19088 SemaRef.Context, /*NamingClass=*/nullptr,
19089 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
19090 /*ADL=*/true, /*Overloaded=*/true, ResSet.begin(), ResSet.end());
19092 // Lookup inside the classes.
19093 // C++ [over.match.oper]p3:
19094 // For a unary operator @ with an operand of a type whose
19095 // cv-unqualified version is T1, and for a binary operator @ with
19096 // a left operand of a type whose cv-unqualified version is T1 and
19097 // a right operand of a type whose cv-unqualified version is T2,
19098 // three sets of candidate functions, designated member
19099 // candidates, non-member candidates and built-in candidates, are
19100 // constructed as follows:
19101 // -- If T1 is a complete class type or a class currently being
19102 // defined, the set of member candidates is the result of the
19103 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
19104 // the set of member candidates is empty.
19105 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
19106 Lookup.suppressDiagnostics();
19107 if (const auto *TyRec = Ty->getAs<RecordType>()) {
19108 // Complete the type if it can be completed.
19109 // If the type is neither complete nor being defined, bail out now.
19110 if (SemaRef.isCompleteType(Loc, Ty) || TyRec->isBeingDefined() ||
19111 TyRec->getDecl()->getDefinition()) {
19112 Lookup.clear();
19113 SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl());
19114 if (Lookup.empty()) {
19115 Lookups.emplace_back();
19116 Lookups.back().append(Lookup.begin(), Lookup.end());
19120 // Perform ADL.
19121 if (SemaRef.getLangOpts().CPlusPlus)
19122 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
19123 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
19124 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
19125 if (!D->isInvalidDecl() &&
19126 SemaRef.Context.hasSameType(D->getType(), Ty))
19127 return D;
19128 return nullptr;
19130 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
19131 VK_LValue, Loc);
19132 if (SemaRef.getLangOpts().CPlusPlus) {
19133 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
19134 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
19135 if (!D->isInvalidDecl() &&
19136 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
19137 !Ty.isMoreQualifiedThan(D->getType()))
19138 return D;
19139 return nullptr;
19140 })) {
19141 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
19142 /*DetectVirtual=*/false);
19143 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
19144 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
19145 VD->getType().getUnqualifiedType()))) {
19146 if (SemaRef.CheckBaseClassAccess(
19147 Loc, VD->getType(), Ty, Paths.front(),
19148 /*DiagID=*/0) != Sema::AR_inaccessible) {
19149 SemaRef.BuildBasePathArray(Paths, BasePath);
19150 return SemaRef.BuildDeclRefExpr(
19151 VD, VD->getType().getNonReferenceType(), VK_LValue, Loc);
19157 if (ReductionIdScopeSpec.isSet()) {
19158 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
19159 << Ty << Range;
19160 return ExprError();
19162 return ExprEmpty();
19165 namespace {
19166 /// Data for the reduction-based clauses.
19167 struct ReductionData {
19168 /// List of original reduction items.
19169 SmallVector<Expr *, 8> Vars;
19170 /// List of private copies of the reduction items.
19171 SmallVector<Expr *, 8> Privates;
19172 /// LHS expressions for the reduction_op expressions.
19173 SmallVector<Expr *, 8> LHSs;
19174 /// RHS expressions for the reduction_op expressions.
19175 SmallVector<Expr *, 8> RHSs;
19176 /// Reduction operation expression.
19177 SmallVector<Expr *, 8> ReductionOps;
19178 /// inscan copy operation expressions.
19179 SmallVector<Expr *, 8> InscanCopyOps;
19180 /// inscan copy temp array expressions for prefix sums.
19181 SmallVector<Expr *, 8> InscanCopyArrayTemps;
19182 /// inscan copy temp array element expressions for prefix sums.
19183 SmallVector<Expr *, 8> InscanCopyArrayElems;
19184 /// Taskgroup descriptors for the corresponding reduction items in
19185 /// in_reduction clauses.
19186 SmallVector<Expr *, 8> TaskgroupDescriptors;
19187 /// List of captures for clause.
19188 SmallVector<Decl *, 4> ExprCaptures;
19189 /// List of postupdate expressions.
19190 SmallVector<Expr *, 4> ExprPostUpdates;
19191 /// Reduction modifier.
19192 unsigned RedModifier = 0;
19193 ReductionData() = delete;
19194 /// Reserves required memory for the reduction data.
19195 ReductionData(unsigned Size, unsigned Modifier = 0) : RedModifier(Modifier) {
19196 Vars.reserve(Size);
19197 Privates.reserve(Size);
19198 LHSs.reserve(Size);
19199 RHSs.reserve(Size);
19200 ReductionOps.reserve(Size);
19201 if (RedModifier == OMPC_REDUCTION_inscan) {
19202 InscanCopyOps.reserve(Size);
19203 InscanCopyArrayTemps.reserve(Size);
19204 InscanCopyArrayElems.reserve(Size);
19206 TaskgroupDescriptors.reserve(Size);
19207 ExprCaptures.reserve(Size);
19208 ExprPostUpdates.reserve(Size);
19210 /// Stores reduction item and reduction operation only (required for dependent
19211 /// reduction item).
19212 void push(Expr *Item, Expr *ReductionOp) {
19213 Vars.emplace_back(Item);
19214 Privates.emplace_back(nullptr);
19215 LHSs.emplace_back(nullptr);
19216 RHSs.emplace_back(nullptr);
19217 ReductionOps.emplace_back(ReductionOp);
19218 TaskgroupDescriptors.emplace_back(nullptr);
19219 if (RedModifier == OMPC_REDUCTION_inscan) {
19220 InscanCopyOps.push_back(nullptr);
19221 InscanCopyArrayTemps.push_back(nullptr);
19222 InscanCopyArrayElems.push_back(nullptr);
19225 /// Stores reduction data.
19226 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
19227 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
19228 Expr *CopyArrayElem) {
19229 Vars.emplace_back(Item);
19230 Privates.emplace_back(Private);
19231 LHSs.emplace_back(LHS);
19232 RHSs.emplace_back(RHS);
19233 ReductionOps.emplace_back(ReductionOp);
19234 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
19235 if (RedModifier == OMPC_REDUCTION_inscan) {
19236 InscanCopyOps.push_back(CopyOp);
19237 InscanCopyArrayTemps.push_back(CopyArrayTemp);
19238 InscanCopyArrayElems.push_back(CopyArrayElem);
19239 } else {
19240 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
19241 CopyArrayElem == nullptr &&
19242 "Copy operation must be used for inscan reductions only.");
19246 } // namespace
19248 static bool checkOMPArraySectionConstantForReduction(
19249 ASTContext &Context, const OMPArraySectionExpr *OASE, bool &SingleElement,
19250 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
19251 const Expr *Length = OASE->getLength();
19252 if (Length == nullptr) {
19253 // For array sections of the form [1:] or [:], we would need to analyze
19254 // the lower bound...
19255 if (OASE->getColonLocFirst().isValid())
19256 return false;
19258 // This is an array subscript which has implicit length 1!
19259 SingleElement = true;
19260 ArraySizes.push_back(llvm::APSInt::get(1));
19261 } else {
19262 Expr::EvalResult Result;
19263 if (!Length->EvaluateAsInt(Result, Context))
19264 return false;
19266 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19267 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
19268 ArraySizes.push_back(ConstantLengthValue);
19271 // Get the base of this array section and walk up from there.
19272 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
19274 // We require length = 1 for all array sections except the right-most to
19275 // guarantee that the memory region is contiguous and has no holes in it.
19276 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) {
19277 Length = TempOASE->getLength();
19278 if (Length == nullptr) {
19279 // For array sections of the form [1:] or [:], we would need to analyze
19280 // the lower bound...
19281 if (OASE->getColonLocFirst().isValid())
19282 return false;
19284 // This is an array subscript which has implicit length 1!
19285 ArraySizes.push_back(llvm::APSInt::get(1));
19286 } else {
19287 Expr::EvalResult Result;
19288 if (!Length->EvaluateAsInt(Result, Context))
19289 return false;
19291 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19292 if (ConstantLengthValue.getSExtValue() != 1)
19293 return false;
19295 ArraySizes.push_back(ConstantLengthValue);
19297 Base = TempOASE->getBase()->IgnoreParenImpCasts();
19300 // If we have a single element, we don't need to add the implicit lengths.
19301 if (!SingleElement) {
19302 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
19303 // Has implicit length 1!
19304 ArraySizes.push_back(llvm::APSInt::get(1));
19305 Base = TempASE->getBase()->IgnoreParenImpCasts();
19309 // This array section can be privatized as a single value or as a constant
19310 // sized array.
19311 return true;
19314 static BinaryOperatorKind
19315 getRelatedCompoundReductionOp(BinaryOperatorKind BOK) {
19316 if (BOK == BO_Add)
19317 return BO_AddAssign;
19318 if (BOK == BO_Mul)
19319 return BO_MulAssign;
19320 if (BOK == BO_And)
19321 return BO_AndAssign;
19322 if (BOK == BO_Or)
19323 return BO_OrAssign;
19324 if (BOK == BO_Xor)
19325 return BO_XorAssign;
19326 return BOK;
19329 static bool actOnOMPReductionKindClause(
19330 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
19331 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19332 SourceLocation ColonLoc, SourceLocation EndLoc,
19333 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19334 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
19335 DeclarationName DN = ReductionId.getName();
19336 OverloadedOperatorKind OOK = DN.getCXXOverloadedOperator();
19337 BinaryOperatorKind BOK = BO_Comma;
19339 ASTContext &Context = S.Context;
19340 // OpenMP [2.14.3.6, reduction clause]
19341 // C
19342 // reduction-identifier is either an identifier or one of the following
19343 // operators: +, -, *, &, |, ^, && and ||
19344 // C++
19345 // reduction-identifier is either an id-expression or one of the following
19346 // operators: +, -, *, &, |, ^, && and ||
19347 switch (OOK) {
19348 case OO_Plus:
19349 BOK = BO_Add;
19350 break;
19351 case OO_Minus:
19352 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
19353 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
19354 // reduction identifier.
19355 if (S.LangOpts.OpenMP > 52)
19356 BOK = BO_Comma;
19357 else
19358 BOK = BO_Add;
19359 break;
19360 case OO_Star:
19361 BOK = BO_Mul;
19362 break;
19363 case OO_Amp:
19364 BOK = BO_And;
19365 break;
19366 case OO_Pipe:
19367 BOK = BO_Or;
19368 break;
19369 case OO_Caret:
19370 BOK = BO_Xor;
19371 break;
19372 case OO_AmpAmp:
19373 BOK = BO_LAnd;
19374 break;
19375 case OO_PipePipe:
19376 BOK = BO_LOr;
19377 break;
19378 case OO_New:
19379 case OO_Delete:
19380 case OO_Array_New:
19381 case OO_Array_Delete:
19382 case OO_Slash:
19383 case OO_Percent:
19384 case OO_Tilde:
19385 case OO_Exclaim:
19386 case OO_Equal:
19387 case OO_Less:
19388 case OO_Greater:
19389 case OO_LessEqual:
19390 case OO_GreaterEqual:
19391 case OO_PlusEqual:
19392 case OO_MinusEqual:
19393 case OO_StarEqual:
19394 case OO_SlashEqual:
19395 case OO_PercentEqual:
19396 case OO_CaretEqual:
19397 case OO_AmpEqual:
19398 case OO_PipeEqual:
19399 case OO_LessLess:
19400 case OO_GreaterGreater:
19401 case OO_LessLessEqual:
19402 case OO_GreaterGreaterEqual:
19403 case OO_EqualEqual:
19404 case OO_ExclaimEqual:
19405 case OO_Spaceship:
19406 case OO_PlusPlus:
19407 case OO_MinusMinus:
19408 case OO_Comma:
19409 case OO_ArrowStar:
19410 case OO_Arrow:
19411 case OO_Call:
19412 case OO_Subscript:
19413 case OO_Conditional:
19414 case OO_Coawait:
19415 case NUM_OVERLOADED_OPERATORS:
19416 llvm_unreachable("Unexpected reduction identifier");
19417 case OO_None:
19418 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
19419 if (II->isStr("max"))
19420 BOK = BO_GT;
19421 else if (II->isStr("min"))
19422 BOK = BO_LT;
19424 break;
19427 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
19428 // A reduction clause with the minus (-) operator was deprecated
19429 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
19430 S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
19432 SourceRange ReductionIdRange;
19433 if (ReductionIdScopeSpec.isValid())
19434 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
19435 else
19436 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
19437 ReductionIdRange.setEnd(ReductionId.getEndLoc());
19439 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
19440 bool FirstIter = true;
19441 for (Expr *RefExpr : VarList) {
19442 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
19443 // OpenMP [2.1, C/C++]
19444 // A list item is a variable or array section, subject to the restrictions
19445 // specified in Section 2.4 on page 42 and in each of the sections
19446 // describing clauses and directives for which a list appears.
19447 // OpenMP [2.14.3.3, Restrictions, p.1]
19448 // A variable that is part of another variable (as an array or
19449 // structure element) cannot appear in a private clause.
19450 if (!FirstIter && IR != ER)
19451 ++IR;
19452 FirstIter = false;
19453 SourceLocation ELoc;
19454 SourceRange ERange;
19455 Expr *SimpleRefExpr = RefExpr;
19456 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
19457 /*AllowArraySection=*/true);
19458 if (Res.second) {
19459 // Try to find 'declare reduction' corresponding construct before using
19460 // builtin/overloaded operators.
19461 QualType Type = Context.DependentTy;
19462 CXXCastPath BasePath;
19463 ExprResult DeclareReductionRef = buildDeclareReductionRef(
19464 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
19465 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
19466 Expr *ReductionOp = nullptr;
19467 if (S.CurContext->isDependentContext() &&
19468 (DeclareReductionRef.isUnset() ||
19469 isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
19470 ReductionOp = DeclareReductionRef.get();
19471 // It will be analyzed later.
19472 RD.push(RefExpr, ReductionOp);
19474 ValueDecl *D = Res.first;
19475 if (!D)
19476 continue;
19478 Expr *TaskgroupDescriptor = nullptr;
19479 QualType Type;
19480 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
19481 auto *OASE = dyn_cast<OMPArraySectionExpr>(RefExpr->IgnoreParens());
19482 if (ASE) {
19483 Type = ASE->getType().getNonReferenceType();
19484 } else if (OASE) {
19485 QualType BaseType =
19486 OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
19487 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
19488 Type = ATy->getElementType();
19489 else
19490 Type = BaseType->getPointeeType();
19491 Type = Type.getNonReferenceType();
19492 } else {
19493 Type = Context.getBaseElementType(D->getType().getNonReferenceType());
19495 auto *VD = dyn_cast<VarDecl>(D);
19497 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19498 // A variable that appears in a private clause must not have an incomplete
19499 // type or a reference type.
19500 if (S.RequireCompleteType(ELoc, D->getType(),
19501 diag::err_omp_reduction_incomplete_type))
19502 continue;
19503 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19504 // A list item that appears in a reduction clause must not be
19505 // const-qualified.
19506 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
19507 /*AcceptIfMutable*/ false, ASE || OASE))
19508 continue;
19510 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
19511 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
19512 // If a list-item is a reference type then it must bind to the same object
19513 // for all threads of the team.
19514 if (!ASE && !OASE) {
19515 if (VD) {
19516 VarDecl *VDDef = VD->getDefinition();
19517 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
19518 DSARefChecker Check(Stack);
19519 if (Check.Visit(VDDef->getInit())) {
19520 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
19521 << getOpenMPClauseName(ClauseKind) << ERange;
19522 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
19523 continue;
19528 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
19529 // in a Construct]
19530 // Variables with the predetermined data-sharing attributes may not be
19531 // listed in data-sharing attributes clauses, except for the cases
19532 // listed below. For these exceptions only, listing a predetermined
19533 // variable in a data-sharing attribute clause is allowed and overrides
19534 // the variable's predetermined data-sharing attributes.
19535 // OpenMP [2.14.3.6, Restrictions, p.3]
19536 // Any number of reduction clauses can be specified on the directive,
19537 // but a list item can appear only once in the reduction clauses for that
19538 // directive.
19539 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19540 if (DVar.CKind == OMPC_reduction) {
19541 S.Diag(ELoc, diag::err_omp_once_referenced)
19542 << getOpenMPClauseName(ClauseKind);
19543 if (DVar.RefExpr)
19544 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
19545 continue;
19547 if (DVar.CKind != OMPC_unknown) {
19548 S.Diag(ELoc, diag::err_omp_wrong_dsa)
19549 << getOpenMPClauseName(DVar.CKind)
19550 << getOpenMPClauseName(OMPC_reduction);
19551 reportOriginalDsa(S, Stack, D, DVar);
19552 continue;
19555 // OpenMP [2.14.3.6, Restrictions, p.1]
19556 // A list item that appears in a reduction clause of a worksharing
19557 // construct must be shared in the parallel regions to which any of the
19558 // worksharing regions arising from the worksharing construct bind.
19559 if (isOpenMPWorksharingDirective(CurrDir) &&
19560 !isOpenMPParallelDirective(CurrDir) &&
19561 !isOpenMPTeamsDirective(CurrDir)) {
19562 DVar = Stack->getImplicitDSA(D, true);
19563 if (DVar.CKind != OMPC_shared) {
19564 S.Diag(ELoc, diag::err_omp_required_access)
19565 << getOpenMPClauseName(OMPC_reduction)
19566 << getOpenMPClauseName(OMPC_shared);
19567 reportOriginalDsa(S, Stack, D, DVar);
19568 continue;
19571 } else {
19572 // Threadprivates cannot be shared between threads, so dignose if the base
19573 // is a threadprivate variable.
19574 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19575 if (DVar.CKind == OMPC_threadprivate) {
19576 S.Diag(ELoc, diag::err_omp_wrong_dsa)
19577 << getOpenMPClauseName(DVar.CKind)
19578 << getOpenMPClauseName(OMPC_reduction);
19579 reportOriginalDsa(S, Stack, D, DVar);
19580 continue;
19584 // Try to find 'declare reduction' corresponding construct before using
19585 // builtin/overloaded operators.
19586 CXXCastPath BasePath;
19587 ExprResult DeclareReductionRef = buildDeclareReductionRef(
19588 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
19589 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
19590 if (DeclareReductionRef.isInvalid())
19591 continue;
19592 if (S.CurContext->isDependentContext() &&
19593 (DeclareReductionRef.isUnset() ||
19594 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
19595 RD.push(RefExpr, DeclareReductionRef.get());
19596 continue;
19598 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
19599 // Not allowed reduction identifier is found.
19600 if (S.LangOpts.OpenMP > 52)
19601 S.Diag(ReductionId.getBeginLoc(),
19602 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
19603 << Type << ReductionIdRange;
19604 else
19605 S.Diag(ReductionId.getBeginLoc(),
19606 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
19607 << Type << ReductionIdRange;
19608 continue;
19611 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19612 // The type of a list item that appears in a reduction clause must be valid
19613 // for the reduction-identifier. For a max or min reduction in C, the type
19614 // of the list item must be an allowed arithmetic data type: char, int,
19615 // float, double, or _Bool, possibly modified with long, short, signed, or
19616 // unsigned. For a max or min reduction in C++, the type of the list item
19617 // must be an allowed arithmetic data type: char, wchar_t, int, float,
19618 // double, or bool, possibly modified with long, short, signed, or unsigned.
19619 if (DeclareReductionRef.isUnset()) {
19620 if ((BOK == BO_GT || BOK == BO_LT) &&
19621 !(Type->isScalarType() ||
19622 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
19623 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
19624 << getOpenMPClauseName(ClauseKind) << S.getLangOpts().CPlusPlus;
19625 if (!ASE && !OASE) {
19626 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19627 VarDecl::DeclarationOnly;
19628 S.Diag(D->getLocation(),
19629 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19630 << D;
19632 continue;
19634 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
19635 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
19636 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
19637 << getOpenMPClauseName(ClauseKind);
19638 if (!ASE && !OASE) {
19639 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19640 VarDecl::DeclarationOnly;
19641 S.Diag(D->getLocation(),
19642 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19643 << D;
19645 continue;
19649 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
19650 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
19651 D->hasAttrs() ? &D->getAttrs() : nullptr);
19652 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
19653 D->hasAttrs() ? &D->getAttrs() : nullptr);
19654 QualType PrivateTy = Type;
19656 // Try if we can determine constant lengths for all array sections and avoid
19657 // the VLA.
19658 bool ConstantLengthOASE = false;
19659 if (OASE) {
19660 bool SingleElement;
19661 llvm::SmallVector<llvm::APSInt, 4> ArraySizes;
19662 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
19663 Context, OASE, SingleElement, ArraySizes);
19665 // If we don't have a single element, we must emit a constant array type.
19666 if (ConstantLengthOASE && !SingleElement) {
19667 for (llvm::APSInt &Size : ArraySizes)
19668 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
19669 ArraySizeModifier::Normal,
19670 /*IndexTypeQuals=*/0);
19674 if ((OASE && !ConstantLengthOASE) ||
19675 (!OASE && !ASE &&
19676 D->getType().getNonReferenceType()->isVariablyModifiedType())) {
19677 if (!Context.getTargetInfo().isVLASupported()) {
19678 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
19679 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19680 S.Diag(ELoc, diag::note_vla_unsupported);
19681 continue;
19682 } else {
19683 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19684 S.targetDiag(ELoc, diag::note_vla_unsupported);
19687 // For arrays/array sections only:
19688 // Create pseudo array type for private copy. The size for this array will
19689 // be generated during codegen.
19690 // For array subscripts or single variables Private Ty is the same as Type
19691 // (type of the variable or single array element).
19692 PrivateTy = Context.getVariableArrayType(
19693 Type,
19694 new (Context)
19695 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
19696 ArraySizeModifier::Normal, /*IndexTypeQuals=*/0, SourceRange());
19697 } else if (!ASE && !OASE &&
19698 Context.getAsArrayType(D->getType().getNonReferenceType())) {
19699 PrivateTy = D->getType().getNonReferenceType();
19701 // Private copy.
19702 VarDecl *PrivateVD =
19703 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
19704 D->hasAttrs() ? &D->getAttrs() : nullptr,
19705 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19706 // Add initializer for private variable.
19707 Expr *Init = nullptr;
19708 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
19709 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
19710 if (DeclareReductionRef.isUsable()) {
19711 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
19712 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
19713 if (DRD->getInitializer()) {
19714 Init = DRDRef;
19715 RHSVD->setInit(DRDRef);
19716 RHSVD->setInitStyle(VarDecl::CallInit);
19718 } else {
19719 switch (BOK) {
19720 case BO_Add:
19721 case BO_Xor:
19722 case BO_Or:
19723 case BO_LOr:
19724 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
19725 if (Type->isScalarType() || Type->isAnyComplexType())
19726 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
19727 break;
19728 case BO_Mul:
19729 case BO_LAnd:
19730 if (Type->isScalarType() || Type->isAnyComplexType()) {
19731 // '*' and '&&' reduction ops - initializer is '1'.
19732 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
19734 break;
19735 case BO_And: {
19736 // '&' reduction op - initializer is '~0'.
19737 QualType OrigType = Type;
19738 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
19739 Type = ComplexTy->getElementType();
19740 if (Type->isRealFloatingType()) {
19741 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
19742 Context.getFloatTypeSemantics(Type));
19743 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
19744 Type, ELoc);
19745 } else if (Type->isScalarType()) {
19746 uint64_t Size = Context.getTypeSize(Type);
19747 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
19748 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
19749 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
19751 if (Init && OrigType->isAnyComplexType()) {
19752 // Init = 0xFFFF + 0xFFFFi;
19753 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
19754 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
19756 Type = OrigType;
19757 break;
19759 case BO_LT:
19760 case BO_GT: {
19761 // 'min' reduction op - initializer is 'Largest representable number in
19762 // the reduction list item type'.
19763 // 'max' reduction op - initializer is 'Least representable number in
19764 // the reduction list item type'.
19765 if (Type->isIntegerType() || Type->isPointerType()) {
19766 bool IsSigned = Type->hasSignedIntegerRepresentation();
19767 uint64_t Size = Context.getTypeSize(Type);
19768 QualType IntTy =
19769 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
19770 llvm::APInt InitValue =
19771 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
19772 : llvm::APInt::getMinValue(Size)
19773 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
19774 : llvm::APInt::getMaxValue(Size);
19775 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
19776 if (Type->isPointerType()) {
19777 // Cast to pointer type.
19778 ExprResult CastExpr = S.BuildCStyleCastExpr(
19779 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
19780 if (CastExpr.isInvalid())
19781 continue;
19782 Init = CastExpr.get();
19784 } else if (Type->isRealFloatingType()) {
19785 llvm::APFloat InitValue = llvm::APFloat::getLargest(
19786 Context.getFloatTypeSemantics(Type), BOK != BO_LT);
19787 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
19788 Type, ELoc);
19790 break;
19792 case BO_PtrMemD:
19793 case BO_PtrMemI:
19794 case BO_MulAssign:
19795 case BO_Div:
19796 case BO_Rem:
19797 case BO_Sub:
19798 case BO_Shl:
19799 case BO_Shr:
19800 case BO_LE:
19801 case BO_GE:
19802 case BO_EQ:
19803 case BO_NE:
19804 case BO_Cmp:
19805 case BO_AndAssign:
19806 case BO_XorAssign:
19807 case BO_OrAssign:
19808 case BO_Assign:
19809 case BO_AddAssign:
19810 case BO_SubAssign:
19811 case BO_DivAssign:
19812 case BO_RemAssign:
19813 case BO_ShlAssign:
19814 case BO_ShrAssign:
19815 case BO_Comma:
19816 llvm_unreachable("Unexpected reduction operation");
19819 if (Init && DeclareReductionRef.isUnset()) {
19820 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
19821 // Store initializer for single element in private copy. Will be used
19822 // during codegen.
19823 PrivateVD->setInit(RHSVD->getInit());
19824 PrivateVD->setInitStyle(RHSVD->getInitStyle());
19825 } else if (!Init) {
19826 S.ActOnUninitializedDecl(RHSVD);
19827 // Store initializer for single element in private copy. Will be used
19828 // during codegen.
19829 PrivateVD->setInit(RHSVD->getInit());
19830 PrivateVD->setInitStyle(RHSVD->getInitStyle());
19832 if (RHSVD->isInvalidDecl())
19833 continue;
19834 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
19835 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
19836 << Type << ReductionIdRange;
19837 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19838 VarDecl::DeclarationOnly;
19839 S.Diag(D->getLocation(),
19840 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19841 << D;
19842 continue;
19844 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
19845 ExprResult ReductionOp;
19846 if (DeclareReductionRef.isUsable()) {
19847 QualType RedTy = DeclareReductionRef.get()->getType();
19848 QualType PtrRedTy = Context.getPointerType(RedTy);
19849 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
19850 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
19851 if (!BasePath.empty()) {
19852 LHS = S.DefaultLvalueConversion(LHS.get());
19853 RHS = S.DefaultLvalueConversion(RHS.get());
19854 LHS = ImplicitCastExpr::Create(
19855 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
19856 LHS.get()->getValueKind(), FPOptionsOverride());
19857 RHS = ImplicitCastExpr::Create(
19858 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
19859 RHS.get()->getValueKind(), FPOptionsOverride());
19861 FunctionProtoType::ExtProtoInfo EPI;
19862 QualType Params[] = {PtrRedTy, PtrRedTy};
19863 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
19864 auto *OVE = new (Context) OpaqueValueExpr(
19865 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
19866 S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
19867 Expr *Args[] = {LHS.get(), RHS.get()};
19868 ReductionOp =
19869 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
19870 S.CurFPFeatureOverrides());
19871 } else {
19872 BinaryOperatorKind CombBOK = getRelatedCompoundReductionOp(BOK);
19873 if (Type->isRecordType() && CombBOK != BOK) {
19874 Sema::TentativeAnalysisScope Trap(S);
19875 ReductionOp =
19876 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19877 CombBOK, LHSDRE, RHSDRE);
19879 if (!ReductionOp.isUsable()) {
19880 ReductionOp =
19881 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
19882 LHSDRE, RHSDRE);
19883 if (ReductionOp.isUsable()) {
19884 if (BOK != BO_LT && BOK != BO_GT) {
19885 ReductionOp =
19886 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19887 BO_Assign, LHSDRE, ReductionOp.get());
19888 } else {
19889 auto *ConditionalOp = new (Context)
19890 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
19891 RHSDRE, Type, VK_LValue, OK_Ordinary);
19892 ReductionOp =
19893 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19894 BO_Assign, LHSDRE, ConditionalOp);
19898 if (ReductionOp.isUsable())
19899 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
19900 /*DiscardedValue*/ false);
19901 if (!ReductionOp.isUsable())
19902 continue;
19905 // Add copy operations for inscan reductions.
19906 // LHS = RHS;
19907 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
19908 if (ClauseKind == OMPC_reduction &&
19909 RD.RedModifier == OMPC_REDUCTION_inscan) {
19910 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
19911 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
19912 RHS.get());
19913 if (!CopyOpRes.isUsable())
19914 continue;
19915 CopyOpRes =
19916 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
19917 if (!CopyOpRes.isUsable())
19918 continue;
19919 // For simd directive and simd-based directives in simd mode no need to
19920 // construct temp array, need just a single temp element.
19921 if (Stack->getCurrentDirective() == OMPD_simd ||
19922 (S.getLangOpts().OpenMPSimd &&
19923 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
19924 VarDecl *TempArrayVD =
19925 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
19926 D->hasAttrs() ? &D->getAttrs() : nullptr);
19927 // Add a constructor to the temp decl.
19928 S.ActOnUninitializedDecl(TempArrayVD);
19929 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
19930 } else {
19931 // Build temp array for prefix sum.
19932 auto *Dim = new (S.Context)
19933 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
19934 QualType ArrayTy = S.Context.getVariableArrayType(
19935 PrivateTy, Dim, ArraySizeModifier::Normal,
19936 /*IndexTypeQuals=*/0, {ELoc, ELoc});
19937 VarDecl *TempArrayVD =
19938 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
19939 D->hasAttrs() ? &D->getAttrs() : nullptr);
19940 // Add a constructor to the temp decl.
19941 S.ActOnUninitializedDecl(TempArrayVD);
19942 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
19943 TempArrayElem =
19944 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
19945 auto *Idx = new (S.Context)
19946 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
19947 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
19948 ELoc, Idx, ELoc);
19952 // OpenMP [2.15.4.6, Restrictions, p.2]
19953 // A list item that appears in an in_reduction clause of a task construct
19954 // must appear in a task_reduction clause of a construct associated with a
19955 // taskgroup region that includes the participating task in its taskgroup
19956 // set. The construct associated with the innermost region that meets this
19957 // condition must specify the same reduction-identifier as the in_reduction
19958 // clause.
19959 if (ClauseKind == OMPC_in_reduction) {
19960 SourceRange ParentSR;
19961 BinaryOperatorKind ParentBOK;
19962 const Expr *ParentReductionOp = nullptr;
19963 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
19964 DSAStackTy::DSAVarData ParentBOKDSA =
19965 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
19966 ParentBOKTD);
19967 DSAStackTy::DSAVarData ParentReductionOpDSA =
19968 Stack->getTopMostTaskgroupReductionData(
19969 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
19970 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
19971 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
19972 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
19973 (DeclareReductionRef.isUsable() && IsParentBOK) ||
19974 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
19975 bool EmitError = true;
19976 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
19977 llvm::FoldingSetNodeID RedId, ParentRedId;
19978 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
19979 DeclareReductionRef.get()->Profile(RedId, Context,
19980 /*Canonical=*/true);
19981 EmitError = RedId != ParentRedId;
19983 if (EmitError) {
19984 S.Diag(ReductionId.getBeginLoc(),
19985 diag::err_omp_reduction_identifier_mismatch)
19986 << ReductionIdRange << RefExpr->getSourceRange();
19987 S.Diag(ParentSR.getBegin(),
19988 diag::note_omp_previous_reduction_identifier)
19989 << ParentSR
19990 << (IsParentBOK ? ParentBOKDSA.RefExpr
19991 : ParentReductionOpDSA.RefExpr)
19992 ->getSourceRange();
19993 continue;
19996 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
19999 DeclRefExpr *Ref = nullptr;
20000 Expr *VarsExpr = RefExpr->IgnoreParens();
20001 if (!VD && !S.CurContext->isDependentContext()) {
20002 if (ASE || OASE) {
20003 TransformExprToCaptures RebuildToCapture(S, D);
20004 VarsExpr =
20005 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
20006 Ref = RebuildToCapture.getCapturedExpr();
20007 } else {
20008 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
20010 if (!S.isOpenMPCapturedDecl(D)) {
20011 RD.ExprCaptures.emplace_back(Ref->getDecl());
20012 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
20013 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
20014 if (!RefRes.isUsable())
20015 continue;
20016 ExprResult PostUpdateRes =
20017 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
20018 RefRes.get());
20019 if (!PostUpdateRes.isUsable())
20020 continue;
20021 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
20022 Stack->getCurrentDirective() == OMPD_taskgroup) {
20023 S.Diag(RefExpr->getExprLoc(),
20024 diag::err_omp_reduction_non_addressable_expression)
20025 << RefExpr->getSourceRange();
20026 continue;
20028 RD.ExprPostUpdates.emplace_back(
20029 S.IgnoredValueConversions(PostUpdateRes.get()).get());
20033 // All reduction items are still marked as reduction (to do not increase
20034 // code base size).
20035 unsigned Modifier = RD.RedModifier;
20036 // Consider task_reductions as reductions with task modifier. Required for
20037 // correct analysis of in_reduction clauses.
20038 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
20039 Modifier = OMPC_REDUCTION_task;
20040 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
20041 ASE || OASE);
20042 if (Modifier == OMPC_REDUCTION_task &&
20043 (CurrDir == OMPD_taskgroup ||
20044 ((isOpenMPParallelDirective(CurrDir) ||
20045 isOpenMPWorksharingDirective(CurrDir)) &&
20046 !isOpenMPSimdDirective(CurrDir)))) {
20047 if (DeclareReductionRef.isUsable())
20048 Stack->addTaskgroupReductionData(D, ReductionIdRange,
20049 DeclareReductionRef.get());
20050 else
20051 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
20053 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
20054 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
20055 TempArrayElem.get());
20057 return RD.Vars.empty();
20060 OMPClause *Sema::ActOnOpenMPReductionClause(
20061 ArrayRef<Expr *> VarList, OpenMPReductionClauseModifier Modifier,
20062 SourceLocation StartLoc, SourceLocation LParenLoc,
20063 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
20064 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20065 ArrayRef<Expr *> UnresolvedReductions) {
20066 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
20067 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
20068 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
20069 /*Last=*/OMPC_REDUCTION_unknown)
20070 << getOpenMPClauseName(OMPC_reduction);
20071 return nullptr;
20073 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
20074 // A reduction clause with the inscan reduction-modifier may only appear on a
20075 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
20076 // construct, a parallel worksharing-loop construct or a parallel
20077 // worksharing-loop SIMD construct.
20078 if (Modifier == OMPC_REDUCTION_inscan &&
20079 (DSAStack->getCurrentDirective() != OMPD_for &&
20080 DSAStack->getCurrentDirective() != OMPD_for_simd &&
20081 DSAStack->getCurrentDirective() != OMPD_simd &&
20082 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
20083 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
20084 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
20085 return nullptr;
20088 ReductionData RD(VarList.size(), Modifier);
20089 if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_reduction, VarList,
20090 StartLoc, LParenLoc, ColonLoc, EndLoc,
20091 ReductionIdScopeSpec, ReductionId,
20092 UnresolvedReductions, RD))
20093 return nullptr;
20095 return OMPReductionClause::Create(
20096 Context, StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc, Modifier,
20097 RD.Vars, ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId,
20098 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
20099 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
20100 buildPreInits(Context, RD.ExprCaptures),
20101 buildPostUpdate(*this, RD.ExprPostUpdates));
20104 OMPClause *Sema::ActOnOpenMPTaskReductionClause(
20105 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20106 SourceLocation ColonLoc, SourceLocation EndLoc,
20107 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20108 ArrayRef<Expr *> UnresolvedReductions) {
20109 ReductionData RD(VarList.size());
20110 if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_task_reduction, VarList,
20111 StartLoc, LParenLoc, ColonLoc, EndLoc,
20112 ReductionIdScopeSpec, ReductionId,
20113 UnresolvedReductions, RD))
20114 return nullptr;
20116 return OMPTaskReductionClause::Create(
20117 Context, StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20118 ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId,
20119 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
20120 buildPreInits(Context, RD.ExprCaptures),
20121 buildPostUpdate(*this, RD.ExprPostUpdates));
20124 OMPClause *Sema::ActOnOpenMPInReductionClause(
20125 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20126 SourceLocation ColonLoc, SourceLocation EndLoc,
20127 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20128 ArrayRef<Expr *> UnresolvedReductions) {
20129 ReductionData RD(VarList.size());
20130 if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_in_reduction, VarList,
20131 StartLoc, LParenLoc, ColonLoc, EndLoc,
20132 ReductionIdScopeSpec, ReductionId,
20133 UnresolvedReductions, RD))
20134 return nullptr;
20136 return OMPInReductionClause::Create(
20137 Context, StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20138 ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId,
20139 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
20140 buildPreInits(Context, RD.ExprCaptures),
20141 buildPostUpdate(*this, RD.ExprPostUpdates));
20144 bool Sema::CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
20145 SourceLocation LinLoc) {
20146 if ((!LangOpts.CPlusPlus && LinKind != OMPC_LINEAR_val) ||
20147 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
20148 Diag(LinLoc, diag::err_omp_wrong_linear_modifier) << LangOpts.CPlusPlus;
20149 return true;
20151 return false;
20154 bool Sema::CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc,
20155 OpenMPLinearClauseKind LinKind, QualType Type,
20156 bool IsDeclareSimd) {
20157 const auto *VD = dyn_cast_or_null<VarDecl>(D);
20158 // A variable must not have an incomplete type or a reference type.
20159 if (RequireCompleteType(ELoc, Type, diag::err_omp_linear_incomplete_type))
20160 return true;
20161 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
20162 !Type->isReferenceType()) {
20163 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
20164 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
20165 return true;
20167 Type = Type.getNonReferenceType();
20169 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
20170 // A variable that is privatized must not have a const-qualified type
20171 // unless it is of class type with a mutable member. This restriction does
20172 // not apply to the firstprivate clause, nor to the linear clause on
20173 // declarative directives (like declare simd).
20174 if (!IsDeclareSimd &&
20175 rejectConstNotMutableType(*this, D, Type, OMPC_linear, ELoc))
20176 return true;
20178 // A list item must be of integral or pointer type.
20179 Type = Type.getUnqualifiedType().getCanonicalType();
20180 const auto *Ty = Type.getTypePtrOrNull();
20181 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
20182 !Ty->isIntegralType(Context) && !Ty->isPointerType())) {
20183 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
20184 if (D) {
20185 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20186 VarDecl::DeclarationOnly;
20187 Diag(D->getLocation(),
20188 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20189 << D;
20191 return true;
20193 return false;
20196 OMPClause *Sema::ActOnOpenMPLinearClause(
20197 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
20198 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
20199 SourceLocation LinLoc, SourceLocation ColonLoc,
20200 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
20201 SmallVector<Expr *, 8> Vars;
20202 SmallVector<Expr *, 8> Privates;
20203 SmallVector<Expr *, 8> Inits;
20204 SmallVector<Decl *, 4> ExprCaptures;
20205 SmallVector<Expr *, 4> ExprPostUpdates;
20206 // OpenMP 5.2 [Section 5.4.6, linear clause]
20207 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
20208 // 'ref'
20209 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
20210 getLangOpts().OpenMP >= 52)
20211 Diag(Step->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
20212 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
20213 LinKind = OMPC_LINEAR_val;
20214 for (Expr *RefExpr : VarList) {
20215 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20216 SourceLocation ELoc;
20217 SourceRange ERange;
20218 Expr *SimpleRefExpr = RefExpr;
20219 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
20220 if (Res.second) {
20221 // It will be analyzed later.
20222 Vars.push_back(RefExpr);
20223 Privates.push_back(nullptr);
20224 Inits.push_back(nullptr);
20226 ValueDecl *D = Res.first;
20227 if (!D)
20228 continue;
20230 QualType Type = D->getType();
20231 auto *VD = dyn_cast<VarDecl>(D);
20233 // OpenMP [2.14.3.7, linear clause]
20234 // A list-item cannot appear in more than one linear clause.
20235 // A list-item that appears in a linear clause cannot appear in any
20236 // other data-sharing attribute clause.
20237 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
20238 if (DVar.RefExpr) {
20239 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
20240 << getOpenMPClauseName(OMPC_linear);
20241 reportOriginalDsa(*this, DSAStack, D, DVar);
20242 continue;
20245 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
20246 continue;
20247 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20249 // Build private copy of original var.
20250 VarDecl *Private =
20251 buildVarDecl(*this, ELoc, Type, D->getName(),
20252 D->hasAttrs() ? &D->getAttrs() : nullptr,
20253 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
20254 DeclRefExpr *PrivateRef = buildDeclRefExpr(*this, Private, Type, ELoc);
20255 // Build var to save initial value.
20256 VarDecl *Init = buildVarDecl(*this, ELoc, Type, ".linear.start");
20257 Expr *InitExpr;
20258 DeclRefExpr *Ref = nullptr;
20259 if (!VD && !CurContext->isDependentContext()) {
20260 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
20261 if (!isOpenMPCapturedDecl(D)) {
20262 ExprCaptures.push_back(Ref->getDecl());
20263 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
20264 ExprResult RefRes = DefaultLvalueConversion(Ref);
20265 if (!RefRes.isUsable())
20266 continue;
20267 ExprResult PostUpdateRes =
20268 BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
20269 SimpleRefExpr, RefRes.get());
20270 if (!PostUpdateRes.isUsable())
20271 continue;
20272 ExprPostUpdates.push_back(
20273 IgnoredValueConversions(PostUpdateRes.get()).get());
20277 if (LinKind == OMPC_LINEAR_uval)
20278 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
20279 else
20280 InitExpr = VD ? SimpleRefExpr : Ref;
20281 AddInitializerToDecl(Init, DefaultLvalueConversion(InitExpr).get(),
20282 /*DirectInit=*/false);
20283 DeclRefExpr *InitRef = buildDeclRefExpr(*this, Init, Type, ELoc);
20285 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
20286 Vars.push_back((VD || CurContext->isDependentContext())
20287 ? RefExpr->IgnoreParens()
20288 : Ref);
20289 Privates.push_back(PrivateRef);
20290 Inits.push_back(InitRef);
20293 if (Vars.empty())
20294 return nullptr;
20296 Expr *StepExpr = Step;
20297 Expr *CalcStepExpr = nullptr;
20298 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
20299 !Step->isInstantiationDependent() &&
20300 !Step->containsUnexpandedParameterPack()) {
20301 SourceLocation StepLoc = Step->getBeginLoc();
20302 ExprResult Val = PerformOpenMPImplicitIntegerConversion(StepLoc, Step);
20303 if (Val.isInvalid())
20304 return nullptr;
20305 StepExpr = Val.get();
20307 // Build var to save the step value.
20308 VarDecl *SaveVar =
20309 buildVarDecl(*this, StepLoc, StepExpr->getType(), ".linear.step");
20310 ExprResult SaveRef =
20311 buildDeclRefExpr(*this, SaveVar, StepExpr->getType(), StepLoc);
20312 ExprResult CalcStep =
20313 BuildBinOp(CurScope, StepLoc, BO_Assign, SaveRef.get(), StepExpr);
20314 CalcStep = ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue*/ false);
20316 // Warn about zero linear step (it would be probably better specified as
20317 // making corresponding variables 'const').
20318 if (std::optional<llvm::APSInt> Result =
20319 StepExpr->getIntegerConstantExpr(Context)) {
20320 if (!Result->isNegative() && !Result->isStrictlyPositive())
20321 Diag(StepLoc, diag::warn_omp_linear_step_zero)
20322 << Vars[0] << (Vars.size() > 1);
20323 } else if (CalcStep.isUsable()) {
20324 // Calculate the step beforehand instead of doing this on each iteration.
20325 // (This is not used if the number of iterations may be kfold-ed).
20326 CalcStepExpr = CalcStep.get();
20330 return OMPLinearClause::Create(Context, StartLoc, LParenLoc, LinKind, LinLoc,
20331 ColonLoc, StepModifierLoc, EndLoc, Vars,
20332 Privates, Inits, StepExpr, CalcStepExpr,
20333 buildPreInits(Context, ExprCaptures),
20334 buildPostUpdate(*this, ExprPostUpdates));
20337 static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
20338 Expr *NumIterations, Sema &SemaRef,
20339 Scope *S, DSAStackTy *Stack) {
20340 // Walk the vars and build update/final expressions for the CodeGen.
20341 SmallVector<Expr *, 8> Updates;
20342 SmallVector<Expr *, 8> Finals;
20343 SmallVector<Expr *, 8> UsedExprs;
20344 Expr *Step = Clause.getStep();
20345 Expr *CalcStep = Clause.getCalcStep();
20346 // OpenMP [2.14.3.7, linear clause]
20347 // If linear-step is not specified it is assumed to be 1.
20348 if (!Step)
20349 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
20350 else if (CalcStep)
20351 Step = cast<BinaryOperator>(CalcStep)->getLHS();
20352 bool HasErrors = false;
20353 auto CurInit = Clause.inits().begin();
20354 auto CurPrivate = Clause.privates().begin();
20355 OpenMPLinearClauseKind LinKind = Clause.getModifier();
20356 for (Expr *RefExpr : Clause.varlists()) {
20357 SourceLocation ELoc;
20358 SourceRange ERange;
20359 Expr *SimpleRefExpr = RefExpr;
20360 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20361 ValueDecl *D = Res.first;
20362 if (Res.second || !D) {
20363 Updates.push_back(nullptr);
20364 Finals.push_back(nullptr);
20365 HasErrors = true;
20366 continue;
20368 auto &&Info = Stack->isLoopControlVariable(D);
20369 // OpenMP [2.15.11, distribute simd Construct]
20370 // A list item may not appear in a linear clause, unless it is the loop
20371 // iteration variable.
20372 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
20373 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
20374 SemaRef.Diag(ELoc,
20375 diag::err_omp_linear_distribute_var_non_loop_iteration);
20376 Updates.push_back(nullptr);
20377 Finals.push_back(nullptr);
20378 HasErrors = true;
20379 continue;
20381 Expr *InitExpr = *CurInit;
20383 // Build privatized reference to the current linear var.
20384 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
20385 Expr *CapturedRef;
20386 if (LinKind == OMPC_LINEAR_uval)
20387 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
20388 else
20389 CapturedRef =
20390 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
20391 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
20392 /*RefersToCapture=*/true);
20394 // Build update: Var = InitExpr + IV * Step
20395 ExprResult Update;
20396 if (!Info.first)
20397 Update = buildCounterUpdate(
20398 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
20399 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
20400 else
20401 Update = *CurPrivate;
20402 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
20403 /*DiscardedValue*/ false);
20405 // Build final: Var = PrivCopy;
20406 ExprResult Final;
20407 if (!Info.first)
20408 Final = SemaRef.BuildBinOp(
20409 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
20410 SemaRef.DefaultLvalueConversion(*CurPrivate).get());
20411 else
20412 Final = *CurPrivate;
20413 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
20414 /*DiscardedValue*/ false);
20416 if (!Update.isUsable() || !Final.isUsable()) {
20417 Updates.push_back(nullptr);
20418 Finals.push_back(nullptr);
20419 UsedExprs.push_back(nullptr);
20420 HasErrors = true;
20421 } else {
20422 Updates.push_back(Update.get());
20423 Finals.push_back(Final.get());
20424 if (!Info.first)
20425 UsedExprs.push_back(SimpleRefExpr);
20427 ++CurInit;
20428 ++CurPrivate;
20430 if (Expr *S = Clause.getStep())
20431 UsedExprs.push_back(S);
20432 // Fill the remaining part with the nullptr.
20433 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
20434 Clause.setUpdates(Updates);
20435 Clause.setFinals(Finals);
20436 Clause.setUsedExprs(UsedExprs);
20437 return HasErrors;
20440 OMPClause *Sema::ActOnOpenMPAlignedClause(
20441 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
20442 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
20443 SmallVector<Expr *, 8> Vars;
20444 for (Expr *RefExpr : VarList) {
20445 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20446 SourceLocation ELoc;
20447 SourceRange ERange;
20448 Expr *SimpleRefExpr = RefExpr;
20449 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
20450 if (Res.second) {
20451 // It will be analyzed later.
20452 Vars.push_back(RefExpr);
20454 ValueDecl *D = Res.first;
20455 if (!D)
20456 continue;
20458 QualType QType = D->getType();
20459 auto *VD = dyn_cast<VarDecl>(D);
20461 // OpenMP [2.8.1, simd construct, Restrictions]
20462 // The type of list items appearing in the aligned clause must be
20463 // array, pointer, reference to array, or reference to pointer.
20464 QType = QType.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20465 const Type *Ty = QType.getTypePtrOrNull();
20466 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
20467 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
20468 << QType << getLangOpts().CPlusPlus << ERange;
20469 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20470 VarDecl::DeclarationOnly;
20471 Diag(D->getLocation(),
20472 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20473 << D;
20474 continue;
20477 // OpenMP [2.8.1, simd construct, Restrictions]
20478 // A list-item cannot appear in more than one aligned clause.
20479 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
20480 Diag(ELoc, diag::err_omp_used_in_clause_twice)
20481 << 0 << getOpenMPClauseName(OMPC_aligned) << ERange;
20482 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
20483 << getOpenMPClauseName(OMPC_aligned);
20484 continue;
20487 DeclRefExpr *Ref = nullptr;
20488 if (!VD && isOpenMPCapturedDecl(D))
20489 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
20490 Vars.push_back(DefaultFunctionArrayConversion(
20491 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
20492 .get());
20495 // OpenMP [2.8.1, simd construct, Description]
20496 // The parameter of the aligned clause, alignment, must be a constant
20497 // positive integer expression.
20498 // If no optional parameter is specified, implementation-defined default
20499 // alignments for SIMD instructions on the target platforms are assumed.
20500 if (Alignment != nullptr) {
20501 ExprResult AlignResult =
20502 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
20503 if (AlignResult.isInvalid())
20504 return nullptr;
20505 Alignment = AlignResult.get();
20507 if (Vars.empty())
20508 return nullptr;
20510 return OMPAlignedClause::Create(Context, StartLoc, LParenLoc, ColonLoc,
20511 EndLoc, Vars, Alignment);
20514 OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
20515 SourceLocation StartLoc,
20516 SourceLocation LParenLoc,
20517 SourceLocation EndLoc) {
20518 SmallVector<Expr *, 8> Vars;
20519 SmallVector<Expr *, 8> SrcExprs;
20520 SmallVector<Expr *, 8> DstExprs;
20521 SmallVector<Expr *, 8> AssignmentOps;
20522 for (Expr *RefExpr : VarList) {
20523 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
20524 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20525 // It will be analyzed later.
20526 Vars.push_back(RefExpr);
20527 SrcExprs.push_back(nullptr);
20528 DstExprs.push_back(nullptr);
20529 AssignmentOps.push_back(nullptr);
20530 continue;
20533 SourceLocation ELoc = RefExpr->getExprLoc();
20534 // OpenMP [2.1, C/C++]
20535 // A list item is a variable name.
20536 // OpenMP [2.14.4.1, Restrictions, p.1]
20537 // A list item that appears in a copyin clause must be threadprivate.
20538 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
20539 if (!DE || !isa<VarDecl>(DE->getDecl())) {
20540 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
20541 << 0 << RefExpr->getSourceRange();
20542 continue;
20545 Decl *D = DE->getDecl();
20546 auto *VD = cast<VarDecl>(D);
20548 QualType Type = VD->getType();
20549 if (Type->isDependentType() || Type->isInstantiationDependentType()) {
20550 // It will be analyzed later.
20551 Vars.push_back(DE);
20552 SrcExprs.push_back(nullptr);
20553 DstExprs.push_back(nullptr);
20554 AssignmentOps.push_back(nullptr);
20555 continue;
20558 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
20559 // A list item that appears in a copyin clause must be threadprivate.
20560 if (!DSAStack->isThreadPrivate(VD)) {
20561 Diag(ELoc, diag::err_omp_required_access)
20562 << getOpenMPClauseName(OMPC_copyin)
20563 << getOpenMPDirectiveName(OMPD_threadprivate);
20564 continue;
20567 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20568 // A variable of class type (or array thereof) that appears in a
20569 // copyin clause requires an accessible, unambiguous copy assignment
20570 // operator for the class type.
20571 QualType ElemType = Context.getBaseElementType(Type).getNonReferenceType();
20572 VarDecl *SrcVD =
20573 buildVarDecl(*this, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
20574 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20575 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
20576 *this, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
20577 VarDecl *DstVD =
20578 buildVarDecl(*this, DE->getBeginLoc(), ElemType, ".copyin.dst",
20579 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20580 DeclRefExpr *PseudoDstExpr =
20581 buildDeclRefExpr(*this, DstVD, ElemType, DE->getExprLoc());
20582 // For arrays generate assignment operation for single element and replace
20583 // it by the original array element in CodeGen.
20584 ExprResult AssignmentOp =
20585 BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign, PseudoDstExpr,
20586 PseudoSrcExpr);
20587 if (AssignmentOp.isInvalid())
20588 continue;
20589 AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
20590 /*DiscardedValue*/ false);
20591 if (AssignmentOp.isInvalid())
20592 continue;
20594 DSAStack->addDSA(VD, DE, OMPC_copyin);
20595 Vars.push_back(DE);
20596 SrcExprs.push_back(PseudoSrcExpr);
20597 DstExprs.push_back(PseudoDstExpr);
20598 AssignmentOps.push_back(AssignmentOp.get());
20601 if (Vars.empty())
20602 return nullptr;
20604 return OMPCopyinClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars,
20605 SrcExprs, DstExprs, AssignmentOps);
20608 OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
20609 SourceLocation StartLoc,
20610 SourceLocation LParenLoc,
20611 SourceLocation EndLoc) {
20612 SmallVector<Expr *, 8> Vars;
20613 SmallVector<Expr *, 8> SrcExprs;
20614 SmallVector<Expr *, 8> DstExprs;
20615 SmallVector<Expr *, 8> AssignmentOps;
20616 for (Expr *RefExpr : VarList) {
20617 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20618 SourceLocation ELoc;
20619 SourceRange ERange;
20620 Expr *SimpleRefExpr = RefExpr;
20621 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
20622 if (Res.second) {
20623 // It will be analyzed later.
20624 Vars.push_back(RefExpr);
20625 SrcExprs.push_back(nullptr);
20626 DstExprs.push_back(nullptr);
20627 AssignmentOps.push_back(nullptr);
20629 ValueDecl *D = Res.first;
20630 if (!D)
20631 continue;
20633 QualType Type = D->getType();
20634 auto *VD = dyn_cast<VarDecl>(D);
20636 // OpenMP [2.14.4.2, Restrictions, p.2]
20637 // A list item that appears in a copyprivate clause may not appear in a
20638 // private or firstprivate clause on the single construct.
20639 if (!VD || !DSAStack->isThreadPrivate(VD)) {
20640 DSAStackTy::DSAVarData DVar =
20641 DSAStack->getTopDSA(D, /*FromParent=*/false);
20642 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
20643 DVar.RefExpr) {
20644 Diag(ELoc, diag::err_omp_wrong_dsa)
20645 << getOpenMPClauseName(DVar.CKind)
20646 << getOpenMPClauseName(OMPC_copyprivate);
20647 reportOriginalDsa(*this, DSAStack, D, DVar);
20648 continue;
20651 // OpenMP [2.11.4.2, Restrictions, p.1]
20652 // All list items that appear in a copyprivate clause must be either
20653 // threadprivate or private in the enclosing context.
20654 if (DVar.CKind == OMPC_unknown) {
20655 DVar = DSAStack->getImplicitDSA(D, false);
20656 if (DVar.CKind == OMPC_shared) {
20657 Diag(ELoc, diag::err_omp_required_access)
20658 << getOpenMPClauseName(OMPC_copyprivate)
20659 << "threadprivate or private in the enclosing context";
20660 reportOriginalDsa(*this, DSAStack, D, DVar);
20661 continue;
20666 // Variably modified types are not supported.
20667 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType()) {
20668 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
20669 << getOpenMPClauseName(OMPC_copyprivate) << Type
20670 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
20671 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20672 VarDecl::DeclarationOnly;
20673 Diag(D->getLocation(),
20674 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20675 << D;
20676 continue;
20679 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20680 // A variable of class type (or array thereof) that appears in a
20681 // copyin clause requires an accessible, unambiguous copy assignment
20682 // operator for the class type.
20683 Type = Context.getBaseElementType(Type.getNonReferenceType())
20684 .getUnqualifiedType();
20685 VarDecl *SrcVD =
20686 buildVarDecl(*this, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
20687 D->hasAttrs() ? &D->getAttrs() : nullptr);
20688 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(*this, SrcVD, Type, ELoc);
20689 VarDecl *DstVD =
20690 buildVarDecl(*this, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
20691 D->hasAttrs() ? &D->getAttrs() : nullptr);
20692 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc);
20693 ExprResult AssignmentOp = BuildBinOp(
20694 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
20695 if (AssignmentOp.isInvalid())
20696 continue;
20697 AssignmentOp =
20698 ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false);
20699 if (AssignmentOp.isInvalid())
20700 continue;
20702 // No need to mark vars as copyprivate, they are already threadprivate or
20703 // implicitly private.
20704 assert(VD || isOpenMPCapturedDecl(D));
20705 Vars.push_back(
20706 VD ? RefExpr->IgnoreParens()
20707 : buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false));
20708 SrcExprs.push_back(PseudoSrcExpr);
20709 DstExprs.push_back(PseudoDstExpr);
20710 AssignmentOps.push_back(AssignmentOp.get());
20713 if (Vars.empty())
20714 return nullptr;
20716 return OMPCopyprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
20717 Vars, SrcExprs, DstExprs, AssignmentOps);
20720 OMPClause *Sema::ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList,
20721 SourceLocation StartLoc,
20722 SourceLocation LParenLoc,
20723 SourceLocation EndLoc) {
20724 if (VarList.empty())
20725 return nullptr;
20727 return OMPFlushClause::Create(Context, StartLoc, LParenLoc, EndLoc, VarList);
20730 /// Tries to find omp_depend_t. type.
20731 static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
20732 bool Diagnose = true) {
20733 QualType OMPDependT = Stack->getOMPDependT();
20734 if (!OMPDependT.isNull())
20735 return true;
20736 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
20737 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
20738 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
20739 if (Diagnose)
20740 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
20741 return false;
20743 Stack->setOMPDependT(PT.get());
20744 return true;
20747 OMPClause *Sema::ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc,
20748 SourceLocation LParenLoc,
20749 SourceLocation EndLoc) {
20750 if (!Depobj)
20751 return nullptr;
20753 bool OMPDependTFound = findOMPDependT(*this, StartLoc, DSAStack);
20755 // OpenMP 5.0, 2.17.10.1 depobj Construct
20756 // depobj is an lvalue expression of type omp_depend_t.
20757 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
20758 !Depobj->isInstantiationDependent() &&
20759 !Depobj->containsUnexpandedParameterPack() &&
20760 (OMPDependTFound &&
20761 !Context.typesAreCompatible(DSAStack->getOMPDependT(), Depobj->getType(),
20762 /*CompareUnqualified=*/true))) {
20763 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20764 << 0 << Depobj->getType() << Depobj->getSourceRange();
20767 if (!Depobj->isLValue()) {
20768 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20769 << 1 << Depobj->getSourceRange();
20772 return OMPDepobjClause::Create(Context, StartLoc, LParenLoc, EndLoc, Depobj);
20775 namespace {
20776 // Utility struct that gathers the related info for doacross clause.
20777 struct DoacrossDataInfoTy {
20778 // The list of expressions.
20779 SmallVector<Expr *, 8> Vars;
20780 // The OperatorOffset for doacross loop.
20781 DSAStackTy::OperatorOffsetTy OpsOffs;
20782 // The depended loop count.
20783 llvm::APSInt TotalDepCount;
20785 } // namespace
20786 static DoacrossDataInfoTy
20787 ProcessOpenMPDoacrossClauseCommon(Sema &SemaRef, bool IsSource,
20788 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
20789 SourceLocation EndLoc) {
20791 SmallVector<Expr *, 8> Vars;
20792 DSAStackTy::OperatorOffsetTy OpsOffs;
20793 llvm::APSInt DepCounter(/*BitWidth=*/32);
20794 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
20796 if (const Expr *OrderedCountExpr =
20797 Stack->getParentOrderedRegionParam().first) {
20798 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.Context);
20799 TotalDepCount.setIsUnsigned(/*Val=*/true);
20802 for (Expr *RefExpr : VarList) {
20803 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
20804 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20805 // It will be analyzed later.
20806 Vars.push_back(RefExpr);
20807 continue;
20810 SourceLocation ELoc = RefExpr->getExprLoc();
20811 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
20812 if (!IsSource) {
20813 if (Stack->getParentOrderedRegionParam().first &&
20814 DepCounter >= TotalDepCount) {
20815 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
20816 continue;
20818 ++DepCounter;
20819 // OpenMP [2.13.9, Summary]
20820 // depend(dependence-type : vec), where dependence-type is:
20821 // 'sink' and where vec is the iteration vector, which has the form:
20822 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
20823 // where n is the value specified by the ordered clause in the loop
20824 // directive, xi denotes the loop iteration variable of the i-th nested
20825 // loop associated with the loop directive, and di is a constant
20826 // non-negative integer.
20827 if (SemaRef.CurContext->isDependentContext()) {
20828 // It will be analyzed later.
20829 Vars.push_back(RefExpr);
20830 continue;
20832 SimpleExpr = SimpleExpr->IgnoreImplicit();
20833 OverloadedOperatorKind OOK = OO_None;
20834 SourceLocation OOLoc;
20835 Expr *LHS = SimpleExpr;
20836 Expr *RHS = nullptr;
20837 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
20838 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
20839 OOLoc = BO->getOperatorLoc();
20840 LHS = BO->getLHS()->IgnoreParenImpCasts();
20841 RHS = BO->getRHS()->IgnoreParenImpCasts();
20842 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
20843 OOK = OCE->getOperator();
20844 OOLoc = OCE->getOperatorLoc();
20845 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20846 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
20847 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
20848 OOK = MCE->getMethodDecl()
20849 ->getNameInfo()
20850 .getName()
20851 .getCXXOverloadedOperator();
20852 OOLoc = MCE->getCallee()->getExprLoc();
20853 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
20854 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20856 SourceLocation ELoc;
20857 SourceRange ERange;
20858 auto Res = getPrivateItem(SemaRef, LHS, ELoc, ERange);
20859 if (Res.second) {
20860 // It will be analyzed later.
20861 Vars.push_back(RefExpr);
20863 ValueDecl *D = Res.first;
20864 if (!D)
20865 continue;
20867 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
20868 SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
20869 continue;
20871 if (RHS) {
20872 ExprResult RHSRes = SemaRef.VerifyPositiveIntegerConstantInClause(
20873 RHS, OMPC_depend, /*StrictlyPositive=*/false);
20874 if (RHSRes.isInvalid())
20875 continue;
20877 if (!SemaRef.CurContext->isDependentContext() &&
20878 Stack->getParentOrderedRegionParam().first &&
20879 DepCounter != Stack->isParentLoopControlVariable(D).first) {
20880 const ValueDecl *VD =
20881 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
20882 if (VD)
20883 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
20884 << 1 << VD;
20885 else
20886 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
20887 << 0;
20888 continue;
20890 OpsOffs.emplace_back(RHS, OOK);
20892 Vars.push_back(RefExpr->IgnoreParenImpCasts());
20894 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
20895 TotalDepCount > VarList.size() &&
20896 Stack->getParentOrderedRegionParam().first &&
20897 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
20898 SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
20899 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
20901 return {Vars, OpsOffs, TotalDepCount};
20904 OMPClause *
20905 Sema::ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data,
20906 Expr *DepModifier, ArrayRef<Expr *> VarList,
20907 SourceLocation StartLoc, SourceLocation LParenLoc,
20908 SourceLocation EndLoc) {
20909 OpenMPDependClauseKind DepKind = Data.DepKind;
20910 SourceLocation DepLoc = Data.DepLoc;
20911 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
20912 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
20913 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20914 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
20915 return nullptr;
20917 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
20918 DepKind == OMPC_DEPEND_mutexinoutset) {
20919 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
20920 return nullptr;
20922 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
20923 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20924 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
20925 DepKind == OMPC_DEPEND_sink ||
20926 ((LangOpts.OpenMP < 50 ||
20927 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20928 DepKind == OMPC_DEPEND_depobj))) {
20929 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
20930 OMPC_DEPEND_outallmemory,
20931 OMPC_DEPEND_inoutallmemory};
20932 if (LangOpts.OpenMP < 50 || DSAStack->getCurrentDirective() == OMPD_depobj)
20933 Except.push_back(OMPC_DEPEND_depobj);
20934 if (LangOpts.OpenMP < 51)
20935 Except.push_back(OMPC_DEPEND_inoutset);
20936 std::string Expected = (LangOpts.OpenMP >= 50 && !DepModifier)
20937 ? "depend modifier(iterator) or "
20938 : "";
20939 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20940 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
20941 /*Last=*/OMPC_DEPEND_unknown,
20942 Except)
20943 << getOpenMPClauseName(OMPC_depend);
20944 return nullptr;
20946 if (DepModifier &&
20947 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
20948 Diag(DepModifier->getExprLoc(),
20949 diag::err_omp_depend_sink_source_with_modifier);
20950 return nullptr;
20952 if (DepModifier &&
20953 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
20954 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
20956 SmallVector<Expr *, 8> Vars;
20957 DSAStackTy::OperatorOffsetTy OpsOffs;
20958 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
20960 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
20961 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
20962 *this, DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
20963 Vars = VarOffset.Vars;
20964 OpsOffs = VarOffset.OpsOffs;
20965 TotalDepCount = VarOffset.TotalDepCount;
20966 } else {
20967 for (Expr *RefExpr : VarList) {
20968 assert(RefExpr && "NULL expr in OpenMP shared clause.");
20969 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20970 // It will be analyzed later.
20971 Vars.push_back(RefExpr);
20972 continue;
20975 SourceLocation ELoc = RefExpr->getExprLoc();
20976 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
20977 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
20978 bool OMPDependTFound = LangOpts.OpenMP >= 50;
20979 if (OMPDependTFound)
20980 OMPDependTFound = findOMPDependT(*this, StartLoc, DSAStack,
20981 DepKind == OMPC_DEPEND_depobj);
20982 if (DepKind == OMPC_DEPEND_depobj) {
20983 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20984 // List items used in depend clauses with the depobj dependence type
20985 // must be expressions of the omp_depend_t type.
20986 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20987 !RefExpr->isInstantiationDependent() &&
20988 !RefExpr->containsUnexpandedParameterPack() &&
20989 (OMPDependTFound &&
20990 !Context.hasSameUnqualifiedType(DSAStack->getOMPDependT(),
20991 RefExpr->getType()))) {
20992 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20993 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
20994 continue;
20996 if (!RefExpr->isLValue()) {
20997 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20998 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
20999 continue;
21001 } else {
21002 // OpenMP 5.0 [2.17.11, Restrictions]
21003 // List items used in depend clauses cannot be zero-length array
21004 // sections.
21005 QualType ExprTy = RefExpr->getType().getNonReferenceType();
21006 const auto *OASE = dyn_cast<OMPArraySectionExpr>(SimpleExpr);
21007 if (OASE) {
21008 QualType BaseType =
21009 OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
21010 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21011 ExprTy = ATy->getElementType();
21012 else
21013 ExprTy = BaseType->getPointeeType();
21014 ExprTy = ExprTy.getNonReferenceType();
21015 const Expr *Length = OASE->getLength();
21016 Expr::EvalResult Result;
21017 if (Length && !Length->isValueDependent() &&
21018 Length->EvaluateAsInt(Result, Context) &&
21019 Result.Val.getInt().isZero()) {
21020 Diag(ELoc,
21021 diag::err_omp_depend_zero_length_array_section_not_allowed)
21022 << SimpleExpr->getSourceRange();
21023 continue;
21027 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21028 // List items used in depend clauses with the in, out, inout,
21029 // inoutset, or mutexinoutset dependence types cannot be
21030 // expressions of the omp_depend_t type.
21031 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21032 !RefExpr->isInstantiationDependent() &&
21033 !RefExpr->containsUnexpandedParameterPack() &&
21034 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
21035 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
21036 ExprTy.getTypePtr()))) {
21037 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21038 << (LangOpts.OpenMP >= 50 ? 1 : 0)
21039 << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
21040 continue;
21043 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
21044 if (ASE && !ASE->getBase()->isTypeDependent() &&
21045 !ASE->getBase()
21046 ->getType()
21047 .getNonReferenceType()
21048 ->isPointerType() &&
21049 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
21050 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21051 << (LangOpts.OpenMP >= 50 ? 1 : 0)
21052 << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
21053 continue;
21056 ExprResult Res;
21058 Sema::TentativeAnalysisScope Trap(*this);
21059 Res = CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
21060 RefExpr->IgnoreParenImpCasts());
21062 if (!Res.isUsable() && !isa<OMPArraySectionExpr>(SimpleExpr) &&
21063 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
21064 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21065 << (LangOpts.OpenMP >= 50 ? 1 : 0)
21066 << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
21067 continue;
21071 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21075 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
21076 DepKind != OMPC_DEPEND_outallmemory &&
21077 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
21078 return nullptr;
21080 auto *C = OMPDependClause::Create(
21081 Context, StartLoc, LParenLoc, EndLoc,
21082 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
21083 TotalDepCount.getZExtValue());
21084 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
21085 DSAStack->isParentOrderedRegion())
21086 DSAStack->addDoacrossDependClause(C, OpsOffs);
21087 return C;
21090 OMPClause *Sema::ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier,
21091 Expr *Device, SourceLocation StartLoc,
21092 SourceLocation LParenLoc,
21093 SourceLocation ModifierLoc,
21094 SourceLocation EndLoc) {
21095 assert((ModifierLoc.isInvalid() || LangOpts.OpenMP >= 50) &&
21096 "Unexpected device modifier in OpenMP < 50.");
21098 bool ErrorFound = false;
21099 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
21100 std::string Values =
21101 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
21102 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
21103 << Values << getOpenMPClauseName(OMPC_device);
21104 ErrorFound = true;
21107 Expr *ValExpr = Device;
21108 Stmt *HelperValStmt = nullptr;
21110 // OpenMP [2.9.1, Restrictions]
21111 // The device expression must evaluate to a non-negative integer value.
21112 ErrorFound = !isNonNegativeIntegerValue(ValExpr, *this, OMPC_device,
21113 /*StrictlyPositive=*/false) ||
21114 ErrorFound;
21115 if (ErrorFound)
21116 return nullptr;
21118 // OpenMP 5.0 [2.12.5, Restrictions]
21119 // In case of ancestor device-modifier, a requires directive with
21120 // the reverse_offload clause must be specified.
21121 if (Modifier == OMPC_DEVICE_ancestor) {
21122 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
21123 targetDiag(
21124 StartLoc,
21125 diag::err_omp_device_ancestor_without_requires_reverse_offload);
21126 ErrorFound = true;
21130 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
21131 OpenMPDirectiveKind CaptureRegion =
21132 getOpenMPCaptureRegionForClause(DKind, OMPC_device, LangOpts.OpenMP);
21133 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
21134 ValExpr = MakeFullExpr(ValExpr).get();
21135 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21136 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
21137 HelperValStmt = buildPreInits(Context, Captures);
21140 return new (Context)
21141 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
21142 LParenLoc, ModifierLoc, EndLoc);
21145 static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef,
21146 DSAStackTy *Stack, QualType QTy,
21147 bool FullCheck = true) {
21148 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
21149 return false;
21150 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
21151 !QTy.isTriviallyCopyableType(SemaRef.Context))
21152 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
21153 return true;
21156 /// Return true if it can be proven that the provided array expression
21157 /// (array section or array subscript) does NOT specify the whole size of the
21158 /// array whose base type is \a BaseQTy.
21159 static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
21160 const Expr *E,
21161 QualType BaseQTy) {
21162 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
21164 // If this is an array subscript, it refers to the whole size if the size of
21165 // the dimension is constant and equals 1. Also, an array section assumes the
21166 // format of an array subscript if no colon is used.
21167 if (isa<ArraySubscriptExpr>(E) ||
21168 (OASE && OASE->getColonLocFirst().isInvalid())) {
21169 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
21170 return ATy->getSize().getSExtValue() != 1;
21171 // Size can't be evaluated statically.
21172 return false;
21175 assert(OASE && "Expecting array section if not an array subscript.");
21176 const Expr *LowerBound = OASE->getLowerBound();
21177 const Expr *Length = OASE->getLength();
21179 // If there is a lower bound that does not evaluates to zero, we are not
21180 // covering the whole dimension.
21181 if (LowerBound) {
21182 Expr::EvalResult Result;
21183 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
21184 return false; // Can't get the integer value as a constant.
21186 llvm::APSInt ConstLowerBound = Result.Val.getInt();
21187 if (ConstLowerBound.getSExtValue())
21188 return true;
21191 // If we don't have a length we covering the whole dimension.
21192 if (!Length)
21193 return false;
21195 // If the base is a pointer, we don't have a way to get the size of the
21196 // pointee.
21197 if (BaseQTy->isPointerType())
21198 return false;
21200 // We can only check if the length is the same as the size of the dimension
21201 // if we have a constant array.
21202 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
21203 if (!CATy)
21204 return false;
21206 Expr::EvalResult Result;
21207 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
21208 return false; // Can't get the integer value as a constant.
21210 llvm::APSInt ConstLength = Result.Val.getInt();
21211 return CATy->getSize().getSExtValue() != ConstLength.getSExtValue();
21214 // Return true if it can be proven that the provided array expression (array
21215 // section or array subscript) does NOT specify a single element of the array
21216 // whose base type is \a BaseQTy.
21217 static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
21218 const Expr *E,
21219 QualType BaseQTy) {
21220 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
21222 // An array subscript always refer to a single element. Also, an array section
21223 // assumes the format of an array subscript if no colon is used.
21224 if (isa<ArraySubscriptExpr>(E) ||
21225 (OASE && OASE->getColonLocFirst().isInvalid()))
21226 return false;
21228 assert(OASE && "Expecting array section if not an array subscript.");
21229 const Expr *Length = OASE->getLength();
21231 // If we don't have a length we have to check if the array has unitary size
21232 // for this dimension. Also, we should always expect a length if the base type
21233 // is pointer.
21234 if (!Length) {
21235 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
21236 return ATy->getSize().getSExtValue() != 1;
21237 // We cannot assume anything.
21238 return false;
21241 // Check if the length evaluates to 1.
21242 Expr::EvalResult Result;
21243 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
21244 return false; // Can't get the integer value as a constant.
21246 llvm::APSInt ConstLength = Result.Val.getInt();
21247 return ConstLength.getSExtValue() != 1;
21250 // The base of elements of list in a map clause have to be either:
21251 // - a reference to variable or field.
21252 // - a member expression.
21253 // - an array expression.
21255 // E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
21256 // reference to 'r'.
21258 // If we have:
21260 // struct SS {
21261 // Bla S;
21262 // foo() {
21263 // #pragma omp target map (S.Arr[:12]);
21264 // }
21265 // }
21267 // We want to retrieve the member expression 'this->S';
21269 // OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
21270 // If a list item is an array section, it must specify contiguous storage.
21272 // For this restriction it is sufficient that we make sure only references
21273 // to variables or fields and array expressions, and that no array sections
21274 // exist except in the rightmost expression (unless they cover the whole
21275 // dimension of the array). E.g. these would be invalid:
21277 // r.ArrS[3:5].Arr[6:7]
21279 // r.ArrS[3:5].x
21281 // but these would be valid:
21282 // r.ArrS[3].Arr[6:7]
21284 // r.ArrS[3].x
21285 namespace {
21286 class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
21287 Sema &SemaRef;
21288 OpenMPClauseKind CKind = OMPC_unknown;
21289 OpenMPDirectiveKind DKind = OMPD_unknown;
21290 OMPClauseMappableExprCommon::MappableExprComponentList &Components;
21291 bool IsNonContiguous = false;
21292 bool NoDiagnose = false;
21293 const Expr *RelevantExpr = nullptr;
21294 bool AllowUnitySizeArraySection = true;
21295 bool AllowWholeSizeArraySection = true;
21296 bool AllowAnotherPtr = true;
21297 SourceLocation ELoc;
21298 SourceRange ERange;
21300 void emitErrorMsg() {
21301 // If nothing else worked, this is not a valid map clause expression.
21302 if (SemaRef.getLangOpts().OpenMP < 50) {
21303 SemaRef.Diag(ELoc,
21304 diag::err_omp_expected_named_var_member_or_array_expression)
21305 << ERange;
21306 } else {
21307 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21308 << getOpenMPClauseName(CKind) << ERange;
21312 public:
21313 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
21314 if (!isa<VarDecl>(DRE->getDecl())) {
21315 emitErrorMsg();
21316 return false;
21318 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21319 RelevantExpr = DRE;
21320 // Record the component.
21321 Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
21322 return true;
21325 bool VisitMemberExpr(MemberExpr *ME) {
21326 Expr *E = ME;
21327 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
21329 if (isa<CXXThisExpr>(BaseE)) {
21330 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21331 // We found a base expression: this->Val.
21332 RelevantExpr = ME;
21333 } else {
21334 E = BaseE;
21337 if (!isa<FieldDecl>(ME->getMemberDecl())) {
21338 if (!NoDiagnose) {
21339 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
21340 << ME->getSourceRange();
21341 return false;
21343 if (RelevantExpr)
21344 return false;
21345 return Visit(E);
21348 auto *FD = cast<FieldDecl>(ME->getMemberDecl());
21350 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
21351 // A bit-field cannot appear in a map clause.
21353 if (FD->isBitField()) {
21354 if (!NoDiagnose) {
21355 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
21356 << ME->getSourceRange() << getOpenMPClauseName(CKind);
21357 return false;
21359 if (RelevantExpr)
21360 return false;
21361 return Visit(E);
21364 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21365 // If the type of a list item is a reference to a type T then the type
21366 // will be considered to be T for all purposes of this clause.
21367 QualType CurType = BaseE->getType().getNonReferenceType();
21369 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
21370 // A list item cannot be a variable that is a member of a structure with
21371 // a union type.
21373 if (CurType->isUnionType()) {
21374 if (!NoDiagnose) {
21375 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
21376 << ME->getSourceRange();
21377 return false;
21379 return RelevantExpr || Visit(E);
21382 // If we got a member expression, we should not expect any array section
21383 // before that:
21385 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
21386 // If a list item is an element of a structure, only the rightmost symbol
21387 // of the variable reference can be an array section.
21389 AllowUnitySizeArraySection = false;
21390 AllowWholeSizeArraySection = false;
21392 // Record the component.
21393 Components.emplace_back(ME, FD, IsNonContiguous);
21394 return RelevantExpr || Visit(E);
21397 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
21398 Expr *E = AE->getBase()->IgnoreParenImpCasts();
21400 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
21401 if (!NoDiagnose) {
21402 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21403 << 0 << AE->getSourceRange();
21404 return false;
21406 return RelevantExpr || Visit(E);
21409 // If we got an array subscript that express the whole dimension we
21410 // can have any array expressions before. If it only expressing part of
21411 // the dimension, we can only have unitary-size array expressions.
21412 if (checkArrayExpressionDoesNotReferToWholeSize(SemaRef, AE, E->getType()))
21413 AllowWholeSizeArraySection = false;
21415 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
21416 Expr::EvalResult Result;
21417 if (!AE->getIdx()->isValueDependent() &&
21418 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
21419 !Result.Val.getInt().isZero()) {
21420 SemaRef.Diag(AE->getIdx()->getExprLoc(),
21421 diag::err_omp_invalid_map_this_expr);
21422 SemaRef.Diag(AE->getIdx()->getExprLoc(),
21423 diag::note_omp_invalid_subscript_on_this_ptr_map);
21425 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21426 RelevantExpr = TE;
21429 // Record the component - we don't have any declaration associated.
21430 Components.emplace_back(AE, nullptr, IsNonContiguous);
21432 return RelevantExpr || Visit(E);
21435 bool VisitOMPArraySectionExpr(OMPArraySectionExpr *OASE) {
21436 // After OMP 5.0 Array section in reduction clause will be implicitly
21437 // mapped
21438 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
21439 "Array sections cannot be implicitly mapped.");
21440 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21441 QualType CurType =
21442 OMPArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
21444 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21445 // If the type of a list item is a reference to a type T then the type
21446 // will be considered to be T for all purposes of this clause.
21447 if (CurType->isReferenceType())
21448 CurType = CurType->getPointeeType();
21450 bool IsPointer = CurType->isAnyPointerType();
21452 if (!IsPointer && !CurType->isArrayType()) {
21453 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21454 << 0 << OASE->getSourceRange();
21455 return false;
21458 bool NotWhole =
21459 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
21460 bool NotUnity =
21461 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
21463 if (AllowWholeSizeArraySection) {
21464 // Any array section is currently allowed. Allowing a whole size array
21465 // section implies allowing a unity array section as well.
21467 // If this array section refers to the whole dimension we can still
21468 // accept other array sections before this one, except if the base is a
21469 // pointer. Otherwise, only unitary sections are accepted.
21470 if (NotWhole || IsPointer)
21471 AllowWholeSizeArraySection = false;
21472 } else if (DKind == OMPD_target_update &&
21473 SemaRef.getLangOpts().OpenMP >= 50) {
21474 if (IsPointer && !AllowAnotherPtr)
21475 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
21476 << /*array of unknown bound */ 1;
21477 else
21478 IsNonContiguous = true;
21479 } else if (AllowUnitySizeArraySection && NotUnity) {
21480 // A unity or whole array section is not allowed and that is not
21481 // compatible with the properties of the current array section.
21482 if (NoDiagnose)
21483 return false;
21484 SemaRef.Diag(ELoc,
21485 diag::err_array_section_does_not_specify_contiguous_storage)
21486 << OASE->getSourceRange();
21487 return false;
21490 if (IsPointer)
21491 AllowAnotherPtr = false;
21493 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
21494 Expr::EvalResult ResultR;
21495 Expr::EvalResult ResultL;
21496 if (!OASE->getLength()->isValueDependent() &&
21497 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
21498 !ResultR.Val.getInt().isOne()) {
21499 SemaRef.Diag(OASE->getLength()->getExprLoc(),
21500 diag::err_omp_invalid_map_this_expr);
21501 SemaRef.Diag(OASE->getLength()->getExprLoc(),
21502 diag::note_omp_invalid_length_on_this_ptr_mapping);
21504 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
21505 OASE->getLowerBound()->EvaluateAsInt(ResultL,
21506 SemaRef.getASTContext()) &&
21507 !ResultL.Val.getInt().isZero()) {
21508 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
21509 diag::err_omp_invalid_map_this_expr);
21510 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
21511 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
21513 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21514 RelevantExpr = TE;
21517 // Record the component - we don't have any declaration associated.
21518 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
21519 return RelevantExpr || Visit(E);
21521 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
21522 Expr *Base = E->getBase();
21524 // Record the component - we don't have any declaration associated.
21525 Components.emplace_back(E, nullptr, IsNonContiguous);
21527 return Visit(Base->IgnoreParenImpCasts());
21530 bool VisitUnaryOperator(UnaryOperator *UO) {
21531 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
21532 UO->getOpcode() != UO_Deref) {
21533 emitErrorMsg();
21534 return false;
21536 if (!RelevantExpr) {
21537 // Record the component if haven't found base decl.
21538 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
21540 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
21542 bool VisitBinaryOperator(BinaryOperator *BO) {
21543 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
21544 emitErrorMsg();
21545 return false;
21548 // Pointer arithmetic is the only thing we expect to happen here so after we
21549 // make sure the binary operator is a pointer type, the only thing we need
21550 // to do is to visit the subtree that has the same type as root (so that we
21551 // know the other subtree is just an offset)
21552 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
21553 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
21554 Components.emplace_back(BO, nullptr, false);
21555 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
21556 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
21557 "Either LHS or RHS have base decl inside");
21558 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
21559 return RelevantExpr || Visit(LE);
21560 return RelevantExpr || Visit(RE);
21562 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
21563 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21564 RelevantExpr = CTE;
21565 Components.emplace_back(CTE, nullptr, IsNonContiguous);
21566 return true;
21568 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
21569 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21570 Components.emplace_back(COCE, nullptr, IsNonContiguous);
21571 return true;
21573 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
21574 Expr *Source = E->getSourceExpr();
21575 if (!Source) {
21576 emitErrorMsg();
21577 return false;
21579 return Visit(Source);
21581 bool VisitStmt(Stmt *) {
21582 emitErrorMsg();
21583 return false;
21585 const Expr *getFoundBase() const { return RelevantExpr; }
21586 explicit MapBaseChecker(
21587 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
21588 OMPClauseMappableExprCommon::MappableExprComponentList &Components,
21589 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
21590 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
21591 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
21593 } // namespace
21595 /// Return the expression of the base of the mappable expression or null if it
21596 /// cannot be determined and do all the necessary checks to see if the
21597 /// expression is valid as a standalone mappable expression. In the process,
21598 /// record all the components of the expression.
21599 static const Expr *checkMapClauseExpressionBase(
21600 Sema &SemaRef, Expr *E,
21601 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
21602 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
21603 SourceLocation ELoc = E->getExprLoc();
21604 SourceRange ERange = E->getSourceRange();
21605 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
21606 ERange);
21607 if (Checker.Visit(E->IgnoreParens())) {
21608 // Check if the highest dimension array section has length specified
21609 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
21610 (CKind == OMPC_to || CKind == OMPC_from)) {
21611 auto CI = CurComponents.rbegin();
21612 auto CE = CurComponents.rend();
21613 for (; CI != CE; ++CI) {
21614 const auto *OASE =
21615 dyn_cast<OMPArraySectionExpr>(CI->getAssociatedExpression());
21616 if (!OASE)
21617 continue;
21618 if (OASE && OASE->getLength())
21619 break;
21620 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
21621 << ERange;
21624 return Checker.getFoundBase();
21626 return nullptr;
21629 // Return true if expression E associated with value VD has conflicts with other
21630 // map information.
21631 static bool checkMapConflicts(
21632 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
21633 bool CurrentRegionOnly,
21634 OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents,
21635 OpenMPClauseKind CKind) {
21636 assert(VD && E);
21637 SourceLocation ELoc = E->getExprLoc();
21638 SourceRange ERange = E->getSourceRange();
21640 // In order to easily check the conflicts we need to match each component of
21641 // the expression under test with the components of the expressions that are
21642 // already in the stack.
21644 assert(!CurComponents.empty() && "Map clause expression with no components!");
21645 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
21646 "Map clause expression with unexpected base!");
21648 // Variables to help detecting enclosing problems in data environment nests.
21649 bool IsEnclosedByDataEnvironmentExpr = false;
21650 const Expr *EnclosingExpr = nullptr;
21652 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
21653 VD, CurrentRegionOnly,
21654 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
21655 ERange, CKind, &EnclosingExpr,
21656 CurComponents](OMPClauseMappableExprCommon::MappableExprComponentListRef
21657 StackComponents,
21658 OpenMPClauseKind Kind) {
21659 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
21660 return false;
21661 assert(!StackComponents.empty() &&
21662 "Map clause expression with no components!");
21663 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
21664 "Map clause expression with unexpected base!");
21665 (void)VD;
21667 // The whole expression in the stack.
21668 const Expr *RE = StackComponents.front().getAssociatedExpression();
21670 // Expressions must start from the same base. Here we detect at which
21671 // point both expressions diverge from each other and see if we can
21672 // detect if the memory referred to both expressions is contiguous and
21673 // do not overlap.
21674 auto CI = CurComponents.rbegin();
21675 auto CE = CurComponents.rend();
21676 auto SI = StackComponents.rbegin();
21677 auto SE = StackComponents.rend();
21678 for (; CI != CE && SI != SE; ++CI, ++SI) {
21680 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
21681 // At most one list item can be an array item derived from a given
21682 // variable in map clauses of the same construct.
21683 if (CurrentRegionOnly &&
21684 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
21685 isa<OMPArraySectionExpr>(CI->getAssociatedExpression()) ||
21686 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
21687 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
21688 isa<OMPArraySectionExpr>(SI->getAssociatedExpression()) ||
21689 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
21690 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
21691 diag::err_omp_multiple_array_items_in_map_clause)
21692 << CI->getAssociatedExpression()->getSourceRange();
21693 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
21694 diag::note_used_here)
21695 << SI->getAssociatedExpression()->getSourceRange();
21696 return true;
21699 // Do both expressions have the same kind?
21700 if (CI->getAssociatedExpression()->getStmtClass() !=
21701 SI->getAssociatedExpression()->getStmtClass())
21702 break;
21704 // Are we dealing with different variables/fields?
21705 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
21706 break;
21708 // Check if the extra components of the expressions in the enclosing
21709 // data environment are redundant for the current base declaration.
21710 // If they are, the maps completely overlap, which is legal.
21711 for (; SI != SE; ++SI) {
21712 QualType Type;
21713 if (const auto *ASE =
21714 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
21715 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
21716 } else if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(
21717 SI->getAssociatedExpression())) {
21718 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21719 Type =
21720 OMPArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
21721 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
21722 SI->getAssociatedExpression())) {
21723 Type = OASE->getBase()->getType()->getPointeeType();
21725 if (Type.isNull() || Type->isAnyPointerType() ||
21726 checkArrayExpressionDoesNotReferToWholeSize(
21727 SemaRef, SI->getAssociatedExpression(), Type))
21728 break;
21731 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21732 // List items of map clauses in the same construct must not share
21733 // original storage.
21735 // If the expressions are exactly the same or one is a subset of the
21736 // other, it means they are sharing storage.
21737 if (CI == CE && SI == SE) {
21738 if (CurrentRegionOnly) {
21739 if (CKind == OMPC_map) {
21740 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21741 } else {
21742 assert(CKind == OMPC_to || CKind == OMPC_from);
21743 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21744 << ERange;
21746 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21747 << RE->getSourceRange();
21748 return true;
21750 // If we find the same expression in the enclosing data environment,
21751 // that is legal.
21752 IsEnclosedByDataEnvironmentExpr = true;
21753 return false;
21756 QualType DerivedType =
21757 std::prev(CI)->getAssociatedDeclaration()->getType();
21758 SourceLocation DerivedLoc =
21759 std::prev(CI)->getAssociatedExpression()->getExprLoc();
21761 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21762 // If the type of a list item is a reference to a type T then the type
21763 // will be considered to be T for all purposes of this clause.
21764 DerivedType = DerivedType.getNonReferenceType();
21766 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
21767 // A variable for which the type is pointer and an array section
21768 // derived from that variable must not appear as list items of map
21769 // clauses of the same construct.
21771 // Also, cover one of the cases in:
21772 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21773 // If any part of the original storage of a list item has corresponding
21774 // storage in the device data environment, all of the original storage
21775 // must have corresponding storage in the device data environment.
21777 if (DerivedType->isAnyPointerType()) {
21778 if (CI == CE || SI == SE) {
21779 SemaRef.Diag(
21780 DerivedLoc,
21781 diag::err_omp_pointer_mapped_along_with_derived_section)
21782 << DerivedLoc;
21783 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21784 << RE->getSourceRange();
21785 return true;
21787 if (CI->getAssociatedExpression()->getStmtClass() !=
21788 SI->getAssociatedExpression()->getStmtClass() ||
21789 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
21790 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
21791 assert(CI != CE && SI != SE);
21792 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
21793 << DerivedLoc;
21794 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21795 << RE->getSourceRange();
21796 return true;
21800 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21801 // List items of map clauses in the same construct must not share
21802 // original storage.
21804 // An expression is a subset of the other.
21805 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
21806 if (CKind == OMPC_map) {
21807 if (CI != CE || SI != SE) {
21808 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
21809 // a pointer.
21810 auto Begin =
21811 CI != CE ? CurComponents.begin() : StackComponents.begin();
21812 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
21813 auto It = Begin;
21814 while (It != End && !It->getAssociatedDeclaration())
21815 std::advance(It, 1);
21816 assert(It != End &&
21817 "Expected at least one component with the declaration.");
21818 if (It != Begin && It->getAssociatedDeclaration()
21819 ->getType()
21820 .getCanonicalType()
21821 ->isAnyPointerType()) {
21822 IsEnclosedByDataEnvironmentExpr = false;
21823 EnclosingExpr = nullptr;
21824 return false;
21827 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21828 } else {
21829 assert(CKind == OMPC_to || CKind == OMPC_from);
21830 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21831 << ERange;
21833 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21834 << RE->getSourceRange();
21835 return true;
21838 // The current expression uses the same base as other expression in the
21839 // data environment but does not contain it completely.
21840 if (!CurrentRegionOnly && SI != SE)
21841 EnclosingExpr = RE;
21843 // The current expression is a subset of the expression in the data
21844 // environment.
21845 IsEnclosedByDataEnvironmentExpr |=
21846 (!CurrentRegionOnly && CI != CE && SI == SE);
21848 return false;
21851 if (CurrentRegionOnly)
21852 return FoundError;
21854 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21855 // If any part of the original storage of a list item has corresponding
21856 // storage in the device data environment, all of the original storage must
21857 // have corresponding storage in the device data environment.
21858 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
21859 // If a list item is an element of a structure, and a different element of
21860 // the structure has a corresponding list item in the device data environment
21861 // prior to a task encountering the construct associated with the map clause,
21862 // then the list item must also have a corresponding list item in the device
21863 // data environment prior to the task encountering the construct.
21865 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
21866 SemaRef.Diag(ELoc,
21867 diag::err_omp_original_storage_is_shared_and_does_not_contain)
21868 << ERange;
21869 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
21870 << EnclosingExpr->getSourceRange();
21871 return true;
21874 return FoundError;
21877 // Look up the user-defined mapper given the mapper name and mapped type, and
21878 // build a reference to it.
21879 static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
21880 CXXScopeSpec &MapperIdScopeSpec,
21881 const DeclarationNameInfo &MapperId,
21882 QualType Type,
21883 Expr *UnresolvedMapper) {
21884 if (MapperIdScopeSpec.isInvalid())
21885 return ExprError();
21886 // Get the actual type for the array type.
21887 if (Type->isArrayType()) {
21888 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
21889 Type = Type->getAsArrayTypeUnsafe()->getElementType().getCanonicalType();
21891 // Find all user-defined mappers with the given MapperId.
21892 SmallVector<UnresolvedSet<8>, 4> Lookups;
21893 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
21894 Lookup.suppressDiagnostics();
21895 if (S) {
21896 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec)) {
21897 NamedDecl *D = Lookup.getRepresentativeDecl();
21898 while (S && !S->isDeclScope(D))
21899 S = S->getParent();
21900 if (S)
21901 S = S->getParent();
21902 Lookups.emplace_back();
21903 Lookups.back().append(Lookup.begin(), Lookup.end());
21904 Lookup.clear();
21906 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
21907 // Extract the user-defined mappers with the given MapperId.
21908 Lookups.push_back(UnresolvedSet<8>());
21909 for (NamedDecl *D : ULE->decls()) {
21910 auto *DMD = cast<OMPDeclareMapperDecl>(D);
21911 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
21912 Lookups.back().addDecl(DMD);
21915 // Defer the lookup for dependent types. The results will be passed through
21916 // UnresolvedMapper on instantiation.
21917 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
21918 Type->isInstantiationDependentType() ||
21919 Type->containsUnexpandedParameterPack() ||
21920 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
21921 return !D->isInvalidDecl() &&
21922 (D->getType()->isDependentType() ||
21923 D->getType()->isInstantiationDependentType() ||
21924 D->getType()->containsUnexpandedParameterPack());
21925 })) {
21926 UnresolvedSet<8> URS;
21927 for (const UnresolvedSet<8> &Set : Lookups) {
21928 if (Set.empty())
21929 continue;
21930 URS.append(Set.begin(), Set.end());
21932 return UnresolvedLookupExpr::Create(
21933 SemaRef.Context, /*NamingClass=*/nullptr,
21934 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
21935 /*ADL=*/false, /*Overloaded=*/true, URS.begin(), URS.end());
21937 SourceLocation Loc = MapperId.getLoc();
21938 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21939 // The type must be of struct, union or class type in C and C++
21940 if (!Type->isStructureOrClassType() && !Type->isUnionType() &&
21941 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
21942 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
21943 return ExprError();
21945 // Perform argument dependent lookup.
21946 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
21947 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
21948 // Return the first user-defined mapper with the desired type.
21949 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21950 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
21951 if (!D->isInvalidDecl() &&
21952 SemaRef.Context.hasSameType(D->getType(), Type))
21953 return D;
21954 return nullptr;
21956 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
21957 // Find the first user-defined mapper with a type derived from the desired
21958 // type.
21959 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21960 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
21961 if (!D->isInvalidDecl() &&
21962 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
21963 !Type.isMoreQualifiedThan(D->getType()))
21964 return D;
21965 return nullptr;
21966 })) {
21967 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
21968 /*DetectVirtual=*/false);
21969 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
21970 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
21971 VD->getType().getUnqualifiedType()))) {
21972 if (SemaRef.CheckBaseClassAccess(
21973 Loc, VD->getType(), Type, Paths.front(),
21974 /*DiagID=*/0) != Sema::AR_inaccessible) {
21975 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
21980 // Report error if a mapper is specified, but cannot be found.
21981 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
21982 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
21983 << Type << MapperId.getName();
21984 return ExprError();
21986 return ExprEmpty();
21989 namespace {
21990 // Utility struct that gathers all the related lists associated with a mappable
21991 // expression.
21992 struct MappableVarListInfo {
21993 // The list of expressions.
21994 ArrayRef<Expr *> VarList;
21995 // The list of processed expressions.
21996 SmallVector<Expr *, 16> ProcessedVarList;
21997 // The mappble components for each expression.
21998 OMPClauseMappableExprCommon::MappableExprComponentLists VarComponents;
21999 // The base declaration of the variable.
22000 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
22001 // The reference to the user-defined mapper associated with every expression.
22002 SmallVector<Expr *, 16> UDMapperList;
22004 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
22005 // We have a list of components and base declarations for each entry in the
22006 // variable list.
22007 VarComponents.reserve(VarList.size());
22008 VarBaseDeclarations.reserve(VarList.size());
22011 } // namespace
22013 // Check the validity of the provided variable list for the provided clause kind
22014 // \a CKind. In the check process the valid expressions, mappable expression
22015 // components, variables, and user-defined mappers are extracted and used to
22016 // fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
22017 // UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
22018 // and \a MapperId are expected to be valid if the clause kind is 'map'.
22019 static void checkMappableExpressionList(
22020 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
22021 MappableVarListInfo &MVLI, SourceLocation StartLoc,
22022 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
22023 ArrayRef<Expr *> UnresolvedMappers,
22024 OpenMPMapClauseKind MapType = OMPC_MAP_unknown,
22025 ArrayRef<OpenMPMapModifierKind> Modifiers = std::nullopt,
22026 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
22027 // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
22028 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
22029 "Unexpected clause kind with mappable expressions!");
22031 // If the identifier of user-defined mapper is not specified, it is "default".
22032 // We do not change the actual name in this clause to distinguish whether a
22033 // mapper is specified explicitly, i.e., it is not explicitly specified when
22034 // MapperId.getName() is empty.
22035 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
22036 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
22037 MapperId.setName(DeclNames.getIdentifier(
22038 &SemaRef.getASTContext().Idents.get("default")));
22039 MapperId.setLoc(StartLoc);
22042 // Iterators to find the current unresolved mapper expression.
22043 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
22044 bool UpdateUMIt = false;
22045 Expr *UnresolvedMapper = nullptr;
22047 bool HasHoldModifier =
22048 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
22050 // Keep track of the mappable components and base declarations in this clause.
22051 // Each entry in the list is going to have a list of components associated. We
22052 // record each set of the components so that we can build the clause later on.
22053 // In the end we should have the same amount of declarations and component
22054 // lists.
22056 for (Expr *RE : MVLI.VarList) {
22057 assert(RE && "Null expr in omp to/from/map clause");
22058 SourceLocation ELoc = RE->getExprLoc();
22060 // Find the current unresolved mapper expression.
22061 if (UpdateUMIt && UMIt != UMEnd) {
22062 UMIt++;
22063 assert(
22064 UMIt != UMEnd &&
22065 "Expect the size of UnresolvedMappers to match with that of VarList");
22067 UpdateUMIt = true;
22068 if (UMIt != UMEnd)
22069 UnresolvedMapper = *UMIt;
22071 const Expr *VE = RE->IgnoreParenLValueCasts();
22073 if (VE->isValueDependent() || VE->isTypeDependent() ||
22074 VE->isInstantiationDependent() ||
22075 VE->containsUnexpandedParameterPack()) {
22076 // Try to find the associated user-defined mapper.
22077 ExprResult ER = buildUserDefinedMapperRef(
22078 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22079 VE->getType().getCanonicalType(), UnresolvedMapper);
22080 if (ER.isInvalid())
22081 continue;
22082 MVLI.UDMapperList.push_back(ER.get());
22083 // We can only analyze this information once the missing information is
22084 // resolved.
22085 MVLI.ProcessedVarList.push_back(RE);
22086 continue;
22089 Expr *SimpleExpr = RE->IgnoreParenCasts();
22091 if (!RE->isLValue()) {
22092 if (SemaRef.getLangOpts().OpenMP < 50) {
22093 SemaRef.Diag(
22094 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
22095 << RE->getSourceRange();
22096 } else {
22097 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
22098 << getOpenMPClauseName(CKind) << RE->getSourceRange();
22100 continue;
22103 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
22104 ValueDecl *CurDeclaration = nullptr;
22106 // Obtain the array or member expression bases if required. Also, fill the
22107 // components array with all the components identified in the process.
22108 const Expr *BE =
22109 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
22110 DSAS->getCurrentDirective(), NoDiagnose);
22111 if (!BE)
22112 continue;
22114 assert(!CurComponents.empty() &&
22115 "Invalid mappable expression information.");
22117 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
22118 // Add store "this" pointer to class in DSAStackTy for future checking
22119 DSAS->addMappedClassesQualTypes(TE->getType());
22120 // Try to find the associated user-defined mapper.
22121 ExprResult ER = buildUserDefinedMapperRef(
22122 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22123 VE->getType().getCanonicalType(), UnresolvedMapper);
22124 if (ER.isInvalid())
22125 continue;
22126 MVLI.UDMapperList.push_back(ER.get());
22127 // Skip restriction checking for variable or field declarations
22128 MVLI.ProcessedVarList.push_back(RE);
22129 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22130 MVLI.VarComponents.back().append(CurComponents.begin(),
22131 CurComponents.end());
22132 MVLI.VarBaseDeclarations.push_back(nullptr);
22133 continue;
22136 // For the following checks, we rely on the base declaration which is
22137 // expected to be associated with the last component. The declaration is
22138 // expected to be a variable or a field (if 'this' is being mapped).
22139 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
22140 assert(CurDeclaration && "Null decl on map clause.");
22141 assert(
22142 CurDeclaration->isCanonicalDecl() &&
22143 "Expecting components to have associated only canonical declarations.");
22145 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
22146 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
22148 assert((VD || FD) && "Only variables or fields are expected here!");
22149 (void)FD;
22151 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
22152 // threadprivate variables cannot appear in a map clause.
22153 // OpenMP 4.5 [2.10.5, target update Construct]
22154 // threadprivate variables cannot appear in a from clause.
22155 if (VD && DSAS->isThreadPrivate(VD)) {
22156 if (NoDiagnose)
22157 continue;
22158 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
22159 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
22160 << getOpenMPClauseName(CKind);
22161 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
22162 continue;
22165 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
22166 // A list item cannot appear in both a map clause and a data-sharing
22167 // attribute clause on the same construct.
22169 // Check conflicts with other map clause expressions. We check the conflicts
22170 // with the current construct separately from the enclosing data
22171 // environment, because the restrictions are different. We only have to
22172 // check conflicts across regions for the map clauses.
22173 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
22174 /*CurrentRegionOnly=*/true, CurComponents, CKind))
22175 break;
22176 if (CKind == OMPC_map &&
22177 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
22178 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
22179 /*CurrentRegionOnly=*/false, CurComponents, CKind))
22180 break;
22182 // OpenMP 4.5 [2.10.5, target update Construct]
22183 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22184 // If the type of a list item is a reference to a type T then the type will
22185 // be considered to be T for all purposes of this clause.
22186 auto I = llvm::find_if(
22187 CurComponents,
22188 [](const OMPClauseMappableExprCommon::MappableComponent &MC) {
22189 return MC.getAssociatedDeclaration();
22191 assert(I != CurComponents.end() && "Null decl on map clause.");
22192 (void)I;
22193 QualType Type;
22194 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
22195 auto *OASE = dyn_cast<OMPArraySectionExpr>(VE->IgnoreParens());
22196 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
22197 if (ASE) {
22198 Type = ASE->getType().getNonReferenceType();
22199 } else if (OASE) {
22200 QualType BaseType =
22201 OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
22202 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
22203 Type = ATy->getElementType();
22204 else
22205 Type = BaseType->getPointeeType();
22206 Type = Type.getNonReferenceType();
22207 } else if (OAShE) {
22208 Type = OAShE->getBase()->getType()->getPointeeType();
22209 } else {
22210 Type = VE->getType();
22213 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
22214 // A list item in a to or from clause must have a mappable type.
22215 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
22216 // A list item must have a mappable type.
22217 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
22218 DSAS, Type, /*FullCheck=*/true))
22219 continue;
22221 if (CKind == OMPC_map) {
22222 // target enter data
22223 // OpenMP [2.10.2, Restrictions, p. 99]
22224 // A map-type must be specified in all map clauses and must be either
22225 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
22226 // no map type is present.
22227 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
22228 if (DKind == OMPD_target_enter_data &&
22229 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
22230 SemaRef.getLangOpts().OpenMP >= 52)) {
22231 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22232 << (IsMapTypeImplicit ? 1 : 0)
22233 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22234 << getOpenMPDirectiveName(DKind);
22235 continue;
22238 // target exit_data
22239 // OpenMP [2.10.3, Restrictions, p. 102]
22240 // A map-type must be specified in all map clauses and must be either
22241 // from, release, or delete. Starting with OpenMP 5.2 the default map
22242 // type is `from` if no map type is present.
22243 if (DKind == OMPD_target_exit_data &&
22244 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
22245 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
22246 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22247 << (IsMapTypeImplicit ? 1 : 0)
22248 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22249 << getOpenMPDirectiveName(DKind);
22250 continue;
22253 // The 'ompx_hold' modifier is specifically intended to be used on a
22254 // 'target' or 'target data' directive to prevent data from being unmapped
22255 // during the associated statement. It is not permitted on a 'target
22256 // enter data' or 'target exit data' directive, which have no associated
22257 // statement.
22258 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
22259 HasHoldModifier) {
22260 SemaRef.Diag(StartLoc,
22261 diag::err_omp_invalid_map_type_modifier_for_directive)
22262 << getOpenMPSimpleClauseTypeName(OMPC_map,
22263 OMPC_MAP_MODIFIER_ompx_hold)
22264 << getOpenMPDirectiveName(DKind);
22265 continue;
22268 // target, target data
22269 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
22270 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
22271 // A map-type in a map clause must be to, from, tofrom or alloc
22272 if ((DKind == OMPD_target_data ||
22273 isOpenMPTargetExecutionDirective(DKind)) &&
22274 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
22275 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
22276 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22277 << (IsMapTypeImplicit ? 1 : 0)
22278 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22279 << getOpenMPDirectiveName(DKind);
22280 continue;
22283 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
22284 // A list item cannot appear in both a map clause and a data-sharing
22285 // attribute clause on the same construct
22287 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
22288 // A list item cannot appear in both a map clause and a data-sharing
22289 // attribute clause on the same construct unless the construct is a
22290 // combined construct.
22291 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
22292 isOpenMPTargetExecutionDirective(DKind)) ||
22293 DKind == OMPD_target)) {
22294 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
22295 if (isOpenMPPrivate(DVar.CKind)) {
22296 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
22297 << getOpenMPClauseName(DVar.CKind)
22298 << getOpenMPClauseName(OMPC_map)
22299 << getOpenMPDirectiveName(DSAS->getCurrentDirective());
22300 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
22301 continue;
22306 // Try to find the associated user-defined mapper.
22307 ExprResult ER = buildUserDefinedMapperRef(
22308 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22309 Type.getCanonicalType(), UnresolvedMapper);
22310 if (ER.isInvalid())
22311 continue;
22312 MVLI.UDMapperList.push_back(ER.get());
22314 // Save the current expression.
22315 MVLI.ProcessedVarList.push_back(RE);
22317 // Store the components in the stack so that they can be used to check
22318 // against other clauses later on.
22319 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
22320 /*WhereFoundClauseKind=*/OMPC_map);
22322 // Save the components and declaration to create the clause. For purposes of
22323 // the clause creation, any component list that has base 'this' uses
22324 // null as base declaration.
22325 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22326 MVLI.VarComponents.back().append(CurComponents.begin(),
22327 CurComponents.end());
22328 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
22329 : CurDeclaration);
22333 OMPClause *Sema::ActOnOpenMPMapClause(
22334 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
22335 ArrayRef<SourceLocation> MapTypeModifiersLoc,
22336 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22337 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
22338 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22339 const OMPVarListLocTy &Locs, bool NoDiagnose,
22340 ArrayRef<Expr *> UnresolvedMappers) {
22341 OpenMPMapModifierKind Modifiers[] = {
22342 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
22343 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
22344 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown};
22345 SourceLocation ModifiersLoc[NumberOfOMPMapClauseModifiers];
22347 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
22348 BuiltinType::OMPIterator))
22349 Diag(IteratorModifier->getExprLoc(),
22350 diag::err_omp_map_modifier_not_iterator);
22352 // Process map-type-modifiers, flag errors for duplicate modifiers.
22353 unsigned Count = 0;
22354 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
22355 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
22356 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
22357 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
22358 continue;
22360 assert(Count < NumberOfOMPMapClauseModifiers &&
22361 "Modifiers exceed the allowed number of map type modifiers");
22362 Modifiers[Count] = MapTypeModifiers[I];
22363 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
22364 ++Count;
22367 MappableVarListInfo MVLI(VarList);
22368 checkMappableExpressionList(*this, DSAStack, OMPC_map, MVLI, Locs.StartLoc,
22369 MapperIdScopeSpec, MapperId, UnresolvedMappers,
22370 MapType, Modifiers, IsMapTypeImplicit,
22371 NoDiagnose);
22373 // We need to produce a map clause even if we don't have variables so that
22374 // other diagnostics related with non-existing map clauses are accurate.
22375 return OMPMapClause::Create(
22376 Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22377 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
22378 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(Context), MapperId,
22379 MapType, IsMapTypeImplicit, MapLoc);
22382 QualType Sema::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc,
22383 TypeResult ParsedType) {
22384 assert(ParsedType.isUsable());
22386 QualType ReductionType = GetTypeFromParser(ParsedType.get());
22387 if (ReductionType.isNull())
22388 return QualType();
22390 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
22391 // A type name in a declare reduction directive cannot be a function type, an
22392 // array type, a reference type, or a type qualified with const, volatile or
22393 // restrict.
22394 if (ReductionType.hasQualifiers()) {
22395 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
22396 return QualType();
22399 if (ReductionType->isFunctionType()) {
22400 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
22401 return QualType();
22403 if (ReductionType->isReferenceType()) {
22404 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
22405 return QualType();
22407 if (ReductionType->isArrayType()) {
22408 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
22409 return QualType();
22411 return ReductionType;
22414 Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareReductionDirectiveStart(
22415 Scope *S, DeclContext *DC, DeclarationName Name,
22416 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
22417 AccessSpecifier AS, Decl *PrevDeclInScope) {
22418 SmallVector<Decl *, 8> Decls;
22419 Decls.reserve(ReductionTypes.size());
22421 LookupResult Lookup(*this, Name, SourceLocation(), LookupOMPReductionName,
22422 forRedeclarationInCurContext());
22423 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
22424 // A reduction-identifier may not be re-declared in the current scope for the
22425 // same type or for a type that is compatible according to the base language
22426 // rules.
22427 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22428 OMPDeclareReductionDecl *PrevDRD = nullptr;
22429 bool InCompoundScope = true;
22430 if (S != nullptr) {
22431 // Find previous declaration with the same name not referenced in other
22432 // declarations.
22433 FunctionScopeInfo *ParentFn = getEnclosingFunction();
22434 InCompoundScope =
22435 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22436 LookupName(Lookup, S);
22437 FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
22438 /*AllowInlineNamespace=*/false);
22439 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
22440 LookupResult::Filter Filter = Lookup.makeFilter();
22441 while (Filter.hasNext()) {
22442 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
22443 if (InCompoundScope) {
22444 auto I = UsedAsPrevious.find(PrevDecl);
22445 if (I == UsedAsPrevious.end())
22446 UsedAsPrevious[PrevDecl] = false;
22447 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
22448 UsedAsPrevious[D] = true;
22450 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22451 PrevDecl->getLocation();
22453 Filter.done();
22454 if (InCompoundScope) {
22455 for (const auto &PrevData : UsedAsPrevious) {
22456 if (!PrevData.second) {
22457 PrevDRD = PrevData.first;
22458 break;
22462 } else if (PrevDeclInScope != nullptr) {
22463 auto *PrevDRDInScope = PrevDRD =
22464 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
22465 do {
22466 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
22467 PrevDRDInScope->getLocation();
22468 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
22469 } while (PrevDRDInScope != nullptr);
22471 for (const auto &TyData : ReductionTypes) {
22472 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
22473 bool Invalid = false;
22474 if (I != PreviousRedeclTypes.end()) {
22475 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
22476 << TyData.first;
22477 Diag(I->second, diag::note_previous_definition);
22478 Invalid = true;
22480 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
22481 auto *DRD = OMPDeclareReductionDecl::Create(Context, DC, TyData.second,
22482 Name, TyData.first, PrevDRD);
22483 DC->addDecl(DRD);
22484 DRD->setAccess(AS);
22485 Decls.push_back(DRD);
22486 if (Invalid)
22487 DRD->setInvalidDecl();
22488 else
22489 PrevDRD = DRD;
22492 return DeclGroupPtrTy::make(
22493 DeclGroupRef::Create(Context, Decls.begin(), Decls.size()));
22496 void Sema::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) {
22497 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22499 // Enter new function scope.
22500 PushFunctionScope();
22501 setFunctionHasBranchProtectedScope();
22502 getCurFunction()->setHasOMPDeclareReductionCombiner();
22504 if (S != nullptr)
22505 PushDeclContext(S, DRD);
22506 else
22507 CurContext = DRD;
22509 PushExpressionEvaluationContext(
22510 ExpressionEvaluationContext::PotentiallyEvaluated);
22512 QualType ReductionType = DRD->getType();
22513 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
22514 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
22515 // uses semantics of argument handles by value, but it should be passed by
22516 // reference. C lang does not support references, so pass all parameters as
22517 // pointers.
22518 // Create 'T omp_in;' variable.
22519 VarDecl *OmpInParm =
22520 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_in");
22521 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
22522 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
22523 // uses semantics of argument handles by value, but it should be passed by
22524 // reference. C lang does not support references, so pass all parameters as
22525 // pointers.
22526 // Create 'T omp_out;' variable.
22527 VarDecl *OmpOutParm =
22528 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_out");
22529 if (S != nullptr) {
22530 PushOnScopeChains(OmpInParm, S);
22531 PushOnScopeChains(OmpOutParm, S);
22532 } else {
22533 DRD->addDecl(OmpInParm);
22534 DRD->addDecl(OmpOutParm);
22536 Expr *InE =
22537 ::buildDeclRefExpr(*this, OmpInParm, ReductionType, D->getLocation());
22538 Expr *OutE =
22539 ::buildDeclRefExpr(*this, OmpOutParm, ReductionType, D->getLocation());
22540 DRD->setCombinerData(InE, OutE);
22543 void Sema::ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner) {
22544 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22545 DiscardCleanupsInEvaluationContext();
22546 PopExpressionEvaluationContext();
22548 PopDeclContext();
22549 PopFunctionScopeInfo();
22551 if (Combiner != nullptr)
22552 DRD->setCombiner(Combiner);
22553 else
22554 DRD->setInvalidDecl();
22557 VarDecl *Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D) {
22558 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22560 // Enter new function scope.
22561 PushFunctionScope();
22562 setFunctionHasBranchProtectedScope();
22564 if (S != nullptr)
22565 PushDeclContext(S, DRD);
22566 else
22567 CurContext = DRD;
22569 PushExpressionEvaluationContext(
22570 ExpressionEvaluationContext::PotentiallyEvaluated);
22572 QualType ReductionType = DRD->getType();
22573 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
22574 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
22575 // uses semantics of argument handles by value, but it should be passed by
22576 // reference. C lang does not support references, so pass all parameters as
22577 // pointers.
22578 // Create 'T omp_priv;' variable.
22579 VarDecl *OmpPrivParm =
22580 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_priv");
22581 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
22582 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
22583 // uses semantics of argument handles by value, but it should be passed by
22584 // reference. C lang does not support references, so pass all parameters as
22585 // pointers.
22586 // Create 'T omp_orig;' variable.
22587 VarDecl *OmpOrigParm =
22588 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_orig");
22589 if (S != nullptr) {
22590 PushOnScopeChains(OmpPrivParm, S);
22591 PushOnScopeChains(OmpOrigParm, S);
22592 } else {
22593 DRD->addDecl(OmpPrivParm);
22594 DRD->addDecl(OmpOrigParm);
22596 Expr *OrigE =
22597 ::buildDeclRefExpr(*this, OmpOrigParm, ReductionType, D->getLocation());
22598 Expr *PrivE =
22599 ::buildDeclRefExpr(*this, OmpPrivParm, ReductionType, D->getLocation());
22600 DRD->setInitializerData(OrigE, PrivE);
22601 return OmpPrivParm;
22604 void Sema::ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer,
22605 VarDecl *OmpPrivParm) {
22606 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22607 DiscardCleanupsInEvaluationContext();
22608 PopExpressionEvaluationContext();
22610 PopDeclContext();
22611 PopFunctionScopeInfo();
22613 if (Initializer != nullptr) {
22614 DRD->setInitializer(Initializer, OMPDeclareReductionInitKind::Call);
22615 } else if (OmpPrivParm->hasInit()) {
22616 DRD->setInitializer(OmpPrivParm->getInit(),
22617 OmpPrivParm->isDirectInit()
22618 ? OMPDeclareReductionInitKind::Direct
22619 : OMPDeclareReductionInitKind::Copy);
22620 } else {
22621 DRD->setInvalidDecl();
22625 Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareReductionDirectiveEnd(
22626 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
22627 for (Decl *D : DeclReductions.get()) {
22628 if (IsValid) {
22629 if (S)
22630 PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
22631 /*AddToContext=*/false);
22632 } else {
22633 D->setInvalidDecl();
22636 return DeclReductions;
22639 TypeResult Sema::ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D) {
22640 TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
22641 QualType T = TInfo->getType();
22642 if (D.isInvalidType())
22643 return true;
22645 if (getLangOpts().CPlusPlus) {
22646 // Check that there are no default arguments (C++ only).
22647 CheckExtraCXXDefaultArguments(D);
22650 return CreateParsedType(T, TInfo);
22653 QualType Sema::ActOnOpenMPDeclareMapperType(SourceLocation TyLoc,
22654 TypeResult ParsedType) {
22655 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
22657 QualType MapperType = GetTypeFromParser(ParsedType.get());
22658 assert(!MapperType.isNull() && "Expect valid mapper type");
22660 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22661 // The type must be of struct, union or class type in C and C++
22662 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
22663 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
22664 return QualType();
22666 return MapperType;
22669 Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareMapperDirective(
22670 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
22671 SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS,
22672 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
22673 LookupResult Lookup(*this, Name, SourceLocation(), LookupOMPMapperName,
22674 forRedeclarationInCurContext());
22675 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22676 // A mapper-identifier may not be redeclared in the current scope for the
22677 // same type or for a type that is compatible according to the base language
22678 // rules.
22679 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22680 OMPDeclareMapperDecl *PrevDMD = nullptr;
22681 bool InCompoundScope = true;
22682 if (S != nullptr) {
22683 // Find previous declaration with the same name not referenced in other
22684 // declarations.
22685 FunctionScopeInfo *ParentFn = getEnclosingFunction();
22686 InCompoundScope =
22687 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22688 LookupName(Lookup, S);
22689 FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
22690 /*AllowInlineNamespace=*/false);
22691 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
22692 LookupResult::Filter Filter = Lookup.makeFilter();
22693 while (Filter.hasNext()) {
22694 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
22695 if (InCompoundScope) {
22696 auto I = UsedAsPrevious.find(PrevDecl);
22697 if (I == UsedAsPrevious.end())
22698 UsedAsPrevious[PrevDecl] = false;
22699 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
22700 UsedAsPrevious[D] = true;
22702 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22703 PrevDecl->getLocation();
22705 Filter.done();
22706 if (InCompoundScope) {
22707 for (const auto &PrevData : UsedAsPrevious) {
22708 if (!PrevData.second) {
22709 PrevDMD = PrevData.first;
22710 break;
22714 } else if (PrevDeclInScope) {
22715 auto *PrevDMDInScope = PrevDMD =
22716 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
22717 do {
22718 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
22719 PrevDMDInScope->getLocation();
22720 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
22721 } while (PrevDMDInScope != nullptr);
22723 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
22724 bool Invalid = false;
22725 if (I != PreviousRedeclTypes.end()) {
22726 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
22727 << MapperType << Name;
22728 Diag(I->second, diag::note_previous_definition);
22729 Invalid = true;
22731 // Build expressions for implicit maps of data members with 'default'
22732 // mappers.
22733 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses.begin(),
22734 Clauses.end());
22735 if (LangOpts.OpenMP >= 50)
22736 processImplicitMapsWithDefaultMappers(*this, DSAStack, ClausesWithImplicit);
22737 auto *DMD =
22738 OMPDeclareMapperDecl::Create(Context, DC, StartLoc, Name, MapperType, VN,
22739 ClausesWithImplicit, PrevDMD);
22740 if (S)
22741 PushOnScopeChains(DMD, S);
22742 else
22743 DC->addDecl(DMD);
22744 DMD->setAccess(AS);
22745 if (Invalid)
22746 DMD->setInvalidDecl();
22748 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
22749 VD->setDeclContext(DMD);
22750 VD->setLexicalDeclContext(DMD);
22751 DMD->addDecl(VD);
22752 DMD->setMapperVarRef(MapperVarRef);
22754 return DeclGroupPtrTy::make(DeclGroupRef(DMD));
22757 ExprResult
22758 Sema::ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType,
22759 SourceLocation StartLoc,
22760 DeclarationName VN) {
22761 TypeSourceInfo *TInfo =
22762 Context.getTrivialTypeSourceInfo(MapperType, StartLoc);
22763 auto *VD = VarDecl::Create(Context, Context.getTranslationUnitDecl(),
22764 StartLoc, StartLoc, VN.getAsIdentifierInfo(),
22765 MapperType, TInfo, SC_None);
22766 if (S)
22767 PushOnScopeChains(VD, S, /*AddToContext=*/false);
22768 Expr *E = buildDeclRefExpr(*this, VD, MapperType, StartLoc);
22769 DSAStack->addDeclareMapperVarRef(E);
22770 return E;
22773 void Sema::ActOnOpenMPIteratorVarDecl(VarDecl *VD) {
22774 if (DSAStack->getDeclareMapperVarRef())
22775 DSAStack->addIteratorVarDecl(VD);
22778 bool Sema::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const {
22779 assert(LangOpts.OpenMP && "Expected OpenMP mode.");
22780 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
22781 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
22782 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
22783 return true;
22784 if (VD->isUsableInConstantExpressions(Context))
22785 return true;
22786 if (LangOpts.OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
22787 return true;
22788 return false;
22790 return true;
22793 const ValueDecl *Sema::getOpenMPDeclareMapperVarName() const {
22794 assert(LangOpts.OpenMP && "Expected OpenMP mode.");
22795 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
22798 OMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams,
22799 SourceLocation StartLoc,
22800 SourceLocation LParenLoc,
22801 SourceLocation EndLoc) {
22802 Expr *ValExpr = NumTeams;
22803 Stmt *HelperValStmt = nullptr;
22805 // OpenMP [teams Constrcut, Restrictions]
22806 // The num_teams expression must evaluate to a positive integer value.
22807 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_num_teams,
22808 /*StrictlyPositive=*/true))
22809 return nullptr;
22811 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22812 OpenMPDirectiveKind CaptureRegion =
22813 getOpenMPCaptureRegionForClause(DKind, OMPC_num_teams, LangOpts.OpenMP);
22814 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
22815 ValExpr = MakeFullExpr(ValExpr).get();
22816 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22817 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
22818 HelperValStmt = buildPreInits(Context, Captures);
22821 return new (Context) OMPNumTeamsClause(ValExpr, HelperValStmt, CaptureRegion,
22822 StartLoc, LParenLoc, EndLoc);
22825 OMPClause *Sema::ActOnOpenMPThreadLimitClause(Expr *ThreadLimit,
22826 SourceLocation StartLoc,
22827 SourceLocation LParenLoc,
22828 SourceLocation EndLoc) {
22829 Expr *ValExpr = ThreadLimit;
22830 Stmt *HelperValStmt = nullptr;
22832 // OpenMP [teams Constrcut, Restrictions]
22833 // The thread_limit expression must evaluate to a positive integer value.
22834 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_thread_limit,
22835 /*StrictlyPositive=*/true))
22836 return nullptr;
22838 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22839 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
22840 DKind, OMPC_thread_limit, LangOpts.OpenMP);
22841 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
22842 ValExpr = MakeFullExpr(ValExpr).get();
22843 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22844 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
22845 HelperValStmt = buildPreInits(Context, Captures);
22848 return new (Context) OMPThreadLimitClause(
22849 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
22852 OMPClause *Sema::ActOnOpenMPPriorityClause(Expr *Priority,
22853 SourceLocation StartLoc,
22854 SourceLocation LParenLoc,
22855 SourceLocation EndLoc) {
22856 Expr *ValExpr = Priority;
22857 Stmt *HelperValStmt = nullptr;
22858 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22860 // OpenMP [2.9.1, task Constrcut]
22861 // The priority-value is a non-negative numerical scalar expression.
22862 if (!isNonNegativeIntegerValue(
22863 ValExpr, *this, OMPC_priority,
22864 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
22865 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22866 return nullptr;
22868 return new (Context) OMPPriorityClause(ValExpr, HelperValStmt, CaptureRegion,
22869 StartLoc, LParenLoc, EndLoc);
22872 OMPClause *Sema::ActOnOpenMPGrainsizeClause(
22873 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
22874 SourceLocation StartLoc, SourceLocation LParenLoc,
22875 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22876 assert((ModifierLoc.isInvalid() || LangOpts.OpenMP >= 51) &&
22877 "Unexpected grainsize modifier in OpenMP < 51.");
22879 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
22880 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
22881 OMPC_GRAINSIZE_unknown);
22882 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22883 << Values << getOpenMPClauseName(OMPC_grainsize);
22884 return nullptr;
22887 Expr *ValExpr = Grainsize;
22888 Stmt *HelperValStmt = nullptr;
22889 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22891 // OpenMP [2.9.2, taskloop Constrcut]
22892 // The parameter of the grainsize clause must be a positive integer
22893 // expression.
22894 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_grainsize,
22895 /*StrictlyPositive=*/true,
22896 /*BuildCapture=*/true,
22897 DSAStack->getCurrentDirective(),
22898 &CaptureRegion, &HelperValStmt))
22899 return nullptr;
22901 return new (Context)
22902 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22903 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22906 OMPClause *Sema::ActOnOpenMPNumTasksClause(
22907 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
22908 SourceLocation StartLoc, SourceLocation LParenLoc,
22909 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22910 assert((ModifierLoc.isInvalid() || LangOpts.OpenMP >= 51) &&
22911 "Unexpected num_tasks modifier in OpenMP < 51.");
22913 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
22914 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
22915 OMPC_NUMTASKS_unknown);
22916 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22917 << Values << getOpenMPClauseName(OMPC_num_tasks);
22918 return nullptr;
22921 Expr *ValExpr = NumTasks;
22922 Stmt *HelperValStmt = nullptr;
22923 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22925 // OpenMP [2.9.2, taskloop Constrcut]
22926 // The parameter of the num_tasks clause must be a positive integer
22927 // expression.
22928 if (!isNonNegativeIntegerValue(
22929 ValExpr, *this, OMPC_num_tasks,
22930 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
22931 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22932 return nullptr;
22934 return new (Context)
22935 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22936 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22939 OMPClause *Sema::ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc,
22940 SourceLocation LParenLoc,
22941 SourceLocation EndLoc) {
22942 // OpenMP [2.13.2, critical construct, Description]
22943 // ... where hint-expression is an integer constant expression that evaluates
22944 // to a valid lock hint.
22945 ExprResult HintExpr =
22946 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
22947 if (HintExpr.isInvalid())
22948 return nullptr;
22949 return new (Context)
22950 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
22953 /// Tries to find omp_event_handle_t type.
22954 static bool findOMPEventHandleT(Sema &S, SourceLocation Loc,
22955 DSAStackTy *Stack) {
22956 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
22957 if (!OMPEventHandleT.isNull())
22958 return true;
22959 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
22960 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
22961 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
22962 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
22963 return false;
22965 Stack->setOMPEventHandleT(PT.get());
22966 return true;
22969 OMPClause *Sema::ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc,
22970 SourceLocation LParenLoc,
22971 SourceLocation EndLoc) {
22972 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
22973 !Evt->isInstantiationDependent() &&
22974 !Evt->containsUnexpandedParameterPack()) {
22975 if (!findOMPEventHandleT(*this, Evt->getExprLoc(), DSAStack))
22976 return nullptr;
22977 // OpenMP 5.0, 2.10.1 task Construct.
22978 // event-handle is a variable of the omp_event_handle_t type.
22979 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
22980 if (!Ref) {
22981 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22982 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22983 return nullptr;
22985 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
22986 if (!VD) {
22987 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22988 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22989 return nullptr;
22991 if (!Context.hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
22992 VD->getType()) ||
22993 VD->getType().isConstant(Context)) {
22994 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22995 << "omp_event_handle_t" << 1 << VD->getType()
22996 << Evt->getSourceRange();
22997 return nullptr;
22999 // OpenMP 5.0, 2.10.1 task Construct
23000 // [detach clause]... The event-handle will be considered as if it was
23001 // specified on a firstprivate clause.
23002 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
23003 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
23004 DVar.RefExpr) {
23005 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
23006 << getOpenMPClauseName(DVar.CKind)
23007 << getOpenMPClauseName(OMPC_firstprivate);
23008 reportOriginalDsa(*this, DSAStack, VD, DVar);
23009 return nullptr;
23013 return new (Context) OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
23016 OMPClause *Sema::ActOnOpenMPDistScheduleClause(
23017 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
23018 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
23019 SourceLocation EndLoc) {
23020 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
23021 std::string Values;
23022 Values += "'";
23023 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
23024 Values += "'";
23025 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23026 << Values << getOpenMPClauseName(OMPC_dist_schedule);
23027 return nullptr;
23029 Expr *ValExpr = ChunkSize;
23030 Stmt *HelperValStmt = nullptr;
23031 if (ChunkSize) {
23032 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
23033 !ChunkSize->isInstantiationDependent() &&
23034 !ChunkSize->containsUnexpandedParameterPack()) {
23035 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
23036 ExprResult Val =
23037 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
23038 if (Val.isInvalid())
23039 return nullptr;
23041 ValExpr = Val.get();
23043 // OpenMP [2.7.1, Restrictions]
23044 // chunk_size must be a loop invariant integer expression with a positive
23045 // value.
23046 if (std::optional<llvm::APSInt> Result =
23047 ValExpr->getIntegerConstantExpr(Context)) {
23048 if (Result->isSigned() && !Result->isStrictlyPositive()) {
23049 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
23050 << "dist_schedule" << ChunkSize->getSourceRange();
23051 return nullptr;
23053 } else if (getOpenMPCaptureRegionForClause(
23054 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
23055 LangOpts.OpenMP) != OMPD_unknown &&
23056 !CurContext->isDependentContext()) {
23057 ValExpr = MakeFullExpr(ValExpr).get();
23058 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23059 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
23060 HelperValStmt = buildPreInits(Context, Captures);
23065 return new (Context)
23066 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
23067 Kind, ValExpr, HelperValStmt);
23070 OMPClause *Sema::ActOnOpenMPDefaultmapClause(
23071 OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind,
23072 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
23073 SourceLocation KindLoc, SourceLocation EndLoc) {
23074 if (getLangOpts().OpenMP < 50) {
23075 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
23076 Kind != OMPC_DEFAULTMAP_scalar) {
23077 std::string Value;
23078 SourceLocation Loc;
23079 Value += "'";
23080 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
23081 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
23082 OMPC_DEFAULTMAP_MODIFIER_tofrom);
23083 Loc = MLoc;
23084 } else {
23085 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
23086 OMPC_DEFAULTMAP_scalar);
23087 Loc = KindLoc;
23089 Value += "'";
23090 Diag(Loc, diag::err_omp_unexpected_clause_value)
23091 << Value << getOpenMPClauseName(OMPC_defaultmap);
23092 return nullptr;
23094 } else {
23095 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
23096 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
23097 (LangOpts.OpenMP >= 50 && KindLoc.isInvalid());
23098 if (!isDefaultmapKind || !isDefaultmapModifier) {
23099 StringRef KindValue = "'scalar', 'aggregate', 'pointer'";
23100 if (LangOpts.OpenMP == 50) {
23101 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
23102 "'firstprivate', 'none', 'default'";
23103 if (!isDefaultmapKind && isDefaultmapModifier) {
23104 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23105 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23106 } else if (isDefaultmapKind && !isDefaultmapModifier) {
23107 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23108 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23109 } else {
23110 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23111 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23112 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23113 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23115 } else {
23116 StringRef ModifierValue =
23117 "'alloc', 'from', 'to', 'tofrom', "
23118 "'firstprivate', 'none', 'default', 'present'";
23119 if (!isDefaultmapKind && isDefaultmapModifier) {
23120 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23121 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23122 } else if (isDefaultmapKind && !isDefaultmapModifier) {
23123 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23124 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23125 } else {
23126 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23127 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23128 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23129 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23132 return nullptr;
23135 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
23136 // At most one defaultmap clause for each category can appear on the
23137 // directive.
23138 if (DSAStack->checkDefaultmapCategory(Kind)) {
23139 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
23140 return nullptr;
23143 if (Kind == OMPC_DEFAULTMAP_unknown) {
23144 // Variable category is not specified - mark all categories.
23145 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
23146 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
23147 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
23148 } else {
23149 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
23152 return new (Context)
23153 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
23156 bool Sema::ActOnStartOpenMPDeclareTargetContext(
23157 DeclareTargetContextInfo &DTCI) {
23158 DeclContext *CurLexicalContext = getCurLexicalContext();
23159 if (!CurLexicalContext->isFileContext() &&
23160 !CurLexicalContext->isExternCContext() &&
23161 !CurLexicalContext->isExternCXXContext() &&
23162 !isa<CXXRecordDecl>(CurLexicalContext) &&
23163 !isa<ClassTemplateDecl>(CurLexicalContext) &&
23164 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
23165 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
23166 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
23167 return false;
23170 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
23171 if (getLangOpts().HIP)
23172 Diag(DTCI.Loc, diag::warn_hip_omp_target_directives);
23174 DeclareTargetNesting.push_back(DTCI);
23175 return true;
23178 const Sema::DeclareTargetContextInfo
23179 Sema::ActOnOpenMPEndDeclareTargetDirective() {
23180 assert(!DeclareTargetNesting.empty() &&
23181 "check isInOpenMPDeclareTargetContext() first!");
23182 return DeclareTargetNesting.pop_back_val();
23185 void Sema::ActOnFinishedOpenMPDeclareTargetContext(
23186 DeclareTargetContextInfo &DTCI) {
23187 for (auto &It : DTCI.ExplicitlyMapped)
23188 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
23191 void Sema::DiagnoseUnterminatedOpenMPDeclareTarget() {
23192 if (DeclareTargetNesting.empty())
23193 return;
23194 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
23195 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
23196 << getOpenMPDirectiveName(DTCI.Kind);
23199 NamedDecl *Sema::lookupOpenMPDeclareTargetName(Scope *CurScope,
23200 CXXScopeSpec &ScopeSpec,
23201 const DeclarationNameInfo &Id) {
23202 LookupResult Lookup(*this, Id, LookupOrdinaryName);
23203 LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
23205 if (Lookup.isAmbiguous())
23206 return nullptr;
23207 Lookup.suppressDiagnostics();
23209 if (!Lookup.isSingleResult()) {
23210 VarOrFuncDeclFilterCCC CCC(*this);
23211 if (TypoCorrection Corrected =
23212 CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr, CCC,
23213 CTK_ErrorRecovery)) {
23214 diagnoseTypo(Corrected, PDiag(diag::err_undeclared_var_use_suggest)
23215 << Id.getName());
23216 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
23217 return nullptr;
23220 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
23221 return nullptr;
23224 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
23225 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
23226 !isa<FunctionTemplateDecl>(ND)) {
23227 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
23228 return nullptr;
23230 return ND;
23233 void Sema::ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc,
23234 OMPDeclareTargetDeclAttr::MapTypeTy MT,
23235 DeclareTargetContextInfo &DTCI) {
23236 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
23237 isa<FunctionTemplateDecl>(ND)) &&
23238 "Expected variable, function or function template.");
23240 // Diagnose marking after use as it may lead to incorrect diagnosis and
23241 // codegen.
23242 if (LangOpts.OpenMP >= 50 &&
23243 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
23244 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
23246 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
23247 if (getLangOpts().HIP)
23248 Diag(Loc, diag::warn_hip_omp_target_directives);
23250 // Explicit declare target lists have precedence.
23251 const unsigned Level = -1;
23253 auto *VD = cast<ValueDecl>(ND);
23254 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23255 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23256 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
23257 (*ActiveAttr)->getLevel() == Level) {
23258 Diag(Loc, diag::err_omp_device_type_mismatch)
23259 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
23260 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
23261 (*ActiveAttr)->getDevType());
23262 return;
23264 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
23265 (*ActiveAttr)->getLevel() == Level) {
23266 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
23267 return;
23270 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
23271 return;
23273 Expr *IndirectE = nullptr;
23274 bool IsIndirect = false;
23275 if (DTCI.Indirect) {
23276 IndirectE = *DTCI.Indirect;
23277 if (!IndirectE)
23278 IsIndirect = true;
23280 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23281 Context, MT, DTCI.DT, IndirectE, IsIndirect, Level,
23282 SourceRange(Loc, Loc));
23283 ND->addAttr(A);
23284 if (ASTMutationListener *ML = Context.getASTMutationListener())
23285 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
23286 checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Loc);
23287 if (auto *VD = dyn_cast<VarDecl>(ND);
23288 LangOpts.OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
23289 VD->hasGlobalStorage())
23290 ActOnOpenMPDeclareTargetInitializer(ND);
23293 static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
23294 Sema &SemaRef, Decl *D) {
23295 if (!D || !isa<VarDecl>(D))
23296 return;
23297 auto *VD = cast<VarDecl>(D);
23298 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
23299 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
23300 if (SemaRef.LangOpts.OpenMP >= 50 &&
23301 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
23302 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
23303 VD->hasGlobalStorage()) {
23304 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
23305 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
23306 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
23307 // If a lambda declaration and definition appears between a
23308 // declare target directive and the matching end declare target
23309 // directive, all variables that are captured by the lambda
23310 // expression must also appear in a to clause.
23311 SemaRef.Diag(VD->getLocation(),
23312 diag::err_omp_lambda_capture_in_declare_target_not_to);
23313 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
23314 << VD << 0 << SR;
23315 return;
23318 if (MapTy)
23319 return;
23320 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
23321 SemaRef.Diag(SL, diag::note_used_here) << SR;
23324 static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR,
23325 Sema &SemaRef, DSAStackTy *Stack,
23326 ValueDecl *VD) {
23327 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
23328 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
23329 /*FullCheck=*/false);
23332 void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
23333 SourceLocation IdLoc) {
23334 if (!D || D->isInvalidDecl())
23335 return;
23336 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
23337 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
23338 if (auto *VD = dyn_cast<VarDecl>(D)) {
23339 // Only global variables can be marked as declare target.
23340 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
23341 !VD->isStaticDataMember())
23342 return;
23343 // 2.10.6: threadprivate variable cannot appear in a declare target
23344 // directive.
23345 if (DSAStack->isThreadPrivate(VD)) {
23346 Diag(SL, diag::err_omp_threadprivate_in_target);
23347 reportOriginalDsa(*this, DSAStack, VD, DSAStack->getTopDSA(VD, false));
23348 return;
23351 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
23352 D = FTD->getTemplatedDecl();
23353 if (auto *FD = dyn_cast<FunctionDecl>(D)) {
23354 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
23355 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
23356 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
23357 Diag(IdLoc, diag::err_omp_function_in_link_clause);
23358 Diag(FD->getLocation(), diag::note_defined_here) << FD;
23359 return;
23362 if (auto *VD = dyn_cast<ValueDecl>(D)) {
23363 // Problem if any with var declared with incomplete type will be reported
23364 // as normal, so no need to check it here.
23365 if ((E || !VD->getType()->isIncompleteType()) &&
23366 !checkValueDeclInTarget(SL, SR, *this, DSAStack, VD))
23367 return;
23368 if (!E && isInOpenMPDeclareTargetContext()) {
23369 // Checking declaration inside declare target region.
23370 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
23371 isa<FunctionTemplateDecl>(D)) {
23372 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23373 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23374 unsigned Level = DeclareTargetNesting.size();
23375 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
23376 return;
23377 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
23378 Expr *IndirectE = nullptr;
23379 bool IsIndirect = false;
23380 if (DTCI.Indirect) {
23381 IndirectE = *DTCI.Indirect;
23382 if (!IndirectE)
23383 IsIndirect = true;
23385 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23386 Context,
23387 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
23388 : OMPDeclareTargetDeclAttr::MT_To,
23389 DTCI.DT, IndirectE, IsIndirect, Level,
23390 SourceRange(DTCI.Loc, DTCI.Loc));
23391 D->addAttr(A);
23392 if (ASTMutationListener *ML = Context.getASTMutationListener())
23393 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
23395 return;
23398 if (!E)
23399 return;
23400 checkDeclInTargetContext(E->getExprLoc(), E->getSourceRange(), *this, D);
23403 /// This class visits every VarDecl that the initializer references and adds
23404 /// OMPDeclareTargetDeclAttr to each of them.
23405 class GlobalDeclRefChecker final
23406 : public StmtVisitor<GlobalDeclRefChecker> {
23407 SmallVector<VarDecl *> DeclVector;
23408 Attr *A;
23410 public:
23411 /// A StmtVisitor class function that visits all DeclRefExpr and adds
23412 /// OMPDeclareTargetDeclAttr to them.
23413 void VisitDeclRefExpr(DeclRefExpr *Node) {
23414 if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) {
23415 VD->addAttr(A);
23416 DeclVector.push_back(VD);
23419 /// A function that iterates across each of the Expr's children.
23420 void VisitExpr(Expr *Ex) {
23421 for (auto *Child : Ex->children()) {
23422 Visit(Child);
23425 /// A function that keeps a record of all the Decls that are variables, has
23426 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
23427 /// each Decl one at a time and use the inherited 'visit' functions to look
23428 /// for DeclRefExpr.
23429 void declareTargetInitializer(Decl *TD) {
23430 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
23431 DeclVector.push_back(cast<VarDecl>(TD));
23432 while (!DeclVector.empty()) {
23433 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
23434 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
23435 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
23436 if (Expr *Ex = TargetVarDecl->getInit())
23437 Visit(Ex);
23443 /// Adding OMPDeclareTargetDeclAttr to variables with static storage
23444 /// duration that are referenced in the initializer expression list of
23445 /// variables with static storage duration in declare target directive.
23446 void Sema::ActOnOpenMPDeclareTargetInitializer(Decl *TargetDecl) {
23447 GlobalDeclRefChecker Checker;
23448 if (isa<VarDecl>(TargetDecl))
23449 Checker.declareTargetInitializer(TargetDecl);
23452 OMPClause *Sema::ActOnOpenMPToClause(
23453 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23454 ArrayRef<SourceLocation> MotionModifiersLoc,
23455 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23456 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23457 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23458 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
23459 OMPC_MOTION_MODIFIER_unknown};
23460 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
23462 // Process motion-modifiers, flag errors for duplicate modifiers.
23463 unsigned Count = 0;
23464 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23465 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23466 llvm::is_contained(Modifiers, MotionModifiers[I])) {
23467 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23468 continue;
23470 assert(Count < NumberOfOMPMotionModifiers &&
23471 "Modifiers exceed the allowed number of motion modifiers");
23472 Modifiers[Count] = MotionModifiers[I];
23473 ModifiersLoc[Count] = MotionModifiersLoc[I];
23474 ++Count;
23477 MappableVarListInfo MVLI(VarList);
23478 checkMappableExpressionList(*this, DSAStack, OMPC_to, MVLI, Locs.StartLoc,
23479 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23480 if (MVLI.ProcessedVarList.empty())
23481 return nullptr;
23483 return OMPToClause::Create(
23484 Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23485 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23486 MapperIdScopeSpec.getWithLocInContext(Context), MapperId);
23489 OMPClause *Sema::ActOnOpenMPFromClause(
23490 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23491 ArrayRef<SourceLocation> MotionModifiersLoc,
23492 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23493 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23494 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23495 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
23496 OMPC_MOTION_MODIFIER_unknown};
23497 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
23499 // Process motion-modifiers, flag errors for duplicate modifiers.
23500 unsigned Count = 0;
23501 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23502 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23503 llvm::is_contained(Modifiers, MotionModifiers[I])) {
23504 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23505 continue;
23507 assert(Count < NumberOfOMPMotionModifiers &&
23508 "Modifiers exceed the allowed number of motion modifiers");
23509 Modifiers[Count] = MotionModifiers[I];
23510 ModifiersLoc[Count] = MotionModifiersLoc[I];
23511 ++Count;
23514 MappableVarListInfo MVLI(VarList);
23515 checkMappableExpressionList(*this, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
23516 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23517 if (MVLI.ProcessedVarList.empty())
23518 return nullptr;
23520 return OMPFromClause::Create(
23521 Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23522 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23523 MapperIdScopeSpec.getWithLocInContext(Context), MapperId);
23526 OMPClause *Sema::ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList,
23527 const OMPVarListLocTy &Locs) {
23528 MappableVarListInfo MVLI(VarList);
23529 SmallVector<Expr *, 8> PrivateCopies;
23530 SmallVector<Expr *, 8> Inits;
23532 for (Expr *RefExpr : VarList) {
23533 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
23534 SourceLocation ELoc;
23535 SourceRange ERange;
23536 Expr *SimpleRefExpr = RefExpr;
23537 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
23538 if (Res.second) {
23539 // It will be analyzed later.
23540 MVLI.ProcessedVarList.push_back(RefExpr);
23541 PrivateCopies.push_back(nullptr);
23542 Inits.push_back(nullptr);
23544 ValueDecl *D = Res.first;
23545 if (!D)
23546 continue;
23548 QualType Type = D->getType();
23549 Type = Type.getNonReferenceType().getUnqualifiedType();
23551 auto *VD = dyn_cast<VarDecl>(D);
23553 // Item should be a pointer or reference to pointer.
23554 if (!Type->isPointerType()) {
23555 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
23556 << 0 << RefExpr->getSourceRange();
23557 continue;
23560 // Build the private variable and the expression that refers to it.
23561 auto VDPrivate =
23562 buildVarDecl(*this, ELoc, Type, D->getName(),
23563 D->hasAttrs() ? &D->getAttrs() : nullptr,
23564 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
23565 if (VDPrivate->isInvalidDecl())
23566 continue;
23568 CurContext->addDecl(VDPrivate);
23569 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
23570 *this, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
23572 // Add temporary variable to initialize the private copy of the pointer.
23573 VarDecl *VDInit =
23574 buildVarDecl(*this, RefExpr->getExprLoc(), Type, ".devptr.temp");
23575 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
23576 *this, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
23577 AddInitializerToDecl(VDPrivate,
23578 DefaultLvalueConversion(VDInitRefExpr).get(),
23579 /*DirectInit=*/false);
23581 // If required, build a capture to implement the privatization initialized
23582 // with the current list item value.
23583 DeclRefExpr *Ref = nullptr;
23584 if (!VD)
23585 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
23586 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
23587 PrivateCopies.push_back(VDPrivateRefExpr);
23588 Inits.push_back(VDInitRefExpr);
23590 // We need to add a data sharing attribute for this variable to make sure it
23591 // is correctly captured. A variable that shows up in a use_device_ptr has
23592 // similar properties of a first private variable.
23593 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23595 // Create a mappable component for the list item. List items in this clause
23596 // only need a component.
23597 MVLI.VarBaseDeclarations.push_back(D);
23598 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23599 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
23600 /*IsNonContiguous=*/false);
23603 if (MVLI.ProcessedVarList.empty())
23604 return nullptr;
23606 return OMPUseDevicePtrClause::Create(
23607 Context, Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
23608 MVLI.VarBaseDeclarations, MVLI.VarComponents);
23611 OMPClause *Sema::ActOnOpenMPUseDeviceAddrClause(ArrayRef<Expr *> VarList,
23612 const OMPVarListLocTy &Locs) {
23613 MappableVarListInfo MVLI(VarList);
23615 for (Expr *RefExpr : VarList) {
23616 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
23617 SourceLocation ELoc;
23618 SourceRange ERange;
23619 Expr *SimpleRefExpr = RefExpr;
23620 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
23621 /*AllowArraySection=*/true);
23622 if (Res.second) {
23623 // It will be analyzed later.
23624 MVLI.ProcessedVarList.push_back(RefExpr);
23626 ValueDecl *D = Res.first;
23627 if (!D)
23628 continue;
23629 auto *VD = dyn_cast<VarDecl>(D);
23631 // If required, build a capture to implement the privatization initialized
23632 // with the current list item value.
23633 DeclRefExpr *Ref = nullptr;
23634 if (!VD)
23635 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
23636 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
23638 // We need to add a data sharing attribute for this variable to make sure it
23639 // is correctly captured. A variable that shows up in a use_device_addr has
23640 // similar properties of a first private variable.
23641 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23643 // Create a mappable component for the list item. List items in this clause
23644 // only need a component.
23645 MVLI.VarBaseDeclarations.push_back(D);
23646 MVLI.VarComponents.emplace_back();
23647 Expr *Component = SimpleRefExpr;
23648 if (VD && (isa<OMPArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23649 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23650 Component = DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
23651 MVLI.VarComponents.back().emplace_back(Component, D,
23652 /*IsNonContiguous=*/false);
23655 if (MVLI.ProcessedVarList.empty())
23656 return nullptr;
23658 return OMPUseDeviceAddrClause::Create(Context, Locs, MVLI.ProcessedVarList,
23659 MVLI.VarBaseDeclarations,
23660 MVLI.VarComponents);
23663 OMPClause *Sema::ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList,
23664 const OMPVarListLocTy &Locs) {
23665 MappableVarListInfo MVLI(VarList);
23666 for (Expr *RefExpr : VarList) {
23667 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
23668 SourceLocation ELoc;
23669 SourceRange ERange;
23670 Expr *SimpleRefExpr = RefExpr;
23671 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
23672 if (Res.second) {
23673 // It will be analyzed later.
23674 MVLI.ProcessedVarList.push_back(RefExpr);
23676 ValueDecl *D = Res.first;
23677 if (!D)
23678 continue;
23680 QualType Type = D->getType();
23681 // item should be a pointer or array or reference to pointer or array
23682 if (!Type.getNonReferenceType()->isPointerType() &&
23683 !Type.getNonReferenceType()->isArrayType()) {
23684 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
23685 << 0 << RefExpr->getSourceRange();
23686 continue;
23689 // Check if the declaration in the clause does not show up in any data
23690 // sharing attribute.
23691 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23692 if (isOpenMPPrivate(DVar.CKind)) {
23693 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23694 << getOpenMPClauseName(DVar.CKind)
23695 << getOpenMPClauseName(OMPC_is_device_ptr)
23696 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
23697 reportOriginalDsa(*this, DSAStack, D, DVar);
23698 continue;
23701 const Expr *ConflictExpr;
23702 if (DSAStack->checkMappableExprComponentListsForDecl(
23703 D, /*CurrentRegionOnly=*/true,
23704 [&ConflictExpr](
23705 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
23706 OpenMPClauseKind) -> bool {
23707 ConflictExpr = R.front().getAssociatedExpression();
23708 return true;
23709 })) {
23710 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23711 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23712 << ConflictExpr->getSourceRange();
23713 continue;
23716 // Store the components in the stack so that they can be used to check
23717 // against other clauses later on.
23718 OMPClauseMappableExprCommon::MappableComponent MC(
23719 SimpleRefExpr, D, /*IsNonContiguous=*/false);
23720 DSAStack->addMappableExpressionComponents(
23721 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
23723 // Record the expression we've just processed.
23724 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
23726 // Create a mappable component for the list item. List items in this clause
23727 // only need a component. We use a null declaration to signal fields in
23728 // 'this'.
23729 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23730 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23731 "Unexpected device pointer expression!");
23732 MVLI.VarBaseDeclarations.push_back(
23733 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23734 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23735 MVLI.VarComponents.back().push_back(MC);
23738 if (MVLI.ProcessedVarList.empty())
23739 return nullptr;
23741 return OMPIsDevicePtrClause::Create(Context, Locs, MVLI.ProcessedVarList,
23742 MVLI.VarBaseDeclarations,
23743 MVLI.VarComponents);
23746 OMPClause *Sema::ActOnOpenMPHasDeviceAddrClause(ArrayRef<Expr *> VarList,
23747 const OMPVarListLocTy &Locs) {
23748 MappableVarListInfo MVLI(VarList);
23749 for (Expr *RefExpr : VarList) {
23750 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
23751 SourceLocation ELoc;
23752 SourceRange ERange;
23753 Expr *SimpleRefExpr = RefExpr;
23754 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
23755 /*AllowArraySection=*/true);
23756 if (Res.second) {
23757 // It will be analyzed later.
23758 MVLI.ProcessedVarList.push_back(RefExpr);
23760 ValueDecl *D = Res.first;
23761 if (!D)
23762 continue;
23764 // Check if the declaration in the clause does not show up in any data
23765 // sharing attribute.
23766 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23767 if (isOpenMPPrivate(DVar.CKind)) {
23768 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23769 << getOpenMPClauseName(DVar.CKind)
23770 << getOpenMPClauseName(OMPC_has_device_addr)
23771 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
23772 reportOriginalDsa(*this, DSAStack, D, DVar);
23773 continue;
23776 const Expr *ConflictExpr;
23777 if (DSAStack->checkMappableExprComponentListsForDecl(
23778 D, /*CurrentRegionOnly=*/true,
23779 [&ConflictExpr](
23780 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
23781 OpenMPClauseKind) -> bool {
23782 ConflictExpr = R.front().getAssociatedExpression();
23783 return true;
23784 })) {
23785 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23786 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23787 << ConflictExpr->getSourceRange();
23788 continue;
23791 // Store the components in the stack so that they can be used to check
23792 // against other clauses later on.
23793 Expr *Component = SimpleRefExpr;
23794 auto *VD = dyn_cast<VarDecl>(D);
23795 if (VD && (isa<OMPArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23796 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23797 Component = DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
23798 OMPClauseMappableExprCommon::MappableComponent MC(
23799 Component, D, /*IsNonContiguous=*/false);
23800 DSAStack->addMappableExpressionComponents(
23801 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
23803 // Record the expression we've just processed.
23804 if (!VD && !CurContext->isDependentContext()) {
23805 DeclRefExpr *Ref =
23806 buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
23807 assert(Ref && "has_device_addr capture failed");
23808 MVLI.ProcessedVarList.push_back(Ref);
23809 } else
23810 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
23812 // Create a mappable component for the list item. List items in this clause
23813 // only need a component. We use a null declaration to signal fields in
23814 // 'this'.
23815 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23816 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23817 "Unexpected device pointer expression!");
23818 MVLI.VarBaseDeclarations.push_back(
23819 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23820 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23821 MVLI.VarComponents.back().push_back(MC);
23824 if (MVLI.ProcessedVarList.empty())
23825 return nullptr;
23827 return OMPHasDeviceAddrClause::Create(Context, Locs, MVLI.ProcessedVarList,
23828 MVLI.VarBaseDeclarations,
23829 MVLI.VarComponents);
23832 OMPClause *Sema::ActOnOpenMPAllocateClause(
23833 Expr *Allocator, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
23834 SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
23835 if (Allocator) {
23836 // OpenMP [2.11.4 allocate Clause, Description]
23837 // allocator is an expression of omp_allocator_handle_t type.
23838 if (!findOMPAllocatorHandleT(*this, Allocator->getExprLoc(), DSAStack))
23839 return nullptr;
23841 ExprResult AllocatorRes = DefaultLvalueConversion(Allocator);
23842 if (AllocatorRes.isInvalid())
23843 return nullptr;
23844 AllocatorRes = PerformImplicitConversion(AllocatorRes.get(),
23845 DSAStack->getOMPAllocatorHandleT(),
23846 Sema::AA_Initializing,
23847 /*AllowExplicit=*/true);
23848 if (AllocatorRes.isInvalid())
23849 return nullptr;
23850 Allocator = AllocatorRes.get();
23851 } else {
23852 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
23853 // allocate clauses that appear on a target construct or on constructs in a
23854 // target region must specify an allocator expression unless a requires
23855 // directive with the dynamic_allocators clause is present in the same
23856 // compilation unit.
23857 if (LangOpts.OpenMPIsTargetDevice &&
23858 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
23859 targetDiag(StartLoc, diag::err_expected_allocator_expression);
23861 // Analyze and build list of variables.
23862 SmallVector<Expr *, 8> Vars;
23863 for (Expr *RefExpr : VarList) {
23864 assert(RefExpr && "NULL expr in OpenMP private clause.");
23865 SourceLocation ELoc;
23866 SourceRange ERange;
23867 Expr *SimpleRefExpr = RefExpr;
23868 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
23869 if (Res.second) {
23870 // It will be analyzed later.
23871 Vars.push_back(RefExpr);
23873 ValueDecl *D = Res.first;
23874 if (!D)
23875 continue;
23877 auto *VD = dyn_cast<VarDecl>(D);
23878 DeclRefExpr *Ref = nullptr;
23879 if (!VD && !CurContext->isDependentContext())
23880 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
23881 Vars.push_back((VD || CurContext->isDependentContext())
23882 ? RefExpr->IgnoreParens()
23883 : Ref);
23886 if (Vars.empty())
23887 return nullptr;
23889 if (Allocator)
23890 DSAStack->addInnerAllocatorExpr(Allocator);
23891 return OMPAllocateClause::Create(Context, StartLoc, LParenLoc, Allocator,
23892 ColonLoc, EndLoc, Vars);
23895 OMPClause *Sema::ActOnOpenMPNontemporalClause(ArrayRef<Expr *> VarList,
23896 SourceLocation StartLoc,
23897 SourceLocation LParenLoc,
23898 SourceLocation EndLoc) {
23899 SmallVector<Expr *, 8> Vars;
23900 for (Expr *RefExpr : VarList) {
23901 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23902 SourceLocation ELoc;
23903 SourceRange ERange;
23904 Expr *SimpleRefExpr = RefExpr;
23905 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
23906 if (Res.second)
23907 // It will be analyzed later.
23908 Vars.push_back(RefExpr);
23909 ValueDecl *D = Res.first;
23910 if (!D)
23911 continue;
23913 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
23914 // A list-item cannot appear in more than one nontemporal clause.
23915 if (const Expr *PrevRef =
23916 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
23917 Diag(ELoc, diag::err_omp_used_in_clause_twice)
23918 << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange;
23919 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
23920 << getOpenMPClauseName(OMPC_nontemporal);
23921 continue;
23924 Vars.push_back(RefExpr);
23927 if (Vars.empty())
23928 return nullptr;
23930 return OMPNontemporalClause::Create(Context, StartLoc, LParenLoc, EndLoc,
23931 Vars);
23934 StmtResult Sema::ActOnOpenMPScopeDirective(ArrayRef<OMPClause *> Clauses,
23935 Stmt *AStmt, SourceLocation StartLoc,
23936 SourceLocation EndLoc) {
23937 if (!AStmt)
23938 return StmtError();
23940 setFunctionHasBranchProtectedScope();
23942 return OMPScopeDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
23945 OMPClause *Sema::ActOnOpenMPInclusiveClause(ArrayRef<Expr *> VarList,
23946 SourceLocation StartLoc,
23947 SourceLocation LParenLoc,
23948 SourceLocation EndLoc) {
23949 SmallVector<Expr *, 8> Vars;
23950 for (Expr *RefExpr : VarList) {
23951 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23952 SourceLocation ELoc;
23953 SourceRange ERange;
23954 Expr *SimpleRefExpr = RefExpr;
23955 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
23956 /*AllowArraySection=*/true);
23957 if (Res.second)
23958 // It will be analyzed later.
23959 Vars.push_back(RefExpr);
23960 ValueDecl *D = Res.first;
23961 if (!D)
23962 continue;
23964 const DSAStackTy::DSAVarData DVar =
23965 DSAStack->getTopDSA(D, /*FromParent=*/true);
23966 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23967 // A list item that appears in the inclusive or exclusive clause must appear
23968 // in a reduction clause with the inscan modifier on the enclosing
23969 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23970 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
23971 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23972 << RefExpr->getSourceRange();
23974 if (DSAStack->getParentDirective() != OMPD_unknown)
23975 DSAStack->markDeclAsUsedInScanDirective(D);
23976 Vars.push_back(RefExpr);
23979 if (Vars.empty())
23980 return nullptr;
23982 return OMPInclusiveClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
23985 OMPClause *Sema::ActOnOpenMPExclusiveClause(ArrayRef<Expr *> VarList,
23986 SourceLocation StartLoc,
23987 SourceLocation LParenLoc,
23988 SourceLocation EndLoc) {
23989 SmallVector<Expr *, 8> Vars;
23990 for (Expr *RefExpr : VarList) {
23991 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23992 SourceLocation ELoc;
23993 SourceRange ERange;
23994 Expr *SimpleRefExpr = RefExpr;
23995 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
23996 /*AllowArraySection=*/true);
23997 if (Res.second)
23998 // It will be analyzed later.
23999 Vars.push_back(RefExpr);
24000 ValueDecl *D = Res.first;
24001 if (!D)
24002 continue;
24004 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
24005 DSAStackTy::DSAVarData DVar;
24006 if (ParentDirective != OMPD_unknown)
24007 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
24008 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
24009 // A list item that appears in the inclusive or exclusive clause must appear
24010 // in a reduction clause with the inscan modifier on the enclosing
24011 // worksharing-loop, worksharing-loop SIMD, or simd construct.
24012 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
24013 DVar.Modifier != OMPC_REDUCTION_inscan) {
24014 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
24015 << RefExpr->getSourceRange();
24016 } else {
24017 DSAStack->markDeclAsUsedInScanDirective(D);
24019 Vars.push_back(RefExpr);
24022 if (Vars.empty())
24023 return nullptr;
24025 return OMPExclusiveClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
24028 /// Tries to find omp_alloctrait_t type.
24029 static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
24030 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
24031 if (!OMPAlloctraitT.isNull())
24032 return true;
24033 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
24034 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
24035 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
24036 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
24037 return false;
24039 Stack->setOMPAlloctraitT(PT.get());
24040 return true;
24043 OMPClause *Sema::ActOnOpenMPUsesAllocatorClause(
24044 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
24045 ArrayRef<UsesAllocatorsData> Data) {
24046 // OpenMP [2.12.5, target Construct]
24047 // allocator is an identifier of omp_allocator_handle_t type.
24048 if (!findOMPAllocatorHandleT(*this, StartLoc, DSAStack))
24049 return nullptr;
24050 // OpenMP [2.12.5, target Construct]
24051 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
24052 if (llvm::any_of(
24053 Data,
24054 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
24055 !findOMPAlloctraitT(*this, StartLoc, DSAStack))
24056 return nullptr;
24057 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
24058 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
24059 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
24060 StringRef Allocator =
24061 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
24062 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
24063 PredefinedAllocators.insert(LookupSingleName(
24064 TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
24067 SmallVector<OMPUsesAllocatorsClause::Data, 4> NewData;
24068 for (const UsesAllocatorsData &D : Data) {
24069 Expr *AllocatorExpr = nullptr;
24070 // Check allocator expression.
24071 if (D.Allocator->isTypeDependent()) {
24072 AllocatorExpr = D.Allocator;
24073 } else {
24074 // Traits were specified - need to assign new allocator to the specified
24075 // allocator, so it must be an lvalue.
24076 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
24077 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
24078 bool IsPredefinedAllocator = false;
24079 if (DRE) {
24080 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
24081 getAllocatorKind(*this, DSAStack, AllocatorExpr);
24082 IsPredefinedAllocator =
24083 AllocatorTy !=
24084 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
24086 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
24087 QualType AllocatorExprType = AllocatorExpr->getType();
24088 bool IsTypeCompatible = IsPredefinedAllocator;
24089 IsTypeCompatible = IsTypeCompatible ||
24090 Context.hasSameUnqualifiedType(AllocatorExprType,
24091 OMPAllocatorHandleT);
24092 IsTypeCompatible =
24093 IsTypeCompatible ||
24094 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
24095 bool IsNonConstantLValue =
24096 !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue();
24097 if (!DRE || !IsTypeCompatible ||
24098 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
24099 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
24100 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
24101 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
24102 continue;
24104 // OpenMP [2.12.5, target Construct]
24105 // Predefined allocators appearing in a uses_allocators clause cannot have
24106 // traits specified.
24107 if (IsPredefinedAllocator && D.AllocatorTraits) {
24108 Diag(D.AllocatorTraits->getExprLoc(),
24109 diag::err_omp_predefined_allocator_with_traits)
24110 << D.AllocatorTraits->getSourceRange();
24111 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
24112 << cast<NamedDecl>(DRE->getDecl())->getName()
24113 << D.Allocator->getSourceRange();
24114 continue;
24116 // OpenMP [2.12.5, target Construct]
24117 // Non-predefined allocators appearing in a uses_allocators clause must
24118 // have traits specified.
24119 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
24120 Diag(D.Allocator->getExprLoc(),
24121 diag::err_omp_nonpredefined_allocator_without_traits);
24122 continue;
24124 // No allocator traits - just convert it to rvalue.
24125 if (!D.AllocatorTraits)
24126 AllocatorExpr = DefaultLvalueConversion(AllocatorExpr).get();
24127 DSAStack->addUsesAllocatorsDecl(
24128 DRE->getDecl(),
24129 IsPredefinedAllocator
24130 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
24131 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
24133 Expr *AllocatorTraitsExpr = nullptr;
24134 if (D.AllocatorTraits) {
24135 if (D.AllocatorTraits->isTypeDependent()) {
24136 AllocatorTraitsExpr = D.AllocatorTraits;
24137 } else {
24138 // OpenMP [2.12.5, target Construct]
24139 // Arrays that contain allocator traits that appear in a uses_allocators
24140 // clause must be constant arrays, have constant values and be defined
24141 // in the same scope as the construct in which the clause appears.
24142 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
24143 // Check that traits expr is a constant array.
24144 QualType TraitTy;
24145 if (const ArrayType *Ty =
24146 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
24147 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
24148 TraitTy = ConstArrayTy->getElementType();
24149 if (TraitTy.isNull() ||
24150 !(Context.hasSameUnqualifiedType(TraitTy,
24151 DSAStack->getOMPAlloctraitT()) ||
24152 Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
24153 /*CompareUnqualified=*/true))) {
24154 Diag(D.AllocatorTraits->getExprLoc(),
24155 diag::err_omp_expected_array_alloctraits)
24156 << AllocatorTraitsExpr->getType();
24157 continue;
24159 // Do not map by default allocator traits if it is a standalone
24160 // variable.
24161 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
24162 DSAStack->addUsesAllocatorsDecl(
24163 DRE->getDecl(),
24164 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
24167 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
24168 NewD.Allocator = AllocatorExpr;
24169 NewD.AllocatorTraits = AllocatorTraitsExpr;
24170 NewD.LParenLoc = D.LParenLoc;
24171 NewD.RParenLoc = D.RParenLoc;
24173 return OMPUsesAllocatorsClause::Create(Context, StartLoc, LParenLoc, EndLoc,
24174 NewData);
24177 OMPClause *Sema::ActOnOpenMPAffinityClause(
24178 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
24179 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
24180 SmallVector<Expr *, 8> Vars;
24181 for (Expr *RefExpr : Locators) {
24182 assert(RefExpr && "NULL expr in OpenMP shared clause.");
24183 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
24184 // It will be analyzed later.
24185 Vars.push_back(RefExpr);
24186 continue;
24189 SourceLocation ELoc = RefExpr->getExprLoc();
24190 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
24192 if (!SimpleExpr->isLValue()) {
24193 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24194 << 1 << 0 << RefExpr->getSourceRange();
24195 continue;
24198 ExprResult Res;
24200 Sema::TentativeAnalysisScope Trap(*this);
24201 Res = CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
24203 if (!Res.isUsable() && !isa<OMPArraySectionExpr>(SimpleExpr) &&
24204 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
24205 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24206 << 1 << 0 << RefExpr->getSourceRange();
24207 continue;
24209 Vars.push_back(SimpleExpr);
24212 return OMPAffinityClause::Create(Context, StartLoc, LParenLoc, ColonLoc,
24213 EndLoc, Modifier, Vars);
24216 OMPClause *Sema::ActOnOpenMPBindClause(OpenMPBindClauseKind Kind,
24217 SourceLocation KindLoc,
24218 SourceLocation StartLoc,
24219 SourceLocation LParenLoc,
24220 SourceLocation EndLoc) {
24221 if (Kind == OMPC_BIND_unknown) {
24222 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24223 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
24224 /*Last=*/unsigned(OMPC_BIND_unknown))
24225 << getOpenMPClauseName(OMPC_bind);
24226 return nullptr;
24229 return OMPBindClause::Create(Context, Kind, KindLoc, StartLoc, LParenLoc,
24230 EndLoc);
24233 OMPClause *Sema::ActOnOpenMPXDynCGroupMemClause(Expr *Size,
24234 SourceLocation StartLoc,
24235 SourceLocation LParenLoc,
24236 SourceLocation EndLoc) {
24237 Expr *ValExpr = Size;
24238 Stmt *HelperValStmt = nullptr;
24240 // OpenMP [2.5, Restrictions]
24241 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
24242 // value.
24243 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_ompx_dyn_cgroup_mem,
24244 /*StrictlyPositive=*/false))
24245 return nullptr;
24247 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
24248 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
24249 DKind, OMPC_ompx_dyn_cgroup_mem, LangOpts.OpenMP);
24250 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
24251 ValExpr = MakeFullExpr(ValExpr).get();
24252 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24253 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
24254 HelperValStmt = buildPreInits(Context, Captures);
24257 return new (Context) OMPXDynCGroupMemClause(
24258 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
24261 OMPClause *Sema::ActOnOpenMPDoacrossClause(
24262 OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc,
24263 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
24264 SourceLocation LParenLoc, SourceLocation EndLoc) {
24266 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
24267 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
24268 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
24269 DepType != OMPC_DOACROSS_source_omp_cur_iteration &&
24270 DepType != OMPC_DOACROSS_source) {
24271 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
24272 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_doacross);
24273 return nullptr;
24276 SmallVector<Expr *, 8> Vars;
24277 DSAStackTy::OperatorOffsetTy OpsOffs;
24278 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
24279 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
24280 *this,
24281 DepType == OMPC_DOACROSS_source ||
24282 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
24283 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
24284 VarList, DSAStack, EndLoc);
24285 Vars = VarOffset.Vars;
24286 OpsOffs = VarOffset.OpsOffs;
24287 TotalDepCount = VarOffset.TotalDepCount;
24288 auto *C = OMPDoacrossClause::Create(Context, StartLoc, LParenLoc, EndLoc,
24289 DepType, DepLoc, ColonLoc, Vars,
24290 TotalDepCount.getZExtValue());
24291 if (DSAStack->isParentOrderedRegion())
24292 DSAStack->addDoacrossDependClause(C, OpsOffs);
24293 return C;
24296 OMPClause *Sema::ActOnOpenMPXAttributeClause(ArrayRef<const Attr *> Attrs,
24297 SourceLocation StartLoc,
24298 SourceLocation LParenLoc,
24299 SourceLocation EndLoc) {
24300 return new (Context) OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
24303 OMPClause *Sema::ActOnOpenMPXBareClause(SourceLocation StartLoc,
24304 SourceLocation EndLoc) {
24305 return new (Context) OMPXBareClause(StartLoc, EndLoc);