[docs] Fix build-docs.sh
[llvm-project.git] / clang / lib / Sema / SemaOpenMP.cpp
blobd05380b30e47f4eec38821e156e5e5d3dd9a2a10
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/Initialization.h"
31 #include "clang/Sema/Lookup.h"
32 #include "clang/Sema/Scope.h"
33 #include "clang/Sema/ScopeInfo.h"
34 #include "clang/Sema/SemaInternal.h"
35 #include "llvm/ADT/IndexedMap.h"
36 #include "llvm/ADT/PointerEmbeddedInt.h"
37 #include "llvm/ADT/STLExtras.h"
38 #include "llvm/ADT/SmallSet.h"
39 #include "llvm/ADT/StringExtras.h"
40 #include "llvm/Frontend/OpenMP/OMPAssume.h"
41 #include "llvm/Frontend/OpenMP/OMPConstants.h"
42 #include <set>
44 using namespace clang;
45 using namespace llvm::omp;
47 //===----------------------------------------------------------------------===//
48 // Stack of data-sharing attributes for variables
49 //===----------------------------------------------------------------------===//
51 static const Expr *checkMapClauseExpressionBase(
52 Sema &SemaRef, Expr *E,
53 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
54 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose);
56 namespace {
57 /// Default data sharing attributes, which can be applied to directive.
58 enum DefaultDataSharingAttributes {
59 DSA_unspecified = 0, /// Data sharing attribute not specified.
60 DSA_none = 1 << 0, /// Default data sharing attribute 'none'.
61 DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
62 DSA_private = 1 << 2, /// Default data sharing attribute 'private'.
63 DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'.
66 /// Stack for tracking declarations used in OpenMP directives and
67 /// clauses and their data-sharing attributes.
68 class DSAStackTy {
69 public:
70 struct DSAVarData {
71 OpenMPDirectiveKind DKind = OMPD_unknown;
72 OpenMPClauseKind CKind = OMPC_unknown;
73 unsigned Modifier = 0;
74 const Expr *RefExpr = nullptr;
75 DeclRefExpr *PrivateCopy = nullptr;
76 SourceLocation ImplicitDSALoc;
77 bool AppliedToPointee = false;
78 DSAVarData() = default;
79 DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
80 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
81 SourceLocation ImplicitDSALoc, unsigned Modifier,
82 bool AppliedToPointee)
83 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
84 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
85 AppliedToPointee(AppliedToPointee) {}
87 using OperatorOffsetTy =
88 llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
89 using DoacrossDependMapTy =
90 llvm::DenseMap<OMPDependClause *, OperatorOffsetTy>;
91 /// Kind of the declaration used in the uses_allocators clauses.
92 enum class UsesAllocatorsDeclKind {
93 /// Predefined allocator
94 PredefinedAllocator,
95 /// User-defined allocator
96 UserDefinedAllocator,
97 /// The declaration that represent allocator trait
98 AllocatorTrait,
101 private:
102 struct DSAInfo {
103 OpenMPClauseKind Attributes = OMPC_unknown;
104 unsigned Modifier = 0;
105 /// Pointer to a reference expression and a flag which shows that the
106 /// variable is marked as lastprivate(true) or not (false).
107 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
108 DeclRefExpr *PrivateCopy = nullptr;
109 /// true if the attribute is applied to the pointee, not the variable
110 /// itself.
111 bool AppliedToPointee = false;
113 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
114 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
115 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
116 using LoopControlVariablesMapTy =
117 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
118 /// Struct that associates a component with the clause kind where they are
119 /// found.
120 struct MappedExprComponentTy {
121 OMPClauseMappableExprCommon::MappableExprComponentLists Components;
122 OpenMPClauseKind Kind = OMPC_unknown;
124 using MappedExprComponentsTy =
125 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
126 using CriticalsWithHintsTy =
127 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
128 struct ReductionData {
129 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
130 SourceRange ReductionRange;
131 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
132 ReductionData() = default;
133 void set(BinaryOperatorKind BO, SourceRange RR) {
134 ReductionRange = RR;
135 ReductionOp = BO;
137 void set(const Expr *RefExpr, SourceRange RR) {
138 ReductionRange = RR;
139 ReductionOp = RefExpr;
142 using DeclReductionMapTy =
143 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
144 struct DefaultmapInfo {
145 OpenMPDefaultmapClauseModifier ImplicitBehavior =
146 OMPC_DEFAULTMAP_MODIFIER_unknown;
147 SourceLocation SLoc;
148 DefaultmapInfo() = default;
149 DefaultmapInfo(OpenMPDefaultmapClauseModifier M, SourceLocation Loc)
150 : ImplicitBehavior(M), SLoc(Loc) {}
153 struct SharingMapTy {
154 DeclSAMapTy SharingMap;
155 DeclReductionMapTy ReductionMap;
156 UsedRefMapTy AlignedMap;
157 UsedRefMapTy NontemporalMap;
158 MappedExprComponentsTy MappedExprComponents;
159 LoopControlVariablesMapTy LCVMap;
160 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
161 SourceLocation DefaultAttrLoc;
162 DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown];
163 OpenMPDirectiveKind Directive = OMPD_unknown;
164 DeclarationNameInfo DirectiveName;
165 Scope *CurScope = nullptr;
166 DeclContext *Context = nullptr;
167 SourceLocation ConstructLoc;
168 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
169 /// get the data (loop counters etc.) about enclosing loop-based construct.
170 /// This data is required during codegen.
171 DoacrossDependMapTy DoacrossDepends;
172 /// First argument (Expr *) contains optional argument of the
173 /// 'ordered' clause, the second one is true if the regions has 'ordered'
174 /// clause, false otherwise.
175 llvm::Optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
176 unsigned AssociatedLoops = 1;
177 bool HasMutipleLoops = false;
178 const Decl *PossiblyLoopCounter = nullptr;
179 bool NowaitRegion = false;
180 bool UntiedRegion = false;
181 bool CancelRegion = false;
182 bool LoopStart = false;
183 bool BodyComplete = false;
184 SourceLocation PrevScanLocation;
185 SourceLocation PrevOrderedLocation;
186 SourceLocation InnerTeamsRegionLoc;
187 /// Reference to the taskgroup task_reduction reference expression.
188 Expr *TaskgroupReductionRef = nullptr;
189 llvm::DenseSet<QualType> MappedClassesQualTypes;
190 SmallVector<Expr *, 4> InnerUsedAllocators;
191 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
192 /// List of globals marked as declare target link in this target region
193 /// (isOpenMPTargetExecutionDirective(Directive) == true).
194 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
195 /// List of decls used in inclusive/exclusive clauses of the scan directive.
196 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
197 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
198 UsesAllocatorsDecls;
199 /// Data is required on creating capture fields for implicit
200 /// default first|private clause.
201 struct ImplicitDefaultFDInfoTy {
202 /// Field decl.
203 const FieldDecl *FD = nullptr;
204 /// Nesting stack level
205 size_t StackLevel = 0;
206 /// Capture variable decl.
207 VarDecl *VD = nullptr;
208 ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel,
209 VarDecl *VD)
210 : FD(FD), StackLevel(StackLevel), VD(VD) {}
212 /// List of captured fields
213 llvm::SmallVector<ImplicitDefaultFDInfoTy, 8>
214 ImplicitDefaultFirstprivateFDs;
215 Expr *DeclareMapperVar = nullptr;
216 SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
217 Scope *CurScope, SourceLocation Loc)
218 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
219 ConstructLoc(Loc) {}
220 SharingMapTy() = default;
223 using StackTy = SmallVector<SharingMapTy, 4>;
225 /// Stack of used declaration and their data-sharing attributes.
226 DeclSAMapTy Threadprivates;
227 const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
228 SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack;
229 /// true, if check for DSA must be from parent directive, false, if
230 /// from current directive.
231 OpenMPClauseKind ClauseKindMode = OMPC_unknown;
232 Sema &SemaRef;
233 bool ForceCapturing = false;
234 /// true if all the variables in the target executable directives must be
235 /// captured by reference.
236 bool ForceCaptureByReferenceInTargetExecutable = false;
237 CriticalsWithHintsTy Criticals;
238 unsigned IgnoredStackElements = 0;
240 /// Iterators over the stack iterate in order from innermost to outermost
241 /// directive.
242 using const_iterator = StackTy::const_reverse_iterator;
243 const_iterator begin() const {
244 return Stack.empty() ? const_iterator()
245 : Stack.back().first.rbegin() + IgnoredStackElements;
247 const_iterator end() const {
248 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
250 using iterator = StackTy::reverse_iterator;
251 iterator begin() {
252 return Stack.empty() ? iterator()
253 : Stack.back().first.rbegin() + IgnoredStackElements;
255 iterator end() {
256 return Stack.empty() ? iterator() : Stack.back().first.rend();
259 // Convenience operations to get at the elements of the stack.
261 bool isStackEmpty() const {
262 return Stack.empty() ||
263 Stack.back().second != CurrentNonCapturingFunctionScope ||
264 Stack.back().first.size() <= IgnoredStackElements;
266 size_t getStackSize() const {
267 return isStackEmpty() ? 0
268 : Stack.back().first.size() - IgnoredStackElements;
271 SharingMapTy *getTopOfStackOrNull() {
272 size_t Size = getStackSize();
273 if (Size == 0)
274 return nullptr;
275 return &Stack.back().first[Size - 1];
277 const SharingMapTy *getTopOfStackOrNull() const {
278 return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull();
280 SharingMapTy &getTopOfStack() {
281 assert(!isStackEmpty() && "no current directive");
282 return *getTopOfStackOrNull();
284 const SharingMapTy &getTopOfStack() const {
285 return const_cast<DSAStackTy &>(*this).getTopOfStack();
288 SharingMapTy *getSecondOnStackOrNull() {
289 size_t Size = getStackSize();
290 if (Size <= 1)
291 return nullptr;
292 return &Stack.back().first[Size - 2];
294 const SharingMapTy *getSecondOnStackOrNull() const {
295 return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull();
298 /// Get the stack element at a certain level (previously returned by
299 /// \c getNestingLevel).
301 /// Note that nesting levels count from outermost to innermost, and this is
302 /// the reverse of our iteration order where new inner levels are pushed at
303 /// the front of the stack.
304 SharingMapTy &getStackElemAtLevel(unsigned Level) {
305 assert(Level < getStackSize() && "no such stack element");
306 return Stack.back().first[Level];
308 const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
309 return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level);
312 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
314 /// Checks if the variable is a local for OpenMP region.
315 bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
317 /// Vector of previously declared requires directives
318 SmallVector<const OMPRequiresDecl *, 2> RequiresDecls;
319 /// omp_allocator_handle_t type.
320 QualType OMPAllocatorHandleT;
321 /// omp_depend_t type.
322 QualType OMPDependT;
323 /// omp_event_handle_t type.
324 QualType OMPEventHandleT;
325 /// omp_alloctrait_t type.
326 QualType OMPAlloctraitT;
327 /// Expression for the predefined allocators.
328 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
329 nullptr};
330 /// Vector of previously encountered target directives
331 SmallVector<SourceLocation, 2> TargetLocations;
332 SourceLocation AtomicLocation;
333 /// Vector of declare variant construct traits.
334 SmallVector<llvm::omp::TraitProperty, 8> ConstructTraits;
336 public:
337 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
339 /// Sets omp_allocator_handle_t type.
340 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
341 /// Gets omp_allocator_handle_t type.
342 QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
343 /// Sets omp_alloctrait_t type.
344 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
345 /// Gets omp_alloctrait_t type.
346 QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
347 /// Sets the given default allocator.
348 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
349 Expr *Allocator) {
350 OMPPredefinedAllocators[AllocatorKind] = Allocator;
352 /// Returns the specified default allocator.
353 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
354 return OMPPredefinedAllocators[AllocatorKind];
356 /// Sets omp_depend_t type.
357 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
358 /// Gets omp_depend_t type.
359 QualType getOMPDependT() const { return OMPDependT; }
361 /// Sets omp_event_handle_t type.
362 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
363 /// Gets omp_event_handle_t type.
364 QualType getOMPEventHandleT() const { return OMPEventHandleT; }
366 bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
367 OpenMPClauseKind getClauseParsingMode() const {
368 assert(isClauseParsingMode() && "Must be in clause parsing mode.");
369 return ClauseKindMode;
371 void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
373 bool isBodyComplete() const {
374 const SharingMapTy *Top = getTopOfStackOrNull();
375 return Top && Top->BodyComplete;
377 void setBodyComplete() { getTopOfStack().BodyComplete = true; }
379 bool isForceVarCapturing() const { return ForceCapturing; }
380 void setForceVarCapturing(bool V) { ForceCapturing = V; }
382 void setForceCaptureByReferenceInTargetExecutable(bool V) {
383 ForceCaptureByReferenceInTargetExecutable = V;
385 bool isForceCaptureByReferenceInTargetExecutable() const {
386 return ForceCaptureByReferenceInTargetExecutable;
389 void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
390 Scope *CurScope, SourceLocation Loc) {
391 assert(!IgnoredStackElements &&
392 "cannot change stack while ignoring elements");
393 if (Stack.empty() ||
394 Stack.back().second != CurrentNonCapturingFunctionScope)
395 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
396 Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc);
397 Stack.back().first.back().DefaultAttrLoc = Loc;
400 void pop() {
401 assert(!IgnoredStackElements &&
402 "cannot change stack while ignoring elements");
403 assert(!Stack.back().first.empty() &&
404 "Data-sharing attributes stack is empty!");
405 Stack.back().first.pop_back();
408 /// RAII object to temporarily leave the scope of a directive when we want to
409 /// logically operate in its parent.
410 class ParentDirectiveScope {
411 DSAStackTy &Self;
412 bool Active;
414 public:
415 ParentDirectiveScope(DSAStackTy &Self, bool Activate)
416 : Self(Self), Active(false) {
417 if (Activate)
418 enable();
420 ~ParentDirectiveScope() { disable(); }
421 void disable() {
422 if (Active) {
423 --Self.IgnoredStackElements;
424 Active = false;
427 void enable() {
428 if (!Active) {
429 ++Self.IgnoredStackElements;
430 Active = true;
435 /// Marks that we're started loop parsing.
436 void loopInit() {
437 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
438 "Expected loop-based directive.");
439 getTopOfStack().LoopStart = true;
441 /// Start capturing of the variables in the loop context.
442 void loopStart() {
443 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
444 "Expected loop-based directive.");
445 getTopOfStack().LoopStart = false;
447 /// true, if variables are captured, false otherwise.
448 bool isLoopStarted() const {
449 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
450 "Expected loop-based directive.");
451 return !getTopOfStack().LoopStart;
453 /// Marks (or clears) declaration as possibly loop counter.
454 void resetPossibleLoopCounter(const Decl *D = nullptr) {
455 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
457 /// Gets the possible loop counter decl.
458 const Decl *getPossiblyLoopCunter() const {
459 return getTopOfStack().PossiblyLoopCounter;
461 /// Start new OpenMP region stack in new non-capturing function.
462 void pushFunction() {
463 assert(!IgnoredStackElements &&
464 "cannot change stack while ignoring elements");
465 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
466 assert(!isa<CapturingScopeInfo>(CurFnScope));
467 CurrentNonCapturingFunctionScope = CurFnScope;
469 /// Pop region stack for non-capturing function.
470 void popFunction(const FunctionScopeInfo *OldFSI) {
471 assert(!IgnoredStackElements &&
472 "cannot change stack while ignoring elements");
473 if (!Stack.empty() && Stack.back().second == OldFSI) {
474 assert(Stack.back().first.empty());
475 Stack.pop_back();
477 CurrentNonCapturingFunctionScope = nullptr;
478 for (const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) {
479 if (!isa<CapturingScopeInfo>(FSI)) {
480 CurrentNonCapturingFunctionScope = FSI;
481 break;
486 void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
487 Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint);
489 const std::pair<const OMPCriticalDirective *, llvm::APSInt>
490 getCriticalWithHint(const DeclarationNameInfo &Name) const {
491 auto I = Criticals.find(Name.getAsString());
492 if (I != Criticals.end())
493 return I->second;
494 return std::make_pair(nullptr, llvm::APSInt());
496 /// If 'aligned' declaration for given variable \a D was not seen yet,
497 /// add it and return NULL; otherwise return previous occurrence's expression
498 /// for diagnostics.
499 const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
500 /// If 'nontemporal' declaration for given variable \a D was not seen yet,
501 /// add it and return NULL; otherwise return previous occurrence's expression
502 /// for diagnostics.
503 const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
505 /// Register specified variable as loop control variable.
506 void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
507 /// Check if the specified variable is a loop control variable for
508 /// current region.
509 /// \return The index of the loop control variable in the list of associated
510 /// for-loops (from outer to inner).
511 const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
512 /// Check if the specified variable is a loop control variable for
513 /// parent region.
514 /// \return The index of the loop control variable in the list of associated
515 /// for-loops (from outer to inner).
516 const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const;
517 /// Check if the specified variable is a loop control variable for
518 /// current region.
519 /// \return The index of the loop control variable in the list of associated
520 /// for-loops (from outer to inner).
521 const LCDeclInfo isLoopControlVariable(const ValueDecl *D,
522 unsigned Level) const;
523 /// Get the loop control variable for the I-th loop (or nullptr) in
524 /// parent directive.
525 const ValueDecl *getParentLoopControlVariable(unsigned I) const;
527 /// Marks the specified decl \p D as used in scan directive.
528 void markDeclAsUsedInScanDirective(ValueDecl *D) {
529 if (SharingMapTy *Stack = getSecondOnStackOrNull())
530 Stack->UsedInScanDirective.insert(D);
533 /// Checks if the specified declaration was used in the inner scan directive.
534 bool isUsedInScanDirective(ValueDecl *D) const {
535 if (const SharingMapTy *Stack = getTopOfStackOrNull())
536 return Stack->UsedInScanDirective.contains(D);
537 return false;
540 /// Adds explicit data sharing attribute to the specified declaration.
541 void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
542 DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
543 bool AppliedToPointee = false);
545 /// Adds additional information for the reduction items with the reduction id
546 /// represented as an operator.
547 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
548 BinaryOperatorKind BOK);
549 /// Adds additional information for the reduction items with the reduction id
550 /// represented as reduction identifier.
551 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
552 const Expr *ReductionRef);
553 /// Returns the location and reduction operation from the innermost parent
554 /// region for the given \p D.
555 const DSAVarData
556 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
557 BinaryOperatorKind &BOK,
558 Expr *&TaskgroupDescriptor) const;
559 /// Returns the location and reduction operation from the innermost parent
560 /// region for the given \p D.
561 const DSAVarData
562 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
563 const Expr *&ReductionRef,
564 Expr *&TaskgroupDescriptor) const;
565 /// Return reduction reference expression for the current taskgroup or
566 /// parallel/worksharing directives with task reductions.
567 Expr *getTaskgroupReductionRef() const {
568 assert((getTopOfStack().Directive == OMPD_taskgroup ||
569 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
570 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
571 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
572 "taskgroup reference expression requested for non taskgroup or "
573 "parallel/worksharing directive.");
574 return getTopOfStack().TaskgroupReductionRef;
576 /// Checks if the given \p VD declaration is actually a taskgroup reduction
577 /// descriptor variable at the \p Level of OpenMP regions.
578 bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
579 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
580 cast<DeclRefExpr>(getStackElemAtLevel(Level).TaskgroupReductionRef)
581 ->getDecl() == VD;
584 /// Returns data sharing attributes from top of the stack for the
585 /// specified declaration.
586 const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
587 /// Returns data-sharing attributes for the specified declaration.
588 const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
589 /// Returns data-sharing attributes for the specified declaration.
590 const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const;
591 /// Checks if the specified variables has data-sharing attributes which
592 /// match specified \a CPred predicate in any directive which matches \a DPred
593 /// predicate.
594 const DSAVarData
595 hasDSA(ValueDecl *D,
596 const llvm::function_ref<bool(OpenMPClauseKind, bool,
597 DefaultDataSharingAttributes)>
598 CPred,
599 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
600 bool FromParent) const;
601 /// Checks if the specified variables has data-sharing attributes which
602 /// match specified \a CPred predicate in any innermost directive which
603 /// matches \a DPred predicate.
604 const DSAVarData
605 hasInnermostDSA(ValueDecl *D,
606 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
607 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
608 bool FromParent) const;
609 /// Checks if the specified variables has explicit data-sharing
610 /// attributes which match specified \a CPred predicate at the specified
611 /// OpenMP region.
612 bool
613 hasExplicitDSA(const ValueDecl *D,
614 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
615 unsigned Level, bool NotLastprivate = false) const;
617 /// Returns true if the directive at level \Level matches in the
618 /// specified \a DPred predicate.
619 bool hasExplicitDirective(
620 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
621 unsigned Level) const;
623 /// Finds a directive which matches specified \a DPred predicate.
624 bool hasDirective(
625 const llvm::function_ref<bool(
626 OpenMPDirectiveKind, const DeclarationNameInfo &, SourceLocation)>
627 DPred,
628 bool FromParent) const;
630 /// Returns currently analyzed directive.
631 OpenMPDirectiveKind getCurrentDirective() const {
632 const SharingMapTy *Top = getTopOfStackOrNull();
633 return Top ? Top->Directive : OMPD_unknown;
635 /// Returns directive kind at specified level.
636 OpenMPDirectiveKind getDirective(unsigned Level) const {
637 assert(!isStackEmpty() && "No directive at specified level.");
638 return getStackElemAtLevel(Level).Directive;
640 /// Returns the capture region at the specified level.
641 OpenMPDirectiveKind getCaptureRegion(unsigned Level,
642 unsigned OpenMPCaptureLevel) const {
643 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
644 getOpenMPCaptureRegions(CaptureRegions, getDirective(Level));
645 return CaptureRegions[OpenMPCaptureLevel];
647 /// Returns parent directive.
648 OpenMPDirectiveKind getParentDirective() const {
649 const SharingMapTy *Parent = getSecondOnStackOrNull();
650 return Parent ? Parent->Directive : OMPD_unknown;
653 /// Add requires decl to internal vector
654 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
656 /// Checks if the defined 'requires' directive has specified type of clause.
657 template <typename ClauseType> bool hasRequiresDeclWithClause() const {
658 return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
659 return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
660 return isa<ClauseType>(C);
665 /// Checks for a duplicate clause amongst previously declared requires
666 /// directives
667 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
668 bool IsDuplicate = false;
669 for (OMPClause *CNew : ClauseList) {
670 for (const OMPRequiresDecl *D : RequiresDecls) {
671 for (const OMPClause *CPrev : D->clauselists()) {
672 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
673 SemaRef.Diag(CNew->getBeginLoc(),
674 diag::err_omp_requires_clause_redeclaration)
675 << getOpenMPClauseName(CNew->getClauseKind());
676 SemaRef.Diag(CPrev->getBeginLoc(),
677 diag::note_omp_requires_previous_clause)
678 << getOpenMPClauseName(CPrev->getClauseKind());
679 IsDuplicate = true;
684 return IsDuplicate;
687 /// Add location of previously encountered target to internal vector
688 void addTargetDirLocation(SourceLocation LocStart) {
689 TargetLocations.push_back(LocStart);
692 /// Add location for the first encountered atomicc directive.
693 void addAtomicDirectiveLoc(SourceLocation Loc) {
694 if (AtomicLocation.isInvalid())
695 AtomicLocation = Loc;
698 /// Returns the location of the first encountered atomic directive in the
699 /// module.
700 SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; }
702 // Return previously encountered target region locations.
703 ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
704 return TargetLocations;
707 /// Set default data sharing attribute to none.
708 void setDefaultDSANone(SourceLocation Loc) {
709 getTopOfStack().DefaultAttr = DSA_none;
710 getTopOfStack().DefaultAttrLoc = Loc;
712 /// Set default data sharing attribute to shared.
713 void setDefaultDSAShared(SourceLocation Loc) {
714 getTopOfStack().DefaultAttr = DSA_shared;
715 getTopOfStack().DefaultAttrLoc = Loc;
717 /// Set default data sharing attribute to private.
718 void setDefaultDSAPrivate(SourceLocation Loc) {
719 getTopOfStack().DefaultAttr = DSA_private;
720 getTopOfStack().DefaultAttrLoc = Loc;
722 /// Set default data sharing attribute to firstprivate.
723 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
724 getTopOfStack().DefaultAttr = DSA_firstprivate;
725 getTopOfStack().DefaultAttrLoc = Loc;
727 /// Set default data mapping attribute to Modifier:Kind
728 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
729 OpenMPDefaultmapClauseKind Kind, SourceLocation Loc) {
730 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind];
731 DMI.ImplicitBehavior = M;
732 DMI.SLoc = Loc;
734 /// Check whether the implicit-behavior has been set in defaultmap
735 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) {
736 if (VariableCategory == OMPC_DEFAULTMAP_unknown)
737 return getTopOfStack()
738 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
739 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
740 getTopOfStack()
741 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
742 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
743 getTopOfStack()
744 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
745 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown;
746 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
747 OMPC_DEFAULTMAP_MODIFIER_unknown;
750 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
751 return ConstructTraits;
753 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
754 bool ScopeEntry) {
755 if (ScopeEntry)
756 ConstructTraits.append(Traits.begin(), Traits.end());
757 else
758 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
759 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
760 assert(Top == Trait && "Something left a trait on the stack!");
761 (void)Trait;
762 (void)Top;
766 DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const {
767 return getStackSize() <= Level ? DSA_unspecified
768 : getStackElemAtLevel(Level).DefaultAttr;
770 DefaultDataSharingAttributes getDefaultDSA() const {
771 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
773 SourceLocation getDefaultDSALocation() const {
774 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
776 OpenMPDefaultmapClauseModifier
777 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const {
778 return isStackEmpty()
779 ? OMPC_DEFAULTMAP_MODIFIER_unknown
780 : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior;
782 OpenMPDefaultmapClauseModifier
783 getDefaultmapModifierAtLevel(unsigned Level,
784 OpenMPDefaultmapClauseKind Kind) const {
785 return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior;
787 bool isDefaultmapCapturedByRef(unsigned Level,
788 OpenMPDefaultmapClauseKind Kind) const {
789 OpenMPDefaultmapClauseModifier M =
790 getDefaultmapModifierAtLevel(Level, Kind);
791 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
792 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
793 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
794 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
795 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom);
797 return true;
799 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
800 OpenMPDefaultmapClauseKind Kind) {
801 switch (Kind) {
802 case OMPC_DEFAULTMAP_scalar:
803 case OMPC_DEFAULTMAP_pointer:
804 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
805 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
806 (M == OMPC_DEFAULTMAP_MODIFIER_default);
807 case OMPC_DEFAULTMAP_aggregate:
808 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
809 default:
810 break;
812 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum");
814 bool mustBeFirstprivateAtLevel(unsigned Level,
815 OpenMPDefaultmapClauseKind Kind) const {
816 OpenMPDefaultmapClauseModifier M =
817 getDefaultmapModifierAtLevel(Level, Kind);
818 return mustBeFirstprivateBase(M, Kind);
820 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
821 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
822 return mustBeFirstprivateBase(M, Kind);
825 /// Checks if the specified variable is a threadprivate.
826 bool isThreadPrivate(VarDecl *D) {
827 const DSAVarData DVar = getTopDSA(D, false);
828 return isOpenMPThreadPrivate(DVar.CKind);
831 /// Marks current region as ordered (it has an 'ordered' clause).
832 void setOrderedRegion(bool IsOrdered, const Expr *Param,
833 OMPOrderedClause *Clause) {
834 if (IsOrdered)
835 getTopOfStack().OrderedRegion.emplace(Param, Clause);
836 else
837 getTopOfStack().OrderedRegion.reset();
839 /// Returns true, if region is ordered (has associated 'ordered' clause),
840 /// false - otherwise.
841 bool isOrderedRegion() const {
842 if (const SharingMapTy *Top = getTopOfStackOrNull())
843 return Top->OrderedRegion.has_value();
844 return false;
846 /// Returns optional parameter for the ordered region.
847 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
848 if (const SharingMapTy *Top = getTopOfStackOrNull())
849 if (Top->OrderedRegion)
850 return Top->OrderedRegion.value();
851 return std::make_pair(nullptr, nullptr);
853 /// Returns true, if parent region is ordered (has associated
854 /// 'ordered' clause), false - otherwise.
855 bool isParentOrderedRegion() const {
856 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
857 return Parent->OrderedRegion.has_value();
858 return false;
860 /// Returns optional parameter for the ordered region.
861 std::pair<const Expr *, OMPOrderedClause *>
862 getParentOrderedRegionParam() const {
863 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
864 if (Parent->OrderedRegion)
865 return Parent->OrderedRegion.value();
866 return std::make_pair(nullptr, nullptr);
868 /// Marks current region as nowait (it has a 'nowait' clause).
869 void setNowaitRegion(bool IsNowait = true) {
870 getTopOfStack().NowaitRegion = IsNowait;
872 /// Returns true, if parent region is nowait (has associated
873 /// 'nowait' clause), false - otherwise.
874 bool isParentNowaitRegion() const {
875 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
876 return Parent->NowaitRegion;
877 return false;
879 /// Marks current region as untied (it has a 'untied' clause).
880 void setUntiedRegion(bool IsUntied = true) {
881 getTopOfStack().UntiedRegion = IsUntied;
883 /// Return true if current region is untied.
884 bool isUntiedRegion() const {
885 const SharingMapTy *Top = getTopOfStackOrNull();
886 return Top ? Top->UntiedRegion : false;
888 /// Marks parent region as cancel region.
889 void setParentCancelRegion(bool Cancel = true) {
890 if (SharingMapTy *Parent = getSecondOnStackOrNull())
891 Parent->CancelRegion |= Cancel;
893 /// Return true if current region has inner cancel construct.
894 bool isCancelRegion() const {
895 const SharingMapTy *Top = getTopOfStackOrNull();
896 return Top ? Top->CancelRegion : false;
899 /// Mark that parent region already has scan directive.
900 void setParentHasScanDirective(SourceLocation Loc) {
901 if (SharingMapTy *Parent = getSecondOnStackOrNull())
902 Parent->PrevScanLocation = Loc;
904 /// Return true if current region has inner cancel construct.
905 bool doesParentHasScanDirective() const {
906 const SharingMapTy *Top = getSecondOnStackOrNull();
907 return Top ? Top->PrevScanLocation.isValid() : false;
909 /// Return true if current region has inner cancel construct.
910 SourceLocation getParentScanDirectiveLoc() const {
911 const SharingMapTy *Top = getSecondOnStackOrNull();
912 return Top ? Top->PrevScanLocation : SourceLocation();
914 /// Mark that parent region already has ordered directive.
915 void setParentHasOrderedDirective(SourceLocation Loc) {
916 if (SharingMapTy *Parent = getSecondOnStackOrNull())
917 Parent->PrevOrderedLocation = Loc;
919 /// Return true if current region has inner ordered construct.
920 bool doesParentHasOrderedDirective() const {
921 const SharingMapTy *Top = getSecondOnStackOrNull();
922 return Top ? Top->PrevOrderedLocation.isValid() : false;
924 /// Returns the location of the previously specified ordered directive.
925 SourceLocation getParentOrderedDirectiveLoc() const {
926 const SharingMapTy *Top = getSecondOnStackOrNull();
927 return Top ? Top->PrevOrderedLocation : SourceLocation();
930 /// Set collapse value for the region.
931 void setAssociatedLoops(unsigned Val) {
932 getTopOfStack().AssociatedLoops = Val;
933 if (Val > 1)
934 getTopOfStack().HasMutipleLoops = true;
936 /// Return collapse value for region.
937 unsigned getAssociatedLoops() const {
938 const SharingMapTy *Top = getTopOfStackOrNull();
939 return Top ? Top->AssociatedLoops : 0;
941 /// Returns true if the construct is associated with multiple loops.
942 bool hasMutipleLoops() const {
943 const SharingMapTy *Top = getTopOfStackOrNull();
944 return Top ? Top->HasMutipleLoops : false;
947 /// Marks current target region as one with closely nested teams
948 /// region.
949 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
950 if (SharingMapTy *Parent = getSecondOnStackOrNull())
951 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
953 /// Returns true, if current region has closely nested teams region.
954 bool hasInnerTeamsRegion() const {
955 return getInnerTeamsRegionLoc().isValid();
957 /// Returns location of the nested teams region (if any).
958 SourceLocation getInnerTeamsRegionLoc() const {
959 const SharingMapTy *Top = getTopOfStackOrNull();
960 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
963 Scope *getCurScope() const {
964 const SharingMapTy *Top = getTopOfStackOrNull();
965 return Top ? Top->CurScope : nullptr;
967 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
968 SourceLocation getConstructLoc() const {
969 const SharingMapTy *Top = getTopOfStackOrNull();
970 return Top ? Top->ConstructLoc : SourceLocation();
973 /// Do the check specified in \a Check to all component lists and return true
974 /// if any issue is found.
975 bool checkMappableExprComponentListsForDecl(
976 const ValueDecl *VD, bool CurrentRegionOnly,
977 const llvm::function_ref<
978 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
979 OpenMPClauseKind)>
980 Check) const {
981 if (isStackEmpty())
982 return false;
983 auto SI = begin();
984 auto SE = end();
986 if (SI == SE)
987 return false;
989 if (CurrentRegionOnly)
990 SE = std::next(SI);
991 else
992 std::advance(SI, 1);
994 for (; SI != SE; ++SI) {
995 auto MI = SI->MappedExprComponents.find(VD);
996 if (MI != SI->MappedExprComponents.end())
997 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
998 MI->second.Components)
999 if (Check(L, MI->second.Kind))
1000 return true;
1002 return false;
1005 /// Do the check specified in \a Check to all component lists at a given level
1006 /// and return true if any issue is found.
1007 bool checkMappableExprComponentListsForDeclAtLevel(
1008 const ValueDecl *VD, unsigned Level,
1009 const llvm::function_ref<
1010 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
1011 OpenMPClauseKind)>
1012 Check) const {
1013 if (getStackSize() <= Level)
1014 return false;
1016 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1017 auto MI = StackElem.MappedExprComponents.find(VD);
1018 if (MI != StackElem.MappedExprComponents.end())
1019 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
1020 MI->second.Components)
1021 if (Check(L, MI->second.Kind))
1022 return true;
1023 return false;
1026 /// Create a new mappable expression component list associated with a given
1027 /// declaration and initialize it with the provided list of components.
1028 void addMappableExpressionComponents(
1029 const ValueDecl *VD,
1030 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
1031 OpenMPClauseKind WhereFoundClauseKind) {
1032 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1033 // Create new entry and append the new components there.
1034 MEC.Components.resize(MEC.Components.size() + 1);
1035 MEC.Components.back().append(Components.begin(), Components.end());
1036 MEC.Kind = WhereFoundClauseKind;
1039 unsigned getNestingLevel() const {
1040 assert(!isStackEmpty());
1041 return getStackSize() - 1;
1043 void addDoacrossDependClause(OMPDependClause *C,
1044 const OperatorOffsetTy &OpsOffs) {
1045 SharingMapTy *Parent = getSecondOnStackOrNull();
1046 assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
1047 Parent->DoacrossDepends.try_emplace(C, OpsOffs);
1049 llvm::iterator_range<DoacrossDependMapTy::const_iterator>
1050 getDoacrossDependClauses() const {
1051 const SharingMapTy &StackElem = getTopOfStack();
1052 if (isOpenMPWorksharingDirective(StackElem.Directive)) {
1053 const DoacrossDependMapTy &Ref = StackElem.DoacrossDepends;
1054 return llvm::make_range(Ref.begin(), Ref.end());
1056 return llvm::make_range(StackElem.DoacrossDepends.end(),
1057 StackElem.DoacrossDepends.end());
1060 // Store types of classes which have been explicitly mapped
1061 void addMappedClassesQualTypes(QualType QT) {
1062 SharingMapTy &StackElem = getTopOfStack();
1063 StackElem.MappedClassesQualTypes.insert(QT);
1066 // Return set of mapped classes types
1067 bool isClassPreviouslyMapped(QualType QT) const {
1068 const SharingMapTy &StackElem = getTopOfStack();
1069 return StackElem.MappedClassesQualTypes.contains(QT);
1072 /// Adds global declare target to the parent target region.
1073 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1074 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1075 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1076 "Expected declare target link global.");
1077 for (auto &Elem : *this) {
1078 if (isOpenMPTargetExecutionDirective(Elem.Directive)) {
1079 Elem.DeclareTargetLinkVarDecls.push_back(E);
1080 return;
1085 /// Returns the list of globals with declare target link if current directive
1086 /// is target.
1087 ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1088 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
1089 "Expected target executable directive.");
1090 return getTopOfStack().DeclareTargetLinkVarDecls;
1093 /// Adds list of allocators expressions.
1094 void addInnerAllocatorExpr(Expr *E) {
1095 getTopOfStack().InnerUsedAllocators.push_back(E);
1097 /// Return list of used allocators.
1098 ArrayRef<Expr *> getInnerAllocators() const {
1099 return getTopOfStack().InnerUsedAllocators;
1101 /// Marks the declaration as implicitly firstprivate nin the task-based
1102 /// regions.
1103 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1104 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(D);
1106 /// Checks if the decl is implicitly firstprivate in the task-based region.
1107 bool isImplicitTaskFirstprivate(Decl *D) const {
1108 return getTopOfStack().ImplicitTaskFirstprivates.contains(D);
1111 /// Marks decl as used in uses_allocators clause as the allocator.
1112 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1113 getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind);
1115 /// Checks if specified decl is used in uses allocator clause as the
1116 /// allocator.
1117 Optional<UsesAllocatorsDeclKind> isUsesAllocatorsDecl(unsigned Level,
1118 const Decl *D) const {
1119 const SharingMapTy &StackElem = getTopOfStack();
1120 auto I = StackElem.UsesAllocatorsDecls.find(D);
1121 if (I == StackElem.UsesAllocatorsDecls.end())
1122 return None;
1123 return I->getSecond();
1125 Optional<UsesAllocatorsDeclKind> isUsesAllocatorsDecl(const Decl *D) const {
1126 const SharingMapTy &StackElem = getTopOfStack();
1127 auto I = StackElem.UsesAllocatorsDecls.find(D);
1128 if (I == StackElem.UsesAllocatorsDecls.end())
1129 return None;
1130 return I->getSecond();
1133 void addDeclareMapperVarRef(Expr *Ref) {
1134 SharingMapTy &StackElem = getTopOfStack();
1135 StackElem.DeclareMapperVar = Ref;
1137 const Expr *getDeclareMapperVarRef() const {
1138 const SharingMapTy *Top = getTopOfStackOrNull();
1139 return Top ? Top->DeclareMapperVar : nullptr;
1141 /// get captured field from ImplicitDefaultFirstprivateFDs
1142 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1143 const_iterator I = begin();
1144 const_iterator EndI = end();
1145 size_t StackLevel = getStackSize();
1146 for (; I != EndI; ++I) {
1147 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1148 break;
1149 StackLevel--;
1151 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1152 if (I == EndI)
1153 return nullptr;
1154 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1155 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1156 return IFD.VD;
1157 return nullptr;
1159 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
1160 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1161 const_iterator I = begin();
1162 const_iterator EndI = end();
1163 for (; I != EndI; ++I)
1164 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1165 break;
1166 if (I == EndI)
1167 return false;
1168 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1169 if (IFD.VD == VD)
1170 return true;
1171 return false;
1173 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
1174 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1175 iterator I = begin();
1176 const_iterator EndI = end();
1177 size_t StackLevel = getStackSize();
1178 for (; I != EndI; ++I) {
1179 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1180 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1181 break;
1183 StackLevel--;
1185 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1189 bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1190 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1193 bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1194 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) ||
1195 DKind == OMPD_unknown;
1198 } // namespace
1200 static const Expr *getExprAsWritten(const Expr *E) {
1201 if (const auto *FE = dyn_cast<FullExpr>(E))
1202 E = FE->getSubExpr();
1204 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
1205 E = MTE->getSubExpr();
1207 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
1208 E = Binder->getSubExpr();
1210 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
1211 E = ICE->getSubExprAsWritten();
1212 return E->IgnoreParens();
1215 static Expr *getExprAsWritten(Expr *E) {
1216 return const_cast<Expr *>(getExprAsWritten(const_cast<const Expr *>(E)));
1219 static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1220 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
1221 if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
1222 D = ME->getMemberDecl();
1223 const auto *VD = dyn_cast<VarDecl>(D);
1224 const auto *FD = dyn_cast<FieldDecl>(D);
1225 if (VD != nullptr) {
1226 VD = VD->getCanonicalDecl();
1227 D = VD;
1228 } else {
1229 assert(FD);
1230 FD = FD->getCanonicalDecl();
1231 D = FD;
1233 return D;
1236 static ValueDecl *getCanonicalDecl(ValueDecl *D) {
1237 return const_cast<ValueDecl *>(
1238 getCanonicalDecl(const_cast<const ValueDecl *>(D)));
1241 DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1242 ValueDecl *D) const {
1243 D = getCanonicalDecl(D);
1244 auto *VD = dyn_cast<VarDecl>(D);
1245 const auto *FD = dyn_cast<FieldDecl>(D);
1246 DSAVarData DVar;
1247 if (Iter == end()) {
1248 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1249 // in a region but not in construct]
1250 // File-scope or namespace-scope variables referenced in called routines
1251 // in the region are shared unless they appear in a threadprivate
1252 // directive.
1253 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD))
1254 DVar.CKind = OMPC_shared;
1256 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1257 // in a region but not in construct]
1258 // Variables with static storage duration that are declared in called
1259 // routines in the region are shared.
1260 if (VD && VD->hasGlobalStorage())
1261 DVar.CKind = OMPC_shared;
1263 // Non-static data members are shared by default.
1264 if (FD)
1265 DVar.CKind = OMPC_shared;
1267 return DVar;
1270 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1271 // in a Construct, C/C++, predetermined, p.1]
1272 // Variables with automatic storage duration that are declared in a scope
1273 // inside the construct are private.
1274 if (VD && isOpenMPLocal(VD, Iter) && VD->isLocalVarDecl() &&
1275 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1276 DVar.CKind = OMPC_private;
1277 return DVar;
1280 DVar.DKind = Iter->Directive;
1281 // Explicitly specified attributes and local variables with predetermined
1282 // attributes.
1283 if (Iter->SharingMap.count(D)) {
1284 const DSAInfo &Data = Iter->SharingMap.lookup(D);
1285 DVar.RefExpr = Data.RefExpr.getPointer();
1286 DVar.PrivateCopy = Data.PrivateCopy;
1287 DVar.CKind = Data.Attributes;
1288 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1289 DVar.Modifier = Data.Modifier;
1290 DVar.AppliedToPointee = Data.AppliedToPointee;
1291 return DVar;
1294 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1295 // in a Construct, C/C++, implicitly determined, p.1]
1296 // In a parallel or task construct, the data-sharing attributes of these
1297 // variables are determined by the default clause, if present.
1298 switch (Iter->DefaultAttr) {
1299 case DSA_shared:
1300 DVar.CKind = OMPC_shared;
1301 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1302 return DVar;
1303 case DSA_none:
1304 return DVar;
1305 case DSA_firstprivate:
1306 if (VD && VD->getStorageDuration() == SD_Static &&
1307 VD->getDeclContext()->isFileContext()) {
1308 DVar.CKind = OMPC_unknown;
1309 } else {
1310 DVar.CKind = OMPC_firstprivate;
1312 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1313 return DVar;
1314 case DSA_private:
1315 // each variable with static storage duration that is declared
1316 // in a namespace or global scope and referenced in the construct,
1317 // and that does not have a predetermined data-sharing attribute
1318 if (VD && VD->getStorageDuration() == SD_Static &&
1319 VD->getDeclContext()->isFileContext()) {
1320 DVar.CKind = OMPC_unknown;
1321 } else {
1322 DVar.CKind = OMPC_private;
1324 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1325 return DVar;
1326 case DSA_unspecified:
1327 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1328 // in a Construct, implicitly determined, p.2]
1329 // In a parallel construct, if no default clause is present, these
1330 // variables are shared.
1331 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1332 if ((isOpenMPParallelDirective(DVar.DKind) &&
1333 !isOpenMPTaskLoopDirective(DVar.DKind)) ||
1334 isOpenMPTeamsDirective(DVar.DKind)) {
1335 DVar.CKind = OMPC_shared;
1336 return DVar;
1339 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1340 // in a Construct, implicitly determined, p.4]
1341 // In a task construct, if no default clause is present, a variable that in
1342 // the enclosing context is determined to be shared by all implicit tasks
1343 // bound to the current team is shared.
1344 if (isOpenMPTaskingDirective(DVar.DKind)) {
1345 DSAVarData DVarTemp;
1346 const_iterator I = Iter, E = end();
1347 do {
1348 ++I;
1349 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1350 // Referenced in a Construct, implicitly determined, p.6]
1351 // In a task construct, if no default clause is present, a variable
1352 // whose data-sharing attribute is not determined by the rules above is
1353 // firstprivate.
1354 DVarTemp = getDSA(I, D);
1355 if (DVarTemp.CKind != OMPC_shared) {
1356 DVar.RefExpr = nullptr;
1357 DVar.CKind = OMPC_firstprivate;
1358 return DVar;
1360 } while (I != E && !isImplicitTaskingRegion(I->Directive));
1361 DVar.CKind =
1362 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1363 return DVar;
1366 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1367 // in a Construct, implicitly determined, p.3]
1368 // For constructs other than task, if no default clause is present, these
1369 // variables inherit their data-sharing attributes from the enclosing
1370 // context.
1371 return getDSA(++Iter, D);
1374 const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1375 const Expr *NewDE) {
1376 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1377 D = getCanonicalDecl(D);
1378 SharingMapTy &StackElem = getTopOfStack();
1379 auto It = StackElem.AlignedMap.find(D);
1380 if (It == StackElem.AlignedMap.end()) {
1381 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1382 StackElem.AlignedMap[D] = NewDE;
1383 return nullptr;
1385 assert(It->second && "Unexpected nullptr expr in the aligned map");
1386 return It->second;
1389 const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1390 const Expr *NewDE) {
1391 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1392 D = getCanonicalDecl(D);
1393 SharingMapTy &StackElem = getTopOfStack();
1394 auto It = StackElem.NontemporalMap.find(D);
1395 if (It == StackElem.NontemporalMap.end()) {
1396 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1397 StackElem.NontemporalMap[D] = NewDE;
1398 return nullptr;
1400 assert(It->second && "Unexpected nullptr expr in the aligned map");
1401 return It->second;
1404 void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1405 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1406 D = getCanonicalDecl(D);
1407 SharingMapTy &StackElem = getTopOfStack();
1408 StackElem.LCVMap.try_emplace(
1409 D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1412 const DSAStackTy::LCDeclInfo
1413 DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1414 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1415 D = getCanonicalDecl(D);
1416 const SharingMapTy &StackElem = getTopOfStack();
1417 auto It = StackElem.LCVMap.find(D);
1418 if (It != StackElem.LCVMap.end())
1419 return It->second;
1420 return {0, nullptr};
1423 const DSAStackTy::LCDeclInfo
1424 DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1425 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1426 D = getCanonicalDecl(D);
1427 for (unsigned I = Level + 1; I > 0; --I) {
1428 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1429 auto It = StackElem.LCVMap.find(D);
1430 if (It != StackElem.LCVMap.end())
1431 return It->second;
1433 return {0, nullptr};
1436 const DSAStackTy::LCDeclInfo
1437 DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1438 const SharingMapTy *Parent = getSecondOnStackOrNull();
1439 assert(Parent && "Data-sharing attributes stack is empty");
1440 D = getCanonicalDecl(D);
1441 auto It = Parent->LCVMap.find(D);
1442 if (It != Parent->LCVMap.end())
1443 return It->second;
1444 return {0, nullptr};
1447 const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1448 const SharingMapTy *Parent = getSecondOnStackOrNull();
1449 assert(Parent && "Data-sharing attributes stack is empty");
1450 if (Parent->LCVMap.size() < I)
1451 return nullptr;
1452 for (const auto &Pair : Parent->LCVMap)
1453 if (Pair.second.first == I)
1454 return Pair.first;
1455 return nullptr;
1458 void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1459 DeclRefExpr *PrivateCopy, unsigned Modifier,
1460 bool AppliedToPointee) {
1461 D = getCanonicalDecl(D);
1462 if (A == OMPC_threadprivate) {
1463 DSAInfo &Data = Threadprivates[D];
1464 Data.Attributes = A;
1465 Data.RefExpr.setPointer(E);
1466 Data.PrivateCopy = nullptr;
1467 Data.Modifier = Modifier;
1468 } else {
1469 DSAInfo &Data = getTopOfStack().SharingMap[D];
1470 assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1471 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1472 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1473 (isLoopControlVariable(D).first && A == OMPC_private));
1474 Data.Modifier = Modifier;
1475 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1476 Data.RefExpr.setInt(/*IntVal=*/true);
1477 return;
1479 const bool IsLastprivate =
1480 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1481 Data.Attributes = A;
1482 Data.RefExpr.setPointerAndInt(E, IsLastprivate);
1483 Data.PrivateCopy = PrivateCopy;
1484 Data.AppliedToPointee = AppliedToPointee;
1485 if (PrivateCopy) {
1486 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1487 Data.Modifier = Modifier;
1488 Data.Attributes = A;
1489 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1490 Data.PrivateCopy = nullptr;
1491 Data.AppliedToPointee = AppliedToPointee;
1496 /// Build a variable declaration for OpenMP loop iteration variable.
1497 static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type,
1498 StringRef Name, const AttrVec *Attrs = nullptr,
1499 DeclRefExpr *OrigRef = nullptr) {
1500 DeclContext *DC = SemaRef.CurContext;
1501 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1502 TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
1503 auto *Decl =
1504 VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
1505 if (Attrs) {
1506 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1507 I != E; ++I)
1508 Decl->addAttr(*I);
1510 Decl->setImplicit();
1511 if (OrigRef) {
1512 Decl->addAttr(
1513 OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef));
1515 return Decl;
1518 static DeclRefExpr *buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty,
1519 SourceLocation Loc,
1520 bool RefersToCapture = false) {
1521 D->setReferenced();
1522 D->markUsed(S.Context);
1523 return DeclRefExpr::Create(S.getASTContext(), NestedNameSpecifierLoc(),
1524 SourceLocation(), D, RefersToCapture, Loc, Ty,
1525 VK_LValue);
1528 void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1529 BinaryOperatorKind BOK) {
1530 D = getCanonicalDecl(D);
1531 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1532 assert(
1533 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1534 "Additional reduction info may be specified only for reduction items.");
1535 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1536 assert(ReductionData.ReductionRange.isInvalid() &&
1537 (getTopOfStack().Directive == OMPD_taskgroup ||
1538 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1539 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1540 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1541 "Additional reduction info may be specified only once for reduction "
1542 "items.");
1543 ReductionData.set(BOK, SR);
1544 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1545 if (!TaskgroupReductionRef) {
1546 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1547 SemaRef.Context.VoidPtrTy, ".task_red.");
1548 TaskgroupReductionRef =
1549 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1553 void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1554 const Expr *ReductionRef) {
1555 D = getCanonicalDecl(D);
1556 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1557 assert(
1558 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1559 "Additional reduction info may be specified only for reduction items.");
1560 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1561 assert(ReductionData.ReductionRange.isInvalid() &&
1562 (getTopOfStack().Directive == OMPD_taskgroup ||
1563 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1564 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1565 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1566 "Additional reduction info may be specified only once for reduction "
1567 "items.");
1568 ReductionData.set(ReductionRef, SR);
1569 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1570 if (!TaskgroupReductionRef) {
1571 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1572 SemaRef.Context.VoidPtrTy, ".task_red.");
1573 TaskgroupReductionRef =
1574 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1578 const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1579 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1580 Expr *&TaskgroupDescriptor) const {
1581 D = getCanonicalDecl(D);
1582 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1583 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1584 const DSAInfo &Data = I->SharingMap.lookup(D);
1585 if (Data.Attributes != OMPC_reduction ||
1586 Data.Modifier != OMPC_REDUCTION_task)
1587 continue;
1588 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1589 if (!ReductionData.ReductionOp ||
1590 ReductionData.ReductionOp.is<const Expr *>())
1591 return DSAVarData();
1592 SR = ReductionData.ReductionRange;
1593 BOK = ReductionData.ReductionOp.get<ReductionData::BOKPtrType>();
1594 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1595 "expression for the descriptor is not "
1596 "set.");
1597 TaskgroupDescriptor = I->TaskgroupReductionRef;
1598 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1599 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1600 /*AppliedToPointee=*/false);
1602 return DSAVarData();
1605 const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1606 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1607 Expr *&TaskgroupDescriptor) const {
1608 D = getCanonicalDecl(D);
1609 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1610 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1611 const DSAInfo &Data = I->SharingMap.lookup(D);
1612 if (Data.Attributes != OMPC_reduction ||
1613 Data.Modifier != OMPC_REDUCTION_task)
1614 continue;
1615 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1616 if (!ReductionData.ReductionOp ||
1617 !ReductionData.ReductionOp.is<const Expr *>())
1618 return DSAVarData();
1619 SR = ReductionData.ReductionRange;
1620 ReductionRef = ReductionData.ReductionOp.get<const Expr *>();
1621 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1622 "expression for the descriptor is not "
1623 "set.");
1624 TaskgroupDescriptor = I->TaskgroupReductionRef;
1625 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1626 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1627 /*AppliedToPointee=*/false);
1629 return DSAVarData();
1632 bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1633 D = D->getCanonicalDecl();
1634 for (const_iterator E = end(); I != E; ++I) {
1635 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1636 isOpenMPTargetExecutionDirective(I->Directive)) {
1637 if (I->CurScope) {
1638 Scope *TopScope = I->CurScope->getParent();
1639 Scope *CurScope = getCurScope();
1640 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1641 CurScope = CurScope->getParent();
1642 return CurScope != TopScope;
1644 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1645 if (I->Context == DC)
1646 return true;
1647 return false;
1650 return false;
1653 static bool isConstNotMutableType(Sema &SemaRef, QualType Type,
1654 bool AcceptIfMutable = true,
1655 bool *IsClassType = nullptr) {
1656 ASTContext &Context = SemaRef.getASTContext();
1657 Type = Type.getNonReferenceType().getCanonicalType();
1658 bool IsConstant = Type.isConstant(Context);
1659 Type = Context.getBaseElementType(Type);
1660 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1661 ? Type->getAsCXXRecordDecl()
1662 : nullptr;
1663 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1664 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1665 RD = CTD->getTemplatedDecl();
1666 if (IsClassType)
1667 *IsClassType = RD;
1668 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1669 RD->hasDefinition() && RD->hasMutableFields());
1672 static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1673 QualType Type, OpenMPClauseKind CKind,
1674 SourceLocation ELoc,
1675 bool AcceptIfMutable = true,
1676 bool ListItemNotVar = false) {
1677 ASTContext &Context = SemaRef.getASTContext();
1678 bool IsClassType;
1679 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, &IsClassType)) {
1680 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1681 : IsClassType ? diag::err_omp_const_not_mutable_variable
1682 : diag::err_omp_const_variable;
1683 SemaRef.Diag(ELoc, Diag) << getOpenMPClauseName(CKind);
1684 if (!ListItemNotVar && D) {
1685 const VarDecl *VD = dyn_cast<VarDecl>(D);
1686 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1687 VarDecl::DeclarationOnly;
1688 SemaRef.Diag(D->getLocation(),
1689 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1690 << D;
1692 return true;
1694 return false;
1697 const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1698 bool FromParent) {
1699 D = getCanonicalDecl(D);
1700 DSAVarData DVar;
1702 auto *VD = dyn_cast<VarDecl>(D);
1703 auto TI = Threadprivates.find(D);
1704 if (TI != Threadprivates.end()) {
1705 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1706 DVar.CKind = OMPC_threadprivate;
1707 DVar.Modifier = TI->getSecond().Modifier;
1708 return DVar;
1710 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1711 DVar.RefExpr = buildDeclRefExpr(
1712 SemaRef, VD, D->getType().getNonReferenceType(),
1713 VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1714 DVar.CKind = OMPC_threadprivate;
1715 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1716 return DVar;
1718 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1719 // in a Construct, C/C++, predetermined, p.1]
1720 // Variables appearing in threadprivate directives are threadprivate.
1721 if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1722 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1723 SemaRef.getLangOpts().OpenMPUseTLS &&
1724 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1725 (VD && VD->getStorageClass() == SC_Register &&
1726 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1727 DVar.RefExpr = buildDeclRefExpr(
1728 SemaRef, VD, D->getType().getNonReferenceType(), D->getLocation());
1729 DVar.CKind = OMPC_threadprivate;
1730 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1731 return DVar;
1733 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1734 VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1735 !isLoopControlVariable(D).first) {
1736 const_iterator IterTarget =
1737 std::find_if(begin(), end(), [](const SharingMapTy &Data) {
1738 return isOpenMPTargetExecutionDirective(Data.Directive);
1740 if (IterTarget != end()) {
1741 const_iterator ParentIterTarget = IterTarget + 1;
1742 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1743 if (isOpenMPLocal(VD, Iter)) {
1744 DVar.RefExpr =
1745 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1746 D->getLocation());
1747 DVar.CKind = OMPC_threadprivate;
1748 return DVar;
1751 if (!isClauseParsingMode() || IterTarget != begin()) {
1752 auto DSAIter = IterTarget->SharingMap.find(D);
1753 if (DSAIter != IterTarget->SharingMap.end() &&
1754 isOpenMPPrivate(DSAIter->getSecond().Attributes)) {
1755 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1756 DVar.CKind = OMPC_threadprivate;
1757 return DVar;
1759 const_iterator End = end();
1760 if (!SemaRef.isOpenMPCapturedByRef(D,
1761 std::distance(ParentIterTarget, End),
1762 /*OpenMPCaptureLevel=*/0)) {
1763 DVar.RefExpr =
1764 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1765 IterTarget->ConstructLoc);
1766 DVar.CKind = OMPC_threadprivate;
1767 return DVar;
1773 if (isStackEmpty())
1774 // Not in OpenMP execution region and top scope was already checked.
1775 return DVar;
1777 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1778 // in a Construct, C/C++, predetermined, p.4]
1779 // Static data members are shared.
1780 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1781 // in a Construct, C/C++, predetermined, p.7]
1782 // Variables with static storage duration that are declared in a scope
1783 // inside the construct are shared.
1784 if (VD && VD->isStaticDataMember()) {
1785 // Check for explicitly specified attributes.
1786 const_iterator I = begin();
1787 const_iterator EndI = end();
1788 if (FromParent && I != EndI)
1789 ++I;
1790 if (I != EndI) {
1791 auto It = I->SharingMap.find(D);
1792 if (It != I->SharingMap.end()) {
1793 const DSAInfo &Data = It->getSecond();
1794 DVar.RefExpr = Data.RefExpr.getPointer();
1795 DVar.PrivateCopy = Data.PrivateCopy;
1796 DVar.CKind = Data.Attributes;
1797 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1798 DVar.DKind = I->Directive;
1799 DVar.Modifier = Data.Modifier;
1800 DVar.AppliedToPointee = Data.AppliedToPointee;
1801 return DVar;
1805 DVar.CKind = OMPC_shared;
1806 return DVar;
1809 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1810 // The predetermined shared attribute for const-qualified types having no
1811 // mutable members was removed after OpenMP 3.1.
1812 if (SemaRef.LangOpts.OpenMP <= 31) {
1813 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1814 // in a Construct, C/C++, predetermined, p.6]
1815 // Variables with const qualified type having no mutable member are
1816 // shared.
1817 if (isConstNotMutableType(SemaRef, D->getType())) {
1818 // Variables with const-qualified type having no mutable member may be
1819 // listed in a firstprivate clause, even if they are static data members.
1820 DSAVarData DVarTemp = hasInnermostDSA(
1822 [](OpenMPClauseKind C, bool) {
1823 return C == OMPC_firstprivate || C == OMPC_shared;
1825 MatchesAlways, FromParent);
1826 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1827 return DVarTemp;
1829 DVar.CKind = OMPC_shared;
1830 return DVar;
1834 // Explicitly specified attributes and local variables with predetermined
1835 // attributes.
1836 const_iterator I = begin();
1837 const_iterator EndI = end();
1838 if (FromParent && I != EndI)
1839 ++I;
1840 if (I == EndI)
1841 return DVar;
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;
1854 return DVar;
1857 const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1858 bool FromParent) const {
1859 if (isStackEmpty()) {
1860 const_iterator I;
1861 return getDSA(I, D);
1863 D = getCanonicalDecl(D);
1864 const_iterator StartI = begin();
1865 const_iterator EndI = end();
1866 if (FromParent && StartI != EndI)
1867 ++StartI;
1868 return getDSA(StartI, D);
1871 const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1872 unsigned Level) const {
1873 if (getStackSize() <= Level)
1874 return DSAVarData();
1875 D = getCanonicalDecl(D);
1876 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
1877 return getDSA(StartI, D);
1880 const DSAStackTy::DSAVarData
1881 DSAStackTy::hasDSA(ValueDecl *D,
1882 const llvm::function_ref<bool(OpenMPClauseKind, bool,
1883 DefaultDataSharingAttributes)>
1884 CPred,
1885 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1886 bool FromParent) const {
1887 if (isStackEmpty())
1888 return {};
1889 D = getCanonicalDecl(D);
1890 const_iterator I = begin();
1891 const_iterator EndI = end();
1892 if (FromParent && I != EndI)
1893 ++I;
1894 for (; I != EndI; ++I) {
1895 if (!DPred(I->Directive) &&
1896 !isImplicitOrExplicitTaskingRegion(I->Directive))
1897 continue;
1898 const_iterator NewI = I;
1899 DSAVarData DVar = getDSA(NewI, D);
1900 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1901 return DVar;
1903 return {};
1906 const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1907 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1908 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1909 bool FromParent) const {
1910 if (isStackEmpty())
1911 return {};
1912 D = getCanonicalDecl(D);
1913 const_iterator StartI = begin();
1914 const_iterator EndI = end();
1915 if (FromParent && StartI != EndI)
1916 ++StartI;
1917 if (StartI == EndI || !DPred(StartI->Directive))
1918 return {};
1919 const_iterator NewI = StartI;
1920 DSAVarData DVar = getDSA(NewI, D);
1921 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
1922 ? DVar
1923 : DSAVarData();
1926 bool DSAStackTy::hasExplicitDSA(
1927 const ValueDecl *D,
1928 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1929 unsigned Level, bool NotLastprivate) const {
1930 if (getStackSize() <= Level)
1931 return false;
1932 D = getCanonicalDecl(D);
1933 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1934 auto I = StackElem.SharingMap.find(D);
1935 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
1936 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
1937 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
1938 return true;
1939 // Check predetermined rules for the loop control variables.
1940 auto LI = StackElem.LCVMap.find(D);
1941 if (LI != StackElem.LCVMap.end())
1942 return CPred(OMPC_private, /*AppliedToPointee=*/false);
1943 return false;
1946 bool DSAStackTy::hasExplicitDirective(
1947 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1948 unsigned Level) const {
1949 if (getStackSize() <= Level)
1950 return false;
1951 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1952 return DPred(StackElem.Directive);
1955 bool DSAStackTy::hasDirective(
1956 const llvm::function_ref<bool(OpenMPDirectiveKind,
1957 const DeclarationNameInfo &, SourceLocation)>
1958 DPred,
1959 bool FromParent) const {
1960 // We look only in the enclosing region.
1961 size_t Skip = FromParent ? 2 : 1;
1962 for (const_iterator I = begin() + std::min(Skip, getStackSize()), E = end();
1963 I != E; ++I) {
1964 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
1965 return true;
1967 return false;
1970 void Sema::InitDataSharingAttributesStack() {
1971 VarDataSharingAttributesStack = new DSAStackTy(*this);
1974 #define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
1976 void Sema::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); }
1978 void Sema::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
1979 DSAStack->popFunction(OldFSI);
1982 static bool isOpenMPDeviceDelayedContext(Sema &S) {
1983 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsDevice &&
1984 "Expected OpenMP device compilation.");
1985 return !S.isInOpenMPTargetExecutionDirective();
1988 namespace {
1989 /// Status of the function emission on the host/device.
1990 enum class FunctionEmissionStatus {
1991 Emitted,
1992 Discarded,
1993 Unknown,
1995 } // anonymous namespace
1997 Sema::SemaDiagnosticBuilder Sema::diagIfOpenMPDeviceCode(SourceLocation Loc,
1998 unsigned DiagID,
1999 FunctionDecl *FD) {
2000 assert(LangOpts.OpenMP && LangOpts.OpenMPIsDevice &&
2001 "Expected OpenMP device compilation.");
2003 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2004 if (FD) {
2005 FunctionEmissionStatus FES = getEmissionStatus(FD);
2006 switch (FES) {
2007 case FunctionEmissionStatus::Emitted:
2008 Kind = SemaDiagnosticBuilder::K_Immediate;
2009 break;
2010 case FunctionEmissionStatus::Unknown:
2011 // TODO: We should always delay diagnostics here in case a target
2012 // region is in a function we do not emit. However, as the
2013 // current diagnostics are associated with the function containing
2014 // the target region and we do not emit that one, we would miss out
2015 // on diagnostics for the target region itself. We need to anchor
2016 // the diagnostics with the new generated function *or* ensure we
2017 // emit diagnostics associated with the surrounding function.
2018 Kind = isOpenMPDeviceDelayedContext(*this)
2019 ? SemaDiagnosticBuilder::K_Deferred
2020 : SemaDiagnosticBuilder::K_Immediate;
2021 break;
2022 case FunctionEmissionStatus::TemplateDiscarded:
2023 case FunctionEmissionStatus::OMPDiscarded:
2024 Kind = SemaDiagnosticBuilder::K_Nop;
2025 break;
2026 case FunctionEmissionStatus::CUDADiscarded:
2027 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2028 break;
2032 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, *this);
2035 Sema::SemaDiagnosticBuilder Sema::diagIfOpenMPHostCode(SourceLocation Loc,
2036 unsigned DiagID,
2037 FunctionDecl *FD) {
2038 assert(LangOpts.OpenMP && !LangOpts.OpenMPIsDevice &&
2039 "Expected OpenMP host compilation.");
2041 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2042 if (FD) {
2043 FunctionEmissionStatus FES = getEmissionStatus(FD);
2044 switch (FES) {
2045 case FunctionEmissionStatus::Emitted:
2046 Kind = SemaDiagnosticBuilder::K_Immediate;
2047 break;
2048 case FunctionEmissionStatus::Unknown:
2049 Kind = SemaDiagnosticBuilder::K_Deferred;
2050 break;
2051 case FunctionEmissionStatus::TemplateDiscarded:
2052 case FunctionEmissionStatus::OMPDiscarded:
2053 case FunctionEmissionStatus::CUDADiscarded:
2054 Kind = SemaDiagnosticBuilder::K_Nop;
2055 break;
2059 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, *this);
2062 static OpenMPDefaultmapClauseKind
2063 getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD) {
2064 if (LO.OpenMP <= 45) {
2065 if (VD->getType().getNonReferenceType()->isScalarType())
2066 return OMPC_DEFAULTMAP_scalar;
2067 return OMPC_DEFAULTMAP_aggregate;
2069 if (VD->getType().getNonReferenceType()->isAnyPointerType())
2070 return OMPC_DEFAULTMAP_pointer;
2071 if (VD->getType().getNonReferenceType()->isScalarType())
2072 return OMPC_DEFAULTMAP_scalar;
2073 return OMPC_DEFAULTMAP_aggregate;
2076 bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
2077 unsigned OpenMPCaptureLevel) const {
2078 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2080 ASTContext &Ctx = getASTContext();
2081 bool IsByRef = true;
2083 // Find the directive that is associated with the provided scope.
2084 D = cast<ValueDecl>(D->getCanonicalDecl());
2085 QualType Ty = D->getType();
2087 bool IsVariableUsedInMapClause = false;
2088 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) {
2089 // This table summarizes how a given variable should be passed to the device
2090 // given its type and the clauses where it appears. This table is based on
2091 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2092 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2094 // =========================================================================
2095 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2096 // | |(tofrom:scalar)| | pvt | | | |
2097 // =========================================================================
2098 // | scl | | | | - | | bycopy|
2099 // | scl | | - | x | - | - | bycopy|
2100 // | scl | | x | - | - | - | null |
2101 // | scl | x | | | - | | byref |
2102 // | scl | x | - | x | - | - | bycopy|
2103 // | scl | x | x | - | - | - | null |
2104 // | scl | | - | - | - | x | byref |
2105 // | scl | x | - | - | - | x | byref |
2107 // | agg | n.a. | | | - | | byref |
2108 // | agg | n.a. | - | x | - | - | byref |
2109 // | agg | n.a. | x | - | - | - | null |
2110 // | agg | n.a. | - | - | - | x | byref |
2111 // | agg | n.a. | - | - | - | x[] | byref |
2113 // | ptr | n.a. | | | - | | bycopy|
2114 // | ptr | n.a. | - | x | - | - | bycopy|
2115 // | ptr | n.a. | x | - | - | - | null |
2116 // | ptr | n.a. | - | - | - | x | byref |
2117 // | ptr | n.a. | - | - | - | x[] | bycopy|
2118 // | ptr | n.a. | - | - | x | | bycopy|
2119 // | ptr | n.a. | - | - | x | x | bycopy|
2120 // | ptr | n.a. | - | - | x | x[] | bycopy|
2121 // =========================================================================
2122 // Legend:
2123 // scl - scalar
2124 // ptr - pointer
2125 // agg - aggregate
2126 // x - applies
2127 // - - invalid in this combination
2128 // [] - mapped with an array section
2129 // byref - should be mapped by reference
2130 // byval - should be mapped by value
2131 // null - initialize a local variable to null on the device
2133 // Observations:
2134 // - All scalar declarations that show up in a map clause have to be passed
2135 // by reference, because they may have been mapped in the enclosing data
2136 // environment.
2137 // - If the scalar value does not fit the size of uintptr, it has to be
2138 // passed by reference, regardless the result in the table above.
2139 // - For pointers mapped by value that have either an implicit map or an
2140 // array section, the runtime library may pass the NULL value to the
2141 // device instead of the value passed to it by the compiler.
2143 if (Ty->isReferenceType())
2144 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2146 // Locate map clauses and see if the variable being captured is referred to
2147 // in any of those clauses. Here we only care about variables, not fields,
2148 // because fields are part of aggregates.
2149 bool IsVariableAssociatedWithSection = false;
2151 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2152 D, Level,
2153 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2154 D](OMPClauseMappableExprCommon::MappableExprComponentListRef
2155 MapExprComponents,
2156 OpenMPClauseKind WhereFoundClauseKind) {
2157 // Only the map clause information influences how a variable is
2158 // captured. E.g. is_device_ptr does not require changing the default
2159 // behavior.
2160 if (WhereFoundClauseKind != OMPC_map)
2161 return false;
2163 auto EI = MapExprComponents.rbegin();
2164 auto EE = MapExprComponents.rend();
2166 assert(EI != EE && "Invalid map expression!");
2168 if (isa<DeclRefExpr>(EI->getAssociatedExpression()))
2169 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D;
2171 ++EI;
2172 if (EI == EE)
2173 return false;
2175 if (isa<ArraySubscriptExpr>(EI->getAssociatedExpression()) ||
2176 isa<OMPArraySectionExpr>(EI->getAssociatedExpression()) ||
2177 isa<MemberExpr>(EI->getAssociatedExpression()) ||
2178 isa<OMPArrayShapingExpr>(EI->getAssociatedExpression())) {
2179 IsVariableAssociatedWithSection = true;
2180 // There is nothing more we need to know about this variable.
2181 return true;
2184 // Keep looking for more map info.
2185 return false;
2188 if (IsVariableUsedInMapClause) {
2189 // If variable is identified in a map clause it is always captured by
2190 // reference except if it is a pointer that is dereferenced somehow.
2191 IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2192 } else {
2193 // By default, all the data that has a scalar type is mapped by copy
2194 // (except for reduction variables).
2195 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2196 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2197 !Ty->isAnyPointerType()) ||
2198 !Ty->isScalarType() ||
2199 DSAStack->isDefaultmapCapturedByRef(
2200 Level, getVariableCategoryFromDecl(LangOpts, D)) ||
2201 DSAStack->hasExplicitDSA(
2203 [](OpenMPClauseKind K, bool AppliedToPointee) {
2204 return K == OMPC_reduction && !AppliedToPointee;
2206 Level);
2210 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2211 IsByRef =
2212 ((IsVariableUsedInMapClause &&
2213 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2214 OMPD_target) ||
2215 !(DSAStack->hasExplicitDSA(
2217 [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2218 return K == OMPC_firstprivate ||
2219 (K == OMPC_reduction && AppliedToPointee);
2221 Level, /*NotLastprivate=*/true) ||
2222 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2223 // If the variable is artificial and must be captured by value - try to
2224 // capture by value.
2225 !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2226 !cast<OMPCapturedExprDecl>(D)->getInit()->isGLValue()) &&
2227 // If the variable is implicitly firstprivate and scalar - capture by
2228 // copy
2229 !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2230 DSAStack->getDefaultDSA() == DSA_private) &&
2231 !DSAStack->hasExplicitDSA(
2232 D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2233 Level) &&
2234 !DSAStack->isLoopControlVariable(D, Level).first);
2237 // When passing data by copy, we need to make sure it fits the uintptr size
2238 // and alignment, because the runtime library only deals with uintptr types.
2239 // If it does not fit the uintptr size, we need to pass the data by reference
2240 // instead.
2241 if (!IsByRef &&
2242 (Ctx.getTypeSizeInChars(Ty) >
2243 Ctx.getTypeSizeInChars(Ctx.getUIntPtrType()) ||
2244 Ctx.getDeclAlign(D) > Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) {
2245 IsByRef = true;
2248 return IsByRef;
2251 unsigned Sema::getOpenMPNestingLevel() const {
2252 assert(getLangOpts().OpenMP);
2253 return DSAStack->getNestingLevel();
2256 bool Sema::isInOpenMPTaskUntiedContext() const {
2257 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2258 DSAStack->isUntiedRegion();
2261 bool Sema::isInOpenMPTargetExecutionDirective() const {
2262 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2263 !DSAStack->isClauseParsingMode()) ||
2264 DSAStack->hasDirective(
2265 [](OpenMPDirectiveKind K, const DeclarationNameInfo &,
2266 SourceLocation) -> bool {
2267 return isOpenMPTargetExecutionDirective(K);
2269 false);
2272 bool Sema::isOpenMPRebuildMemberExpr(ValueDecl *D) {
2273 // Only rebuild for Field.
2274 if (!dyn_cast<FieldDecl>(D))
2275 return false;
2276 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2278 [](OpenMPClauseKind C, bool AppliedToPointee,
2279 DefaultDataSharingAttributes DefaultAttr) {
2280 return isOpenMPPrivate(C) && !AppliedToPointee &&
2281 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2283 [](OpenMPDirectiveKind) { return true; },
2284 DSAStack->isClauseParsingMode());
2285 if (DVarPrivate.CKind != OMPC_unknown)
2286 return true;
2287 return false;
2290 static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
2291 Expr *CaptureExpr, bool WithInit,
2292 DeclContext *CurContext,
2293 bool AsExpression);
2295 VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo,
2296 unsigned StopAt) {
2297 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2298 D = getCanonicalDecl(D);
2300 auto *VD = dyn_cast<VarDecl>(D);
2301 // Do not capture constexpr variables.
2302 if (VD && VD->isConstexpr())
2303 return nullptr;
2305 // If we want to determine whether the variable should be captured from the
2306 // perspective of the current capturing scope, and we've already left all the
2307 // capturing scopes of the top directive on the stack, check from the
2308 // perspective of its parent directive (if any) instead.
2309 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2310 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2312 // If we are attempting to capture a global variable in a directive with
2313 // 'target' we return true so that this global is also mapped to the device.
2315 if (VD && !VD->hasLocalStorage() &&
2316 (getCurCapturedRegion() || getCurBlock() || getCurLambda())) {
2317 if (isInOpenMPTargetExecutionDirective()) {
2318 DSAStackTy::DSAVarData DVarTop =
2319 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2320 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2321 return VD;
2322 // If the declaration is enclosed in a 'declare target' directive,
2323 // then it should not be captured.
2325 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2326 return nullptr;
2327 CapturedRegionScopeInfo *CSI = nullptr;
2328 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2329 llvm::reverse(FunctionScopes),
2330 CheckScopeInfo ? (FunctionScopes.size() - (StopAt + 1)) : 0)) {
2331 if (!isa<CapturingScopeInfo>(FSI))
2332 return nullptr;
2333 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2334 if (RSI->CapRegionKind == CR_OpenMP) {
2335 CSI = RSI;
2336 break;
2339 assert(CSI && "Failed to find CapturedRegionScopeInfo");
2340 SmallVector<OpenMPDirectiveKind, 4> Regions;
2341 getOpenMPCaptureRegions(Regions,
2342 DSAStack->getDirective(CSI->OpenMPLevel));
2343 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2344 return VD;
2346 if (isInOpenMPDeclareTargetContext()) {
2347 // Try to mark variable as declare target if it is used in capturing
2348 // regions.
2349 if (LangOpts.OpenMP <= 45 &&
2350 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2351 checkDeclIsAllowedInOpenMPTarget(nullptr, VD);
2352 return nullptr;
2356 if (CheckScopeInfo) {
2357 bool OpenMPFound = false;
2358 for (unsigned I = StopAt + 1; I > 0; --I) {
2359 FunctionScopeInfo *FSI = FunctionScopes[I - 1];
2360 if (!isa<CapturingScopeInfo>(FSI))
2361 return nullptr;
2362 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2363 if (RSI->CapRegionKind == CR_OpenMP) {
2364 OpenMPFound = true;
2365 break;
2368 if (!OpenMPFound)
2369 return nullptr;
2372 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2373 (!DSAStack->isClauseParsingMode() ||
2374 DSAStack->getParentDirective() != OMPD_unknown)) {
2375 auto &&Info = DSAStack->isLoopControlVariable(D);
2376 if (Info.first ||
2377 (VD && VD->hasLocalStorage() &&
2378 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2379 (VD && DSAStack->isForceVarCapturing()))
2380 return VD ? VD : Info.second;
2381 DSAStackTy::DSAVarData DVarTop =
2382 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2383 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) &&
2384 (!VD || VD->hasLocalStorage() || !DVarTop.AppliedToPointee))
2385 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2386 // Threadprivate variables must not be captured.
2387 if (isOpenMPThreadPrivate(DVarTop.CKind))
2388 return nullptr;
2389 // The variable is not private or it is the variable in the directive with
2390 // default(none) clause and not used in any clause.
2391 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2393 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2394 return isOpenMPPrivate(C) && !AppliedToPointee;
2396 [](OpenMPDirectiveKind) { return true; },
2397 DSAStack->isClauseParsingMode());
2398 // Global shared must not be captured.
2399 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2400 ((DSAStack->getDefaultDSA() != DSA_none &&
2401 DSAStack->getDefaultDSA() != DSA_private &&
2402 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2403 DVarTop.CKind == OMPC_shared))
2404 return nullptr;
2405 auto *FD = dyn_cast<FieldDecl>(D);
2406 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2407 !DVarPrivate.PrivateCopy) {
2408 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2410 [](OpenMPClauseKind C, bool AppliedToPointee,
2411 DefaultDataSharingAttributes DefaultAttr) {
2412 return isOpenMPPrivate(C) && !AppliedToPointee &&
2413 (DefaultAttr == DSA_firstprivate ||
2414 DefaultAttr == DSA_private);
2416 [](OpenMPDirectiveKind) { return true; },
2417 DSAStack->isClauseParsingMode());
2418 if (DVarPrivate.CKind == OMPC_unknown)
2419 return nullptr;
2421 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2422 if (VD)
2423 return VD;
2424 if (getCurrentThisType().isNull())
2425 return nullptr;
2426 Expr *ThisExpr = BuildCXXThisExpr(SourceLocation(), getCurrentThisType(),
2427 /*IsImplicit=*/true);
2428 const CXXScopeSpec CS = CXXScopeSpec();
2429 Expr *ME = BuildMemberExpr(ThisExpr, /*IsArrow=*/true, SourceLocation(),
2430 NestedNameSpecifierLoc(), SourceLocation(), FD,
2431 DeclAccessPair::make(FD, FD->getAccess()),
2432 /*HadMultipleCandidates=*/false,
2433 DeclarationNameInfo(), FD->getType(),
2434 VK_LValue, OK_Ordinary);
2435 OMPCapturedExprDecl *CD = buildCaptureDecl(
2436 *this, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private,
2437 CurContext->getParent(), /*AsExpression=*/false);
2438 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2439 *this, CD, CD->getType().getNonReferenceType(), SourceLocation());
2440 VD = cast<VarDecl>(VDPrivateRefExpr->getDecl());
2441 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2442 return VD;
2444 if (DVarPrivate.CKind != OMPC_unknown ||
2445 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2446 DSAStack->getDefaultDSA() == DSA_private ||
2447 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2448 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2450 return nullptr;
2453 void Sema::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2454 unsigned Level) const {
2455 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2458 void Sema::startOpenMPLoop() {
2459 assert(LangOpts.OpenMP && "OpenMP must be enabled.");
2460 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2461 DSAStack->loopInit();
2464 void Sema::startOpenMPCXXRangeFor() {
2465 assert(LangOpts.OpenMP && "OpenMP must be enabled.");
2466 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2467 DSAStack->resetPossibleLoopCounter();
2468 DSAStack->loopStart();
2472 OpenMPClauseKind Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level,
2473 unsigned CapLevel) const {
2474 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2475 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2476 (!DSAStack->isClauseParsingMode() ||
2477 DSAStack->getParentDirective() != OMPD_unknown)) {
2478 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2480 [](OpenMPClauseKind C, bool AppliedToPointee,
2481 DefaultDataSharingAttributes DefaultAttr) {
2482 return isOpenMPPrivate(C) && !AppliedToPointee &&
2483 DefaultAttr == DSA_private;
2485 [](OpenMPDirectiveKind) { return true; },
2486 DSAStack->isClauseParsingMode());
2487 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) &&
2488 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) &&
2489 !DSAStack->isLoopControlVariable(D).first)
2490 return OMPC_private;
2492 if (DSAStack->hasExplicitDirective(isOpenMPTaskingDirective, Level)) {
2493 bool IsTriviallyCopyable =
2494 D->getType().getNonReferenceType().isTriviallyCopyableType(Context) &&
2495 !D->getType()
2496 .getNonReferenceType()
2497 .getCanonicalType()
2498 ->getAsCXXRecordDecl();
2499 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2500 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
2501 getOpenMPCaptureRegions(CaptureRegions, DKind);
2502 if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) &&
2503 (IsTriviallyCopyable ||
2504 !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) {
2505 if (DSAStack->hasExplicitDSA(
2507 [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2508 Level, /*NotLastprivate=*/true))
2509 return OMPC_firstprivate;
2510 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2511 if (DVar.CKind != OMPC_shared &&
2512 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2513 DSAStack->addImplicitTaskFirstprivate(Level, D);
2514 return OMPC_firstprivate;
2518 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2519 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2520 DSAStack->resetPossibleLoopCounter(D);
2521 DSAStack->loopStart();
2522 return OMPC_private;
2524 if ((DSAStack->getPossiblyLoopCunter() == D->getCanonicalDecl() ||
2525 DSAStack->isLoopControlVariable(D).first) &&
2526 !DSAStack->hasExplicitDSA(
2527 D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2528 Level) &&
2529 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2530 return OMPC_private;
2532 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2533 if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
2534 DSAStack->isForceVarCapturing() &&
2535 !DSAStack->hasExplicitDSA(
2536 D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2537 Level))
2538 return OMPC_private;
2540 // User-defined allocators are private since they must be defined in the
2541 // context of target region.
2542 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) &&
2543 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2544 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2545 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2546 return OMPC_private;
2547 return (DSAStack->hasExplicitDSA(
2548 D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2549 Level) ||
2550 (DSAStack->isClauseParsingMode() &&
2551 DSAStack->getClauseParsingMode() == OMPC_private) ||
2552 // Consider taskgroup reduction descriptor variable a private
2553 // to avoid possible capture in the region.
2554 (DSAStack->hasExplicitDirective(
2555 [](OpenMPDirectiveKind K) {
2556 return K == OMPD_taskgroup ||
2557 ((isOpenMPParallelDirective(K) ||
2558 isOpenMPWorksharingDirective(K)) &&
2559 !isOpenMPSimdDirective(K));
2561 Level) &&
2562 DSAStack->isTaskgroupReductionRef(D, Level)))
2563 ? OMPC_private
2564 : OMPC_unknown;
2567 void Sema::setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D,
2568 unsigned Level) {
2569 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2570 D = getCanonicalDecl(D);
2571 OpenMPClauseKind OMPC = OMPC_unknown;
2572 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2573 const unsigned NewLevel = I - 1;
2574 if (DSAStack->hasExplicitDSA(
2576 [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2577 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2578 OMPC = K;
2579 return true;
2581 return false;
2583 NewLevel))
2584 break;
2585 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2586 D, NewLevel,
2587 [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
2588 OpenMPClauseKind) { return true; })) {
2589 OMPC = OMPC_map;
2590 break;
2592 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2593 NewLevel)) {
2594 OMPC = OMPC_map;
2595 if (DSAStack->mustBeFirstprivateAtLevel(
2596 NewLevel, getVariableCategoryFromDecl(LangOpts, D)))
2597 OMPC = OMPC_firstprivate;
2598 break;
2601 if (OMPC != OMPC_unknown)
2602 FD->addAttr(OMPCaptureKindAttr::CreateImplicit(Context, unsigned(OMPC)));
2605 bool Sema::isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level,
2606 unsigned CaptureLevel) const {
2607 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2608 // Return true if the current level is no longer enclosed in a target region.
2610 SmallVector<OpenMPDirectiveKind, 4> Regions;
2611 getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level));
2612 const auto *VD = dyn_cast<VarDecl>(D);
2613 return VD && !VD->hasLocalStorage() &&
2614 DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2615 Level) &&
2616 Regions[CaptureLevel] != OMPD_task;
2619 bool Sema::isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level,
2620 unsigned CaptureLevel) const {
2621 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2622 // Return true if the current level is no longer enclosed in a target region.
2624 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2625 if (!VD->hasLocalStorage()) {
2626 if (isInOpenMPTargetExecutionDirective())
2627 return true;
2628 DSAStackTy::DSAVarData TopDVar =
2629 DSAStack->getTopDSA(D, /*FromParent=*/false);
2630 unsigned NumLevels =
2631 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2632 if (Level == 0)
2633 // non-file scope static variale with default(firstprivate)
2634 // should be gloabal captured.
2635 return (NumLevels == CaptureLevel + 1 &&
2636 (TopDVar.CKind != OMPC_shared ||
2637 DSAStack->getDefaultDSA() == DSA_firstprivate));
2638 do {
2639 --Level;
2640 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2641 if (DVar.CKind != OMPC_shared)
2642 return true;
2643 } while (Level > 0);
2646 return true;
2649 void Sema::DestroyDataSharingAttributesStack() { delete DSAStack; }
2651 void Sema::ActOnOpenMPBeginDeclareVariant(SourceLocation Loc,
2652 OMPTraitInfo &TI) {
2653 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2656 void Sema::ActOnOpenMPEndDeclareVariant() {
2657 assert(isInOpenMPDeclareVariantScope() &&
2658 "Not in OpenMP declare variant scope!");
2660 OMPDeclareVariantScopes.pop_back();
2663 void Sema::finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller,
2664 const FunctionDecl *Callee,
2665 SourceLocation Loc) {
2666 assert(LangOpts.OpenMP && "Expected OpenMP compilation mode.");
2667 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2668 OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
2669 // Ignore host functions during device analyzis.
2670 if (LangOpts.OpenMPIsDevice &&
2671 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2672 return;
2673 // Ignore nohost functions during host analyzis.
2674 if (!LangOpts.OpenMPIsDevice && DevTy &&
2675 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2676 return;
2677 const FunctionDecl *FD = Callee->getMostRecentDecl();
2678 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2679 if (LangOpts.OpenMPIsDevice && DevTy &&
2680 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2681 // Diagnose host function called during device codegen.
2682 StringRef HostDevTy =
2683 getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
2684 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2685 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2686 diag::note_omp_marked_device_type_here)
2687 << HostDevTy;
2688 return;
2690 if (!LangOpts.OpenMPIsDevice && !LangOpts.OpenMPOffloadMandatory && DevTy &&
2691 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2692 // Diagnose nohost function called during host codegen.
2693 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2694 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2695 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2696 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2697 diag::note_omp_marked_device_type_here)
2698 << NoHostDevTy;
2702 void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
2703 const DeclarationNameInfo &DirName,
2704 Scope *CurScope, SourceLocation Loc) {
2705 DSAStack->push(DKind, DirName, CurScope, Loc);
2706 PushExpressionEvaluationContext(
2707 ExpressionEvaluationContext::PotentiallyEvaluated);
2710 void Sema::StartOpenMPClause(OpenMPClauseKind K) {
2711 DSAStack->setClauseParsingMode(K);
2714 void Sema::EndOpenMPClause() {
2715 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2716 CleanupVarDeclMarking();
2719 static std::pair<ValueDecl *, bool>
2720 getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2721 SourceRange &ERange, bool AllowArraySection = false,
2722 StringRef DiagType = "");
2724 /// Check consistency of the reduction clauses.
2725 static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2726 ArrayRef<OMPClause *> Clauses) {
2727 bool InscanFound = false;
2728 SourceLocation InscanLoc;
2729 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2730 // A reduction clause without the inscan reduction-modifier may not appear on
2731 // a construct on which a reduction clause with the inscan reduction-modifier
2732 // appears.
2733 for (OMPClause *C : Clauses) {
2734 if (C->getClauseKind() != OMPC_reduction)
2735 continue;
2736 auto *RC = cast<OMPReductionClause>(C);
2737 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2738 InscanFound = true;
2739 InscanLoc = RC->getModifierLoc();
2740 continue;
2742 if (RC->getModifier() == OMPC_REDUCTION_task) {
2743 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2744 // A reduction clause with the task reduction-modifier may only appear on
2745 // a parallel construct, a worksharing construct or a combined or
2746 // composite construct for which any of the aforementioned constructs is a
2747 // constituent construct and simd or loop are not constituent constructs.
2748 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2749 if (!(isOpenMPParallelDirective(CurDir) ||
2750 isOpenMPWorksharingDirective(CurDir)) ||
2751 isOpenMPSimdDirective(CurDir))
2752 S.Diag(RC->getModifierLoc(),
2753 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2754 continue;
2757 if (InscanFound) {
2758 for (OMPClause *C : Clauses) {
2759 if (C->getClauseKind() != OMPC_reduction)
2760 continue;
2761 auto *RC = cast<OMPReductionClause>(C);
2762 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2763 S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2764 ? RC->getBeginLoc()
2765 : RC->getModifierLoc(),
2766 diag::err_omp_inscan_reduction_expected);
2767 S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2768 continue;
2770 for (Expr *Ref : RC->varlists()) {
2771 assert(Ref && "NULL expr in OpenMP nontemporal clause.");
2772 SourceLocation ELoc;
2773 SourceRange ERange;
2774 Expr *SimpleRefExpr = Ref;
2775 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2776 /*AllowArraySection=*/true);
2777 ValueDecl *D = Res.first;
2778 if (!D)
2779 continue;
2780 if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2781 S.Diag(Ref->getExprLoc(),
2782 diag::err_omp_reduction_not_inclusive_exclusive)
2783 << Ref->getSourceRange();
2790 static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2791 ArrayRef<OMPClause *> Clauses);
2792 static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2793 bool WithInit);
2795 static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2796 const ValueDecl *D,
2797 const DSAStackTy::DSAVarData &DVar,
2798 bool IsLoopIterVar = false);
2800 void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
2801 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2802 // A variable of class type (or array thereof) that appears in a lastprivate
2803 // clause requires an accessible, unambiguous default constructor for the
2804 // class type, unless the list item is also specified in a firstprivate
2805 // clause.
2806 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
2807 for (OMPClause *C : D->clauses()) {
2808 if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
2809 SmallVector<Expr *, 8> PrivateCopies;
2810 for (Expr *DE : Clause->varlists()) {
2811 if (DE->isValueDependent() || DE->isTypeDependent()) {
2812 PrivateCopies.push_back(nullptr);
2813 continue;
2815 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2816 auto *VD = cast<VarDecl>(DRE->getDecl());
2817 QualType Type = VD->getType().getNonReferenceType();
2818 const DSAStackTy::DSAVarData DVar =
2819 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2820 if (DVar.CKind == OMPC_lastprivate) {
2821 // Generate helper private variable and initialize it with the
2822 // default value. The address of the original variable is replaced
2823 // by the address of the new private variable in CodeGen. This new
2824 // variable is not added to IdResolver, so the code in the OpenMP
2825 // region uses original variable for proper diagnostics.
2826 VarDecl *VDPrivate = buildVarDecl(
2827 *this, DE->getExprLoc(), Type.getUnqualifiedType(),
2828 VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
2829 ActOnUninitializedDecl(VDPrivate);
2830 if (VDPrivate->isInvalidDecl()) {
2831 PrivateCopies.push_back(nullptr);
2832 continue;
2834 PrivateCopies.push_back(buildDeclRefExpr(
2835 *this, VDPrivate, DE->getType(), DE->getExprLoc()));
2836 } else {
2837 // The variable is also a firstprivate, so initialization sequence
2838 // for private copy is generated already.
2839 PrivateCopies.push_back(nullptr);
2842 Clause->setPrivateCopies(PrivateCopies);
2843 continue;
2845 // Finalize nontemporal clause by handling private copies, if any.
2846 if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) {
2847 SmallVector<Expr *, 8> PrivateRefs;
2848 for (Expr *RefExpr : Clause->varlists()) {
2849 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
2850 SourceLocation ELoc;
2851 SourceRange ERange;
2852 Expr *SimpleRefExpr = RefExpr;
2853 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
2854 if (Res.second)
2855 // It will be analyzed later.
2856 PrivateRefs.push_back(RefExpr);
2857 ValueDecl *D = Res.first;
2858 if (!D)
2859 continue;
2861 const DSAStackTy::DSAVarData DVar =
2862 DSAStack->getTopDSA(D, /*FromParent=*/false);
2863 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2864 : SimpleRefExpr);
2866 Clause->setPrivateRefs(PrivateRefs);
2867 continue;
2869 if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) {
2870 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
2871 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
2872 auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts());
2873 if (!DRE)
2874 continue;
2875 ValueDecl *VD = DRE->getDecl();
2876 if (!VD || !isa<VarDecl>(VD))
2877 continue;
2878 DSAStackTy::DSAVarData DVar =
2879 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2880 // OpenMP [2.12.5, target Construct]
2881 // Memory allocators that appear in a uses_allocators clause cannot
2882 // appear in other data-sharing attribute clauses or data-mapping
2883 // attribute clauses in the same construct.
2884 Expr *MapExpr = nullptr;
2885 if (DVar.RefExpr ||
2886 DSAStack->checkMappableExprComponentListsForDecl(
2887 VD, /*CurrentRegionOnly=*/true,
2888 [VD, &MapExpr](
2889 OMPClauseMappableExprCommon::MappableExprComponentListRef
2890 MapExprComponents,
2891 OpenMPClauseKind C) {
2892 auto MI = MapExprComponents.rbegin();
2893 auto ME = MapExprComponents.rend();
2894 if (MI != ME &&
2895 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
2896 VD->getCanonicalDecl()) {
2897 MapExpr = MI->getAssociatedExpression();
2898 return true;
2900 return false;
2901 })) {
2902 Diag(D.Allocator->getExprLoc(),
2903 diag::err_omp_allocator_used_in_clauses)
2904 << D.Allocator->getSourceRange();
2905 if (DVar.RefExpr)
2906 reportOriginalDsa(*this, DSAStack, VD, DVar);
2907 else
2908 Diag(MapExpr->getExprLoc(), diag::note_used_here)
2909 << MapExpr->getSourceRange();
2912 continue;
2915 // Check allocate clauses.
2916 if (!CurContext->isDependentContext())
2917 checkAllocateClauses(*this, DSAStack, D->clauses());
2918 checkReductionClauses(*this, DSAStack, D->clauses());
2921 DSAStack->pop();
2922 DiscardCleanupsInEvaluationContext();
2923 PopExpressionEvaluationContext();
2926 static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
2927 Expr *NumIterations, Sema &SemaRef,
2928 Scope *S, DSAStackTy *Stack);
2930 namespace {
2932 class VarDeclFilterCCC final : public CorrectionCandidateCallback {
2933 private:
2934 Sema &SemaRef;
2936 public:
2937 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
2938 bool ValidateCandidate(const TypoCorrection &Candidate) override {
2939 NamedDecl *ND = Candidate.getCorrectionDecl();
2940 if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
2941 return VD->hasGlobalStorage() &&
2942 SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
2943 SemaRef.getCurScope());
2945 return false;
2948 std::unique_ptr<CorrectionCandidateCallback> clone() override {
2949 return std::make_unique<VarDeclFilterCCC>(*this);
2953 class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
2954 private:
2955 Sema &SemaRef;
2957 public:
2958 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
2959 bool ValidateCandidate(const TypoCorrection &Candidate) override {
2960 NamedDecl *ND = Candidate.getCorrectionDecl();
2961 if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
2962 isa<FunctionDecl>(ND))) {
2963 return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
2964 SemaRef.getCurScope());
2966 return false;
2969 std::unique_ptr<CorrectionCandidateCallback> clone() override {
2970 return std::make_unique<VarOrFuncDeclFilterCCC>(*this);
2974 } // namespace
2976 ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
2977 CXXScopeSpec &ScopeSpec,
2978 const DeclarationNameInfo &Id,
2979 OpenMPDirectiveKind Kind) {
2980 LookupResult Lookup(*this, Id, LookupOrdinaryName);
2981 LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
2983 if (Lookup.isAmbiguous())
2984 return ExprError();
2986 VarDecl *VD;
2987 if (!Lookup.isSingleResult()) {
2988 VarDeclFilterCCC CCC(*this);
2989 if (TypoCorrection Corrected =
2990 CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr, CCC,
2991 CTK_ErrorRecovery)) {
2992 diagnoseTypo(Corrected,
2993 PDiag(Lookup.empty()
2994 ? diag::err_undeclared_var_use_suggest
2995 : diag::err_omp_expected_var_arg_suggest)
2996 << Id.getName());
2997 VD = Corrected.getCorrectionDeclAs<VarDecl>();
2998 } else {
2999 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
3000 : diag::err_omp_expected_var_arg)
3001 << Id.getName();
3002 return ExprError();
3004 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3005 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3006 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3007 return ExprError();
3009 Lookup.suppressDiagnostics();
3011 // OpenMP [2.9.2, Syntax, C/C++]
3012 // Variables must be file-scope, namespace-scope, or static block-scope.
3013 if (Kind == OMPD_threadprivate && !VD->hasGlobalStorage()) {
3014 Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3015 << getOpenMPDirectiveName(Kind) << !VD->isStaticLocal();
3016 bool IsDecl =
3017 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3018 Diag(VD->getLocation(),
3019 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3020 << VD;
3021 return ExprError();
3024 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3025 NamedDecl *ND = CanonicalVD;
3026 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3027 // A threadprivate directive for file-scope variables must appear outside
3028 // any definition or declaration.
3029 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3030 !getCurLexicalContext()->isTranslationUnit()) {
3031 Diag(Id.getLoc(), diag::err_omp_var_scope)
3032 << getOpenMPDirectiveName(Kind) << VD;
3033 bool IsDecl =
3034 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3035 Diag(VD->getLocation(),
3036 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3037 << VD;
3038 return ExprError();
3040 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3041 // A threadprivate directive for static class member variables must appear
3042 // in the class definition, in the same scope in which the member
3043 // variables are declared.
3044 if (CanonicalVD->isStaticDataMember() &&
3045 !CanonicalVD->getDeclContext()->Equals(getCurLexicalContext())) {
3046 Diag(Id.getLoc(), diag::err_omp_var_scope)
3047 << getOpenMPDirectiveName(Kind) << VD;
3048 bool IsDecl =
3049 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3050 Diag(VD->getLocation(),
3051 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3052 << VD;
3053 return ExprError();
3055 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3056 // A threadprivate directive for namespace-scope variables must appear
3057 // outside any definition or declaration other than the namespace
3058 // definition itself.
3059 if (CanonicalVD->getDeclContext()->isNamespace() &&
3060 (!getCurLexicalContext()->isFileContext() ||
3061 !getCurLexicalContext()->Encloses(CanonicalVD->getDeclContext()))) {
3062 Diag(Id.getLoc(), diag::err_omp_var_scope)
3063 << getOpenMPDirectiveName(Kind) << VD;
3064 bool IsDecl =
3065 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3066 Diag(VD->getLocation(),
3067 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3068 << VD;
3069 return ExprError();
3071 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3072 // A threadprivate directive for static block-scope variables must appear
3073 // in the scope of the variable and not in a nested scope.
3074 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3075 !isDeclInScope(ND, getCurLexicalContext(), CurScope)) {
3076 Diag(Id.getLoc(), diag::err_omp_var_scope)
3077 << getOpenMPDirectiveName(Kind) << VD;
3078 bool IsDecl =
3079 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3080 Diag(VD->getLocation(),
3081 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3082 << VD;
3083 return ExprError();
3086 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3087 // A threadprivate directive must lexically precede all references to any
3088 // of the variables in its list.
3089 if (Kind == OMPD_threadprivate && VD->isUsed() &&
3090 !DSAStack->isThreadPrivate(VD)) {
3091 Diag(Id.getLoc(), diag::err_omp_var_used)
3092 << getOpenMPDirectiveName(Kind) << VD;
3093 return ExprError();
3096 QualType ExprType = VD->getType().getNonReferenceType();
3097 return DeclRefExpr::Create(Context, NestedNameSpecifierLoc(),
3098 SourceLocation(), VD,
3099 /*RefersToEnclosingVariableOrCapture=*/false,
3100 Id.getLoc(), ExprType, VK_LValue);
3103 Sema::DeclGroupPtrTy
3104 Sema::ActOnOpenMPThreadprivateDirective(SourceLocation Loc,
3105 ArrayRef<Expr *> VarList) {
3106 if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
3107 CurContext->addDecl(D);
3108 return DeclGroupPtrTy::make(DeclGroupRef(D));
3110 return nullptr;
3113 namespace {
3114 class LocalVarRefChecker final
3115 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3116 Sema &SemaRef;
3118 public:
3119 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3120 if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3121 if (VD->hasLocalStorage()) {
3122 SemaRef.Diag(E->getBeginLoc(),
3123 diag::err_omp_local_var_in_threadprivate_init)
3124 << E->getSourceRange();
3125 SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3126 << VD << VD->getSourceRange();
3127 return true;
3130 return false;
3132 bool VisitStmt(const Stmt *S) {
3133 for (const Stmt *Child : S->children()) {
3134 if (Child && Visit(Child))
3135 return true;
3137 return false;
3139 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3141 } // namespace
3143 OMPThreadPrivateDecl *
3144 Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) {
3145 SmallVector<Expr *, 8> Vars;
3146 for (Expr *RefExpr : VarList) {
3147 auto *DE = cast<DeclRefExpr>(RefExpr);
3148 auto *VD = cast<VarDecl>(DE->getDecl());
3149 SourceLocation ILoc = DE->getExprLoc();
3151 // Mark variable as used.
3152 VD->setReferenced();
3153 VD->markUsed(Context);
3155 QualType QType = VD->getType();
3156 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3157 // It will be analyzed later.
3158 Vars.push_back(DE);
3159 continue;
3162 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3163 // A threadprivate variable must not have an incomplete type.
3164 if (RequireCompleteType(ILoc, VD->getType(),
3165 diag::err_omp_threadprivate_incomplete_type)) {
3166 continue;
3169 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3170 // A threadprivate variable must not have a reference type.
3171 if (VD->getType()->isReferenceType()) {
3172 Diag(ILoc, diag::err_omp_ref_type_arg)
3173 << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType();
3174 bool IsDecl =
3175 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3176 Diag(VD->getLocation(),
3177 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3178 << VD;
3179 continue;
3182 // Check if this is a TLS variable. If TLS is not being supported, produce
3183 // the corresponding diagnostic.
3184 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3185 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3186 getLangOpts().OpenMPUseTLS &&
3187 getASTContext().getTargetInfo().isTLSSupported())) ||
3188 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3189 !VD->isLocalVarDecl())) {
3190 Diag(ILoc, diag::err_omp_var_thread_local)
3191 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3192 bool IsDecl =
3193 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3194 Diag(VD->getLocation(),
3195 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3196 << VD;
3197 continue;
3200 // Check if initial value of threadprivate variable reference variable with
3201 // local storage (it is not supported by runtime).
3202 if (const Expr *Init = VD->getAnyInitializer()) {
3203 LocalVarRefChecker Checker(*this);
3204 if (Checker.Visit(Init))
3205 continue;
3208 Vars.push_back(RefExpr);
3209 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3210 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3211 Context, SourceRange(Loc, Loc)));
3212 if (ASTMutationListener *ML = Context.getASTMutationListener())
3213 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3215 OMPThreadPrivateDecl *D = nullptr;
3216 if (!Vars.empty()) {
3217 D = OMPThreadPrivateDecl::Create(Context, getCurLexicalContext(), Loc,
3218 Vars);
3219 D->setAccess(AS_public);
3221 return D;
3224 static OMPAllocateDeclAttr::AllocatorTypeTy
3225 getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3226 if (!Allocator)
3227 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3228 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3229 Allocator->isInstantiationDependent() ||
3230 Allocator->containsUnexpandedParameterPack())
3231 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3232 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3233 const Expr *AE = Allocator->IgnoreParenImpCasts();
3234 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3235 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3236 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3237 llvm::FoldingSetNodeID AEId, DAEId;
3238 AE->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3239 DefAllocator->Profile(DAEId, S.getASTContext(), /*Canonical=*/true);
3240 if (AEId == DAEId) {
3241 AllocatorKindRes = AllocatorKind;
3242 break;
3245 return AllocatorKindRes;
3248 static bool checkPreviousOMPAllocateAttribute(
3249 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3250 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3251 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3252 return false;
3253 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3254 Expr *PrevAllocator = A->getAllocator();
3255 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3256 getAllocatorKind(S, Stack, PrevAllocator);
3257 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3258 if (AllocatorsMatch &&
3259 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3260 Allocator && PrevAllocator) {
3261 const Expr *AE = Allocator->IgnoreParenImpCasts();
3262 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3263 llvm::FoldingSetNodeID AEId, PAEId;
3264 AE->Profile(AEId, S.Context, /*Canonical=*/true);
3265 PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3266 AllocatorsMatch = AEId == PAEId;
3268 if (!AllocatorsMatch) {
3269 SmallString<256> AllocatorBuffer;
3270 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3271 if (Allocator)
3272 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3273 SmallString<256> PrevAllocatorBuffer;
3274 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3275 if (PrevAllocator)
3276 PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3277 S.getPrintingPolicy());
3279 SourceLocation AllocatorLoc =
3280 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3281 SourceRange AllocatorRange =
3282 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3283 SourceLocation PrevAllocatorLoc =
3284 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3285 SourceRange PrevAllocatorRange =
3286 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3287 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3288 << (Allocator ? 1 : 0) << AllocatorStream.str()
3289 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3290 << AllocatorRange;
3291 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3292 << PrevAllocatorRange;
3293 return true;
3295 return false;
3298 static void
3299 applyOMPAllocateAttribute(Sema &S, VarDecl *VD,
3300 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3301 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3302 if (VD->hasAttr<OMPAllocateDeclAttr>())
3303 return;
3304 if (Alignment &&
3305 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3306 Alignment->isInstantiationDependent() ||
3307 Alignment->containsUnexpandedParameterPack()))
3308 // Apply later when we have a usable value.
3309 return;
3310 if (Allocator &&
3311 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3312 Allocator->isInstantiationDependent() ||
3313 Allocator->containsUnexpandedParameterPack()))
3314 return;
3315 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3316 Allocator, Alignment, SR);
3317 VD->addAttr(A);
3318 if (ASTMutationListener *ML = S.Context.getASTMutationListener())
3319 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3322 Sema::DeclGroupPtrTy
3323 Sema::ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef<Expr *> VarList,
3324 ArrayRef<OMPClause *> Clauses,
3325 DeclContext *Owner) {
3326 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3327 Expr *Alignment = nullptr;
3328 Expr *Allocator = nullptr;
3329 if (Clauses.empty()) {
3330 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3331 // allocate directives that appear in a target region must specify an
3332 // allocator clause unless a requires directive with the dynamic_allocators
3333 // clause is present in the same compilation unit.
3334 if (LangOpts.OpenMPIsDevice &&
3335 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3336 targetDiag(Loc, diag::err_expected_allocator_clause);
3337 } else {
3338 for (const OMPClause *C : Clauses)
3339 if (const auto *AC = dyn_cast<OMPAllocatorClause>(C))
3340 Allocator = AC->getAllocator();
3341 else if (const auto *AC = dyn_cast<OMPAlignClause>(C))
3342 Alignment = AC->getAlignment();
3343 else
3344 llvm_unreachable("Unexpected clause on allocate directive");
3346 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3347 getAllocatorKind(*this, DSAStack, Allocator);
3348 SmallVector<Expr *, 8> Vars;
3349 for (Expr *RefExpr : VarList) {
3350 auto *DE = cast<DeclRefExpr>(RefExpr);
3351 auto *VD = cast<VarDecl>(DE->getDecl());
3353 // Check if this is a TLS variable or global register.
3354 if (VD->getTLSKind() != VarDecl::TLS_None ||
3355 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3356 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3357 !VD->isLocalVarDecl()))
3358 continue;
3360 // If the used several times in the allocate directive, the same allocator
3361 // must be used.
3362 if (checkPreviousOMPAllocateAttribute(*this, DSAStack, RefExpr, VD,
3363 AllocatorKind, Allocator))
3364 continue;
3366 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3367 // If a list item has a static storage type, the allocator expression in the
3368 // allocator clause must be a constant expression that evaluates to one of
3369 // the predefined memory allocator values.
3370 if (Allocator && VD->hasGlobalStorage()) {
3371 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3372 Diag(Allocator->getExprLoc(),
3373 diag::err_omp_expected_predefined_allocator)
3374 << Allocator->getSourceRange();
3375 bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
3376 VarDecl::DeclarationOnly;
3377 Diag(VD->getLocation(),
3378 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3379 << VD;
3380 continue;
3384 Vars.push_back(RefExpr);
3385 applyOMPAllocateAttribute(*this, VD, AllocatorKind, Allocator, Alignment,
3386 DE->getSourceRange());
3388 if (Vars.empty())
3389 return nullptr;
3390 if (!Owner)
3391 Owner = getCurLexicalContext();
3392 auto *D = OMPAllocateDecl::Create(Context, Owner, Loc, Vars, Clauses);
3393 D->setAccess(AS_public);
3394 Owner->addDecl(D);
3395 return DeclGroupPtrTy::make(DeclGroupRef(D));
3398 Sema::DeclGroupPtrTy
3399 Sema::ActOnOpenMPRequiresDirective(SourceLocation Loc,
3400 ArrayRef<OMPClause *> ClauseList) {
3401 OMPRequiresDecl *D = nullptr;
3402 if (!CurContext->isFileContext()) {
3403 Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3404 } else {
3405 D = CheckOMPRequiresDecl(Loc, ClauseList);
3406 if (D) {
3407 CurContext->addDecl(D);
3408 DSAStack->addRequiresDecl(D);
3411 return DeclGroupPtrTy::make(DeclGroupRef(D));
3414 void Sema::ActOnOpenMPAssumesDirective(SourceLocation Loc,
3415 OpenMPDirectiveKind DKind,
3416 ArrayRef<std::string> Assumptions,
3417 bool SkippedClauses) {
3418 if (!SkippedClauses && Assumptions.empty())
3419 Diag(Loc, diag::err_omp_no_clause_for_directive)
3420 << llvm::omp::getAllAssumeClauseOptions()
3421 << llvm::omp::getOpenMPDirectiveName(DKind);
3423 auto *AA = AssumptionAttr::Create(Context, llvm::join(Assumptions, ","), Loc);
3424 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3425 OMPAssumeScoped.push_back(AA);
3426 return;
3429 // Global assumes without assumption clauses are ignored.
3430 if (Assumptions.empty())
3431 return;
3433 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3434 "Unexpected omp assumption directive!");
3435 OMPAssumeGlobal.push_back(AA);
3437 // The OMPAssumeGlobal scope above will take care of new declarations but
3438 // we also want to apply the assumption to existing ones, e.g., to
3439 // declarations in included headers. To this end, we traverse all existing
3440 // declaration contexts and annotate function declarations here.
3441 SmallVector<DeclContext *, 8> DeclContexts;
3442 auto *Ctx = CurContext;
3443 while (Ctx->getLexicalParent())
3444 Ctx = Ctx->getLexicalParent();
3445 DeclContexts.push_back(Ctx);
3446 while (!DeclContexts.empty()) {
3447 DeclContext *DC = DeclContexts.pop_back_val();
3448 for (auto *SubDC : DC->decls()) {
3449 if (SubDC->isInvalidDecl())
3450 continue;
3451 if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3452 DeclContexts.push_back(CTD->getTemplatedDecl());
3453 llvm::append_range(DeclContexts, CTD->specializations());
3454 continue;
3456 if (auto *DC = dyn_cast<DeclContext>(SubDC))
3457 DeclContexts.push_back(DC);
3458 if (auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3459 F->addAttr(AA);
3460 continue;
3466 void Sema::ActOnOpenMPEndAssumesDirective() {
3467 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3468 OMPAssumeScoped.pop_back();
3471 OMPRequiresDecl *Sema::CheckOMPRequiresDecl(SourceLocation Loc,
3472 ArrayRef<OMPClause *> ClauseList) {
3473 /// For target specific clauses, the requires directive cannot be
3474 /// specified after the handling of any of the target regions in the
3475 /// current compilation unit.
3476 ArrayRef<SourceLocation> TargetLocations =
3477 DSAStack->getEncounteredTargetLocs();
3478 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3479 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3480 for (const OMPClause *CNew : ClauseList) {
3481 // Check if any of the requires clauses affect target regions.
3482 if (isa<OMPUnifiedSharedMemoryClause>(CNew) ||
3483 isa<OMPUnifiedAddressClause>(CNew) ||
3484 isa<OMPReverseOffloadClause>(CNew) ||
3485 isa<OMPDynamicAllocatorsClause>(CNew)) {
3486 Diag(Loc, diag::err_omp_directive_before_requires)
3487 << "target" << getOpenMPClauseName(CNew->getClauseKind());
3488 for (SourceLocation TargetLoc : TargetLocations) {
3489 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3490 << "target";
3492 } else if (!AtomicLoc.isInvalid() &&
3493 isa<OMPAtomicDefaultMemOrderClause>(CNew)) {
3494 Diag(Loc, diag::err_omp_directive_before_requires)
3495 << "atomic" << getOpenMPClauseName(CNew->getClauseKind());
3496 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3497 << "atomic";
3502 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3503 return OMPRequiresDecl::Create(Context, getCurLexicalContext(), Loc,
3504 ClauseList);
3505 return nullptr;
3508 static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3509 const ValueDecl *D,
3510 const DSAStackTy::DSAVarData &DVar,
3511 bool IsLoopIterVar) {
3512 if (DVar.RefExpr) {
3513 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3514 << getOpenMPClauseName(DVar.CKind);
3515 return;
3517 enum {
3518 PDSA_StaticMemberShared,
3519 PDSA_StaticLocalVarShared,
3520 PDSA_LoopIterVarPrivate,
3521 PDSA_LoopIterVarLinear,
3522 PDSA_LoopIterVarLastprivate,
3523 PDSA_ConstVarShared,
3524 PDSA_GlobalVarShared,
3525 PDSA_TaskVarFirstprivate,
3526 PDSA_LocalVarPrivate,
3527 PDSA_Implicit
3528 } Reason = PDSA_Implicit;
3529 bool ReportHint = false;
3530 auto ReportLoc = D->getLocation();
3531 auto *VD = dyn_cast<VarDecl>(D);
3532 if (IsLoopIterVar) {
3533 if (DVar.CKind == OMPC_private)
3534 Reason = PDSA_LoopIterVarPrivate;
3535 else if (DVar.CKind == OMPC_lastprivate)
3536 Reason = PDSA_LoopIterVarLastprivate;
3537 else
3538 Reason = PDSA_LoopIterVarLinear;
3539 } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3540 DVar.CKind == OMPC_firstprivate) {
3541 Reason = PDSA_TaskVarFirstprivate;
3542 ReportLoc = DVar.ImplicitDSALoc;
3543 } else if (VD && VD->isStaticLocal())
3544 Reason = PDSA_StaticLocalVarShared;
3545 else if (VD && VD->isStaticDataMember())
3546 Reason = PDSA_StaticMemberShared;
3547 else if (VD && VD->isFileVarDecl())
3548 Reason = PDSA_GlobalVarShared;
3549 else if (D->getType().isConstant(SemaRef.getASTContext()))
3550 Reason = PDSA_ConstVarShared;
3551 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3552 ReportHint = true;
3553 Reason = PDSA_LocalVarPrivate;
3555 if (Reason != PDSA_Implicit) {
3556 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3557 << Reason << ReportHint
3558 << getOpenMPDirectiveName(Stack->getCurrentDirective());
3559 } else if (DVar.ImplicitDSALoc.isValid()) {
3560 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3561 << getOpenMPClauseName(DVar.CKind);
3565 static OpenMPMapClauseKind
3566 getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M,
3567 bool IsAggregateOrDeclareTarget) {
3568 OpenMPMapClauseKind Kind = OMPC_MAP_unknown;
3569 switch (M) {
3570 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3571 Kind = OMPC_MAP_alloc;
3572 break;
3573 case OMPC_DEFAULTMAP_MODIFIER_to:
3574 Kind = OMPC_MAP_to;
3575 break;
3576 case OMPC_DEFAULTMAP_MODIFIER_from:
3577 Kind = OMPC_MAP_from;
3578 break;
3579 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3580 Kind = OMPC_MAP_tofrom;
3581 break;
3582 case OMPC_DEFAULTMAP_MODIFIER_present:
3583 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3584 // If implicit-behavior is present, each variable referenced in the
3585 // construct in the category specified by variable-category is treated as if
3586 // it had been listed in a map clause with the map-type of alloc and
3587 // map-type-modifier of present.
3588 Kind = OMPC_MAP_alloc;
3589 break;
3590 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3591 case OMPC_DEFAULTMAP_MODIFIER_last:
3592 llvm_unreachable("Unexpected defaultmap implicit behavior");
3593 case OMPC_DEFAULTMAP_MODIFIER_none:
3594 case OMPC_DEFAULTMAP_MODIFIER_default:
3595 case OMPC_DEFAULTMAP_MODIFIER_unknown:
3596 // IsAggregateOrDeclareTarget could be true if:
3597 // 1. the implicit behavior for aggregate is tofrom
3598 // 2. it's a declare target link
3599 if (IsAggregateOrDeclareTarget) {
3600 Kind = OMPC_MAP_tofrom;
3601 break;
3603 llvm_unreachable("Unexpected defaultmap implicit behavior");
3605 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3606 return Kind;
3609 namespace {
3610 class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3611 DSAStackTy *Stack;
3612 Sema &SemaRef;
3613 bool ErrorFound = false;
3614 bool TryCaptureCXXThisMembers = false;
3615 CapturedStmt *CS = nullptr;
3616 const static unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_pointer + 1;
3617 llvm::SmallVector<Expr *, 4> ImplicitFirstprivate;
3618 llvm::SmallVector<Expr *, 4> ImplicitPrivate;
3619 llvm::SmallVector<Expr *, 4> ImplicitMap[DefaultmapKindNum][OMPC_MAP_delete];
3620 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
3621 ImplicitMapModifier[DefaultmapKindNum];
3622 Sema::VarsWithInheritedDSAType VarsWithInheritedDSA;
3623 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3625 void VisitSubCaptures(OMPExecutableDirective *S) {
3626 // Check implicitly captured variables.
3627 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3628 return;
3629 if (S->getDirectiveKind() == OMPD_atomic ||
3630 S->getDirectiveKind() == OMPD_critical ||
3631 S->getDirectiveKind() == OMPD_section ||
3632 S->getDirectiveKind() == OMPD_master ||
3633 S->getDirectiveKind() == OMPD_masked ||
3634 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
3635 Visit(S->getAssociatedStmt());
3636 return;
3638 visitSubCaptures(S->getInnermostCapturedStmt());
3639 // Try to capture inner this->member references to generate correct mappings
3640 // and diagnostics.
3641 if (TryCaptureCXXThisMembers ||
3642 (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
3643 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3644 [](const CapturedStmt::Capture &C) {
3645 return C.capturesThis();
3646 }))) {
3647 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3648 TryCaptureCXXThisMembers = true;
3649 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3650 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3652 // In tasks firstprivates are not captured anymore, need to analyze them
3653 // explicitly.
3654 if (isOpenMPTaskingDirective(S->getDirectiveKind()) &&
3655 !isOpenMPTaskLoopDirective(S->getDirectiveKind())) {
3656 for (OMPClause *C : S->clauses())
3657 if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) {
3658 for (Expr *Ref : FC->varlists())
3659 Visit(Ref);
3664 public:
3665 void VisitDeclRefExpr(DeclRefExpr *E) {
3666 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
3667 E->isValueDependent() || E->containsUnexpandedParameterPack() ||
3668 E->isInstantiationDependent())
3669 return;
3670 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3671 // Check the datasharing rules for the expressions in the clauses.
3672 if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) &&
3673 !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr &&
3674 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3675 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3676 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3677 Visit(CED->getInit());
3678 return;
3680 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD))
3681 // Do not analyze internal variables and do not enclose them into
3682 // implicit clauses.
3683 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3684 return;
3685 VD = VD->getCanonicalDecl();
3686 // Skip internally declared variables.
3687 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) &&
3688 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3689 !Stack->isImplicitTaskFirstprivate(VD))
3690 return;
3691 // Skip allocators in uses_allocators clauses.
3692 if (Stack->isUsesAllocatorsDecl(VD))
3693 return;
3695 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
3696 // Check if the variable has explicit DSA set and stop analysis if it so.
3697 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3698 return;
3700 // Skip internally declared static variables.
3701 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3702 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3703 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
3704 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
3705 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3706 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3707 !Stack->isImplicitTaskFirstprivate(VD))
3708 return;
3710 SourceLocation ELoc = E->getExprLoc();
3711 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3712 // The default(none) clause requires that each variable that is referenced
3713 // in the construct, and does not have a predetermined data-sharing
3714 // attribute, must have its data-sharing attribute explicitly determined
3715 // by being listed in a data-sharing attribute clause.
3716 if (DVar.CKind == OMPC_unknown &&
3717 (Stack->getDefaultDSA() == DSA_none ||
3718 Stack->getDefaultDSA() == DSA_private ||
3719 Stack->getDefaultDSA() == DSA_firstprivate) &&
3720 isImplicitOrExplicitTaskingRegion(DKind) &&
3721 VarsWithInheritedDSA.count(VD) == 0) {
3722 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
3723 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
3724 Stack->getDefaultDSA() == DSA_private)) {
3725 DSAStackTy::DSAVarData DVar =
3726 Stack->getImplicitDSA(VD, /*FromParent=*/false);
3727 InheritedDSA = DVar.CKind == OMPC_unknown;
3729 if (InheritedDSA)
3730 VarsWithInheritedDSA[VD] = E;
3731 if (Stack->getDefaultDSA() == DSA_none)
3732 return;
3735 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
3736 // If implicit-behavior is none, each variable referenced in the
3737 // construct that does not have a predetermined data-sharing attribute
3738 // and does not appear in a to or link clause on a declare target
3739 // directive must be listed in a data-mapping attribute clause, a
3740 // data-sharing attribute clause (including a data-sharing attribute
3741 // clause on a combined construct where target. is one of the
3742 // constituent constructs), or an is_device_ptr clause.
3743 OpenMPDefaultmapClauseKind ClauseKind =
3744 getVariableCategoryFromDecl(SemaRef.getLangOpts(), VD);
3745 if (SemaRef.getLangOpts().OpenMP >= 50) {
3746 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
3747 OMPC_DEFAULTMAP_MODIFIER_none;
3748 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
3749 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
3750 // Only check for data-mapping attribute and is_device_ptr here
3751 // since we have already make sure that the declaration does not
3752 // have a data-sharing attribute above
3753 if (!Stack->checkMappableExprComponentListsForDecl(
3754 VD, /*CurrentRegionOnly=*/true,
3755 [VD](OMPClauseMappableExprCommon::MappableExprComponentListRef
3756 MapExprComponents,
3757 OpenMPClauseKind) {
3758 auto MI = MapExprComponents.rbegin();
3759 auto ME = MapExprComponents.rend();
3760 return MI != ME && MI->getAssociatedDeclaration() == VD;
3761 })) {
3762 VarsWithInheritedDSA[VD] = E;
3763 return;
3767 if (SemaRef.getLangOpts().OpenMP > 50) {
3768 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
3769 OMPC_DEFAULTMAP_MODIFIER_present;
3770 if (IsModifierPresent) {
3771 if (!llvm::is_contained(ImplicitMapModifier[ClauseKind],
3772 OMPC_MAP_MODIFIER_present)) {
3773 ImplicitMapModifier[ClauseKind].push_back(
3774 OMPC_MAP_MODIFIER_present);
3779 if (isOpenMPTargetExecutionDirective(DKind) &&
3780 !Stack->isLoopControlVariable(VD).first) {
3781 if (!Stack->checkMappableExprComponentListsForDecl(
3782 VD, /*CurrentRegionOnly=*/true,
3783 [this](OMPClauseMappableExprCommon::MappableExprComponentListRef
3784 StackComponents,
3785 OpenMPClauseKind) {
3786 if (SemaRef.LangOpts.OpenMP >= 50)
3787 return !StackComponents.empty();
3788 // Variable is used if it has been marked as an array, array
3789 // section, array shaping or the variable iself.
3790 return StackComponents.size() == 1 ||
3791 llvm::all_of(
3792 llvm::drop_begin(llvm::reverse(StackComponents)),
3793 [](const OMPClauseMappableExprCommon::
3794 MappableComponent &MC) {
3795 return MC.getAssociatedDeclaration() ==
3796 nullptr &&
3797 (isa<OMPArraySectionExpr>(
3798 MC.getAssociatedExpression()) ||
3799 isa<OMPArrayShapingExpr>(
3800 MC.getAssociatedExpression()) ||
3801 isa<ArraySubscriptExpr>(
3802 MC.getAssociatedExpression()));
3804 })) {
3805 bool IsFirstprivate = false;
3806 // By default lambdas are captured as firstprivates.
3807 if (const auto *RD =
3808 VD->getType().getNonReferenceType()->getAsCXXRecordDecl())
3809 IsFirstprivate = RD->isLambda();
3810 IsFirstprivate =
3811 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
3812 if (IsFirstprivate) {
3813 ImplicitFirstprivate.emplace_back(E);
3814 } else {
3815 OpenMPDefaultmapClauseModifier M =
3816 Stack->getDefaultmapModifier(ClauseKind);
3817 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
3818 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
3819 ImplicitMap[ClauseKind][Kind].emplace_back(E);
3821 return;
3825 // OpenMP [2.9.3.6, Restrictions, p.2]
3826 // A list item that appears in a reduction clause of the innermost
3827 // enclosing worksharing or parallel construct may not be accessed in an
3828 // explicit task.
3829 DVar = Stack->hasInnermostDSA(
3831 [](OpenMPClauseKind C, bool AppliedToPointee) {
3832 return C == OMPC_reduction && !AppliedToPointee;
3834 [](OpenMPDirectiveKind K) {
3835 return isOpenMPParallelDirective(K) ||
3836 isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K);
3838 /*FromParent=*/true);
3839 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
3840 ErrorFound = true;
3841 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
3842 reportOriginalDsa(SemaRef, Stack, VD, DVar);
3843 return;
3846 // Define implicit data-sharing attributes for task.
3847 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
3848 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
3849 (((Stack->getDefaultDSA() == DSA_firstprivate &&
3850 DVar.CKind == OMPC_firstprivate) ||
3851 (Stack->getDefaultDSA() == DSA_private &&
3852 DVar.CKind == OMPC_private)) &&
3853 !DVar.RefExpr)) &&
3854 !Stack->isLoopControlVariable(VD).first) {
3855 if (Stack->getDefaultDSA() == DSA_private)
3856 ImplicitPrivate.push_back(E);
3857 else
3858 ImplicitFirstprivate.push_back(E);
3859 return;
3862 // Store implicitly used globals with declare target link for parent
3863 // target.
3864 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
3865 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
3866 Stack->addToParentTargetRegionLinkGlobals(E);
3867 return;
3871 void VisitMemberExpr(MemberExpr *E) {
3872 if (E->isTypeDependent() || E->isValueDependent() ||
3873 E->containsUnexpandedParameterPack() || E->isInstantiationDependent())
3874 return;
3875 auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
3876 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3877 if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) {
3878 if (!FD)
3879 return;
3880 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
3881 // Check if the variable has explicit DSA set and stop analysis if it
3882 // so.
3883 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
3884 return;
3886 if (isOpenMPTargetExecutionDirective(DKind) &&
3887 !Stack->isLoopControlVariable(FD).first &&
3888 !Stack->checkMappableExprComponentListsForDecl(
3889 FD, /*CurrentRegionOnly=*/true,
3890 [](OMPClauseMappableExprCommon::MappableExprComponentListRef
3891 StackComponents,
3892 OpenMPClauseKind) {
3893 return isa<CXXThisExpr>(
3894 cast<MemberExpr>(
3895 StackComponents.back().getAssociatedExpression())
3896 ->getBase()
3897 ->IgnoreParens());
3898 })) {
3899 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
3900 // A bit-field cannot appear in a map clause.
3902 if (FD->isBitField())
3903 return;
3905 // Check to see if the member expression is referencing a class that
3906 // has already been explicitly mapped
3907 if (Stack->isClassPreviouslyMapped(TE->getType()))
3908 return;
3910 OpenMPDefaultmapClauseModifier Modifier =
3911 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
3912 OpenMPDefaultmapClauseKind ClauseKind =
3913 getVariableCategoryFromDecl(SemaRef.getLangOpts(), FD);
3914 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
3915 Modifier, /*IsAggregateOrDeclareTarget*/ true);
3916 ImplicitMap[ClauseKind][Kind].emplace_back(E);
3917 return;
3920 SourceLocation ELoc = E->getExprLoc();
3921 // OpenMP [2.9.3.6, Restrictions, p.2]
3922 // A list item that appears in a reduction clause of the innermost
3923 // enclosing worksharing or parallel construct may not be accessed in
3924 // an explicit task.
3925 DVar = Stack->hasInnermostDSA(
3927 [](OpenMPClauseKind C, bool AppliedToPointee) {
3928 return C == OMPC_reduction && !AppliedToPointee;
3930 [](OpenMPDirectiveKind K) {
3931 return isOpenMPParallelDirective(K) ||
3932 isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K);
3934 /*FromParent=*/true);
3935 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
3936 ErrorFound = true;
3937 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
3938 reportOriginalDsa(SemaRef, Stack, FD, DVar);
3939 return;
3942 // Define implicit data-sharing attributes for task.
3943 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
3944 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
3945 !Stack->isLoopControlVariable(FD).first) {
3946 // Check if there is a captured expression for the current field in the
3947 // region. Do not mark it as firstprivate unless there is no captured
3948 // expression.
3949 // TODO: try to make it firstprivate.
3950 if (DVar.CKind != OMPC_unknown)
3951 ImplicitFirstprivate.push_back(E);
3953 return;
3955 if (isOpenMPTargetExecutionDirective(DKind)) {
3956 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
3957 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
3958 Stack->getCurrentDirective(),
3959 /*NoDiagnose=*/true))
3960 return;
3961 const auto *VD = cast<ValueDecl>(
3962 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
3963 if (!Stack->checkMappableExprComponentListsForDecl(
3964 VD, /*CurrentRegionOnly=*/true,
3965 [&CurComponents](
3966 OMPClauseMappableExprCommon::MappableExprComponentListRef
3967 StackComponents,
3968 OpenMPClauseKind) {
3969 auto CCI = CurComponents.rbegin();
3970 auto CCE = CurComponents.rend();
3971 for (const auto &SC : llvm::reverse(StackComponents)) {
3972 // Do both expressions have the same kind?
3973 if (CCI->getAssociatedExpression()->getStmtClass() !=
3974 SC.getAssociatedExpression()->getStmtClass())
3975 if (!((isa<OMPArraySectionExpr>(
3976 SC.getAssociatedExpression()) ||
3977 isa<OMPArrayShapingExpr>(
3978 SC.getAssociatedExpression())) &&
3979 isa<ArraySubscriptExpr>(
3980 CCI->getAssociatedExpression())))
3981 return false;
3983 const Decl *CCD = CCI->getAssociatedDeclaration();
3984 const Decl *SCD = SC.getAssociatedDeclaration();
3985 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
3986 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
3987 if (SCD != CCD)
3988 return false;
3989 std::advance(CCI, 1);
3990 if (CCI == CCE)
3991 break;
3993 return true;
3994 })) {
3995 Visit(E->getBase());
3997 } else if (!TryCaptureCXXThisMembers) {
3998 Visit(E->getBase());
4001 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4002 for (OMPClause *C : S->clauses()) {
4003 // Skip analysis of arguments of private clauses for task|target
4004 // directives.
4005 if (isa_and_nonnull<OMPPrivateClause>(C))
4006 continue;
4007 // Skip analysis of arguments of implicitly defined firstprivate clause
4008 // for task|target directives.
4009 // Skip analysis of arguments of implicitly defined map clause for target
4010 // directives.
4011 if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) &&
4012 C->isImplicit() &&
4013 !isOpenMPTaskingDirective(Stack->getCurrentDirective()))) {
4014 for (Stmt *CC : C->children()) {
4015 if (CC)
4016 Visit(CC);
4020 // Check implicitly captured variables.
4021 VisitSubCaptures(S);
4024 void VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective *S) {
4025 // Loop transformation directives do not introduce data sharing
4026 VisitStmt(S);
4029 void VisitCallExpr(CallExpr *S) {
4030 for (Stmt *C : S->arguments()) {
4031 if (C) {
4032 // Check implicitly captured variables in the task-based directives to
4033 // check if they must be firstprivatized.
4034 Visit(C);
4037 if (Expr *Callee = S->getCallee())
4038 if (auto *CE = dyn_cast<MemberExpr>(Callee->IgnoreParenImpCasts()))
4039 Visit(CE->getBase());
4041 void VisitStmt(Stmt *S) {
4042 for (Stmt *C : S->children()) {
4043 if (C) {
4044 // Check implicitly captured variables in the task-based directives to
4045 // check if they must be firstprivatized.
4046 Visit(C);
4051 void visitSubCaptures(CapturedStmt *S) {
4052 for (const CapturedStmt::Capture &Cap : S->captures()) {
4053 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4054 continue;
4055 VarDecl *VD = Cap.getCapturedVar();
4056 // Do not try to map the variable if it or its sub-component was mapped
4057 // already.
4058 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
4059 Stack->checkMappableExprComponentListsForDecl(
4060 VD, /*CurrentRegionOnly=*/true,
4061 [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
4062 OpenMPClauseKind) { return true; }))
4063 continue;
4064 DeclRefExpr *DRE = buildDeclRefExpr(
4065 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4066 Cap.getLocation(), /*RefersToCapture=*/true);
4067 Visit(DRE);
4070 bool isErrorFound() const { return ErrorFound; }
4071 ArrayRef<Expr *> getImplicitFirstprivate() const {
4072 return ImplicitFirstprivate;
4074 ArrayRef<Expr *> getImplicitPrivate() const { return ImplicitPrivate; }
4075 ArrayRef<Expr *> getImplicitMap(OpenMPDefaultmapClauseKind DK,
4076 OpenMPMapClauseKind MK) const {
4077 return ImplicitMap[DK][MK];
4079 ArrayRef<OpenMPMapModifierKind>
4080 getImplicitMapModifier(OpenMPDefaultmapClauseKind Kind) const {
4081 return ImplicitMapModifier[Kind];
4083 const Sema::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4084 return VarsWithInheritedDSA;
4087 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4088 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4089 // Process declare target link variables for the target directives.
4090 if (isOpenMPTargetExecutionDirective(S->getCurrentDirective())) {
4091 for (DeclRefExpr *E : Stack->getLinkGlobals())
4092 Visit(E);
4096 } // namespace
4098 static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4099 OpenMPDirectiveKind DKind,
4100 bool ScopeEntry) {
4101 SmallVector<llvm::omp::TraitProperty, 8> Traits;
4102 if (isOpenMPTargetExecutionDirective(DKind))
4103 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4104 if (isOpenMPTeamsDirective(DKind))
4105 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4106 if (isOpenMPParallelDirective(DKind))
4107 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4108 if (isOpenMPWorksharingDirective(DKind))
4109 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4110 if (isOpenMPSimdDirective(DKind))
4111 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4112 Stack->handleConstructTrait(Traits, ScopeEntry);
4115 void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
4116 switch (DKind) {
4117 case OMPD_parallel:
4118 case OMPD_parallel_for:
4119 case OMPD_parallel_for_simd:
4120 case OMPD_parallel_sections:
4121 case OMPD_parallel_master:
4122 case OMPD_parallel_masked:
4123 case OMPD_parallel_loop:
4124 case OMPD_teams:
4125 case OMPD_teams_distribute:
4126 case OMPD_teams_distribute_simd: {
4127 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4128 QualType KmpInt32PtrTy =
4129 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4130 Sema::CapturedParamNameType Params[] = {
4131 std::make_pair(".global_tid.", KmpInt32PtrTy),
4132 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4133 std::make_pair(StringRef(), QualType()) // __context with shared vars
4135 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4136 Params);
4137 break;
4139 case OMPD_target_teams:
4140 case OMPD_target_parallel:
4141 case OMPD_target_parallel_for:
4142 case OMPD_target_parallel_for_simd:
4143 case OMPD_target_teams_loop:
4144 case OMPD_target_parallel_loop:
4145 case OMPD_target_teams_distribute:
4146 case OMPD_target_teams_distribute_simd: {
4147 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4148 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4149 QualType KmpInt32PtrTy =
4150 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4151 QualType Args[] = {VoidPtrTy};
4152 FunctionProtoType::ExtProtoInfo EPI;
4153 EPI.Variadic = true;
4154 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4155 Sema::CapturedParamNameType Params[] = {
4156 std::make_pair(".global_tid.", KmpInt32Ty),
4157 std::make_pair(".part_id.", KmpInt32PtrTy),
4158 std::make_pair(".privates.", VoidPtrTy),
4159 std::make_pair(
4160 ".copy_fn.",
4161 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4162 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4163 std::make_pair(StringRef(), QualType()) // __context with shared vars
4165 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4166 Params, /*OpenMPCaptureLevel=*/0);
4167 // Mark this captured region as inlined, because we don't use outlined
4168 // function directly.
4169 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4170 AlwaysInlineAttr::CreateImplicit(
4171 Context, {}, AttributeCommonInfo::AS_Keyword,
4172 AlwaysInlineAttr::Keyword_forceinline));
4173 Sema::CapturedParamNameType ParamsTarget[] = {
4174 std::make_pair(StringRef(), QualType()) // __context with shared vars
4176 // Start a captured region for 'target' with no implicit parameters.
4177 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4178 ParamsTarget, /*OpenMPCaptureLevel=*/1);
4179 Sema::CapturedParamNameType ParamsTeamsOrParallel[] = {
4180 std::make_pair(".global_tid.", KmpInt32PtrTy),
4181 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4182 std::make_pair(StringRef(), QualType()) // __context with shared vars
4184 // Start a captured region for 'teams' or 'parallel'. Both regions have
4185 // the same implicit parameters.
4186 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4187 ParamsTeamsOrParallel, /*OpenMPCaptureLevel=*/2);
4188 break;
4190 case OMPD_target:
4191 case OMPD_target_simd: {
4192 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4193 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4194 QualType KmpInt32PtrTy =
4195 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4196 QualType Args[] = {VoidPtrTy};
4197 FunctionProtoType::ExtProtoInfo EPI;
4198 EPI.Variadic = true;
4199 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4200 Sema::CapturedParamNameType Params[] = {
4201 std::make_pair(".global_tid.", KmpInt32Ty),
4202 std::make_pair(".part_id.", KmpInt32PtrTy),
4203 std::make_pair(".privates.", VoidPtrTy),
4204 std::make_pair(
4205 ".copy_fn.",
4206 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4207 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4208 std::make_pair(StringRef(), QualType()) // __context with shared vars
4210 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4211 Params, /*OpenMPCaptureLevel=*/0);
4212 // Mark this captured region as inlined, because we don't use outlined
4213 // function directly.
4214 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4215 AlwaysInlineAttr::CreateImplicit(
4216 Context, {}, AttributeCommonInfo::AS_Keyword,
4217 AlwaysInlineAttr::Keyword_forceinline));
4218 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4219 std::make_pair(StringRef(), QualType()),
4220 /*OpenMPCaptureLevel=*/1);
4221 break;
4223 case OMPD_atomic:
4224 case OMPD_critical:
4225 case OMPD_section:
4226 case OMPD_master:
4227 case OMPD_masked:
4228 case OMPD_tile:
4229 case OMPD_unroll:
4230 break;
4231 case OMPD_loop:
4232 // TODO: 'loop' may require additional parameters depending on the binding.
4233 // Treat similar to OMPD_simd/OMPD_for for now.
4234 case OMPD_simd:
4235 case OMPD_for:
4236 case OMPD_for_simd:
4237 case OMPD_sections:
4238 case OMPD_single:
4239 case OMPD_taskgroup:
4240 case OMPD_distribute:
4241 case OMPD_distribute_simd:
4242 case OMPD_ordered:
4243 case OMPD_target_data:
4244 case OMPD_dispatch: {
4245 Sema::CapturedParamNameType Params[] = {
4246 std::make_pair(StringRef(), QualType()) // __context with shared vars
4248 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4249 Params);
4250 break;
4252 case OMPD_task: {
4253 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4254 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4255 QualType KmpInt32PtrTy =
4256 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4257 QualType Args[] = {VoidPtrTy};
4258 FunctionProtoType::ExtProtoInfo EPI;
4259 EPI.Variadic = true;
4260 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4261 Sema::CapturedParamNameType Params[] = {
4262 std::make_pair(".global_tid.", KmpInt32Ty),
4263 std::make_pair(".part_id.", KmpInt32PtrTy),
4264 std::make_pair(".privates.", VoidPtrTy),
4265 std::make_pair(
4266 ".copy_fn.",
4267 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4268 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4269 std::make_pair(StringRef(), QualType()) // __context with shared vars
4271 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4272 Params);
4273 // Mark this captured region as inlined, because we don't use outlined
4274 // function directly.
4275 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4276 AlwaysInlineAttr::CreateImplicit(
4277 Context, {}, AttributeCommonInfo::AS_Keyword,
4278 AlwaysInlineAttr::Keyword_forceinline));
4279 break;
4281 case OMPD_taskloop:
4282 case OMPD_taskloop_simd:
4283 case OMPD_master_taskloop:
4284 case OMPD_masked_taskloop:
4285 case OMPD_masked_taskloop_simd:
4286 case OMPD_master_taskloop_simd: {
4287 QualType KmpInt32Ty =
4288 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
4289 .withConst();
4290 QualType KmpUInt64Ty =
4291 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
4292 .withConst();
4293 QualType KmpInt64Ty =
4294 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
4295 .withConst();
4296 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4297 QualType KmpInt32PtrTy =
4298 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4299 QualType Args[] = {VoidPtrTy};
4300 FunctionProtoType::ExtProtoInfo EPI;
4301 EPI.Variadic = true;
4302 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4303 Sema::CapturedParamNameType Params[] = {
4304 std::make_pair(".global_tid.", KmpInt32Ty),
4305 std::make_pair(".part_id.", KmpInt32PtrTy),
4306 std::make_pair(".privates.", VoidPtrTy),
4307 std::make_pair(
4308 ".copy_fn.",
4309 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4310 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4311 std::make_pair(".lb.", KmpUInt64Ty),
4312 std::make_pair(".ub.", KmpUInt64Ty),
4313 std::make_pair(".st.", KmpInt64Ty),
4314 std::make_pair(".liter.", KmpInt32Ty),
4315 std::make_pair(".reductions.", VoidPtrTy),
4316 std::make_pair(StringRef(), QualType()) // __context with shared vars
4318 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4319 Params);
4320 // Mark this captured region as inlined, because we don't use outlined
4321 // function directly.
4322 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4323 AlwaysInlineAttr::CreateImplicit(
4324 Context, {}, AttributeCommonInfo::AS_Keyword,
4325 AlwaysInlineAttr::Keyword_forceinline));
4326 break;
4328 case OMPD_parallel_masked_taskloop:
4329 case OMPD_parallel_masked_taskloop_simd:
4330 case OMPD_parallel_master_taskloop:
4331 case OMPD_parallel_master_taskloop_simd: {
4332 QualType KmpInt32Ty =
4333 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
4334 .withConst();
4335 QualType KmpUInt64Ty =
4336 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
4337 .withConst();
4338 QualType KmpInt64Ty =
4339 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
4340 .withConst();
4341 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4342 QualType KmpInt32PtrTy =
4343 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4344 Sema::CapturedParamNameType ParamsParallel[] = {
4345 std::make_pair(".global_tid.", KmpInt32PtrTy),
4346 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4347 std::make_pair(StringRef(), QualType()) // __context with shared vars
4349 // Start a captured region for 'parallel'.
4350 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4351 ParamsParallel, /*OpenMPCaptureLevel=*/0);
4352 QualType Args[] = {VoidPtrTy};
4353 FunctionProtoType::ExtProtoInfo EPI;
4354 EPI.Variadic = true;
4355 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4356 Sema::CapturedParamNameType Params[] = {
4357 std::make_pair(".global_tid.", KmpInt32Ty),
4358 std::make_pair(".part_id.", KmpInt32PtrTy),
4359 std::make_pair(".privates.", VoidPtrTy),
4360 std::make_pair(
4361 ".copy_fn.",
4362 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4363 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4364 std::make_pair(".lb.", KmpUInt64Ty),
4365 std::make_pair(".ub.", KmpUInt64Ty),
4366 std::make_pair(".st.", KmpInt64Ty),
4367 std::make_pair(".liter.", KmpInt32Ty),
4368 std::make_pair(".reductions.", VoidPtrTy),
4369 std::make_pair(StringRef(), QualType()) // __context with shared vars
4371 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4372 Params, /*OpenMPCaptureLevel=*/1);
4373 // Mark this captured region as inlined, because we don't use outlined
4374 // function directly.
4375 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4376 AlwaysInlineAttr::CreateImplicit(
4377 Context, {}, AttributeCommonInfo::AS_Keyword,
4378 AlwaysInlineAttr::Keyword_forceinline));
4379 break;
4381 case OMPD_distribute_parallel_for_simd:
4382 case OMPD_distribute_parallel_for: {
4383 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4384 QualType KmpInt32PtrTy =
4385 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4386 Sema::CapturedParamNameType Params[] = {
4387 std::make_pair(".global_tid.", KmpInt32PtrTy),
4388 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4389 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4390 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4391 std::make_pair(StringRef(), QualType()) // __context with shared vars
4393 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4394 Params);
4395 break;
4397 case OMPD_target_teams_distribute_parallel_for:
4398 case OMPD_target_teams_distribute_parallel_for_simd: {
4399 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4400 QualType KmpInt32PtrTy =
4401 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4402 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4404 QualType Args[] = {VoidPtrTy};
4405 FunctionProtoType::ExtProtoInfo EPI;
4406 EPI.Variadic = true;
4407 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4408 Sema::CapturedParamNameType Params[] = {
4409 std::make_pair(".global_tid.", KmpInt32Ty),
4410 std::make_pair(".part_id.", KmpInt32PtrTy),
4411 std::make_pair(".privates.", VoidPtrTy),
4412 std::make_pair(
4413 ".copy_fn.",
4414 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4415 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4416 std::make_pair(StringRef(), QualType()) // __context with shared vars
4418 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4419 Params, /*OpenMPCaptureLevel=*/0);
4420 // Mark this captured region as inlined, because we don't use outlined
4421 // function directly.
4422 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4423 AlwaysInlineAttr::CreateImplicit(
4424 Context, {}, AttributeCommonInfo::AS_Keyword,
4425 AlwaysInlineAttr::Keyword_forceinline));
4426 Sema::CapturedParamNameType ParamsTarget[] = {
4427 std::make_pair(StringRef(), QualType()) // __context with shared vars
4429 // Start a captured region for 'target' with no implicit parameters.
4430 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4431 ParamsTarget, /*OpenMPCaptureLevel=*/1);
4433 Sema::CapturedParamNameType ParamsTeams[] = {
4434 std::make_pair(".global_tid.", KmpInt32PtrTy),
4435 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4436 std::make_pair(StringRef(), QualType()) // __context with shared vars
4438 // Start a captured region for 'target' with no implicit parameters.
4439 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4440 ParamsTeams, /*OpenMPCaptureLevel=*/2);
4442 Sema::CapturedParamNameType ParamsParallel[] = {
4443 std::make_pair(".global_tid.", KmpInt32PtrTy),
4444 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4445 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4446 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4447 std::make_pair(StringRef(), QualType()) // __context with shared vars
4449 // Start a captured region for 'teams' or 'parallel'. Both regions have
4450 // the same implicit parameters.
4451 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4452 ParamsParallel, /*OpenMPCaptureLevel=*/3);
4453 break;
4456 case OMPD_teams_loop: {
4457 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4458 QualType KmpInt32PtrTy =
4459 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4461 Sema::CapturedParamNameType ParamsTeams[] = {
4462 std::make_pair(".global_tid.", KmpInt32PtrTy),
4463 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4464 std::make_pair(StringRef(), QualType()) // __context with shared vars
4466 // Start a captured region for 'teams'.
4467 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4468 ParamsTeams, /*OpenMPCaptureLevel=*/0);
4469 break;
4472 case OMPD_teams_distribute_parallel_for:
4473 case OMPD_teams_distribute_parallel_for_simd: {
4474 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4475 QualType KmpInt32PtrTy =
4476 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4478 Sema::CapturedParamNameType ParamsTeams[] = {
4479 std::make_pair(".global_tid.", KmpInt32PtrTy),
4480 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4481 std::make_pair(StringRef(), QualType()) // __context with shared vars
4483 // Start a captured region for 'target' with no implicit parameters.
4484 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4485 ParamsTeams, /*OpenMPCaptureLevel=*/0);
4487 Sema::CapturedParamNameType ParamsParallel[] = {
4488 std::make_pair(".global_tid.", KmpInt32PtrTy),
4489 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4490 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4491 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4492 std::make_pair(StringRef(), QualType()) // __context with shared vars
4494 // Start a captured region for 'teams' or 'parallel'. Both regions have
4495 // the same implicit parameters.
4496 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4497 ParamsParallel, /*OpenMPCaptureLevel=*/1);
4498 break;
4500 case OMPD_target_update:
4501 case OMPD_target_enter_data:
4502 case OMPD_target_exit_data: {
4503 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4504 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4505 QualType KmpInt32PtrTy =
4506 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4507 QualType Args[] = {VoidPtrTy};
4508 FunctionProtoType::ExtProtoInfo EPI;
4509 EPI.Variadic = true;
4510 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4511 Sema::CapturedParamNameType Params[] = {
4512 std::make_pair(".global_tid.", KmpInt32Ty),
4513 std::make_pair(".part_id.", KmpInt32PtrTy),
4514 std::make_pair(".privates.", VoidPtrTy),
4515 std::make_pair(
4516 ".copy_fn.",
4517 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4518 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4519 std::make_pair(StringRef(), QualType()) // __context with shared vars
4521 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4522 Params);
4523 // Mark this captured region as inlined, because we don't use outlined
4524 // function directly.
4525 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4526 AlwaysInlineAttr::CreateImplicit(
4527 Context, {}, AttributeCommonInfo::AS_Keyword,
4528 AlwaysInlineAttr::Keyword_forceinline));
4529 break;
4531 case OMPD_threadprivate:
4532 case OMPD_allocate:
4533 case OMPD_taskyield:
4534 case OMPD_barrier:
4535 case OMPD_taskwait:
4536 case OMPD_cancellation_point:
4537 case OMPD_cancel:
4538 case OMPD_flush:
4539 case OMPD_depobj:
4540 case OMPD_scan:
4541 case OMPD_declare_reduction:
4542 case OMPD_declare_mapper:
4543 case OMPD_declare_simd:
4544 case OMPD_declare_target:
4545 case OMPD_end_declare_target:
4546 case OMPD_requires:
4547 case OMPD_declare_variant:
4548 case OMPD_begin_declare_variant:
4549 case OMPD_end_declare_variant:
4550 case OMPD_metadirective:
4551 llvm_unreachable("OpenMP Directive is not allowed");
4552 case OMPD_unknown:
4553 default:
4554 llvm_unreachable("Unknown OpenMP directive");
4556 DSAStack->setContext(CurContext);
4557 handleDeclareVariantConstructTrait(DSAStack, DKind, /* ScopeEntry */ true);
4560 int Sema::getNumberOfConstructScopes(unsigned Level) const {
4561 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4564 int Sema::getOpenMPCaptureLevels(OpenMPDirectiveKind DKind) {
4565 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4566 getOpenMPCaptureRegions(CaptureRegions, DKind);
4567 return CaptureRegions.size();
4570 static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
4571 Expr *CaptureExpr, bool WithInit,
4572 DeclContext *CurContext,
4573 bool AsExpression) {
4574 assert(CaptureExpr);
4575 ASTContext &C = S.getASTContext();
4576 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4577 QualType Ty = Init->getType();
4578 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4579 if (S.getLangOpts().CPlusPlus) {
4580 Ty = C.getLValueReferenceType(Ty);
4581 } else {
4582 Ty = C.getPointerType(Ty);
4583 ExprResult Res =
4584 S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init);
4585 if (!Res.isUsable())
4586 return nullptr;
4587 Init = Res.get();
4589 WithInit = true;
4591 auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty,
4592 CaptureExpr->getBeginLoc());
4593 if (!WithInit)
4594 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
4595 CurContext->addHiddenDecl(CED);
4596 Sema::TentativeAnalysisScope Trap(S);
4597 S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
4598 return CED;
4601 static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4602 bool WithInit) {
4603 OMPCapturedExprDecl *CD;
4604 if (VarDecl *VD = S.isOpenMPCapturedDecl(D))
4605 CD = cast<OMPCapturedExprDecl>(VD);
4606 else
4607 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
4608 S.CurContext,
4609 /*AsExpression=*/false);
4610 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4611 CaptureExpr->getExprLoc());
4614 static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref) {
4615 CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get();
4616 if (!Ref) {
4617 OMPCapturedExprDecl *CD = buildCaptureDecl(
4618 S, &S.getASTContext().Idents.get(".capture_expr."), CaptureExpr,
4619 /*WithInit=*/true, S.CurContext, /*AsExpression=*/true);
4620 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4621 CaptureExpr->getExprLoc());
4623 ExprResult Res = Ref;
4624 if (!S.getLangOpts().CPlusPlus &&
4625 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4626 Ref->getType()->isPointerType()) {
4627 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
4628 if (!Res.isUsable())
4629 return ExprError();
4631 return S.DefaultLvalueConversion(Res.get());
4634 namespace {
4635 // OpenMP directives parsed in this section are represented as a
4636 // CapturedStatement with an associated statement. If a syntax error
4637 // is detected during the parsing of the associated statement, the
4638 // compiler must abort processing and close the CapturedStatement.
4640 // Combined directives such as 'target parallel' have more than one
4641 // nested CapturedStatements. This RAII ensures that we unwind out
4642 // of all the nested CapturedStatements when an error is found.
4643 class CaptureRegionUnwinderRAII {
4644 private:
4645 Sema &S;
4646 bool &ErrorFound;
4647 OpenMPDirectiveKind DKind = OMPD_unknown;
4649 public:
4650 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4651 OpenMPDirectiveKind DKind)
4652 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4653 ~CaptureRegionUnwinderRAII() {
4654 if (ErrorFound) {
4655 int ThisCaptureLevel = S.getOpenMPCaptureLevels(DKind);
4656 while (--ThisCaptureLevel >= 0)
4657 S.ActOnCapturedRegionError();
4661 } // namespace
4663 void Sema::tryCaptureOpenMPLambdas(ValueDecl *V) {
4664 // Capture variables captured by reference in lambdas for target-based
4665 // directives.
4666 if (!CurContext->isDependentContext() &&
4667 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4668 isOpenMPTargetDataManagementDirective(
4669 DSAStack->getCurrentDirective()))) {
4670 QualType Type = V->getType();
4671 if (const auto *RD = Type.getCanonicalType()
4672 .getNonReferenceType()
4673 ->getAsCXXRecordDecl()) {
4674 bool SavedForceCaptureByReferenceInTargetExecutable =
4675 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4676 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4677 /*V=*/true);
4678 if (RD->isLambda()) {
4679 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4680 FieldDecl *ThisCapture;
4681 RD->getCaptureFields(Captures, ThisCapture);
4682 for (const LambdaCapture &LC : RD->captures()) {
4683 if (LC.getCaptureKind() == LCK_ByRef) {
4684 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4685 DeclContext *VDC = VD->getDeclContext();
4686 if (!VDC->Encloses(CurContext))
4687 continue;
4688 MarkVariableReferenced(LC.getLocation(), VD);
4689 } else if (LC.getCaptureKind() == LCK_This) {
4690 QualType ThisTy = getCurrentThisType();
4691 if (!ThisTy.isNull() &&
4692 Context.typesAreCompatible(ThisTy, ThisCapture->getType()))
4693 CheckCXXThisCapture(LC.getLocation());
4697 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4698 SavedForceCaptureByReferenceInTargetExecutable);
4703 static bool checkOrderedOrderSpecified(Sema &S,
4704 const ArrayRef<OMPClause *> Clauses) {
4705 const OMPOrderedClause *Ordered = nullptr;
4706 const OMPOrderClause *Order = nullptr;
4708 for (const OMPClause *Clause : Clauses) {
4709 if (Clause->getClauseKind() == OMPC_ordered)
4710 Ordered = cast<OMPOrderedClause>(Clause);
4711 else if (Clause->getClauseKind() == OMPC_order) {
4712 Order = cast<OMPOrderClause>(Clause);
4713 if (Order->getKind() != OMPC_ORDER_concurrent)
4714 Order = nullptr;
4716 if (Ordered && Order)
4717 break;
4720 if (Ordered && Order) {
4721 S.Diag(Order->getKindKwLoc(),
4722 diag::err_omp_simple_clause_incompatible_with_ordered)
4723 << getOpenMPClauseName(OMPC_order)
4724 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
4725 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4726 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4727 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4728 return true;
4730 return false;
4733 StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
4734 ArrayRef<OMPClause *> Clauses) {
4735 handleDeclareVariantConstructTrait(DSAStack, DSAStack->getCurrentDirective(),
4736 /* ScopeEntry */ false);
4737 if (DSAStack->getCurrentDirective() == OMPD_atomic ||
4738 DSAStack->getCurrentDirective() == OMPD_critical ||
4739 DSAStack->getCurrentDirective() == OMPD_section ||
4740 DSAStack->getCurrentDirective() == OMPD_master ||
4741 DSAStack->getCurrentDirective() == OMPD_masked)
4742 return S;
4744 bool ErrorFound = false;
4745 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4746 *this, ErrorFound, DSAStack->getCurrentDirective());
4747 if (!S.isUsable()) {
4748 ErrorFound = true;
4749 return StmtError();
4752 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4753 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4754 OMPOrderedClause *OC = nullptr;
4755 OMPScheduleClause *SC = nullptr;
4756 SmallVector<const OMPLinearClause *, 4> LCs;
4757 SmallVector<const OMPClauseWithPreInit *, 4> PICs;
4758 // This is required for proper codegen.
4759 for (OMPClause *Clause : Clauses) {
4760 if (!LangOpts.OpenMPSimd &&
4761 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4762 DSAStack->getCurrentDirective() == OMPD_target) &&
4763 Clause->getClauseKind() == OMPC_in_reduction) {
4764 // Capture taskgroup task_reduction descriptors inside the tasking regions
4765 // with the corresponding in_reduction items.
4766 auto *IRC = cast<OMPInReductionClause>(Clause);
4767 for (Expr *E : IRC->taskgroup_descriptors())
4768 if (E)
4769 MarkDeclarationsReferencedInExpr(E);
4771 if (isOpenMPPrivate(Clause->getClauseKind()) ||
4772 Clause->getClauseKind() == OMPC_copyprivate ||
4773 (getLangOpts().OpenMPUseTLS &&
4774 getASTContext().getTargetInfo().isTLSSupported() &&
4775 Clause->getClauseKind() == OMPC_copyin)) {
4776 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4777 // Mark all variables in private list clauses as used in inner region.
4778 for (Stmt *VarRef : Clause->children()) {
4779 if (auto *E = cast_or_null<Expr>(VarRef)) {
4780 MarkDeclarationsReferencedInExpr(E);
4783 DSAStack->setForceVarCapturing(/*V=*/false);
4784 } else if (isOpenMPLoopTransformationDirective(
4785 DSAStack->getCurrentDirective())) {
4786 assert(CaptureRegions.empty() &&
4787 "No captured regions in loop transformation directives.");
4788 } else if (CaptureRegions.size() > 1 ||
4789 CaptureRegions.back() != OMPD_unknown) {
4790 if (auto *C = OMPClauseWithPreInit::get(Clause))
4791 PICs.push_back(C);
4792 if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
4793 if (Expr *E = C->getPostUpdateExpr())
4794 MarkDeclarationsReferencedInExpr(E);
4797 if (Clause->getClauseKind() == OMPC_schedule)
4798 SC = cast<OMPScheduleClause>(Clause);
4799 else if (Clause->getClauseKind() == OMPC_ordered)
4800 OC = cast<OMPOrderedClause>(Clause);
4801 else if (Clause->getClauseKind() == OMPC_linear)
4802 LCs.push_back(cast<OMPLinearClause>(Clause));
4804 // Capture allocator expressions if used.
4805 for (Expr *E : DSAStack->getInnerAllocators())
4806 MarkDeclarationsReferencedInExpr(E);
4807 // OpenMP, 2.7.1 Loop Construct, Restrictions
4808 // The nonmonotonic modifier cannot be specified if an ordered clause is
4809 // specified.
4810 if (SC &&
4811 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4812 SC->getSecondScheduleModifier() ==
4813 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4814 OC) {
4815 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4816 ? SC->getFirstScheduleModifierLoc()
4817 : SC->getSecondScheduleModifierLoc(),
4818 diag::err_omp_simple_clause_incompatible_with_ordered)
4819 << getOpenMPClauseName(OMPC_schedule)
4820 << getOpenMPSimpleClauseTypeName(OMPC_schedule,
4821 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4822 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4823 ErrorFound = true;
4825 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4826 // If an order(concurrent) clause is present, an ordered clause may not appear
4827 // on the same directive.
4828 if (checkOrderedOrderSpecified(*this, Clauses))
4829 ErrorFound = true;
4830 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4831 for (const OMPLinearClause *C : LCs) {
4832 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
4833 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4835 ErrorFound = true;
4837 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4838 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4839 OC->getNumForLoops()) {
4840 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4841 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
4842 ErrorFound = true;
4844 if (ErrorFound) {
4845 return StmtError();
4847 StmtResult SR = S;
4848 unsigned CompletedRegions = 0;
4849 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
4850 // Mark all variables in private list clauses as used in inner region.
4851 // Required for proper codegen of combined directives.
4852 // TODO: add processing for other clauses.
4853 if (ThisCaptureRegion != OMPD_unknown) {
4854 for (const clang::OMPClauseWithPreInit *C : PICs) {
4855 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4856 // Find the particular capture region for the clause if the
4857 // directive is a combined one with multiple capture regions.
4858 // If the directive is not a combined one, the capture region
4859 // associated with the clause is OMPD_unknown and is generated
4860 // only once.
4861 if (CaptureRegion == ThisCaptureRegion ||
4862 CaptureRegion == OMPD_unknown) {
4863 if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
4864 for (Decl *D : DS->decls())
4865 MarkVariableReferenced(D->getLocation(), cast<VarDecl>(D));
4870 if (ThisCaptureRegion == OMPD_target) {
4871 // Capture allocator traits in the target region. They are used implicitly
4872 // and, thus, are not captured by default.
4873 for (OMPClause *C : Clauses) {
4874 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) {
4875 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4876 ++I) {
4877 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4878 if (Expr *E = D.AllocatorTraits)
4879 MarkDeclarationsReferencedInExpr(E);
4881 continue;
4885 if (ThisCaptureRegion == OMPD_parallel) {
4886 // Capture temp arrays for inscan reductions and locals in aligned
4887 // clauses.
4888 for (OMPClause *C : Clauses) {
4889 if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
4890 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4891 continue;
4892 for (Expr *E : RC->copy_array_temps())
4893 MarkDeclarationsReferencedInExpr(E);
4895 if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
4896 for (Expr *E : AC->varlists())
4897 MarkDeclarationsReferencedInExpr(E);
4901 if (++CompletedRegions == CaptureRegions.size())
4902 DSAStack->setBodyComplete();
4903 SR = ActOnCapturedRegionEnd(SR.get());
4905 return SR;
4908 static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4909 OpenMPDirectiveKind CancelRegion,
4910 SourceLocation StartLoc) {
4911 // CancelRegion is only needed for cancel and cancellation_point.
4912 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4913 return false;
4915 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4916 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4917 return false;
4919 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4920 << getOpenMPDirectiveName(CancelRegion);
4921 return true;
4924 static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
4925 OpenMPDirectiveKind CurrentRegion,
4926 const DeclarationNameInfo &CurrentName,
4927 OpenMPDirectiveKind CancelRegion,
4928 OpenMPBindClauseKind BindKind,
4929 SourceLocation StartLoc) {
4930 if (Stack->getCurScope()) {
4931 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
4932 OpenMPDirectiveKind OffendingRegion = ParentRegion;
4933 bool NestingProhibited = false;
4934 bool CloseNesting = true;
4935 bool OrphanSeen = false;
4936 enum {
4937 NoRecommend,
4938 ShouldBeInParallelRegion,
4939 ShouldBeInOrderedRegion,
4940 ShouldBeInTargetRegion,
4941 ShouldBeInTeamsRegion,
4942 ShouldBeInLoopSimdRegion,
4943 } Recommend = NoRecommend;
4944 if (isOpenMPSimdDirective(ParentRegion) &&
4945 ((SemaRef.LangOpts.OpenMP <= 45 && CurrentRegion != OMPD_ordered) ||
4946 (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion != OMPD_ordered &&
4947 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
4948 CurrentRegion != OMPD_scan))) {
4949 // OpenMP [2.16, Nesting of Regions]
4950 // OpenMP constructs may not be nested inside a simd region.
4951 // OpenMP [2.8.1,simd Construct, Restrictions]
4952 // An ordered construct with the simd clause is the only OpenMP
4953 // construct that can appear in the simd region.
4954 // Allowing a SIMD construct nested in another SIMD construct is an
4955 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
4956 // message.
4957 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
4958 // The only OpenMP constructs that can be encountered during execution of
4959 // a simd region are the atomic construct, the loop construct, the simd
4960 // construct and the ordered construct with the simd clause.
4961 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
4962 ? diag::err_omp_prohibited_region_simd
4963 : diag::warn_omp_nesting_simd)
4964 << (SemaRef.LangOpts.OpenMP >= 50 ? 1 : 0);
4965 return CurrentRegion != OMPD_simd;
4967 if (ParentRegion == OMPD_atomic) {
4968 // OpenMP [2.16, Nesting of Regions]
4969 // OpenMP constructs may not be nested inside an atomic region.
4970 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
4971 return true;
4973 if (CurrentRegion == OMPD_section) {
4974 // OpenMP [2.7.2, sections Construct, Restrictions]
4975 // Orphaned section directives are prohibited. That is, the section
4976 // directives must appear within the sections construct and must not be
4977 // encountered elsewhere in the sections region.
4978 if (ParentRegion != OMPD_sections &&
4979 ParentRegion != OMPD_parallel_sections) {
4980 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
4981 << (ParentRegion != OMPD_unknown)
4982 << getOpenMPDirectiveName(ParentRegion);
4983 return true;
4985 return false;
4987 // Allow some constructs (except teams and cancellation constructs) to be
4988 // orphaned (they could be used in functions, called from OpenMP regions
4989 // with the required preconditions).
4990 if (ParentRegion == OMPD_unknown &&
4991 !isOpenMPNestingTeamsDirective(CurrentRegion) &&
4992 CurrentRegion != OMPD_cancellation_point &&
4993 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
4994 return false;
4995 if (CurrentRegion == OMPD_cancellation_point ||
4996 CurrentRegion == OMPD_cancel) {
4997 // OpenMP [2.16, Nesting of Regions]
4998 // A cancellation point construct for which construct-type-clause is
4999 // taskgroup must be nested inside a task construct. A cancellation
5000 // point construct for which construct-type-clause is not taskgroup must
5001 // be closely nested inside an OpenMP construct that matches the type
5002 // specified in construct-type-clause.
5003 // A cancel construct for which construct-type-clause is taskgroup must be
5004 // nested inside a task construct. A cancel construct for which
5005 // construct-type-clause is not taskgroup must be closely nested inside an
5006 // OpenMP construct that matches the type specified in
5007 // construct-type-clause.
5008 NestingProhibited =
5009 !((CancelRegion == OMPD_parallel &&
5010 (ParentRegion == OMPD_parallel ||
5011 ParentRegion == OMPD_target_parallel)) ||
5012 (CancelRegion == OMPD_for &&
5013 (ParentRegion == OMPD_for || ParentRegion == OMPD_parallel_for ||
5014 ParentRegion == OMPD_target_parallel_for ||
5015 ParentRegion == OMPD_distribute_parallel_for ||
5016 ParentRegion == OMPD_teams_distribute_parallel_for ||
5017 ParentRegion == OMPD_target_teams_distribute_parallel_for)) ||
5018 (CancelRegion == OMPD_taskgroup &&
5019 (ParentRegion == OMPD_task ||
5020 (SemaRef.getLangOpts().OpenMP >= 50 &&
5021 (ParentRegion == OMPD_taskloop ||
5022 ParentRegion == OMPD_master_taskloop ||
5023 ParentRegion == OMPD_masked_taskloop ||
5024 ParentRegion == OMPD_parallel_masked_taskloop ||
5025 ParentRegion == OMPD_parallel_master_taskloop)))) ||
5026 (CancelRegion == OMPD_sections &&
5027 (ParentRegion == OMPD_section || ParentRegion == OMPD_sections ||
5028 ParentRegion == OMPD_parallel_sections)));
5029 OrphanSeen = ParentRegion == OMPD_unknown;
5030 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5031 // OpenMP 5.1 [2.22, Nesting of Regions]
5032 // A masked region may not be closely nested inside a worksharing, loop,
5033 // atomic, task, or taskloop region.
5034 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5035 isOpenMPGenericLoopDirective(ParentRegion) ||
5036 isOpenMPTaskingDirective(ParentRegion);
5037 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
5038 // OpenMP [2.16, Nesting of Regions]
5039 // A critical region may not be nested (closely or otherwise) inside a
5040 // critical region with the same name. Note that this restriction is not
5041 // sufficient to prevent deadlock.
5042 SourceLocation PreviousCriticalLoc;
5043 bool DeadLock = Stack->hasDirective(
5044 [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
5045 const DeclarationNameInfo &DNI,
5046 SourceLocation Loc) {
5047 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
5048 PreviousCriticalLoc = Loc;
5049 return true;
5051 return false;
5053 false /* skip top directive */);
5054 if (DeadLock) {
5055 SemaRef.Diag(StartLoc,
5056 diag::err_omp_prohibited_region_critical_same_name)
5057 << CurrentName.getName();
5058 if (PreviousCriticalLoc.isValid())
5059 SemaRef.Diag(PreviousCriticalLoc,
5060 diag::note_omp_previous_critical_region);
5061 return true;
5063 } else if (CurrentRegion == OMPD_barrier) {
5064 // OpenMP 5.1 [2.22, Nesting of Regions]
5065 // A barrier region may not be closely nested inside a worksharing, loop,
5066 // task, taskloop, critical, ordered, atomic, or masked region.
5067 NestingProhibited =
5068 isOpenMPWorksharingDirective(ParentRegion) ||
5069 isOpenMPGenericLoopDirective(ParentRegion) ||
5070 isOpenMPTaskingDirective(ParentRegion) ||
5071 ParentRegion == OMPD_master || ParentRegion == OMPD_masked ||
5072 ParentRegion == OMPD_parallel_master ||
5073 ParentRegion == OMPD_parallel_masked ||
5074 ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
5075 } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
5076 !isOpenMPParallelDirective(CurrentRegion) &&
5077 !isOpenMPTeamsDirective(CurrentRegion)) {
5078 // OpenMP 5.1 [2.22, Nesting of Regions]
5079 // A loop region that binds to a parallel region or a worksharing region
5080 // may not be closely nested inside a worksharing, loop, task, taskloop,
5081 // critical, ordered, atomic, or masked region.
5082 NestingProhibited =
5083 isOpenMPWorksharingDirective(ParentRegion) ||
5084 isOpenMPGenericLoopDirective(ParentRegion) ||
5085 isOpenMPTaskingDirective(ParentRegion) ||
5086 ParentRegion == OMPD_master || ParentRegion == OMPD_masked ||
5087 ParentRegion == OMPD_parallel_master ||
5088 ParentRegion == OMPD_parallel_masked ||
5089 ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
5090 Recommend = ShouldBeInParallelRegion;
5091 } else if (CurrentRegion == OMPD_ordered) {
5092 // OpenMP [2.16, Nesting of Regions]
5093 // An ordered region may not be closely nested inside a critical,
5094 // atomic, or explicit task region.
5095 // An ordered region must be closely nested inside a loop region (or
5096 // parallel loop region) with an ordered clause.
5097 // OpenMP [2.8.1,simd Construct, Restrictions]
5098 // An ordered construct with the simd clause is the only OpenMP construct
5099 // that can appear in the simd region.
5100 NestingProhibited = ParentRegion == OMPD_critical ||
5101 isOpenMPTaskingDirective(ParentRegion) ||
5102 !(isOpenMPSimdDirective(ParentRegion) ||
5103 Stack->isParentOrderedRegion());
5104 Recommend = ShouldBeInOrderedRegion;
5105 } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
5106 // OpenMP [2.16, Nesting of Regions]
5107 // If specified, a teams construct must be contained within a target
5108 // construct.
5109 NestingProhibited =
5110 (SemaRef.LangOpts.OpenMP <= 45 && ParentRegion != OMPD_target) ||
5111 (SemaRef.LangOpts.OpenMP >= 50 && ParentRegion != OMPD_unknown &&
5112 ParentRegion != OMPD_target);
5113 OrphanSeen = ParentRegion == OMPD_unknown;
5114 Recommend = ShouldBeInTargetRegion;
5115 } else if (CurrentRegion == OMPD_scan) {
5116 // OpenMP [2.16, Nesting of Regions]
5117 // If specified, a teams construct must be contained within a target
5118 // construct.
5119 NestingProhibited =
5120 SemaRef.LangOpts.OpenMP < 50 ||
5121 (ParentRegion != OMPD_simd && ParentRegion != OMPD_for &&
5122 ParentRegion != OMPD_for_simd && ParentRegion != OMPD_parallel_for &&
5123 ParentRegion != OMPD_parallel_for_simd);
5124 OrphanSeen = ParentRegion == OMPD_unknown;
5125 Recommend = ShouldBeInLoopSimdRegion;
5127 if (!NestingProhibited &&
5128 !isOpenMPTargetExecutionDirective(CurrentRegion) &&
5129 !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
5130 (ParentRegion == OMPD_teams || ParentRegion == OMPD_target_teams)) {
5131 // OpenMP [5.1, 2.22, Nesting of Regions]
5132 // distribute, distribute simd, distribute parallel worksharing-loop,
5133 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5134 // including any parallel regions arising from combined constructs,
5135 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5136 // only OpenMP regions that may be strictly nested inside the teams
5137 // region.
5139 // As an extension, we permit atomic within teams as well.
5140 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
5141 !isOpenMPDistributeDirective(CurrentRegion) &&
5142 CurrentRegion != OMPD_loop &&
5143 !(SemaRef.getLangOpts().OpenMPExtensions &&
5144 CurrentRegion == OMPD_atomic);
5145 Recommend = ShouldBeInParallelRegion;
5147 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5148 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5149 // If the bind clause is present on the loop construct and binding is
5150 // teams then the corresponding loop region must be strictly nested inside
5151 // a teams region.
5152 NestingProhibited = BindKind == OMPC_BIND_teams &&
5153 ParentRegion != OMPD_teams &&
5154 ParentRegion != OMPD_target_teams;
5155 Recommend = ShouldBeInTeamsRegion;
5157 if (!NestingProhibited &&
5158 isOpenMPNestingDistributeDirective(CurrentRegion)) {
5159 // OpenMP 4.5 [2.17 Nesting of Regions]
5160 // The region associated with the distribute construct must be strictly
5161 // nested inside a teams region
5162 NestingProhibited =
5163 (ParentRegion != OMPD_teams && ParentRegion != OMPD_target_teams);
5164 Recommend = ShouldBeInTeamsRegion;
5166 if (!NestingProhibited &&
5167 (isOpenMPTargetExecutionDirective(CurrentRegion) ||
5168 isOpenMPTargetDataManagementDirective(CurrentRegion))) {
5169 // OpenMP 4.5 [2.17 Nesting of Regions]
5170 // If a target, target update, target data, target enter data, or
5171 // target exit data construct is encountered during execution of a
5172 // target region, the behavior is unspecified.
5173 NestingProhibited = Stack->hasDirective(
5174 [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5175 SourceLocation) {
5176 if (isOpenMPTargetExecutionDirective(K)) {
5177 OffendingRegion = K;
5178 return true;
5180 return false;
5182 false /* don't skip top directive */);
5183 CloseNesting = false;
5185 if (NestingProhibited) {
5186 if (OrphanSeen) {
5187 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5188 << getOpenMPDirectiveName(CurrentRegion) << Recommend;
5189 } else {
5190 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5191 << CloseNesting << getOpenMPDirectiveName(OffendingRegion)
5192 << Recommend << getOpenMPDirectiveName(CurrentRegion);
5194 return true;
5197 return false;
5200 struct Kind2Unsigned {
5201 using argument_type = OpenMPDirectiveKind;
5202 unsigned operator()(argument_type DK) { return unsigned(DK); }
5204 static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind,
5205 ArrayRef<OMPClause *> Clauses,
5206 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5207 bool ErrorFound = false;
5208 unsigned NamedModifiersNumber = 0;
5209 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5210 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5211 SmallVector<SourceLocation, 4> NameModifierLoc;
5212 for (const OMPClause *C : Clauses) {
5213 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
5214 // At most one if clause without a directive-name-modifier can appear on
5215 // the directive.
5216 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5217 if (FoundNameModifiers[CurNM]) {
5218 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5219 << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if)
5220 << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM);
5221 ErrorFound = true;
5222 } else if (CurNM != OMPD_unknown) {
5223 NameModifierLoc.push_back(IC->getNameModifierLoc());
5224 ++NamedModifiersNumber;
5226 FoundNameModifiers[CurNM] = IC;
5227 if (CurNM == OMPD_unknown)
5228 continue;
5229 // Check if the specified name modifier is allowed for the current
5230 // directive.
5231 // At most one if clause with the particular directive-name-modifier can
5232 // appear on the directive.
5233 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5234 S.Diag(IC->getNameModifierLoc(),
5235 diag::err_omp_wrong_if_directive_name_modifier)
5236 << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind);
5237 ErrorFound = true;
5241 // If any if clause on the directive includes a directive-name-modifier then
5242 // all if clauses on the directive must include a directive-name-modifier.
5243 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5244 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5245 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5246 diag::err_omp_no_more_if_clause);
5247 } else {
5248 std::string Values;
5249 std::string Sep(", ");
5250 unsigned AllowedCnt = 0;
5251 unsigned TotalAllowedNum =
5252 AllowedNameModifiers.size() - NamedModifiersNumber;
5253 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5254 ++Cnt) {
5255 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5256 if (!FoundNameModifiers[NM]) {
5257 Values += "'";
5258 Values += getOpenMPDirectiveName(NM);
5259 Values += "'";
5260 if (AllowedCnt + 2 == TotalAllowedNum)
5261 Values += " or ";
5262 else if (AllowedCnt + 1 != TotalAllowedNum)
5263 Values += Sep;
5264 ++AllowedCnt;
5267 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5268 diag::err_omp_unnamed_if_clause)
5269 << (TotalAllowedNum > 1) << Values;
5271 for (SourceLocation Loc : NameModifierLoc) {
5272 S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5274 ErrorFound = true;
5276 return ErrorFound;
5279 static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr,
5280 SourceLocation &ELoc,
5281 SourceRange &ERange,
5282 bool AllowArraySection,
5283 StringRef DiagType) {
5284 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5285 RefExpr->containsUnexpandedParameterPack())
5286 return std::make_pair(nullptr, true);
5288 // OpenMP [3.1, C/C++]
5289 // A list item is a variable name.
5290 // OpenMP [2.9.3.3, Restrictions, p.1]
5291 // A variable that is part of another variable (as an array or
5292 // structure element) cannot appear in a private clause.
5293 RefExpr = RefExpr->IgnoreParens();
5294 enum {
5295 NoArrayExpr = -1,
5296 ArraySubscript = 0,
5297 OMPArraySection = 1
5298 } IsArrayExpr = NoArrayExpr;
5299 if (AllowArraySection) {
5300 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5301 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5302 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5303 Base = TempASE->getBase()->IgnoreParenImpCasts();
5304 RefExpr = Base;
5305 IsArrayExpr = ArraySubscript;
5306 } else if (auto *OASE = dyn_cast_or_null<OMPArraySectionExpr>(RefExpr)) {
5307 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5308 while (auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
5309 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5310 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5311 Base = TempASE->getBase()->IgnoreParenImpCasts();
5312 RefExpr = Base;
5313 IsArrayExpr = OMPArraySection;
5316 ELoc = RefExpr->getExprLoc();
5317 ERange = RefExpr->getSourceRange();
5318 RefExpr = RefExpr->IgnoreParenImpCasts();
5319 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5320 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5321 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5322 (S.getCurrentThisType().isNull() || !ME ||
5323 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5324 !isa<FieldDecl>(ME->getMemberDecl()))) {
5325 if (IsArrayExpr != NoArrayExpr) {
5326 S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5327 << IsArrayExpr << ERange;
5328 } else if (!DiagType.empty()) {
5329 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5330 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5331 : 0;
5332 S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5333 << DiagSelect << DiagType << ERange;
5334 } else {
5335 S.Diag(ELoc,
5336 AllowArraySection
5337 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5338 : diag::err_omp_expected_var_name_member_expr)
5339 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5341 return std::make_pair(nullptr, false);
5343 return std::make_pair(
5344 getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
5347 namespace {
5348 /// Checks if the allocator is used in uses_allocators clause to be allowed in
5349 /// target regions.
5350 class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5351 DSAStackTy *S = nullptr;
5353 public:
5354 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5355 return S->isUsesAllocatorsDecl(E->getDecl())
5356 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5357 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5359 bool VisitStmt(const Stmt *S) {
5360 for (const Stmt *Child : S->children()) {
5361 if (Child && Visit(Child))
5362 return true;
5364 return false;
5366 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5368 } // namespace
5370 static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5371 ArrayRef<OMPClause *> Clauses) {
5372 assert(!S.CurContext->isDependentContext() &&
5373 "Expected non-dependent context.");
5374 auto AllocateRange =
5375 llvm::make_filter_range(Clauses, OMPAllocateClause::classof);
5376 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5377 auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) {
5378 return isOpenMPPrivate(C->getClauseKind());
5380 for (OMPClause *Cl : PrivateRange) {
5381 MutableArrayRef<Expr *>::iterator I, It, Et;
5382 if (Cl->getClauseKind() == OMPC_private) {
5383 auto *PC = cast<OMPPrivateClause>(Cl);
5384 I = PC->private_copies().begin();
5385 It = PC->varlist_begin();
5386 Et = PC->varlist_end();
5387 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5388 auto *PC = cast<OMPFirstprivateClause>(Cl);
5389 I = PC->private_copies().begin();
5390 It = PC->varlist_begin();
5391 Et = PC->varlist_end();
5392 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5393 auto *PC = cast<OMPLastprivateClause>(Cl);
5394 I = PC->private_copies().begin();
5395 It = PC->varlist_begin();
5396 Et = PC->varlist_end();
5397 } else if (Cl->getClauseKind() == OMPC_linear) {
5398 auto *PC = cast<OMPLinearClause>(Cl);
5399 I = PC->privates().begin();
5400 It = PC->varlist_begin();
5401 Et = PC->varlist_end();
5402 } else if (Cl->getClauseKind() == OMPC_reduction) {
5403 auto *PC = cast<OMPReductionClause>(Cl);
5404 I = PC->privates().begin();
5405 It = PC->varlist_begin();
5406 Et = PC->varlist_end();
5407 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5408 auto *PC = cast<OMPTaskReductionClause>(Cl);
5409 I = PC->privates().begin();
5410 It = PC->varlist_begin();
5411 Et = PC->varlist_end();
5412 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5413 auto *PC = cast<OMPInReductionClause>(Cl);
5414 I = PC->privates().begin();
5415 It = PC->varlist_begin();
5416 Et = PC->varlist_end();
5417 } else {
5418 llvm_unreachable("Expected private clause.");
5420 for (Expr *E : llvm::make_range(It, Et)) {
5421 if (!*I) {
5422 ++I;
5423 continue;
5425 SourceLocation ELoc;
5426 SourceRange ERange;
5427 Expr *SimpleRefExpr = E;
5428 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
5429 /*AllowArraySection=*/true);
5430 DeclToCopy.try_emplace(Res.first,
5431 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5432 ++I;
5435 for (OMPClause *C : AllocateRange) {
5436 auto *AC = cast<OMPAllocateClause>(C);
5437 if (S.getLangOpts().OpenMP >= 50 &&
5438 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5439 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
5440 AC->getAllocator()) {
5441 Expr *Allocator = AC->getAllocator();
5442 // OpenMP, 2.12.5 target Construct
5443 // Memory allocators that do not appear in a uses_allocators clause cannot
5444 // appear as an allocator in an allocate clause or be used in the target
5445 // region unless a requires directive with the dynamic_allocators clause
5446 // is present in the same compilation unit.
5447 AllocatorChecker Checker(Stack);
5448 if (Checker.Visit(Allocator))
5449 S.Diag(Allocator->getExprLoc(),
5450 diag::err_omp_allocator_not_in_uses_allocators)
5451 << Allocator->getSourceRange();
5453 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5454 getAllocatorKind(S, Stack, AC->getAllocator());
5455 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5456 // For task, taskloop or target directives, allocation requests to memory
5457 // allocators with the trait access set to thread result in unspecified
5458 // behavior.
5459 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5460 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
5461 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
5462 S.Diag(AC->getAllocator()->getExprLoc(),
5463 diag::warn_omp_allocate_thread_on_task_target_directive)
5464 << getOpenMPDirectiveName(Stack->getCurrentDirective());
5466 for (Expr *E : AC->varlists()) {
5467 SourceLocation ELoc;
5468 SourceRange ERange;
5469 Expr *SimpleRefExpr = E;
5470 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
5471 ValueDecl *VD = Res.first;
5472 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
5473 if (!isOpenMPPrivate(Data.CKind)) {
5474 S.Diag(E->getExprLoc(),
5475 diag::err_omp_expected_private_copy_for_allocate);
5476 continue;
5478 VarDecl *PrivateVD = DeclToCopy[VD];
5479 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5480 AllocatorKind, AC->getAllocator()))
5481 continue;
5482 // Placeholder until allocate clause supports align modifier.
5483 Expr *Alignment = nullptr;
5484 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5485 Alignment, E->getSourceRange());
5490 namespace {
5491 /// Rewrite statements and expressions for Sema \p Actions CurContext.
5493 /// Used to wrap already parsed statements/expressions into a new CapturedStmt
5494 /// context. DeclRefExpr used inside the new context are changed to refer to the
5495 /// captured variable instead.
5496 class CaptureVars : public TreeTransform<CaptureVars> {
5497 using BaseTransform = TreeTransform<CaptureVars>;
5499 public:
5500 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5502 bool AlwaysRebuild() { return true; }
5504 } // namespace
5506 static VarDecl *precomputeExpr(Sema &Actions,
5507 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5508 StringRef Name) {
5509 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
5510 VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
5511 dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
5512 auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
5513 Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
5514 Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
5515 BodyStmts.push_back(NewDeclStmt);
5516 return NewVar;
5519 /// Create a closure that computes the number of iterations of a loop.
5521 /// \param Actions The Sema object.
5522 /// \param LogicalTy Type for the logical iteration number.
5523 /// \param Rel Comparison operator of the loop condition.
5524 /// \param StartExpr Value of the loop counter at the first iteration.
5525 /// \param StopExpr Expression the loop counter is compared against in the loop
5526 /// condition. \param StepExpr Amount of increment after each iteration.
5528 /// \return Closure (CapturedStmt) of the distance calculation.
5529 static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5530 BinaryOperator::Opcode Rel,
5531 Expr *StartExpr, Expr *StopExpr,
5532 Expr *StepExpr) {
5533 ASTContext &Ctx = Actions.getASTContext();
5534 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
5536 // Captured regions currently don't support return values, we use an
5537 // out-parameter instead. All inputs are implicit captures.
5538 // TODO: Instead of capturing each DeclRefExpr occurring in
5539 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5540 QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
5541 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5542 {StringRef(), QualType()}};
5543 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5545 Stmt *Body;
5547 Sema::CompoundScopeRAII CompoundScope(Actions);
5548 CapturedDecl *CS = cast<CapturedDecl>(Actions.CurContext);
5550 // Get the LValue expression for the result.
5551 ImplicitParamDecl *DistParam = CS->getParam(0);
5552 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5553 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5555 SmallVector<Stmt *, 4> BodyStmts;
5557 // Capture all referenced variable references.
5558 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5559 // CapturedStmt, we could compute them before and capture the result, to be
5560 // used jointly with the LoopVar function.
5561 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
5562 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
5563 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
5564 auto BuildVarRef = [&](VarDecl *VD) {
5565 return buildDeclRefExpr(Actions, VD, VD->getType(), {});
5568 IntegerLiteral *Zero = IntegerLiteral::Create(
5569 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
5570 IntegerLiteral *One = IntegerLiteral::Create(
5571 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5572 Expr *Dist;
5573 if (Rel == BO_NE) {
5574 // When using a != comparison, the increment can be +1 or -1. This can be
5575 // dynamic at runtime, so we need to check for the direction.
5576 Expr *IsNegStep = AssertSuccess(
5577 Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5579 // Positive increment.
5580 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
5581 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5582 ForwardRange = AssertSuccess(
5583 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
5584 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
5585 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5587 // Negative increment.
5588 Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
5589 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5590 BackwardRange = AssertSuccess(
5591 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange));
5592 Expr *NegIncAmount = AssertSuccess(
5593 Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5594 Expr *BackwardDist = AssertSuccess(
5595 Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5597 // Use the appropriate case.
5598 Dist = AssertSuccess(Actions.ActOnConditionalOp(
5599 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5600 } else {
5601 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5602 "Expected one of these relational operators");
5604 // We can derive the direction from any other comparison operator. It is
5605 // non well-formed OpenMP if Step increments/decrements in the other
5606 // directions. Whether at least the first iteration passes the loop
5607 // condition.
5608 Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
5609 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5611 // Compute the range between first and last counter value.
5612 Expr *Range;
5613 if (Rel == BO_GE || Rel == BO_GT)
5614 Range = AssertSuccess(Actions.BuildBinOp(
5615 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5616 else
5617 Range = AssertSuccess(Actions.BuildBinOp(
5618 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5620 // Ensure unsigned range space.
5621 Range =
5622 AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range));
5624 if (Rel == BO_LE || Rel == BO_GE) {
5625 // Add one to the range if the relational operator is inclusive.
5626 Range =
5627 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One));
5630 // Divide by the absolute step amount. If the range is not a multiple of
5631 // the step size, rounding-up the effective upper bound ensures that the
5632 // last iteration is included.
5633 // Note that the rounding-up may cause an overflow in a temporry that
5634 // could be avoided, but would have occurred in a C-style for-loop as well.
5635 Expr *Divisor = BuildVarRef(NewStep);
5636 if (Rel == BO_GE || Rel == BO_GT)
5637 Divisor =
5638 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor));
5639 Expr *DivisorMinusOne =
5640 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One));
5641 Expr *RangeRoundUp = AssertSuccess(
5642 Actions.BuildBinOp(nullptr, {}, BO_Add, Range, DivisorMinusOne));
5643 Dist = AssertSuccess(
5644 Actions.BuildBinOp(nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5646 // If there is not at least one iteration, the range contains garbage. Fix
5647 // to zero in this case.
5648 Dist = AssertSuccess(
5649 Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
5652 // Assign the result to the out-parameter.
5653 Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp(
5654 Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
5655 BodyStmts.push_back(ResultAssign);
5657 Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false));
5660 return cast<CapturedStmt>(
5661 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5664 /// Create a closure that computes the loop variable from the logical iteration
5665 /// number.
5667 /// \param Actions The Sema object.
5668 /// \param LoopVarTy Type for the loop variable used for result value.
5669 /// \param LogicalTy Type for the logical iteration number.
5670 /// \param StartExpr Value of the loop counter at the first iteration.
5671 /// \param Step Amount of increment after each iteration.
5672 /// \param Deref Whether the loop variable is a dereference of the loop
5673 /// counter variable.
5675 /// \return Closure (CapturedStmt) of the loop value calculation.
5676 static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5677 QualType LogicalTy,
5678 DeclRefExpr *StartExpr, Expr *Step,
5679 bool Deref) {
5680 ASTContext &Ctx = Actions.getASTContext();
5682 // Pass the result as an out-parameter. Passing as return value would require
5683 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5684 // invoke a copy constructor.
5685 QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy);
5686 Sema::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5687 {"Logical", LogicalTy},
5688 {StringRef(), QualType()}};
5689 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5691 // Capture the initial iterator which represents the LoopVar value at the
5692 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5693 // it in every iteration, capture it by value before it is modified.
5694 VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl());
5695 bool Invalid = Actions.tryCaptureVariable(StartVar, {},
5696 Sema::TryCapture_ExplicitByVal, {});
5697 (void)Invalid;
5698 assert(!Invalid && "Expecting capture-by-value to work.");
5700 Expr *Body;
5702 Sema::CompoundScopeRAII CompoundScope(Actions);
5703 auto *CS = cast<CapturedDecl>(Actions.CurContext);
5705 ImplicitParamDecl *TargetParam = CS->getParam(0);
5706 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5707 TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5708 ImplicitParamDecl *IndvarParam = CS->getParam(1);
5709 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5710 IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5712 // Capture the Start expression.
5713 CaptureVars Recap(Actions);
5714 Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
5715 Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
5717 Expr *Skip = AssertSuccess(
5718 Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
5719 // TODO: Explicitly cast to the iterator's difference_type instead of
5720 // relying on implicit conversion.
5721 Expr *Advanced =
5722 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip));
5724 if (Deref) {
5725 // For range-based for-loops convert the loop counter value to a concrete
5726 // loop variable value by dereferencing the iterator.
5727 Advanced =
5728 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced));
5731 // Assign the result to the output parameter.
5732 Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {},
5733 BO_Assign, TargetRef, Advanced));
5735 return cast<CapturedStmt>(
5736 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5739 StmtResult Sema::ActOnOpenMPCanonicalLoop(Stmt *AStmt) {
5740 ASTContext &Ctx = getASTContext();
5742 // Extract the common elements of ForStmt and CXXForRangeStmt:
5743 // Loop variable, repeat condition, increment
5744 Expr *Cond, *Inc;
5745 VarDecl *LIVDecl, *LUVDecl;
5746 if (auto *For = dyn_cast<ForStmt>(AStmt)) {
5747 Stmt *Init = For->getInit();
5748 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) {
5749 // For statement declares loop variable.
5750 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5751 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) {
5752 // For statement reuses variable.
5753 assert(LCAssign->getOpcode() == BO_Assign &&
5754 "init part must be a loop variable assignment");
5755 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5756 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5757 } else
5758 llvm_unreachable("Cannot determine loop variable");
5759 LUVDecl = LIVDecl;
5761 Cond = For->getCond();
5762 Inc = For->getInc();
5763 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5764 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5765 LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl());
5766 LUVDecl = RangeFor->getLoopVariable();
5768 Cond = RangeFor->getCond();
5769 Inc = RangeFor->getInc();
5770 } else
5771 llvm_unreachable("unhandled kind of loop");
5773 QualType CounterTy = LIVDecl->getType();
5774 QualType LVTy = LUVDecl->getType();
5776 // Analyze the loop condition.
5777 Expr *LHS, *RHS;
5778 BinaryOperator::Opcode CondRel;
5779 Cond = Cond->IgnoreImplicit();
5780 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5781 LHS = CondBinExpr->getLHS();
5782 RHS = CondBinExpr->getRHS();
5783 CondRel = CondBinExpr->getOpcode();
5784 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5785 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5786 LHS = CondCXXOp->getArg(0);
5787 RHS = CondCXXOp->getArg(1);
5788 switch (CondCXXOp->getOperator()) {
5789 case OO_ExclaimEqual:
5790 CondRel = BO_NE;
5791 break;
5792 case OO_Less:
5793 CondRel = BO_LT;
5794 break;
5795 case OO_LessEqual:
5796 CondRel = BO_LE;
5797 break;
5798 case OO_Greater:
5799 CondRel = BO_GT;
5800 break;
5801 case OO_GreaterEqual:
5802 CondRel = BO_GE;
5803 break;
5804 default:
5805 llvm_unreachable("unexpected iterator operator");
5807 } else
5808 llvm_unreachable("unexpected loop condition");
5810 // Normalize such that the loop counter is on the LHS.
5811 if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) ||
5812 cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5813 std::swap(LHS, RHS);
5814 CondRel = BinaryOperator::reverseComparisonOp(CondRel);
5816 auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit());
5818 // Decide the bit width for the logical iteration counter. By default use the
5819 // unsigned ptrdiff_t integer size (for iterators and pointers).
5820 // TODO: For iterators, use iterator::difference_type,
5821 // std::iterator_traits<>::difference_type or decltype(it - end).
5822 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5823 if (CounterTy->isIntegerType()) {
5824 unsigned BitWidth = Ctx.getIntWidth(CounterTy);
5825 LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false);
5828 // Analyze the loop increment.
5829 Expr *Step;
5830 if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5831 int Direction;
5832 switch (IncUn->getOpcode()) {
5833 case UO_PreInc:
5834 case UO_PostInc:
5835 Direction = 1;
5836 break;
5837 case UO_PreDec:
5838 case UO_PostDec:
5839 Direction = -1;
5840 break;
5841 default:
5842 llvm_unreachable("unhandled unary increment operator");
5844 Step = IntegerLiteral::Create(
5845 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction), LogicalTy, {});
5846 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5847 if (IncBin->getOpcode() == BO_AddAssign) {
5848 Step = IncBin->getRHS();
5849 } else if (IncBin->getOpcode() == BO_SubAssign) {
5850 Step =
5851 AssertSuccess(BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS()));
5852 } else
5853 llvm_unreachable("unhandled binary increment operator");
5854 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5855 switch (CondCXXOp->getOperator()) {
5856 case OO_PlusPlus:
5857 Step = IntegerLiteral::Create(
5858 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5859 break;
5860 case OO_MinusMinus:
5861 Step = IntegerLiteral::Create(
5862 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
5863 break;
5864 case OO_PlusEqual:
5865 Step = CondCXXOp->getArg(1);
5866 break;
5867 case OO_MinusEqual:
5868 Step = AssertSuccess(
5869 BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5870 break;
5871 default:
5872 llvm_unreachable("unhandled overloaded increment operator");
5874 } else
5875 llvm_unreachable("unknown increment expression");
5877 CapturedStmt *DistanceFunc =
5878 buildDistanceFunc(*this, LogicalTy, CondRel, LHS, RHS, Step);
5879 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
5880 *this, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
5881 DeclRefExpr *LVRef = BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue,
5882 {}, nullptr, nullptr, {}, nullptr);
5883 return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc,
5884 LoopVarFunc, LVRef);
5887 StmtResult Sema::ActOnOpenMPLoopnest(Stmt *AStmt) {
5888 // Handle a literal loop.
5889 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
5890 return ActOnOpenMPCanonicalLoop(AStmt);
5892 // If not a literal loop, it must be the result of a loop transformation.
5893 OMPExecutableDirective *LoopTransform = cast<OMPExecutableDirective>(AStmt);
5894 assert(
5895 isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) &&
5896 "Loop transformation directive expected");
5897 return LoopTransform;
5900 static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
5901 CXXScopeSpec &MapperIdScopeSpec,
5902 const DeclarationNameInfo &MapperId,
5903 QualType Type,
5904 Expr *UnresolvedMapper);
5906 /// Perform DFS through the structure/class data members trying to find
5907 /// member(s) with user-defined 'default' mapper and generate implicit map
5908 /// clauses for such members with the found 'default' mapper.
5909 static void
5910 processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack,
5911 SmallVectorImpl<OMPClause *> &Clauses) {
5912 // Check for the deault mapper for data members.
5913 if (S.getLangOpts().OpenMP < 50)
5914 return;
5915 SmallVector<OMPClause *, 4> ImplicitMaps;
5916 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
5917 auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
5918 if (!C)
5919 continue;
5920 SmallVector<Expr *, 4> SubExprs;
5921 auto *MI = C->mapperlist_begin();
5922 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
5923 ++I, ++MI) {
5924 // Expression is mapped using mapper - skip it.
5925 if (*MI)
5926 continue;
5927 Expr *E = *I;
5928 // Expression is dependent - skip it, build the mapper when it gets
5929 // instantiated.
5930 if (E->isTypeDependent() || E->isValueDependent() ||
5931 E->containsUnexpandedParameterPack())
5932 continue;
5933 // Array section - need to check for the mapping of the array section
5934 // element.
5935 QualType CanonType = E->getType().getCanonicalType();
5936 if (CanonType->isSpecificBuiltinType(BuiltinType::OMPArraySection)) {
5937 const auto *OASE = cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts());
5938 QualType BaseType =
5939 OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
5940 QualType ElemType;
5941 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
5942 ElemType = ATy->getElementType();
5943 else
5944 ElemType = BaseType->getPointeeType();
5945 CanonType = ElemType;
5948 // DFS over data members in structures/classes.
5949 SmallVector<std::pair<QualType, FieldDecl *>, 4> Types(
5950 1, {CanonType, nullptr});
5951 llvm::DenseMap<const Type *, Expr *> Visited;
5952 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(
5953 1, {nullptr, 1});
5954 while (!Types.empty()) {
5955 QualType BaseType;
5956 FieldDecl *CurFD;
5957 std::tie(BaseType, CurFD) = Types.pop_back_val();
5958 while (ParentChain.back().second == 0)
5959 ParentChain.pop_back();
5960 --ParentChain.back().second;
5961 if (BaseType.isNull())
5962 continue;
5963 // Only structs/classes are allowed to have mappers.
5964 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
5965 if (!RD)
5966 continue;
5967 auto It = Visited.find(BaseType.getTypePtr());
5968 if (It == Visited.end()) {
5969 // Try to find the associated user-defined mapper.
5970 CXXScopeSpec MapperIdScopeSpec;
5971 DeclarationNameInfo DefaultMapperId;
5972 DefaultMapperId.setName(S.Context.DeclarationNames.getIdentifier(
5973 &S.Context.Idents.get("default")));
5974 DefaultMapperId.setLoc(E->getExprLoc());
5975 ExprResult ER = buildUserDefinedMapperRef(
5976 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
5977 BaseType, /*UnresolvedMapper=*/nullptr);
5978 if (ER.isInvalid())
5979 continue;
5980 It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first;
5982 // Found default mapper.
5983 if (It->second) {
5984 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
5985 VK_LValue, OK_Ordinary, E);
5986 OE->setIsUnique(/*V=*/true);
5987 Expr *BaseExpr = OE;
5988 for (const auto &P : ParentChain) {
5989 if (P.first) {
5990 BaseExpr = S.BuildMemberExpr(
5991 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
5992 NestedNameSpecifierLoc(), SourceLocation(), P.first,
5993 DeclAccessPair::make(P.first, P.first->getAccess()),
5994 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
5995 P.first->getType(), VK_LValue, OK_Ordinary);
5996 BaseExpr = S.DefaultLvalueConversion(BaseExpr).get();
5999 if (CurFD)
6000 BaseExpr = S.BuildMemberExpr(
6001 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6002 NestedNameSpecifierLoc(), SourceLocation(), CurFD,
6003 DeclAccessPair::make(CurFD, CurFD->getAccess()),
6004 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6005 CurFD->getType(), VK_LValue, OK_Ordinary);
6006 SubExprs.push_back(BaseExpr);
6007 continue;
6009 // Check for the "default" mapper for data members.
6010 bool FirstIter = true;
6011 for (FieldDecl *FD : RD->fields()) {
6012 if (!FD)
6013 continue;
6014 QualType FieldTy = FD->getType();
6015 if (FieldTy.isNull() ||
6016 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
6017 continue;
6018 if (FirstIter) {
6019 FirstIter = false;
6020 ParentChain.emplace_back(CurFD, 1);
6021 } else {
6022 ++ParentChain.back().second;
6024 Types.emplace_back(FieldTy, FD);
6028 if (SubExprs.empty())
6029 continue;
6030 CXXScopeSpec MapperIdScopeSpec;
6031 DeclarationNameInfo MapperId;
6032 if (OMPClause *NewClause = S.ActOnOpenMPMapClause(
6033 C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(),
6034 MapperIdScopeSpec, MapperId, C->getMapType(),
6035 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6036 SubExprs, OMPVarListLocTy()))
6037 Clauses.push_back(NewClause);
6041 StmtResult Sema::ActOnOpenMPExecutableDirective(
6042 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6043 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
6044 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
6045 StmtResult Res = StmtError();
6046 OpenMPBindClauseKind BindKind = OMPC_BIND_unknown;
6047 if (const OMPBindClause *BC =
6048 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6049 BindKind = BC->getBindKind();
6050 // First check CancelRegion which is then used in checkNestingOfRegions.
6051 if (checkCancelRegion(*this, Kind, CancelRegion, StartLoc) ||
6052 checkNestingOfRegions(*this, DSAStack, Kind, DirName, CancelRegion,
6053 BindKind, StartLoc))
6054 return StmtError();
6056 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
6057 VarsWithInheritedDSAType VarsWithInheritedDSA;
6058 bool ErrorFound = false;
6059 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6060 if (AStmt && !CurContext->isDependentContext() && Kind != OMPD_atomic &&
6061 Kind != OMPD_critical && Kind != OMPD_section && Kind != OMPD_master &&
6062 Kind != OMPD_masked && !isOpenMPLoopTransformationDirective(Kind)) {
6063 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6065 // Check default data sharing attributes for referenced variables.
6066 DSAAttrChecker DSAChecker(DSAStack, *this, cast<CapturedStmt>(AStmt));
6067 int ThisCaptureLevel = getOpenMPCaptureLevels(Kind);
6068 Stmt *S = AStmt;
6069 while (--ThisCaptureLevel >= 0)
6070 S = cast<CapturedStmt>(S)->getCapturedStmt();
6071 DSAChecker.Visit(S);
6072 if (!isOpenMPTargetDataManagementDirective(Kind) &&
6073 !isOpenMPTaskingDirective(Kind)) {
6074 // Visit subcaptures to generate implicit clauses for captured vars.
6075 auto *CS = cast<CapturedStmt>(AStmt);
6076 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
6077 getOpenMPCaptureRegions(CaptureRegions, Kind);
6078 // Ignore outer tasking regions for target directives.
6079 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6080 CS = cast<CapturedStmt>(CS->getCapturedStmt());
6081 DSAChecker.visitSubCaptures(CS);
6083 if (DSAChecker.isErrorFound())
6084 return StmtError();
6085 // Generate list of implicitly defined firstprivate variables.
6086 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6088 SmallVector<Expr *, 4> ImplicitFirstprivates(
6089 DSAChecker.getImplicitFirstprivate().begin(),
6090 DSAChecker.getImplicitFirstprivate().end());
6091 SmallVector<Expr *, 4> ImplicitPrivates(
6092 DSAChecker.getImplicitPrivate().begin(),
6093 DSAChecker.getImplicitPrivate().end());
6094 const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_pointer + 1;
6095 SmallVector<Expr *, 4> ImplicitMaps[DefaultmapKindNum][OMPC_MAP_delete];
6096 SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
6097 ImplicitMapModifiers[DefaultmapKindNum];
6098 SmallVector<SourceLocation, NumberOfOMPMapClauseModifiers>
6099 ImplicitMapModifiersLoc[DefaultmapKindNum];
6100 // Get the original location of present modifier from Defaultmap clause.
6101 SourceLocation PresentModifierLocs[DefaultmapKindNum];
6102 for (OMPClause *C : Clauses) {
6103 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C))
6104 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6105 PresentModifierLocs[DMC->getDefaultmapKind()] =
6106 DMC->getDefaultmapModifierLoc();
6108 for (unsigned VC = 0; VC < DefaultmapKindNum; ++VC) {
6109 auto Kind = static_cast<OpenMPDefaultmapClauseKind>(VC);
6110 for (unsigned I = 0; I < OMPC_MAP_delete; ++I) {
6111 ArrayRef<Expr *> ImplicitMap = DSAChecker.getImplicitMap(
6112 Kind, static_cast<OpenMPMapClauseKind>(I));
6113 ImplicitMaps[VC][I].append(ImplicitMap.begin(), ImplicitMap.end());
6115 ArrayRef<OpenMPMapModifierKind> ImplicitModifier =
6116 DSAChecker.getImplicitMapModifier(Kind);
6117 ImplicitMapModifiers[VC].append(ImplicitModifier.begin(),
6118 ImplicitModifier.end());
6119 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[VC]),
6120 ImplicitModifier.size(), PresentModifierLocs[VC]);
6122 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6123 for (OMPClause *C : Clauses) {
6124 if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
6125 for (Expr *E : IRC->taskgroup_descriptors())
6126 if (E)
6127 ImplicitFirstprivates.emplace_back(E);
6129 // OpenMP 5.0, 2.10.1 task Construct
6130 // [detach clause]... The event-handle will be considered as if it was
6131 // specified on a firstprivate clause.
6132 if (auto *DC = dyn_cast<OMPDetachClause>(C))
6133 ImplicitFirstprivates.push_back(DC->getEventHandler());
6135 if (!ImplicitFirstprivates.empty()) {
6136 if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause(
6137 ImplicitFirstprivates, SourceLocation(), SourceLocation(),
6138 SourceLocation())) {
6139 ClausesWithImplicit.push_back(Implicit);
6140 ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
6141 ImplicitFirstprivates.size();
6142 } else {
6143 ErrorFound = true;
6146 if (!ImplicitPrivates.empty()) {
6147 if (OMPClause *Implicit =
6148 ActOnOpenMPPrivateClause(ImplicitPrivates, SourceLocation(),
6149 SourceLocation(), SourceLocation())) {
6150 ClausesWithImplicit.push_back(Implicit);
6151 ErrorFound = cast<OMPPrivateClause>(Implicit)->varlist_size() !=
6152 ImplicitPrivates.size();
6153 } else {
6154 ErrorFound = true;
6157 // OpenMP 5.0 [2.19.7]
6158 // If a list item appears in a reduction, lastprivate or linear
6159 // clause on a combined target construct then it is treated as
6160 // if it also appears in a map clause with a map-type of tofrom
6161 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6162 isOpenMPTargetExecutionDirective(Kind)) {
6163 SmallVector<Expr *, 4> ImplicitExprs;
6164 for (OMPClause *C : Clauses) {
6165 if (auto *RC = dyn_cast<OMPReductionClause>(C))
6166 for (Expr *E : RC->varlists())
6167 if (!isa<DeclRefExpr>(E->IgnoreParenImpCasts()))
6168 ImplicitExprs.emplace_back(E);
6170 if (!ImplicitExprs.empty()) {
6171 ArrayRef<Expr *> Exprs = ImplicitExprs;
6172 CXXScopeSpec MapperIdScopeSpec;
6173 DeclarationNameInfo MapperId;
6174 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6175 OMPC_MAP_MODIFIER_unknown, SourceLocation(), MapperIdScopeSpec,
6176 MapperId, OMPC_MAP_tofrom,
6177 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6178 Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true))
6179 ClausesWithImplicit.emplace_back(Implicit);
6182 for (unsigned I = 0, E = DefaultmapKindNum; I < E; ++I) {
6183 int ClauseKindCnt = -1;
6184 for (ArrayRef<Expr *> ImplicitMap : ImplicitMaps[I]) {
6185 ++ClauseKindCnt;
6186 if (ImplicitMap.empty())
6187 continue;
6188 CXXScopeSpec MapperIdScopeSpec;
6189 DeclarationNameInfo MapperId;
6190 auto Kind = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6191 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6192 ImplicitMapModifiers[I], ImplicitMapModifiersLoc[I],
6193 MapperIdScopeSpec, MapperId, Kind, /*IsMapTypeImplicit=*/true,
6194 SourceLocation(), SourceLocation(), ImplicitMap,
6195 OMPVarListLocTy())) {
6196 ClausesWithImplicit.emplace_back(Implicit);
6197 ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() !=
6198 ImplicitMap.size();
6199 } else {
6200 ErrorFound = true;
6204 // Build expressions for implicit maps of data members with 'default'
6205 // mappers.
6206 if (LangOpts.OpenMP >= 50)
6207 processImplicitMapsWithDefaultMappers(*this, DSAStack,
6208 ClausesWithImplicit);
6211 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6212 switch (Kind) {
6213 case OMPD_parallel:
6214 Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
6215 EndLoc);
6216 AllowedNameModifiers.push_back(OMPD_parallel);
6217 break;
6218 case OMPD_simd:
6219 Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6220 VarsWithInheritedDSA);
6221 if (LangOpts.OpenMP >= 50)
6222 AllowedNameModifiers.push_back(OMPD_simd);
6223 break;
6224 case OMPD_tile:
6225 Res =
6226 ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6227 break;
6228 case OMPD_unroll:
6229 Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc,
6230 EndLoc);
6231 break;
6232 case OMPD_for:
6233 Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6234 VarsWithInheritedDSA);
6235 break;
6236 case OMPD_for_simd:
6237 Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6238 EndLoc, VarsWithInheritedDSA);
6239 if (LangOpts.OpenMP >= 50)
6240 AllowedNameModifiers.push_back(OMPD_simd);
6241 break;
6242 case OMPD_sections:
6243 Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc,
6244 EndLoc);
6245 break;
6246 case OMPD_section:
6247 assert(ClausesWithImplicit.empty() &&
6248 "No clauses are allowed for 'omp section' directive");
6249 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6250 break;
6251 case OMPD_single:
6252 Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc,
6253 EndLoc);
6254 break;
6255 case OMPD_master:
6256 assert(ClausesWithImplicit.empty() &&
6257 "No clauses are allowed for 'omp master' directive");
6258 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6259 break;
6260 case OMPD_masked:
6261 Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc,
6262 EndLoc);
6263 break;
6264 case OMPD_critical:
6265 Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
6266 StartLoc, EndLoc);
6267 break;
6268 case OMPD_parallel_for:
6269 Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
6270 EndLoc, VarsWithInheritedDSA);
6271 AllowedNameModifiers.push_back(OMPD_parallel);
6272 break;
6273 case OMPD_parallel_for_simd:
6274 Res = ActOnOpenMPParallelForSimdDirective(
6275 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6276 AllowedNameModifiers.push_back(OMPD_parallel);
6277 if (LangOpts.OpenMP >= 50)
6278 AllowedNameModifiers.push_back(OMPD_simd);
6279 break;
6280 case OMPD_parallel_master:
6281 Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt,
6282 StartLoc, EndLoc);
6283 AllowedNameModifiers.push_back(OMPD_parallel);
6284 break;
6285 case OMPD_parallel_masked:
6286 Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt,
6287 StartLoc, EndLoc);
6288 AllowedNameModifiers.push_back(OMPD_parallel);
6289 break;
6290 case OMPD_parallel_sections:
6291 Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
6292 StartLoc, EndLoc);
6293 AllowedNameModifiers.push_back(OMPD_parallel);
6294 break;
6295 case OMPD_task:
6296 Res =
6297 ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6298 AllowedNameModifiers.push_back(OMPD_task);
6299 break;
6300 case OMPD_taskyield:
6301 assert(ClausesWithImplicit.empty() &&
6302 "No clauses are allowed for 'omp taskyield' directive");
6303 assert(AStmt == nullptr &&
6304 "No associated statement allowed for 'omp taskyield' directive");
6305 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6306 break;
6307 case OMPD_barrier:
6308 assert(ClausesWithImplicit.empty() &&
6309 "No clauses are allowed for 'omp barrier' directive");
6310 assert(AStmt == nullptr &&
6311 "No associated statement allowed for 'omp barrier' directive");
6312 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6313 break;
6314 case OMPD_taskwait:
6315 assert(AStmt == nullptr &&
6316 "No associated statement allowed for 'omp taskwait' directive");
6317 Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc);
6318 break;
6319 case OMPD_taskgroup:
6320 Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc,
6321 EndLoc);
6322 break;
6323 case OMPD_flush:
6324 assert(AStmt == nullptr &&
6325 "No associated statement allowed for 'omp flush' directive");
6326 Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
6327 break;
6328 case OMPD_depobj:
6329 assert(AStmt == nullptr &&
6330 "No associated statement allowed for 'omp depobj' directive");
6331 Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc);
6332 break;
6333 case OMPD_scan:
6334 assert(AStmt == nullptr &&
6335 "No associated statement allowed for 'omp scan' directive");
6336 Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc);
6337 break;
6338 case OMPD_ordered:
6339 Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
6340 EndLoc);
6341 break;
6342 case OMPD_atomic:
6343 Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
6344 EndLoc);
6345 break;
6346 case OMPD_teams:
6347 Res =
6348 ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6349 break;
6350 case OMPD_target:
6351 Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
6352 EndLoc);
6353 AllowedNameModifiers.push_back(OMPD_target);
6354 break;
6355 case OMPD_target_parallel:
6356 Res = ActOnOpenMPTargetParallelDirective(ClausesWithImplicit, AStmt,
6357 StartLoc, EndLoc);
6358 AllowedNameModifiers.push_back(OMPD_target);
6359 AllowedNameModifiers.push_back(OMPD_parallel);
6360 break;
6361 case OMPD_target_parallel_for:
6362 Res = ActOnOpenMPTargetParallelForDirective(
6363 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6364 AllowedNameModifiers.push_back(OMPD_target);
6365 AllowedNameModifiers.push_back(OMPD_parallel);
6366 break;
6367 case OMPD_cancellation_point:
6368 assert(ClausesWithImplicit.empty() &&
6369 "No clauses are allowed for 'omp cancellation point' directive");
6370 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6371 "cancellation point' directive");
6372 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6373 break;
6374 case OMPD_cancel:
6375 assert(AStmt == nullptr &&
6376 "No associated statement allowed for 'omp cancel' directive");
6377 Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
6378 CancelRegion);
6379 AllowedNameModifiers.push_back(OMPD_cancel);
6380 break;
6381 case OMPD_target_data:
6382 Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
6383 EndLoc);
6384 AllowedNameModifiers.push_back(OMPD_target_data);
6385 break;
6386 case OMPD_target_enter_data:
6387 Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc,
6388 EndLoc, AStmt);
6389 AllowedNameModifiers.push_back(OMPD_target_enter_data);
6390 break;
6391 case OMPD_target_exit_data:
6392 Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc,
6393 EndLoc, AStmt);
6394 AllowedNameModifiers.push_back(OMPD_target_exit_data);
6395 break;
6396 case OMPD_taskloop:
6397 Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6398 EndLoc, VarsWithInheritedDSA);
6399 AllowedNameModifiers.push_back(OMPD_taskloop);
6400 break;
6401 case OMPD_taskloop_simd:
6402 Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6403 EndLoc, VarsWithInheritedDSA);
6404 AllowedNameModifiers.push_back(OMPD_taskloop);
6405 if (LangOpts.OpenMP >= 50)
6406 AllowedNameModifiers.push_back(OMPD_simd);
6407 break;
6408 case OMPD_master_taskloop:
6409 Res = ActOnOpenMPMasterTaskLoopDirective(
6410 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6411 AllowedNameModifiers.push_back(OMPD_taskloop);
6412 break;
6413 case OMPD_masked_taskloop:
6414 Res = ActOnOpenMPMaskedTaskLoopDirective(
6415 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6416 AllowedNameModifiers.push_back(OMPD_taskloop);
6417 break;
6418 case OMPD_master_taskloop_simd:
6419 Res = ActOnOpenMPMasterTaskLoopSimdDirective(
6420 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6421 AllowedNameModifiers.push_back(OMPD_taskloop);
6422 if (LangOpts.OpenMP >= 50)
6423 AllowedNameModifiers.push_back(OMPD_simd);
6424 break;
6425 case OMPD_masked_taskloop_simd:
6426 Res = ActOnOpenMPMaskedTaskLoopSimdDirective(
6427 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6428 if (LangOpts.OpenMP >= 51) {
6429 AllowedNameModifiers.push_back(OMPD_taskloop);
6430 AllowedNameModifiers.push_back(OMPD_simd);
6432 break;
6433 case OMPD_parallel_master_taskloop:
6434 Res = ActOnOpenMPParallelMasterTaskLoopDirective(
6435 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6436 AllowedNameModifiers.push_back(OMPD_taskloop);
6437 AllowedNameModifiers.push_back(OMPD_parallel);
6438 break;
6439 case OMPD_parallel_masked_taskloop:
6440 Res = ActOnOpenMPParallelMaskedTaskLoopDirective(
6441 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6442 if (LangOpts.OpenMP >= 51) {
6443 AllowedNameModifiers.push_back(OMPD_taskloop);
6444 AllowedNameModifiers.push_back(OMPD_parallel);
6446 break;
6447 case OMPD_parallel_master_taskloop_simd:
6448 Res = ActOnOpenMPParallelMasterTaskLoopSimdDirective(
6449 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6450 AllowedNameModifiers.push_back(OMPD_taskloop);
6451 AllowedNameModifiers.push_back(OMPD_parallel);
6452 if (LangOpts.OpenMP >= 50)
6453 AllowedNameModifiers.push_back(OMPD_simd);
6454 break;
6455 case OMPD_parallel_masked_taskloop_simd:
6456 Res = ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
6457 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6458 if (LangOpts.OpenMP >= 51) {
6459 AllowedNameModifiers.push_back(OMPD_taskloop);
6460 AllowedNameModifiers.push_back(OMPD_parallel);
6461 AllowedNameModifiers.push_back(OMPD_simd);
6463 break;
6464 case OMPD_distribute:
6465 Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc,
6466 EndLoc, VarsWithInheritedDSA);
6467 break;
6468 case OMPD_target_update:
6469 Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc,
6470 EndLoc, AStmt);
6471 AllowedNameModifiers.push_back(OMPD_target_update);
6472 break;
6473 case OMPD_distribute_parallel_for:
6474 Res = ActOnOpenMPDistributeParallelForDirective(
6475 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6476 AllowedNameModifiers.push_back(OMPD_parallel);
6477 break;
6478 case OMPD_distribute_parallel_for_simd:
6479 Res = ActOnOpenMPDistributeParallelForSimdDirective(
6480 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6481 AllowedNameModifiers.push_back(OMPD_parallel);
6482 if (LangOpts.OpenMP >= 50)
6483 AllowedNameModifiers.push_back(OMPD_simd);
6484 break;
6485 case OMPD_distribute_simd:
6486 Res = ActOnOpenMPDistributeSimdDirective(
6487 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6488 if (LangOpts.OpenMP >= 50)
6489 AllowedNameModifiers.push_back(OMPD_simd);
6490 break;
6491 case OMPD_target_parallel_for_simd:
6492 Res = ActOnOpenMPTargetParallelForSimdDirective(
6493 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6494 AllowedNameModifiers.push_back(OMPD_target);
6495 AllowedNameModifiers.push_back(OMPD_parallel);
6496 if (LangOpts.OpenMP >= 50)
6497 AllowedNameModifiers.push_back(OMPD_simd);
6498 break;
6499 case OMPD_target_simd:
6500 Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6501 EndLoc, VarsWithInheritedDSA);
6502 AllowedNameModifiers.push_back(OMPD_target);
6503 if (LangOpts.OpenMP >= 50)
6504 AllowedNameModifiers.push_back(OMPD_simd);
6505 break;
6506 case OMPD_teams_distribute:
6507 Res = ActOnOpenMPTeamsDistributeDirective(
6508 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6509 break;
6510 case OMPD_teams_distribute_simd:
6511 Res = ActOnOpenMPTeamsDistributeSimdDirective(
6512 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6513 if (LangOpts.OpenMP >= 50)
6514 AllowedNameModifiers.push_back(OMPD_simd);
6515 break;
6516 case OMPD_teams_distribute_parallel_for_simd:
6517 Res = ActOnOpenMPTeamsDistributeParallelForSimdDirective(
6518 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6519 AllowedNameModifiers.push_back(OMPD_parallel);
6520 if (LangOpts.OpenMP >= 50)
6521 AllowedNameModifiers.push_back(OMPD_simd);
6522 break;
6523 case OMPD_teams_distribute_parallel_for:
6524 Res = ActOnOpenMPTeamsDistributeParallelForDirective(
6525 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6526 AllowedNameModifiers.push_back(OMPD_parallel);
6527 break;
6528 case OMPD_target_teams:
6529 Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc,
6530 EndLoc);
6531 AllowedNameModifiers.push_back(OMPD_target);
6532 break;
6533 case OMPD_target_teams_distribute:
6534 Res = ActOnOpenMPTargetTeamsDistributeDirective(
6535 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6536 AllowedNameModifiers.push_back(OMPD_target);
6537 break;
6538 case OMPD_target_teams_distribute_parallel_for:
6539 Res = ActOnOpenMPTargetTeamsDistributeParallelForDirective(
6540 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6541 AllowedNameModifiers.push_back(OMPD_target);
6542 AllowedNameModifiers.push_back(OMPD_parallel);
6543 break;
6544 case OMPD_target_teams_distribute_parallel_for_simd:
6545 Res = ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
6546 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6547 AllowedNameModifiers.push_back(OMPD_target);
6548 AllowedNameModifiers.push_back(OMPD_parallel);
6549 if (LangOpts.OpenMP >= 50)
6550 AllowedNameModifiers.push_back(OMPD_simd);
6551 break;
6552 case OMPD_target_teams_distribute_simd:
6553 Res = ActOnOpenMPTargetTeamsDistributeSimdDirective(
6554 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6555 AllowedNameModifiers.push_back(OMPD_target);
6556 if (LangOpts.OpenMP >= 50)
6557 AllowedNameModifiers.push_back(OMPD_simd);
6558 break;
6559 case OMPD_interop:
6560 assert(AStmt == nullptr &&
6561 "No associated statement allowed for 'omp interop' directive");
6562 Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc);
6563 break;
6564 case OMPD_dispatch:
6565 Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc,
6566 EndLoc);
6567 break;
6568 case OMPD_loop:
6569 Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6570 EndLoc, VarsWithInheritedDSA);
6571 break;
6572 case OMPD_teams_loop:
6573 Res = ActOnOpenMPTeamsGenericLoopDirective(
6574 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6575 break;
6576 case OMPD_target_teams_loop:
6577 Res = ActOnOpenMPTargetTeamsGenericLoopDirective(
6578 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6579 break;
6580 case OMPD_parallel_loop:
6581 Res = ActOnOpenMPParallelGenericLoopDirective(
6582 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6583 break;
6584 case OMPD_target_parallel_loop:
6585 Res = ActOnOpenMPTargetParallelGenericLoopDirective(
6586 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6587 break;
6588 case OMPD_declare_target:
6589 case OMPD_end_declare_target:
6590 case OMPD_threadprivate:
6591 case OMPD_allocate:
6592 case OMPD_declare_reduction:
6593 case OMPD_declare_mapper:
6594 case OMPD_declare_simd:
6595 case OMPD_requires:
6596 case OMPD_declare_variant:
6597 case OMPD_begin_declare_variant:
6598 case OMPD_end_declare_variant:
6599 llvm_unreachable("OpenMP Directive is not allowed");
6600 case OMPD_unknown:
6601 default:
6602 llvm_unreachable("Unknown OpenMP directive");
6605 ErrorFound = Res.isInvalid() || ErrorFound;
6607 // Check variables in the clauses if default(none) or
6608 // default(firstprivate) was specified.
6609 if (DSAStack->getDefaultDSA() == DSA_none ||
6610 DSAStack->getDefaultDSA() == DSA_private ||
6611 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6612 DSAAttrChecker DSAChecker(DSAStack, *this, nullptr);
6613 for (OMPClause *C : Clauses) {
6614 switch (C->getClauseKind()) {
6615 case OMPC_num_threads:
6616 case OMPC_dist_schedule:
6617 // Do not analyse if no parent teams directive.
6618 if (isOpenMPTeamsDirective(Kind))
6619 break;
6620 continue;
6621 case OMPC_if:
6622 if (isOpenMPTeamsDirective(Kind) &&
6623 cast<OMPIfClause>(C)->getNameModifier() != OMPD_target)
6624 break;
6625 if (isOpenMPParallelDirective(Kind) &&
6626 isOpenMPTaskLoopDirective(Kind) &&
6627 cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel)
6628 break;
6629 continue;
6630 case OMPC_schedule:
6631 case OMPC_detach:
6632 break;
6633 case OMPC_grainsize:
6634 case OMPC_num_tasks:
6635 case OMPC_final:
6636 case OMPC_priority:
6637 case OMPC_novariants:
6638 case OMPC_nocontext:
6639 // Do not analyze if no parent parallel directive.
6640 if (isOpenMPParallelDirective(Kind))
6641 break;
6642 continue;
6643 case OMPC_ordered:
6644 case OMPC_device:
6645 case OMPC_num_teams:
6646 case OMPC_thread_limit:
6647 case OMPC_hint:
6648 case OMPC_collapse:
6649 case OMPC_safelen:
6650 case OMPC_simdlen:
6651 case OMPC_sizes:
6652 case OMPC_default:
6653 case OMPC_proc_bind:
6654 case OMPC_private:
6655 case OMPC_firstprivate:
6656 case OMPC_lastprivate:
6657 case OMPC_shared:
6658 case OMPC_reduction:
6659 case OMPC_task_reduction:
6660 case OMPC_in_reduction:
6661 case OMPC_linear:
6662 case OMPC_aligned:
6663 case OMPC_copyin:
6664 case OMPC_copyprivate:
6665 case OMPC_nowait:
6666 case OMPC_untied:
6667 case OMPC_mergeable:
6668 case OMPC_allocate:
6669 case OMPC_read:
6670 case OMPC_write:
6671 case OMPC_update:
6672 case OMPC_capture:
6673 case OMPC_compare:
6674 case OMPC_seq_cst:
6675 case OMPC_acq_rel:
6676 case OMPC_acquire:
6677 case OMPC_release:
6678 case OMPC_relaxed:
6679 case OMPC_depend:
6680 case OMPC_threads:
6681 case OMPC_simd:
6682 case OMPC_map:
6683 case OMPC_nogroup:
6684 case OMPC_defaultmap:
6685 case OMPC_to:
6686 case OMPC_from:
6687 case OMPC_use_device_ptr:
6688 case OMPC_use_device_addr:
6689 case OMPC_is_device_ptr:
6690 case OMPC_has_device_addr:
6691 case OMPC_nontemporal:
6692 case OMPC_order:
6693 case OMPC_destroy:
6694 case OMPC_inclusive:
6695 case OMPC_exclusive:
6696 case OMPC_uses_allocators:
6697 case OMPC_affinity:
6698 case OMPC_bind:
6699 case OMPC_filter:
6700 continue;
6701 case OMPC_allocator:
6702 case OMPC_flush:
6703 case OMPC_depobj:
6704 case OMPC_threadprivate:
6705 case OMPC_uniform:
6706 case OMPC_unknown:
6707 case OMPC_unified_address:
6708 case OMPC_unified_shared_memory:
6709 case OMPC_reverse_offload:
6710 case OMPC_dynamic_allocators:
6711 case OMPC_atomic_default_mem_order:
6712 case OMPC_device_type:
6713 case OMPC_match:
6714 case OMPC_when:
6715 default:
6716 llvm_unreachable("Unexpected clause");
6718 for (Stmt *CC : C->children()) {
6719 if (CC)
6720 DSAChecker.Visit(CC);
6723 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6724 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6726 for (const auto &P : VarsWithInheritedDSA) {
6727 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst()))
6728 continue;
6729 ErrorFound = true;
6730 if (DSAStack->getDefaultDSA() == DSA_none ||
6731 DSAStack->getDefaultDSA() == DSA_private ||
6732 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6733 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6734 << P.first << P.second->getSourceRange();
6735 Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6736 } else if (getLangOpts().OpenMP >= 50) {
6737 Diag(P.second->getExprLoc(),
6738 diag::err_omp_defaultmap_no_attr_for_variable)
6739 << P.first << P.second->getSourceRange();
6740 Diag(DSAStack->getDefaultDSALocation(),
6741 diag::note_omp_defaultmap_attr_none);
6745 if (!AllowedNameModifiers.empty())
6746 ErrorFound = checkIfClauses(*this, Kind, Clauses, AllowedNameModifiers) ||
6747 ErrorFound;
6749 if (ErrorFound)
6750 return StmtError();
6752 if (!CurContext->isDependentContext() &&
6753 isOpenMPTargetExecutionDirective(Kind) &&
6754 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6755 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6756 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6757 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6758 // Register target to DSA Stack.
6759 DSAStack->addTargetDirLocation(StartLoc);
6762 return Res;
6765 Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective(
6766 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6767 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6768 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6769 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6770 assert(Aligneds.size() == Alignments.size());
6771 assert(Linears.size() == LinModifiers.size());
6772 assert(Linears.size() == Steps.size());
6773 if (!DG || DG.get().isNull())
6774 return DeclGroupPtrTy();
6776 const int SimdId = 0;
6777 if (!DG.get().isSingleDecl()) {
6778 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6779 << SimdId;
6780 return DG;
6782 Decl *ADecl = DG.get().getSingleDecl();
6783 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6784 ADecl = FTD->getTemplatedDecl();
6786 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6787 if (!FD) {
6788 Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
6789 return DeclGroupPtrTy();
6792 // OpenMP [2.8.2, declare simd construct, Description]
6793 // The parameter of the simdlen clause must be a constant positive integer
6794 // expression.
6795 ExprResult SL;
6796 if (Simdlen)
6797 SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen);
6798 // OpenMP [2.8.2, declare simd construct, Description]
6799 // The special this pointer can be used as if was one of the arguments to the
6800 // function in any of the linear, aligned, or uniform clauses.
6801 // The uniform clause declares one or more arguments to have an invariant
6802 // value for all concurrent invocations of the function in the execution of a
6803 // single SIMD loop.
6804 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6805 const Expr *UniformedLinearThis = nullptr;
6806 for (const Expr *E : Uniforms) {
6807 E = E->IgnoreParenImpCasts();
6808 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6809 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
6810 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6811 FD->getParamDecl(PVD->getFunctionScopeIndex())
6812 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
6813 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
6814 continue;
6816 if (isa<CXXThisExpr>(E)) {
6817 UniformedLinearThis = E;
6818 continue;
6820 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6821 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6823 // OpenMP [2.8.2, declare simd construct, Description]
6824 // The aligned clause declares that the object to which each list item points
6825 // is aligned to the number of bytes expressed in the optional parameter of
6826 // the aligned clause.
6827 // The special this pointer can be used as if was one of the arguments to the
6828 // function in any of the linear, aligned, or uniform clauses.
6829 // The type of list items appearing in the aligned clause must be array,
6830 // pointer, reference to array, or reference to pointer.
6831 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6832 const Expr *AlignedThis = nullptr;
6833 for (const Expr *E : Aligneds) {
6834 E = E->IgnoreParenImpCasts();
6835 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6836 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6837 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6838 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6839 FD->getParamDecl(PVD->getFunctionScopeIndex())
6840 ->getCanonicalDecl() == CanonPVD) {
6841 // OpenMP [2.8.1, simd construct, Restrictions]
6842 // A list-item cannot appear in more than one aligned clause.
6843 if (AlignedArgs.count(CanonPVD) > 0) {
6844 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6845 << 1 << getOpenMPClauseName(OMPC_aligned)
6846 << E->getSourceRange();
6847 Diag(AlignedArgs[CanonPVD]->getExprLoc(),
6848 diag::note_omp_explicit_dsa)
6849 << getOpenMPClauseName(OMPC_aligned);
6850 continue;
6852 AlignedArgs[CanonPVD] = E;
6853 QualType QTy = PVD->getType()
6854 .getNonReferenceType()
6855 .getUnqualifiedType()
6856 .getCanonicalType();
6857 const Type *Ty = QTy.getTypePtrOrNull();
6858 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
6859 Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
6860 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
6861 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
6863 continue;
6866 if (isa<CXXThisExpr>(E)) {
6867 if (AlignedThis) {
6868 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6869 << 2 << getOpenMPClauseName(OMPC_aligned) << E->getSourceRange();
6870 Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
6871 << getOpenMPClauseName(OMPC_aligned);
6873 AlignedThis = E;
6874 continue;
6876 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6877 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6879 // The optional parameter of the aligned clause, alignment, must be a constant
6880 // positive integer expression. If no optional parameter is specified,
6881 // implementation-defined default alignments for SIMD instructions on the
6882 // target platforms are assumed.
6883 SmallVector<const Expr *, 4> NewAligns;
6884 for (Expr *E : Alignments) {
6885 ExprResult Align;
6886 if (E)
6887 Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
6888 NewAligns.push_back(Align.get());
6890 // OpenMP [2.8.2, declare simd construct, Description]
6891 // The linear clause declares one or more list items to be private to a SIMD
6892 // lane and to have a linear relationship with respect to the iteration space
6893 // of a loop.
6894 // The special this pointer can be used as if was one of the arguments to the
6895 // function in any of the linear, aligned, or uniform clauses.
6896 // When a linear-step expression is specified in a linear clause it must be
6897 // either a constant integer expression or an integer-typed parameter that is
6898 // specified in a uniform clause on the directive.
6899 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
6900 const bool IsUniformedThis = UniformedLinearThis != nullptr;
6901 auto MI = LinModifiers.begin();
6902 for (const Expr *E : Linears) {
6903 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
6904 ++MI;
6905 E = E->IgnoreParenImpCasts();
6906 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6907 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6908 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6909 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6910 FD->getParamDecl(PVD->getFunctionScopeIndex())
6911 ->getCanonicalDecl() == CanonPVD) {
6912 // OpenMP [2.15.3.7, linear Clause, Restrictions]
6913 // A list-item cannot appear in more than one linear clause.
6914 if (LinearArgs.count(CanonPVD) > 0) {
6915 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6916 << getOpenMPClauseName(OMPC_linear)
6917 << getOpenMPClauseName(OMPC_linear) << E->getSourceRange();
6918 Diag(LinearArgs[CanonPVD]->getExprLoc(),
6919 diag::note_omp_explicit_dsa)
6920 << getOpenMPClauseName(OMPC_linear);
6921 continue;
6923 // Each argument can appear in at most one uniform or linear clause.
6924 if (UniformedArgs.count(CanonPVD) > 0) {
6925 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6926 << getOpenMPClauseName(OMPC_linear)
6927 << getOpenMPClauseName(OMPC_uniform) << E->getSourceRange();
6928 Diag(UniformedArgs[CanonPVD]->getExprLoc(),
6929 diag::note_omp_explicit_dsa)
6930 << getOpenMPClauseName(OMPC_uniform);
6931 continue;
6933 LinearArgs[CanonPVD] = E;
6934 if (E->isValueDependent() || E->isTypeDependent() ||
6935 E->isInstantiationDependent() ||
6936 E->containsUnexpandedParameterPack())
6937 continue;
6938 (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind,
6939 PVD->getOriginalType(),
6940 /*IsDeclareSimd=*/true);
6941 continue;
6944 if (isa<CXXThisExpr>(E)) {
6945 if (UniformedLinearThis) {
6946 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6947 << getOpenMPClauseName(OMPC_linear)
6948 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform : OMPC_linear)
6949 << E->getSourceRange();
6950 Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa)
6951 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform
6952 : OMPC_linear);
6953 continue;
6955 UniformedLinearThis = E;
6956 if (E->isValueDependent() || E->isTypeDependent() ||
6957 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
6958 continue;
6959 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind,
6960 E->getType(), /*IsDeclareSimd=*/true);
6961 continue;
6963 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6964 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6966 Expr *Step = nullptr;
6967 Expr *NewStep = nullptr;
6968 SmallVector<Expr *, 4> NewSteps;
6969 for (Expr *E : Steps) {
6970 // Skip the same step expression, it was checked already.
6971 if (Step == E || !E) {
6972 NewSteps.push_back(E ? NewStep : nullptr);
6973 continue;
6975 Step = E;
6976 if (const auto *DRE = dyn_cast<DeclRefExpr>(Step))
6977 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6978 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6979 if (UniformedArgs.count(CanonPVD) == 0) {
6980 Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
6981 << Step->getSourceRange();
6982 } else if (E->isValueDependent() || E->isTypeDependent() ||
6983 E->isInstantiationDependent() ||
6984 E->containsUnexpandedParameterPack() ||
6985 CanonPVD->getType()->hasIntegerRepresentation()) {
6986 NewSteps.push_back(Step);
6987 } else {
6988 Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
6989 << Step->getSourceRange();
6991 continue;
6993 NewStep = Step;
6994 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
6995 !Step->isInstantiationDependent() &&
6996 !Step->containsUnexpandedParameterPack()) {
6997 NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step)
6998 .get();
6999 if (NewStep)
7000 NewStep =
7001 VerifyIntegerConstantExpression(NewStep, /*FIXME*/ AllowFold).get();
7003 NewSteps.push_back(NewStep);
7005 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7006 Context, BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
7007 Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
7008 const_cast<Expr **>(NewAligns.data()), NewAligns.size(),
7009 const_cast<Expr **>(Linears.data()), Linears.size(),
7010 const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(),
7011 NewSteps.data(), NewSteps.size(), SR);
7012 ADecl->addAttr(NewAttr);
7013 return DG;
7016 static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
7017 QualType NewType) {
7018 assert(NewType->isFunctionProtoType() &&
7019 "Expected function type with prototype.");
7020 assert(FD->getType()->isFunctionNoProtoType() &&
7021 "Expected function with type with no prototype.");
7022 assert(FDWithProto->getType()->isFunctionProtoType() &&
7023 "Expected function with prototype.");
7024 // Synthesize parameters with the same types.
7025 FD->setType(NewType);
7026 SmallVector<ParmVarDecl *, 16> Params;
7027 for (const ParmVarDecl *P : FDWithProto->parameters()) {
7028 auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(),
7029 SourceLocation(), nullptr, P->getType(),
7030 /*TInfo=*/nullptr, SC_None, nullptr);
7031 Param->setScopeInfo(0, Params.size());
7032 Param->setImplicit();
7033 Params.push_back(Param);
7036 FD->setParams(Params);
7039 void Sema::ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D) {
7040 if (D->isInvalidDecl())
7041 return;
7042 FunctionDecl *FD = nullptr;
7043 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7044 FD = UTemplDecl->getTemplatedDecl();
7045 else
7046 FD = cast<FunctionDecl>(D);
7047 assert(FD && "Expected a function declaration!");
7049 // If we are instantiating templates we do *not* apply scoped assumptions but
7050 // only global ones. We apply scoped assumption to the template definition
7051 // though.
7052 if (!inTemplateInstantiation()) {
7053 for (AssumptionAttr *AA : OMPAssumeScoped)
7054 FD->addAttr(AA);
7056 for (AssumptionAttr *AA : OMPAssumeGlobal)
7057 FD->addAttr(AA);
7060 Sema::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7061 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7063 void Sema::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(
7064 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7065 SmallVectorImpl<FunctionDecl *> &Bases) {
7066 if (!D.getIdentifier())
7067 return;
7069 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7071 // Template specialization is an extension, check if we do it.
7072 bool IsTemplated = !TemplateParamLists.empty();
7073 if (IsTemplated &
7074 !DVScope.TI->isExtensionActive(
7075 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7076 return;
7078 IdentifierInfo *BaseII = D.getIdentifier();
7079 LookupResult Lookup(*this, DeclarationName(BaseII), D.getIdentifierLoc(),
7080 LookupOrdinaryName);
7081 LookupParsedName(Lookup, S, &D.getCXXScopeSpec());
7083 TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
7084 QualType FType = TInfo->getType();
7086 bool IsConstexpr =
7087 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr;
7088 bool IsConsteval =
7089 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Consteval;
7091 for (auto *Candidate : Lookup) {
7092 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7093 FunctionDecl *UDecl = nullptr;
7094 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7095 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7096 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7097 UDecl = FTD->getTemplatedDecl();
7098 } else if (!IsTemplated)
7099 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7100 if (!UDecl)
7101 continue;
7103 // Don't specialize constexpr/consteval functions with
7104 // non-constexpr/consteval functions.
7105 if (UDecl->isConstexpr() && !IsConstexpr)
7106 continue;
7107 if (UDecl->isConsteval() && !IsConsteval)
7108 continue;
7110 QualType UDeclTy = UDecl->getType();
7111 if (!UDeclTy->isDependentType()) {
7112 QualType NewType = Context.mergeFunctionTypes(
7113 FType, UDeclTy, /* OfBlockPointer */ false,
7114 /* Unqualified */ false, /* AllowCXX */ true);
7115 if (NewType.isNull())
7116 continue;
7119 // Found a base!
7120 Bases.push_back(UDecl);
7123 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7124 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7125 // If no base was found we create a declaration that we use as base.
7126 if (Bases.empty() && UseImplicitBase) {
7127 D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration);
7128 Decl *BaseD = HandleDeclarator(S, D, TemplateParamLists);
7129 BaseD->setImplicit(true);
7130 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7131 Bases.push_back(BaseTemplD->getTemplatedDecl());
7132 else
7133 Bases.push_back(cast<FunctionDecl>(BaseD));
7136 std::string MangledName;
7137 MangledName += D.getIdentifier()->getName();
7138 MangledName += getOpenMPVariantManglingSeparatorStr();
7139 MangledName += DVScope.NameSuffix;
7140 IdentifierInfo &VariantII = Context.Idents.get(MangledName);
7142 VariantII.setMangledOpenMPVariantName(true);
7143 D.SetIdentifier(&VariantII, D.getBeginLoc());
7146 void Sema::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
7147 Decl *D, SmallVectorImpl<FunctionDecl *> &Bases) {
7148 // Do not mark function as is used to prevent its emission if this is the
7149 // only place where it is used.
7150 EnterExpressionEvaluationContext Unevaluated(
7151 *this, Sema::ExpressionEvaluationContext::Unevaluated);
7153 FunctionDecl *FD = nullptr;
7154 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7155 FD = UTemplDecl->getTemplatedDecl();
7156 else
7157 FD = cast<FunctionDecl>(D);
7158 auto *VariantFuncRef = DeclRefExpr::Create(
7159 Context, NestedNameSpecifierLoc(), SourceLocation(), FD,
7160 /* RefersToEnclosingVariableOrCapture */ false,
7161 /* NameLoc */ FD->getLocation(), FD->getType(),
7162 ExprValueKind::VK_PRValue);
7164 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7165 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7166 Context, VariantFuncRef, DVScope.TI,
7167 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7168 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7169 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7170 for (FunctionDecl *BaseFD : Bases)
7171 BaseFD->addAttr(OMPDeclareVariantA);
7174 ExprResult Sema::ActOnOpenMPCall(ExprResult Call, Scope *Scope,
7175 SourceLocation LParenLoc,
7176 MultiExprArg ArgExprs,
7177 SourceLocation RParenLoc, Expr *ExecConfig) {
7178 // The common case is a regular call we do not want to specialize at all. Try
7179 // to make that case fast by bailing early.
7180 CallExpr *CE = dyn_cast<CallExpr>(Call.get());
7181 if (!CE)
7182 return Call;
7184 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7185 if (!CalleeFnDecl)
7186 return Call;
7188 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7189 return Call;
7191 ASTContext &Context = getASTContext();
7192 std::function<void(StringRef)> DiagUnknownTrait = [this,
7193 CE](StringRef ISATrait) {
7194 // TODO Track the selector locations in a way that is accessible here to
7195 // improve the diagnostic location.
7196 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7197 << ISATrait;
7199 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7200 getCurFunctionDecl(), DSAStack->getConstructTraits());
7202 QualType CalleeFnType = CalleeFnDecl->getType();
7204 SmallVector<Expr *, 4> Exprs;
7205 SmallVector<VariantMatchInfo, 4> VMIs;
7206 while (CalleeFnDecl) {
7207 for (OMPDeclareVariantAttr *A :
7208 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7209 Expr *VariantRef = A->getVariantFuncRef();
7211 VariantMatchInfo VMI;
7212 OMPTraitInfo &TI = A->getTraitInfo();
7213 TI.getAsVariantMatchInfo(Context, VMI);
7214 if (!isVariantApplicableInContext(VMI, OMPCtx,
7215 /* DeviceSetOnly */ false))
7216 continue;
7218 VMIs.push_back(VMI);
7219 Exprs.push_back(VariantRef);
7222 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7225 ExprResult NewCall;
7226 do {
7227 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7228 if (BestIdx < 0)
7229 return Call;
7230 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7231 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7234 // Try to build a (member) call expression for the current best applicable
7235 // variant expression. We allow this to fail in which case we continue
7236 // with the next best variant expression. The fail case is part of the
7237 // implementation defined behavior in the OpenMP standard when it talks
7238 // about what differences in the function prototypes: "Any differences
7239 // that the specific OpenMP context requires in the prototype of the
7240 // variant from the base function prototype are implementation defined."
7241 // This wording is there to allow the specialized variant to have a
7242 // different type than the base function. This is intended and OK but if
7243 // we cannot create a call the difference is not in the "implementation
7244 // defined range" we allow.
7245 Sema::TentativeAnalysisScope Trap(*this);
7247 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7248 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7249 BestExpr = MemberExpr::CreateImplicit(
7250 Context, MemberCall->getImplicitObjectArgument(),
7251 /* IsArrow */ false, SpecializedMethod, Context.BoundMemberTy,
7252 MemberCall->getValueKind(), MemberCall->getObjectKind());
7254 NewCall = BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs, RParenLoc,
7255 ExecConfig);
7256 if (NewCall.isUsable()) {
7257 if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) {
7258 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7259 QualType NewType = Context.mergeFunctionTypes(
7260 CalleeFnType, NewCalleeFnDecl->getType(),
7261 /* OfBlockPointer */ false,
7262 /* Unqualified */ false, /* AllowCXX */ true);
7263 if (!NewType.isNull())
7264 break;
7265 // Don't use the call if the function type was not compatible.
7266 NewCall = nullptr;
7271 VMIs.erase(VMIs.begin() + BestIdx);
7272 Exprs.erase(Exprs.begin() + BestIdx);
7273 } while (!VMIs.empty());
7275 if (!NewCall.isUsable())
7276 return Call;
7277 return PseudoObjectExpr::Create(Context, CE, {NewCall.get()}, 0);
7280 Optional<std::pair<FunctionDecl *, Expr *>>
7281 Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG,
7282 Expr *VariantRef, OMPTraitInfo &TI,
7283 unsigned NumAppendArgs,
7284 SourceRange SR) {
7285 if (!DG || DG.get().isNull())
7286 return None;
7288 const int VariantId = 1;
7289 // Must be applied only to single decl.
7290 if (!DG.get().isSingleDecl()) {
7291 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7292 << VariantId << SR;
7293 return None;
7295 Decl *ADecl = DG.get().getSingleDecl();
7296 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7297 ADecl = FTD->getTemplatedDecl();
7299 // Decl must be a function.
7300 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7301 if (!FD) {
7302 Diag(ADecl->getLocation(), diag::err_omp_function_expected)
7303 << VariantId << SR;
7304 return None;
7307 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7308 // The 'target' attribute needs to be separately checked because it does
7309 // not always signify a multiversion function declaration.
7310 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7312 // OpenMP is not compatible with multiversion function attributes.
7313 if (HasMultiVersionAttributes(FD)) {
7314 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7315 << SR;
7316 return None;
7319 // Allow #pragma omp declare variant only if the function is not used.
7320 if (FD->isUsed(false))
7321 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
7322 << FD->getLocation();
7324 // Check if the function was emitted already.
7325 const FunctionDecl *Definition;
7326 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7327 (LangOpts.EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
7328 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
7329 << FD->getLocation();
7331 // The VariantRef must point to function.
7332 if (!VariantRef) {
7333 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
7334 return None;
7337 auto ShouldDelayChecks = [](Expr *&E, bool) {
7338 return E && (E->isTypeDependent() || E->isValueDependent() ||
7339 E->containsUnexpandedParameterPack() ||
7340 E->isInstantiationDependent());
7342 // Do not check templates, wait until instantiation.
7343 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7344 TI.anyScoreOrCondition(ShouldDelayChecks))
7345 return std::make_pair(FD, VariantRef);
7347 // Deal with non-constant score and user condition expressions.
7348 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7349 bool IsScore) -> bool {
7350 if (!E || E->isIntegerConstantExpr(Context))
7351 return false;
7353 if (IsScore) {
7354 // We warn on non-constant scores and pretend they were not present.
7355 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7356 << E;
7357 E = nullptr;
7358 } else {
7359 // We could replace a non-constant user condition with "false" but we
7360 // will soon need to handle these anyway for the dynamic version of
7361 // OpenMP context selectors.
7362 Diag(E->getExprLoc(),
7363 diag::err_omp_declare_variant_user_condition_not_constant)
7364 << E;
7366 return true;
7368 if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions))
7369 return None;
7371 QualType AdjustedFnType = FD->getType();
7372 if (NumAppendArgs) {
7373 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7374 if (!PTy) {
7375 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
7376 << SR;
7377 return None;
7379 // Adjust the function type to account for an extra omp_interop_t for each
7380 // specified in the append_args clause.
7381 const TypeDecl *TD = nullptr;
7382 LookupResult Result(*this, &Context.Idents.get("omp_interop_t"),
7383 SR.getBegin(), Sema::LookupOrdinaryName);
7384 if (LookupName(Result, getCurScope())) {
7385 NamedDecl *ND = Result.getFoundDecl();
7386 TD = dyn_cast_or_null<TypeDecl>(ND);
7388 if (!TD) {
7389 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
7390 return None;
7392 QualType InteropType = Context.getTypeDeclType(TD);
7393 if (PTy->isVariadic()) {
7394 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7395 return None;
7397 llvm::SmallVector<QualType, 8> Params;
7398 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7399 Params.insert(Params.end(), NumAppendArgs, InteropType);
7400 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7401 PTy->getExtProtoInfo());
7404 // Convert VariantRef expression to the type of the original function to
7405 // resolve possible conflicts.
7406 ExprResult VariantRefCast = VariantRef;
7407 if (LangOpts.CPlusPlus) {
7408 QualType FnPtrType;
7409 auto *Method = dyn_cast<CXXMethodDecl>(FD);
7410 if (Method && !Method->isStatic()) {
7411 const Type *ClassType =
7412 Context.getTypeDeclType(Method->getParent()).getTypePtr();
7413 FnPtrType = Context.getMemberPointerType(AdjustedFnType, ClassType);
7414 ExprResult ER;
7416 // Build adrr_of unary op to correctly handle type checks for member
7417 // functions.
7418 Sema::TentativeAnalysisScope Trap(*this);
7419 ER = CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf,
7420 VariantRef);
7422 if (!ER.isUsable()) {
7423 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7424 << VariantId << VariantRef->getSourceRange();
7425 return None;
7427 VariantRef = ER.get();
7428 } else {
7429 FnPtrType = Context.getPointerType(AdjustedFnType);
7431 QualType VarianPtrType = Context.getPointerType(VariantRef->getType());
7432 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7433 ImplicitConversionSequence ICS = TryImplicitConversion(
7434 VariantRef, FnPtrType.getUnqualifiedType(),
7435 /*SuppressUserConversions=*/false, AllowedExplicit::None,
7436 /*InOverloadResolution=*/false,
7437 /*CStyle=*/false,
7438 /*AllowObjCWritebackConversion=*/false);
7439 if (ICS.isFailure()) {
7440 Diag(VariantRef->getExprLoc(),
7441 diag::err_omp_declare_variant_incompat_types)
7442 << VariantRef->getType()
7443 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7444 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7445 return None;
7447 VariantRefCast = PerformImplicitConversion(
7448 VariantRef, FnPtrType.getUnqualifiedType(), AA_Converting);
7449 if (!VariantRefCast.isUsable())
7450 return None;
7452 // Drop previously built artificial addr_of unary op for member functions.
7453 if (Method && !Method->isStatic()) {
7454 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7455 if (auto *UO = dyn_cast<UnaryOperator>(
7456 PossibleAddrOfVariantRef->IgnoreImplicit()))
7457 VariantRefCast = UO->getSubExpr();
7461 ExprResult ER = CheckPlaceholderExpr(VariantRefCast.get());
7462 if (!ER.isUsable() ||
7463 !ER.get()->IgnoreParenImpCasts()->getType()->isFunctionType()) {
7464 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7465 << VariantId << VariantRef->getSourceRange();
7466 return None;
7469 // The VariantRef must point to function.
7470 auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts());
7471 if (!DRE) {
7472 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7473 << VariantId << VariantRef->getSourceRange();
7474 return None;
7476 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7477 if (!NewFD) {
7478 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7479 << VariantId << VariantRef->getSourceRange();
7480 return None;
7483 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7484 Diag(VariantRef->getExprLoc(),
7485 diag::err_omp_declare_variant_same_base_function)
7486 << VariantRef->getSourceRange();
7487 return None;
7490 // Check if function types are compatible in C.
7491 if (!LangOpts.CPlusPlus) {
7492 QualType NewType =
7493 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7494 if (NewType.isNull()) {
7495 Diag(VariantRef->getExprLoc(),
7496 diag::err_omp_declare_variant_incompat_types)
7497 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7498 << VariantRef->getSourceRange();
7499 return None;
7501 if (NewType->isFunctionProtoType()) {
7502 if (FD->getType()->isFunctionNoProtoType())
7503 setPrototype(*this, FD, NewFD, NewType);
7504 else if (NewFD->getType()->isFunctionNoProtoType())
7505 setPrototype(*this, NewFD, FD, NewType);
7509 // Check if variant function is not marked with declare variant directive.
7510 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7511 Diag(VariantRef->getExprLoc(),
7512 diag::warn_omp_declare_variant_marked_as_declare_variant)
7513 << VariantRef->getSourceRange();
7514 SourceRange SR =
7515 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7516 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7517 return None;
7520 enum DoesntSupport {
7521 VirtFuncs = 1,
7522 Constructors = 3,
7523 Destructors = 4,
7524 DeletedFuncs = 5,
7525 DefaultedFuncs = 6,
7526 ConstexprFuncs = 7,
7527 ConstevalFuncs = 8,
7529 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7530 if (CXXFD->isVirtual()) {
7531 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7532 << VirtFuncs;
7533 return None;
7536 if (isa<CXXConstructorDecl>(FD)) {
7537 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7538 << Constructors;
7539 return None;
7542 if (isa<CXXDestructorDecl>(FD)) {
7543 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7544 << Destructors;
7545 return None;
7549 if (FD->isDeleted()) {
7550 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7551 << DeletedFuncs;
7552 return None;
7555 if (FD->isDefaulted()) {
7556 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7557 << DefaultedFuncs;
7558 return None;
7561 if (FD->isConstexpr()) {
7562 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7563 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7564 return None;
7567 // Check general compatibility.
7568 if (areMultiversionVariantFunctionsCompatible(
7569 FD, NewFD, PartialDiagnostic::NullDiagnostic(),
7570 PartialDiagnosticAt(SourceLocation(),
7571 PartialDiagnostic::NullDiagnostic()),
7572 PartialDiagnosticAt(
7573 VariantRef->getExprLoc(),
7574 PDiag(diag::err_omp_declare_variant_doesnt_support)),
7575 PartialDiagnosticAt(VariantRef->getExprLoc(),
7576 PDiag(diag::err_omp_declare_variant_diff)
7577 << FD->getLocation()),
7578 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7579 /*CLinkageMayDiffer=*/true))
7580 return None;
7581 return std::make_pair(FD, cast<Expr>(DRE));
7584 void Sema::ActOnOpenMPDeclareVariantDirective(
7585 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7586 ArrayRef<Expr *> AdjustArgsNothing,
7587 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7588 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7589 SourceLocation AppendArgsLoc, SourceRange SR) {
7591 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7592 // An adjust_args clause or append_args clause can only be specified if the
7593 // dispatch selector of the construct selector set appears in the match
7594 // clause.
7596 SmallVector<Expr *, 8> AllAdjustArgs;
7597 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7598 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7600 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7601 VariantMatchInfo VMI;
7602 TI.getAsVariantMatchInfo(Context, VMI);
7603 if (!llvm::is_contained(
7604 VMI.ConstructTraits,
7605 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7606 if (!AllAdjustArgs.empty())
7607 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7608 << getOpenMPClauseName(OMPC_adjust_args);
7609 if (!AppendArgs.empty())
7610 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7611 << getOpenMPClauseName(OMPC_append_args);
7612 return;
7616 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7617 // Each argument can only appear in a single adjust_args clause for each
7618 // declare variant directive.
7619 llvm::SmallPtrSet<const VarDecl *, 4> AdjustVars;
7621 for (Expr *E : AllAdjustArgs) {
7622 E = E->IgnoreParenImpCasts();
7623 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7624 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7625 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7626 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7627 FD->getParamDecl(PVD->getFunctionScopeIndex())
7628 ->getCanonicalDecl() == CanonPVD) {
7629 // It's a parameter of the function, check duplicates.
7630 if (!AdjustVars.insert(CanonPVD).second) {
7631 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7632 << PVD;
7633 return;
7635 continue;
7639 // Anything that is not a function parameter is an error.
7640 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7641 return;
7644 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7645 Context, VariantRef, &TI, const_cast<Expr **>(AdjustArgsNothing.data()),
7646 AdjustArgsNothing.size(),
7647 const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7648 AdjustArgsNeedDevicePtr.size(),
7649 const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR);
7650 FD->addAttr(NewAttr);
7653 StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
7654 Stmt *AStmt,
7655 SourceLocation StartLoc,
7656 SourceLocation EndLoc) {
7657 if (!AStmt)
7658 return StmtError();
7660 auto *CS = cast<CapturedStmt>(AStmt);
7661 // 1.2.2 OpenMP Language Terminology
7662 // Structured block - An executable statement with a single entry at the
7663 // top and a single exit at the bottom.
7664 // The point of exit cannot be a branch out of the structured block.
7665 // longjmp() and throw() must not violate the entry/exit criteria.
7666 CS->getCapturedDecl()->setNothrow();
7668 setFunctionHasBranchProtectedScope();
7670 return OMPParallelDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
7671 DSAStack->getTaskgroupReductionRef(),
7672 DSAStack->isCancelRegion());
7675 namespace {
7676 /// Iteration space of a single for loop.
7677 struct LoopIterationSpace final {
7678 /// True if the condition operator is the strict compare operator (<, > or
7679 /// !=).
7680 bool IsStrictCompare = false;
7681 /// Condition of the loop.
7682 Expr *PreCond = nullptr;
7683 /// This expression calculates the number of iterations in the loop.
7684 /// It is always possible to calculate it before starting the loop.
7685 Expr *NumIterations = nullptr;
7686 /// The loop counter variable.
7687 Expr *CounterVar = nullptr;
7688 /// Private loop counter variable.
7689 Expr *PrivateCounterVar = nullptr;
7690 /// This is initializer for the initial value of #CounterVar.
7691 Expr *CounterInit = nullptr;
7692 /// This is step for the #CounterVar used to generate its update:
7693 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7694 Expr *CounterStep = nullptr;
7695 /// Should step be subtracted?
7696 bool Subtract = false;
7697 /// Source range of the loop init.
7698 SourceRange InitSrcRange;
7699 /// Source range of the loop condition.
7700 SourceRange CondSrcRange;
7701 /// Source range of the loop increment.
7702 SourceRange IncSrcRange;
7703 /// Minimum value that can have the loop control variable. Used to support
7704 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
7705 /// since only such variables can be used in non-loop invariant expressions.
7706 Expr *MinValue = nullptr;
7707 /// Maximum value that can have the loop control variable. Used to support
7708 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
7709 /// since only such variables can be used in non-loop invariant expressions.
7710 Expr *MaxValue = nullptr;
7711 /// true, if the lower bound depends on the outer loop control var.
7712 bool IsNonRectangularLB = false;
7713 /// true, if the upper bound depends on the outer loop control var.
7714 bool IsNonRectangularUB = false;
7715 /// Index of the loop this loop depends on and forms non-rectangular loop
7716 /// nest.
7717 unsigned LoopDependentIdx = 0;
7718 /// Final condition for the non-rectangular loop nest support. It is used to
7719 /// check that the number of iterations for this particular counter must be
7720 /// finished.
7721 Expr *FinalCondition = nullptr;
7724 /// Helper class for checking canonical form of the OpenMP loops and
7725 /// extracting iteration space of each loop in the loop nest, that will be used
7726 /// for IR generation.
7727 class OpenMPIterationSpaceChecker {
7728 /// Reference to Sema.
7729 Sema &SemaRef;
7730 /// Does the loop associated directive support non-rectangular loops?
7731 bool SupportsNonRectangular;
7732 /// Data-sharing stack.
7733 DSAStackTy &Stack;
7734 /// A location for diagnostics (when there is no some better location).
7735 SourceLocation DefaultLoc;
7736 /// A location for diagnostics (when increment is not compatible).
7737 SourceLocation ConditionLoc;
7738 /// A source location for referring to loop init later.
7739 SourceRange InitSrcRange;
7740 /// A source location for referring to condition later.
7741 SourceRange ConditionSrcRange;
7742 /// A source location for referring to increment later.
7743 SourceRange IncrementSrcRange;
7744 /// Loop variable.
7745 ValueDecl *LCDecl = nullptr;
7746 /// Reference to loop variable.
7747 Expr *LCRef = nullptr;
7748 /// Lower bound (initializer for the var).
7749 Expr *LB = nullptr;
7750 /// Upper bound.
7751 Expr *UB = nullptr;
7752 /// Loop step (increment).
7753 Expr *Step = nullptr;
7754 /// This flag is true when condition is one of:
7755 /// Var < UB
7756 /// Var <= UB
7757 /// UB > Var
7758 /// UB >= Var
7759 /// This will have no value when the condition is !=
7760 llvm::Optional<bool> TestIsLessOp;
7761 /// This flag is true when condition is strict ( < or > ).
7762 bool TestIsStrictOp = false;
7763 /// This flag is true when step is subtracted on each iteration.
7764 bool SubtractStep = false;
7765 /// The outer loop counter this loop depends on (if any).
7766 const ValueDecl *DepDecl = nullptr;
7767 /// Contains number of loop (starts from 1) on which loop counter init
7768 /// expression of this loop depends on.
7769 Optional<unsigned> InitDependOnLC;
7770 /// Contains number of loop (starts from 1) on which loop counter condition
7771 /// expression of this loop depends on.
7772 Optional<unsigned> CondDependOnLC;
7773 /// Checks if the provide statement depends on the loop counter.
7774 Optional<unsigned> doesDependOnLoopCounter(const Stmt *S, bool IsInitializer);
7775 /// Original condition required for checking of the exit condition for
7776 /// non-rectangular loop.
7777 Expr *Condition = nullptr;
7779 public:
7780 OpenMPIterationSpaceChecker(Sema &SemaRef, bool SupportsNonRectangular,
7781 DSAStackTy &Stack, SourceLocation DefaultLoc)
7782 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
7783 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc) {}
7784 /// Check init-expr for canonical loop form and save loop counter
7785 /// variable - #Var and its initialization value - #LB.
7786 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
7787 /// Check test-expr for canonical form, save upper-bound (#UB), flags
7788 /// for less/greater and for strict/non-strict comparison.
7789 bool checkAndSetCond(Expr *S);
7790 /// Check incr-expr for canonical loop form and return true if it
7791 /// does not conform, otherwise save loop step (#Step).
7792 bool checkAndSetInc(Expr *S);
7793 /// Return the loop counter variable.
7794 ValueDecl *getLoopDecl() const { return LCDecl; }
7795 /// Return the reference expression to loop counter variable.
7796 Expr *getLoopDeclRefExpr() const { return LCRef; }
7797 /// Source range of the loop init.
7798 SourceRange getInitSrcRange() const { return InitSrcRange; }
7799 /// Source range of the loop condition.
7800 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
7801 /// Source range of the loop increment.
7802 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
7803 /// True if the step should be subtracted.
7804 bool shouldSubtractStep() const { return SubtractStep; }
7805 /// True, if the compare operator is strict (<, > or !=).
7806 bool isStrictTestOp() const { return TestIsStrictOp; }
7807 /// Build the expression to calculate the number of iterations.
7808 Expr *buildNumIterations(
7809 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
7810 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7811 /// Build the precondition expression for the loops.
7812 Expr *
7813 buildPreCond(Scope *S, Expr *Cond,
7814 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7815 /// Build reference expression to the counter be used for codegen.
7816 DeclRefExpr *
7817 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7818 DSAStackTy &DSA) const;
7819 /// Build reference expression to the private counter be used for
7820 /// codegen.
7821 Expr *buildPrivateCounterVar() const;
7822 /// Build initialization of the counter be used for codegen.
7823 Expr *buildCounterInit() const;
7824 /// Build step of the counter be used for codegen.
7825 Expr *buildCounterStep() const;
7826 /// Build loop data with counter value for depend clauses in ordered
7827 /// directives.
7828 Expr *
7829 buildOrderedLoopData(Scope *S, Expr *Counter,
7830 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7831 SourceLocation Loc, Expr *Inc = nullptr,
7832 OverloadedOperatorKind OOK = OO_Amp);
7833 /// Builds the minimum value for the loop counter.
7834 std::pair<Expr *, Expr *> buildMinMaxValues(
7835 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7836 /// Builds final condition for the non-rectangular loops.
7837 Expr *buildFinalCondition(Scope *S) const;
7838 /// Return true if any expression is dependent.
7839 bool dependent() const;
7840 /// Returns true if the initializer forms non-rectangular loop.
7841 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
7842 /// Returns true if the condition forms non-rectangular loop.
7843 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
7844 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
7845 unsigned getLoopDependentIdx() const {
7846 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
7849 private:
7850 /// Check the right-hand side of an assignment in the increment
7851 /// expression.
7852 bool checkAndSetIncRHS(Expr *RHS);
7853 /// Helper to set loop counter variable and its initializer.
7854 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
7855 bool EmitDiags);
7856 /// Helper to set upper bound.
7857 bool setUB(Expr *NewUB, llvm::Optional<bool> LessOp, bool StrictOp,
7858 SourceRange SR, SourceLocation SL);
7859 /// Helper to set loop increment.
7860 bool setStep(Expr *NewStep, bool Subtract);
7863 bool OpenMPIterationSpaceChecker::dependent() const {
7864 if (!LCDecl) {
7865 assert(!LB && !UB && !Step);
7866 return false;
7868 return LCDecl->getType()->isDependentType() ||
7869 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
7870 (Step && Step->isValueDependent());
7873 bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
7874 Expr *NewLCRefExpr,
7875 Expr *NewLB, bool EmitDiags) {
7876 // State consistency checking to ensure correct usage.
7877 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
7878 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
7879 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
7880 return true;
7881 LCDecl = getCanonicalDecl(NewLCDecl);
7882 LCRef = NewLCRefExpr;
7883 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
7884 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
7885 if ((Ctor->isCopyOrMoveConstructor() ||
7886 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
7887 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
7888 NewLB = CE->getArg(0)->IgnoreParenImpCasts();
7889 LB = NewLB;
7890 if (EmitDiags)
7891 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
7892 return false;
7895 bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB,
7896 llvm::Optional<bool> LessOp,
7897 bool StrictOp, SourceRange SR,
7898 SourceLocation SL) {
7899 // State consistency checking to ensure correct usage.
7900 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
7901 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
7902 if (!NewUB || NewUB->containsErrors())
7903 return true;
7904 UB = NewUB;
7905 if (LessOp)
7906 TestIsLessOp = LessOp;
7907 TestIsStrictOp = StrictOp;
7908 ConditionSrcRange = SR;
7909 ConditionLoc = SL;
7910 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
7911 return false;
7914 bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
7915 // State consistency checking to ensure correct usage.
7916 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
7917 if (!NewStep || NewStep->containsErrors())
7918 return true;
7919 if (!NewStep->isValueDependent()) {
7920 // Check that the step is integer expression.
7921 SourceLocation StepLoc = NewStep->getBeginLoc();
7922 ExprResult Val = SemaRef.PerformOpenMPImplicitIntegerConversion(
7923 StepLoc, getExprAsWritten(NewStep));
7924 if (Val.isInvalid())
7925 return true;
7926 NewStep = Val.get();
7928 // OpenMP [2.6, Canonical Loop Form, Restrictions]
7929 // If test-expr is of form var relational-op b and relational-op is < or
7930 // <= then incr-expr must cause var to increase on each iteration of the
7931 // loop. If test-expr is of form var relational-op b and relational-op is
7932 // > or >= then incr-expr must cause var to decrease on each iteration of
7933 // the loop.
7934 // If test-expr is of form b relational-op var and relational-op is < or
7935 // <= then incr-expr must cause var to decrease on each iteration of the
7936 // loop. If test-expr is of form b relational-op var and relational-op is
7937 // > or >= then incr-expr must cause var to increase on each iteration of
7938 // the loop.
7939 Optional<llvm::APSInt> Result =
7940 NewStep->getIntegerConstantExpr(SemaRef.Context);
7941 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
7942 bool IsConstNeg =
7943 Result && Result->isSigned() && (Subtract != Result->isNegative());
7944 bool IsConstPos =
7945 Result && Result->isSigned() && (Subtract == Result->isNegative());
7946 bool IsConstZero = Result && !Result->getBoolValue();
7948 // != with increment is treated as <; != with decrement is treated as >
7949 if (!TestIsLessOp)
7950 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
7951 if (UB &&
7952 (IsConstZero ||
7953 (TestIsLessOp.value() ? (IsConstNeg || (IsUnsigned && Subtract))
7954 : (IsConstPos || (IsUnsigned && !Subtract))))) {
7955 SemaRef.Diag(NewStep->getExprLoc(),
7956 diag::err_omp_loop_incr_not_compatible)
7957 << LCDecl << TestIsLessOp.value() << NewStep->getSourceRange();
7958 SemaRef.Diag(ConditionLoc,
7959 diag::note_omp_loop_cond_requres_compatible_incr)
7960 << TestIsLessOp.value() << ConditionSrcRange;
7961 return true;
7963 if (TestIsLessOp.value() == Subtract) {
7964 NewStep =
7965 SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
7966 .get();
7967 Subtract = !Subtract;
7971 Step = NewStep;
7972 SubtractStep = Subtract;
7973 return false;
7976 namespace {
7977 /// Checker for the non-rectangular loops. Checks if the initializer or
7978 /// condition expression references loop counter variable.
7979 class LoopCounterRefChecker final
7980 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
7981 Sema &SemaRef;
7982 DSAStackTy &Stack;
7983 const ValueDecl *CurLCDecl = nullptr;
7984 const ValueDecl *DepDecl = nullptr;
7985 const ValueDecl *PrevDepDecl = nullptr;
7986 bool IsInitializer = true;
7987 bool SupportsNonRectangular;
7988 unsigned BaseLoopId = 0;
7989 bool checkDecl(const Expr *E, const ValueDecl *VD) {
7990 if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
7991 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
7992 << (IsInitializer ? 0 : 1);
7993 return false;
7995 const auto &&Data = Stack.isLoopControlVariable(VD);
7996 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
7997 // The type of the loop iterator on which we depend may not have a random
7998 // access iterator type.
7999 if (Data.first && VD->getType()->isRecordType()) {
8000 SmallString<128> Name;
8001 llvm::raw_svector_ostream OS(Name);
8002 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8003 /*Qualified=*/true);
8004 SemaRef.Diag(E->getExprLoc(),
8005 diag::err_omp_wrong_dependency_iterator_type)
8006 << OS.str();
8007 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
8008 return false;
8010 if (Data.first && !SupportsNonRectangular) {
8011 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
8012 return false;
8014 if (Data.first &&
8015 (DepDecl || (PrevDepDecl &&
8016 getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
8017 if (!DepDecl && PrevDepDecl)
8018 DepDecl = PrevDepDecl;
8019 SmallString<128> Name;
8020 llvm::raw_svector_ostream OS(Name);
8021 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8022 /*Qualified=*/true);
8023 SemaRef.Diag(E->getExprLoc(),
8024 diag::err_omp_invariant_or_linear_dependency)
8025 << OS.str();
8026 return false;
8028 if (Data.first) {
8029 DepDecl = VD;
8030 BaseLoopId = Data.first;
8032 return Data.first;
8035 public:
8036 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8037 const ValueDecl *VD = E->getDecl();
8038 if (isa<VarDecl>(VD))
8039 return checkDecl(E, VD);
8040 return false;
8042 bool VisitMemberExpr(const MemberExpr *E) {
8043 if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
8044 const ValueDecl *VD = E->getMemberDecl();
8045 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8046 return checkDecl(E, VD);
8048 return false;
8050 bool VisitStmt(const Stmt *S) {
8051 bool Res = false;
8052 for (const Stmt *Child : S->children())
8053 Res = (Child && Visit(Child)) || Res;
8054 return Res;
8056 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8057 const ValueDecl *CurLCDecl, bool IsInitializer,
8058 const ValueDecl *PrevDepDecl = nullptr,
8059 bool SupportsNonRectangular = true)
8060 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8061 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8062 SupportsNonRectangular(SupportsNonRectangular) {}
8063 unsigned getBaseLoopId() const {
8064 assert(CurLCDecl && "Expected loop dependency.");
8065 return BaseLoopId;
8067 const ValueDecl *getDepDecl() const {
8068 assert(CurLCDecl && "Expected loop dependency.");
8069 return DepDecl;
8072 } // namespace
8074 Optional<unsigned>
8075 OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8076 bool IsInitializer) {
8077 // Check for the non-rectangular loops.
8078 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8079 DepDecl, SupportsNonRectangular);
8080 if (LoopStmtChecker.Visit(S)) {
8081 DepDecl = LoopStmtChecker.getDepDecl();
8082 return LoopStmtChecker.getBaseLoopId();
8084 return llvm::None;
8087 bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8088 // Check init-expr for canonical loop form and save loop counter
8089 // variable - #Var and its initialization value - #LB.
8090 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8091 // var = lb
8092 // integer-type var = lb
8093 // random-access-iterator-type var = lb
8094 // pointer-type var = lb
8096 if (!S) {
8097 if (EmitDiags) {
8098 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8100 return true;
8102 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8103 if (!ExprTemp->cleanupsHaveSideEffects())
8104 S = ExprTemp->getSubExpr();
8106 InitSrcRange = S->getSourceRange();
8107 if (Expr *E = dyn_cast<Expr>(S))
8108 S = E->IgnoreParens();
8109 if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8110 if (BO->getOpcode() == BO_Assign) {
8111 Expr *LHS = BO->getLHS()->IgnoreParens();
8112 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8113 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8114 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8115 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8116 EmitDiags);
8117 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8119 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8120 if (ME->isArrow() &&
8121 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8122 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8123 EmitDiags);
8126 } else if (auto *DS = dyn_cast<DeclStmt>(S)) {
8127 if (DS->isSingleDecl()) {
8128 if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8129 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8130 // Accept non-canonical init form here but emit ext. warning.
8131 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8132 SemaRef.Diag(S->getBeginLoc(),
8133 diag::ext_omp_loop_not_canonical_init)
8134 << S->getSourceRange();
8135 return setLCDeclAndLB(
8136 Var,
8137 buildDeclRefExpr(SemaRef, Var,
8138 Var->getType().getNonReferenceType(),
8139 DS->getBeginLoc()),
8140 Var->getInit(), EmitDiags);
8144 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8145 if (CE->getOperator() == OO_Equal) {
8146 Expr *LHS = CE->getArg(0);
8147 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8148 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8149 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8150 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8151 EmitDiags);
8152 return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags);
8154 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8155 if (ME->isArrow() &&
8156 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8157 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8158 EmitDiags);
8163 if (dependent() || SemaRef.CurContext->isDependentContext())
8164 return false;
8165 if (EmitDiags) {
8166 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8167 << S->getSourceRange();
8169 return true;
8172 /// Ignore parenthesizes, implicit casts, copy constructor and return the
8173 /// variable (which may be the loop variable) if possible.
8174 static const ValueDecl *getInitLCDecl(const Expr *E) {
8175 if (!E)
8176 return nullptr;
8177 E = getExprAsWritten(E);
8178 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8179 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8180 if ((Ctor->isCopyOrMoveConstructor() ||
8181 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8182 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8183 E = CE->getArg(0)->IgnoreParenImpCasts();
8184 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8185 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
8186 return getCanonicalDecl(VD);
8188 if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8189 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8190 return getCanonicalDecl(ME->getMemberDecl());
8191 return nullptr;
8194 bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8195 // Check test-expr for canonical form, save upper-bound UB, flags for
8196 // less/greater and for strict/non-strict comparison.
8197 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8198 // var relational-op b
8199 // b relational-op var
8201 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8202 if (!S) {
8203 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8204 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8205 return true;
8207 Condition = S;
8208 S = getExprAsWritten(S);
8209 SourceLocation CondLoc = S->getBeginLoc();
8210 auto &&CheckAndSetCond = [this, IneqCondIsCanonical](
8211 BinaryOperatorKind Opcode, const Expr *LHS,
8212 const Expr *RHS, SourceRange SR,
8213 SourceLocation OpLoc) -> llvm::Optional<bool> {
8214 if (BinaryOperator::isRelationalOp(Opcode)) {
8215 if (getInitLCDecl(LHS) == LCDecl)
8216 return setUB(const_cast<Expr *>(RHS),
8217 (Opcode == BO_LT || Opcode == BO_LE),
8218 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8219 if (getInitLCDecl(RHS) == LCDecl)
8220 return setUB(const_cast<Expr *>(LHS),
8221 (Opcode == BO_GT || Opcode == BO_GE),
8222 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8223 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8224 return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8225 /*LessOp=*/llvm::None,
8226 /*StrictOp=*/true, SR, OpLoc);
8228 return llvm::None;
8230 llvm::Optional<bool> Res;
8231 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8232 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8233 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8234 RBO->getOperatorLoc());
8235 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8236 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8237 BO->getSourceRange(), BO->getOperatorLoc());
8238 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8239 if (CE->getNumArgs() == 2) {
8240 Res = CheckAndSetCond(
8241 BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0),
8242 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8245 if (Res)
8246 return *Res;
8247 if (dependent() || SemaRef.CurContext->isDependentContext())
8248 return false;
8249 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8250 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8251 return true;
8254 bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8255 // RHS of canonical loop form increment can be:
8256 // var + incr
8257 // incr + var
8258 // var - incr
8260 RHS = RHS->IgnoreParenImpCasts();
8261 if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8262 if (BO->isAdditiveOp()) {
8263 bool IsAdd = BO->getOpcode() == BO_Add;
8264 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8265 return setStep(BO->getRHS(), !IsAdd);
8266 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8267 return setStep(BO->getLHS(), /*Subtract=*/false);
8269 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8270 bool IsAdd = CE->getOperator() == OO_Plus;
8271 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8272 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8273 return setStep(CE->getArg(1), !IsAdd);
8274 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8275 return setStep(CE->getArg(0), /*Subtract=*/false);
8278 if (dependent() || SemaRef.CurContext->isDependentContext())
8279 return false;
8280 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8281 << RHS->getSourceRange() << LCDecl;
8282 return true;
8285 bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8286 // Check incr-expr for canonical loop form and return true if it
8287 // does not conform.
8288 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8289 // ++var
8290 // var++
8291 // --var
8292 // var--
8293 // var += incr
8294 // var -= incr
8295 // var = var + incr
8296 // var = incr + var
8297 // var = var - incr
8299 if (!S) {
8300 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8301 return true;
8303 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8304 if (!ExprTemp->cleanupsHaveSideEffects())
8305 S = ExprTemp->getSubExpr();
8307 IncrementSrcRange = S->getSourceRange();
8308 S = S->IgnoreParens();
8309 if (auto *UO = dyn_cast<UnaryOperator>(S)) {
8310 if (UO->isIncrementDecrementOp() &&
8311 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8312 return setStep(SemaRef
8313 .ActOnIntegerConstant(UO->getBeginLoc(),
8314 (UO->isDecrementOp() ? -1 : 1))
8315 .get(),
8316 /*Subtract=*/false);
8317 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8318 switch (BO->getOpcode()) {
8319 case BO_AddAssign:
8320 case BO_SubAssign:
8321 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8322 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8323 break;
8324 case BO_Assign:
8325 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8326 return checkAndSetIncRHS(BO->getRHS());
8327 break;
8328 default:
8329 break;
8331 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8332 switch (CE->getOperator()) {
8333 case OO_PlusPlus:
8334 case OO_MinusMinus:
8335 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8336 return setStep(SemaRef
8337 .ActOnIntegerConstant(
8338 CE->getBeginLoc(),
8339 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8340 .get(),
8341 /*Subtract=*/false);
8342 break;
8343 case OO_PlusEqual:
8344 case OO_MinusEqual:
8345 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8346 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8347 break;
8348 case OO_Equal:
8349 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8350 return checkAndSetIncRHS(CE->getArg(1));
8351 break;
8352 default:
8353 break;
8356 if (dependent() || SemaRef.CurContext->isDependentContext())
8357 return false;
8358 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8359 << S->getSourceRange() << LCDecl;
8360 return true;
8363 static ExprResult
8364 tryBuildCapture(Sema &SemaRef, Expr *Capture,
8365 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8366 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8367 return Capture;
8368 if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects))
8369 return SemaRef.PerformImplicitConversion(
8370 Capture->IgnoreImpCasts(), Capture->getType(), Sema::AA_Converting,
8371 /*AllowExplicit=*/true);
8372 auto I = Captures.find(Capture);
8373 if (I != Captures.end())
8374 return buildCapture(SemaRef, Capture, I->second);
8375 DeclRefExpr *Ref = nullptr;
8376 ExprResult Res = buildCapture(SemaRef, Capture, Ref);
8377 Captures[Capture] = Ref;
8378 return Res;
8381 /// Calculate number of iterations, transforming to unsigned, if number of
8382 /// iterations may be larger than the original type.
8383 static Expr *
8384 calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8385 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8386 bool TestIsStrictOp, bool RoundToStep,
8387 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8388 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures);
8389 if (!NewStep.isUsable())
8390 return nullptr;
8391 llvm::APSInt LRes, SRes;
8392 bool IsLowerConst = false, IsStepConst = false;
8393 if (Optional<llvm::APSInt> Res =
8394 Lower->getIntegerConstantExpr(SemaRef.Context)) {
8395 LRes = *Res;
8396 IsLowerConst = true;
8398 if (Optional<llvm::APSInt> Res =
8399 Step->getIntegerConstantExpr(SemaRef.Context)) {
8400 SRes = *Res;
8401 IsStepConst = true;
8403 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8404 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8405 (TestIsStrictOp && LRes.isStrictlyPositive()));
8406 bool NeedToReorganize = false;
8407 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8408 if (!NoNeedToConvert && IsLowerConst &&
8409 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8410 NoNeedToConvert = true;
8411 if (RoundToStep) {
8412 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8413 ? LRes.getBitWidth()
8414 : SRes.getBitWidth();
8415 LRes = LRes.extend(BW + 1);
8416 LRes.setIsSigned(true);
8417 SRes = SRes.extend(BW + 1);
8418 SRes.setIsSigned(true);
8419 LRes -= SRes;
8420 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8421 LRes = LRes.trunc(BW);
8423 if (TestIsStrictOp) {
8424 unsigned BW = LRes.getBitWidth();
8425 LRes = LRes.extend(BW + 1);
8426 LRes.setIsSigned(true);
8427 ++LRes;
8428 NoNeedToConvert =
8429 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8430 // truncate to the original bitwidth.
8431 LRes = LRes.trunc(BW);
8433 NeedToReorganize = NoNeedToConvert;
8435 llvm::APSInt URes;
8436 bool IsUpperConst = false;
8437 if (Optional<llvm::APSInt> Res =
8438 Upper->getIntegerConstantExpr(SemaRef.Context)) {
8439 URes = *Res;
8440 IsUpperConst = true;
8442 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8443 (!RoundToStep || IsStepConst)) {
8444 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8445 : URes.getBitWidth();
8446 LRes = LRes.extend(BW + 1);
8447 LRes.setIsSigned(true);
8448 URes = URes.extend(BW + 1);
8449 URes.setIsSigned(true);
8450 URes -= LRes;
8451 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8452 NeedToReorganize = NoNeedToConvert;
8454 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8455 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8456 // unsigned.
8457 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8458 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8459 QualType LowerTy = Lower->getType();
8460 QualType UpperTy = Upper->getType();
8461 uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy);
8462 uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy);
8463 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8464 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8465 QualType CastType = SemaRef.Context.getIntTypeForBitwidth(
8466 LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8467 Upper =
8468 SemaRef
8469 .PerformImplicitConversion(
8470 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8471 CastType, Sema::AA_Converting)
8472 .get();
8473 Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get();
8474 NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get());
8477 if (!Lower || !Upper || NewStep.isInvalid())
8478 return nullptr;
8480 ExprResult Diff;
8481 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8482 // 1]).
8483 if (NeedToReorganize) {
8484 Diff = Lower;
8486 if (RoundToStep) {
8487 // Lower - Step
8488 Diff =
8489 SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get());
8490 if (!Diff.isUsable())
8491 return nullptr;
8494 // Lower - Step [+ 1]
8495 if (TestIsStrictOp)
8496 Diff = SemaRef.BuildBinOp(
8497 S, DefaultLoc, BO_Add, Diff.get(),
8498 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8499 if (!Diff.isUsable())
8500 return nullptr;
8502 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8503 if (!Diff.isUsable())
8504 return nullptr;
8506 // Upper - (Lower - Step [+ 1]).
8507 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get());
8508 if (!Diff.isUsable())
8509 return nullptr;
8510 } else {
8511 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8513 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8514 // BuildBinOp already emitted error, this one is to point user to upper
8515 // and lower bound, and to tell what is passed to 'operator-'.
8516 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
8517 << Upper->getSourceRange() << Lower->getSourceRange();
8518 return nullptr;
8521 if (!Diff.isUsable())
8522 return nullptr;
8524 // Upper - Lower [- 1]
8525 if (TestIsStrictOp)
8526 Diff = SemaRef.BuildBinOp(
8527 S, DefaultLoc, BO_Sub, Diff.get(),
8528 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8529 if (!Diff.isUsable())
8530 return nullptr;
8532 if (RoundToStep) {
8533 // Upper - Lower [- 1] + Step
8534 Diff =
8535 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
8536 if (!Diff.isUsable())
8537 return nullptr;
8541 // Parentheses (for dumping/debugging purposes only).
8542 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8543 if (!Diff.isUsable())
8544 return nullptr;
8546 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8547 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
8548 if (!Diff.isUsable())
8549 return nullptr;
8551 return Diff.get();
8554 /// Build the expression to calculate the number of iterations.
8555 Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8556 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8557 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8558 QualType VarType = LCDecl->getType().getNonReferenceType();
8559 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8560 !SemaRef.getLangOpts().CPlusPlus)
8561 return nullptr;
8562 Expr *LBVal = LB;
8563 Expr *UBVal = UB;
8564 // LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8565 // max(LB(MinVal), LB(MaxVal))
8566 if (InitDependOnLC) {
8567 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8568 if (!IS.MinValue || !IS.MaxValue)
8569 return nullptr;
8570 // OuterVar = Min
8571 ExprResult MinValue =
8572 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8573 if (!MinValue.isUsable())
8574 return nullptr;
8576 ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8577 IS.CounterVar, MinValue.get());
8578 if (!LBMinVal.isUsable())
8579 return nullptr;
8580 // OuterVar = Min, LBVal
8581 LBMinVal =
8582 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal);
8583 if (!LBMinVal.isUsable())
8584 return nullptr;
8585 // (OuterVar = Min, LBVal)
8586 LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get());
8587 if (!LBMinVal.isUsable())
8588 return nullptr;
8590 // OuterVar = Max
8591 ExprResult MaxValue =
8592 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8593 if (!MaxValue.isUsable())
8594 return nullptr;
8596 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8597 IS.CounterVar, MaxValue.get());
8598 if (!LBMaxVal.isUsable())
8599 return nullptr;
8600 // OuterVar = Max, LBVal
8601 LBMaxVal =
8602 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal);
8603 if (!LBMaxVal.isUsable())
8604 return nullptr;
8605 // (OuterVar = Max, LBVal)
8606 LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get());
8607 if (!LBMaxVal.isUsable())
8608 return nullptr;
8610 Expr *LBMin = tryBuildCapture(SemaRef, LBMinVal.get(), Captures).get();
8611 Expr *LBMax = tryBuildCapture(SemaRef, LBMaxVal.get(), Captures).get();
8612 if (!LBMin || !LBMax)
8613 return nullptr;
8614 // LB(MinVal) < LB(MaxVal)
8615 ExprResult MinLessMaxRes =
8616 SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8617 if (!MinLessMaxRes.isUsable())
8618 return nullptr;
8619 Expr *MinLessMax =
8620 tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures).get();
8621 if (!MinLessMax)
8622 return nullptr;
8623 if (*TestIsLessOp) {
8624 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8625 // LB(MaxVal))
8626 ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8627 MinLessMax, LBMin, LBMax);
8628 if (!MinLB.isUsable())
8629 return nullptr;
8630 LBVal = MinLB.get();
8631 } else {
8632 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8633 // LB(MaxVal))
8634 ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8635 MinLessMax, LBMax, LBMin);
8636 if (!MaxLB.isUsable())
8637 return nullptr;
8638 LBVal = MaxLB.get();
8641 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8642 // min(UB(MinVal), UB(MaxVal))
8643 if (CondDependOnLC) {
8644 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8645 if (!IS.MinValue || !IS.MaxValue)
8646 return nullptr;
8647 // OuterVar = Min
8648 ExprResult MinValue =
8649 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8650 if (!MinValue.isUsable())
8651 return nullptr;
8653 ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8654 IS.CounterVar, MinValue.get());
8655 if (!UBMinVal.isUsable())
8656 return nullptr;
8657 // OuterVar = Min, UBVal
8658 UBMinVal =
8659 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal);
8660 if (!UBMinVal.isUsable())
8661 return nullptr;
8662 // (OuterVar = Min, UBVal)
8663 UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get());
8664 if (!UBMinVal.isUsable())
8665 return nullptr;
8667 // OuterVar = Max
8668 ExprResult MaxValue =
8669 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8670 if (!MaxValue.isUsable())
8671 return nullptr;
8673 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8674 IS.CounterVar, MaxValue.get());
8675 if (!UBMaxVal.isUsable())
8676 return nullptr;
8677 // OuterVar = Max, UBVal
8678 UBMaxVal =
8679 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal);
8680 if (!UBMaxVal.isUsable())
8681 return nullptr;
8682 // (OuterVar = Max, UBVal)
8683 UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get());
8684 if (!UBMaxVal.isUsable())
8685 return nullptr;
8687 Expr *UBMin = tryBuildCapture(SemaRef, UBMinVal.get(), Captures).get();
8688 Expr *UBMax = tryBuildCapture(SemaRef, UBMaxVal.get(), Captures).get();
8689 if (!UBMin || !UBMax)
8690 return nullptr;
8691 // UB(MinVal) > UB(MaxVal)
8692 ExprResult MinGreaterMaxRes =
8693 SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
8694 if (!MinGreaterMaxRes.isUsable())
8695 return nullptr;
8696 Expr *MinGreaterMax =
8697 tryBuildCapture(SemaRef, MinGreaterMaxRes.get(), Captures).get();
8698 if (!MinGreaterMax)
8699 return nullptr;
8700 if (*TestIsLessOp) {
8701 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
8702 // UB(MaxVal))
8703 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
8704 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
8705 if (!MaxUB.isUsable())
8706 return nullptr;
8707 UBVal = MaxUB.get();
8708 } else {
8709 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
8710 // UB(MaxVal))
8711 ExprResult MinUB = SemaRef.ActOnConditionalOp(
8712 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
8713 if (!MinUB.isUsable())
8714 return nullptr;
8715 UBVal = MinUB.get();
8718 Expr *UBExpr = TestIsLessOp.value() ? UBVal : LBVal;
8719 Expr *LBExpr = TestIsLessOp.value() ? LBVal : UBVal;
8720 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures).get();
8721 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures).get();
8722 if (!Upper || !Lower)
8723 return nullptr;
8725 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8726 Step, VarType, TestIsStrictOp,
8727 /*RoundToStep=*/true, Captures);
8728 if (!Diff.isUsable())
8729 return nullptr;
8731 // OpenMP runtime requires 32-bit or 64-bit loop variables.
8732 QualType Type = Diff.get()->getType();
8733 ASTContext &C = SemaRef.Context;
8734 bool UseVarType = VarType->hasIntegerRepresentation() &&
8735 C.getTypeSize(Type) > C.getTypeSize(VarType);
8736 if (!Type->isIntegerType() || UseVarType) {
8737 unsigned NewSize =
8738 UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type);
8739 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
8740 : Type->hasSignedIntegerRepresentation();
8741 Type = C.getIntTypeForBitwidth(NewSize, IsSigned);
8742 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) {
8743 Diff = SemaRef.PerformImplicitConversion(
8744 Diff.get(), Type, Sema::AA_Converting, /*AllowExplicit=*/true);
8745 if (!Diff.isUsable())
8746 return nullptr;
8749 if (LimitedType) {
8750 unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
8751 if (NewSize != C.getTypeSize(Type)) {
8752 if (NewSize < C.getTypeSize(Type)) {
8753 assert(NewSize == 64 && "incorrect loop var size");
8754 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
8755 << InitSrcRange << ConditionSrcRange;
8757 QualType NewType = C.getIntTypeForBitwidth(
8758 NewSize, Type->hasSignedIntegerRepresentation() ||
8759 C.getTypeSize(Type) < NewSize);
8760 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) {
8761 Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
8762 Sema::AA_Converting, true);
8763 if (!Diff.isUsable())
8764 return nullptr;
8769 return Diff.get();
8772 std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
8773 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8774 // Do not build for iterators, they cannot be used in non-rectangular loop
8775 // nests.
8776 if (LCDecl->getType()->isRecordType())
8777 return std::make_pair(nullptr, nullptr);
8778 // If we subtract, the min is in the condition, otherwise the min is in the
8779 // init value.
8780 Expr *MinExpr = nullptr;
8781 Expr *MaxExpr = nullptr;
8782 Expr *LBExpr = TestIsLessOp.value() ? LB : UB;
8783 Expr *UBExpr = TestIsLessOp.value() ? UB : LB;
8784 bool LBNonRect = TestIsLessOp.value() ? InitDependOnLC.has_value()
8785 : CondDependOnLC.has_value();
8786 bool UBNonRect = TestIsLessOp.value() ? CondDependOnLC.has_value()
8787 : InitDependOnLC.has_value();
8788 Expr *Lower =
8789 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
8790 Expr *Upper =
8791 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
8792 if (!Upper || !Lower)
8793 return std::make_pair(nullptr, nullptr);
8795 if (*TestIsLessOp)
8796 MinExpr = Lower;
8797 else
8798 MaxExpr = Upper;
8800 // Build minimum/maximum value based on number of iterations.
8801 QualType VarType = LCDecl->getType().getNonReferenceType();
8803 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8804 Step, VarType, TestIsStrictOp,
8805 /*RoundToStep=*/false, Captures);
8806 if (!Diff.isUsable())
8807 return std::make_pair(nullptr, nullptr);
8809 // ((Upper - Lower [- 1]) / Step) * Step
8810 // Parentheses (for dumping/debugging purposes only).
8811 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8812 if (!Diff.isUsable())
8813 return std::make_pair(nullptr, nullptr);
8815 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures);
8816 if (!NewStep.isUsable())
8817 return std::make_pair(nullptr, nullptr);
8818 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get());
8819 if (!Diff.isUsable())
8820 return std::make_pair(nullptr, nullptr);
8822 // Parentheses (for dumping/debugging purposes only).
8823 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8824 if (!Diff.isUsable())
8825 return std::make_pair(nullptr, nullptr);
8827 // Convert to the ptrdiff_t, if original type is pointer.
8828 if (VarType->isAnyPointerType() &&
8829 !SemaRef.Context.hasSameType(
8830 Diff.get()->getType(),
8831 SemaRef.Context.getUnsignedPointerDiffType())) {
8832 Diff = SemaRef.PerformImplicitConversion(
8833 Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(),
8834 Sema::AA_Converting, /*AllowExplicit=*/true);
8836 if (!Diff.isUsable())
8837 return std::make_pair(nullptr, nullptr);
8839 if (*TestIsLessOp) {
8840 // MinExpr = Lower;
8841 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
8842 Diff = SemaRef.BuildBinOp(
8843 S, DefaultLoc, BO_Add,
8844 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(),
8845 Diff.get());
8846 if (!Diff.isUsable())
8847 return std::make_pair(nullptr, nullptr);
8848 } else {
8849 // MaxExpr = Upper;
8850 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
8851 Diff = SemaRef.BuildBinOp(
8852 S, DefaultLoc, BO_Sub,
8853 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8854 Diff.get());
8855 if (!Diff.isUsable())
8856 return std::make_pair(nullptr, nullptr);
8859 // Convert to the original type.
8860 if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType))
8861 Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType,
8862 Sema::AA_Converting,
8863 /*AllowExplicit=*/true);
8864 if (!Diff.isUsable())
8865 return std::make_pair(nullptr, nullptr);
8867 Sema::TentativeAnalysisScope Trap(SemaRef);
8868 Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false);
8869 if (!Diff.isUsable())
8870 return std::make_pair(nullptr, nullptr);
8872 if (*TestIsLessOp)
8873 MaxExpr = Diff.get();
8874 else
8875 MinExpr = Diff.get();
8877 return std::make_pair(MinExpr, MaxExpr);
8880 Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
8881 if (InitDependOnLC || CondDependOnLC)
8882 return Condition;
8883 return nullptr;
8886 Expr *OpenMPIterationSpaceChecker::buildPreCond(
8887 Scope *S, Expr *Cond,
8888 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8889 // Do not build a precondition when the condition/initialization is dependent
8890 // to prevent pessimistic early loop exit.
8891 // TODO: this can be improved by calculating min/max values but not sure that
8892 // it will be very effective.
8893 if (CondDependOnLC || InitDependOnLC)
8894 return SemaRef
8895 .PerformImplicitConversion(
8896 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(),
8897 SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
8898 /*AllowExplicit=*/true)
8899 .get();
8901 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
8902 Sema::TentativeAnalysisScope Trap(SemaRef);
8904 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
8905 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
8906 if (!NewLB.isUsable() || !NewUB.isUsable())
8907 return nullptr;
8909 ExprResult CondExpr = SemaRef.BuildBinOp(
8910 S, DefaultLoc,
8911 TestIsLessOp.value() ? (TestIsStrictOp ? BO_LT : BO_LE)
8912 : (TestIsStrictOp ? BO_GT : BO_GE),
8913 NewLB.get(), NewUB.get());
8914 if (CondExpr.isUsable()) {
8915 if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
8916 SemaRef.Context.BoolTy))
8917 CondExpr = SemaRef.PerformImplicitConversion(
8918 CondExpr.get(), SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
8919 /*AllowExplicit=*/true);
8922 // Otherwise use original loop condition and evaluate it in runtime.
8923 return CondExpr.isUsable() ? CondExpr.get() : Cond;
8926 /// Build reference expression to the counter be used for codegen.
8927 DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
8928 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8929 DSAStackTy &DSA) const {
8930 auto *VD = dyn_cast<VarDecl>(LCDecl);
8931 if (!VD) {
8932 VD = SemaRef.isOpenMPCapturedDecl(LCDecl);
8933 DeclRefExpr *Ref = buildDeclRefExpr(
8934 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
8935 const DSAStackTy::DSAVarData Data =
8936 DSA.getTopDSA(LCDecl, /*FromParent=*/false);
8937 // If the loop control decl is explicitly marked as private, do not mark it
8938 // as captured again.
8939 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
8940 Captures.insert(std::make_pair(LCRef, Ref));
8941 return Ref;
8943 return cast<DeclRefExpr>(LCRef);
8946 Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
8947 if (LCDecl && !LCDecl->isInvalidDecl()) {
8948 QualType Type = LCDecl->getType().getNonReferenceType();
8949 VarDecl *PrivateVar = buildVarDecl(
8950 SemaRef, DefaultLoc, Type, LCDecl->getName(),
8951 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
8952 isa<VarDecl>(LCDecl)
8953 ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
8954 : nullptr);
8955 if (PrivateVar->isInvalidDecl())
8956 return nullptr;
8957 return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
8959 return nullptr;
8962 /// Build initialization of the counter to be used for codegen.
8963 Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
8965 /// Build step of the counter be used for codegen.
8966 Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
8968 Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
8969 Scope *S, Expr *Counter,
8970 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
8971 Expr *Inc, OverloadedOperatorKind OOK) {
8972 Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
8973 if (!Cnt)
8974 return nullptr;
8975 if (Inc) {
8976 assert((OOK == OO_Plus || OOK == OO_Minus) &&
8977 "Expected only + or - operations for depend clauses.");
8978 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
8979 Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
8980 if (!Cnt)
8981 return nullptr;
8983 QualType VarType = LCDecl->getType().getNonReferenceType();
8984 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8985 !SemaRef.getLangOpts().CPlusPlus)
8986 return nullptr;
8987 // Upper - Lower
8988 Expr *Upper =
8989 TestIsLessOp.value() ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
8990 Expr *Lower =
8991 TestIsLessOp.value() ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
8992 if (!Upper || !Lower)
8993 return nullptr;
8995 ExprResult Diff = calculateNumIters(
8996 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
8997 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures);
8998 if (!Diff.isUsable())
8999 return nullptr;
9001 return Diff.get();
9003 } // namespace
9005 void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) {
9006 assert(getLangOpts().OpenMP && "OpenMP is not active.");
9007 assert(Init && "Expected loop in canonical form.");
9008 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9009 if (AssociatedLoops > 0 &&
9010 isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
9011 DSAStack->loopStart();
9012 OpenMPIterationSpaceChecker ISC(*this, /*SupportsNonRectangular=*/true,
9013 *DSAStack, ForLoc);
9014 if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
9015 if (ValueDecl *D = ISC.getLoopDecl()) {
9016 auto *VD = dyn_cast<VarDecl>(D);
9017 DeclRefExpr *PrivateRef = nullptr;
9018 if (!VD) {
9019 if (VarDecl *Private = isOpenMPCapturedDecl(D)) {
9020 VD = Private;
9021 } else {
9022 PrivateRef = buildCapture(*this, D, ISC.getLoopDeclRefExpr(),
9023 /*WithInit=*/false);
9024 VD = cast<VarDecl>(PrivateRef->getDecl());
9027 DSAStack->addLoopControlVariable(D, VD);
9028 const Decl *LD = DSAStack->getPossiblyLoopCunter();
9029 if (LD != D->getCanonicalDecl()) {
9030 DSAStack->resetPossibleLoopCounter();
9031 if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
9032 MarkDeclarationsReferencedInExpr(
9033 buildDeclRefExpr(*this, const_cast<VarDecl *>(Var),
9034 Var->getType().getNonLValueExprType(Context),
9035 ForLoc, /*RefersToCapture=*/true));
9037 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9038 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9039 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9040 // associated for-loop of a simd construct with just one associated
9041 // for-loop may be listed in a linear clause with a constant-linear-step
9042 // that is the increment of the associated for-loop. The loop iteration
9043 // variable(s) in the associated for-loop(s) of a for or parallel for
9044 // construct may be listed in a private or lastprivate clause.
9045 DSAStackTy::DSAVarData DVar =
9046 DSAStack->getTopDSA(D, /*FromParent=*/false);
9047 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9048 // is declared in the loop and it is predetermined as a private.
9049 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9050 OpenMPClauseKind PredeterminedCKind =
9051 isOpenMPSimdDirective(DKind)
9052 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9053 : OMPC_private;
9054 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9055 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9056 (LangOpts.OpenMP <= 45 || (DVar.CKind != OMPC_lastprivate &&
9057 DVar.CKind != OMPC_private))) ||
9058 ((isOpenMPWorksharingDirective(DKind) || DKind == OMPD_taskloop ||
9059 DKind == OMPD_master_taskloop || DKind == OMPD_masked_taskloop ||
9060 DKind == OMPD_parallel_master_taskloop ||
9061 DKind == OMPD_parallel_masked_taskloop ||
9062 isOpenMPDistributeDirective(DKind)) &&
9063 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9064 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9065 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9066 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9067 << getOpenMPClauseName(DVar.CKind)
9068 << getOpenMPDirectiveName(DKind)
9069 << getOpenMPClauseName(PredeterminedCKind);
9070 if (DVar.RefExpr == nullptr)
9071 DVar.CKind = PredeterminedCKind;
9072 reportOriginalDsa(*this, DSAStack, D, DVar,
9073 /*IsLoopIterVar=*/true);
9074 } else if (LoopDeclRefExpr) {
9075 // Make the loop iteration variable private (for worksharing
9076 // constructs), linear (for simd directives with the only one
9077 // associated loop) or lastprivate (for simd directives with several
9078 // collapsed or ordered loops).
9079 if (DVar.CKind == OMPC_unknown)
9080 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind,
9081 PrivateRef);
9085 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9089 /// Called on a for stmt to check and extract its iteration space
9090 /// for further processing (such as collapsing).
9091 static bool checkOpenMPIterationSpace(
9092 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9093 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9094 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9095 Expr *OrderedLoopCountExpr,
9096 Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9097 llvm::MutableArrayRef<LoopIterationSpace> ResultIterSpaces,
9098 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9099 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9100 // OpenMP [2.9.1, Canonical Loop Form]
9101 // for (init-expr; test-expr; incr-expr) structured-block
9102 // for (range-decl: range-expr) structured-block
9103 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9104 S = CanonLoop->getLoopStmt();
9105 auto *For = dyn_cast_or_null<ForStmt>(S);
9106 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9107 // Ranged for is supported only in OpenMP 5.0.
9108 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9109 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
9110 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9111 << getOpenMPDirectiveName(DKind) << TotalNestedLoopCount
9112 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9113 if (TotalNestedLoopCount > 1) {
9114 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9115 SemaRef.Diag(DSA.getConstructLoc(),
9116 diag::note_omp_collapse_ordered_expr)
9117 << 2 << CollapseLoopCountExpr->getSourceRange()
9118 << OrderedLoopCountExpr->getSourceRange();
9119 else if (CollapseLoopCountExpr)
9120 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9121 diag::note_omp_collapse_ordered_expr)
9122 << 0 << CollapseLoopCountExpr->getSourceRange();
9123 else
9124 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9125 diag::note_omp_collapse_ordered_expr)
9126 << 1 << OrderedLoopCountExpr->getSourceRange();
9128 return true;
9130 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9131 "No loop body.");
9132 // Postpone analysis in dependent contexts for ranged for loops.
9133 if (CXXFor && SemaRef.CurContext->isDependentContext())
9134 return false;
9136 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9137 For ? For->getForLoc() : CXXFor->getForLoc());
9139 // Check init.
9140 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9141 if (ISC.checkAndSetInit(Init))
9142 return true;
9144 bool HasErrors = false;
9146 // Check loop variable's type.
9147 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9148 // OpenMP [2.6, Canonical Loop Form]
9149 // Var is one of the following:
9150 // A variable of signed or unsigned integer type.
9151 // For C++, a variable of a random access iterator type.
9152 // For C, a variable of a pointer type.
9153 QualType VarType = LCDecl->getType().getNonReferenceType();
9154 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9155 !VarType->isPointerType() &&
9156 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9157 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9158 << SemaRef.getLangOpts().CPlusPlus;
9159 HasErrors = true;
9162 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9163 // a Construct
9164 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9165 // parallel for construct is (are) private.
9166 // The loop iteration variable in the associated for-loop of a simd
9167 // construct with just one associated for-loop is linear with a
9168 // constant-linear-step that is the increment of the associated for-loop.
9169 // Exclude loop var from the list of variables with implicitly defined data
9170 // sharing attributes.
9171 VarsWithImplicitDSA.erase(LCDecl);
9173 assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
9175 // Check test-expr.
9176 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9178 // Check incr-expr.
9179 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9182 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9183 return HasErrors;
9185 // Build the loop's iteration space representation.
9186 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9187 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9188 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9189 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9190 (isOpenMPWorksharingDirective(DKind) ||
9191 isOpenMPGenericLoopDirective(DKind) ||
9192 isOpenMPTaskLoopDirective(DKind) ||
9193 isOpenMPDistributeDirective(DKind) ||
9194 isOpenMPLoopTransformationDirective(DKind)),
9195 Captures);
9196 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9197 ISC.buildCounterVar(Captures, DSA);
9198 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9199 ISC.buildPrivateCounterVar();
9200 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9201 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9202 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9203 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9204 ISC.getConditionSrcRange();
9205 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9206 ISC.getIncrementSrcRange();
9207 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9208 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9209 ISC.isStrictTestOp();
9210 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9211 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9212 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9213 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9214 ISC.buildFinalCondition(DSA.getCurScope());
9215 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9216 ISC.doesInitDependOnLC();
9217 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9218 ISC.doesCondDependOnLC();
9219 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9220 ISC.getLoopDependentIdx();
9222 HasErrors |=
9223 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9224 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9225 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9226 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9227 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9228 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9229 if (!HasErrors && DSA.isOrderedRegion()) {
9230 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9231 if (CurrentNestedLoopCount <
9232 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9233 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9234 CurrentNestedLoopCount,
9235 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9236 DSA.getOrderedRegionParam().second->setLoopCounter(
9237 CurrentNestedLoopCount,
9238 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9241 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9242 if (CurrentNestedLoopCount >= Pair.first->getNumLoops()) {
9243 // Erroneous case - clause has some problems.
9244 continue;
9246 if (Pair.first->getDependencyKind() == OMPC_DEPEND_sink &&
9247 Pair.second.size() <= CurrentNestedLoopCount) {
9248 // Erroneous case - clause has some problems.
9249 Pair.first->setLoopData(CurrentNestedLoopCount, nullptr);
9250 continue;
9252 Expr *CntValue;
9253 if (Pair.first->getDependencyKind() == OMPC_DEPEND_source)
9254 CntValue = ISC.buildOrderedLoopData(
9255 DSA.getCurScope(),
9256 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9257 Pair.first->getDependencyLoc());
9258 else
9259 CntValue = ISC.buildOrderedLoopData(
9260 DSA.getCurScope(),
9261 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9262 Pair.first->getDependencyLoc(),
9263 Pair.second[CurrentNestedLoopCount].first,
9264 Pair.second[CurrentNestedLoopCount].second);
9265 Pair.first->setLoopData(CurrentNestedLoopCount, CntValue);
9269 return HasErrors;
9272 /// Build 'VarRef = Start.
9273 static ExprResult
9274 buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9275 ExprResult Start, bool IsNonRectangularLB,
9276 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9277 // Build 'VarRef = Start.
9278 ExprResult NewStart = IsNonRectangularLB
9279 ? Start.get()
9280 : tryBuildCapture(SemaRef, Start.get(), Captures);
9281 if (!NewStart.isUsable())
9282 return ExprError();
9283 if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
9284 VarRef.get()->getType())) {
9285 NewStart = SemaRef.PerformImplicitConversion(
9286 NewStart.get(), VarRef.get()->getType(), Sema::AA_Converting,
9287 /*AllowExplicit=*/true);
9288 if (!NewStart.isUsable())
9289 return ExprError();
9292 ExprResult Init =
9293 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9294 return Init;
9297 /// Build 'VarRef = Start + Iter * Step'.
9298 static ExprResult buildCounterUpdate(
9299 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9300 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9301 bool IsNonRectangularLB,
9302 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9303 // Add parentheses (for debugging purposes only).
9304 Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
9305 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9306 !Step.isUsable())
9307 return ExprError();
9309 ExprResult NewStep = Step;
9310 if (Captures)
9311 NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures);
9312 if (NewStep.isInvalid())
9313 return ExprError();
9314 ExprResult Update =
9315 SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get());
9316 if (!Update.isUsable())
9317 return ExprError();
9319 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9320 // 'VarRef = Start (+|-) Iter * Step'.
9321 if (!Start.isUsable())
9322 return ExprError();
9323 ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get());
9324 if (!NewStart.isUsable())
9325 return ExprError();
9326 if (Captures && !IsNonRectangularLB)
9327 NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures);
9328 if (NewStart.isInvalid())
9329 return ExprError();
9331 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9332 ExprResult SavedUpdate = Update;
9333 ExprResult UpdateVal;
9334 if (VarRef.get()->getType()->isOverloadableType() ||
9335 NewStart.get()->getType()->isOverloadableType() ||
9336 Update.get()->getType()->isOverloadableType()) {
9337 Sema::TentativeAnalysisScope Trap(SemaRef);
9339 Update =
9340 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9341 if (Update.isUsable()) {
9342 UpdateVal =
9343 SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9344 VarRef.get(), SavedUpdate.get());
9345 if (UpdateVal.isUsable()) {
9346 Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(),
9347 UpdateVal.get());
9352 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9353 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9354 Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add,
9355 NewStart.get(), SavedUpdate.get());
9356 if (!Update.isUsable())
9357 return ExprError();
9359 if (!SemaRef.Context.hasSameType(Update.get()->getType(),
9360 VarRef.get()->getType())) {
9361 Update = SemaRef.PerformImplicitConversion(
9362 Update.get(), VarRef.get()->getType(), Sema::AA_Converting, true);
9363 if (!Update.isUsable())
9364 return ExprError();
9367 Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
9369 return Update;
9372 /// Convert integer expression \a E to make it have at least \a Bits
9373 /// bits.
9374 static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9375 if (E == nullptr)
9376 return ExprError();
9377 ASTContext &C = SemaRef.Context;
9378 QualType OldType = E->getType();
9379 unsigned HasBits = C.getTypeSize(OldType);
9380 if (HasBits >= Bits)
9381 return ExprResult(E);
9382 // OK to convert to signed, because new type has more bits than old.
9383 QualType NewType = C.getIntTypeForBitwidth(Bits, /* Signed */ true);
9384 return SemaRef.PerformImplicitConversion(E, NewType, Sema::AA_Converting,
9385 true);
9388 /// Check if the given expression \a E is a constant integer that fits
9389 /// into \a Bits bits.
9390 static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9391 if (E == nullptr)
9392 return false;
9393 if (Optional<llvm::APSInt> Result =
9394 E->getIntegerConstantExpr(SemaRef.Context))
9395 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9396 return false;
9399 /// Build preinits statement for the given declarations.
9400 static Stmt *buildPreInits(ASTContext &Context,
9401 MutableArrayRef<Decl *> PreInits) {
9402 if (!PreInits.empty()) {
9403 return new (Context) DeclStmt(
9404 DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()),
9405 SourceLocation(), SourceLocation());
9407 return nullptr;
9410 /// Build preinits statement for the given declarations.
9411 static Stmt *
9412 buildPreInits(ASTContext &Context,
9413 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9414 if (!Captures.empty()) {
9415 SmallVector<Decl *, 16> PreInits;
9416 for (const auto &Pair : Captures)
9417 PreInits.push_back(Pair.second->getDecl());
9418 return buildPreInits(Context, PreInits);
9420 return nullptr;
9423 /// Build postupdate expression for the given list of postupdates expressions.
9424 static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9425 Expr *PostUpdate = nullptr;
9426 if (!PostUpdates.empty()) {
9427 for (Expr *E : PostUpdates) {
9428 Expr *ConvE = S.BuildCStyleCastExpr(
9429 E->getExprLoc(),
9430 S.Context.getTrivialTypeSourceInfo(S.Context.VoidTy),
9431 E->getExprLoc(), E)
9432 .get();
9433 PostUpdate = PostUpdate
9434 ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma,
9435 PostUpdate, ConvE)
9436 .get()
9437 : ConvE;
9440 return PostUpdate;
9443 /// Called on a for stmt to check itself and nested loops (if any).
9444 /// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9445 /// number of collapsed loops otherwise.
9446 static unsigned
9447 checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9448 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
9449 DSAStackTy &DSA,
9450 Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9451 OMPLoopBasedDirective::HelperExprs &Built) {
9452 unsigned NestedLoopCount = 1;
9453 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9454 !isOpenMPLoopTransformationDirective(DKind);
9456 if (CollapseLoopCountExpr) {
9457 // Found 'collapse' clause - calculate collapse number.
9458 Expr::EvalResult Result;
9459 if (!CollapseLoopCountExpr->isValueDependent() &&
9460 CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
9461 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9462 } else {
9463 Built.clear(/*Size=*/1);
9464 return 1;
9467 unsigned OrderedLoopCount = 1;
9468 if (OrderedLoopCountExpr) {
9469 // Found 'ordered' clause - calculate collapse number.
9470 Expr::EvalResult EVResult;
9471 if (!OrderedLoopCountExpr->isValueDependent() &&
9472 OrderedLoopCountExpr->EvaluateAsInt(EVResult,
9473 SemaRef.getASTContext())) {
9474 llvm::APSInt Result = EVResult.Val.getInt();
9475 if (Result.getLimitedValue() < NestedLoopCount) {
9476 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9477 diag::err_omp_wrong_ordered_loop_count)
9478 << OrderedLoopCountExpr->getSourceRange();
9479 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9480 diag::note_collapse_loop_count)
9481 << CollapseLoopCountExpr->getSourceRange();
9483 OrderedLoopCount = Result.getLimitedValue();
9484 } else {
9485 Built.clear(/*Size=*/1);
9486 return 1;
9489 // This is helper routine for loop directives (e.g., 'for', 'simd',
9490 // 'for simd', etc.).
9491 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9492 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9493 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
9494 if (!OMPLoopBasedDirective::doForAllLoops(
9495 AStmt->IgnoreContainers(!isOpenMPLoopTransformationDirective(DKind)),
9496 SupportsNonPerfectlyNested, NumLoops,
9497 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9498 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9499 &IterSpaces, &Captures](unsigned Cnt, Stmt *CurStmt) {
9500 if (checkOpenMPIterationSpace(
9501 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9502 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9503 VarsWithImplicitDSA, IterSpaces, Captures))
9504 return true;
9505 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9506 IterSpaces[Cnt].CounterVar) {
9507 // Handle initialization of captured loop iterator variables.
9508 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9509 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
9510 Captures[DRE] = DRE;
9513 return false;
9515 [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
9516 Stmt *DependentPreInits = Transform->getPreInits();
9517 if (!DependentPreInits)
9518 return;
9519 for (Decl *C : cast<DeclStmt>(DependentPreInits)->getDeclGroup()) {
9520 auto *D = cast<VarDecl>(C);
9521 DeclRefExpr *Ref = buildDeclRefExpr(SemaRef, D, D->getType(),
9522 Transform->getBeginLoc());
9523 Captures[Ref] = Ref;
9526 return 0;
9528 Built.clear(/* size */ NestedLoopCount);
9530 if (SemaRef.CurContext->isDependentContext())
9531 return NestedLoopCount;
9533 // An example of what is generated for the following code:
9535 // #pragma omp simd collapse(2) ordered(2)
9536 // for (i = 0; i < NI; ++i)
9537 // for (k = 0; k < NK; ++k)
9538 // for (j = J0; j < NJ; j+=2) {
9539 // <loop body>
9540 // }
9542 // We generate the code below.
9543 // Note: the loop body may be outlined in CodeGen.
9544 // Note: some counters may be C++ classes, operator- is used to find number of
9545 // iterations and operator+= to calculate counter value.
9546 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
9547 // or i64 is currently supported).
9549 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
9550 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
9551 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
9552 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
9553 // // similar updates for vars in clauses (e.g. 'linear')
9554 // <loop body (using local i and j)>
9555 // }
9556 // i = NI; // assign final values of counters
9557 // j = NJ;
9560 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
9561 // the iteration counts of the collapsed for loops.
9562 // Precondition tests if there is at least one iteration (all conditions are
9563 // true).
9564 auto PreCond = ExprResult(IterSpaces[0].PreCond);
9565 Expr *N0 = IterSpaces[0].NumIterations;
9566 ExprResult LastIteration32 =
9567 widenIterationCount(/*Bits=*/32,
9568 SemaRef
9569 .PerformImplicitConversion(
9570 N0->IgnoreImpCasts(), N0->getType(),
9571 Sema::AA_Converting, /*AllowExplicit=*/true)
9572 .get(),
9573 SemaRef);
9574 ExprResult LastIteration64 = widenIterationCount(
9575 /*Bits=*/64,
9576 SemaRef
9577 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
9578 Sema::AA_Converting,
9579 /*AllowExplicit=*/true)
9580 .get(),
9581 SemaRef);
9583 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
9584 return NestedLoopCount;
9586 ASTContext &C = SemaRef.Context;
9587 bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
9589 Scope *CurScope = DSA.getCurScope();
9590 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
9591 if (PreCond.isUsable()) {
9592 PreCond =
9593 SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
9594 PreCond.get(), IterSpaces[Cnt].PreCond);
9596 Expr *N = IterSpaces[Cnt].NumIterations;
9597 SourceLocation Loc = N->getExprLoc();
9598 AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
9599 if (LastIteration32.isUsable())
9600 LastIteration32 = SemaRef.BuildBinOp(
9601 CurScope, Loc, BO_Mul, LastIteration32.get(),
9602 SemaRef
9603 .PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(),
9604 Sema::AA_Converting,
9605 /*AllowExplicit=*/true)
9606 .get());
9607 if (LastIteration64.isUsable())
9608 LastIteration64 = SemaRef.BuildBinOp(
9609 CurScope, Loc, BO_Mul, LastIteration64.get(),
9610 SemaRef
9611 .PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(),
9612 Sema::AA_Converting,
9613 /*AllowExplicit=*/true)
9614 .get());
9617 // Choose either the 32-bit or 64-bit version.
9618 ExprResult LastIteration = LastIteration64;
9619 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
9620 (LastIteration32.isUsable() &&
9621 C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
9622 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
9623 fitsInto(
9624 /*Bits=*/32,
9625 LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
9626 LastIteration64.get(), SemaRef))))
9627 LastIteration = LastIteration32;
9628 QualType VType = LastIteration.get()->getType();
9629 QualType RealVType = VType;
9630 QualType StrideVType = VType;
9631 if (isOpenMPTaskLoopDirective(DKind)) {
9632 VType =
9633 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
9634 StrideVType =
9635 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
9638 if (!LastIteration.isUsable())
9639 return 0;
9641 // Save the number of iterations.
9642 ExprResult NumIterations = LastIteration;
9644 LastIteration = SemaRef.BuildBinOp(
9645 CurScope, LastIteration.get()->getExprLoc(), BO_Sub,
9646 LastIteration.get(),
9647 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9648 if (!LastIteration.isUsable())
9649 return 0;
9652 // Calculate the last iteration number beforehand instead of doing this on
9653 // each iteration. Do not do this if the number of iterations may be kfold-ed.
9654 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context);
9655 ExprResult CalcLastIteration;
9656 if (!IsConstant) {
9657 ExprResult SaveRef =
9658 tryBuildCapture(SemaRef, LastIteration.get(), Captures);
9659 LastIteration = SaveRef;
9661 // Prepare SaveRef + 1.
9662 NumIterations = SemaRef.BuildBinOp(
9663 CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(),
9664 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9665 if (!NumIterations.isUsable())
9666 return 0;
9669 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
9671 // Build variables passed into runtime, necessary for worksharing directives.
9672 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
9673 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
9674 isOpenMPDistributeDirective(DKind) ||
9675 isOpenMPGenericLoopDirective(DKind) ||
9676 isOpenMPLoopTransformationDirective(DKind)) {
9677 // Lower bound variable, initialized with zero.
9678 VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
9679 LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
9680 SemaRef.AddInitializerToDecl(LBDecl,
9681 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9682 /*DirectInit*/ false);
9684 // Upper bound variable, initialized with last iteration number.
9685 VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
9686 UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
9687 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
9688 /*DirectInit*/ false);
9690 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
9691 // This will be used to implement clause 'lastprivate'.
9692 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
9693 VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
9694 IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
9695 SemaRef.AddInitializerToDecl(ILDecl,
9696 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9697 /*DirectInit*/ false);
9699 // Stride variable returned by runtime (we initialize it to 1 by default).
9700 VarDecl *STDecl =
9701 buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride");
9702 ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc);
9703 SemaRef.AddInitializerToDecl(STDecl,
9704 SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
9705 /*DirectInit*/ false);
9707 // Build expression: UB = min(UB, LastIteration)
9708 // It is necessary for CodeGen of directives with static scheduling.
9709 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
9710 UB.get(), LastIteration.get());
9711 ExprResult CondOp = SemaRef.ActOnConditionalOp(
9712 LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
9713 LastIteration.get(), UB.get());
9714 EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
9715 CondOp.get());
9716 EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue*/ false);
9718 // If we have a combined directive that combines 'distribute', 'for' or
9719 // 'simd' we need to be able to access the bounds of the schedule of the
9720 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
9721 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
9722 if (isOpenMPLoopBoundSharingDirective(DKind)) {
9723 // Lower bound variable, initialized with zero.
9724 VarDecl *CombLBDecl =
9725 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
9726 CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc);
9727 SemaRef.AddInitializerToDecl(
9728 CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9729 /*DirectInit*/ false);
9731 // Upper bound variable, initialized with last iteration number.
9732 VarDecl *CombUBDecl =
9733 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub");
9734 CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc);
9735 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
9736 /*DirectInit*/ false);
9738 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
9739 CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get());
9740 ExprResult CombCondOp =
9741 SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(),
9742 LastIteration.get(), CombUB.get());
9743 CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
9744 CombCondOp.get());
9745 CombEUB =
9746 SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue*/ false);
9748 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
9749 // We expect to have at least 2 more parameters than the 'parallel'
9750 // directive does - the lower and upper bounds of the previous schedule.
9751 assert(CD->getNumParams() >= 4 &&
9752 "Unexpected number of parameters in loop combined directive");
9754 // Set the proper type for the bounds given what we learned from the
9755 // enclosed loops.
9756 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
9757 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
9759 // Previous lower and upper bounds are obtained from the region
9760 // parameters.
9761 PrevLB =
9762 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
9763 PrevUB =
9764 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
9768 // Build the iteration variable and its initialization before loop.
9769 ExprResult IV;
9770 ExprResult Init, CombInit;
9772 VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
9773 IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
9774 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
9775 isOpenMPGenericLoopDirective(DKind) ||
9776 isOpenMPTaskLoopDirective(DKind) ||
9777 isOpenMPDistributeDirective(DKind) ||
9778 isOpenMPLoopTransformationDirective(DKind))
9779 ? LB.get()
9780 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
9781 Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
9782 Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false);
9784 if (isOpenMPLoopBoundSharingDirective(DKind)) {
9785 Expr *CombRHS =
9786 (isOpenMPWorksharingDirective(DKind) ||
9787 isOpenMPGenericLoopDirective(DKind) ||
9788 isOpenMPTaskLoopDirective(DKind) ||
9789 isOpenMPDistributeDirective(DKind))
9790 ? CombLB.get()
9791 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
9792 CombInit =
9793 SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
9794 CombInit =
9795 SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue*/ false);
9799 bool UseStrictCompare =
9800 RealVType->hasUnsignedIntegerRepresentation() &&
9801 llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) {
9802 return LIS.IsStrictCompare;
9804 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
9805 // unsigned IV)) for worksharing loops.
9806 SourceLocation CondLoc = AStmt->getBeginLoc();
9807 Expr *BoundUB = UB.get();
9808 if (UseStrictCompare) {
9809 BoundUB =
9810 SemaRef
9811 .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
9812 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
9813 .get();
9814 BoundUB =
9815 SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue*/ false).get();
9817 ExprResult Cond =
9818 (isOpenMPWorksharingDirective(DKind) ||
9819 isOpenMPGenericLoopDirective(DKind) ||
9820 isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind) ||
9821 isOpenMPLoopTransformationDirective(DKind))
9822 ? SemaRef.BuildBinOp(CurScope, CondLoc,
9823 UseStrictCompare ? BO_LT : BO_LE, IV.get(),
9824 BoundUB)
9825 : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
9826 NumIterations.get());
9827 ExprResult CombDistCond;
9828 if (isOpenMPLoopBoundSharingDirective(DKind)) {
9829 CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
9830 NumIterations.get());
9833 ExprResult CombCond;
9834 if (isOpenMPLoopBoundSharingDirective(DKind)) {
9835 Expr *BoundCombUB = CombUB.get();
9836 if (UseStrictCompare) {
9837 BoundCombUB =
9838 SemaRef
9839 .BuildBinOp(
9840 CurScope, CondLoc, BO_Add, BoundCombUB,
9841 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
9842 .get();
9843 BoundCombUB =
9844 SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue*/ false)
9845 .get();
9847 CombCond =
9848 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
9849 IV.get(), BoundCombUB);
9851 // Loop increment (IV = IV + 1)
9852 SourceLocation IncLoc = AStmt->getBeginLoc();
9853 ExprResult Inc =
9854 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
9855 SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
9856 if (!Inc.isUsable())
9857 return 0;
9858 Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
9859 Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue*/ false);
9860 if (!Inc.isUsable())
9861 return 0;
9863 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
9864 // Used for directives with static scheduling.
9865 // In combined construct, add combined version that use CombLB and CombUB
9866 // base variables for the update
9867 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
9868 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
9869 isOpenMPGenericLoopDirective(DKind) ||
9870 isOpenMPDistributeDirective(DKind) ||
9871 isOpenMPLoopTransformationDirective(DKind)) {
9872 // LB + ST
9873 NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
9874 if (!NextLB.isUsable())
9875 return 0;
9876 // LB = LB + ST
9877 NextLB =
9878 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
9879 NextLB =
9880 SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue*/ false);
9881 if (!NextLB.isUsable())
9882 return 0;
9883 // UB + ST
9884 NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get());
9885 if (!NextUB.isUsable())
9886 return 0;
9887 // UB = UB + ST
9888 NextUB =
9889 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
9890 NextUB =
9891 SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue*/ false);
9892 if (!NextUB.isUsable())
9893 return 0;
9894 if (isOpenMPLoopBoundSharingDirective(DKind)) {
9895 CombNextLB =
9896 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get());
9897 if (!NextLB.isUsable())
9898 return 0;
9899 // LB = LB + ST
9900 CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
9901 CombNextLB.get());
9902 CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
9903 /*DiscardedValue*/ false);
9904 if (!CombNextLB.isUsable())
9905 return 0;
9906 // UB + ST
9907 CombNextUB =
9908 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get());
9909 if (!CombNextUB.isUsable())
9910 return 0;
9911 // UB = UB + ST
9912 CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
9913 CombNextUB.get());
9914 CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
9915 /*DiscardedValue*/ false);
9916 if (!CombNextUB.isUsable())
9917 return 0;
9921 // Create increment expression for distribute loop when combined in a same
9922 // directive with for as IV = IV + ST; ensure upper bound expression based
9923 // on PrevUB instead of NumIterations - used to implement 'for' when found
9924 // in combination with 'distribute', like in 'distribute parallel for'
9925 SourceLocation DistIncLoc = AStmt->getBeginLoc();
9926 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
9927 if (isOpenMPLoopBoundSharingDirective(DKind)) {
9928 DistCond = SemaRef.BuildBinOp(
9929 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB);
9930 assert(DistCond.isUsable() && "distribute cond expr was not built");
9932 DistInc =
9933 SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get());
9934 assert(DistInc.isUsable() && "distribute inc expr was not built");
9935 DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
9936 DistInc.get());
9937 DistInc =
9938 SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue*/ false);
9939 assert(DistInc.isUsable() && "distribute inc expr was not built");
9941 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
9942 // construct
9943 ExprResult NewPrevUB = PrevUB;
9944 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
9945 if (!SemaRef.Context.hasSameType(UB.get()->getType(),
9946 PrevUB.get()->getType())) {
9947 NewPrevUB = SemaRef.BuildCStyleCastExpr(
9948 DistEUBLoc,
9949 SemaRef.Context.getTrivialTypeSourceInfo(UB.get()->getType()),
9950 DistEUBLoc, NewPrevUB.get());
9951 if (!NewPrevUB.isUsable())
9952 return 0;
9954 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT,
9955 UB.get(), NewPrevUB.get());
9956 ExprResult CondOp = SemaRef.ActOnConditionalOp(
9957 DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get());
9958 PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
9959 CondOp.get());
9960 PrevEUB =
9961 SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue*/ false);
9963 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
9964 // parallel for is in combination with a distribute directive with
9965 // schedule(static, 1)
9966 Expr *BoundPrevUB = PrevUB.get();
9967 if (UseStrictCompare) {
9968 BoundPrevUB =
9969 SemaRef
9970 .BuildBinOp(
9971 CurScope, CondLoc, BO_Add, BoundPrevUB,
9972 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
9973 .get();
9974 BoundPrevUB =
9975 SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue*/ false)
9976 .get();
9978 ParForInDistCond =
9979 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
9980 IV.get(), BoundPrevUB);
9983 // Build updates and final values of the loop counters.
9984 bool HasErrors = false;
9985 Built.Counters.resize(NestedLoopCount);
9986 Built.Inits.resize(NestedLoopCount);
9987 Built.Updates.resize(NestedLoopCount);
9988 Built.Finals.resize(NestedLoopCount);
9989 Built.DependentCounters.resize(NestedLoopCount);
9990 Built.DependentInits.resize(NestedLoopCount);
9991 Built.FinalsConditions.resize(NestedLoopCount);
9993 // We implement the following algorithm for obtaining the
9994 // original loop iteration variable values based on the
9995 // value of the collapsed loop iteration variable IV.
9997 // Let n+1 be the number of collapsed loops in the nest.
9998 // Iteration variables (I0, I1, .... In)
9999 // Iteration counts (N0, N1, ... Nn)
10001 // Acc = IV;
10003 // To compute Ik for loop k, 0 <= k <= n, generate:
10004 // Prod = N(k+1) * N(k+2) * ... * Nn;
10005 // Ik = Acc / Prod;
10006 // Acc -= Ik * Prod;
10008 ExprResult Acc = IV;
10009 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10010 LoopIterationSpace &IS = IterSpaces[Cnt];
10011 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10012 ExprResult Iter;
10014 // Compute prod
10015 ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
10016 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10017 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(),
10018 IterSpaces[K].NumIterations);
10020 // Iter = Acc / Prod
10021 // If there is at least one more inner loop to avoid
10022 // multiplication by 1.
10023 if (Cnt + 1 < NestedLoopCount)
10024 Iter =
10025 SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get());
10026 else
10027 Iter = Acc;
10028 if (!Iter.isUsable()) {
10029 HasErrors = true;
10030 break;
10033 // Update Acc:
10034 // Acc -= Iter * Prod
10035 // Check if there is at least one more inner loop to avoid
10036 // multiplication by 1.
10037 if (Cnt + 1 < NestedLoopCount)
10038 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(),
10039 Prod.get());
10040 else
10041 Prod = Iter;
10042 Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get());
10044 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10045 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10046 DeclRefExpr *CounterVar = buildDeclRefExpr(
10047 SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
10048 /*RefersToCapture=*/true);
10049 ExprResult Init =
10050 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
10051 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10052 if (!Init.isUsable()) {
10053 HasErrors = true;
10054 break;
10056 ExprResult Update = buildCounterUpdate(
10057 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10058 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10059 if (!Update.isUsable()) {
10060 HasErrors = true;
10061 break;
10064 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10065 ExprResult Final =
10066 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
10067 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10068 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10069 if (!Final.isUsable()) {
10070 HasErrors = true;
10071 break;
10074 if (!Update.isUsable() || !Final.isUsable()) {
10075 HasErrors = true;
10076 break;
10078 // Save results
10079 Built.Counters[Cnt] = IS.CounterVar;
10080 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10081 Built.Inits[Cnt] = Init.get();
10082 Built.Updates[Cnt] = Update.get();
10083 Built.Finals[Cnt] = Final.get();
10084 Built.DependentCounters[Cnt] = nullptr;
10085 Built.DependentInits[Cnt] = nullptr;
10086 Built.FinalsConditions[Cnt] = nullptr;
10087 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10088 Built.DependentCounters[Cnt] =
10089 Built.Counters[NestedLoopCount - 1 - IS.LoopDependentIdx];
10090 Built.DependentInits[Cnt] =
10091 Built.Inits[NestedLoopCount - 1 - IS.LoopDependentIdx];
10092 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10097 if (HasErrors)
10098 return 0;
10100 // Save results
10101 Built.IterationVarRef = IV.get();
10102 Built.LastIteration = LastIteration.get();
10103 Built.NumIterations = NumIterations.get();
10104 Built.CalcLastIteration = SemaRef
10105 .ActOnFinishFullExpr(CalcLastIteration.get(),
10106 /*DiscardedValue=*/false)
10107 .get();
10108 Built.PreCond = PreCond.get();
10109 Built.PreInits = buildPreInits(C, Captures);
10110 Built.Cond = Cond.get();
10111 Built.Init = Init.get();
10112 Built.Inc = Inc.get();
10113 Built.LB = LB.get();
10114 Built.UB = UB.get();
10115 Built.IL = IL.get();
10116 Built.ST = ST.get();
10117 Built.EUB = EUB.get();
10118 Built.NLB = NextLB.get();
10119 Built.NUB = NextUB.get();
10120 Built.PrevLB = PrevLB.get();
10121 Built.PrevUB = PrevUB.get();
10122 Built.DistInc = DistInc.get();
10123 Built.PrevEUB = PrevEUB.get();
10124 Built.DistCombinedFields.LB = CombLB.get();
10125 Built.DistCombinedFields.UB = CombUB.get();
10126 Built.DistCombinedFields.EUB = CombEUB.get();
10127 Built.DistCombinedFields.Init = CombInit.get();
10128 Built.DistCombinedFields.Cond = CombCond.get();
10129 Built.DistCombinedFields.NLB = CombNextLB.get();
10130 Built.DistCombinedFields.NUB = CombNextUB.get();
10131 Built.DistCombinedFields.DistCond = CombDistCond.get();
10132 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10134 return NestedLoopCount;
10137 static Expr *getCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) {
10138 auto CollapseClauses =
10139 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10140 if (CollapseClauses.begin() != CollapseClauses.end())
10141 return (*CollapseClauses.begin())->getNumForLoops();
10142 return nullptr;
10145 static Expr *getOrderedNumberExpr(ArrayRef<OMPClause *> Clauses) {
10146 auto OrderedClauses =
10147 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10148 if (OrderedClauses.begin() != OrderedClauses.end())
10149 return (*OrderedClauses.begin())->getNumForLoops();
10150 return nullptr;
10153 static bool checkSimdlenSafelenSpecified(Sema &S,
10154 const ArrayRef<OMPClause *> Clauses) {
10155 const OMPSafelenClause *Safelen = nullptr;
10156 const OMPSimdlenClause *Simdlen = nullptr;
10158 for (const OMPClause *Clause : Clauses) {
10159 if (Clause->getClauseKind() == OMPC_safelen)
10160 Safelen = cast<OMPSafelenClause>(Clause);
10161 else if (Clause->getClauseKind() == OMPC_simdlen)
10162 Simdlen = cast<OMPSimdlenClause>(Clause);
10163 if (Safelen && Simdlen)
10164 break;
10167 if (Simdlen && Safelen) {
10168 const Expr *SimdlenLength = Simdlen->getSimdlen();
10169 const Expr *SafelenLength = Safelen->getSafelen();
10170 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10171 SimdlenLength->isInstantiationDependent() ||
10172 SimdlenLength->containsUnexpandedParameterPack())
10173 return false;
10174 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10175 SafelenLength->isInstantiationDependent() ||
10176 SafelenLength->containsUnexpandedParameterPack())
10177 return false;
10178 Expr::EvalResult SimdlenResult, SafelenResult;
10179 SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
10180 SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
10181 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10182 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10183 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10184 // If both simdlen and safelen clauses are specified, the value of the
10185 // simdlen parameter must be less than or equal to the value of the safelen
10186 // parameter.
10187 if (SimdlenRes > SafelenRes) {
10188 S.Diag(SimdlenLength->getExprLoc(),
10189 diag::err_omp_wrong_simdlen_safelen_values)
10190 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10191 return true;
10194 return false;
10197 StmtResult
10198 Sema::ActOnOpenMPSimdDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt,
10199 SourceLocation StartLoc, SourceLocation EndLoc,
10200 VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10201 if (!AStmt)
10202 return StmtError();
10204 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10205 OMPLoopBasedDirective::HelperExprs B;
10206 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10207 // define the nested loops number.
10208 unsigned NestedLoopCount = checkOpenMPLoop(
10209 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10210 AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
10211 if (NestedLoopCount == 0)
10212 return StmtError();
10214 assert((CurContext->isDependentContext() || B.builtAll()) &&
10215 "omp simd loop exprs were not built");
10217 if (!CurContext->isDependentContext()) {
10218 // Finalize the clauses that need pre-built expressions for CodeGen.
10219 for (OMPClause *C : Clauses) {
10220 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10221 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10222 B.NumIterations, *this, CurScope,
10223 DSAStack))
10224 return StmtError();
10228 if (checkSimdlenSafelenSpecified(*this, Clauses))
10229 return StmtError();
10231 setFunctionHasBranchProtectedScope();
10232 return OMPSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
10233 Clauses, AStmt, B);
10236 StmtResult
10237 Sema::ActOnOpenMPForDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt,
10238 SourceLocation StartLoc, SourceLocation EndLoc,
10239 VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10240 if (!AStmt)
10241 return StmtError();
10243 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10244 OMPLoopBasedDirective::HelperExprs B;
10245 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10246 // define the nested loops number.
10247 unsigned NestedLoopCount = checkOpenMPLoop(
10248 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10249 AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
10250 if (NestedLoopCount == 0)
10251 return StmtError();
10253 assert((CurContext->isDependentContext() || B.builtAll()) &&
10254 "omp for loop exprs were not built");
10256 if (!CurContext->isDependentContext()) {
10257 // Finalize the clauses that need pre-built expressions for CodeGen.
10258 for (OMPClause *C : Clauses) {
10259 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10260 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10261 B.NumIterations, *this, CurScope,
10262 DSAStack))
10263 return StmtError();
10267 setFunctionHasBranchProtectedScope();
10268 return OMPForDirective::Create(
10269 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10270 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10273 StmtResult Sema::ActOnOpenMPForSimdDirective(
10274 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10275 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10276 if (!AStmt)
10277 return StmtError();
10279 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10280 OMPLoopBasedDirective::HelperExprs B;
10281 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10282 // define the nested loops number.
10283 unsigned NestedLoopCount =
10284 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
10285 getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
10286 VarsWithImplicitDSA, B);
10287 if (NestedLoopCount == 0)
10288 return StmtError();
10290 assert((CurContext->isDependentContext() || B.builtAll()) &&
10291 "omp for simd loop exprs were not built");
10293 if (!CurContext->isDependentContext()) {
10294 // Finalize the clauses that need pre-built expressions for CodeGen.
10295 for (OMPClause *C : Clauses) {
10296 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10297 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10298 B.NumIterations, *this, CurScope,
10299 DSAStack))
10300 return StmtError();
10304 if (checkSimdlenSafelenSpecified(*this, Clauses))
10305 return StmtError();
10307 setFunctionHasBranchProtectedScope();
10308 return OMPForSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
10309 Clauses, AStmt, B);
10312 StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
10313 Stmt *AStmt,
10314 SourceLocation StartLoc,
10315 SourceLocation EndLoc) {
10316 if (!AStmt)
10317 return StmtError();
10319 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10320 auto BaseStmt = AStmt;
10321 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10322 BaseStmt = CS->getCapturedStmt();
10323 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10324 auto S = C->children();
10325 if (S.begin() == S.end())
10326 return StmtError();
10327 // All associated statements must be '#pragma omp section' except for
10328 // the first one.
10329 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
10330 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10331 if (SectionStmt)
10332 Diag(SectionStmt->getBeginLoc(),
10333 diag::err_omp_sections_substmt_not_section);
10334 return StmtError();
10336 cast<OMPSectionDirective>(SectionStmt)
10337 ->setHasCancel(DSAStack->isCancelRegion());
10339 } else {
10340 Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt);
10341 return StmtError();
10344 setFunctionHasBranchProtectedScope();
10346 return OMPSectionsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
10347 DSAStack->getTaskgroupReductionRef(),
10348 DSAStack->isCancelRegion());
10351 StmtResult Sema::ActOnOpenMPSectionDirective(Stmt *AStmt,
10352 SourceLocation StartLoc,
10353 SourceLocation EndLoc) {
10354 if (!AStmt)
10355 return StmtError();
10357 setFunctionHasBranchProtectedScope();
10358 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10360 return OMPSectionDirective::Create(Context, StartLoc, EndLoc, AStmt,
10361 DSAStack->isCancelRegion());
10364 static Expr *getDirectCallExpr(Expr *E) {
10365 E = E->IgnoreParenCasts()->IgnoreImplicit();
10366 if (auto *CE = dyn_cast<CallExpr>(E))
10367 if (CE->getDirectCallee())
10368 return E;
10369 return nullptr;
10372 StmtResult Sema::ActOnOpenMPDispatchDirective(ArrayRef<OMPClause *> Clauses,
10373 Stmt *AStmt,
10374 SourceLocation StartLoc,
10375 SourceLocation EndLoc) {
10376 if (!AStmt)
10377 return StmtError();
10379 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10381 // 5.1 OpenMP
10382 // expression-stmt : an expression statement with one of the following forms:
10383 // expression = target-call ( [expression-list] );
10384 // target-call ( [expression-list] );
10386 SourceLocation TargetCallLoc;
10388 if (!CurContext->isDependentContext()) {
10389 Expr *TargetCall = nullptr;
10391 auto *E = dyn_cast<Expr>(S);
10392 if (!E) {
10393 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10394 return StmtError();
10397 E = E->IgnoreParenCasts()->IgnoreImplicit();
10399 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
10400 if (BO->getOpcode() == BO_Assign)
10401 TargetCall = getDirectCallExpr(BO->getRHS());
10402 } else {
10403 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10404 if (COCE->getOperator() == OO_Equal)
10405 TargetCall = getDirectCallExpr(COCE->getArg(1));
10406 if (!TargetCall)
10407 TargetCall = getDirectCallExpr(E);
10409 if (!TargetCall) {
10410 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10411 return StmtError();
10413 TargetCallLoc = TargetCall->getExprLoc();
10416 setFunctionHasBranchProtectedScope();
10418 return OMPDispatchDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
10419 TargetCallLoc);
10422 static bool checkGenericLoopLastprivate(Sema &S, ArrayRef<OMPClause *> Clauses,
10423 OpenMPDirectiveKind K,
10424 DSAStackTy *Stack) {
10425 bool ErrorFound = false;
10426 for (OMPClause *C : Clauses) {
10427 if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) {
10428 for (Expr *RefExpr : LPC->varlists()) {
10429 SourceLocation ELoc;
10430 SourceRange ERange;
10431 Expr *SimpleRefExpr = RefExpr;
10432 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
10433 if (ValueDecl *D = Res.first) {
10434 auto &&Info = Stack->isLoopControlVariable(D);
10435 if (!Info.first) {
10436 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10437 << getOpenMPDirectiveName(K);
10438 ErrorFound = true;
10444 return ErrorFound;
10447 StmtResult Sema::ActOnOpenMPGenericLoopDirective(
10448 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10449 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10450 if (!AStmt)
10451 return StmtError();
10453 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10454 // A list item may not appear in a lastprivate clause unless it is the
10455 // loop iteration variable of a loop that is associated with the construct.
10456 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_loop, DSAStack))
10457 return StmtError();
10459 auto *CS = cast<CapturedStmt>(AStmt);
10460 // 1.2.2 OpenMP Language Terminology
10461 // Structured block - An executable statement with a single entry at the
10462 // top and a single exit at the bottom.
10463 // The point of exit cannot be a branch out of the structured block.
10464 // longjmp() and throw() must not violate the entry/exit criteria.
10465 CS->getCapturedDecl()->setNothrow();
10467 OMPLoopDirective::HelperExprs B;
10468 // In presence of clause 'collapse', it will define the nested loops number.
10469 unsigned NestedLoopCount = checkOpenMPLoop(
10470 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10471 AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
10472 if (NestedLoopCount == 0)
10473 return StmtError();
10475 assert((CurContext->isDependentContext() || B.builtAll()) &&
10476 "omp loop exprs were not built");
10478 setFunctionHasBranchProtectedScope();
10479 return OMPGenericLoopDirective::Create(Context, StartLoc, EndLoc,
10480 NestedLoopCount, Clauses, AStmt, B);
10483 StmtResult Sema::ActOnOpenMPTeamsGenericLoopDirective(
10484 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10485 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10486 if (!AStmt)
10487 return StmtError();
10489 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10490 // A list item may not appear in a lastprivate clause unless it is the
10491 // loop iteration variable of a loop that is associated with the construct.
10492 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_teams_loop, DSAStack))
10493 return StmtError();
10495 auto *CS = cast<CapturedStmt>(AStmt);
10496 // 1.2.2 OpenMP Language Terminology
10497 // Structured block - An executable statement with a single entry at the
10498 // top and a single exit at the bottom.
10499 // The point of exit cannot be a branch out of the structured block.
10500 // longjmp() and throw() must not violate the entry/exit criteria.
10501 CS->getCapturedDecl()->setNothrow();
10502 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_teams_loop);
10503 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10504 CS = cast<CapturedStmt>(CS->getCapturedStmt());
10505 // 1.2.2 OpenMP Language Terminology
10506 // Structured block - An executable statement with a single entry at the
10507 // top and a single exit at the bottom.
10508 // The point of exit cannot be a branch out of the structured block.
10509 // longjmp() and throw() must not violate the entry/exit criteria.
10510 CS->getCapturedDecl()->setNothrow();
10513 OMPLoopDirective::HelperExprs B;
10514 // In presence of clause 'collapse', it will define the nested loops number.
10515 unsigned NestedLoopCount =
10516 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
10517 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10518 VarsWithImplicitDSA, B);
10519 if (NestedLoopCount == 0)
10520 return StmtError();
10522 assert((CurContext->isDependentContext() || B.builtAll()) &&
10523 "omp loop exprs were not built");
10525 setFunctionHasBranchProtectedScope();
10526 DSAStack->setParentTeamsRegionLoc(StartLoc);
10528 return OMPTeamsGenericLoopDirective::Create(
10529 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10532 StmtResult Sema::ActOnOpenMPTargetTeamsGenericLoopDirective(
10533 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10534 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10535 if (!AStmt)
10536 return StmtError();
10538 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10539 // A list item may not appear in a lastprivate clause unless it is the
10540 // loop iteration variable of a loop that is associated with the construct.
10541 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_target_teams_loop,
10542 DSAStack))
10543 return StmtError();
10545 auto *CS = cast<CapturedStmt>(AStmt);
10546 // 1.2.2 OpenMP Language Terminology
10547 // Structured block - An executable statement with a single entry at the
10548 // top and a single exit at the bottom.
10549 // The point of exit cannot be a branch out of the structured block.
10550 // longjmp() and throw() must not violate the entry/exit criteria.
10551 CS->getCapturedDecl()->setNothrow();
10552 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_teams_loop);
10553 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10554 CS = cast<CapturedStmt>(CS->getCapturedStmt());
10555 // 1.2.2 OpenMP Language Terminology
10556 // Structured block - An executable statement with a single entry at the
10557 // top and a single exit at the bottom.
10558 // The point of exit cannot be a branch out of the structured block.
10559 // longjmp() and throw() must not violate the entry/exit criteria.
10560 CS->getCapturedDecl()->setNothrow();
10563 OMPLoopDirective::HelperExprs B;
10564 // In presence of clause 'collapse', it will define the nested loops number.
10565 unsigned NestedLoopCount =
10566 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
10567 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10568 VarsWithImplicitDSA, B);
10569 if (NestedLoopCount == 0)
10570 return StmtError();
10572 assert((CurContext->isDependentContext() || B.builtAll()) &&
10573 "omp loop exprs were not built");
10575 setFunctionHasBranchProtectedScope();
10577 return OMPTargetTeamsGenericLoopDirective::Create(
10578 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10581 StmtResult Sema::ActOnOpenMPParallelGenericLoopDirective(
10582 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10583 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10584 if (!AStmt)
10585 return StmtError();
10587 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10588 // A list item may not appear in a lastprivate clause unless it is the
10589 // loop iteration variable of a loop that is associated with the construct.
10590 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_parallel_loop, DSAStack))
10591 return StmtError();
10593 auto *CS = cast<CapturedStmt>(AStmt);
10594 // 1.2.2 OpenMP Language Terminology
10595 // Structured block - An executable statement with a single entry at the
10596 // top and a single exit at the bottom.
10597 // The point of exit cannot be a branch out of the structured block.
10598 // longjmp() and throw() must not violate the entry/exit criteria.
10599 CS->getCapturedDecl()->setNothrow();
10600 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_parallel_loop);
10601 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10602 CS = cast<CapturedStmt>(CS->getCapturedStmt());
10603 // 1.2.2 OpenMP Language Terminology
10604 // Structured block - An executable statement with a single entry at the
10605 // top and a single exit at the bottom.
10606 // The point of exit cannot be a branch out of the structured block.
10607 // longjmp() and throw() must not violate the entry/exit criteria.
10608 CS->getCapturedDecl()->setNothrow();
10611 OMPLoopDirective::HelperExprs B;
10612 // In presence of clause 'collapse', it will define the nested loops number.
10613 unsigned NestedLoopCount =
10614 checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses),
10615 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10616 VarsWithImplicitDSA, B);
10617 if (NestedLoopCount == 0)
10618 return StmtError();
10620 assert((CurContext->isDependentContext() || B.builtAll()) &&
10621 "omp loop exprs were not built");
10623 setFunctionHasBranchProtectedScope();
10625 return OMPParallelGenericLoopDirective::Create(
10626 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10629 StmtResult Sema::ActOnOpenMPTargetParallelGenericLoopDirective(
10630 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10631 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10632 if (!AStmt)
10633 return StmtError();
10635 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10636 // A list item may not appear in a lastprivate clause unless it is the
10637 // loop iteration variable of a loop that is associated with the construct.
10638 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_target_parallel_loop,
10639 DSAStack))
10640 return StmtError();
10642 auto *CS = cast<CapturedStmt>(AStmt);
10643 // 1.2.2 OpenMP Language Terminology
10644 // Structured block - An executable statement with a single entry at the
10645 // top and a single exit at the bottom.
10646 // The point of exit cannot be a branch out of the structured block.
10647 // longjmp() and throw() must not violate the entry/exit criteria.
10648 CS->getCapturedDecl()->setNothrow();
10649 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_loop);
10650 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10651 CS = cast<CapturedStmt>(CS->getCapturedStmt());
10652 // 1.2.2 OpenMP Language Terminology
10653 // Structured block - An executable statement with a single entry at the
10654 // top and a single exit at the bottom.
10655 // The point of exit cannot be a branch out of the structured block.
10656 // longjmp() and throw() must not violate the entry/exit criteria.
10657 CS->getCapturedDecl()->setNothrow();
10660 OMPLoopDirective::HelperExprs B;
10661 // In presence of clause 'collapse', it will define the nested loops number.
10662 unsigned NestedLoopCount =
10663 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses),
10664 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10665 VarsWithImplicitDSA, B);
10666 if (NestedLoopCount == 0)
10667 return StmtError();
10669 assert((CurContext->isDependentContext() || B.builtAll()) &&
10670 "omp loop exprs were not built");
10672 setFunctionHasBranchProtectedScope();
10674 return OMPTargetParallelGenericLoopDirective::Create(
10675 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10678 StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
10679 Stmt *AStmt,
10680 SourceLocation StartLoc,
10681 SourceLocation EndLoc) {
10682 if (!AStmt)
10683 return StmtError();
10685 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10687 setFunctionHasBranchProtectedScope();
10689 // OpenMP [2.7.3, single Construct, Restrictions]
10690 // The copyprivate clause must not be used with the nowait clause.
10691 const OMPClause *Nowait = nullptr;
10692 const OMPClause *Copyprivate = nullptr;
10693 for (const OMPClause *Clause : Clauses) {
10694 if (Clause->getClauseKind() == OMPC_nowait)
10695 Nowait = Clause;
10696 else if (Clause->getClauseKind() == OMPC_copyprivate)
10697 Copyprivate = Clause;
10698 if (Copyprivate && Nowait) {
10699 Diag(Copyprivate->getBeginLoc(),
10700 diag::err_omp_single_copyprivate_with_nowait);
10701 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
10702 return StmtError();
10706 return OMPSingleDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
10709 StmtResult Sema::ActOnOpenMPMasterDirective(Stmt *AStmt,
10710 SourceLocation StartLoc,
10711 SourceLocation EndLoc) {
10712 if (!AStmt)
10713 return StmtError();
10715 setFunctionHasBranchProtectedScope();
10717 return OMPMasterDirective::Create(Context, StartLoc, EndLoc, AStmt);
10720 StmtResult Sema::ActOnOpenMPMaskedDirective(ArrayRef<OMPClause *> Clauses,
10721 Stmt *AStmt,
10722 SourceLocation StartLoc,
10723 SourceLocation EndLoc) {
10724 if (!AStmt)
10725 return StmtError();
10727 setFunctionHasBranchProtectedScope();
10729 return OMPMaskedDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
10732 StmtResult Sema::ActOnOpenMPCriticalDirective(
10733 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
10734 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
10735 if (!AStmt)
10736 return StmtError();
10738 bool ErrorFound = false;
10739 llvm::APSInt Hint;
10740 SourceLocation HintLoc;
10741 bool DependentHint = false;
10742 for (const OMPClause *C : Clauses) {
10743 if (C->getClauseKind() == OMPC_hint) {
10744 if (!DirName.getName()) {
10745 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
10746 ErrorFound = true;
10748 Expr *E = cast<OMPHintClause>(C)->getHint();
10749 if (E->isTypeDependent() || E->isValueDependent() ||
10750 E->isInstantiationDependent()) {
10751 DependentHint = true;
10752 } else {
10753 Hint = E->EvaluateKnownConstInt(Context);
10754 HintLoc = C->getBeginLoc();
10758 if (ErrorFound)
10759 return StmtError();
10760 const auto Pair = DSAStack->getCriticalWithHint(DirName);
10761 if (Pair.first && DirName.getName() && !DependentHint) {
10762 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
10763 Diag(StartLoc, diag::err_omp_critical_with_hint);
10764 if (HintLoc.isValid())
10765 Diag(HintLoc, diag::note_omp_critical_hint_here)
10766 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
10767 else
10768 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
10769 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
10770 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
10771 << 1
10772 << toString(C->getHint()->EvaluateKnownConstInt(Context),
10773 /*Radix=*/10, /*Signed=*/false);
10774 } else {
10775 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
10780 setFunctionHasBranchProtectedScope();
10782 auto *Dir = OMPCriticalDirective::Create(Context, DirName, StartLoc, EndLoc,
10783 Clauses, AStmt);
10784 if (!Pair.first && DirName.getName() && !DependentHint)
10785 DSAStack->addCriticalWithHint(Dir, Hint);
10786 return Dir;
10789 StmtResult Sema::ActOnOpenMPParallelForDirective(
10790 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10791 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10792 if (!AStmt)
10793 return StmtError();
10795 auto *CS = cast<CapturedStmt>(AStmt);
10796 // 1.2.2 OpenMP Language Terminology
10797 // Structured block - An executable statement with a single entry at the
10798 // top and a single exit at the bottom.
10799 // The point of exit cannot be a branch out of the structured block.
10800 // longjmp() and throw() must not violate the entry/exit criteria.
10801 CS->getCapturedDecl()->setNothrow();
10803 OMPLoopBasedDirective::HelperExprs B;
10804 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10805 // define the nested loops number.
10806 unsigned NestedLoopCount =
10807 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
10808 getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
10809 VarsWithImplicitDSA, B);
10810 if (NestedLoopCount == 0)
10811 return StmtError();
10813 assert((CurContext->isDependentContext() || B.builtAll()) &&
10814 "omp parallel for loop exprs were not built");
10816 if (!CurContext->isDependentContext()) {
10817 // Finalize the clauses that need pre-built expressions for CodeGen.
10818 for (OMPClause *C : Clauses) {
10819 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10820 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10821 B.NumIterations, *this, CurScope,
10822 DSAStack))
10823 return StmtError();
10827 setFunctionHasBranchProtectedScope();
10828 return OMPParallelForDirective::Create(
10829 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10830 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10833 StmtResult Sema::ActOnOpenMPParallelForSimdDirective(
10834 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10835 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10836 if (!AStmt)
10837 return StmtError();
10839 auto *CS = cast<CapturedStmt>(AStmt);
10840 // 1.2.2 OpenMP Language Terminology
10841 // Structured block - An executable statement with a single entry at the
10842 // top and a single exit at the bottom.
10843 // The point of exit cannot be a branch out of the structured block.
10844 // longjmp() and throw() must not violate the entry/exit criteria.
10845 CS->getCapturedDecl()->setNothrow();
10847 OMPLoopBasedDirective::HelperExprs B;
10848 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10849 // define the nested loops number.
10850 unsigned NestedLoopCount =
10851 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
10852 getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
10853 VarsWithImplicitDSA, B);
10854 if (NestedLoopCount == 0)
10855 return StmtError();
10857 if (!CurContext->isDependentContext()) {
10858 // Finalize the clauses that need pre-built expressions for CodeGen.
10859 for (OMPClause *C : Clauses) {
10860 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10861 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10862 B.NumIterations, *this, CurScope,
10863 DSAStack))
10864 return StmtError();
10868 if (checkSimdlenSafelenSpecified(*this, Clauses))
10869 return StmtError();
10871 setFunctionHasBranchProtectedScope();
10872 return OMPParallelForSimdDirective::Create(
10873 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10876 StmtResult
10877 Sema::ActOnOpenMPParallelMasterDirective(ArrayRef<OMPClause *> Clauses,
10878 Stmt *AStmt, SourceLocation StartLoc,
10879 SourceLocation EndLoc) {
10880 if (!AStmt)
10881 return StmtError();
10883 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10884 auto *CS = cast<CapturedStmt>(AStmt);
10885 // 1.2.2 OpenMP Language Terminology
10886 // Structured block - An executable statement with a single entry at the
10887 // top and a single exit at the bottom.
10888 // The point of exit cannot be a branch out of the structured block.
10889 // longjmp() and throw() must not violate the entry/exit criteria.
10890 CS->getCapturedDecl()->setNothrow();
10892 setFunctionHasBranchProtectedScope();
10894 return OMPParallelMasterDirective::Create(
10895 Context, StartLoc, EndLoc, Clauses, AStmt,
10896 DSAStack->getTaskgroupReductionRef());
10899 StmtResult
10900 Sema::ActOnOpenMPParallelMaskedDirective(ArrayRef<OMPClause *> Clauses,
10901 Stmt *AStmt, SourceLocation StartLoc,
10902 SourceLocation EndLoc) {
10903 if (!AStmt)
10904 return StmtError();
10906 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10907 auto *CS = cast<CapturedStmt>(AStmt);
10908 // 1.2.2 OpenMP Language Terminology
10909 // Structured block - An executable statement with a single entry at the
10910 // top and a single exit at the bottom.
10911 // The point of exit cannot be a branch out of the structured block.
10912 // longjmp() and throw() must not violate the entry/exit criteria.
10913 CS->getCapturedDecl()->setNothrow();
10915 setFunctionHasBranchProtectedScope();
10917 return OMPParallelMaskedDirective::Create(
10918 Context, StartLoc, EndLoc, Clauses, AStmt,
10919 DSAStack->getTaskgroupReductionRef());
10922 StmtResult
10923 Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
10924 Stmt *AStmt, SourceLocation StartLoc,
10925 SourceLocation EndLoc) {
10926 if (!AStmt)
10927 return StmtError();
10929 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10930 auto BaseStmt = AStmt;
10931 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10932 BaseStmt = CS->getCapturedStmt();
10933 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10934 auto S = C->children();
10935 if (S.begin() == S.end())
10936 return StmtError();
10937 // All associated statements must be '#pragma omp section' except for
10938 // the first one.
10939 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
10940 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10941 if (SectionStmt)
10942 Diag(SectionStmt->getBeginLoc(),
10943 diag::err_omp_parallel_sections_substmt_not_section);
10944 return StmtError();
10946 cast<OMPSectionDirective>(SectionStmt)
10947 ->setHasCancel(DSAStack->isCancelRegion());
10949 } else {
10950 Diag(AStmt->getBeginLoc(),
10951 diag::err_omp_parallel_sections_not_compound_stmt);
10952 return StmtError();
10955 setFunctionHasBranchProtectedScope();
10957 return OMPParallelSectionsDirective::Create(
10958 Context, StartLoc, EndLoc, Clauses, AStmt,
10959 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10962 /// Find and diagnose mutually exclusive clause kinds.
10963 static bool checkMutuallyExclusiveClauses(
10964 Sema &S, ArrayRef<OMPClause *> Clauses,
10965 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
10966 const OMPClause *PrevClause = nullptr;
10967 bool ErrorFound = false;
10968 for (const OMPClause *C : Clauses) {
10969 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
10970 if (!PrevClause) {
10971 PrevClause = C;
10972 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
10973 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
10974 << getOpenMPClauseName(C->getClauseKind())
10975 << getOpenMPClauseName(PrevClause->getClauseKind());
10976 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
10977 << getOpenMPClauseName(PrevClause->getClauseKind());
10978 ErrorFound = true;
10982 return ErrorFound;
10985 StmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
10986 Stmt *AStmt, SourceLocation StartLoc,
10987 SourceLocation EndLoc) {
10988 if (!AStmt)
10989 return StmtError();
10991 // OpenMP 5.0, 2.10.1 task Construct
10992 // If a detach clause appears on the directive, then a mergeable clause cannot
10993 // appear on the same directive.
10994 if (checkMutuallyExclusiveClauses(*this, Clauses,
10995 {OMPC_detach, OMPC_mergeable}))
10996 return StmtError();
10998 auto *CS = cast<CapturedStmt>(AStmt);
10999 // 1.2.2 OpenMP Language Terminology
11000 // Structured block - An executable statement with a single entry at the
11001 // top and a single exit at the bottom.
11002 // The point of exit cannot be a branch out of the structured block.
11003 // longjmp() and throw() must not violate the entry/exit criteria.
11004 CS->getCapturedDecl()->setNothrow();
11006 setFunctionHasBranchProtectedScope();
11008 return OMPTaskDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
11009 DSAStack->isCancelRegion());
11012 StmtResult Sema::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc,
11013 SourceLocation EndLoc) {
11014 return OMPTaskyieldDirective::Create(Context, StartLoc, EndLoc);
11017 StmtResult Sema::ActOnOpenMPBarrierDirective(SourceLocation StartLoc,
11018 SourceLocation EndLoc) {
11019 return OMPBarrierDirective::Create(Context, StartLoc, EndLoc);
11022 StmtResult Sema::ActOnOpenMPTaskwaitDirective(ArrayRef<OMPClause *> Clauses,
11023 SourceLocation StartLoc,
11024 SourceLocation EndLoc) {
11025 return OMPTaskwaitDirective::Create(Context, StartLoc, EndLoc, Clauses);
11028 StmtResult Sema::ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause *> Clauses,
11029 Stmt *AStmt,
11030 SourceLocation StartLoc,
11031 SourceLocation EndLoc) {
11032 if (!AStmt)
11033 return StmtError();
11035 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11037 setFunctionHasBranchProtectedScope();
11039 return OMPTaskgroupDirective::Create(Context, StartLoc, EndLoc, Clauses,
11040 AStmt,
11041 DSAStack->getTaskgroupReductionRef());
11044 StmtResult Sema::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
11045 SourceLocation StartLoc,
11046 SourceLocation EndLoc) {
11047 OMPFlushClause *FC = nullptr;
11048 OMPClause *OrderClause = nullptr;
11049 for (OMPClause *C : Clauses) {
11050 if (C->getClauseKind() == OMPC_flush)
11051 FC = cast<OMPFlushClause>(C);
11052 else
11053 OrderClause = C;
11055 OpenMPClauseKind MemOrderKind = OMPC_unknown;
11056 SourceLocation MemOrderLoc;
11057 for (const OMPClause *C : Clauses) {
11058 if (C->getClauseKind() == OMPC_acq_rel ||
11059 C->getClauseKind() == OMPC_acquire ||
11060 C->getClauseKind() == OMPC_release) {
11061 if (MemOrderKind != OMPC_unknown) {
11062 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11063 << getOpenMPDirectiveName(OMPD_flush) << 1
11064 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11065 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11066 << getOpenMPClauseName(MemOrderKind);
11067 } else {
11068 MemOrderKind = C->getClauseKind();
11069 MemOrderLoc = C->getBeginLoc();
11073 if (FC && OrderClause) {
11074 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11075 << getOpenMPClauseName(OrderClause->getClauseKind());
11076 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
11077 << getOpenMPClauseName(OrderClause->getClauseKind());
11078 return StmtError();
11080 return OMPFlushDirective::Create(Context, StartLoc, EndLoc, Clauses);
11083 StmtResult Sema::ActOnOpenMPDepobjDirective(ArrayRef<OMPClause *> Clauses,
11084 SourceLocation StartLoc,
11085 SourceLocation EndLoc) {
11086 if (Clauses.empty()) {
11087 Diag(StartLoc, diag::err_omp_depobj_expected);
11088 return StmtError();
11089 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11090 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11091 return StmtError();
11093 // Only depobj expression and another single clause is allowed.
11094 if (Clauses.size() > 2) {
11095 Diag(Clauses[2]->getBeginLoc(),
11096 diag::err_omp_depobj_single_clause_expected);
11097 return StmtError();
11098 } else if (Clauses.size() < 1) {
11099 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11100 return StmtError();
11102 return OMPDepobjDirective::Create(Context, StartLoc, EndLoc, Clauses);
11105 StmtResult Sema::ActOnOpenMPScanDirective(ArrayRef<OMPClause *> Clauses,
11106 SourceLocation StartLoc,
11107 SourceLocation EndLoc) {
11108 // Check that exactly one clause is specified.
11109 if (Clauses.size() != 1) {
11110 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11111 diag::err_omp_scan_single_clause_expected);
11112 return StmtError();
11114 // Check that scan directive is used in the scopeof the OpenMP loop body.
11115 if (Scope *S = DSAStack->getCurScope()) {
11116 Scope *ParentS = S->getParent();
11117 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11118 !ParentS->getBreakParent()->isOpenMPLoopScope())
11119 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11120 << getOpenMPDirectiveName(OMPD_scan) << 5);
11122 // Check that only one instance of scan directives is used in the same outer
11123 // region.
11124 if (DSAStack->doesParentHasScanDirective()) {
11125 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
11126 Diag(DSAStack->getParentScanDirectiveLoc(),
11127 diag::note_omp_previous_directive)
11128 << "scan";
11129 return StmtError();
11131 DSAStack->setParentHasScanDirective(StartLoc);
11132 return OMPScanDirective::Create(Context, StartLoc, EndLoc, Clauses);
11135 StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
11136 Stmt *AStmt,
11137 SourceLocation StartLoc,
11138 SourceLocation EndLoc) {
11139 const OMPClause *DependFound = nullptr;
11140 const OMPClause *DependSourceClause = nullptr;
11141 const OMPClause *DependSinkClause = nullptr;
11142 bool ErrorFound = false;
11143 const OMPThreadsClause *TC = nullptr;
11144 const OMPSIMDClause *SC = nullptr;
11145 for (const OMPClause *C : Clauses) {
11146 if (auto *DC = dyn_cast<OMPDependClause>(C)) {
11147 DependFound = C;
11148 if (DC->getDependencyKind() == OMPC_DEPEND_source) {
11149 if (DependSourceClause) {
11150 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
11151 << getOpenMPDirectiveName(OMPD_ordered)
11152 << getOpenMPClauseName(OMPC_depend) << 2;
11153 ErrorFound = true;
11154 } else {
11155 DependSourceClause = C;
11157 if (DependSinkClause) {
11158 Diag(C->getBeginLoc(), diag::err_omp_depend_sink_source_not_allowed)
11159 << 0;
11160 ErrorFound = true;
11162 } else if (DC->getDependencyKind() == OMPC_DEPEND_sink) {
11163 if (DependSourceClause) {
11164 Diag(C->getBeginLoc(), diag::err_omp_depend_sink_source_not_allowed)
11165 << 1;
11166 ErrorFound = true;
11168 DependSinkClause = C;
11170 } else if (C->getClauseKind() == OMPC_threads) {
11171 TC = cast<OMPThreadsClause>(C);
11172 } else if (C->getClauseKind() == OMPC_simd) {
11173 SC = cast<OMPSIMDClause>(C);
11176 if (!ErrorFound && !SC &&
11177 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11178 // OpenMP [2.8.1,simd Construct, Restrictions]
11179 // An ordered construct with the simd clause is the only OpenMP construct
11180 // that can appear in the simd region.
11181 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11182 << (LangOpts.OpenMP >= 50 ? 1 : 0);
11183 ErrorFound = true;
11184 } else if (DependFound && (TC || SC)) {
11185 Diag(DependFound->getBeginLoc(), diag::err_omp_depend_clause_thread_simd)
11186 << getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind());
11187 ErrorFound = true;
11188 } else if (DependFound && !DSAStack->getParentOrderedRegionParam().first) {
11189 Diag(DependFound->getBeginLoc(),
11190 diag::err_omp_ordered_directive_without_param);
11191 ErrorFound = true;
11192 } else if (TC || Clauses.empty()) {
11193 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11194 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11195 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11196 << (TC != nullptr);
11197 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11198 ErrorFound = true;
11201 if ((!AStmt && !DependFound) || ErrorFound)
11202 return StmtError();
11204 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11205 // During execution of an iteration of a worksharing-loop or a loop nest
11206 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11207 // must not execute more than one ordered region corresponding to an ordered
11208 // construct without a depend clause.
11209 if (!DependFound) {
11210 if (DSAStack->doesParentHasOrderedDirective()) {
11211 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
11212 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11213 diag::note_omp_previous_directive)
11214 << "ordered";
11215 return StmtError();
11217 DSAStack->setParentHasOrderedDirective(StartLoc);
11220 if (AStmt) {
11221 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11223 setFunctionHasBranchProtectedScope();
11226 return OMPOrderedDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
11229 namespace {
11230 /// Helper class for checking expression in 'omp atomic [update]'
11231 /// construct.
11232 class OpenMPAtomicUpdateChecker {
11233 /// Error results for atomic update expressions.
11234 enum ExprAnalysisErrorCode {
11235 /// A statement is not an expression statement.
11236 NotAnExpression,
11237 /// Expression is not builtin binary or unary operation.
11238 NotABinaryOrUnaryExpression,
11239 /// Unary operation is not post-/pre- increment/decrement operation.
11240 NotAnUnaryIncDecExpression,
11241 /// An expression is not of scalar type.
11242 NotAScalarType,
11243 /// A binary operation is not an assignment operation.
11244 NotAnAssignmentOp,
11245 /// RHS part of the binary operation is not a binary expression.
11246 NotABinaryExpression,
11247 /// RHS part is not additive/multiplicative/shift/biwise binary
11248 /// expression.
11249 NotABinaryOperator,
11250 /// RHS binary operation does not have reference to the updated LHS
11251 /// part.
11252 NotAnUpdateExpression,
11253 /// No errors is found.
11254 NoError
11256 /// Reference to Sema.
11257 Sema &SemaRef;
11258 /// A location for note diagnostics (when error is found).
11259 SourceLocation NoteLoc;
11260 /// 'x' lvalue part of the source atomic expression.
11261 Expr *X;
11262 /// 'expr' rvalue part of the source atomic expression.
11263 Expr *E;
11264 /// Helper expression of the form
11265 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11266 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11267 Expr *UpdateExpr;
11268 /// Is 'x' a LHS in a RHS part of full update expression. It is
11269 /// important for non-associative operations.
11270 bool IsXLHSInRHSPart;
11271 BinaryOperatorKind Op;
11272 SourceLocation OpLoc;
11273 /// true if the source expression is a postfix unary operation, false
11274 /// if it is a prefix unary operation.
11275 bool IsPostfixUpdate;
11277 public:
11278 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11279 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11280 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11281 /// Check specified statement that it is suitable for 'atomic update'
11282 /// constructs and extract 'x', 'expr' and Operation from the original
11283 /// expression. If DiagId and NoteId == 0, then only check is performed
11284 /// without error notification.
11285 /// \param DiagId Diagnostic which should be emitted if error is found.
11286 /// \param NoteId Diagnostic note for the main error message.
11287 /// \return true if statement is not an update expression, false otherwise.
11288 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11289 /// Return the 'x' lvalue part of the source atomic expression.
11290 Expr *getX() const { return X; }
11291 /// Return the 'expr' rvalue part of the source atomic expression.
11292 Expr *getExpr() const { return E; }
11293 /// Return the update expression used in calculation of the updated
11294 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11295 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11296 Expr *getUpdateExpr() const { return UpdateExpr; }
11297 /// Return true if 'x' is LHS in RHS part of full update expression,
11298 /// false otherwise.
11299 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11301 /// true if the source expression is a postfix unary operation, false
11302 /// if it is a prefix unary operation.
11303 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11305 private:
11306 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11307 unsigned NoteId = 0);
11310 bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11311 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11312 ExprAnalysisErrorCode ErrorFound = NoError;
11313 SourceLocation ErrorLoc, NoteLoc;
11314 SourceRange ErrorRange, NoteRange;
11315 // Allowed constructs are:
11316 // x = x binop expr;
11317 // x = expr binop x;
11318 if (AtomicBinOp->getOpcode() == BO_Assign) {
11319 X = AtomicBinOp->getLHS();
11320 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11321 AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11322 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11323 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11324 AtomicInnerBinOp->isBitwiseOp()) {
11325 Op = AtomicInnerBinOp->getOpcode();
11326 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11327 Expr *LHS = AtomicInnerBinOp->getLHS();
11328 Expr *RHS = AtomicInnerBinOp->getRHS();
11329 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11330 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11331 /*Canonical=*/true);
11332 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11333 /*Canonical=*/true);
11334 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11335 /*Canonical=*/true);
11336 if (XId == LHSId) {
11337 E = RHS;
11338 IsXLHSInRHSPart = true;
11339 } else if (XId == RHSId) {
11340 E = LHS;
11341 IsXLHSInRHSPart = false;
11342 } else {
11343 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11344 ErrorRange = AtomicInnerBinOp->getSourceRange();
11345 NoteLoc = X->getExprLoc();
11346 NoteRange = X->getSourceRange();
11347 ErrorFound = NotAnUpdateExpression;
11349 } else {
11350 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11351 ErrorRange = AtomicInnerBinOp->getSourceRange();
11352 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11353 NoteRange = SourceRange(NoteLoc, NoteLoc);
11354 ErrorFound = NotABinaryOperator;
11356 } else {
11357 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11358 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11359 ErrorFound = NotABinaryExpression;
11361 } else {
11362 ErrorLoc = AtomicBinOp->getExprLoc();
11363 ErrorRange = AtomicBinOp->getSourceRange();
11364 NoteLoc = AtomicBinOp->getOperatorLoc();
11365 NoteRange = SourceRange(NoteLoc, NoteLoc);
11366 ErrorFound = NotAnAssignmentOp;
11368 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11369 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11370 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11371 return true;
11373 if (SemaRef.CurContext->isDependentContext())
11374 E = X = UpdateExpr = nullptr;
11375 return ErrorFound != NoError;
11378 bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11379 unsigned NoteId) {
11380 ExprAnalysisErrorCode ErrorFound = NoError;
11381 SourceLocation ErrorLoc, NoteLoc;
11382 SourceRange ErrorRange, NoteRange;
11383 // Allowed constructs are:
11384 // x++;
11385 // x--;
11386 // ++x;
11387 // --x;
11388 // x binop= expr;
11389 // x = x binop expr;
11390 // x = expr binop x;
11391 if (auto *AtomicBody = dyn_cast<Expr>(S)) {
11392 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11393 if (AtomicBody->getType()->isScalarType() ||
11394 AtomicBody->isInstantiationDependent()) {
11395 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11396 AtomicBody->IgnoreParenImpCasts())) {
11397 // Check for Compound Assignment Operation
11398 Op = BinaryOperator::getOpForCompoundAssignment(
11399 AtomicCompAssignOp->getOpcode());
11400 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11401 E = AtomicCompAssignOp->getRHS();
11402 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11403 IsXLHSInRHSPart = true;
11404 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11405 AtomicBody->IgnoreParenImpCasts())) {
11406 // Check for Binary Operation
11407 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11408 return true;
11409 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11410 AtomicBody->IgnoreParenImpCasts())) {
11411 // Check for Unary Operation
11412 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11413 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11414 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11415 OpLoc = AtomicUnaryOp->getOperatorLoc();
11416 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11417 E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
11418 IsXLHSInRHSPart = true;
11419 } else {
11420 ErrorFound = NotAnUnaryIncDecExpression;
11421 ErrorLoc = AtomicUnaryOp->getExprLoc();
11422 ErrorRange = AtomicUnaryOp->getSourceRange();
11423 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11424 NoteRange = SourceRange(NoteLoc, NoteLoc);
11426 } else if (!AtomicBody->isInstantiationDependent()) {
11427 ErrorFound = NotABinaryOrUnaryExpression;
11428 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11429 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11431 } else {
11432 ErrorFound = NotAScalarType;
11433 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11434 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11436 } else {
11437 ErrorFound = NotAnExpression;
11438 NoteLoc = ErrorLoc = S->getBeginLoc();
11439 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11441 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11442 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11443 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11444 return true;
11446 if (SemaRef.CurContext->isDependentContext())
11447 E = X = UpdateExpr = nullptr;
11448 if (ErrorFound == NoError && E && X) {
11449 // Build an update expression of form 'OpaqueValueExpr(x) binop
11450 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11451 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11452 auto *OVEX = new (SemaRef.getASTContext())
11453 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11454 auto *OVEExpr = new (SemaRef.getASTContext())
11455 OpaqueValueExpr(E->getExprLoc(), E->getType(), VK_PRValue);
11456 ExprResult Update =
11457 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11458 IsXLHSInRHSPart ? OVEExpr : OVEX);
11459 if (Update.isInvalid())
11460 return true;
11461 Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
11462 Sema::AA_Casting);
11463 if (Update.isInvalid())
11464 return true;
11465 UpdateExpr = Update.get();
11467 return ErrorFound != NoError;
11470 /// Get the node id of the fixed point of an expression \a S.
11471 llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11472 llvm::FoldingSetNodeID Id;
11473 S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11474 return Id;
11477 /// Check if two expressions are same.
11478 bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11479 const Expr *RHS) {
11480 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11483 class OpenMPAtomicCompareChecker {
11484 public:
11485 /// All kinds of errors that can occur in `atomic compare`
11486 enum ErrorTy {
11487 /// Empty compound statement.
11488 NoStmt = 0,
11489 /// More than one statement in a compound statement.
11490 MoreThanOneStmt,
11491 /// Not an assignment binary operator.
11492 NotAnAssignment,
11493 /// Not a conditional operator.
11494 NotCondOp,
11495 /// Wrong false expr. According to the spec, 'x' should be at the false
11496 /// expression of a conditional expression.
11497 WrongFalseExpr,
11498 /// The condition of a conditional expression is not a binary operator.
11499 NotABinaryOp,
11500 /// Invalid binary operator (not <, >, or ==).
11501 InvalidBinaryOp,
11502 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11503 InvalidComparison,
11504 /// X is not a lvalue.
11505 XNotLValue,
11506 /// Not a scalar.
11507 NotScalar,
11508 /// Not an integer.
11509 NotInteger,
11510 /// 'else' statement is not expected.
11511 UnexpectedElse,
11512 /// Not an equality operator.
11513 NotEQ,
11514 /// Invalid assignment (not v == x).
11515 InvalidAssignment,
11516 /// Not if statement
11517 NotIfStmt,
11518 /// More than two statements in a compund statement.
11519 MoreThanTwoStmts,
11520 /// Not a compound statement.
11521 NotCompoundStmt,
11522 /// No else statement.
11523 NoElse,
11524 /// Not 'if (r)'.
11525 InvalidCondition,
11526 /// No error.
11527 NoError,
11530 struct ErrorInfoTy {
11531 ErrorTy Error;
11532 SourceLocation ErrorLoc;
11533 SourceRange ErrorRange;
11534 SourceLocation NoteLoc;
11535 SourceRange NoteRange;
11538 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11540 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11541 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11543 Expr *getX() const { return X; }
11544 Expr *getE() const { return E; }
11545 Expr *getD() const { return D; }
11546 Expr *getCond() const { return C; }
11547 bool isXBinopExpr() const { return IsXBinopExpr; }
11549 protected:
11550 /// Reference to ASTContext
11551 ASTContext &ContextRef;
11552 /// 'x' lvalue part of the source atomic expression.
11553 Expr *X = nullptr;
11554 /// 'expr' or 'e' rvalue part of the source atomic expression.
11555 Expr *E = nullptr;
11556 /// 'd' rvalue part of the source atomic expression.
11557 Expr *D = nullptr;
11558 /// 'cond' part of the source atomic expression. It is in one of the following
11559 /// forms:
11560 /// expr ordop x
11561 /// x ordop expr
11562 /// x == e
11563 /// e == x
11564 Expr *C = nullptr;
11565 /// True if the cond expr is in the form of 'x ordop expr'.
11566 bool IsXBinopExpr = true;
11568 /// Check if it is a valid conditional update statement (cond-update-stmt).
11569 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11571 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11572 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11574 /// Check if all captured values have right type.
11575 bool checkType(ErrorInfoTy &ErrorInfo) const;
11577 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
11578 bool ShouldBeLValue, bool ShouldBeInteger = false) {
11579 if (ShouldBeLValue && !E->isLValue()) {
11580 ErrorInfo.Error = ErrorTy::XNotLValue;
11581 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11582 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11583 return false;
11586 if (!E->isInstantiationDependent()) {
11587 QualType QTy = E->getType();
11588 if (!QTy->isScalarType()) {
11589 ErrorInfo.Error = ErrorTy::NotScalar;
11590 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11591 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11592 return false;
11594 if (ShouldBeInteger && !QTy->isIntegerType()) {
11595 ErrorInfo.Error = ErrorTy::NotInteger;
11596 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11597 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11598 return false;
11602 return true;
11606 bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
11607 ErrorInfoTy &ErrorInfo) {
11608 auto *Then = S->getThen();
11609 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11610 if (CS->body_empty()) {
11611 ErrorInfo.Error = ErrorTy::NoStmt;
11612 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11613 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11614 return false;
11616 if (CS->size() > 1) {
11617 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11618 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11619 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11620 return false;
11622 Then = CS->body_front();
11625 auto *BO = dyn_cast<BinaryOperator>(Then);
11626 if (!BO) {
11627 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11628 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11629 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11630 return false;
11632 if (BO->getOpcode() != BO_Assign) {
11633 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11634 ErrorInfo.ErrorLoc = BO->getExprLoc();
11635 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11636 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11637 return false;
11640 X = BO->getLHS();
11642 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11643 if (!Cond) {
11644 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11645 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11646 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11647 return false;
11650 switch (Cond->getOpcode()) {
11651 case BO_EQ: {
11652 C = Cond;
11653 D = BO->getRHS();
11654 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
11655 E = Cond->getRHS();
11656 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11657 E = Cond->getLHS();
11658 } else {
11659 ErrorInfo.Error = ErrorTy::InvalidComparison;
11660 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11661 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11662 return false;
11664 break;
11666 case BO_LT:
11667 case BO_GT: {
11668 E = BO->getRHS();
11669 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
11670 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
11671 C = Cond;
11672 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
11673 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11674 C = Cond;
11675 IsXBinopExpr = false;
11676 } else {
11677 ErrorInfo.Error = ErrorTy::InvalidComparison;
11678 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11679 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11680 return false;
11682 break;
11684 default:
11685 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11686 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11687 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11688 return false;
11691 if (S->getElse()) {
11692 ErrorInfo.Error = ErrorTy::UnexpectedElse;
11693 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
11694 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
11695 return false;
11698 return true;
11701 bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
11702 ErrorInfoTy &ErrorInfo) {
11703 auto *BO = dyn_cast<BinaryOperator>(S);
11704 if (!BO) {
11705 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11706 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
11707 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11708 return false;
11710 if (BO->getOpcode() != BO_Assign) {
11711 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11712 ErrorInfo.ErrorLoc = BO->getExprLoc();
11713 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11714 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11715 return false;
11718 X = BO->getLHS();
11720 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
11721 if (!CO) {
11722 ErrorInfo.Error = ErrorTy::NotCondOp;
11723 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
11724 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
11725 return false;
11728 if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
11729 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
11730 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
11731 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11732 CO->getFalseExpr()->getSourceRange();
11733 return false;
11736 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
11737 if (!Cond) {
11738 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11739 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11740 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11741 CO->getCond()->getSourceRange();
11742 return false;
11745 switch (Cond->getOpcode()) {
11746 case BO_EQ: {
11747 C = Cond;
11748 D = CO->getTrueExpr();
11749 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
11750 E = Cond->getRHS();
11751 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11752 E = Cond->getLHS();
11753 } else {
11754 ErrorInfo.Error = ErrorTy::InvalidComparison;
11755 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11756 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11757 return false;
11759 break;
11761 case BO_LT:
11762 case BO_GT: {
11763 E = CO->getTrueExpr();
11764 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
11765 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
11766 C = Cond;
11767 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
11768 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11769 C = Cond;
11770 IsXBinopExpr = false;
11771 } else {
11772 ErrorInfo.Error = ErrorTy::InvalidComparison;
11773 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11774 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11775 return false;
11777 break;
11779 default:
11780 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11781 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11782 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11783 return false;
11786 return true;
11789 bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
11790 // 'x' and 'e' cannot be nullptr
11791 assert(X && E && "X and E cannot be nullptr");
11793 if (!CheckValue(X, ErrorInfo, true))
11794 return false;
11796 if (!CheckValue(E, ErrorInfo, false))
11797 return false;
11799 if (D && !CheckValue(D, ErrorInfo, false))
11800 return false;
11802 return true;
11805 bool OpenMPAtomicCompareChecker::checkStmt(
11806 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
11807 auto *CS = dyn_cast<CompoundStmt>(S);
11808 if (CS) {
11809 if (CS->body_empty()) {
11810 ErrorInfo.Error = ErrorTy::NoStmt;
11811 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11812 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11813 return false;
11816 if (CS->size() != 1) {
11817 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11818 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11819 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11820 return false;
11822 S = CS->body_front();
11825 auto Res = false;
11827 if (auto *IS = dyn_cast<IfStmt>(S)) {
11828 // Check if the statement is in one of the following forms
11829 // (cond-update-stmt):
11830 // if (expr ordop x) { x = expr; }
11831 // if (x ordop expr) { x = expr; }
11832 // if (x == e) { x = d; }
11833 Res = checkCondUpdateStmt(IS, ErrorInfo);
11834 } else {
11835 // Check if the statement is in one of the following forms (cond-expr-stmt):
11836 // x = expr ordop x ? expr : x;
11837 // x = x ordop expr ? expr : x;
11838 // x = x == e ? d : x;
11839 Res = checkCondExprStmt(S, ErrorInfo);
11842 if (!Res)
11843 return false;
11845 return checkType(ErrorInfo);
11848 class OpenMPAtomicCompareCaptureChecker final
11849 : public OpenMPAtomicCompareChecker {
11850 public:
11851 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
11853 Expr *getV() const { return V; }
11854 Expr *getR() const { return R; }
11855 bool isFailOnly() const { return IsFailOnly; }
11856 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11858 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
11859 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11861 private:
11862 bool checkType(ErrorInfoTy &ErrorInfo);
11864 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
11865 // form of 'conditional-update-capture-atomic' structured block on the v5.2
11866 // spec p.p. 82:
11867 // (1) { v = x; cond-update-stmt }
11868 // (2) { cond-update-stmt v = x; }
11869 // (3) if(x == e) { x = d; } else { v = x; }
11870 // (4) { r = x == e; if(r) { x = d; } }
11871 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
11873 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
11874 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
11876 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
11877 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
11878 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
11880 /// 'v' lvalue part of the source atomic expression.
11881 Expr *V = nullptr;
11882 /// 'r' lvalue part of the source atomic expression.
11883 Expr *R = nullptr;
11884 /// If 'v' is only updated when the comparison fails.
11885 bool IsFailOnly = false;
11886 /// If original value of 'x' must be stored in 'v', not an updated one.
11887 bool IsPostfixUpdate = false;
11890 bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
11891 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
11892 return false;
11894 if (V && !CheckValue(V, ErrorInfo, true))
11895 return false;
11897 if (R && !CheckValue(R, ErrorInfo, true, true))
11898 return false;
11900 return true;
11903 bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
11904 ErrorInfoTy &ErrorInfo) {
11905 IsFailOnly = true;
11907 auto *Then = S->getThen();
11908 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11909 if (CS->body_empty()) {
11910 ErrorInfo.Error = ErrorTy::NoStmt;
11911 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11912 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11913 return false;
11915 if (CS->size() > 1) {
11916 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11917 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11918 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11919 return false;
11921 Then = CS->body_front();
11924 auto *BO = dyn_cast<BinaryOperator>(Then);
11925 if (!BO) {
11926 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11927 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11928 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11929 return false;
11931 if (BO->getOpcode() != BO_Assign) {
11932 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11933 ErrorInfo.ErrorLoc = BO->getExprLoc();
11934 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11935 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11936 return false;
11939 X = BO->getLHS();
11940 D = BO->getRHS();
11942 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11943 if (!Cond) {
11944 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11945 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11946 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11947 return false;
11949 if (Cond->getOpcode() != BO_EQ) {
11950 ErrorInfo.Error = ErrorTy::NotEQ;
11951 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11952 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11953 return false;
11956 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
11957 E = Cond->getRHS();
11958 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11959 E = Cond->getLHS();
11960 } else {
11961 ErrorInfo.Error = ErrorTy::InvalidComparison;
11962 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11963 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11964 return false;
11967 C = Cond;
11969 if (!S->getElse()) {
11970 ErrorInfo.Error = ErrorTy::NoElse;
11971 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
11972 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11973 return false;
11976 auto *Else = S->getElse();
11977 if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
11978 if (CS->body_empty()) {
11979 ErrorInfo.Error = ErrorTy::NoStmt;
11980 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11981 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11982 return false;
11984 if (CS->size() > 1) {
11985 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11986 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11987 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11988 return false;
11990 Else = CS->body_front();
11993 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
11994 if (!ElseBO) {
11995 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11996 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
11997 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
11998 return false;
12000 if (ElseBO->getOpcode() != BO_Assign) {
12001 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12002 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12003 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12004 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12005 return false;
12008 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12009 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12010 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12011 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12012 ElseBO->getRHS()->getSourceRange();
12013 return false;
12016 V = ElseBO->getLHS();
12018 return checkType(ErrorInfo);
12021 bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12022 ErrorInfoTy &ErrorInfo) {
12023 // We don't check here as they should be already done before call this
12024 // function.
12025 auto *CS = cast<CompoundStmt>(S);
12026 assert(CS->size() == 2 && "CompoundStmt size is not expected");
12027 auto *S1 = cast<BinaryOperator>(CS->body_front());
12028 auto *S2 = cast<IfStmt>(CS->body_back());
12029 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12031 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12032 ErrorInfo.Error = ErrorTy::InvalidCondition;
12033 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12034 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12035 return false;
12038 R = S1->getLHS();
12040 auto *Then = S2->getThen();
12041 if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12042 if (ThenCS->body_empty()) {
12043 ErrorInfo.Error = ErrorTy::NoStmt;
12044 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12045 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12046 return false;
12048 if (ThenCS->size() > 1) {
12049 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12050 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12051 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12052 return false;
12054 Then = ThenCS->body_front();
12057 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12058 if (!ThenBO) {
12059 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12060 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12061 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12062 return false;
12064 if (ThenBO->getOpcode() != BO_Assign) {
12065 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12066 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12067 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12068 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12069 return false;
12072 X = ThenBO->getLHS();
12073 D = ThenBO->getRHS();
12075 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12076 if (BO->getOpcode() != BO_EQ) {
12077 ErrorInfo.Error = ErrorTy::NotEQ;
12078 ErrorInfo.ErrorLoc = BO->getExprLoc();
12079 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12080 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12081 return false;
12084 C = BO;
12086 if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) {
12087 E = BO->getRHS();
12088 } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) {
12089 E = BO->getLHS();
12090 } else {
12091 ErrorInfo.Error = ErrorTy::InvalidComparison;
12092 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12093 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12094 return false;
12097 if (S2->getElse()) {
12098 IsFailOnly = true;
12100 auto *Else = S2->getElse();
12101 if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12102 if (ElseCS->body_empty()) {
12103 ErrorInfo.Error = ErrorTy::NoStmt;
12104 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12105 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12106 return false;
12108 if (ElseCS->size() > 1) {
12109 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12110 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12111 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12112 return false;
12114 Else = ElseCS->body_front();
12117 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12118 if (!ElseBO) {
12119 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12120 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12121 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12122 return false;
12124 if (ElseBO->getOpcode() != BO_Assign) {
12125 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12126 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12127 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12128 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12129 return false;
12131 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12132 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12133 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12134 ErrorInfo.NoteLoc = X->getExprLoc();
12135 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12136 ErrorInfo.NoteRange = X->getSourceRange();
12137 return false;
12140 V = ElseBO->getLHS();
12143 return checkType(ErrorInfo);
12146 bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12147 ErrorInfoTy &ErrorInfo) {
12148 // if(x == e) { x = d; } else { v = x; }
12149 if (auto *IS = dyn_cast<IfStmt>(S))
12150 return checkForm3(IS, ErrorInfo);
12152 auto *CS = dyn_cast<CompoundStmt>(S);
12153 if (!CS) {
12154 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12155 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12156 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12157 return false;
12159 if (CS->body_empty()) {
12160 ErrorInfo.Error = ErrorTy::NoStmt;
12161 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12162 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12163 return false;
12166 // { if(x == e) { x = d; } else { v = x; } }
12167 if (CS->size() == 1) {
12168 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12169 if (!IS) {
12170 ErrorInfo.Error = ErrorTy::NotIfStmt;
12171 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12172 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12173 CS->body_front()->getSourceRange();
12174 return false;
12177 return checkForm3(IS, ErrorInfo);
12178 } else if (CS->size() == 2) {
12179 auto *S1 = CS->body_front();
12180 auto *S2 = CS->body_back();
12182 Stmt *UpdateStmt = nullptr;
12183 Stmt *CondUpdateStmt = nullptr;
12185 if (auto *BO = dyn_cast<BinaryOperator>(S1)) {
12186 // { v = x; cond-update-stmt } or form 45.
12187 UpdateStmt = S1;
12188 CondUpdateStmt = S2;
12189 // Check if form 45.
12190 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) &&
12191 isa<IfStmt>(S2))
12192 return checkForm45(CS, ErrorInfo);
12193 // It cannot be set before we the check for form45.
12194 IsPostfixUpdate = true;
12195 } else {
12196 // { cond-update-stmt v = x; }
12197 UpdateStmt = S2;
12198 CondUpdateStmt = S1;
12201 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12202 auto *IS = dyn_cast<IfStmt>(CUS);
12203 if (!IS) {
12204 ErrorInfo.Error = ErrorTy::NotIfStmt;
12205 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12206 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12207 return false;
12210 if (!checkCondUpdateStmt(IS, ErrorInfo))
12211 return false;
12213 return true;
12216 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12217 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12218 auto *BO = dyn_cast<BinaryOperator>(US);
12219 if (!BO) {
12220 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12221 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12222 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12223 return false;
12225 if (BO->getOpcode() != BO_Assign) {
12226 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12227 ErrorInfo.ErrorLoc = BO->getExprLoc();
12228 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12229 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12230 return false;
12232 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12233 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12234 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12235 ErrorInfo.NoteLoc = this->X->getExprLoc();
12236 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12237 ErrorInfo.NoteRange = this->X->getSourceRange();
12238 return false;
12241 this->V = BO->getLHS();
12243 return true;
12246 if (!CheckCondUpdateStmt(CondUpdateStmt))
12247 return false;
12248 if (!CheckUpdateStmt(UpdateStmt))
12249 return false;
12250 } else {
12251 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12252 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12253 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12254 return false;
12257 return checkType(ErrorInfo);
12259 } // namespace
12261 StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
12262 Stmt *AStmt,
12263 SourceLocation StartLoc,
12264 SourceLocation EndLoc) {
12265 // Register location of the first atomic directive.
12266 DSAStack->addAtomicDirectiveLoc(StartLoc);
12267 if (!AStmt)
12268 return StmtError();
12270 // 1.2.2 OpenMP Language Terminology
12271 // Structured block - An executable statement with a single entry at the
12272 // top and a single exit at the bottom.
12273 // The point of exit cannot be a branch out of the structured block.
12274 // longjmp() and throw() must not violate the entry/exit criteria.
12275 OpenMPClauseKind AtomicKind = OMPC_unknown;
12276 SourceLocation AtomicKindLoc;
12277 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12278 SourceLocation MemOrderLoc;
12279 bool MutexClauseEncountered = false;
12280 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12281 for (const OMPClause *C : Clauses) {
12282 switch (C->getClauseKind()) {
12283 case OMPC_read:
12284 case OMPC_write:
12285 case OMPC_update:
12286 MutexClauseEncountered = true;
12287 [[fallthrough]];
12288 case OMPC_capture:
12289 case OMPC_compare: {
12290 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12291 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12292 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12293 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12294 << getOpenMPClauseName(AtomicKind);
12295 } else {
12296 AtomicKind = C->getClauseKind();
12297 AtomicKindLoc = C->getBeginLoc();
12298 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12299 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12300 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12301 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12302 << getOpenMPClauseName(AtomicKind);
12305 break;
12307 case OMPC_seq_cst:
12308 case OMPC_acq_rel:
12309 case OMPC_acquire:
12310 case OMPC_release:
12311 case OMPC_relaxed: {
12312 if (MemOrderKind != OMPC_unknown) {
12313 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12314 << getOpenMPDirectiveName(OMPD_atomic) << 0
12315 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12316 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12317 << getOpenMPClauseName(MemOrderKind);
12318 } else {
12319 MemOrderKind = C->getClauseKind();
12320 MemOrderLoc = C->getBeginLoc();
12322 break;
12324 // The following clauses are allowed, but we don't need to do anything here.
12325 case OMPC_hint:
12326 break;
12327 default:
12328 llvm_unreachable("unknown clause is encountered");
12331 bool IsCompareCapture = false;
12332 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12333 EncounteredAtomicKinds.contains(OMPC_capture)) {
12334 IsCompareCapture = true;
12335 AtomicKind = OMPC_compare;
12337 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12338 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12339 // release.
12340 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12341 // acquire.
12342 // If atomic-clause is update or not present then memory-order-clause must not
12343 // be acq_rel or acquire.
12344 if ((AtomicKind == OMPC_read &&
12345 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12346 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12347 AtomicKind == OMPC_unknown) &&
12348 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12349 SourceLocation Loc = AtomicKindLoc;
12350 if (AtomicKind == OMPC_unknown)
12351 Loc = StartLoc;
12352 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12353 << getOpenMPClauseName(AtomicKind)
12354 << (AtomicKind == OMPC_unknown ? 1 : 0)
12355 << getOpenMPClauseName(MemOrderKind);
12356 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12357 << getOpenMPClauseName(MemOrderKind);
12360 Stmt *Body = AStmt;
12361 if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12362 Body = EWC->getSubExpr();
12364 Expr *X = nullptr;
12365 Expr *V = nullptr;
12366 Expr *E = nullptr;
12367 Expr *UE = nullptr;
12368 Expr *D = nullptr;
12369 Expr *CE = nullptr;
12370 Expr *R = nullptr;
12371 bool IsXLHSInRHSPart = false;
12372 bool IsPostfixUpdate = false;
12373 bool IsFailOnly = false;
12374 // OpenMP [2.12.6, atomic Construct]
12375 // In the next expressions:
12376 // * x and v (as applicable) are both l-value expressions with scalar type.
12377 // * During the execution of an atomic region, multiple syntactic
12378 // occurrences of x must designate the same storage location.
12379 // * Neither of v and expr (as applicable) may access the storage location
12380 // designated by x.
12381 // * Neither of x and expr (as applicable) may access the storage location
12382 // designated by v.
12383 // * expr is an expression with scalar type.
12384 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12385 // * binop, binop=, ++, and -- are not overloaded operators.
12386 // * The expression x binop expr must be numerically equivalent to x binop
12387 // (expr). This requirement is satisfied if the operators in expr have
12388 // precedence greater than binop, or by using parentheses around expr or
12389 // subexpressions of expr.
12390 // * The expression expr binop x must be numerically equivalent to (expr)
12391 // binop x. This requirement is satisfied if the operators in expr have
12392 // precedence equal to or greater than binop, or by using parentheses around
12393 // expr or subexpressions of expr.
12394 // * For forms that allow multiple occurrences of x, the number of times
12395 // that x is evaluated is unspecified.
12396 if (AtomicKind == OMPC_read) {
12397 enum {
12398 NotAnExpression,
12399 NotAnAssignmentOp,
12400 NotAScalarType,
12401 NotAnLValue,
12402 NoError
12403 } ErrorFound = NoError;
12404 SourceLocation ErrorLoc, NoteLoc;
12405 SourceRange ErrorRange, NoteRange;
12406 // If clause is read:
12407 // v = x;
12408 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12409 const auto *AtomicBinOp =
12410 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12411 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12412 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12413 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12414 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12415 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12416 if (!X->isLValue() || !V->isLValue()) {
12417 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12418 ErrorFound = NotAnLValue;
12419 ErrorLoc = AtomicBinOp->getExprLoc();
12420 ErrorRange = AtomicBinOp->getSourceRange();
12421 NoteLoc = NotLValueExpr->getExprLoc();
12422 NoteRange = NotLValueExpr->getSourceRange();
12424 } else if (!X->isInstantiationDependent() ||
12425 !V->isInstantiationDependent()) {
12426 const Expr *NotScalarExpr =
12427 (X->isInstantiationDependent() || X->getType()->isScalarType())
12429 : X;
12430 ErrorFound = NotAScalarType;
12431 ErrorLoc = AtomicBinOp->getExprLoc();
12432 ErrorRange = AtomicBinOp->getSourceRange();
12433 NoteLoc = NotScalarExpr->getExprLoc();
12434 NoteRange = NotScalarExpr->getSourceRange();
12436 } else if (!AtomicBody->isInstantiationDependent()) {
12437 ErrorFound = NotAnAssignmentOp;
12438 ErrorLoc = AtomicBody->getExprLoc();
12439 ErrorRange = AtomicBody->getSourceRange();
12440 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12441 : AtomicBody->getExprLoc();
12442 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12443 : AtomicBody->getSourceRange();
12445 } else {
12446 ErrorFound = NotAnExpression;
12447 NoteLoc = ErrorLoc = Body->getBeginLoc();
12448 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12450 if (ErrorFound != NoError) {
12451 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12452 << ErrorRange;
12453 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12454 << ErrorFound << NoteRange;
12455 return StmtError();
12457 if (CurContext->isDependentContext())
12458 V = X = nullptr;
12459 } else if (AtomicKind == OMPC_write) {
12460 enum {
12461 NotAnExpression,
12462 NotAnAssignmentOp,
12463 NotAScalarType,
12464 NotAnLValue,
12465 NoError
12466 } ErrorFound = NoError;
12467 SourceLocation ErrorLoc, NoteLoc;
12468 SourceRange ErrorRange, NoteRange;
12469 // If clause is write:
12470 // x = expr;
12471 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12472 const auto *AtomicBinOp =
12473 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12474 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12475 X = AtomicBinOp->getLHS();
12476 E = AtomicBinOp->getRHS();
12477 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12478 (E->isInstantiationDependent() || E->getType()->isScalarType())) {
12479 if (!X->isLValue()) {
12480 ErrorFound = NotAnLValue;
12481 ErrorLoc = AtomicBinOp->getExprLoc();
12482 ErrorRange = AtomicBinOp->getSourceRange();
12483 NoteLoc = X->getExprLoc();
12484 NoteRange = X->getSourceRange();
12486 } else if (!X->isInstantiationDependent() ||
12487 !E->isInstantiationDependent()) {
12488 const Expr *NotScalarExpr =
12489 (X->isInstantiationDependent() || X->getType()->isScalarType())
12491 : X;
12492 ErrorFound = NotAScalarType;
12493 ErrorLoc = AtomicBinOp->getExprLoc();
12494 ErrorRange = AtomicBinOp->getSourceRange();
12495 NoteLoc = NotScalarExpr->getExprLoc();
12496 NoteRange = NotScalarExpr->getSourceRange();
12498 } else if (!AtomicBody->isInstantiationDependent()) {
12499 ErrorFound = NotAnAssignmentOp;
12500 ErrorLoc = AtomicBody->getExprLoc();
12501 ErrorRange = AtomicBody->getSourceRange();
12502 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12503 : AtomicBody->getExprLoc();
12504 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12505 : AtomicBody->getSourceRange();
12507 } else {
12508 ErrorFound = NotAnExpression;
12509 NoteLoc = ErrorLoc = Body->getBeginLoc();
12510 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12512 if (ErrorFound != NoError) {
12513 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12514 << ErrorRange;
12515 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12516 << ErrorFound << NoteRange;
12517 return StmtError();
12519 if (CurContext->isDependentContext())
12520 E = X = nullptr;
12521 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12522 // If clause is update:
12523 // x++;
12524 // x--;
12525 // ++x;
12526 // --x;
12527 // x binop= expr;
12528 // x = x binop expr;
12529 // x = expr binop x;
12530 OpenMPAtomicUpdateChecker Checker(*this);
12531 if (Checker.checkStatement(
12532 Body,
12533 (AtomicKind == OMPC_update)
12534 ? diag::err_omp_atomic_update_not_expression_statement
12535 : diag::err_omp_atomic_not_expression_statement,
12536 diag::note_omp_atomic_update))
12537 return StmtError();
12538 if (!CurContext->isDependentContext()) {
12539 E = Checker.getExpr();
12540 X = Checker.getX();
12541 UE = Checker.getUpdateExpr();
12542 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12544 } else if (AtomicKind == OMPC_capture) {
12545 enum {
12546 NotAnAssignmentOp,
12547 NotACompoundStatement,
12548 NotTwoSubstatements,
12549 NotASpecificExpression,
12550 NoError
12551 } ErrorFound = NoError;
12552 SourceLocation ErrorLoc, NoteLoc;
12553 SourceRange ErrorRange, NoteRange;
12554 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12555 // If clause is a capture:
12556 // v = x++;
12557 // v = x--;
12558 // v = ++x;
12559 // v = --x;
12560 // v = x binop= expr;
12561 // v = x = x binop expr;
12562 // v = x = expr binop x;
12563 const auto *AtomicBinOp =
12564 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12565 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12566 V = AtomicBinOp->getLHS();
12567 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12568 OpenMPAtomicUpdateChecker Checker(*this);
12569 if (Checker.checkStatement(
12570 Body, diag::err_omp_atomic_capture_not_expression_statement,
12571 diag::note_omp_atomic_update))
12572 return StmtError();
12573 E = Checker.getExpr();
12574 X = Checker.getX();
12575 UE = Checker.getUpdateExpr();
12576 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12577 IsPostfixUpdate = Checker.isPostfixUpdate();
12578 } else if (!AtomicBody->isInstantiationDependent()) {
12579 ErrorLoc = AtomicBody->getExprLoc();
12580 ErrorRange = AtomicBody->getSourceRange();
12581 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12582 : AtomicBody->getExprLoc();
12583 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12584 : AtomicBody->getSourceRange();
12585 ErrorFound = NotAnAssignmentOp;
12587 if (ErrorFound != NoError) {
12588 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
12589 << ErrorRange;
12590 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12591 return StmtError();
12593 if (CurContext->isDependentContext())
12594 UE = V = E = X = nullptr;
12595 } else {
12596 // If clause is a capture:
12597 // { v = x; x = expr; }
12598 // { v = x; x++; }
12599 // { v = x; x--; }
12600 // { v = x; ++x; }
12601 // { v = x; --x; }
12602 // { v = x; x binop= expr; }
12603 // { v = x; x = x binop expr; }
12604 // { v = x; x = expr binop x; }
12605 // { x++; v = x; }
12606 // { x--; v = x; }
12607 // { ++x; v = x; }
12608 // { --x; v = x; }
12609 // { x binop= expr; v = x; }
12610 // { x = x binop expr; v = x; }
12611 // { x = expr binop x; v = x; }
12612 if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
12613 // Check that this is { expr1; expr2; }
12614 if (CS->size() == 2) {
12615 Stmt *First = CS->body_front();
12616 Stmt *Second = CS->body_back();
12617 if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
12618 First = EWC->getSubExpr()->IgnoreParenImpCasts();
12619 if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
12620 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
12621 // Need to find what subexpression is 'v' and what is 'x'.
12622 OpenMPAtomicUpdateChecker Checker(*this);
12623 bool IsUpdateExprFound = !Checker.checkStatement(Second);
12624 BinaryOperator *BinOp = nullptr;
12625 if (IsUpdateExprFound) {
12626 BinOp = dyn_cast<BinaryOperator>(First);
12627 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12629 if (IsUpdateExprFound && !CurContext->isDependentContext()) {
12630 // { v = x; x++; }
12631 // { v = x; x--; }
12632 // { v = x; ++x; }
12633 // { v = x; --x; }
12634 // { v = x; x binop= expr; }
12635 // { v = x; x = x binop expr; }
12636 // { v = x; x = expr binop x; }
12637 // Check that the first expression has form v = x.
12638 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
12639 llvm::FoldingSetNodeID XId, PossibleXId;
12640 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
12641 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
12642 IsUpdateExprFound = XId == PossibleXId;
12643 if (IsUpdateExprFound) {
12644 V = BinOp->getLHS();
12645 X = Checker.getX();
12646 E = Checker.getExpr();
12647 UE = Checker.getUpdateExpr();
12648 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12649 IsPostfixUpdate = true;
12652 if (!IsUpdateExprFound) {
12653 IsUpdateExprFound = !Checker.checkStatement(First);
12654 BinOp = nullptr;
12655 if (IsUpdateExprFound) {
12656 BinOp = dyn_cast<BinaryOperator>(Second);
12657 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12659 if (IsUpdateExprFound && !CurContext->isDependentContext()) {
12660 // { x++; v = x; }
12661 // { x--; v = x; }
12662 // { ++x; v = x; }
12663 // { --x; v = x; }
12664 // { x binop= expr; v = x; }
12665 // { x = x binop expr; v = x; }
12666 // { x = expr binop x; v = x; }
12667 // Check that the second expression has form v = x.
12668 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
12669 llvm::FoldingSetNodeID XId, PossibleXId;
12670 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
12671 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
12672 IsUpdateExprFound = XId == PossibleXId;
12673 if (IsUpdateExprFound) {
12674 V = BinOp->getLHS();
12675 X = Checker.getX();
12676 E = Checker.getExpr();
12677 UE = Checker.getUpdateExpr();
12678 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12679 IsPostfixUpdate = false;
12683 if (!IsUpdateExprFound) {
12684 // { v = x; x = expr; }
12685 auto *FirstExpr = dyn_cast<Expr>(First);
12686 auto *SecondExpr = dyn_cast<Expr>(Second);
12687 if (!FirstExpr || !SecondExpr ||
12688 !(FirstExpr->isInstantiationDependent() ||
12689 SecondExpr->isInstantiationDependent())) {
12690 auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
12691 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
12692 ErrorFound = NotAnAssignmentOp;
12693 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
12694 : First->getBeginLoc();
12695 NoteRange = ErrorRange = FirstBinOp
12696 ? FirstBinOp->getSourceRange()
12697 : SourceRange(ErrorLoc, ErrorLoc);
12698 } else {
12699 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
12700 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
12701 ErrorFound = NotAnAssignmentOp;
12702 NoteLoc = ErrorLoc = SecondBinOp
12703 ? SecondBinOp->getOperatorLoc()
12704 : Second->getBeginLoc();
12705 NoteRange = ErrorRange =
12706 SecondBinOp ? SecondBinOp->getSourceRange()
12707 : SourceRange(ErrorLoc, ErrorLoc);
12708 } else {
12709 Expr *PossibleXRHSInFirst =
12710 FirstBinOp->getRHS()->IgnoreParenImpCasts();
12711 Expr *PossibleXLHSInSecond =
12712 SecondBinOp->getLHS()->IgnoreParenImpCasts();
12713 llvm::FoldingSetNodeID X1Id, X2Id;
12714 PossibleXRHSInFirst->Profile(X1Id, Context,
12715 /*Canonical=*/true);
12716 PossibleXLHSInSecond->Profile(X2Id, Context,
12717 /*Canonical=*/true);
12718 IsUpdateExprFound = X1Id == X2Id;
12719 if (IsUpdateExprFound) {
12720 V = FirstBinOp->getLHS();
12721 X = SecondBinOp->getLHS();
12722 E = SecondBinOp->getRHS();
12723 UE = nullptr;
12724 IsXLHSInRHSPart = false;
12725 IsPostfixUpdate = true;
12726 } else {
12727 ErrorFound = NotASpecificExpression;
12728 ErrorLoc = FirstBinOp->getExprLoc();
12729 ErrorRange = FirstBinOp->getSourceRange();
12730 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
12731 NoteRange = SecondBinOp->getRHS()->getSourceRange();
12737 } else {
12738 NoteLoc = ErrorLoc = Body->getBeginLoc();
12739 NoteRange = ErrorRange =
12740 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12741 ErrorFound = NotTwoSubstatements;
12743 } else {
12744 NoteLoc = ErrorLoc = Body->getBeginLoc();
12745 NoteRange = ErrorRange =
12746 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12747 ErrorFound = NotACompoundStatement;
12750 if (ErrorFound != NoError) {
12751 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
12752 << ErrorRange;
12753 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12754 return StmtError();
12756 if (CurContext->isDependentContext())
12757 UE = V = E = X = nullptr;
12758 } else if (AtomicKind == OMPC_compare) {
12759 if (IsCompareCapture) {
12760 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
12761 OpenMPAtomicCompareCaptureChecker Checker(*this);
12762 if (!Checker.checkStmt(Body, ErrorInfo)) {
12763 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
12764 << ErrorInfo.ErrorRange;
12765 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12766 << ErrorInfo.Error << ErrorInfo.NoteRange;
12767 return StmtError();
12769 X = Checker.getX();
12770 E = Checker.getE();
12771 D = Checker.getD();
12772 CE = Checker.getCond();
12773 V = Checker.getV();
12774 R = Checker.getR();
12775 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
12776 IsXLHSInRHSPart = Checker.isXBinopExpr();
12777 IsFailOnly = Checker.isFailOnly();
12778 IsPostfixUpdate = Checker.isPostfixUpdate();
12779 } else {
12780 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
12781 OpenMPAtomicCompareChecker Checker(*this);
12782 if (!Checker.checkStmt(Body, ErrorInfo)) {
12783 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
12784 << ErrorInfo.ErrorRange;
12785 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12786 << ErrorInfo.Error << ErrorInfo.NoteRange;
12787 return StmtError();
12789 X = Checker.getX();
12790 E = Checker.getE();
12791 D = Checker.getD();
12792 CE = Checker.getCond();
12793 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
12794 IsXLHSInRHSPart = Checker.isXBinopExpr();
12798 setFunctionHasBranchProtectedScope();
12800 return OMPAtomicDirective::Create(
12801 Context, StartLoc, EndLoc, Clauses, AStmt,
12802 {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
12805 StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
12806 Stmt *AStmt,
12807 SourceLocation StartLoc,
12808 SourceLocation EndLoc) {
12809 if (!AStmt)
12810 return StmtError();
12812 auto *CS = cast<CapturedStmt>(AStmt);
12813 // 1.2.2 OpenMP Language Terminology
12814 // Structured block - An executable statement with a single entry at the
12815 // top and a single exit at the bottom.
12816 // The point of exit cannot be a branch out of the structured block.
12817 // longjmp() and throw() must not violate the entry/exit criteria.
12818 CS->getCapturedDecl()->setNothrow();
12819 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target);
12820 ThisCaptureLevel > 1; --ThisCaptureLevel) {
12821 CS = cast<CapturedStmt>(CS->getCapturedStmt());
12822 // 1.2.2 OpenMP Language Terminology
12823 // Structured block - An executable statement with a single entry at the
12824 // top and a single exit at the bottom.
12825 // The point of exit cannot be a branch out of the structured block.
12826 // longjmp() and throw() must not violate the entry/exit criteria.
12827 CS->getCapturedDecl()->setNothrow();
12830 // OpenMP [2.16, Nesting of Regions]
12831 // If specified, a teams construct must be contained within a target
12832 // construct. That target construct must contain no statements or directives
12833 // outside of the teams construct.
12834 if (DSAStack->hasInnerTeamsRegion()) {
12835 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
12836 bool OMPTeamsFound = true;
12837 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
12838 auto I = CS->body_begin();
12839 while (I != CS->body_end()) {
12840 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
12841 if (!OED || !isOpenMPTeamsDirective(OED->getDirectiveKind()) ||
12842 OMPTeamsFound) {
12844 OMPTeamsFound = false;
12845 break;
12847 ++I;
12849 assert(I != CS->body_end() && "Not found statement");
12850 S = *I;
12851 } else {
12852 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
12853 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
12855 if (!OMPTeamsFound) {
12856 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
12857 Diag(DSAStack->getInnerTeamsRegionLoc(),
12858 diag::note_omp_nested_teams_construct_here);
12859 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
12860 << isa<OMPExecutableDirective>(S);
12861 return StmtError();
12865 setFunctionHasBranchProtectedScope();
12867 return OMPTargetDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
12870 StmtResult
12871 Sema::ActOnOpenMPTargetParallelDirective(ArrayRef<OMPClause *> Clauses,
12872 Stmt *AStmt, SourceLocation StartLoc,
12873 SourceLocation EndLoc) {
12874 if (!AStmt)
12875 return StmtError();
12877 auto *CS = cast<CapturedStmt>(AStmt);
12878 // 1.2.2 OpenMP Language Terminology
12879 // Structured block - An executable statement with a single entry at the
12880 // top and a single exit at the bottom.
12881 // The point of exit cannot be a branch out of the structured block.
12882 // longjmp() and throw() must not violate the entry/exit criteria.
12883 CS->getCapturedDecl()->setNothrow();
12884 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel);
12885 ThisCaptureLevel > 1; --ThisCaptureLevel) {
12886 CS = cast<CapturedStmt>(CS->getCapturedStmt());
12887 // 1.2.2 OpenMP Language Terminology
12888 // Structured block - An executable statement with a single entry at the
12889 // top and a single exit at the bottom.
12890 // The point of exit cannot be a branch out of the structured block.
12891 // longjmp() and throw() must not violate the entry/exit criteria.
12892 CS->getCapturedDecl()->setNothrow();
12895 setFunctionHasBranchProtectedScope();
12897 return OMPTargetParallelDirective::Create(
12898 Context, StartLoc, EndLoc, Clauses, AStmt,
12899 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
12902 StmtResult Sema::ActOnOpenMPTargetParallelForDirective(
12903 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
12904 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
12905 if (!AStmt)
12906 return StmtError();
12908 auto *CS = cast<CapturedStmt>(AStmt);
12909 // 1.2.2 OpenMP Language Terminology
12910 // Structured block - An executable statement with a single entry at the
12911 // top and a single exit at the bottom.
12912 // The point of exit cannot be a branch out of the structured block.
12913 // longjmp() and throw() must not violate the entry/exit criteria.
12914 CS->getCapturedDecl()->setNothrow();
12915 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_for);
12916 ThisCaptureLevel > 1; --ThisCaptureLevel) {
12917 CS = cast<CapturedStmt>(CS->getCapturedStmt());
12918 // 1.2.2 OpenMP Language Terminology
12919 // Structured block - An executable statement with a single entry at the
12920 // top and a single exit at the bottom.
12921 // The point of exit cannot be a branch out of the structured block.
12922 // longjmp() and throw() must not violate the entry/exit criteria.
12923 CS->getCapturedDecl()->setNothrow();
12926 OMPLoopBasedDirective::HelperExprs B;
12927 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
12928 // define the nested loops number.
12929 unsigned NestedLoopCount =
12930 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
12931 getOrderedNumberExpr(Clauses), CS, *this, *DSAStack,
12932 VarsWithImplicitDSA, B);
12933 if (NestedLoopCount == 0)
12934 return StmtError();
12936 assert((CurContext->isDependentContext() || B.builtAll()) &&
12937 "omp target parallel for loop exprs were not built");
12939 if (!CurContext->isDependentContext()) {
12940 // Finalize the clauses that need pre-built expressions for CodeGen.
12941 for (OMPClause *C : Clauses) {
12942 if (auto *LC = dyn_cast<OMPLinearClause>(C))
12943 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
12944 B.NumIterations, *this, CurScope,
12945 DSAStack))
12946 return StmtError();
12950 setFunctionHasBranchProtectedScope();
12951 return OMPTargetParallelForDirective::Create(
12952 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
12953 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
12956 /// Check for existence of a map clause in the list of clauses.
12957 static bool hasClauses(ArrayRef<OMPClause *> Clauses,
12958 const OpenMPClauseKind K) {
12959 return llvm::any_of(
12960 Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
12963 template <typename... Params>
12964 static bool hasClauses(ArrayRef<OMPClause *> Clauses, const OpenMPClauseKind K,
12965 const Params... ClauseTypes) {
12966 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
12969 /// Check if the variables in the mapping clause are externally visible.
12970 static bool isClauseMappable(ArrayRef<OMPClause *> Clauses) {
12971 for (const OMPClause *C : Clauses) {
12972 if (auto *TC = dyn_cast<OMPToClause>(C))
12973 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
12974 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
12975 (VD->isExternallyVisible() &&
12976 VD->getVisibility() != HiddenVisibility);
12978 else if (auto *FC = dyn_cast<OMPFromClause>(C))
12979 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
12980 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
12981 (VD->isExternallyVisible() &&
12982 VD->getVisibility() != HiddenVisibility);
12986 return true;
12989 StmtResult Sema::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
12990 Stmt *AStmt,
12991 SourceLocation StartLoc,
12992 SourceLocation EndLoc) {
12993 if (!AStmt)
12994 return StmtError();
12996 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
12998 // OpenMP [2.12.2, target data Construct, Restrictions]
12999 // At least one map, use_device_addr or use_device_ptr clause must appear on
13000 // the directive.
13001 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13002 (LangOpts.OpenMP < 50 || !hasClauses(Clauses, OMPC_use_device_addr))) {
13003 StringRef Expected;
13004 if (LangOpts.OpenMP < 50)
13005 Expected = "'map' or 'use_device_ptr'";
13006 else
13007 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13008 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13009 << Expected << getOpenMPDirectiveName(OMPD_target_data);
13010 return StmtError();
13013 setFunctionHasBranchProtectedScope();
13015 return OMPTargetDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
13016 AStmt);
13019 StmtResult
13020 Sema::ActOnOpenMPTargetEnterDataDirective(ArrayRef<OMPClause *> Clauses,
13021 SourceLocation StartLoc,
13022 SourceLocation EndLoc, Stmt *AStmt) {
13023 if (!AStmt)
13024 return StmtError();
13026 auto *CS = cast<CapturedStmt>(AStmt);
13027 // 1.2.2 OpenMP Language Terminology
13028 // Structured block - An executable statement with a single entry at the
13029 // top and a single exit at the bottom.
13030 // The point of exit cannot be a branch out of the structured block.
13031 // longjmp() and throw() must not violate the entry/exit criteria.
13032 CS->getCapturedDecl()->setNothrow();
13033 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_enter_data);
13034 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13035 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13036 // 1.2.2 OpenMP Language Terminology
13037 // Structured block - An executable statement with a single entry at the
13038 // top and a single exit at the bottom.
13039 // The point of exit cannot be a branch out of the structured block.
13040 // longjmp() and throw() must not violate the entry/exit criteria.
13041 CS->getCapturedDecl()->setNothrow();
13044 // OpenMP [2.10.2, Restrictions, p. 99]
13045 // At least one map clause must appear on the directive.
13046 if (!hasClauses(Clauses, OMPC_map)) {
13047 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13048 << "'map'" << getOpenMPDirectiveName(OMPD_target_enter_data);
13049 return StmtError();
13052 return OMPTargetEnterDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
13053 AStmt);
13056 StmtResult
13057 Sema::ActOnOpenMPTargetExitDataDirective(ArrayRef<OMPClause *> Clauses,
13058 SourceLocation StartLoc,
13059 SourceLocation EndLoc, Stmt *AStmt) {
13060 if (!AStmt)
13061 return StmtError();
13063 auto *CS = cast<CapturedStmt>(AStmt);
13064 // 1.2.2 OpenMP Language Terminology
13065 // Structured block - An executable statement with a single entry at the
13066 // top and a single exit at the bottom.
13067 // The point of exit cannot be a branch out of the structured block.
13068 // longjmp() and throw() must not violate the entry/exit criteria.
13069 CS->getCapturedDecl()->setNothrow();
13070 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_exit_data);
13071 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13072 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13073 // 1.2.2 OpenMP Language Terminology
13074 // Structured block - An executable statement with a single entry at the
13075 // top and a single exit at the bottom.
13076 // The point of exit cannot be a branch out of the structured block.
13077 // longjmp() and throw() must not violate the entry/exit criteria.
13078 CS->getCapturedDecl()->setNothrow();
13081 // OpenMP [2.10.3, Restrictions, p. 102]
13082 // At least one map clause must appear on the directive.
13083 if (!hasClauses(Clauses, OMPC_map)) {
13084 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13085 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data);
13086 return StmtError();
13089 return OMPTargetExitDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
13090 AStmt);
13093 StmtResult Sema::ActOnOpenMPTargetUpdateDirective(ArrayRef<OMPClause *> Clauses,
13094 SourceLocation StartLoc,
13095 SourceLocation EndLoc,
13096 Stmt *AStmt) {
13097 if (!AStmt)
13098 return StmtError();
13100 auto *CS = cast<CapturedStmt>(AStmt);
13101 // 1.2.2 OpenMP Language Terminology
13102 // Structured block - An executable statement with a single entry at the
13103 // top and a single exit at the bottom.
13104 // The point of exit cannot be a branch out of the structured block.
13105 // longjmp() and throw() must not violate the entry/exit criteria.
13106 CS->getCapturedDecl()->setNothrow();
13107 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_update);
13108 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13109 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13110 // 1.2.2 OpenMP Language Terminology
13111 // Structured block - An executable statement with a single entry at the
13112 // top and a single exit at the bottom.
13113 // The point of exit cannot be a branch out of the structured block.
13114 // longjmp() and throw() must not violate the entry/exit criteria.
13115 CS->getCapturedDecl()->setNothrow();
13118 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
13119 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13120 return StmtError();
13123 if (!isClauseMappable(Clauses)) {
13124 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13125 return StmtError();
13128 return OMPTargetUpdateDirective::Create(Context, StartLoc, EndLoc, Clauses,
13129 AStmt);
13132 StmtResult Sema::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
13133 Stmt *AStmt, SourceLocation StartLoc,
13134 SourceLocation EndLoc) {
13135 if (!AStmt)
13136 return StmtError();
13138 auto *CS = cast<CapturedStmt>(AStmt);
13139 // 1.2.2 OpenMP Language Terminology
13140 // Structured block - An executable statement with a single entry at the
13141 // top and a single exit at the bottom.
13142 // The point of exit cannot be a branch out of the structured block.
13143 // longjmp() and throw() must not violate the entry/exit criteria.
13144 CS->getCapturedDecl()->setNothrow();
13146 setFunctionHasBranchProtectedScope();
13148 DSAStack->setParentTeamsRegionLoc(StartLoc);
13150 return OMPTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
13153 StmtResult
13154 Sema::ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc,
13155 SourceLocation EndLoc,
13156 OpenMPDirectiveKind CancelRegion) {
13157 if (DSAStack->isParentNowaitRegion()) {
13158 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13159 return StmtError();
13161 if (DSAStack->isParentOrderedRegion()) {
13162 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13163 return StmtError();
13165 return OMPCancellationPointDirective::Create(Context, StartLoc, EndLoc,
13166 CancelRegion);
13169 StmtResult Sema::ActOnOpenMPCancelDirective(ArrayRef<OMPClause *> Clauses,
13170 SourceLocation StartLoc,
13171 SourceLocation EndLoc,
13172 OpenMPDirectiveKind CancelRegion) {
13173 if (DSAStack->isParentNowaitRegion()) {
13174 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13175 return StmtError();
13177 if (DSAStack->isParentOrderedRegion()) {
13178 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13179 return StmtError();
13181 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13182 return OMPCancelDirective::Create(Context, StartLoc, EndLoc, Clauses,
13183 CancelRegion);
13186 static bool checkReductionClauseWithNogroup(Sema &S,
13187 ArrayRef<OMPClause *> Clauses) {
13188 const OMPClause *ReductionClause = nullptr;
13189 const OMPClause *NogroupClause = nullptr;
13190 for (const OMPClause *C : Clauses) {
13191 if (C->getClauseKind() == OMPC_reduction) {
13192 ReductionClause = C;
13193 if (NogroupClause)
13194 break;
13195 continue;
13197 if (C->getClauseKind() == OMPC_nogroup) {
13198 NogroupClause = C;
13199 if (ReductionClause)
13200 break;
13201 continue;
13204 if (ReductionClause && NogroupClause) {
13205 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13206 << SourceRange(NogroupClause->getBeginLoc(),
13207 NogroupClause->getEndLoc());
13208 return true;
13210 return false;
13213 StmtResult Sema::ActOnOpenMPTaskLoopDirective(
13214 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13215 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13216 if (!AStmt)
13217 return StmtError();
13219 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13220 OMPLoopBasedDirective::HelperExprs B;
13221 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13222 // define the nested loops number.
13223 unsigned NestedLoopCount =
13224 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13225 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13226 VarsWithImplicitDSA, B);
13227 if (NestedLoopCount == 0)
13228 return StmtError();
13230 assert((CurContext->isDependentContext() || B.builtAll()) &&
13231 "omp for loop exprs were not built");
13233 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13234 // The grainsize clause and num_tasks clause are mutually exclusive and may
13235 // not appear on the same taskloop directive.
13236 if (checkMutuallyExclusiveClauses(*this, Clauses,
13237 {OMPC_grainsize, OMPC_num_tasks}))
13238 return StmtError();
13239 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13240 // If a reduction clause is present on the taskloop directive, the nogroup
13241 // clause must not be specified.
13242 if (checkReductionClauseWithNogroup(*this, Clauses))
13243 return StmtError();
13245 setFunctionHasBranchProtectedScope();
13246 return OMPTaskLoopDirective::Create(Context, StartLoc, EndLoc,
13247 NestedLoopCount, Clauses, AStmt, B,
13248 DSAStack->isCancelRegion());
13251 StmtResult Sema::ActOnOpenMPTaskLoopSimdDirective(
13252 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13253 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13254 if (!AStmt)
13255 return StmtError();
13257 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13258 OMPLoopBasedDirective::HelperExprs B;
13259 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13260 // define the nested loops number.
13261 unsigned NestedLoopCount =
13262 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13263 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13264 VarsWithImplicitDSA, B);
13265 if (NestedLoopCount == 0)
13266 return StmtError();
13268 assert((CurContext->isDependentContext() || B.builtAll()) &&
13269 "omp for loop exprs were not built");
13271 if (!CurContext->isDependentContext()) {
13272 // Finalize the clauses that need pre-built expressions for CodeGen.
13273 for (OMPClause *C : Clauses) {
13274 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13275 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13276 B.NumIterations, *this, CurScope,
13277 DSAStack))
13278 return StmtError();
13282 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13283 // The grainsize clause and num_tasks clause are mutually exclusive and may
13284 // not appear on the same taskloop directive.
13285 if (checkMutuallyExclusiveClauses(*this, Clauses,
13286 {OMPC_grainsize, OMPC_num_tasks}))
13287 return StmtError();
13288 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13289 // If a reduction clause is present on the taskloop directive, the nogroup
13290 // clause must not be specified.
13291 if (checkReductionClauseWithNogroup(*this, Clauses))
13292 return StmtError();
13293 if (checkSimdlenSafelenSpecified(*this, Clauses))
13294 return StmtError();
13296 setFunctionHasBranchProtectedScope();
13297 return OMPTaskLoopSimdDirective::Create(Context, StartLoc, EndLoc,
13298 NestedLoopCount, Clauses, AStmt, B);
13301 StmtResult Sema::ActOnOpenMPMasterTaskLoopDirective(
13302 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13303 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13304 if (!AStmt)
13305 return StmtError();
13307 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13308 OMPLoopBasedDirective::HelperExprs B;
13309 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13310 // define the nested loops number.
13311 unsigned NestedLoopCount =
13312 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13313 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13314 VarsWithImplicitDSA, B);
13315 if (NestedLoopCount == 0)
13316 return StmtError();
13318 assert((CurContext->isDependentContext() || B.builtAll()) &&
13319 "omp for loop exprs were not built");
13321 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13322 // The grainsize clause and num_tasks clause are mutually exclusive and may
13323 // not appear on the same taskloop directive.
13324 if (checkMutuallyExclusiveClauses(*this, Clauses,
13325 {OMPC_grainsize, OMPC_num_tasks}))
13326 return StmtError();
13327 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13328 // If a reduction clause is present on the taskloop directive, the nogroup
13329 // clause must not be specified.
13330 if (checkReductionClauseWithNogroup(*this, Clauses))
13331 return StmtError();
13333 setFunctionHasBranchProtectedScope();
13334 return OMPMasterTaskLoopDirective::Create(Context, StartLoc, EndLoc,
13335 NestedLoopCount, Clauses, AStmt, B,
13336 DSAStack->isCancelRegion());
13339 StmtResult Sema::ActOnOpenMPMaskedTaskLoopDirective(
13340 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13341 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13342 if (!AStmt)
13343 return StmtError();
13345 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13346 OMPLoopBasedDirective::HelperExprs B;
13347 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13348 // define the nested loops number.
13349 unsigned NestedLoopCount =
13350 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13351 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13352 VarsWithImplicitDSA, B);
13353 if (NestedLoopCount == 0)
13354 return StmtError();
13356 assert((CurContext->isDependentContext() || B.builtAll()) &&
13357 "omp for loop exprs were not built");
13359 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13360 // The grainsize clause and num_tasks clause are mutually exclusive and may
13361 // not appear on the same taskloop directive.
13362 if (checkMutuallyExclusiveClauses(*this, Clauses,
13363 {OMPC_grainsize, OMPC_num_tasks}))
13364 return StmtError();
13365 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13366 // If a reduction clause is present on the taskloop directive, the nogroup
13367 // clause must not be specified.
13368 if (checkReductionClauseWithNogroup(*this, Clauses))
13369 return StmtError();
13371 setFunctionHasBranchProtectedScope();
13372 return OMPMaskedTaskLoopDirective::Create(Context, StartLoc, EndLoc,
13373 NestedLoopCount, Clauses, AStmt, B,
13374 DSAStack->isCancelRegion());
13377 StmtResult Sema::ActOnOpenMPMasterTaskLoopSimdDirective(
13378 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13379 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13380 if (!AStmt)
13381 return StmtError();
13383 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13384 OMPLoopBasedDirective::HelperExprs B;
13385 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13386 // define the nested loops number.
13387 unsigned NestedLoopCount =
13388 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13389 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13390 VarsWithImplicitDSA, B);
13391 if (NestedLoopCount == 0)
13392 return StmtError();
13394 assert((CurContext->isDependentContext() || B.builtAll()) &&
13395 "omp for loop exprs were not built");
13397 if (!CurContext->isDependentContext()) {
13398 // Finalize the clauses that need pre-built expressions for CodeGen.
13399 for (OMPClause *C : Clauses) {
13400 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13401 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13402 B.NumIterations, *this, CurScope,
13403 DSAStack))
13404 return StmtError();
13408 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13409 // The grainsize clause and num_tasks clause are mutually exclusive and may
13410 // not appear on the same taskloop directive.
13411 if (checkMutuallyExclusiveClauses(*this, Clauses,
13412 {OMPC_grainsize, OMPC_num_tasks}))
13413 return StmtError();
13414 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13415 // If a reduction clause is present on the taskloop directive, the nogroup
13416 // clause must not be specified.
13417 if (checkReductionClauseWithNogroup(*this, Clauses))
13418 return StmtError();
13419 if (checkSimdlenSafelenSpecified(*this, Clauses))
13420 return StmtError();
13422 setFunctionHasBranchProtectedScope();
13423 return OMPMasterTaskLoopSimdDirective::Create(
13424 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13427 StmtResult Sema::ActOnOpenMPMaskedTaskLoopSimdDirective(
13428 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13429 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13430 if (!AStmt)
13431 return StmtError();
13433 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13434 OMPLoopBasedDirective::HelperExprs B;
13435 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13436 // define the nested loops number.
13437 unsigned NestedLoopCount =
13438 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13439 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13440 VarsWithImplicitDSA, B);
13441 if (NestedLoopCount == 0)
13442 return StmtError();
13444 assert((CurContext->isDependentContext() || B.builtAll()) &&
13445 "omp for loop exprs were not built");
13447 if (!CurContext->isDependentContext()) {
13448 // Finalize the clauses that need pre-built expressions for CodeGen.
13449 for (OMPClause *C : Clauses) {
13450 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13451 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13452 B.NumIterations, *this, CurScope,
13453 DSAStack))
13454 return StmtError();
13458 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13459 // The grainsize clause and num_tasks clause are mutually exclusive and may
13460 // not appear on the same taskloop directive.
13461 if (checkMutuallyExclusiveClauses(*this, Clauses,
13462 {OMPC_grainsize, OMPC_num_tasks}))
13463 return StmtError();
13464 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13465 // If a reduction clause is present on the taskloop directive, the nogroup
13466 // clause must not be specified.
13467 if (checkReductionClauseWithNogroup(*this, Clauses))
13468 return StmtError();
13469 if (checkSimdlenSafelenSpecified(*this, Clauses))
13470 return StmtError();
13472 setFunctionHasBranchProtectedScope();
13473 return OMPMaskedTaskLoopSimdDirective::Create(
13474 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13477 StmtResult Sema::ActOnOpenMPParallelMasterTaskLoopDirective(
13478 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13479 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13480 if (!AStmt)
13481 return StmtError();
13483 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13484 auto *CS = cast<CapturedStmt>(AStmt);
13485 // 1.2.2 OpenMP Language Terminology
13486 // Structured block - An executable statement with a single entry at the
13487 // top and a single exit at the bottom.
13488 // The point of exit cannot be a branch out of the structured block.
13489 // longjmp() and throw() must not violate the entry/exit criteria.
13490 CS->getCapturedDecl()->setNothrow();
13491 for (int ThisCaptureLevel =
13492 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop);
13493 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13494 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13495 // 1.2.2 OpenMP Language Terminology
13496 // Structured block - An executable statement with a single entry at the
13497 // top and a single exit at the bottom.
13498 // The point of exit cannot be a branch out of the structured block.
13499 // longjmp() and throw() must not violate the entry/exit criteria.
13500 CS->getCapturedDecl()->setNothrow();
13503 OMPLoopBasedDirective::HelperExprs B;
13504 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13505 // define the nested loops number.
13506 unsigned NestedLoopCount = checkOpenMPLoop(
13507 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
13508 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
13509 VarsWithImplicitDSA, B);
13510 if (NestedLoopCount == 0)
13511 return StmtError();
13513 assert((CurContext->isDependentContext() || B.builtAll()) &&
13514 "omp for loop exprs were not built");
13516 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13517 // The grainsize clause and num_tasks clause are mutually exclusive and may
13518 // not appear on the same taskloop directive.
13519 if (checkMutuallyExclusiveClauses(*this, Clauses,
13520 {OMPC_grainsize, OMPC_num_tasks}))
13521 return StmtError();
13522 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13523 // If a reduction clause is present on the taskloop directive, the nogroup
13524 // clause must not be specified.
13525 if (checkReductionClauseWithNogroup(*this, Clauses))
13526 return StmtError();
13528 setFunctionHasBranchProtectedScope();
13529 return OMPParallelMasterTaskLoopDirective::Create(
13530 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13531 DSAStack->isCancelRegion());
13534 StmtResult Sema::ActOnOpenMPParallelMaskedTaskLoopDirective(
13535 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13536 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13537 if (!AStmt)
13538 return StmtError();
13540 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13541 auto *CS = cast<CapturedStmt>(AStmt);
13542 // 1.2.2 OpenMP Language Terminology
13543 // Structured block - An executable statement with a single entry at the
13544 // top and a single exit at the bottom.
13545 // The point of exit cannot be a branch out of the structured block.
13546 // longjmp() and throw() must not violate the entry/exit criteria.
13547 CS->getCapturedDecl()->setNothrow();
13548 for (int ThisCaptureLevel =
13549 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop);
13550 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13551 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13552 // 1.2.2 OpenMP Language Terminology
13553 // Structured block - An executable statement with a single entry at the
13554 // top and a single exit at the bottom.
13555 // The point of exit cannot be a branch out of the structured block.
13556 // longjmp() and throw() must not violate the entry/exit criteria.
13557 CS->getCapturedDecl()->setNothrow();
13560 OMPLoopBasedDirective::HelperExprs B;
13561 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13562 // define the nested loops number.
13563 unsigned NestedLoopCount = checkOpenMPLoop(
13564 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
13565 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
13566 VarsWithImplicitDSA, B);
13567 if (NestedLoopCount == 0)
13568 return StmtError();
13570 assert((CurContext->isDependentContext() || B.builtAll()) &&
13571 "omp for loop exprs were not built");
13573 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13574 // The grainsize clause and num_tasks clause are mutually exclusive and may
13575 // not appear on the same taskloop directive.
13576 if (checkMutuallyExclusiveClauses(*this, Clauses,
13577 {OMPC_grainsize, OMPC_num_tasks}))
13578 return StmtError();
13579 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13580 // If a reduction clause is present on the taskloop directive, the nogroup
13581 // clause must not be specified.
13582 if (checkReductionClauseWithNogroup(*this, Clauses))
13583 return StmtError();
13585 setFunctionHasBranchProtectedScope();
13586 return OMPParallelMaskedTaskLoopDirective::Create(
13587 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13588 DSAStack->isCancelRegion());
13591 StmtResult Sema::ActOnOpenMPParallelMasterTaskLoopSimdDirective(
13592 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13593 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13594 if (!AStmt)
13595 return StmtError();
13597 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13598 auto *CS = cast<CapturedStmt>(AStmt);
13599 // 1.2.2 OpenMP Language Terminology
13600 // Structured block - An executable statement with a single entry at the
13601 // top and a single exit at the bottom.
13602 // The point of exit cannot be a branch out of the structured block.
13603 // longjmp() and throw() must not violate the entry/exit criteria.
13604 CS->getCapturedDecl()->setNothrow();
13605 for (int ThisCaptureLevel =
13606 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop_simd);
13607 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13608 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13609 // 1.2.2 OpenMP Language Terminology
13610 // Structured block - An executable statement with a single entry at the
13611 // top and a single exit at the bottom.
13612 // The point of exit cannot be a branch out of the structured block.
13613 // longjmp() and throw() must not violate the entry/exit criteria.
13614 CS->getCapturedDecl()->setNothrow();
13617 OMPLoopBasedDirective::HelperExprs B;
13618 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13619 // define the nested loops number.
13620 unsigned NestedLoopCount = checkOpenMPLoop(
13621 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13622 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
13623 VarsWithImplicitDSA, B);
13624 if (NestedLoopCount == 0)
13625 return StmtError();
13627 assert((CurContext->isDependentContext() || B.builtAll()) &&
13628 "omp for loop exprs were not built");
13630 if (!CurContext->isDependentContext()) {
13631 // Finalize the clauses that need pre-built expressions for CodeGen.
13632 for (OMPClause *C : Clauses) {
13633 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13634 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13635 B.NumIterations, *this, CurScope,
13636 DSAStack))
13637 return StmtError();
13641 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13642 // The grainsize clause and num_tasks clause are mutually exclusive and may
13643 // not appear on the same taskloop directive.
13644 if (checkMutuallyExclusiveClauses(*this, Clauses,
13645 {OMPC_grainsize, OMPC_num_tasks}))
13646 return StmtError();
13647 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13648 // If a reduction clause is present on the taskloop directive, the nogroup
13649 // clause must not be specified.
13650 if (checkReductionClauseWithNogroup(*this, Clauses))
13651 return StmtError();
13652 if (checkSimdlenSafelenSpecified(*this, Clauses))
13653 return StmtError();
13655 setFunctionHasBranchProtectedScope();
13656 return OMPParallelMasterTaskLoopSimdDirective::Create(
13657 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13660 StmtResult Sema::ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
13661 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13662 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13663 if (!AStmt)
13664 return StmtError();
13666 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13667 auto *CS = cast<CapturedStmt>(AStmt);
13668 // 1.2.2 OpenMP Language Terminology
13669 // Structured block - An executable statement with a single entry at the
13670 // top and a single exit at the bottom.
13671 // The point of exit cannot be a branch out of the structured block.
13672 // longjmp() and throw() must not violate the entry/exit criteria.
13673 CS->getCapturedDecl()->setNothrow();
13674 for (int ThisCaptureLevel =
13675 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop_simd);
13676 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13677 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13678 // 1.2.2 OpenMP Language Terminology
13679 // Structured block - An executable statement with a single entry at the
13680 // top and a single exit at the bottom.
13681 // The point of exit cannot be a branch out of the structured block.
13682 // longjmp() and throw() must not violate the entry/exit criteria.
13683 CS->getCapturedDecl()->setNothrow();
13686 OMPLoopBasedDirective::HelperExprs B;
13687 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13688 // define the nested loops number.
13689 unsigned NestedLoopCount = checkOpenMPLoop(
13690 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13691 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
13692 VarsWithImplicitDSA, B);
13693 if (NestedLoopCount == 0)
13694 return StmtError();
13696 assert((CurContext->isDependentContext() || B.builtAll()) &&
13697 "omp for loop exprs were not built");
13699 if (!CurContext->isDependentContext()) {
13700 // Finalize the clauses that need pre-built expressions for CodeGen.
13701 for (OMPClause *C : Clauses) {
13702 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13703 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13704 B.NumIterations, *this, CurScope,
13705 DSAStack))
13706 return StmtError();
13710 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13711 // The grainsize clause and num_tasks clause are mutually exclusive and may
13712 // not appear on the same taskloop directive.
13713 if (checkMutuallyExclusiveClauses(*this, Clauses,
13714 {OMPC_grainsize, OMPC_num_tasks}))
13715 return StmtError();
13716 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13717 // If a reduction clause is present on the taskloop directive, the nogroup
13718 // clause must not be specified.
13719 if (checkReductionClauseWithNogroup(*this, Clauses))
13720 return StmtError();
13721 if (checkSimdlenSafelenSpecified(*this, Clauses))
13722 return StmtError();
13724 setFunctionHasBranchProtectedScope();
13725 return OMPParallelMaskedTaskLoopSimdDirective::Create(
13726 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13729 StmtResult Sema::ActOnOpenMPDistributeDirective(
13730 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13731 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13732 if (!AStmt)
13733 return StmtError();
13735 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13736 OMPLoopBasedDirective::HelperExprs B;
13737 // In presence of clause 'collapse' with number of loops, it will
13738 // define the nested loops number.
13739 unsigned NestedLoopCount =
13740 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
13741 nullptr /*ordered not a clause on distribute*/, AStmt,
13742 *this, *DSAStack, VarsWithImplicitDSA, B);
13743 if (NestedLoopCount == 0)
13744 return StmtError();
13746 assert((CurContext->isDependentContext() || B.builtAll()) &&
13747 "omp for loop exprs were not built");
13749 setFunctionHasBranchProtectedScope();
13750 return OMPDistributeDirective::Create(Context, StartLoc, EndLoc,
13751 NestedLoopCount, Clauses, AStmt, B);
13754 StmtResult Sema::ActOnOpenMPDistributeParallelForDirective(
13755 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13756 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13757 if (!AStmt)
13758 return StmtError();
13760 auto *CS = cast<CapturedStmt>(AStmt);
13761 // 1.2.2 OpenMP Language Terminology
13762 // Structured block - An executable statement with a single entry at the
13763 // top and a single exit at the bottom.
13764 // The point of exit cannot be a branch out of the structured block.
13765 // longjmp() and throw() must not violate the entry/exit criteria.
13766 CS->getCapturedDecl()->setNothrow();
13767 for (int ThisCaptureLevel =
13768 getOpenMPCaptureLevels(OMPD_distribute_parallel_for);
13769 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13770 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13771 // 1.2.2 OpenMP Language Terminology
13772 // Structured block - An executable statement with a single entry at the
13773 // top and a single exit at the bottom.
13774 // The point of exit cannot be a branch out of the structured block.
13775 // longjmp() and throw() must not violate the entry/exit criteria.
13776 CS->getCapturedDecl()->setNothrow();
13779 OMPLoopBasedDirective::HelperExprs B;
13780 // In presence of clause 'collapse' with number of loops, it will
13781 // define the nested loops number.
13782 unsigned NestedLoopCount = checkOpenMPLoop(
13783 OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
13784 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
13785 VarsWithImplicitDSA, B);
13786 if (NestedLoopCount == 0)
13787 return StmtError();
13789 assert((CurContext->isDependentContext() || B.builtAll()) &&
13790 "omp for loop exprs were not built");
13792 setFunctionHasBranchProtectedScope();
13793 return OMPDistributeParallelForDirective::Create(
13794 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13795 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13798 StmtResult Sema::ActOnOpenMPDistributeParallelForSimdDirective(
13799 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13800 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13801 if (!AStmt)
13802 return StmtError();
13804 auto *CS = cast<CapturedStmt>(AStmt);
13805 // 1.2.2 OpenMP Language Terminology
13806 // Structured block - An executable statement with a single entry at the
13807 // top and a single exit at the bottom.
13808 // The point of exit cannot be a branch out of the structured block.
13809 // longjmp() and throw() must not violate the entry/exit criteria.
13810 CS->getCapturedDecl()->setNothrow();
13811 for (int ThisCaptureLevel =
13812 getOpenMPCaptureLevels(OMPD_distribute_parallel_for_simd);
13813 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13814 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13815 // 1.2.2 OpenMP Language Terminology
13816 // Structured block - An executable statement with a single entry at the
13817 // top and a single exit at the bottom.
13818 // The point of exit cannot be a branch out of the structured block.
13819 // longjmp() and throw() must not violate the entry/exit criteria.
13820 CS->getCapturedDecl()->setNothrow();
13823 OMPLoopBasedDirective::HelperExprs B;
13824 // In presence of clause 'collapse' with number of loops, it will
13825 // define the nested loops number.
13826 unsigned NestedLoopCount = checkOpenMPLoop(
13827 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
13828 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
13829 VarsWithImplicitDSA, B);
13830 if (NestedLoopCount == 0)
13831 return StmtError();
13833 assert((CurContext->isDependentContext() || B.builtAll()) &&
13834 "omp for loop exprs were not built");
13836 if (!CurContext->isDependentContext()) {
13837 // Finalize the clauses that need pre-built expressions for CodeGen.
13838 for (OMPClause *C : Clauses) {
13839 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13840 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13841 B.NumIterations, *this, CurScope,
13842 DSAStack))
13843 return StmtError();
13847 if (checkSimdlenSafelenSpecified(*this, Clauses))
13848 return StmtError();
13850 setFunctionHasBranchProtectedScope();
13851 return OMPDistributeParallelForSimdDirective::Create(
13852 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13855 StmtResult Sema::ActOnOpenMPDistributeSimdDirective(
13856 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13857 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13858 if (!AStmt)
13859 return StmtError();
13861 auto *CS = cast<CapturedStmt>(AStmt);
13862 // 1.2.2 OpenMP Language Terminology
13863 // Structured block - An executable statement with a single entry at the
13864 // top and a single exit at the bottom.
13865 // The point of exit cannot be a branch out of the structured block.
13866 // longjmp() and throw() must not violate the entry/exit criteria.
13867 CS->getCapturedDecl()->setNothrow();
13868 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_distribute_simd);
13869 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13870 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13871 // 1.2.2 OpenMP Language Terminology
13872 // Structured block - An executable statement with a single entry at the
13873 // top and a single exit at the bottom.
13874 // The point of exit cannot be a branch out of the structured block.
13875 // longjmp() and throw() must not violate the entry/exit criteria.
13876 CS->getCapturedDecl()->setNothrow();
13879 OMPLoopBasedDirective::HelperExprs B;
13880 // In presence of clause 'collapse' with number of loops, it will
13881 // define the nested loops number.
13882 unsigned NestedLoopCount =
13883 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
13884 nullptr /*ordered not a clause on distribute*/, CS, *this,
13885 *DSAStack, VarsWithImplicitDSA, B);
13886 if (NestedLoopCount == 0)
13887 return StmtError();
13889 assert((CurContext->isDependentContext() || B.builtAll()) &&
13890 "omp for loop exprs were not built");
13892 if (!CurContext->isDependentContext()) {
13893 // Finalize the clauses that need pre-built expressions for CodeGen.
13894 for (OMPClause *C : Clauses) {
13895 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13896 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13897 B.NumIterations, *this, CurScope,
13898 DSAStack))
13899 return StmtError();
13903 if (checkSimdlenSafelenSpecified(*this, Clauses))
13904 return StmtError();
13906 setFunctionHasBranchProtectedScope();
13907 return OMPDistributeSimdDirective::Create(Context, StartLoc, EndLoc,
13908 NestedLoopCount, Clauses, AStmt, B);
13911 StmtResult Sema::ActOnOpenMPTargetParallelForSimdDirective(
13912 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13913 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13914 if (!AStmt)
13915 return StmtError();
13917 auto *CS = cast<CapturedStmt>(AStmt);
13918 // 1.2.2 OpenMP Language Terminology
13919 // Structured block - An executable statement with a single entry at the
13920 // top and a single exit at the bottom.
13921 // The point of exit cannot be a branch out of the structured block.
13922 // longjmp() and throw() must not violate the entry/exit criteria.
13923 CS->getCapturedDecl()->setNothrow();
13924 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_for);
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_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
13940 getOrderedNumberExpr(Clauses), CS, *this, *DSAStack, VarsWithImplicitDSA,
13942 if (NestedLoopCount == 0)
13943 return StmtError();
13945 assert((CurContext->isDependentContext() || B.builtAll()) &&
13946 "omp target parallel for simd loop exprs were not built");
13948 if (!CurContext->isDependentContext()) {
13949 // Finalize the clauses that need pre-built expressions for CodeGen.
13950 for (OMPClause *C : Clauses) {
13951 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13952 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13953 B.NumIterations, *this, CurScope,
13954 DSAStack))
13955 return StmtError();
13958 if (checkSimdlenSafelenSpecified(*this, Clauses))
13959 return StmtError();
13961 setFunctionHasBranchProtectedScope();
13962 return OMPTargetParallelForSimdDirective::Create(
13963 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13966 StmtResult Sema::ActOnOpenMPTargetSimdDirective(
13967 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13968 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13969 if (!AStmt)
13970 return StmtError();
13972 auto *CS = cast<CapturedStmt>(AStmt);
13973 // 1.2.2 OpenMP Language Terminology
13974 // Structured block - An executable statement with a single entry at the
13975 // top and a single exit at the bottom.
13976 // The point of exit cannot be a branch out of the structured block.
13977 // longjmp() and throw() must not violate the entry/exit criteria.
13978 CS->getCapturedDecl()->setNothrow();
13979 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_simd);
13980 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13981 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13982 // 1.2.2 OpenMP Language Terminology
13983 // Structured block - An executable statement with a single entry at the
13984 // top and a single exit at the bottom.
13985 // The point of exit cannot be a branch out of the structured block.
13986 // longjmp() and throw() must not violate the entry/exit criteria.
13987 CS->getCapturedDecl()->setNothrow();
13990 OMPLoopBasedDirective::HelperExprs B;
13991 // In presence of clause 'collapse' with number of loops, it will define the
13992 // nested loops number.
13993 unsigned NestedLoopCount =
13994 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
13995 getOrderedNumberExpr(Clauses), CS, *this, *DSAStack,
13996 VarsWithImplicitDSA, B);
13997 if (NestedLoopCount == 0)
13998 return StmtError();
14000 assert((CurContext->isDependentContext() || B.builtAll()) &&
14001 "omp target simd loop exprs were not built");
14003 if (!CurContext->isDependentContext()) {
14004 // Finalize the clauses that need pre-built expressions for CodeGen.
14005 for (OMPClause *C : Clauses) {
14006 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14007 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14008 B.NumIterations, *this, CurScope,
14009 DSAStack))
14010 return StmtError();
14014 if (checkSimdlenSafelenSpecified(*this, Clauses))
14015 return StmtError();
14017 setFunctionHasBranchProtectedScope();
14018 return OMPTargetSimdDirective::Create(Context, StartLoc, EndLoc,
14019 NestedLoopCount, Clauses, AStmt, B);
14022 StmtResult Sema::ActOnOpenMPTeamsDistributeDirective(
14023 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14024 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14025 if (!AStmt)
14026 return StmtError();
14028 auto *CS = cast<CapturedStmt>(AStmt);
14029 // 1.2.2 OpenMP Language Terminology
14030 // Structured block - An executable statement with a single entry at the
14031 // top and a single exit at the bottom.
14032 // The point of exit cannot be a branch out of the structured block.
14033 // longjmp() and throw() must not violate the entry/exit criteria.
14034 CS->getCapturedDecl()->setNothrow();
14035 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_teams_distribute);
14036 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14037 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14038 // 1.2.2 OpenMP Language Terminology
14039 // Structured block - An executable statement with a single entry at the
14040 // top and a single exit at the bottom.
14041 // The point of exit cannot be a branch out of the structured block.
14042 // longjmp() and throw() must not violate the entry/exit criteria.
14043 CS->getCapturedDecl()->setNothrow();
14046 OMPLoopBasedDirective::HelperExprs B;
14047 // In presence of clause 'collapse' with number of loops, it will
14048 // define the nested loops number.
14049 unsigned NestedLoopCount =
14050 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
14051 nullptr /*ordered not a clause on distribute*/, CS, *this,
14052 *DSAStack, VarsWithImplicitDSA, B);
14053 if (NestedLoopCount == 0)
14054 return StmtError();
14056 assert((CurContext->isDependentContext() || B.builtAll()) &&
14057 "omp teams distribute loop exprs were not built");
14059 setFunctionHasBranchProtectedScope();
14061 DSAStack->setParentTeamsRegionLoc(StartLoc);
14063 return OMPTeamsDistributeDirective::Create(
14064 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14067 StmtResult Sema::ActOnOpenMPTeamsDistributeSimdDirective(
14068 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14069 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14070 if (!AStmt)
14071 return StmtError();
14073 auto *CS = cast<CapturedStmt>(AStmt);
14074 // 1.2.2 OpenMP Language Terminology
14075 // Structured block - An executable statement with a single entry at the
14076 // top and a single exit at the bottom.
14077 // The point of exit cannot be a branch out of the structured block.
14078 // longjmp() and throw() must not violate the entry/exit criteria.
14079 CS->getCapturedDecl()->setNothrow();
14080 for (int ThisCaptureLevel =
14081 getOpenMPCaptureLevels(OMPD_teams_distribute_simd);
14082 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14083 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14084 // 1.2.2 OpenMP Language Terminology
14085 // Structured block - An executable statement with a single entry at the
14086 // top and a single exit at the bottom.
14087 // The point of exit cannot be a branch out of the structured block.
14088 // longjmp() and throw() must not violate the entry/exit criteria.
14089 CS->getCapturedDecl()->setNothrow();
14092 OMPLoopBasedDirective::HelperExprs B;
14093 // In presence of clause 'collapse' with number of loops, it will
14094 // define the nested loops number.
14095 unsigned NestedLoopCount = checkOpenMPLoop(
14096 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14097 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14098 VarsWithImplicitDSA, B);
14100 if (NestedLoopCount == 0)
14101 return StmtError();
14103 assert((CurContext->isDependentContext() || B.builtAll()) &&
14104 "omp teams distribute simd loop exprs were not built");
14106 if (!CurContext->isDependentContext()) {
14107 // Finalize the clauses that need pre-built expressions for CodeGen.
14108 for (OMPClause *C : Clauses) {
14109 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14110 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14111 B.NumIterations, *this, CurScope,
14112 DSAStack))
14113 return StmtError();
14117 if (checkSimdlenSafelenSpecified(*this, Clauses))
14118 return StmtError();
14120 setFunctionHasBranchProtectedScope();
14122 DSAStack->setParentTeamsRegionLoc(StartLoc);
14124 return OMPTeamsDistributeSimdDirective::Create(
14125 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14128 StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
14129 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14130 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14131 if (!AStmt)
14132 return StmtError();
14134 auto *CS = cast<CapturedStmt>(AStmt);
14135 // 1.2.2 OpenMP Language Terminology
14136 // Structured block - An executable statement with a single entry at the
14137 // top and a single exit at the bottom.
14138 // The point of exit cannot be a branch out of the structured block.
14139 // longjmp() and throw() must not violate the entry/exit criteria.
14140 CS->getCapturedDecl()->setNothrow();
14142 for (int ThisCaptureLevel =
14143 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for_simd);
14144 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14145 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14146 // 1.2.2 OpenMP Language Terminology
14147 // Structured block - An executable statement with a single entry at the
14148 // top and a single exit at the bottom.
14149 // The point of exit cannot be a branch out of the structured block.
14150 // longjmp() and throw() must not violate the entry/exit criteria.
14151 CS->getCapturedDecl()->setNothrow();
14154 OMPLoopBasedDirective::HelperExprs B;
14155 // In presence of clause 'collapse' with number of loops, it will
14156 // define the nested loops number.
14157 unsigned NestedLoopCount = checkOpenMPLoop(
14158 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14159 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14160 VarsWithImplicitDSA, B);
14162 if (NestedLoopCount == 0)
14163 return StmtError();
14165 assert((CurContext->isDependentContext() || B.builtAll()) &&
14166 "omp for loop exprs were not built");
14168 if (!CurContext->isDependentContext()) {
14169 // Finalize the clauses that need pre-built expressions for CodeGen.
14170 for (OMPClause *C : Clauses) {
14171 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14172 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14173 B.NumIterations, *this, CurScope,
14174 DSAStack))
14175 return StmtError();
14179 if (checkSimdlenSafelenSpecified(*this, Clauses))
14180 return StmtError();
14182 setFunctionHasBranchProtectedScope();
14184 DSAStack->setParentTeamsRegionLoc(StartLoc);
14186 return OMPTeamsDistributeParallelForSimdDirective::Create(
14187 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14190 StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForDirective(
14191 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14192 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14193 if (!AStmt)
14194 return StmtError();
14196 auto *CS = cast<CapturedStmt>(AStmt);
14197 // 1.2.2 OpenMP Language Terminology
14198 // Structured block - An executable statement with a single entry at the
14199 // top and a single exit at the bottom.
14200 // The point of exit cannot be a branch out of the structured block.
14201 // longjmp() and throw() must not violate the entry/exit criteria.
14202 CS->getCapturedDecl()->setNothrow();
14204 for (int ThisCaptureLevel =
14205 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for);
14206 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14207 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14208 // 1.2.2 OpenMP Language Terminology
14209 // Structured block - An executable statement with a single entry at the
14210 // top and a single exit at the bottom.
14211 // The point of exit cannot be a branch out of the structured block.
14212 // longjmp() and throw() must not violate the entry/exit criteria.
14213 CS->getCapturedDecl()->setNothrow();
14216 OMPLoopBasedDirective::HelperExprs B;
14217 // In presence of clause 'collapse' with number of loops, it will
14218 // define the nested loops number.
14219 unsigned NestedLoopCount = checkOpenMPLoop(
14220 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14221 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14222 VarsWithImplicitDSA, B);
14224 if (NestedLoopCount == 0)
14225 return StmtError();
14227 assert((CurContext->isDependentContext() || B.builtAll()) &&
14228 "omp for loop exprs were not built");
14230 setFunctionHasBranchProtectedScope();
14232 DSAStack->setParentTeamsRegionLoc(StartLoc);
14234 return OMPTeamsDistributeParallelForDirective::Create(
14235 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14236 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14239 StmtResult Sema::ActOnOpenMPTargetTeamsDirective(ArrayRef<OMPClause *> Clauses,
14240 Stmt *AStmt,
14241 SourceLocation StartLoc,
14242 SourceLocation EndLoc) {
14243 if (!AStmt)
14244 return StmtError();
14246 auto *CS = cast<CapturedStmt>(AStmt);
14247 // 1.2.2 OpenMP Language Terminology
14248 // Structured block - An executable statement with a single entry at the
14249 // top and a single exit at the bottom.
14250 // The point of exit cannot be a branch out of the structured block.
14251 // longjmp() and throw() must not violate the entry/exit criteria.
14252 CS->getCapturedDecl()->setNothrow();
14254 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_teams);
14255 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14256 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14257 // 1.2.2 OpenMP Language Terminology
14258 // Structured block - An executable statement with a single entry at the
14259 // top and a single exit at the bottom.
14260 // The point of exit cannot be a branch out of the structured block.
14261 // longjmp() and throw() must not violate the entry/exit criteria.
14262 CS->getCapturedDecl()->setNothrow();
14264 setFunctionHasBranchProtectedScope();
14266 return OMPTargetTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses,
14267 AStmt);
14270 StmtResult Sema::ActOnOpenMPTargetTeamsDistributeDirective(
14271 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14272 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14273 if (!AStmt)
14274 return StmtError();
14276 auto *CS = cast<CapturedStmt>(AStmt);
14277 // 1.2.2 OpenMP Language Terminology
14278 // Structured block - An executable statement with a single entry at the
14279 // top and a single exit at the bottom.
14280 // The point of exit cannot be a branch out of the structured block.
14281 // longjmp() and throw() must not violate the entry/exit criteria.
14282 CS->getCapturedDecl()->setNothrow();
14283 for (int ThisCaptureLevel =
14284 getOpenMPCaptureLevels(OMPD_target_teams_distribute);
14285 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14286 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14287 // 1.2.2 OpenMP Language Terminology
14288 // Structured block - An executable statement with a single entry at the
14289 // top and a single exit at the bottom.
14290 // The point of exit cannot be a branch out of the structured block.
14291 // longjmp() and throw() must not violate the entry/exit criteria.
14292 CS->getCapturedDecl()->setNothrow();
14295 OMPLoopBasedDirective::HelperExprs B;
14296 // In presence of clause 'collapse' with number of loops, it will
14297 // define the nested loops number.
14298 unsigned NestedLoopCount = checkOpenMPLoop(
14299 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
14300 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14301 VarsWithImplicitDSA, B);
14302 if (NestedLoopCount == 0)
14303 return StmtError();
14305 assert((CurContext->isDependentContext() || B.builtAll()) &&
14306 "omp target teams distribute loop exprs were not built");
14308 setFunctionHasBranchProtectedScope();
14309 return OMPTargetTeamsDistributeDirective::Create(
14310 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14313 StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForDirective(
14314 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14315 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14316 if (!AStmt)
14317 return StmtError();
14319 auto *CS = cast<CapturedStmt>(AStmt);
14320 // 1.2.2 OpenMP Language Terminology
14321 // Structured block - An executable statement with a single entry at the
14322 // top and a single exit at the bottom.
14323 // The point of exit cannot be a branch out of the structured block.
14324 // longjmp() and throw() must not violate the entry/exit criteria.
14325 CS->getCapturedDecl()->setNothrow();
14326 for (int ThisCaptureLevel =
14327 getOpenMPCaptureLevels(OMPD_target_teams_distribute_parallel_for);
14328 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14329 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14330 // 1.2.2 OpenMP Language Terminology
14331 // Structured block - An executable statement with a single entry at the
14332 // top and a single exit at the bottom.
14333 // The point of exit cannot be a branch out of the structured block.
14334 // longjmp() and throw() must not violate the entry/exit criteria.
14335 CS->getCapturedDecl()->setNothrow();
14338 OMPLoopBasedDirective::HelperExprs B;
14339 // In presence of clause 'collapse' with number of loops, it will
14340 // define the nested loops number.
14341 unsigned NestedLoopCount = checkOpenMPLoop(
14342 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14343 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14344 VarsWithImplicitDSA, B);
14345 if (NestedLoopCount == 0)
14346 return StmtError();
14348 assert((CurContext->isDependentContext() || B.builtAll()) &&
14349 "omp target teams distribute parallel for loop exprs were not built");
14351 if (!CurContext->isDependentContext()) {
14352 // Finalize the clauses that need pre-built expressions for CodeGen.
14353 for (OMPClause *C : Clauses) {
14354 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14355 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14356 B.NumIterations, *this, CurScope,
14357 DSAStack))
14358 return StmtError();
14362 setFunctionHasBranchProtectedScope();
14363 return OMPTargetTeamsDistributeParallelForDirective::Create(
14364 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14365 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14368 StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
14369 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14370 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14371 if (!AStmt)
14372 return StmtError();
14374 auto *CS = cast<CapturedStmt>(AStmt);
14375 // 1.2.2 OpenMP Language Terminology
14376 // Structured block - An executable statement with a single entry at the
14377 // top and a single exit at the bottom.
14378 // The point of exit cannot be a branch out of the structured block.
14379 // longjmp() and throw() must not violate the entry/exit criteria.
14380 CS->getCapturedDecl()->setNothrow();
14381 for (int ThisCaptureLevel = getOpenMPCaptureLevels(
14382 OMPD_target_teams_distribute_parallel_for_simd);
14383 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14384 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14385 // 1.2.2 OpenMP Language Terminology
14386 // Structured block - An executable statement with a single entry at the
14387 // top and a single exit at the bottom.
14388 // The point of exit cannot be a branch out of the structured block.
14389 // longjmp() and throw() must not violate the entry/exit criteria.
14390 CS->getCapturedDecl()->setNothrow();
14393 OMPLoopBasedDirective::HelperExprs B;
14394 // In presence of clause 'collapse' with number of loops, it will
14395 // define the nested loops number.
14396 unsigned NestedLoopCount =
14397 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
14398 getCollapseNumberExpr(Clauses),
14399 nullptr /*ordered not a clause on distribute*/, CS, *this,
14400 *DSAStack, VarsWithImplicitDSA, B);
14401 if (NestedLoopCount == 0)
14402 return StmtError();
14404 assert((CurContext->isDependentContext() || B.builtAll()) &&
14405 "omp target teams distribute parallel for simd loop exprs were not "
14406 "built");
14408 if (!CurContext->isDependentContext()) {
14409 // Finalize the clauses that need pre-built expressions for CodeGen.
14410 for (OMPClause *C : Clauses) {
14411 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14412 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14413 B.NumIterations, *this, CurScope,
14414 DSAStack))
14415 return StmtError();
14419 if (checkSimdlenSafelenSpecified(*this, Clauses))
14420 return StmtError();
14422 setFunctionHasBranchProtectedScope();
14423 return OMPTargetTeamsDistributeParallelForSimdDirective::Create(
14424 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14427 StmtResult Sema::ActOnOpenMPTargetTeamsDistributeSimdDirective(
14428 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14429 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14430 if (!AStmt)
14431 return StmtError();
14433 auto *CS = cast<CapturedStmt>(AStmt);
14434 // 1.2.2 OpenMP Language Terminology
14435 // Structured block - An executable statement with a single entry at the
14436 // top and a single exit at the bottom.
14437 // The point of exit cannot be a branch out of the structured block.
14438 // longjmp() and throw() must not violate the entry/exit criteria.
14439 CS->getCapturedDecl()->setNothrow();
14440 for (int ThisCaptureLevel =
14441 getOpenMPCaptureLevels(OMPD_target_teams_distribute_simd);
14442 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14443 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14444 // 1.2.2 OpenMP Language Terminology
14445 // Structured block - An executable statement with a single entry at the
14446 // top and a single exit at the bottom.
14447 // The point of exit cannot be a branch out of the structured block.
14448 // longjmp() and throw() must not violate the entry/exit criteria.
14449 CS->getCapturedDecl()->setNothrow();
14452 OMPLoopBasedDirective::HelperExprs B;
14453 // In presence of clause 'collapse' with number of loops, it will
14454 // define the nested loops number.
14455 unsigned NestedLoopCount = checkOpenMPLoop(
14456 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14457 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14458 VarsWithImplicitDSA, B);
14459 if (NestedLoopCount == 0)
14460 return StmtError();
14462 assert((CurContext->isDependentContext() || B.builtAll()) &&
14463 "omp target teams distribute simd loop exprs were not built");
14465 if (!CurContext->isDependentContext()) {
14466 // Finalize the clauses that need pre-built expressions for CodeGen.
14467 for (OMPClause *C : Clauses) {
14468 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14469 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14470 B.NumIterations, *this, CurScope,
14471 DSAStack))
14472 return StmtError();
14476 if (checkSimdlenSafelenSpecified(*this, Clauses))
14477 return StmtError();
14479 setFunctionHasBranchProtectedScope();
14480 return OMPTargetTeamsDistributeSimdDirective::Create(
14481 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14484 bool Sema::checkTransformableLoopNest(
14485 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14486 SmallVectorImpl<OMPLoopBasedDirective::HelperExprs> &LoopHelpers,
14487 Stmt *&Body,
14488 SmallVectorImpl<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>>
14489 &OriginalInits) {
14490 OriginalInits.emplace_back();
14491 bool Result = OMPLoopBasedDirective::doForAllLoops(
14492 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14493 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14494 Stmt *CurStmt) {
14495 VarsWithInheritedDSAType TmpDSA;
14496 unsigned SingleNumLoops =
14497 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, *this, *DSAStack,
14498 TmpDSA, LoopHelpers[Cnt]);
14499 if (SingleNumLoops == 0)
14500 return true;
14501 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14502 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14503 OriginalInits.back().push_back(For->getInit());
14504 Body = For->getBody();
14505 } else {
14506 assert(isa<CXXForRangeStmt>(CurStmt) &&
14507 "Expected canonical for or range-based for loops.");
14508 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14509 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14510 Body = CXXFor->getBody();
14512 OriginalInits.emplace_back();
14513 return false;
14515 [&OriginalInits](OMPLoopBasedDirective *Transform) {
14516 Stmt *DependentPreInits;
14517 if (auto *Dir = dyn_cast<OMPTileDirective>(Transform))
14518 DependentPreInits = Dir->getPreInits();
14519 else if (auto *Dir = dyn_cast<OMPUnrollDirective>(Transform))
14520 DependentPreInits = Dir->getPreInits();
14521 else
14522 llvm_unreachable("Unhandled loop transformation");
14523 if (!DependentPreInits)
14524 return;
14525 llvm::append_range(OriginalInits.back(),
14526 cast<DeclStmt>(DependentPreInits)->getDeclGroup());
14528 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14529 OriginalInits.pop_back();
14530 return Result;
14533 StmtResult Sema::ActOnOpenMPTileDirective(ArrayRef<OMPClause *> Clauses,
14534 Stmt *AStmt, SourceLocation StartLoc,
14535 SourceLocation EndLoc) {
14536 auto SizesClauses =
14537 OMPExecutableDirective::getClausesOfKind<OMPSizesClause>(Clauses);
14538 if (SizesClauses.empty()) {
14539 // A missing 'sizes' clause is already reported by the parser.
14540 return StmtError();
14542 const OMPSizesClause *SizesClause = *SizesClauses.begin();
14543 unsigned NumLoops = SizesClause->getNumSizes();
14545 // Empty statement should only be possible if there already was an error.
14546 if (!AStmt)
14547 return StmtError();
14549 // Verify and diagnose loop nest.
14550 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
14551 Stmt *Body = nullptr;
14552 SmallVector<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>, 4>
14553 OriginalInits;
14554 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14555 OriginalInits))
14556 return StmtError();
14558 // Delay tiling to when template is completely instantiated.
14559 if (CurContext->isDependentContext())
14560 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
14561 NumLoops, AStmt, nullptr, nullptr);
14563 SmallVector<Decl *, 4> PreInits;
14565 // Create iteration variables for the generated loops.
14566 SmallVector<VarDecl *, 4> FloorIndVars;
14567 SmallVector<VarDecl *, 4> TileIndVars;
14568 FloorIndVars.resize(NumLoops);
14569 TileIndVars.resize(NumLoops);
14570 for (unsigned I = 0; I < NumLoops; ++I) {
14571 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14573 assert(LoopHelper.Counters.size() == 1 &&
14574 "Expect single-dimensional loop iteration space");
14575 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14576 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14577 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14578 QualType CntTy = IterVarRef->getType();
14580 // Iteration variable for the floor (i.e. outer) loop.
14582 std::string FloorCntName =
14583 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14584 VarDecl *FloorCntDecl =
14585 buildVarDecl(*this, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
14586 FloorIndVars[I] = FloorCntDecl;
14589 // Iteration variable for the tile (i.e. inner) loop.
14591 std::string TileCntName =
14592 (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14594 // Reuse the iteration variable created by checkOpenMPLoop. It is also
14595 // used by the expressions to derive the original iteration variable's
14596 // value from the logical iteration number.
14597 auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
14598 TileCntDecl->setDeclName(&PP.getIdentifierTable().get(TileCntName));
14599 TileIndVars[I] = TileCntDecl;
14601 for (auto &P : OriginalInits[I]) {
14602 if (auto *D = P.dyn_cast<Decl *>())
14603 PreInits.push_back(D);
14604 else if (auto *PI = dyn_cast_or_null<DeclStmt>(P.dyn_cast<Stmt *>()))
14605 PreInits.append(PI->decl_begin(), PI->decl_end());
14607 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits))
14608 PreInits.append(PI->decl_begin(), PI->decl_end());
14609 // Gather declarations for the data members used as counters.
14610 for (Expr *CounterRef : LoopHelper.Counters) {
14611 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14612 if (isa<OMPCapturedExprDecl>(CounterDecl))
14613 PreInits.push_back(CounterDecl);
14617 // Once the original iteration values are set, append the innermost body.
14618 Stmt *Inner = Body;
14620 // Create tile loops from the inside to the outside.
14621 for (int I = NumLoops - 1; I >= 0; --I) {
14622 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14623 Expr *NumIterations = LoopHelper.NumIterations;
14624 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14625 QualType CntTy = OrigCntVar->getType();
14626 Expr *DimTileSize = SizesClause->getSizesRefs()[I];
14627 Scope *CurScope = getCurScope();
14629 // Commonly used variables.
14630 DeclRefExpr *TileIV = buildDeclRefExpr(*this, TileIndVars[I], CntTy,
14631 OrigCntVar->getExprLoc());
14632 DeclRefExpr *FloorIV = buildDeclRefExpr(*this, FloorIndVars[I], CntTy,
14633 OrigCntVar->getExprLoc());
14635 // For init-statement: auto .tile.iv = .floor.iv
14636 AddInitializerToDecl(TileIndVars[I], DefaultLvalueConversion(FloorIV).get(),
14637 /*DirectInit=*/false);
14638 Decl *CounterDecl = TileIndVars[I];
14639 StmtResult InitStmt = new (Context)
14640 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14641 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14642 if (!InitStmt.isUsable())
14643 return StmtError();
14645 // For cond-expression: .tile.iv < min(.floor.iv + DimTileSize,
14646 // NumIterations)
14647 ExprResult EndOfTile = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
14648 BO_Add, FloorIV, DimTileSize);
14649 if (!EndOfTile.isUsable())
14650 return StmtError();
14651 ExprResult IsPartialTile =
14652 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14653 NumIterations, EndOfTile.get());
14654 if (!IsPartialTile.isUsable())
14655 return StmtError();
14656 ExprResult MinTileAndIterSpace = ActOnConditionalOp(
14657 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
14658 IsPartialTile.get(), NumIterations, EndOfTile.get());
14659 if (!MinTileAndIterSpace.isUsable())
14660 return StmtError();
14661 ExprResult CondExpr = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
14662 BO_LT, TileIV, MinTileAndIterSpace.get());
14663 if (!CondExpr.isUsable())
14664 return StmtError();
14666 // For incr-statement: ++.tile.iv
14667 ExprResult IncrStmt =
14668 BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, TileIV);
14669 if (!IncrStmt.isUsable())
14670 return StmtError();
14672 // Statements to set the original iteration variable's value from the
14673 // logical iteration number.
14674 // Generated for loop is:
14675 // Original_for_init;
14676 // for (auto .tile.iv = .floor.iv; .tile.iv < min(.floor.iv + DimTileSize,
14677 // NumIterations); ++.tile.iv) {
14678 // Original_Body;
14679 // Original_counter_update;
14680 // }
14681 // FIXME: If the innermost body is an loop itself, inserting these
14682 // statements stops it being recognized as a perfectly nested loop (e.g.
14683 // for applying tiling again). If this is the case, sink the expressions
14684 // further into the inner loop.
14685 SmallVector<Stmt *, 4> BodyParts;
14686 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
14687 BodyParts.push_back(Inner);
14688 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
14689 Inner->getBeginLoc(), Inner->getEndLoc());
14690 Inner = new (Context)
14691 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14692 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14693 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14696 // Create floor loops from the inside to the outside.
14697 for (int I = NumLoops - 1; I >= 0; --I) {
14698 auto &LoopHelper = LoopHelpers[I];
14699 Expr *NumIterations = LoopHelper.NumIterations;
14700 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14701 QualType CntTy = OrigCntVar->getType();
14702 Expr *DimTileSize = SizesClause->getSizesRefs()[I];
14703 Scope *CurScope = getCurScope();
14705 // Commonly used variables.
14706 DeclRefExpr *FloorIV = buildDeclRefExpr(*this, FloorIndVars[I], CntTy,
14707 OrigCntVar->getExprLoc());
14709 // For init-statement: auto .floor.iv = 0
14710 AddInitializerToDecl(
14711 FloorIndVars[I],
14712 ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
14713 /*DirectInit=*/false);
14714 Decl *CounterDecl = FloorIndVars[I];
14715 StmtResult InitStmt = new (Context)
14716 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14717 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14718 if (!InitStmt.isUsable())
14719 return StmtError();
14721 // For cond-expression: .floor.iv < NumIterations
14722 ExprResult CondExpr = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
14723 BO_LT, FloorIV, NumIterations);
14724 if (!CondExpr.isUsable())
14725 return StmtError();
14727 // For incr-statement: .floor.iv += DimTileSize
14728 ExprResult IncrStmt = BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(),
14729 BO_AddAssign, FloorIV, DimTileSize);
14730 if (!IncrStmt.isUsable())
14731 return StmtError();
14733 Inner = new (Context)
14734 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14735 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14736 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14739 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
14740 AStmt, Inner,
14741 buildPreInits(Context, PreInits));
14744 StmtResult Sema::ActOnOpenMPUnrollDirective(ArrayRef<OMPClause *> Clauses,
14745 Stmt *AStmt,
14746 SourceLocation StartLoc,
14747 SourceLocation EndLoc) {
14748 // Empty statement should only be possible if there already was an error.
14749 if (!AStmt)
14750 return StmtError();
14752 if (checkMutuallyExclusiveClauses(*this, Clauses, {OMPC_partial, OMPC_full}))
14753 return StmtError();
14755 const OMPFullClause *FullClause =
14756 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
14757 const OMPPartialClause *PartialClause =
14758 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
14759 assert(!(FullClause && PartialClause) &&
14760 "mutual exclusivity must have been checked before");
14762 constexpr unsigned NumLoops = 1;
14763 Stmt *Body = nullptr;
14764 SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
14765 NumLoops);
14766 SmallVector<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>, NumLoops + 1>
14767 OriginalInits;
14768 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
14769 Body, OriginalInits))
14770 return StmtError();
14772 unsigned NumGeneratedLoops = PartialClause ? 1 : 0;
14774 // Delay unrolling to when template is completely instantiated.
14775 if (CurContext->isDependentContext())
14776 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14777 NumGeneratedLoops, nullptr, nullptr);
14779 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
14781 if (FullClause) {
14782 if (!VerifyPositiveIntegerConstantInClause(
14783 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
14784 /*SuppressExprDiags=*/true)
14785 .isUsable()) {
14786 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
14787 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
14788 << "#pragma omp unroll full";
14789 return StmtError();
14793 // The generated loop may only be passed to other loop-associated directive
14794 // when a partial clause is specified. Without the requirement it is
14795 // sufficient to generate loop unroll metadata at code-generation.
14796 if (NumGeneratedLoops == 0)
14797 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14798 NumGeneratedLoops, nullptr, nullptr);
14800 // Otherwise, we need to provide a de-sugared/transformed AST that can be
14801 // associated with another loop directive.
14803 // The canonical loop analysis return by checkTransformableLoopNest assumes
14804 // the following structure to be the same loop without transformations or
14805 // directives applied: \code OriginalInits; LoopHelper.PreInits;
14806 // LoopHelper.Counters;
14807 // for (; IV < LoopHelper.NumIterations; ++IV) {
14808 // LoopHelper.Updates;
14809 // Body;
14810 // }
14811 // \endcode
14812 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
14813 // and referenced by LoopHelper.IterationVarRef.
14815 // The unrolling directive transforms this into the following loop:
14816 // \code
14817 // OriginalInits; \
14818 // LoopHelper.PreInits; > NewPreInits
14819 // LoopHelper.Counters; /
14820 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
14821 // #pragma clang loop unroll_count(Factor)
14822 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
14823 // {
14824 // LoopHelper.Updates;
14825 // Body;
14826 // }
14827 // }
14828 // \endcode
14829 // where UIV is a new logical iteration counter. IV must be the same VarDecl
14830 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
14831 // references it. If the partially unrolled loop is associated with another
14832 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
14833 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
14834 // OpenMP canonical loop. The inner loop is not an associable canonical loop
14835 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
14836 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
14837 // property of the OMPLoopBasedDirective instead of statements in
14838 // CompoundStatement. This is to allow the loop to become a non-outermost loop
14839 // of a canonical loop nest where these PreInits are emitted before the
14840 // outermost directive.
14842 // Determine the PreInit declarations.
14843 SmallVector<Decl *, 4> PreInits;
14844 assert(OriginalInits.size() == 1 &&
14845 "Expecting a single-dimensional loop iteration space");
14846 for (auto &P : OriginalInits[0]) {
14847 if (auto *D = P.dyn_cast<Decl *>())
14848 PreInits.push_back(D);
14849 else if (auto *PI = dyn_cast_or_null<DeclStmt>(P.dyn_cast<Stmt *>()))
14850 PreInits.append(PI->decl_begin(), PI->decl_end());
14852 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits))
14853 PreInits.append(PI->decl_begin(), PI->decl_end());
14854 // Gather declarations for the data members used as counters.
14855 for (Expr *CounterRef : LoopHelper.Counters) {
14856 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14857 if (isa<OMPCapturedExprDecl>(CounterDecl))
14858 PreInits.push_back(CounterDecl);
14861 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14862 QualType IVTy = IterationVarRef->getType();
14863 assert(LoopHelper.Counters.size() == 1 &&
14864 "Expecting a single-dimensional loop iteration space");
14865 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14867 // Determine the unroll factor.
14868 uint64_t Factor;
14869 SourceLocation FactorLoc;
14870 if (Expr *FactorVal = PartialClause->getFactor()) {
14871 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
14872 FactorLoc = FactorVal->getExprLoc();
14873 } else {
14874 // TODO: Use a better profitability model.
14875 Factor = 2;
14877 assert(Factor > 0 && "Expected positive unroll factor");
14878 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
14879 return IntegerLiteral::Create(
14880 Context, llvm::APInt(Context.getIntWidth(IVTy), Factor), IVTy,
14881 FactorLoc);
14884 // Iteration variable SourceLocations.
14885 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
14886 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
14887 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
14889 // Internal variable names.
14890 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
14891 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
14892 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
14893 std::string InnerTripCountName =
14894 (Twine(".unroll_inner.tripcount.") + OrigVarName).str();
14896 // Create the iteration variable for the unrolled loop.
14897 VarDecl *OuterIVDecl =
14898 buildVarDecl(*this, {}, IVTy, OuterIVName, nullptr, OrigVar);
14899 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
14900 return buildDeclRefExpr(*this, OuterIVDecl, IVTy, OrigVarLoc);
14903 // Iteration variable for the inner loop: Reuse the iteration variable created
14904 // by checkOpenMPLoop.
14905 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
14906 InnerIVDecl->setDeclName(&PP.getIdentifierTable().get(InnerIVName));
14907 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
14908 return buildDeclRefExpr(*this, InnerIVDecl, IVTy, OrigVarLoc);
14911 // Make a copy of the NumIterations expression for each use: By the AST
14912 // constraints, every expression object in a DeclContext must be unique.
14913 CaptureVars CopyTransformer(*this);
14914 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
14915 return AssertSuccess(
14916 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
14919 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
14920 ExprResult LValueConv = DefaultLvalueConversion(MakeOuterRef());
14921 AddInitializerToDecl(InnerIVDecl, LValueConv.get(), /*DirectInit=*/false);
14922 StmtResult InnerInit = new (Context)
14923 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
14924 if (!InnerInit.isUsable())
14925 return StmtError();
14927 // Inner For cond-expression:
14928 // \code
14929 // .unroll_inner.iv < .unrolled.iv + Factor &&
14930 // .unroll_inner.iv < NumIterations
14931 // \endcode
14932 // This conjunction of two conditions allows ScalarEvolution to derive the
14933 // maximum trip count of the inner loop.
14934 ExprResult EndOfTile = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
14935 BO_Add, MakeOuterRef(), MakeFactorExpr());
14936 if (!EndOfTile.isUsable())
14937 return StmtError();
14938 ExprResult InnerCond1 = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
14939 BO_LT, MakeInnerRef(), EndOfTile.get());
14940 if (!InnerCond1.isUsable())
14941 return StmtError();
14942 ExprResult InnerCond2 =
14943 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, MakeInnerRef(),
14944 MakeNumIterations());
14945 if (!InnerCond2.isUsable())
14946 return StmtError();
14947 ExprResult InnerCond =
14948 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
14949 InnerCond1.get(), InnerCond2.get());
14950 if (!InnerCond.isUsable())
14951 return StmtError();
14953 // Inner For incr-statement: ++.unroll_inner.iv
14954 ExprResult InnerIncr = BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(),
14955 UO_PreInc, MakeInnerRef());
14956 if (!InnerIncr.isUsable())
14957 return StmtError();
14959 // Inner For statement.
14960 SmallVector<Stmt *> InnerBodyStmts;
14961 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
14962 InnerBodyStmts.push_back(Body);
14963 CompoundStmt *InnerBody =
14964 CompoundStmt::Create(Context, InnerBodyStmts, FPOptionsOverride(),
14965 Body->getBeginLoc(), Body->getEndLoc());
14966 ForStmt *InnerFor = new (Context)
14967 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
14968 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
14969 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14971 // Unroll metadata for the inner loop.
14972 // This needs to take into account the remainder portion of the unrolled loop,
14973 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
14974 // supports multiple loop exits. Instead, unroll using a factor equivalent to
14975 // the maximum trip count, which will also generate a remainder loop. Just
14976 // `unroll(enable)` (which could have been useful if the user has not
14977 // specified a concrete factor; even though the outer loop cannot be
14978 // influenced anymore, would avoid more code bloat than necessary) will refuse
14979 // the loop because "Won't unroll; remainder loop could not be generated when
14980 // assuming runtime trip count". Even if it did work, it must not choose a
14981 // larger unroll factor than the maximum loop length, or it would always just
14982 // execute the remainder loop.
14983 LoopHintAttr *UnrollHintAttr =
14984 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
14985 LoopHintAttr::Numeric, MakeFactorExpr());
14986 AttributedStmt *InnerUnrolled =
14987 AttributedStmt::Create(Context, StartLoc, {UnrollHintAttr}, InnerFor);
14989 // Outer For init-statement: auto .unrolled.iv = 0
14990 AddInitializerToDecl(
14991 OuterIVDecl, ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
14992 /*DirectInit=*/false);
14993 StmtResult OuterInit = new (Context)
14994 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
14995 if (!OuterInit.isUsable())
14996 return StmtError();
14998 // Outer For cond-expression: .unrolled.iv < NumIterations
14999 ExprResult OuterConde =
15000 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, MakeOuterRef(),
15001 MakeNumIterations());
15002 if (!OuterConde.isUsable())
15003 return StmtError();
15005 // Outer For incr-statement: .unrolled.iv += Factor
15006 ExprResult OuterIncr =
15007 BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15008 MakeOuterRef(), MakeFactorExpr());
15009 if (!OuterIncr.isUsable())
15010 return StmtError();
15012 // Outer For statement.
15013 ForStmt *OuterFor = new (Context)
15014 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
15015 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
15016 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15018 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15019 NumGeneratedLoops, OuterFor,
15020 buildPreInits(Context, PreInits));
15023 OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
15024 SourceLocation StartLoc,
15025 SourceLocation LParenLoc,
15026 SourceLocation EndLoc) {
15027 OMPClause *Res = nullptr;
15028 switch (Kind) {
15029 case OMPC_final:
15030 Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
15031 break;
15032 case OMPC_num_threads:
15033 Res = ActOnOpenMPNumThreadsClause(Expr, StartLoc, LParenLoc, EndLoc);
15034 break;
15035 case OMPC_safelen:
15036 Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
15037 break;
15038 case OMPC_simdlen:
15039 Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
15040 break;
15041 case OMPC_allocator:
15042 Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
15043 break;
15044 case OMPC_collapse:
15045 Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
15046 break;
15047 case OMPC_ordered:
15048 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
15049 break;
15050 case OMPC_num_teams:
15051 Res = ActOnOpenMPNumTeamsClause(Expr, StartLoc, LParenLoc, EndLoc);
15052 break;
15053 case OMPC_thread_limit:
15054 Res = ActOnOpenMPThreadLimitClause(Expr, StartLoc, LParenLoc, EndLoc);
15055 break;
15056 case OMPC_priority:
15057 Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
15058 break;
15059 case OMPC_grainsize:
15060 Res = ActOnOpenMPGrainsizeClause(Expr, StartLoc, LParenLoc, EndLoc);
15061 break;
15062 case OMPC_num_tasks:
15063 Res = ActOnOpenMPNumTasksClause(Expr, StartLoc, LParenLoc, EndLoc);
15064 break;
15065 case OMPC_hint:
15066 Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
15067 break;
15068 case OMPC_depobj:
15069 Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
15070 break;
15071 case OMPC_detach:
15072 Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
15073 break;
15074 case OMPC_novariants:
15075 Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
15076 break;
15077 case OMPC_nocontext:
15078 Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
15079 break;
15080 case OMPC_filter:
15081 Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
15082 break;
15083 case OMPC_partial:
15084 Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
15085 break;
15086 case OMPC_align:
15087 Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
15088 break;
15089 case OMPC_device:
15090 case OMPC_if:
15091 case OMPC_default:
15092 case OMPC_proc_bind:
15093 case OMPC_schedule:
15094 case OMPC_private:
15095 case OMPC_firstprivate:
15096 case OMPC_lastprivate:
15097 case OMPC_shared:
15098 case OMPC_reduction:
15099 case OMPC_task_reduction:
15100 case OMPC_in_reduction:
15101 case OMPC_linear:
15102 case OMPC_aligned:
15103 case OMPC_copyin:
15104 case OMPC_copyprivate:
15105 case OMPC_nowait:
15106 case OMPC_untied:
15107 case OMPC_mergeable:
15108 case OMPC_threadprivate:
15109 case OMPC_sizes:
15110 case OMPC_allocate:
15111 case OMPC_flush:
15112 case OMPC_read:
15113 case OMPC_write:
15114 case OMPC_update:
15115 case OMPC_capture:
15116 case OMPC_compare:
15117 case OMPC_seq_cst:
15118 case OMPC_acq_rel:
15119 case OMPC_acquire:
15120 case OMPC_release:
15121 case OMPC_relaxed:
15122 case OMPC_depend:
15123 case OMPC_threads:
15124 case OMPC_simd:
15125 case OMPC_map:
15126 case OMPC_nogroup:
15127 case OMPC_dist_schedule:
15128 case OMPC_defaultmap:
15129 case OMPC_unknown:
15130 case OMPC_uniform:
15131 case OMPC_to:
15132 case OMPC_from:
15133 case OMPC_use_device_ptr:
15134 case OMPC_use_device_addr:
15135 case OMPC_is_device_ptr:
15136 case OMPC_unified_address:
15137 case OMPC_unified_shared_memory:
15138 case OMPC_reverse_offload:
15139 case OMPC_dynamic_allocators:
15140 case OMPC_atomic_default_mem_order:
15141 case OMPC_device_type:
15142 case OMPC_match:
15143 case OMPC_nontemporal:
15144 case OMPC_order:
15145 case OMPC_destroy:
15146 case OMPC_inclusive:
15147 case OMPC_exclusive:
15148 case OMPC_uses_allocators:
15149 case OMPC_affinity:
15150 case OMPC_when:
15151 case OMPC_bind:
15152 default:
15153 llvm_unreachable("Clause is not allowed.");
15155 return Res;
15158 // An OpenMP directive such as 'target parallel' has two captured regions:
15159 // for the 'target' and 'parallel' respectively. This function returns
15160 // the region in which to capture expressions associated with a clause.
15161 // A return value of OMPD_unknown signifies that the expression should not
15162 // be captured.
15163 static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
15164 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
15165 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
15166 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15167 switch (CKind) {
15168 case OMPC_if:
15169 switch (DKind) {
15170 case OMPD_target_parallel_for_simd:
15171 if (OpenMPVersion >= 50 &&
15172 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15173 CaptureRegion = OMPD_parallel;
15174 break;
15176 [[fallthrough]];
15177 case OMPD_target_parallel:
15178 case OMPD_target_parallel_for:
15179 case OMPD_target_parallel_loop:
15180 // If this clause applies to the nested 'parallel' region, capture within
15181 // the 'target' region, otherwise do not capture.
15182 if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel)
15183 CaptureRegion = OMPD_target;
15184 break;
15185 case OMPD_target_teams_distribute_parallel_for_simd:
15186 if (OpenMPVersion >= 50 &&
15187 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15188 CaptureRegion = OMPD_parallel;
15189 break;
15191 [[fallthrough]];
15192 case OMPD_target_teams_distribute_parallel_for:
15193 // If this clause applies to the nested 'parallel' region, capture within
15194 // the 'teams' region, otherwise do not capture.
15195 if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel)
15196 CaptureRegion = OMPD_teams;
15197 break;
15198 case OMPD_teams_distribute_parallel_for_simd:
15199 if (OpenMPVersion >= 50 &&
15200 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15201 CaptureRegion = OMPD_parallel;
15202 break;
15204 [[fallthrough]];
15205 case OMPD_teams_distribute_parallel_for:
15206 CaptureRegion = OMPD_teams;
15207 break;
15208 case OMPD_target_update:
15209 case OMPD_target_enter_data:
15210 case OMPD_target_exit_data:
15211 CaptureRegion = OMPD_task;
15212 break;
15213 case OMPD_parallel_masked_taskloop:
15214 if (NameModifier == OMPD_unknown || NameModifier == OMPD_taskloop)
15215 CaptureRegion = OMPD_parallel;
15216 break;
15217 case OMPD_parallel_master_taskloop:
15218 if (NameModifier == OMPD_unknown || NameModifier == OMPD_taskloop)
15219 CaptureRegion = OMPD_parallel;
15220 break;
15221 case OMPD_parallel_masked_taskloop_simd:
15222 if ((OpenMPVersion <= 45 && NameModifier == OMPD_unknown) ||
15223 NameModifier == OMPD_taskloop) {
15224 CaptureRegion = OMPD_parallel;
15225 break;
15227 if (OpenMPVersion <= 45)
15228 break;
15229 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15230 CaptureRegion = OMPD_taskloop;
15231 break;
15232 case OMPD_parallel_master_taskloop_simd:
15233 if ((OpenMPVersion <= 45 && NameModifier == OMPD_unknown) ||
15234 NameModifier == OMPD_taskloop) {
15235 CaptureRegion = OMPD_parallel;
15236 break;
15238 if (OpenMPVersion <= 45)
15239 break;
15240 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15241 CaptureRegion = OMPD_taskloop;
15242 break;
15243 case OMPD_parallel_for_simd:
15244 if (OpenMPVersion <= 45)
15245 break;
15246 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15247 CaptureRegion = OMPD_parallel;
15248 break;
15249 case OMPD_taskloop_simd:
15250 case OMPD_master_taskloop_simd:
15251 case OMPD_masked_taskloop_simd:
15252 if (OpenMPVersion <= 45)
15253 break;
15254 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15255 CaptureRegion = OMPD_taskloop;
15256 break;
15257 case OMPD_distribute_parallel_for_simd:
15258 if (OpenMPVersion <= 45)
15259 break;
15260 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15261 CaptureRegion = OMPD_parallel;
15262 break;
15263 case OMPD_target_simd:
15264 if (OpenMPVersion >= 50 &&
15265 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd))
15266 CaptureRegion = OMPD_target;
15267 break;
15268 case OMPD_teams_distribute_simd:
15269 case OMPD_target_teams_distribute_simd:
15270 if (OpenMPVersion >= 50 &&
15271 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd))
15272 CaptureRegion = OMPD_teams;
15273 break;
15274 case OMPD_cancel:
15275 case OMPD_parallel:
15276 case OMPD_parallel_master:
15277 case OMPD_parallel_masked:
15278 case OMPD_parallel_sections:
15279 case OMPD_parallel_for:
15280 case OMPD_parallel_loop:
15281 case OMPD_target:
15282 case OMPD_target_teams:
15283 case OMPD_target_teams_distribute:
15284 case OMPD_target_teams_loop:
15285 case OMPD_distribute_parallel_for:
15286 case OMPD_task:
15287 case OMPD_taskloop:
15288 case OMPD_master_taskloop:
15289 case OMPD_masked_taskloop:
15290 case OMPD_target_data:
15291 case OMPD_simd:
15292 case OMPD_for_simd:
15293 case OMPD_distribute_simd:
15294 // Do not capture if-clause expressions.
15295 break;
15296 case OMPD_threadprivate:
15297 case OMPD_allocate:
15298 case OMPD_taskyield:
15299 case OMPD_barrier:
15300 case OMPD_taskwait:
15301 case OMPD_cancellation_point:
15302 case OMPD_flush:
15303 case OMPD_depobj:
15304 case OMPD_scan:
15305 case OMPD_declare_reduction:
15306 case OMPD_declare_mapper:
15307 case OMPD_declare_simd:
15308 case OMPD_declare_variant:
15309 case OMPD_begin_declare_variant:
15310 case OMPD_end_declare_variant:
15311 case OMPD_declare_target:
15312 case OMPD_end_declare_target:
15313 case OMPD_loop:
15314 case OMPD_teams_loop:
15315 case OMPD_teams:
15316 case OMPD_tile:
15317 case OMPD_unroll:
15318 case OMPD_for:
15319 case OMPD_sections:
15320 case OMPD_section:
15321 case OMPD_single:
15322 case OMPD_master:
15323 case OMPD_masked:
15324 case OMPD_critical:
15325 case OMPD_taskgroup:
15326 case OMPD_distribute:
15327 case OMPD_ordered:
15328 case OMPD_atomic:
15329 case OMPD_teams_distribute:
15330 case OMPD_requires:
15331 case OMPD_metadirective:
15332 llvm_unreachable("Unexpected OpenMP directive with if-clause");
15333 case OMPD_unknown:
15334 default:
15335 llvm_unreachable("Unknown OpenMP directive");
15337 break;
15338 case OMPC_num_threads:
15339 switch (DKind) {
15340 case OMPD_target_parallel:
15341 case OMPD_target_parallel_for:
15342 case OMPD_target_parallel_for_simd:
15343 case OMPD_target_parallel_loop:
15344 CaptureRegion = OMPD_target;
15345 break;
15346 case OMPD_teams_distribute_parallel_for:
15347 case OMPD_teams_distribute_parallel_for_simd:
15348 case OMPD_target_teams_distribute_parallel_for:
15349 case OMPD_target_teams_distribute_parallel_for_simd:
15350 CaptureRegion = OMPD_teams;
15351 break;
15352 case OMPD_parallel:
15353 case OMPD_parallel_master:
15354 case OMPD_parallel_masked:
15355 case OMPD_parallel_sections:
15356 case OMPD_parallel_for:
15357 case OMPD_parallel_for_simd:
15358 case OMPD_parallel_loop:
15359 case OMPD_distribute_parallel_for:
15360 case OMPD_distribute_parallel_for_simd:
15361 case OMPD_parallel_master_taskloop:
15362 case OMPD_parallel_masked_taskloop:
15363 case OMPD_parallel_master_taskloop_simd:
15364 case OMPD_parallel_masked_taskloop_simd:
15365 // Do not capture num_threads-clause expressions.
15366 break;
15367 case OMPD_target_data:
15368 case OMPD_target_enter_data:
15369 case OMPD_target_exit_data:
15370 case OMPD_target_update:
15371 case OMPD_target:
15372 case OMPD_target_simd:
15373 case OMPD_target_teams:
15374 case OMPD_target_teams_distribute:
15375 case OMPD_target_teams_distribute_simd:
15376 case OMPD_cancel:
15377 case OMPD_task:
15378 case OMPD_taskloop:
15379 case OMPD_taskloop_simd:
15380 case OMPD_master_taskloop:
15381 case OMPD_masked_taskloop:
15382 case OMPD_master_taskloop_simd:
15383 case OMPD_masked_taskloop_simd:
15384 case OMPD_threadprivate:
15385 case OMPD_allocate:
15386 case OMPD_taskyield:
15387 case OMPD_barrier:
15388 case OMPD_taskwait:
15389 case OMPD_cancellation_point:
15390 case OMPD_flush:
15391 case OMPD_depobj:
15392 case OMPD_scan:
15393 case OMPD_declare_reduction:
15394 case OMPD_declare_mapper:
15395 case OMPD_declare_simd:
15396 case OMPD_declare_variant:
15397 case OMPD_begin_declare_variant:
15398 case OMPD_end_declare_variant:
15399 case OMPD_declare_target:
15400 case OMPD_end_declare_target:
15401 case OMPD_loop:
15402 case OMPD_teams_loop:
15403 case OMPD_target_teams_loop:
15404 case OMPD_teams:
15405 case OMPD_simd:
15406 case OMPD_tile:
15407 case OMPD_unroll:
15408 case OMPD_for:
15409 case OMPD_for_simd:
15410 case OMPD_sections:
15411 case OMPD_section:
15412 case OMPD_single:
15413 case OMPD_master:
15414 case OMPD_masked:
15415 case OMPD_critical:
15416 case OMPD_taskgroup:
15417 case OMPD_distribute:
15418 case OMPD_ordered:
15419 case OMPD_atomic:
15420 case OMPD_distribute_simd:
15421 case OMPD_teams_distribute:
15422 case OMPD_teams_distribute_simd:
15423 case OMPD_requires:
15424 case OMPD_metadirective:
15425 llvm_unreachable("Unexpected OpenMP directive with num_threads-clause");
15426 case OMPD_unknown:
15427 default:
15428 llvm_unreachable("Unknown OpenMP directive");
15430 break;
15431 case OMPC_num_teams:
15432 switch (DKind) {
15433 case OMPD_target_teams:
15434 case OMPD_target_teams_distribute:
15435 case OMPD_target_teams_distribute_simd:
15436 case OMPD_target_teams_distribute_parallel_for:
15437 case OMPD_target_teams_distribute_parallel_for_simd:
15438 case OMPD_target_teams_loop:
15439 CaptureRegion = OMPD_target;
15440 break;
15441 case OMPD_teams_distribute_parallel_for:
15442 case OMPD_teams_distribute_parallel_for_simd:
15443 case OMPD_teams:
15444 case OMPD_teams_distribute:
15445 case OMPD_teams_distribute_simd:
15446 case OMPD_teams_loop:
15447 // Do not capture num_teams-clause expressions.
15448 break;
15449 case OMPD_distribute_parallel_for:
15450 case OMPD_distribute_parallel_for_simd:
15451 case OMPD_task:
15452 case OMPD_taskloop:
15453 case OMPD_taskloop_simd:
15454 case OMPD_master_taskloop:
15455 case OMPD_masked_taskloop:
15456 case OMPD_master_taskloop_simd:
15457 case OMPD_masked_taskloop_simd:
15458 case OMPD_parallel_master_taskloop:
15459 case OMPD_parallel_masked_taskloop:
15460 case OMPD_parallel_master_taskloop_simd:
15461 case OMPD_parallel_masked_taskloop_simd:
15462 case OMPD_target_data:
15463 case OMPD_target_enter_data:
15464 case OMPD_target_exit_data:
15465 case OMPD_target_update:
15466 case OMPD_cancel:
15467 case OMPD_parallel:
15468 case OMPD_parallel_master:
15469 case OMPD_parallel_masked:
15470 case OMPD_parallel_sections:
15471 case OMPD_parallel_for:
15472 case OMPD_parallel_for_simd:
15473 case OMPD_parallel_loop:
15474 case OMPD_target:
15475 case OMPD_target_simd:
15476 case OMPD_target_parallel:
15477 case OMPD_target_parallel_for:
15478 case OMPD_target_parallel_for_simd:
15479 case OMPD_target_parallel_loop:
15480 case OMPD_threadprivate:
15481 case OMPD_allocate:
15482 case OMPD_taskyield:
15483 case OMPD_barrier:
15484 case OMPD_taskwait:
15485 case OMPD_cancellation_point:
15486 case OMPD_flush:
15487 case OMPD_depobj:
15488 case OMPD_scan:
15489 case OMPD_declare_reduction:
15490 case OMPD_declare_mapper:
15491 case OMPD_declare_simd:
15492 case OMPD_declare_variant:
15493 case OMPD_begin_declare_variant:
15494 case OMPD_end_declare_variant:
15495 case OMPD_declare_target:
15496 case OMPD_end_declare_target:
15497 case OMPD_loop:
15498 case OMPD_simd:
15499 case OMPD_tile:
15500 case OMPD_unroll:
15501 case OMPD_for:
15502 case OMPD_for_simd:
15503 case OMPD_sections:
15504 case OMPD_section:
15505 case OMPD_single:
15506 case OMPD_master:
15507 case OMPD_masked:
15508 case OMPD_critical:
15509 case OMPD_taskgroup:
15510 case OMPD_distribute:
15511 case OMPD_ordered:
15512 case OMPD_atomic:
15513 case OMPD_distribute_simd:
15514 case OMPD_requires:
15515 case OMPD_metadirective:
15516 llvm_unreachable("Unexpected OpenMP directive with num_teams-clause");
15517 case OMPD_unknown:
15518 default:
15519 llvm_unreachable("Unknown OpenMP directive");
15521 break;
15522 case OMPC_thread_limit:
15523 switch (DKind) {
15524 case OMPD_target_teams:
15525 case OMPD_target_teams_distribute:
15526 case OMPD_target_teams_distribute_simd:
15527 case OMPD_target_teams_distribute_parallel_for:
15528 case OMPD_target_teams_distribute_parallel_for_simd:
15529 case OMPD_target_teams_loop:
15530 CaptureRegion = OMPD_target;
15531 break;
15532 case OMPD_teams_distribute_parallel_for:
15533 case OMPD_teams_distribute_parallel_for_simd:
15534 case OMPD_teams:
15535 case OMPD_teams_distribute:
15536 case OMPD_teams_distribute_simd:
15537 case OMPD_teams_loop:
15538 // Do not capture thread_limit-clause expressions.
15539 break;
15540 case OMPD_distribute_parallel_for:
15541 case OMPD_distribute_parallel_for_simd:
15542 case OMPD_task:
15543 case OMPD_taskloop:
15544 case OMPD_taskloop_simd:
15545 case OMPD_master_taskloop:
15546 case OMPD_masked_taskloop:
15547 case OMPD_master_taskloop_simd:
15548 case OMPD_masked_taskloop_simd:
15549 case OMPD_parallel_master_taskloop:
15550 case OMPD_parallel_masked_taskloop:
15551 case OMPD_parallel_master_taskloop_simd:
15552 case OMPD_parallel_masked_taskloop_simd:
15553 case OMPD_target_data:
15554 case OMPD_target_enter_data:
15555 case OMPD_target_exit_data:
15556 case OMPD_target_update:
15557 case OMPD_cancel:
15558 case OMPD_parallel:
15559 case OMPD_parallel_master:
15560 case OMPD_parallel_masked:
15561 case OMPD_parallel_sections:
15562 case OMPD_parallel_for:
15563 case OMPD_parallel_for_simd:
15564 case OMPD_parallel_loop:
15565 case OMPD_target:
15566 case OMPD_target_simd:
15567 case OMPD_target_parallel:
15568 case OMPD_target_parallel_for:
15569 case OMPD_target_parallel_for_simd:
15570 case OMPD_target_parallel_loop:
15571 case OMPD_threadprivate:
15572 case OMPD_allocate:
15573 case OMPD_taskyield:
15574 case OMPD_barrier:
15575 case OMPD_taskwait:
15576 case OMPD_cancellation_point:
15577 case OMPD_flush:
15578 case OMPD_depobj:
15579 case OMPD_scan:
15580 case OMPD_declare_reduction:
15581 case OMPD_declare_mapper:
15582 case OMPD_declare_simd:
15583 case OMPD_declare_variant:
15584 case OMPD_begin_declare_variant:
15585 case OMPD_end_declare_variant:
15586 case OMPD_declare_target:
15587 case OMPD_end_declare_target:
15588 case OMPD_loop:
15589 case OMPD_simd:
15590 case OMPD_tile:
15591 case OMPD_unroll:
15592 case OMPD_for:
15593 case OMPD_for_simd:
15594 case OMPD_sections:
15595 case OMPD_section:
15596 case OMPD_single:
15597 case OMPD_master:
15598 case OMPD_masked:
15599 case OMPD_critical:
15600 case OMPD_taskgroup:
15601 case OMPD_distribute:
15602 case OMPD_ordered:
15603 case OMPD_atomic:
15604 case OMPD_distribute_simd:
15605 case OMPD_requires:
15606 case OMPD_metadirective:
15607 llvm_unreachable("Unexpected OpenMP directive with thread_limit-clause");
15608 case OMPD_unknown:
15609 default:
15610 llvm_unreachable("Unknown OpenMP directive");
15612 break;
15613 case OMPC_schedule:
15614 switch (DKind) {
15615 case OMPD_parallel_for:
15616 case OMPD_parallel_for_simd:
15617 case OMPD_distribute_parallel_for:
15618 case OMPD_distribute_parallel_for_simd:
15619 case OMPD_teams_distribute_parallel_for:
15620 case OMPD_teams_distribute_parallel_for_simd:
15621 case OMPD_target_parallel_for:
15622 case OMPD_target_parallel_for_simd:
15623 case OMPD_target_teams_distribute_parallel_for:
15624 case OMPD_target_teams_distribute_parallel_for_simd:
15625 CaptureRegion = OMPD_parallel;
15626 break;
15627 case OMPD_for:
15628 case OMPD_for_simd:
15629 // Do not capture schedule-clause expressions.
15630 break;
15631 case OMPD_task:
15632 case OMPD_taskloop:
15633 case OMPD_taskloop_simd:
15634 case OMPD_master_taskloop:
15635 case OMPD_masked_taskloop:
15636 case OMPD_master_taskloop_simd:
15637 case OMPD_masked_taskloop_simd:
15638 case OMPD_parallel_master_taskloop:
15639 case OMPD_parallel_masked_taskloop:
15640 case OMPD_parallel_master_taskloop_simd:
15641 case OMPD_parallel_masked_taskloop_simd:
15642 case OMPD_target_data:
15643 case OMPD_target_enter_data:
15644 case OMPD_target_exit_data:
15645 case OMPD_target_update:
15646 case OMPD_teams:
15647 case OMPD_teams_distribute:
15648 case OMPD_teams_distribute_simd:
15649 case OMPD_target_teams_distribute:
15650 case OMPD_target_teams_distribute_simd:
15651 case OMPD_target:
15652 case OMPD_target_simd:
15653 case OMPD_target_parallel:
15654 case OMPD_cancel:
15655 case OMPD_parallel:
15656 case OMPD_parallel_master:
15657 case OMPD_parallel_masked:
15658 case OMPD_parallel_sections:
15659 case OMPD_threadprivate:
15660 case OMPD_allocate:
15661 case OMPD_taskyield:
15662 case OMPD_barrier:
15663 case OMPD_taskwait:
15664 case OMPD_cancellation_point:
15665 case OMPD_flush:
15666 case OMPD_depobj:
15667 case OMPD_scan:
15668 case OMPD_declare_reduction:
15669 case OMPD_declare_mapper:
15670 case OMPD_declare_simd:
15671 case OMPD_declare_variant:
15672 case OMPD_begin_declare_variant:
15673 case OMPD_end_declare_variant:
15674 case OMPD_declare_target:
15675 case OMPD_end_declare_target:
15676 case OMPD_loop:
15677 case OMPD_teams_loop:
15678 case OMPD_target_teams_loop:
15679 case OMPD_parallel_loop:
15680 case OMPD_target_parallel_loop:
15681 case OMPD_simd:
15682 case OMPD_tile:
15683 case OMPD_unroll:
15684 case OMPD_sections:
15685 case OMPD_section:
15686 case OMPD_single:
15687 case OMPD_master:
15688 case OMPD_masked:
15689 case OMPD_critical:
15690 case OMPD_taskgroup:
15691 case OMPD_distribute:
15692 case OMPD_ordered:
15693 case OMPD_atomic:
15694 case OMPD_distribute_simd:
15695 case OMPD_target_teams:
15696 case OMPD_requires:
15697 case OMPD_metadirective:
15698 llvm_unreachable("Unexpected OpenMP directive with schedule clause");
15699 case OMPD_unknown:
15700 default:
15701 llvm_unreachable("Unknown OpenMP directive");
15703 break;
15704 case OMPC_dist_schedule:
15705 switch (DKind) {
15706 case OMPD_teams_distribute_parallel_for:
15707 case OMPD_teams_distribute_parallel_for_simd:
15708 case OMPD_teams_distribute:
15709 case OMPD_teams_distribute_simd:
15710 case OMPD_target_teams_distribute_parallel_for:
15711 case OMPD_target_teams_distribute_parallel_for_simd:
15712 case OMPD_target_teams_distribute:
15713 case OMPD_target_teams_distribute_simd:
15714 CaptureRegion = OMPD_teams;
15715 break;
15716 case OMPD_distribute_parallel_for:
15717 case OMPD_distribute_parallel_for_simd:
15718 case OMPD_distribute:
15719 case OMPD_distribute_simd:
15720 // Do not capture dist_schedule-clause expressions.
15721 break;
15722 case OMPD_parallel_for:
15723 case OMPD_parallel_for_simd:
15724 case OMPD_target_parallel_for_simd:
15725 case OMPD_target_parallel_for:
15726 case OMPD_task:
15727 case OMPD_taskloop:
15728 case OMPD_taskloop_simd:
15729 case OMPD_master_taskloop:
15730 case OMPD_masked_taskloop:
15731 case OMPD_master_taskloop_simd:
15732 case OMPD_masked_taskloop_simd:
15733 case OMPD_parallel_master_taskloop:
15734 case OMPD_parallel_masked_taskloop:
15735 case OMPD_parallel_master_taskloop_simd:
15736 case OMPD_parallel_masked_taskloop_simd:
15737 case OMPD_target_data:
15738 case OMPD_target_enter_data:
15739 case OMPD_target_exit_data:
15740 case OMPD_target_update:
15741 case OMPD_teams:
15742 case OMPD_target:
15743 case OMPD_target_simd:
15744 case OMPD_target_parallel:
15745 case OMPD_cancel:
15746 case OMPD_parallel:
15747 case OMPD_parallel_master:
15748 case OMPD_parallel_masked:
15749 case OMPD_parallel_sections:
15750 case OMPD_threadprivate:
15751 case OMPD_allocate:
15752 case OMPD_taskyield:
15753 case OMPD_barrier:
15754 case OMPD_taskwait:
15755 case OMPD_cancellation_point:
15756 case OMPD_flush:
15757 case OMPD_depobj:
15758 case OMPD_scan:
15759 case OMPD_declare_reduction:
15760 case OMPD_declare_mapper:
15761 case OMPD_declare_simd:
15762 case OMPD_declare_variant:
15763 case OMPD_begin_declare_variant:
15764 case OMPD_end_declare_variant:
15765 case OMPD_declare_target:
15766 case OMPD_end_declare_target:
15767 case OMPD_loop:
15768 case OMPD_teams_loop:
15769 case OMPD_target_teams_loop:
15770 case OMPD_parallel_loop:
15771 case OMPD_target_parallel_loop:
15772 case OMPD_simd:
15773 case OMPD_tile:
15774 case OMPD_unroll:
15775 case OMPD_for:
15776 case OMPD_for_simd:
15777 case OMPD_sections:
15778 case OMPD_section:
15779 case OMPD_single:
15780 case OMPD_master:
15781 case OMPD_masked:
15782 case OMPD_critical:
15783 case OMPD_taskgroup:
15784 case OMPD_ordered:
15785 case OMPD_atomic:
15786 case OMPD_target_teams:
15787 case OMPD_requires:
15788 case OMPD_metadirective:
15789 llvm_unreachable("Unexpected OpenMP directive with dist_schedule clause");
15790 case OMPD_unknown:
15791 default:
15792 llvm_unreachable("Unknown OpenMP directive");
15794 break;
15795 case OMPC_device:
15796 switch (DKind) {
15797 case OMPD_target_update:
15798 case OMPD_target_enter_data:
15799 case OMPD_target_exit_data:
15800 case OMPD_target:
15801 case OMPD_target_simd:
15802 case OMPD_target_teams:
15803 case OMPD_target_parallel:
15804 case OMPD_target_teams_distribute:
15805 case OMPD_target_teams_distribute_simd:
15806 case OMPD_target_parallel_for:
15807 case OMPD_target_parallel_for_simd:
15808 case OMPD_target_parallel_loop:
15809 case OMPD_target_teams_distribute_parallel_for:
15810 case OMPD_target_teams_distribute_parallel_for_simd:
15811 case OMPD_target_teams_loop:
15812 case OMPD_dispatch:
15813 CaptureRegion = OMPD_task;
15814 break;
15815 case OMPD_target_data:
15816 case OMPD_interop:
15817 // Do not capture device-clause expressions.
15818 break;
15819 case OMPD_teams_distribute_parallel_for:
15820 case OMPD_teams_distribute_parallel_for_simd:
15821 case OMPD_teams:
15822 case OMPD_teams_distribute:
15823 case OMPD_teams_distribute_simd:
15824 case OMPD_distribute_parallel_for:
15825 case OMPD_distribute_parallel_for_simd:
15826 case OMPD_task:
15827 case OMPD_taskloop:
15828 case OMPD_taskloop_simd:
15829 case OMPD_master_taskloop:
15830 case OMPD_masked_taskloop:
15831 case OMPD_master_taskloop_simd:
15832 case OMPD_masked_taskloop_simd:
15833 case OMPD_parallel_master_taskloop:
15834 case OMPD_parallel_masked_taskloop:
15835 case OMPD_parallel_master_taskloop_simd:
15836 case OMPD_parallel_masked_taskloop_simd:
15837 case OMPD_cancel:
15838 case OMPD_parallel:
15839 case OMPD_parallel_master:
15840 case OMPD_parallel_masked:
15841 case OMPD_parallel_sections:
15842 case OMPD_parallel_for:
15843 case OMPD_parallel_for_simd:
15844 case OMPD_threadprivate:
15845 case OMPD_allocate:
15846 case OMPD_taskyield:
15847 case OMPD_barrier:
15848 case OMPD_taskwait:
15849 case OMPD_cancellation_point:
15850 case OMPD_flush:
15851 case OMPD_depobj:
15852 case OMPD_scan:
15853 case OMPD_declare_reduction:
15854 case OMPD_declare_mapper:
15855 case OMPD_declare_simd:
15856 case OMPD_declare_variant:
15857 case OMPD_begin_declare_variant:
15858 case OMPD_end_declare_variant:
15859 case OMPD_declare_target:
15860 case OMPD_end_declare_target:
15861 case OMPD_loop:
15862 case OMPD_teams_loop:
15863 case OMPD_parallel_loop:
15864 case OMPD_simd:
15865 case OMPD_tile:
15866 case OMPD_unroll:
15867 case OMPD_for:
15868 case OMPD_for_simd:
15869 case OMPD_sections:
15870 case OMPD_section:
15871 case OMPD_single:
15872 case OMPD_master:
15873 case OMPD_masked:
15874 case OMPD_critical:
15875 case OMPD_taskgroup:
15876 case OMPD_distribute:
15877 case OMPD_ordered:
15878 case OMPD_atomic:
15879 case OMPD_distribute_simd:
15880 case OMPD_requires:
15881 case OMPD_metadirective:
15882 llvm_unreachable("Unexpected OpenMP directive with device-clause");
15883 case OMPD_unknown:
15884 default:
15885 llvm_unreachable("Unknown OpenMP directive");
15887 break;
15888 case OMPC_grainsize:
15889 case OMPC_num_tasks:
15890 case OMPC_final:
15891 case OMPC_priority:
15892 switch (DKind) {
15893 case OMPD_task:
15894 case OMPD_taskloop:
15895 case OMPD_taskloop_simd:
15896 case OMPD_master_taskloop:
15897 case OMPD_masked_taskloop:
15898 case OMPD_master_taskloop_simd:
15899 case OMPD_masked_taskloop_simd:
15900 break;
15901 case OMPD_parallel_masked_taskloop:
15902 case OMPD_parallel_masked_taskloop_simd:
15903 case OMPD_parallel_master_taskloop:
15904 case OMPD_parallel_master_taskloop_simd:
15905 CaptureRegion = OMPD_parallel;
15906 break;
15907 case OMPD_target_update:
15908 case OMPD_target_enter_data:
15909 case OMPD_target_exit_data:
15910 case OMPD_target:
15911 case OMPD_target_simd:
15912 case OMPD_target_teams:
15913 case OMPD_target_parallel:
15914 case OMPD_target_teams_distribute:
15915 case OMPD_target_teams_distribute_simd:
15916 case OMPD_target_parallel_for:
15917 case OMPD_target_parallel_for_simd:
15918 case OMPD_target_teams_distribute_parallel_for:
15919 case OMPD_target_teams_distribute_parallel_for_simd:
15920 case OMPD_target_data:
15921 case OMPD_teams_distribute_parallel_for:
15922 case OMPD_teams_distribute_parallel_for_simd:
15923 case OMPD_teams:
15924 case OMPD_teams_distribute:
15925 case OMPD_teams_distribute_simd:
15926 case OMPD_distribute_parallel_for:
15927 case OMPD_distribute_parallel_for_simd:
15928 case OMPD_cancel:
15929 case OMPD_parallel:
15930 case OMPD_parallel_master:
15931 case OMPD_parallel_masked:
15932 case OMPD_parallel_sections:
15933 case OMPD_parallel_for:
15934 case OMPD_parallel_for_simd:
15935 case OMPD_threadprivate:
15936 case OMPD_allocate:
15937 case OMPD_taskyield:
15938 case OMPD_barrier:
15939 case OMPD_taskwait:
15940 case OMPD_cancellation_point:
15941 case OMPD_flush:
15942 case OMPD_depobj:
15943 case OMPD_scan:
15944 case OMPD_declare_reduction:
15945 case OMPD_declare_mapper:
15946 case OMPD_declare_simd:
15947 case OMPD_declare_variant:
15948 case OMPD_begin_declare_variant:
15949 case OMPD_end_declare_variant:
15950 case OMPD_declare_target:
15951 case OMPD_end_declare_target:
15952 case OMPD_loop:
15953 case OMPD_teams_loop:
15954 case OMPD_target_teams_loop:
15955 case OMPD_parallel_loop:
15956 case OMPD_target_parallel_loop:
15957 case OMPD_simd:
15958 case OMPD_tile:
15959 case OMPD_unroll:
15960 case OMPD_for:
15961 case OMPD_for_simd:
15962 case OMPD_sections:
15963 case OMPD_section:
15964 case OMPD_single:
15965 case OMPD_master:
15966 case OMPD_masked:
15967 case OMPD_critical:
15968 case OMPD_taskgroup:
15969 case OMPD_distribute:
15970 case OMPD_ordered:
15971 case OMPD_atomic:
15972 case OMPD_distribute_simd:
15973 case OMPD_requires:
15974 case OMPD_metadirective:
15975 llvm_unreachable("Unexpected OpenMP directive with grainsize-clause");
15976 case OMPD_unknown:
15977 default:
15978 llvm_unreachable("Unknown OpenMP directive");
15980 break;
15981 case OMPC_novariants:
15982 case OMPC_nocontext:
15983 switch (DKind) {
15984 case OMPD_dispatch:
15985 CaptureRegion = OMPD_task;
15986 break;
15987 default:
15988 llvm_unreachable("Unexpected OpenMP directive");
15990 break;
15991 case OMPC_filter:
15992 // Do not capture filter-clause expressions.
15993 break;
15994 case OMPC_when:
15995 if (DKind == OMPD_metadirective) {
15996 CaptureRegion = OMPD_metadirective;
15997 } else if (DKind == OMPD_unknown) {
15998 llvm_unreachable("Unknown OpenMP directive");
15999 } else {
16000 llvm_unreachable("Unexpected OpenMP directive with when clause");
16002 break;
16003 case OMPC_firstprivate:
16004 case OMPC_lastprivate:
16005 case OMPC_reduction:
16006 case OMPC_task_reduction:
16007 case OMPC_in_reduction:
16008 case OMPC_linear:
16009 case OMPC_default:
16010 case OMPC_proc_bind:
16011 case OMPC_safelen:
16012 case OMPC_simdlen:
16013 case OMPC_sizes:
16014 case OMPC_allocator:
16015 case OMPC_collapse:
16016 case OMPC_private:
16017 case OMPC_shared:
16018 case OMPC_aligned:
16019 case OMPC_copyin:
16020 case OMPC_copyprivate:
16021 case OMPC_ordered:
16022 case OMPC_nowait:
16023 case OMPC_untied:
16024 case OMPC_mergeable:
16025 case OMPC_threadprivate:
16026 case OMPC_allocate:
16027 case OMPC_flush:
16028 case OMPC_depobj:
16029 case OMPC_read:
16030 case OMPC_write:
16031 case OMPC_update:
16032 case OMPC_capture:
16033 case OMPC_compare:
16034 case OMPC_seq_cst:
16035 case OMPC_acq_rel:
16036 case OMPC_acquire:
16037 case OMPC_release:
16038 case OMPC_relaxed:
16039 case OMPC_depend:
16040 case OMPC_threads:
16041 case OMPC_simd:
16042 case OMPC_map:
16043 case OMPC_nogroup:
16044 case OMPC_hint:
16045 case OMPC_defaultmap:
16046 case OMPC_unknown:
16047 case OMPC_uniform:
16048 case OMPC_to:
16049 case OMPC_from:
16050 case OMPC_use_device_ptr:
16051 case OMPC_use_device_addr:
16052 case OMPC_is_device_ptr:
16053 case OMPC_unified_address:
16054 case OMPC_unified_shared_memory:
16055 case OMPC_reverse_offload:
16056 case OMPC_dynamic_allocators:
16057 case OMPC_atomic_default_mem_order:
16058 case OMPC_device_type:
16059 case OMPC_match:
16060 case OMPC_nontemporal:
16061 case OMPC_order:
16062 case OMPC_destroy:
16063 case OMPC_detach:
16064 case OMPC_inclusive:
16065 case OMPC_exclusive:
16066 case OMPC_uses_allocators:
16067 case OMPC_affinity:
16068 case OMPC_bind:
16069 default:
16070 llvm_unreachable("Unexpected OpenMP clause.");
16072 return CaptureRegion;
16075 OMPClause *Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier,
16076 Expr *Condition, SourceLocation StartLoc,
16077 SourceLocation LParenLoc,
16078 SourceLocation NameModifierLoc,
16079 SourceLocation ColonLoc,
16080 SourceLocation EndLoc) {
16081 Expr *ValExpr = Condition;
16082 Stmt *HelperValStmt = nullptr;
16083 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16084 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16085 !Condition->isInstantiationDependent() &&
16086 !Condition->containsUnexpandedParameterPack()) {
16087 ExprResult Val = CheckBooleanCondition(StartLoc, Condition);
16088 if (Val.isInvalid())
16089 return nullptr;
16091 ValExpr = Val.get();
16093 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16094 CaptureRegion = getOpenMPCaptureRegionForClause(
16095 DKind, OMPC_if, LangOpts.OpenMP, NameModifier);
16096 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
16097 ValExpr = MakeFullExpr(ValExpr).get();
16098 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16099 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
16100 HelperValStmt = buildPreInits(Context, Captures);
16104 return new (Context)
16105 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
16106 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
16109 OMPClause *Sema::ActOnOpenMPFinalClause(Expr *Condition,
16110 SourceLocation StartLoc,
16111 SourceLocation LParenLoc,
16112 SourceLocation EndLoc) {
16113 Expr *ValExpr = Condition;
16114 Stmt *HelperValStmt = nullptr;
16115 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16116 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16117 !Condition->isInstantiationDependent() &&
16118 !Condition->containsUnexpandedParameterPack()) {
16119 ExprResult Val = CheckBooleanCondition(StartLoc, Condition);
16120 if (Val.isInvalid())
16121 return nullptr;
16123 ValExpr = MakeFullExpr(Val.get()).get();
16125 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16126 CaptureRegion =
16127 getOpenMPCaptureRegionForClause(DKind, OMPC_final, LangOpts.OpenMP);
16128 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
16129 ValExpr = MakeFullExpr(ValExpr).get();
16130 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16131 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
16132 HelperValStmt = buildPreInits(Context, Captures);
16136 return new (Context) OMPFinalClause(ValExpr, HelperValStmt, CaptureRegion,
16137 StartLoc, LParenLoc, EndLoc);
16140 ExprResult Sema::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc,
16141 Expr *Op) {
16142 if (!Op)
16143 return ExprError();
16145 class IntConvertDiagnoser : public ICEConvertDiagnoser {
16146 public:
16147 IntConvertDiagnoser()
16148 : ICEConvertDiagnoser(/*AllowScopedEnumerations*/ false, false, true) {}
16149 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
16150 QualType T) override {
16151 return S.Diag(Loc, diag::err_omp_not_integral) << T;
16153 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
16154 QualType T) override {
16155 return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
16157 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
16158 QualType T,
16159 QualType ConvTy) override {
16160 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
16162 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
16163 QualType ConvTy) override {
16164 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16165 << ConvTy->isEnumeralType() << ConvTy;
16167 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
16168 QualType T) override {
16169 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
16171 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
16172 QualType ConvTy) override {
16173 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16174 << ConvTy->isEnumeralType() << ConvTy;
16176 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
16177 QualType) override {
16178 llvm_unreachable("conversion functions are permitted");
16180 } ConvertDiagnoser;
16181 return PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
16184 static bool
16185 isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind,
16186 bool StrictlyPositive, bool BuildCapture = false,
16187 OpenMPDirectiveKind DKind = OMPD_unknown,
16188 OpenMPDirectiveKind *CaptureRegion = nullptr,
16189 Stmt **HelperValStmt = nullptr) {
16190 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
16191 !ValExpr->isInstantiationDependent()) {
16192 SourceLocation Loc = ValExpr->getExprLoc();
16193 ExprResult Value =
16194 SemaRef.PerformOpenMPImplicitIntegerConversion(Loc, ValExpr);
16195 if (Value.isInvalid())
16196 return false;
16198 ValExpr = Value.get();
16199 // The expression must evaluate to a non-negative integer value.
16200 if (Optional<llvm::APSInt> Result =
16201 ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
16202 if (Result->isSigned() &&
16203 !((!StrictlyPositive && Result->isNonNegative()) ||
16204 (StrictlyPositive && Result->isStrictlyPositive()))) {
16205 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
16206 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
16207 << ValExpr->getSourceRange();
16208 return false;
16211 if (!BuildCapture)
16212 return true;
16213 *CaptureRegion =
16214 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
16215 if (*CaptureRegion != OMPD_unknown &&
16216 !SemaRef.CurContext->isDependentContext()) {
16217 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16218 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16219 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16220 *HelperValStmt = buildPreInits(SemaRef.Context, Captures);
16223 return true;
16226 OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads,
16227 SourceLocation StartLoc,
16228 SourceLocation LParenLoc,
16229 SourceLocation EndLoc) {
16230 Expr *ValExpr = NumThreads;
16231 Stmt *HelperValStmt = nullptr;
16233 // OpenMP [2.5, Restrictions]
16234 // The num_threads expression must evaluate to a positive integer value.
16235 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_num_threads,
16236 /*StrictlyPositive=*/true))
16237 return nullptr;
16239 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16240 OpenMPDirectiveKind CaptureRegion =
16241 getOpenMPCaptureRegionForClause(DKind, OMPC_num_threads, LangOpts.OpenMP);
16242 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
16243 ValExpr = MakeFullExpr(ValExpr).get();
16244 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16245 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
16246 HelperValStmt = buildPreInits(Context, Captures);
16249 return new (Context) OMPNumThreadsClause(
16250 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16253 ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,
16254 OpenMPClauseKind CKind,
16255 bool StrictlyPositive,
16256 bool SuppressExprDiags) {
16257 if (!E)
16258 return ExprError();
16259 if (E->isValueDependent() || E->isTypeDependent() ||
16260 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
16261 return E;
16263 llvm::APSInt Result;
16264 ExprResult ICE;
16265 if (SuppressExprDiags) {
16266 // Use a custom diagnoser that suppresses 'note' diagnostics about the
16267 // expression.
16268 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
16269 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
16270 Sema::SemaDiagnosticBuilder diagnoseNotICE(Sema &S,
16271 SourceLocation Loc) override {
16272 llvm_unreachable("Diagnostic suppressed");
16274 } Diagnoser;
16275 ICE = VerifyIntegerConstantExpression(E, &Result, Diagnoser, AllowFold);
16276 } else {
16277 ICE = VerifyIntegerConstantExpression(E, &Result, /*FIXME*/ AllowFold);
16279 if (ICE.isInvalid())
16280 return ExprError();
16282 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
16283 (!StrictlyPositive && !Result.isNonNegative())) {
16284 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
16285 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
16286 << E->getSourceRange();
16287 return ExprError();
16289 if ((CKind == OMPC_aligned || CKind == OMPC_align) && !Result.isPowerOf2()) {
16290 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
16291 << E->getSourceRange();
16292 return ExprError();
16294 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
16295 DSAStack->setAssociatedLoops(Result.getExtValue());
16296 else if (CKind == OMPC_ordered)
16297 DSAStack->setAssociatedLoops(Result.getExtValue());
16298 return ICE;
16301 OMPClause *Sema::ActOnOpenMPSafelenClause(Expr *Len, SourceLocation StartLoc,
16302 SourceLocation LParenLoc,
16303 SourceLocation EndLoc) {
16304 // OpenMP [2.8.1, simd construct, Description]
16305 // The parameter of the safelen clause must be a constant
16306 // positive integer expression.
16307 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
16308 if (Safelen.isInvalid())
16309 return nullptr;
16310 return new (Context)
16311 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
16314 OMPClause *Sema::ActOnOpenMPSimdlenClause(Expr *Len, SourceLocation StartLoc,
16315 SourceLocation LParenLoc,
16316 SourceLocation EndLoc) {
16317 // OpenMP [2.8.1, simd construct, Description]
16318 // The parameter of the simdlen clause must be a constant
16319 // positive integer expression.
16320 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
16321 if (Simdlen.isInvalid())
16322 return nullptr;
16323 return new (Context)
16324 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
16327 /// Tries to find omp_allocator_handle_t type.
16328 static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc,
16329 DSAStackTy *Stack) {
16330 QualType OMPAllocatorHandleT = Stack->getOMPAllocatorHandleT();
16331 if (!OMPAllocatorHandleT.isNull())
16332 return true;
16333 // Build the predefined allocator expressions.
16334 bool ErrorFound = false;
16335 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
16336 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
16337 StringRef Allocator =
16338 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
16339 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
16340 auto *VD = dyn_cast_or_null<ValueDecl>(
16341 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
16342 if (!VD) {
16343 ErrorFound = true;
16344 break;
16346 QualType AllocatorType =
16347 VD->getType().getNonLValueExprType(S.getASTContext());
16348 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
16349 if (!Res.isUsable()) {
16350 ErrorFound = true;
16351 break;
16353 if (OMPAllocatorHandleT.isNull())
16354 OMPAllocatorHandleT = AllocatorType;
16355 if (!S.getASTContext().hasSameType(OMPAllocatorHandleT, AllocatorType)) {
16356 ErrorFound = true;
16357 break;
16359 Stack->setAllocator(AllocatorKind, Res.get());
16361 if (ErrorFound) {
16362 S.Diag(Loc, diag::err_omp_implied_type_not_found)
16363 << "omp_allocator_handle_t";
16364 return false;
16366 OMPAllocatorHandleT.addConst();
16367 Stack->setOMPAllocatorHandleT(OMPAllocatorHandleT);
16368 return true;
16371 OMPClause *Sema::ActOnOpenMPAllocatorClause(Expr *A, SourceLocation StartLoc,
16372 SourceLocation LParenLoc,
16373 SourceLocation EndLoc) {
16374 // OpenMP [2.11.3, allocate Directive, Description]
16375 // allocator is an expression of omp_allocator_handle_t type.
16376 if (!findOMPAllocatorHandleT(*this, A->getExprLoc(), DSAStack))
16377 return nullptr;
16379 ExprResult Allocator = DefaultLvalueConversion(A);
16380 if (Allocator.isInvalid())
16381 return nullptr;
16382 Allocator = PerformImplicitConversion(Allocator.get(),
16383 DSAStack->getOMPAllocatorHandleT(),
16384 Sema::AA_Initializing,
16385 /*AllowExplicit=*/true);
16386 if (Allocator.isInvalid())
16387 return nullptr;
16388 return new (Context)
16389 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
16392 OMPClause *Sema::ActOnOpenMPCollapseClause(Expr *NumForLoops,
16393 SourceLocation StartLoc,
16394 SourceLocation LParenLoc,
16395 SourceLocation EndLoc) {
16396 // OpenMP [2.7.1, loop construct, Description]
16397 // OpenMP [2.8.1, simd construct, Description]
16398 // OpenMP [2.9.6, distribute construct, Description]
16399 // The parameter of the collapse clause must be a constant
16400 // positive integer expression.
16401 ExprResult NumForLoopsResult =
16402 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
16403 if (NumForLoopsResult.isInvalid())
16404 return nullptr;
16405 return new (Context)
16406 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
16409 OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc,
16410 SourceLocation EndLoc,
16411 SourceLocation LParenLoc,
16412 Expr *NumForLoops) {
16413 // OpenMP [2.7.1, loop construct, Description]
16414 // OpenMP [2.8.1, simd construct, Description]
16415 // OpenMP [2.9.6, distribute construct, Description]
16416 // The parameter of the ordered clause must be a constant
16417 // positive integer expression if any.
16418 if (NumForLoops && LParenLoc.isValid()) {
16419 ExprResult NumForLoopsResult =
16420 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
16421 if (NumForLoopsResult.isInvalid())
16422 return nullptr;
16423 NumForLoops = NumForLoopsResult.get();
16424 } else {
16425 NumForLoops = nullptr;
16427 auto *Clause = OMPOrderedClause::Create(
16428 Context, NumForLoops, NumForLoops ? DSAStack->getAssociatedLoops() : 0,
16429 StartLoc, LParenLoc, EndLoc);
16430 DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
16431 return Clause;
16434 OMPClause *Sema::ActOnOpenMPSimpleClause(
16435 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
16436 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
16437 OMPClause *Res = nullptr;
16438 switch (Kind) {
16439 case OMPC_default:
16440 Res = ActOnOpenMPDefaultClause(static_cast<DefaultKind>(Argument),
16441 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16442 break;
16443 case OMPC_proc_bind:
16444 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
16445 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16446 break;
16447 case OMPC_atomic_default_mem_order:
16448 Res = ActOnOpenMPAtomicDefaultMemOrderClause(
16449 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
16450 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16451 break;
16452 case OMPC_order:
16453 Res = ActOnOpenMPOrderClause(static_cast<OpenMPOrderClauseKind>(Argument),
16454 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16455 break;
16456 case OMPC_update:
16457 Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument),
16458 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16459 break;
16460 case OMPC_bind:
16461 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
16462 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16463 break;
16464 case OMPC_if:
16465 case OMPC_final:
16466 case OMPC_num_threads:
16467 case OMPC_safelen:
16468 case OMPC_simdlen:
16469 case OMPC_sizes:
16470 case OMPC_allocator:
16471 case OMPC_collapse:
16472 case OMPC_schedule:
16473 case OMPC_private:
16474 case OMPC_firstprivate:
16475 case OMPC_lastprivate:
16476 case OMPC_shared:
16477 case OMPC_reduction:
16478 case OMPC_task_reduction:
16479 case OMPC_in_reduction:
16480 case OMPC_linear:
16481 case OMPC_aligned:
16482 case OMPC_copyin:
16483 case OMPC_copyprivate:
16484 case OMPC_ordered:
16485 case OMPC_nowait:
16486 case OMPC_untied:
16487 case OMPC_mergeable:
16488 case OMPC_threadprivate:
16489 case OMPC_allocate:
16490 case OMPC_flush:
16491 case OMPC_depobj:
16492 case OMPC_read:
16493 case OMPC_write:
16494 case OMPC_capture:
16495 case OMPC_compare:
16496 case OMPC_seq_cst:
16497 case OMPC_acq_rel:
16498 case OMPC_acquire:
16499 case OMPC_release:
16500 case OMPC_relaxed:
16501 case OMPC_depend:
16502 case OMPC_device:
16503 case OMPC_threads:
16504 case OMPC_simd:
16505 case OMPC_map:
16506 case OMPC_num_teams:
16507 case OMPC_thread_limit:
16508 case OMPC_priority:
16509 case OMPC_grainsize:
16510 case OMPC_nogroup:
16511 case OMPC_num_tasks:
16512 case OMPC_hint:
16513 case OMPC_dist_schedule:
16514 case OMPC_defaultmap:
16515 case OMPC_unknown:
16516 case OMPC_uniform:
16517 case OMPC_to:
16518 case OMPC_from:
16519 case OMPC_use_device_ptr:
16520 case OMPC_use_device_addr:
16521 case OMPC_is_device_ptr:
16522 case OMPC_has_device_addr:
16523 case OMPC_unified_address:
16524 case OMPC_unified_shared_memory:
16525 case OMPC_reverse_offload:
16526 case OMPC_dynamic_allocators:
16527 case OMPC_device_type:
16528 case OMPC_match:
16529 case OMPC_nontemporal:
16530 case OMPC_destroy:
16531 case OMPC_novariants:
16532 case OMPC_nocontext:
16533 case OMPC_detach:
16534 case OMPC_inclusive:
16535 case OMPC_exclusive:
16536 case OMPC_uses_allocators:
16537 case OMPC_affinity:
16538 case OMPC_when:
16539 default:
16540 llvm_unreachable("Clause is not allowed.");
16542 return Res;
16545 static std::string
16546 getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last,
16547 ArrayRef<unsigned> Exclude = llvm::None) {
16548 SmallString<256> Buffer;
16549 llvm::raw_svector_ostream Out(Buffer);
16550 unsigned Skipped = Exclude.size();
16551 auto S = Exclude.begin(), E = Exclude.end();
16552 for (unsigned I = First; I < Last; ++I) {
16553 if (std::find(S, E, I) != E) {
16554 --Skipped;
16555 continue;
16557 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
16558 if (I + Skipped + 2 == Last)
16559 Out << " or ";
16560 else if (I + Skipped + 1 != Last)
16561 Out << ", ";
16563 return std::string(Out.str());
16566 OMPClause *Sema::ActOnOpenMPDefaultClause(DefaultKind Kind,
16567 SourceLocation KindKwLoc,
16568 SourceLocation StartLoc,
16569 SourceLocation LParenLoc,
16570 SourceLocation EndLoc) {
16571 if (Kind == OMP_DEFAULT_unknown) {
16572 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16573 << getListOfPossibleValues(OMPC_default, /*First=*/0,
16574 /*Last=*/unsigned(OMP_DEFAULT_unknown))
16575 << getOpenMPClauseName(OMPC_default);
16576 return nullptr;
16579 switch (Kind) {
16580 case OMP_DEFAULT_none:
16581 DSAStack->setDefaultDSANone(KindKwLoc);
16582 break;
16583 case OMP_DEFAULT_shared:
16584 DSAStack->setDefaultDSAShared(KindKwLoc);
16585 break;
16586 case OMP_DEFAULT_firstprivate:
16587 DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
16588 break;
16589 case OMP_DEFAULT_private:
16590 DSAStack->setDefaultDSAPrivate(KindKwLoc);
16591 break;
16592 default:
16593 llvm_unreachable("DSA unexpected in OpenMP default clause");
16596 return new (Context)
16597 OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16600 OMPClause *Sema::ActOnOpenMPProcBindClause(ProcBindKind Kind,
16601 SourceLocation KindKwLoc,
16602 SourceLocation StartLoc,
16603 SourceLocation LParenLoc,
16604 SourceLocation EndLoc) {
16605 if (Kind == OMP_PROC_BIND_unknown) {
16606 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16607 << getListOfPossibleValues(OMPC_proc_bind,
16608 /*First=*/unsigned(OMP_PROC_BIND_master),
16609 /*Last=*/
16610 unsigned(LangOpts.OpenMP > 50
16611 ? OMP_PROC_BIND_primary
16612 : OMP_PROC_BIND_spread) +
16614 << getOpenMPClauseName(OMPC_proc_bind);
16615 return nullptr;
16617 if (Kind == OMP_PROC_BIND_primary && LangOpts.OpenMP < 51)
16618 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16619 << getListOfPossibleValues(OMPC_proc_bind,
16620 /*First=*/unsigned(OMP_PROC_BIND_master),
16621 /*Last=*/
16622 unsigned(OMP_PROC_BIND_spread) + 1)
16623 << getOpenMPClauseName(OMPC_proc_bind);
16624 return new (Context)
16625 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16628 OMPClause *Sema::ActOnOpenMPAtomicDefaultMemOrderClause(
16629 OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindKwLoc,
16630 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
16631 if (Kind == OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown) {
16632 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16633 << getListOfPossibleValues(
16634 OMPC_atomic_default_mem_order, /*First=*/0,
16635 /*Last=*/OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown)
16636 << getOpenMPClauseName(OMPC_atomic_default_mem_order);
16637 return nullptr;
16639 return new (Context) OMPAtomicDefaultMemOrderClause(Kind, KindKwLoc, StartLoc,
16640 LParenLoc, EndLoc);
16643 OMPClause *Sema::ActOnOpenMPOrderClause(OpenMPOrderClauseKind Kind,
16644 SourceLocation KindKwLoc,
16645 SourceLocation StartLoc,
16646 SourceLocation LParenLoc,
16647 SourceLocation EndLoc) {
16648 if (Kind == OMPC_ORDER_unknown) {
16649 static_assert(OMPC_ORDER_unknown > 0,
16650 "OMPC_ORDER_unknown not greater than 0");
16651 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16652 << getListOfPossibleValues(OMPC_order, /*First=*/0,
16653 /*Last=*/OMPC_ORDER_unknown)
16654 << getOpenMPClauseName(OMPC_order);
16655 return nullptr;
16657 return new (Context)
16658 OMPOrderClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16661 OMPClause *Sema::ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind,
16662 SourceLocation KindKwLoc,
16663 SourceLocation StartLoc,
16664 SourceLocation LParenLoc,
16665 SourceLocation EndLoc) {
16666 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
16667 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
16668 SmallVector<unsigned> Except = {
16669 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
16670 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
16671 if (LangOpts.OpenMP < 51)
16672 Except.push_back(OMPC_DEPEND_inoutset);
16673 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16674 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
16675 /*Last=*/OMPC_DEPEND_unknown, Except)
16676 << getOpenMPClauseName(OMPC_update);
16677 return nullptr;
16679 return OMPUpdateClause::Create(Context, StartLoc, LParenLoc, KindKwLoc, Kind,
16680 EndLoc);
16683 OMPClause *Sema::ActOnOpenMPSizesClause(ArrayRef<Expr *> SizeExprs,
16684 SourceLocation StartLoc,
16685 SourceLocation LParenLoc,
16686 SourceLocation EndLoc) {
16687 for (Expr *SizeExpr : SizeExprs) {
16688 ExprResult NumForLoopsResult = VerifyPositiveIntegerConstantInClause(
16689 SizeExpr, OMPC_sizes, /*StrictlyPositive=*/true);
16690 if (!NumForLoopsResult.isUsable())
16691 return nullptr;
16694 DSAStack->setAssociatedLoops(SizeExprs.size());
16695 return OMPSizesClause::Create(Context, StartLoc, LParenLoc, EndLoc,
16696 SizeExprs);
16699 OMPClause *Sema::ActOnOpenMPFullClause(SourceLocation StartLoc,
16700 SourceLocation EndLoc) {
16701 return OMPFullClause::Create(Context, StartLoc, EndLoc);
16704 OMPClause *Sema::ActOnOpenMPPartialClause(Expr *FactorExpr,
16705 SourceLocation StartLoc,
16706 SourceLocation LParenLoc,
16707 SourceLocation EndLoc) {
16708 if (FactorExpr) {
16709 // If an argument is specified, it must be a constant (or an unevaluated
16710 // template expression).
16711 ExprResult FactorResult = VerifyPositiveIntegerConstantInClause(
16712 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
16713 if (FactorResult.isInvalid())
16714 return nullptr;
16715 FactorExpr = FactorResult.get();
16718 return OMPPartialClause::Create(Context, StartLoc, LParenLoc, EndLoc,
16719 FactorExpr);
16722 OMPClause *Sema::ActOnOpenMPAlignClause(Expr *A, SourceLocation StartLoc,
16723 SourceLocation LParenLoc,
16724 SourceLocation EndLoc) {
16725 ExprResult AlignVal;
16726 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
16727 if (AlignVal.isInvalid())
16728 return nullptr;
16729 return OMPAlignClause::Create(Context, AlignVal.get(), StartLoc, LParenLoc,
16730 EndLoc);
16733 OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
16734 OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr,
16735 SourceLocation StartLoc, SourceLocation LParenLoc,
16736 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
16737 SourceLocation EndLoc) {
16738 OMPClause *Res = nullptr;
16739 switch (Kind) {
16740 case OMPC_schedule:
16741 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
16742 assert(Argument.size() == NumberOfElements &&
16743 ArgumentLoc.size() == NumberOfElements);
16744 Res = ActOnOpenMPScheduleClause(
16745 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
16746 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
16747 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
16748 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
16749 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
16750 break;
16751 case OMPC_if:
16752 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16753 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
16754 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
16755 DelimLoc, EndLoc);
16756 break;
16757 case OMPC_dist_schedule:
16758 Res = ActOnOpenMPDistScheduleClause(
16759 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
16760 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
16761 break;
16762 case OMPC_defaultmap:
16763 enum { Modifier, DefaultmapKind };
16764 Res = ActOnOpenMPDefaultmapClause(
16765 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
16766 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
16767 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
16768 EndLoc);
16769 break;
16770 case OMPC_device:
16771 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16772 Res = ActOnOpenMPDeviceClause(
16773 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
16774 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16775 break;
16776 case OMPC_final:
16777 case OMPC_num_threads:
16778 case OMPC_safelen:
16779 case OMPC_simdlen:
16780 case OMPC_sizes:
16781 case OMPC_allocator:
16782 case OMPC_collapse:
16783 case OMPC_default:
16784 case OMPC_proc_bind:
16785 case OMPC_private:
16786 case OMPC_firstprivate:
16787 case OMPC_lastprivate:
16788 case OMPC_shared:
16789 case OMPC_reduction:
16790 case OMPC_task_reduction:
16791 case OMPC_in_reduction:
16792 case OMPC_linear:
16793 case OMPC_aligned:
16794 case OMPC_copyin:
16795 case OMPC_copyprivate:
16796 case OMPC_ordered:
16797 case OMPC_nowait:
16798 case OMPC_untied:
16799 case OMPC_mergeable:
16800 case OMPC_threadprivate:
16801 case OMPC_allocate:
16802 case OMPC_flush:
16803 case OMPC_depobj:
16804 case OMPC_read:
16805 case OMPC_write:
16806 case OMPC_update:
16807 case OMPC_capture:
16808 case OMPC_compare:
16809 case OMPC_seq_cst:
16810 case OMPC_acq_rel:
16811 case OMPC_acquire:
16812 case OMPC_release:
16813 case OMPC_relaxed:
16814 case OMPC_depend:
16815 case OMPC_threads:
16816 case OMPC_simd:
16817 case OMPC_map:
16818 case OMPC_num_teams:
16819 case OMPC_thread_limit:
16820 case OMPC_priority:
16821 case OMPC_grainsize:
16822 case OMPC_nogroup:
16823 case OMPC_num_tasks:
16824 case OMPC_hint:
16825 case OMPC_unknown:
16826 case OMPC_uniform:
16827 case OMPC_to:
16828 case OMPC_from:
16829 case OMPC_use_device_ptr:
16830 case OMPC_use_device_addr:
16831 case OMPC_is_device_ptr:
16832 case OMPC_has_device_addr:
16833 case OMPC_unified_address:
16834 case OMPC_unified_shared_memory:
16835 case OMPC_reverse_offload:
16836 case OMPC_dynamic_allocators:
16837 case OMPC_atomic_default_mem_order:
16838 case OMPC_device_type:
16839 case OMPC_match:
16840 case OMPC_nontemporal:
16841 case OMPC_order:
16842 case OMPC_destroy:
16843 case OMPC_novariants:
16844 case OMPC_nocontext:
16845 case OMPC_detach:
16846 case OMPC_inclusive:
16847 case OMPC_exclusive:
16848 case OMPC_uses_allocators:
16849 case OMPC_affinity:
16850 case OMPC_when:
16851 case OMPC_bind:
16852 default:
16853 llvm_unreachable("Clause is not allowed.");
16855 return Res;
16858 static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1,
16859 OpenMPScheduleClauseModifier M2,
16860 SourceLocation M1Loc, SourceLocation M2Loc) {
16861 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
16862 SmallVector<unsigned, 2> Excluded;
16863 if (M2 != OMPC_SCHEDULE_MODIFIER_unknown)
16864 Excluded.push_back(M2);
16865 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
16866 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
16867 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
16868 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
16869 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
16870 << getListOfPossibleValues(OMPC_schedule,
16871 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
16872 /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
16873 Excluded)
16874 << getOpenMPClauseName(OMPC_schedule);
16875 return true;
16877 return false;
16880 OMPClause *Sema::ActOnOpenMPScheduleClause(
16881 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
16882 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
16883 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
16884 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
16885 if (checkScheduleModifiers(*this, M1, M2, M1Loc, M2Loc) ||
16886 checkScheduleModifiers(*this, M2, M1, M2Loc, M1Loc))
16887 return nullptr;
16888 // OpenMP, 2.7.1, Loop Construct, Restrictions
16889 // Either the monotonic modifier or the nonmonotonic modifier can be specified
16890 // but not both.
16891 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
16892 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
16893 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
16894 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
16895 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
16896 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
16897 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
16898 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
16899 return nullptr;
16901 if (Kind == OMPC_SCHEDULE_unknown) {
16902 std::string Values;
16903 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
16904 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
16905 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
16906 /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
16907 Exclude);
16908 } else {
16909 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
16910 /*Last=*/OMPC_SCHEDULE_unknown);
16912 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16913 << Values << getOpenMPClauseName(OMPC_schedule);
16914 return nullptr;
16916 // OpenMP, 2.7.1, Loop Construct, Restrictions
16917 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
16918 // schedule(guided).
16919 // OpenMP 5.0 does not have this restriction.
16920 if (LangOpts.OpenMP < 50 &&
16921 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
16922 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
16923 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
16924 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
16925 diag::err_omp_schedule_nonmonotonic_static);
16926 return nullptr;
16928 Expr *ValExpr = ChunkSize;
16929 Stmt *HelperValStmt = nullptr;
16930 if (ChunkSize) {
16931 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
16932 !ChunkSize->isInstantiationDependent() &&
16933 !ChunkSize->containsUnexpandedParameterPack()) {
16934 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
16935 ExprResult Val =
16936 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
16937 if (Val.isInvalid())
16938 return nullptr;
16940 ValExpr = Val.get();
16942 // OpenMP [2.7.1, Restrictions]
16943 // chunk_size must be a loop invariant integer expression with a positive
16944 // value.
16945 if (Optional<llvm::APSInt> Result =
16946 ValExpr->getIntegerConstantExpr(Context)) {
16947 if (Result->isSigned() && !Result->isStrictlyPositive()) {
16948 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
16949 << "schedule" << 1 << ChunkSize->getSourceRange();
16950 return nullptr;
16952 } else if (getOpenMPCaptureRegionForClause(
16953 DSAStack->getCurrentDirective(), OMPC_schedule,
16954 LangOpts.OpenMP) != OMPD_unknown &&
16955 !CurContext->isDependentContext()) {
16956 ValExpr = MakeFullExpr(ValExpr).get();
16957 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16958 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
16959 HelperValStmt = buildPreInits(Context, Captures);
16964 return new (Context)
16965 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
16966 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
16969 OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
16970 SourceLocation StartLoc,
16971 SourceLocation EndLoc) {
16972 OMPClause *Res = nullptr;
16973 switch (Kind) {
16974 case OMPC_ordered:
16975 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
16976 break;
16977 case OMPC_nowait:
16978 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc);
16979 break;
16980 case OMPC_untied:
16981 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
16982 break;
16983 case OMPC_mergeable:
16984 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
16985 break;
16986 case OMPC_read:
16987 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
16988 break;
16989 case OMPC_write:
16990 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
16991 break;
16992 case OMPC_update:
16993 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
16994 break;
16995 case OMPC_capture:
16996 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
16997 break;
16998 case OMPC_compare:
16999 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
17000 break;
17001 case OMPC_seq_cst:
17002 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
17003 break;
17004 case OMPC_acq_rel:
17005 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
17006 break;
17007 case OMPC_acquire:
17008 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
17009 break;
17010 case OMPC_release:
17011 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
17012 break;
17013 case OMPC_relaxed:
17014 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
17015 break;
17016 case OMPC_threads:
17017 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
17018 break;
17019 case OMPC_simd:
17020 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
17021 break;
17022 case OMPC_nogroup:
17023 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
17024 break;
17025 case OMPC_unified_address:
17026 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
17027 break;
17028 case OMPC_unified_shared_memory:
17029 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
17030 break;
17031 case OMPC_reverse_offload:
17032 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
17033 break;
17034 case OMPC_dynamic_allocators:
17035 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
17036 break;
17037 case OMPC_destroy:
17038 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
17039 /*LParenLoc=*/SourceLocation(),
17040 /*VarLoc=*/SourceLocation(), EndLoc);
17041 break;
17042 case OMPC_full:
17043 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
17044 break;
17045 case OMPC_partial:
17046 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
17047 break;
17048 case OMPC_if:
17049 case OMPC_final:
17050 case OMPC_num_threads:
17051 case OMPC_safelen:
17052 case OMPC_simdlen:
17053 case OMPC_sizes:
17054 case OMPC_allocator:
17055 case OMPC_collapse:
17056 case OMPC_schedule:
17057 case OMPC_private:
17058 case OMPC_firstprivate:
17059 case OMPC_lastprivate:
17060 case OMPC_shared:
17061 case OMPC_reduction:
17062 case OMPC_task_reduction:
17063 case OMPC_in_reduction:
17064 case OMPC_linear:
17065 case OMPC_aligned:
17066 case OMPC_copyin:
17067 case OMPC_copyprivate:
17068 case OMPC_default:
17069 case OMPC_proc_bind:
17070 case OMPC_threadprivate:
17071 case OMPC_allocate:
17072 case OMPC_flush:
17073 case OMPC_depobj:
17074 case OMPC_depend:
17075 case OMPC_device:
17076 case OMPC_map:
17077 case OMPC_num_teams:
17078 case OMPC_thread_limit:
17079 case OMPC_priority:
17080 case OMPC_grainsize:
17081 case OMPC_num_tasks:
17082 case OMPC_hint:
17083 case OMPC_dist_schedule:
17084 case OMPC_defaultmap:
17085 case OMPC_unknown:
17086 case OMPC_uniform:
17087 case OMPC_to:
17088 case OMPC_from:
17089 case OMPC_use_device_ptr:
17090 case OMPC_use_device_addr:
17091 case OMPC_is_device_ptr:
17092 case OMPC_has_device_addr:
17093 case OMPC_atomic_default_mem_order:
17094 case OMPC_device_type:
17095 case OMPC_match:
17096 case OMPC_nontemporal:
17097 case OMPC_order:
17098 case OMPC_novariants:
17099 case OMPC_nocontext:
17100 case OMPC_detach:
17101 case OMPC_inclusive:
17102 case OMPC_exclusive:
17103 case OMPC_uses_allocators:
17104 case OMPC_affinity:
17105 case OMPC_when:
17106 default:
17107 llvm_unreachable("Clause is not allowed.");
17109 return Res;
17112 OMPClause *Sema::ActOnOpenMPNowaitClause(SourceLocation StartLoc,
17113 SourceLocation EndLoc) {
17114 DSAStack->setNowaitRegion();
17115 return new (Context) OMPNowaitClause(StartLoc, EndLoc);
17118 OMPClause *Sema::ActOnOpenMPUntiedClause(SourceLocation StartLoc,
17119 SourceLocation EndLoc) {
17120 DSAStack->setUntiedRegion();
17121 return new (Context) OMPUntiedClause(StartLoc, EndLoc);
17124 OMPClause *Sema::ActOnOpenMPMergeableClause(SourceLocation StartLoc,
17125 SourceLocation EndLoc) {
17126 return new (Context) OMPMergeableClause(StartLoc, EndLoc);
17129 OMPClause *Sema::ActOnOpenMPReadClause(SourceLocation StartLoc,
17130 SourceLocation EndLoc) {
17131 return new (Context) OMPReadClause(StartLoc, EndLoc);
17134 OMPClause *Sema::ActOnOpenMPWriteClause(SourceLocation StartLoc,
17135 SourceLocation EndLoc) {
17136 return new (Context) OMPWriteClause(StartLoc, EndLoc);
17139 OMPClause *Sema::ActOnOpenMPUpdateClause(SourceLocation StartLoc,
17140 SourceLocation EndLoc) {
17141 return OMPUpdateClause::Create(Context, StartLoc, EndLoc);
17144 OMPClause *Sema::ActOnOpenMPCaptureClause(SourceLocation StartLoc,
17145 SourceLocation EndLoc) {
17146 return new (Context) OMPCaptureClause(StartLoc, EndLoc);
17149 OMPClause *Sema::ActOnOpenMPCompareClause(SourceLocation StartLoc,
17150 SourceLocation EndLoc) {
17151 return new (Context) OMPCompareClause(StartLoc, EndLoc);
17154 OMPClause *Sema::ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
17155 SourceLocation EndLoc) {
17156 return new (Context) OMPSeqCstClause(StartLoc, EndLoc);
17159 OMPClause *Sema::ActOnOpenMPAcqRelClause(SourceLocation StartLoc,
17160 SourceLocation EndLoc) {
17161 return new (Context) OMPAcqRelClause(StartLoc, EndLoc);
17164 OMPClause *Sema::ActOnOpenMPAcquireClause(SourceLocation StartLoc,
17165 SourceLocation EndLoc) {
17166 return new (Context) OMPAcquireClause(StartLoc, EndLoc);
17169 OMPClause *Sema::ActOnOpenMPReleaseClause(SourceLocation StartLoc,
17170 SourceLocation EndLoc) {
17171 return new (Context) OMPReleaseClause(StartLoc, EndLoc);
17174 OMPClause *Sema::ActOnOpenMPRelaxedClause(SourceLocation StartLoc,
17175 SourceLocation EndLoc) {
17176 return new (Context) OMPRelaxedClause(StartLoc, EndLoc);
17179 OMPClause *Sema::ActOnOpenMPThreadsClause(SourceLocation StartLoc,
17180 SourceLocation EndLoc) {
17181 return new (Context) OMPThreadsClause(StartLoc, EndLoc);
17184 OMPClause *Sema::ActOnOpenMPSIMDClause(SourceLocation StartLoc,
17185 SourceLocation EndLoc) {
17186 return new (Context) OMPSIMDClause(StartLoc, EndLoc);
17189 OMPClause *Sema::ActOnOpenMPNogroupClause(SourceLocation StartLoc,
17190 SourceLocation EndLoc) {
17191 return new (Context) OMPNogroupClause(StartLoc, EndLoc);
17194 OMPClause *Sema::ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc,
17195 SourceLocation EndLoc) {
17196 return new (Context) OMPUnifiedAddressClause(StartLoc, EndLoc);
17199 OMPClause *Sema::ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc,
17200 SourceLocation EndLoc) {
17201 return new (Context) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
17204 OMPClause *Sema::ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc,
17205 SourceLocation EndLoc) {
17206 return new (Context) OMPReverseOffloadClause(StartLoc, EndLoc);
17209 OMPClause *Sema::ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc,
17210 SourceLocation EndLoc) {
17211 return new (Context) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
17214 StmtResult Sema::ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses,
17215 SourceLocation StartLoc,
17216 SourceLocation EndLoc) {
17218 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17219 // At least one action-clause must appear on a directive.
17220 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
17221 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
17222 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
17223 << Expected << getOpenMPDirectiveName(OMPD_interop);
17224 return StmtError();
17227 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17228 // A depend clause can only appear on the directive if a targetsync
17229 // interop-type is present or the interop-var was initialized with
17230 // the targetsync interop-type.
17232 // If there is any 'init' clause diagnose if there is no 'init' clause with
17233 // interop-type of 'targetsync'. Cases involving other directives cannot be
17234 // diagnosed.
17235 const OMPDependClause *DependClause = nullptr;
17236 bool HasInitClause = false;
17237 bool IsTargetSync = false;
17238 for (const OMPClause *C : Clauses) {
17239 if (IsTargetSync)
17240 break;
17241 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
17242 HasInitClause = true;
17243 if (InitClause->getIsTargetSync())
17244 IsTargetSync = true;
17245 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
17246 DependClause = DC;
17249 if (DependClause && HasInitClause && !IsTargetSync) {
17250 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
17251 return StmtError();
17254 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17255 // Each interop-var may be specified for at most one action-clause of each
17256 // interop construct.
17257 llvm::SmallPtrSet<const ValueDecl *, 4> InteropVars;
17258 for (OMPClause *C : Clauses) {
17259 OpenMPClauseKind ClauseKind = C->getClauseKind();
17260 std::pair<ValueDecl *, bool> DeclResult;
17261 SourceLocation ELoc;
17262 SourceRange ERange;
17264 if (ClauseKind == OMPC_init) {
17265 auto *E = cast<OMPInitClause>(C)->getInteropVar();
17266 DeclResult = getPrivateItem(*this, E, ELoc, ERange);
17267 } else if (ClauseKind == OMPC_use) {
17268 auto *E = cast<OMPUseClause>(C)->getInteropVar();
17269 DeclResult = getPrivateItem(*this, E, ELoc, ERange);
17270 } else if (ClauseKind == OMPC_destroy) {
17271 auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
17272 DeclResult = getPrivateItem(*this, E, ELoc, ERange);
17275 if (DeclResult.first) {
17276 if (!InteropVars.insert(DeclResult.first).second) {
17277 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
17278 << DeclResult.first;
17279 return StmtError();
17284 return OMPInteropDirective::Create(Context, StartLoc, EndLoc, Clauses);
17287 static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
17288 SourceLocation VarLoc,
17289 OpenMPClauseKind Kind) {
17290 SourceLocation ELoc;
17291 SourceRange ERange;
17292 Expr *RefExpr = InteropVarExpr;
17293 auto Res =
17294 getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
17295 /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t");
17297 if (Res.second) {
17298 // It will be analyzed later.
17299 return true;
17302 if (!Res.first)
17303 return false;
17305 // Interop variable should be of type omp_interop_t.
17306 bool HasError = false;
17307 QualType InteropType;
17308 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
17309 VarLoc, Sema::LookupOrdinaryName);
17310 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
17311 NamedDecl *ND = Result.getFoundDecl();
17312 if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
17313 InteropType = QualType(TD->getTypeForDecl(), 0);
17314 } else {
17315 HasError = true;
17317 } else {
17318 HasError = true;
17321 if (HasError) {
17322 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
17323 << "omp_interop_t";
17324 return false;
17327 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
17328 if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
17329 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
17330 return false;
17333 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17334 // The interop-var passed to init or destroy must be non-const.
17335 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
17336 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
17337 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
17338 << /*non-const*/ 1;
17339 return false;
17341 return true;
17344 OMPClause *
17345 Sema::ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo,
17346 SourceLocation StartLoc, SourceLocation LParenLoc,
17347 SourceLocation VarLoc, SourceLocation EndLoc) {
17349 if (!isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_init))
17350 return nullptr;
17352 // Check prefer_type values. These foreign-runtime-id values are either
17353 // string literals or constant integral expressions.
17354 for (const Expr *E : InteropInfo.PreferTypes) {
17355 if (E->isValueDependent() || E->isTypeDependent() ||
17356 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
17357 continue;
17358 if (E->isIntegerConstantExpr(Context))
17359 continue;
17360 if (isa<StringLiteral>(E))
17361 continue;
17362 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
17363 return nullptr;
17366 return OMPInitClause::Create(Context, InteropVar, InteropInfo, StartLoc,
17367 LParenLoc, VarLoc, EndLoc);
17370 OMPClause *Sema::ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc,
17371 SourceLocation LParenLoc,
17372 SourceLocation VarLoc,
17373 SourceLocation EndLoc) {
17375 if (!isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_use))
17376 return nullptr;
17378 return new (Context)
17379 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
17382 OMPClause *Sema::ActOnOpenMPDestroyClause(Expr *InteropVar,
17383 SourceLocation StartLoc,
17384 SourceLocation LParenLoc,
17385 SourceLocation VarLoc,
17386 SourceLocation EndLoc) {
17387 if (InteropVar &&
17388 !isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_destroy))
17389 return nullptr;
17391 return new (Context)
17392 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
17395 OMPClause *Sema::ActOnOpenMPNovariantsClause(Expr *Condition,
17396 SourceLocation StartLoc,
17397 SourceLocation LParenLoc,
17398 SourceLocation EndLoc) {
17399 Expr *ValExpr = Condition;
17400 Stmt *HelperValStmt = nullptr;
17401 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17402 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17403 !Condition->isInstantiationDependent() &&
17404 !Condition->containsUnexpandedParameterPack()) {
17405 ExprResult Val = CheckBooleanCondition(StartLoc, Condition);
17406 if (Val.isInvalid())
17407 return nullptr;
17409 ValExpr = MakeFullExpr(Val.get()).get();
17411 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17412 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
17413 LangOpts.OpenMP);
17414 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
17415 ValExpr = MakeFullExpr(ValExpr).get();
17416 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17417 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
17418 HelperValStmt = buildPreInits(Context, Captures);
17422 return new (Context) OMPNovariantsClause(
17423 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17426 OMPClause *Sema::ActOnOpenMPNocontextClause(Expr *Condition,
17427 SourceLocation StartLoc,
17428 SourceLocation LParenLoc,
17429 SourceLocation EndLoc) {
17430 Expr *ValExpr = Condition;
17431 Stmt *HelperValStmt = nullptr;
17432 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17433 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17434 !Condition->isInstantiationDependent() &&
17435 !Condition->containsUnexpandedParameterPack()) {
17436 ExprResult Val = CheckBooleanCondition(StartLoc, Condition);
17437 if (Val.isInvalid())
17438 return nullptr;
17440 ValExpr = MakeFullExpr(Val.get()).get();
17442 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17443 CaptureRegion =
17444 getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext, LangOpts.OpenMP);
17445 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
17446 ValExpr = MakeFullExpr(ValExpr).get();
17447 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17448 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
17449 HelperValStmt = buildPreInits(Context, Captures);
17453 return new (Context) OMPNocontextClause(ValExpr, HelperValStmt, CaptureRegion,
17454 StartLoc, LParenLoc, EndLoc);
17457 OMPClause *Sema::ActOnOpenMPFilterClause(Expr *ThreadID,
17458 SourceLocation StartLoc,
17459 SourceLocation LParenLoc,
17460 SourceLocation EndLoc) {
17461 Expr *ValExpr = ThreadID;
17462 Stmt *HelperValStmt = nullptr;
17464 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17465 OpenMPDirectiveKind CaptureRegion =
17466 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, LangOpts.OpenMP);
17467 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
17468 ValExpr = MakeFullExpr(ValExpr).get();
17469 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17470 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
17471 HelperValStmt = buildPreInits(Context, Captures);
17474 return new (Context) OMPFilterClause(ValExpr, HelperValStmt, CaptureRegion,
17475 StartLoc, LParenLoc, EndLoc);
17478 OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
17479 ArrayRef<Expr *> VarList,
17480 const OMPVarListLocTy &Locs,
17481 OpenMPVarListDataTy &Data) {
17482 SourceLocation StartLoc = Locs.StartLoc;
17483 SourceLocation LParenLoc = Locs.LParenLoc;
17484 SourceLocation EndLoc = Locs.EndLoc;
17485 OMPClause *Res = nullptr;
17486 int ExtraModifier = Data.ExtraModifier;
17487 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
17488 SourceLocation ColonLoc = Data.ColonLoc;
17489 switch (Kind) {
17490 case OMPC_private:
17491 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17492 break;
17493 case OMPC_firstprivate:
17494 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17495 break;
17496 case OMPC_lastprivate:
17497 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
17498 "Unexpected lastprivate modifier.");
17499 Res = ActOnOpenMPLastprivateClause(
17500 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
17501 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
17502 break;
17503 case OMPC_shared:
17504 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
17505 break;
17506 case OMPC_reduction:
17507 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
17508 "Unexpected lastprivate modifier.");
17509 Res = ActOnOpenMPReductionClause(
17510 VarList, static_cast<OpenMPReductionClauseModifier>(ExtraModifier),
17511 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
17512 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17513 break;
17514 case OMPC_task_reduction:
17515 Res = ActOnOpenMPTaskReductionClause(
17516 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17517 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17518 break;
17519 case OMPC_in_reduction:
17520 Res = ActOnOpenMPInReductionClause(
17521 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17522 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17523 break;
17524 case OMPC_linear:
17525 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
17526 "Unexpected linear modifier.");
17527 Res = ActOnOpenMPLinearClause(
17528 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
17529 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
17530 ColonLoc, EndLoc);
17531 break;
17532 case OMPC_aligned:
17533 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
17534 LParenLoc, ColonLoc, EndLoc);
17535 break;
17536 case OMPC_copyin:
17537 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
17538 break;
17539 case OMPC_copyprivate:
17540 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17541 break;
17542 case OMPC_flush:
17543 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
17544 break;
17545 case OMPC_depend:
17546 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
17547 "Unexpected depend modifier.");
17548 Res = ActOnOpenMPDependClause(
17549 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
17550 ColonLoc, Data.OmpAllMemoryLoc},
17551 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
17552 break;
17553 case OMPC_map:
17554 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
17555 "Unexpected map modifier.");
17556 Res = ActOnOpenMPMapClause(
17557 Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
17558 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
17559 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
17560 ExtraModifierLoc, ColonLoc, VarList, Locs);
17561 break;
17562 case OMPC_to:
17563 Res =
17564 ActOnOpenMPToClause(Data.MotionModifiers, Data.MotionModifiersLoc,
17565 Data.ReductionOrMapperIdScopeSpec,
17566 Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
17567 break;
17568 case OMPC_from:
17569 Res = ActOnOpenMPFromClause(Data.MotionModifiers, Data.MotionModifiersLoc,
17570 Data.ReductionOrMapperIdScopeSpec,
17571 Data.ReductionOrMapperId, ColonLoc, VarList,
17572 Locs);
17573 break;
17574 case OMPC_use_device_ptr:
17575 Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
17576 break;
17577 case OMPC_use_device_addr:
17578 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
17579 break;
17580 case OMPC_is_device_ptr:
17581 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
17582 break;
17583 case OMPC_has_device_addr:
17584 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
17585 break;
17586 case OMPC_allocate:
17587 Res = ActOnOpenMPAllocateClause(Data.DepModOrTailExpr, VarList, StartLoc,
17588 LParenLoc, ColonLoc, EndLoc);
17589 break;
17590 case OMPC_nontemporal:
17591 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
17592 break;
17593 case OMPC_inclusive:
17594 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17595 break;
17596 case OMPC_exclusive:
17597 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17598 break;
17599 case OMPC_affinity:
17600 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
17601 Data.DepModOrTailExpr, VarList);
17602 break;
17603 case OMPC_if:
17604 case OMPC_depobj:
17605 case OMPC_final:
17606 case OMPC_num_threads:
17607 case OMPC_safelen:
17608 case OMPC_simdlen:
17609 case OMPC_sizes:
17610 case OMPC_allocator:
17611 case OMPC_collapse:
17612 case OMPC_default:
17613 case OMPC_proc_bind:
17614 case OMPC_schedule:
17615 case OMPC_ordered:
17616 case OMPC_nowait:
17617 case OMPC_untied:
17618 case OMPC_mergeable:
17619 case OMPC_threadprivate:
17620 case OMPC_read:
17621 case OMPC_write:
17622 case OMPC_update:
17623 case OMPC_capture:
17624 case OMPC_compare:
17625 case OMPC_seq_cst:
17626 case OMPC_acq_rel:
17627 case OMPC_acquire:
17628 case OMPC_release:
17629 case OMPC_relaxed:
17630 case OMPC_device:
17631 case OMPC_threads:
17632 case OMPC_simd:
17633 case OMPC_num_teams:
17634 case OMPC_thread_limit:
17635 case OMPC_priority:
17636 case OMPC_grainsize:
17637 case OMPC_nogroup:
17638 case OMPC_num_tasks:
17639 case OMPC_hint:
17640 case OMPC_dist_schedule:
17641 case OMPC_defaultmap:
17642 case OMPC_unknown:
17643 case OMPC_uniform:
17644 case OMPC_unified_address:
17645 case OMPC_unified_shared_memory:
17646 case OMPC_reverse_offload:
17647 case OMPC_dynamic_allocators:
17648 case OMPC_atomic_default_mem_order:
17649 case OMPC_device_type:
17650 case OMPC_match:
17651 case OMPC_order:
17652 case OMPC_destroy:
17653 case OMPC_novariants:
17654 case OMPC_nocontext:
17655 case OMPC_detach:
17656 case OMPC_uses_allocators:
17657 case OMPC_when:
17658 case OMPC_bind:
17659 default:
17660 llvm_unreachable("Clause is not allowed.");
17662 return Res;
17665 ExprResult Sema::getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
17666 ExprObjectKind OK, SourceLocation Loc) {
17667 ExprResult Res = BuildDeclRefExpr(
17668 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
17669 if (!Res.isUsable())
17670 return ExprError();
17671 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
17672 Res = CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
17673 if (!Res.isUsable())
17674 return ExprError();
17676 if (VK != VK_LValue && Res.get()->isGLValue()) {
17677 Res = DefaultLvalueConversion(Res.get());
17678 if (!Res.isUsable())
17679 return ExprError();
17681 return Res;
17684 OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
17685 SourceLocation StartLoc,
17686 SourceLocation LParenLoc,
17687 SourceLocation EndLoc) {
17688 SmallVector<Expr *, 8> Vars;
17689 SmallVector<Expr *, 8> PrivateCopies;
17690 bool IsImplicitClause =
17691 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17692 for (Expr *RefExpr : VarList) {
17693 assert(RefExpr && "NULL expr in OpenMP private clause.");
17694 SourceLocation ELoc;
17695 SourceRange ERange;
17696 Expr *SimpleRefExpr = RefExpr;
17697 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
17698 if (Res.second) {
17699 // It will be analyzed later.
17700 Vars.push_back(RefExpr);
17701 PrivateCopies.push_back(nullptr);
17703 ValueDecl *D = Res.first;
17704 if (!D)
17705 continue;
17707 QualType Type = D->getType();
17708 auto *VD = dyn_cast<VarDecl>(D);
17710 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
17711 // A variable that appears in a private clause must not have an incomplete
17712 // type or a reference type.
17713 if (RequireCompleteType(ELoc, Type, diag::err_omp_private_incomplete_type))
17714 continue;
17715 Type = Type.getNonReferenceType();
17717 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
17718 // A variable that is privatized must not have a const-qualified type
17719 // unless it is of class type with a mutable member. This restriction does
17720 // not apply to the firstprivate clause.
17722 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
17723 // A variable that appears in a private clause must not have a
17724 // const-qualified type unless it is of class type with a mutable member.
17725 if (rejectConstNotMutableType(*this, D, Type, OMPC_private, ELoc))
17726 continue;
17728 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17729 // in a Construct]
17730 // Variables with the predetermined data-sharing attributes may not be
17731 // listed in data-sharing attributes clauses, except for the cases
17732 // listed below. For these exceptions only, listing a predetermined
17733 // variable in a data-sharing attribute clause is allowed and overrides
17734 // the variable's predetermined data-sharing attributes.
17735 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
17736 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
17737 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
17738 << getOpenMPClauseName(OMPC_private);
17739 reportOriginalDsa(*this, DSAStack, D, DVar);
17740 continue;
17743 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17744 // Variably modified types are not supported for tasks.
17745 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
17746 isOpenMPTaskingDirective(CurrDir)) {
17747 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17748 << getOpenMPClauseName(OMPC_private) << Type
17749 << getOpenMPDirectiveName(CurrDir);
17750 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
17751 VarDecl::DeclarationOnly;
17752 Diag(D->getLocation(),
17753 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17754 << D;
17755 continue;
17758 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
17759 // A list item cannot appear in both a map clause and a data-sharing
17760 // attribute clause on the same construct
17762 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
17763 // A list item cannot appear in both a map clause and a data-sharing
17764 // attribute clause on the same construct unless the construct is a
17765 // combined construct.
17766 if ((LangOpts.OpenMP <= 45 && isOpenMPTargetExecutionDirective(CurrDir)) ||
17767 CurrDir == OMPD_target) {
17768 OpenMPClauseKind ConflictKind;
17769 if (DSAStack->checkMappableExprComponentListsForDecl(
17770 VD, /*CurrentRegionOnly=*/true,
17771 [&](OMPClauseMappableExprCommon::MappableExprComponentListRef,
17772 OpenMPClauseKind WhereFoundClauseKind) -> bool {
17773 ConflictKind = WhereFoundClauseKind;
17774 return true;
17775 })) {
17776 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17777 << getOpenMPClauseName(OMPC_private)
17778 << getOpenMPClauseName(ConflictKind)
17779 << getOpenMPDirectiveName(CurrDir);
17780 reportOriginalDsa(*this, DSAStack, D, DVar);
17781 continue;
17785 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
17786 // A variable of class type (or array thereof) that appears in a private
17787 // clause requires an accessible, unambiguous default constructor for the
17788 // class type.
17789 // Generate helper private variable and initialize it with the default
17790 // value. The address of the original variable is replaced by the address of
17791 // the new private variable in CodeGen. This new variable is not added to
17792 // IdResolver, so the code in the OpenMP region uses original variable for
17793 // proper diagnostics.
17794 Type = Type.getUnqualifiedType();
17795 VarDecl *VDPrivate =
17796 buildVarDecl(*this, ELoc, Type, D->getName(),
17797 D->hasAttrs() ? &D->getAttrs() : nullptr,
17798 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
17799 ActOnUninitializedDecl(VDPrivate);
17800 if (VDPrivate->isInvalidDecl())
17801 continue;
17802 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
17803 *this, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
17805 DeclRefExpr *Ref = nullptr;
17806 if (!VD && !CurContext->isDependentContext()) {
17807 auto *FD = dyn_cast<FieldDecl>(D);
17808 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
17809 if (VD)
17810 Ref = buildDeclRefExpr(*this, VD, VD->getType().getNonReferenceType(),
17811 RefExpr->getExprLoc());
17812 else
17813 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
17815 if (!IsImplicitClause)
17816 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
17817 Vars.push_back((VD || CurContext->isDependentContext())
17818 ? RefExpr->IgnoreParens()
17819 : Ref);
17820 PrivateCopies.push_back(VDPrivateRefExpr);
17823 if (Vars.empty())
17824 return nullptr;
17826 return OMPPrivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars,
17827 PrivateCopies);
17830 OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
17831 SourceLocation StartLoc,
17832 SourceLocation LParenLoc,
17833 SourceLocation EndLoc) {
17834 SmallVector<Expr *, 8> Vars;
17835 SmallVector<Expr *, 8> PrivateCopies;
17836 SmallVector<Expr *, 8> Inits;
17837 SmallVector<Decl *, 4> ExprCaptures;
17838 bool IsImplicitClause =
17839 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17840 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
17842 for (Expr *RefExpr : VarList) {
17843 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
17844 SourceLocation ELoc;
17845 SourceRange ERange;
17846 Expr *SimpleRefExpr = RefExpr;
17847 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
17848 if (Res.second) {
17849 // It will be analyzed later.
17850 Vars.push_back(RefExpr);
17851 PrivateCopies.push_back(nullptr);
17852 Inits.push_back(nullptr);
17854 ValueDecl *D = Res.first;
17855 if (!D)
17856 continue;
17858 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
17859 QualType Type = D->getType();
17860 auto *VD = dyn_cast<VarDecl>(D);
17862 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
17863 // A variable that appears in a private clause must not have an incomplete
17864 // type or a reference type.
17865 if (RequireCompleteType(ELoc, Type,
17866 diag::err_omp_firstprivate_incomplete_type))
17867 continue;
17868 Type = Type.getNonReferenceType();
17870 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
17871 // A variable of class type (or array thereof) that appears in a private
17872 // clause requires an accessible, unambiguous copy constructor for the
17873 // class type.
17874 QualType ElemType = Context.getBaseElementType(Type).getNonReferenceType();
17876 // If an implicit firstprivate variable found it was checked already.
17877 DSAStackTy::DSAVarData TopDVar;
17878 if (!IsImplicitClause) {
17879 DSAStackTy::DSAVarData DVar =
17880 DSAStack->getTopDSA(D, /*FromParent=*/false);
17881 TopDVar = DVar;
17882 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17883 bool IsConstant = ElemType.isConstant(Context);
17884 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
17885 // A list item that specifies a given variable may not appear in more
17886 // than one clause on the same directive, except that a variable may be
17887 // specified in both firstprivate and lastprivate clauses.
17888 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
17889 // A list item may appear in a firstprivate or lastprivate clause but not
17890 // both.
17891 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
17892 (isOpenMPDistributeDirective(CurrDir) ||
17893 DVar.CKind != OMPC_lastprivate) &&
17894 DVar.RefExpr) {
17895 Diag(ELoc, diag::err_omp_wrong_dsa)
17896 << getOpenMPClauseName(DVar.CKind)
17897 << getOpenMPClauseName(OMPC_firstprivate);
17898 reportOriginalDsa(*this, DSAStack, D, DVar);
17899 continue;
17902 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17903 // in a Construct]
17904 // Variables with the predetermined data-sharing attributes may not be
17905 // listed in data-sharing attributes clauses, except for the cases
17906 // listed below. For these exceptions only, listing a predetermined
17907 // variable in a data-sharing attribute clause is allowed and overrides
17908 // the variable's predetermined data-sharing attributes.
17909 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17910 // in a Construct, C/C++, p.2]
17911 // Variables with const-qualified type having no mutable member may be
17912 // listed in a firstprivate clause, even if they are static data members.
17913 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
17914 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
17915 Diag(ELoc, diag::err_omp_wrong_dsa)
17916 << getOpenMPClauseName(DVar.CKind)
17917 << getOpenMPClauseName(OMPC_firstprivate);
17918 reportOriginalDsa(*this, DSAStack, D, DVar);
17919 continue;
17922 // OpenMP [2.9.3.4, Restrictions, p.2]
17923 // A list item that is private within a parallel region must not appear
17924 // in a firstprivate clause on a worksharing construct if any of the
17925 // worksharing regions arising from the worksharing construct ever bind
17926 // to any of the parallel regions arising from the parallel construct.
17927 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
17928 // A list item that is private within a teams region must not appear in a
17929 // firstprivate clause on a distribute construct if any of the distribute
17930 // regions arising from the distribute construct ever bind to any of the
17931 // teams regions arising from the teams construct.
17932 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
17933 // A list item that appears in a reduction clause of a teams construct
17934 // must not appear in a firstprivate clause on a distribute construct if
17935 // any of the distribute regions arising from the distribute construct
17936 // ever bind to any of the teams regions arising from the teams construct.
17937 if ((isOpenMPWorksharingDirective(CurrDir) ||
17938 isOpenMPDistributeDirective(CurrDir)) &&
17939 !isOpenMPParallelDirective(CurrDir) &&
17940 !isOpenMPTeamsDirective(CurrDir)) {
17941 DVar = DSAStack->getImplicitDSA(D, true);
17942 if (DVar.CKind != OMPC_shared &&
17943 (isOpenMPParallelDirective(DVar.DKind) ||
17944 isOpenMPTeamsDirective(DVar.DKind) ||
17945 DVar.DKind == OMPD_unknown)) {
17946 Diag(ELoc, diag::err_omp_required_access)
17947 << getOpenMPClauseName(OMPC_firstprivate)
17948 << getOpenMPClauseName(OMPC_shared);
17949 reportOriginalDsa(*this, DSAStack, D, DVar);
17950 continue;
17953 // OpenMP [2.9.3.4, Restrictions, p.3]
17954 // A list item that appears in a reduction clause of a parallel construct
17955 // must not appear in a firstprivate clause on a worksharing or task
17956 // construct if any of the worksharing or task regions arising from the
17957 // worksharing or task construct ever bind to any of the parallel regions
17958 // arising from the parallel construct.
17959 // OpenMP [2.9.3.4, Restrictions, p.4]
17960 // A list item that appears in a reduction clause in worksharing
17961 // construct must not appear in a firstprivate clause in a task construct
17962 // encountered during execution of any of the worksharing regions arising
17963 // from the worksharing construct.
17964 if (isOpenMPTaskingDirective(CurrDir)) {
17965 DVar = DSAStack->hasInnermostDSA(
17967 [](OpenMPClauseKind C, bool AppliedToPointee) {
17968 return C == OMPC_reduction && !AppliedToPointee;
17970 [](OpenMPDirectiveKind K) {
17971 return isOpenMPParallelDirective(K) ||
17972 isOpenMPWorksharingDirective(K) ||
17973 isOpenMPTeamsDirective(K);
17975 /*FromParent=*/true);
17976 if (DVar.CKind == OMPC_reduction &&
17977 (isOpenMPParallelDirective(DVar.DKind) ||
17978 isOpenMPWorksharingDirective(DVar.DKind) ||
17979 isOpenMPTeamsDirective(DVar.DKind))) {
17980 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
17981 << getOpenMPDirectiveName(DVar.DKind);
17982 reportOriginalDsa(*this, DSAStack, D, DVar);
17983 continue;
17987 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
17988 // A list item cannot appear in both a map clause and a data-sharing
17989 // attribute clause on the same construct
17991 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
17992 // A list item cannot appear in both a map clause and a data-sharing
17993 // attribute clause on the same construct unless the construct is a
17994 // combined construct.
17995 if ((LangOpts.OpenMP <= 45 &&
17996 isOpenMPTargetExecutionDirective(CurrDir)) ||
17997 CurrDir == OMPD_target) {
17998 OpenMPClauseKind ConflictKind;
17999 if (DSAStack->checkMappableExprComponentListsForDecl(
18000 VD, /*CurrentRegionOnly=*/true,
18001 [&ConflictKind](
18002 OMPClauseMappableExprCommon::MappableExprComponentListRef,
18003 OpenMPClauseKind WhereFoundClauseKind) {
18004 ConflictKind = WhereFoundClauseKind;
18005 return true;
18006 })) {
18007 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18008 << getOpenMPClauseName(OMPC_firstprivate)
18009 << getOpenMPClauseName(ConflictKind)
18010 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
18011 reportOriginalDsa(*this, DSAStack, D, DVar);
18012 continue;
18017 // Variably modified types are not supported for tasks.
18018 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
18019 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
18020 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18021 << getOpenMPClauseName(OMPC_firstprivate) << Type
18022 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
18023 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18024 VarDecl::DeclarationOnly;
18025 Diag(D->getLocation(),
18026 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18027 << D;
18028 continue;
18031 Type = Type.getUnqualifiedType();
18032 VarDecl *VDPrivate =
18033 buildVarDecl(*this, ELoc, Type, D->getName(),
18034 D->hasAttrs() ? &D->getAttrs() : nullptr,
18035 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18036 // Generate helper private variable and initialize it with the value of the
18037 // original variable. The address of the original variable is replaced by
18038 // the address of the new private variable in the CodeGen. This new variable
18039 // is not added to IdResolver, so the code in the OpenMP region uses
18040 // original variable for proper diagnostics and variable capturing.
18041 Expr *VDInitRefExpr = nullptr;
18042 // For arrays generate initializer for single element and replace it by the
18043 // original array element in CodeGen.
18044 if (Type->isArrayType()) {
18045 VarDecl *VDInit =
18046 buildVarDecl(*this, RefExpr->getExprLoc(), ElemType, D->getName());
18047 VDInitRefExpr = buildDeclRefExpr(*this, VDInit, ElemType, ELoc);
18048 Expr *Init = DefaultLvalueConversion(VDInitRefExpr).get();
18049 ElemType = ElemType.getUnqualifiedType();
18050 VarDecl *VDInitTemp = buildVarDecl(*this, RefExpr->getExprLoc(), ElemType,
18051 ".firstprivate.temp");
18052 InitializedEntity Entity =
18053 InitializedEntity::InitializeVariable(VDInitTemp);
18054 InitializationKind Kind = InitializationKind::CreateCopy(ELoc, ELoc);
18056 InitializationSequence InitSeq(*this, Entity, Kind, Init);
18057 ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Init);
18058 if (Result.isInvalid())
18059 VDPrivate->setInvalidDecl();
18060 else
18061 VDPrivate->setInit(Result.getAs<Expr>());
18062 // Remove temp variable declaration.
18063 Context.Deallocate(VDInitTemp);
18064 } else {
18065 VarDecl *VDInit = buildVarDecl(*this, RefExpr->getExprLoc(), Type,
18066 ".firstprivate.temp");
18067 VDInitRefExpr = buildDeclRefExpr(*this, VDInit, RefExpr->getType(),
18068 RefExpr->getExprLoc());
18069 AddInitializerToDecl(VDPrivate,
18070 DefaultLvalueConversion(VDInitRefExpr).get(),
18071 /*DirectInit=*/false);
18073 if (VDPrivate->isInvalidDecl()) {
18074 if (IsImplicitClause) {
18075 Diag(RefExpr->getExprLoc(),
18076 diag::note_omp_task_predetermined_firstprivate_here);
18078 continue;
18080 CurContext->addDecl(VDPrivate);
18081 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18082 *this, VDPrivate, RefExpr->getType().getUnqualifiedType(),
18083 RefExpr->getExprLoc());
18084 DeclRefExpr *Ref = nullptr;
18085 if (!VD && !CurContext->isDependentContext()) {
18086 if (TopDVar.CKind == OMPC_lastprivate) {
18087 Ref = TopDVar.PrivateCopy;
18088 } else {
18089 auto *FD = dyn_cast<FieldDecl>(D);
18090 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
18091 if (VD)
18092 Ref = buildDeclRefExpr(*this, VD, VD->getType().getNonReferenceType(),
18093 RefExpr->getExprLoc());
18094 else
18095 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
18096 if (VD || !isOpenMPCapturedDecl(D))
18097 ExprCaptures.push_back(Ref->getDecl());
18100 if (!IsImplicitClause)
18101 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
18102 Vars.push_back((VD || CurContext->isDependentContext())
18103 ? RefExpr->IgnoreParens()
18104 : Ref);
18105 PrivateCopies.push_back(VDPrivateRefExpr);
18106 Inits.push_back(VDInitRefExpr);
18109 if (Vars.empty())
18110 return nullptr;
18112 return OMPFirstprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
18113 Vars, PrivateCopies, Inits,
18114 buildPreInits(Context, ExprCaptures));
18117 OMPClause *Sema::ActOnOpenMPLastprivateClause(
18118 ArrayRef<Expr *> VarList, OpenMPLastprivateModifier LPKind,
18119 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
18120 SourceLocation LParenLoc, SourceLocation EndLoc) {
18121 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
18122 assert(ColonLoc.isValid() && "Colon location must be valid.");
18123 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
18124 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
18125 /*Last=*/OMPC_LASTPRIVATE_unknown)
18126 << getOpenMPClauseName(OMPC_lastprivate);
18127 return nullptr;
18130 SmallVector<Expr *, 8> Vars;
18131 SmallVector<Expr *, 8> SrcExprs;
18132 SmallVector<Expr *, 8> DstExprs;
18133 SmallVector<Expr *, 8> AssignmentOps;
18134 SmallVector<Decl *, 4> ExprCaptures;
18135 SmallVector<Expr *, 4> ExprPostUpdates;
18136 for (Expr *RefExpr : VarList) {
18137 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
18138 SourceLocation ELoc;
18139 SourceRange ERange;
18140 Expr *SimpleRefExpr = RefExpr;
18141 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
18142 if (Res.second) {
18143 // It will be analyzed later.
18144 Vars.push_back(RefExpr);
18145 SrcExprs.push_back(nullptr);
18146 DstExprs.push_back(nullptr);
18147 AssignmentOps.push_back(nullptr);
18149 ValueDecl *D = Res.first;
18150 if (!D)
18151 continue;
18153 QualType Type = D->getType();
18154 auto *VD = dyn_cast<VarDecl>(D);
18156 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
18157 // A variable that appears in a lastprivate clause must not have an
18158 // incomplete type or a reference type.
18159 if (RequireCompleteType(ELoc, Type,
18160 diag::err_omp_lastprivate_incomplete_type))
18161 continue;
18162 Type = Type.getNonReferenceType();
18164 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18165 // A variable that is privatized must not have a const-qualified type
18166 // unless it is of class type with a mutable member. This restriction does
18167 // not apply to the firstprivate clause.
18169 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
18170 // A variable that appears in a lastprivate clause must not have a
18171 // const-qualified type unless it is of class type with a mutable member.
18172 if (rejectConstNotMutableType(*this, D, Type, OMPC_lastprivate, ELoc))
18173 continue;
18175 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
18176 // A list item that appears in a lastprivate clause with the conditional
18177 // modifier must be a scalar variable.
18178 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
18179 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
18180 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18181 VarDecl::DeclarationOnly;
18182 Diag(D->getLocation(),
18183 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18184 << D;
18185 continue;
18188 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18189 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
18190 // in a Construct]
18191 // Variables with the predetermined data-sharing attributes may not be
18192 // listed in data-sharing attributes clauses, except for the cases
18193 // listed below.
18194 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18195 // A list item may appear in a firstprivate or lastprivate clause but not
18196 // both.
18197 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18198 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
18199 (isOpenMPDistributeDirective(CurrDir) ||
18200 DVar.CKind != OMPC_firstprivate) &&
18201 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
18202 Diag(ELoc, diag::err_omp_wrong_dsa)
18203 << getOpenMPClauseName(DVar.CKind)
18204 << getOpenMPClauseName(OMPC_lastprivate);
18205 reportOriginalDsa(*this, DSAStack, D, DVar);
18206 continue;
18209 // OpenMP [2.14.3.5, Restrictions, p.2]
18210 // A list item that is private within a parallel region, or that appears in
18211 // the reduction clause of a parallel construct, must not appear in a
18212 // lastprivate clause on a worksharing construct if any of the corresponding
18213 // worksharing regions ever binds to any of the corresponding parallel
18214 // regions.
18215 DSAStackTy::DSAVarData TopDVar = DVar;
18216 if (isOpenMPWorksharingDirective(CurrDir) &&
18217 !isOpenMPParallelDirective(CurrDir) &&
18218 !isOpenMPTeamsDirective(CurrDir)) {
18219 DVar = DSAStack->getImplicitDSA(D, true);
18220 if (DVar.CKind != OMPC_shared) {
18221 Diag(ELoc, diag::err_omp_required_access)
18222 << getOpenMPClauseName(OMPC_lastprivate)
18223 << getOpenMPClauseName(OMPC_shared);
18224 reportOriginalDsa(*this, DSAStack, D, DVar);
18225 continue;
18229 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
18230 // A variable of class type (or array thereof) that appears in a
18231 // lastprivate clause requires an accessible, unambiguous default
18232 // constructor for the class type, unless the list item is also specified
18233 // in a firstprivate clause.
18234 // A variable of class type (or array thereof) that appears in a
18235 // lastprivate clause requires an accessible, unambiguous copy assignment
18236 // operator for the class type.
18237 Type = Context.getBaseElementType(Type).getNonReferenceType();
18238 VarDecl *SrcVD = buildVarDecl(*this, ERange.getBegin(),
18239 Type.getUnqualifiedType(), ".lastprivate.src",
18240 D->hasAttrs() ? &D->getAttrs() : nullptr);
18241 DeclRefExpr *PseudoSrcExpr =
18242 buildDeclRefExpr(*this, SrcVD, Type.getUnqualifiedType(), ELoc);
18243 VarDecl *DstVD =
18244 buildVarDecl(*this, ERange.getBegin(), Type, ".lastprivate.dst",
18245 D->hasAttrs() ? &D->getAttrs() : nullptr);
18246 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc);
18247 // For arrays generate assignment operation for single element and replace
18248 // it by the original array element in CodeGen.
18249 ExprResult AssignmentOp = BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
18250 PseudoDstExpr, PseudoSrcExpr);
18251 if (AssignmentOp.isInvalid())
18252 continue;
18253 AssignmentOp =
18254 ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false);
18255 if (AssignmentOp.isInvalid())
18256 continue;
18258 DeclRefExpr *Ref = nullptr;
18259 if (!VD && !CurContext->isDependentContext()) {
18260 if (TopDVar.CKind == OMPC_firstprivate) {
18261 Ref = TopDVar.PrivateCopy;
18262 } else {
18263 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
18264 if (!isOpenMPCapturedDecl(D))
18265 ExprCaptures.push_back(Ref->getDecl());
18267 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
18268 (!isOpenMPCapturedDecl(D) &&
18269 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
18270 ExprResult RefRes = DefaultLvalueConversion(Ref);
18271 if (!RefRes.isUsable())
18272 continue;
18273 ExprResult PostUpdateRes =
18274 BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
18275 RefRes.get());
18276 if (!PostUpdateRes.isUsable())
18277 continue;
18278 ExprPostUpdates.push_back(
18279 IgnoredValueConversions(PostUpdateRes.get()).get());
18282 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
18283 Vars.push_back((VD || CurContext->isDependentContext())
18284 ? RefExpr->IgnoreParens()
18285 : Ref);
18286 SrcExprs.push_back(PseudoSrcExpr);
18287 DstExprs.push_back(PseudoDstExpr);
18288 AssignmentOps.push_back(AssignmentOp.get());
18291 if (Vars.empty())
18292 return nullptr;
18294 return OMPLastprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
18295 Vars, SrcExprs, DstExprs, AssignmentOps,
18296 LPKind, LPKindLoc, ColonLoc,
18297 buildPreInits(Context, ExprCaptures),
18298 buildPostUpdate(*this, ExprPostUpdates));
18301 OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
18302 SourceLocation StartLoc,
18303 SourceLocation LParenLoc,
18304 SourceLocation EndLoc) {
18305 SmallVector<Expr *, 8> Vars;
18306 for (Expr *RefExpr : VarList) {
18307 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
18308 SourceLocation ELoc;
18309 SourceRange ERange;
18310 Expr *SimpleRefExpr = RefExpr;
18311 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
18312 if (Res.second) {
18313 // It will be analyzed later.
18314 Vars.push_back(RefExpr);
18316 ValueDecl *D = Res.first;
18317 if (!D)
18318 continue;
18320 auto *VD = dyn_cast<VarDecl>(D);
18321 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18322 // in a Construct]
18323 // Variables with the predetermined data-sharing attributes may not be
18324 // listed in data-sharing attributes clauses, except for the cases
18325 // listed below. For these exceptions only, listing a predetermined
18326 // variable in a data-sharing attribute clause is allowed and overrides
18327 // the variable's predetermined data-sharing attributes.
18328 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18329 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
18330 DVar.RefExpr) {
18331 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
18332 << getOpenMPClauseName(OMPC_shared);
18333 reportOriginalDsa(*this, DSAStack, D, DVar);
18334 continue;
18337 DeclRefExpr *Ref = nullptr;
18338 if (!VD && isOpenMPCapturedDecl(D) && !CurContext->isDependentContext())
18339 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
18340 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
18341 Vars.push_back((VD || !Ref || CurContext->isDependentContext())
18342 ? RefExpr->IgnoreParens()
18343 : Ref);
18346 if (Vars.empty())
18347 return nullptr;
18349 return OMPSharedClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
18352 namespace {
18353 class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
18354 DSAStackTy *Stack;
18356 public:
18357 bool VisitDeclRefExpr(DeclRefExpr *E) {
18358 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
18359 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
18360 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
18361 return false;
18362 if (DVar.CKind != OMPC_unknown)
18363 return true;
18364 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
18366 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
18367 return isOpenMPPrivate(C) && !AppliedToPointee;
18369 [](OpenMPDirectiveKind) { return true; },
18370 /*FromParent=*/true);
18371 return DVarPrivate.CKind != OMPC_unknown;
18373 return false;
18375 bool VisitStmt(Stmt *S) {
18376 for (Stmt *Child : S->children()) {
18377 if (Child && Visit(Child))
18378 return true;
18380 return false;
18382 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
18384 } // namespace
18386 namespace {
18387 // Transform MemberExpression for specified FieldDecl of current class to
18388 // DeclRefExpr to specified OMPCapturedExprDecl.
18389 class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
18390 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
18391 ValueDecl *Field = nullptr;
18392 DeclRefExpr *CapturedExpr = nullptr;
18394 public:
18395 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
18396 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
18398 ExprResult TransformMemberExpr(MemberExpr *E) {
18399 if (isa<CXXThisExpr>(E->getBase()->IgnoreParenImpCasts()) &&
18400 E->getMemberDecl() == Field) {
18401 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
18402 return CapturedExpr;
18404 return BaseTransform::TransformMemberExpr(E);
18406 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
18408 } // namespace
18410 template <typename T, typename U>
18411 static T filterLookupForUDReductionAndMapper(
18412 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
18413 for (U &Set : Lookups) {
18414 for (auto *D : Set) {
18415 if (T Res = Gen(cast<ValueDecl>(D)))
18416 return Res;
18419 return T();
18422 static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
18423 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
18425 for (auto *RD : D->redecls()) {
18426 // Don't bother with extra checks if we already know this one isn't visible.
18427 if (RD == D)
18428 continue;
18430 auto ND = cast<NamedDecl>(RD);
18431 if (LookupResult::isVisible(SemaRef, ND))
18432 return ND;
18435 return nullptr;
18438 static void
18439 argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id,
18440 SourceLocation Loc, QualType Ty,
18441 SmallVectorImpl<UnresolvedSet<8>> &Lookups) {
18442 // Find all of the associated namespaces and classes based on the
18443 // arguments we have.
18444 Sema::AssociatedNamespaceSet AssociatedNamespaces;
18445 Sema::AssociatedClassSet AssociatedClasses;
18446 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
18447 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
18448 AssociatedClasses);
18450 // C++ [basic.lookup.argdep]p3:
18451 // Let X be the lookup set produced by unqualified lookup (3.4.1)
18452 // and let Y be the lookup set produced by argument dependent
18453 // lookup (defined as follows). If X contains [...] then Y is
18454 // empty. Otherwise Y is the set of declarations found in the
18455 // namespaces associated with the argument types as described
18456 // below. The set of declarations found by the lookup of the name
18457 // is the union of X and Y.
18459 // Here, we compute Y and add its members to the overloaded
18460 // candidate set.
18461 for (auto *NS : AssociatedNamespaces) {
18462 // When considering an associated namespace, the lookup is the
18463 // same as the lookup performed when the associated namespace is
18464 // used as a qualifier (3.4.3.2) except that:
18466 // -- Any using-directives in the associated namespace are
18467 // ignored.
18469 // -- Any namespace-scope friend functions declared in
18470 // associated classes are visible within their respective
18471 // namespaces even if they are not visible during an ordinary
18472 // lookup (11.4).
18473 DeclContext::lookup_result R = NS->lookup(Id.getName());
18474 for (auto *D : R) {
18475 auto *Underlying = D;
18476 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
18477 Underlying = USD->getTargetDecl();
18479 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
18480 !isa<OMPDeclareMapperDecl>(Underlying))
18481 continue;
18483 if (!SemaRef.isVisible(D)) {
18484 D = findAcceptableDecl(SemaRef, D);
18485 if (!D)
18486 continue;
18487 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
18488 Underlying = USD->getTargetDecl();
18490 Lookups.emplace_back();
18491 Lookups.back().addDecl(Underlying);
18496 static ExprResult
18497 buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
18498 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
18499 const DeclarationNameInfo &ReductionId, QualType Ty,
18500 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
18501 if (ReductionIdScopeSpec.isInvalid())
18502 return ExprError();
18503 SmallVector<UnresolvedSet<8>, 4> Lookups;
18504 if (S) {
18505 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
18506 Lookup.suppressDiagnostics();
18507 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec)) {
18508 NamedDecl *D = Lookup.getRepresentativeDecl();
18509 do {
18510 S = S->getParent();
18511 } while (S && !S->isDeclScope(D));
18512 if (S)
18513 S = S->getParent();
18514 Lookups.emplace_back();
18515 Lookups.back().append(Lookup.begin(), Lookup.end());
18516 Lookup.clear();
18518 } else if (auto *ULE =
18519 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
18520 Lookups.push_back(UnresolvedSet<8>());
18521 Decl *PrevD = nullptr;
18522 for (NamedDecl *D : ULE->decls()) {
18523 if (D == PrevD)
18524 Lookups.push_back(UnresolvedSet<8>());
18525 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
18526 Lookups.back().addDecl(DRD);
18527 PrevD = D;
18530 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
18531 Ty->isInstantiationDependentType() ||
18532 Ty->containsUnexpandedParameterPack() ||
18533 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
18534 return !D->isInvalidDecl() &&
18535 (D->getType()->isDependentType() ||
18536 D->getType()->isInstantiationDependentType() ||
18537 D->getType()->containsUnexpandedParameterPack());
18538 })) {
18539 UnresolvedSet<8> ResSet;
18540 for (const UnresolvedSet<8> &Set : Lookups) {
18541 if (Set.empty())
18542 continue;
18543 ResSet.append(Set.begin(), Set.end());
18544 // The last item marks the end of all declarations at the specified scope.
18545 ResSet.addDecl(Set[Set.size() - 1]);
18547 return UnresolvedLookupExpr::Create(
18548 SemaRef.Context, /*NamingClass=*/nullptr,
18549 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
18550 /*ADL=*/true, /*Overloaded=*/true, ResSet.begin(), ResSet.end());
18552 // Lookup inside the classes.
18553 // C++ [over.match.oper]p3:
18554 // For a unary operator @ with an operand of a type whose
18555 // cv-unqualified version is T1, and for a binary operator @ with
18556 // a left operand of a type whose cv-unqualified version is T1 and
18557 // a right operand of a type whose cv-unqualified version is T2,
18558 // three sets of candidate functions, designated member
18559 // candidates, non-member candidates and built-in candidates, are
18560 // constructed as follows:
18561 // -- If T1 is a complete class type or a class currently being
18562 // defined, the set of member candidates is the result of the
18563 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
18564 // the set of member candidates is empty.
18565 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
18566 Lookup.suppressDiagnostics();
18567 if (const auto *TyRec = Ty->getAs<RecordType>()) {
18568 // Complete the type if it can be completed.
18569 // If the type is neither complete nor being defined, bail out now.
18570 if (SemaRef.isCompleteType(Loc, Ty) || TyRec->isBeingDefined() ||
18571 TyRec->getDecl()->getDefinition()) {
18572 Lookup.clear();
18573 SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl());
18574 if (Lookup.empty()) {
18575 Lookups.emplace_back();
18576 Lookups.back().append(Lookup.begin(), Lookup.end());
18580 // Perform ADL.
18581 if (SemaRef.getLangOpts().CPlusPlus)
18582 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
18583 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18584 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
18585 if (!D->isInvalidDecl() &&
18586 SemaRef.Context.hasSameType(D->getType(), Ty))
18587 return D;
18588 return nullptr;
18590 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
18591 VK_LValue, Loc);
18592 if (SemaRef.getLangOpts().CPlusPlus) {
18593 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18594 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
18595 if (!D->isInvalidDecl() &&
18596 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
18597 !Ty.isMoreQualifiedThan(D->getType()))
18598 return D;
18599 return nullptr;
18600 })) {
18601 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
18602 /*DetectVirtual=*/false);
18603 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
18604 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
18605 VD->getType().getUnqualifiedType()))) {
18606 if (SemaRef.CheckBaseClassAccess(
18607 Loc, VD->getType(), Ty, Paths.front(),
18608 /*DiagID=*/0) != Sema::AR_inaccessible) {
18609 SemaRef.BuildBasePathArray(Paths, BasePath);
18610 return SemaRef.BuildDeclRefExpr(
18611 VD, VD->getType().getNonReferenceType(), VK_LValue, Loc);
18617 if (ReductionIdScopeSpec.isSet()) {
18618 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
18619 << Ty << Range;
18620 return ExprError();
18622 return ExprEmpty();
18625 namespace {
18626 /// Data for the reduction-based clauses.
18627 struct ReductionData {
18628 /// List of original reduction items.
18629 SmallVector<Expr *, 8> Vars;
18630 /// List of private copies of the reduction items.
18631 SmallVector<Expr *, 8> Privates;
18632 /// LHS expressions for the reduction_op expressions.
18633 SmallVector<Expr *, 8> LHSs;
18634 /// RHS expressions for the reduction_op expressions.
18635 SmallVector<Expr *, 8> RHSs;
18636 /// Reduction operation expression.
18637 SmallVector<Expr *, 8> ReductionOps;
18638 /// inscan copy operation expressions.
18639 SmallVector<Expr *, 8> InscanCopyOps;
18640 /// inscan copy temp array expressions for prefix sums.
18641 SmallVector<Expr *, 8> InscanCopyArrayTemps;
18642 /// inscan copy temp array element expressions for prefix sums.
18643 SmallVector<Expr *, 8> InscanCopyArrayElems;
18644 /// Taskgroup descriptors for the corresponding reduction items in
18645 /// in_reduction clauses.
18646 SmallVector<Expr *, 8> TaskgroupDescriptors;
18647 /// List of captures for clause.
18648 SmallVector<Decl *, 4> ExprCaptures;
18649 /// List of postupdate expressions.
18650 SmallVector<Expr *, 4> ExprPostUpdates;
18651 /// Reduction modifier.
18652 unsigned RedModifier = 0;
18653 ReductionData() = delete;
18654 /// Reserves required memory for the reduction data.
18655 ReductionData(unsigned Size, unsigned Modifier = 0) : RedModifier(Modifier) {
18656 Vars.reserve(Size);
18657 Privates.reserve(Size);
18658 LHSs.reserve(Size);
18659 RHSs.reserve(Size);
18660 ReductionOps.reserve(Size);
18661 if (RedModifier == OMPC_REDUCTION_inscan) {
18662 InscanCopyOps.reserve(Size);
18663 InscanCopyArrayTemps.reserve(Size);
18664 InscanCopyArrayElems.reserve(Size);
18666 TaskgroupDescriptors.reserve(Size);
18667 ExprCaptures.reserve(Size);
18668 ExprPostUpdates.reserve(Size);
18670 /// Stores reduction item and reduction operation only (required for dependent
18671 /// reduction item).
18672 void push(Expr *Item, Expr *ReductionOp) {
18673 Vars.emplace_back(Item);
18674 Privates.emplace_back(nullptr);
18675 LHSs.emplace_back(nullptr);
18676 RHSs.emplace_back(nullptr);
18677 ReductionOps.emplace_back(ReductionOp);
18678 TaskgroupDescriptors.emplace_back(nullptr);
18679 if (RedModifier == OMPC_REDUCTION_inscan) {
18680 InscanCopyOps.push_back(nullptr);
18681 InscanCopyArrayTemps.push_back(nullptr);
18682 InscanCopyArrayElems.push_back(nullptr);
18685 /// Stores reduction data.
18686 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
18687 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
18688 Expr *CopyArrayElem) {
18689 Vars.emplace_back(Item);
18690 Privates.emplace_back(Private);
18691 LHSs.emplace_back(LHS);
18692 RHSs.emplace_back(RHS);
18693 ReductionOps.emplace_back(ReductionOp);
18694 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
18695 if (RedModifier == OMPC_REDUCTION_inscan) {
18696 InscanCopyOps.push_back(CopyOp);
18697 InscanCopyArrayTemps.push_back(CopyArrayTemp);
18698 InscanCopyArrayElems.push_back(CopyArrayElem);
18699 } else {
18700 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
18701 CopyArrayElem == nullptr &&
18702 "Copy operation must be used for inscan reductions only.");
18706 } // namespace
18708 static bool checkOMPArraySectionConstantForReduction(
18709 ASTContext &Context, const OMPArraySectionExpr *OASE, bool &SingleElement,
18710 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
18711 const Expr *Length = OASE->getLength();
18712 if (Length == nullptr) {
18713 // For array sections of the form [1:] or [:], we would need to analyze
18714 // the lower bound...
18715 if (OASE->getColonLocFirst().isValid())
18716 return false;
18718 // This is an array subscript which has implicit length 1!
18719 SingleElement = true;
18720 ArraySizes.push_back(llvm::APSInt::get(1));
18721 } else {
18722 Expr::EvalResult Result;
18723 if (!Length->EvaluateAsInt(Result, Context))
18724 return false;
18726 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
18727 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
18728 ArraySizes.push_back(ConstantLengthValue);
18731 // Get the base of this array section and walk up from there.
18732 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
18734 // We require length = 1 for all array sections except the right-most to
18735 // guarantee that the memory region is contiguous and has no holes in it.
18736 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) {
18737 Length = TempOASE->getLength();
18738 if (Length == nullptr) {
18739 // For array sections of the form [1:] or [:], we would need to analyze
18740 // the lower bound...
18741 if (OASE->getColonLocFirst().isValid())
18742 return false;
18744 // This is an array subscript which has implicit length 1!
18745 ArraySizes.push_back(llvm::APSInt::get(1));
18746 } else {
18747 Expr::EvalResult Result;
18748 if (!Length->EvaluateAsInt(Result, Context))
18749 return false;
18751 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
18752 if (ConstantLengthValue.getSExtValue() != 1)
18753 return false;
18755 ArraySizes.push_back(ConstantLengthValue);
18757 Base = TempOASE->getBase()->IgnoreParenImpCasts();
18760 // If we have a single element, we don't need to add the implicit lengths.
18761 if (!SingleElement) {
18762 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
18763 // Has implicit length 1!
18764 ArraySizes.push_back(llvm::APSInt::get(1));
18765 Base = TempASE->getBase()->IgnoreParenImpCasts();
18769 // This array section can be privatized as a single value or as a constant
18770 // sized array.
18771 return true;
18774 static BinaryOperatorKind
18775 getRelatedCompoundReductionOp(BinaryOperatorKind BOK) {
18776 if (BOK == BO_Add)
18777 return BO_AddAssign;
18778 if (BOK == BO_Mul)
18779 return BO_MulAssign;
18780 if (BOK == BO_And)
18781 return BO_AndAssign;
18782 if (BOK == BO_Or)
18783 return BO_OrAssign;
18784 if (BOK == BO_Xor)
18785 return BO_XorAssign;
18786 return BOK;
18789 static bool actOnOMPReductionKindClause(
18790 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
18791 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
18792 SourceLocation ColonLoc, SourceLocation EndLoc,
18793 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
18794 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
18795 DeclarationName DN = ReductionId.getName();
18796 OverloadedOperatorKind OOK = DN.getCXXOverloadedOperator();
18797 BinaryOperatorKind BOK = BO_Comma;
18799 ASTContext &Context = S.Context;
18800 // OpenMP [2.14.3.6, reduction clause]
18801 // C
18802 // reduction-identifier is either an identifier or one of the following
18803 // operators: +, -, *, &, |, ^, && and ||
18804 // C++
18805 // reduction-identifier is either an id-expression or one of the following
18806 // operators: +, -, *, &, |, ^, && and ||
18807 switch (OOK) {
18808 case OO_Plus:
18809 case OO_Minus:
18810 BOK = BO_Add;
18811 break;
18812 case OO_Star:
18813 BOK = BO_Mul;
18814 break;
18815 case OO_Amp:
18816 BOK = BO_And;
18817 break;
18818 case OO_Pipe:
18819 BOK = BO_Or;
18820 break;
18821 case OO_Caret:
18822 BOK = BO_Xor;
18823 break;
18824 case OO_AmpAmp:
18825 BOK = BO_LAnd;
18826 break;
18827 case OO_PipePipe:
18828 BOK = BO_LOr;
18829 break;
18830 case OO_New:
18831 case OO_Delete:
18832 case OO_Array_New:
18833 case OO_Array_Delete:
18834 case OO_Slash:
18835 case OO_Percent:
18836 case OO_Tilde:
18837 case OO_Exclaim:
18838 case OO_Equal:
18839 case OO_Less:
18840 case OO_Greater:
18841 case OO_LessEqual:
18842 case OO_GreaterEqual:
18843 case OO_PlusEqual:
18844 case OO_MinusEqual:
18845 case OO_StarEqual:
18846 case OO_SlashEqual:
18847 case OO_PercentEqual:
18848 case OO_CaretEqual:
18849 case OO_AmpEqual:
18850 case OO_PipeEqual:
18851 case OO_LessLess:
18852 case OO_GreaterGreater:
18853 case OO_LessLessEqual:
18854 case OO_GreaterGreaterEqual:
18855 case OO_EqualEqual:
18856 case OO_ExclaimEqual:
18857 case OO_Spaceship:
18858 case OO_PlusPlus:
18859 case OO_MinusMinus:
18860 case OO_Comma:
18861 case OO_ArrowStar:
18862 case OO_Arrow:
18863 case OO_Call:
18864 case OO_Subscript:
18865 case OO_Conditional:
18866 case OO_Coawait:
18867 case NUM_OVERLOADED_OPERATORS:
18868 llvm_unreachable("Unexpected reduction identifier");
18869 case OO_None:
18870 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
18871 if (II->isStr("max"))
18872 BOK = BO_GT;
18873 else if (II->isStr("min"))
18874 BOK = BO_LT;
18876 break;
18878 SourceRange ReductionIdRange;
18879 if (ReductionIdScopeSpec.isValid())
18880 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
18881 else
18882 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
18883 ReductionIdRange.setEnd(ReductionId.getEndLoc());
18885 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
18886 bool FirstIter = true;
18887 for (Expr *RefExpr : VarList) {
18888 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
18889 // OpenMP [2.1, C/C++]
18890 // A list item is a variable or array section, subject to the restrictions
18891 // specified in Section 2.4 on page 42 and in each of the sections
18892 // describing clauses and directives for which a list appears.
18893 // OpenMP [2.14.3.3, Restrictions, p.1]
18894 // A variable that is part of another variable (as an array or
18895 // structure element) cannot appear in a private clause.
18896 if (!FirstIter && IR != ER)
18897 ++IR;
18898 FirstIter = false;
18899 SourceLocation ELoc;
18900 SourceRange ERange;
18901 Expr *SimpleRefExpr = RefExpr;
18902 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
18903 /*AllowArraySection=*/true);
18904 if (Res.second) {
18905 // Try to find 'declare reduction' corresponding construct before using
18906 // builtin/overloaded operators.
18907 QualType Type = Context.DependentTy;
18908 CXXCastPath BasePath;
18909 ExprResult DeclareReductionRef = buildDeclareReductionRef(
18910 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
18911 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
18912 Expr *ReductionOp = nullptr;
18913 if (S.CurContext->isDependentContext() &&
18914 (DeclareReductionRef.isUnset() ||
18915 isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
18916 ReductionOp = DeclareReductionRef.get();
18917 // It will be analyzed later.
18918 RD.push(RefExpr, ReductionOp);
18920 ValueDecl *D = Res.first;
18921 if (!D)
18922 continue;
18924 Expr *TaskgroupDescriptor = nullptr;
18925 QualType Type;
18926 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
18927 auto *OASE = dyn_cast<OMPArraySectionExpr>(RefExpr->IgnoreParens());
18928 if (ASE) {
18929 Type = ASE->getType().getNonReferenceType();
18930 } else if (OASE) {
18931 QualType BaseType =
18932 OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
18933 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
18934 Type = ATy->getElementType();
18935 else
18936 Type = BaseType->getPointeeType();
18937 Type = Type.getNonReferenceType();
18938 } else {
18939 Type = Context.getBaseElementType(D->getType().getNonReferenceType());
18941 auto *VD = dyn_cast<VarDecl>(D);
18943 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18944 // A variable that appears in a private clause must not have an incomplete
18945 // type or a reference type.
18946 if (S.RequireCompleteType(ELoc, D->getType(),
18947 diag::err_omp_reduction_incomplete_type))
18948 continue;
18949 // OpenMP [2.14.3.6, reduction clause, Restrictions]
18950 // A list item that appears in a reduction clause must not be
18951 // const-qualified.
18952 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
18953 /*AcceptIfMutable*/ false, ASE || OASE))
18954 continue;
18956 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
18957 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
18958 // If a list-item is a reference type then it must bind to the same object
18959 // for all threads of the team.
18960 if (!ASE && !OASE) {
18961 if (VD) {
18962 VarDecl *VDDef = VD->getDefinition();
18963 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
18964 DSARefChecker Check(Stack);
18965 if (Check.Visit(VDDef->getInit())) {
18966 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
18967 << getOpenMPClauseName(ClauseKind) << ERange;
18968 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
18969 continue;
18974 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
18975 // in a Construct]
18976 // Variables with the predetermined data-sharing attributes may not be
18977 // listed in data-sharing attributes clauses, except for the cases
18978 // listed below. For these exceptions only, listing a predetermined
18979 // variable in a data-sharing attribute clause is allowed and overrides
18980 // the variable's predetermined data-sharing attributes.
18981 // OpenMP [2.14.3.6, Restrictions, p.3]
18982 // Any number of reduction clauses can be specified on the directive,
18983 // but a list item can appear only once in the reduction clauses for that
18984 // directive.
18985 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
18986 if (DVar.CKind == OMPC_reduction) {
18987 S.Diag(ELoc, diag::err_omp_once_referenced)
18988 << getOpenMPClauseName(ClauseKind);
18989 if (DVar.RefExpr)
18990 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
18991 continue;
18993 if (DVar.CKind != OMPC_unknown) {
18994 S.Diag(ELoc, diag::err_omp_wrong_dsa)
18995 << getOpenMPClauseName(DVar.CKind)
18996 << getOpenMPClauseName(OMPC_reduction);
18997 reportOriginalDsa(S, Stack, D, DVar);
18998 continue;
19001 // OpenMP [2.14.3.6, Restrictions, p.1]
19002 // A list item that appears in a reduction clause of a worksharing
19003 // construct must be shared in the parallel regions to which any of the
19004 // worksharing regions arising from the worksharing construct bind.
19005 if (isOpenMPWorksharingDirective(CurrDir) &&
19006 !isOpenMPParallelDirective(CurrDir) &&
19007 !isOpenMPTeamsDirective(CurrDir)) {
19008 DVar = Stack->getImplicitDSA(D, true);
19009 if (DVar.CKind != OMPC_shared) {
19010 S.Diag(ELoc, diag::err_omp_required_access)
19011 << getOpenMPClauseName(OMPC_reduction)
19012 << getOpenMPClauseName(OMPC_shared);
19013 reportOriginalDsa(S, Stack, D, DVar);
19014 continue;
19017 } else {
19018 // Threadprivates cannot be shared between threads, so dignose if the base
19019 // is a threadprivate variable.
19020 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19021 if (DVar.CKind == OMPC_threadprivate) {
19022 S.Diag(ELoc, diag::err_omp_wrong_dsa)
19023 << getOpenMPClauseName(DVar.CKind)
19024 << getOpenMPClauseName(OMPC_reduction);
19025 reportOriginalDsa(S, Stack, D, DVar);
19026 continue;
19030 // Try to find 'declare reduction' corresponding construct before using
19031 // builtin/overloaded operators.
19032 CXXCastPath BasePath;
19033 ExprResult DeclareReductionRef = buildDeclareReductionRef(
19034 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
19035 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
19036 if (DeclareReductionRef.isInvalid())
19037 continue;
19038 if (S.CurContext->isDependentContext() &&
19039 (DeclareReductionRef.isUnset() ||
19040 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
19041 RD.push(RefExpr, DeclareReductionRef.get());
19042 continue;
19044 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
19045 // Not allowed reduction identifier is found.
19046 S.Diag(ReductionId.getBeginLoc(),
19047 diag::err_omp_unknown_reduction_identifier)
19048 << Type << ReductionIdRange;
19049 continue;
19052 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19053 // The type of a list item that appears in a reduction clause must be valid
19054 // for the reduction-identifier. For a max or min reduction in C, the type
19055 // of the list item must be an allowed arithmetic data type: char, int,
19056 // float, double, or _Bool, possibly modified with long, short, signed, or
19057 // unsigned. For a max or min reduction in C++, the type of the list item
19058 // must be an allowed arithmetic data type: char, wchar_t, int, float,
19059 // double, or bool, possibly modified with long, short, signed, or unsigned.
19060 if (DeclareReductionRef.isUnset()) {
19061 if ((BOK == BO_GT || BOK == BO_LT) &&
19062 !(Type->isScalarType() ||
19063 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
19064 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
19065 << getOpenMPClauseName(ClauseKind) << S.getLangOpts().CPlusPlus;
19066 if (!ASE && !OASE) {
19067 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19068 VarDecl::DeclarationOnly;
19069 S.Diag(D->getLocation(),
19070 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19071 << D;
19073 continue;
19075 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
19076 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
19077 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
19078 << getOpenMPClauseName(ClauseKind);
19079 if (!ASE && !OASE) {
19080 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19081 VarDecl::DeclarationOnly;
19082 S.Diag(D->getLocation(),
19083 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19084 << D;
19086 continue;
19090 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
19091 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
19092 D->hasAttrs() ? &D->getAttrs() : nullptr);
19093 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
19094 D->hasAttrs() ? &D->getAttrs() : nullptr);
19095 QualType PrivateTy = Type;
19097 // Try if we can determine constant lengths for all array sections and avoid
19098 // the VLA.
19099 bool ConstantLengthOASE = false;
19100 if (OASE) {
19101 bool SingleElement;
19102 llvm::SmallVector<llvm::APSInt, 4> ArraySizes;
19103 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
19104 Context, OASE, SingleElement, ArraySizes);
19106 // If we don't have a single element, we must emit a constant array type.
19107 if (ConstantLengthOASE && !SingleElement) {
19108 for (llvm::APSInt &Size : ArraySizes)
19109 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
19110 ArrayType::Normal,
19111 /*IndexTypeQuals=*/0);
19115 if ((OASE && !ConstantLengthOASE) ||
19116 (!OASE && !ASE &&
19117 D->getType().getNonReferenceType()->isVariablyModifiedType())) {
19118 if (!Context.getTargetInfo().isVLASupported()) {
19119 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
19120 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19121 S.Diag(ELoc, diag::note_vla_unsupported);
19122 continue;
19123 } else {
19124 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19125 S.targetDiag(ELoc, diag::note_vla_unsupported);
19128 // For arrays/array sections only:
19129 // Create pseudo array type for private copy. The size for this array will
19130 // be generated during codegen.
19131 // For array subscripts or single variables Private Ty is the same as Type
19132 // (type of the variable or single array element).
19133 PrivateTy = Context.getVariableArrayType(
19134 Type,
19135 new (Context)
19136 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
19137 ArrayType::Normal, /*IndexTypeQuals=*/0, SourceRange());
19138 } else if (!ASE && !OASE &&
19139 Context.getAsArrayType(D->getType().getNonReferenceType())) {
19140 PrivateTy = D->getType().getNonReferenceType();
19142 // Private copy.
19143 VarDecl *PrivateVD =
19144 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
19145 D->hasAttrs() ? &D->getAttrs() : nullptr,
19146 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19147 // Add initializer for private variable.
19148 Expr *Init = nullptr;
19149 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
19150 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
19151 if (DeclareReductionRef.isUsable()) {
19152 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
19153 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
19154 if (DRD->getInitializer()) {
19155 Init = DRDRef;
19156 RHSVD->setInit(DRDRef);
19157 RHSVD->setInitStyle(VarDecl::CallInit);
19159 } else {
19160 switch (BOK) {
19161 case BO_Add:
19162 case BO_Xor:
19163 case BO_Or:
19164 case BO_LOr:
19165 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
19166 if (Type->isScalarType() || Type->isAnyComplexType())
19167 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
19168 break;
19169 case BO_Mul:
19170 case BO_LAnd:
19171 if (Type->isScalarType() || Type->isAnyComplexType()) {
19172 // '*' and '&&' reduction ops - initializer is '1'.
19173 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
19175 break;
19176 case BO_And: {
19177 // '&' reduction op - initializer is '~0'.
19178 QualType OrigType = Type;
19179 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
19180 Type = ComplexTy->getElementType();
19181 if (Type->isRealFloatingType()) {
19182 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
19183 Context.getFloatTypeSemantics(Type));
19184 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
19185 Type, ELoc);
19186 } else if (Type->isScalarType()) {
19187 uint64_t Size = Context.getTypeSize(Type);
19188 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
19189 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
19190 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
19192 if (Init && OrigType->isAnyComplexType()) {
19193 // Init = 0xFFFF + 0xFFFFi;
19194 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
19195 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
19197 Type = OrigType;
19198 break;
19200 case BO_LT:
19201 case BO_GT: {
19202 // 'min' reduction op - initializer is 'Largest representable number in
19203 // the reduction list item type'.
19204 // 'max' reduction op - initializer is 'Least representable number in
19205 // the reduction list item type'.
19206 if (Type->isIntegerType() || Type->isPointerType()) {
19207 bool IsSigned = Type->hasSignedIntegerRepresentation();
19208 uint64_t Size = Context.getTypeSize(Type);
19209 QualType IntTy =
19210 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
19211 llvm::APInt InitValue =
19212 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
19213 : llvm::APInt::getMinValue(Size)
19214 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
19215 : llvm::APInt::getMaxValue(Size);
19216 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
19217 if (Type->isPointerType()) {
19218 // Cast to pointer type.
19219 ExprResult CastExpr = S.BuildCStyleCastExpr(
19220 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
19221 if (CastExpr.isInvalid())
19222 continue;
19223 Init = CastExpr.get();
19225 } else if (Type->isRealFloatingType()) {
19226 llvm::APFloat InitValue = llvm::APFloat::getLargest(
19227 Context.getFloatTypeSemantics(Type), BOK != BO_LT);
19228 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
19229 Type, ELoc);
19231 break;
19233 case BO_PtrMemD:
19234 case BO_PtrMemI:
19235 case BO_MulAssign:
19236 case BO_Div:
19237 case BO_Rem:
19238 case BO_Sub:
19239 case BO_Shl:
19240 case BO_Shr:
19241 case BO_LE:
19242 case BO_GE:
19243 case BO_EQ:
19244 case BO_NE:
19245 case BO_Cmp:
19246 case BO_AndAssign:
19247 case BO_XorAssign:
19248 case BO_OrAssign:
19249 case BO_Assign:
19250 case BO_AddAssign:
19251 case BO_SubAssign:
19252 case BO_DivAssign:
19253 case BO_RemAssign:
19254 case BO_ShlAssign:
19255 case BO_ShrAssign:
19256 case BO_Comma:
19257 llvm_unreachable("Unexpected reduction operation");
19260 if (Init && DeclareReductionRef.isUnset()) {
19261 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
19262 // Store initializer for single element in private copy. Will be used
19263 // during codegen.
19264 PrivateVD->setInit(RHSVD->getInit());
19265 PrivateVD->setInitStyle(RHSVD->getInitStyle());
19266 } else if (!Init) {
19267 S.ActOnUninitializedDecl(RHSVD);
19268 // Store initializer for single element in private copy. Will be used
19269 // during codegen.
19270 PrivateVD->setInit(RHSVD->getInit());
19271 PrivateVD->setInitStyle(RHSVD->getInitStyle());
19273 if (RHSVD->isInvalidDecl())
19274 continue;
19275 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
19276 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
19277 << Type << ReductionIdRange;
19278 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19279 VarDecl::DeclarationOnly;
19280 S.Diag(D->getLocation(),
19281 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19282 << D;
19283 continue;
19285 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
19286 ExprResult ReductionOp;
19287 if (DeclareReductionRef.isUsable()) {
19288 QualType RedTy = DeclareReductionRef.get()->getType();
19289 QualType PtrRedTy = Context.getPointerType(RedTy);
19290 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
19291 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
19292 if (!BasePath.empty()) {
19293 LHS = S.DefaultLvalueConversion(LHS.get());
19294 RHS = S.DefaultLvalueConversion(RHS.get());
19295 LHS = ImplicitCastExpr::Create(
19296 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
19297 LHS.get()->getValueKind(), FPOptionsOverride());
19298 RHS = ImplicitCastExpr::Create(
19299 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
19300 RHS.get()->getValueKind(), FPOptionsOverride());
19302 FunctionProtoType::ExtProtoInfo EPI;
19303 QualType Params[] = {PtrRedTy, PtrRedTy};
19304 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
19305 auto *OVE = new (Context) OpaqueValueExpr(
19306 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
19307 S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
19308 Expr *Args[] = {LHS.get(), RHS.get()};
19309 ReductionOp =
19310 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
19311 S.CurFPFeatureOverrides());
19312 } else {
19313 BinaryOperatorKind CombBOK = getRelatedCompoundReductionOp(BOK);
19314 if (Type->isRecordType() && CombBOK != BOK) {
19315 Sema::TentativeAnalysisScope Trap(S);
19316 ReductionOp =
19317 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19318 CombBOK, LHSDRE, RHSDRE);
19320 if (!ReductionOp.isUsable()) {
19321 ReductionOp =
19322 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
19323 LHSDRE, RHSDRE);
19324 if (ReductionOp.isUsable()) {
19325 if (BOK != BO_LT && BOK != BO_GT) {
19326 ReductionOp =
19327 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19328 BO_Assign, LHSDRE, ReductionOp.get());
19329 } else {
19330 auto *ConditionalOp = new (Context)
19331 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
19332 RHSDRE, Type, VK_LValue, OK_Ordinary);
19333 ReductionOp =
19334 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19335 BO_Assign, LHSDRE, ConditionalOp);
19339 if (ReductionOp.isUsable())
19340 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
19341 /*DiscardedValue*/ false);
19342 if (!ReductionOp.isUsable())
19343 continue;
19346 // Add copy operations for inscan reductions.
19347 // LHS = RHS;
19348 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
19349 if (ClauseKind == OMPC_reduction &&
19350 RD.RedModifier == OMPC_REDUCTION_inscan) {
19351 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
19352 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
19353 RHS.get());
19354 if (!CopyOpRes.isUsable())
19355 continue;
19356 CopyOpRes =
19357 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
19358 if (!CopyOpRes.isUsable())
19359 continue;
19360 // For simd directive and simd-based directives in simd mode no need to
19361 // construct temp array, need just a single temp element.
19362 if (Stack->getCurrentDirective() == OMPD_simd ||
19363 (S.getLangOpts().OpenMPSimd &&
19364 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
19365 VarDecl *TempArrayVD =
19366 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
19367 D->hasAttrs() ? &D->getAttrs() : nullptr);
19368 // Add a constructor to the temp decl.
19369 S.ActOnUninitializedDecl(TempArrayVD);
19370 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
19371 } else {
19372 // Build temp array for prefix sum.
19373 auto *Dim = new (S.Context)
19374 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
19375 QualType ArrayTy =
19376 S.Context.getVariableArrayType(PrivateTy, Dim, ArrayType::Normal,
19377 /*IndexTypeQuals=*/0, {ELoc, ELoc});
19378 VarDecl *TempArrayVD =
19379 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
19380 D->hasAttrs() ? &D->getAttrs() : nullptr);
19381 // Add a constructor to the temp decl.
19382 S.ActOnUninitializedDecl(TempArrayVD);
19383 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
19384 TempArrayElem =
19385 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
19386 auto *Idx = new (S.Context)
19387 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
19388 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
19389 ELoc, Idx, ELoc);
19393 // OpenMP [2.15.4.6, Restrictions, p.2]
19394 // A list item that appears in an in_reduction clause of a task construct
19395 // must appear in a task_reduction clause of a construct associated with a
19396 // taskgroup region that includes the participating task in its taskgroup
19397 // set. The construct associated with the innermost region that meets this
19398 // condition must specify the same reduction-identifier as the in_reduction
19399 // clause.
19400 if (ClauseKind == OMPC_in_reduction) {
19401 SourceRange ParentSR;
19402 BinaryOperatorKind ParentBOK;
19403 const Expr *ParentReductionOp = nullptr;
19404 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
19405 DSAStackTy::DSAVarData ParentBOKDSA =
19406 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
19407 ParentBOKTD);
19408 DSAStackTy::DSAVarData ParentReductionOpDSA =
19409 Stack->getTopMostTaskgroupReductionData(
19410 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
19411 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
19412 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
19413 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
19414 (DeclareReductionRef.isUsable() && IsParentBOK) ||
19415 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
19416 bool EmitError = true;
19417 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
19418 llvm::FoldingSetNodeID RedId, ParentRedId;
19419 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
19420 DeclareReductionRef.get()->Profile(RedId, Context,
19421 /*Canonical=*/true);
19422 EmitError = RedId != ParentRedId;
19424 if (EmitError) {
19425 S.Diag(ReductionId.getBeginLoc(),
19426 diag::err_omp_reduction_identifier_mismatch)
19427 << ReductionIdRange << RefExpr->getSourceRange();
19428 S.Diag(ParentSR.getBegin(),
19429 diag::note_omp_previous_reduction_identifier)
19430 << ParentSR
19431 << (IsParentBOK ? ParentBOKDSA.RefExpr
19432 : ParentReductionOpDSA.RefExpr)
19433 ->getSourceRange();
19434 continue;
19437 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
19440 DeclRefExpr *Ref = nullptr;
19441 Expr *VarsExpr = RefExpr->IgnoreParens();
19442 if (!VD && !S.CurContext->isDependentContext()) {
19443 if (ASE || OASE) {
19444 TransformExprToCaptures RebuildToCapture(S, D);
19445 VarsExpr =
19446 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
19447 Ref = RebuildToCapture.getCapturedExpr();
19448 } else {
19449 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
19451 if (!S.isOpenMPCapturedDecl(D)) {
19452 RD.ExprCaptures.emplace_back(Ref->getDecl());
19453 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
19454 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
19455 if (!RefRes.isUsable())
19456 continue;
19457 ExprResult PostUpdateRes =
19458 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
19459 RefRes.get());
19460 if (!PostUpdateRes.isUsable())
19461 continue;
19462 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
19463 Stack->getCurrentDirective() == OMPD_taskgroup) {
19464 S.Diag(RefExpr->getExprLoc(),
19465 diag::err_omp_reduction_non_addressable_expression)
19466 << RefExpr->getSourceRange();
19467 continue;
19469 RD.ExprPostUpdates.emplace_back(
19470 S.IgnoredValueConversions(PostUpdateRes.get()).get());
19474 // All reduction items are still marked as reduction (to do not increase
19475 // code base size).
19476 unsigned Modifier = RD.RedModifier;
19477 // Consider task_reductions as reductions with task modifier. Required for
19478 // correct analysis of in_reduction clauses.
19479 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
19480 Modifier = OMPC_REDUCTION_task;
19481 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
19482 ASE || OASE);
19483 if (Modifier == OMPC_REDUCTION_task &&
19484 (CurrDir == OMPD_taskgroup ||
19485 ((isOpenMPParallelDirective(CurrDir) ||
19486 isOpenMPWorksharingDirective(CurrDir)) &&
19487 !isOpenMPSimdDirective(CurrDir)))) {
19488 if (DeclareReductionRef.isUsable())
19489 Stack->addTaskgroupReductionData(D, ReductionIdRange,
19490 DeclareReductionRef.get());
19491 else
19492 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
19494 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
19495 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
19496 TempArrayElem.get());
19498 return RD.Vars.empty();
19501 OMPClause *Sema::ActOnOpenMPReductionClause(
19502 ArrayRef<Expr *> VarList, OpenMPReductionClauseModifier Modifier,
19503 SourceLocation StartLoc, SourceLocation LParenLoc,
19504 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
19505 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19506 ArrayRef<Expr *> UnresolvedReductions) {
19507 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
19508 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
19509 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
19510 /*Last=*/OMPC_REDUCTION_unknown)
19511 << getOpenMPClauseName(OMPC_reduction);
19512 return nullptr;
19514 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
19515 // A reduction clause with the inscan reduction-modifier may only appear on a
19516 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
19517 // construct, a parallel worksharing-loop construct or a parallel
19518 // worksharing-loop SIMD construct.
19519 if (Modifier == OMPC_REDUCTION_inscan &&
19520 (DSAStack->getCurrentDirective() != OMPD_for &&
19521 DSAStack->getCurrentDirective() != OMPD_for_simd &&
19522 DSAStack->getCurrentDirective() != OMPD_simd &&
19523 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
19524 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
19525 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
19526 return nullptr;
19529 ReductionData RD(VarList.size(), Modifier);
19530 if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_reduction, VarList,
19531 StartLoc, LParenLoc, ColonLoc, EndLoc,
19532 ReductionIdScopeSpec, ReductionId,
19533 UnresolvedReductions, RD))
19534 return nullptr;
19536 return OMPReductionClause::Create(
19537 Context, StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc, Modifier,
19538 RD.Vars, ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId,
19539 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
19540 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
19541 buildPreInits(Context, RD.ExprCaptures),
19542 buildPostUpdate(*this, RD.ExprPostUpdates));
19545 OMPClause *Sema::ActOnOpenMPTaskReductionClause(
19546 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19547 SourceLocation ColonLoc, SourceLocation EndLoc,
19548 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19549 ArrayRef<Expr *> UnresolvedReductions) {
19550 ReductionData RD(VarList.size());
19551 if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_task_reduction, VarList,
19552 StartLoc, LParenLoc, ColonLoc, EndLoc,
19553 ReductionIdScopeSpec, ReductionId,
19554 UnresolvedReductions, RD))
19555 return nullptr;
19557 return OMPTaskReductionClause::Create(
19558 Context, StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19559 ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId,
19560 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
19561 buildPreInits(Context, RD.ExprCaptures),
19562 buildPostUpdate(*this, RD.ExprPostUpdates));
19565 OMPClause *Sema::ActOnOpenMPInReductionClause(
19566 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19567 SourceLocation ColonLoc, SourceLocation EndLoc,
19568 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19569 ArrayRef<Expr *> UnresolvedReductions) {
19570 ReductionData RD(VarList.size());
19571 if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_in_reduction, VarList,
19572 StartLoc, LParenLoc, ColonLoc, EndLoc,
19573 ReductionIdScopeSpec, ReductionId,
19574 UnresolvedReductions, RD))
19575 return nullptr;
19577 return OMPInReductionClause::Create(
19578 Context, StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19579 ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId,
19580 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
19581 buildPreInits(Context, RD.ExprCaptures),
19582 buildPostUpdate(*this, RD.ExprPostUpdates));
19585 bool Sema::CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
19586 SourceLocation LinLoc) {
19587 if ((!LangOpts.CPlusPlus && LinKind != OMPC_LINEAR_val) ||
19588 LinKind == OMPC_LINEAR_unknown) {
19589 Diag(LinLoc, diag::err_omp_wrong_linear_modifier) << LangOpts.CPlusPlus;
19590 return true;
19592 return false;
19595 bool Sema::CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc,
19596 OpenMPLinearClauseKind LinKind, QualType Type,
19597 bool IsDeclareSimd) {
19598 const auto *VD = dyn_cast_or_null<VarDecl>(D);
19599 // A variable must not have an incomplete type or a reference type.
19600 if (RequireCompleteType(ELoc, Type, diag::err_omp_linear_incomplete_type))
19601 return true;
19602 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
19603 !Type->isReferenceType()) {
19604 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
19605 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
19606 return true;
19608 Type = Type.getNonReferenceType();
19610 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19611 // A variable that is privatized must not have a const-qualified type
19612 // unless it is of class type with a mutable member. This restriction does
19613 // not apply to the firstprivate clause, nor to the linear clause on
19614 // declarative directives (like declare simd).
19615 if (!IsDeclareSimd &&
19616 rejectConstNotMutableType(*this, D, Type, OMPC_linear, ELoc))
19617 return true;
19619 // A list item must be of integral or pointer type.
19620 Type = Type.getUnqualifiedType().getCanonicalType();
19621 const auto *Ty = Type.getTypePtrOrNull();
19622 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
19623 !Ty->isIntegralType(Context) && !Ty->isPointerType())) {
19624 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
19625 if (D) {
19626 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19627 VarDecl::DeclarationOnly;
19628 Diag(D->getLocation(),
19629 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19630 << D;
19632 return true;
19634 return false;
19637 OMPClause *Sema::ActOnOpenMPLinearClause(
19638 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
19639 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
19640 SourceLocation LinLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
19641 SmallVector<Expr *, 8> Vars;
19642 SmallVector<Expr *, 8> Privates;
19643 SmallVector<Expr *, 8> Inits;
19644 SmallVector<Decl *, 4> ExprCaptures;
19645 SmallVector<Expr *, 4> ExprPostUpdates;
19646 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
19647 LinKind = OMPC_LINEAR_val;
19648 for (Expr *RefExpr : VarList) {
19649 assert(RefExpr && "NULL expr in OpenMP linear clause.");
19650 SourceLocation ELoc;
19651 SourceRange ERange;
19652 Expr *SimpleRefExpr = RefExpr;
19653 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
19654 if (Res.second) {
19655 // It will be analyzed later.
19656 Vars.push_back(RefExpr);
19657 Privates.push_back(nullptr);
19658 Inits.push_back(nullptr);
19660 ValueDecl *D = Res.first;
19661 if (!D)
19662 continue;
19664 QualType Type = D->getType();
19665 auto *VD = dyn_cast<VarDecl>(D);
19667 // OpenMP [2.14.3.7, linear clause]
19668 // A list-item cannot appear in more than one linear clause.
19669 // A list-item that appears in a linear clause cannot appear in any
19670 // other data-sharing attribute clause.
19671 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19672 if (DVar.RefExpr) {
19673 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
19674 << getOpenMPClauseName(OMPC_linear);
19675 reportOriginalDsa(*this, DSAStack, D, DVar);
19676 continue;
19679 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
19680 continue;
19681 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
19683 // Build private copy of original var.
19684 VarDecl *Private =
19685 buildVarDecl(*this, ELoc, Type, D->getName(),
19686 D->hasAttrs() ? &D->getAttrs() : nullptr,
19687 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19688 DeclRefExpr *PrivateRef = buildDeclRefExpr(*this, Private, Type, ELoc);
19689 // Build var to save initial value.
19690 VarDecl *Init = buildVarDecl(*this, ELoc, Type, ".linear.start");
19691 Expr *InitExpr;
19692 DeclRefExpr *Ref = nullptr;
19693 if (!VD && !CurContext->isDependentContext()) {
19694 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
19695 if (!isOpenMPCapturedDecl(D)) {
19696 ExprCaptures.push_back(Ref->getDecl());
19697 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
19698 ExprResult RefRes = DefaultLvalueConversion(Ref);
19699 if (!RefRes.isUsable())
19700 continue;
19701 ExprResult PostUpdateRes =
19702 BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
19703 SimpleRefExpr, RefRes.get());
19704 if (!PostUpdateRes.isUsable())
19705 continue;
19706 ExprPostUpdates.push_back(
19707 IgnoredValueConversions(PostUpdateRes.get()).get());
19711 if (LinKind == OMPC_LINEAR_uval)
19712 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
19713 else
19714 InitExpr = VD ? SimpleRefExpr : Ref;
19715 AddInitializerToDecl(Init, DefaultLvalueConversion(InitExpr).get(),
19716 /*DirectInit=*/false);
19717 DeclRefExpr *InitRef = buildDeclRefExpr(*this, Init, Type, ELoc);
19719 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
19720 Vars.push_back((VD || CurContext->isDependentContext())
19721 ? RefExpr->IgnoreParens()
19722 : Ref);
19723 Privates.push_back(PrivateRef);
19724 Inits.push_back(InitRef);
19727 if (Vars.empty())
19728 return nullptr;
19730 Expr *StepExpr = Step;
19731 Expr *CalcStepExpr = nullptr;
19732 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
19733 !Step->isInstantiationDependent() &&
19734 !Step->containsUnexpandedParameterPack()) {
19735 SourceLocation StepLoc = Step->getBeginLoc();
19736 ExprResult Val = PerformOpenMPImplicitIntegerConversion(StepLoc, Step);
19737 if (Val.isInvalid())
19738 return nullptr;
19739 StepExpr = Val.get();
19741 // Build var to save the step value.
19742 VarDecl *SaveVar =
19743 buildVarDecl(*this, StepLoc, StepExpr->getType(), ".linear.step");
19744 ExprResult SaveRef =
19745 buildDeclRefExpr(*this, SaveVar, StepExpr->getType(), StepLoc);
19746 ExprResult CalcStep =
19747 BuildBinOp(CurScope, StepLoc, BO_Assign, SaveRef.get(), StepExpr);
19748 CalcStep = ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue*/ false);
19750 // Warn about zero linear step (it would be probably better specified as
19751 // making corresponding variables 'const').
19752 if (Optional<llvm::APSInt> Result =
19753 StepExpr->getIntegerConstantExpr(Context)) {
19754 if (!Result->isNegative() && !Result->isStrictlyPositive())
19755 Diag(StepLoc, diag::warn_omp_linear_step_zero)
19756 << Vars[0] << (Vars.size() > 1);
19757 } else if (CalcStep.isUsable()) {
19758 // Calculate the step beforehand instead of doing this on each iteration.
19759 // (This is not used if the number of iterations may be kfold-ed).
19760 CalcStepExpr = CalcStep.get();
19764 return OMPLinearClause::Create(Context, StartLoc, LParenLoc, LinKind, LinLoc,
19765 ColonLoc, EndLoc, Vars, Privates, Inits,
19766 StepExpr, CalcStepExpr,
19767 buildPreInits(Context, ExprCaptures),
19768 buildPostUpdate(*this, ExprPostUpdates));
19771 static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
19772 Expr *NumIterations, Sema &SemaRef,
19773 Scope *S, DSAStackTy *Stack) {
19774 // Walk the vars and build update/final expressions for the CodeGen.
19775 SmallVector<Expr *, 8> Updates;
19776 SmallVector<Expr *, 8> Finals;
19777 SmallVector<Expr *, 8> UsedExprs;
19778 Expr *Step = Clause.getStep();
19779 Expr *CalcStep = Clause.getCalcStep();
19780 // OpenMP [2.14.3.7, linear clause]
19781 // If linear-step is not specified it is assumed to be 1.
19782 if (!Step)
19783 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
19784 else if (CalcStep)
19785 Step = cast<BinaryOperator>(CalcStep)->getLHS();
19786 bool HasErrors = false;
19787 auto CurInit = Clause.inits().begin();
19788 auto CurPrivate = Clause.privates().begin();
19789 OpenMPLinearClauseKind LinKind = Clause.getModifier();
19790 for (Expr *RefExpr : Clause.varlists()) {
19791 SourceLocation ELoc;
19792 SourceRange ERange;
19793 Expr *SimpleRefExpr = RefExpr;
19794 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19795 ValueDecl *D = Res.first;
19796 if (Res.second || !D) {
19797 Updates.push_back(nullptr);
19798 Finals.push_back(nullptr);
19799 HasErrors = true;
19800 continue;
19802 auto &&Info = Stack->isLoopControlVariable(D);
19803 // OpenMP [2.15.11, distribute simd Construct]
19804 // A list item may not appear in a linear clause, unless it is the loop
19805 // iteration variable.
19806 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
19807 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
19808 SemaRef.Diag(ELoc,
19809 diag::err_omp_linear_distribute_var_non_loop_iteration);
19810 Updates.push_back(nullptr);
19811 Finals.push_back(nullptr);
19812 HasErrors = true;
19813 continue;
19815 Expr *InitExpr = *CurInit;
19817 // Build privatized reference to the current linear var.
19818 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
19819 Expr *CapturedRef;
19820 if (LinKind == OMPC_LINEAR_uval)
19821 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
19822 else
19823 CapturedRef =
19824 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
19825 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
19826 /*RefersToCapture=*/true);
19828 // Build update: Var = InitExpr + IV * Step
19829 ExprResult Update;
19830 if (!Info.first)
19831 Update = buildCounterUpdate(
19832 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
19833 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
19834 else
19835 Update = *CurPrivate;
19836 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
19837 /*DiscardedValue*/ false);
19839 // Build final: Var = PrivCopy;
19840 ExprResult Final;
19841 if (!Info.first)
19842 Final = SemaRef.BuildBinOp(
19843 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
19844 SemaRef.DefaultLvalueConversion(*CurPrivate).get());
19845 else
19846 Final = *CurPrivate;
19847 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
19848 /*DiscardedValue*/ false);
19850 if (!Update.isUsable() || !Final.isUsable()) {
19851 Updates.push_back(nullptr);
19852 Finals.push_back(nullptr);
19853 UsedExprs.push_back(nullptr);
19854 HasErrors = true;
19855 } else {
19856 Updates.push_back(Update.get());
19857 Finals.push_back(Final.get());
19858 if (!Info.first)
19859 UsedExprs.push_back(SimpleRefExpr);
19861 ++CurInit;
19862 ++CurPrivate;
19864 if (Expr *S = Clause.getStep())
19865 UsedExprs.push_back(S);
19866 // Fill the remaining part with the nullptr.
19867 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
19868 Clause.setUpdates(Updates);
19869 Clause.setFinals(Finals);
19870 Clause.setUsedExprs(UsedExprs);
19871 return HasErrors;
19874 OMPClause *Sema::ActOnOpenMPAlignedClause(
19875 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
19876 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
19877 SmallVector<Expr *, 8> Vars;
19878 for (Expr *RefExpr : VarList) {
19879 assert(RefExpr && "NULL expr in OpenMP linear clause.");
19880 SourceLocation ELoc;
19881 SourceRange ERange;
19882 Expr *SimpleRefExpr = RefExpr;
19883 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
19884 if (Res.second) {
19885 // It will be analyzed later.
19886 Vars.push_back(RefExpr);
19888 ValueDecl *D = Res.first;
19889 if (!D)
19890 continue;
19892 QualType QType = D->getType();
19893 auto *VD = dyn_cast<VarDecl>(D);
19895 // OpenMP [2.8.1, simd construct, Restrictions]
19896 // The type of list items appearing in the aligned clause must be
19897 // array, pointer, reference to array, or reference to pointer.
19898 QType = QType.getNonReferenceType().getUnqualifiedType().getCanonicalType();
19899 const Type *Ty = QType.getTypePtrOrNull();
19900 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
19901 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
19902 << QType << getLangOpts().CPlusPlus << ERange;
19903 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19904 VarDecl::DeclarationOnly;
19905 Diag(D->getLocation(),
19906 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19907 << D;
19908 continue;
19911 // OpenMP [2.8.1, simd construct, Restrictions]
19912 // A list-item cannot appear in more than one aligned clause.
19913 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
19914 Diag(ELoc, diag::err_omp_used_in_clause_twice)
19915 << 0 << getOpenMPClauseName(OMPC_aligned) << ERange;
19916 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
19917 << getOpenMPClauseName(OMPC_aligned);
19918 continue;
19921 DeclRefExpr *Ref = nullptr;
19922 if (!VD && isOpenMPCapturedDecl(D))
19923 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
19924 Vars.push_back(DefaultFunctionArrayConversion(
19925 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
19926 .get());
19929 // OpenMP [2.8.1, simd construct, Description]
19930 // The parameter of the aligned clause, alignment, must be a constant
19931 // positive integer expression.
19932 // If no optional parameter is specified, implementation-defined default
19933 // alignments for SIMD instructions on the target platforms are assumed.
19934 if (Alignment != nullptr) {
19935 ExprResult AlignResult =
19936 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
19937 if (AlignResult.isInvalid())
19938 return nullptr;
19939 Alignment = AlignResult.get();
19941 if (Vars.empty())
19942 return nullptr;
19944 return OMPAlignedClause::Create(Context, StartLoc, LParenLoc, ColonLoc,
19945 EndLoc, Vars, Alignment);
19948 OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
19949 SourceLocation StartLoc,
19950 SourceLocation LParenLoc,
19951 SourceLocation EndLoc) {
19952 SmallVector<Expr *, 8> Vars;
19953 SmallVector<Expr *, 8> SrcExprs;
19954 SmallVector<Expr *, 8> DstExprs;
19955 SmallVector<Expr *, 8> AssignmentOps;
19956 for (Expr *RefExpr : VarList) {
19957 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
19958 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19959 // It will be analyzed later.
19960 Vars.push_back(RefExpr);
19961 SrcExprs.push_back(nullptr);
19962 DstExprs.push_back(nullptr);
19963 AssignmentOps.push_back(nullptr);
19964 continue;
19967 SourceLocation ELoc = RefExpr->getExprLoc();
19968 // OpenMP [2.1, C/C++]
19969 // A list item is a variable name.
19970 // OpenMP [2.14.4.1, Restrictions, p.1]
19971 // A list item that appears in a copyin clause must be threadprivate.
19972 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
19973 if (!DE || !isa<VarDecl>(DE->getDecl())) {
19974 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
19975 << 0 << RefExpr->getSourceRange();
19976 continue;
19979 Decl *D = DE->getDecl();
19980 auto *VD = cast<VarDecl>(D);
19982 QualType Type = VD->getType();
19983 if (Type->isDependentType() || Type->isInstantiationDependentType()) {
19984 // It will be analyzed later.
19985 Vars.push_back(DE);
19986 SrcExprs.push_back(nullptr);
19987 DstExprs.push_back(nullptr);
19988 AssignmentOps.push_back(nullptr);
19989 continue;
19992 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
19993 // A list item that appears in a copyin clause must be threadprivate.
19994 if (!DSAStack->isThreadPrivate(VD)) {
19995 Diag(ELoc, diag::err_omp_required_access)
19996 << getOpenMPClauseName(OMPC_copyin)
19997 << getOpenMPDirectiveName(OMPD_threadprivate);
19998 continue;
20001 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20002 // A variable of class type (or array thereof) that appears in a
20003 // copyin clause requires an accessible, unambiguous copy assignment
20004 // operator for the class type.
20005 QualType ElemType = Context.getBaseElementType(Type).getNonReferenceType();
20006 VarDecl *SrcVD =
20007 buildVarDecl(*this, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
20008 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20009 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
20010 *this, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
20011 VarDecl *DstVD =
20012 buildVarDecl(*this, DE->getBeginLoc(), ElemType, ".copyin.dst",
20013 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20014 DeclRefExpr *PseudoDstExpr =
20015 buildDeclRefExpr(*this, DstVD, ElemType, DE->getExprLoc());
20016 // For arrays generate assignment operation for single element and replace
20017 // it by the original array element in CodeGen.
20018 ExprResult AssignmentOp =
20019 BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign, PseudoDstExpr,
20020 PseudoSrcExpr);
20021 if (AssignmentOp.isInvalid())
20022 continue;
20023 AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
20024 /*DiscardedValue*/ false);
20025 if (AssignmentOp.isInvalid())
20026 continue;
20028 DSAStack->addDSA(VD, DE, OMPC_copyin);
20029 Vars.push_back(DE);
20030 SrcExprs.push_back(PseudoSrcExpr);
20031 DstExprs.push_back(PseudoDstExpr);
20032 AssignmentOps.push_back(AssignmentOp.get());
20035 if (Vars.empty())
20036 return nullptr;
20038 return OMPCopyinClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars,
20039 SrcExprs, DstExprs, AssignmentOps);
20042 OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
20043 SourceLocation StartLoc,
20044 SourceLocation LParenLoc,
20045 SourceLocation EndLoc) {
20046 SmallVector<Expr *, 8> Vars;
20047 SmallVector<Expr *, 8> SrcExprs;
20048 SmallVector<Expr *, 8> DstExprs;
20049 SmallVector<Expr *, 8> AssignmentOps;
20050 for (Expr *RefExpr : VarList) {
20051 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20052 SourceLocation ELoc;
20053 SourceRange ERange;
20054 Expr *SimpleRefExpr = RefExpr;
20055 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
20056 if (Res.second) {
20057 // It will be analyzed later.
20058 Vars.push_back(RefExpr);
20059 SrcExprs.push_back(nullptr);
20060 DstExprs.push_back(nullptr);
20061 AssignmentOps.push_back(nullptr);
20063 ValueDecl *D = Res.first;
20064 if (!D)
20065 continue;
20067 QualType Type = D->getType();
20068 auto *VD = dyn_cast<VarDecl>(D);
20070 // OpenMP [2.14.4.2, Restrictions, p.2]
20071 // A list item that appears in a copyprivate clause may not appear in a
20072 // private or firstprivate clause on the single construct.
20073 if (!VD || !DSAStack->isThreadPrivate(VD)) {
20074 DSAStackTy::DSAVarData DVar =
20075 DSAStack->getTopDSA(D, /*FromParent=*/false);
20076 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
20077 DVar.RefExpr) {
20078 Diag(ELoc, diag::err_omp_wrong_dsa)
20079 << getOpenMPClauseName(DVar.CKind)
20080 << getOpenMPClauseName(OMPC_copyprivate);
20081 reportOriginalDsa(*this, DSAStack, D, DVar);
20082 continue;
20085 // OpenMP [2.11.4.2, Restrictions, p.1]
20086 // All list items that appear in a copyprivate clause must be either
20087 // threadprivate or private in the enclosing context.
20088 if (DVar.CKind == OMPC_unknown) {
20089 DVar = DSAStack->getImplicitDSA(D, false);
20090 if (DVar.CKind == OMPC_shared) {
20091 Diag(ELoc, diag::err_omp_required_access)
20092 << getOpenMPClauseName(OMPC_copyprivate)
20093 << "threadprivate or private in the enclosing context";
20094 reportOriginalDsa(*this, DSAStack, D, DVar);
20095 continue;
20100 // Variably modified types are not supported.
20101 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType()) {
20102 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
20103 << getOpenMPClauseName(OMPC_copyprivate) << Type
20104 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
20105 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20106 VarDecl::DeclarationOnly;
20107 Diag(D->getLocation(),
20108 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20109 << D;
20110 continue;
20113 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20114 // A variable of class type (or array thereof) that appears in a
20115 // copyin clause requires an accessible, unambiguous copy assignment
20116 // operator for the class type.
20117 Type = Context.getBaseElementType(Type.getNonReferenceType())
20118 .getUnqualifiedType();
20119 VarDecl *SrcVD =
20120 buildVarDecl(*this, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
20121 D->hasAttrs() ? &D->getAttrs() : nullptr);
20122 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(*this, SrcVD, Type, ELoc);
20123 VarDecl *DstVD =
20124 buildVarDecl(*this, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
20125 D->hasAttrs() ? &D->getAttrs() : nullptr);
20126 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc);
20127 ExprResult AssignmentOp = BuildBinOp(
20128 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
20129 if (AssignmentOp.isInvalid())
20130 continue;
20131 AssignmentOp =
20132 ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false);
20133 if (AssignmentOp.isInvalid())
20134 continue;
20136 // No need to mark vars as copyprivate, they are already threadprivate or
20137 // implicitly private.
20138 assert(VD || isOpenMPCapturedDecl(D));
20139 Vars.push_back(
20140 VD ? RefExpr->IgnoreParens()
20141 : buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false));
20142 SrcExprs.push_back(PseudoSrcExpr);
20143 DstExprs.push_back(PseudoDstExpr);
20144 AssignmentOps.push_back(AssignmentOp.get());
20147 if (Vars.empty())
20148 return nullptr;
20150 return OMPCopyprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
20151 Vars, SrcExprs, DstExprs, AssignmentOps);
20154 OMPClause *Sema::ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList,
20155 SourceLocation StartLoc,
20156 SourceLocation LParenLoc,
20157 SourceLocation EndLoc) {
20158 if (VarList.empty())
20159 return nullptr;
20161 return OMPFlushClause::Create(Context, StartLoc, LParenLoc, EndLoc, VarList);
20164 /// Tries to find omp_depend_t. type.
20165 static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
20166 bool Diagnose = true) {
20167 QualType OMPDependT = Stack->getOMPDependT();
20168 if (!OMPDependT.isNull())
20169 return true;
20170 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
20171 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
20172 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
20173 if (Diagnose)
20174 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
20175 return false;
20177 Stack->setOMPDependT(PT.get());
20178 return true;
20181 OMPClause *Sema::ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc,
20182 SourceLocation LParenLoc,
20183 SourceLocation EndLoc) {
20184 if (!Depobj)
20185 return nullptr;
20187 bool OMPDependTFound = findOMPDependT(*this, StartLoc, DSAStack);
20189 // OpenMP 5.0, 2.17.10.1 depobj Construct
20190 // depobj is an lvalue expression of type omp_depend_t.
20191 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
20192 !Depobj->isInstantiationDependent() &&
20193 !Depobj->containsUnexpandedParameterPack() &&
20194 (OMPDependTFound &&
20195 !Context.typesAreCompatible(DSAStack->getOMPDependT(), Depobj->getType(),
20196 /*CompareUnqualified=*/true))) {
20197 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20198 << 0 << Depobj->getType() << Depobj->getSourceRange();
20201 if (!Depobj->isLValue()) {
20202 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20203 << 1 << Depobj->getSourceRange();
20206 return OMPDepobjClause::Create(Context, StartLoc, LParenLoc, EndLoc, Depobj);
20209 OMPClause *
20210 Sema::ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data,
20211 Expr *DepModifier, ArrayRef<Expr *> VarList,
20212 SourceLocation StartLoc, SourceLocation LParenLoc,
20213 SourceLocation EndLoc) {
20214 OpenMPDependClauseKind DepKind = Data.DepKind;
20215 SourceLocation DepLoc = Data.DepLoc;
20216 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
20217 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
20218 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20219 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
20220 return nullptr;
20222 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
20223 DepKind == OMPC_DEPEND_mutexinoutset) {
20224 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
20225 return nullptr;
20227 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
20228 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20229 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
20230 DepKind == OMPC_DEPEND_sink ||
20231 ((LangOpts.OpenMP < 50 ||
20232 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20233 DepKind == OMPC_DEPEND_depobj))) {
20234 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
20235 OMPC_DEPEND_outallmemory,
20236 OMPC_DEPEND_inoutallmemory};
20237 if (LangOpts.OpenMP < 50 || DSAStack->getCurrentDirective() == OMPD_depobj)
20238 Except.push_back(OMPC_DEPEND_depobj);
20239 if (LangOpts.OpenMP < 51)
20240 Except.push_back(OMPC_DEPEND_inoutset);
20241 std::string Expected = (LangOpts.OpenMP >= 50 && !DepModifier)
20242 ? "depend modifier(iterator) or "
20243 : "";
20244 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20245 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
20246 /*Last=*/OMPC_DEPEND_unknown,
20247 Except)
20248 << getOpenMPClauseName(OMPC_depend);
20249 return nullptr;
20251 if (DepModifier &&
20252 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
20253 Diag(DepModifier->getExprLoc(),
20254 diag::err_omp_depend_sink_source_with_modifier);
20255 return nullptr;
20257 if (DepModifier &&
20258 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
20259 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
20261 SmallVector<Expr *, 8> Vars;
20262 DSAStackTy::OperatorOffsetTy OpsOffs;
20263 llvm::APSInt DepCounter(/*BitWidth=*/32);
20264 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
20265 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
20266 if (const Expr *OrderedCountExpr =
20267 DSAStack->getParentOrderedRegionParam().first) {
20268 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(Context);
20269 TotalDepCount.setIsUnsigned(/*Val=*/true);
20272 for (Expr *RefExpr : VarList) {
20273 assert(RefExpr && "NULL expr in OpenMP shared clause.");
20274 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20275 // It will be analyzed later.
20276 Vars.push_back(RefExpr);
20277 continue;
20280 SourceLocation ELoc = RefExpr->getExprLoc();
20281 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
20282 if (DepKind == OMPC_DEPEND_sink) {
20283 if (DSAStack->getParentOrderedRegionParam().first &&
20284 DepCounter >= TotalDepCount) {
20285 Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
20286 continue;
20288 ++DepCounter;
20289 // OpenMP [2.13.9, Summary]
20290 // depend(dependence-type : vec), where dependence-type is:
20291 // 'sink' and where vec is the iteration vector, which has the form:
20292 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
20293 // where n is the value specified by the ordered clause in the loop
20294 // directive, xi denotes the loop iteration variable of the i-th nested
20295 // loop associated with the loop directive, and di is a constant
20296 // non-negative integer.
20297 if (CurContext->isDependentContext()) {
20298 // It will be analyzed later.
20299 Vars.push_back(RefExpr);
20300 continue;
20302 SimpleExpr = SimpleExpr->IgnoreImplicit();
20303 OverloadedOperatorKind OOK = OO_None;
20304 SourceLocation OOLoc;
20305 Expr *LHS = SimpleExpr;
20306 Expr *RHS = nullptr;
20307 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
20308 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
20309 OOLoc = BO->getOperatorLoc();
20310 LHS = BO->getLHS()->IgnoreParenImpCasts();
20311 RHS = BO->getRHS()->IgnoreParenImpCasts();
20312 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
20313 OOK = OCE->getOperator();
20314 OOLoc = OCE->getOperatorLoc();
20315 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20316 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
20317 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
20318 OOK = MCE->getMethodDecl()
20319 ->getNameInfo()
20320 .getName()
20321 .getCXXOverloadedOperator();
20322 OOLoc = MCE->getCallee()->getExprLoc();
20323 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
20324 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20326 SourceLocation ELoc;
20327 SourceRange ERange;
20328 auto Res = getPrivateItem(*this, LHS, ELoc, ERange);
20329 if (Res.second) {
20330 // It will be analyzed later.
20331 Vars.push_back(RefExpr);
20333 ValueDecl *D = Res.first;
20334 if (!D)
20335 continue;
20337 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
20338 Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
20339 continue;
20341 if (RHS) {
20342 ExprResult RHSRes = VerifyPositiveIntegerConstantInClause(
20343 RHS, OMPC_depend, /*StrictlyPositive=*/false);
20344 if (RHSRes.isInvalid())
20345 continue;
20347 if (!CurContext->isDependentContext() &&
20348 DSAStack->getParentOrderedRegionParam().first &&
20349 DepCounter != DSAStack->isParentLoopControlVariable(D).first) {
20350 const ValueDecl *VD =
20351 DSAStack->getParentLoopControlVariable(DepCounter.getZExtValue());
20352 if (VD)
20353 Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
20354 << 1 << VD;
20355 else
20356 Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration) << 0;
20357 continue;
20359 OpsOffs.emplace_back(RHS, OOK);
20360 } else {
20361 bool OMPDependTFound = LangOpts.OpenMP >= 50;
20362 if (OMPDependTFound)
20363 OMPDependTFound = findOMPDependT(*this, StartLoc, DSAStack,
20364 DepKind == OMPC_DEPEND_depobj);
20365 if (DepKind == OMPC_DEPEND_depobj) {
20366 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20367 // List items used in depend clauses with the depobj dependence type
20368 // must be expressions of the omp_depend_t type.
20369 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20370 !RefExpr->isInstantiationDependent() &&
20371 !RefExpr->containsUnexpandedParameterPack() &&
20372 (OMPDependTFound &&
20373 !Context.hasSameUnqualifiedType(DSAStack->getOMPDependT(),
20374 RefExpr->getType()))) {
20375 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20376 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
20377 continue;
20379 if (!RefExpr->isLValue()) {
20380 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20381 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
20382 continue;
20384 } else {
20385 // OpenMP 5.0 [2.17.11, Restrictions]
20386 // List items used in depend clauses cannot be zero-length array
20387 // sections.
20388 QualType ExprTy = RefExpr->getType().getNonReferenceType();
20389 const auto *OASE = dyn_cast<OMPArraySectionExpr>(SimpleExpr);
20390 if (OASE) {
20391 QualType BaseType =
20392 OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
20393 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20394 ExprTy = ATy->getElementType();
20395 else
20396 ExprTy = BaseType->getPointeeType();
20397 ExprTy = ExprTy.getNonReferenceType();
20398 const Expr *Length = OASE->getLength();
20399 Expr::EvalResult Result;
20400 if (Length && !Length->isValueDependent() &&
20401 Length->EvaluateAsInt(Result, Context) &&
20402 Result.Val.getInt().isZero()) {
20403 Diag(ELoc,
20404 diag::err_omp_depend_zero_length_array_section_not_allowed)
20405 << SimpleExpr->getSourceRange();
20406 continue;
20410 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20411 // List items used in depend clauses with the in, out, inout,
20412 // inoutset, or mutexinoutset dependence types cannot be
20413 // expressions of the omp_depend_t type.
20414 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20415 !RefExpr->isInstantiationDependent() &&
20416 !RefExpr->containsUnexpandedParameterPack() &&
20417 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
20418 (OMPDependTFound &&
20419 DSAStack->getOMPDependT().getTypePtr() == ExprTy.getTypePtr()))) {
20420 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20421 << (LangOpts.OpenMP >= 50 ? 1 : 0)
20422 << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
20423 continue;
20426 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
20427 if (ASE && !ASE->getBase()->isTypeDependent() &&
20428 !ASE->getBase()->getType().getNonReferenceType()->isPointerType() &&
20429 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
20430 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20431 << (LangOpts.OpenMP >= 50 ? 1 : 0)
20432 << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
20433 continue;
20436 ExprResult Res;
20438 Sema::TentativeAnalysisScope Trap(*this);
20439 Res = CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
20440 RefExpr->IgnoreParenImpCasts());
20442 if (!Res.isUsable() && !isa<OMPArraySectionExpr>(SimpleExpr) &&
20443 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
20444 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20445 << (LangOpts.OpenMP >= 50 ? 1 : 0)
20446 << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
20447 continue;
20451 Vars.push_back(RefExpr->IgnoreParenImpCasts());
20454 if (!CurContext->isDependentContext() && DepKind == OMPC_DEPEND_sink &&
20455 TotalDepCount > VarList.size() &&
20456 DSAStack->getParentOrderedRegionParam().first &&
20457 DSAStack->getParentLoopControlVariable(VarList.size() + 1)) {
20458 Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
20459 << 1 << DSAStack->getParentLoopControlVariable(VarList.size() + 1);
20461 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
20462 DepKind != OMPC_DEPEND_outallmemory &&
20463 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
20464 return nullptr;
20466 auto *C = OMPDependClause::Create(
20467 Context, StartLoc, LParenLoc, EndLoc,
20468 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
20469 TotalDepCount.getZExtValue());
20470 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
20471 DSAStack->isParentOrderedRegion())
20472 DSAStack->addDoacrossDependClause(C, OpsOffs);
20473 return C;
20476 OMPClause *Sema::ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier,
20477 Expr *Device, SourceLocation StartLoc,
20478 SourceLocation LParenLoc,
20479 SourceLocation ModifierLoc,
20480 SourceLocation EndLoc) {
20481 assert((ModifierLoc.isInvalid() || LangOpts.OpenMP >= 50) &&
20482 "Unexpected device modifier in OpenMP < 50.");
20484 bool ErrorFound = false;
20485 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
20486 std::string Values =
20487 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
20488 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
20489 << Values << getOpenMPClauseName(OMPC_device);
20490 ErrorFound = true;
20493 Expr *ValExpr = Device;
20494 Stmt *HelperValStmt = nullptr;
20496 // OpenMP [2.9.1, Restrictions]
20497 // The device expression must evaluate to a non-negative integer value.
20498 ErrorFound = !isNonNegativeIntegerValue(ValExpr, *this, OMPC_device,
20499 /*StrictlyPositive=*/false) ||
20500 ErrorFound;
20501 if (ErrorFound)
20502 return nullptr;
20504 // OpenMP 5.0 [2.12.5, Restrictions]
20505 // In case of ancestor device-modifier, a requires directive with
20506 // the reverse_offload clause must be specified.
20507 if (Modifier == OMPC_DEVICE_ancestor) {
20508 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
20509 targetDiag(
20510 StartLoc,
20511 diag::err_omp_device_ancestor_without_requires_reverse_offload);
20512 ErrorFound = true;
20516 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
20517 OpenMPDirectiveKind CaptureRegion =
20518 getOpenMPCaptureRegionForClause(DKind, OMPC_device, LangOpts.OpenMP);
20519 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
20520 ValExpr = MakeFullExpr(ValExpr).get();
20521 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20522 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
20523 HelperValStmt = buildPreInits(Context, Captures);
20526 return new (Context)
20527 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
20528 LParenLoc, ModifierLoc, EndLoc);
20531 static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef,
20532 DSAStackTy *Stack, QualType QTy,
20533 bool FullCheck = true) {
20534 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
20535 return false;
20536 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
20537 !QTy.isTriviallyCopyableType(SemaRef.Context))
20538 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
20539 return true;
20542 /// Return true if it can be proven that the provided array expression
20543 /// (array section or array subscript) does NOT specify the whole size of the
20544 /// array whose base type is \a BaseQTy.
20545 static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
20546 const Expr *E,
20547 QualType BaseQTy) {
20548 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
20550 // If this is an array subscript, it refers to the whole size if the size of
20551 // the dimension is constant and equals 1. Also, an array section assumes the
20552 // format of an array subscript if no colon is used.
20553 if (isa<ArraySubscriptExpr>(E) ||
20554 (OASE && OASE->getColonLocFirst().isInvalid())) {
20555 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
20556 return ATy->getSize().getSExtValue() != 1;
20557 // Size can't be evaluated statically.
20558 return false;
20561 assert(OASE && "Expecting array section if not an array subscript.");
20562 const Expr *LowerBound = OASE->getLowerBound();
20563 const Expr *Length = OASE->getLength();
20565 // If there is a lower bound that does not evaluates to zero, we are not
20566 // covering the whole dimension.
20567 if (LowerBound) {
20568 Expr::EvalResult Result;
20569 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
20570 return false; // Can't get the integer value as a constant.
20572 llvm::APSInt ConstLowerBound = Result.Val.getInt();
20573 if (ConstLowerBound.getSExtValue())
20574 return true;
20577 // If we don't have a length we covering the whole dimension.
20578 if (!Length)
20579 return false;
20581 // If the base is a pointer, we don't have a way to get the size of the
20582 // pointee.
20583 if (BaseQTy->isPointerType())
20584 return false;
20586 // We can only check if the length is the same as the size of the dimension
20587 // if we have a constant array.
20588 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
20589 if (!CATy)
20590 return false;
20592 Expr::EvalResult Result;
20593 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
20594 return false; // Can't get the integer value as a constant.
20596 llvm::APSInt ConstLength = Result.Val.getInt();
20597 return CATy->getSize().getSExtValue() != ConstLength.getSExtValue();
20600 // Return true if it can be proven that the provided array expression (array
20601 // section or array subscript) does NOT specify a single element of the array
20602 // whose base type is \a BaseQTy.
20603 static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
20604 const Expr *E,
20605 QualType BaseQTy) {
20606 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
20608 // An array subscript always refer to a single element. Also, an array section
20609 // assumes the format of an array subscript if no colon is used.
20610 if (isa<ArraySubscriptExpr>(E) ||
20611 (OASE && OASE->getColonLocFirst().isInvalid()))
20612 return false;
20614 assert(OASE && "Expecting array section if not an array subscript.");
20615 const Expr *Length = OASE->getLength();
20617 // If we don't have a length we have to check if the array has unitary size
20618 // for this dimension. Also, we should always expect a length if the base type
20619 // is pointer.
20620 if (!Length) {
20621 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
20622 return ATy->getSize().getSExtValue() != 1;
20623 // We cannot assume anything.
20624 return false;
20627 // Check if the length evaluates to 1.
20628 Expr::EvalResult Result;
20629 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
20630 return false; // Can't get the integer value as a constant.
20632 llvm::APSInt ConstLength = Result.Val.getInt();
20633 return ConstLength.getSExtValue() != 1;
20636 // The base of elements of list in a map clause have to be either:
20637 // - a reference to variable or field.
20638 // - a member expression.
20639 // - an array expression.
20641 // E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
20642 // reference to 'r'.
20644 // If we have:
20646 // struct SS {
20647 // Bla S;
20648 // foo() {
20649 // #pragma omp target map (S.Arr[:12]);
20650 // }
20651 // }
20653 // We want to retrieve the member expression 'this->S';
20655 // OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
20656 // If a list item is an array section, it must specify contiguous storage.
20658 // For this restriction it is sufficient that we make sure only references
20659 // to variables or fields and array expressions, and that no array sections
20660 // exist except in the rightmost expression (unless they cover the whole
20661 // dimension of the array). E.g. these would be invalid:
20663 // r.ArrS[3:5].Arr[6:7]
20665 // r.ArrS[3:5].x
20667 // but these would be valid:
20668 // r.ArrS[3].Arr[6:7]
20670 // r.ArrS[3].x
20671 namespace {
20672 class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
20673 Sema &SemaRef;
20674 OpenMPClauseKind CKind = OMPC_unknown;
20675 OpenMPDirectiveKind DKind = OMPD_unknown;
20676 OMPClauseMappableExprCommon::MappableExprComponentList &Components;
20677 bool IsNonContiguous = false;
20678 bool NoDiagnose = false;
20679 const Expr *RelevantExpr = nullptr;
20680 bool AllowUnitySizeArraySection = true;
20681 bool AllowWholeSizeArraySection = true;
20682 bool AllowAnotherPtr = true;
20683 SourceLocation ELoc;
20684 SourceRange ERange;
20686 void emitErrorMsg() {
20687 // If nothing else worked, this is not a valid map clause expression.
20688 if (SemaRef.getLangOpts().OpenMP < 50) {
20689 SemaRef.Diag(ELoc,
20690 diag::err_omp_expected_named_var_member_or_array_expression)
20691 << ERange;
20692 } else {
20693 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
20694 << getOpenMPClauseName(CKind) << ERange;
20698 public:
20699 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
20700 if (!isa<VarDecl>(DRE->getDecl())) {
20701 emitErrorMsg();
20702 return false;
20704 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20705 RelevantExpr = DRE;
20706 // Record the component.
20707 Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
20708 return true;
20711 bool VisitMemberExpr(MemberExpr *ME) {
20712 Expr *E = ME;
20713 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
20715 if (isa<CXXThisExpr>(BaseE)) {
20716 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20717 // We found a base expression: this->Val.
20718 RelevantExpr = ME;
20719 } else {
20720 E = BaseE;
20723 if (!isa<FieldDecl>(ME->getMemberDecl())) {
20724 if (!NoDiagnose) {
20725 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
20726 << ME->getSourceRange();
20727 return false;
20729 if (RelevantExpr)
20730 return false;
20731 return Visit(E);
20734 auto *FD = cast<FieldDecl>(ME->getMemberDecl());
20736 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
20737 // A bit-field cannot appear in a map clause.
20739 if (FD->isBitField()) {
20740 if (!NoDiagnose) {
20741 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
20742 << ME->getSourceRange() << getOpenMPClauseName(CKind);
20743 return false;
20745 if (RelevantExpr)
20746 return false;
20747 return Visit(E);
20750 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20751 // If the type of a list item is a reference to a type T then the type
20752 // will be considered to be T for all purposes of this clause.
20753 QualType CurType = BaseE->getType().getNonReferenceType();
20755 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
20756 // A list item cannot be a variable that is a member of a structure with
20757 // a union type.
20759 if (CurType->isUnionType()) {
20760 if (!NoDiagnose) {
20761 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
20762 << ME->getSourceRange();
20763 return false;
20765 return RelevantExpr || Visit(E);
20768 // If we got a member expression, we should not expect any array section
20769 // before that:
20771 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
20772 // If a list item is an element of a structure, only the rightmost symbol
20773 // of the variable reference can be an array section.
20775 AllowUnitySizeArraySection = false;
20776 AllowWholeSizeArraySection = false;
20778 // Record the component.
20779 Components.emplace_back(ME, FD, IsNonContiguous);
20780 return RelevantExpr || Visit(E);
20783 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
20784 Expr *E = AE->getBase()->IgnoreParenImpCasts();
20786 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
20787 if (!NoDiagnose) {
20788 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20789 << 0 << AE->getSourceRange();
20790 return false;
20792 return RelevantExpr || Visit(E);
20795 // If we got an array subscript that express the whole dimension we
20796 // can have any array expressions before. If it only expressing part of
20797 // the dimension, we can only have unitary-size array expressions.
20798 if (checkArrayExpressionDoesNotReferToWholeSize(SemaRef, AE, E->getType()))
20799 AllowWholeSizeArraySection = false;
20801 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
20802 Expr::EvalResult Result;
20803 if (!AE->getIdx()->isValueDependent() &&
20804 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
20805 !Result.Val.getInt().isZero()) {
20806 SemaRef.Diag(AE->getIdx()->getExprLoc(),
20807 diag::err_omp_invalid_map_this_expr);
20808 SemaRef.Diag(AE->getIdx()->getExprLoc(),
20809 diag::note_omp_invalid_subscript_on_this_ptr_map);
20811 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20812 RelevantExpr = TE;
20815 // Record the component - we don't have any declaration associated.
20816 Components.emplace_back(AE, nullptr, IsNonContiguous);
20818 return RelevantExpr || Visit(E);
20821 bool VisitOMPArraySectionExpr(OMPArraySectionExpr *OASE) {
20822 // After OMP 5.0 Array section in reduction clause will be implicitly
20823 // mapped
20824 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
20825 "Array sections cannot be implicitly mapped.");
20826 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
20827 QualType CurType =
20828 OMPArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
20830 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20831 // If the type of a list item is a reference to a type T then the type
20832 // will be considered to be T for all purposes of this clause.
20833 if (CurType->isReferenceType())
20834 CurType = CurType->getPointeeType();
20836 bool IsPointer = CurType->isAnyPointerType();
20838 if (!IsPointer && !CurType->isArrayType()) {
20839 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20840 << 0 << OASE->getSourceRange();
20841 return false;
20844 bool NotWhole =
20845 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
20846 bool NotUnity =
20847 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
20849 if (AllowWholeSizeArraySection) {
20850 // Any array section is currently allowed. Allowing a whole size array
20851 // section implies allowing a unity array section as well.
20853 // If this array section refers to the whole dimension we can still
20854 // accept other array sections before this one, except if the base is a
20855 // pointer. Otherwise, only unitary sections are accepted.
20856 if (NotWhole || IsPointer)
20857 AllowWholeSizeArraySection = false;
20858 } else if (DKind == OMPD_target_update &&
20859 SemaRef.getLangOpts().OpenMP >= 50) {
20860 if (IsPointer && !AllowAnotherPtr)
20861 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
20862 << /*array of unknown bound */ 1;
20863 else
20864 IsNonContiguous = true;
20865 } else if (AllowUnitySizeArraySection && NotUnity) {
20866 // A unity or whole array section is not allowed and that is not
20867 // compatible with the properties of the current array section.
20868 if (NoDiagnose)
20869 return false;
20870 SemaRef.Diag(ELoc,
20871 diag::err_array_section_does_not_specify_contiguous_storage)
20872 << OASE->getSourceRange();
20873 return false;
20876 if (IsPointer)
20877 AllowAnotherPtr = false;
20879 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
20880 Expr::EvalResult ResultR;
20881 Expr::EvalResult ResultL;
20882 if (!OASE->getLength()->isValueDependent() &&
20883 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
20884 !ResultR.Val.getInt().isOne()) {
20885 SemaRef.Diag(OASE->getLength()->getExprLoc(),
20886 diag::err_omp_invalid_map_this_expr);
20887 SemaRef.Diag(OASE->getLength()->getExprLoc(),
20888 diag::note_omp_invalid_length_on_this_ptr_mapping);
20890 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
20891 OASE->getLowerBound()->EvaluateAsInt(ResultL,
20892 SemaRef.getASTContext()) &&
20893 !ResultL.Val.getInt().isZero()) {
20894 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
20895 diag::err_omp_invalid_map_this_expr);
20896 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
20897 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
20899 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20900 RelevantExpr = TE;
20903 // Record the component - we don't have any declaration associated.
20904 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
20905 return RelevantExpr || Visit(E);
20907 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
20908 Expr *Base = E->getBase();
20910 // Record the component - we don't have any declaration associated.
20911 Components.emplace_back(E, nullptr, IsNonContiguous);
20913 return Visit(Base->IgnoreParenImpCasts());
20916 bool VisitUnaryOperator(UnaryOperator *UO) {
20917 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
20918 UO->getOpcode() != UO_Deref) {
20919 emitErrorMsg();
20920 return false;
20922 if (!RelevantExpr) {
20923 // Record the component if haven't found base decl.
20924 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
20926 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
20928 bool VisitBinaryOperator(BinaryOperator *BO) {
20929 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
20930 emitErrorMsg();
20931 return false;
20934 // Pointer arithmetic is the only thing we expect to happen here so after we
20935 // make sure the binary operator is a pointer type, the we only thing need
20936 // to to is to visit the subtree that has the same type as root (so that we
20937 // know the other subtree is just an offset)
20938 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
20939 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
20940 Components.emplace_back(BO, nullptr, false);
20941 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
20942 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
20943 "Either LHS or RHS have base decl inside");
20944 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
20945 return RelevantExpr || Visit(LE);
20946 return RelevantExpr || Visit(RE);
20948 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
20949 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20950 RelevantExpr = CTE;
20951 Components.emplace_back(CTE, nullptr, IsNonContiguous);
20952 return true;
20954 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
20955 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20956 Components.emplace_back(COCE, nullptr, IsNonContiguous);
20957 return true;
20959 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
20960 Expr *Source = E->getSourceExpr();
20961 if (!Source) {
20962 emitErrorMsg();
20963 return false;
20965 return Visit(Source);
20967 bool VisitStmt(Stmt *) {
20968 emitErrorMsg();
20969 return false;
20971 const Expr *getFoundBase() const { return RelevantExpr; }
20972 explicit MapBaseChecker(
20973 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
20974 OMPClauseMappableExprCommon::MappableExprComponentList &Components,
20975 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
20976 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
20977 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
20979 } // namespace
20981 /// Return the expression of the base of the mappable expression or null if it
20982 /// cannot be determined and do all the necessary checks to see if the
20983 /// expression is valid as a standalone mappable expression. In the process,
20984 /// record all the components of the expression.
20985 static const Expr *checkMapClauseExpressionBase(
20986 Sema &SemaRef, Expr *E,
20987 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
20988 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
20989 SourceLocation ELoc = E->getExprLoc();
20990 SourceRange ERange = E->getSourceRange();
20991 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
20992 ERange);
20993 if (Checker.Visit(E->IgnoreParens())) {
20994 // Check if the highest dimension array section has length specified
20995 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
20996 (CKind == OMPC_to || CKind == OMPC_from)) {
20997 auto CI = CurComponents.rbegin();
20998 auto CE = CurComponents.rend();
20999 for (; CI != CE; ++CI) {
21000 const auto *OASE =
21001 dyn_cast<OMPArraySectionExpr>(CI->getAssociatedExpression());
21002 if (!OASE)
21003 continue;
21004 if (OASE && OASE->getLength())
21005 break;
21006 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
21007 << ERange;
21010 return Checker.getFoundBase();
21012 return nullptr;
21015 // Return true if expression E associated with value VD has conflicts with other
21016 // map information.
21017 static bool checkMapConflicts(
21018 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
21019 bool CurrentRegionOnly,
21020 OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents,
21021 OpenMPClauseKind CKind) {
21022 assert(VD && E);
21023 SourceLocation ELoc = E->getExprLoc();
21024 SourceRange ERange = E->getSourceRange();
21026 // In order to easily check the conflicts we need to match each component of
21027 // the expression under test with the components of the expressions that are
21028 // already in the stack.
21030 assert(!CurComponents.empty() && "Map clause expression with no components!");
21031 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
21032 "Map clause expression with unexpected base!");
21034 // Variables to help detecting enclosing problems in data environment nests.
21035 bool IsEnclosedByDataEnvironmentExpr = false;
21036 const Expr *EnclosingExpr = nullptr;
21038 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
21039 VD, CurrentRegionOnly,
21040 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
21041 ERange, CKind, &EnclosingExpr,
21042 CurComponents](OMPClauseMappableExprCommon::MappableExprComponentListRef
21043 StackComponents,
21044 OpenMPClauseKind Kind) {
21045 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
21046 return false;
21047 assert(!StackComponents.empty() &&
21048 "Map clause expression with no components!");
21049 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
21050 "Map clause expression with unexpected base!");
21051 (void)VD;
21053 // The whole expression in the stack.
21054 const Expr *RE = StackComponents.front().getAssociatedExpression();
21056 // Expressions must start from the same base. Here we detect at which
21057 // point both expressions diverge from each other and see if we can
21058 // detect if the memory referred to both expressions is contiguous and
21059 // do not overlap.
21060 auto CI = CurComponents.rbegin();
21061 auto CE = CurComponents.rend();
21062 auto SI = StackComponents.rbegin();
21063 auto SE = StackComponents.rend();
21064 for (; CI != CE && SI != SE; ++CI, ++SI) {
21066 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
21067 // At most one list item can be an array item derived from a given
21068 // variable in map clauses of the same construct.
21069 if (CurrentRegionOnly &&
21070 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
21071 isa<OMPArraySectionExpr>(CI->getAssociatedExpression()) ||
21072 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
21073 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
21074 isa<OMPArraySectionExpr>(SI->getAssociatedExpression()) ||
21075 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
21076 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
21077 diag::err_omp_multiple_array_items_in_map_clause)
21078 << CI->getAssociatedExpression()->getSourceRange();
21079 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
21080 diag::note_used_here)
21081 << SI->getAssociatedExpression()->getSourceRange();
21082 return true;
21085 // Do both expressions have the same kind?
21086 if (CI->getAssociatedExpression()->getStmtClass() !=
21087 SI->getAssociatedExpression()->getStmtClass())
21088 break;
21090 // Are we dealing with different variables/fields?
21091 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
21092 break;
21094 // Check if the extra components of the expressions in the enclosing
21095 // data environment are redundant for the current base declaration.
21096 // If they are, the maps completely overlap, which is legal.
21097 for (; SI != SE; ++SI) {
21098 QualType Type;
21099 if (const auto *ASE =
21100 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
21101 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
21102 } else if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(
21103 SI->getAssociatedExpression())) {
21104 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21105 Type =
21106 OMPArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
21107 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
21108 SI->getAssociatedExpression())) {
21109 Type = OASE->getBase()->getType()->getPointeeType();
21111 if (Type.isNull() || Type->isAnyPointerType() ||
21112 checkArrayExpressionDoesNotReferToWholeSize(
21113 SemaRef, SI->getAssociatedExpression(), Type))
21114 break;
21117 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21118 // List items of map clauses in the same construct must not share
21119 // original storage.
21121 // If the expressions are exactly the same or one is a subset of the
21122 // other, it means they are sharing storage.
21123 if (CI == CE && SI == SE) {
21124 if (CurrentRegionOnly) {
21125 if (CKind == OMPC_map) {
21126 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21127 } else {
21128 assert(CKind == OMPC_to || CKind == OMPC_from);
21129 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21130 << ERange;
21132 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21133 << RE->getSourceRange();
21134 return true;
21136 // If we find the same expression in the enclosing data environment,
21137 // that is legal.
21138 IsEnclosedByDataEnvironmentExpr = true;
21139 return false;
21142 QualType DerivedType =
21143 std::prev(CI)->getAssociatedDeclaration()->getType();
21144 SourceLocation DerivedLoc =
21145 std::prev(CI)->getAssociatedExpression()->getExprLoc();
21147 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21148 // If the type of a list item is a reference to a type T then the type
21149 // will be considered to be T for all purposes of this clause.
21150 DerivedType = DerivedType.getNonReferenceType();
21152 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
21153 // A variable for which the type is pointer and an array section
21154 // derived from that variable must not appear as list items of map
21155 // clauses of the same construct.
21157 // Also, cover one of the cases in:
21158 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21159 // If any part of the original storage of a list item has corresponding
21160 // storage in the device data environment, all of the original storage
21161 // must have corresponding storage in the device data environment.
21163 if (DerivedType->isAnyPointerType()) {
21164 if (CI == CE || SI == SE) {
21165 SemaRef.Diag(
21166 DerivedLoc,
21167 diag::err_omp_pointer_mapped_along_with_derived_section)
21168 << DerivedLoc;
21169 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21170 << RE->getSourceRange();
21171 return true;
21173 if (CI->getAssociatedExpression()->getStmtClass() !=
21174 SI->getAssociatedExpression()->getStmtClass() ||
21175 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
21176 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
21177 assert(CI != CE && SI != SE);
21178 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
21179 << DerivedLoc;
21180 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21181 << RE->getSourceRange();
21182 return true;
21186 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21187 // List items of map clauses in the same construct must not share
21188 // original storage.
21190 // An expression is a subset of the other.
21191 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
21192 if (CKind == OMPC_map) {
21193 if (CI != CE || SI != SE) {
21194 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
21195 // a pointer.
21196 auto Begin =
21197 CI != CE ? CurComponents.begin() : StackComponents.begin();
21198 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
21199 auto It = Begin;
21200 while (It != End && !It->getAssociatedDeclaration())
21201 std::advance(It, 1);
21202 assert(It != End &&
21203 "Expected at least one component with the declaration.");
21204 if (It != Begin && It->getAssociatedDeclaration()
21205 ->getType()
21206 .getCanonicalType()
21207 ->isAnyPointerType()) {
21208 IsEnclosedByDataEnvironmentExpr = false;
21209 EnclosingExpr = nullptr;
21210 return false;
21213 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21214 } else {
21215 assert(CKind == OMPC_to || CKind == OMPC_from);
21216 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21217 << ERange;
21219 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21220 << RE->getSourceRange();
21221 return true;
21224 // The current expression uses the same base as other expression in the
21225 // data environment but does not contain it completely.
21226 if (!CurrentRegionOnly && SI != SE)
21227 EnclosingExpr = RE;
21229 // The current expression is a subset of the expression in the data
21230 // environment.
21231 IsEnclosedByDataEnvironmentExpr |=
21232 (!CurrentRegionOnly && CI != CE && SI == SE);
21234 return false;
21237 if (CurrentRegionOnly)
21238 return FoundError;
21240 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21241 // If any part of the original storage of a list item has corresponding
21242 // storage in the device data environment, all of the original storage must
21243 // have corresponding storage in the device data environment.
21244 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
21245 // If a list item is an element of a structure, and a different element of
21246 // the structure has a corresponding list item in the device data environment
21247 // prior to a task encountering the construct associated with the map clause,
21248 // then the list item must also have a corresponding list item in the device
21249 // data environment prior to the task encountering the construct.
21251 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
21252 SemaRef.Diag(ELoc,
21253 diag::err_omp_original_storage_is_shared_and_does_not_contain)
21254 << ERange;
21255 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
21256 << EnclosingExpr->getSourceRange();
21257 return true;
21260 return FoundError;
21263 // Look up the user-defined mapper given the mapper name and mapped type, and
21264 // build a reference to it.
21265 static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
21266 CXXScopeSpec &MapperIdScopeSpec,
21267 const DeclarationNameInfo &MapperId,
21268 QualType Type,
21269 Expr *UnresolvedMapper) {
21270 if (MapperIdScopeSpec.isInvalid())
21271 return ExprError();
21272 // Get the actual type for the array type.
21273 if (Type->isArrayType()) {
21274 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
21275 Type = Type->getAsArrayTypeUnsafe()->getElementType().getCanonicalType();
21277 // Find all user-defined mappers with the given MapperId.
21278 SmallVector<UnresolvedSet<8>, 4> Lookups;
21279 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
21280 Lookup.suppressDiagnostics();
21281 if (S) {
21282 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec)) {
21283 NamedDecl *D = Lookup.getRepresentativeDecl();
21284 while (S && !S->isDeclScope(D))
21285 S = S->getParent();
21286 if (S)
21287 S = S->getParent();
21288 Lookups.emplace_back();
21289 Lookups.back().append(Lookup.begin(), Lookup.end());
21290 Lookup.clear();
21292 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
21293 // Extract the user-defined mappers with the given MapperId.
21294 Lookups.push_back(UnresolvedSet<8>());
21295 for (NamedDecl *D : ULE->decls()) {
21296 auto *DMD = cast<OMPDeclareMapperDecl>(D);
21297 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
21298 Lookups.back().addDecl(DMD);
21301 // Defer the lookup for dependent types. The results will be passed through
21302 // UnresolvedMapper on instantiation.
21303 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
21304 Type->isInstantiationDependentType() ||
21305 Type->containsUnexpandedParameterPack() ||
21306 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
21307 return !D->isInvalidDecl() &&
21308 (D->getType()->isDependentType() ||
21309 D->getType()->isInstantiationDependentType() ||
21310 D->getType()->containsUnexpandedParameterPack());
21311 })) {
21312 UnresolvedSet<8> URS;
21313 for (const UnresolvedSet<8> &Set : Lookups) {
21314 if (Set.empty())
21315 continue;
21316 URS.append(Set.begin(), Set.end());
21318 return UnresolvedLookupExpr::Create(
21319 SemaRef.Context, /*NamingClass=*/nullptr,
21320 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
21321 /*ADL=*/false, /*Overloaded=*/true, URS.begin(), URS.end());
21323 SourceLocation Loc = MapperId.getLoc();
21324 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21325 // The type must be of struct, union or class type in C and C++
21326 if (!Type->isStructureOrClassType() && !Type->isUnionType() &&
21327 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
21328 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
21329 return ExprError();
21331 // Perform argument dependent lookup.
21332 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
21333 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
21334 // Return the first user-defined mapper with the desired type.
21335 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21336 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
21337 if (!D->isInvalidDecl() &&
21338 SemaRef.Context.hasSameType(D->getType(), Type))
21339 return D;
21340 return nullptr;
21342 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
21343 // Find the first user-defined mapper with a type derived from the desired
21344 // type.
21345 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21346 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
21347 if (!D->isInvalidDecl() &&
21348 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
21349 !Type.isMoreQualifiedThan(D->getType()))
21350 return D;
21351 return nullptr;
21352 })) {
21353 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
21354 /*DetectVirtual=*/false);
21355 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
21356 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
21357 VD->getType().getUnqualifiedType()))) {
21358 if (SemaRef.CheckBaseClassAccess(
21359 Loc, VD->getType(), Type, Paths.front(),
21360 /*DiagID=*/0) != Sema::AR_inaccessible) {
21361 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
21366 // Report error if a mapper is specified, but cannot be found.
21367 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
21368 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
21369 << Type << MapperId.getName();
21370 return ExprError();
21372 return ExprEmpty();
21375 namespace {
21376 // Utility struct that gathers all the related lists associated with a mappable
21377 // expression.
21378 struct MappableVarListInfo {
21379 // The list of expressions.
21380 ArrayRef<Expr *> VarList;
21381 // The list of processed expressions.
21382 SmallVector<Expr *, 16> ProcessedVarList;
21383 // The mappble components for each expression.
21384 OMPClauseMappableExprCommon::MappableExprComponentLists VarComponents;
21385 // The base declaration of the variable.
21386 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
21387 // The reference to the user-defined mapper associated with every expression.
21388 SmallVector<Expr *, 16> UDMapperList;
21390 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
21391 // We have a list of components and base declarations for each entry in the
21392 // variable list.
21393 VarComponents.reserve(VarList.size());
21394 VarBaseDeclarations.reserve(VarList.size());
21397 } // namespace
21399 // Check the validity of the provided variable list for the provided clause kind
21400 // \a CKind. In the check process the valid expressions, mappable expression
21401 // components, variables, and user-defined mappers are extracted and used to
21402 // fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
21403 // UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
21404 // and \a MapperId are expected to be valid if the clause kind is 'map'.
21405 static void checkMappableExpressionList(
21406 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
21407 MappableVarListInfo &MVLI, SourceLocation StartLoc,
21408 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
21409 ArrayRef<Expr *> UnresolvedMappers,
21410 OpenMPMapClauseKind MapType = OMPC_MAP_unknown,
21411 ArrayRef<OpenMPMapModifierKind> Modifiers = None,
21412 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
21413 // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
21414 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
21415 "Unexpected clause kind with mappable expressions!");
21417 // If the identifier of user-defined mapper is not specified, it is "default".
21418 // We do not change the actual name in this clause to distinguish whether a
21419 // mapper is specified explicitly, i.e., it is not explicitly specified when
21420 // MapperId.getName() is empty.
21421 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
21422 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
21423 MapperId.setName(DeclNames.getIdentifier(
21424 &SemaRef.getASTContext().Idents.get("default")));
21425 MapperId.setLoc(StartLoc);
21428 // Iterators to find the current unresolved mapper expression.
21429 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
21430 bool UpdateUMIt = false;
21431 Expr *UnresolvedMapper = nullptr;
21433 bool HasHoldModifier =
21434 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
21436 // Keep track of the mappable components and base declarations in this clause.
21437 // Each entry in the list is going to have a list of components associated. We
21438 // record each set of the components so that we can build the clause later on.
21439 // In the end we should have the same amount of declarations and component
21440 // lists.
21442 for (Expr *RE : MVLI.VarList) {
21443 assert(RE && "Null expr in omp to/from/map clause");
21444 SourceLocation ELoc = RE->getExprLoc();
21446 // Find the current unresolved mapper expression.
21447 if (UpdateUMIt && UMIt != UMEnd) {
21448 UMIt++;
21449 assert(
21450 UMIt != UMEnd &&
21451 "Expect the size of UnresolvedMappers to match with that of VarList");
21453 UpdateUMIt = true;
21454 if (UMIt != UMEnd)
21455 UnresolvedMapper = *UMIt;
21457 const Expr *VE = RE->IgnoreParenLValueCasts();
21459 if (VE->isValueDependent() || VE->isTypeDependent() ||
21460 VE->isInstantiationDependent() ||
21461 VE->containsUnexpandedParameterPack()) {
21462 // Try to find the associated user-defined mapper.
21463 ExprResult ER = buildUserDefinedMapperRef(
21464 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21465 VE->getType().getCanonicalType(), UnresolvedMapper);
21466 if (ER.isInvalid())
21467 continue;
21468 MVLI.UDMapperList.push_back(ER.get());
21469 // We can only analyze this information once the missing information is
21470 // resolved.
21471 MVLI.ProcessedVarList.push_back(RE);
21472 continue;
21475 Expr *SimpleExpr = RE->IgnoreParenCasts();
21477 if (!RE->isLValue()) {
21478 if (SemaRef.getLangOpts().OpenMP < 50) {
21479 SemaRef.Diag(
21480 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
21481 << RE->getSourceRange();
21482 } else {
21483 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21484 << getOpenMPClauseName(CKind) << RE->getSourceRange();
21486 continue;
21489 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
21490 ValueDecl *CurDeclaration = nullptr;
21492 // Obtain the array or member expression bases if required. Also, fill the
21493 // components array with all the components identified in the process.
21494 const Expr *BE =
21495 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
21496 DSAS->getCurrentDirective(), NoDiagnose);
21497 if (!BE)
21498 continue;
21500 assert(!CurComponents.empty() &&
21501 "Invalid mappable expression information.");
21503 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
21504 // Add store "this" pointer to class in DSAStackTy for future checking
21505 DSAS->addMappedClassesQualTypes(TE->getType());
21506 // Try to find the associated user-defined mapper.
21507 ExprResult ER = buildUserDefinedMapperRef(
21508 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21509 VE->getType().getCanonicalType(), UnresolvedMapper);
21510 if (ER.isInvalid())
21511 continue;
21512 MVLI.UDMapperList.push_back(ER.get());
21513 // Skip restriction checking for variable or field declarations
21514 MVLI.ProcessedVarList.push_back(RE);
21515 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21516 MVLI.VarComponents.back().append(CurComponents.begin(),
21517 CurComponents.end());
21518 MVLI.VarBaseDeclarations.push_back(nullptr);
21519 continue;
21522 // For the following checks, we rely on the base declaration which is
21523 // expected to be associated with the last component. The declaration is
21524 // expected to be a variable or a field (if 'this' is being mapped).
21525 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
21526 assert(CurDeclaration && "Null decl on map clause.");
21527 assert(
21528 CurDeclaration->isCanonicalDecl() &&
21529 "Expecting components to have associated only canonical declarations.");
21531 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
21532 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
21534 assert((VD || FD) && "Only variables or fields are expected here!");
21535 (void)FD;
21537 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
21538 // threadprivate variables cannot appear in a map clause.
21539 // OpenMP 4.5 [2.10.5, target update Construct]
21540 // threadprivate variables cannot appear in a from clause.
21541 if (VD && DSAS->isThreadPrivate(VD)) {
21542 if (NoDiagnose)
21543 continue;
21544 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
21545 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
21546 << getOpenMPClauseName(CKind);
21547 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
21548 continue;
21551 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21552 // A list item cannot appear in both a map clause and a data-sharing
21553 // attribute clause on the same construct.
21555 // Check conflicts with other map clause expressions. We check the conflicts
21556 // with the current construct separately from the enclosing data
21557 // environment, because the restrictions are different. We only have to
21558 // check conflicts across regions for the map clauses.
21559 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
21560 /*CurrentRegionOnly=*/true, CurComponents, CKind))
21561 break;
21562 if (CKind == OMPC_map &&
21563 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
21564 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
21565 /*CurrentRegionOnly=*/false, CurComponents, CKind))
21566 break;
21568 // OpenMP 4.5 [2.10.5, target update Construct]
21569 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21570 // If the type of a list item is a reference to a type T then the type will
21571 // be considered to be T for all purposes of this clause.
21572 auto I = llvm::find_if(
21573 CurComponents,
21574 [](const OMPClauseMappableExprCommon::MappableComponent &MC) {
21575 return MC.getAssociatedDeclaration();
21577 assert(I != CurComponents.end() && "Null decl on map clause.");
21578 (void)I;
21579 QualType Type;
21580 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
21581 auto *OASE = dyn_cast<OMPArraySectionExpr>(VE->IgnoreParens());
21582 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
21583 if (ASE) {
21584 Type = ASE->getType().getNonReferenceType();
21585 } else if (OASE) {
21586 QualType BaseType =
21587 OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
21588 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21589 Type = ATy->getElementType();
21590 else
21591 Type = BaseType->getPointeeType();
21592 Type = Type.getNonReferenceType();
21593 } else if (OAShE) {
21594 Type = OAShE->getBase()->getType()->getPointeeType();
21595 } else {
21596 Type = VE->getType();
21599 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
21600 // A list item in a to or from clause must have a mappable type.
21601 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21602 // A list item must have a mappable type.
21603 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
21604 DSAS, Type, /*FullCheck=*/true))
21605 continue;
21607 if (CKind == OMPC_map) {
21608 // target enter data
21609 // OpenMP [2.10.2, Restrictions, p. 99]
21610 // A map-type must be specified in all map clauses and must be either
21611 // to or alloc.
21612 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
21613 if (DKind == OMPD_target_enter_data &&
21614 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc)) {
21615 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21616 << (IsMapTypeImplicit ? 1 : 0)
21617 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21618 << getOpenMPDirectiveName(DKind);
21619 continue;
21622 // target exit_data
21623 // OpenMP [2.10.3, Restrictions, p. 102]
21624 // A map-type must be specified in all map clauses and must be either
21625 // from, release, or delete.
21626 if (DKind == OMPD_target_exit_data &&
21627 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
21628 MapType == OMPC_MAP_delete)) {
21629 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21630 << (IsMapTypeImplicit ? 1 : 0)
21631 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21632 << getOpenMPDirectiveName(DKind);
21633 continue;
21636 // The 'ompx_hold' modifier is specifically intended to be used on a
21637 // 'target' or 'target data' directive to prevent data from being unmapped
21638 // during the associated statement. It is not permitted on a 'target
21639 // enter data' or 'target exit data' directive, which have no associated
21640 // statement.
21641 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
21642 HasHoldModifier) {
21643 SemaRef.Diag(StartLoc,
21644 diag::err_omp_invalid_map_type_modifier_for_directive)
21645 << getOpenMPSimpleClauseTypeName(OMPC_map,
21646 OMPC_MAP_MODIFIER_ompx_hold)
21647 << getOpenMPDirectiveName(DKind);
21648 continue;
21651 // target, target data
21652 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
21653 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
21654 // A map-type in a map clause must be to, from, tofrom or alloc
21655 if ((DKind == OMPD_target_data ||
21656 isOpenMPTargetExecutionDirective(DKind)) &&
21657 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
21658 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
21659 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21660 << (IsMapTypeImplicit ? 1 : 0)
21661 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21662 << getOpenMPDirectiveName(DKind);
21663 continue;
21666 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
21667 // A list item cannot appear in both a map clause and a data-sharing
21668 // attribute clause on the same construct
21670 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
21671 // A list item cannot appear in both a map clause and a data-sharing
21672 // attribute clause on the same construct unless the construct is a
21673 // combined construct.
21674 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
21675 isOpenMPTargetExecutionDirective(DKind)) ||
21676 DKind == OMPD_target)) {
21677 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
21678 if (isOpenMPPrivate(DVar.CKind)) {
21679 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
21680 << getOpenMPClauseName(DVar.CKind)
21681 << getOpenMPClauseName(OMPC_map)
21682 << getOpenMPDirectiveName(DSAS->getCurrentDirective());
21683 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
21684 continue;
21689 // Try to find the associated user-defined mapper.
21690 ExprResult ER = buildUserDefinedMapperRef(
21691 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21692 Type.getCanonicalType(), UnresolvedMapper);
21693 if (ER.isInvalid())
21694 continue;
21695 MVLI.UDMapperList.push_back(ER.get());
21697 // Save the current expression.
21698 MVLI.ProcessedVarList.push_back(RE);
21700 // Store the components in the stack so that they can be used to check
21701 // against other clauses later on.
21702 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
21703 /*WhereFoundClauseKind=*/OMPC_map);
21705 // Save the components and declaration to create the clause. For purposes of
21706 // the clause creation, any component list that has has base 'this' uses
21707 // null as base declaration.
21708 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21709 MVLI.VarComponents.back().append(CurComponents.begin(),
21710 CurComponents.end());
21711 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
21712 : CurDeclaration);
21716 OMPClause *Sema::ActOnOpenMPMapClause(
21717 ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
21718 ArrayRef<SourceLocation> MapTypeModifiersLoc,
21719 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
21720 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
21721 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
21722 const OMPVarListLocTy &Locs, bool NoDiagnose,
21723 ArrayRef<Expr *> UnresolvedMappers) {
21724 OpenMPMapModifierKind Modifiers[] = {
21725 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
21726 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
21727 OMPC_MAP_MODIFIER_unknown};
21728 SourceLocation ModifiersLoc[NumberOfOMPMapClauseModifiers];
21730 // Process map-type-modifiers, flag errors for duplicate modifiers.
21731 unsigned Count = 0;
21732 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
21733 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
21734 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
21735 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
21736 continue;
21738 assert(Count < NumberOfOMPMapClauseModifiers &&
21739 "Modifiers exceed the allowed number of map type modifiers");
21740 Modifiers[Count] = MapTypeModifiers[I];
21741 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
21742 ++Count;
21745 MappableVarListInfo MVLI(VarList);
21746 checkMappableExpressionList(*this, DSAStack, OMPC_map, MVLI, Locs.StartLoc,
21747 MapperIdScopeSpec, MapperId, UnresolvedMappers,
21748 MapType, Modifiers, IsMapTypeImplicit,
21749 NoDiagnose);
21751 // We need to produce a map clause even if we don't have variables so that
21752 // other diagnostics related with non-existing map clauses are accurate.
21753 return OMPMapClause::Create(Context, Locs, MVLI.ProcessedVarList,
21754 MVLI.VarBaseDeclarations, MVLI.VarComponents,
21755 MVLI.UDMapperList, Modifiers, ModifiersLoc,
21756 MapperIdScopeSpec.getWithLocInContext(Context),
21757 MapperId, MapType, IsMapTypeImplicit, MapLoc);
21760 QualType Sema::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc,
21761 TypeResult ParsedType) {
21762 assert(ParsedType.isUsable());
21764 QualType ReductionType = GetTypeFromParser(ParsedType.get());
21765 if (ReductionType.isNull())
21766 return QualType();
21768 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
21769 // A type name in a declare reduction directive cannot be a function type, an
21770 // array type, a reference type, or a type qualified with const, volatile or
21771 // restrict.
21772 if (ReductionType.hasQualifiers()) {
21773 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
21774 return QualType();
21777 if (ReductionType->isFunctionType()) {
21778 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
21779 return QualType();
21781 if (ReductionType->isReferenceType()) {
21782 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
21783 return QualType();
21785 if (ReductionType->isArrayType()) {
21786 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
21787 return QualType();
21789 return ReductionType;
21792 Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareReductionDirectiveStart(
21793 Scope *S, DeclContext *DC, DeclarationName Name,
21794 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
21795 AccessSpecifier AS, Decl *PrevDeclInScope) {
21796 SmallVector<Decl *, 8> Decls;
21797 Decls.reserve(ReductionTypes.size());
21799 LookupResult Lookup(*this, Name, SourceLocation(), LookupOMPReductionName,
21800 forRedeclarationInCurContext());
21801 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
21802 // A reduction-identifier may not be re-declared in the current scope for the
21803 // same type or for a type that is compatible according to the base language
21804 // rules.
21805 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
21806 OMPDeclareReductionDecl *PrevDRD = nullptr;
21807 bool InCompoundScope = true;
21808 if (S != nullptr) {
21809 // Find previous declaration with the same name not referenced in other
21810 // declarations.
21811 FunctionScopeInfo *ParentFn = getEnclosingFunction();
21812 InCompoundScope =
21813 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
21814 LookupName(Lookup, S);
21815 FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
21816 /*AllowInlineNamespace=*/false);
21817 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
21818 LookupResult::Filter Filter = Lookup.makeFilter();
21819 while (Filter.hasNext()) {
21820 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
21821 if (InCompoundScope) {
21822 auto I = UsedAsPrevious.find(PrevDecl);
21823 if (I == UsedAsPrevious.end())
21824 UsedAsPrevious[PrevDecl] = false;
21825 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
21826 UsedAsPrevious[D] = true;
21828 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
21829 PrevDecl->getLocation();
21831 Filter.done();
21832 if (InCompoundScope) {
21833 for (const auto &PrevData : UsedAsPrevious) {
21834 if (!PrevData.second) {
21835 PrevDRD = PrevData.first;
21836 break;
21840 } else if (PrevDeclInScope != nullptr) {
21841 auto *PrevDRDInScope = PrevDRD =
21842 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
21843 do {
21844 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
21845 PrevDRDInScope->getLocation();
21846 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
21847 } while (PrevDRDInScope != nullptr);
21849 for (const auto &TyData : ReductionTypes) {
21850 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
21851 bool Invalid = false;
21852 if (I != PreviousRedeclTypes.end()) {
21853 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
21854 << TyData.first;
21855 Diag(I->second, diag::note_previous_definition);
21856 Invalid = true;
21858 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
21859 auto *DRD = OMPDeclareReductionDecl::Create(Context, DC, TyData.second,
21860 Name, TyData.first, PrevDRD);
21861 DC->addDecl(DRD);
21862 DRD->setAccess(AS);
21863 Decls.push_back(DRD);
21864 if (Invalid)
21865 DRD->setInvalidDecl();
21866 else
21867 PrevDRD = DRD;
21870 return DeclGroupPtrTy::make(
21871 DeclGroupRef::Create(Context, Decls.begin(), Decls.size()));
21874 void Sema::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) {
21875 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21877 // Enter new function scope.
21878 PushFunctionScope();
21879 setFunctionHasBranchProtectedScope();
21880 getCurFunction()->setHasOMPDeclareReductionCombiner();
21882 if (S != nullptr)
21883 PushDeclContext(S, DRD);
21884 else
21885 CurContext = DRD;
21887 PushExpressionEvaluationContext(
21888 ExpressionEvaluationContext::PotentiallyEvaluated);
21890 QualType ReductionType = DRD->getType();
21891 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
21892 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
21893 // uses semantics of argument handles by value, but it should be passed by
21894 // reference. C lang does not support references, so pass all parameters as
21895 // pointers.
21896 // Create 'T omp_in;' variable.
21897 VarDecl *OmpInParm =
21898 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_in");
21899 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
21900 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
21901 // uses semantics of argument handles by value, but it should be passed by
21902 // reference. C lang does not support references, so pass all parameters as
21903 // pointers.
21904 // Create 'T omp_out;' variable.
21905 VarDecl *OmpOutParm =
21906 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_out");
21907 if (S != nullptr) {
21908 PushOnScopeChains(OmpInParm, S);
21909 PushOnScopeChains(OmpOutParm, S);
21910 } else {
21911 DRD->addDecl(OmpInParm);
21912 DRD->addDecl(OmpOutParm);
21914 Expr *InE =
21915 ::buildDeclRefExpr(*this, OmpInParm, ReductionType, D->getLocation());
21916 Expr *OutE =
21917 ::buildDeclRefExpr(*this, OmpOutParm, ReductionType, D->getLocation());
21918 DRD->setCombinerData(InE, OutE);
21921 void Sema::ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner) {
21922 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21923 DiscardCleanupsInEvaluationContext();
21924 PopExpressionEvaluationContext();
21926 PopDeclContext();
21927 PopFunctionScopeInfo();
21929 if (Combiner != nullptr)
21930 DRD->setCombiner(Combiner);
21931 else
21932 DRD->setInvalidDecl();
21935 VarDecl *Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D) {
21936 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21938 // Enter new function scope.
21939 PushFunctionScope();
21940 setFunctionHasBranchProtectedScope();
21942 if (S != nullptr)
21943 PushDeclContext(S, DRD);
21944 else
21945 CurContext = DRD;
21947 PushExpressionEvaluationContext(
21948 ExpressionEvaluationContext::PotentiallyEvaluated);
21950 QualType ReductionType = DRD->getType();
21951 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
21952 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
21953 // uses semantics of argument handles by value, but it should be passed by
21954 // reference. C lang does not support references, so pass all parameters as
21955 // pointers.
21956 // Create 'T omp_priv;' variable.
21957 VarDecl *OmpPrivParm =
21958 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_priv");
21959 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
21960 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
21961 // uses semantics of argument handles by value, but it should be passed by
21962 // reference. C lang does not support references, so pass all parameters as
21963 // pointers.
21964 // Create 'T omp_orig;' variable.
21965 VarDecl *OmpOrigParm =
21966 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_orig");
21967 if (S != nullptr) {
21968 PushOnScopeChains(OmpPrivParm, S);
21969 PushOnScopeChains(OmpOrigParm, S);
21970 } else {
21971 DRD->addDecl(OmpPrivParm);
21972 DRD->addDecl(OmpOrigParm);
21974 Expr *OrigE =
21975 ::buildDeclRefExpr(*this, OmpOrigParm, ReductionType, D->getLocation());
21976 Expr *PrivE =
21977 ::buildDeclRefExpr(*this, OmpPrivParm, ReductionType, D->getLocation());
21978 DRD->setInitializerData(OrigE, PrivE);
21979 return OmpPrivParm;
21982 void Sema::ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer,
21983 VarDecl *OmpPrivParm) {
21984 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21985 DiscardCleanupsInEvaluationContext();
21986 PopExpressionEvaluationContext();
21988 PopDeclContext();
21989 PopFunctionScopeInfo();
21991 if (Initializer != nullptr) {
21992 DRD->setInitializer(Initializer, OMPDeclareReductionDecl::CallInit);
21993 } else if (OmpPrivParm->hasInit()) {
21994 DRD->setInitializer(OmpPrivParm->getInit(),
21995 OmpPrivParm->isDirectInit()
21996 ? OMPDeclareReductionDecl::DirectInit
21997 : OMPDeclareReductionDecl::CopyInit);
21998 } else {
21999 DRD->setInvalidDecl();
22003 Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareReductionDirectiveEnd(
22004 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
22005 for (Decl *D : DeclReductions.get()) {
22006 if (IsValid) {
22007 if (S)
22008 PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
22009 /*AddToContext=*/false);
22010 } else {
22011 D->setInvalidDecl();
22014 return DeclReductions;
22017 TypeResult Sema::ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D) {
22018 TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
22019 QualType T = TInfo->getType();
22020 if (D.isInvalidType())
22021 return true;
22023 if (getLangOpts().CPlusPlus) {
22024 // Check that there are no default arguments (C++ only).
22025 CheckExtraCXXDefaultArguments(D);
22028 return CreateParsedType(T, TInfo);
22031 QualType Sema::ActOnOpenMPDeclareMapperType(SourceLocation TyLoc,
22032 TypeResult ParsedType) {
22033 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
22035 QualType MapperType = GetTypeFromParser(ParsedType.get());
22036 assert(!MapperType.isNull() && "Expect valid mapper type");
22038 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22039 // The type must be of struct, union or class type in C and C++
22040 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
22041 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
22042 return QualType();
22044 return MapperType;
22047 Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareMapperDirective(
22048 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
22049 SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS,
22050 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
22051 LookupResult Lookup(*this, Name, SourceLocation(), LookupOMPMapperName,
22052 forRedeclarationInCurContext());
22053 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22054 // A mapper-identifier may not be redeclared in the current scope for the
22055 // same type or for a type that is compatible according to the base language
22056 // rules.
22057 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22058 OMPDeclareMapperDecl *PrevDMD = nullptr;
22059 bool InCompoundScope = true;
22060 if (S != nullptr) {
22061 // Find previous declaration with the same name not referenced in other
22062 // declarations.
22063 FunctionScopeInfo *ParentFn = getEnclosingFunction();
22064 InCompoundScope =
22065 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22066 LookupName(Lookup, S);
22067 FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
22068 /*AllowInlineNamespace=*/false);
22069 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
22070 LookupResult::Filter Filter = Lookup.makeFilter();
22071 while (Filter.hasNext()) {
22072 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
22073 if (InCompoundScope) {
22074 auto I = UsedAsPrevious.find(PrevDecl);
22075 if (I == UsedAsPrevious.end())
22076 UsedAsPrevious[PrevDecl] = false;
22077 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
22078 UsedAsPrevious[D] = true;
22080 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22081 PrevDecl->getLocation();
22083 Filter.done();
22084 if (InCompoundScope) {
22085 for (const auto &PrevData : UsedAsPrevious) {
22086 if (!PrevData.second) {
22087 PrevDMD = PrevData.first;
22088 break;
22092 } else if (PrevDeclInScope) {
22093 auto *PrevDMDInScope = PrevDMD =
22094 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
22095 do {
22096 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
22097 PrevDMDInScope->getLocation();
22098 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
22099 } while (PrevDMDInScope != nullptr);
22101 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
22102 bool Invalid = false;
22103 if (I != PreviousRedeclTypes.end()) {
22104 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
22105 << MapperType << Name;
22106 Diag(I->second, diag::note_previous_definition);
22107 Invalid = true;
22109 // Build expressions for implicit maps of data members with 'default'
22110 // mappers.
22111 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses.begin(),
22112 Clauses.end());
22113 if (LangOpts.OpenMP >= 50)
22114 processImplicitMapsWithDefaultMappers(*this, DSAStack, ClausesWithImplicit);
22115 auto *DMD =
22116 OMPDeclareMapperDecl::Create(Context, DC, StartLoc, Name, MapperType, VN,
22117 ClausesWithImplicit, PrevDMD);
22118 if (S)
22119 PushOnScopeChains(DMD, S);
22120 else
22121 DC->addDecl(DMD);
22122 DMD->setAccess(AS);
22123 if (Invalid)
22124 DMD->setInvalidDecl();
22126 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
22127 VD->setDeclContext(DMD);
22128 VD->setLexicalDeclContext(DMD);
22129 DMD->addDecl(VD);
22130 DMD->setMapperVarRef(MapperVarRef);
22132 return DeclGroupPtrTy::make(DeclGroupRef(DMD));
22135 ExprResult
22136 Sema::ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType,
22137 SourceLocation StartLoc,
22138 DeclarationName VN) {
22139 TypeSourceInfo *TInfo =
22140 Context.getTrivialTypeSourceInfo(MapperType, StartLoc);
22141 auto *VD = VarDecl::Create(Context, Context.getTranslationUnitDecl(),
22142 StartLoc, StartLoc, VN.getAsIdentifierInfo(),
22143 MapperType, TInfo, SC_None);
22144 if (S)
22145 PushOnScopeChains(VD, S, /*AddToContext=*/false);
22146 Expr *E = buildDeclRefExpr(*this, VD, MapperType, StartLoc);
22147 DSAStack->addDeclareMapperVarRef(E);
22148 return E;
22151 bool Sema::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const {
22152 assert(LangOpts.OpenMP && "Expected OpenMP mode.");
22153 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
22154 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
22155 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
22156 return true;
22157 if (VD->isUsableInConstantExpressions(Context))
22158 return true;
22159 return false;
22161 return true;
22164 const ValueDecl *Sema::getOpenMPDeclareMapperVarName() const {
22165 assert(LangOpts.OpenMP && "Expected OpenMP mode.");
22166 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
22169 OMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams,
22170 SourceLocation StartLoc,
22171 SourceLocation LParenLoc,
22172 SourceLocation EndLoc) {
22173 Expr *ValExpr = NumTeams;
22174 Stmt *HelperValStmt = nullptr;
22176 // OpenMP [teams Constrcut, Restrictions]
22177 // The num_teams expression must evaluate to a positive integer value.
22178 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_num_teams,
22179 /*StrictlyPositive=*/true))
22180 return nullptr;
22182 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22183 OpenMPDirectiveKind CaptureRegion =
22184 getOpenMPCaptureRegionForClause(DKind, OMPC_num_teams, LangOpts.OpenMP);
22185 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
22186 ValExpr = MakeFullExpr(ValExpr).get();
22187 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22188 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
22189 HelperValStmt = buildPreInits(Context, Captures);
22192 return new (Context) OMPNumTeamsClause(ValExpr, HelperValStmt, CaptureRegion,
22193 StartLoc, LParenLoc, EndLoc);
22196 OMPClause *Sema::ActOnOpenMPThreadLimitClause(Expr *ThreadLimit,
22197 SourceLocation StartLoc,
22198 SourceLocation LParenLoc,
22199 SourceLocation EndLoc) {
22200 Expr *ValExpr = ThreadLimit;
22201 Stmt *HelperValStmt = nullptr;
22203 // OpenMP [teams Constrcut, Restrictions]
22204 // The thread_limit expression must evaluate to a positive integer value.
22205 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_thread_limit,
22206 /*StrictlyPositive=*/true))
22207 return nullptr;
22209 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22210 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
22211 DKind, OMPC_thread_limit, LangOpts.OpenMP);
22212 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
22213 ValExpr = MakeFullExpr(ValExpr).get();
22214 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22215 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
22216 HelperValStmt = buildPreInits(Context, Captures);
22219 return new (Context) OMPThreadLimitClause(
22220 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
22223 OMPClause *Sema::ActOnOpenMPPriorityClause(Expr *Priority,
22224 SourceLocation StartLoc,
22225 SourceLocation LParenLoc,
22226 SourceLocation EndLoc) {
22227 Expr *ValExpr = Priority;
22228 Stmt *HelperValStmt = nullptr;
22229 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22231 // OpenMP [2.9.1, task Constrcut]
22232 // The priority-value is a non-negative numerical scalar expression.
22233 if (!isNonNegativeIntegerValue(
22234 ValExpr, *this, OMPC_priority,
22235 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
22236 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22237 return nullptr;
22239 return new (Context) OMPPriorityClause(ValExpr, HelperValStmt, CaptureRegion,
22240 StartLoc, LParenLoc, EndLoc);
22243 OMPClause *Sema::ActOnOpenMPGrainsizeClause(Expr *Grainsize,
22244 SourceLocation StartLoc,
22245 SourceLocation LParenLoc,
22246 SourceLocation EndLoc) {
22247 Expr *ValExpr = Grainsize;
22248 Stmt *HelperValStmt = nullptr;
22249 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22251 // OpenMP [2.9.2, taskloop Constrcut]
22252 // The parameter of the grainsize clause must be a positive integer
22253 // expression.
22254 if (!isNonNegativeIntegerValue(
22255 ValExpr, *this, OMPC_grainsize,
22256 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
22257 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22258 return nullptr;
22260 return new (Context) OMPGrainsizeClause(ValExpr, HelperValStmt, CaptureRegion,
22261 StartLoc, LParenLoc, EndLoc);
22264 OMPClause *Sema::ActOnOpenMPNumTasksClause(Expr *NumTasks,
22265 SourceLocation StartLoc,
22266 SourceLocation LParenLoc,
22267 SourceLocation EndLoc) {
22268 Expr *ValExpr = NumTasks;
22269 Stmt *HelperValStmt = nullptr;
22270 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22272 // OpenMP [2.9.2, taskloop Constrcut]
22273 // The parameter of the num_tasks clause must be a positive integer
22274 // expression.
22275 if (!isNonNegativeIntegerValue(
22276 ValExpr, *this, OMPC_num_tasks,
22277 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
22278 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22279 return nullptr;
22281 return new (Context) OMPNumTasksClause(ValExpr, HelperValStmt, CaptureRegion,
22282 StartLoc, LParenLoc, EndLoc);
22285 OMPClause *Sema::ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc,
22286 SourceLocation LParenLoc,
22287 SourceLocation EndLoc) {
22288 // OpenMP [2.13.2, critical construct, Description]
22289 // ... where hint-expression is an integer constant expression that evaluates
22290 // to a valid lock hint.
22291 ExprResult HintExpr =
22292 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
22293 if (HintExpr.isInvalid())
22294 return nullptr;
22295 return new (Context)
22296 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
22299 /// Tries to find omp_event_handle_t type.
22300 static bool findOMPEventHandleT(Sema &S, SourceLocation Loc,
22301 DSAStackTy *Stack) {
22302 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
22303 if (!OMPEventHandleT.isNull())
22304 return true;
22305 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
22306 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
22307 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
22308 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
22309 return false;
22311 Stack->setOMPEventHandleT(PT.get());
22312 return true;
22315 OMPClause *Sema::ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc,
22316 SourceLocation LParenLoc,
22317 SourceLocation EndLoc) {
22318 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
22319 !Evt->isInstantiationDependent() &&
22320 !Evt->containsUnexpandedParameterPack()) {
22321 if (!findOMPEventHandleT(*this, Evt->getExprLoc(), DSAStack))
22322 return nullptr;
22323 // OpenMP 5.0, 2.10.1 task Construct.
22324 // event-handle is a variable of the omp_event_handle_t type.
22325 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
22326 if (!Ref) {
22327 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22328 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22329 return nullptr;
22331 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
22332 if (!VD) {
22333 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22334 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22335 return nullptr;
22337 if (!Context.hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
22338 VD->getType()) ||
22339 VD->getType().isConstant(Context)) {
22340 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22341 << "omp_event_handle_t" << 1 << VD->getType()
22342 << Evt->getSourceRange();
22343 return nullptr;
22345 // OpenMP 5.0, 2.10.1 task Construct
22346 // [detach clause]... The event-handle will be considered as if it was
22347 // specified on a firstprivate clause.
22348 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
22349 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
22350 DVar.RefExpr) {
22351 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
22352 << getOpenMPClauseName(DVar.CKind)
22353 << getOpenMPClauseName(OMPC_firstprivate);
22354 reportOriginalDsa(*this, DSAStack, VD, DVar);
22355 return nullptr;
22359 return new (Context) OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
22362 OMPClause *Sema::ActOnOpenMPDistScheduleClause(
22363 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
22364 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
22365 SourceLocation EndLoc) {
22366 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
22367 std::string Values;
22368 Values += "'";
22369 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
22370 Values += "'";
22371 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22372 << Values << getOpenMPClauseName(OMPC_dist_schedule);
22373 return nullptr;
22375 Expr *ValExpr = ChunkSize;
22376 Stmt *HelperValStmt = nullptr;
22377 if (ChunkSize) {
22378 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
22379 !ChunkSize->isInstantiationDependent() &&
22380 !ChunkSize->containsUnexpandedParameterPack()) {
22381 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
22382 ExprResult Val =
22383 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
22384 if (Val.isInvalid())
22385 return nullptr;
22387 ValExpr = Val.get();
22389 // OpenMP [2.7.1, Restrictions]
22390 // chunk_size must be a loop invariant integer expression with a positive
22391 // value.
22392 if (Optional<llvm::APSInt> Result =
22393 ValExpr->getIntegerConstantExpr(Context)) {
22394 if (Result->isSigned() && !Result->isStrictlyPositive()) {
22395 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
22396 << "dist_schedule" << ChunkSize->getSourceRange();
22397 return nullptr;
22399 } else if (getOpenMPCaptureRegionForClause(
22400 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
22401 LangOpts.OpenMP) != OMPD_unknown &&
22402 !CurContext->isDependentContext()) {
22403 ValExpr = MakeFullExpr(ValExpr).get();
22404 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22405 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
22406 HelperValStmt = buildPreInits(Context, Captures);
22411 return new (Context)
22412 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
22413 Kind, ValExpr, HelperValStmt);
22416 OMPClause *Sema::ActOnOpenMPDefaultmapClause(
22417 OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind,
22418 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
22419 SourceLocation KindLoc, SourceLocation EndLoc) {
22420 if (getLangOpts().OpenMP < 50) {
22421 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
22422 Kind != OMPC_DEFAULTMAP_scalar) {
22423 std::string Value;
22424 SourceLocation Loc;
22425 Value += "'";
22426 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
22427 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
22428 OMPC_DEFAULTMAP_MODIFIER_tofrom);
22429 Loc = MLoc;
22430 } else {
22431 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
22432 OMPC_DEFAULTMAP_scalar);
22433 Loc = KindLoc;
22435 Value += "'";
22436 Diag(Loc, diag::err_omp_unexpected_clause_value)
22437 << Value << getOpenMPClauseName(OMPC_defaultmap);
22438 return nullptr;
22440 } else {
22441 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
22442 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
22443 (LangOpts.OpenMP >= 50 && KindLoc.isInvalid());
22444 if (!isDefaultmapKind || !isDefaultmapModifier) {
22445 StringRef KindValue = "'scalar', 'aggregate', 'pointer'";
22446 if (LangOpts.OpenMP == 50) {
22447 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
22448 "'firstprivate', 'none', 'default'";
22449 if (!isDefaultmapKind && isDefaultmapModifier) {
22450 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22451 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22452 } else if (isDefaultmapKind && !isDefaultmapModifier) {
22453 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22454 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22455 } else {
22456 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22457 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22458 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22459 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22461 } else {
22462 StringRef ModifierValue =
22463 "'alloc', 'from', 'to', 'tofrom', "
22464 "'firstprivate', 'none', 'default', 'present'";
22465 if (!isDefaultmapKind && isDefaultmapModifier) {
22466 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22467 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22468 } else if (isDefaultmapKind && !isDefaultmapModifier) {
22469 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22470 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22471 } else {
22472 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22473 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22474 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22475 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22478 return nullptr;
22481 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
22482 // At most one defaultmap clause for each category can appear on the
22483 // directive.
22484 if (DSAStack->checkDefaultmapCategory(Kind)) {
22485 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
22486 return nullptr;
22489 if (Kind == OMPC_DEFAULTMAP_unknown) {
22490 // Variable category is not specified - mark all categories.
22491 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
22492 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
22493 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
22494 } else {
22495 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
22498 return new (Context)
22499 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
22502 bool Sema::ActOnStartOpenMPDeclareTargetContext(
22503 DeclareTargetContextInfo &DTCI) {
22504 DeclContext *CurLexicalContext = getCurLexicalContext();
22505 if (!CurLexicalContext->isFileContext() &&
22506 !CurLexicalContext->isExternCContext() &&
22507 !CurLexicalContext->isExternCXXContext() &&
22508 !isa<CXXRecordDecl>(CurLexicalContext) &&
22509 !isa<ClassTemplateDecl>(CurLexicalContext) &&
22510 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
22511 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
22512 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
22513 return false;
22515 DeclareTargetNesting.push_back(DTCI);
22516 return true;
22519 const Sema::DeclareTargetContextInfo
22520 Sema::ActOnOpenMPEndDeclareTargetDirective() {
22521 assert(!DeclareTargetNesting.empty() &&
22522 "check isInOpenMPDeclareTargetContext() first!");
22523 return DeclareTargetNesting.pop_back_val();
22526 void Sema::ActOnFinishedOpenMPDeclareTargetContext(
22527 DeclareTargetContextInfo &DTCI) {
22528 for (auto &It : DTCI.ExplicitlyMapped)
22529 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
22532 void Sema::DiagnoseUnterminatedOpenMPDeclareTarget() {
22533 if (DeclareTargetNesting.empty())
22534 return;
22535 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
22536 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
22537 << getOpenMPDirectiveName(DTCI.Kind);
22540 NamedDecl *Sema::lookupOpenMPDeclareTargetName(Scope *CurScope,
22541 CXXScopeSpec &ScopeSpec,
22542 const DeclarationNameInfo &Id) {
22543 LookupResult Lookup(*this, Id, LookupOrdinaryName);
22544 LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
22546 if (Lookup.isAmbiguous())
22547 return nullptr;
22548 Lookup.suppressDiagnostics();
22550 if (!Lookup.isSingleResult()) {
22551 VarOrFuncDeclFilterCCC CCC(*this);
22552 if (TypoCorrection Corrected =
22553 CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr, CCC,
22554 CTK_ErrorRecovery)) {
22555 diagnoseTypo(Corrected, PDiag(diag::err_undeclared_var_use_suggest)
22556 << Id.getName());
22557 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
22558 return nullptr;
22561 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
22562 return nullptr;
22565 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
22566 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
22567 !isa<FunctionTemplateDecl>(ND)) {
22568 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
22569 return nullptr;
22571 return ND;
22574 void Sema::ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc,
22575 OMPDeclareTargetDeclAttr::MapTypeTy MT,
22576 DeclareTargetContextInfo &DTCI) {
22577 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
22578 isa<FunctionTemplateDecl>(ND)) &&
22579 "Expected variable, function or function template.");
22581 // Diagnose marking after use as it may lead to incorrect diagnosis and
22582 // codegen.
22583 if (LangOpts.OpenMP >= 50 &&
22584 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
22585 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
22587 // Explicit declare target lists have precedence.
22588 const unsigned Level = -1;
22590 auto *VD = cast<ValueDecl>(ND);
22591 llvm::Optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22592 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22593 if (ActiveAttr && ActiveAttr.value()->getDevType() != DTCI.DT &&
22594 ActiveAttr.value()->getLevel() == Level) {
22595 Diag(Loc, diag::err_omp_device_type_mismatch)
22596 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
22597 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
22598 ActiveAttr.value()->getDevType());
22599 return;
22601 if (ActiveAttr && ActiveAttr.value()->getMapType() != MT &&
22602 ActiveAttr.value()->getLevel() == Level) {
22603 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
22604 return;
22607 if (ActiveAttr && ActiveAttr.value()->getLevel() == Level)
22608 return;
22610 Expr *IndirectE = nullptr;
22611 bool IsIndirect = false;
22612 if (DTCI.Indirect) {
22613 IndirectE = DTCI.Indirect.value();
22614 if (!IndirectE)
22615 IsIndirect = true;
22617 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22618 Context, MT, DTCI.DT, IndirectE, IsIndirect, Level,
22619 SourceRange(Loc, Loc));
22620 ND->addAttr(A);
22621 if (ASTMutationListener *ML = Context.getASTMutationListener())
22622 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
22623 checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Loc);
22626 static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
22627 Sema &SemaRef, Decl *D) {
22628 if (!D || !isa<VarDecl>(D))
22629 return;
22630 auto *VD = cast<VarDecl>(D);
22631 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
22632 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
22633 if (SemaRef.LangOpts.OpenMP >= 50 &&
22634 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
22635 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
22636 VD->hasGlobalStorage()) {
22637 if (!MapTy || *MapTy != OMPDeclareTargetDeclAttr::MT_To) {
22638 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
22639 // If a lambda declaration and definition appears between a
22640 // declare target directive and the matching end declare target
22641 // directive, all variables that are captured by the lambda
22642 // expression must also appear in a to clause.
22643 SemaRef.Diag(VD->getLocation(),
22644 diag::err_omp_lambda_capture_in_declare_target_not_to);
22645 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
22646 << VD << 0 << SR;
22647 return;
22650 if (MapTy)
22651 return;
22652 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
22653 SemaRef.Diag(SL, diag::note_used_here) << SR;
22656 static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR,
22657 Sema &SemaRef, DSAStackTy *Stack,
22658 ValueDecl *VD) {
22659 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
22660 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
22661 /*FullCheck=*/false);
22664 void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
22665 SourceLocation IdLoc) {
22666 if (!D || D->isInvalidDecl())
22667 return;
22668 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
22669 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
22670 if (auto *VD = dyn_cast<VarDecl>(D)) {
22671 // Only global variables can be marked as declare target.
22672 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
22673 !VD->isStaticDataMember())
22674 return;
22675 // 2.10.6: threadprivate variable cannot appear in a declare target
22676 // directive.
22677 if (DSAStack->isThreadPrivate(VD)) {
22678 Diag(SL, diag::err_omp_threadprivate_in_target);
22679 reportOriginalDsa(*this, DSAStack, VD, DSAStack->getTopDSA(VD, false));
22680 return;
22683 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
22684 D = FTD->getTemplatedDecl();
22685 if (auto *FD = dyn_cast<FunctionDecl>(D)) {
22686 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
22687 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
22688 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
22689 Diag(IdLoc, diag::err_omp_function_in_link_clause);
22690 Diag(FD->getLocation(), diag::note_defined_here) << FD;
22691 return;
22694 if (auto *VD = dyn_cast<ValueDecl>(D)) {
22695 // Problem if any with var declared with incomplete type will be reported
22696 // as normal, so no need to check it here.
22697 if ((E || !VD->getType()->isIncompleteType()) &&
22698 !checkValueDeclInTarget(SL, SR, *this, DSAStack, VD))
22699 return;
22700 if (!E && isInOpenMPDeclareTargetContext()) {
22701 // Checking declaration inside declare target region.
22702 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
22703 isa<FunctionTemplateDecl>(D)) {
22704 llvm::Optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22705 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22706 unsigned Level = DeclareTargetNesting.size();
22707 if (ActiveAttr && ActiveAttr.value()->getLevel() >= Level)
22708 return;
22709 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
22710 Expr *IndirectE = nullptr;
22711 bool IsIndirect = false;
22712 if (DTCI.Indirect) {
22713 IndirectE = DTCI.Indirect.value();
22714 if (!IndirectE)
22715 IsIndirect = true;
22717 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22718 Context, OMPDeclareTargetDeclAttr::MT_To, DTCI.DT, IndirectE,
22719 IsIndirect, Level, SourceRange(DTCI.Loc, DTCI.Loc));
22720 D->addAttr(A);
22721 if (ASTMutationListener *ML = Context.getASTMutationListener())
22722 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
22724 return;
22727 if (!E)
22728 return;
22729 checkDeclInTargetContext(E->getExprLoc(), E->getSourceRange(), *this, D);
22732 OMPClause *Sema::ActOnOpenMPToClause(
22733 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
22734 ArrayRef<SourceLocation> MotionModifiersLoc,
22735 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22736 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22737 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
22738 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
22739 OMPC_MOTION_MODIFIER_unknown};
22740 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
22742 // Process motion-modifiers, flag errors for duplicate modifiers.
22743 unsigned Count = 0;
22744 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
22745 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
22746 llvm::is_contained(Modifiers, MotionModifiers[I])) {
22747 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22748 continue;
22750 assert(Count < NumberOfOMPMotionModifiers &&
22751 "Modifiers exceed the allowed number of motion modifiers");
22752 Modifiers[Count] = MotionModifiers[I];
22753 ModifiersLoc[Count] = MotionModifiersLoc[I];
22754 ++Count;
22757 MappableVarListInfo MVLI(VarList);
22758 checkMappableExpressionList(*this, DSAStack, OMPC_to, MVLI, Locs.StartLoc,
22759 MapperIdScopeSpec, MapperId, UnresolvedMappers);
22760 if (MVLI.ProcessedVarList.empty())
22761 return nullptr;
22763 return OMPToClause::Create(
22764 Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22765 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22766 MapperIdScopeSpec.getWithLocInContext(Context), MapperId);
22769 OMPClause *Sema::ActOnOpenMPFromClause(
22770 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
22771 ArrayRef<SourceLocation> MotionModifiersLoc,
22772 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22773 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22774 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
22775 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
22776 OMPC_MOTION_MODIFIER_unknown};
22777 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
22779 // Process motion-modifiers, flag errors for duplicate modifiers.
22780 unsigned Count = 0;
22781 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
22782 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
22783 llvm::is_contained(Modifiers, MotionModifiers[I])) {
22784 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22785 continue;
22787 assert(Count < NumberOfOMPMotionModifiers &&
22788 "Modifiers exceed the allowed number of motion modifiers");
22789 Modifiers[Count] = MotionModifiers[I];
22790 ModifiersLoc[Count] = MotionModifiersLoc[I];
22791 ++Count;
22794 MappableVarListInfo MVLI(VarList);
22795 checkMappableExpressionList(*this, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
22796 MapperIdScopeSpec, MapperId, UnresolvedMappers);
22797 if (MVLI.ProcessedVarList.empty())
22798 return nullptr;
22800 return OMPFromClause::Create(
22801 Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22802 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22803 MapperIdScopeSpec.getWithLocInContext(Context), MapperId);
22806 OMPClause *Sema::ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList,
22807 const OMPVarListLocTy &Locs) {
22808 MappableVarListInfo MVLI(VarList);
22809 SmallVector<Expr *, 8> PrivateCopies;
22810 SmallVector<Expr *, 8> Inits;
22812 for (Expr *RefExpr : VarList) {
22813 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
22814 SourceLocation ELoc;
22815 SourceRange ERange;
22816 Expr *SimpleRefExpr = RefExpr;
22817 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
22818 if (Res.second) {
22819 // It will be analyzed later.
22820 MVLI.ProcessedVarList.push_back(RefExpr);
22821 PrivateCopies.push_back(nullptr);
22822 Inits.push_back(nullptr);
22824 ValueDecl *D = Res.first;
22825 if (!D)
22826 continue;
22828 QualType Type = D->getType();
22829 Type = Type.getNonReferenceType().getUnqualifiedType();
22831 auto *VD = dyn_cast<VarDecl>(D);
22833 // Item should be a pointer or reference to pointer.
22834 if (!Type->isPointerType()) {
22835 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
22836 << 0 << RefExpr->getSourceRange();
22837 continue;
22840 // Build the private variable and the expression that refers to it.
22841 auto VDPrivate =
22842 buildVarDecl(*this, ELoc, Type, D->getName(),
22843 D->hasAttrs() ? &D->getAttrs() : nullptr,
22844 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
22845 if (VDPrivate->isInvalidDecl())
22846 continue;
22848 CurContext->addDecl(VDPrivate);
22849 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
22850 *this, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
22852 // Add temporary variable to initialize the private copy of the pointer.
22853 VarDecl *VDInit =
22854 buildVarDecl(*this, RefExpr->getExprLoc(), Type, ".devptr.temp");
22855 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
22856 *this, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
22857 AddInitializerToDecl(VDPrivate,
22858 DefaultLvalueConversion(VDInitRefExpr).get(),
22859 /*DirectInit=*/false);
22861 // If required, build a capture to implement the privatization initialized
22862 // with the current list item value.
22863 DeclRefExpr *Ref = nullptr;
22864 if (!VD)
22865 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
22866 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22867 PrivateCopies.push_back(VDPrivateRefExpr);
22868 Inits.push_back(VDInitRefExpr);
22870 // We need to add a data sharing attribute for this variable to make sure it
22871 // is correctly captured. A variable that shows up in a use_device_ptr has
22872 // similar properties of a first private variable.
22873 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22875 // Create a mappable component for the list item. List items in this clause
22876 // only need a component.
22877 MVLI.VarBaseDeclarations.push_back(D);
22878 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22879 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
22880 /*IsNonContiguous=*/false);
22883 if (MVLI.ProcessedVarList.empty())
22884 return nullptr;
22886 return OMPUseDevicePtrClause::Create(
22887 Context, Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
22888 MVLI.VarBaseDeclarations, MVLI.VarComponents);
22891 OMPClause *Sema::ActOnOpenMPUseDeviceAddrClause(ArrayRef<Expr *> VarList,
22892 const OMPVarListLocTy &Locs) {
22893 MappableVarListInfo MVLI(VarList);
22895 for (Expr *RefExpr : VarList) {
22896 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
22897 SourceLocation ELoc;
22898 SourceRange ERange;
22899 Expr *SimpleRefExpr = RefExpr;
22900 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
22901 /*AllowArraySection=*/true);
22902 if (Res.second) {
22903 // It will be analyzed later.
22904 MVLI.ProcessedVarList.push_back(RefExpr);
22906 ValueDecl *D = Res.first;
22907 if (!D)
22908 continue;
22909 auto *VD = dyn_cast<VarDecl>(D);
22911 // If required, build a capture to implement the privatization initialized
22912 // with the current list item value.
22913 DeclRefExpr *Ref = nullptr;
22914 if (!VD)
22915 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
22916 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22918 // We need to add a data sharing attribute for this variable to make sure it
22919 // is correctly captured. A variable that shows up in a use_device_addr has
22920 // similar properties of a first private variable.
22921 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22923 // Create a mappable component for the list item. List items in this clause
22924 // only need a component.
22925 MVLI.VarBaseDeclarations.push_back(D);
22926 MVLI.VarComponents.emplace_back();
22927 Expr *Component = SimpleRefExpr;
22928 if (VD && (isa<OMPArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
22929 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
22930 Component = DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
22931 MVLI.VarComponents.back().emplace_back(Component, D,
22932 /*IsNonContiguous=*/false);
22935 if (MVLI.ProcessedVarList.empty())
22936 return nullptr;
22938 return OMPUseDeviceAddrClause::Create(Context, Locs, MVLI.ProcessedVarList,
22939 MVLI.VarBaseDeclarations,
22940 MVLI.VarComponents);
22943 OMPClause *Sema::ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList,
22944 const OMPVarListLocTy &Locs) {
22945 MappableVarListInfo MVLI(VarList);
22946 for (Expr *RefExpr : VarList) {
22947 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
22948 SourceLocation ELoc;
22949 SourceRange ERange;
22950 Expr *SimpleRefExpr = RefExpr;
22951 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
22952 if (Res.second) {
22953 // It will be analyzed later.
22954 MVLI.ProcessedVarList.push_back(RefExpr);
22956 ValueDecl *D = Res.first;
22957 if (!D)
22958 continue;
22960 QualType Type = D->getType();
22961 // item should be a pointer or array or reference to pointer or array
22962 if (!Type.getNonReferenceType()->isPointerType() &&
22963 !Type.getNonReferenceType()->isArrayType()) {
22964 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
22965 << 0 << RefExpr->getSourceRange();
22966 continue;
22969 // Check if the declaration in the clause does not show up in any data
22970 // sharing attribute.
22971 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
22972 if (isOpenMPPrivate(DVar.CKind)) {
22973 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
22974 << getOpenMPClauseName(DVar.CKind)
22975 << getOpenMPClauseName(OMPC_is_device_ptr)
22976 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
22977 reportOriginalDsa(*this, DSAStack, D, DVar);
22978 continue;
22981 const Expr *ConflictExpr;
22982 if (DSAStack->checkMappableExprComponentListsForDecl(
22983 D, /*CurrentRegionOnly=*/true,
22984 [&ConflictExpr](
22985 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
22986 OpenMPClauseKind) -> bool {
22987 ConflictExpr = R.front().getAssociatedExpression();
22988 return true;
22989 })) {
22990 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
22991 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
22992 << ConflictExpr->getSourceRange();
22993 continue;
22996 // Store the components in the stack so that they can be used to check
22997 // against other clauses later on.
22998 OMPClauseMappableExprCommon::MappableComponent MC(
22999 SimpleRefExpr, D, /*IsNonContiguous=*/false);
23000 DSAStack->addMappableExpressionComponents(
23001 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
23003 // Record the expression we've just processed.
23004 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
23006 // Create a mappable component for the list item. List items in this clause
23007 // only need a component. We use a null declaration to signal fields in
23008 // 'this'.
23009 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23010 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23011 "Unexpected device pointer expression!");
23012 MVLI.VarBaseDeclarations.push_back(
23013 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23014 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23015 MVLI.VarComponents.back().push_back(MC);
23018 if (MVLI.ProcessedVarList.empty())
23019 return nullptr;
23021 return OMPIsDevicePtrClause::Create(Context, Locs, MVLI.ProcessedVarList,
23022 MVLI.VarBaseDeclarations,
23023 MVLI.VarComponents);
23026 OMPClause *Sema::ActOnOpenMPHasDeviceAddrClause(ArrayRef<Expr *> VarList,
23027 const OMPVarListLocTy &Locs) {
23028 MappableVarListInfo MVLI(VarList);
23029 for (Expr *RefExpr : VarList) {
23030 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
23031 SourceLocation ELoc;
23032 SourceRange ERange;
23033 Expr *SimpleRefExpr = RefExpr;
23034 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
23035 /*AllowArraySection=*/true);
23036 if (Res.second) {
23037 // It will be analyzed later.
23038 MVLI.ProcessedVarList.push_back(RefExpr);
23040 ValueDecl *D = Res.first;
23041 if (!D)
23042 continue;
23044 // Check if the declaration in the clause does not show up in any data
23045 // sharing attribute.
23046 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23047 if (isOpenMPPrivate(DVar.CKind)) {
23048 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23049 << getOpenMPClauseName(DVar.CKind)
23050 << getOpenMPClauseName(OMPC_has_device_addr)
23051 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
23052 reportOriginalDsa(*this, DSAStack, D, DVar);
23053 continue;
23056 const Expr *ConflictExpr;
23057 if (DSAStack->checkMappableExprComponentListsForDecl(
23058 D, /*CurrentRegionOnly=*/true,
23059 [&ConflictExpr](
23060 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
23061 OpenMPClauseKind) -> bool {
23062 ConflictExpr = R.front().getAssociatedExpression();
23063 return true;
23064 })) {
23065 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23066 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23067 << ConflictExpr->getSourceRange();
23068 continue;
23071 // Store the components in the stack so that they can be used to check
23072 // against other clauses later on.
23073 OMPClauseMappableExprCommon::MappableComponent MC(
23074 SimpleRefExpr, D, /*IsNonContiguous=*/false);
23075 DSAStack->addMappableExpressionComponents(
23076 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
23078 // Record the expression we've just processed.
23079 auto *VD = dyn_cast<VarDecl>(D);
23080 if (!VD && !CurContext->isDependentContext()) {
23081 DeclRefExpr *Ref =
23082 buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
23083 assert(Ref && "has_device_addr capture failed");
23084 MVLI.ProcessedVarList.push_back(Ref);
23085 } else
23086 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
23088 // Create a mappable component for the list item. List items in this clause
23089 // only need a component. We use a null declaration to signal fields in
23090 // 'this'.
23091 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23092 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23093 "Unexpected device pointer expression!");
23094 MVLI.VarBaseDeclarations.push_back(
23095 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23096 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23097 MVLI.VarComponents.back().push_back(MC);
23100 if (MVLI.ProcessedVarList.empty())
23101 return nullptr;
23103 return OMPHasDeviceAddrClause::Create(Context, Locs, MVLI.ProcessedVarList,
23104 MVLI.VarBaseDeclarations,
23105 MVLI.VarComponents);
23108 OMPClause *Sema::ActOnOpenMPAllocateClause(
23109 Expr *Allocator, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
23110 SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
23111 if (Allocator) {
23112 // OpenMP [2.11.4 allocate Clause, Description]
23113 // allocator is an expression of omp_allocator_handle_t type.
23114 if (!findOMPAllocatorHandleT(*this, Allocator->getExprLoc(), DSAStack))
23115 return nullptr;
23117 ExprResult AllocatorRes = DefaultLvalueConversion(Allocator);
23118 if (AllocatorRes.isInvalid())
23119 return nullptr;
23120 AllocatorRes = PerformImplicitConversion(AllocatorRes.get(),
23121 DSAStack->getOMPAllocatorHandleT(),
23122 Sema::AA_Initializing,
23123 /*AllowExplicit=*/true);
23124 if (AllocatorRes.isInvalid())
23125 return nullptr;
23126 Allocator = AllocatorRes.get();
23127 } else {
23128 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
23129 // allocate clauses that appear on a target construct or on constructs in a
23130 // target region must specify an allocator expression unless a requires
23131 // directive with the dynamic_allocators clause is present in the same
23132 // compilation unit.
23133 if (LangOpts.OpenMPIsDevice &&
23134 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
23135 targetDiag(StartLoc, diag::err_expected_allocator_expression);
23137 // Analyze and build list of variables.
23138 SmallVector<Expr *, 8> Vars;
23139 for (Expr *RefExpr : VarList) {
23140 assert(RefExpr && "NULL expr in OpenMP private clause.");
23141 SourceLocation ELoc;
23142 SourceRange ERange;
23143 Expr *SimpleRefExpr = RefExpr;
23144 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
23145 if (Res.second) {
23146 // It will be analyzed later.
23147 Vars.push_back(RefExpr);
23149 ValueDecl *D = Res.first;
23150 if (!D)
23151 continue;
23153 auto *VD = dyn_cast<VarDecl>(D);
23154 DeclRefExpr *Ref = nullptr;
23155 if (!VD && !CurContext->isDependentContext())
23156 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
23157 Vars.push_back((VD || CurContext->isDependentContext())
23158 ? RefExpr->IgnoreParens()
23159 : Ref);
23162 if (Vars.empty())
23163 return nullptr;
23165 if (Allocator)
23166 DSAStack->addInnerAllocatorExpr(Allocator);
23167 return OMPAllocateClause::Create(Context, StartLoc, LParenLoc, Allocator,
23168 ColonLoc, EndLoc, Vars);
23171 OMPClause *Sema::ActOnOpenMPNontemporalClause(ArrayRef<Expr *> VarList,
23172 SourceLocation StartLoc,
23173 SourceLocation LParenLoc,
23174 SourceLocation EndLoc) {
23175 SmallVector<Expr *, 8> Vars;
23176 for (Expr *RefExpr : VarList) {
23177 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23178 SourceLocation ELoc;
23179 SourceRange ERange;
23180 Expr *SimpleRefExpr = RefExpr;
23181 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
23182 if (Res.second)
23183 // It will be analyzed later.
23184 Vars.push_back(RefExpr);
23185 ValueDecl *D = Res.first;
23186 if (!D)
23187 continue;
23189 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
23190 // A list-item cannot appear in more than one nontemporal clause.
23191 if (const Expr *PrevRef =
23192 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
23193 Diag(ELoc, diag::err_omp_used_in_clause_twice)
23194 << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange;
23195 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
23196 << getOpenMPClauseName(OMPC_nontemporal);
23197 continue;
23200 Vars.push_back(RefExpr);
23203 if (Vars.empty())
23204 return nullptr;
23206 return OMPNontemporalClause::Create(Context, StartLoc, LParenLoc, EndLoc,
23207 Vars);
23210 OMPClause *Sema::ActOnOpenMPInclusiveClause(ArrayRef<Expr *> VarList,
23211 SourceLocation StartLoc,
23212 SourceLocation LParenLoc,
23213 SourceLocation EndLoc) {
23214 SmallVector<Expr *, 8> Vars;
23215 for (Expr *RefExpr : VarList) {
23216 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23217 SourceLocation ELoc;
23218 SourceRange ERange;
23219 Expr *SimpleRefExpr = RefExpr;
23220 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
23221 /*AllowArraySection=*/true);
23222 if (Res.second)
23223 // It will be analyzed later.
23224 Vars.push_back(RefExpr);
23225 ValueDecl *D = Res.first;
23226 if (!D)
23227 continue;
23229 const DSAStackTy::DSAVarData DVar =
23230 DSAStack->getTopDSA(D, /*FromParent=*/true);
23231 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23232 // A list item that appears in the inclusive or exclusive clause must appear
23233 // in a reduction clause with the inscan modifier on the enclosing
23234 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23235 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
23236 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23237 << RefExpr->getSourceRange();
23239 if (DSAStack->getParentDirective() != OMPD_unknown)
23240 DSAStack->markDeclAsUsedInScanDirective(D);
23241 Vars.push_back(RefExpr);
23244 if (Vars.empty())
23245 return nullptr;
23247 return OMPInclusiveClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
23250 OMPClause *Sema::ActOnOpenMPExclusiveClause(ArrayRef<Expr *> VarList,
23251 SourceLocation StartLoc,
23252 SourceLocation LParenLoc,
23253 SourceLocation EndLoc) {
23254 SmallVector<Expr *, 8> Vars;
23255 for (Expr *RefExpr : VarList) {
23256 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23257 SourceLocation ELoc;
23258 SourceRange ERange;
23259 Expr *SimpleRefExpr = RefExpr;
23260 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
23261 /*AllowArraySection=*/true);
23262 if (Res.second)
23263 // It will be analyzed later.
23264 Vars.push_back(RefExpr);
23265 ValueDecl *D = Res.first;
23266 if (!D)
23267 continue;
23269 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
23270 DSAStackTy::DSAVarData DVar;
23271 if (ParentDirective != OMPD_unknown)
23272 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
23273 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23274 // A list item that appears in the inclusive or exclusive clause must appear
23275 // in a reduction clause with the inscan modifier on the enclosing
23276 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23277 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
23278 DVar.Modifier != OMPC_REDUCTION_inscan) {
23279 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23280 << RefExpr->getSourceRange();
23281 } else {
23282 DSAStack->markDeclAsUsedInScanDirective(D);
23284 Vars.push_back(RefExpr);
23287 if (Vars.empty())
23288 return nullptr;
23290 return OMPExclusiveClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
23293 /// Tries to find omp_alloctrait_t type.
23294 static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
23295 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
23296 if (!OMPAlloctraitT.isNull())
23297 return true;
23298 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
23299 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
23300 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
23301 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
23302 return false;
23304 Stack->setOMPAlloctraitT(PT.get());
23305 return true;
23308 OMPClause *Sema::ActOnOpenMPUsesAllocatorClause(
23309 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
23310 ArrayRef<UsesAllocatorsData> Data) {
23311 // OpenMP [2.12.5, target Construct]
23312 // allocator is an identifier of omp_allocator_handle_t type.
23313 if (!findOMPAllocatorHandleT(*this, StartLoc, DSAStack))
23314 return nullptr;
23315 // OpenMP [2.12.5, target Construct]
23316 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
23317 if (llvm::any_of(
23318 Data,
23319 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
23320 !findOMPAlloctraitT(*this, StartLoc, DSAStack))
23321 return nullptr;
23322 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
23323 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
23324 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
23325 StringRef Allocator =
23326 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
23327 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
23328 PredefinedAllocators.insert(LookupSingleName(
23329 TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
23332 SmallVector<OMPUsesAllocatorsClause::Data, 4> NewData;
23333 for (const UsesAllocatorsData &D : Data) {
23334 Expr *AllocatorExpr = nullptr;
23335 // Check allocator expression.
23336 if (D.Allocator->isTypeDependent()) {
23337 AllocatorExpr = D.Allocator;
23338 } else {
23339 // Traits were specified - need to assign new allocator to the specified
23340 // allocator, so it must be an lvalue.
23341 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
23342 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
23343 bool IsPredefinedAllocator = false;
23344 if (DRE)
23345 IsPredefinedAllocator = PredefinedAllocators.count(DRE->getDecl());
23346 if (!DRE ||
23347 !(Context.hasSameUnqualifiedType(
23348 AllocatorExpr->getType(), DSAStack->getOMPAllocatorHandleT()) ||
23349 Context.typesAreCompatible(AllocatorExpr->getType(),
23350 DSAStack->getOMPAllocatorHandleT(),
23351 /*CompareUnqualified=*/true)) ||
23352 (!IsPredefinedAllocator &&
23353 (AllocatorExpr->getType().isConstant(Context) ||
23354 !AllocatorExpr->isLValue()))) {
23355 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
23356 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
23357 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
23358 continue;
23360 // OpenMP [2.12.5, target Construct]
23361 // Predefined allocators appearing in a uses_allocators clause cannot have
23362 // traits specified.
23363 if (IsPredefinedAllocator && D.AllocatorTraits) {
23364 Diag(D.AllocatorTraits->getExprLoc(),
23365 diag::err_omp_predefined_allocator_with_traits)
23366 << D.AllocatorTraits->getSourceRange();
23367 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
23368 << cast<NamedDecl>(DRE->getDecl())->getName()
23369 << D.Allocator->getSourceRange();
23370 continue;
23372 // OpenMP [2.12.5, target Construct]
23373 // Non-predefined allocators appearing in a uses_allocators clause must
23374 // have traits specified.
23375 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
23376 Diag(D.Allocator->getExprLoc(),
23377 diag::err_omp_nonpredefined_allocator_without_traits);
23378 continue;
23380 // No allocator traits - just convert it to rvalue.
23381 if (!D.AllocatorTraits)
23382 AllocatorExpr = DefaultLvalueConversion(AllocatorExpr).get();
23383 DSAStack->addUsesAllocatorsDecl(
23384 DRE->getDecl(),
23385 IsPredefinedAllocator
23386 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
23387 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
23389 Expr *AllocatorTraitsExpr = nullptr;
23390 if (D.AllocatorTraits) {
23391 if (D.AllocatorTraits->isTypeDependent()) {
23392 AllocatorTraitsExpr = D.AllocatorTraits;
23393 } else {
23394 // OpenMP [2.12.5, target Construct]
23395 // Arrays that contain allocator traits that appear in a uses_allocators
23396 // clause must be constant arrays, have constant values and be defined
23397 // in the same scope as the construct in which the clause appears.
23398 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
23399 // Check that traits expr is a constant array.
23400 QualType TraitTy;
23401 if (const ArrayType *Ty =
23402 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
23403 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
23404 TraitTy = ConstArrayTy->getElementType();
23405 if (TraitTy.isNull() ||
23406 !(Context.hasSameUnqualifiedType(TraitTy,
23407 DSAStack->getOMPAlloctraitT()) ||
23408 Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
23409 /*CompareUnqualified=*/true))) {
23410 Diag(D.AllocatorTraits->getExprLoc(),
23411 diag::err_omp_expected_array_alloctraits)
23412 << AllocatorTraitsExpr->getType();
23413 continue;
23415 // Do not map by default allocator traits if it is a standalone
23416 // variable.
23417 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
23418 DSAStack->addUsesAllocatorsDecl(
23419 DRE->getDecl(),
23420 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
23423 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
23424 NewD.Allocator = AllocatorExpr;
23425 NewD.AllocatorTraits = AllocatorTraitsExpr;
23426 NewD.LParenLoc = D.LParenLoc;
23427 NewD.RParenLoc = D.RParenLoc;
23429 return OMPUsesAllocatorsClause::Create(Context, StartLoc, LParenLoc, EndLoc,
23430 NewData);
23433 OMPClause *Sema::ActOnOpenMPAffinityClause(
23434 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
23435 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
23436 SmallVector<Expr *, 8> Vars;
23437 for (Expr *RefExpr : Locators) {
23438 assert(RefExpr && "NULL expr in OpenMP shared clause.");
23439 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
23440 // It will be analyzed later.
23441 Vars.push_back(RefExpr);
23442 continue;
23445 SourceLocation ELoc = RefExpr->getExprLoc();
23446 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
23448 if (!SimpleExpr->isLValue()) {
23449 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23450 << 1 << 0 << RefExpr->getSourceRange();
23451 continue;
23454 ExprResult Res;
23456 Sema::TentativeAnalysisScope Trap(*this);
23457 Res = CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
23459 if (!Res.isUsable() && !isa<OMPArraySectionExpr>(SimpleExpr) &&
23460 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
23461 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23462 << 1 << 0 << RefExpr->getSourceRange();
23463 continue;
23465 Vars.push_back(SimpleExpr);
23468 return OMPAffinityClause::Create(Context, StartLoc, LParenLoc, ColonLoc,
23469 EndLoc, Modifier, Vars);
23472 OMPClause *Sema::ActOnOpenMPBindClause(OpenMPBindClauseKind Kind,
23473 SourceLocation KindLoc,
23474 SourceLocation StartLoc,
23475 SourceLocation LParenLoc,
23476 SourceLocation EndLoc) {
23477 if (Kind == OMPC_BIND_unknown) {
23478 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23479 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
23480 /*Last=*/unsigned(OMPC_BIND_unknown))
23481 << getOpenMPClauseName(OMPC_bind);
23482 return nullptr;
23485 return OMPBindClause::Create(Context, Kind, KindLoc, StartLoc, LParenLoc,
23486 EndLoc);