1 //===--- SemaOpenMP.cpp - Semantic Analysis for OpenMP constructs ---------===//
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
7 //===----------------------------------------------------------------------===//
9 /// This file implements semantic analysis for OpenMP directives and
12 //===----------------------------------------------------------------------===//
14 #include "TreeTransform.h"
15 #include "clang/AST/ASTContext.h"
16 #include "clang/AST/ASTMutationListener.h"
17 #include "clang/AST/CXXInheritance.h"
18 #include "clang/AST/Decl.h"
19 #include "clang/AST/DeclCXX.h"
20 #include "clang/AST/DeclOpenMP.h"
21 #include "clang/AST/OpenMPClause.h"
22 #include "clang/AST/StmtCXX.h"
23 #include "clang/AST/StmtOpenMP.h"
24 #include "clang/AST/StmtVisitor.h"
25 #include "clang/AST/TypeOrdering.h"
26 #include "clang/Basic/DiagnosticSema.h"
27 #include "clang/Basic/OpenMPKinds.h"
28 #include "clang/Basic/PartialDiagnostic.h"
29 #include "clang/Basic/TargetInfo.h"
30 #include "clang/Sema/EnterExpressionEvaluationContext.h"
31 #include "clang/Sema/Initialization.h"
32 #include "clang/Sema/Lookup.h"
33 #include "clang/Sema/ParsedAttr.h"
34 #include "clang/Sema/Scope.h"
35 #include "clang/Sema/ScopeInfo.h"
36 #include "clang/Sema/SemaInternal.h"
37 #include "llvm/ADT/IndexedMap.h"
38 #include "llvm/ADT/PointerEmbeddedInt.h"
39 #include "llvm/ADT/STLExtras.h"
40 #include "llvm/ADT/SmallSet.h"
41 #include "llvm/ADT/StringExtras.h"
42 #include "llvm/Frontend/OpenMP/OMPAssume.h"
43 #include "llvm/Frontend/OpenMP/OMPConstants.h"
47 using namespace clang
;
48 using namespace llvm::omp
;
50 //===----------------------------------------------------------------------===//
51 // Stack of data-sharing attributes for variables
52 //===----------------------------------------------------------------------===//
54 static const Expr
*checkMapClauseExpressionBase(
55 Sema
&SemaRef
, Expr
*E
,
56 OMPClauseMappableExprCommon::MappableExprComponentList
&CurComponents
,
57 OpenMPClauseKind CKind
, OpenMPDirectiveKind DKind
, bool NoDiagnose
);
60 /// Default data sharing attributes, which can be applied to directive.
61 enum DefaultDataSharingAttributes
{
62 DSA_unspecified
= 0, /// Data sharing attribute not specified.
63 DSA_none
= 1 << 0, /// Default data sharing attribute 'none'.
64 DSA_shared
= 1 << 1, /// Default data sharing attribute 'shared'.
65 DSA_private
= 1 << 2, /// Default data sharing attribute 'private'.
66 DSA_firstprivate
= 1 << 3, /// Default data sharing attribute 'firstprivate'.
69 /// Stack for tracking declarations used in OpenMP directives and
70 /// clauses and their data-sharing attributes.
74 OpenMPDirectiveKind DKind
= OMPD_unknown
;
75 OpenMPClauseKind CKind
= OMPC_unknown
;
76 unsigned Modifier
= 0;
77 const Expr
*RefExpr
= nullptr;
78 DeclRefExpr
*PrivateCopy
= nullptr;
79 SourceLocation ImplicitDSALoc
;
80 bool AppliedToPointee
= false;
81 DSAVarData() = default;
82 DSAVarData(OpenMPDirectiveKind DKind
, OpenMPClauseKind CKind
,
83 const Expr
*RefExpr
, DeclRefExpr
*PrivateCopy
,
84 SourceLocation ImplicitDSALoc
, unsigned Modifier
,
85 bool AppliedToPointee
)
86 : DKind(DKind
), CKind(CKind
), Modifier(Modifier
), RefExpr(RefExpr
),
87 PrivateCopy(PrivateCopy
), ImplicitDSALoc(ImplicitDSALoc
),
88 AppliedToPointee(AppliedToPointee
) {}
90 using OperatorOffsetTy
=
91 llvm::SmallVector
<std::pair
<Expr
*, OverloadedOperatorKind
>, 4>;
92 using DoacrossClauseMapTy
= llvm::DenseMap
<OMPClause
*, OperatorOffsetTy
>;
93 /// Kind of the declaration used in the uses_allocators clauses.
94 enum class UsesAllocatorsDeclKind
{
95 /// Predefined allocator
97 /// User-defined allocator
99 /// The declaration that represent allocator trait
105 OpenMPClauseKind Attributes
= OMPC_unknown
;
106 unsigned Modifier
= 0;
107 /// Pointer to a reference expression and a flag which shows that the
108 /// variable is marked as lastprivate(true) or not (false).
109 llvm::PointerIntPair
<const Expr
*, 1, bool> RefExpr
;
110 DeclRefExpr
*PrivateCopy
= nullptr;
111 /// true if the attribute is applied to the pointee, not the variable
113 bool AppliedToPointee
= false;
115 using DeclSAMapTy
= llvm::SmallDenseMap
<const ValueDecl
*, DSAInfo
, 8>;
116 using UsedRefMapTy
= llvm::SmallDenseMap
<const ValueDecl
*, const Expr
*, 8>;
117 using LCDeclInfo
= std::pair
<unsigned, VarDecl
*>;
118 using LoopControlVariablesMapTy
=
119 llvm::SmallDenseMap
<const ValueDecl
*, LCDeclInfo
, 8>;
120 /// Struct that associates a component with the clause kind where they are
122 struct MappedExprComponentTy
{
123 OMPClauseMappableExprCommon::MappableExprComponentLists Components
;
124 OpenMPClauseKind Kind
= OMPC_unknown
;
126 using MappedExprComponentsTy
=
127 llvm::DenseMap
<const ValueDecl
*, MappedExprComponentTy
>;
128 using CriticalsWithHintsTy
=
129 llvm::StringMap
<std::pair
<const OMPCriticalDirective
*, llvm::APSInt
>>;
130 struct ReductionData
{
131 using BOKPtrType
= llvm::PointerEmbeddedInt
<BinaryOperatorKind
, 16>;
132 SourceRange ReductionRange
;
133 llvm::PointerUnion
<const Expr
*, BOKPtrType
> ReductionOp
;
134 ReductionData() = default;
135 void set(BinaryOperatorKind BO
, SourceRange RR
) {
139 void set(const Expr
*RefExpr
, SourceRange RR
) {
141 ReductionOp
= RefExpr
;
144 using DeclReductionMapTy
=
145 llvm::SmallDenseMap
<const ValueDecl
*, ReductionData
, 4>;
146 struct DefaultmapInfo
{
147 OpenMPDefaultmapClauseModifier ImplicitBehavior
=
148 OMPC_DEFAULTMAP_MODIFIER_unknown
;
150 DefaultmapInfo() = default;
151 DefaultmapInfo(OpenMPDefaultmapClauseModifier M
, SourceLocation Loc
)
152 : ImplicitBehavior(M
), SLoc(Loc
) {}
155 struct SharingMapTy
{
156 DeclSAMapTy SharingMap
;
157 DeclReductionMapTy ReductionMap
;
158 UsedRefMapTy AlignedMap
;
159 UsedRefMapTy NontemporalMap
;
160 MappedExprComponentsTy MappedExprComponents
;
161 LoopControlVariablesMapTy LCVMap
;
162 DefaultDataSharingAttributes DefaultAttr
= DSA_unspecified
;
163 SourceLocation DefaultAttrLoc
;
164 DefaultmapInfo DefaultmapMap
[OMPC_DEFAULTMAP_unknown
];
165 OpenMPDirectiveKind Directive
= OMPD_unknown
;
166 /// GenericLoopDirective with bind clause is mapped to other directives,
167 /// like for, distribute and simd. Presently, set MappedDirective to
168 /// OMPLoop. This may also be used in a similar way for other constructs.
169 OpenMPDirectiveKind MappedDirective
= OMPD_unknown
;
170 DeclarationNameInfo DirectiveName
;
171 Scope
*CurScope
= nullptr;
172 DeclContext
*Context
= nullptr;
173 SourceLocation ConstructLoc
;
174 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
175 /// get the data (loop counters etc.) about enclosing loop-based construct.
176 /// This data is required during codegen.
177 DoacrossClauseMapTy DoacrossDepends
;
178 /// First argument (Expr *) contains optional argument of the
179 /// 'ordered' clause, the second one is true if the regions has 'ordered'
180 /// clause, false otherwise.
181 std::optional
<std::pair
<const Expr
*, OMPOrderedClause
*>> OrderedRegion
;
182 bool RegionHasOrderConcurrent
= false;
183 unsigned AssociatedLoops
= 1;
184 bool HasMutipleLoops
= false;
185 const Decl
*PossiblyLoopCounter
= nullptr;
186 bool NowaitRegion
= false;
187 bool UntiedRegion
= false;
188 bool CancelRegion
= false;
189 bool LoopStart
= false;
190 bool BodyComplete
= false;
191 SourceLocation PrevScanLocation
;
192 SourceLocation PrevOrderedLocation
;
193 SourceLocation InnerTeamsRegionLoc
;
194 /// Reference to the taskgroup task_reduction reference expression.
195 Expr
*TaskgroupReductionRef
= nullptr;
196 llvm::DenseSet
<QualType
> MappedClassesQualTypes
;
197 SmallVector
<Expr
*, 4> InnerUsedAllocators
;
198 llvm::DenseSet
<CanonicalDeclPtr
<Decl
>> ImplicitTaskFirstprivates
;
199 /// List of globals marked as declare target link in this target region
200 /// (isOpenMPTargetExecutionDirective(Directive) == true).
201 llvm::SmallVector
<DeclRefExpr
*, 4> DeclareTargetLinkVarDecls
;
202 /// List of decls used in inclusive/exclusive clauses of the scan directive.
203 llvm::DenseSet
<CanonicalDeclPtr
<Decl
>> UsedInScanDirective
;
204 llvm::DenseMap
<CanonicalDeclPtr
<const Decl
>, UsesAllocatorsDeclKind
>
206 /// Data is required on creating capture fields for implicit
207 /// default first|private clause.
208 struct ImplicitDefaultFDInfoTy
{
210 const FieldDecl
*FD
= nullptr;
211 /// Nesting stack level
212 size_t StackLevel
= 0;
213 /// Capture variable decl.
214 VarDecl
*VD
= nullptr;
215 ImplicitDefaultFDInfoTy(const FieldDecl
*FD
, size_t StackLevel
,
217 : FD(FD
), StackLevel(StackLevel
), VD(VD
) {}
219 /// List of captured fields
220 llvm::SmallVector
<ImplicitDefaultFDInfoTy
, 8>
221 ImplicitDefaultFirstprivateFDs
;
222 Expr
*DeclareMapperVar
= nullptr;
223 SmallVector
<VarDecl
*, 16> IteratorVarDecls
;
224 SharingMapTy(OpenMPDirectiveKind DKind
, DeclarationNameInfo Name
,
225 Scope
*CurScope
, SourceLocation Loc
)
226 : Directive(DKind
), DirectiveName(Name
), CurScope(CurScope
),
228 SharingMapTy() = default;
231 using StackTy
= SmallVector
<SharingMapTy
, 4>;
233 /// Stack of used declaration and their data-sharing attributes.
234 DeclSAMapTy Threadprivates
;
235 const FunctionScopeInfo
*CurrentNonCapturingFunctionScope
= nullptr;
236 SmallVector
<std::pair
<StackTy
, const FunctionScopeInfo
*>, 4> Stack
;
237 /// true, if check for DSA must be from parent directive, false, if
238 /// from current directive.
239 OpenMPClauseKind ClauseKindMode
= OMPC_unknown
;
241 bool ForceCapturing
= false;
242 /// true if all the variables in the target executable directives must be
243 /// captured by reference.
244 bool ForceCaptureByReferenceInTargetExecutable
= false;
245 CriticalsWithHintsTy Criticals
;
246 unsigned IgnoredStackElements
= 0;
248 /// Iterators over the stack iterate in order from innermost to outermost
250 using const_iterator
= StackTy::const_reverse_iterator
;
251 const_iterator
begin() const {
252 return Stack
.empty() ? const_iterator()
253 : Stack
.back().first
.rbegin() + IgnoredStackElements
;
255 const_iterator
end() const {
256 return Stack
.empty() ? const_iterator() : Stack
.back().first
.rend();
258 using iterator
= StackTy::reverse_iterator
;
260 return Stack
.empty() ? iterator()
261 : Stack
.back().first
.rbegin() + IgnoredStackElements
;
264 return Stack
.empty() ? iterator() : Stack
.back().first
.rend();
267 // Convenience operations to get at the elements of the stack.
269 bool isStackEmpty() const {
270 return Stack
.empty() ||
271 Stack
.back().second
!= CurrentNonCapturingFunctionScope
||
272 Stack
.back().first
.size() <= IgnoredStackElements
;
274 size_t getStackSize() const {
275 return isStackEmpty() ? 0
276 : Stack
.back().first
.size() - IgnoredStackElements
;
279 SharingMapTy
*getTopOfStackOrNull() {
280 size_t Size
= getStackSize();
283 return &Stack
.back().first
[Size
- 1];
285 const SharingMapTy
*getTopOfStackOrNull() const {
286 return const_cast<DSAStackTy
&>(*this).getTopOfStackOrNull();
288 SharingMapTy
&getTopOfStack() {
289 assert(!isStackEmpty() && "no current directive");
290 return *getTopOfStackOrNull();
292 const SharingMapTy
&getTopOfStack() const {
293 return const_cast<DSAStackTy
&>(*this).getTopOfStack();
296 SharingMapTy
*getSecondOnStackOrNull() {
297 size_t Size
= getStackSize();
300 return &Stack
.back().first
[Size
- 2];
302 const SharingMapTy
*getSecondOnStackOrNull() const {
303 return const_cast<DSAStackTy
&>(*this).getSecondOnStackOrNull();
306 /// Get the stack element at a certain level (previously returned by
307 /// \c getNestingLevel).
309 /// Note that nesting levels count from outermost to innermost, and this is
310 /// the reverse of our iteration order where new inner levels are pushed at
311 /// the front of the stack.
312 SharingMapTy
&getStackElemAtLevel(unsigned Level
) {
313 assert(Level
< getStackSize() && "no such stack element");
314 return Stack
.back().first
[Level
];
316 const SharingMapTy
&getStackElemAtLevel(unsigned Level
) const {
317 return const_cast<DSAStackTy
&>(*this).getStackElemAtLevel(Level
);
320 DSAVarData
getDSA(const_iterator
&Iter
, ValueDecl
*D
) const;
322 /// Checks if the variable is a local for OpenMP region.
323 bool isOpenMPLocal(VarDecl
*D
, const_iterator Iter
) const;
325 /// Vector of previously declared requires directives
326 SmallVector
<const OMPRequiresDecl
*, 2> RequiresDecls
;
327 /// omp_allocator_handle_t type.
328 QualType OMPAllocatorHandleT
;
329 /// omp_depend_t type.
331 /// omp_event_handle_t type.
332 QualType OMPEventHandleT
;
333 /// omp_alloctrait_t type.
334 QualType OMPAlloctraitT
;
335 /// Expression for the predefined allocators.
336 Expr
*OMPPredefinedAllocators
[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc
] = {
338 /// Vector of previously encountered target directives
339 SmallVector
<SourceLocation
, 2> TargetLocations
;
340 SourceLocation AtomicLocation
;
341 /// Vector of declare variant construct traits.
342 SmallVector
<llvm::omp::TraitProperty
, 8> ConstructTraits
;
345 explicit DSAStackTy(Sema
&S
) : SemaRef(S
) {}
347 /// Sets omp_allocator_handle_t type.
348 void setOMPAllocatorHandleT(QualType Ty
) { OMPAllocatorHandleT
= Ty
; }
349 /// Gets omp_allocator_handle_t type.
350 QualType
getOMPAllocatorHandleT() const { return OMPAllocatorHandleT
; }
351 /// Sets omp_alloctrait_t type.
352 void setOMPAlloctraitT(QualType Ty
) { OMPAlloctraitT
= Ty
; }
353 /// Gets omp_alloctrait_t type.
354 QualType
getOMPAlloctraitT() const { return OMPAlloctraitT
; }
355 /// Sets the given default allocator.
356 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind
,
358 OMPPredefinedAllocators
[AllocatorKind
] = Allocator
;
360 /// Returns the specified default allocator.
361 Expr
*getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind
) const {
362 return OMPPredefinedAllocators
[AllocatorKind
];
364 /// Sets omp_depend_t type.
365 void setOMPDependT(QualType Ty
) { OMPDependT
= Ty
; }
366 /// Gets omp_depend_t type.
367 QualType
getOMPDependT() const { return OMPDependT
; }
369 /// Sets omp_event_handle_t type.
370 void setOMPEventHandleT(QualType Ty
) { OMPEventHandleT
= Ty
; }
371 /// Gets omp_event_handle_t type.
372 QualType
getOMPEventHandleT() const { return OMPEventHandleT
; }
374 bool isClauseParsingMode() const { return ClauseKindMode
!= OMPC_unknown
; }
375 OpenMPClauseKind
getClauseParsingMode() const {
376 assert(isClauseParsingMode() && "Must be in clause parsing mode.");
377 return ClauseKindMode
;
379 void setClauseParsingMode(OpenMPClauseKind K
) { ClauseKindMode
= K
; }
381 bool isBodyComplete() const {
382 const SharingMapTy
*Top
= getTopOfStackOrNull();
383 return Top
&& Top
->BodyComplete
;
385 void setBodyComplete() { getTopOfStack().BodyComplete
= true; }
387 bool isForceVarCapturing() const { return ForceCapturing
; }
388 void setForceVarCapturing(bool V
) { ForceCapturing
= V
; }
390 void setForceCaptureByReferenceInTargetExecutable(bool V
) {
391 ForceCaptureByReferenceInTargetExecutable
= V
;
393 bool isForceCaptureByReferenceInTargetExecutable() const {
394 return ForceCaptureByReferenceInTargetExecutable
;
397 void push(OpenMPDirectiveKind DKind
, const DeclarationNameInfo
&DirName
,
398 Scope
*CurScope
, SourceLocation Loc
) {
399 assert(!IgnoredStackElements
&&
400 "cannot change stack while ignoring elements");
402 Stack
.back().second
!= CurrentNonCapturingFunctionScope
)
403 Stack
.emplace_back(StackTy(), CurrentNonCapturingFunctionScope
);
404 Stack
.back().first
.emplace_back(DKind
, DirName
, CurScope
, Loc
);
405 Stack
.back().first
.back().DefaultAttrLoc
= Loc
;
409 assert(!IgnoredStackElements
&&
410 "cannot change stack while ignoring elements");
411 assert(!Stack
.back().first
.empty() &&
412 "Data-sharing attributes stack is empty!");
413 Stack
.back().first
.pop_back();
416 /// RAII object to temporarily leave the scope of a directive when we want to
417 /// logically operate in its parent.
418 class ParentDirectiveScope
{
423 ParentDirectiveScope(DSAStackTy
&Self
, bool Activate
)
424 : Self(Self
), Active(false) {
428 ~ParentDirectiveScope() { disable(); }
431 --Self
.IgnoredStackElements
;
437 ++Self
.IgnoredStackElements
;
443 /// Marks that we're started loop parsing.
445 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
446 "Expected loop-based directive.");
447 getTopOfStack().LoopStart
= true;
449 /// Start capturing of the variables in the loop context.
451 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
452 "Expected loop-based directive.");
453 getTopOfStack().LoopStart
= false;
455 /// true, if variables are captured, false otherwise.
456 bool isLoopStarted() const {
457 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
458 "Expected loop-based directive.");
459 return !getTopOfStack().LoopStart
;
461 /// Marks (or clears) declaration as possibly loop counter.
462 void resetPossibleLoopCounter(const Decl
*D
= nullptr) {
463 getTopOfStack().PossiblyLoopCounter
= D
? D
->getCanonicalDecl() : D
;
465 /// Gets the possible loop counter decl.
466 const Decl
*getPossiblyLoopCunter() const {
467 return getTopOfStack().PossiblyLoopCounter
;
469 /// Start new OpenMP region stack in new non-capturing function.
470 void pushFunction() {
471 assert(!IgnoredStackElements
&&
472 "cannot change stack while ignoring elements");
473 const FunctionScopeInfo
*CurFnScope
= SemaRef
.getCurFunction();
474 assert(!isa
<CapturingScopeInfo
>(CurFnScope
));
475 CurrentNonCapturingFunctionScope
= CurFnScope
;
477 /// Pop region stack for non-capturing function.
478 void popFunction(const FunctionScopeInfo
*OldFSI
) {
479 assert(!IgnoredStackElements
&&
480 "cannot change stack while ignoring elements");
481 if (!Stack
.empty() && Stack
.back().second
== OldFSI
) {
482 assert(Stack
.back().first
.empty());
485 CurrentNonCapturingFunctionScope
= nullptr;
486 for (const FunctionScopeInfo
*FSI
: llvm::reverse(SemaRef
.FunctionScopes
)) {
487 if (!isa
<CapturingScopeInfo
>(FSI
)) {
488 CurrentNonCapturingFunctionScope
= FSI
;
494 void addCriticalWithHint(const OMPCriticalDirective
*D
, llvm::APSInt Hint
) {
495 Criticals
.try_emplace(D
->getDirectiveName().getAsString(), D
, Hint
);
497 const std::pair
<const OMPCriticalDirective
*, llvm::APSInt
>
498 getCriticalWithHint(const DeclarationNameInfo
&Name
) const {
499 auto I
= Criticals
.find(Name
.getAsString());
500 if (I
!= Criticals
.end())
502 return std::make_pair(nullptr, llvm::APSInt());
504 /// If 'aligned' declaration for given variable \a D was not seen yet,
505 /// add it and return NULL; otherwise return previous occurrence's expression
507 const Expr
*addUniqueAligned(const ValueDecl
*D
, const Expr
*NewDE
);
508 /// If 'nontemporal' declaration for given variable \a D was not seen yet,
509 /// add it and return NULL; otherwise return previous occurrence's expression
511 const Expr
*addUniqueNontemporal(const ValueDecl
*D
, const Expr
*NewDE
);
513 /// Register specified variable as loop control variable.
514 void addLoopControlVariable(const ValueDecl
*D
, VarDecl
*Capture
);
515 /// Check if the specified variable is a loop control variable for
517 /// \return The index of the loop control variable in the list of associated
518 /// for-loops (from outer to inner).
519 const LCDeclInfo
isLoopControlVariable(const ValueDecl
*D
) const;
520 /// Check if the specified variable is a loop control variable for
522 /// \return The index of the loop control variable in the list of associated
523 /// for-loops (from outer to inner).
524 const LCDeclInfo
isParentLoopControlVariable(const ValueDecl
*D
) const;
525 /// Check if the specified variable is a loop control variable for
527 /// \return The index of the loop control variable in the list of associated
528 /// for-loops (from outer to inner).
529 const LCDeclInfo
isLoopControlVariable(const ValueDecl
*D
,
530 unsigned Level
) const;
531 /// Get the loop control variable for the I-th loop (or nullptr) in
532 /// parent directive.
533 const ValueDecl
*getParentLoopControlVariable(unsigned I
) const;
535 /// Marks the specified decl \p D as used in scan directive.
536 void markDeclAsUsedInScanDirective(ValueDecl
*D
) {
537 if (SharingMapTy
*Stack
= getSecondOnStackOrNull())
538 Stack
->UsedInScanDirective
.insert(D
);
541 /// Checks if the specified declaration was used in the inner scan directive.
542 bool isUsedInScanDirective(ValueDecl
*D
) const {
543 if (const SharingMapTy
*Stack
= getTopOfStackOrNull())
544 return Stack
->UsedInScanDirective
.contains(D
);
548 /// Adds explicit data sharing attribute to the specified declaration.
549 void addDSA(const ValueDecl
*D
, const Expr
*E
, OpenMPClauseKind A
,
550 DeclRefExpr
*PrivateCopy
= nullptr, unsigned Modifier
= 0,
551 bool AppliedToPointee
= false);
553 /// Adds additional information for the reduction items with the reduction id
554 /// represented as an operator.
555 void addTaskgroupReductionData(const ValueDecl
*D
, SourceRange SR
,
556 BinaryOperatorKind BOK
);
557 /// Adds additional information for the reduction items with the reduction id
558 /// represented as reduction identifier.
559 void addTaskgroupReductionData(const ValueDecl
*D
, SourceRange SR
,
560 const Expr
*ReductionRef
);
561 /// Returns the location and reduction operation from the innermost parent
562 /// region for the given \p D.
564 getTopMostTaskgroupReductionData(const ValueDecl
*D
, SourceRange
&SR
,
565 BinaryOperatorKind
&BOK
,
566 Expr
*&TaskgroupDescriptor
) const;
567 /// Returns the location and reduction operation from the innermost parent
568 /// region for the given \p D.
570 getTopMostTaskgroupReductionData(const ValueDecl
*D
, SourceRange
&SR
,
571 const Expr
*&ReductionRef
,
572 Expr
*&TaskgroupDescriptor
) const;
573 /// Return reduction reference expression for the current taskgroup or
574 /// parallel/worksharing directives with task reductions.
575 Expr
*getTaskgroupReductionRef() const {
576 assert((getTopOfStack().Directive
== OMPD_taskgroup
||
577 ((isOpenMPParallelDirective(getTopOfStack().Directive
) ||
578 isOpenMPWorksharingDirective(getTopOfStack().Directive
)) &&
579 !isOpenMPSimdDirective(getTopOfStack().Directive
))) &&
580 "taskgroup reference expression requested for non taskgroup or "
581 "parallel/worksharing directive.");
582 return getTopOfStack().TaskgroupReductionRef
;
584 /// Checks if the given \p VD declaration is actually a taskgroup reduction
585 /// descriptor variable at the \p Level of OpenMP regions.
586 bool isTaskgroupReductionRef(const ValueDecl
*VD
, unsigned Level
) const {
587 return getStackElemAtLevel(Level
).TaskgroupReductionRef
&&
588 cast
<DeclRefExpr
>(getStackElemAtLevel(Level
).TaskgroupReductionRef
)
592 /// Returns data sharing attributes from top of the stack for the
593 /// specified declaration.
594 const DSAVarData
getTopDSA(ValueDecl
*D
, bool FromParent
);
595 /// Returns data-sharing attributes for the specified declaration.
596 const DSAVarData
getImplicitDSA(ValueDecl
*D
, bool FromParent
) const;
597 /// Returns data-sharing attributes for the specified declaration.
598 const DSAVarData
getImplicitDSA(ValueDecl
*D
, unsigned Level
) const;
599 /// Checks if the specified variables has data-sharing attributes which
600 /// match specified \a CPred predicate in any directive which matches \a DPred
604 const llvm::function_ref
<bool(OpenMPClauseKind
, bool,
605 DefaultDataSharingAttributes
)>
607 const llvm::function_ref
<bool(OpenMPDirectiveKind
)> DPred
,
608 bool FromParent
) const;
609 /// Checks if the specified variables has data-sharing attributes which
610 /// match specified \a CPred predicate in any innermost directive which
611 /// matches \a DPred predicate.
613 hasInnermostDSA(ValueDecl
*D
,
614 const llvm::function_ref
<bool(OpenMPClauseKind
, bool)> CPred
,
615 const llvm::function_ref
<bool(OpenMPDirectiveKind
)> DPred
,
616 bool FromParent
) const;
617 /// Checks if the specified variables has explicit data-sharing
618 /// attributes which match specified \a CPred predicate at the specified
621 hasExplicitDSA(const ValueDecl
*D
,
622 const llvm::function_ref
<bool(OpenMPClauseKind
, bool)> CPred
,
623 unsigned Level
, bool NotLastprivate
= false) const;
625 /// Returns true if the directive at level \Level matches in the
626 /// specified \a DPred predicate.
627 bool hasExplicitDirective(
628 const llvm::function_ref
<bool(OpenMPDirectiveKind
)> DPred
,
629 unsigned Level
) const;
631 /// Finds a directive which matches specified \a DPred predicate.
633 const llvm::function_ref
<bool(
634 OpenMPDirectiveKind
, const DeclarationNameInfo
&, SourceLocation
)>
636 bool FromParent
) const;
638 /// Returns currently analyzed directive.
639 OpenMPDirectiveKind
getCurrentDirective() const {
640 const SharingMapTy
*Top
= getTopOfStackOrNull();
641 return Top
? Top
->Directive
: OMPD_unknown
;
643 OpenMPDirectiveKind
getMappedDirective() const {
644 const SharingMapTy
*Top
= getTopOfStackOrNull();
645 return Top
? Top
->MappedDirective
: OMPD_unknown
;
647 void setCurrentDirective(OpenMPDirectiveKind NewDK
) {
648 SharingMapTy
*Top
= getTopOfStackOrNull();
650 "Before calling setCurrentDirective Top of Stack not to be NULL.");
651 // Store the old into MappedDirective & assign argument NewDK to Directive.
652 Top
->Directive
= NewDK
;
654 void setMappedDirective(OpenMPDirectiveKind NewDK
) {
655 SharingMapTy
*Top
= getTopOfStackOrNull();
657 "Before calling setMappedDirective Top of Stack not to be NULL.");
658 // Store the old into MappedDirective & assign argument NewDK to Directive.
659 Top
->MappedDirective
= NewDK
;
661 /// Returns directive kind at specified level.
662 OpenMPDirectiveKind
getDirective(unsigned Level
) const {
663 assert(!isStackEmpty() && "No directive at specified level.");
664 return getStackElemAtLevel(Level
).Directive
;
666 /// Returns the capture region at the specified level.
667 OpenMPDirectiveKind
getCaptureRegion(unsigned Level
,
668 unsigned OpenMPCaptureLevel
) const {
669 SmallVector
<OpenMPDirectiveKind
, 4> CaptureRegions
;
670 getOpenMPCaptureRegions(CaptureRegions
, getDirective(Level
));
671 return CaptureRegions
[OpenMPCaptureLevel
];
673 /// Returns parent directive.
674 OpenMPDirectiveKind
getParentDirective() const {
675 const SharingMapTy
*Parent
= getSecondOnStackOrNull();
676 return Parent
? Parent
->Directive
: OMPD_unknown
;
679 /// Add requires decl to internal vector
680 void addRequiresDecl(OMPRequiresDecl
*RD
) { RequiresDecls
.push_back(RD
); }
682 /// Checks if the defined 'requires' directive has specified type of clause.
683 template <typename ClauseType
> bool hasRequiresDeclWithClause() const {
684 return llvm::any_of(RequiresDecls
, [](const OMPRequiresDecl
*D
) {
685 return llvm::any_of(D
->clauselists(), [](const OMPClause
*C
) {
686 return isa
<ClauseType
>(C
);
691 /// Checks for a duplicate clause amongst previously declared requires
693 bool hasDuplicateRequiresClause(ArrayRef
<OMPClause
*> ClauseList
) const {
694 bool IsDuplicate
= false;
695 for (OMPClause
*CNew
: ClauseList
) {
696 for (const OMPRequiresDecl
*D
: RequiresDecls
) {
697 for (const OMPClause
*CPrev
: D
->clauselists()) {
698 if (CNew
->getClauseKind() == CPrev
->getClauseKind()) {
699 SemaRef
.Diag(CNew
->getBeginLoc(),
700 diag::err_omp_requires_clause_redeclaration
)
701 << getOpenMPClauseName(CNew
->getClauseKind());
702 SemaRef
.Diag(CPrev
->getBeginLoc(),
703 diag::note_omp_requires_previous_clause
)
704 << getOpenMPClauseName(CPrev
->getClauseKind());
713 /// Add location of previously encountered target to internal vector
714 void addTargetDirLocation(SourceLocation LocStart
) {
715 TargetLocations
.push_back(LocStart
);
718 /// Add location for the first encountered atomicc directive.
719 void addAtomicDirectiveLoc(SourceLocation Loc
) {
720 if (AtomicLocation
.isInvalid())
721 AtomicLocation
= Loc
;
724 /// Returns the location of the first encountered atomic directive in the
726 SourceLocation
getAtomicDirectiveLoc() const { return AtomicLocation
; }
728 // Return previously encountered target region locations.
729 ArrayRef
<SourceLocation
> getEncounteredTargetLocs() const {
730 return TargetLocations
;
733 /// Set default data sharing attribute to none.
734 void setDefaultDSANone(SourceLocation Loc
) {
735 getTopOfStack().DefaultAttr
= DSA_none
;
736 getTopOfStack().DefaultAttrLoc
= Loc
;
738 /// Set default data sharing attribute to shared.
739 void setDefaultDSAShared(SourceLocation Loc
) {
740 getTopOfStack().DefaultAttr
= DSA_shared
;
741 getTopOfStack().DefaultAttrLoc
= Loc
;
743 /// Set default data sharing attribute to private.
744 void setDefaultDSAPrivate(SourceLocation Loc
) {
745 getTopOfStack().DefaultAttr
= DSA_private
;
746 getTopOfStack().DefaultAttrLoc
= Loc
;
748 /// Set default data sharing attribute to firstprivate.
749 void setDefaultDSAFirstPrivate(SourceLocation Loc
) {
750 getTopOfStack().DefaultAttr
= DSA_firstprivate
;
751 getTopOfStack().DefaultAttrLoc
= Loc
;
753 /// Set default data mapping attribute to Modifier:Kind
754 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M
,
755 OpenMPDefaultmapClauseKind Kind
, SourceLocation Loc
) {
756 DefaultmapInfo
&DMI
= getTopOfStack().DefaultmapMap
[Kind
];
757 DMI
.ImplicitBehavior
= M
;
760 /// Check whether the implicit-behavior has been set in defaultmap
761 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory
) {
762 if (VariableCategory
== OMPC_DEFAULTMAP_unknown
)
763 return getTopOfStack()
764 .DefaultmapMap
[OMPC_DEFAULTMAP_aggregate
]
765 .ImplicitBehavior
!= OMPC_DEFAULTMAP_MODIFIER_unknown
||
767 .DefaultmapMap
[OMPC_DEFAULTMAP_scalar
]
768 .ImplicitBehavior
!= OMPC_DEFAULTMAP_MODIFIER_unknown
||
770 .DefaultmapMap
[OMPC_DEFAULTMAP_pointer
]
771 .ImplicitBehavior
!= OMPC_DEFAULTMAP_MODIFIER_unknown
;
772 return getTopOfStack().DefaultmapMap
[VariableCategory
].ImplicitBehavior
!=
773 OMPC_DEFAULTMAP_MODIFIER_unknown
;
776 ArrayRef
<llvm::omp::TraitProperty
> getConstructTraits() {
777 return ConstructTraits
;
779 void handleConstructTrait(ArrayRef
<llvm::omp::TraitProperty
> Traits
,
782 ConstructTraits
.append(Traits
.begin(), Traits
.end());
784 for (llvm::omp::TraitProperty Trait
: llvm::reverse(Traits
)) {
785 llvm::omp::TraitProperty Top
= ConstructTraits
.pop_back_val();
786 assert(Top
== Trait
&& "Something left a trait on the stack!");
792 DefaultDataSharingAttributes
getDefaultDSA(unsigned Level
) const {
793 return getStackSize() <= Level
? DSA_unspecified
794 : getStackElemAtLevel(Level
).DefaultAttr
;
796 DefaultDataSharingAttributes
getDefaultDSA() const {
797 return isStackEmpty() ? DSA_unspecified
: getTopOfStack().DefaultAttr
;
799 SourceLocation
getDefaultDSALocation() const {
800 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc
;
802 OpenMPDefaultmapClauseModifier
803 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind
) const {
804 return isStackEmpty()
805 ? OMPC_DEFAULTMAP_MODIFIER_unknown
806 : getTopOfStack().DefaultmapMap
[Kind
].ImplicitBehavior
;
808 OpenMPDefaultmapClauseModifier
809 getDefaultmapModifierAtLevel(unsigned Level
,
810 OpenMPDefaultmapClauseKind Kind
) const {
811 return getStackElemAtLevel(Level
).DefaultmapMap
[Kind
].ImplicitBehavior
;
813 bool isDefaultmapCapturedByRef(unsigned Level
,
814 OpenMPDefaultmapClauseKind Kind
) const {
815 OpenMPDefaultmapClauseModifier M
=
816 getDefaultmapModifierAtLevel(Level
, Kind
);
817 if (Kind
== OMPC_DEFAULTMAP_scalar
|| Kind
== OMPC_DEFAULTMAP_pointer
) {
818 return (M
== OMPC_DEFAULTMAP_MODIFIER_alloc
) ||
819 (M
== OMPC_DEFAULTMAP_MODIFIER_to
) ||
820 (M
== OMPC_DEFAULTMAP_MODIFIER_from
) ||
821 (M
== OMPC_DEFAULTMAP_MODIFIER_tofrom
);
825 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M
,
826 OpenMPDefaultmapClauseKind Kind
) {
828 case OMPC_DEFAULTMAP_scalar
:
829 case OMPC_DEFAULTMAP_pointer
:
830 return (M
== OMPC_DEFAULTMAP_MODIFIER_unknown
) ||
831 (M
== OMPC_DEFAULTMAP_MODIFIER_firstprivate
) ||
832 (M
== OMPC_DEFAULTMAP_MODIFIER_default
);
833 case OMPC_DEFAULTMAP_aggregate
:
834 return M
== OMPC_DEFAULTMAP_MODIFIER_firstprivate
;
838 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum");
840 bool mustBeFirstprivateAtLevel(unsigned Level
,
841 OpenMPDefaultmapClauseKind Kind
) const {
842 OpenMPDefaultmapClauseModifier M
=
843 getDefaultmapModifierAtLevel(Level
, Kind
);
844 return mustBeFirstprivateBase(M
, Kind
);
846 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind
) const {
847 OpenMPDefaultmapClauseModifier M
= getDefaultmapModifier(Kind
);
848 return mustBeFirstprivateBase(M
, Kind
);
851 /// Checks if the specified variable is a threadprivate.
852 bool isThreadPrivate(VarDecl
*D
) {
853 const DSAVarData DVar
= getTopDSA(D
, false);
854 return isOpenMPThreadPrivate(DVar
.CKind
);
857 /// Marks current region as ordered (it has an 'ordered' clause).
858 void setOrderedRegion(bool IsOrdered
, const Expr
*Param
,
859 OMPOrderedClause
*Clause
) {
861 getTopOfStack().OrderedRegion
.emplace(Param
, Clause
);
863 getTopOfStack().OrderedRegion
.reset();
865 /// Returns true, if region is ordered (has associated 'ordered' clause),
866 /// false - otherwise.
867 bool isOrderedRegion() const {
868 if (const SharingMapTy
*Top
= getTopOfStackOrNull())
869 return Top
->OrderedRegion
.has_value();
872 /// Returns optional parameter for the ordered region.
873 std::pair
<const Expr
*, OMPOrderedClause
*> getOrderedRegionParam() const {
874 if (const SharingMapTy
*Top
= getTopOfStackOrNull())
875 if (Top
->OrderedRegion
)
876 return *Top
->OrderedRegion
;
877 return std::make_pair(nullptr, nullptr);
879 /// Returns true, if parent region is ordered (has associated
880 /// 'ordered' clause), false - otherwise.
881 bool isParentOrderedRegion() const {
882 if (const SharingMapTy
*Parent
= getSecondOnStackOrNull())
883 return Parent
->OrderedRegion
.has_value();
886 /// Returns optional parameter for the ordered region.
887 std::pair
<const Expr
*, OMPOrderedClause
*>
888 getParentOrderedRegionParam() const {
889 if (const SharingMapTy
*Parent
= getSecondOnStackOrNull())
890 if (Parent
->OrderedRegion
)
891 return *Parent
->OrderedRegion
;
892 return std::make_pair(nullptr, nullptr);
894 /// Marks current region as having an 'order' clause.
895 void setRegionHasOrderConcurrent(bool HasOrderConcurrent
) {
896 getTopOfStack().RegionHasOrderConcurrent
= HasOrderConcurrent
;
898 /// Returns true, if parent region is order (has associated
899 /// 'order' clause), false - otherwise.
900 bool isParentOrderConcurrent() const {
901 if (const SharingMapTy
*Parent
= getSecondOnStackOrNull())
902 return Parent
->RegionHasOrderConcurrent
;
905 /// Marks current region as nowait (it has a 'nowait' clause).
906 void setNowaitRegion(bool IsNowait
= true) {
907 getTopOfStack().NowaitRegion
= IsNowait
;
909 /// Returns true, if parent region is nowait (has associated
910 /// 'nowait' clause), false - otherwise.
911 bool isParentNowaitRegion() const {
912 if (const SharingMapTy
*Parent
= getSecondOnStackOrNull())
913 return Parent
->NowaitRegion
;
916 /// Marks current region as untied (it has a 'untied' clause).
917 void setUntiedRegion(bool IsUntied
= true) {
918 getTopOfStack().UntiedRegion
= IsUntied
;
920 /// Return true if current region is untied.
921 bool isUntiedRegion() const {
922 const SharingMapTy
*Top
= getTopOfStackOrNull();
923 return Top
? Top
->UntiedRegion
: false;
925 /// Marks parent region as cancel region.
926 void setParentCancelRegion(bool Cancel
= true) {
927 if (SharingMapTy
*Parent
= getSecondOnStackOrNull())
928 Parent
->CancelRegion
|= Cancel
;
930 /// Return true if current region has inner cancel construct.
931 bool isCancelRegion() const {
932 const SharingMapTy
*Top
= getTopOfStackOrNull();
933 return Top
? Top
->CancelRegion
: false;
936 /// Mark that parent region already has scan directive.
937 void setParentHasScanDirective(SourceLocation Loc
) {
938 if (SharingMapTy
*Parent
= getSecondOnStackOrNull())
939 Parent
->PrevScanLocation
= Loc
;
941 /// Return true if current region has inner cancel construct.
942 bool doesParentHasScanDirective() const {
943 const SharingMapTy
*Top
= getSecondOnStackOrNull();
944 return Top
? Top
->PrevScanLocation
.isValid() : false;
946 /// Return true if current region has inner cancel construct.
947 SourceLocation
getParentScanDirectiveLoc() const {
948 const SharingMapTy
*Top
= getSecondOnStackOrNull();
949 return Top
? Top
->PrevScanLocation
: SourceLocation();
951 /// Mark that parent region already has ordered directive.
952 void setParentHasOrderedDirective(SourceLocation Loc
) {
953 if (SharingMapTy
*Parent
= getSecondOnStackOrNull())
954 Parent
->PrevOrderedLocation
= Loc
;
956 /// Return true if current region has inner ordered construct.
957 bool doesParentHasOrderedDirective() const {
958 const SharingMapTy
*Top
= getSecondOnStackOrNull();
959 return Top
? Top
->PrevOrderedLocation
.isValid() : false;
961 /// Returns the location of the previously specified ordered directive.
962 SourceLocation
getParentOrderedDirectiveLoc() const {
963 const SharingMapTy
*Top
= getSecondOnStackOrNull();
964 return Top
? Top
->PrevOrderedLocation
: SourceLocation();
967 /// Set collapse value for the region.
968 void setAssociatedLoops(unsigned Val
) {
969 getTopOfStack().AssociatedLoops
= Val
;
971 getTopOfStack().HasMutipleLoops
= true;
973 /// Return collapse value for region.
974 unsigned getAssociatedLoops() const {
975 const SharingMapTy
*Top
= getTopOfStackOrNull();
976 return Top
? Top
->AssociatedLoops
: 0;
978 /// Returns true if the construct is associated with multiple loops.
979 bool hasMutipleLoops() const {
980 const SharingMapTy
*Top
= getTopOfStackOrNull();
981 return Top
? Top
->HasMutipleLoops
: false;
984 /// Marks current target region as one with closely nested teams
986 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc
) {
987 if (SharingMapTy
*Parent
= getSecondOnStackOrNull())
988 Parent
->InnerTeamsRegionLoc
= TeamsRegionLoc
;
990 /// Returns true, if current region has closely nested teams region.
991 bool hasInnerTeamsRegion() const {
992 return getInnerTeamsRegionLoc().isValid();
994 /// Returns location of the nested teams region (if any).
995 SourceLocation
getInnerTeamsRegionLoc() const {
996 const SharingMapTy
*Top
= getTopOfStackOrNull();
997 return Top
? Top
->InnerTeamsRegionLoc
: SourceLocation();
1000 Scope
*getCurScope() const {
1001 const SharingMapTy
*Top
= getTopOfStackOrNull();
1002 return Top
? Top
->CurScope
: nullptr;
1004 void setContext(DeclContext
*DC
) { getTopOfStack().Context
= DC
; }
1005 SourceLocation
getConstructLoc() const {
1006 const SharingMapTy
*Top
= getTopOfStackOrNull();
1007 return Top
? Top
->ConstructLoc
: SourceLocation();
1010 /// Do the check specified in \a Check to all component lists and return true
1011 /// if any issue is found.
1012 bool checkMappableExprComponentListsForDecl(
1013 const ValueDecl
*VD
, bool CurrentRegionOnly
,
1014 const llvm::function_ref
<
1015 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef
,
1026 if (CurrentRegionOnly
)
1029 std::advance(SI
, 1);
1031 for (; SI
!= SE
; ++SI
) {
1032 auto MI
= SI
->MappedExprComponents
.find(VD
);
1033 if (MI
!= SI
->MappedExprComponents
.end())
1034 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L
:
1035 MI
->second
.Components
)
1036 if (Check(L
, MI
->second
.Kind
))
1042 /// Do the check specified in \a Check to all component lists at a given level
1043 /// and return true if any issue is found.
1044 bool checkMappableExprComponentListsForDeclAtLevel(
1045 const ValueDecl
*VD
, unsigned Level
,
1046 const llvm::function_ref
<
1047 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef
,
1050 if (getStackSize() <= Level
)
1053 const SharingMapTy
&StackElem
= getStackElemAtLevel(Level
);
1054 auto MI
= StackElem
.MappedExprComponents
.find(VD
);
1055 if (MI
!= StackElem
.MappedExprComponents
.end())
1056 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L
:
1057 MI
->second
.Components
)
1058 if (Check(L
, MI
->second
.Kind
))
1063 /// Create a new mappable expression component list associated with a given
1064 /// declaration and initialize it with the provided list of components.
1065 void addMappableExpressionComponents(
1066 const ValueDecl
*VD
,
1067 OMPClauseMappableExprCommon::MappableExprComponentListRef Components
,
1068 OpenMPClauseKind WhereFoundClauseKind
) {
1069 MappedExprComponentTy
&MEC
= getTopOfStack().MappedExprComponents
[VD
];
1070 // Create new entry and append the new components there.
1071 MEC
.Components
.resize(MEC
.Components
.size() + 1);
1072 MEC
.Components
.back().append(Components
.begin(), Components
.end());
1073 MEC
.Kind
= WhereFoundClauseKind
;
1076 unsigned getNestingLevel() const {
1077 assert(!isStackEmpty());
1078 return getStackSize() - 1;
1080 void addDoacrossDependClause(OMPClause
*C
, const OperatorOffsetTy
&OpsOffs
) {
1081 SharingMapTy
*Parent
= getSecondOnStackOrNull();
1082 assert(Parent
&& isOpenMPWorksharingDirective(Parent
->Directive
));
1083 Parent
->DoacrossDepends
.try_emplace(C
, OpsOffs
);
1085 llvm::iterator_range
<DoacrossClauseMapTy::const_iterator
>
1086 getDoacrossDependClauses() const {
1087 const SharingMapTy
&StackElem
= getTopOfStack();
1088 if (isOpenMPWorksharingDirective(StackElem
.Directive
)) {
1089 const DoacrossClauseMapTy
&Ref
= StackElem
.DoacrossDepends
;
1090 return llvm::make_range(Ref
.begin(), Ref
.end());
1092 return llvm::make_range(StackElem
.DoacrossDepends
.end(),
1093 StackElem
.DoacrossDepends
.end());
1096 // Store types of classes which have been explicitly mapped
1097 void addMappedClassesQualTypes(QualType QT
) {
1098 SharingMapTy
&StackElem
= getTopOfStack();
1099 StackElem
.MappedClassesQualTypes
.insert(QT
);
1102 // Return set of mapped classes types
1103 bool isClassPreviouslyMapped(QualType QT
) const {
1104 const SharingMapTy
&StackElem
= getTopOfStack();
1105 return StackElem
.MappedClassesQualTypes
.contains(QT
);
1108 /// Adds global declare target to the parent target region.
1109 void addToParentTargetRegionLinkGlobals(DeclRefExpr
*E
) {
1110 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1111 E
->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link
&&
1112 "Expected declare target link global.");
1113 for (auto &Elem
: *this) {
1114 if (isOpenMPTargetExecutionDirective(Elem
.Directive
)) {
1115 Elem
.DeclareTargetLinkVarDecls
.push_back(E
);
1121 /// Returns the list of globals with declare target link if current directive
1123 ArrayRef
<DeclRefExpr
*> getLinkGlobals() const {
1124 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
1125 "Expected target executable directive.");
1126 return getTopOfStack().DeclareTargetLinkVarDecls
;
1129 /// Adds list of allocators expressions.
1130 void addInnerAllocatorExpr(Expr
*E
) {
1131 getTopOfStack().InnerUsedAllocators
.push_back(E
);
1133 /// Return list of used allocators.
1134 ArrayRef
<Expr
*> getInnerAllocators() const {
1135 return getTopOfStack().InnerUsedAllocators
;
1137 /// Marks the declaration as implicitly firstprivate nin the task-based
1139 void addImplicitTaskFirstprivate(unsigned Level
, Decl
*D
) {
1140 getStackElemAtLevel(Level
).ImplicitTaskFirstprivates
.insert(D
);
1142 /// Checks if the decl is implicitly firstprivate in the task-based region.
1143 bool isImplicitTaskFirstprivate(Decl
*D
) const {
1144 return getTopOfStack().ImplicitTaskFirstprivates
.contains(D
);
1147 /// Marks decl as used in uses_allocators clause as the allocator.
1148 void addUsesAllocatorsDecl(const Decl
*D
, UsesAllocatorsDeclKind Kind
) {
1149 getTopOfStack().UsesAllocatorsDecls
.try_emplace(D
, Kind
);
1151 /// Checks if specified decl is used in uses allocator clause as the
1153 std::optional
<UsesAllocatorsDeclKind
>
1154 isUsesAllocatorsDecl(unsigned Level
, const Decl
*D
) const {
1155 const SharingMapTy
&StackElem
= getTopOfStack();
1156 auto I
= StackElem
.UsesAllocatorsDecls
.find(D
);
1157 if (I
== StackElem
.UsesAllocatorsDecls
.end())
1158 return std::nullopt
;
1159 return I
->getSecond();
1161 std::optional
<UsesAllocatorsDeclKind
>
1162 isUsesAllocatorsDecl(const Decl
*D
) const {
1163 const SharingMapTy
&StackElem
= getTopOfStack();
1164 auto I
= StackElem
.UsesAllocatorsDecls
.find(D
);
1165 if (I
== StackElem
.UsesAllocatorsDecls
.end())
1166 return std::nullopt
;
1167 return I
->getSecond();
1170 void addDeclareMapperVarRef(Expr
*Ref
) {
1171 SharingMapTy
&StackElem
= getTopOfStack();
1172 StackElem
.DeclareMapperVar
= Ref
;
1174 const Expr
*getDeclareMapperVarRef() const {
1175 const SharingMapTy
*Top
= getTopOfStackOrNull();
1176 return Top
? Top
->DeclareMapperVar
: nullptr;
1179 /// Add a new iterator variable.
1180 void addIteratorVarDecl(VarDecl
*VD
) {
1181 SharingMapTy
&StackElem
= getTopOfStack();
1182 StackElem
.IteratorVarDecls
.push_back(VD
->getCanonicalDecl());
1184 /// Check if variable declaration is an iterator VarDecl.
1185 bool isIteratorVarDecl(const VarDecl
*VD
) const {
1186 const SharingMapTy
*Top
= getTopOfStackOrNull();
1190 return llvm::any_of(Top
->IteratorVarDecls
, [VD
](const VarDecl
*IteratorVD
) {
1191 return IteratorVD
== VD
->getCanonicalDecl();
1194 /// get captured field from ImplicitDefaultFirstprivateFDs
1195 VarDecl
*getImplicitFDCapExprDecl(const FieldDecl
*FD
) const {
1196 const_iterator I
= begin();
1197 const_iterator EndI
= end();
1198 size_t StackLevel
= getStackSize();
1199 for (; I
!= EndI
; ++I
) {
1200 if (I
->DefaultAttr
== DSA_firstprivate
|| I
->DefaultAttr
== DSA_private
)
1204 assert((StackLevel
> 0 && I
!= EndI
) || (StackLevel
== 0 && I
== EndI
));
1207 for (const auto &IFD
: I
->ImplicitDefaultFirstprivateFDs
)
1208 if (IFD
.FD
== FD
&& IFD
.StackLevel
== StackLevel
)
1212 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
1213 bool isImplicitDefaultFirstprivateFD(VarDecl
*VD
) const {
1214 const_iterator I
= begin();
1215 const_iterator EndI
= end();
1216 for (; I
!= EndI
; ++I
)
1217 if (I
->DefaultAttr
== DSA_firstprivate
|| I
->DefaultAttr
== DSA_private
)
1221 for (const auto &IFD
: I
->ImplicitDefaultFirstprivateFDs
)
1226 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
1227 void addImplicitDefaultFirstprivateFD(const FieldDecl
*FD
, VarDecl
*VD
) {
1228 iterator I
= begin();
1229 const_iterator EndI
= end();
1230 size_t StackLevel
= getStackSize();
1231 for (; I
!= EndI
; ++I
) {
1232 if (I
->DefaultAttr
== DSA_private
|| I
->DefaultAttr
== DSA_firstprivate
) {
1233 I
->ImplicitDefaultFirstprivateFDs
.emplace_back(FD
, StackLevel
, VD
);
1238 assert((StackLevel
> 0 && I
!= EndI
) || (StackLevel
== 0 && I
== EndI
));
1242 bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind
) {
1243 return isOpenMPParallelDirective(DKind
) || isOpenMPTeamsDirective(DKind
);
1246 bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind
) {
1247 return isImplicitTaskingRegion(DKind
) || isOpenMPTaskingDirective(DKind
) ||
1248 DKind
== OMPD_unknown
;
1253 static const Expr
*getExprAsWritten(const Expr
*E
) {
1254 if (const auto *FE
= dyn_cast
<FullExpr
>(E
))
1255 E
= FE
->getSubExpr();
1257 if (const auto *MTE
= dyn_cast
<MaterializeTemporaryExpr
>(E
))
1258 E
= MTE
->getSubExpr();
1260 while (const auto *Binder
= dyn_cast
<CXXBindTemporaryExpr
>(E
))
1261 E
= Binder
->getSubExpr();
1263 if (const auto *ICE
= dyn_cast
<ImplicitCastExpr
>(E
))
1264 E
= ICE
->getSubExprAsWritten();
1265 return E
->IgnoreParens();
1268 static Expr
*getExprAsWritten(Expr
*E
) {
1269 return const_cast<Expr
*>(getExprAsWritten(const_cast<const Expr
*>(E
)));
1272 static const ValueDecl
*getCanonicalDecl(const ValueDecl
*D
) {
1273 if (const auto *CED
= dyn_cast
<OMPCapturedExprDecl
>(D
))
1274 if (const auto *ME
= dyn_cast
<MemberExpr
>(getExprAsWritten(CED
->getInit())))
1275 D
= ME
->getMemberDecl();
1276 const auto *VD
= dyn_cast
<VarDecl
>(D
);
1277 const auto *FD
= dyn_cast
<FieldDecl
>(D
);
1278 if (VD
!= nullptr) {
1279 VD
= VD
->getCanonicalDecl();
1283 FD
= FD
->getCanonicalDecl();
1289 static ValueDecl
*getCanonicalDecl(ValueDecl
*D
) {
1290 return const_cast<ValueDecl
*>(
1291 getCanonicalDecl(const_cast<const ValueDecl
*>(D
)));
1294 DSAStackTy::DSAVarData
DSAStackTy::getDSA(const_iterator
&Iter
,
1295 ValueDecl
*D
) const {
1296 D
= getCanonicalDecl(D
);
1297 auto *VD
= dyn_cast
<VarDecl
>(D
);
1298 const auto *FD
= dyn_cast
<FieldDecl
>(D
);
1300 if (Iter
== end()) {
1301 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1302 // in a region but not in construct]
1303 // File-scope or namespace-scope variables referenced in called routines
1304 // in the region are shared unless they appear in a threadprivate
1306 if (VD
&& !VD
->isFunctionOrMethodVarDecl() && !isa
<ParmVarDecl
>(VD
))
1307 DVar
.CKind
= OMPC_shared
;
1309 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1310 // in a region but not in construct]
1311 // Variables with static storage duration that are declared in called
1312 // routines in the region are shared.
1313 if (VD
&& VD
->hasGlobalStorage())
1314 DVar
.CKind
= OMPC_shared
;
1316 // Non-static data members are shared by default.
1318 DVar
.CKind
= OMPC_shared
;
1323 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1324 // in a Construct, C/C++, predetermined, p.1]
1325 // Variables with automatic storage duration that are declared in a scope
1326 // inside the construct are private.
1327 if (VD
&& isOpenMPLocal(VD
, Iter
) && VD
->isLocalVarDecl() &&
1328 (VD
->getStorageClass() == SC_Auto
|| VD
->getStorageClass() == SC_None
)) {
1329 DVar
.CKind
= OMPC_private
;
1333 DVar
.DKind
= Iter
->Directive
;
1334 // Explicitly specified attributes and local variables with predetermined
1336 if (Iter
->SharingMap
.count(D
)) {
1337 const DSAInfo
&Data
= Iter
->SharingMap
.lookup(D
);
1338 DVar
.RefExpr
= Data
.RefExpr
.getPointer();
1339 DVar
.PrivateCopy
= Data
.PrivateCopy
;
1340 DVar
.CKind
= Data
.Attributes
;
1341 DVar
.ImplicitDSALoc
= Iter
->DefaultAttrLoc
;
1342 DVar
.Modifier
= Data
.Modifier
;
1343 DVar
.AppliedToPointee
= Data
.AppliedToPointee
;
1347 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1348 // in a Construct, C/C++, implicitly determined, p.1]
1349 // In a parallel or task construct, the data-sharing attributes of these
1350 // variables are determined by the default clause, if present.
1351 switch (Iter
->DefaultAttr
) {
1353 DVar
.CKind
= OMPC_shared
;
1354 DVar
.ImplicitDSALoc
= Iter
->DefaultAttrLoc
;
1358 case DSA_firstprivate
:
1359 if (VD
&& VD
->getStorageDuration() == SD_Static
&&
1360 VD
->getDeclContext()->isFileContext()) {
1361 DVar
.CKind
= OMPC_unknown
;
1363 DVar
.CKind
= OMPC_firstprivate
;
1365 DVar
.ImplicitDSALoc
= Iter
->DefaultAttrLoc
;
1368 // each variable with static storage duration that is declared
1369 // in a namespace or global scope and referenced in the construct,
1370 // and that does not have a predetermined data-sharing attribute
1371 if (VD
&& VD
->getStorageDuration() == SD_Static
&&
1372 VD
->getDeclContext()->isFileContext()) {
1373 DVar
.CKind
= OMPC_unknown
;
1375 DVar
.CKind
= OMPC_private
;
1377 DVar
.ImplicitDSALoc
= Iter
->DefaultAttrLoc
;
1379 case DSA_unspecified
:
1380 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1381 // in a Construct, implicitly determined, p.2]
1382 // In a parallel construct, if no default clause is present, these
1383 // variables are shared.
1384 DVar
.ImplicitDSALoc
= Iter
->DefaultAttrLoc
;
1385 if ((isOpenMPParallelDirective(DVar
.DKind
) &&
1386 !isOpenMPTaskLoopDirective(DVar
.DKind
)) ||
1387 isOpenMPTeamsDirective(DVar
.DKind
)) {
1388 DVar
.CKind
= OMPC_shared
;
1392 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1393 // in a Construct, implicitly determined, p.4]
1394 // In a task construct, if no default clause is present, a variable that in
1395 // the enclosing context is determined to be shared by all implicit tasks
1396 // bound to the current team is shared.
1397 if (isOpenMPTaskingDirective(DVar
.DKind
)) {
1398 DSAVarData DVarTemp
;
1399 const_iterator I
= Iter
, E
= end();
1402 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1403 // Referenced in a Construct, implicitly determined, p.6]
1404 // In a task construct, if no default clause is present, a variable
1405 // whose data-sharing attribute is not determined by the rules above is
1407 DVarTemp
= getDSA(I
, D
);
1408 if (DVarTemp
.CKind
!= OMPC_shared
) {
1409 DVar
.RefExpr
= nullptr;
1410 DVar
.CKind
= OMPC_firstprivate
;
1413 } while (I
!= E
&& !isImplicitTaskingRegion(I
->Directive
));
1415 (DVarTemp
.CKind
== OMPC_unknown
) ? OMPC_firstprivate
: OMPC_shared
;
1419 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1420 // in a Construct, implicitly determined, p.3]
1421 // For constructs other than task, if no default clause is present, these
1422 // variables inherit their data-sharing attributes from the enclosing
1424 return getDSA(++Iter
, D
);
1427 const Expr
*DSAStackTy::addUniqueAligned(const ValueDecl
*D
,
1428 const Expr
*NewDE
) {
1429 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1430 D
= getCanonicalDecl(D
);
1431 SharingMapTy
&StackElem
= getTopOfStack();
1432 auto It
= StackElem
.AlignedMap
.find(D
);
1433 if (It
== StackElem
.AlignedMap
.end()) {
1434 assert(NewDE
&& "Unexpected nullptr expr to be added into aligned map");
1435 StackElem
.AlignedMap
[D
] = NewDE
;
1438 assert(It
->second
&& "Unexpected nullptr expr in the aligned map");
1442 const Expr
*DSAStackTy::addUniqueNontemporal(const ValueDecl
*D
,
1443 const Expr
*NewDE
) {
1444 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1445 D
= getCanonicalDecl(D
);
1446 SharingMapTy
&StackElem
= getTopOfStack();
1447 auto It
= StackElem
.NontemporalMap
.find(D
);
1448 if (It
== StackElem
.NontemporalMap
.end()) {
1449 assert(NewDE
&& "Unexpected nullptr expr to be added into aligned map");
1450 StackElem
.NontemporalMap
[D
] = NewDE
;
1453 assert(It
->second
&& "Unexpected nullptr expr in the aligned map");
1457 void DSAStackTy::addLoopControlVariable(const ValueDecl
*D
, VarDecl
*Capture
) {
1458 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1459 D
= getCanonicalDecl(D
);
1460 SharingMapTy
&StackElem
= getTopOfStack();
1461 StackElem
.LCVMap
.try_emplace(
1462 D
, LCDeclInfo(StackElem
.LCVMap
.size() + 1, Capture
));
1465 const DSAStackTy::LCDeclInfo
1466 DSAStackTy::isLoopControlVariable(const ValueDecl
*D
) const {
1467 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1468 D
= getCanonicalDecl(D
);
1469 const SharingMapTy
&StackElem
= getTopOfStack();
1470 auto It
= StackElem
.LCVMap
.find(D
);
1471 if (It
!= StackElem
.LCVMap
.end())
1473 return {0, nullptr};
1476 const DSAStackTy::LCDeclInfo
1477 DSAStackTy::isLoopControlVariable(const ValueDecl
*D
, unsigned Level
) const {
1478 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1479 D
= getCanonicalDecl(D
);
1480 for (unsigned I
= Level
+ 1; I
> 0; --I
) {
1481 const SharingMapTy
&StackElem
= getStackElemAtLevel(I
- 1);
1482 auto It
= StackElem
.LCVMap
.find(D
);
1483 if (It
!= StackElem
.LCVMap
.end())
1486 return {0, nullptr};
1489 const DSAStackTy::LCDeclInfo
1490 DSAStackTy::isParentLoopControlVariable(const ValueDecl
*D
) const {
1491 const SharingMapTy
*Parent
= getSecondOnStackOrNull();
1492 assert(Parent
&& "Data-sharing attributes stack is empty");
1493 D
= getCanonicalDecl(D
);
1494 auto It
= Parent
->LCVMap
.find(D
);
1495 if (It
!= Parent
->LCVMap
.end())
1497 return {0, nullptr};
1500 const ValueDecl
*DSAStackTy::getParentLoopControlVariable(unsigned I
) const {
1501 const SharingMapTy
*Parent
= getSecondOnStackOrNull();
1502 assert(Parent
&& "Data-sharing attributes stack is empty");
1503 if (Parent
->LCVMap
.size() < I
)
1505 for (const auto &Pair
: Parent
->LCVMap
)
1506 if (Pair
.second
.first
== I
)
1511 void DSAStackTy::addDSA(const ValueDecl
*D
, const Expr
*E
, OpenMPClauseKind A
,
1512 DeclRefExpr
*PrivateCopy
, unsigned Modifier
,
1513 bool AppliedToPointee
) {
1514 D
= getCanonicalDecl(D
);
1515 if (A
== OMPC_threadprivate
) {
1516 DSAInfo
&Data
= Threadprivates
[D
];
1517 Data
.Attributes
= A
;
1518 Data
.RefExpr
.setPointer(E
);
1519 Data
.PrivateCopy
= nullptr;
1520 Data
.Modifier
= Modifier
;
1522 DSAInfo
&Data
= getTopOfStack().SharingMap
[D
];
1523 assert(Data
.Attributes
== OMPC_unknown
|| (A
== Data
.Attributes
) ||
1524 (A
== OMPC_firstprivate
&& Data
.Attributes
== OMPC_lastprivate
) ||
1525 (A
== OMPC_lastprivate
&& Data
.Attributes
== OMPC_firstprivate
) ||
1526 (isLoopControlVariable(D
).first
&& A
== OMPC_private
));
1527 Data
.Modifier
= Modifier
;
1528 if (A
== OMPC_lastprivate
&& Data
.Attributes
== OMPC_firstprivate
) {
1529 Data
.RefExpr
.setInt(/*IntVal=*/true);
1532 const bool IsLastprivate
=
1533 A
== OMPC_lastprivate
|| Data
.Attributes
== OMPC_lastprivate
;
1534 Data
.Attributes
= A
;
1535 Data
.RefExpr
.setPointerAndInt(E
, IsLastprivate
);
1536 Data
.PrivateCopy
= PrivateCopy
;
1537 Data
.AppliedToPointee
= AppliedToPointee
;
1539 DSAInfo
&Data
= getTopOfStack().SharingMap
[PrivateCopy
->getDecl()];
1540 Data
.Modifier
= Modifier
;
1541 Data
.Attributes
= A
;
1542 Data
.RefExpr
.setPointerAndInt(PrivateCopy
, IsLastprivate
);
1543 Data
.PrivateCopy
= nullptr;
1544 Data
.AppliedToPointee
= AppliedToPointee
;
1549 /// Build a variable declaration for OpenMP loop iteration variable.
1550 static VarDecl
*buildVarDecl(Sema
&SemaRef
, SourceLocation Loc
, QualType Type
,
1551 StringRef Name
, const AttrVec
*Attrs
= nullptr,
1552 DeclRefExpr
*OrigRef
= nullptr) {
1553 DeclContext
*DC
= SemaRef
.CurContext
;
1554 IdentifierInfo
*II
= &SemaRef
.PP
.getIdentifierTable().get(Name
);
1555 TypeSourceInfo
*TInfo
= SemaRef
.Context
.getTrivialTypeSourceInfo(Type
, Loc
);
1557 VarDecl::Create(SemaRef
.Context
, DC
, Loc
, Loc
, II
, Type
, TInfo
, SC_None
);
1559 for (specific_attr_iterator
<AlignedAttr
> I(Attrs
->begin()), E(Attrs
->end());
1563 Decl
->setImplicit();
1566 OMPReferencedVarAttr::CreateImplicit(SemaRef
.Context
, OrigRef
));
1571 static DeclRefExpr
*buildDeclRefExpr(Sema
&S
, VarDecl
*D
, QualType Ty
,
1573 bool RefersToCapture
= false) {
1575 D
->markUsed(S
.Context
);
1576 return DeclRefExpr::Create(S
.getASTContext(), NestedNameSpecifierLoc(),
1577 SourceLocation(), D
, RefersToCapture
, Loc
, Ty
,
1581 void DSAStackTy::addTaskgroupReductionData(const ValueDecl
*D
, SourceRange SR
,
1582 BinaryOperatorKind BOK
) {
1583 D
= getCanonicalDecl(D
);
1584 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1586 getTopOfStack().SharingMap
[D
].Attributes
== OMPC_reduction
&&
1587 "Additional reduction info may be specified only for reduction items.");
1588 ReductionData
&ReductionData
= getTopOfStack().ReductionMap
[D
];
1589 assert(ReductionData
.ReductionRange
.isInvalid() &&
1590 (getTopOfStack().Directive
== OMPD_taskgroup
||
1591 ((isOpenMPParallelDirective(getTopOfStack().Directive
) ||
1592 isOpenMPWorksharingDirective(getTopOfStack().Directive
)) &&
1593 !isOpenMPSimdDirective(getTopOfStack().Directive
))) &&
1594 "Additional reduction info may be specified only once for reduction "
1596 ReductionData
.set(BOK
, SR
);
1597 Expr
*&TaskgroupReductionRef
= getTopOfStack().TaskgroupReductionRef
;
1598 if (!TaskgroupReductionRef
) {
1599 VarDecl
*VD
= buildVarDecl(SemaRef
, SR
.getBegin(),
1600 SemaRef
.Context
.VoidPtrTy
, ".task_red.");
1601 TaskgroupReductionRef
=
1602 buildDeclRefExpr(SemaRef
, VD
, SemaRef
.Context
.VoidPtrTy
, SR
.getBegin());
1606 void DSAStackTy::addTaskgroupReductionData(const ValueDecl
*D
, SourceRange SR
,
1607 const Expr
*ReductionRef
) {
1608 D
= getCanonicalDecl(D
);
1609 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1611 getTopOfStack().SharingMap
[D
].Attributes
== OMPC_reduction
&&
1612 "Additional reduction info may be specified only for reduction items.");
1613 ReductionData
&ReductionData
= getTopOfStack().ReductionMap
[D
];
1614 assert(ReductionData
.ReductionRange
.isInvalid() &&
1615 (getTopOfStack().Directive
== OMPD_taskgroup
||
1616 ((isOpenMPParallelDirective(getTopOfStack().Directive
) ||
1617 isOpenMPWorksharingDirective(getTopOfStack().Directive
)) &&
1618 !isOpenMPSimdDirective(getTopOfStack().Directive
))) &&
1619 "Additional reduction info may be specified only once for reduction "
1621 ReductionData
.set(ReductionRef
, SR
);
1622 Expr
*&TaskgroupReductionRef
= getTopOfStack().TaskgroupReductionRef
;
1623 if (!TaskgroupReductionRef
) {
1624 VarDecl
*VD
= buildVarDecl(SemaRef
, SR
.getBegin(),
1625 SemaRef
.Context
.VoidPtrTy
, ".task_red.");
1626 TaskgroupReductionRef
=
1627 buildDeclRefExpr(SemaRef
, VD
, SemaRef
.Context
.VoidPtrTy
, SR
.getBegin());
1631 const DSAStackTy::DSAVarData
DSAStackTy::getTopMostTaskgroupReductionData(
1632 const ValueDecl
*D
, SourceRange
&SR
, BinaryOperatorKind
&BOK
,
1633 Expr
*&TaskgroupDescriptor
) const {
1634 D
= getCanonicalDecl(D
);
1635 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1636 for (const_iterator I
= begin() + 1, E
= end(); I
!= E
; ++I
) {
1637 const DSAInfo
&Data
= I
->SharingMap
.lookup(D
);
1638 if (Data
.Attributes
!= OMPC_reduction
||
1639 Data
.Modifier
!= OMPC_REDUCTION_task
)
1641 const ReductionData
&ReductionData
= I
->ReductionMap
.lookup(D
);
1642 if (!ReductionData
.ReductionOp
||
1643 ReductionData
.ReductionOp
.is
<const Expr
*>())
1644 return DSAVarData();
1645 SR
= ReductionData
.ReductionRange
;
1646 BOK
= ReductionData
.ReductionOp
.get
<ReductionData::BOKPtrType
>();
1647 assert(I
->TaskgroupReductionRef
&& "taskgroup reduction reference "
1648 "expression for the descriptor is not "
1650 TaskgroupDescriptor
= I
->TaskgroupReductionRef
;
1651 return DSAVarData(I
->Directive
, OMPC_reduction
, Data
.RefExpr
.getPointer(),
1652 Data
.PrivateCopy
, I
->DefaultAttrLoc
, OMPC_REDUCTION_task
,
1653 /*AppliedToPointee=*/false);
1655 return DSAVarData();
1658 const DSAStackTy::DSAVarData
DSAStackTy::getTopMostTaskgroupReductionData(
1659 const ValueDecl
*D
, SourceRange
&SR
, const Expr
*&ReductionRef
,
1660 Expr
*&TaskgroupDescriptor
) const {
1661 D
= getCanonicalDecl(D
);
1662 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1663 for (const_iterator I
= begin() + 1, E
= end(); I
!= E
; ++I
) {
1664 const DSAInfo
&Data
= I
->SharingMap
.lookup(D
);
1665 if (Data
.Attributes
!= OMPC_reduction
||
1666 Data
.Modifier
!= OMPC_REDUCTION_task
)
1668 const ReductionData
&ReductionData
= I
->ReductionMap
.lookup(D
);
1669 if (!ReductionData
.ReductionOp
||
1670 !ReductionData
.ReductionOp
.is
<const Expr
*>())
1671 return DSAVarData();
1672 SR
= ReductionData
.ReductionRange
;
1673 ReductionRef
= ReductionData
.ReductionOp
.get
<const Expr
*>();
1674 assert(I
->TaskgroupReductionRef
&& "taskgroup reduction reference "
1675 "expression for the descriptor is not "
1677 TaskgroupDescriptor
= I
->TaskgroupReductionRef
;
1678 return DSAVarData(I
->Directive
, OMPC_reduction
, Data
.RefExpr
.getPointer(),
1679 Data
.PrivateCopy
, I
->DefaultAttrLoc
, OMPC_REDUCTION_task
,
1680 /*AppliedToPointee=*/false);
1682 return DSAVarData();
1685 bool DSAStackTy::isOpenMPLocal(VarDecl
*D
, const_iterator I
) const {
1686 D
= D
->getCanonicalDecl();
1687 for (const_iterator E
= end(); I
!= E
; ++I
) {
1688 if (isImplicitOrExplicitTaskingRegion(I
->Directive
) ||
1689 isOpenMPTargetExecutionDirective(I
->Directive
)) {
1691 Scope
*TopScope
= I
->CurScope
->getParent();
1692 Scope
*CurScope
= getCurScope();
1693 while (CurScope
&& CurScope
!= TopScope
&& !CurScope
->isDeclScope(D
))
1694 CurScope
= CurScope
->getParent();
1695 return CurScope
!= TopScope
;
1697 for (DeclContext
*DC
= D
->getDeclContext(); DC
; DC
= DC
->getParent())
1698 if (I
->Context
== DC
)
1706 static bool isConstNotMutableType(Sema
&SemaRef
, QualType Type
,
1707 bool AcceptIfMutable
= true,
1708 bool *IsClassType
= nullptr) {
1709 ASTContext
&Context
= SemaRef
.getASTContext();
1710 Type
= Type
.getNonReferenceType().getCanonicalType();
1711 bool IsConstant
= Type
.isConstant(Context
);
1712 Type
= Context
.getBaseElementType(Type
);
1713 const CXXRecordDecl
*RD
= AcceptIfMutable
&& SemaRef
.getLangOpts().CPlusPlus
1714 ? Type
->getAsCXXRecordDecl()
1716 if (const auto *CTSD
= dyn_cast_or_null
<ClassTemplateSpecializationDecl
>(RD
))
1717 if (const ClassTemplateDecl
*CTD
= CTSD
->getSpecializedTemplate())
1718 RD
= CTD
->getTemplatedDecl();
1721 return IsConstant
&& !(SemaRef
.getLangOpts().CPlusPlus
&& RD
&&
1722 RD
->hasDefinition() && RD
->hasMutableFields());
1725 static bool rejectConstNotMutableType(Sema
&SemaRef
, const ValueDecl
*D
,
1726 QualType Type
, OpenMPClauseKind CKind
,
1727 SourceLocation ELoc
,
1728 bool AcceptIfMutable
= true,
1729 bool ListItemNotVar
= false) {
1730 ASTContext
&Context
= SemaRef
.getASTContext();
1732 if (isConstNotMutableType(SemaRef
, Type
, AcceptIfMutable
, &IsClassType
)) {
1733 unsigned Diag
= ListItemNotVar
? diag::err_omp_const_list_item
1734 : IsClassType
? diag::err_omp_const_not_mutable_variable
1735 : diag::err_omp_const_variable
;
1736 SemaRef
.Diag(ELoc
, Diag
) << getOpenMPClauseName(CKind
);
1737 if (!ListItemNotVar
&& D
) {
1738 const VarDecl
*VD
= dyn_cast
<VarDecl
>(D
);
1739 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
1740 VarDecl::DeclarationOnly
;
1741 SemaRef
.Diag(D
->getLocation(),
1742 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
1750 const DSAStackTy::DSAVarData
DSAStackTy::getTopDSA(ValueDecl
*D
,
1752 D
= getCanonicalDecl(D
);
1755 auto *VD
= dyn_cast
<VarDecl
>(D
);
1756 auto TI
= Threadprivates
.find(D
);
1757 if (TI
!= Threadprivates
.end()) {
1758 DVar
.RefExpr
= TI
->getSecond().RefExpr
.getPointer();
1759 DVar
.CKind
= OMPC_threadprivate
;
1760 DVar
.Modifier
= TI
->getSecond().Modifier
;
1763 if (VD
&& VD
->hasAttr
<OMPThreadPrivateDeclAttr
>()) {
1764 DVar
.RefExpr
= buildDeclRefExpr(
1765 SemaRef
, VD
, D
->getType().getNonReferenceType(),
1766 VD
->getAttr
<OMPThreadPrivateDeclAttr
>()->getLocation());
1767 DVar
.CKind
= OMPC_threadprivate
;
1768 addDSA(D
, DVar
.RefExpr
, OMPC_threadprivate
);
1771 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1772 // in a Construct, C/C++, predetermined, p.1]
1773 // Variables appearing in threadprivate directives are threadprivate.
1774 if ((VD
&& VD
->getTLSKind() != VarDecl::TLS_None
&&
1775 !(VD
->hasAttr
<OMPThreadPrivateDeclAttr
>() &&
1776 SemaRef
.getLangOpts().OpenMPUseTLS
&&
1777 SemaRef
.getASTContext().getTargetInfo().isTLSSupported())) ||
1778 (VD
&& VD
->getStorageClass() == SC_Register
&&
1779 VD
->hasAttr
<AsmLabelAttr
>() && !VD
->isLocalVarDecl())) {
1780 DVar
.RefExpr
= buildDeclRefExpr(
1781 SemaRef
, VD
, D
->getType().getNonReferenceType(), D
->getLocation());
1782 DVar
.CKind
= OMPC_threadprivate
;
1783 addDSA(D
, DVar
.RefExpr
, OMPC_threadprivate
);
1786 if (SemaRef
.getLangOpts().OpenMPCUDAMode
&& VD
&&
1787 VD
->isLocalVarDeclOrParm() && !isStackEmpty() &&
1788 !isLoopControlVariable(D
).first
) {
1789 const_iterator IterTarget
=
1790 std::find_if(begin(), end(), [](const SharingMapTy
&Data
) {
1791 return isOpenMPTargetExecutionDirective(Data
.Directive
);
1793 if (IterTarget
!= end()) {
1794 const_iterator ParentIterTarget
= IterTarget
+ 1;
1795 for (const_iterator Iter
= begin(); Iter
!= ParentIterTarget
; ++Iter
) {
1796 if (isOpenMPLocal(VD
, Iter
)) {
1798 buildDeclRefExpr(SemaRef
, VD
, D
->getType().getNonReferenceType(),
1800 DVar
.CKind
= OMPC_threadprivate
;
1804 if (!isClauseParsingMode() || IterTarget
!= begin()) {
1805 auto DSAIter
= IterTarget
->SharingMap
.find(D
);
1806 if (DSAIter
!= IterTarget
->SharingMap
.end() &&
1807 isOpenMPPrivate(DSAIter
->getSecond().Attributes
)) {
1808 DVar
.RefExpr
= DSAIter
->getSecond().RefExpr
.getPointer();
1809 DVar
.CKind
= OMPC_threadprivate
;
1812 const_iterator End
= end();
1813 if (!SemaRef
.isOpenMPCapturedByRef(D
,
1814 std::distance(ParentIterTarget
, End
),
1815 /*OpenMPCaptureLevel=*/0)) {
1817 buildDeclRefExpr(SemaRef
, VD
, D
->getType().getNonReferenceType(),
1818 IterTarget
->ConstructLoc
);
1819 DVar
.CKind
= OMPC_threadprivate
;
1827 // Not in OpenMP execution region and top scope was already checked.
1830 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1831 // in a Construct, C/C++, predetermined, p.4]
1832 // Static data members are shared.
1833 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1834 // in a Construct, C/C++, predetermined, p.7]
1835 // Variables with static storage duration that are declared in a scope
1836 // inside the construct are shared.
1837 if (VD
&& VD
->isStaticDataMember()) {
1838 // Check for explicitly specified attributes.
1839 const_iterator I
= begin();
1840 const_iterator EndI
= end();
1841 if (FromParent
&& I
!= EndI
)
1844 auto It
= I
->SharingMap
.find(D
);
1845 if (It
!= I
->SharingMap
.end()) {
1846 const DSAInfo
&Data
= It
->getSecond();
1847 DVar
.RefExpr
= Data
.RefExpr
.getPointer();
1848 DVar
.PrivateCopy
= Data
.PrivateCopy
;
1849 DVar
.CKind
= Data
.Attributes
;
1850 DVar
.ImplicitDSALoc
= I
->DefaultAttrLoc
;
1851 DVar
.DKind
= I
->Directive
;
1852 DVar
.Modifier
= Data
.Modifier
;
1853 DVar
.AppliedToPointee
= Data
.AppliedToPointee
;
1858 DVar
.CKind
= OMPC_shared
;
1862 auto &&MatchesAlways
= [](OpenMPDirectiveKind
) { return true; };
1863 // The predetermined shared attribute for const-qualified types having no
1864 // mutable members was removed after OpenMP 3.1.
1865 if (SemaRef
.LangOpts
.OpenMP
<= 31) {
1866 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1867 // in a Construct, C/C++, predetermined, p.6]
1868 // Variables with const qualified type having no mutable member are
1870 if (isConstNotMutableType(SemaRef
, D
->getType())) {
1871 // Variables with const-qualified type having no mutable member may be
1872 // listed in a firstprivate clause, even if they are static data members.
1873 DSAVarData DVarTemp
= hasInnermostDSA(
1875 [](OpenMPClauseKind C
, bool) {
1876 return C
== OMPC_firstprivate
|| C
== OMPC_shared
;
1878 MatchesAlways
, FromParent
);
1879 if (DVarTemp
.CKind
!= OMPC_unknown
&& DVarTemp
.RefExpr
)
1882 DVar
.CKind
= OMPC_shared
;
1887 // Explicitly specified attributes and local variables with predetermined
1889 const_iterator I
= begin();
1890 const_iterator EndI
= end();
1891 if (FromParent
&& I
!= EndI
)
1895 auto It
= I
->SharingMap
.find(D
);
1896 if (It
!= I
->SharingMap
.end()) {
1897 const DSAInfo
&Data
= It
->getSecond();
1898 DVar
.RefExpr
= Data
.RefExpr
.getPointer();
1899 DVar
.PrivateCopy
= Data
.PrivateCopy
;
1900 DVar
.CKind
= Data
.Attributes
;
1901 DVar
.ImplicitDSALoc
= I
->DefaultAttrLoc
;
1902 DVar
.DKind
= I
->Directive
;
1903 DVar
.Modifier
= Data
.Modifier
;
1904 DVar
.AppliedToPointee
= Data
.AppliedToPointee
;
1910 const DSAStackTy::DSAVarData
DSAStackTy::getImplicitDSA(ValueDecl
*D
,
1911 bool FromParent
) const {
1912 if (isStackEmpty()) {
1914 return getDSA(I
, D
);
1916 D
= getCanonicalDecl(D
);
1917 const_iterator StartI
= begin();
1918 const_iterator EndI
= end();
1919 if (FromParent
&& StartI
!= EndI
)
1921 return getDSA(StartI
, D
);
1924 const DSAStackTy::DSAVarData
DSAStackTy::getImplicitDSA(ValueDecl
*D
,
1925 unsigned Level
) const {
1926 if (getStackSize() <= Level
)
1927 return DSAVarData();
1928 D
= getCanonicalDecl(D
);
1929 const_iterator StartI
= std::next(begin(), getStackSize() - 1 - Level
);
1930 return getDSA(StartI
, D
);
1933 const DSAStackTy::DSAVarData
1934 DSAStackTy::hasDSA(ValueDecl
*D
,
1935 const llvm::function_ref
<bool(OpenMPClauseKind
, bool,
1936 DefaultDataSharingAttributes
)>
1938 const llvm::function_ref
<bool(OpenMPDirectiveKind
)> DPred
,
1939 bool FromParent
) const {
1942 D
= getCanonicalDecl(D
);
1943 const_iterator I
= begin();
1944 const_iterator EndI
= end();
1945 if (FromParent
&& I
!= EndI
)
1947 for (; I
!= EndI
; ++I
) {
1948 if (!DPred(I
->Directive
) &&
1949 !isImplicitOrExplicitTaskingRegion(I
->Directive
))
1951 const_iterator NewI
= I
;
1952 DSAVarData DVar
= getDSA(NewI
, D
);
1953 if (I
== NewI
&& CPred(DVar
.CKind
, DVar
.AppliedToPointee
, I
->DefaultAttr
))
1959 const DSAStackTy::DSAVarData
DSAStackTy::hasInnermostDSA(
1960 ValueDecl
*D
, const llvm::function_ref
<bool(OpenMPClauseKind
, bool)> CPred
,
1961 const llvm::function_ref
<bool(OpenMPDirectiveKind
)> DPred
,
1962 bool FromParent
) const {
1965 D
= getCanonicalDecl(D
);
1966 const_iterator StartI
= begin();
1967 const_iterator EndI
= end();
1968 if (FromParent
&& StartI
!= EndI
)
1970 if (StartI
== EndI
|| !DPred(StartI
->Directive
))
1972 const_iterator NewI
= StartI
;
1973 DSAVarData DVar
= getDSA(NewI
, D
);
1974 return (NewI
== StartI
&& CPred(DVar
.CKind
, DVar
.AppliedToPointee
))
1979 bool DSAStackTy::hasExplicitDSA(
1981 const llvm::function_ref
<bool(OpenMPClauseKind
, bool)> CPred
,
1982 unsigned Level
, bool NotLastprivate
) const {
1983 if (getStackSize() <= Level
)
1985 D
= getCanonicalDecl(D
);
1986 const SharingMapTy
&StackElem
= getStackElemAtLevel(Level
);
1987 auto I
= StackElem
.SharingMap
.find(D
);
1988 if (I
!= StackElem
.SharingMap
.end() && I
->getSecond().RefExpr
.getPointer() &&
1989 CPred(I
->getSecond().Attributes
, I
->getSecond().AppliedToPointee
) &&
1990 (!NotLastprivate
|| !I
->getSecond().RefExpr
.getInt()))
1992 // Check predetermined rules for the loop control variables.
1993 auto LI
= StackElem
.LCVMap
.find(D
);
1994 if (LI
!= StackElem
.LCVMap
.end())
1995 return CPred(OMPC_private
, /*AppliedToPointee=*/false);
1999 bool DSAStackTy::hasExplicitDirective(
2000 const llvm::function_ref
<bool(OpenMPDirectiveKind
)> DPred
,
2001 unsigned Level
) const {
2002 if (getStackSize() <= Level
)
2004 const SharingMapTy
&StackElem
= getStackElemAtLevel(Level
);
2005 return DPred(StackElem
.Directive
);
2008 bool DSAStackTy::hasDirective(
2009 const llvm::function_ref
<bool(OpenMPDirectiveKind
,
2010 const DeclarationNameInfo
&, SourceLocation
)>
2012 bool FromParent
) const {
2013 // We look only in the enclosing region.
2014 size_t Skip
= FromParent
? 2 : 1;
2015 for (const_iterator I
= begin() + std::min(Skip
, getStackSize()), E
= end();
2017 if (DPred(I
->Directive
, I
->DirectiveName
, I
->ConstructLoc
))
2023 void Sema::InitDataSharingAttributesStack() {
2024 VarDataSharingAttributesStack
= new DSAStackTy(*this);
2027 #define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2029 void Sema::pushOpenMPFunctionRegion() { DSAStack
->pushFunction(); }
2031 void Sema::popOpenMPFunctionRegion(const FunctionScopeInfo
*OldFSI
) {
2032 DSAStack
->popFunction(OldFSI
);
2035 static bool isOpenMPDeviceDelayedContext(Sema
&S
) {
2036 assert(S
.LangOpts
.OpenMP
&& S
.LangOpts
.OpenMPIsTargetDevice
&&
2037 "Expected OpenMP device compilation.");
2038 return !S
.isInOpenMPTargetExecutionDirective();
2042 /// Status of the function emission on the host/device.
2043 enum class FunctionEmissionStatus
{
2048 } // anonymous namespace
2050 Sema::SemaDiagnosticBuilder
2051 Sema::diagIfOpenMPDeviceCode(SourceLocation Loc
, unsigned DiagID
,
2052 const FunctionDecl
*FD
) {
2053 assert(LangOpts
.OpenMP
&& LangOpts
.OpenMPIsTargetDevice
&&
2054 "Expected OpenMP device compilation.");
2056 SemaDiagnosticBuilder::Kind Kind
= SemaDiagnosticBuilder::K_Nop
;
2058 FunctionEmissionStatus FES
= getEmissionStatus(FD
);
2060 case FunctionEmissionStatus::Emitted
:
2061 Kind
= SemaDiagnosticBuilder::K_Immediate
;
2063 case FunctionEmissionStatus::Unknown
:
2064 // TODO: We should always delay diagnostics here in case a target
2065 // region is in a function we do not emit. However, as the
2066 // current diagnostics are associated with the function containing
2067 // the target region and we do not emit that one, we would miss out
2068 // on diagnostics for the target region itself. We need to anchor
2069 // the diagnostics with the new generated function *or* ensure we
2070 // emit diagnostics associated with the surrounding function.
2071 Kind
= isOpenMPDeviceDelayedContext(*this)
2072 ? SemaDiagnosticBuilder::K_Deferred
2073 : SemaDiagnosticBuilder::K_Immediate
;
2075 case FunctionEmissionStatus::TemplateDiscarded
:
2076 case FunctionEmissionStatus::OMPDiscarded
:
2077 Kind
= SemaDiagnosticBuilder::K_Nop
;
2079 case FunctionEmissionStatus::CUDADiscarded
:
2080 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2085 return SemaDiagnosticBuilder(Kind
, Loc
, DiagID
, FD
, *this);
2088 Sema::SemaDiagnosticBuilder
Sema::diagIfOpenMPHostCode(SourceLocation Loc
,
2090 const FunctionDecl
*FD
) {
2091 assert(LangOpts
.OpenMP
&& !LangOpts
.OpenMPIsTargetDevice
&&
2092 "Expected OpenMP host compilation.");
2094 SemaDiagnosticBuilder::Kind Kind
= SemaDiagnosticBuilder::K_Nop
;
2096 FunctionEmissionStatus FES
= getEmissionStatus(FD
);
2098 case FunctionEmissionStatus::Emitted
:
2099 Kind
= SemaDiagnosticBuilder::K_Immediate
;
2101 case FunctionEmissionStatus::Unknown
:
2102 Kind
= SemaDiagnosticBuilder::K_Deferred
;
2104 case FunctionEmissionStatus::TemplateDiscarded
:
2105 case FunctionEmissionStatus::OMPDiscarded
:
2106 case FunctionEmissionStatus::CUDADiscarded
:
2107 Kind
= SemaDiagnosticBuilder::K_Nop
;
2112 return SemaDiagnosticBuilder(Kind
, Loc
, DiagID
, FD
, *this);
2115 static OpenMPDefaultmapClauseKind
2116 getVariableCategoryFromDecl(const LangOptions
&LO
, const ValueDecl
*VD
) {
2117 if (LO
.OpenMP
<= 45) {
2118 if (VD
->getType().getNonReferenceType()->isScalarType())
2119 return OMPC_DEFAULTMAP_scalar
;
2120 return OMPC_DEFAULTMAP_aggregate
;
2122 if (VD
->getType().getNonReferenceType()->isAnyPointerType())
2123 return OMPC_DEFAULTMAP_pointer
;
2124 if (VD
->getType().getNonReferenceType()->isScalarType())
2125 return OMPC_DEFAULTMAP_scalar
;
2126 return OMPC_DEFAULTMAP_aggregate
;
2129 bool Sema::isOpenMPCapturedByRef(const ValueDecl
*D
, unsigned Level
,
2130 unsigned OpenMPCaptureLevel
) const {
2131 assert(LangOpts
.OpenMP
&& "OpenMP is not allowed");
2133 ASTContext
&Ctx
= getASTContext();
2134 bool IsByRef
= true;
2136 // Find the directive that is associated with the provided scope.
2137 D
= cast
<ValueDecl
>(D
->getCanonicalDecl());
2138 QualType Ty
= D
->getType();
2140 bool IsVariableUsedInMapClause
= false;
2141 if (DSAStack
->hasExplicitDirective(isOpenMPTargetExecutionDirective
, Level
)) {
2142 // This table summarizes how a given variable should be passed to the device
2143 // given its type and the clauses where it appears. This table is based on
2144 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2145 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2147 // =========================================================================
2148 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2149 // | |(tofrom:scalar)| | pvt | |has_dv_adr| |
2150 // =========================================================================
2151 // | scl | | | | - | | bycopy|
2152 // | scl | | - | x | - | - | bycopy|
2153 // | scl | | x | - | - | - | null |
2154 // | scl | x | | | - | | byref |
2155 // | scl | x | - | x | - | - | bycopy|
2156 // | scl | x | x | - | - | - | null |
2157 // | scl | | - | - | - | x | byref |
2158 // | scl | x | - | - | - | x | byref |
2160 // | agg | n.a. | | | - | | byref |
2161 // | agg | n.a. | - | x | - | - | byref |
2162 // | agg | n.a. | x | - | - | - | null |
2163 // | agg | n.a. | - | - | - | x | byref |
2164 // | agg | n.a. | - | - | - | x[] | byref |
2166 // | ptr | n.a. | | | - | | bycopy|
2167 // | ptr | n.a. | - | x | - | - | bycopy|
2168 // | ptr | n.a. | x | - | - | - | null |
2169 // | ptr | n.a. | - | - | - | x | byref |
2170 // | ptr | n.a. | - | - | - | x[] | bycopy|
2171 // | ptr | n.a. | - | - | x | | bycopy|
2172 // | ptr | n.a. | - | - | x | x | bycopy|
2173 // | ptr | n.a. | - | - | x | x[] | bycopy|
2174 // =========================================================================
2180 // - - invalid in this combination
2181 // [] - mapped with an array section
2182 // byref - should be mapped by reference
2183 // byval - should be mapped by value
2184 // null - initialize a local variable to null on the device
2187 // - All scalar declarations that show up in a map clause have to be passed
2188 // by reference, because they may have been mapped in the enclosing data
2190 // - If the scalar value does not fit the size of uintptr, it has to be
2191 // passed by reference, regardless the result in the table above.
2192 // - For pointers mapped by value that have either an implicit map or an
2193 // array section, the runtime library may pass the NULL value to the
2194 // device instead of the value passed to it by the compiler.
2196 if (Ty
->isReferenceType())
2197 Ty
= Ty
->castAs
<ReferenceType
>()->getPointeeType();
2199 // Locate map clauses and see if the variable being captured is referred to
2200 // in any of those clauses. Here we only care about variables, not fields,
2201 // because fields are part of aggregates.
2202 bool IsVariableAssociatedWithSection
= false;
2204 DSAStack
->checkMappableExprComponentListsForDeclAtLevel(
2206 [&IsVariableUsedInMapClause
, &IsVariableAssociatedWithSection
,
2207 D
](OMPClauseMappableExprCommon::MappableExprComponentListRef
2209 OpenMPClauseKind WhereFoundClauseKind
) {
2210 // Both map and has_device_addr clauses information influences how a
2211 // variable is captured. E.g. is_device_ptr does not require changing
2212 // the default behavior.
2213 if (WhereFoundClauseKind
!= OMPC_map
&&
2214 WhereFoundClauseKind
!= OMPC_has_device_addr
)
2217 auto EI
= MapExprComponents
.rbegin();
2218 auto EE
= MapExprComponents
.rend();
2220 assert(EI
!= EE
&& "Invalid map expression!");
2222 if (isa
<DeclRefExpr
>(EI
->getAssociatedExpression()))
2223 IsVariableUsedInMapClause
|= EI
->getAssociatedDeclaration() == D
;
2228 auto Last
= std::prev(EE
);
2230 dyn_cast
<UnaryOperator
>(Last
->getAssociatedExpression());
2231 if ((UO
&& UO
->getOpcode() == UO_Deref
) ||
2232 isa
<ArraySubscriptExpr
>(Last
->getAssociatedExpression()) ||
2233 isa
<OMPArraySectionExpr
>(Last
->getAssociatedExpression()) ||
2234 isa
<MemberExpr
>(EI
->getAssociatedExpression()) ||
2235 isa
<OMPArrayShapingExpr
>(Last
->getAssociatedExpression())) {
2236 IsVariableAssociatedWithSection
= true;
2237 // There is nothing more we need to know about this variable.
2241 // Keep looking for more map info.
2245 if (IsVariableUsedInMapClause
) {
2246 // If variable is identified in a map clause it is always captured by
2247 // reference except if it is a pointer that is dereferenced somehow.
2248 IsByRef
= !(Ty
->isPointerType() && IsVariableAssociatedWithSection
);
2250 // By default, all the data that has a scalar type is mapped by copy
2251 // (except for reduction variables).
2252 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2253 IsByRef
= (DSAStack
->isForceCaptureByReferenceInTargetExecutable() &&
2254 !Ty
->isAnyPointerType()) ||
2255 !Ty
->isScalarType() ||
2256 DSAStack
->isDefaultmapCapturedByRef(
2257 Level
, getVariableCategoryFromDecl(LangOpts
, D
)) ||
2258 DSAStack
->hasExplicitDSA(
2260 [](OpenMPClauseKind K
, bool AppliedToPointee
) {
2261 return K
== OMPC_reduction
&& !AppliedToPointee
;
2267 if (IsByRef
&& Ty
.getNonReferenceType()->isScalarType()) {
2269 ((IsVariableUsedInMapClause
&&
2270 DSAStack
->getCaptureRegion(Level
, OpenMPCaptureLevel
) ==
2272 !(DSAStack
->hasExplicitDSA(
2274 [](OpenMPClauseKind K
, bool AppliedToPointee
) -> bool {
2275 return K
== OMPC_firstprivate
||
2276 (K
== OMPC_reduction
&& AppliedToPointee
);
2278 Level
, /*NotLastprivate=*/true) ||
2279 DSAStack
->isUsesAllocatorsDecl(Level
, D
))) &&
2280 // If the variable is artificial and must be captured by value - try to
2281 // capture by value.
2282 !(isa
<OMPCapturedExprDecl
>(D
) && !D
->hasAttr
<OMPCaptureNoInitAttr
>() &&
2283 !cast
<OMPCapturedExprDecl
>(D
)->getInit()->isGLValue()) &&
2284 // If the variable is implicitly firstprivate and scalar - capture by
2286 !((DSAStack
->getDefaultDSA() == DSA_firstprivate
||
2287 DSAStack
->getDefaultDSA() == DSA_private
) &&
2288 !DSAStack
->hasExplicitDSA(
2289 D
, [](OpenMPClauseKind K
, bool) { return K
!= OMPC_unknown
; },
2291 !DSAStack
->isLoopControlVariable(D
, Level
).first
);
2294 // When passing data by copy, we need to make sure it fits the uintptr size
2295 // and alignment, because the runtime library only deals with uintptr types.
2296 // If it does not fit the uintptr size, we need to pass the data by reference
2298 if (!IsByRef
&& (Ctx
.getTypeSizeInChars(Ty
) >
2299 Ctx
.getTypeSizeInChars(Ctx
.getUIntPtrType()) ||
2300 Ctx
.getAlignOfGlobalVarInChars(Ty
) >
2301 Ctx
.getTypeAlignInChars(Ctx
.getUIntPtrType()))) {
2308 unsigned Sema::getOpenMPNestingLevel() const {
2309 assert(getLangOpts().OpenMP
);
2310 return DSAStack
->getNestingLevel();
2313 bool Sema::isInOpenMPTaskUntiedContext() const {
2314 return isOpenMPTaskingDirective(DSAStack
->getCurrentDirective()) &&
2315 DSAStack
->isUntiedRegion();
2318 bool Sema::isInOpenMPTargetExecutionDirective() const {
2319 return (isOpenMPTargetExecutionDirective(DSAStack
->getCurrentDirective()) &&
2320 !DSAStack
->isClauseParsingMode()) ||
2321 DSAStack
->hasDirective(
2322 [](OpenMPDirectiveKind K
, const DeclarationNameInfo
&,
2323 SourceLocation
) -> bool {
2324 return isOpenMPTargetExecutionDirective(K
);
2329 bool Sema::isOpenMPRebuildMemberExpr(ValueDecl
*D
) {
2330 // Only rebuild for Field.
2331 if (!dyn_cast
<FieldDecl
>(D
))
2333 DSAStackTy::DSAVarData DVarPrivate
= DSAStack
->hasDSA(
2335 [](OpenMPClauseKind C
, bool AppliedToPointee
,
2336 DefaultDataSharingAttributes DefaultAttr
) {
2337 return isOpenMPPrivate(C
) && !AppliedToPointee
&&
2338 (DefaultAttr
== DSA_firstprivate
|| DefaultAttr
== DSA_private
);
2340 [](OpenMPDirectiveKind
) { return true; },
2341 DSAStack
->isClauseParsingMode());
2342 if (DVarPrivate
.CKind
!= OMPC_unknown
)
2347 static OMPCapturedExprDecl
*buildCaptureDecl(Sema
&S
, IdentifierInfo
*Id
,
2348 Expr
*CaptureExpr
, bool WithInit
,
2349 DeclContext
*CurContext
,
2352 VarDecl
*Sema::isOpenMPCapturedDecl(ValueDecl
*D
, bool CheckScopeInfo
,
2354 assert(LangOpts
.OpenMP
&& "OpenMP is not allowed");
2355 D
= getCanonicalDecl(D
);
2357 auto *VD
= dyn_cast
<VarDecl
>(D
);
2358 // Do not capture constexpr variables.
2359 if (VD
&& VD
->isConstexpr())
2362 // If we want to determine whether the variable should be captured from the
2363 // perspective of the current capturing scope, and we've already left all the
2364 // capturing scopes of the top directive on the stack, check from the
2365 // perspective of its parent directive (if any) instead.
2366 DSAStackTy::ParentDirectiveScope
InParentDirectiveRAII(
2367 *DSAStack
, CheckScopeInfo
&& DSAStack
->isBodyComplete());
2369 // If we are attempting to capture a global variable in a directive with
2370 // 'target' we return true so that this global is also mapped to the device.
2372 if (VD
&& !VD
->hasLocalStorage() &&
2373 (getCurCapturedRegion() || getCurBlock() || getCurLambda())) {
2374 if (isInOpenMPTargetExecutionDirective()) {
2375 DSAStackTy::DSAVarData DVarTop
=
2376 DSAStack
->getTopDSA(D
, DSAStack
->isClauseParsingMode());
2377 if (DVarTop
.CKind
!= OMPC_unknown
&& DVarTop
.RefExpr
)
2379 // If the declaration is enclosed in a 'declare target' directive,
2380 // then it should not be captured.
2382 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD
))
2384 CapturedRegionScopeInfo
*CSI
= nullptr;
2385 for (FunctionScopeInfo
*FSI
: llvm::drop_begin(
2386 llvm::reverse(FunctionScopes
),
2387 CheckScopeInfo
? (FunctionScopes
.size() - (StopAt
+ 1)) : 0)) {
2388 if (!isa
<CapturingScopeInfo
>(FSI
))
2390 if (auto *RSI
= dyn_cast
<CapturedRegionScopeInfo
>(FSI
))
2391 if (RSI
->CapRegionKind
== CR_OpenMP
) {
2396 assert(CSI
&& "Failed to find CapturedRegionScopeInfo");
2397 SmallVector
<OpenMPDirectiveKind
, 4> Regions
;
2398 getOpenMPCaptureRegions(Regions
,
2399 DSAStack
->getDirective(CSI
->OpenMPLevel
));
2400 if (Regions
[CSI
->OpenMPCaptureLevel
] != OMPD_task
)
2403 if (isInOpenMPDeclareTargetContext()) {
2404 // Try to mark variable as declare target if it is used in capturing
2406 if (LangOpts
.OpenMP
<= 45 &&
2407 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD
))
2408 checkDeclIsAllowedInOpenMPTarget(nullptr, VD
);
2413 if (CheckScopeInfo
) {
2414 bool OpenMPFound
= false;
2415 for (unsigned I
= StopAt
+ 1; I
> 0; --I
) {
2416 FunctionScopeInfo
*FSI
= FunctionScopes
[I
- 1];
2417 if (!isa
<CapturingScopeInfo
>(FSI
))
2419 if (auto *RSI
= dyn_cast
<CapturedRegionScopeInfo
>(FSI
))
2420 if (RSI
->CapRegionKind
== CR_OpenMP
) {
2429 if (DSAStack
->getCurrentDirective() != OMPD_unknown
&&
2430 (!DSAStack
->isClauseParsingMode() ||
2431 DSAStack
->getParentDirective() != OMPD_unknown
)) {
2432 auto &&Info
= DSAStack
->isLoopControlVariable(D
);
2434 (VD
&& VD
->hasLocalStorage() &&
2435 isImplicitOrExplicitTaskingRegion(DSAStack
->getCurrentDirective())) ||
2436 (VD
&& DSAStack
->isForceVarCapturing()))
2437 return VD
? VD
: Info
.second
;
2438 DSAStackTy::DSAVarData DVarTop
=
2439 DSAStack
->getTopDSA(D
, DSAStack
->isClauseParsingMode());
2440 if (DVarTop
.CKind
!= OMPC_unknown
&& isOpenMPPrivate(DVarTop
.CKind
) &&
2441 (!VD
|| VD
->hasLocalStorage() || !DVarTop
.AppliedToPointee
))
2442 return VD
? VD
: cast
<VarDecl
>(DVarTop
.PrivateCopy
->getDecl());
2443 // Threadprivate variables must not be captured.
2444 if (isOpenMPThreadPrivate(DVarTop
.CKind
))
2446 // The variable is not private or it is the variable in the directive with
2447 // default(none) clause and not used in any clause.
2448 DSAStackTy::DSAVarData DVarPrivate
= DSAStack
->hasDSA(
2450 [](OpenMPClauseKind C
, bool AppliedToPointee
, bool) {
2451 return isOpenMPPrivate(C
) && !AppliedToPointee
;
2453 [](OpenMPDirectiveKind
) { return true; },
2454 DSAStack
->isClauseParsingMode());
2455 // Global shared must not be captured.
2456 if (VD
&& !VD
->hasLocalStorage() && DVarPrivate
.CKind
== OMPC_unknown
&&
2457 ((DSAStack
->getDefaultDSA() != DSA_none
&&
2458 DSAStack
->getDefaultDSA() != DSA_private
&&
2459 DSAStack
->getDefaultDSA() != DSA_firstprivate
) ||
2460 DVarTop
.CKind
== OMPC_shared
))
2462 auto *FD
= dyn_cast
<FieldDecl
>(D
);
2463 if (DVarPrivate
.CKind
!= OMPC_unknown
&& !VD
&& FD
&&
2464 !DVarPrivate
.PrivateCopy
) {
2465 DSAStackTy::DSAVarData DVarPrivate
= DSAStack
->hasDSA(
2467 [](OpenMPClauseKind C
, bool AppliedToPointee
,
2468 DefaultDataSharingAttributes DefaultAttr
) {
2469 return isOpenMPPrivate(C
) && !AppliedToPointee
&&
2470 (DefaultAttr
== DSA_firstprivate
||
2471 DefaultAttr
== DSA_private
);
2473 [](OpenMPDirectiveKind
) { return true; },
2474 DSAStack
->isClauseParsingMode());
2475 if (DVarPrivate
.CKind
== OMPC_unknown
)
2478 VarDecl
*VD
= DSAStack
->getImplicitFDCapExprDecl(FD
);
2481 if (getCurrentThisType().isNull())
2483 Expr
*ThisExpr
= BuildCXXThisExpr(SourceLocation(), getCurrentThisType(),
2484 /*IsImplicit=*/true);
2485 const CXXScopeSpec CS
= CXXScopeSpec();
2486 Expr
*ME
= BuildMemberExpr(ThisExpr
, /*IsArrow=*/true, SourceLocation(),
2487 NestedNameSpecifierLoc(), SourceLocation(), FD
,
2488 DeclAccessPair::make(FD
, FD
->getAccess()),
2489 /*HadMultipleCandidates=*/false,
2490 DeclarationNameInfo(), FD
->getType(),
2491 VK_LValue
, OK_Ordinary
);
2492 OMPCapturedExprDecl
*CD
= buildCaptureDecl(
2493 *this, FD
->getIdentifier(), ME
, DVarPrivate
.CKind
!= OMPC_private
,
2494 CurContext
->getParent(), /*AsExpression=*/false);
2495 DeclRefExpr
*VDPrivateRefExpr
= buildDeclRefExpr(
2496 *this, CD
, CD
->getType().getNonReferenceType(), SourceLocation());
2497 VD
= cast
<VarDecl
>(VDPrivateRefExpr
->getDecl());
2498 DSAStack
->addImplicitDefaultFirstprivateFD(FD
, VD
);
2501 if (DVarPrivate
.CKind
!= OMPC_unknown
||
2502 (VD
&& (DSAStack
->getDefaultDSA() == DSA_none
||
2503 DSAStack
->getDefaultDSA() == DSA_private
||
2504 DSAStack
->getDefaultDSA() == DSA_firstprivate
)))
2505 return VD
? VD
: cast
<VarDecl
>(DVarPrivate
.PrivateCopy
->getDecl());
2510 void Sema::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex
,
2511 unsigned Level
) const {
2512 FunctionScopesIndex
-= getOpenMPCaptureLevels(DSAStack
->getDirective(Level
));
2515 void Sema::startOpenMPLoop() {
2516 assert(LangOpts
.OpenMP
&& "OpenMP must be enabled.");
2517 if (isOpenMPLoopDirective(DSAStack
->getCurrentDirective()))
2518 DSAStack
->loopInit();
2521 void Sema::startOpenMPCXXRangeFor() {
2522 assert(LangOpts
.OpenMP
&& "OpenMP must be enabled.");
2523 if (isOpenMPLoopDirective(DSAStack
->getCurrentDirective())) {
2524 DSAStack
->resetPossibleLoopCounter();
2525 DSAStack
->loopStart();
2529 OpenMPClauseKind
Sema::isOpenMPPrivateDecl(ValueDecl
*D
, unsigned Level
,
2530 unsigned CapLevel
) const {
2531 assert(LangOpts
.OpenMP
&& "OpenMP is not allowed");
2532 if (DSAStack
->getCurrentDirective() != OMPD_unknown
&&
2533 (!DSAStack
->isClauseParsingMode() ||
2534 DSAStack
->getParentDirective() != OMPD_unknown
)) {
2535 DSAStackTy::DSAVarData DVarPrivate
= DSAStack
->hasDSA(
2537 [](OpenMPClauseKind C
, bool AppliedToPointee
,
2538 DefaultDataSharingAttributes DefaultAttr
) {
2539 return isOpenMPPrivate(C
) && !AppliedToPointee
&&
2540 DefaultAttr
== DSA_private
;
2542 [](OpenMPDirectiveKind
) { return true; },
2543 DSAStack
->isClauseParsingMode());
2544 if (DVarPrivate
.CKind
== OMPC_private
&& isa
<OMPCapturedExprDecl
>(D
) &&
2545 DSAStack
->isImplicitDefaultFirstprivateFD(cast
<VarDecl
>(D
)) &&
2546 !DSAStack
->isLoopControlVariable(D
).first
)
2547 return OMPC_private
;
2549 if (DSAStack
->hasExplicitDirective(isOpenMPTaskingDirective
, Level
)) {
2550 bool IsTriviallyCopyable
=
2551 D
->getType().getNonReferenceType().isTriviallyCopyableType(Context
) &&
2553 .getNonReferenceType()
2555 ->getAsCXXRecordDecl();
2556 OpenMPDirectiveKind DKind
= DSAStack
->getDirective(Level
);
2557 SmallVector
<OpenMPDirectiveKind
, 4> CaptureRegions
;
2558 getOpenMPCaptureRegions(CaptureRegions
, DKind
);
2559 if (isOpenMPTaskingDirective(CaptureRegions
[CapLevel
]) &&
2560 (IsTriviallyCopyable
||
2561 !isOpenMPTaskLoopDirective(CaptureRegions
[CapLevel
]))) {
2562 if (DSAStack
->hasExplicitDSA(
2564 [](OpenMPClauseKind K
, bool) { return K
== OMPC_firstprivate
; },
2565 Level
, /*NotLastprivate=*/true))
2566 return OMPC_firstprivate
;
2567 DSAStackTy::DSAVarData DVar
= DSAStack
->getImplicitDSA(D
, Level
);
2568 if (DVar
.CKind
!= OMPC_shared
&&
2569 !DSAStack
->isLoopControlVariable(D
, Level
).first
&& !DVar
.RefExpr
) {
2570 DSAStack
->addImplicitTaskFirstprivate(Level
, D
);
2571 return OMPC_firstprivate
;
2575 if (isOpenMPLoopDirective(DSAStack
->getCurrentDirective()) &&
2576 !isOpenMPLoopTransformationDirective(DSAStack
->getCurrentDirective())) {
2577 if (DSAStack
->getAssociatedLoops() > 0 && !DSAStack
->isLoopStarted()) {
2578 DSAStack
->resetPossibleLoopCounter(D
);
2579 DSAStack
->loopStart();
2580 return OMPC_private
;
2582 if ((DSAStack
->getPossiblyLoopCunter() == D
->getCanonicalDecl() ||
2583 DSAStack
->isLoopControlVariable(D
).first
) &&
2584 !DSAStack
->hasExplicitDSA(
2585 D
, [](OpenMPClauseKind K
, bool) { return K
!= OMPC_private
; },
2587 !isOpenMPSimdDirective(DSAStack
->getCurrentDirective()))
2588 return OMPC_private
;
2590 if (const auto *VD
= dyn_cast
<VarDecl
>(D
)) {
2591 if (DSAStack
->isThreadPrivate(const_cast<VarDecl
*>(VD
)) &&
2592 DSAStack
->isForceVarCapturing() &&
2593 !DSAStack
->hasExplicitDSA(
2594 D
, [](OpenMPClauseKind K
, bool) { return K
== OMPC_copyin
; },
2596 return OMPC_private
;
2598 // User-defined allocators are private since they must be defined in the
2599 // context of target region.
2600 if (DSAStack
->hasExplicitDirective(isOpenMPTargetExecutionDirective
, Level
) &&
2601 DSAStack
->isUsesAllocatorsDecl(Level
, D
).value_or(
2602 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait
) ==
2603 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator
)
2604 return OMPC_private
;
2605 return (DSAStack
->hasExplicitDSA(
2606 D
, [](OpenMPClauseKind K
, bool) { return K
== OMPC_private
; },
2608 (DSAStack
->isClauseParsingMode() &&
2609 DSAStack
->getClauseParsingMode() == OMPC_private
) ||
2610 // Consider taskgroup reduction descriptor variable a private
2611 // to avoid possible capture in the region.
2612 (DSAStack
->hasExplicitDirective(
2613 [](OpenMPDirectiveKind K
) {
2614 return K
== OMPD_taskgroup
||
2615 ((isOpenMPParallelDirective(K
) ||
2616 isOpenMPWorksharingDirective(K
)) &&
2617 !isOpenMPSimdDirective(K
));
2620 DSAStack
->isTaskgroupReductionRef(D
, Level
)))
2625 void Sema::setOpenMPCaptureKind(FieldDecl
*FD
, const ValueDecl
*D
,
2627 assert(LangOpts
.OpenMP
&& "OpenMP is not allowed");
2628 D
= getCanonicalDecl(D
);
2629 OpenMPClauseKind OMPC
= OMPC_unknown
;
2630 for (unsigned I
= DSAStack
->getNestingLevel() + 1; I
> Level
; --I
) {
2631 const unsigned NewLevel
= I
- 1;
2632 if (DSAStack
->hasExplicitDSA(
2634 [&OMPC
](const OpenMPClauseKind K
, bool AppliedToPointee
) {
2635 if (isOpenMPPrivate(K
) && !AppliedToPointee
) {
2643 if (DSAStack
->checkMappableExprComponentListsForDeclAtLevel(
2645 [](OMPClauseMappableExprCommon::MappableExprComponentListRef
,
2646 OpenMPClauseKind
) { return true; })) {
2650 if (DSAStack
->hasExplicitDirective(isOpenMPTargetExecutionDirective
,
2653 if (DSAStack
->mustBeFirstprivateAtLevel(
2654 NewLevel
, getVariableCategoryFromDecl(LangOpts
, D
)))
2655 OMPC
= OMPC_firstprivate
;
2659 if (OMPC
!= OMPC_unknown
)
2660 FD
->addAttr(OMPCaptureKindAttr::CreateImplicit(Context
, unsigned(OMPC
)));
2663 bool Sema::isOpenMPTargetCapturedDecl(const ValueDecl
*D
, unsigned Level
,
2664 unsigned CaptureLevel
) const {
2665 assert(LangOpts
.OpenMP
&& "OpenMP is not allowed");
2666 // Return true if the current level is no longer enclosed in a target region.
2668 SmallVector
<OpenMPDirectiveKind
, 4> Regions
;
2669 getOpenMPCaptureRegions(Regions
, DSAStack
->getDirective(Level
));
2670 const auto *VD
= dyn_cast
<VarDecl
>(D
);
2671 return VD
&& !VD
->hasLocalStorage() &&
2672 DSAStack
->hasExplicitDirective(isOpenMPTargetExecutionDirective
,
2674 Regions
[CaptureLevel
] != OMPD_task
;
2677 bool Sema::isOpenMPGlobalCapturedDecl(ValueDecl
*D
, unsigned Level
,
2678 unsigned CaptureLevel
) const {
2679 assert(LangOpts
.OpenMP
&& "OpenMP is not allowed");
2680 // Return true if the current level is no longer enclosed in a target region.
2682 if (const auto *VD
= dyn_cast
<VarDecl
>(D
)) {
2683 if (!VD
->hasLocalStorage()) {
2684 if (isInOpenMPTargetExecutionDirective())
2686 DSAStackTy::DSAVarData TopDVar
=
2687 DSAStack
->getTopDSA(D
, /*FromParent=*/false);
2688 unsigned NumLevels
=
2689 getOpenMPCaptureLevels(DSAStack
->getDirective(Level
));
2691 // non-file scope static variale with default(firstprivate)
2692 // should be gloabal captured.
2693 return (NumLevels
== CaptureLevel
+ 1 &&
2694 (TopDVar
.CKind
!= OMPC_shared
||
2695 DSAStack
->getDefaultDSA() == DSA_firstprivate
));
2698 DSAStackTy::DSAVarData DVar
= DSAStack
->getImplicitDSA(D
, Level
);
2699 if (DVar
.CKind
!= OMPC_shared
)
2701 } while (Level
> 0);
2707 void Sema::DestroyDataSharingAttributesStack() { delete DSAStack
; }
2709 void Sema::ActOnOpenMPBeginDeclareVariant(SourceLocation Loc
,
2711 OMPDeclareVariantScopes
.push_back(OMPDeclareVariantScope(TI
));
2714 void Sema::ActOnOpenMPEndDeclareVariant() {
2715 assert(isInOpenMPDeclareVariantScope() &&
2716 "Not in OpenMP declare variant scope!");
2718 OMPDeclareVariantScopes
.pop_back();
2721 void Sema::finalizeOpenMPDelayedAnalysis(const FunctionDecl
*Caller
,
2722 const FunctionDecl
*Callee
,
2723 SourceLocation Loc
) {
2724 assert(LangOpts
.OpenMP
&& "Expected OpenMP compilation mode.");
2725 std::optional
<OMPDeclareTargetDeclAttr::DevTypeTy
> DevTy
=
2726 OMPDeclareTargetDeclAttr::getDeviceType(Caller
->getMostRecentDecl());
2727 // Ignore host functions during device analyzis.
2728 if (LangOpts
.OpenMPIsTargetDevice
&&
2729 (!DevTy
|| *DevTy
== OMPDeclareTargetDeclAttr::DT_Host
))
2731 // Ignore nohost functions during host analyzis.
2732 if (!LangOpts
.OpenMPIsTargetDevice
&& DevTy
&&
2733 *DevTy
== OMPDeclareTargetDeclAttr::DT_NoHost
)
2735 const FunctionDecl
*FD
= Callee
->getMostRecentDecl();
2736 DevTy
= OMPDeclareTargetDeclAttr::getDeviceType(FD
);
2737 if (LangOpts
.OpenMPIsTargetDevice
&& DevTy
&&
2738 *DevTy
== OMPDeclareTargetDeclAttr::DT_Host
) {
2739 // Diagnose host function called during device codegen.
2740 StringRef HostDevTy
=
2741 getOpenMPSimpleClauseTypeName(OMPC_device_type
, OMPC_DEVICE_TYPE_host
);
2742 Diag(Loc
, diag::err_omp_wrong_device_function_call
) << HostDevTy
<< 0;
2743 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD
),
2744 diag::note_omp_marked_device_type_here
)
2748 if (!LangOpts
.OpenMPIsTargetDevice
&& !LangOpts
.OpenMPOffloadMandatory
&&
2749 DevTy
&& *DevTy
== OMPDeclareTargetDeclAttr::DT_NoHost
) {
2750 // In OpenMP 5.2 or later, if the function has a host variant then allow
2751 // that to be called instead
2752 auto &&HasHostAttr
= [](const FunctionDecl
*Callee
) {
2753 for (OMPDeclareVariantAttr
*A
:
2754 Callee
->specific_attrs
<OMPDeclareVariantAttr
>()) {
2755 auto *DeclRefVariant
= cast
<DeclRefExpr
>(A
->getVariantFuncRef());
2756 auto *VariantFD
= cast
<FunctionDecl
>(DeclRefVariant
->getDecl());
2757 std::optional
<OMPDeclareTargetDeclAttr::DevTypeTy
> DevTy
=
2758 OMPDeclareTargetDeclAttr::getDeviceType(
2759 VariantFD
->getMostRecentDecl());
2760 if (!DevTy
|| *DevTy
== OMPDeclareTargetDeclAttr::DT_Host
)
2765 if (getLangOpts().OpenMP
>= 52 &&
2766 Callee
->hasAttr
<OMPDeclareVariantAttr
>() && HasHostAttr(Callee
))
2768 // Diagnose nohost function called during host codegen.
2769 StringRef NoHostDevTy
= getOpenMPSimpleClauseTypeName(
2770 OMPC_device_type
, OMPC_DEVICE_TYPE_nohost
);
2771 Diag(Loc
, diag::err_omp_wrong_device_function_call
) << NoHostDevTy
<< 1;
2772 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD
),
2773 diag::note_omp_marked_device_type_here
)
2778 void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind
,
2779 const DeclarationNameInfo
&DirName
,
2780 Scope
*CurScope
, SourceLocation Loc
) {
2781 DSAStack
->push(DKind
, DirName
, CurScope
, Loc
);
2782 PushExpressionEvaluationContext(
2783 ExpressionEvaluationContext::PotentiallyEvaluated
);
2786 void Sema::StartOpenMPClause(OpenMPClauseKind K
) {
2787 DSAStack
->setClauseParsingMode(K
);
2790 void Sema::EndOpenMPClause() {
2791 DSAStack
->setClauseParsingMode(/*K=*/OMPC_unknown
);
2792 CleanupVarDeclMarking();
2795 static std::pair
<ValueDecl
*, bool>
2796 getPrivateItem(Sema
&S
, Expr
*&RefExpr
, SourceLocation
&ELoc
,
2797 SourceRange
&ERange
, bool AllowArraySection
= false,
2798 StringRef DiagType
= "");
2800 /// Check consistency of the reduction clauses.
2801 static void checkReductionClauses(Sema
&S
, DSAStackTy
*Stack
,
2802 ArrayRef
<OMPClause
*> Clauses
) {
2803 bool InscanFound
= false;
2804 SourceLocation InscanLoc
;
2805 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2806 // A reduction clause without the inscan reduction-modifier may not appear on
2807 // a construct on which a reduction clause with the inscan reduction-modifier
2809 for (OMPClause
*C
: Clauses
) {
2810 if (C
->getClauseKind() != OMPC_reduction
)
2812 auto *RC
= cast
<OMPReductionClause
>(C
);
2813 if (RC
->getModifier() == OMPC_REDUCTION_inscan
) {
2815 InscanLoc
= RC
->getModifierLoc();
2818 if (RC
->getModifier() == OMPC_REDUCTION_task
) {
2819 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2820 // A reduction clause with the task reduction-modifier may only appear on
2821 // a parallel construct, a worksharing construct or a combined or
2822 // composite construct for which any of the aforementioned constructs is a
2823 // constituent construct and simd or loop are not constituent constructs.
2824 OpenMPDirectiveKind CurDir
= Stack
->getCurrentDirective();
2825 if (!(isOpenMPParallelDirective(CurDir
) ||
2826 isOpenMPWorksharingDirective(CurDir
)) ||
2827 isOpenMPSimdDirective(CurDir
))
2828 S
.Diag(RC
->getModifierLoc(),
2829 diag::err_omp_reduction_task_not_parallel_or_worksharing
);
2834 for (OMPClause
*C
: Clauses
) {
2835 if (C
->getClauseKind() != OMPC_reduction
)
2837 auto *RC
= cast
<OMPReductionClause
>(C
);
2838 if (RC
->getModifier() != OMPC_REDUCTION_inscan
) {
2839 S
.Diag(RC
->getModifier() == OMPC_REDUCTION_unknown
2841 : RC
->getModifierLoc(),
2842 diag::err_omp_inscan_reduction_expected
);
2843 S
.Diag(InscanLoc
, diag::note_omp_previous_inscan_reduction
);
2846 for (Expr
*Ref
: RC
->varlists()) {
2847 assert(Ref
&& "NULL expr in OpenMP nontemporal clause.");
2848 SourceLocation ELoc
;
2850 Expr
*SimpleRefExpr
= Ref
;
2851 auto Res
= getPrivateItem(S
, SimpleRefExpr
, ELoc
, ERange
,
2852 /*AllowArraySection=*/true);
2853 ValueDecl
*D
= Res
.first
;
2856 if (!Stack
->isUsedInScanDirective(getCanonicalDecl(D
))) {
2857 S
.Diag(Ref
->getExprLoc(),
2858 diag::err_omp_reduction_not_inclusive_exclusive
)
2859 << Ref
->getSourceRange();
2866 static void checkAllocateClauses(Sema
&S
, DSAStackTy
*Stack
,
2867 ArrayRef
<OMPClause
*> Clauses
);
2868 static DeclRefExpr
*buildCapture(Sema
&S
, ValueDecl
*D
, Expr
*CaptureExpr
,
2871 static void reportOriginalDsa(Sema
&SemaRef
, const DSAStackTy
*Stack
,
2873 const DSAStackTy::DSAVarData
&DVar
,
2874 bool IsLoopIterVar
= false);
2876 void Sema::EndOpenMPDSABlock(Stmt
*CurDirective
) {
2877 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2878 // A variable of class type (or array thereof) that appears in a lastprivate
2879 // clause requires an accessible, unambiguous default constructor for the
2880 // class type, unless the list item is also specified in a firstprivate
2882 if (const auto *D
= dyn_cast_or_null
<OMPExecutableDirective
>(CurDirective
)) {
2883 for (OMPClause
*C
: D
->clauses()) {
2884 if (auto *Clause
= dyn_cast
<OMPLastprivateClause
>(C
)) {
2885 SmallVector
<Expr
*, 8> PrivateCopies
;
2886 for (Expr
*DE
: Clause
->varlists()) {
2887 if (DE
->isValueDependent() || DE
->isTypeDependent()) {
2888 PrivateCopies
.push_back(nullptr);
2891 auto *DRE
= cast
<DeclRefExpr
>(DE
->IgnoreParens());
2892 auto *VD
= cast
<VarDecl
>(DRE
->getDecl());
2893 QualType Type
= VD
->getType().getNonReferenceType();
2894 const DSAStackTy::DSAVarData DVar
=
2895 DSAStack
->getTopDSA(VD
, /*FromParent=*/false);
2896 if (DVar
.CKind
== OMPC_lastprivate
) {
2897 // Generate helper private variable and initialize it with the
2898 // default value. The address of the original variable is replaced
2899 // by the address of the new private variable in CodeGen. This new
2900 // variable is not added to IdResolver, so the code in the OpenMP
2901 // region uses original variable for proper diagnostics.
2902 VarDecl
*VDPrivate
= buildVarDecl(
2903 *this, DE
->getExprLoc(), Type
.getUnqualifiedType(),
2904 VD
->getName(), VD
->hasAttrs() ? &VD
->getAttrs() : nullptr, DRE
);
2905 ActOnUninitializedDecl(VDPrivate
);
2906 if (VDPrivate
->isInvalidDecl()) {
2907 PrivateCopies
.push_back(nullptr);
2910 PrivateCopies
.push_back(buildDeclRefExpr(
2911 *this, VDPrivate
, DE
->getType(), DE
->getExprLoc()));
2913 // The variable is also a firstprivate, so initialization sequence
2914 // for private copy is generated already.
2915 PrivateCopies
.push_back(nullptr);
2918 Clause
->setPrivateCopies(PrivateCopies
);
2921 // Finalize nontemporal clause by handling private copies, if any.
2922 if (auto *Clause
= dyn_cast
<OMPNontemporalClause
>(C
)) {
2923 SmallVector
<Expr
*, 8> PrivateRefs
;
2924 for (Expr
*RefExpr
: Clause
->varlists()) {
2925 assert(RefExpr
&& "NULL expr in OpenMP nontemporal clause.");
2926 SourceLocation ELoc
;
2928 Expr
*SimpleRefExpr
= RefExpr
;
2929 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
2931 // It will be analyzed later.
2932 PrivateRefs
.push_back(RefExpr
);
2933 ValueDecl
*D
= Res
.first
;
2937 const DSAStackTy::DSAVarData DVar
=
2938 DSAStack
->getTopDSA(D
, /*FromParent=*/false);
2939 PrivateRefs
.push_back(DVar
.PrivateCopy
? DVar
.PrivateCopy
2942 Clause
->setPrivateRefs(PrivateRefs
);
2945 if (auto *Clause
= dyn_cast
<OMPUsesAllocatorsClause
>(C
)) {
2946 for (unsigned I
= 0, E
= Clause
->getNumberOfAllocators(); I
< E
; ++I
) {
2947 OMPUsesAllocatorsClause::Data D
= Clause
->getAllocatorData(I
);
2948 auto *DRE
= dyn_cast
<DeclRefExpr
>(D
.Allocator
->IgnoreParenImpCasts());
2951 ValueDecl
*VD
= DRE
->getDecl();
2952 if (!VD
|| !isa
<VarDecl
>(VD
))
2954 DSAStackTy::DSAVarData DVar
=
2955 DSAStack
->getTopDSA(VD
, /*FromParent=*/false);
2956 // OpenMP [2.12.5, target Construct]
2957 // Memory allocators that appear in a uses_allocators clause cannot
2958 // appear in other data-sharing attribute clauses or data-mapping
2959 // attribute clauses in the same construct.
2960 Expr
*MapExpr
= nullptr;
2962 DSAStack
->checkMappableExprComponentListsForDecl(
2963 VD
, /*CurrentRegionOnly=*/true,
2965 OMPClauseMappableExprCommon::MappableExprComponentListRef
2967 OpenMPClauseKind C
) {
2968 auto MI
= MapExprComponents
.rbegin();
2969 auto ME
= MapExprComponents
.rend();
2971 MI
->getAssociatedDeclaration()->getCanonicalDecl() ==
2972 VD
->getCanonicalDecl()) {
2973 MapExpr
= MI
->getAssociatedExpression();
2978 Diag(D
.Allocator
->getExprLoc(),
2979 diag::err_omp_allocator_used_in_clauses
)
2980 << D
.Allocator
->getSourceRange();
2982 reportOriginalDsa(*this, DSAStack
, VD
, DVar
);
2984 Diag(MapExpr
->getExprLoc(), diag::note_used_here
)
2985 << MapExpr
->getSourceRange();
2991 // Check allocate clauses.
2992 if (!CurContext
->isDependentContext())
2993 checkAllocateClauses(*this, DSAStack
, D
->clauses());
2994 checkReductionClauses(*this, DSAStack
, D
->clauses());
2998 DiscardCleanupsInEvaluationContext();
2999 PopExpressionEvaluationContext();
3002 static bool FinishOpenMPLinearClause(OMPLinearClause
&Clause
, DeclRefExpr
*IV
,
3003 Expr
*NumIterations
, Sema
&SemaRef
,
3004 Scope
*S
, DSAStackTy
*Stack
);
3008 class VarDeclFilterCCC final
: public CorrectionCandidateCallback
{
3013 explicit VarDeclFilterCCC(Sema
&S
) : SemaRef(S
) {}
3014 bool ValidateCandidate(const TypoCorrection
&Candidate
) override
{
3015 NamedDecl
*ND
= Candidate
.getCorrectionDecl();
3016 if (const auto *VD
= dyn_cast_or_null
<VarDecl
>(ND
)) {
3017 return VD
->hasGlobalStorage() &&
3018 SemaRef
.isDeclInScope(ND
, SemaRef
.getCurLexicalContext(),
3019 SemaRef
.getCurScope());
3024 std::unique_ptr
<CorrectionCandidateCallback
> clone() override
{
3025 return std::make_unique
<VarDeclFilterCCC
>(*this);
3029 class VarOrFuncDeclFilterCCC final
: public CorrectionCandidateCallback
{
3034 explicit VarOrFuncDeclFilterCCC(Sema
&S
) : SemaRef(S
) {}
3035 bool ValidateCandidate(const TypoCorrection
&Candidate
) override
{
3036 NamedDecl
*ND
= Candidate
.getCorrectionDecl();
3037 if (ND
&& ((isa
<VarDecl
>(ND
) && ND
->getKind() == Decl::Var
) ||
3038 isa
<FunctionDecl
>(ND
))) {
3039 return SemaRef
.isDeclInScope(ND
, SemaRef
.getCurLexicalContext(),
3040 SemaRef
.getCurScope());
3045 std::unique_ptr
<CorrectionCandidateCallback
> clone() override
{
3046 return std::make_unique
<VarOrFuncDeclFilterCCC
>(*this);
3052 ExprResult
Sema::ActOnOpenMPIdExpression(Scope
*CurScope
,
3053 CXXScopeSpec
&ScopeSpec
,
3054 const DeclarationNameInfo
&Id
,
3055 OpenMPDirectiveKind Kind
) {
3056 LookupResult
Lookup(*this, Id
, LookupOrdinaryName
);
3057 LookupParsedName(Lookup
, CurScope
, &ScopeSpec
, true);
3059 if (Lookup
.isAmbiguous())
3063 if (!Lookup
.isSingleResult()) {
3064 VarDeclFilterCCC
CCC(*this);
3065 if (TypoCorrection Corrected
=
3066 CorrectTypo(Id
, LookupOrdinaryName
, CurScope
, nullptr, CCC
,
3067 CTK_ErrorRecovery
)) {
3068 diagnoseTypo(Corrected
,
3069 PDiag(Lookup
.empty()
3070 ? diag::err_undeclared_var_use_suggest
3071 : diag::err_omp_expected_var_arg_suggest
)
3073 VD
= Corrected
.getCorrectionDeclAs
<VarDecl
>();
3075 Diag(Id
.getLoc(), Lookup
.empty() ? diag::err_undeclared_var_use
3076 : diag::err_omp_expected_var_arg
)
3080 } else if (!(VD
= Lookup
.getAsSingle
<VarDecl
>())) {
3081 Diag(Id
.getLoc(), diag::err_omp_expected_var_arg
) << Id
.getName();
3082 Diag(Lookup
.getFoundDecl()->getLocation(), diag::note_declared_at
);
3085 Lookup
.suppressDiagnostics();
3087 // OpenMP [2.9.2, Syntax, C/C++]
3088 // Variables must be file-scope, namespace-scope, or static block-scope.
3089 if (Kind
== OMPD_threadprivate
&& !VD
->hasGlobalStorage()) {
3090 Diag(Id
.getLoc(), diag::err_omp_global_var_arg
)
3091 << getOpenMPDirectiveName(Kind
) << !VD
->isStaticLocal();
3093 VD
->isThisDeclarationADefinition(Context
) == VarDecl::DeclarationOnly
;
3094 Diag(VD
->getLocation(),
3095 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
3100 VarDecl
*CanonicalVD
= VD
->getCanonicalDecl();
3101 NamedDecl
*ND
= CanonicalVD
;
3102 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3103 // A threadprivate directive for file-scope variables must appear outside
3104 // any definition or declaration.
3105 if (CanonicalVD
->getDeclContext()->isTranslationUnit() &&
3106 !getCurLexicalContext()->isTranslationUnit()) {
3107 Diag(Id
.getLoc(), diag::err_omp_var_scope
)
3108 << getOpenMPDirectiveName(Kind
) << VD
;
3110 VD
->isThisDeclarationADefinition(Context
) == VarDecl::DeclarationOnly
;
3111 Diag(VD
->getLocation(),
3112 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
3116 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3117 // A threadprivate directive for static class member variables must appear
3118 // in the class definition, in the same scope in which the member
3119 // variables are declared.
3120 if (CanonicalVD
->isStaticDataMember() &&
3121 !CanonicalVD
->getDeclContext()->Equals(getCurLexicalContext())) {
3122 Diag(Id
.getLoc(), diag::err_omp_var_scope
)
3123 << getOpenMPDirectiveName(Kind
) << VD
;
3125 VD
->isThisDeclarationADefinition(Context
) == VarDecl::DeclarationOnly
;
3126 Diag(VD
->getLocation(),
3127 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
3131 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3132 // A threadprivate directive for namespace-scope variables must appear
3133 // outside any definition or declaration other than the namespace
3134 // definition itself.
3135 if (CanonicalVD
->getDeclContext()->isNamespace() &&
3136 (!getCurLexicalContext()->isFileContext() ||
3137 !getCurLexicalContext()->Encloses(CanonicalVD
->getDeclContext()))) {
3138 Diag(Id
.getLoc(), diag::err_omp_var_scope
)
3139 << getOpenMPDirectiveName(Kind
) << VD
;
3141 VD
->isThisDeclarationADefinition(Context
) == VarDecl::DeclarationOnly
;
3142 Diag(VD
->getLocation(),
3143 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
3147 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3148 // A threadprivate directive for static block-scope variables must appear
3149 // in the scope of the variable and not in a nested scope.
3150 if (CanonicalVD
->isLocalVarDecl() && CurScope
&&
3151 !isDeclInScope(ND
, getCurLexicalContext(), CurScope
)) {
3152 Diag(Id
.getLoc(), diag::err_omp_var_scope
)
3153 << getOpenMPDirectiveName(Kind
) << VD
;
3155 VD
->isThisDeclarationADefinition(Context
) == VarDecl::DeclarationOnly
;
3156 Diag(VD
->getLocation(),
3157 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
3162 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3163 // A threadprivate directive must lexically precede all references to any
3164 // of the variables in its list.
3165 if (Kind
== OMPD_threadprivate
&& VD
->isUsed() &&
3166 !DSAStack
->isThreadPrivate(VD
)) {
3167 Diag(Id
.getLoc(), diag::err_omp_var_used
)
3168 << getOpenMPDirectiveName(Kind
) << VD
;
3172 QualType ExprType
= VD
->getType().getNonReferenceType();
3173 return DeclRefExpr::Create(Context
, NestedNameSpecifierLoc(),
3174 SourceLocation(), VD
,
3175 /*RefersToEnclosingVariableOrCapture=*/false,
3176 Id
.getLoc(), ExprType
, VK_LValue
);
3179 Sema::DeclGroupPtrTy
3180 Sema::ActOnOpenMPThreadprivateDirective(SourceLocation Loc
,
3181 ArrayRef
<Expr
*> VarList
) {
3182 if (OMPThreadPrivateDecl
*D
= CheckOMPThreadPrivateDecl(Loc
, VarList
)) {
3183 CurContext
->addDecl(D
);
3184 return DeclGroupPtrTy::make(DeclGroupRef(D
));
3190 class LocalVarRefChecker final
3191 : public ConstStmtVisitor
<LocalVarRefChecker
, bool> {
3195 bool VisitDeclRefExpr(const DeclRefExpr
*E
) {
3196 if (const auto *VD
= dyn_cast
<VarDecl
>(E
->getDecl())) {
3197 if (VD
->hasLocalStorage()) {
3198 SemaRef
.Diag(E
->getBeginLoc(),
3199 diag::err_omp_local_var_in_threadprivate_init
)
3200 << E
->getSourceRange();
3201 SemaRef
.Diag(VD
->getLocation(), diag::note_defined_here
)
3202 << VD
<< VD
->getSourceRange();
3208 bool VisitStmt(const Stmt
*S
) {
3209 for (const Stmt
*Child
: S
->children()) {
3210 if (Child
&& Visit(Child
))
3215 explicit LocalVarRefChecker(Sema
&SemaRef
) : SemaRef(SemaRef
) {}
3219 OMPThreadPrivateDecl
*
3220 Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc
, ArrayRef
<Expr
*> VarList
) {
3221 SmallVector
<Expr
*, 8> Vars
;
3222 for (Expr
*RefExpr
: VarList
) {
3223 auto *DE
= cast
<DeclRefExpr
>(RefExpr
);
3224 auto *VD
= cast
<VarDecl
>(DE
->getDecl());
3225 SourceLocation ILoc
= DE
->getExprLoc();
3227 // Mark variable as used.
3228 VD
->setReferenced();
3229 VD
->markUsed(Context
);
3231 QualType QType
= VD
->getType();
3232 if (QType
->isDependentType() || QType
->isInstantiationDependentType()) {
3233 // It will be analyzed later.
3238 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3239 // A threadprivate variable must not have an incomplete type.
3240 if (RequireCompleteType(ILoc
, VD
->getType(),
3241 diag::err_omp_threadprivate_incomplete_type
)) {
3245 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3246 // A threadprivate variable must not have a reference type.
3247 if (VD
->getType()->isReferenceType()) {
3248 Diag(ILoc
, diag::err_omp_ref_type_arg
)
3249 << getOpenMPDirectiveName(OMPD_threadprivate
) << VD
->getType();
3251 VD
->isThisDeclarationADefinition(Context
) == VarDecl::DeclarationOnly
;
3252 Diag(VD
->getLocation(),
3253 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
3258 // Check if this is a TLS variable. If TLS is not being supported, produce
3259 // the corresponding diagnostic.
3260 if ((VD
->getTLSKind() != VarDecl::TLS_None
&&
3261 !(VD
->hasAttr
<OMPThreadPrivateDeclAttr
>() &&
3262 getLangOpts().OpenMPUseTLS
&&
3263 getASTContext().getTargetInfo().isTLSSupported())) ||
3264 (VD
->getStorageClass() == SC_Register
&& VD
->hasAttr
<AsmLabelAttr
>() &&
3265 !VD
->isLocalVarDecl())) {
3266 Diag(ILoc
, diag::err_omp_var_thread_local
)
3267 << VD
<< ((VD
->getTLSKind() != VarDecl::TLS_None
) ? 0 : 1);
3269 VD
->isThisDeclarationADefinition(Context
) == VarDecl::DeclarationOnly
;
3270 Diag(VD
->getLocation(),
3271 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
3276 // Check if initial value of threadprivate variable reference variable with
3277 // local storage (it is not supported by runtime).
3278 if (const Expr
*Init
= VD
->getAnyInitializer()) {
3279 LocalVarRefChecker
Checker(*this);
3280 if (Checker
.Visit(Init
))
3284 Vars
.push_back(RefExpr
);
3285 DSAStack
->addDSA(VD
, DE
, OMPC_threadprivate
);
3286 VD
->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3287 Context
, SourceRange(Loc
, Loc
)));
3288 if (ASTMutationListener
*ML
= Context
.getASTMutationListener())
3289 ML
->DeclarationMarkedOpenMPThreadPrivate(VD
);
3291 OMPThreadPrivateDecl
*D
= nullptr;
3292 if (!Vars
.empty()) {
3293 D
= OMPThreadPrivateDecl::Create(Context
, getCurLexicalContext(), Loc
,
3295 D
->setAccess(AS_public
);
3300 static OMPAllocateDeclAttr::AllocatorTypeTy
3301 getAllocatorKind(Sema
&S
, DSAStackTy
*Stack
, Expr
*Allocator
) {
3303 return OMPAllocateDeclAttr::OMPNullMemAlloc
;
3304 if (Allocator
->isTypeDependent() || Allocator
->isValueDependent() ||
3305 Allocator
->isInstantiationDependent() ||
3306 Allocator
->containsUnexpandedParameterPack())
3307 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc
;
3308 auto AllocatorKindRes
= OMPAllocateDeclAttr::OMPUserDefinedMemAlloc
;
3309 llvm::FoldingSetNodeID AEId
;
3310 const Expr
*AE
= Allocator
->IgnoreParenImpCasts();
3311 AE
->IgnoreImpCasts()->Profile(AEId
, S
.getASTContext(), /*Canonical=*/true);
3312 for (int I
= 0; I
< OMPAllocateDeclAttr::OMPUserDefinedMemAlloc
; ++I
) {
3313 auto AllocatorKind
= static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I
);
3314 const Expr
*DefAllocator
= Stack
->getAllocator(AllocatorKind
);
3315 llvm::FoldingSetNodeID DAEId
;
3316 DefAllocator
->IgnoreImpCasts()->Profile(DAEId
, S
.getASTContext(),
3317 /*Canonical=*/true);
3318 if (AEId
== DAEId
) {
3319 AllocatorKindRes
= AllocatorKind
;
3323 return AllocatorKindRes
;
3326 static bool checkPreviousOMPAllocateAttribute(
3327 Sema
&S
, DSAStackTy
*Stack
, Expr
*RefExpr
, VarDecl
*VD
,
3328 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind
, Expr
*Allocator
) {
3329 if (!VD
->hasAttr
<OMPAllocateDeclAttr
>())
3331 const auto *A
= VD
->getAttr
<OMPAllocateDeclAttr
>();
3332 Expr
*PrevAllocator
= A
->getAllocator();
3333 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind
=
3334 getAllocatorKind(S
, Stack
, PrevAllocator
);
3335 bool AllocatorsMatch
= AllocatorKind
== PrevAllocatorKind
;
3336 if (AllocatorsMatch
&&
3337 AllocatorKind
== OMPAllocateDeclAttr::OMPUserDefinedMemAlloc
&&
3338 Allocator
&& PrevAllocator
) {
3339 const Expr
*AE
= Allocator
->IgnoreParenImpCasts();
3340 const Expr
*PAE
= PrevAllocator
->IgnoreParenImpCasts();
3341 llvm::FoldingSetNodeID AEId
, PAEId
;
3342 AE
->Profile(AEId
, S
.Context
, /*Canonical=*/true);
3343 PAE
->Profile(PAEId
, S
.Context
, /*Canonical=*/true);
3344 AllocatorsMatch
= AEId
== PAEId
;
3346 if (!AllocatorsMatch
) {
3347 SmallString
<256> AllocatorBuffer
;
3348 llvm::raw_svector_ostream
AllocatorStream(AllocatorBuffer
);
3350 Allocator
->printPretty(AllocatorStream
, nullptr, S
.getPrintingPolicy());
3351 SmallString
<256> PrevAllocatorBuffer
;
3352 llvm::raw_svector_ostream
PrevAllocatorStream(PrevAllocatorBuffer
);
3354 PrevAllocator
->printPretty(PrevAllocatorStream
, nullptr,
3355 S
.getPrintingPolicy());
3357 SourceLocation AllocatorLoc
=
3358 Allocator
? Allocator
->getExprLoc() : RefExpr
->getExprLoc();
3359 SourceRange AllocatorRange
=
3360 Allocator
? Allocator
->getSourceRange() : RefExpr
->getSourceRange();
3361 SourceLocation PrevAllocatorLoc
=
3362 PrevAllocator
? PrevAllocator
->getExprLoc() : A
->getLocation();
3363 SourceRange PrevAllocatorRange
=
3364 PrevAllocator
? PrevAllocator
->getSourceRange() : A
->getRange();
3365 S
.Diag(AllocatorLoc
, diag::warn_omp_used_different_allocator
)
3366 << (Allocator
? 1 : 0) << AllocatorStream
.str()
3367 << (PrevAllocator
? 1 : 0) << PrevAllocatorStream
.str()
3369 S
.Diag(PrevAllocatorLoc
, diag::note_omp_previous_allocator
)
3370 << PrevAllocatorRange
;
3377 applyOMPAllocateAttribute(Sema
&S
, VarDecl
*VD
,
3378 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind
,
3379 Expr
*Allocator
, Expr
*Alignment
, SourceRange SR
) {
3380 if (VD
->hasAttr
<OMPAllocateDeclAttr
>())
3383 (Alignment
->isTypeDependent() || Alignment
->isValueDependent() ||
3384 Alignment
->isInstantiationDependent() ||
3385 Alignment
->containsUnexpandedParameterPack()))
3386 // Apply later when we have a usable value.
3389 (Allocator
->isTypeDependent() || Allocator
->isValueDependent() ||
3390 Allocator
->isInstantiationDependent() ||
3391 Allocator
->containsUnexpandedParameterPack()))
3393 auto *A
= OMPAllocateDeclAttr::CreateImplicit(S
.Context
, AllocatorKind
,
3394 Allocator
, Alignment
, SR
);
3396 if (ASTMutationListener
*ML
= S
.Context
.getASTMutationListener())
3397 ML
->DeclarationMarkedOpenMPAllocate(VD
, A
);
3400 Sema::DeclGroupPtrTy
3401 Sema::ActOnOpenMPAllocateDirective(SourceLocation Loc
, ArrayRef
<Expr
*> VarList
,
3402 ArrayRef
<OMPClause
*> Clauses
,
3403 DeclContext
*Owner
) {
3404 assert(Clauses
.size() <= 2 && "Expected at most two clauses.");
3405 Expr
*Alignment
= nullptr;
3406 Expr
*Allocator
= nullptr;
3407 if (Clauses
.empty()) {
3408 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3409 // allocate directives that appear in a target region must specify an
3410 // allocator clause unless a requires directive with the dynamic_allocators
3411 // clause is present in the same compilation unit.
3412 if (LangOpts
.OpenMPIsTargetDevice
&&
3413 !DSAStack
->hasRequiresDeclWithClause
<OMPDynamicAllocatorsClause
>())
3414 targetDiag(Loc
, diag::err_expected_allocator_clause
);
3416 for (const OMPClause
*C
: Clauses
)
3417 if (const auto *AC
= dyn_cast
<OMPAllocatorClause
>(C
))
3418 Allocator
= AC
->getAllocator();
3419 else if (const auto *AC
= dyn_cast
<OMPAlignClause
>(C
))
3420 Alignment
= AC
->getAlignment();
3422 llvm_unreachable("Unexpected clause on allocate directive");
3424 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind
=
3425 getAllocatorKind(*this, DSAStack
, Allocator
);
3426 SmallVector
<Expr
*, 8> Vars
;
3427 for (Expr
*RefExpr
: VarList
) {
3428 auto *DE
= cast
<DeclRefExpr
>(RefExpr
);
3429 auto *VD
= cast
<VarDecl
>(DE
->getDecl());
3431 // Check if this is a TLS variable or global register.
3432 if (VD
->getTLSKind() != VarDecl::TLS_None
||
3433 VD
->hasAttr
<OMPThreadPrivateDeclAttr
>() ||
3434 (VD
->getStorageClass() == SC_Register
&& VD
->hasAttr
<AsmLabelAttr
>() &&
3435 !VD
->isLocalVarDecl()))
3438 // If the used several times in the allocate directive, the same allocator
3440 if (checkPreviousOMPAllocateAttribute(*this, DSAStack
, RefExpr
, VD
,
3441 AllocatorKind
, Allocator
))
3444 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3445 // If a list item has a static storage type, the allocator expression in the
3446 // allocator clause must be a constant expression that evaluates to one of
3447 // the predefined memory allocator values.
3448 if (Allocator
&& VD
->hasGlobalStorage()) {
3449 if (AllocatorKind
== OMPAllocateDeclAttr::OMPUserDefinedMemAlloc
) {
3450 Diag(Allocator
->getExprLoc(),
3451 diag::err_omp_expected_predefined_allocator
)
3452 << Allocator
->getSourceRange();
3453 bool IsDecl
= VD
->isThisDeclarationADefinition(Context
) ==
3454 VarDecl::DeclarationOnly
;
3455 Diag(VD
->getLocation(),
3456 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
3462 Vars
.push_back(RefExpr
);
3463 applyOMPAllocateAttribute(*this, VD
, AllocatorKind
, Allocator
, Alignment
,
3464 DE
->getSourceRange());
3469 Owner
= getCurLexicalContext();
3470 auto *D
= OMPAllocateDecl::Create(Context
, Owner
, Loc
, Vars
, Clauses
);
3471 D
->setAccess(AS_public
);
3473 return DeclGroupPtrTy::make(DeclGroupRef(D
));
3476 Sema::DeclGroupPtrTy
3477 Sema::ActOnOpenMPRequiresDirective(SourceLocation Loc
,
3478 ArrayRef
<OMPClause
*> ClauseList
) {
3479 OMPRequiresDecl
*D
= nullptr;
3480 if (!CurContext
->isFileContext()) {
3481 Diag(Loc
, diag::err_omp_invalid_scope
) << "requires";
3483 D
= CheckOMPRequiresDecl(Loc
, ClauseList
);
3485 CurContext
->addDecl(D
);
3486 DSAStack
->addRequiresDecl(D
);
3489 return DeclGroupPtrTy::make(DeclGroupRef(D
));
3492 void Sema::ActOnOpenMPAssumesDirective(SourceLocation Loc
,
3493 OpenMPDirectiveKind DKind
,
3494 ArrayRef
<std::string
> Assumptions
,
3495 bool SkippedClauses
) {
3496 if (!SkippedClauses
&& Assumptions
.empty())
3497 Diag(Loc
, diag::err_omp_no_clause_for_directive
)
3498 << llvm::omp::getAllAssumeClauseOptions()
3499 << llvm::omp::getOpenMPDirectiveName(DKind
);
3501 auto *AA
= AssumptionAttr::Create(Context
, llvm::join(Assumptions
, ","), Loc
);
3502 if (DKind
== llvm::omp::Directive::OMPD_begin_assumes
) {
3503 OMPAssumeScoped
.push_back(AA
);
3507 // Global assumes without assumption clauses are ignored.
3508 if (Assumptions
.empty())
3511 assert(DKind
== llvm::omp::Directive::OMPD_assumes
&&
3512 "Unexpected omp assumption directive!");
3513 OMPAssumeGlobal
.push_back(AA
);
3515 // The OMPAssumeGlobal scope above will take care of new declarations but
3516 // we also want to apply the assumption to existing ones, e.g., to
3517 // declarations in included headers. To this end, we traverse all existing
3518 // declaration contexts and annotate function declarations here.
3519 SmallVector
<DeclContext
*, 8> DeclContexts
;
3520 auto *Ctx
= CurContext
;
3521 while (Ctx
->getLexicalParent())
3522 Ctx
= Ctx
->getLexicalParent();
3523 DeclContexts
.push_back(Ctx
);
3524 while (!DeclContexts
.empty()) {
3525 DeclContext
*DC
= DeclContexts
.pop_back_val();
3526 for (auto *SubDC
: DC
->decls()) {
3527 if (SubDC
->isInvalidDecl())
3529 if (auto *CTD
= dyn_cast
<ClassTemplateDecl
>(SubDC
)) {
3530 DeclContexts
.push_back(CTD
->getTemplatedDecl());
3531 llvm::append_range(DeclContexts
, CTD
->specializations());
3534 if (auto *DC
= dyn_cast
<DeclContext
>(SubDC
))
3535 DeclContexts
.push_back(DC
);
3536 if (auto *F
= dyn_cast
<FunctionDecl
>(SubDC
)) {
3544 void Sema::ActOnOpenMPEndAssumesDirective() {
3545 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3546 OMPAssumeScoped
.pop_back();
3549 OMPRequiresDecl
*Sema::CheckOMPRequiresDecl(SourceLocation Loc
,
3550 ArrayRef
<OMPClause
*> ClauseList
) {
3551 /// For target specific clauses, the requires directive cannot be
3552 /// specified after the handling of any of the target regions in the
3553 /// current compilation unit.
3554 ArrayRef
<SourceLocation
> TargetLocations
=
3555 DSAStack
->getEncounteredTargetLocs();
3556 SourceLocation AtomicLoc
= DSAStack
->getAtomicDirectiveLoc();
3557 if (!TargetLocations
.empty() || !AtomicLoc
.isInvalid()) {
3558 for (const OMPClause
*CNew
: ClauseList
) {
3559 // Check if any of the requires clauses affect target regions.
3560 if (isa
<OMPUnifiedSharedMemoryClause
>(CNew
) ||
3561 isa
<OMPUnifiedAddressClause
>(CNew
) ||
3562 isa
<OMPReverseOffloadClause
>(CNew
) ||
3563 isa
<OMPDynamicAllocatorsClause
>(CNew
)) {
3564 Diag(Loc
, diag::err_omp_directive_before_requires
)
3565 << "target" << getOpenMPClauseName(CNew
->getClauseKind());
3566 for (SourceLocation TargetLoc
: TargetLocations
) {
3567 Diag(TargetLoc
, diag::note_omp_requires_encountered_directive
)
3570 } else if (!AtomicLoc
.isInvalid() &&
3571 isa
<OMPAtomicDefaultMemOrderClause
>(CNew
)) {
3572 Diag(Loc
, diag::err_omp_directive_before_requires
)
3573 << "atomic" << getOpenMPClauseName(CNew
->getClauseKind());
3574 Diag(AtomicLoc
, diag::note_omp_requires_encountered_directive
)
3580 if (!DSAStack
->hasDuplicateRequiresClause(ClauseList
))
3581 return OMPRequiresDecl::Create(Context
, getCurLexicalContext(), Loc
,
3586 static void reportOriginalDsa(Sema
&SemaRef
, const DSAStackTy
*Stack
,
3588 const DSAStackTy::DSAVarData
&DVar
,
3589 bool IsLoopIterVar
) {
3591 SemaRef
.Diag(DVar
.RefExpr
->getExprLoc(), diag::note_omp_explicit_dsa
)
3592 << getOpenMPClauseName(DVar
.CKind
);
3596 PDSA_StaticMemberShared
,
3597 PDSA_StaticLocalVarShared
,
3598 PDSA_LoopIterVarPrivate
,
3599 PDSA_LoopIterVarLinear
,
3600 PDSA_LoopIterVarLastprivate
,
3601 PDSA_ConstVarShared
,
3602 PDSA_GlobalVarShared
,
3603 PDSA_TaskVarFirstprivate
,
3604 PDSA_LocalVarPrivate
,
3606 } Reason
= PDSA_Implicit
;
3607 bool ReportHint
= false;
3608 auto ReportLoc
= D
->getLocation();
3609 auto *VD
= dyn_cast
<VarDecl
>(D
);
3610 if (IsLoopIterVar
) {
3611 if (DVar
.CKind
== OMPC_private
)
3612 Reason
= PDSA_LoopIterVarPrivate
;
3613 else if (DVar
.CKind
== OMPC_lastprivate
)
3614 Reason
= PDSA_LoopIterVarLastprivate
;
3616 Reason
= PDSA_LoopIterVarLinear
;
3617 } else if (isOpenMPTaskingDirective(DVar
.DKind
) &&
3618 DVar
.CKind
== OMPC_firstprivate
) {
3619 Reason
= PDSA_TaskVarFirstprivate
;
3620 ReportLoc
= DVar
.ImplicitDSALoc
;
3621 } else if (VD
&& VD
->isStaticLocal())
3622 Reason
= PDSA_StaticLocalVarShared
;
3623 else if (VD
&& VD
->isStaticDataMember())
3624 Reason
= PDSA_StaticMemberShared
;
3625 else if (VD
&& VD
->isFileVarDecl())
3626 Reason
= PDSA_GlobalVarShared
;
3627 else if (D
->getType().isConstant(SemaRef
.getASTContext()))
3628 Reason
= PDSA_ConstVarShared
;
3629 else if (VD
&& VD
->isLocalVarDecl() && DVar
.CKind
== OMPC_private
) {
3631 Reason
= PDSA_LocalVarPrivate
;
3633 if (Reason
!= PDSA_Implicit
) {
3634 SemaRef
.Diag(ReportLoc
, diag::note_omp_predetermined_dsa
)
3635 << Reason
<< ReportHint
3636 << getOpenMPDirectiveName(Stack
->getCurrentDirective());
3637 } else if (DVar
.ImplicitDSALoc
.isValid()) {
3638 SemaRef
.Diag(DVar
.ImplicitDSALoc
, diag::note_omp_implicit_dsa
)
3639 << getOpenMPClauseName(DVar
.CKind
);
3643 static OpenMPMapClauseKind
3644 getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M
,
3645 bool IsAggregateOrDeclareTarget
) {
3646 OpenMPMapClauseKind Kind
= OMPC_MAP_unknown
;
3648 case OMPC_DEFAULTMAP_MODIFIER_alloc
:
3649 Kind
= OMPC_MAP_alloc
;
3651 case OMPC_DEFAULTMAP_MODIFIER_to
:
3654 case OMPC_DEFAULTMAP_MODIFIER_from
:
3655 Kind
= OMPC_MAP_from
;
3657 case OMPC_DEFAULTMAP_MODIFIER_tofrom
:
3658 Kind
= OMPC_MAP_tofrom
;
3660 case OMPC_DEFAULTMAP_MODIFIER_present
:
3661 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3662 // If implicit-behavior is present, each variable referenced in the
3663 // construct in the category specified by variable-category is treated as if
3664 // it had been listed in a map clause with the map-type of alloc and
3665 // map-type-modifier of present.
3666 Kind
= OMPC_MAP_alloc
;
3668 case OMPC_DEFAULTMAP_MODIFIER_firstprivate
:
3669 case OMPC_DEFAULTMAP_MODIFIER_last
:
3670 llvm_unreachable("Unexpected defaultmap implicit behavior");
3671 case OMPC_DEFAULTMAP_MODIFIER_none
:
3672 case OMPC_DEFAULTMAP_MODIFIER_default
:
3673 case OMPC_DEFAULTMAP_MODIFIER_unknown
:
3674 // IsAggregateOrDeclareTarget could be true if:
3675 // 1. the implicit behavior for aggregate is tofrom
3676 // 2. it's a declare target link
3677 if (IsAggregateOrDeclareTarget
) {
3678 Kind
= OMPC_MAP_tofrom
;
3681 llvm_unreachable("Unexpected defaultmap implicit behavior");
3683 assert(Kind
!= OMPC_MAP_unknown
&& "Expect map kind to be known");
3688 class DSAAttrChecker final
: public StmtVisitor
<DSAAttrChecker
, void> {
3691 bool ErrorFound
= false;
3692 bool TryCaptureCXXThisMembers
= false;
3693 CapturedStmt
*CS
= nullptr;
3694 const static unsigned DefaultmapKindNum
= OMPC_DEFAULTMAP_pointer
+ 1;
3695 llvm::SmallVector
<Expr
*, 4> ImplicitFirstprivate
;
3696 llvm::SmallVector
<Expr
*, 4> ImplicitPrivate
;
3697 llvm::SmallVector
<Expr
*, 4> ImplicitMap
[DefaultmapKindNum
][OMPC_MAP_delete
];
3698 llvm::SmallVector
<OpenMPMapModifierKind
, NumberOfOMPMapClauseModifiers
>
3699 ImplicitMapModifier
[DefaultmapKindNum
];
3700 Sema::VarsWithInheritedDSAType VarsWithInheritedDSA
;
3701 llvm::SmallDenseSet
<const ValueDecl
*, 4> ImplicitDeclarations
;
3703 void VisitSubCaptures(OMPExecutableDirective
*S
) {
3704 // Check implicitly captured variables.
3705 if (!S
->hasAssociatedStmt() || !S
->getAssociatedStmt())
3707 if (S
->getDirectiveKind() == OMPD_atomic
||
3708 S
->getDirectiveKind() == OMPD_critical
||
3709 S
->getDirectiveKind() == OMPD_section
||
3710 S
->getDirectiveKind() == OMPD_master
||
3711 S
->getDirectiveKind() == OMPD_masked
||
3712 S
->getDirectiveKind() == OMPD_scope
||
3713 isOpenMPLoopTransformationDirective(S
->getDirectiveKind())) {
3714 Visit(S
->getAssociatedStmt());
3717 visitSubCaptures(S
->getInnermostCapturedStmt());
3718 // Try to capture inner this->member references to generate correct mappings
3720 if (TryCaptureCXXThisMembers
||
3721 (isOpenMPTargetExecutionDirective(Stack
->getCurrentDirective()) &&
3722 llvm::any_of(S
->getInnermostCapturedStmt()->captures(),
3723 [](const CapturedStmt::Capture
&C
) {
3724 return C
.capturesThis();
3726 bool SavedTryCaptureCXXThisMembers
= TryCaptureCXXThisMembers
;
3727 TryCaptureCXXThisMembers
= true;
3728 Visit(S
->getInnermostCapturedStmt()->getCapturedStmt());
3729 TryCaptureCXXThisMembers
= SavedTryCaptureCXXThisMembers
;
3731 // In tasks firstprivates are not captured anymore, need to analyze them
3733 if (isOpenMPTaskingDirective(S
->getDirectiveKind()) &&
3734 !isOpenMPTaskLoopDirective(S
->getDirectiveKind())) {
3735 for (OMPClause
*C
: S
->clauses())
3736 if (auto *FC
= dyn_cast
<OMPFirstprivateClause
>(C
)) {
3737 for (Expr
*Ref
: FC
->varlists())
3744 void VisitDeclRefExpr(DeclRefExpr
*E
) {
3745 if (TryCaptureCXXThisMembers
|| E
->isTypeDependent() ||
3746 E
->isValueDependent() || E
->containsUnexpandedParameterPack() ||
3747 E
->isInstantiationDependent())
3749 if (auto *VD
= dyn_cast
<VarDecl
>(E
->getDecl())) {
3750 // Check the datasharing rules for the expressions in the clauses.
3751 if (!CS
|| (isa
<OMPCapturedExprDecl
>(VD
) && !CS
->capturesVariable(VD
) &&
3752 !Stack
->getTopDSA(VD
, /*FromParent=*/false).RefExpr
&&
3753 !Stack
->isImplicitDefaultFirstprivateFD(VD
))) {
3754 if (auto *CED
= dyn_cast
<OMPCapturedExprDecl
>(VD
))
3755 if (!CED
->hasAttr
<OMPCaptureNoInitAttr
>()) {
3756 Visit(CED
->getInit());
3759 } else if (VD
->isImplicit() || isa
<OMPCapturedExprDecl
>(VD
))
3760 // Do not analyze internal variables and do not enclose them into
3761 // implicit clauses.
3762 if (!Stack
->isImplicitDefaultFirstprivateFD(VD
))
3764 VD
= VD
->getCanonicalDecl();
3765 // Skip internally declared variables.
3766 if (VD
->hasLocalStorage() && CS
&& !CS
->capturesVariable(VD
) &&
3767 !Stack
->isImplicitDefaultFirstprivateFD(VD
) &&
3768 !Stack
->isImplicitTaskFirstprivate(VD
))
3770 // Skip allocators in uses_allocators clauses.
3771 if (Stack
->isUsesAllocatorsDecl(VD
))
3774 DSAStackTy::DSAVarData DVar
= Stack
->getTopDSA(VD
, /*FromParent=*/false);
3775 // Check if the variable has explicit DSA set and stop analysis if it so.
3776 if (DVar
.RefExpr
|| !ImplicitDeclarations
.insert(VD
).second
)
3779 // Skip internally declared static variables.
3780 std::optional
<OMPDeclareTargetDeclAttr::MapTypeTy
> Res
=
3781 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD
);
3782 if (VD
->hasGlobalStorage() && CS
&& !CS
->capturesVariable(VD
) &&
3783 (Stack
->hasRequiresDeclWithClause
<OMPUnifiedSharedMemoryClause
>() ||
3784 !Res
|| *Res
!= OMPDeclareTargetDeclAttr::MT_Link
) &&
3785 !Stack
->isImplicitDefaultFirstprivateFD(VD
) &&
3786 !Stack
->isImplicitTaskFirstprivate(VD
))
3789 SourceLocation ELoc
= E
->getExprLoc();
3790 OpenMPDirectiveKind DKind
= Stack
->getCurrentDirective();
3791 // The default(none) clause requires that each variable that is referenced
3792 // in the construct, and does not have a predetermined data-sharing
3793 // attribute, must have its data-sharing attribute explicitly determined
3794 // by being listed in a data-sharing attribute clause.
3795 if (DVar
.CKind
== OMPC_unknown
&&
3796 (Stack
->getDefaultDSA() == DSA_none
||
3797 Stack
->getDefaultDSA() == DSA_private
||
3798 Stack
->getDefaultDSA() == DSA_firstprivate
) &&
3799 isImplicitOrExplicitTaskingRegion(DKind
) &&
3800 VarsWithInheritedDSA
.count(VD
) == 0) {
3801 bool InheritedDSA
= Stack
->getDefaultDSA() == DSA_none
;
3802 if (!InheritedDSA
&& (Stack
->getDefaultDSA() == DSA_firstprivate
||
3803 Stack
->getDefaultDSA() == DSA_private
)) {
3804 DSAStackTy::DSAVarData DVar
=
3805 Stack
->getImplicitDSA(VD
, /*FromParent=*/false);
3806 InheritedDSA
= DVar
.CKind
== OMPC_unknown
;
3809 VarsWithInheritedDSA
[VD
] = E
;
3810 if (Stack
->getDefaultDSA() == DSA_none
)
3814 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
3815 // If implicit-behavior is none, each variable referenced in the
3816 // construct that does not have a predetermined data-sharing attribute
3817 // and does not appear in a to or link clause on a declare target
3818 // directive must be listed in a data-mapping attribute clause, a
3819 // data-sharing attribute clause (including a data-sharing attribute
3820 // clause on a combined construct where target. is one of the
3821 // constituent constructs), or an is_device_ptr clause.
3822 OpenMPDefaultmapClauseKind ClauseKind
=
3823 getVariableCategoryFromDecl(SemaRef
.getLangOpts(), VD
);
3824 if (SemaRef
.getLangOpts().OpenMP
>= 50) {
3825 bool IsModifierNone
= Stack
->getDefaultmapModifier(ClauseKind
) ==
3826 OMPC_DEFAULTMAP_MODIFIER_none
;
3827 if (DVar
.CKind
== OMPC_unknown
&& IsModifierNone
&&
3828 VarsWithInheritedDSA
.count(VD
) == 0 && !Res
) {
3829 // Only check for data-mapping attribute and is_device_ptr here
3830 // since we have already make sure that the declaration does not
3831 // have a data-sharing attribute above
3832 if (!Stack
->checkMappableExprComponentListsForDecl(
3833 VD
, /*CurrentRegionOnly=*/true,
3834 [VD
](OMPClauseMappableExprCommon::MappableExprComponentListRef
3837 auto MI
= MapExprComponents
.rbegin();
3838 auto ME
= MapExprComponents
.rend();
3839 return MI
!= ME
&& MI
->getAssociatedDeclaration() == VD
;
3841 VarsWithInheritedDSA
[VD
] = E
;
3846 if (SemaRef
.getLangOpts().OpenMP
> 50) {
3847 bool IsModifierPresent
= Stack
->getDefaultmapModifier(ClauseKind
) ==
3848 OMPC_DEFAULTMAP_MODIFIER_present
;
3849 if (IsModifierPresent
) {
3850 if (!llvm::is_contained(ImplicitMapModifier
[ClauseKind
],
3851 OMPC_MAP_MODIFIER_present
)) {
3852 ImplicitMapModifier
[ClauseKind
].push_back(
3853 OMPC_MAP_MODIFIER_present
);
3858 if (isOpenMPTargetExecutionDirective(DKind
) &&
3859 !Stack
->isLoopControlVariable(VD
).first
) {
3860 if (!Stack
->checkMappableExprComponentListsForDecl(
3861 VD
, /*CurrentRegionOnly=*/true,
3862 [this](OMPClauseMappableExprCommon::MappableExprComponentListRef
3865 if (SemaRef
.LangOpts
.OpenMP
>= 50)
3866 return !StackComponents
.empty();
3867 // Variable is used if it has been marked as an array, array
3868 // section, array shaping or the variable iself.
3869 return StackComponents
.size() == 1 ||
3871 llvm::drop_begin(llvm::reverse(StackComponents
)),
3872 [](const OMPClauseMappableExprCommon::
3873 MappableComponent
&MC
) {
3874 return MC
.getAssociatedDeclaration() ==
3876 (isa
<OMPArraySectionExpr
>(
3877 MC
.getAssociatedExpression()) ||
3878 isa
<OMPArrayShapingExpr
>(
3879 MC
.getAssociatedExpression()) ||
3880 isa
<ArraySubscriptExpr
>(
3881 MC
.getAssociatedExpression()));
3884 bool IsFirstprivate
= false;
3885 // By default lambdas are captured as firstprivates.
3886 if (const auto *RD
=
3887 VD
->getType().getNonReferenceType()->getAsCXXRecordDecl())
3888 IsFirstprivate
= RD
->isLambda();
3890 IsFirstprivate
|| (Stack
->mustBeFirstprivate(ClauseKind
) && !Res
);
3891 if (IsFirstprivate
) {
3892 ImplicitFirstprivate
.emplace_back(E
);
3894 OpenMPDefaultmapClauseModifier M
=
3895 Stack
->getDefaultmapModifier(ClauseKind
);
3896 OpenMPMapClauseKind Kind
= getMapClauseKindFromModifier(
3897 M
, ClauseKind
== OMPC_DEFAULTMAP_aggregate
|| Res
);
3898 ImplicitMap
[ClauseKind
][Kind
].emplace_back(E
);
3904 // OpenMP [2.9.3.6, Restrictions, p.2]
3905 // A list item that appears in a reduction clause of the innermost
3906 // enclosing worksharing or parallel construct may not be accessed in an
3908 DVar
= Stack
->hasInnermostDSA(
3910 [](OpenMPClauseKind C
, bool AppliedToPointee
) {
3911 return C
== OMPC_reduction
&& !AppliedToPointee
;
3913 [](OpenMPDirectiveKind K
) {
3914 return isOpenMPParallelDirective(K
) ||
3915 isOpenMPWorksharingDirective(K
) || isOpenMPTeamsDirective(K
);
3917 /*FromParent=*/true);
3918 if (isOpenMPTaskingDirective(DKind
) && DVar
.CKind
== OMPC_reduction
) {
3920 SemaRef
.Diag(ELoc
, diag::err_omp_reduction_in_task
);
3921 reportOriginalDsa(SemaRef
, Stack
, VD
, DVar
);
3925 // Define implicit data-sharing attributes for task.
3926 DVar
= Stack
->getImplicitDSA(VD
, /*FromParent=*/false);
3927 if (((isOpenMPTaskingDirective(DKind
) && DVar
.CKind
!= OMPC_shared
) ||
3928 (((Stack
->getDefaultDSA() == DSA_firstprivate
&&
3929 DVar
.CKind
== OMPC_firstprivate
) ||
3930 (Stack
->getDefaultDSA() == DSA_private
&&
3931 DVar
.CKind
== OMPC_private
)) &&
3933 !Stack
->isLoopControlVariable(VD
).first
) {
3934 if (Stack
->getDefaultDSA() == DSA_private
)
3935 ImplicitPrivate
.push_back(E
);
3937 ImplicitFirstprivate
.push_back(E
);
3941 // Store implicitly used globals with declare target link for parent
3943 if (!isOpenMPTargetExecutionDirective(DKind
) && Res
&&
3944 *Res
== OMPDeclareTargetDeclAttr::MT_Link
) {
3945 Stack
->addToParentTargetRegionLinkGlobals(E
);
3950 void VisitMemberExpr(MemberExpr
*E
) {
3951 if (E
->isTypeDependent() || E
->isValueDependent() ||
3952 E
->containsUnexpandedParameterPack() || E
->isInstantiationDependent())
3954 auto *FD
= dyn_cast
<FieldDecl
>(E
->getMemberDecl());
3955 OpenMPDirectiveKind DKind
= Stack
->getCurrentDirective();
3956 if (auto *TE
= dyn_cast
<CXXThisExpr
>(E
->getBase()->IgnoreParenCasts())) {
3959 DSAStackTy::DSAVarData DVar
= Stack
->getTopDSA(FD
, /*FromParent=*/false);
3960 // Check if the variable has explicit DSA set and stop analysis if it
3962 if (DVar
.RefExpr
|| !ImplicitDeclarations
.insert(FD
).second
)
3965 if (isOpenMPTargetExecutionDirective(DKind
) &&
3966 !Stack
->isLoopControlVariable(FD
).first
&&
3967 !Stack
->checkMappableExprComponentListsForDecl(
3968 FD
, /*CurrentRegionOnly=*/true,
3969 [](OMPClauseMappableExprCommon::MappableExprComponentListRef
3972 return isa
<CXXThisExpr
>(
3974 StackComponents
.back().getAssociatedExpression())
3978 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
3979 // A bit-field cannot appear in a map clause.
3981 if (FD
->isBitField())
3984 // Check to see if the member expression is referencing a class that
3985 // has already been explicitly mapped
3986 if (Stack
->isClassPreviouslyMapped(TE
->getType()))
3989 OpenMPDefaultmapClauseModifier Modifier
=
3990 Stack
->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate
);
3991 OpenMPDefaultmapClauseKind ClauseKind
=
3992 getVariableCategoryFromDecl(SemaRef
.getLangOpts(), FD
);
3993 OpenMPMapClauseKind Kind
= getMapClauseKindFromModifier(
3994 Modifier
, /*IsAggregateOrDeclareTarget*/ true);
3995 ImplicitMap
[ClauseKind
][Kind
].emplace_back(E
);
3999 SourceLocation ELoc
= E
->getExprLoc();
4000 // OpenMP [2.9.3.6, Restrictions, p.2]
4001 // A list item that appears in a reduction clause of the innermost
4002 // enclosing worksharing or parallel construct may not be accessed in
4003 // an explicit task.
4004 DVar
= Stack
->hasInnermostDSA(
4006 [](OpenMPClauseKind C
, bool AppliedToPointee
) {
4007 return C
== OMPC_reduction
&& !AppliedToPointee
;
4009 [](OpenMPDirectiveKind K
) {
4010 return isOpenMPParallelDirective(K
) ||
4011 isOpenMPWorksharingDirective(K
) || isOpenMPTeamsDirective(K
);
4013 /*FromParent=*/true);
4014 if (isOpenMPTaskingDirective(DKind
) && DVar
.CKind
== OMPC_reduction
) {
4016 SemaRef
.Diag(ELoc
, diag::err_omp_reduction_in_task
);
4017 reportOriginalDsa(SemaRef
, Stack
, FD
, DVar
);
4021 // Define implicit data-sharing attributes for task.
4022 DVar
= Stack
->getImplicitDSA(FD
, /*FromParent=*/false);
4023 if (isOpenMPTaskingDirective(DKind
) && DVar
.CKind
!= OMPC_shared
&&
4024 !Stack
->isLoopControlVariable(FD
).first
) {
4025 // Check if there is a captured expression for the current field in the
4026 // region. Do not mark it as firstprivate unless there is no captured
4028 // TODO: try to make it firstprivate.
4029 if (DVar
.CKind
!= OMPC_unknown
)
4030 ImplicitFirstprivate
.push_back(E
);
4034 if (isOpenMPTargetExecutionDirective(DKind
)) {
4035 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents
;
4036 if (!checkMapClauseExpressionBase(SemaRef
, E
, CurComponents
, OMPC_map
,
4037 Stack
->getCurrentDirective(),
4038 /*NoDiagnose=*/true))
4040 const auto *VD
= cast
<ValueDecl
>(
4041 CurComponents
.back().getAssociatedDeclaration()->getCanonicalDecl());
4042 if (!Stack
->checkMappableExprComponentListsForDecl(
4043 VD
, /*CurrentRegionOnly=*/true,
4045 OMPClauseMappableExprCommon::MappableExprComponentListRef
4048 auto CCI
= CurComponents
.rbegin();
4049 auto CCE
= CurComponents
.rend();
4050 for (const auto &SC
: llvm::reverse(StackComponents
)) {
4051 // Do both expressions have the same kind?
4052 if (CCI
->getAssociatedExpression()->getStmtClass() !=
4053 SC
.getAssociatedExpression()->getStmtClass())
4054 if (!((isa
<OMPArraySectionExpr
>(
4055 SC
.getAssociatedExpression()) ||
4056 isa
<OMPArrayShapingExpr
>(
4057 SC
.getAssociatedExpression())) &&
4058 isa
<ArraySubscriptExpr
>(
4059 CCI
->getAssociatedExpression())))
4062 const Decl
*CCD
= CCI
->getAssociatedDeclaration();
4063 const Decl
*SCD
= SC
.getAssociatedDeclaration();
4064 CCD
= CCD
? CCD
->getCanonicalDecl() : nullptr;
4065 SCD
= SCD
? SCD
->getCanonicalDecl() : nullptr;
4068 std::advance(CCI
, 1);
4074 Visit(E
->getBase());
4076 } else if (!TryCaptureCXXThisMembers
) {
4077 Visit(E
->getBase());
4080 void VisitOMPExecutableDirective(OMPExecutableDirective
*S
) {
4081 for (OMPClause
*C
: S
->clauses()) {
4082 // Skip analysis of arguments of private clauses for task|target
4084 if (isa_and_nonnull
<OMPPrivateClause
>(C
))
4086 // Skip analysis of arguments of implicitly defined firstprivate clause
4087 // for task|target directives.
4088 // Skip analysis of arguments of implicitly defined map clause for target
4090 if (C
&& !((isa
<OMPFirstprivateClause
>(C
) || isa
<OMPMapClause
>(C
)) &&
4092 !isOpenMPTaskingDirective(Stack
->getCurrentDirective()))) {
4093 for (Stmt
*CC
: C
->children()) {
4099 // Check implicitly captured variables.
4100 VisitSubCaptures(S
);
4103 void VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective
*S
) {
4104 // Loop transformation directives do not introduce data sharing
4108 void VisitCallExpr(CallExpr
*S
) {
4109 for (Stmt
*C
: S
->arguments()) {
4111 // Check implicitly captured variables in the task-based directives to
4112 // check if they must be firstprivatized.
4116 if (Expr
*Callee
= S
->getCallee()) {
4117 auto *CI
= Callee
->IgnoreParenImpCasts();
4118 if (auto *CE
= dyn_cast
<MemberExpr
>(CI
))
4119 Visit(CE
->getBase());
4120 else if (auto *CE
= dyn_cast
<DeclRefExpr
>(CI
))
4124 void VisitStmt(Stmt
*S
) {
4125 for (Stmt
*C
: S
->children()) {
4127 // Check implicitly captured variables in the task-based directives to
4128 // check if they must be firstprivatized.
4134 void visitSubCaptures(CapturedStmt
*S
) {
4135 for (const CapturedStmt::Capture
&Cap
: S
->captures()) {
4136 if (!Cap
.capturesVariable() && !Cap
.capturesVariableByCopy())
4138 VarDecl
*VD
= Cap
.getCapturedVar();
4139 // Do not try to map the variable if it or its sub-component was mapped
4141 if (isOpenMPTargetExecutionDirective(Stack
->getCurrentDirective()) &&
4142 Stack
->checkMappableExprComponentListsForDecl(
4143 VD
, /*CurrentRegionOnly=*/true,
4144 [](OMPClauseMappableExprCommon::MappableExprComponentListRef
,
4145 OpenMPClauseKind
) { return true; }))
4147 DeclRefExpr
*DRE
= buildDeclRefExpr(
4148 SemaRef
, VD
, VD
->getType().getNonLValueExprType(SemaRef
.Context
),
4149 Cap
.getLocation(), /*RefersToCapture=*/true);
4153 bool isErrorFound() const { return ErrorFound
; }
4154 ArrayRef
<Expr
*> getImplicitFirstprivate() const {
4155 return ImplicitFirstprivate
;
4157 ArrayRef
<Expr
*> getImplicitPrivate() const { return ImplicitPrivate
; }
4158 ArrayRef
<Expr
*> getImplicitMap(OpenMPDefaultmapClauseKind DK
,
4159 OpenMPMapClauseKind MK
) const {
4160 return ImplicitMap
[DK
][MK
];
4162 ArrayRef
<OpenMPMapModifierKind
>
4163 getImplicitMapModifier(OpenMPDefaultmapClauseKind Kind
) const {
4164 return ImplicitMapModifier
[Kind
];
4166 const Sema::VarsWithInheritedDSAType
&getVarsWithInheritedDSA() const {
4167 return VarsWithInheritedDSA
;
4170 DSAAttrChecker(DSAStackTy
*S
, Sema
&SemaRef
, CapturedStmt
*CS
)
4171 : Stack(S
), SemaRef(SemaRef
), ErrorFound(false), CS(CS
) {
4172 // Process declare target link variables for the target directives.
4173 if (isOpenMPTargetExecutionDirective(S
->getCurrentDirective())) {
4174 for (DeclRefExpr
*E
: Stack
->getLinkGlobals())
4181 static void handleDeclareVariantConstructTrait(DSAStackTy
*Stack
,
4182 OpenMPDirectiveKind DKind
,
4184 SmallVector
<llvm::omp::TraitProperty
, 8> Traits
;
4185 if (isOpenMPTargetExecutionDirective(DKind
))
4186 Traits
.emplace_back(llvm::omp::TraitProperty::construct_target_target
);
4187 if (isOpenMPTeamsDirective(DKind
))
4188 Traits
.emplace_back(llvm::omp::TraitProperty::construct_teams_teams
);
4189 if (isOpenMPParallelDirective(DKind
))
4190 Traits
.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel
);
4191 if (isOpenMPWorksharingDirective(DKind
))
4192 Traits
.emplace_back(llvm::omp::TraitProperty::construct_for_for
);
4193 if (isOpenMPSimdDirective(DKind
))
4194 Traits
.emplace_back(llvm::omp::TraitProperty::construct_simd_simd
);
4195 Stack
->handleConstructTrait(Traits
, ScopeEntry
);
4198 void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind
, Scope
*CurScope
) {
4201 case OMPD_parallel_for
:
4202 case OMPD_parallel_for_simd
:
4203 case OMPD_parallel_sections
:
4204 case OMPD_parallel_master
:
4205 case OMPD_parallel_masked
:
4206 case OMPD_parallel_loop
:
4208 case OMPD_teams_distribute
:
4209 case OMPD_teams_distribute_simd
: {
4210 QualType KmpInt32Ty
= Context
.getIntTypeForBitwidth(32, 1).withConst();
4211 QualType KmpInt32PtrTy
=
4212 Context
.getPointerType(KmpInt32Ty
).withConst().withRestrict();
4213 Sema::CapturedParamNameType Params
[] = {
4214 std::make_pair(".global_tid.", KmpInt32PtrTy
),
4215 std::make_pair(".bound_tid.", KmpInt32PtrTy
),
4216 std::make_pair(StringRef(), QualType()) // __context with shared vars
4218 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4222 case OMPD_target_teams
:
4223 case OMPD_target_parallel
:
4224 case OMPD_target_parallel_for
:
4225 case OMPD_target_parallel_for_simd
:
4226 case OMPD_target_parallel_loop
:
4227 case OMPD_target_teams_distribute
:
4228 case OMPD_target_teams_distribute_simd
: {
4229 QualType KmpInt32Ty
= Context
.getIntTypeForBitwidth(32, 1).withConst();
4230 QualType VoidPtrTy
= Context
.VoidPtrTy
.withConst().withRestrict();
4231 QualType KmpInt32PtrTy
=
4232 Context
.getPointerType(KmpInt32Ty
).withConst().withRestrict();
4233 QualType Args
[] = {VoidPtrTy
};
4234 FunctionProtoType::ExtProtoInfo EPI
;
4235 EPI
.Variadic
= true;
4236 QualType CopyFnType
= Context
.getFunctionType(Context
.VoidTy
, Args
, EPI
);
4237 Sema::CapturedParamNameType Params
[] = {
4238 std::make_pair(".global_tid.", KmpInt32Ty
),
4239 std::make_pair(".part_id.", KmpInt32PtrTy
),
4240 std::make_pair(".privates.", VoidPtrTy
),
4243 Context
.getPointerType(CopyFnType
).withConst().withRestrict()),
4244 std::make_pair(".task_t.", Context
.VoidPtrTy
.withConst()),
4245 std::make_pair(StringRef(), QualType()) // __context with shared vars
4247 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4248 Params
, /*OpenMPCaptureLevel=*/0);
4249 // Mark this captured region as inlined, because we don't use outlined
4250 // function directly.
4251 getCurCapturedRegion()->TheCapturedDecl
->addAttr(
4252 AlwaysInlineAttr::CreateImplicit(
4253 Context
, {}, AlwaysInlineAttr::Keyword_forceinline
));
4254 Sema::CapturedParamNameType ParamsTarget
[] = {
4255 std::make_pair(StringRef(), QualType()) // __context with shared vars
4257 // Start a captured region for 'target' with no implicit parameters.
4258 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4259 ParamsTarget
, /*OpenMPCaptureLevel=*/1);
4260 Sema::CapturedParamNameType ParamsTeamsOrParallel
[] = {
4261 std::make_pair(".global_tid.", KmpInt32PtrTy
),
4262 std::make_pair(".bound_tid.", KmpInt32PtrTy
),
4263 std::make_pair(StringRef(), QualType()) // __context with shared vars
4265 // Start a captured region for 'teams' or 'parallel'. Both regions have
4266 // the same implicit parameters.
4267 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4268 ParamsTeamsOrParallel
, /*OpenMPCaptureLevel=*/2);
4272 case OMPD_target_simd
: {
4273 QualType KmpInt32Ty
= Context
.getIntTypeForBitwidth(32, 1).withConst();
4274 QualType VoidPtrTy
= Context
.VoidPtrTy
.withConst().withRestrict();
4275 QualType KmpInt32PtrTy
=
4276 Context
.getPointerType(KmpInt32Ty
).withConst().withRestrict();
4277 QualType Args
[] = {VoidPtrTy
};
4278 FunctionProtoType::ExtProtoInfo EPI
;
4279 EPI
.Variadic
= true;
4280 QualType CopyFnType
= Context
.getFunctionType(Context
.VoidTy
, Args
, EPI
);
4281 Sema::CapturedParamNameType Params
[] = {
4282 std::make_pair(".global_tid.", KmpInt32Ty
),
4283 std::make_pair(".part_id.", KmpInt32PtrTy
),
4284 std::make_pair(".privates.", VoidPtrTy
),
4287 Context
.getPointerType(CopyFnType
).withConst().withRestrict()),
4288 std::make_pair(".task_t.", Context
.VoidPtrTy
.withConst()),
4289 std::make_pair(StringRef(), QualType()) // __context with shared vars
4291 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4292 Params
, /*OpenMPCaptureLevel=*/0);
4293 // Mark this captured region as inlined, because we don't use outlined
4294 // function directly.
4295 getCurCapturedRegion()->TheCapturedDecl
->addAttr(
4296 AlwaysInlineAttr::CreateImplicit(
4297 Context
, {}, AlwaysInlineAttr::Keyword_forceinline
));
4298 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4299 std::make_pair(StringRef(), QualType()),
4300 /*OpenMPCaptureLevel=*/1);
4312 // TODO: 'loop' may require additional parameters depending on the binding.
4313 // Treat similar to OMPD_simd/OMPD_for for now.
4319 case OMPD_taskgroup
:
4320 case OMPD_distribute
:
4321 case OMPD_distribute_simd
:
4324 case OMPD_target_data
:
4325 case OMPD_dispatch
: {
4326 Sema::CapturedParamNameType Params
[] = {
4327 std::make_pair(StringRef(), QualType()) // __context with shared vars
4329 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4334 QualType KmpInt32Ty
= Context
.getIntTypeForBitwidth(32, 1).withConst();
4335 QualType VoidPtrTy
= Context
.VoidPtrTy
.withConst().withRestrict();
4336 QualType KmpInt32PtrTy
=
4337 Context
.getPointerType(KmpInt32Ty
).withConst().withRestrict();
4338 QualType Args
[] = {VoidPtrTy
};
4339 FunctionProtoType::ExtProtoInfo EPI
;
4340 EPI
.Variadic
= true;
4341 QualType CopyFnType
= Context
.getFunctionType(Context
.VoidTy
, Args
, EPI
);
4342 Sema::CapturedParamNameType Params
[] = {
4343 std::make_pair(".global_tid.", KmpInt32Ty
),
4344 std::make_pair(".part_id.", KmpInt32PtrTy
),
4345 std::make_pair(".privates.", VoidPtrTy
),
4348 Context
.getPointerType(CopyFnType
).withConst().withRestrict()),
4349 std::make_pair(".task_t.", Context
.VoidPtrTy
.withConst()),
4350 std::make_pair(StringRef(), QualType()) // __context with shared vars
4352 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4354 // Mark this captured region as inlined, because we don't use outlined
4355 // function directly.
4356 getCurCapturedRegion()->TheCapturedDecl
->addAttr(
4357 AlwaysInlineAttr::CreateImplicit(
4358 Context
, {}, AlwaysInlineAttr::Keyword_forceinline
));
4362 case OMPD_taskloop_simd
:
4363 case OMPD_master_taskloop
:
4364 case OMPD_masked_taskloop
:
4365 case OMPD_masked_taskloop_simd
:
4366 case OMPD_master_taskloop_simd
: {
4367 QualType KmpInt32Ty
=
4368 Context
.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
4370 QualType KmpUInt64Ty
=
4371 Context
.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
4373 QualType KmpInt64Ty
=
4374 Context
.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
4376 QualType VoidPtrTy
= Context
.VoidPtrTy
.withConst().withRestrict();
4377 QualType KmpInt32PtrTy
=
4378 Context
.getPointerType(KmpInt32Ty
).withConst().withRestrict();
4379 QualType Args
[] = {VoidPtrTy
};
4380 FunctionProtoType::ExtProtoInfo EPI
;
4381 EPI
.Variadic
= true;
4382 QualType CopyFnType
= Context
.getFunctionType(Context
.VoidTy
, Args
, EPI
);
4383 Sema::CapturedParamNameType Params
[] = {
4384 std::make_pair(".global_tid.", KmpInt32Ty
),
4385 std::make_pair(".part_id.", KmpInt32PtrTy
),
4386 std::make_pair(".privates.", VoidPtrTy
),
4389 Context
.getPointerType(CopyFnType
).withConst().withRestrict()),
4390 std::make_pair(".task_t.", Context
.VoidPtrTy
.withConst()),
4391 std::make_pair(".lb.", KmpUInt64Ty
),
4392 std::make_pair(".ub.", KmpUInt64Ty
),
4393 std::make_pair(".st.", KmpInt64Ty
),
4394 std::make_pair(".liter.", KmpInt32Ty
),
4395 std::make_pair(".reductions.", VoidPtrTy
),
4396 std::make_pair(StringRef(), QualType()) // __context with shared vars
4398 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4400 // Mark this captured region as inlined, because we don't use outlined
4401 // function directly.
4402 getCurCapturedRegion()->TheCapturedDecl
->addAttr(
4403 AlwaysInlineAttr::CreateImplicit(
4404 Context
, {}, AlwaysInlineAttr::Keyword_forceinline
));
4407 case OMPD_parallel_masked_taskloop
:
4408 case OMPD_parallel_masked_taskloop_simd
:
4409 case OMPD_parallel_master_taskloop
:
4410 case OMPD_parallel_master_taskloop_simd
: {
4411 QualType KmpInt32Ty
=
4412 Context
.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
4414 QualType KmpUInt64Ty
=
4415 Context
.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
4417 QualType KmpInt64Ty
=
4418 Context
.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
4420 QualType VoidPtrTy
= Context
.VoidPtrTy
.withConst().withRestrict();
4421 QualType KmpInt32PtrTy
=
4422 Context
.getPointerType(KmpInt32Ty
).withConst().withRestrict();
4423 Sema::CapturedParamNameType ParamsParallel
[] = {
4424 std::make_pair(".global_tid.", KmpInt32PtrTy
),
4425 std::make_pair(".bound_tid.", KmpInt32PtrTy
),
4426 std::make_pair(StringRef(), QualType()) // __context with shared vars
4428 // Start a captured region for 'parallel'.
4429 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4430 ParamsParallel
, /*OpenMPCaptureLevel=*/0);
4431 QualType Args
[] = {VoidPtrTy
};
4432 FunctionProtoType::ExtProtoInfo EPI
;
4433 EPI
.Variadic
= true;
4434 QualType CopyFnType
= Context
.getFunctionType(Context
.VoidTy
, Args
, EPI
);
4435 Sema::CapturedParamNameType Params
[] = {
4436 std::make_pair(".global_tid.", KmpInt32Ty
),
4437 std::make_pair(".part_id.", KmpInt32PtrTy
),
4438 std::make_pair(".privates.", VoidPtrTy
),
4441 Context
.getPointerType(CopyFnType
).withConst().withRestrict()),
4442 std::make_pair(".task_t.", Context
.VoidPtrTy
.withConst()),
4443 std::make_pair(".lb.", KmpUInt64Ty
),
4444 std::make_pair(".ub.", KmpUInt64Ty
),
4445 std::make_pair(".st.", KmpInt64Ty
),
4446 std::make_pair(".liter.", KmpInt32Ty
),
4447 std::make_pair(".reductions.", VoidPtrTy
),
4448 std::make_pair(StringRef(), QualType()) // __context with shared vars
4450 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4451 Params
, /*OpenMPCaptureLevel=*/1);
4452 // Mark this captured region as inlined, because we don't use outlined
4453 // function directly.
4454 getCurCapturedRegion()->TheCapturedDecl
->addAttr(
4455 AlwaysInlineAttr::CreateImplicit(
4456 Context
, {}, AlwaysInlineAttr::Keyword_forceinline
));
4459 case OMPD_distribute_parallel_for_simd
:
4460 case OMPD_distribute_parallel_for
: {
4461 QualType KmpInt32Ty
= Context
.getIntTypeForBitwidth(32, 1).withConst();
4462 QualType KmpInt32PtrTy
=
4463 Context
.getPointerType(KmpInt32Ty
).withConst().withRestrict();
4464 Sema::CapturedParamNameType Params
[] = {
4465 std::make_pair(".global_tid.", KmpInt32PtrTy
),
4466 std::make_pair(".bound_tid.", KmpInt32PtrTy
),
4467 std::make_pair(".previous.lb.", Context
.getSizeType().withConst()),
4468 std::make_pair(".previous.ub.", Context
.getSizeType().withConst()),
4469 std::make_pair(StringRef(), QualType()) // __context with shared vars
4471 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4475 case OMPD_target_teams_loop
:
4476 case OMPD_target_teams_distribute_parallel_for
:
4477 case OMPD_target_teams_distribute_parallel_for_simd
: {
4478 QualType KmpInt32Ty
= Context
.getIntTypeForBitwidth(32, 1).withConst();
4479 QualType KmpInt32PtrTy
=
4480 Context
.getPointerType(KmpInt32Ty
).withConst().withRestrict();
4481 QualType VoidPtrTy
= Context
.VoidPtrTy
.withConst().withRestrict();
4483 QualType Args
[] = {VoidPtrTy
};
4484 FunctionProtoType::ExtProtoInfo EPI
;
4485 EPI
.Variadic
= true;
4486 QualType CopyFnType
= Context
.getFunctionType(Context
.VoidTy
, Args
, EPI
);
4487 Sema::CapturedParamNameType Params
[] = {
4488 std::make_pair(".global_tid.", KmpInt32Ty
),
4489 std::make_pair(".part_id.", KmpInt32PtrTy
),
4490 std::make_pair(".privates.", VoidPtrTy
),
4493 Context
.getPointerType(CopyFnType
).withConst().withRestrict()),
4494 std::make_pair(".task_t.", Context
.VoidPtrTy
.withConst()),
4495 std::make_pair(StringRef(), QualType()) // __context with shared vars
4497 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4498 Params
, /*OpenMPCaptureLevel=*/0);
4499 // Mark this captured region as inlined, because we don't use outlined
4500 // function directly.
4501 getCurCapturedRegion()->TheCapturedDecl
->addAttr(
4502 AlwaysInlineAttr::CreateImplicit(
4503 Context
, {}, AlwaysInlineAttr::Keyword_forceinline
));
4504 Sema::CapturedParamNameType ParamsTarget
[] = {
4505 std::make_pair(StringRef(), QualType()) // __context with shared vars
4507 // Start a captured region for 'target' with no implicit parameters.
4508 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4509 ParamsTarget
, /*OpenMPCaptureLevel=*/1);
4511 Sema::CapturedParamNameType ParamsTeams
[] = {
4512 std::make_pair(".global_tid.", KmpInt32PtrTy
),
4513 std::make_pair(".bound_tid.", KmpInt32PtrTy
),
4514 std::make_pair(StringRef(), QualType()) // __context with shared vars
4516 // Start a captured region for 'target' with no implicit parameters.
4517 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4518 ParamsTeams
, /*OpenMPCaptureLevel=*/2);
4520 Sema::CapturedParamNameType ParamsParallel
[] = {
4521 std::make_pair(".global_tid.", KmpInt32PtrTy
),
4522 std::make_pair(".bound_tid.", KmpInt32PtrTy
),
4523 std::make_pair(".previous.lb.", Context
.getSizeType().withConst()),
4524 std::make_pair(".previous.ub.", Context
.getSizeType().withConst()),
4525 std::make_pair(StringRef(), QualType()) // __context with shared vars
4527 // Start a captured region for 'teams' or 'parallel'. Both regions have
4528 // the same implicit parameters.
4529 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4530 ParamsParallel
, /*OpenMPCaptureLevel=*/3);
4534 case OMPD_teams_loop
:
4535 case OMPD_teams_distribute_parallel_for
:
4536 case OMPD_teams_distribute_parallel_for_simd
: {
4537 QualType KmpInt32Ty
= Context
.getIntTypeForBitwidth(32, 1).withConst();
4538 QualType KmpInt32PtrTy
=
4539 Context
.getPointerType(KmpInt32Ty
).withConst().withRestrict();
4541 Sema::CapturedParamNameType ParamsTeams
[] = {
4542 std::make_pair(".global_tid.", KmpInt32PtrTy
),
4543 std::make_pair(".bound_tid.", KmpInt32PtrTy
),
4544 std::make_pair(StringRef(), QualType()) // __context with shared vars
4546 // Start a captured region for 'target' with no implicit parameters.
4547 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4548 ParamsTeams
, /*OpenMPCaptureLevel=*/0);
4550 Sema::CapturedParamNameType ParamsParallel
[] = {
4551 std::make_pair(".global_tid.", KmpInt32PtrTy
),
4552 std::make_pair(".bound_tid.", KmpInt32PtrTy
),
4553 std::make_pair(".previous.lb.", Context
.getSizeType().withConst()),
4554 std::make_pair(".previous.ub.", Context
.getSizeType().withConst()),
4555 std::make_pair(StringRef(), QualType()) // __context with shared vars
4557 // Start a captured region for 'teams' or 'parallel'. Both regions have
4558 // the same implicit parameters.
4559 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4560 ParamsParallel
, /*OpenMPCaptureLevel=*/1);
4563 case OMPD_target_update
:
4564 case OMPD_target_enter_data
:
4565 case OMPD_target_exit_data
: {
4566 QualType KmpInt32Ty
= Context
.getIntTypeForBitwidth(32, 1).withConst();
4567 QualType VoidPtrTy
= Context
.VoidPtrTy
.withConst().withRestrict();
4568 QualType KmpInt32PtrTy
=
4569 Context
.getPointerType(KmpInt32Ty
).withConst().withRestrict();
4570 QualType Args
[] = {VoidPtrTy
};
4571 FunctionProtoType::ExtProtoInfo EPI
;
4572 EPI
.Variadic
= true;
4573 QualType CopyFnType
= Context
.getFunctionType(Context
.VoidTy
, Args
, EPI
);
4574 Sema::CapturedParamNameType Params
[] = {
4575 std::make_pair(".global_tid.", KmpInt32Ty
),
4576 std::make_pair(".part_id.", KmpInt32PtrTy
),
4577 std::make_pair(".privates.", VoidPtrTy
),
4580 Context
.getPointerType(CopyFnType
).withConst().withRestrict()),
4581 std::make_pair(".task_t.", Context
.VoidPtrTy
.withConst()),
4582 std::make_pair(StringRef(), QualType()) // __context with shared vars
4584 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4586 // Mark this captured region as inlined, because we don't use outlined
4587 // function directly.
4588 getCurCapturedRegion()->TheCapturedDecl
->addAttr(
4589 AlwaysInlineAttr::CreateImplicit(
4590 Context
, {}, AlwaysInlineAttr::Keyword_forceinline
));
4593 case OMPD_threadprivate
:
4595 case OMPD_taskyield
:
4599 case OMPD_cancellation_point
:
4604 case OMPD_declare_reduction
:
4605 case OMPD_declare_mapper
:
4606 case OMPD_declare_simd
:
4607 case OMPD_declare_target
:
4608 case OMPD_end_declare_target
:
4610 case OMPD_declare_variant
:
4611 case OMPD_begin_declare_variant
:
4612 case OMPD_end_declare_variant
:
4613 case OMPD_metadirective
:
4614 llvm_unreachable("OpenMP Directive is not allowed");
4617 llvm_unreachable("Unknown OpenMP directive");
4619 DSAStack
->setContext(CurContext
);
4620 handleDeclareVariantConstructTrait(DSAStack
, DKind
, /* ScopeEntry */ true);
4623 int Sema::getNumberOfConstructScopes(unsigned Level
) const {
4624 return getOpenMPCaptureLevels(DSAStack
->getDirective(Level
));
4627 int Sema::getOpenMPCaptureLevels(OpenMPDirectiveKind DKind
) {
4628 SmallVector
<OpenMPDirectiveKind
, 4> CaptureRegions
;
4629 getOpenMPCaptureRegions(CaptureRegions
, DKind
);
4630 return CaptureRegions
.size();
4633 static OMPCapturedExprDecl
*buildCaptureDecl(Sema
&S
, IdentifierInfo
*Id
,
4634 Expr
*CaptureExpr
, bool WithInit
,
4635 DeclContext
*CurContext
,
4636 bool AsExpression
) {
4637 assert(CaptureExpr
);
4638 ASTContext
&C
= S
.getASTContext();
4639 Expr
*Init
= AsExpression
? CaptureExpr
: CaptureExpr
->IgnoreImpCasts();
4640 QualType Ty
= Init
->getType();
4641 if (CaptureExpr
->getObjectKind() == OK_Ordinary
&& CaptureExpr
->isGLValue()) {
4642 if (S
.getLangOpts().CPlusPlus
) {
4643 Ty
= C
.getLValueReferenceType(Ty
);
4645 Ty
= C
.getPointerType(Ty
);
4647 S
.CreateBuiltinUnaryOp(CaptureExpr
->getExprLoc(), UO_AddrOf
, Init
);
4648 if (!Res
.isUsable())
4654 auto *CED
= OMPCapturedExprDecl::Create(C
, CurContext
, Id
, Ty
,
4655 CaptureExpr
->getBeginLoc());
4657 CED
->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C
));
4658 CurContext
->addHiddenDecl(CED
);
4659 Sema::TentativeAnalysisScope
Trap(S
);
4660 S
.AddInitializerToDecl(CED
, Init
, /*DirectInit=*/false);
4664 static DeclRefExpr
*buildCapture(Sema
&S
, ValueDecl
*D
, Expr
*CaptureExpr
,
4666 OMPCapturedExprDecl
*CD
;
4667 if (VarDecl
*VD
= S
.isOpenMPCapturedDecl(D
))
4668 CD
= cast
<OMPCapturedExprDecl
>(VD
);
4670 CD
= buildCaptureDecl(S
, D
->getIdentifier(), CaptureExpr
, WithInit
,
4672 /*AsExpression=*/false);
4673 return buildDeclRefExpr(S
, CD
, CD
->getType().getNonReferenceType(),
4674 CaptureExpr
->getExprLoc());
4677 static ExprResult
buildCapture(Sema
&S
, Expr
*CaptureExpr
, DeclRefExpr
*&Ref
,
4679 CaptureExpr
= S
.DefaultLvalueConversion(CaptureExpr
).get();
4681 OMPCapturedExprDecl
*CD
= buildCaptureDecl(
4682 S
, &S
.getASTContext().Idents
.get(Name
), CaptureExpr
,
4683 /*WithInit=*/true, S
.CurContext
, /*AsExpression=*/true);
4684 Ref
= buildDeclRefExpr(S
, CD
, CD
->getType().getNonReferenceType(),
4685 CaptureExpr
->getExprLoc());
4687 ExprResult Res
= Ref
;
4688 if (!S
.getLangOpts().CPlusPlus
&&
4689 CaptureExpr
->getObjectKind() == OK_Ordinary
&& CaptureExpr
->isGLValue() &&
4690 Ref
->getType()->isPointerType()) {
4691 Res
= S
.CreateBuiltinUnaryOp(CaptureExpr
->getExprLoc(), UO_Deref
, Ref
);
4692 if (!Res
.isUsable())
4695 return S
.DefaultLvalueConversion(Res
.get());
4699 // OpenMP directives parsed in this section are represented as a
4700 // CapturedStatement with an associated statement. If a syntax error
4701 // is detected during the parsing of the associated statement, the
4702 // compiler must abort processing and close the CapturedStatement.
4704 // Combined directives such as 'target parallel' have more than one
4705 // nested CapturedStatements. This RAII ensures that we unwind out
4706 // of all the nested CapturedStatements when an error is found.
4707 class CaptureRegionUnwinderRAII
{
4711 OpenMPDirectiveKind DKind
= OMPD_unknown
;
4714 CaptureRegionUnwinderRAII(Sema
&S
, bool &ErrorFound
,
4715 OpenMPDirectiveKind DKind
)
4716 : S(S
), ErrorFound(ErrorFound
), DKind(DKind
) {}
4717 ~CaptureRegionUnwinderRAII() {
4719 int ThisCaptureLevel
= S
.getOpenMPCaptureLevels(DKind
);
4720 while (--ThisCaptureLevel
>= 0)
4721 S
.ActOnCapturedRegionError();
4727 void Sema::tryCaptureOpenMPLambdas(ValueDecl
*V
) {
4728 // Capture variables captured by reference in lambdas for target-based
4730 if (!CurContext
->isDependentContext() &&
4731 (isOpenMPTargetExecutionDirective(DSAStack
->getCurrentDirective()) ||
4732 isOpenMPTargetDataManagementDirective(
4733 DSAStack
->getCurrentDirective()))) {
4734 QualType Type
= V
->getType();
4735 if (const auto *RD
= Type
.getCanonicalType()
4736 .getNonReferenceType()
4737 ->getAsCXXRecordDecl()) {
4738 bool SavedForceCaptureByReferenceInTargetExecutable
=
4739 DSAStack
->isForceCaptureByReferenceInTargetExecutable();
4740 DSAStack
->setForceCaptureByReferenceInTargetExecutable(
4742 if (RD
->isLambda()) {
4743 llvm::DenseMap
<const ValueDecl
*, FieldDecl
*> Captures
;
4744 FieldDecl
*ThisCapture
;
4745 RD
->getCaptureFields(Captures
, ThisCapture
);
4746 for (const LambdaCapture
&LC
: RD
->captures()) {
4747 if (LC
.getCaptureKind() == LCK_ByRef
) {
4748 VarDecl
*VD
= cast
<VarDecl
>(LC
.getCapturedVar());
4749 DeclContext
*VDC
= VD
->getDeclContext();
4750 if (!VDC
->Encloses(CurContext
))
4752 MarkVariableReferenced(LC
.getLocation(), VD
);
4753 } else if (LC
.getCaptureKind() == LCK_This
) {
4754 QualType ThisTy
= getCurrentThisType();
4755 if (!ThisTy
.isNull() &&
4756 Context
.typesAreCompatible(ThisTy
, ThisCapture
->getType()))
4757 CheckCXXThisCapture(LC
.getLocation());
4761 DSAStack
->setForceCaptureByReferenceInTargetExecutable(
4762 SavedForceCaptureByReferenceInTargetExecutable
);
4767 static bool checkOrderedOrderSpecified(Sema
&S
,
4768 const ArrayRef
<OMPClause
*> Clauses
) {
4769 const OMPOrderedClause
*Ordered
= nullptr;
4770 const OMPOrderClause
*Order
= nullptr;
4772 for (const OMPClause
*Clause
: Clauses
) {
4773 if (Clause
->getClauseKind() == OMPC_ordered
)
4774 Ordered
= cast
<OMPOrderedClause
>(Clause
);
4775 else if (Clause
->getClauseKind() == OMPC_order
) {
4776 Order
= cast
<OMPOrderClause
>(Clause
);
4777 if (Order
->getKind() != OMPC_ORDER_concurrent
)
4780 if (Ordered
&& Order
)
4784 if (Ordered
&& Order
) {
4785 S
.Diag(Order
->getKindKwLoc(),
4786 diag::err_omp_simple_clause_incompatible_with_ordered
)
4787 << getOpenMPClauseName(OMPC_order
)
4788 << getOpenMPSimpleClauseTypeName(OMPC_order
, OMPC_ORDER_concurrent
)
4789 << SourceRange(Order
->getBeginLoc(), Order
->getEndLoc());
4790 S
.Diag(Ordered
->getBeginLoc(), diag::note_omp_ordered_param
)
4791 << 0 << SourceRange(Ordered
->getBeginLoc(), Ordered
->getEndLoc());
4797 StmtResult
Sema::ActOnOpenMPRegionEnd(StmtResult S
,
4798 ArrayRef
<OMPClause
*> Clauses
) {
4799 handleDeclareVariantConstructTrait(DSAStack
, DSAStack
->getCurrentDirective(),
4800 /* ScopeEntry */ false);
4801 if (DSAStack
->getCurrentDirective() == OMPD_atomic
||
4802 DSAStack
->getCurrentDirective() == OMPD_critical
||
4803 DSAStack
->getCurrentDirective() == OMPD_section
||
4804 DSAStack
->getCurrentDirective() == OMPD_master
||
4805 DSAStack
->getCurrentDirective() == OMPD_masked
)
4808 bool ErrorFound
= false;
4809 CaptureRegionUnwinderRAII
CaptureRegionUnwinder(
4810 *this, ErrorFound
, DSAStack
->getCurrentDirective());
4811 if (!S
.isUsable()) {
4816 SmallVector
<OpenMPDirectiveKind
, 4> CaptureRegions
;
4817 getOpenMPCaptureRegions(CaptureRegions
, DSAStack
->getCurrentDirective());
4818 OMPOrderedClause
*OC
= nullptr;
4819 OMPScheduleClause
*SC
= nullptr;
4820 SmallVector
<const OMPLinearClause
*, 4> LCs
;
4821 SmallVector
<const OMPClauseWithPreInit
*, 4> PICs
;
4822 // This is required for proper codegen.
4823 for (OMPClause
*Clause
: Clauses
) {
4824 if (!LangOpts
.OpenMPSimd
&&
4825 (isOpenMPTaskingDirective(DSAStack
->getCurrentDirective()) ||
4826 DSAStack
->getCurrentDirective() == OMPD_target
) &&
4827 Clause
->getClauseKind() == OMPC_in_reduction
) {
4828 // Capture taskgroup task_reduction descriptors inside the tasking regions
4829 // with the corresponding in_reduction items.
4830 auto *IRC
= cast
<OMPInReductionClause
>(Clause
);
4831 for (Expr
*E
: IRC
->taskgroup_descriptors())
4833 MarkDeclarationsReferencedInExpr(E
);
4835 if (isOpenMPPrivate(Clause
->getClauseKind()) ||
4836 Clause
->getClauseKind() == OMPC_copyprivate
||
4837 (getLangOpts().OpenMPUseTLS
&&
4838 getASTContext().getTargetInfo().isTLSSupported() &&
4839 Clause
->getClauseKind() == OMPC_copyin
)) {
4840 DSAStack
->setForceVarCapturing(Clause
->getClauseKind() == OMPC_copyin
);
4841 // Mark all variables in private list clauses as used in inner region.
4842 for (Stmt
*VarRef
: Clause
->children()) {
4843 if (auto *E
= cast_or_null
<Expr
>(VarRef
)) {
4844 MarkDeclarationsReferencedInExpr(E
);
4847 DSAStack
->setForceVarCapturing(/*V=*/false);
4848 } else if (isOpenMPLoopTransformationDirective(
4849 DSAStack
->getCurrentDirective())) {
4850 assert(CaptureRegions
.empty() &&
4851 "No captured regions in loop transformation directives.");
4852 } else if (CaptureRegions
.size() > 1 ||
4853 CaptureRegions
.back() != OMPD_unknown
) {
4854 if (auto *C
= OMPClauseWithPreInit::get(Clause
))
4856 if (auto *C
= OMPClauseWithPostUpdate::get(Clause
)) {
4857 if (Expr
*E
= C
->getPostUpdateExpr())
4858 MarkDeclarationsReferencedInExpr(E
);
4861 if (Clause
->getClauseKind() == OMPC_schedule
)
4862 SC
= cast
<OMPScheduleClause
>(Clause
);
4863 else if (Clause
->getClauseKind() == OMPC_ordered
)
4864 OC
= cast
<OMPOrderedClause
>(Clause
);
4865 else if (Clause
->getClauseKind() == OMPC_linear
)
4866 LCs
.push_back(cast
<OMPLinearClause
>(Clause
));
4868 // Capture allocator expressions if used.
4869 for (Expr
*E
: DSAStack
->getInnerAllocators())
4870 MarkDeclarationsReferencedInExpr(E
);
4871 // OpenMP, 2.7.1 Loop Construct, Restrictions
4872 // The nonmonotonic modifier cannot be specified if an ordered clause is
4875 (SC
->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
||
4876 SC
->getSecondScheduleModifier() ==
4877 OMPC_SCHEDULE_MODIFIER_nonmonotonic
) &&
4879 Diag(SC
->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4880 ? SC
->getFirstScheduleModifierLoc()
4881 : SC
->getSecondScheduleModifierLoc(),
4882 diag::err_omp_simple_clause_incompatible_with_ordered
)
4883 << getOpenMPClauseName(OMPC_schedule
)
4884 << getOpenMPSimpleClauseTypeName(OMPC_schedule
,
4885 OMPC_SCHEDULE_MODIFIER_nonmonotonic
)
4886 << SourceRange(OC
->getBeginLoc(), OC
->getEndLoc());
4889 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4890 // If an order(concurrent) clause is present, an ordered clause may not appear
4891 // on the same directive.
4892 if (checkOrderedOrderSpecified(*this, Clauses
))
4894 if (!LCs
.empty() && OC
&& OC
->getNumForLoops()) {
4895 for (const OMPLinearClause
*C
: LCs
) {
4896 Diag(C
->getBeginLoc(), diag::err_omp_linear_ordered
)
4897 << SourceRange(OC
->getBeginLoc(), OC
->getEndLoc());
4901 if (isOpenMPWorksharingDirective(DSAStack
->getCurrentDirective()) &&
4902 isOpenMPSimdDirective(DSAStack
->getCurrentDirective()) && OC
&&
4903 OC
->getNumForLoops()) {
4904 Diag(OC
->getBeginLoc(), diag::err_omp_ordered_simd
)
4905 << getOpenMPDirectiveName(DSAStack
->getCurrentDirective());
4912 unsigned CompletedRegions
= 0;
4913 for (OpenMPDirectiveKind ThisCaptureRegion
: llvm::reverse(CaptureRegions
)) {
4914 // Mark all variables in private list clauses as used in inner region.
4915 // Required for proper codegen of combined directives.
4916 // TODO: add processing for other clauses.
4917 if (ThisCaptureRegion
!= OMPD_unknown
) {
4918 for (const clang::OMPClauseWithPreInit
*C
: PICs
) {
4919 OpenMPDirectiveKind CaptureRegion
= C
->getCaptureRegion();
4920 // Find the particular capture region for the clause if the
4921 // directive is a combined one with multiple capture regions.
4922 // If the directive is not a combined one, the capture region
4923 // associated with the clause is OMPD_unknown and is generated
4925 if (CaptureRegion
== ThisCaptureRegion
||
4926 CaptureRegion
== OMPD_unknown
) {
4927 if (auto *DS
= cast_or_null
<DeclStmt
>(C
->getPreInitStmt())) {
4928 for (Decl
*D
: DS
->decls())
4929 MarkVariableReferenced(D
->getLocation(), cast
<VarDecl
>(D
));
4934 if (ThisCaptureRegion
== OMPD_target
) {
4935 // Capture allocator traits in the target region. They are used implicitly
4936 // and, thus, are not captured by default.
4937 for (OMPClause
*C
: Clauses
) {
4938 if (const auto *UAC
= dyn_cast
<OMPUsesAllocatorsClause
>(C
)) {
4939 for (unsigned I
= 0, End
= UAC
->getNumberOfAllocators(); I
< End
;
4941 OMPUsesAllocatorsClause::Data D
= UAC
->getAllocatorData(I
);
4942 if (Expr
*E
= D
.AllocatorTraits
)
4943 MarkDeclarationsReferencedInExpr(E
);
4949 if (ThisCaptureRegion
== OMPD_parallel
) {
4950 // Capture temp arrays for inscan reductions and locals in aligned
4952 for (OMPClause
*C
: Clauses
) {
4953 if (auto *RC
= dyn_cast
<OMPReductionClause
>(C
)) {
4954 if (RC
->getModifier() != OMPC_REDUCTION_inscan
)
4956 for (Expr
*E
: RC
->copy_array_temps())
4957 MarkDeclarationsReferencedInExpr(E
);
4959 if (auto *AC
= dyn_cast
<OMPAlignedClause
>(C
)) {
4960 for (Expr
*E
: AC
->varlists())
4961 MarkDeclarationsReferencedInExpr(E
);
4965 if (++CompletedRegions
== CaptureRegions
.size())
4966 DSAStack
->setBodyComplete();
4967 SR
= ActOnCapturedRegionEnd(SR
.get());
4972 static bool checkCancelRegion(Sema
&SemaRef
, OpenMPDirectiveKind CurrentRegion
,
4973 OpenMPDirectiveKind CancelRegion
,
4974 SourceLocation StartLoc
) {
4975 // CancelRegion is only needed for cancel and cancellation_point.
4976 if (CurrentRegion
!= OMPD_cancel
&& CurrentRegion
!= OMPD_cancellation_point
)
4979 if (CancelRegion
== OMPD_parallel
|| CancelRegion
== OMPD_for
||
4980 CancelRegion
== OMPD_sections
|| CancelRegion
== OMPD_taskgroup
)
4983 SemaRef
.Diag(StartLoc
, diag::err_omp_wrong_cancel_region
)
4984 << getOpenMPDirectiveName(CancelRegion
);
4988 static bool checkNestingOfRegions(Sema
&SemaRef
, const DSAStackTy
*Stack
,
4989 OpenMPDirectiveKind CurrentRegion
,
4990 const DeclarationNameInfo
&CurrentName
,
4991 OpenMPDirectiveKind CancelRegion
,
4992 OpenMPBindClauseKind BindKind
,
4993 SourceLocation StartLoc
) {
4994 if (Stack
->getCurScope()) {
4995 OpenMPDirectiveKind ParentRegion
= Stack
->getParentDirective();
4996 OpenMPDirectiveKind OffendingRegion
= ParentRegion
;
4997 bool NestingProhibited
= false;
4998 bool CloseNesting
= true;
4999 bool OrphanSeen
= false;
5002 ShouldBeInParallelRegion
,
5003 ShouldBeInOrderedRegion
,
5004 ShouldBeInTargetRegion
,
5005 ShouldBeInTeamsRegion
,
5006 ShouldBeInLoopSimdRegion
,
5007 } Recommend
= NoRecommend
;
5008 if (SemaRef
.LangOpts
.OpenMP
>= 51 && Stack
->isParentOrderConcurrent() &&
5009 CurrentRegion
!= OMPD_simd
&& CurrentRegion
!= OMPD_loop
&&
5010 CurrentRegion
!= OMPD_parallel
&&
5011 !isOpenMPCombinedParallelADirective(CurrentRegion
)) {
5012 SemaRef
.Diag(StartLoc
, diag::err_omp_prohibited_region_order
)
5013 << getOpenMPDirectiveName(CurrentRegion
);
5016 if (isOpenMPSimdDirective(ParentRegion
) &&
5017 ((SemaRef
.LangOpts
.OpenMP
<= 45 && CurrentRegion
!= OMPD_ordered
) ||
5018 (SemaRef
.LangOpts
.OpenMP
>= 50 && CurrentRegion
!= OMPD_ordered
&&
5019 CurrentRegion
!= OMPD_simd
&& CurrentRegion
!= OMPD_atomic
&&
5020 CurrentRegion
!= OMPD_scan
))) {
5021 // OpenMP [2.16, Nesting of Regions]
5022 // OpenMP constructs may not be nested inside a simd region.
5023 // OpenMP [2.8.1,simd Construct, Restrictions]
5024 // An ordered construct with the simd clause is the only OpenMP
5025 // construct that can appear in the simd region.
5026 // Allowing a SIMD construct nested in another SIMD construct is an
5027 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
5029 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
5030 // The only OpenMP constructs that can be encountered during execution of
5031 // a simd region are the atomic construct, the loop construct, the simd
5032 // construct and the ordered construct with the simd clause.
5033 SemaRef
.Diag(StartLoc
, (CurrentRegion
!= OMPD_simd
)
5034 ? diag::err_omp_prohibited_region_simd
5035 : diag::warn_omp_nesting_simd
)
5036 << (SemaRef
.LangOpts
.OpenMP
>= 50 ? 1 : 0);
5037 return CurrentRegion
!= OMPD_simd
;
5039 if (ParentRegion
== OMPD_atomic
) {
5040 // OpenMP [2.16, Nesting of Regions]
5041 // OpenMP constructs may not be nested inside an atomic region.
5042 SemaRef
.Diag(StartLoc
, diag::err_omp_prohibited_region_atomic
);
5045 if (CurrentRegion
== OMPD_section
) {
5046 // OpenMP [2.7.2, sections Construct, Restrictions]
5047 // Orphaned section directives are prohibited. That is, the section
5048 // directives must appear within the sections construct and must not be
5049 // encountered elsewhere in the sections region.
5050 if (ParentRegion
!= OMPD_sections
&&
5051 ParentRegion
!= OMPD_parallel_sections
) {
5052 SemaRef
.Diag(StartLoc
, diag::err_omp_orphaned_section_directive
)
5053 << (ParentRegion
!= OMPD_unknown
)
5054 << getOpenMPDirectiveName(ParentRegion
);
5059 // Allow some constructs (except teams and cancellation constructs) to be
5060 // orphaned (they could be used in functions, called from OpenMP regions
5061 // with the required preconditions).
5062 if (ParentRegion
== OMPD_unknown
&&
5063 !isOpenMPNestingTeamsDirective(CurrentRegion
) &&
5064 CurrentRegion
!= OMPD_cancellation_point
&&
5065 CurrentRegion
!= OMPD_cancel
&& CurrentRegion
!= OMPD_scan
)
5067 if (CurrentRegion
== OMPD_cancellation_point
||
5068 CurrentRegion
== OMPD_cancel
) {
5069 // OpenMP [2.16, Nesting of Regions]
5070 // A cancellation point construct for which construct-type-clause is
5071 // taskgroup must be nested inside a task construct. A cancellation
5072 // point construct for which construct-type-clause is not taskgroup must
5073 // be closely nested inside an OpenMP construct that matches the type
5074 // specified in construct-type-clause.
5075 // A cancel construct for which construct-type-clause is taskgroup must be
5076 // nested inside a task construct. A cancel construct for which
5077 // construct-type-clause is not taskgroup must be closely nested inside an
5078 // OpenMP construct that matches the type specified in
5079 // construct-type-clause.
5081 !((CancelRegion
== OMPD_parallel
&&
5082 (ParentRegion
== OMPD_parallel
||
5083 ParentRegion
== OMPD_target_parallel
)) ||
5084 (CancelRegion
== OMPD_for
&&
5085 (ParentRegion
== OMPD_for
|| ParentRegion
== OMPD_parallel_for
||
5086 ParentRegion
== OMPD_target_parallel_for
||
5087 ParentRegion
== OMPD_distribute_parallel_for
||
5088 ParentRegion
== OMPD_teams_distribute_parallel_for
||
5089 ParentRegion
== OMPD_target_teams_distribute_parallel_for
)) ||
5090 (CancelRegion
== OMPD_taskgroup
&&
5091 (ParentRegion
== OMPD_task
||
5092 (SemaRef
.getLangOpts().OpenMP
>= 50 &&
5093 (ParentRegion
== OMPD_taskloop
||
5094 ParentRegion
== OMPD_master_taskloop
||
5095 ParentRegion
== OMPD_masked_taskloop
||
5096 ParentRegion
== OMPD_parallel_masked_taskloop
||
5097 ParentRegion
== OMPD_parallel_master_taskloop
)))) ||
5098 (CancelRegion
== OMPD_sections
&&
5099 (ParentRegion
== OMPD_section
|| ParentRegion
== OMPD_sections
||
5100 ParentRegion
== OMPD_parallel_sections
)));
5101 OrphanSeen
= ParentRegion
== OMPD_unknown
;
5102 } else if (CurrentRegion
== OMPD_master
|| CurrentRegion
== OMPD_masked
) {
5103 // OpenMP 5.1 [2.22, Nesting of Regions]
5104 // A masked region may not be closely nested inside a worksharing, loop,
5105 // atomic, task, or taskloop region.
5106 NestingProhibited
= isOpenMPWorksharingDirective(ParentRegion
) ||
5107 isOpenMPGenericLoopDirective(ParentRegion
) ||
5108 isOpenMPTaskingDirective(ParentRegion
);
5109 } else if (CurrentRegion
== OMPD_critical
&& CurrentName
.getName()) {
5110 // OpenMP [2.16, Nesting of Regions]
5111 // A critical region may not be nested (closely or otherwise) inside a
5112 // critical region with the same name. Note that this restriction is not
5113 // sufficient to prevent deadlock.
5114 SourceLocation PreviousCriticalLoc
;
5115 bool DeadLock
= Stack
->hasDirective(
5116 [CurrentName
, &PreviousCriticalLoc
](OpenMPDirectiveKind K
,
5117 const DeclarationNameInfo
&DNI
,
5118 SourceLocation Loc
) {
5119 if (K
== OMPD_critical
&& DNI
.getName() == CurrentName
.getName()) {
5120 PreviousCriticalLoc
= Loc
;
5125 false /* skip top directive */);
5127 SemaRef
.Diag(StartLoc
,
5128 diag::err_omp_prohibited_region_critical_same_name
)
5129 << CurrentName
.getName();
5130 if (PreviousCriticalLoc
.isValid())
5131 SemaRef
.Diag(PreviousCriticalLoc
,
5132 diag::note_omp_previous_critical_region
);
5135 } else if (CurrentRegion
== OMPD_barrier
|| CurrentRegion
== OMPD_scope
) {
5136 // OpenMP 5.1 [2.22, Nesting of Regions]
5137 // A scope region may not be closely nested inside a worksharing, loop,
5138 // task, taskloop, critical, ordered, atomic, or masked region.
5139 // OpenMP 5.1 [2.22, Nesting of Regions]
5140 // A barrier region may not be closely nested inside a worksharing, loop,
5141 // task, taskloop, critical, ordered, atomic, or masked region.
5143 isOpenMPWorksharingDirective(ParentRegion
) ||
5144 isOpenMPGenericLoopDirective(ParentRegion
) ||
5145 isOpenMPTaskingDirective(ParentRegion
) ||
5146 ParentRegion
== OMPD_master
|| ParentRegion
== OMPD_masked
||
5147 ParentRegion
== OMPD_parallel_master
||
5148 ParentRegion
== OMPD_parallel_masked
||
5149 ParentRegion
== OMPD_critical
|| ParentRegion
== OMPD_ordered
;
5150 } else if (isOpenMPWorksharingDirective(CurrentRegion
) &&
5151 !isOpenMPParallelDirective(CurrentRegion
) &&
5152 !isOpenMPTeamsDirective(CurrentRegion
)) {
5153 // OpenMP 5.1 [2.22, Nesting of Regions]
5154 // A loop region that binds to a parallel region or a worksharing region
5155 // may not be closely nested inside a worksharing, loop, task, taskloop,
5156 // critical, ordered, atomic, or masked region.
5158 isOpenMPWorksharingDirective(ParentRegion
) ||
5159 isOpenMPGenericLoopDirective(ParentRegion
) ||
5160 isOpenMPTaskingDirective(ParentRegion
) ||
5161 ParentRegion
== OMPD_master
|| ParentRegion
== OMPD_masked
||
5162 ParentRegion
== OMPD_parallel_master
||
5163 ParentRegion
== OMPD_parallel_masked
||
5164 ParentRegion
== OMPD_critical
|| ParentRegion
== OMPD_ordered
;
5165 Recommend
= ShouldBeInParallelRegion
;
5166 } else if (CurrentRegion
== OMPD_ordered
) {
5167 // OpenMP [2.16, Nesting of Regions]
5168 // An ordered region may not be closely nested inside a critical,
5169 // atomic, or explicit task region.
5170 // An ordered region must be closely nested inside a loop region (or
5171 // parallel loop region) with an ordered clause.
5172 // OpenMP [2.8.1,simd Construct, Restrictions]
5173 // An ordered construct with the simd clause is the only OpenMP construct
5174 // that can appear in the simd region.
5175 NestingProhibited
= ParentRegion
== OMPD_critical
||
5176 isOpenMPTaskingDirective(ParentRegion
) ||
5177 !(isOpenMPSimdDirective(ParentRegion
) ||
5178 Stack
->isParentOrderedRegion());
5179 Recommend
= ShouldBeInOrderedRegion
;
5180 } else if (isOpenMPNestingTeamsDirective(CurrentRegion
)) {
5181 // OpenMP [2.16, Nesting of Regions]
5182 // If specified, a teams construct must be contained within a target
5185 (SemaRef
.LangOpts
.OpenMP
<= 45 && ParentRegion
!= OMPD_target
) ||
5186 (SemaRef
.LangOpts
.OpenMP
>= 50 && ParentRegion
!= OMPD_unknown
&&
5187 ParentRegion
!= OMPD_target
);
5188 OrphanSeen
= ParentRegion
== OMPD_unknown
;
5189 Recommend
= ShouldBeInTargetRegion
;
5190 } else if (CurrentRegion
== OMPD_scan
) {
5191 // OpenMP [2.16, Nesting of Regions]
5192 // If specified, a teams construct must be contained within a target
5195 SemaRef
.LangOpts
.OpenMP
< 50 ||
5196 (ParentRegion
!= OMPD_simd
&& ParentRegion
!= OMPD_for
&&
5197 ParentRegion
!= OMPD_for_simd
&& ParentRegion
!= OMPD_parallel_for
&&
5198 ParentRegion
!= OMPD_parallel_for_simd
);
5199 OrphanSeen
= ParentRegion
== OMPD_unknown
;
5200 Recommend
= ShouldBeInLoopSimdRegion
;
5202 if (!NestingProhibited
&&
5203 !isOpenMPTargetExecutionDirective(CurrentRegion
) &&
5204 !isOpenMPTargetDataManagementDirective(CurrentRegion
) &&
5205 (ParentRegion
== OMPD_teams
|| ParentRegion
== OMPD_target_teams
)) {
5206 // OpenMP [5.1, 2.22, Nesting of Regions]
5207 // distribute, distribute simd, distribute parallel worksharing-loop,
5208 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5209 // including any parallel regions arising from combined constructs,
5210 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5211 // only OpenMP regions that may be strictly nested inside the teams
5214 // As an extension, we permit atomic within teams as well.
5215 NestingProhibited
= !isOpenMPParallelDirective(CurrentRegion
) &&
5216 !isOpenMPDistributeDirective(CurrentRegion
) &&
5217 CurrentRegion
!= OMPD_loop
&&
5218 !(SemaRef
.getLangOpts().OpenMPExtensions
&&
5219 CurrentRegion
== OMPD_atomic
);
5220 Recommend
= ShouldBeInParallelRegion
;
5222 if (!NestingProhibited
&& CurrentRegion
== OMPD_loop
) {
5223 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5224 // If the bind clause is present on the loop construct and binding is
5225 // teams then the corresponding loop region must be strictly nested inside
5227 NestingProhibited
= BindKind
== OMPC_BIND_teams
&&
5228 ParentRegion
!= OMPD_teams
&&
5229 ParentRegion
!= OMPD_target_teams
;
5230 Recommend
= ShouldBeInTeamsRegion
;
5232 if (!NestingProhibited
&&
5233 isOpenMPNestingDistributeDirective(CurrentRegion
)) {
5234 // OpenMP 4.5 [2.17 Nesting of Regions]
5235 // The region associated with the distribute construct must be strictly
5236 // nested inside a teams region
5238 (ParentRegion
!= OMPD_teams
&& ParentRegion
!= OMPD_target_teams
);
5239 Recommend
= ShouldBeInTeamsRegion
;
5241 if (!NestingProhibited
&&
5242 (isOpenMPTargetExecutionDirective(CurrentRegion
) ||
5243 isOpenMPTargetDataManagementDirective(CurrentRegion
))) {
5244 // OpenMP 4.5 [2.17 Nesting of Regions]
5245 // If a target, target update, target data, target enter data, or
5246 // target exit data construct is encountered during execution of a
5247 // target region, the behavior is unspecified.
5248 NestingProhibited
= Stack
->hasDirective(
5249 [&OffendingRegion
](OpenMPDirectiveKind K
, const DeclarationNameInfo
&,
5251 if (isOpenMPTargetExecutionDirective(K
)) {
5252 OffendingRegion
= K
;
5257 false /* don't skip top directive */);
5258 CloseNesting
= false;
5260 if (NestingProhibited
) {
5262 SemaRef
.Diag(StartLoc
, diag::err_omp_orphaned_device_directive
)
5263 << getOpenMPDirectiveName(CurrentRegion
) << Recommend
;
5265 SemaRef
.Diag(StartLoc
, diag::err_omp_prohibited_region
)
5266 << CloseNesting
<< getOpenMPDirectiveName(OffendingRegion
)
5267 << Recommend
<< getOpenMPDirectiveName(CurrentRegion
);
5275 struct Kind2Unsigned
{
5276 using argument_type
= OpenMPDirectiveKind
;
5277 unsigned operator()(argument_type DK
) { return unsigned(DK
); }
5279 static bool checkIfClauses(Sema
&S
, OpenMPDirectiveKind Kind
,
5280 ArrayRef
<OMPClause
*> Clauses
,
5281 ArrayRef
<OpenMPDirectiveKind
> AllowedNameModifiers
) {
5282 bool ErrorFound
= false;
5283 unsigned NamedModifiersNumber
= 0;
5284 llvm::IndexedMap
<const OMPIfClause
*, Kind2Unsigned
> FoundNameModifiers
;
5285 FoundNameModifiers
.resize(llvm::omp::Directive_enumSize
+ 1);
5286 SmallVector
<SourceLocation
, 4> NameModifierLoc
;
5287 for (const OMPClause
*C
: Clauses
) {
5288 if (const auto *IC
= dyn_cast_or_null
<OMPIfClause
>(C
)) {
5289 // At most one if clause without a directive-name-modifier can appear on
5291 OpenMPDirectiveKind CurNM
= IC
->getNameModifier();
5292 if (FoundNameModifiers
[CurNM
]) {
5293 S
.Diag(C
->getBeginLoc(), diag::err_omp_more_one_clause
)
5294 << getOpenMPDirectiveName(Kind
) << getOpenMPClauseName(OMPC_if
)
5295 << (CurNM
!= OMPD_unknown
) << getOpenMPDirectiveName(CurNM
);
5297 } else if (CurNM
!= OMPD_unknown
) {
5298 NameModifierLoc
.push_back(IC
->getNameModifierLoc());
5299 ++NamedModifiersNumber
;
5301 FoundNameModifiers
[CurNM
] = IC
;
5302 if (CurNM
== OMPD_unknown
)
5304 // Check if the specified name modifier is allowed for the current
5306 // At most one if clause with the particular directive-name-modifier can
5307 // appear on the directive.
5308 if (!llvm::is_contained(AllowedNameModifiers
, CurNM
)) {
5309 S
.Diag(IC
->getNameModifierLoc(),
5310 diag::err_omp_wrong_if_directive_name_modifier
)
5311 << getOpenMPDirectiveName(CurNM
) << getOpenMPDirectiveName(Kind
);
5316 // If any if clause on the directive includes a directive-name-modifier then
5317 // all if clauses on the directive must include a directive-name-modifier.
5318 if (FoundNameModifiers
[OMPD_unknown
] && NamedModifiersNumber
> 0) {
5319 if (NamedModifiersNumber
== AllowedNameModifiers
.size()) {
5320 S
.Diag(FoundNameModifiers
[OMPD_unknown
]->getBeginLoc(),
5321 diag::err_omp_no_more_if_clause
);
5324 std::string
Sep(", ");
5325 unsigned AllowedCnt
= 0;
5326 unsigned TotalAllowedNum
=
5327 AllowedNameModifiers
.size() - NamedModifiersNumber
;
5328 for (unsigned Cnt
= 0, End
= AllowedNameModifiers
.size(); Cnt
< End
;
5330 OpenMPDirectiveKind NM
= AllowedNameModifiers
[Cnt
];
5331 if (!FoundNameModifiers
[NM
]) {
5333 Values
+= getOpenMPDirectiveName(NM
);
5335 if (AllowedCnt
+ 2 == TotalAllowedNum
)
5337 else if (AllowedCnt
+ 1 != TotalAllowedNum
)
5342 S
.Diag(FoundNameModifiers
[OMPD_unknown
]->getCondition()->getBeginLoc(),
5343 diag::err_omp_unnamed_if_clause
)
5344 << (TotalAllowedNum
> 1) << Values
;
5346 for (SourceLocation Loc
: NameModifierLoc
) {
5347 S
.Diag(Loc
, diag::note_omp_previous_named_if_clause
);
5354 static std::pair
<ValueDecl
*, bool> getPrivateItem(Sema
&S
, Expr
*&RefExpr
,
5355 SourceLocation
&ELoc
,
5356 SourceRange
&ERange
,
5357 bool AllowArraySection
,
5358 StringRef DiagType
) {
5359 if (RefExpr
->isTypeDependent() || RefExpr
->isValueDependent() ||
5360 RefExpr
->containsUnexpandedParameterPack())
5361 return std::make_pair(nullptr, true);
5363 // OpenMP [3.1, C/C++]
5364 // A list item is a variable name.
5365 // OpenMP [2.9.3.3, Restrictions, p.1]
5366 // A variable that is part of another variable (as an array or
5367 // structure element) cannot appear in a private clause.
5368 RefExpr
= RefExpr
->IgnoreParens();
5373 } IsArrayExpr
= NoArrayExpr
;
5374 if (AllowArraySection
) {
5375 if (auto *ASE
= dyn_cast_or_null
<ArraySubscriptExpr
>(RefExpr
)) {
5376 Expr
*Base
= ASE
->getBase()->IgnoreParenImpCasts();
5377 while (auto *TempASE
= dyn_cast
<ArraySubscriptExpr
>(Base
))
5378 Base
= TempASE
->getBase()->IgnoreParenImpCasts();
5380 IsArrayExpr
= ArraySubscript
;
5381 } else if (auto *OASE
= dyn_cast_or_null
<OMPArraySectionExpr
>(RefExpr
)) {
5382 Expr
*Base
= OASE
->getBase()->IgnoreParenImpCasts();
5383 while (auto *TempOASE
= dyn_cast
<OMPArraySectionExpr
>(Base
))
5384 Base
= TempOASE
->getBase()->IgnoreParenImpCasts();
5385 while (auto *TempASE
= dyn_cast
<ArraySubscriptExpr
>(Base
))
5386 Base
= TempASE
->getBase()->IgnoreParenImpCasts();
5388 IsArrayExpr
= OMPArraySection
;
5391 ELoc
= RefExpr
->getExprLoc();
5392 ERange
= RefExpr
->getSourceRange();
5393 RefExpr
= RefExpr
->IgnoreParenImpCasts();
5394 auto *DE
= dyn_cast_or_null
<DeclRefExpr
>(RefExpr
);
5395 auto *ME
= dyn_cast_or_null
<MemberExpr
>(RefExpr
);
5396 if ((!DE
|| !isa
<VarDecl
>(DE
->getDecl())) &&
5397 (S
.getCurrentThisType().isNull() || !ME
||
5398 !isa
<CXXThisExpr
>(ME
->getBase()->IgnoreParenImpCasts()) ||
5399 !isa
<FieldDecl
>(ME
->getMemberDecl()))) {
5400 if (IsArrayExpr
!= NoArrayExpr
) {
5401 S
.Diag(ELoc
, diag::err_omp_expected_base_var_name
)
5402 << IsArrayExpr
<< ERange
;
5403 } else if (!DiagType
.empty()) {
5404 unsigned DiagSelect
= S
.getLangOpts().CPlusPlus
5405 ? (S
.getCurrentThisType().isNull() ? 1 : 2)
5407 S
.Diag(ELoc
, diag::err_omp_expected_var_name_member_expr_with_type
)
5408 << DiagSelect
<< DiagType
<< ERange
;
5412 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5413 : diag::err_omp_expected_var_name_member_expr
)
5414 << (S
.getCurrentThisType().isNull() ? 0 : 1) << ERange
;
5416 return std::make_pair(nullptr, false);
5418 return std::make_pair(
5419 getCanonicalDecl(DE
? DE
->getDecl() : ME
->getMemberDecl()), false);
5423 /// Checks if the allocator is used in uses_allocators clause to be allowed in
5425 class AllocatorChecker final
: public ConstStmtVisitor
<AllocatorChecker
, bool> {
5426 DSAStackTy
*S
= nullptr;
5429 bool VisitDeclRefExpr(const DeclRefExpr
*E
) {
5430 return S
->isUsesAllocatorsDecl(E
->getDecl())
5431 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait
) ==
5432 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait
;
5434 bool VisitStmt(const Stmt
*S
) {
5435 for (const Stmt
*Child
: S
->children()) {
5436 if (Child
&& Visit(Child
))
5441 explicit AllocatorChecker(DSAStackTy
*S
) : S(S
) {}
5445 static void checkAllocateClauses(Sema
&S
, DSAStackTy
*Stack
,
5446 ArrayRef
<OMPClause
*> Clauses
) {
5447 assert(!S
.CurContext
->isDependentContext() &&
5448 "Expected non-dependent context.");
5449 auto AllocateRange
=
5450 llvm::make_filter_range(Clauses
, OMPAllocateClause::classof
);
5451 llvm::DenseMap
<CanonicalDeclPtr
<Decl
>, CanonicalDeclPtr
<VarDecl
>> DeclToCopy
;
5452 auto PrivateRange
= llvm::make_filter_range(Clauses
, [](const OMPClause
*C
) {
5453 return isOpenMPPrivate(C
->getClauseKind());
5455 for (OMPClause
*Cl
: PrivateRange
) {
5456 MutableArrayRef
<Expr
*>::iterator I
, It
, Et
;
5457 if (Cl
->getClauseKind() == OMPC_private
) {
5458 auto *PC
= cast
<OMPPrivateClause
>(Cl
);
5459 I
= PC
->private_copies().begin();
5460 It
= PC
->varlist_begin();
5461 Et
= PC
->varlist_end();
5462 } else if (Cl
->getClauseKind() == OMPC_firstprivate
) {
5463 auto *PC
= cast
<OMPFirstprivateClause
>(Cl
);
5464 I
= PC
->private_copies().begin();
5465 It
= PC
->varlist_begin();
5466 Et
= PC
->varlist_end();
5467 } else if (Cl
->getClauseKind() == OMPC_lastprivate
) {
5468 auto *PC
= cast
<OMPLastprivateClause
>(Cl
);
5469 I
= PC
->private_copies().begin();
5470 It
= PC
->varlist_begin();
5471 Et
= PC
->varlist_end();
5472 } else if (Cl
->getClauseKind() == OMPC_linear
) {
5473 auto *PC
= cast
<OMPLinearClause
>(Cl
);
5474 I
= PC
->privates().begin();
5475 It
= PC
->varlist_begin();
5476 Et
= PC
->varlist_end();
5477 } else if (Cl
->getClauseKind() == OMPC_reduction
) {
5478 auto *PC
= cast
<OMPReductionClause
>(Cl
);
5479 I
= PC
->privates().begin();
5480 It
= PC
->varlist_begin();
5481 Et
= PC
->varlist_end();
5482 } else if (Cl
->getClauseKind() == OMPC_task_reduction
) {
5483 auto *PC
= cast
<OMPTaskReductionClause
>(Cl
);
5484 I
= PC
->privates().begin();
5485 It
= PC
->varlist_begin();
5486 Et
= PC
->varlist_end();
5487 } else if (Cl
->getClauseKind() == OMPC_in_reduction
) {
5488 auto *PC
= cast
<OMPInReductionClause
>(Cl
);
5489 I
= PC
->privates().begin();
5490 It
= PC
->varlist_begin();
5491 Et
= PC
->varlist_end();
5493 llvm_unreachable("Expected private clause.");
5495 for (Expr
*E
: llvm::make_range(It
, Et
)) {
5500 SourceLocation ELoc
;
5502 Expr
*SimpleRefExpr
= E
;
5503 auto Res
= getPrivateItem(S
, SimpleRefExpr
, ELoc
, ERange
,
5504 /*AllowArraySection=*/true);
5505 DeclToCopy
.try_emplace(Res
.first
,
5506 cast
<VarDecl
>(cast
<DeclRefExpr
>(*I
)->getDecl()));
5510 for (OMPClause
*C
: AllocateRange
) {
5511 auto *AC
= cast
<OMPAllocateClause
>(C
);
5512 if (S
.getLangOpts().OpenMP
>= 50 &&
5513 !Stack
->hasRequiresDeclWithClause
<OMPDynamicAllocatorsClause
>() &&
5514 isOpenMPTargetExecutionDirective(Stack
->getCurrentDirective()) &&
5515 AC
->getAllocator()) {
5516 Expr
*Allocator
= AC
->getAllocator();
5517 // OpenMP, 2.12.5 target Construct
5518 // Memory allocators that do not appear in a uses_allocators clause cannot
5519 // appear as an allocator in an allocate clause or be used in the target
5520 // region unless a requires directive with the dynamic_allocators clause
5521 // is present in the same compilation unit.
5522 AllocatorChecker
Checker(Stack
);
5523 if (Checker
.Visit(Allocator
))
5524 S
.Diag(Allocator
->getExprLoc(),
5525 diag::err_omp_allocator_not_in_uses_allocators
)
5526 << Allocator
->getSourceRange();
5528 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind
=
5529 getAllocatorKind(S
, Stack
, AC
->getAllocator());
5530 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5531 // For task, taskloop or target directives, allocation requests to memory
5532 // allocators with the trait access set to thread result in unspecified
5534 if (AllocatorKind
== OMPAllocateDeclAttr::OMPThreadMemAlloc
&&
5535 (isOpenMPTaskingDirective(Stack
->getCurrentDirective()) ||
5536 isOpenMPTargetExecutionDirective(Stack
->getCurrentDirective()))) {
5537 S
.Diag(AC
->getAllocator()->getExprLoc(),
5538 diag::warn_omp_allocate_thread_on_task_target_directive
)
5539 << getOpenMPDirectiveName(Stack
->getCurrentDirective());
5541 for (Expr
*E
: AC
->varlists()) {
5542 SourceLocation ELoc
;
5544 Expr
*SimpleRefExpr
= E
;
5545 auto Res
= getPrivateItem(S
, SimpleRefExpr
, ELoc
, ERange
);
5546 ValueDecl
*VD
= Res
.first
;
5547 DSAStackTy::DSAVarData Data
= Stack
->getTopDSA(VD
, /*FromParent=*/false);
5548 if (!isOpenMPPrivate(Data
.CKind
)) {
5549 S
.Diag(E
->getExprLoc(),
5550 diag::err_omp_expected_private_copy_for_allocate
);
5553 VarDecl
*PrivateVD
= DeclToCopy
[VD
];
5554 if (checkPreviousOMPAllocateAttribute(S
, Stack
, E
, PrivateVD
,
5555 AllocatorKind
, AC
->getAllocator()))
5557 // Placeholder until allocate clause supports align modifier.
5558 Expr
*Alignment
= nullptr;
5559 applyOMPAllocateAttribute(S
, PrivateVD
, AllocatorKind
, AC
->getAllocator(),
5560 Alignment
, E
->getSourceRange());
5566 /// Rewrite statements and expressions for Sema \p Actions CurContext.
5568 /// Used to wrap already parsed statements/expressions into a new CapturedStmt
5569 /// context. DeclRefExpr used inside the new context are changed to refer to the
5570 /// captured variable instead.
5571 class CaptureVars
: public TreeTransform
<CaptureVars
> {
5572 using BaseTransform
= TreeTransform
<CaptureVars
>;
5575 CaptureVars(Sema
&Actions
) : BaseTransform(Actions
) {}
5577 bool AlwaysRebuild() { return true; }
5581 static VarDecl
*precomputeExpr(Sema
&Actions
,
5582 SmallVectorImpl
<Stmt
*> &BodyStmts
, Expr
*E
,
5584 Expr
*NewE
= AssertSuccess(CaptureVars(Actions
).TransformExpr(E
));
5585 VarDecl
*NewVar
= buildVarDecl(Actions
, {}, NewE
->getType(), Name
, nullptr,
5586 dyn_cast
<DeclRefExpr
>(E
->IgnoreImplicit()));
5587 auto *NewDeclStmt
= cast
<DeclStmt
>(AssertSuccess(
5588 Actions
.ActOnDeclStmt(Actions
.ConvertDeclToDeclGroup(NewVar
), {}, {})));
5589 Actions
.AddInitializerToDecl(NewDeclStmt
->getSingleDecl(), NewE
, false);
5590 BodyStmts
.push_back(NewDeclStmt
);
5594 /// Create a closure that computes the number of iterations of a loop.
5596 /// \param Actions The Sema object.
5597 /// \param LogicalTy Type for the logical iteration number.
5598 /// \param Rel Comparison operator of the loop condition.
5599 /// \param StartExpr Value of the loop counter at the first iteration.
5600 /// \param StopExpr Expression the loop counter is compared against in the loop
5601 /// condition. \param StepExpr Amount of increment after each iteration.
5603 /// \return Closure (CapturedStmt) of the distance calculation.
5604 static CapturedStmt
*buildDistanceFunc(Sema
&Actions
, QualType LogicalTy
,
5605 BinaryOperator::Opcode Rel
,
5606 Expr
*StartExpr
, Expr
*StopExpr
,
5608 ASTContext
&Ctx
= Actions
.getASTContext();
5609 TypeSourceInfo
*LogicalTSI
= Ctx
.getTrivialTypeSourceInfo(LogicalTy
);
5611 // Captured regions currently don't support return values, we use an
5612 // out-parameter instead. All inputs are implicit captures.
5613 // TODO: Instead of capturing each DeclRefExpr occurring in
5614 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5615 QualType ResultTy
= Ctx
.getLValueReferenceType(LogicalTy
);
5616 Sema::CapturedParamNameType Params
[] = {{"Distance", ResultTy
},
5617 {StringRef(), QualType()}};
5618 Actions
.ActOnCapturedRegionStart({}, nullptr, CR_Default
, Params
);
5622 Sema::CompoundScopeRAII
CompoundScope(Actions
);
5623 CapturedDecl
*CS
= cast
<CapturedDecl
>(Actions
.CurContext
);
5625 // Get the LValue expression for the result.
5626 ImplicitParamDecl
*DistParam
= CS
->getParam(0);
5627 DeclRefExpr
*DistRef
= Actions
.BuildDeclRefExpr(
5628 DistParam
, LogicalTy
, VK_LValue
, {}, nullptr, nullptr, {}, nullptr);
5630 SmallVector
<Stmt
*, 4> BodyStmts
;
5632 // Capture all referenced variable references.
5633 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5634 // CapturedStmt, we could compute them before and capture the result, to be
5635 // used jointly with the LoopVar function.
5636 VarDecl
*NewStart
= precomputeExpr(Actions
, BodyStmts
, StartExpr
, ".start");
5637 VarDecl
*NewStop
= precomputeExpr(Actions
, BodyStmts
, StopExpr
, ".stop");
5638 VarDecl
*NewStep
= precomputeExpr(Actions
, BodyStmts
, StepExpr
, ".step");
5639 auto BuildVarRef
= [&](VarDecl
*VD
) {
5640 return buildDeclRefExpr(Actions
, VD
, VD
->getType(), {});
5643 IntegerLiteral
*Zero
= IntegerLiteral::Create(
5644 Ctx
, llvm::APInt(Ctx
.getIntWidth(LogicalTy
), 0), LogicalTy
, {});
5645 IntegerLiteral
*One
= IntegerLiteral::Create(
5646 Ctx
, llvm::APInt(Ctx
.getIntWidth(LogicalTy
), 1), LogicalTy
, {});
5649 // When using a != comparison, the increment can be +1 or -1. This can be
5650 // dynamic at runtime, so we need to check for the direction.
5651 Expr
*IsNegStep
= AssertSuccess(
5652 Actions
.BuildBinOp(nullptr, {}, BO_LT
, BuildVarRef(NewStep
), Zero
));
5654 // Positive increment.
5655 Expr
*ForwardRange
= AssertSuccess(Actions
.BuildBinOp(
5656 nullptr, {}, BO_Sub
, BuildVarRef(NewStop
), BuildVarRef(NewStart
)));
5657 ForwardRange
= AssertSuccess(
5658 Actions
.BuildCStyleCastExpr({}, LogicalTSI
, {}, ForwardRange
));
5659 Expr
*ForwardDist
= AssertSuccess(Actions
.BuildBinOp(
5660 nullptr, {}, BO_Div
, ForwardRange
, BuildVarRef(NewStep
)));
5662 // Negative increment.
5663 Expr
*BackwardRange
= AssertSuccess(Actions
.BuildBinOp(
5664 nullptr, {}, BO_Sub
, BuildVarRef(NewStart
), BuildVarRef(NewStop
)));
5665 BackwardRange
= AssertSuccess(
5666 Actions
.BuildCStyleCastExpr({}, LogicalTSI
, {}, BackwardRange
));
5667 Expr
*NegIncAmount
= AssertSuccess(
5668 Actions
.BuildUnaryOp(nullptr, {}, UO_Minus
, BuildVarRef(NewStep
)));
5669 Expr
*BackwardDist
= AssertSuccess(
5670 Actions
.BuildBinOp(nullptr, {}, BO_Div
, BackwardRange
, NegIncAmount
));
5672 // Use the appropriate case.
5673 Dist
= AssertSuccess(Actions
.ActOnConditionalOp(
5674 {}, {}, IsNegStep
, BackwardDist
, ForwardDist
));
5676 assert((Rel
== BO_LT
|| Rel
== BO_LE
|| Rel
== BO_GE
|| Rel
== BO_GT
) &&
5677 "Expected one of these relational operators");
5679 // We can derive the direction from any other comparison operator. It is
5680 // non well-formed OpenMP if Step increments/decrements in the other
5681 // directions. Whether at least the first iteration passes the loop
5683 Expr
*HasAnyIteration
= AssertSuccess(Actions
.BuildBinOp(
5684 nullptr, {}, Rel
, BuildVarRef(NewStart
), BuildVarRef(NewStop
)));
5686 // Compute the range between first and last counter value.
5688 if (Rel
== BO_GE
|| Rel
== BO_GT
)
5689 Range
= AssertSuccess(Actions
.BuildBinOp(
5690 nullptr, {}, BO_Sub
, BuildVarRef(NewStart
), BuildVarRef(NewStop
)));
5692 Range
= AssertSuccess(Actions
.BuildBinOp(
5693 nullptr, {}, BO_Sub
, BuildVarRef(NewStop
), BuildVarRef(NewStart
)));
5695 // Ensure unsigned range space.
5697 AssertSuccess(Actions
.BuildCStyleCastExpr({}, LogicalTSI
, {}, Range
));
5699 if (Rel
== BO_LE
|| Rel
== BO_GE
) {
5700 // Add one to the range if the relational operator is inclusive.
5702 AssertSuccess(Actions
.BuildBinOp(nullptr, {}, BO_Add
, Range
, One
));
5705 // Divide by the absolute step amount. If the range is not a multiple of
5706 // the step size, rounding-up the effective upper bound ensures that the
5707 // last iteration is included.
5708 // Note that the rounding-up may cause an overflow in a temporry that
5709 // could be avoided, but would have occurred in a C-style for-loop as
5711 Expr
*Divisor
= BuildVarRef(NewStep
);
5712 if (Rel
== BO_GE
|| Rel
== BO_GT
)
5714 AssertSuccess(Actions
.BuildUnaryOp(nullptr, {}, UO_Minus
, Divisor
));
5715 Expr
*DivisorMinusOne
=
5716 AssertSuccess(Actions
.BuildBinOp(nullptr, {}, BO_Sub
, Divisor
, One
));
5717 Expr
*RangeRoundUp
= AssertSuccess(
5718 Actions
.BuildBinOp(nullptr, {}, BO_Add
, Range
, DivisorMinusOne
));
5719 Dist
= AssertSuccess(
5720 Actions
.BuildBinOp(nullptr, {}, BO_Div
, RangeRoundUp
, Divisor
));
5722 // If there is not at least one iteration, the range contains garbage. Fix
5723 // to zero in this case.
5724 Dist
= AssertSuccess(
5725 Actions
.ActOnConditionalOp({}, {}, HasAnyIteration
, Dist
, Zero
));
5728 // Assign the result to the out-parameter.
5729 Stmt
*ResultAssign
= AssertSuccess(Actions
.BuildBinOp(
5730 Actions
.getCurScope(), {}, BO_Assign
, DistRef
, Dist
));
5731 BodyStmts
.push_back(ResultAssign
);
5733 Body
= AssertSuccess(Actions
.ActOnCompoundStmt({}, {}, BodyStmts
, false));
5736 return cast
<CapturedStmt
>(
5737 AssertSuccess(Actions
.ActOnCapturedRegionEnd(Body
)));
5740 /// Create a closure that computes the loop variable from the logical iteration
5743 /// \param Actions The Sema object.
5744 /// \param LoopVarTy Type for the loop variable used for result value.
5745 /// \param LogicalTy Type for the logical iteration number.
5746 /// \param StartExpr Value of the loop counter at the first iteration.
5747 /// \param Step Amount of increment after each iteration.
5748 /// \param Deref Whether the loop variable is a dereference of the loop
5749 /// counter variable.
5751 /// \return Closure (CapturedStmt) of the loop value calculation.
5752 static CapturedStmt
*buildLoopVarFunc(Sema
&Actions
, QualType LoopVarTy
,
5754 DeclRefExpr
*StartExpr
, Expr
*Step
,
5756 ASTContext
&Ctx
= Actions
.getASTContext();
5758 // Pass the result as an out-parameter. Passing as return value would require
5759 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5760 // invoke a copy constructor.
5761 QualType TargetParamTy
= Ctx
.getLValueReferenceType(LoopVarTy
);
5762 Sema::CapturedParamNameType Params
[] = {{"LoopVar", TargetParamTy
},
5763 {"Logical", LogicalTy
},
5764 {StringRef(), QualType()}};
5765 Actions
.ActOnCapturedRegionStart({}, nullptr, CR_Default
, Params
);
5767 // Capture the initial iterator which represents the LoopVar value at the
5768 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5769 // it in every iteration, capture it by value before it is modified.
5770 VarDecl
*StartVar
= cast
<VarDecl
>(StartExpr
->getDecl());
5771 bool Invalid
= Actions
.tryCaptureVariable(StartVar
, {},
5772 Sema::TryCapture_ExplicitByVal
, {});
5774 assert(!Invalid
&& "Expecting capture-by-value to work.");
5778 Sema::CompoundScopeRAII
CompoundScope(Actions
);
5779 auto *CS
= cast
<CapturedDecl
>(Actions
.CurContext
);
5781 ImplicitParamDecl
*TargetParam
= CS
->getParam(0);
5782 DeclRefExpr
*TargetRef
= Actions
.BuildDeclRefExpr(
5783 TargetParam
, LoopVarTy
, VK_LValue
, {}, nullptr, nullptr, {}, nullptr);
5784 ImplicitParamDecl
*IndvarParam
= CS
->getParam(1);
5785 DeclRefExpr
*LogicalRef
= Actions
.BuildDeclRefExpr(
5786 IndvarParam
, LogicalTy
, VK_LValue
, {}, nullptr, nullptr, {}, nullptr);
5788 // Capture the Start expression.
5789 CaptureVars
Recap(Actions
);
5790 Expr
*NewStart
= AssertSuccess(Recap
.TransformExpr(StartExpr
));
5791 Expr
*NewStep
= AssertSuccess(Recap
.TransformExpr(Step
));
5793 Expr
*Skip
= AssertSuccess(
5794 Actions
.BuildBinOp(nullptr, {}, BO_Mul
, NewStep
, LogicalRef
));
5795 // TODO: Explicitly cast to the iterator's difference_type instead of
5796 // relying on implicit conversion.
5798 AssertSuccess(Actions
.BuildBinOp(nullptr, {}, BO_Add
, NewStart
, Skip
));
5801 // For range-based for-loops convert the loop counter value to a concrete
5802 // loop variable value by dereferencing the iterator.
5804 AssertSuccess(Actions
.BuildUnaryOp(nullptr, {}, UO_Deref
, Advanced
));
5807 // Assign the result to the output parameter.
5808 Body
= AssertSuccess(Actions
.BuildBinOp(Actions
.getCurScope(), {},
5809 BO_Assign
, TargetRef
, Advanced
));
5811 return cast
<CapturedStmt
>(
5812 AssertSuccess(Actions
.ActOnCapturedRegionEnd(Body
)));
5815 StmtResult
Sema::ActOnOpenMPCanonicalLoop(Stmt
*AStmt
) {
5816 ASTContext
&Ctx
= getASTContext();
5818 // Extract the common elements of ForStmt and CXXForRangeStmt:
5819 // Loop variable, repeat condition, increment
5821 VarDecl
*LIVDecl
, *LUVDecl
;
5822 if (auto *For
= dyn_cast
<ForStmt
>(AStmt
)) {
5823 Stmt
*Init
= For
->getInit();
5824 if (auto *LCVarDeclStmt
= dyn_cast
<DeclStmt
>(Init
)) {
5825 // For statement declares loop variable.
5826 LIVDecl
= cast
<VarDecl
>(LCVarDeclStmt
->getSingleDecl());
5827 } else if (auto *LCAssign
= dyn_cast
<BinaryOperator
>(Init
)) {
5828 // For statement reuses variable.
5829 assert(LCAssign
->getOpcode() == BO_Assign
&&
5830 "init part must be a loop variable assignment");
5831 auto *CounterRef
= cast
<DeclRefExpr
>(LCAssign
->getLHS());
5832 LIVDecl
= cast
<VarDecl
>(CounterRef
->getDecl());
5834 llvm_unreachable("Cannot determine loop variable");
5837 Cond
= For
->getCond();
5838 Inc
= For
->getInc();
5839 } else if (auto *RangeFor
= dyn_cast
<CXXForRangeStmt
>(AStmt
)) {
5840 DeclStmt
*BeginStmt
= RangeFor
->getBeginStmt();
5841 LIVDecl
= cast
<VarDecl
>(BeginStmt
->getSingleDecl());
5842 LUVDecl
= RangeFor
->getLoopVariable();
5844 Cond
= RangeFor
->getCond();
5845 Inc
= RangeFor
->getInc();
5847 llvm_unreachable("unhandled kind of loop");
5849 QualType CounterTy
= LIVDecl
->getType();
5850 QualType LVTy
= LUVDecl
->getType();
5852 // Analyze the loop condition.
5854 BinaryOperator::Opcode CondRel
;
5855 Cond
= Cond
->IgnoreImplicit();
5856 if (auto *CondBinExpr
= dyn_cast
<BinaryOperator
>(Cond
)) {
5857 LHS
= CondBinExpr
->getLHS();
5858 RHS
= CondBinExpr
->getRHS();
5859 CondRel
= CondBinExpr
->getOpcode();
5860 } else if (auto *CondCXXOp
= dyn_cast
<CXXOperatorCallExpr
>(Cond
)) {
5861 assert(CondCXXOp
->getNumArgs() == 2 && "Comparison should have 2 operands");
5862 LHS
= CondCXXOp
->getArg(0);
5863 RHS
= CondCXXOp
->getArg(1);
5864 switch (CondCXXOp
->getOperator()) {
5865 case OO_ExclaimEqual
:
5877 case OO_GreaterEqual
:
5881 llvm_unreachable("unexpected iterator operator");
5884 llvm_unreachable("unexpected loop condition");
5886 // Normalize such that the loop counter is on the LHS.
5887 if (!isa
<DeclRefExpr
>(LHS
->IgnoreImplicit()) ||
5888 cast
<DeclRefExpr
>(LHS
->IgnoreImplicit())->getDecl() != LIVDecl
) {
5889 std::swap(LHS
, RHS
);
5890 CondRel
= BinaryOperator::reverseComparisonOp(CondRel
);
5892 auto *CounterRef
= cast
<DeclRefExpr
>(LHS
->IgnoreImplicit());
5894 // Decide the bit width for the logical iteration counter. By default use the
5895 // unsigned ptrdiff_t integer size (for iterators and pointers).
5896 // TODO: For iterators, use iterator::difference_type,
5897 // std::iterator_traits<>::difference_type or decltype(it - end).
5898 QualType LogicalTy
= Ctx
.getUnsignedPointerDiffType();
5899 if (CounterTy
->isIntegerType()) {
5900 unsigned BitWidth
= Ctx
.getIntWidth(CounterTy
);
5901 LogicalTy
= Ctx
.getIntTypeForBitwidth(BitWidth
, false);
5904 // Analyze the loop increment.
5906 if (auto *IncUn
= dyn_cast
<UnaryOperator
>(Inc
)) {
5908 switch (IncUn
->getOpcode()) {
5918 llvm_unreachable("unhandled unary increment operator");
5920 Step
= IntegerLiteral::Create(
5921 Ctx
, llvm::APInt(Ctx
.getIntWidth(LogicalTy
), Direction
), LogicalTy
, {});
5922 } else if (auto *IncBin
= dyn_cast
<BinaryOperator
>(Inc
)) {
5923 if (IncBin
->getOpcode() == BO_AddAssign
) {
5924 Step
= IncBin
->getRHS();
5925 } else if (IncBin
->getOpcode() == BO_SubAssign
) {
5927 AssertSuccess(BuildUnaryOp(nullptr, {}, UO_Minus
, IncBin
->getRHS()));
5929 llvm_unreachable("unhandled binary increment operator");
5930 } else if (auto *CondCXXOp
= dyn_cast
<CXXOperatorCallExpr
>(Inc
)) {
5931 switch (CondCXXOp
->getOperator()) {
5933 Step
= IntegerLiteral::Create(
5934 Ctx
, llvm::APInt(Ctx
.getIntWidth(LogicalTy
), 1), LogicalTy
, {});
5937 Step
= IntegerLiteral::Create(
5938 Ctx
, llvm::APInt(Ctx
.getIntWidth(LogicalTy
), -1), LogicalTy
, {});
5941 Step
= CondCXXOp
->getArg(1);
5944 Step
= AssertSuccess(
5945 BuildUnaryOp(nullptr, {}, UO_Minus
, CondCXXOp
->getArg(1)));
5948 llvm_unreachable("unhandled overloaded increment operator");
5951 llvm_unreachable("unknown increment expression");
5953 CapturedStmt
*DistanceFunc
=
5954 buildDistanceFunc(*this, LogicalTy
, CondRel
, LHS
, RHS
, Step
);
5955 CapturedStmt
*LoopVarFunc
= buildLoopVarFunc(
5956 *this, LVTy
, LogicalTy
, CounterRef
, Step
, isa
<CXXForRangeStmt
>(AStmt
));
5957 DeclRefExpr
*LVRef
= BuildDeclRefExpr(LUVDecl
, LUVDecl
->getType(), VK_LValue
,
5958 {}, nullptr, nullptr, {}, nullptr);
5959 return OMPCanonicalLoop::create(getASTContext(), AStmt
, DistanceFunc
,
5960 LoopVarFunc
, LVRef
);
5963 StmtResult
Sema::ActOnOpenMPLoopnest(Stmt
*AStmt
) {
5964 // Handle a literal loop.
5965 if (isa
<ForStmt
>(AStmt
) || isa
<CXXForRangeStmt
>(AStmt
))
5966 return ActOnOpenMPCanonicalLoop(AStmt
);
5968 // If not a literal loop, it must be the result of a loop transformation.
5969 OMPExecutableDirective
*LoopTransform
= cast
<OMPExecutableDirective
>(AStmt
);
5971 isOpenMPLoopTransformationDirective(LoopTransform
->getDirectiveKind()) &&
5972 "Loop transformation directive expected");
5973 return LoopTransform
;
5976 static ExprResult
buildUserDefinedMapperRef(Sema
&SemaRef
, Scope
*S
,
5977 CXXScopeSpec
&MapperIdScopeSpec
,
5978 const DeclarationNameInfo
&MapperId
,
5980 Expr
*UnresolvedMapper
);
5982 /// Perform DFS through the structure/class data members trying to find
5983 /// member(s) with user-defined 'default' mapper and generate implicit map
5984 /// clauses for such members with the found 'default' mapper.
5986 processImplicitMapsWithDefaultMappers(Sema
&S
, DSAStackTy
*Stack
,
5987 SmallVectorImpl
<OMPClause
*> &Clauses
) {
5988 // Check for the deault mapper for data members.
5989 if (S
.getLangOpts().OpenMP
< 50)
5991 SmallVector
<OMPClause
*, 4> ImplicitMaps
;
5992 for (int Cnt
= 0, EndCnt
= Clauses
.size(); Cnt
< EndCnt
; ++Cnt
) {
5993 auto *C
= dyn_cast
<OMPMapClause
>(Clauses
[Cnt
]);
5996 SmallVector
<Expr
*, 4> SubExprs
;
5997 auto *MI
= C
->mapperlist_begin();
5998 for (auto I
= C
->varlist_begin(), End
= C
->varlist_end(); I
!= End
;
6000 // Expression is mapped using mapper - skip it.
6004 // Expression is dependent - skip it, build the mapper when it gets
6006 if (E
->isTypeDependent() || E
->isValueDependent() ||
6007 E
->containsUnexpandedParameterPack())
6009 // Array section - need to check for the mapping of the array section
6011 QualType CanonType
= E
->getType().getCanonicalType();
6012 if (CanonType
->isSpecificBuiltinType(BuiltinType::OMPArraySection
)) {
6013 const auto *OASE
= cast
<OMPArraySectionExpr
>(E
->IgnoreParenImpCasts());
6015 OMPArraySectionExpr::getBaseOriginalType(OASE
->getBase());
6017 if (const auto *ATy
= BaseType
->getAsArrayTypeUnsafe())
6018 ElemType
= ATy
->getElementType();
6020 ElemType
= BaseType
->getPointeeType();
6021 CanonType
= ElemType
;
6024 // DFS over data members in structures/classes.
6025 SmallVector
<std::pair
<QualType
, FieldDecl
*>, 4> Types(
6026 1, {CanonType
, nullptr});
6027 llvm::DenseMap
<const Type
*, Expr
*> Visited
;
6028 SmallVector
<std::pair
<FieldDecl
*, unsigned>, 4> ParentChain(
6030 while (!Types
.empty()) {
6033 std::tie(BaseType
, CurFD
) = Types
.pop_back_val();
6034 while (ParentChain
.back().second
== 0)
6035 ParentChain
.pop_back();
6036 --ParentChain
.back().second
;
6037 if (BaseType
.isNull())
6039 // Only structs/classes are allowed to have mappers.
6040 const RecordDecl
*RD
= BaseType
.getCanonicalType()->getAsRecordDecl();
6043 auto It
= Visited
.find(BaseType
.getTypePtr());
6044 if (It
== Visited
.end()) {
6045 // Try to find the associated user-defined mapper.
6046 CXXScopeSpec MapperIdScopeSpec
;
6047 DeclarationNameInfo DefaultMapperId
;
6048 DefaultMapperId
.setName(S
.Context
.DeclarationNames
.getIdentifier(
6049 &S
.Context
.Idents
.get("default")));
6050 DefaultMapperId
.setLoc(E
->getExprLoc());
6051 ExprResult ER
= buildUserDefinedMapperRef(
6052 S
, Stack
->getCurScope(), MapperIdScopeSpec
, DefaultMapperId
,
6053 BaseType
, /*UnresolvedMapper=*/nullptr);
6056 It
= Visited
.try_emplace(BaseType
.getTypePtr(), ER
.get()).first
;
6058 // Found default mapper.
6060 auto *OE
= new (S
.Context
) OpaqueValueExpr(E
->getExprLoc(), CanonType
,
6061 VK_LValue
, OK_Ordinary
, E
);
6062 OE
->setIsUnique(/*V=*/true);
6063 Expr
*BaseExpr
= OE
;
6064 for (const auto &P
: ParentChain
) {
6066 BaseExpr
= S
.BuildMemberExpr(
6067 BaseExpr
, /*IsArrow=*/false, E
->getExprLoc(),
6068 NestedNameSpecifierLoc(), SourceLocation(), P
.first
,
6069 DeclAccessPair::make(P
.first
, P
.first
->getAccess()),
6070 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6071 P
.first
->getType(), VK_LValue
, OK_Ordinary
);
6072 BaseExpr
= S
.DefaultLvalueConversion(BaseExpr
).get();
6076 BaseExpr
= S
.BuildMemberExpr(
6077 BaseExpr
, /*IsArrow=*/false, E
->getExprLoc(),
6078 NestedNameSpecifierLoc(), SourceLocation(), CurFD
,
6079 DeclAccessPair::make(CurFD
, CurFD
->getAccess()),
6080 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6081 CurFD
->getType(), VK_LValue
, OK_Ordinary
);
6082 SubExprs
.push_back(BaseExpr
);
6085 // Check for the "default" mapper for data members.
6086 bool FirstIter
= true;
6087 for (FieldDecl
*FD
: RD
->fields()) {
6090 QualType FieldTy
= FD
->getType();
6091 if (FieldTy
.isNull() ||
6092 !(FieldTy
->isStructureOrClassType() || FieldTy
->isUnionType()))
6096 ParentChain
.emplace_back(CurFD
, 1);
6098 ++ParentChain
.back().second
;
6100 Types
.emplace_back(FieldTy
, FD
);
6104 if (SubExprs
.empty())
6106 CXXScopeSpec MapperIdScopeSpec
;
6107 DeclarationNameInfo MapperId
;
6108 if (OMPClause
*NewClause
= S
.ActOnOpenMPMapClause(
6109 nullptr, C
->getMapTypeModifiers(), C
->getMapTypeModifiersLoc(),
6110 MapperIdScopeSpec
, MapperId
, C
->getMapType(),
6111 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6112 SubExprs
, OMPVarListLocTy()))
6113 Clauses
.push_back(NewClause
);
6117 bool Sema::mapLoopConstruct(llvm::SmallVector
<OMPClause
*> &ClausesWithoutBind
,
6118 ArrayRef
<OMPClause
*> Clauses
,
6119 OpenMPBindClauseKind BindKind
,
6120 OpenMPDirectiveKind
&Kind
,
6121 OpenMPDirectiveKind
&PrevMappedDirective
) {
6123 bool UseClausesWithoutBind
= false;
6125 // Restricting to "#pragma omp loop bind"
6126 if (getLangOpts().OpenMP
>= 50 && Kind
== OMPD_loop
) {
6127 if (BindKind
== OMPC_BIND_unknown
) {
6128 // Setting the enclosing teams or parallel construct for the loop
6129 // directive without bind clause.
6130 BindKind
= OMPC_BIND_thread
; // Default bind(thread) if binding is unknown
6132 const OpenMPDirectiveKind ParentDirective
=
6133 DSAStack
->getParentDirective();
6134 if (ParentDirective
== OMPD_unknown
) {
6135 Diag(DSAStack
->getDefaultDSALocation(),
6136 diag::err_omp_bind_required_on_loop
);
6137 } else if (ParentDirective
== OMPD_parallel
||
6138 ParentDirective
== OMPD_target_parallel
) {
6139 BindKind
= OMPC_BIND_parallel
;
6140 } else if (ParentDirective
== OMPD_teams
||
6141 ParentDirective
== OMPD_target_teams
) {
6142 BindKind
= OMPC_BIND_teams
;
6145 // bind clause is present, so we should set flag indicating to only
6146 // use the clauses that aren't the bind clause for the new directive that
6147 // loop is lowered to.
6148 UseClausesWithoutBind
= true;
6151 for (OMPClause
*C
: Clauses
) {
6152 // Spec restriction : bind(teams) and reduction not permitted.
6153 if (BindKind
== OMPC_BIND_teams
&&
6154 C
->getClauseKind() == llvm::omp::Clause::OMPC_reduction
)
6155 Diag(DSAStack
->getDefaultDSALocation(),
6156 diag::err_omp_loop_reduction_clause
);
6158 // A new Vector ClausesWithoutBind, which does not contain the bind
6159 // clause, for passing to new directive.
6160 if (C
->getClauseKind() != llvm::omp::Clause::OMPC_bind
)
6161 ClausesWithoutBind
.push_back(C
);
6165 case OMPC_BIND_parallel
:
6167 DSAStack
->setCurrentDirective(OMPD_for
);
6168 DSAStack
->setMappedDirective(OMPD_loop
);
6169 PrevMappedDirective
= OMPD_loop
;
6171 case OMPC_BIND_teams
:
6172 Kind
= OMPD_distribute
;
6173 DSAStack
->setCurrentDirective(OMPD_distribute
);
6174 DSAStack
->setMappedDirective(OMPD_loop
);
6175 PrevMappedDirective
= OMPD_loop
;
6177 case OMPC_BIND_thread
:
6179 DSAStack
->setCurrentDirective(OMPD_simd
);
6180 DSAStack
->setMappedDirective(OMPD_loop
);
6181 PrevMappedDirective
= OMPD_loop
;
6183 case OMPC_BIND_unknown
:
6186 } else if (PrevMappedDirective
== OMPD_loop
) {
6187 /// An initial pass after recognizing all the statements is done in the
6188 /// Parser when the directive OMPD_loop is mapped to OMPD_for,
6189 /// OMPD_distribute or OMPD_simd. A second transform pass with call from
6190 /// clang::TreeTransform::TransformOMPExecutableDirective() is done
6191 /// with the Directive as one of the above mapped directive without
6192 /// the bind clause. Then "PrevMappedDirective" stored in the
6193 /// OMPExecutableDirective is accessed and hence this else statement.
6195 DSAStack
->setMappedDirective(OMPD_loop
);
6198 return UseClausesWithoutBind
;
6201 StmtResult
Sema::ActOnOpenMPExecutableDirective(
6202 OpenMPDirectiveKind Kind
, const DeclarationNameInfo
&DirName
,
6203 OpenMPDirectiveKind CancelRegion
, ArrayRef
<OMPClause
*> Clauses
,
6204 Stmt
*AStmt
, SourceLocation StartLoc
, SourceLocation EndLoc
,
6205 OpenMPDirectiveKind PrevMappedDirective
) {
6206 StmtResult Res
= StmtError();
6207 OpenMPBindClauseKind BindKind
= OMPC_BIND_unknown
;
6208 if (const OMPBindClause
*BC
=
6209 OMPExecutableDirective::getSingleClause
<OMPBindClause
>(Clauses
))
6210 BindKind
= BC
->getBindKind();
6211 // First check CancelRegion which is then used in checkNestingOfRegions.
6212 if (checkCancelRegion(*this, Kind
, CancelRegion
, StartLoc
) ||
6213 checkNestingOfRegions(*this, DSAStack
, Kind
, DirName
, CancelRegion
,
6214 BindKind
, StartLoc
))
6217 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6218 if (getLangOpts().HIP
&& (isOpenMPTargetExecutionDirective(Kind
) ||
6219 isOpenMPTargetDataManagementDirective(Kind
)))
6220 Diag(StartLoc
, diag::warn_hip_omp_target_directives
);
6222 llvm::SmallVector
<OMPClause
*> ClausesWithoutBind
;
6223 bool UseClausesWithoutBind
= false;
6225 UseClausesWithoutBind
= mapLoopConstruct(ClausesWithoutBind
, Clauses
,
6226 BindKind
, Kind
, PrevMappedDirective
);
6228 llvm::SmallVector
<OMPClause
*, 8> ClausesWithImplicit
;
6229 VarsWithInheritedDSAType VarsWithInheritedDSA
;
6230 bool ErrorFound
= false;
6231 if (getLangOpts().OpenMP
>= 50 && UseClausesWithoutBind
) {
6232 ClausesWithImplicit
.append(ClausesWithoutBind
.begin(),
6233 ClausesWithoutBind
.end());
6235 ClausesWithImplicit
.append(Clauses
.begin(), Clauses
.end());
6237 if (AStmt
&& !CurContext
->isDependentContext() && Kind
!= OMPD_atomic
&&
6238 Kind
!= OMPD_critical
&& Kind
!= OMPD_section
&& Kind
!= OMPD_master
&&
6239 Kind
!= OMPD_masked
&& !isOpenMPLoopTransformationDirective(Kind
)) {
6240 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
6242 // Check default data sharing attributes for referenced variables.
6243 DSAAttrChecker
DSAChecker(DSAStack
, *this, cast
<CapturedStmt
>(AStmt
));
6244 int ThisCaptureLevel
= getOpenMPCaptureLevels(Kind
);
6246 while (--ThisCaptureLevel
>= 0)
6247 S
= cast
<CapturedStmt
>(S
)->getCapturedStmt();
6248 DSAChecker
.Visit(S
);
6249 if (!isOpenMPTargetDataManagementDirective(Kind
) &&
6250 !isOpenMPTaskingDirective(Kind
)) {
6251 // Visit subcaptures to generate implicit clauses for captured vars.
6252 auto *CS
= cast
<CapturedStmt
>(AStmt
);
6253 SmallVector
<OpenMPDirectiveKind
, 4> CaptureRegions
;
6254 getOpenMPCaptureRegions(CaptureRegions
, Kind
);
6255 // Ignore outer tasking regions for target directives.
6256 if (CaptureRegions
.size() > 1 && CaptureRegions
.front() == OMPD_task
)
6257 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
6258 DSAChecker
.visitSubCaptures(CS
);
6260 if (DSAChecker
.isErrorFound())
6262 // Generate list of implicitly defined firstprivate variables.
6263 VarsWithInheritedDSA
= DSAChecker
.getVarsWithInheritedDSA();
6265 SmallVector
<Expr
*, 4> ImplicitFirstprivates(
6266 DSAChecker
.getImplicitFirstprivate().begin(),
6267 DSAChecker
.getImplicitFirstprivate().end());
6268 SmallVector
<Expr
*, 4> ImplicitPrivates(
6269 DSAChecker
.getImplicitPrivate().begin(),
6270 DSAChecker
.getImplicitPrivate().end());
6271 const unsigned DefaultmapKindNum
= OMPC_DEFAULTMAP_pointer
+ 1;
6272 SmallVector
<Expr
*, 4> ImplicitMaps
[DefaultmapKindNum
][OMPC_MAP_delete
];
6273 SmallVector
<OpenMPMapModifierKind
, NumberOfOMPMapClauseModifiers
>
6274 ImplicitMapModifiers
[DefaultmapKindNum
];
6275 SmallVector
<SourceLocation
, NumberOfOMPMapClauseModifiers
>
6276 ImplicitMapModifiersLoc
[DefaultmapKindNum
];
6277 // Get the original location of present modifier from Defaultmap clause.
6278 SourceLocation PresentModifierLocs
[DefaultmapKindNum
];
6279 for (OMPClause
*C
: Clauses
) {
6280 if (auto *DMC
= dyn_cast
<OMPDefaultmapClause
>(C
))
6281 if (DMC
->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present
)
6282 PresentModifierLocs
[DMC
->getDefaultmapKind()] =
6283 DMC
->getDefaultmapModifierLoc();
6285 for (unsigned VC
= 0; VC
< DefaultmapKindNum
; ++VC
) {
6286 auto Kind
= static_cast<OpenMPDefaultmapClauseKind
>(VC
);
6287 for (unsigned I
= 0; I
< OMPC_MAP_delete
; ++I
) {
6288 ArrayRef
<Expr
*> ImplicitMap
= DSAChecker
.getImplicitMap(
6289 Kind
, static_cast<OpenMPMapClauseKind
>(I
));
6290 ImplicitMaps
[VC
][I
].append(ImplicitMap
.begin(), ImplicitMap
.end());
6292 ArrayRef
<OpenMPMapModifierKind
> ImplicitModifier
=
6293 DSAChecker
.getImplicitMapModifier(Kind
);
6294 ImplicitMapModifiers
[VC
].append(ImplicitModifier
.begin(),
6295 ImplicitModifier
.end());
6296 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc
[VC
]),
6297 ImplicitModifier
.size(), PresentModifierLocs
[VC
]);
6299 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6300 for (OMPClause
*C
: Clauses
) {
6301 if (auto *IRC
= dyn_cast
<OMPInReductionClause
>(C
)) {
6302 for (Expr
*E
: IRC
->taskgroup_descriptors())
6304 ImplicitFirstprivates
.emplace_back(E
);
6306 // OpenMP 5.0, 2.10.1 task Construct
6307 // [detach clause]... The event-handle will be considered as if it was
6308 // specified on a firstprivate clause.
6309 if (auto *DC
= dyn_cast
<OMPDetachClause
>(C
))
6310 ImplicitFirstprivates
.push_back(DC
->getEventHandler());
6312 if (!ImplicitFirstprivates
.empty()) {
6313 if (OMPClause
*Implicit
= ActOnOpenMPFirstprivateClause(
6314 ImplicitFirstprivates
, SourceLocation(), SourceLocation(),
6315 SourceLocation())) {
6316 ClausesWithImplicit
.push_back(Implicit
);
6317 ErrorFound
= cast
<OMPFirstprivateClause
>(Implicit
)->varlist_size() !=
6318 ImplicitFirstprivates
.size();
6323 if (!ImplicitPrivates
.empty()) {
6324 if (OMPClause
*Implicit
=
6325 ActOnOpenMPPrivateClause(ImplicitPrivates
, SourceLocation(),
6326 SourceLocation(), SourceLocation())) {
6327 ClausesWithImplicit
.push_back(Implicit
);
6328 ErrorFound
= cast
<OMPPrivateClause
>(Implicit
)->varlist_size() !=
6329 ImplicitPrivates
.size();
6334 // OpenMP 5.0 [2.19.7]
6335 // If a list item appears in a reduction, lastprivate or linear
6336 // clause on a combined target construct then it is treated as
6337 // if it also appears in a map clause with a map-type of tofrom
6338 if (getLangOpts().OpenMP
>= 50 && Kind
!= OMPD_target
&&
6339 isOpenMPTargetExecutionDirective(Kind
)) {
6340 SmallVector
<Expr
*, 4> ImplicitExprs
;
6341 for (OMPClause
*C
: Clauses
) {
6342 if (auto *RC
= dyn_cast
<OMPReductionClause
>(C
))
6343 for (Expr
*E
: RC
->varlists())
6344 if (!isa
<DeclRefExpr
>(E
->IgnoreParenImpCasts()))
6345 ImplicitExprs
.emplace_back(E
);
6347 if (!ImplicitExprs
.empty()) {
6348 ArrayRef
<Expr
*> Exprs
= ImplicitExprs
;
6349 CXXScopeSpec MapperIdScopeSpec
;
6350 DeclarationNameInfo MapperId
;
6351 if (OMPClause
*Implicit
= ActOnOpenMPMapClause(
6352 nullptr, OMPC_MAP_MODIFIER_unknown
, SourceLocation(),
6353 MapperIdScopeSpec
, MapperId
, OMPC_MAP_tofrom
,
6354 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6355 Exprs
, OMPVarListLocTy(), /*NoDiagnose=*/true))
6356 ClausesWithImplicit
.emplace_back(Implicit
);
6359 for (unsigned I
= 0, E
= DefaultmapKindNum
; I
< E
; ++I
) {
6360 int ClauseKindCnt
= -1;
6361 for (ArrayRef
<Expr
*> ImplicitMap
: ImplicitMaps
[I
]) {
6363 if (ImplicitMap
.empty())
6365 CXXScopeSpec MapperIdScopeSpec
;
6366 DeclarationNameInfo MapperId
;
6367 auto Kind
= static_cast<OpenMPMapClauseKind
>(ClauseKindCnt
);
6368 if (OMPClause
*Implicit
= ActOnOpenMPMapClause(
6369 nullptr, ImplicitMapModifiers
[I
], ImplicitMapModifiersLoc
[I
],
6370 MapperIdScopeSpec
, MapperId
, Kind
, /*IsMapTypeImplicit=*/true,
6371 SourceLocation(), SourceLocation(), ImplicitMap
,
6372 OMPVarListLocTy())) {
6373 ClausesWithImplicit
.emplace_back(Implicit
);
6374 ErrorFound
|= cast
<OMPMapClause
>(Implicit
)->varlist_size() !=
6381 // Build expressions for implicit maps of data members with 'default'
6383 if (LangOpts
.OpenMP
>= 50)
6384 processImplicitMapsWithDefaultMappers(*this, DSAStack
,
6385 ClausesWithImplicit
);
6388 llvm::SmallVector
<OpenMPDirectiveKind
, 4> AllowedNameModifiers
;
6391 Res
= ActOnOpenMPParallelDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6393 AllowedNameModifiers
.push_back(OMPD_parallel
);
6396 Res
= ActOnOpenMPSimdDirective(ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
,
6397 VarsWithInheritedDSA
);
6398 if (LangOpts
.OpenMP
>= 50)
6399 AllowedNameModifiers
.push_back(OMPD_simd
);
6403 ActOnOpenMPTileDirective(ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
);
6406 Res
= ActOnOpenMPUnrollDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6410 Res
= ActOnOpenMPForDirective(ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
,
6411 VarsWithInheritedDSA
);
6414 Res
= ActOnOpenMPForSimdDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6415 EndLoc
, VarsWithInheritedDSA
);
6416 if (LangOpts
.OpenMP
>= 50)
6417 AllowedNameModifiers
.push_back(OMPD_simd
);
6420 Res
= ActOnOpenMPSectionsDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6424 assert(ClausesWithImplicit
.empty() &&
6425 "No clauses are allowed for 'omp section' directive");
6426 Res
= ActOnOpenMPSectionDirective(AStmt
, StartLoc
, EndLoc
);
6429 Res
= ActOnOpenMPSingleDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6433 assert(ClausesWithImplicit
.empty() &&
6434 "No clauses are allowed for 'omp master' directive");
6435 Res
= ActOnOpenMPMasterDirective(AStmt
, StartLoc
, EndLoc
);
6438 Res
= ActOnOpenMPMaskedDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6442 Res
= ActOnOpenMPCriticalDirective(DirName
, ClausesWithImplicit
, AStmt
,
6445 case OMPD_parallel_for
:
6446 Res
= ActOnOpenMPParallelForDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6447 EndLoc
, VarsWithInheritedDSA
);
6448 AllowedNameModifiers
.push_back(OMPD_parallel
);
6450 case OMPD_parallel_for_simd
:
6451 Res
= ActOnOpenMPParallelForSimdDirective(
6452 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6453 AllowedNameModifiers
.push_back(OMPD_parallel
);
6454 if (LangOpts
.OpenMP
>= 50)
6455 AllowedNameModifiers
.push_back(OMPD_simd
);
6459 ActOnOpenMPScopeDirective(ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
);
6461 case OMPD_parallel_master
:
6462 Res
= ActOnOpenMPParallelMasterDirective(ClausesWithImplicit
, AStmt
,
6464 AllowedNameModifiers
.push_back(OMPD_parallel
);
6466 case OMPD_parallel_masked
:
6467 Res
= ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit
, AStmt
,
6469 AllowedNameModifiers
.push_back(OMPD_parallel
);
6471 case OMPD_parallel_sections
:
6472 Res
= ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit
, AStmt
,
6474 AllowedNameModifiers
.push_back(OMPD_parallel
);
6478 ActOnOpenMPTaskDirective(ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
);
6479 AllowedNameModifiers
.push_back(OMPD_task
);
6481 case OMPD_taskyield
:
6482 assert(ClausesWithImplicit
.empty() &&
6483 "No clauses are allowed for 'omp taskyield' directive");
6484 assert(AStmt
== nullptr &&
6485 "No associated statement allowed for 'omp taskyield' directive");
6486 Res
= ActOnOpenMPTaskyieldDirective(StartLoc
, EndLoc
);
6489 assert(AStmt
== nullptr &&
6490 "No associated statement allowed for 'omp error' directive");
6491 Res
= ActOnOpenMPErrorDirective(ClausesWithImplicit
, StartLoc
, EndLoc
);
6494 assert(ClausesWithImplicit
.empty() &&
6495 "No clauses are allowed for 'omp barrier' directive");
6496 assert(AStmt
== nullptr &&
6497 "No associated statement allowed for 'omp barrier' directive");
6498 Res
= ActOnOpenMPBarrierDirective(StartLoc
, EndLoc
);
6501 assert(AStmt
== nullptr &&
6502 "No associated statement allowed for 'omp taskwait' directive");
6503 Res
= ActOnOpenMPTaskwaitDirective(ClausesWithImplicit
, StartLoc
, EndLoc
);
6505 case OMPD_taskgroup
:
6506 Res
= ActOnOpenMPTaskgroupDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6510 assert(AStmt
== nullptr &&
6511 "No associated statement allowed for 'omp flush' directive");
6512 Res
= ActOnOpenMPFlushDirective(ClausesWithImplicit
, StartLoc
, EndLoc
);
6515 assert(AStmt
== nullptr &&
6516 "No associated statement allowed for 'omp depobj' directive");
6517 Res
= ActOnOpenMPDepobjDirective(ClausesWithImplicit
, StartLoc
, EndLoc
);
6520 assert(AStmt
== nullptr &&
6521 "No associated statement allowed for 'omp scan' directive");
6522 Res
= ActOnOpenMPScanDirective(ClausesWithImplicit
, StartLoc
, EndLoc
);
6525 Res
= ActOnOpenMPOrderedDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6529 Res
= ActOnOpenMPAtomicDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6534 ActOnOpenMPTeamsDirective(ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
);
6537 Res
= ActOnOpenMPTargetDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6539 AllowedNameModifiers
.push_back(OMPD_target
);
6541 case OMPD_target_parallel
:
6542 Res
= ActOnOpenMPTargetParallelDirective(ClausesWithImplicit
, AStmt
,
6544 AllowedNameModifiers
.push_back(OMPD_target
);
6545 AllowedNameModifiers
.push_back(OMPD_parallel
);
6547 case OMPD_target_parallel_for
:
6548 Res
= ActOnOpenMPTargetParallelForDirective(
6549 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6550 AllowedNameModifiers
.push_back(OMPD_target
);
6551 AllowedNameModifiers
.push_back(OMPD_parallel
);
6553 case OMPD_cancellation_point
:
6554 assert(ClausesWithImplicit
.empty() &&
6555 "No clauses are allowed for 'omp cancellation point' directive");
6556 assert(AStmt
== nullptr && "No associated statement allowed for 'omp "
6557 "cancellation point' directive");
6558 Res
= ActOnOpenMPCancellationPointDirective(StartLoc
, EndLoc
, CancelRegion
);
6561 assert(AStmt
== nullptr &&
6562 "No associated statement allowed for 'omp cancel' directive");
6563 Res
= ActOnOpenMPCancelDirective(ClausesWithImplicit
, StartLoc
, EndLoc
,
6565 AllowedNameModifiers
.push_back(OMPD_cancel
);
6567 case OMPD_target_data
:
6568 Res
= ActOnOpenMPTargetDataDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6570 AllowedNameModifiers
.push_back(OMPD_target_data
);
6572 case OMPD_target_enter_data
:
6573 Res
= ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit
, StartLoc
,
6575 AllowedNameModifiers
.push_back(OMPD_target_enter_data
);
6577 case OMPD_target_exit_data
:
6578 Res
= ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit
, StartLoc
,
6580 AllowedNameModifiers
.push_back(OMPD_target_exit_data
);
6583 Res
= ActOnOpenMPTaskLoopDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6584 EndLoc
, VarsWithInheritedDSA
);
6585 AllowedNameModifiers
.push_back(OMPD_taskloop
);
6587 case OMPD_taskloop_simd
:
6588 Res
= ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6589 EndLoc
, VarsWithInheritedDSA
);
6590 AllowedNameModifiers
.push_back(OMPD_taskloop
);
6591 if (LangOpts
.OpenMP
>= 50)
6592 AllowedNameModifiers
.push_back(OMPD_simd
);
6594 case OMPD_master_taskloop
:
6595 Res
= ActOnOpenMPMasterTaskLoopDirective(
6596 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6597 AllowedNameModifiers
.push_back(OMPD_taskloop
);
6599 case OMPD_masked_taskloop
:
6600 Res
= ActOnOpenMPMaskedTaskLoopDirective(
6601 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6602 AllowedNameModifiers
.push_back(OMPD_taskloop
);
6604 case OMPD_master_taskloop_simd
:
6605 Res
= ActOnOpenMPMasterTaskLoopSimdDirective(
6606 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6607 AllowedNameModifiers
.push_back(OMPD_taskloop
);
6608 if (LangOpts
.OpenMP
>= 50)
6609 AllowedNameModifiers
.push_back(OMPD_simd
);
6611 case OMPD_masked_taskloop_simd
:
6612 Res
= ActOnOpenMPMaskedTaskLoopSimdDirective(
6613 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6614 if (LangOpts
.OpenMP
>= 51) {
6615 AllowedNameModifiers
.push_back(OMPD_taskloop
);
6616 AllowedNameModifiers
.push_back(OMPD_simd
);
6619 case OMPD_parallel_master_taskloop
:
6620 Res
= ActOnOpenMPParallelMasterTaskLoopDirective(
6621 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6622 AllowedNameModifiers
.push_back(OMPD_taskloop
);
6623 AllowedNameModifiers
.push_back(OMPD_parallel
);
6625 case OMPD_parallel_masked_taskloop
:
6626 Res
= ActOnOpenMPParallelMaskedTaskLoopDirective(
6627 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6628 if (LangOpts
.OpenMP
>= 51) {
6629 AllowedNameModifiers
.push_back(OMPD_taskloop
);
6630 AllowedNameModifiers
.push_back(OMPD_parallel
);
6633 case OMPD_parallel_master_taskloop_simd
:
6634 Res
= ActOnOpenMPParallelMasterTaskLoopSimdDirective(
6635 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6636 AllowedNameModifiers
.push_back(OMPD_taskloop
);
6637 AllowedNameModifiers
.push_back(OMPD_parallel
);
6638 if (LangOpts
.OpenMP
>= 50)
6639 AllowedNameModifiers
.push_back(OMPD_simd
);
6641 case OMPD_parallel_masked_taskloop_simd
:
6642 Res
= ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
6643 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6644 if (LangOpts
.OpenMP
>= 51) {
6645 AllowedNameModifiers
.push_back(OMPD_taskloop
);
6646 AllowedNameModifiers
.push_back(OMPD_parallel
);
6647 AllowedNameModifiers
.push_back(OMPD_simd
);
6650 case OMPD_distribute
:
6651 Res
= ActOnOpenMPDistributeDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6652 EndLoc
, VarsWithInheritedDSA
);
6654 case OMPD_target_update
:
6655 Res
= ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit
, StartLoc
,
6657 AllowedNameModifiers
.push_back(OMPD_target_update
);
6659 case OMPD_distribute_parallel_for
:
6660 Res
= ActOnOpenMPDistributeParallelForDirective(
6661 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6662 AllowedNameModifiers
.push_back(OMPD_parallel
);
6664 case OMPD_distribute_parallel_for_simd
:
6665 Res
= ActOnOpenMPDistributeParallelForSimdDirective(
6666 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6667 AllowedNameModifiers
.push_back(OMPD_parallel
);
6668 if (LangOpts
.OpenMP
>= 50)
6669 AllowedNameModifiers
.push_back(OMPD_simd
);
6671 case OMPD_distribute_simd
:
6672 Res
= ActOnOpenMPDistributeSimdDirective(
6673 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6674 if (LangOpts
.OpenMP
>= 50)
6675 AllowedNameModifiers
.push_back(OMPD_simd
);
6677 case OMPD_target_parallel_for_simd
:
6678 Res
= ActOnOpenMPTargetParallelForSimdDirective(
6679 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6680 AllowedNameModifiers
.push_back(OMPD_target
);
6681 AllowedNameModifiers
.push_back(OMPD_parallel
);
6682 if (LangOpts
.OpenMP
>= 50)
6683 AllowedNameModifiers
.push_back(OMPD_simd
);
6685 case OMPD_target_simd
:
6686 Res
= ActOnOpenMPTargetSimdDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6687 EndLoc
, VarsWithInheritedDSA
);
6688 AllowedNameModifiers
.push_back(OMPD_target
);
6689 if (LangOpts
.OpenMP
>= 50)
6690 AllowedNameModifiers
.push_back(OMPD_simd
);
6692 case OMPD_teams_distribute
:
6693 Res
= ActOnOpenMPTeamsDistributeDirective(
6694 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6696 case OMPD_teams_distribute_simd
:
6697 Res
= ActOnOpenMPTeamsDistributeSimdDirective(
6698 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6699 if (LangOpts
.OpenMP
>= 50)
6700 AllowedNameModifiers
.push_back(OMPD_simd
);
6702 case OMPD_teams_distribute_parallel_for_simd
:
6703 Res
= ActOnOpenMPTeamsDistributeParallelForSimdDirective(
6704 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6705 AllowedNameModifiers
.push_back(OMPD_parallel
);
6706 if (LangOpts
.OpenMP
>= 50)
6707 AllowedNameModifiers
.push_back(OMPD_simd
);
6709 case OMPD_teams_distribute_parallel_for
:
6710 Res
= ActOnOpenMPTeamsDistributeParallelForDirective(
6711 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6712 AllowedNameModifiers
.push_back(OMPD_parallel
);
6714 case OMPD_target_teams
:
6715 Res
= ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6717 AllowedNameModifiers
.push_back(OMPD_target
);
6719 case OMPD_target_teams_distribute
:
6720 Res
= ActOnOpenMPTargetTeamsDistributeDirective(
6721 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6722 AllowedNameModifiers
.push_back(OMPD_target
);
6724 case OMPD_target_teams_distribute_parallel_for
:
6725 Res
= ActOnOpenMPTargetTeamsDistributeParallelForDirective(
6726 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6727 AllowedNameModifiers
.push_back(OMPD_target
);
6728 AllowedNameModifiers
.push_back(OMPD_parallel
);
6730 case OMPD_target_teams_distribute_parallel_for_simd
:
6731 Res
= ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
6732 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6733 AllowedNameModifiers
.push_back(OMPD_target
);
6734 AllowedNameModifiers
.push_back(OMPD_parallel
);
6735 if (LangOpts
.OpenMP
>= 50)
6736 AllowedNameModifiers
.push_back(OMPD_simd
);
6738 case OMPD_target_teams_distribute_simd
:
6739 Res
= ActOnOpenMPTargetTeamsDistributeSimdDirective(
6740 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6741 AllowedNameModifiers
.push_back(OMPD_target
);
6742 if (LangOpts
.OpenMP
>= 50)
6743 AllowedNameModifiers
.push_back(OMPD_simd
);
6746 assert(AStmt
== nullptr &&
6747 "No associated statement allowed for 'omp interop' directive");
6748 Res
= ActOnOpenMPInteropDirective(ClausesWithImplicit
, StartLoc
, EndLoc
);
6751 Res
= ActOnOpenMPDispatchDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6755 Res
= ActOnOpenMPGenericLoopDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6756 EndLoc
, VarsWithInheritedDSA
);
6758 case OMPD_teams_loop
:
6759 Res
= ActOnOpenMPTeamsGenericLoopDirective(
6760 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6762 case OMPD_target_teams_loop
:
6763 Res
= ActOnOpenMPTargetTeamsGenericLoopDirective(
6764 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6765 AllowedNameModifiers
.push_back(OMPD_target
);
6767 case OMPD_parallel_loop
:
6768 Res
= ActOnOpenMPParallelGenericLoopDirective(
6769 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6771 case OMPD_target_parallel_loop
:
6772 Res
= ActOnOpenMPTargetParallelGenericLoopDirective(
6773 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6775 case OMPD_declare_target
:
6776 case OMPD_end_declare_target
:
6777 case OMPD_threadprivate
:
6779 case OMPD_declare_reduction
:
6780 case OMPD_declare_mapper
:
6781 case OMPD_declare_simd
:
6783 case OMPD_declare_variant
:
6784 case OMPD_begin_declare_variant
:
6785 case OMPD_end_declare_variant
:
6786 llvm_unreachable("OpenMP Directive is not allowed");
6789 llvm_unreachable("Unknown OpenMP directive");
6792 ErrorFound
= Res
.isInvalid() || ErrorFound
;
6794 // Check variables in the clauses if default(none) or
6795 // default(firstprivate) was specified.
6796 if (DSAStack
->getDefaultDSA() == DSA_none
||
6797 DSAStack
->getDefaultDSA() == DSA_private
||
6798 DSAStack
->getDefaultDSA() == DSA_firstprivate
) {
6799 DSAAttrChecker
DSAChecker(DSAStack
, *this, nullptr);
6800 for (OMPClause
*C
: Clauses
) {
6801 switch (C
->getClauseKind()) {
6802 case OMPC_num_threads
:
6803 case OMPC_dist_schedule
:
6804 // Do not analyse if no parent teams directive.
6805 if (isOpenMPTeamsDirective(Kind
))
6809 if (isOpenMPTeamsDirective(Kind
) &&
6810 cast
<OMPIfClause
>(C
)->getNameModifier() != OMPD_target
)
6812 if (isOpenMPParallelDirective(Kind
) &&
6813 isOpenMPTaskLoopDirective(Kind
) &&
6814 cast
<OMPIfClause
>(C
)->getNameModifier() != OMPD_parallel
)
6820 case OMPC_grainsize
:
6821 case OMPC_num_tasks
:
6824 case OMPC_novariants
:
6825 case OMPC_nocontext
:
6826 // Do not analyze if no parent parallel directive.
6827 if (isOpenMPParallelDirective(Kind
))
6832 case OMPC_num_teams
:
6833 case OMPC_thread_limit
:
6840 case OMPC_proc_bind
:
6842 case OMPC_firstprivate
:
6843 case OMPC_lastprivate
:
6845 case OMPC_reduction
:
6846 case OMPC_task_reduction
:
6847 case OMPC_in_reduction
:
6851 case OMPC_copyprivate
:
6854 case OMPC_mergeable
:
6871 case OMPC_defaultmap
:
6874 case OMPC_use_device_ptr
:
6875 case OMPC_use_device_addr
:
6876 case OMPC_is_device_ptr
:
6877 case OMPC_has_device_addr
:
6878 case OMPC_nontemporal
:
6881 case OMPC_inclusive
:
6882 case OMPC_exclusive
:
6883 case OMPC_uses_allocators
:
6888 case OMPC_allocator
:
6891 case OMPC_threadprivate
:
6894 case OMPC_unified_address
:
6895 case OMPC_unified_shared_memory
:
6896 case OMPC_reverse_offload
:
6897 case OMPC_dynamic_allocators
:
6898 case OMPC_atomic_default_mem_order
:
6899 case OMPC_device_type
:
6906 llvm_unreachable("Unexpected clause");
6908 for (Stmt
*CC
: C
->children()) {
6910 DSAChecker
.Visit(CC
);
6913 for (const auto &P
: DSAChecker
.getVarsWithInheritedDSA())
6914 VarsWithInheritedDSA
[P
.getFirst()] = P
.getSecond();
6916 for (const auto &P
: VarsWithInheritedDSA
) {
6917 if (P
.getFirst()->isImplicit() || isa
<OMPCapturedExprDecl
>(P
.getFirst()))
6920 if (DSAStack
->getDefaultDSA() == DSA_none
||
6921 DSAStack
->getDefaultDSA() == DSA_private
||
6922 DSAStack
->getDefaultDSA() == DSA_firstprivate
) {
6923 Diag(P
.second
->getExprLoc(), diag::err_omp_no_dsa_for_variable
)
6924 << P
.first
<< P
.second
->getSourceRange();
6925 Diag(DSAStack
->getDefaultDSALocation(), diag::note_omp_default_dsa_none
);
6926 } else if (getLangOpts().OpenMP
>= 50) {
6927 Diag(P
.second
->getExprLoc(),
6928 diag::err_omp_defaultmap_no_attr_for_variable
)
6929 << P
.first
<< P
.second
->getSourceRange();
6930 Diag(DSAStack
->getDefaultDSALocation(),
6931 diag::note_omp_defaultmap_attr_none
);
6935 if (!AllowedNameModifiers
.empty())
6936 ErrorFound
= checkIfClauses(*this, Kind
, Clauses
, AllowedNameModifiers
) ||
6942 if (!CurContext
->isDependentContext() &&
6943 isOpenMPTargetExecutionDirective(Kind
) &&
6944 !(DSAStack
->hasRequiresDeclWithClause
<OMPUnifiedSharedMemoryClause
>() ||
6945 DSAStack
->hasRequiresDeclWithClause
<OMPUnifiedAddressClause
>() ||
6946 DSAStack
->hasRequiresDeclWithClause
<OMPReverseOffloadClause
>() ||
6947 DSAStack
->hasRequiresDeclWithClause
<OMPDynamicAllocatorsClause
>())) {
6948 // Register target to DSA Stack.
6949 DSAStack
->addTargetDirLocation(StartLoc
);
6955 Sema::DeclGroupPtrTy
Sema::ActOnOpenMPDeclareSimdDirective(
6956 DeclGroupPtrTy DG
, OMPDeclareSimdDeclAttr::BranchStateTy BS
, Expr
*Simdlen
,
6957 ArrayRef
<Expr
*> Uniforms
, ArrayRef
<Expr
*> Aligneds
,
6958 ArrayRef
<Expr
*> Alignments
, ArrayRef
<Expr
*> Linears
,
6959 ArrayRef
<unsigned> LinModifiers
, ArrayRef
<Expr
*> Steps
, SourceRange SR
) {
6960 assert(Aligneds
.size() == Alignments
.size());
6961 assert(Linears
.size() == LinModifiers
.size());
6962 assert(Linears
.size() == Steps
.size());
6963 if (!DG
|| DG
.get().isNull())
6964 return DeclGroupPtrTy();
6966 const int SimdId
= 0;
6967 if (!DG
.get().isSingleDecl()) {
6968 Diag(SR
.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant
)
6972 Decl
*ADecl
= DG
.get().getSingleDecl();
6973 if (auto *FTD
= dyn_cast
<FunctionTemplateDecl
>(ADecl
))
6974 ADecl
= FTD
->getTemplatedDecl();
6976 auto *FD
= dyn_cast
<FunctionDecl
>(ADecl
);
6978 Diag(ADecl
->getLocation(), diag::err_omp_function_expected
) << SimdId
;
6979 return DeclGroupPtrTy();
6982 // OpenMP [2.8.2, declare simd construct, Description]
6983 // The parameter of the simdlen clause must be a constant positive integer
6987 SL
= VerifyPositiveIntegerConstantInClause(Simdlen
, OMPC_simdlen
);
6988 // OpenMP [2.8.2, declare simd construct, Description]
6989 // The special this pointer can be used as if was one of the arguments to the
6990 // function in any of the linear, aligned, or uniform clauses.
6991 // The uniform clause declares one or more arguments to have an invariant
6992 // value for all concurrent invocations of the function in the execution of a
6993 // single SIMD loop.
6994 llvm::DenseMap
<const Decl
*, const Expr
*> UniformedArgs
;
6995 const Expr
*UniformedLinearThis
= nullptr;
6996 for (const Expr
*E
: Uniforms
) {
6997 E
= E
->IgnoreParenImpCasts();
6998 if (const auto *DRE
= dyn_cast
<DeclRefExpr
>(E
))
6999 if (const auto *PVD
= dyn_cast
<ParmVarDecl
>(DRE
->getDecl()))
7000 if (FD
->getNumParams() > PVD
->getFunctionScopeIndex() &&
7001 FD
->getParamDecl(PVD
->getFunctionScopeIndex())
7002 ->getCanonicalDecl() == PVD
->getCanonicalDecl()) {
7003 UniformedArgs
.try_emplace(PVD
->getCanonicalDecl(), E
);
7006 if (isa
<CXXThisExpr
>(E
)) {
7007 UniformedLinearThis
= E
;
7010 Diag(E
->getExprLoc(), diag::err_omp_param_or_this_in_clause
)
7011 << FD
->getDeclName() << (isa
<CXXMethodDecl
>(ADecl
) ? 1 : 0);
7013 // OpenMP [2.8.2, declare simd construct, Description]
7014 // The aligned clause declares that the object to which each list item points
7015 // is aligned to the number of bytes expressed in the optional parameter of
7016 // the aligned clause.
7017 // The special this pointer can be used as if was one of the arguments to the
7018 // function in any of the linear, aligned, or uniform clauses.
7019 // The type of list items appearing in the aligned clause must be array,
7020 // pointer, reference to array, or reference to pointer.
7021 llvm::DenseMap
<const Decl
*, const Expr
*> AlignedArgs
;
7022 const Expr
*AlignedThis
= nullptr;
7023 for (const Expr
*E
: Aligneds
) {
7024 E
= E
->IgnoreParenImpCasts();
7025 if (const auto *DRE
= dyn_cast
<DeclRefExpr
>(E
))
7026 if (const auto *PVD
= dyn_cast
<ParmVarDecl
>(DRE
->getDecl())) {
7027 const VarDecl
*CanonPVD
= PVD
->getCanonicalDecl();
7028 if (FD
->getNumParams() > PVD
->getFunctionScopeIndex() &&
7029 FD
->getParamDecl(PVD
->getFunctionScopeIndex())
7030 ->getCanonicalDecl() == CanonPVD
) {
7031 // OpenMP [2.8.1, simd construct, Restrictions]
7032 // A list-item cannot appear in more than one aligned clause.
7033 if (AlignedArgs
.count(CanonPVD
) > 0) {
7034 Diag(E
->getExprLoc(), diag::err_omp_used_in_clause_twice
)
7035 << 1 << getOpenMPClauseName(OMPC_aligned
)
7036 << E
->getSourceRange();
7037 Diag(AlignedArgs
[CanonPVD
]->getExprLoc(),
7038 diag::note_omp_explicit_dsa
)
7039 << getOpenMPClauseName(OMPC_aligned
);
7042 AlignedArgs
[CanonPVD
] = E
;
7043 QualType QTy
= PVD
->getType()
7044 .getNonReferenceType()
7045 .getUnqualifiedType()
7046 .getCanonicalType();
7047 const Type
*Ty
= QTy
.getTypePtrOrNull();
7048 if (!Ty
|| (!Ty
->isArrayType() && !Ty
->isPointerType())) {
7049 Diag(E
->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr
)
7050 << QTy
<< getLangOpts().CPlusPlus
<< E
->getSourceRange();
7051 Diag(PVD
->getLocation(), diag::note_previous_decl
) << PVD
;
7056 if (isa
<CXXThisExpr
>(E
)) {
7058 Diag(E
->getExprLoc(), diag::err_omp_used_in_clause_twice
)
7059 << 2 << getOpenMPClauseName(OMPC_aligned
) << E
->getSourceRange();
7060 Diag(AlignedThis
->getExprLoc(), diag::note_omp_explicit_dsa
)
7061 << getOpenMPClauseName(OMPC_aligned
);
7066 Diag(E
->getExprLoc(), diag::err_omp_param_or_this_in_clause
)
7067 << FD
->getDeclName() << (isa
<CXXMethodDecl
>(ADecl
) ? 1 : 0);
7069 // The optional parameter of the aligned clause, alignment, must be a constant
7070 // positive integer expression. If no optional parameter is specified,
7071 // implementation-defined default alignments for SIMD instructions on the
7072 // target platforms are assumed.
7073 SmallVector
<const Expr
*, 4> NewAligns
;
7074 for (Expr
*E
: Alignments
) {
7077 Align
= VerifyPositiveIntegerConstantInClause(E
, OMPC_aligned
);
7078 NewAligns
.push_back(Align
.get());
7080 // OpenMP [2.8.2, declare simd construct, Description]
7081 // The linear clause declares one or more list items to be private to a SIMD
7082 // lane and to have a linear relationship with respect to the iteration space
7084 // The special this pointer can be used as if was one of the arguments to the
7085 // function in any of the linear, aligned, or uniform clauses.
7086 // When a linear-step expression is specified in a linear clause it must be
7087 // either a constant integer expression or an integer-typed parameter that is
7088 // specified in a uniform clause on the directive.
7089 llvm::DenseMap
<const Decl
*, const Expr
*> LinearArgs
;
7090 const bool IsUniformedThis
= UniformedLinearThis
!= nullptr;
7091 auto MI
= LinModifiers
.begin();
7092 for (const Expr
*E
: Linears
) {
7093 auto LinKind
= static_cast<OpenMPLinearClauseKind
>(*MI
);
7095 E
= E
->IgnoreParenImpCasts();
7096 if (const auto *DRE
= dyn_cast
<DeclRefExpr
>(E
))
7097 if (const auto *PVD
= dyn_cast
<ParmVarDecl
>(DRE
->getDecl())) {
7098 const VarDecl
*CanonPVD
= PVD
->getCanonicalDecl();
7099 if (FD
->getNumParams() > PVD
->getFunctionScopeIndex() &&
7100 FD
->getParamDecl(PVD
->getFunctionScopeIndex())
7101 ->getCanonicalDecl() == CanonPVD
) {
7102 // OpenMP [2.15.3.7, linear Clause, Restrictions]
7103 // A list-item cannot appear in more than one linear clause.
7104 if (LinearArgs
.count(CanonPVD
) > 0) {
7105 Diag(E
->getExprLoc(), diag::err_omp_wrong_dsa
)
7106 << getOpenMPClauseName(OMPC_linear
)
7107 << getOpenMPClauseName(OMPC_linear
) << E
->getSourceRange();
7108 Diag(LinearArgs
[CanonPVD
]->getExprLoc(),
7109 diag::note_omp_explicit_dsa
)
7110 << getOpenMPClauseName(OMPC_linear
);
7113 // Each argument can appear in at most one uniform or linear clause.
7114 if (UniformedArgs
.count(CanonPVD
) > 0) {
7115 Diag(E
->getExprLoc(), diag::err_omp_wrong_dsa
)
7116 << getOpenMPClauseName(OMPC_linear
)
7117 << getOpenMPClauseName(OMPC_uniform
) << E
->getSourceRange();
7118 Diag(UniformedArgs
[CanonPVD
]->getExprLoc(),
7119 diag::note_omp_explicit_dsa
)
7120 << getOpenMPClauseName(OMPC_uniform
);
7123 LinearArgs
[CanonPVD
] = E
;
7124 if (E
->isValueDependent() || E
->isTypeDependent() ||
7125 E
->isInstantiationDependent() ||
7126 E
->containsUnexpandedParameterPack())
7128 (void)CheckOpenMPLinearDecl(CanonPVD
, E
->getExprLoc(), LinKind
,
7129 PVD
->getOriginalType(),
7130 /*IsDeclareSimd=*/true);
7134 if (isa
<CXXThisExpr
>(E
)) {
7135 if (UniformedLinearThis
) {
7136 Diag(E
->getExprLoc(), diag::err_omp_wrong_dsa
)
7137 << getOpenMPClauseName(OMPC_linear
)
7138 << getOpenMPClauseName(IsUniformedThis
? OMPC_uniform
: OMPC_linear
)
7139 << E
->getSourceRange();
7140 Diag(UniformedLinearThis
->getExprLoc(), diag::note_omp_explicit_dsa
)
7141 << getOpenMPClauseName(IsUniformedThis
? OMPC_uniform
7145 UniformedLinearThis
= E
;
7146 if (E
->isValueDependent() || E
->isTypeDependent() ||
7147 E
->isInstantiationDependent() || E
->containsUnexpandedParameterPack())
7149 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E
->getExprLoc(), LinKind
,
7150 E
->getType(), /*IsDeclareSimd=*/true);
7153 Diag(E
->getExprLoc(), diag::err_omp_param_or_this_in_clause
)
7154 << FD
->getDeclName() << (isa
<CXXMethodDecl
>(ADecl
) ? 1 : 0);
7156 Expr
*Step
= nullptr;
7157 Expr
*NewStep
= nullptr;
7158 SmallVector
<Expr
*, 4> NewSteps
;
7159 for (Expr
*E
: Steps
) {
7160 // Skip the same step expression, it was checked already.
7161 if (Step
== E
|| !E
) {
7162 NewSteps
.push_back(E
? NewStep
: nullptr);
7166 if (const auto *DRE
= dyn_cast
<DeclRefExpr
>(Step
))
7167 if (const auto *PVD
= dyn_cast
<ParmVarDecl
>(DRE
->getDecl())) {
7168 const VarDecl
*CanonPVD
= PVD
->getCanonicalDecl();
7169 if (UniformedArgs
.count(CanonPVD
) == 0) {
7170 Diag(Step
->getExprLoc(), diag::err_omp_expected_uniform_param
)
7171 << Step
->getSourceRange();
7172 } else if (E
->isValueDependent() || E
->isTypeDependent() ||
7173 E
->isInstantiationDependent() ||
7174 E
->containsUnexpandedParameterPack() ||
7175 CanonPVD
->getType()->hasIntegerRepresentation()) {
7176 NewSteps
.push_back(Step
);
7178 Diag(Step
->getExprLoc(), diag::err_omp_expected_int_param
)
7179 << Step
->getSourceRange();
7184 if (Step
&& !Step
->isValueDependent() && !Step
->isTypeDependent() &&
7185 !Step
->isInstantiationDependent() &&
7186 !Step
->containsUnexpandedParameterPack()) {
7187 NewStep
= PerformOpenMPImplicitIntegerConversion(Step
->getExprLoc(), Step
)
7191 VerifyIntegerConstantExpression(NewStep
, /*FIXME*/ AllowFold
).get();
7193 NewSteps
.push_back(NewStep
);
7195 auto *NewAttr
= OMPDeclareSimdDeclAttr::CreateImplicit(
7196 Context
, BS
, SL
.get(), const_cast<Expr
**>(Uniforms
.data()),
7197 Uniforms
.size(), const_cast<Expr
**>(Aligneds
.data()), Aligneds
.size(),
7198 const_cast<Expr
**>(NewAligns
.data()), NewAligns
.size(),
7199 const_cast<Expr
**>(Linears
.data()), Linears
.size(),
7200 const_cast<unsigned *>(LinModifiers
.data()), LinModifiers
.size(),
7201 NewSteps
.data(), NewSteps
.size(), SR
);
7202 ADecl
->addAttr(NewAttr
);
7206 static void setPrototype(Sema
&S
, FunctionDecl
*FD
, FunctionDecl
*FDWithProto
,
7208 assert(NewType
->isFunctionProtoType() &&
7209 "Expected function type with prototype.");
7210 assert(FD
->getType()->isFunctionNoProtoType() &&
7211 "Expected function with type with no prototype.");
7212 assert(FDWithProto
->getType()->isFunctionProtoType() &&
7213 "Expected function with prototype.");
7214 // Synthesize parameters with the same types.
7215 FD
->setType(NewType
);
7216 SmallVector
<ParmVarDecl
*, 16> Params
;
7217 for (const ParmVarDecl
*P
: FDWithProto
->parameters()) {
7218 auto *Param
= ParmVarDecl::Create(S
.getASTContext(), FD
, SourceLocation(),
7219 SourceLocation(), nullptr, P
->getType(),
7220 /*TInfo=*/nullptr, SC_None
, nullptr);
7221 Param
->setScopeInfo(0, Params
.size());
7222 Param
->setImplicit();
7223 Params
.push_back(Param
);
7226 FD
->setParams(Params
);
7229 void Sema::ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl
*D
) {
7230 if (D
->isInvalidDecl())
7232 FunctionDecl
*FD
= nullptr;
7233 if (auto *UTemplDecl
= dyn_cast
<FunctionTemplateDecl
>(D
))
7234 FD
= UTemplDecl
->getTemplatedDecl();
7236 FD
= cast
<FunctionDecl
>(D
);
7237 assert(FD
&& "Expected a function declaration!");
7239 // If we are instantiating templates we do *not* apply scoped assumptions but
7240 // only global ones. We apply scoped assumption to the template definition
7242 if (!inTemplateInstantiation()) {
7243 for (AssumptionAttr
*AA
: OMPAssumeScoped
)
7246 for (AssumptionAttr
*AA
: OMPAssumeGlobal
)
7250 Sema::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo
&TI
)
7251 : TI(&TI
), NameSuffix(TI
.getMangledName()) {}
7253 void Sema::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(
7254 Scope
*S
, Declarator
&D
, MultiTemplateParamsArg TemplateParamLists
,
7255 SmallVectorImpl
<FunctionDecl
*> &Bases
) {
7256 if (!D
.getIdentifier())
7259 OMPDeclareVariantScope
&DVScope
= OMPDeclareVariantScopes
.back();
7261 // Template specialization is an extension, check if we do it.
7262 bool IsTemplated
= !TemplateParamLists
.empty();
7264 !DVScope
.TI
->isExtensionActive(
7265 llvm::omp::TraitProperty::implementation_extension_allow_templates
))
7268 IdentifierInfo
*BaseII
= D
.getIdentifier();
7269 LookupResult
Lookup(*this, DeclarationName(BaseII
), D
.getIdentifierLoc(),
7270 LookupOrdinaryName
);
7271 LookupParsedName(Lookup
, S
, &D
.getCXXScopeSpec());
7273 TypeSourceInfo
*TInfo
= GetTypeForDeclarator(D
, S
);
7274 QualType FType
= TInfo
->getType();
7277 D
.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr
;
7279 D
.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Consteval
;
7281 for (auto *Candidate
: Lookup
) {
7282 auto *CandidateDecl
= Candidate
->getUnderlyingDecl();
7283 FunctionDecl
*UDecl
= nullptr;
7284 if (IsTemplated
&& isa
<FunctionTemplateDecl
>(CandidateDecl
)) {
7285 auto *FTD
= cast
<FunctionTemplateDecl
>(CandidateDecl
);
7286 if (FTD
->getTemplateParameters()->size() == TemplateParamLists
.size())
7287 UDecl
= FTD
->getTemplatedDecl();
7288 } else if (!IsTemplated
)
7289 UDecl
= dyn_cast
<FunctionDecl
>(CandidateDecl
);
7293 // Don't specialize constexpr/consteval functions with
7294 // non-constexpr/consteval functions.
7295 if (UDecl
->isConstexpr() && !IsConstexpr
)
7297 if (UDecl
->isConsteval() && !IsConsteval
)
7300 QualType UDeclTy
= UDecl
->getType();
7301 if (!UDeclTy
->isDependentType()) {
7302 QualType NewType
= Context
.mergeFunctionTypes(
7303 FType
, UDeclTy
, /* OfBlockPointer */ false,
7304 /* Unqualified */ false, /* AllowCXX */ true);
7305 if (NewType
.isNull())
7310 Bases
.push_back(UDecl
);
7313 bool UseImplicitBase
= !DVScope
.TI
->isExtensionActive(
7314 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base
);
7315 // If no base was found we create a declaration that we use as base.
7316 if (Bases
.empty() && UseImplicitBase
) {
7317 D
.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration
);
7318 Decl
*BaseD
= HandleDeclarator(S
, D
, TemplateParamLists
);
7319 BaseD
->setImplicit(true);
7320 if (auto *BaseTemplD
= dyn_cast
<FunctionTemplateDecl
>(BaseD
))
7321 Bases
.push_back(BaseTemplD
->getTemplatedDecl());
7323 Bases
.push_back(cast
<FunctionDecl
>(BaseD
));
7326 std::string MangledName
;
7327 MangledName
+= D
.getIdentifier()->getName();
7328 MangledName
+= getOpenMPVariantManglingSeparatorStr();
7329 MangledName
+= DVScope
.NameSuffix
;
7330 IdentifierInfo
&VariantII
= Context
.Idents
.get(MangledName
);
7332 VariantII
.setMangledOpenMPVariantName(true);
7333 D
.SetIdentifier(&VariantII
, D
.getBeginLoc());
7336 void Sema::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
7337 Decl
*D
, SmallVectorImpl
<FunctionDecl
*> &Bases
) {
7338 // Do not mark function as is used to prevent its emission if this is the
7339 // only place where it is used.
7340 EnterExpressionEvaluationContext
Unevaluated(
7341 *this, Sema::ExpressionEvaluationContext::Unevaluated
);
7343 FunctionDecl
*FD
= nullptr;
7344 if (auto *UTemplDecl
= dyn_cast
<FunctionTemplateDecl
>(D
))
7345 FD
= UTemplDecl
->getTemplatedDecl();
7347 FD
= cast
<FunctionDecl
>(D
);
7348 auto *VariantFuncRef
= DeclRefExpr::Create(
7349 Context
, NestedNameSpecifierLoc(), SourceLocation(), FD
,
7350 /* RefersToEnclosingVariableOrCapture */ false,
7351 /* NameLoc */ FD
->getLocation(), FD
->getType(),
7352 ExprValueKind::VK_PRValue
);
7354 OMPDeclareVariantScope
&DVScope
= OMPDeclareVariantScopes
.back();
7355 auto *OMPDeclareVariantA
= OMPDeclareVariantAttr::CreateImplicit(
7356 Context
, VariantFuncRef
, DVScope
.TI
,
7357 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7358 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7359 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7360 for (FunctionDecl
*BaseFD
: Bases
)
7361 BaseFD
->addAttr(OMPDeclareVariantA
);
7364 ExprResult
Sema::ActOnOpenMPCall(ExprResult Call
, Scope
*Scope
,
7365 SourceLocation LParenLoc
,
7366 MultiExprArg ArgExprs
,
7367 SourceLocation RParenLoc
, Expr
*ExecConfig
) {
7368 // The common case is a regular call we do not want to specialize at all. Try
7369 // to make that case fast by bailing early.
7370 CallExpr
*CE
= dyn_cast
<CallExpr
>(Call
.get());
7374 FunctionDecl
*CalleeFnDecl
= CE
->getDirectCallee();
7378 if (LangOpts
.OpenMP
>= 51 && CalleeFnDecl
->getIdentifier() &&
7379 CalleeFnDecl
->getName().starts_with_insensitive("omp_")) {
7380 // checking for any calls inside an Order region
7381 if (Scope
&& Scope
->isOpenMPOrderClauseScope())
7382 Diag(LParenLoc
, diag::err_omp_unexpected_call_to_omp_runtime_api
);
7385 if (!CalleeFnDecl
->hasAttr
<OMPDeclareVariantAttr
>())
7388 ASTContext
&Context
= getASTContext();
7389 std::function
<void(StringRef
)> DiagUnknownTrait
= [this,
7390 CE
](StringRef ISATrait
) {
7391 // TODO Track the selector locations in a way that is accessible here to
7392 // improve the diagnostic location.
7393 Diag(CE
->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait
)
7396 TargetOMPContext
OMPCtx(Context
, std::move(DiagUnknownTrait
),
7397 getCurFunctionDecl(), DSAStack
->getConstructTraits());
7399 QualType CalleeFnType
= CalleeFnDecl
->getType();
7401 SmallVector
<Expr
*, 4> Exprs
;
7402 SmallVector
<VariantMatchInfo
, 4> VMIs
;
7403 while (CalleeFnDecl
) {
7404 for (OMPDeclareVariantAttr
*A
:
7405 CalleeFnDecl
->specific_attrs
<OMPDeclareVariantAttr
>()) {
7406 Expr
*VariantRef
= A
->getVariantFuncRef();
7408 VariantMatchInfo VMI
;
7409 OMPTraitInfo
&TI
= A
->getTraitInfo();
7410 TI
.getAsVariantMatchInfo(Context
, VMI
);
7411 if (!isVariantApplicableInContext(VMI
, OMPCtx
,
7412 /* DeviceSetOnly */ false))
7415 VMIs
.push_back(VMI
);
7416 Exprs
.push_back(VariantRef
);
7419 CalleeFnDecl
= CalleeFnDecl
->getPreviousDecl();
7424 int BestIdx
= getBestVariantMatchForContext(VMIs
, OMPCtx
);
7427 Expr
*BestExpr
= cast
<DeclRefExpr
>(Exprs
[BestIdx
]);
7428 Decl
*BestDecl
= cast
<DeclRefExpr
>(BestExpr
)->getDecl();
7431 // Try to build a (member) call expression for the current best applicable
7432 // variant expression. We allow this to fail in which case we continue
7433 // with the next best variant expression. The fail case is part of the
7434 // implementation defined behavior in the OpenMP standard when it talks
7435 // about what differences in the function prototypes: "Any differences
7436 // that the specific OpenMP context requires in the prototype of the
7437 // variant from the base function prototype are implementation defined."
7438 // This wording is there to allow the specialized variant to have a
7439 // different type than the base function. This is intended and OK but if
7440 // we cannot create a call the difference is not in the "implementation
7441 // defined range" we allow.
7442 Sema::TentativeAnalysisScope
Trap(*this);
7444 if (auto *SpecializedMethod
= dyn_cast
<CXXMethodDecl
>(BestDecl
)) {
7445 auto *MemberCall
= dyn_cast
<CXXMemberCallExpr
>(CE
);
7446 BestExpr
= MemberExpr::CreateImplicit(
7447 Context
, MemberCall
->getImplicitObjectArgument(),
7448 /* IsArrow */ false, SpecializedMethod
, Context
.BoundMemberTy
,
7449 MemberCall
->getValueKind(), MemberCall
->getObjectKind());
7451 NewCall
= BuildCallExpr(Scope
, BestExpr
, LParenLoc
, ArgExprs
, RParenLoc
,
7453 if (NewCall
.isUsable()) {
7454 if (CallExpr
*NCE
= dyn_cast
<CallExpr
>(NewCall
.get())) {
7455 FunctionDecl
*NewCalleeFnDecl
= NCE
->getDirectCallee();
7456 QualType NewType
= Context
.mergeFunctionTypes(
7457 CalleeFnType
, NewCalleeFnDecl
->getType(),
7458 /* OfBlockPointer */ false,
7459 /* Unqualified */ false, /* AllowCXX */ true);
7460 if (!NewType
.isNull())
7462 // Don't use the call if the function type was not compatible.
7468 VMIs
.erase(VMIs
.begin() + BestIdx
);
7469 Exprs
.erase(Exprs
.begin() + BestIdx
);
7470 } while (!VMIs
.empty());
7472 if (!NewCall
.isUsable())
7474 return PseudoObjectExpr::Create(Context
, CE
, {NewCall
.get()}, 0);
7477 std::optional
<std::pair
<FunctionDecl
*, Expr
*>>
7478 Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG
,
7479 Expr
*VariantRef
, OMPTraitInfo
&TI
,
7480 unsigned NumAppendArgs
,
7482 if (!DG
|| DG
.get().isNull())
7483 return std::nullopt
;
7485 const int VariantId
= 1;
7486 // Must be applied only to single decl.
7487 if (!DG
.get().isSingleDecl()) {
7488 Diag(SR
.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant
)
7490 return std::nullopt
;
7492 Decl
*ADecl
= DG
.get().getSingleDecl();
7493 if (auto *FTD
= dyn_cast
<FunctionTemplateDecl
>(ADecl
))
7494 ADecl
= FTD
->getTemplatedDecl();
7496 // Decl must be a function.
7497 auto *FD
= dyn_cast
<FunctionDecl
>(ADecl
);
7499 Diag(ADecl
->getLocation(), diag::err_omp_function_expected
)
7501 return std::nullopt
;
7504 auto &&HasMultiVersionAttributes
= [](const FunctionDecl
*FD
) {
7505 // The 'target' attribute needs to be separately checked because it does
7506 // not always signify a multiversion function declaration.
7507 return FD
->isMultiVersion() || FD
->hasAttr
<TargetAttr
>();
7509 // OpenMP is not compatible with multiversion function attributes.
7510 if (HasMultiVersionAttributes(FD
)) {
7511 Diag(FD
->getLocation(), diag::err_omp_declare_variant_incompat_attributes
)
7513 return std::nullopt
;
7516 // Allow #pragma omp declare variant only if the function is not used.
7517 if (FD
->isUsed(false))
7518 Diag(SR
.getBegin(), diag::warn_omp_declare_variant_after_used
)
7519 << FD
->getLocation();
7521 // Check if the function was emitted already.
7522 const FunctionDecl
*Definition
;
7523 if (!FD
->isThisDeclarationADefinition() && FD
->isDefined(Definition
) &&
7524 (LangOpts
.EmitAllDecls
|| Context
.DeclMustBeEmitted(Definition
)))
7525 Diag(SR
.getBegin(), diag::warn_omp_declare_variant_after_emitted
)
7526 << FD
->getLocation();
7528 // The VariantRef must point to function.
7530 Diag(SR
.getBegin(), diag::err_omp_function_expected
) << VariantId
;
7531 return std::nullopt
;
7534 auto ShouldDelayChecks
= [](Expr
*&E
, bool) {
7535 return E
&& (E
->isTypeDependent() || E
->isValueDependent() ||
7536 E
->containsUnexpandedParameterPack() ||
7537 E
->isInstantiationDependent());
7539 // Do not check templates, wait until instantiation.
7540 if (FD
->isDependentContext() || ShouldDelayChecks(VariantRef
, false) ||
7541 TI
.anyScoreOrCondition(ShouldDelayChecks
))
7542 return std::make_pair(FD
, VariantRef
);
7544 // Deal with non-constant score and user condition expressions.
7545 auto HandleNonConstantScoresAndConditions
= [this](Expr
*&E
,
7546 bool IsScore
) -> bool {
7547 if (!E
|| E
->isIntegerConstantExpr(Context
))
7551 // We warn on non-constant scores and pretend they were not present.
7552 Diag(E
->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant
)
7556 // We could replace a non-constant user condition with "false" but we
7557 // will soon need to handle these anyway for the dynamic version of
7558 // OpenMP context selectors.
7559 Diag(E
->getExprLoc(),
7560 diag::err_omp_declare_variant_user_condition_not_constant
)
7565 if (TI
.anyScoreOrCondition(HandleNonConstantScoresAndConditions
))
7566 return std::nullopt
;
7568 QualType AdjustedFnType
= FD
->getType();
7569 if (NumAppendArgs
) {
7570 const auto *PTy
= AdjustedFnType
->getAsAdjusted
<FunctionProtoType
>();
7572 Diag(FD
->getLocation(), diag::err_omp_declare_variant_prototype_required
)
7574 return std::nullopt
;
7576 // Adjust the function type to account for an extra omp_interop_t for each
7577 // specified in the append_args clause.
7578 const TypeDecl
*TD
= nullptr;
7579 LookupResult
Result(*this, &Context
.Idents
.get("omp_interop_t"),
7580 SR
.getBegin(), Sema::LookupOrdinaryName
);
7581 if (LookupName(Result
, getCurScope())) {
7582 NamedDecl
*ND
= Result
.getFoundDecl();
7583 TD
= dyn_cast_or_null
<TypeDecl
>(ND
);
7586 Diag(SR
.getBegin(), diag::err_omp_interop_type_not_found
) << SR
;
7587 return std::nullopt
;
7589 QualType InteropType
= Context
.getTypeDeclType(TD
);
7590 if (PTy
->isVariadic()) {
7591 Diag(FD
->getLocation(), diag::err_omp_append_args_with_varargs
) << SR
;
7592 return std::nullopt
;
7594 llvm::SmallVector
<QualType
, 8> Params
;
7595 Params
.append(PTy
->param_type_begin(), PTy
->param_type_end());
7596 Params
.insert(Params
.end(), NumAppendArgs
, InteropType
);
7597 AdjustedFnType
= Context
.getFunctionType(PTy
->getReturnType(), Params
,
7598 PTy
->getExtProtoInfo());
7601 // Convert VariantRef expression to the type of the original function to
7602 // resolve possible conflicts.
7603 ExprResult VariantRefCast
= VariantRef
;
7604 if (LangOpts
.CPlusPlus
) {
7606 auto *Method
= dyn_cast
<CXXMethodDecl
>(FD
);
7607 if (Method
&& !Method
->isStatic()) {
7608 const Type
*ClassType
=
7609 Context
.getTypeDeclType(Method
->getParent()).getTypePtr();
7610 FnPtrType
= Context
.getMemberPointerType(AdjustedFnType
, ClassType
);
7613 // Build adrr_of unary op to correctly handle type checks for member
7615 Sema::TentativeAnalysisScope
Trap(*this);
7616 ER
= CreateBuiltinUnaryOp(VariantRef
->getBeginLoc(), UO_AddrOf
,
7619 if (!ER
.isUsable()) {
7620 Diag(VariantRef
->getExprLoc(), diag::err_omp_function_expected
)
7621 << VariantId
<< VariantRef
->getSourceRange();
7622 return std::nullopt
;
7624 VariantRef
= ER
.get();
7626 FnPtrType
= Context
.getPointerType(AdjustedFnType
);
7628 QualType VarianPtrType
= Context
.getPointerType(VariantRef
->getType());
7629 if (VarianPtrType
.getUnqualifiedType() != FnPtrType
.getUnqualifiedType()) {
7630 ImplicitConversionSequence ICS
= TryImplicitConversion(
7631 VariantRef
, FnPtrType
.getUnqualifiedType(),
7632 /*SuppressUserConversions=*/false, AllowedExplicit::None
,
7633 /*InOverloadResolution=*/false,
7635 /*AllowObjCWritebackConversion=*/false);
7636 if (ICS
.isFailure()) {
7637 Diag(VariantRef
->getExprLoc(),
7638 diag::err_omp_declare_variant_incompat_types
)
7639 << VariantRef
->getType()
7640 << ((Method
&& !Method
->isStatic()) ? FnPtrType
: FD
->getType())
7641 << (NumAppendArgs
? 1 : 0) << VariantRef
->getSourceRange();
7642 return std::nullopt
;
7644 VariantRefCast
= PerformImplicitConversion(
7645 VariantRef
, FnPtrType
.getUnqualifiedType(), AA_Converting
);
7646 if (!VariantRefCast
.isUsable())
7647 return std::nullopt
;
7649 // Drop previously built artificial addr_of unary op for member functions.
7650 if (Method
&& !Method
->isStatic()) {
7651 Expr
*PossibleAddrOfVariantRef
= VariantRefCast
.get();
7652 if (auto *UO
= dyn_cast
<UnaryOperator
>(
7653 PossibleAddrOfVariantRef
->IgnoreImplicit()))
7654 VariantRefCast
= UO
->getSubExpr();
7658 ExprResult ER
= CheckPlaceholderExpr(VariantRefCast
.get());
7659 if (!ER
.isUsable() ||
7660 !ER
.get()->IgnoreParenImpCasts()->getType()->isFunctionType()) {
7661 Diag(VariantRef
->getExprLoc(), diag::err_omp_function_expected
)
7662 << VariantId
<< VariantRef
->getSourceRange();
7663 return std::nullopt
;
7666 // The VariantRef must point to function.
7667 auto *DRE
= dyn_cast
<DeclRefExpr
>(ER
.get()->IgnoreParenImpCasts());
7669 Diag(VariantRef
->getExprLoc(), diag::err_omp_function_expected
)
7670 << VariantId
<< VariantRef
->getSourceRange();
7671 return std::nullopt
;
7673 auto *NewFD
= dyn_cast_or_null
<FunctionDecl
>(DRE
->getDecl());
7675 Diag(VariantRef
->getExprLoc(), diag::err_omp_function_expected
)
7676 << VariantId
<< VariantRef
->getSourceRange();
7677 return std::nullopt
;
7680 if (FD
->getCanonicalDecl() == NewFD
->getCanonicalDecl()) {
7681 Diag(VariantRef
->getExprLoc(),
7682 diag::err_omp_declare_variant_same_base_function
)
7683 << VariantRef
->getSourceRange();
7684 return std::nullopt
;
7687 // Check if function types are compatible in C.
7688 if (!LangOpts
.CPlusPlus
) {
7690 Context
.mergeFunctionTypes(AdjustedFnType
, NewFD
->getType());
7691 if (NewType
.isNull()) {
7692 Diag(VariantRef
->getExprLoc(),
7693 diag::err_omp_declare_variant_incompat_types
)
7694 << NewFD
->getType() << FD
->getType() << (NumAppendArgs
? 1 : 0)
7695 << VariantRef
->getSourceRange();
7696 return std::nullopt
;
7698 if (NewType
->isFunctionProtoType()) {
7699 if (FD
->getType()->isFunctionNoProtoType())
7700 setPrototype(*this, FD
, NewFD
, NewType
);
7701 else if (NewFD
->getType()->isFunctionNoProtoType())
7702 setPrototype(*this, NewFD
, FD
, NewType
);
7706 // Check if variant function is not marked with declare variant directive.
7707 if (NewFD
->hasAttrs() && NewFD
->hasAttr
<OMPDeclareVariantAttr
>()) {
7708 Diag(VariantRef
->getExprLoc(),
7709 diag::warn_omp_declare_variant_marked_as_declare_variant
)
7710 << VariantRef
->getSourceRange();
7712 NewFD
->specific_attr_begin
<OMPDeclareVariantAttr
>()->getRange();
7713 Diag(SR
.getBegin(), diag::note_omp_marked_declare_variant_here
) << SR
;
7714 return std::nullopt
;
7717 enum DoesntSupport
{
7726 if (const auto *CXXFD
= dyn_cast
<CXXMethodDecl
>(FD
)) {
7727 if (CXXFD
->isVirtual()) {
7728 Diag(FD
->getLocation(), diag::err_omp_declare_variant_doesnt_support
)
7730 return std::nullopt
;
7733 if (isa
<CXXConstructorDecl
>(FD
)) {
7734 Diag(FD
->getLocation(), diag::err_omp_declare_variant_doesnt_support
)
7736 return std::nullopt
;
7739 if (isa
<CXXDestructorDecl
>(FD
)) {
7740 Diag(FD
->getLocation(), diag::err_omp_declare_variant_doesnt_support
)
7742 return std::nullopt
;
7746 if (FD
->isDeleted()) {
7747 Diag(FD
->getLocation(), diag::err_omp_declare_variant_doesnt_support
)
7749 return std::nullopt
;
7752 if (FD
->isDefaulted()) {
7753 Diag(FD
->getLocation(), diag::err_omp_declare_variant_doesnt_support
)
7755 return std::nullopt
;
7758 if (FD
->isConstexpr()) {
7759 Diag(FD
->getLocation(), diag::err_omp_declare_variant_doesnt_support
)
7760 << (NewFD
->isConsteval() ? ConstevalFuncs
: ConstexprFuncs
);
7761 return std::nullopt
;
7764 // Check general compatibility.
7765 if (areMultiversionVariantFunctionsCompatible(
7766 FD
, NewFD
, PartialDiagnostic::NullDiagnostic(),
7767 PartialDiagnosticAt(SourceLocation(),
7768 PartialDiagnostic::NullDiagnostic()),
7769 PartialDiagnosticAt(
7770 VariantRef
->getExprLoc(),
7771 PDiag(diag::err_omp_declare_variant_doesnt_support
)),
7772 PartialDiagnosticAt(VariantRef
->getExprLoc(),
7773 PDiag(diag::err_omp_declare_variant_diff
)
7774 << FD
->getLocation()),
7775 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7776 /*CLinkageMayDiffer=*/true))
7777 return std::nullopt
;
7778 return std::make_pair(FD
, cast
<Expr
>(DRE
));
7781 void Sema::ActOnOpenMPDeclareVariantDirective(
7782 FunctionDecl
*FD
, Expr
*VariantRef
, OMPTraitInfo
&TI
,
7783 ArrayRef
<Expr
*> AdjustArgsNothing
,
7784 ArrayRef
<Expr
*> AdjustArgsNeedDevicePtr
,
7785 ArrayRef
<OMPInteropInfo
> AppendArgs
, SourceLocation AdjustArgsLoc
,
7786 SourceLocation AppendArgsLoc
, SourceRange SR
) {
7788 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7789 // An adjust_args clause or append_args clause can only be specified if the
7790 // dispatch selector of the construct selector set appears in the match
7793 SmallVector
<Expr
*, 8> AllAdjustArgs
;
7794 llvm::append_range(AllAdjustArgs
, AdjustArgsNothing
);
7795 llvm::append_range(AllAdjustArgs
, AdjustArgsNeedDevicePtr
);
7797 if (!AllAdjustArgs
.empty() || !AppendArgs
.empty()) {
7798 VariantMatchInfo VMI
;
7799 TI
.getAsVariantMatchInfo(Context
, VMI
);
7800 if (!llvm::is_contained(
7801 VMI
.ConstructTraits
,
7802 llvm::omp::TraitProperty::construct_dispatch_dispatch
)) {
7803 if (!AllAdjustArgs
.empty())
7804 Diag(AdjustArgsLoc
, diag::err_omp_clause_requires_dispatch_construct
)
7805 << getOpenMPClauseName(OMPC_adjust_args
);
7806 if (!AppendArgs
.empty())
7807 Diag(AppendArgsLoc
, diag::err_omp_clause_requires_dispatch_construct
)
7808 << getOpenMPClauseName(OMPC_append_args
);
7813 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7814 // Each argument can only appear in a single adjust_args clause for each
7815 // declare variant directive.
7816 llvm::SmallPtrSet
<const VarDecl
*, 4> AdjustVars
;
7818 for (Expr
*E
: AllAdjustArgs
) {
7819 E
= E
->IgnoreParenImpCasts();
7820 if (const auto *DRE
= dyn_cast
<DeclRefExpr
>(E
)) {
7821 if (const auto *PVD
= dyn_cast
<ParmVarDecl
>(DRE
->getDecl())) {
7822 const VarDecl
*CanonPVD
= PVD
->getCanonicalDecl();
7823 if (FD
->getNumParams() > PVD
->getFunctionScopeIndex() &&
7824 FD
->getParamDecl(PVD
->getFunctionScopeIndex())
7825 ->getCanonicalDecl() == CanonPVD
) {
7826 // It's a parameter of the function, check duplicates.
7827 if (!AdjustVars
.insert(CanonPVD
).second
) {
7828 Diag(DRE
->getLocation(), diag::err_omp_adjust_arg_multiple_clauses
)
7836 // Anything that is not a function parameter is an error.
7837 Diag(E
->getExprLoc(), diag::err_omp_param_or_this_in_clause
) << FD
<< 0;
7841 auto *NewAttr
= OMPDeclareVariantAttr::CreateImplicit(
7842 Context
, VariantRef
, &TI
, const_cast<Expr
**>(AdjustArgsNothing
.data()),
7843 AdjustArgsNothing
.size(),
7844 const_cast<Expr
**>(AdjustArgsNeedDevicePtr
.data()),
7845 AdjustArgsNeedDevicePtr
.size(),
7846 const_cast<OMPInteropInfo
*>(AppendArgs
.data()), AppendArgs
.size(), SR
);
7847 FD
->addAttr(NewAttr
);
7850 StmtResult
Sema::ActOnOpenMPParallelDirective(ArrayRef
<OMPClause
*> Clauses
,
7852 SourceLocation StartLoc
,
7853 SourceLocation EndLoc
) {
7857 auto *CS
= cast
<CapturedStmt
>(AStmt
);
7858 // 1.2.2 OpenMP Language Terminology
7859 // Structured block - An executable statement with a single entry at the
7860 // top and a single exit at the bottom.
7861 // The point of exit cannot be a branch out of the structured block.
7862 // longjmp() and throw() must not violate the entry/exit criteria.
7863 CS
->getCapturedDecl()->setNothrow();
7865 setFunctionHasBranchProtectedScope();
7867 return OMPParallelDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
7868 DSAStack
->getTaskgroupReductionRef(),
7869 DSAStack
->isCancelRegion());
7873 /// Iteration space of a single for loop.
7874 struct LoopIterationSpace final
{
7875 /// True if the condition operator is the strict compare operator (<, > or
7877 bool IsStrictCompare
= false;
7878 /// Condition of the loop.
7879 Expr
*PreCond
= nullptr;
7880 /// This expression calculates the number of iterations in the loop.
7881 /// It is always possible to calculate it before starting the loop.
7882 Expr
*NumIterations
= nullptr;
7883 /// The loop counter variable.
7884 Expr
*CounterVar
= nullptr;
7885 /// Private loop counter variable.
7886 Expr
*PrivateCounterVar
= nullptr;
7887 /// This is initializer for the initial value of #CounterVar.
7888 Expr
*CounterInit
= nullptr;
7889 /// This is step for the #CounterVar used to generate its update:
7890 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7891 Expr
*CounterStep
= nullptr;
7892 /// Should step be subtracted?
7893 bool Subtract
= false;
7894 /// Source range of the loop init.
7895 SourceRange InitSrcRange
;
7896 /// Source range of the loop condition.
7897 SourceRange CondSrcRange
;
7898 /// Source range of the loop increment.
7899 SourceRange IncSrcRange
;
7900 /// Minimum value that can have the loop control variable. Used to support
7901 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
7902 /// since only such variables can be used in non-loop invariant expressions.
7903 Expr
*MinValue
= nullptr;
7904 /// Maximum value that can have the loop control variable. Used to support
7905 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
7906 /// since only such variables can be used in non-loop invariant expressions.
7907 Expr
*MaxValue
= nullptr;
7908 /// true, if the lower bound depends on the outer loop control var.
7909 bool IsNonRectangularLB
= false;
7910 /// true, if the upper bound depends on the outer loop control var.
7911 bool IsNonRectangularUB
= false;
7912 /// Index of the loop this loop depends on and forms non-rectangular loop
7914 unsigned LoopDependentIdx
= 0;
7915 /// Final condition for the non-rectangular loop nest support. It is used to
7916 /// check that the number of iterations for this particular counter must be
7918 Expr
*FinalCondition
= nullptr;
7921 /// Helper class for checking canonical form of the OpenMP loops and
7922 /// extracting iteration space of each loop in the loop nest, that will be used
7923 /// for IR generation.
7924 class OpenMPIterationSpaceChecker
{
7925 /// Reference to Sema.
7927 /// Does the loop associated directive support non-rectangular loops?
7928 bool SupportsNonRectangular
;
7929 /// Data-sharing stack.
7931 /// A location for diagnostics (when there is no some better location).
7932 SourceLocation DefaultLoc
;
7933 /// A location for diagnostics (when increment is not compatible).
7934 SourceLocation ConditionLoc
;
7935 /// A source location for referring to loop init later.
7936 SourceRange InitSrcRange
;
7937 /// A source location for referring to condition later.
7938 SourceRange ConditionSrcRange
;
7939 /// A source location for referring to increment later.
7940 SourceRange IncrementSrcRange
;
7942 ValueDecl
*LCDecl
= nullptr;
7943 /// Reference to loop variable.
7944 Expr
*LCRef
= nullptr;
7945 /// Lower bound (initializer for the var).
7949 /// Loop step (increment).
7950 Expr
*Step
= nullptr;
7951 /// This flag is true when condition is one of:
7956 /// This will have no value when the condition is !=
7957 std::optional
<bool> TestIsLessOp
;
7958 /// This flag is true when condition is strict ( < or > ).
7959 bool TestIsStrictOp
= false;
7960 /// This flag is true when step is subtracted on each iteration.
7961 bool SubtractStep
= false;
7962 /// The outer loop counter this loop depends on (if any).
7963 const ValueDecl
*DepDecl
= nullptr;
7964 /// Contains number of loop (starts from 1) on which loop counter init
7965 /// expression of this loop depends on.
7966 std::optional
<unsigned> InitDependOnLC
;
7967 /// Contains number of loop (starts from 1) on which loop counter condition
7968 /// expression of this loop depends on.
7969 std::optional
<unsigned> CondDependOnLC
;
7970 /// Checks if the provide statement depends on the loop counter.
7971 std::optional
<unsigned> doesDependOnLoopCounter(const Stmt
*S
,
7972 bool IsInitializer
);
7973 /// Original condition required for checking of the exit condition for
7974 /// non-rectangular loop.
7975 Expr
*Condition
= nullptr;
7978 OpenMPIterationSpaceChecker(Sema
&SemaRef
, bool SupportsNonRectangular
,
7979 DSAStackTy
&Stack
, SourceLocation DefaultLoc
)
7980 : SemaRef(SemaRef
), SupportsNonRectangular(SupportsNonRectangular
),
7981 Stack(Stack
), DefaultLoc(DefaultLoc
), ConditionLoc(DefaultLoc
) {}
7982 /// Check init-expr for canonical loop form and save loop counter
7983 /// variable - #Var and its initialization value - #LB.
7984 bool checkAndSetInit(Stmt
*S
, bool EmitDiags
= true);
7985 /// Check test-expr for canonical form, save upper-bound (#UB), flags
7986 /// for less/greater and for strict/non-strict comparison.
7987 bool checkAndSetCond(Expr
*S
);
7988 /// Check incr-expr for canonical loop form and return true if it
7989 /// does not conform, otherwise save loop step (#Step).
7990 bool checkAndSetInc(Expr
*S
);
7991 /// Return the loop counter variable.
7992 ValueDecl
*getLoopDecl() const { return LCDecl
; }
7993 /// Return the reference expression to loop counter variable.
7994 Expr
*getLoopDeclRefExpr() const { return LCRef
; }
7995 /// Source range of the loop init.
7996 SourceRange
getInitSrcRange() const { return InitSrcRange
; }
7997 /// Source range of the loop condition.
7998 SourceRange
getConditionSrcRange() const { return ConditionSrcRange
; }
7999 /// Source range of the loop increment.
8000 SourceRange
getIncrementSrcRange() const { return IncrementSrcRange
; }
8001 /// True if the step should be subtracted.
8002 bool shouldSubtractStep() const { return SubtractStep
; }
8003 /// True, if the compare operator is strict (<, > or !=).
8004 bool isStrictTestOp() const { return TestIsStrictOp
; }
8005 /// Build the expression to calculate the number of iterations.
8006 Expr
*buildNumIterations(
8007 Scope
*S
, ArrayRef
<LoopIterationSpace
> ResultIterSpaces
, bool LimitedType
,
8008 llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
) const;
8009 /// Build the precondition expression for the loops.
8011 buildPreCond(Scope
*S
, Expr
*Cond
,
8012 llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
) const;
8013 /// Build reference expression to the counter be used for codegen.
8015 buildCounterVar(llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
,
8016 DSAStackTy
&DSA
) const;
8017 /// Build reference expression to the private counter be used for
8019 Expr
*buildPrivateCounterVar() const;
8020 /// Build initialization of the counter be used for codegen.
8021 Expr
*buildCounterInit() const;
8022 /// Build step of the counter be used for codegen.
8023 Expr
*buildCounterStep() const;
8024 /// Build loop data with counter value for depend clauses in ordered
8027 buildOrderedLoopData(Scope
*S
, Expr
*Counter
,
8028 llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
,
8029 SourceLocation Loc
, Expr
*Inc
= nullptr,
8030 OverloadedOperatorKind OOK
= OO_Amp
);
8031 /// Builds the minimum value for the loop counter.
8032 std::pair
<Expr
*, Expr
*> buildMinMaxValues(
8033 Scope
*S
, llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
) const;
8034 /// Builds final condition for the non-rectangular loops.
8035 Expr
*buildFinalCondition(Scope
*S
) const;
8036 /// Return true if any expression is dependent.
8037 bool dependent() const;
8038 /// Returns true if the initializer forms non-rectangular loop.
8039 bool doesInitDependOnLC() const { return InitDependOnLC
.has_value(); }
8040 /// Returns true if the condition forms non-rectangular loop.
8041 bool doesCondDependOnLC() const { return CondDependOnLC
.has_value(); }
8042 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
8043 unsigned getLoopDependentIdx() const {
8044 return InitDependOnLC
.value_or(CondDependOnLC
.value_or(0));
8048 /// Check the right-hand side of an assignment in the increment
8050 bool checkAndSetIncRHS(Expr
*RHS
);
8051 /// Helper to set loop counter variable and its initializer.
8052 bool setLCDeclAndLB(ValueDecl
*NewLCDecl
, Expr
*NewDeclRefExpr
, Expr
*NewLB
,
8054 /// Helper to set upper bound.
8055 bool setUB(Expr
*NewUB
, std::optional
<bool> LessOp
, bool StrictOp
,
8056 SourceRange SR
, SourceLocation SL
);
8057 /// Helper to set loop increment.
8058 bool setStep(Expr
*NewStep
, bool Subtract
);
8061 bool OpenMPIterationSpaceChecker::dependent() const {
8063 assert(!LB
&& !UB
&& !Step
);
8066 return LCDecl
->getType()->isDependentType() ||
8067 (LB
&& LB
->isValueDependent()) || (UB
&& UB
->isValueDependent()) ||
8068 (Step
&& Step
->isValueDependent());
8071 bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl
*NewLCDecl
,
8073 Expr
*NewLB
, bool EmitDiags
) {
8074 // State consistency checking to ensure correct usage.
8075 assert(LCDecl
== nullptr && LB
== nullptr && LCRef
== nullptr &&
8076 UB
== nullptr && Step
== nullptr && !TestIsLessOp
&& !TestIsStrictOp
);
8077 if (!NewLCDecl
|| !NewLB
|| NewLB
->containsErrors())
8079 LCDecl
= getCanonicalDecl(NewLCDecl
);
8080 LCRef
= NewLCRefExpr
;
8081 if (auto *CE
= dyn_cast_or_null
<CXXConstructExpr
>(NewLB
))
8082 if (const CXXConstructorDecl
*Ctor
= CE
->getConstructor())
8083 if ((Ctor
->isCopyOrMoveConstructor() ||
8084 Ctor
->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8085 CE
->getNumArgs() > 0 && CE
->getArg(0) != nullptr)
8086 NewLB
= CE
->getArg(0)->IgnoreParenImpCasts();
8089 InitDependOnLC
= doesDependOnLoopCounter(LB
, /*IsInitializer=*/true);
8093 bool OpenMPIterationSpaceChecker::setUB(Expr
*NewUB
, std::optional
<bool> LessOp
,
8094 bool StrictOp
, SourceRange SR
,
8095 SourceLocation SL
) {
8096 // State consistency checking to ensure correct usage.
8097 assert(LCDecl
!= nullptr && LB
!= nullptr && UB
== nullptr &&
8098 Step
== nullptr && !TestIsLessOp
&& !TestIsStrictOp
);
8099 if (!NewUB
|| NewUB
->containsErrors())
8103 TestIsLessOp
= LessOp
;
8104 TestIsStrictOp
= StrictOp
;
8105 ConditionSrcRange
= SR
;
8107 CondDependOnLC
= doesDependOnLoopCounter(UB
, /*IsInitializer=*/false);
8111 bool OpenMPIterationSpaceChecker::setStep(Expr
*NewStep
, bool Subtract
) {
8112 // State consistency checking to ensure correct usage.
8113 assert(LCDecl
!= nullptr && LB
!= nullptr && Step
== nullptr);
8114 if (!NewStep
|| NewStep
->containsErrors())
8116 if (!NewStep
->isValueDependent()) {
8117 // Check that the step is integer expression.
8118 SourceLocation StepLoc
= NewStep
->getBeginLoc();
8119 ExprResult Val
= SemaRef
.PerformOpenMPImplicitIntegerConversion(
8120 StepLoc
, getExprAsWritten(NewStep
));
8121 if (Val
.isInvalid())
8123 NewStep
= Val
.get();
8125 // OpenMP [2.6, Canonical Loop Form, Restrictions]
8126 // If test-expr is of form var relational-op b and relational-op is < or
8127 // <= then incr-expr must cause var to increase on each iteration of the
8128 // loop. If test-expr is of form var relational-op b and relational-op is
8129 // > or >= then incr-expr must cause var to decrease on each iteration of
8131 // If test-expr is of form b relational-op var and relational-op is < or
8132 // <= then incr-expr must cause var to decrease on each iteration of the
8133 // loop. If test-expr is of form b relational-op var and relational-op is
8134 // > or >= then incr-expr must cause var to increase on each iteration of
8136 std::optional
<llvm::APSInt
> Result
=
8137 NewStep
->getIntegerConstantExpr(SemaRef
.Context
);
8138 bool IsUnsigned
= !NewStep
->getType()->hasSignedIntegerRepresentation();
8140 Result
&& Result
->isSigned() && (Subtract
!= Result
->isNegative());
8142 Result
&& Result
->isSigned() && (Subtract
== Result
->isNegative());
8143 bool IsConstZero
= Result
&& !Result
->getBoolValue();
8145 // != with increment is treated as <; != with decrement is treated as >
8147 TestIsLessOp
= IsConstPos
|| (IsUnsigned
&& !Subtract
);
8148 if (UB
&& (IsConstZero
||
8149 (*TestIsLessOp
? (IsConstNeg
|| (IsUnsigned
&& Subtract
))
8150 : (IsConstPos
|| (IsUnsigned
&& !Subtract
))))) {
8151 SemaRef
.Diag(NewStep
->getExprLoc(),
8152 diag::err_omp_loop_incr_not_compatible
)
8153 << LCDecl
<< *TestIsLessOp
<< NewStep
->getSourceRange();
8154 SemaRef
.Diag(ConditionLoc
,
8155 diag::note_omp_loop_cond_requres_compatible_incr
)
8156 << *TestIsLessOp
<< ConditionSrcRange
;
8159 if (*TestIsLessOp
== Subtract
) {
8161 SemaRef
.CreateBuiltinUnaryOp(NewStep
->getExprLoc(), UO_Minus
, NewStep
)
8163 Subtract
= !Subtract
;
8168 SubtractStep
= Subtract
;
8173 /// Checker for the non-rectangular loops. Checks if the initializer or
8174 /// condition expression references loop counter variable.
8175 class LoopCounterRefChecker final
8176 : public ConstStmtVisitor
<LoopCounterRefChecker
, bool> {
8179 const ValueDecl
*CurLCDecl
= nullptr;
8180 const ValueDecl
*DepDecl
= nullptr;
8181 const ValueDecl
*PrevDepDecl
= nullptr;
8182 bool IsInitializer
= true;
8183 bool SupportsNonRectangular
;
8184 unsigned BaseLoopId
= 0;
8185 bool checkDecl(const Expr
*E
, const ValueDecl
*VD
) {
8186 if (getCanonicalDecl(VD
) == getCanonicalDecl(CurLCDecl
)) {
8187 SemaRef
.Diag(E
->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter
)
8188 << (IsInitializer
? 0 : 1);
8191 const auto &&Data
= Stack
.isLoopControlVariable(VD
);
8192 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8193 // The type of the loop iterator on which we depend may not have a random
8194 // access iterator type.
8195 if (Data
.first
&& VD
->getType()->isRecordType()) {
8196 SmallString
<128> Name
;
8197 llvm::raw_svector_ostream
OS(Name
);
8198 VD
->getNameForDiagnostic(OS
, SemaRef
.getPrintingPolicy(),
8199 /*Qualified=*/true);
8200 SemaRef
.Diag(E
->getExprLoc(),
8201 diag::err_omp_wrong_dependency_iterator_type
)
8203 SemaRef
.Diag(VD
->getLocation(), diag::note_previous_decl
) << VD
;
8206 if (Data
.first
&& !SupportsNonRectangular
) {
8207 SemaRef
.Diag(E
->getExprLoc(), diag::err_omp_invariant_dependency
);
8211 (DepDecl
|| (PrevDepDecl
&&
8212 getCanonicalDecl(VD
) != getCanonicalDecl(PrevDepDecl
)))) {
8213 if (!DepDecl
&& PrevDepDecl
)
8214 DepDecl
= PrevDepDecl
;
8215 SmallString
<128> Name
;
8216 llvm::raw_svector_ostream
OS(Name
);
8217 DepDecl
->getNameForDiagnostic(OS
, SemaRef
.getPrintingPolicy(),
8218 /*Qualified=*/true);
8219 SemaRef
.Diag(E
->getExprLoc(),
8220 diag::err_omp_invariant_or_linear_dependency
)
8226 BaseLoopId
= Data
.first
;
8232 bool VisitDeclRefExpr(const DeclRefExpr
*E
) {
8233 const ValueDecl
*VD
= E
->getDecl();
8234 if (isa
<VarDecl
>(VD
))
8235 return checkDecl(E
, VD
);
8238 bool VisitMemberExpr(const MemberExpr
*E
) {
8239 if (isa
<CXXThisExpr
>(E
->getBase()->IgnoreParens())) {
8240 const ValueDecl
*VD
= E
->getMemberDecl();
8241 if (isa
<VarDecl
>(VD
) || isa
<FieldDecl
>(VD
))
8242 return checkDecl(E
, VD
);
8246 bool VisitStmt(const Stmt
*S
) {
8248 for (const Stmt
*Child
: S
->children())
8249 Res
= (Child
&& Visit(Child
)) || Res
;
8252 explicit LoopCounterRefChecker(Sema
&SemaRef
, DSAStackTy
&Stack
,
8253 const ValueDecl
*CurLCDecl
, bool IsInitializer
,
8254 const ValueDecl
*PrevDepDecl
= nullptr,
8255 bool SupportsNonRectangular
= true)
8256 : SemaRef(SemaRef
), Stack(Stack
), CurLCDecl(CurLCDecl
),
8257 PrevDepDecl(PrevDepDecl
), IsInitializer(IsInitializer
),
8258 SupportsNonRectangular(SupportsNonRectangular
) {}
8259 unsigned getBaseLoopId() const {
8260 assert(CurLCDecl
&& "Expected loop dependency.");
8263 const ValueDecl
*getDepDecl() const {
8264 assert(CurLCDecl
&& "Expected loop dependency.");
8270 std::optional
<unsigned>
8271 OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt
*S
,
8272 bool IsInitializer
) {
8273 // Check for the non-rectangular loops.
8274 LoopCounterRefChecker
LoopStmtChecker(SemaRef
, Stack
, LCDecl
, IsInitializer
,
8275 DepDecl
, SupportsNonRectangular
);
8276 if (LoopStmtChecker
.Visit(S
)) {
8277 DepDecl
= LoopStmtChecker
.getDepDecl();
8278 return LoopStmtChecker
.getBaseLoopId();
8280 return std::nullopt
;
8283 bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt
*S
, bool EmitDiags
) {
8284 // Check init-expr for canonical loop form and save loop counter
8285 // variable - #Var and its initialization value - #LB.
8286 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8288 // integer-type var = lb
8289 // random-access-iterator-type var = lb
8290 // pointer-type var = lb
8294 SemaRef
.Diag(DefaultLoc
, diag::err_omp_loop_not_canonical_init
);
8298 if (auto *ExprTemp
= dyn_cast
<ExprWithCleanups
>(S
))
8299 if (!ExprTemp
->cleanupsHaveSideEffects())
8300 S
= ExprTemp
->getSubExpr();
8302 InitSrcRange
= S
->getSourceRange();
8303 if (Expr
*E
= dyn_cast
<Expr
>(S
))
8304 S
= E
->IgnoreParens();
8305 if (auto *BO
= dyn_cast
<BinaryOperator
>(S
)) {
8306 if (BO
->getOpcode() == BO_Assign
) {
8307 Expr
*LHS
= BO
->getLHS()->IgnoreParens();
8308 if (auto *DRE
= dyn_cast
<DeclRefExpr
>(LHS
)) {
8309 if (auto *CED
= dyn_cast
<OMPCapturedExprDecl
>(DRE
->getDecl()))
8310 if (auto *ME
= dyn_cast
<MemberExpr
>(getExprAsWritten(CED
->getInit())))
8311 return setLCDeclAndLB(ME
->getMemberDecl(), ME
, BO
->getRHS(),
8313 return setLCDeclAndLB(DRE
->getDecl(), DRE
, BO
->getRHS(), EmitDiags
);
8315 if (auto *ME
= dyn_cast
<MemberExpr
>(LHS
)) {
8316 if (ME
->isArrow() &&
8317 isa
<CXXThisExpr
>(ME
->getBase()->IgnoreParenImpCasts()))
8318 return setLCDeclAndLB(ME
->getMemberDecl(), ME
, BO
->getRHS(),
8322 } else if (auto *DS
= dyn_cast
<DeclStmt
>(S
)) {
8323 if (DS
->isSingleDecl()) {
8324 if (auto *Var
= dyn_cast_or_null
<VarDecl
>(DS
->getSingleDecl())) {
8325 if (Var
->hasInit() && !Var
->getType()->isReferenceType()) {
8326 // Accept non-canonical init form here but emit ext. warning.
8327 if (Var
->getInitStyle() != VarDecl::CInit
&& EmitDiags
)
8328 SemaRef
.Diag(S
->getBeginLoc(),
8329 diag::ext_omp_loop_not_canonical_init
)
8330 << S
->getSourceRange();
8331 return setLCDeclAndLB(
8333 buildDeclRefExpr(SemaRef
, Var
,
8334 Var
->getType().getNonReferenceType(),
8336 Var
->getInit(), EmitDiags
);
8340 } else if (auto *CE
= dyn_cast
<CXXOperatorCallExpr
>(S
)) {
8341 if (CE
->getOperator() == OO_Equal
) {
8342 Expr
*LHS
= CE
->getArg(0);
8343 if (auto *DRE
= dyn_cast
<DeclRefExpr
>(LHS
)) {
8344 if (auto *CED
= dyn_cast
<OMPCapturedExprDecl
>(DRE
->getDecl()))
8345 if (auto *ME
= dyn_cast
<MemberExpr
>(getExprAsWritten(CED
->getInit())))
8346 return setLCDeclAndLB(ME
->getMemberDecl(), ME
, BO
->getRHS(),
8348 return setLCDeclAndLB(DRE
->getDecl(), DRE
, CE
->getArg(1), EmitDiags
);
8350 if (auto *ME
= dyn_cast
<MemberExpr
>(LHS
)) {
8351 if (ME
->isArrow() &&
8352 isa
<CXXThisExpr
>(ME
->getBase()->IgnoreParenImpCasts()))
8353 return setLCDeclAndLB(ME
->getMemberDecl(), ME
, BO
->getRHS(),
8359 if (dependent() || SemaRef
.CurContext
->isDependentContext())
8362 SemaRef
.Diag(S
->getBeginLoc(), diag::err_omp_loop_not_canonical_init
)
8363 << S
->getSourceRange();
8368 /// Ignore parenthesizes, implicit casts, copy constructor and return the
8369 /// variable (which may be the loop variable) if possible.
8370 static const ValueDecl
*getInitLCDecl(const Expr
*E
) {
8373 E
= getExprAsWritten(E
);
8374 if (const auto *CE
= dyn_cast_or_null
<CXXConstructExpr
>(E
))
8375 if (const CXXConstructorDecl
*Ctor
= CE
->getConstructor())
8376 if ((Ctor
->isCopyOrMoveConstructor() ||
8377 Ctor
->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8378 CE
->getNumArgs() > 0 && CE
->getArg(0) != nullptr)
8379 E
= CE
->getArg(0)->IgnoreParenImpCasts();
8380 if (const auto *DRE
= dyn_cast_or_null
<DeclRefExpr
>(E
)) {
8381 if (const auto *VD
= dyn_cast
<VarDecl
>(DRE
->getDecl()))
8382 return getCanonicalDecl(VD
);
8384 if (const auto *ME
= dyn_cast_or_null
<MemberExpr
>(E
))
8385 if (ME
->isArrow() && isa
<CXXThisExpr
>(ME
->getBase()->IgnoreParenImpCasts()))
8386 return getCanonicalDecl(ME
->getMemberDecl());
8390 bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr
*S
) {
8391 // Check test-expr for canonical form, save upper-bound UB, flags for
8392 // less/greater and for strict/non-strict comparison.
8393 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8394 // var relational-op b
8395 // b relational-op var
8397 bool IneqCondIsCanonical
= SemaRef
.getLangOpts().OpenMP
>= 50;
8399 SemaRef
.Diag(DefaultLoc
, diag::err_omp_loop_not_canonical_cond
)
8400 << (IneqCondIsCanonical
? 1 : 0) << LCDecl
;
8404 S
= getExprAsWritten(S
);
8405 SourceLocation CondLoc
= S
->getBeginLoc();
8406 auto &&CheckAndSetCond
=
8407 [this, IneqCondIsCanonical
](BinaryOperatorKind Opcode
, const Expr
*LHS
,
8408 const Expr
*RHS
, SourceRange SR
,
8409 SourceLocation OpLoc
) -> std::optional
<bool> {
8410 if (BinaryOperator::isRelationalOp(Opcode
)) {
8411 if (getInitLCDecl(LHS
) == LCDecl
)
8412 return setUB(const_cast<Expr
*>(RHS
),
8413 (Opcode
== BO_LT
|| Opcode
== BO_LE
),
8414 (Opcode
== BO_LT
|| Opcode
== BO_GT
), SR
, OpLoc
);
8415 if (getInitLCDecl(RHS
) == LCDecl
)
8416 return setUB(const_cast<Expr
*>(LHS
),
8417 (Opcode
== BO_GT
|| Opcode
== BO_GE
),
8418 (Opcode
== BO_LT
|| Opcode
== BO_GT
), SR
, OpLoc
);
8419 } else if (IneqCondIsCanonical
&& Opcode
== BO_NE
) {
8420 return setUB(const_cast<Expr
*>(getInitLCDecl(LHS
) == LCDecl
? RHS
: LHS
),
8421 /*LessOp=*/std::nullopt
,
8422 /*StrictOp=*/true, SR
, OpLoc
);
8424 return std::nullopt
;
8426 std::optional
<bool> Res
;
8427 if (auto *RBO
= dyn_cast
<CXXRewrittenBinaryOperator
>(S
)) {
8428 CXXRewrittenBinaryOperator::DecomposedForm DF
= RBO
->getDecomposedForm();
8429 Res
= CheckAndSetCond(DF
.Opcode
, DF
.LHS
, DF
.RHS
, RBO
->getSourceRange(),
8430 RBO
->getOperatorLoc());
8431 } else if (auto *BO
= dyn_cast
<BinaryOperator
>(S
)) {
8432 Res
= CheckAndSetCond(BO
->getOpcode(), BO
->getLHS(), BO
->getRHS(),
8433 BO
->getSourceRange(), BO
->getOperatorLoc());
8434 } else if (auto *CE
= dyn_cast
<CXXOperatorCallExpr
>(S
)) {
8435 if (CE
->getNumArgs() == 2) {
8436 Res
= CheckAndSetCond(
8437 BinaryOperator::getOverloadedOpcode(CE
->getOperator()), CE
->getArg(0),
8438 CE
->getArg(1), CE
->getSourceRange(), CE
->getOperatorLoc());
8443 if (dependent() || SemaRef
.CurContext
->isDependentContext())
8445 SemaRef
.Diag(CondLoc
, diag::err_omp_loop_not_canonical_cond
)
8446 << (IneqCondIsCanonical
? 1 : 0) << S
->getSourceRange() << LCDecl
;
8450 bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr
*RHS
) {
8451 // RHS of canonical loop form increment can be:
8456 RHS
= RHS
->IgnoreParenImpCasts();
8457 if (auto *BO
= dyn_cast
<BinaryOperator
>(RHS
)) {
8458 if (BO
->isAdditiveOp()) {
8459 bool IsAdd
= BO
->getOpcode() == BO_Add
;
8460 if (getInitLCDecl(BO
->getLHS()) == LCDecl
)
8461 return setStep(BO
->getRHS(), !IsAdd
);
8462 if (IsAdd
&& getInitLCDecl(BO
->getRHS()) == LCDecl
)
8463 return setStep(BO
->getLHS(), /*Subtract=*/false);
8465 } else if (auto *CE
= dyn_cast
<CXXOperatorCallExpr
>(RHS
)) {
8466 bool IsAdd
= CE
->getOperator() == OO_Plus
;
8467 if ((IsAdd
|| CE
->getOperator() == OO_Minus
) && CE
->getNumArgs() == 2) {
8468 if (getInitLCDecl(CE
->getArg(0)) == LCDecl
)
8469 return setStep(CE
->getArg(1), !IsAdd
);
8470 if (IsAdd
&& getInitLCDecl(CE
->getArg(1)) == LCDecl
)
8471 return setStep(CE
->getArg(0), /*Subtract=*/false);
8474 if (dependent() || SemaRef
.CurContext
->isDependentContext())
8476 SemaRef
.Diag(RHS
->getBeginLoc(), diag::err_omp_loop_not_canonical_incr
)
8477 << RHS
->getSourceRange() << LCDecl
;
8481 bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr
*S
) {
8482 // Check incr-expr for canonical loop form and return true if it
8483 // does not conform.
8484 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8496 SemaRef
.Diag(DefaultLoc
, diag::err_omp_loop_not_canonical_incr
) << LCDecl
;
8499 if (auto *ExprTemp
= dyn_cast
<ExprWithCleanups
>(S
))
8500 if (!ExprTemp
->cleanupsHaveSideEffects())
8501 S
= ExprTemp
->getSubExpr();
8503 IncrementSrcRange
= S
->getSourceRange();
8504 S
= S
->IgnoreParens();
8505 if (auto *UO
= dyn_cast
<UnaryOperator
>(S
)) {
8506 if (UO
->isIncrementDecrementOp() &&
8507 getInitLCDecl(UO
->getSubExpr()) == LCDecl
)
8508 return setStep(SemaRef
8509 .ActOnIntegerConstant(UO
->getBeginLoc(),
8510 (UO
->isDecrementOp() ? -1 : 1))
8512 /*Subtract=*/false);
8513 } else if (auto *BO
= dyn_cast
<BinaryOperator
>(S
)) {
8514 switch (BO
->getOpcode()) {
8517 if (getInitLCDecl(BO
->getLHS()) == LCDecl
)
8518 return setStep(BO
->getRHS(), BO
->getOpcode() == BO_SubAssign
);
8521 if (getInitLCDecl(BO
->getLHS()) == LCDecl
)
8522 return checkAndSetIncRHS(BO
->getRHS());
8527 } else if (auto *CE
= dyn_cast
<CXXOperatorCallExpr
>(S
)) {
8528 switch (CE
->getOperator()) {
8531 if (getInitLCDecl(CE
->getArg(0)) == LCDecl
)
8532 return setStep(SemaRef
8533 .ActOnIntegerConstant(
8535 ((CE
->getOperator() == OO_MinusMinus
) ? -1 : 1))
8537 /*Subtract=*/false);
8541 if (getInitLCDecl(CE
->getArg(0)) == LCDecl
)
8542 return setStep(CE
->getArg(1), CE
->getOperator() == OO_MinusEqual
);
8545 if (getInitLCDecl(CE
->getArg(0)) == LCDecl
)
8546 return checkAndSetIncRHS(CE
->getArg(1));
8552 if (dependent() || SemaRef
.CurContext
->isDependentContext())
8554 SemaRef
.Diag(S
->getBeginLoc(), diag::err_omp_loop_not_canonical_incr
)
8555 << S
->getSourceRange() << LCDecl
;
8560 tryBuildCapture(Sema
&SemaRef
, Expr
*Capture
,
8561 llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
,
8562 StringRef Name
= ".capture_expr.") {
8563 if (SemaRef
.CurContext
->isDependentContext() || Capture
->containsErrors())
8565 if (Capture
->isEvaluatable(SemaRef
.Context
, Expr::SE_AllowSideEffects
))
8566 return SemaRef
.PerformImplicitConversion(
8567 Capture
->IgnoreImpCasts(), Capture
->getType(), Sema::AA_Converting
,
8568 /*AllowExplicit=*/true);
8569 auto I
= Captures
.find(Capture
);
8570 if (I
!= Captures
.end())
8571 return buildCapture(SemaRef
, Capture
, I
->second
, Name
);
8572 DeclRefExpr
*Ref
= nullptr;
8573 ExprResult Res
= buildCapture(SemaRef
, Capture
, Ref
, Name
);
8574 Captures
[Capture
] = Ref
;
8578 /// Calculate number of iterations, transforming to unsigned, if number of
8579 /// iterations may be larger than the original type.
8581 calculateNumIters(Sema
&SemaRef
, Scope
*S
, SourceLocation DefaultLoc
,
8582 Expr
*Lower
, Expr
*Upper
, Expr
*Step
, QualType LCTy
,
8583 bool TestIsStrictOp
, bool RoundToStep
,
8584 llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
) {
8585 ExprResult NewStep
= tryBuildCapture(SemaRef
, Step
, Captures
, ".new_step");
8586 if (!NewStep
.isUsable())
8588 llvm::APSInt LRes
, SRes
;
8589 bool IsLowerConst
= false, IsStepConst
= false;
8590 if (std::optional
<llvm::APSInt
> Res
=
8591 Lower
->getIntegerConstantExpr(SemaRef
.Context
)) {
8593 IsLowerConst
= true;
8595 if (std::optional
<llvm::APSInt
> Res
=
8596 Step
->getIntegerConstantExpr(SemaRef
.Context
)) {
8600 bool NoNeedToConvert
= IsLowerConst
&& !RoundToStep
&&
8601 ((!TestIsStrictOp
&& LRes
.isNonNegative()) ||
8602 (TestIsStrictOp
&& LRes
.isStrictlyPositive()));
8603 bool NeedToReorganize
= false;
8604 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8605 if (!NoNeedToConvert
&& IsLowerConst
&&
8606 (TestIsStrictOp
|| (RoundToStep
&& IsStepConst
))) {
8607 NoNeedToConvert
= true;
8609 unsigned BW
= LRes
.getBitWidth() > SRes
.getBitWidth()
8610 ? LRes
.getBitWidth()
8611 : SRes
.getBitWidth();
8612 LRes
= LRes
.extend(BW
+ 1);
8613 LRes
.setIsSigned(true);
8614 SRes
= SRes
.extend(BW
+ 1);
8615 SRes
.setIsSigned(true);
8617 NoNeedToConvert
= LRes
.trunc(BW
).extend(BW
+ 1) == LRes
;
8618 LRes
= LRes
.trunc(BW
);
8620 if (TestIsStrictOp
) {
8621 unsigned BW
= LRes
.getBitWidth();
8622 LRes
= LRes
.extend(BW
+ 1);
8623 LRes
.setIsSigned(true);
8626 NoNeedToConvert
&& LRes
.trunc(BW
).extend(BW
+ 1) == LRes
;
8627 // truncate to the original bitwidth.
8628 LRes
= LRes
.trunc(BW
);
8630 NeedToReorganize
= NoNeedToConvert
;
8633 bool IsUpperConst
= false;
8634 if (std::optional
<llvm::APSInt
> Res
=
8635 Upper
->getIntegerConstantExpr(SemaRef
.Context
)) {
8637 IsUpperConst
= true;
8639 if (NoNeedToConvert
&& IsLowerConst
&& IsUpperConst
&&
8640 (!RoundToStep
|| IsStepConst
)) {
8641 unsigned BW
= LRes
.getBitWidth() > URes
.getBitWidth() ? LRes
.getBitWidth()
8642 : URes
.getBitWidth();
8643 LRes
= LRes
.extend(BW
+ 1);
8644 LRes
.setIsSigned(true);
8645 URes
= URes
.extend(BW
+ 1);
8646 URes
.setIsSigned(true);
8648 NoNeedToConvert
= URes
.trunc(BW
).extend(BW
+ 1) == URes
;
8649 NeedToReorganize
= NoNeedToConvert
;
8651 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8652 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8654 if ((!NoNeedToConvert
|| (LRes
.isNegative() && !IsUpperConst
)) &&
8655 !LCTy
->isDependentType() && LCTy
->isIntegerType()) {
8656 QualType LowerTy
= Lower
->getType();
8657 QualType UpperTy
= Upper
->getType();
8658 uint64_t LowerSize
= SemaRef
.Context
.getTypeSize(LowerTy
);
8659 uint64_t UpperSize
= SemaRef
.Context
.getTypeSize(UpperTy
);
8660 if ((LowerSize
<= UpperSize
&& UpperTy
->hasSignedIntegerRepresentation()) ||
8661 (LowerSize
> UpperSize
&& LowerTy
->hasSignedIntegerRepresentation())) {
8662 QualType CastType
= SemaRef
.Context
.getIntTypeForBitwidth(
8663 LowerSize
> UpperSize
? LowerSize
: UpperSize
, /*Signed=*/0);
8666 .PerformImplicitConversion(
8667 SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, Upper
).get(),
8668 CastType
, Sema::AA_Converting
)
8670 Lower
= SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, Lower
).get();
8671 NewStep
= SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, NewStep
.get());
8674 if (!Lower
|| !Upper
|| NewStep
.isInvalid())
8678 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8680 if (NeedToReorganize
) {
8686 SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Sub
, Diff
.get(), NewStep
.get());
8687 if (!Diff
.isUsable())
8691 // Lower - Step [+ 1]
8693 Diff
= SemaRef
.BuildBinOp(
8694 S
, DefaultLoc
, BO_Add
, Diff
.get(),
8695 SemaRef
.ActOnIntegerConstant(SourceLocation(), 1).get());
8696 if (!Diff
.isUsable())
8699 Diff
= SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, Diff
.get());
8700 if (!Diff
.isUsable())
8703 // Upper - (Lower - Step [+ 1]).
8704 Diff
= SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Sub
, Upper
, Diff
.get());
8705 if (!Diff
.isUsable())
8708 Diff
= SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Sub
, Upper
, Lower
);
8710 if (!Diff
.isUsable() && LCTy
->getAsCXXRecordDecl()) {
8711 // BuildBinOp already emitted error, this one is to point user to upper
8712 // and lower bound, and to tell what is passed to 'operator-'.
8713 SemaRef
.Diag(Upper
->getBeginLoc(), diag::err_omp_loop_diff_cxx
)
8714 << Upper
->getSourceRange() << Lower
->getSourceRange();
8718 if (!Diff
.isUsable())
8721 // Upper - Lower [- 1]
8723 Diff
= SemaRef
.BuildBinOp(
8724 S
, DefaultLoc
, BO_Sub
, Diff
.get(),
8725 SemaRef
.ActOnIntegerConstant(SourceLocation(), 1).get());
8726 if (!Diff
.isUsable())
8730 // Upper - Lower [- 1] + Step
8732 SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Add
, Diff
.get(), NewStep
.get());
8733 if (!Diff
.isUsable())
8738 // Parentheses (for dumping/debugging purposes only).
8739 Diff
= SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, Diff
.get());
8740 if (!Diff
.isUsable())
8743 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8744 Diff
= SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Div
, Diff
.get(), NewStep
.get());
8745 if (!Diff
.isUsable())
8751 /// Build the expression to calculate the number of iterations.
8752 Expr
*OpenMPIterationSpaceChecker::buildNumIterations(
8753 Scope
*S
, ArrayRef
<LoopIterationSpace
> ResultIterSpaces
, bool LimitedType
,
8754 llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
) const {
8755 QualType VarType
= LCDecl
->getType().getNonReferenceType();
8756 if (!VarType
->isIntegerType() && !VarType
->isPointerType() &&
8757 !SemaRef
.getLangOpts().CPlusPlus
)
8761 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8762 // max(LB(MinVal), LB(MaxVal)))
8763 if (InitDependOnLC
) {
8764 const LoopIterationSpace
&IS
= ResultIterSpaces
[*InitDependOnLC
- 1];
8765 if (!IS
.MinValue
|| !IS
.MaxValue
)
8768 ExprResult MinValue
=
8769 SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, IS
.MinValue
);
8770 if (!MinValue
.isUsable())
8773 ExprResult LBMinVal
= SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Assign
,
8774 IS
.CounterVar
, MinValue
.get());
8775 if (!LBMinVal
.isUsable())
8777 // OuterVar = Min, LBVal
8779 SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Comma
, LBMinVal
.get(), LBVal
);
8780 if (!LBMinVal
.isUsable())
8782 // (OuterVar = Min, LBVal)
8783 LBMinVal
= SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, LBMinVal
.get());
8784 if (!LBMinVal
.isUsable())
8788 ExprResult MaxValue
=
8789 SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, IS
.MaxValue
);
8790 if (!MaxValue
.isUsable())
8793 ExprResult LBMaxVal
= SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Assign
,
8794 IS
.CounterVar
, MaxValue
.get());
8795 if (!LBMaxVal
.isUsable())
8797 // OuterVar = Max, LBVal
8799 SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Comma
, LBMaxVal
.get(), LBVal
);
8800 if (!LBMaxVal
.isUsable())
8802 // (OuterVar = Max, LBVal)
8803 LBMaxVal
= SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, LBMaxVal
.get());
8804 if (!LBMaxVal
.isUsable())
8808 tryBuildCapture(SemaRef
, LBMinVal
.get(), Captures
, ".lb_min").get();
8810 tryBuildCapture(SemaRef
, LBMaxVal
.get(), Captures
, ".lb_max").get();
8811 if (!LBMin
|| !LBMax
)
8813 // LB(MinVal) < LB(MaxVal)
8814 ExprResult MinLessMaxRes
=
8815 SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_LT
, LBMin
, LBMax
);
8816 if (!MinLessMaxRes
.isUsable())
8819 tryBuildCapture(SemaRef
, MinLessMaxRes
.get(), Captures
, ".min_less_max")
8823 if (*TestIsLessOp
) {
8824 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8826 ExprResult MinLB
= SemaRef
.ActOnConditionalOp(DefaultLoc
, DefaultLoc
,
8827 MinLessMax
, LBMin
, LBMax
);
8828 if (!MinLB
.isUsable())
8830 LBVal
= MinLB
.get();
8832 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8834 ExprResult MaxLB
= SemaRef
.ActOnConditionalOp(DefaultLoc
, DefaultLoc
,
8835 MinLessMax
, LBMax
, LBMin
);
8836 if (!MaxLB
.isUsable())
8838 LBVal
= MaxLB
.get();
8842 SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Assign
, IS
.CounterVar
, LBVal
);
8843 if (!LBMinVal
.isUsable())
8845 LBVal
= LBMinVal
.get();
8847 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8848 // min(UB(MinVal), UB(MaxVal))
8849 if (CondDependOnLC
) {
8850 const LoopIterationSpace
&IS
= ResultIterSpaces
[*CondDependOnLC
- 1];
8851 if (!IS
.MinValue
|| !IS
.MaxValue
)
8854 ExprResult MinValue
=
8855 SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, IS
.MinValue
);
8856 if (!MinValue
.isUsable())
8859 ExprResult UBMinVal
= SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Assign
,
8860 IS
.CounterVar
, MinValue
.get());
8861 if (!UBMinVal
.isUsable())
8863 // OuterVar = Min, UBVal
8865 SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Comma
, UBMinVal
.get(), UBVal
);
8866 if (!UBMinVal
.isUsable())
8868 // (OuterVar = Min, UBVal)
8869 UBMinVal
= SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, UBMinVal
.get());
8870 if (!UBMinVal
.isUsable())
8874 ExprResult MaxValue
=
8875 SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, IS
.MaxValue
);
8876 if (!MaxValue
.isUsable())
8879 ExprResult UBMaxVal
= SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Assign
,
8880 IS
.CounterVar
, MaxValue
.get());
8881 if (!UBMaxVal
.isUsable())
8883 // OuterVar = Max, UBVal
8885 SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Comma
, UBMaxVal
.get(), UBVal
);
8886 if (!UBMaxVal
.isUsable())
8888 // (OuterVar = Max, UBVal)
8889 UBMaxVal
= SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, UBMaxVal
.get());
8890 if (!UBMaxVal
.isUsable())
8894 tryBuildCapture(SemaRef
, UBMinVal
.get(), Captures
, ".ub_min").get();
8896 tryBuildCapture(SemaRef
, UBMaxVal
.get(), Captures
, ".ub_max").get();
8897 if (!UBMin
|| !UBMax
)
8899 // UB(MinVal) > UB(MaxVal)
8900 ExprResult MinGreaterMaxRes
=
8901 SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_GT
, UBMin
, UBMax
);
8902 if (!MinGreaterMaxRes
.isUsable())
8904 Expr
*MinGreaterMax
= tryBuildCapture(SemaRef
, MinGreaterMaxRes
.get(),
8905 Captures
, ".min_greater_max")
8909 if (*TestIsLessOp
) {
8910 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
8912 ExprResult MaxUB
= SemaRef
.ActOnConditionalOp(
8913 DefaultLoc
, DefaultLoc
, MinGreaterMax
, UBMin
, UBMax
);
8914 if (!MaxUB
.isUsable())
8916 UBVal
= MaxUB
.get();
8918 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
8920 ExprResult MinUB
= SemaRef
.ActOnConditionalOp(
8921 DefaultLoc
, DefaultLoc
, MinGreaterMax
, UBMax
, UBMin
);
8922 if (!MinUB
.isUsable())
8924 UBVal
= MinUB
.get();
8927 Expr
*UBExpr
= *TestIsLessOp
? UBVal
: LBVal
;
8928 Expr
*LBExpr
= *TestIsLessOp
? LBVal
: UBVal
;
8929 Expr
*Upper
= tryBuildCapture(SemaRef
, UBExpr
, Captures
, ".upper").get();
8930 Expr
*Lower
= tryBuildCapture(SemaRef
, LBExpr
, Captures
, ".lower").get();
8931 if (!Upper
|| !Lower
)
8934 ExprResult Diff
= calculateNumIters(SemaRef
, S
, DefaultLoc
, Lower
, Upper
,
8935 Step
, VarType
, TestIsStrictOp
,
8936 /*RoundToStep=*/true, Captures
);
8937 if (!Diff
.isUsable())
8940 // OpenMP runtime requires 32-bit or 64-bit loop variables.
8941 QualType Type
= Diff
.get()->getType();
8942 ASTContext
&C
= SemaRef
.Context
;
8943 bool UseVarType
= VarType
->hasIntegerRepresentation() &&
8944 C
.getTypeSize(Type
) > C
.getTypeSize(VarType
);
8945 if (!Type
->isIntegerType() || UseVarType
) {
8947 UseVarType
? C
.getTypeSize(VarType
) : C
.getTypeSize(Type
);
8948 bool IsSigned
= UseVarType
? VarType
->hasSignedIntegerRepresentation()
8949 : Type
->hasSignedIntegerRepresentation();
8950 Type
= C
.getIntTypeForBitwidth(NewSize
, IsSigned
);
8951 if (!SemaRef
.Context
.hasSameType(Diff
.get()->getType(), Type
)) {
8952 Diff
= SemaRef
.PerformImplicitConversion(
8953 Diff
.get(), Type
, Sema::AA_Converting
, /*AllowExplicit=*/true);
8954 if (!Diff
.isUsable())
8959 unsigned NewSize
= (C
.getTypeSize(Type
) > 32) ? 64 : 32;
8960 if (NewSize
!= C
.getTypeSize(Type
)) {
8961 if (NewSize
< C
.getTypeSize(Type
)) {
8962 assert(NewSize
== 64 && "incorrect loop var size");
8963 SemaRef
.Diag(DefaultLoc
, diag::warn_omp_loop_64_bit_var
)
8964 << InitSrcRange
<< ConditionSrcRange
;
8966 QualType NewType
= C
.getIntTypeForBitwidth(
8967 NewSize
, Type
->hasSignedIntegerRepresentation() ||
8968 C
.getTypeSize(Type
) < NewSize
);
8969 if (!SemaRef
.Context
.hasSameType(Diff
.get()->getType(), NewType
)) {
8970 Diff
= SemaRef
.PerformImplicitConversion(Diff
.get(), NewType
,
8971 Sema::AA_Converting
, true);
8972 if (!Diff
.isUsable())
8981 std::pair
<Expr
*, Expr
*> OpenMPIterationSpaceChecker::buildMinMaxValues(
8982 Scope
*S
, llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
) const {
8983 // Do not build for iterators, they cannot be used in non-rectangular loop
8985 if (LCDecl
->getType()->isRecordType())
8986 return std::make_pair(nullptr, nullptr);
8987 // If we subtract, the min is in the condition, otherwise the min is in the
8989 Expr
*MinExpr
= nullptr;
8990 Expr
*MaxExpr
= nullptr;
8991 Expr
*LBExpr
= *TestIsLessOp
? LB
: UB
;
8992 Expr
*UBExpr
= *TestIsLessOp
? UB
: LB
;
8994 *TestIsLessOp
? InitDependOnLC
.has_value() : CondDependOnLC
.has_value();
8996 *TestIsLessOp
? CondDependOnLC
.has_value() : InitDependOnLC
.has_value();
8998 LBNonRect
? LBExpr
: tryBuildCapture(SemaRef
, LBExpr
, Captures
).get();
9000 UBNonRect
? UBExpr
: tryBuildCapture(SemaRef
, UBExpr
, Captures
).get();
9001 if (!Upper
|| !Lower
)
9002 return std::make_pair(nullptr, nullptr);
9009 // Build minimum/maximum value based on number of iterations.
9010 QualType VarType
= LCDecl
->getType().getNonReferenceType();
9012 ExprResult Diff
= calculateNumIters(SemaRef
, S
, DefaultLoc
, Lower
, Upper
,
9013 Step
, VarType
, TestIsStrictOp
,
9014 /*RoundToStep=*/false, Captures
);
9015 if (!Diff
.isUsable())
9016 return std::make_pair(nullptr, nullptr);
9018 // ((Upper - Lower [- 1]) / Step) * Step
9019 // Parentheses (for dumping/debugging purposes only).
9020 Diff
= SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, Diff
.get());
9021 if (!Diff
.isUsable())
9022 return std::make_pair(nullptr, nullptr);
9024 ExprResult NewStep
= tryBuildCapture(SemaRef
, Step
, Captures
, ".new_step");
9025 if (!NewStep
.isUsable())
9026 return std::make_pair(nullptr, nullptr);
9027 Diff
= SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Mul
, Diff
.get(), NewStep
.get());
9028 if (!Diff
.isUsable())
9029 return std::make_pair(nullptr, nullptr);
9031 // Parentheses (for dumping/debugging purposes only).
9032 Diff
= SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, Diff
.get());
9033 if (!Diff
.isUsable())
9034 return std::make_pair(nullptr, nullptr);
9036 // Convert to the ptrdiff_t, if original type is pointer.
9037 if (VarType
->isAnyPointerType() &&
9038 !SemaRef
.Context
.hasSameType(
9039 Diff
.get()->getType(),
9040 SemaRef
.Context
.getUnsignedPointerDiffType())) {
9041 Diff
= SemaRef
.PerformImplicitConversion(
9042 Diff
.get(), SemaRef
.Context
.getUnsignedPointerDiffType(),
9043 Sema::AA_Converting
, /*AllowExplicit=*/true);
9045 if (!Diff
.isUsable())
9046 return std::make_pair(nullptr, nullptr);
9048 if (*TestIsLessOp
) {
9050 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
9051 Diff
= SemaRef
.BuildBinOp(
9052 S
, DefaultLoc
, BO_Add
,
9053 SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, Lower
).get(),
9055 if (!Diff
.isUsable())
9056 return std::make_pair(nullptr, nullptr);
9059 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
9060 Diff
= SemaRef
.BuildBinOp(
9061 S
, DefaultLoc
, BO_Sub
,
9062 SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, Upper
).get(),
9064 if (!Diff
.isUsable())
9065 return std::make_pair(nullptr, nullptr);
9068 // Convert to the original type.
9069 if (SemaRef
.Context
.hasSameType(Diff
.get()->getType(), VarType
))
9070 Diff
= SemaRef
.PerformImplicitConversion(Diff
.get(), VarType
,
9071 Sema::AA_Converting
,
9072 /*AllowExplicit=*/true);
9073 if (!Diff
.isUsable())
9074 return std::make_pair(nullptr, nullptr);
9076 Sema::TentativeAnalysisScope
Trap(SemaRef
);
9077 Diff
= SemaRef
.ActOnFinishFullExpr(Diff
.get(), /*DiscardedValue=*/false);
9078 if (!Diff
.isUsable())
9079 return std::make_pair(nullptr, nullptr);
9082 MaxExpr
= Diff
.get();
9084 MinExpr
= Diff
.get();
9086 return std::make_pair(MinExpr
, MaxExpr
);
9089 Expr
*OpenMPIterationSpaceChecker::buildFinalCondition(Scope
*S
) const {
9090 if (InitDependOnLC
|| CondDependOnLC
)
9095 Expr
*OpenMPIterationSpaceChecker::buildPreCond(
9096 Scope
*S
, Expr
*Cond
,
9097 llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
) const {
9098 // Do not build a precondition when the condition/initialization is dependent
9099 // to prevent pessimistic early loop exit.
9100 // TODO: this can be improved by calculating min/max values but not sure that
9101 // it will be very effective.
9102 if (CondDependOnLC
|| InitDependOnLC
)
9104 .PerformImplicitConversion(
9105 SemaRef
.ActOnIntegerConstant(SourceLocation(), 1).get(),
9106 SemaRef
.Context
.BoolTy
, /*Action=*/Sema::AA_Casting
,
9107 /*AllowExplicit=*/true)
9110 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
9111 Sema::TentativeAnalysisScope
Trap(SemaRef
);
9113 ExprResult NewLB
= tryBuildCapture(SemaRef
, LB
, Captures
);
9114 ExprResult NewUB
= tryBuildCapture(SemaRef
, UB
, Captures
);
9115 if (!NewLB
.isUsable() || !NewUB
.isUsable())
9118 ExprResult CondExpr
=
9119 SemaRef
.BuildBinOp(S
, DefaultLoc
,
9120 *TestIsLessOp
? (TestIsStrictOp
? BO_LT
: BO_LE
)
9121 : (TestIsStrictOp
? BO_GT
: BO_GE
),
9122 NewLB
.get(), NewUB
.get());
9123 if (CondExpr
.isUsable()) {
9124 if (!SemaRef
.Context
.hasSameUnqualifiedType(CondExpr
.get()->getType(),
9125 SemaRef
.Context
.BoolTy
))
9126 CondExpr
= SemaRef
.PerformImplicitConversion(
9127 CondExpr
.get(), SemaRef
.Context
.BoolTy
, /*Action=*/Sema::AA_Casting
,
9128 /*AllowExplicit=*/true);
9131 // Otherwise use original loop condition and evaluate it in runtime.
9132 return CondExpr
.isUsable() ? CondExpr
.get() : Cond
;
9135 /// Build reference expression to the counter be used for codegen.
9136 DeclRefExpr
*OpenMPIterationSpaceChecker::buildCounterVar(
9137 llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
,
9138 DSAStackTy
&DSA
) const {
9139 auto *VD
= dyn_cast
<VarDecl
>(LCDecl
);
9141 VD
= SemaRef
.isOpenMPCapturedDecl(LCDecl
);
9142 DeclRefExpr
*Ref
= buildDeclRefExpr(
9143 SemaRef
, VD
, VD
->getType().getNonReferenceType(), DefaultLoc
);
9144 const DSAStackTy::DSAVarData Data
=
9145 DSA
.getTopDSA(LCDecl
, /*FromParent=*/false);
9146 // If the loop control decl is explicitly marked as private, do not mark it
9147 // as captured again.
9148 if (!isOpenMPPrivate(Data
.CKind
) || !Data
.RefExpr
)
9149 Captures
.insert(std::make_pair(LCRef
, Ref
));
9152 return cast
<DeclRefExpr
>(LCRef
);
9155 Expr
*OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9156 if (LCDecl
&& !LCDecl
->isInvalidDecl()) {
9157 QualType Type
= LCDecl
->getType().getNonReferenceType();
9158 VarDecl
*PrivateVar
= buildVarDecl(
9159 SemaRef
, DefaultLoc
, Type
, LCDecl
->getName(),
9160 LCDecl
->hasAttrs() ? &LCDecl
->getAttrs() : nullptr,
9161 isa
<VarDecl
>(LCDecl
)
9162 ? buildDeclRefExpr(SemaRef
, cast
<VarDecl
>(LCDecl
), Type
, DefaultLoc
)
9164 if (PrivateVar
->isInvalidDecl())
9166 return buildDeclRefExpr(SemaRef
, PrivateVar
, Type
, DefaultLoc
);
9171 /// Build initialization of the counter to be used for codegen.
9172 Expr
*OpenMPIterationSpaceChecker::buildCounterInit() const { return LB
; }
9174 /// Build step of the counter be used for codegen.
9175 Expr
*OpenMPIterationSpaceChecker::buildCounterStep() const { return Step
; }
9177 Expr
*OpenMPIterationSpaceChecker::buildOrderedLoopData(
9178 Scope
*S
, Expr
*Counter
,
9179 llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
, SourceLocation Loc
,
9180 Expr
*Inc
, OverloadedOperatorKind OOK
) {
9181 Expr
*Cnt
= SemaRef
.DefaultLvalueConversion(Counter
).get();
9185 assert((OOK
== OO_Plus
|| OOK
== OO_Minus
) &&
9186 "Expected only + or - operations for depend clauses.");
9187 BinaryOperatorKind BOK
= (OOK
== OO_Plus
) ? BO_Add
: BO_Sub
;
9188 Cnt
= SemaRef
.BuildBinOp(S
, Loc
, BOK
, Cnt
, Inc
).get();
9192 QualType VarType
= LCDecl
->getType().getNonReferenceType();
9193 if (!VarType
->isIntegerType() && !VarType
->isPointerType() &&
9194 !SemaRef
.getLangOpts().CPlusPlus
)
9198 *TestIsLessOp
? Cnt
: tryBuildCapture(SemaRef
, LB
, Captures
).get();
9200 *TestIsLessOp
? tryBuildCapture(SemaRef
, LB
, Captures
).get() : Cnt
;
9201 if (!Upper
|| !Lower
)
9204 ExprResult Diff
= calculateNumIters(
9205 SemaRef
, S
, DefaultLoc
, Lower
, Upper
, Step
, VarType
,
9206 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures
);
9207 if (!Diff
.isUsable())
9214 void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc
, Stmt
*Init
) {
9215 assert(getLangOpts().OpenMP
&& "OpenMP is not active.");
9216 assert(Init
&& "Expected loop in canonical form.");
9217 unsigned AssociatedLoops
= DSAStack
->getAssociatedLoops();
9218 if (AssociatedLoops
> 0 &&
9219 isOpenMPLoopDirective(DSAStack
->getCurrentDirective())) {
9220 DSAStack
->loopStart();
9221 OpenMPIterationSpaceChecker
ISC(*this, /*SupportsNonRectangular=*/true,
9223 if (!ISC
.checkAndSetInit(Init
, /*EmitDiags=*/false)) {
9224 if (ValueDecl
*D
= ISC
.getLoopDecl()) {
9225 auto *VD
= dyn_cast
<VarDecl
>(D
);
9226 DeclRefExpr
*PrivateRef
= nullptr;
9228 if (VarDecl
*Private
= isOpenMPCapturedDecl(D
)) {
9231 PrivateRef
= buildCapture(*this, D
, ISC
.getLoopDeclRefExpr(),
9232 /*WithInit=*/false);
9233 VD
= cast
<VarDecl
>(PrivateRef
->getDecl());
9236 DSAStack
->addLoopControlVariable(D
, VD
);
9237 const Decl
*LD
= DSAStack
->getPossiblyLoopCunter();
9238 if (LD
!= D
->getCanonicalDecl()) {
9239 DSAStack
->resetPossibleLoopCounter();
9240 if (auto *Var
= dyn_cast_or_null
<VarDecl
>(LD
))
9241 MarkDeclarationsReferencedInExpr(
9242 buildDeclRefExpr(*this, const_cast<VarDecl
*>(Var
),
9243 Var
->getType().getNonLValueExprType(Context
),
9244 ForLoc
, /*RefersToCapture=*/true));
9246 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
9247 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9248 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9249 // associated for-loop of a simd construct with just one associated
9250 // for-loop may be listed in a linear clause with a constant-linear-step
9251 // that is the increment of the associated for-loop. The loop iteration
9252 // variable(s) in the associated for-loop(s) of a for or parallel for
9253 // construct may be listed in a private or lastprivate clause.
9254 DSAStackTy::DSAVarData DVar
=
9255 DSAStack
->getTopDSA(D
, /*FromParent=*/false);
9256 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9257 // is declared in the loop and it is predetermined as a private.
9258 Expr
*LoopDeclRefExpr
= ISC
.getLoopDeclRefExpr();
9259 OpenMPClauseKind PredeterminedCKind
=
9260 isOpenMPSimdDirective(DKind
)
9261 ? (DSAStack
->hasMutipleLoops() ? OMPC_lastprivate
: OMPC_linear
)
9263 if (((isOpenMPSimdDirective(DKind
) && DVar
.CKind
!= OMPC_unknown
&&
9264 DVar
.CKind
!= PredeterminedCKind
&& DVar
.RefExpr
&&
9265 (LangOpts
.OpenMP
<= 45 || (DVar
.CKind
!= OMPC_lastprivate
&&
9266 DVar
.CKind
!= OMPC_private
))) ||
9267 ((isOpenMPWorksharingDirective(DKind
) || DKind
== OMPD_taskloop
||
9268 DKind
== OMPD_master_taskloop
|| DKind
== OMPD_masked_taskloop
||
9269 DKind
== OMPD_parallel_master_taskloop
||
9270 DKind
== OMPD_parallel_masked_taskloop
||
9271 isOpenMPDistributeDirective(DKind
)) &&
9272 !isOpenMPSimdDirective(DKind
) && DVar
.CKind
!= OMPC_unknown
&&
9273 DVar
.CKind
!= OMPC_private
&& DVar
.CKind
!= OMPC_lastprivate
)) &&
9274 (DVar
.CKind
!= OMPC_private
|| DVar
.RefExpr
)) {
9275 Diag(Init
->getBeginLoc(), diag::err_omp_loop_var_dsa
)
9276 << getOpenMPClauseName(DVar
.CKind
)
9277 << getOpenMPDirectiveName(DKind
)
9278 << getOpenMPClauseName(PredeterminedCKind
);
9279 if (DVar
.RefExpr
== nullptr)
9280 DVar
.CKind
= PredeterminedCKind
;
9281 reportOriginalDsa(*this, DSAStack
, D
, DVar
,
9282 /*IsLoopIterVar=*/true);
9283 } else if (LoopDeclRefExpr
) {
9284 // Make the loop iteration variable private (for worksharing
9285 // constructs), linear (for simd directives with the only one
9286 // associated loop) or lastprivate (for simd directives with several
9287 // collapsed or ordered loops).
9288 if (DVar
.CKind
== OMPC_unknown
)
9289 DSAStack
->addDSA(D
, LoopDeclRefExpr
, PredeterminedCKind
,
9294 DSAStack
->setAssociatedLoops(AssociatedLoops
- 1);
9299 // Utility for openmp doacross clause kind
9300 class OMPDoacrossKind
{
9302 bool isSource(const OMPDoacrossClause
*C
) {
9303 return C
->getDependenceType() == OMPC_DOACROSS_source
||
9304 C
->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration
;
9306 bool isSink(const OMPDoacrossClause
*C
) {
9307 return C
->getDependenceType() == OMPC_DOACROSS_sink
;
9309 bool isSinkIter(const OMPDoacrossClause
*C
) {
9310 return C
->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration
;
9314 /// Called on a for stmt to check and extract its iteration space
9315 /// for further processing (such as collapsing).
9316 static bool checkOpenMPIterationSpace(
9317 OpenMPDirectiveKind DKind
, Stmt
*S
, Sema
&SemaRef
, DSAStackTy
&DSA
,
9318 unsigned CurrentNestedLoopCount
, unsigned NestedLoopCount
,
9319 unsigned TotalNestedLoopCount
, Expr
*CollapseLoopCountExpr
,
9320 Expr
*OrderedLoopCountExpr
,
9321 Sema::VarsWithInheritedDSAType
&VarsWithImplicitDSA
,
9322 llvm::MutableArrayRef
<LoopIterationSpace
> ResultIterSpaces
,
9323 llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
) {
9324 bool SupportsNonRectangular
= !isOpenMPLoopTransformationDirective(DKind
);
9325 // OpenMP [2.9.1, Canonical Loop Form]
9326 // for (init-expr; test-expr; incr-expr) structured-block
9327 // for (range-decl: range-expr) structured-block
9328 if (auto *CanonLoop
= dyn_cast_or_null
<OMPCanonicalLoop
>(S
))
9329 S
= CanonLoop
->getLoopStmt();
9330 auto *For
= dyn_cast_or_null
<ForStmt
>(S
);
9331 auto *CXXFor
= dyn_cast_or_null
<CXXForRangeStmt
>(S
);
9332 // Ranged for is supported only in OpenMP 5.0.
9333 if (!For
&& (SemaRef
.LangOpts
.OpenMP
<= 45 || !CXXFor
)) {
9334 OpenMPDirectiveKind DK
= (SemaRef
.getLangOpts().OpenMP
< 50 ||
9335 DSA
.getMappedDirective() == OMPD_unknown
)
9337 : DSA
.getMappedDirective();
9338 SemaRef
.Diag(S
->getBeginLoc(), diag::err_omp_not_for
)
9339 << (CollapseLoopCountExpr
!= nullptr || OrderedLoopCountExpr
!= nullptr)
9340 << getOpenMPDirectiveName(DK
) << TotalNestedLoopCount
9341 << (CurrentNestedLoopCount
> 0) << CurrentNestedLoopCount
;
9342 if (TotalNestedLoopCount
> 1) {
9343 if (CollapseLoopCountExpr
&& OrderedLoopCountExpr
)
9344 SemaRef
.Diag(DSA
.getConstructLoc(),
9345 diag::note_omp_collapse_ordered_expr
)
9346 << 2 << CollapseLoopCountExpr
->getSourceRange()
9347 << OrderedLoopCountExpr
->getSourceRange();
9348 else if (CollapseLoopCountExpr
)
9349 SemaRef
.Diag(CollapseLoopCountExpr
->getExprLoc(),
9350 diag::note_omp_collapse_ordered_expr
)
9351 << 0 << CollapseLoopCountExpr
->getSourceRange();
9353 SemaRef
.Diag(OrderedLoopCountExpr
->getExprLoc(),
9354 diag::note_omp_collapse_ordered_expr
)
9355 << 1 << OrderedLoopCountExpr
->getSourceRange();
9359 assert(((For
&& For
->getBody()) || (CXXFor
&& CXXFor
->getBody())) &&
9361 // Postpone analysis in dependent contexts for ranged for loops.
9362 if (CXXFor
&& SemaRef
.CurContext
->isDependentContext())
9365 OpenMPIterationSpaceChecker
ISC(SemaRef
, SupportsNonRectangular
, DSA
,
9366 For
? For
->getForLoc() : CXXFor
->getForLoc());
9369 Stmt
*Init
= For
? For
->getInit() : CXXFor
->getBeginStmt();
9370 if (ISC
.checkAndSetInit(Init
))
9373 bool HasErrors
= false;
9375 // Check loop variable's type.
9376 if (ValueDecl
*LCDecl
= ISC
.getLoopDecl()) {
9377 // OpenMP [2.6, Canonical Loop Form]
9378 // Var is one of the following:
9379 // A variable of signed or unsigned integer type.
9380 // For C++, a variable of a random access iterator type.
9381 // For C, a variable of a pointer type.
9382 QualType VarType
= LCDecl
->getType().getNonReferenceType();
9383 if (!VarType
->isDependentType() && !VarType
->isIntegerType() &&
9384 !VarType
->isPointerType() &&
9385 !(SemaRef
.getLangOpts().CPlusPlus
&& VarType
->isOverloadableType())) {
9386 SemaRef
.Diag(Init
->getBeginLoc(), diag::err_omp_loop_variable_type
)
9387 << SemaRef
.getLangOpts().CPlusPlus
;
9391 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9393 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9394 // parallel for construct is (are) private.
9395 // The loop iteration variable in the associated for-loop of a simd
9396 // construct with just one associated for-loop is linear with a
9397 // constant-linear-step that is the increment of the associated for-loop.
9398 // Exclude loop var from the list of variables with implicitly defined data
9399 // sharing attributes.
9400 VarsWithImplicitDSA
.erase(LCDecl
);
9402 assert(isOpenMPLoopDirective(DKind
) && "DSA for non-loop vars");
9405 HasErrors
|= ISC
.checkAndSetCond(For
? For
->getCond() : CXXFor
->getCond());
9408 HasErrors
|= ISC
.checkAndSetInc(For
? For
->getInc() : CXXFor
->getInc());
9411 if (ISC
.dependent() || SemaRef
.CurContext
->isDependentContext() || HasErrors
)
9414 // Build the loop's iteration space representation.
9415 ResultIterSpaces
[CurrentNestedLoopCount
].PreCond
= ISC
.buildPreCond(
9416 DSA
.getCurScope(), For
? For
->getCond() : CXXFor
->getCond(), Captures
);
9417 ResultIterSpaces
[CurrentNestedLoopCount
].NumIterations
=
9418 ISC
.buildNumIterations(DSA
.getCurScope(), ResultIterSpaces
,
9419 (isOpenMPWorksharingDirective(DKind
) ||
9420 isOpenMPGenericLoopDirective(DKind
) ||
9421 isOpenMPTaskLoopDirective(DKind
) ||
9422 isOpenMPDistributeDirective(DKind
) ||
9423 isOpenMPLoopTransformationDirective(DKind
)),
9425 ResultIterSpaces
[CurrentNestedLoopCount
].CounterVar
=
9426 ISC
.buildCounterVar(Captures
, DSA
);
9427 ResultIterSpaces
[CurrentNestedLoopCount
].PrivateCounterVar
=
9428 ISC
.buildPrivateCounterVar();
9429 ResultIterSpaces
[CurrentNestedLoopCount
].CounterInit
= ISC
.buildCounterInit();
9430 ResultIterSpaces
[CurrentNestedLoopCount
].CounterStep
= ISC
.buildCounterStep();
9431 ResultIterSpaces
[CurrentNestedLoopCount
].InitSrcRange
= ISC
.getInitSrcRange();
9432 ResultIterSpaces
[CurrentNestedLoopCount
].CondSrcRange
=
9433 ISC
.getConditionSrcRange();
9434 ResultIterSpaces
[CurrentNestedLoopCount
].IncSrcRange
=
9435 ISC
.getIncrementSrcRange();
9436 ResultIterSpaces
[CurrentNestedLoopCount
].Subtract
= ISC
.shouldSubtractStep();
9437 ResultIterSpaces
[CurrentNestedLoopCount
].IsStrictCompare
=
9438 ISC
.isStrictTestOp();
9439 std::tie(ResultIterSpaces
[CurrentNestedLoopCount
].MinValue
,
9440 ResultIterSpaces
[CurrentNestedLoopCount
].MaxValue
) =
9441 ISC
.buildMinMaxValues(DSA
.getCurScope(), Captures
);
9442 ResultIterSpaces
[CurrentNestedLoopCount
].FinalCondition
=
9443 ISC
.buildFinalCondition(DSA
.getCurScope());
9444 ResultIterSpaces
[CurrentNestedLoopCount
].IsNonRectangularLB
=
9445 ISC
.doesInitDependOnLC();
9446 ResultIterSpaces
[CurrentNestedLoopCount
].IsNonRectangularUB
=
9447 ISC
.doesCondDependOnLC();
9448 ResultIterSpaces
[CurrentNestedLoopCount
].LoopDependentIdx
=
9449 ISC
.getLoopDependentIdx();
9452 (ResultIterSpaces
[CurrentNestedLoopCount
].PreCond
== nullptr ||
9453 ResultIterSpaces
[CurrentNestedLoopCount
].NumIterations
== nullptr ||
9454 ResultIterSpaces
[CurrentNestedLoopCount
].CounterVar
== nullptr ||
9455 ResultIterSpaces
[CurrentNestedLoopCount
].PrivateCounterVar
== nullptr ||
9456 ResultIterSpaces
[CurrentNestedLoopCount
].CounterInit
== nullptr ||
9457 ResultIterSpaces
[CurrentNestedLoopCount
].CounterStep
== nullptr);
9458 if (!HasErrors
&& DSA
.isOrderedRegion()) {
9459 if (DSA
.getOrderedRegionParam().second
->getNumForLoops()) {
9460 if (CurrentNestedLoopCount
<
9461 DSA
.getOrderedRegionParam().second
->getLoopNumIterations().size()) {
9462 DSA
.getOrderedRegionParam().second
->setLoopNumIterations(
9463 CurrentNestedLoopCount
,
9464 ResultIterSpaces
[CurrentNestedLoopCount
].NumIterations
);
9465 DSA
.getOrderedRegionParam().second
->setLoopCounter(
9466 CurrentNestedLoopCount
,
9467 ResultIterSpaces
[CurrentNestedLoopCount
].CounterVar
);
9470 for (auto &Pair
: DSA
.getDoacrossDependClauses()) {
9471 auto *DependC
= dyn_cast
<OMPDependClause
>(Pair
.first
);
9472 auto *DoacrossC
= dyn_cast
<OMPDoacrossClause
>(Pair
.first
);
9474 DependC
? DependC
->getNumLoops() : DoacrossC
->getNumLoops();
9475 if (CurrentNestedLoopCount
>= NumLoops
) {
9476 // Erroneous case - clause has some problems.
9479 if (DependC
&& DependC
->getDependencyKind() == OMPC_DEPEND_sink
&&
9480 Pair
.second
.size() <= CurrentNestedLoopCount
) {
9481 // Erroneous case - clause has some problems.
9482 DependC
->setLoopData(CurrentNestedLoopCount
, nullptr);
9485 OMPDoacrossKind ODK
;
9486 if (DoacrossC
&& ODK
.isSink(DoacrossC
) &&
9487 Pair
.second
.size() <= CurrentNestedLoopCount
) {
9488 // Erroneous case - clause has some problems.
9489 DoacrossC
->setLoopData(CurrentNestedLoopCount
, nullptr);
9493 SourceLocation DepLoc
=
9494 DependC
? DependC
->getDependencyLoc() : DoacrossC
->getDependenceLoc();
9495 if ((DependC
&& DependC
->getDependencyKind() == OMPC_DEPEND_source
) ||
9496 (DoacrossC
&& ODK
.isSource(DoacrossC
)))
9497 CntValue
= ISC
.buildOrderedLoopData(
9499 ResultIterSpaces
[CurrentNestedLoopCount
].CounterVar
, Captures
,
9501 else if (DoacrossC
&& ODK
.isSinkIter(DoacrossC
)) {
9503 .DefaultLvalueConversion(
9504 ResultIterSpaces
[CurrentNestedLoopCount
].CounterVar
)
9508 // build CounterVar - 1
9510 SemaRef
.ActOnIntegerConstant(DoacrossC
->getColonLoc(), /*Val=*/1)
9512 CntValue
= ISC
.buildOrderedLoopData(
9514 ResultIterSpaces
[CurrentNestedLoopCount
].CounterVar
, Captures
,
9515 DepLoc
, Inc
, clang::OO_Minus
);
9517 CntValue
= ISC
.buildOrderedLoopData(
9519 ResultIterSpaces
[CurrentNestedLoopCount
].CounterVar
, Captures
,
9520 DepLoc
, Pair
.second
[CurrentNestedLoopCount
].first
,
9521 Pair
.second
[CurrentNestedLoopCount
].second
);
9523 DependC
->setLoopData(CurrentNestedLoopCount
, CntValue
);
9525 DoacrossC
->setLoopData(CurrentNestedLoopCount
, CntValue
);
9532 /// Build 'VarRef = Start.
9534 buildCounterInit(Sema
&SemaRef
, Scope
*S
, SourceLocation Loc
, ExprResult VarRef
,
9535 ExprResult Start
, bool IsNonRectangularLB
,
9536 llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
) {
9537 // Build 'VarRef = Start.
9538 ExprResult NewStart
= IsNonRectangularLB
9540 : tryBuildCapture(SemaRef
, Start
.get(), Captures
);
9541 if (!NewStart
.isUsable())
9543 if (!SemaRef
.Context
.hasSameType(NewStart
.get()->getType(),
9544 VarRef
.get()->getType())) {
9545 NewStart
= SemaRef
.PerformImplicitConversion(
9546 NewStart
.get(), VarRef
.get()->getType(), Sema::AA_Converting
,
9547 /*AllowExplicit=*/true);
9548 if (!NewStart
.isUsable())
9553 SemaRef
.BuildBinOp(S
, Loc
, BO_Assign
, VarRef
.get(), NewStart
.get());
9557 /// Build 'VarRef = Start + Iter * Step'.
9558 static ExprResult
buildCounterUpdate(
9559 Sema
&SemaRef
, Scope
*S
, SourceLocation Loc
, ExprResult VarRef
,
9560 ExprResult Start
, ExprResult Iter
, ExprResult Step
, bool Subtract
,
9561 bool IsNonRectangularLB
,
9562 llvm::MapVector
<const Expr
*, DeclRefExpr
*> *Captures
= nullptr) {
9563 // Add parentheses (for debugging purposes only).
9564 Iter
= SemaRef
.ActOnParenExpr(Loc
, Loc
, Iter
.get());
9565 if (!VarRef
.isUsable() || !Start
.isUsable() || !Iter
.isUsable() ||
9569 ExprResult NewStep
= Step
;
9571 NewStep
= tryBuildCapture(SemaRef
, Step
.get(), *Captures
);
9572 if (NewStep
.isInvalid())
9575 SemaRef
.BuildBinOp(S
, Loc
, BO_Mul
, Iter
.get(), NewStep
.get());
9576 if (!Update
.isUsable())
9579 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9580 // 'VarRef = Start (+|-) Iter * Step'.
9581 if (!Start
.isUsable())
9583 ExprResult NewStart
= SemaRef
.ActOnParenExpr(Loc
, Loc
, Start
.get());
9584 if (!NewStart
.isUsable())
9586 if (Captures
&& !IsNonRectangularLB
)
9587 NewStart
= tryBuildCapture(SemaRef
, Start
.get(), *Captures
);
9588 if (NewStart
.isInvalid())
9591 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9592 ExprResult SavedUpdate
= Update
;
9593 ExprResult UpdateVal
;
9594 if (VarRef
.get()->getType()->isOverloadableType() ||
9595 NewStart
.get()->getType()->isOverloadableType() ||
9596 Update
.get()->getType()->isOverloadableType()) {
9597 Sema::TentativeAnalysisScope
Trap(SemaRef
);
9600 SemaRef
.BuildBinOp(S
, Loc
, BO_Assign
, VarRef
.get(), NewStart
.get());
9601 if (Update
.isUsable()) {
9603 SemaRef
.BuildBinOp(S
, Loc
, Subtract
? BO_SubAssign
: BO_AddAssign
,
9604 VarRef
.get(), SavedUpdate
.get());
9605 if (UpdateVal
.isUsable()) {
9606 Update
= SemaRef
.CreateBuiltinBinOp(Loc
, BO_Comma
, Update
.get(),
9612 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9613 if (!Update
.isUsable() || !UpdateVal
.isUsable()) {
9614 Update
= SemaRef
.BuildBinOp(S
, Loc
, Subtract
? BO_Sub
: BO_Add
,
9615 NewStart
.get(), SavedUpdate
.get());
9616 if (!Update
.isUsable())
9619 if (!SemaRef
.Context
.hasSameType(Update
.get()->getType(),
9620 VarRef
.get()->getType())) {
9621 Update
= SemaRef
.PerformImplicitConversion(
9622 Update
.get(), VarRef
.get()->getType(), Sema::AA_Converting
, true);
9623 if (!Update
.isUsable())
9627 Update
= SemaRef
.BuildBinOp(S
, Loc
, BO_Assign
, VarRef
.get(), Update
.get());
9632 /// Convert integer expression \a E to make it have at least \a Bits
9634 static ExprResult
widenIterationCount(unsigned Bits
, Expr
*E
, Sema
&SemaRef
) {
9637 ASTContext
&C
= SemaRef
.Context
;
9638 QualType OldType
= E
->getType();
9639 unsigned HasBits
= C
.getTypeSize(OldType
);
9640 if (HasBits
>= Bits
)
9641 return ExprResult(E
);
9642 // OK to convert to signed, because new type has more bits than old.
9643 QualType NewType
= C
.getIntTypeForBitwidth(Bits
, /* Signed */ true);
9644 return SemaRef
.PerformImplicitConversion(E
, NewType
, Sema::AA_Converting
,
9648 /// Check if the given expression \a E is a constant integer that fits
9649 /// into \a Bits bits.
9650 static bool fitsInto(unsigned Bits
, bool Signed
, const Expr
*E
, Sema
&SemaRef
) {
9653 if (std::optional
<llvm::APSInt
> Result
=
9654 E
->getIntegerConstantExpr(SemaRef
.Context
))
9655 return Signed
? Result
->isSignedIntN(Bits
) : Result
->isIntN(Bits
);
9659 /// Build preinits statement for the given declarations.
9660 static Stmt
*buildPreInits(ASTContext
&Context
,
9661 MutableArrayRef
<Decl
*> PreInits
) {
9662 if (!PreInits
.empty()) {
9663 return new (Context
) DeclStmt(
9664 DeclGroupRef::Create(Context
, PreInits
.begin(), PreInits
.size()),
9665 SourceLocation(), SourceLocation());
9670 /// Build preinits statement for the given declarations.
9672 buildPreInits(ASTContext
&Context
,
9673 const llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
) {
9674 if (!Captures
.empty()) {
9675 SmallVector
<Decl
*, 16> PreInits
;
9676 for (const auto &Pair
: Captures
)
9677 PreInits
.push_back(Pair
.second
->getDecl());
9678 return buildPreInits(Context
, PreInits
);
9683 /// Build postupdate expression for the given list of postupdates expressions.
9684 static Expr
*buildPostUpdate(Sema
&S
, ArrayRef
<Expr
*> PostUpdates
) {
9685 Expr
*PostUpdate
= nullptr;
9686 if (!PostUpdates
.empty()) {
9687 for (Expr
*E
: PostUpdates
) {
9688 Expr
*ConvE
= S
.BuildCStyleCastExpr(
9690 S
.Context
.getTrivialTypeSourceInfo(S
.Context
.VoidTy
),
9693 PostUpdate
= PostUpdate
9694 ? S
.CreateBuiltinBinOp(ConvE
->getExprLoc(), BO_Comma
,
9703 /// Called on a for stmt to check itself and nested loops (if any).
9704 /// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9705 /// number of collapsed loops otherwise.
9707 checkOpenMPLoop(OpenMPDirectiveKind DKind
, Expr
*CollapseLoopCountExpr
,
9708 Expr
*OrderedLoopCountExpr
, Stmt
*AStmt
, Sema
&SemaRef
,
9710 Sema::VarsWithInheritedDSAType
&VarsWithImplicitDSA
,
9711 OMPLoopBasedDirective::HelperExprs
&Built
) {
9712 unsigned NestedLoopCount
= 1;
9713 bool SupportsNonPerfectlyNested
= (SemaRef
.LangOpts
.OpenMP
>= 50) &&
9714 !isOpenMPLoopTransformationDirective(DKind
);
9716 if (CollapseLoopCountExpr
) {
9717 // Found 'collapse' clause - calculate collapse number.
9718 Expr::EvalResult Result
;
9719 if (!CollapseLoopCountExpr
->isValueDependent() &&
9720 CollapseLoopCountExpr
->EvaluateAsInt(Result
, SemaRef
.getASTContext())) {
9721 NestedLoopCount
= Result
.Val
.getInt().getLimitedValue();
9723 Built
.clear(/*Size=*/1);
9727 unsigned OrderedLoopCount
= 1;
9728 if (OrderedLoopCountExpr
) {
9729 // Found 'ordered' clause - calculate collapse number.
9730 Expr::EvalResult EVResult
;
9731 if (!OrderedLoopCountExpr
->isValueDependent() &&
9732 OrderedLoopCountExpr
->EvaluateAsInt(EVResult
,
9733 SemaRef
.getASTContext())) {
9734 llvm::APSInt Result
= EVResult
.Val
.getInt();
9735 if (Result
.getLimitedValue() < NestedLoopCount
) {
9736 SemaRef
.Diag(OrderedLoopCountExpr
->getExprLoc(),
9737 diag::err_omp_wrong_ordered_loop_count
)
9738 << OrderedLoopCountExpr
->getSourceRange();
9739 SemaRef
.Diag(CollapseLoopCountExpr
->getExprLoc(),
9740 diag::note_collapse_loop_count
)
9741 << CollapseLoopCountExpr
->getSourceRange();
9743 OrderedLoopCount
= Result
.getLimitedValue();
9745 Built
.clear(/*Size=*/1);
9749 // This is helper routine for loop directives (e.g., 'for', 'simd',
9750 // 'for simd', etc.).
9751 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
9752 unsigned NumLoops
= std::max(OrderedLoopCount
, NestedLoopCount
);
9753 SmallVector
<LoopIterationSpace
, 4> IterSpaces(NumLoops
);
9754 if (!OMPLoopBasedDirective::doForAllLoops(
9755 AStmt
->IgnoreContainers(!isOpenMPLoopTransformationDirective(DKind
)),
9756 SupportsNonPerfectlyNested
, NumLoops
,
9757 [DKind
, &SemaRef
, &DSA
, NumLoops
, NestedLoopCount
,
9758 CollapseLoopCountExpr
, OrderedLoopCountExpr
, &VarsWithImplicitDSA
,
9759 &IterSpaces
, &Captures
](unsigned Cnt
, Stmt
*CurStmt
) {
9760 if (checkOpenMPIterationSpace(
9761 DKind
, CurStmt
, SemaRef
, DSA
, Cnt
, NestedLoopCount
,
9762 NumLoops
, CollapseLoopCountExpr
, OrderedLoopCountExpr
,
9763 VarsWithImplicitDSA
, IterSpaces
, Captures
))
9765 if (Cnt
> 0 && Cnt
>= NestedLoopCount
&&
9766 IterSpaces
[Cnt
].CounterVar
) {
9767 // Handle initialization of captured loop iterator variables.
9768 auto *DRE
= cast
<DeclRefExpr
>(IterSpaces
[Cnt
].CounterVar
);
9769 if (isa
<OMPCapturedExprDecl
>(DRE
->getDecl())) {
9770 Captures
[DRE
] = DRE
;
9775 [&SemaRef
, &Captures
](OMPLoopTransformationDirective
*Transform
) {
9776 Stmt
*DependentPreInits
= Transform
->getPreInits();
9777 if (!DependentPreInits
)
9779 for (Decl
*C
: cast
<DeclStmt
>(DependentPreInits
)->getDeclGroup()) {
9780 auto *D
= cast
<VarDecl
>(C
);
9781 DeclRefExpr
*Ref
= buildDeclRefExpr(SemaRef
, D
, D
->getType(),
9782 Transform
->getBeginLoc());
9783 Captures
[Ref
] = Ref
;
9788 Built
.clear(/* size */ NestedLoopCount
);
9790 if (SemaRef
.CurContext
->isDependentContext())
9791 return NestedLoopCount
;
9793 // An example of what is generated for the following code:
9795 // #pragma omp simd collapse(2) ordered(2)
9796 // for (i = 0; i < NI; ++i)
9797 // for (k = 0; k < NK; ++k)
9798 // for (j = J0; j < NJ; j+=2) {
9802 // We generate the code below.
9803 // Note: the loop body may be outlined in CodeGen.
9804 // Note: some counters may be C++ classes, operator- is used to find number of
9805 // iterations and operator+= to calculate counter value.
9806 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
9807 // or i64 is currently supported).
9809 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
9810 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
9811 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
9812 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
9813 // // similar updates for vars in clauses (e.g. 'linear')
9814 // <loop body (using local i and j)>
9816 // i = NI; // assign final values of counters
9820 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
9821 // the iteration counts of the collapsed for loops.
9822 // Precondition tests if there is at least one iteration (all conditions are
9824 auto PreCond
= ExprResult(IterSpaces
[0].PreCond
);
9825 Expr
*N0
= IterSpaces
[0].NumIterations
;
9826 ExprResult LastIteration32
=
9827 widenIterationCount(/*Bits=*/32,
9829 .PerformImplicitConversion(
9830 N0
->IgnoreImpCasts(), N0
->getType(),
9831 Sema::AA_Converting
, /*AllowExplicit=*/true)
9834 ExprResult LastIteration64
= widenIterationCount(
9837 .PerformImplicitConversion(N0
->IgnoreImpCasts(), N0
->getType(),
9838 Sema::AA_Converting
,
9839 /*AllowExplicit=*/true)
9843 if (!LastIteration32
.isUsable() || !LastIteration64
.isUsable())
9844 return NestedLoopCount
;
9846 ASTContext
&C
= SemaRef
.Context
;
9847 bool AllCountsNeedLessThan32Bits
= C
.getTypeSize(N0
->getType()) < 32;
9849 Scope
*CurScope
= DSA
.getCurScope();
9850 for (unsigned Cnt
= 1; Cnt
< NestedLoopCount
; ++Cnt
) {
9851 if (PreCond
.isUsable()) {
9853 SemaRef
.BuildBinOp(CurScope
, PreCond
.get()->getExprLoc(), BO_LAnd
,
9854 PreCond
.get(), IterSpaces
[Cnt
].PreCond
);
9856 Expr
*N
= IterSpaces
[Cnt
].NumIterations
;
9857 SourceLocation Loc
= N
->getExprLoc();
9858 AllCountsNeedLessThan32Bits
&= C
.getTypeSize(N
->getType()) < 32;
9859 if (LastIteration32
.isUsable())
9860 LastIteration32
= SemaRef
.BuildBinOp(
9861 CurScope
, Loc
, BO_Mul
, LastIteration32
.get(),
9863 .PerformImplicitConversion(N
->IgnoreImpCasts(), N
->getType(),
9864 Sema::AA_Converting
,
9865 /*AllowExplicit=*/true)
9867 if (LastIteration64
.isUsable())
9868 LastIteration64
= SemaRef
.BuildBinOp(
9869 CurScope
, Loc
, BO_Mul
, LastIteration64
.get(),
9871 .PerformImplicitConversion(N
->IgnoreImpCasts(), N
->getType(),
9872 Sema::AA_Converting
,
9873 /*AllowExplicit=*/true)
9877 // Choose either the 32-bit or 64-bit version.
9878 ExprResult LastIteration
= LastIteration64
;
9879 if (SemaRef
.getLangOpts().OpenMPOptimisticCollapse
||
9880 (LastIteration32
.isUsable() &&
9881 C
.getTypeSize(LastIteration32
.get()->getType()) == 32 &&
9882 (AllCountsNeedLessThan32Bits
|| NestedLoopCount
== 1 ||
9885 LastIteration32
.get()->getType()->hasSignedIntegerRepresentation(),
9886 LastIteration64
.get(), SemaRef
))))
9887 LastIteration
= LastIteration32
;
9888 QualType VType
= LastIteration
.get()->getType();
9889 QualType RealVType
= VType
;
9890 QualType StrideVType
= VType
;
9891 if (isOpenMPTaskLoopDirective(DKind
)) {
9893 SemaRef
.Context
.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
9895 SemaRef
.Context
.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
9898 if (!LastIteration
.isUsable())
9901 // Save the number of iterations.
9902 ExprResult NumIterations
= LastIteration
;
9904 LastIteration
= SemaRef
.BuildBinOp(
9905 CurScope
, LastIteration
.get()->getExprLoc(), BO_Sub
,
9906 LastIteration
.get(),
9907 SemaRef
.ActOnIntegerConstant(SourceLocation(), 1).get());
9908 if (!LastIteration
.isUsable())
9912 // Calculate the last iteration number beforehand instead of doing this on
9913 // each iteration. Do not do this if the number of iterations may be kfold-ed.
9914 bool IsConstant
= LastIteration
.get()->isIntegerConstantExpr(SemaRef
.Context
);
9915 ExprResult CalcLastIteration
;
9917 ExprResult SaveRef
=
9918 tryBuildCapture(SemaRef
, LastIteration
.get(), Captures
);
9919 LastIteration
= SaveRef
;
9921 // Prepare SaveRef + 1.
9922 NumIterations
= SemaRef
.BuildBinOp(
9923 CurScope
, SaveRef
.get()->getExprLoc(), BO_Add
, SaveRef
.get(),
9924 SemaRef
.ActOnIntegerConstant(SourceLocation(), 1).get());
9925 if (!NumIterations
.isUsable())
9929 SourceLocation InitLoc
= IterSpaces
[0].InitSrcRange
.getBegin();
9931 // Build variables passed into runtime, necessary for worksharing directives.
9932 ExprResult LB
, UB
, IL
, ST
, EUB
, CombLB
, CombUB
, PrevLB
, PrevUB
, CombEUB
;
9933 if (isOpenMPWorksharingDirective(DKind
) || isOpenMPTaskLoopDirective(DKind
) ||
9934 isOpenMPDistributeDirective(DKind
) ||
9935 isOpenMPGenericLoopDirective(DKind
) ||
9936 isOpenMPLoopTransformationDirective(DKind
)) {
9937 // Lower bound variable, initialized with zero.
9938 VarDecl
*LBDecl
= buildVarDecl(SemaRef
, InitLoc
, VType
, ".omp.lb");
9939 LB
= buildDeclRefExpr(SemaRef
, LBDecl
, VType
, InitLoc
);
9940 SemaRef
.AddInitializerToDecl(LBDecl
,
9941 SemaRef
.ActOnIntegerConstant(InitLoc
, 0).get(),
9942 /*DirectInit*/ false);
9944 // Upper bound variable, initialized with last iteration number.
9945 VarDecl
*UBDecl
= buildVarDecl(SemaRef
, InitLoc
, VType
, ".omp.ub");
9946 UB
= buildDeclRefExpr(SemaRef
, UBDecl
, VType
, InitLoc
);
9947 SemaRef
.AddInitializerToDecl(UBDecl
, LastIteration
.get(),
9948 /*DirectInit*/ false);
9950 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
9951 // This will be used to implement clause 'lastprivate'.
9952 QualType Int32Ty
= SemaRef
.Context
.getIntTypeForBitwidth(32, true);
9953 VarDecl
*ILDecl
= buildVarDecl(SemaRef
, InitLoc
, Int32Ty
, ".omp.is_last");
9954 IL
= buildDeclRefExpr(SemaRef
, ILDecl
, Int32Ty
, InitLoc
);
9955 SemaRef
.AddInitializerToDecl(ILDecl
,
9956 SemaRef
.ActOnIntegerConstant(InitLoc
, 0).get(),
9957 /*DirectInit*/ false);
9959 // Stride variable returned by runtime (we initialize it to 1 by default).
9961 buildVarDecl(SemaRef
, InitLoc
, StrideVType
, ".omp.stride");
9962 ST
= buildDeclRefExpr(SemaRef
, STDecl
, StrideVType
, InitLoc
);
9963 SemaRef
.AddInitializerToDecl(STDecl
,
9964 SemaRef
.ActOnIntegerConstant(InitLoc
, 1).get(),
9965 /*DirectInit*/ false);
9967 // Build expression: UB = min(UB, LastIteration)
9968 // It is necessary for CodeGen of directives with static scheduling.
9969 ExprResult IsUBGreater
= SemaRef
.BuildBinOp(CurScope
, InitLoc
, BO_GT
,
9970 UB
.get(), LastIteration
.get());
9971 ExprResult CondOp
= SemaRef
.ActOnConditionalOp(
9972 LastIteration
.get()->getExprLoc(), InitLoc
, IsUBGreater
.get(),
9973 LastIteration
.get(), UB
.get());
9974 EUB
= SemaRef
.BuildBinOp(CurScope
, InitLoc
, BO_Assign
, UB
.get(),
9976 EUB
= SemaRef
.ActOnFinishFullExpr(EUB
.get(), /*DiscardedValue*/ false);
9978 // If we have a combined directive that combines 'distribute', 'for' or
9979 // 'simd' we need to be able to access the bounds of the schedule of the
9980 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
9981 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
9982 if (isOpenMPLoopBoundSharingDirective(DKind
)) {
9983 // Lower bound variable, initialized with zero.
9984 VarDecl
*CombLBDecl
=
9985 buildVarDecl(SemaRef
, InitLoc
, VType
, ".omp.comb.lb");
9986 CombLB
= buildDeclRefExpr(SemaRef
, CombLBDecl
, VType
, InitLoc
);
9987 SemaRef
.AddInitializerToDecl(
9988 CombLBDecl
, SemaRef
.ActOnIntegerConstant(InitLoc
, 0).get(),
9989 /*DirectInit*/ false);
9991 // Upper bound variable, initialized with last iteration number.
9992 VarDecl
*CombUBDecl
=
9993 buildVarDecl(SemaRef
, InitLoc
, VType
, ".omp.comb.ub");
9994 CombUB
= buildDeclRefExpr(SemaRef
, CombUBDecl
, VType
, InitLoc
);
9995 SemaRef
.AddInitializerToDecl(CombUBDecl
, LastIteration
.get(),
9996 /*DirectInit*/ false);
9998 ExprResult CombIsUBGreater
= SemaRef
.BuildBinOp(
9999 CurScope
, InitLoc
, BO_GT
, CombUB
.get(), LastIteration
.get());
10000 ExprResult CombCondOp
=
10001 SemaRef
.ActOnConditionalOp(InitLoc
, InitLoc
, CombIsUBGreater
.get(),
10002 LastIteration
.get(), CombUB
.get());
10003 CombEUB
= SemaRef
.BuildBinOp(CurScope
, InitLoc
, BO_Assign
, CombUB
.get(),
10006 SemaRef
.ActOnFinishFullExpr(CombEUB
.get(), /*DiscardedValue*/ false);
10008 const CapturedDecl
*CD
= cast
<CapturedStmt
>(AStmt
)->getCapturedDecl();
10009 // We expect to have at least 2 more parameters than the 'parallel'
10010 // directive does - the lower and upper bounds of the previous schedule.
10011 assert(CD
->getNumParams() >= 4 &&
10012 "Unexpected number of parameters in loop combined directive");
10014 // Set the proper type for the bounds given what we learned from the
10016 ImplicitParamDecl
*PrevLBDecl
= CD
->getParam(/*PrevLB=*/2);
10017 ImplicitParamDecl
*PrevUBDecl
= CD
->getParam(/*PrevUB=*/3);
10019 // Previous lower and upper bounds are obtained from the region
10022 buildDeclRefExpr(SemaRef
, PrevLBDecl
, PrevLBDecl
->getType(), InitLoc
);
10024 buildDeclRefExpr(SemaRef
, PrevUBDecl
, PrevUBDecl
->getType(), InitLoc
);
10028 // Build the iteration variable and its initialization before loop.
10030 ExprResult Init
, CombInit
;
10032 VarDecl
*IVDecl
= buildVarDecl(SemaRef
, InitLoc
, RealVType
, ".omp.iv");
10033 IV
= buildDeclRefExpr(SemaRef
, IVDecl
, RealVType
, InitLoc
);
10034 Expr
*RHS
= (isOpenMPWorksharingDirective(DKind
) ||
10035 isOpenMPGenericLoopDirective(DKind
) ||
10036 isOpenMPTaskLoopDirective(DKind
) ||
10037 isOpenMPDistributeDirective(DKind
) ||
10038 isOpenMPLoopTransformationDirective(DKind
))
10040 : SemaRef
.ActOnIntegerConstant(SourceLocation(), 0).get();
10041 Init
= SemaRef
.BuildBinOp(CurScope
, InitLoc
, BO_Assign
, IV
.get(), RHS
);
10042 Init
= SemaRef
.ActOnFinishFullExpr(Init
.get(), /*DiscardedValue*/ false);
10044 if (isOpenMPLoopBoundSharingDirective(DKind
)) {
10046 (isOpenMPWorksharingDirective(DKind
) ||
10047 isOpenMPGenericLoopDirective(DKind
) ||
10048 isOpenMPTaskLoopDirective(DKind
) ||
10049 isOpenMPDistributeDirective(DKind
))
10051 : SemaRef
.ActOnIntegerConstant(SourceLocation(), 0).get();
10053 SemaRef
.BuildBinOp(CurScope
, InitLoc
, BO_Assign
, IV
.get(), CombRHS
);
10055 SemaRef
.ActOnFinishFullExpr(CombInit
.get(), /*DiscardedValue*/ false);
10059 bool UseStrictCompare
=
10060 RealVType
->hasUnsignedIntegerRepresentation() &&
10061 llvm::all_of(IterSpaces
, [](const LoopIterationSpace
&LIS
) {
10062 return LIS
.IsStrictCompare
;
10064 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
10065 // unsigned IV)) for worksharing loops.
10066 SourceLocation CondLoc
= AStmt
->getBeginLoc();
10067 Expr
*BoundUB
= UB
.get();
10068 if (UseStrictCompare
) {
10071 .BuildBinOp(CurScope
, CondLoc
, BO_Add
, BoundUB
,
10072 SemaRef
.ActOnIntegerConstant(SourceLocation(), 1).get())
10075 SemaRef
.ActOnFinishFullExpr(BoundUB
, /*DiscardedValue*/ false).get();
10078 (isOpenMPWorksharingDirective(DKind
) ||
10079 isOpenMPGenericLoopDirective(DKind
) ||
10080 isOpenMPTaskLoopDirective(DKind
) || isOpenMPDistributeDirective(DKind
) ||
10081 isOpenMPLoopTransformationDirective(DKind
))
10082 ? SemaRef
.BuildBinOp(CurScope
, CondLoc
,
10083 UseStrictCompare
? BO_LT
: BO_LE
, IV
.get(),
10085 : SemaRef
.BuildBinOp(CurScope
, CondLoc
, BO_LT
, IV
.get(),
10086 NumIterations
.get());
10087 ExprResult CombDistCond
;
10088 if (isOpenMPLoopBoundSharingDirective(DKind
)) {
10089 CombDistCond
= SemaRef
.BuildBinOp(CurScope
, CondLoc
, BO_LT
, IV
.get(),
10090 NumIterations
.get());
10093 ExprResult CombCond
;
10094 if (isOpenMPLoopBoundSharingDirective(DKind
)) {
10095 Expr
*BoundCombUB
= CombUB
.get();
10096 if (UseStrictCompare
) {
10100 CurScope
, CondLoc
, BO_Add
, BoundCombUB
,
10101 SemaRef
.ActOnIntegerConstant(SourceLocation(), 1).get())
10104 SemaRef
.ActOnFinishFullExpr(BoundCombUB
, /*DiscardedValue*/ false)
10108 SemaRef
.BuildBinOp(CurScope
, CondLoc
, UseStrictCompare
? BO_LT
: BO_LE
,
10109 IV
.get(), BoundCombUB
);
10111 // Loop increment (IV = IV + 1)
10112 SourceLocation IncLoc
= AStmt
->getBeginLoc();
10114 SemaRef
.BuildBinOp(CurScope
, IncLoc
, BO_Add
, IV
.get(),
10115 SemaRef
.ActOnIntegerConstant(IncLoc
, 1).get());
10116 if (!Inc
.isUsable())
10118 Inc
= SemaRef
.BuildBinOp(CurScope
, IncLoc
, BO_Assign
, IV
.get(), Inc
.get());
10119 Inc
= SemaRef
.ActOnFinishFullExpr(Inc
.get(), /*DiscardedValue*/ false);
10120 if (!Inc
.isUsable())
10123 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
10124 // Used for directives with static scheduling.
10125 // In combined construct, add combined version that use CombLB and CombUB
10126 // base variables for the update
10127 ExprResult NextLB
, NextUB
, CombNextLB
, CombNextUB
;
10128 if (isOpenMPWorksharingDirective(DKind
) || isOpenMPTaskLoopDirective(DKind
) ||
10129 isOpenMPGenericLoopDirective(DKind
) ||
10130 isOpenMPDistributeDirective(DKind
) ||
10131 isOpenMPLoopTransformationDirective(DKind
)) {
10133 NextLB
= SemaRef
.BuildBinOp(CurScope
, IncLoc
, BO_Add
, LB
.get(), ST
.get());
10134 if (!NextLB
.isUsable())
10138 SemaRef
.BuildBinOp(CurScope
, IncLoc
, BO_Assign
, LB
.get(), NextLB
.get());
10140 SemaRef
.ActOnFinishFullExpr(NextLB
.get(), /*DiscardedValue*/ false);
10141 if (!NextLB
.isUsable())
10144 NextUB
= SemaRef
.BuildBinOp(CurScope
, IncLoc
, BO_Add
, UB
.get(), ST
.get());
10145 if (!NextUB
.isUsable())
10149 SemaRef
.BuildBinOp(CurScope
, IncLoc
, BO_Assign
, UB
.get(), NextUB
.get());
10151 SemaRef
.ActOnFinishFullExpr(NextUB
.get(), /*DiscardedValue*/ false);
10152 if (!NextUB
.isUsable())
10154 if (isOpenMPLoopBoundSharingDirective(DKind
)) {
10156 SemaRef
.BuildBinOp(CurScope
, IncLoc
, BO_Add
, CombLB
.get(), ST
.get());
10157 if (!NextLB
.isUsable())
10160 CombNextLB
= SemaRef
.BuildBinOp(CurScope
, IncLoc
, BO_Assign
, CombLB
.get(),
10162 CombNextLB
= SemaRef
.ActOnFinishFullExpr(CombNextLB
.get(),
10163 /*DiscardedValue*/ false);
10164 if (!CombNextLB
.isUsable())
10168 SemaRef
.BuildBinOp(CurScope
, IncLoc
, BO_Add
, CombUB
.get(), ST
.get());
10169 if (!CombNextUB
.isUsable())
10172 CombNextUB
= SemaRef
.BuildBinOp(CurScope
, IncLoc
, BO_Assign
, CombUB
.get(),
10174 CombNextUB
= SemaRef
.ActOnFinishFullExpr(CombNextUB
.get(),
10175 /*DiscardedValue*/ false);
10176 if (!CombNextUB
.isUsable())
10181 // Create increment expression for distribute loop when combined in a same
10182 // directive with for as IV = IV + ST; ensure upper bound expression based
10183 // on PrevUB instead of NumIterations - used to implement 'for' when found
10184 // in combination with 'distribute', like in 'distribute parallel for'
10185 SourceLocation DistIncLoc
= AStmt
->getBeginLoc();
10186 ExprResult DistCond
, DistInc
, PrevEUB
, ParForInDistCond
;
10187 if (isOpenMPLoopBoundSharingDirective(DKind
)) {
10188 DistCond
= SemaRef
.BuildBinOp(
10189 CurScope
, CondLoc
, UseStrictCompare
? BO_LT
: BO_LE
, IV
.get(), BoundUB
);
10190 assert(DistCond
.isUsable() && "distribute cond expr was not built");
10193 SemaRef
.BuildBinOp(CurScope
, DistIncLoc
, BO_Add
, IV
.get(), ST
.get());
10194 assert(DistInc
.isUsable() && "distribute inc expr was not built");
10195 DistInc
= SemaRef
.BuildBinOp(CurScope
, DistIncLoc
, BO_Assign
, IV
.get(),
10198 SemaRef
.ActOnFinishFullExpr(DistInc
.get(), /*DiscardedValue*/ false);
10199 assert(DistInc
.isUsable() && "distribute inc expr was not built");
10201 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10203 ExprResult NewPrevUB
= PrevUB
;
10204 SourceLocation DistEUBLoc
= AStmt
->getBeginLoc();
10205 if (!SemaRef
.Context
.hasSameType(UB
.get()->getType(),
10206 PrevUB
.get()->getType())) {
10207 NewPrevUB
= SemaRef
.BuildCStyleCastExpr(
10209 SemaRef
.Context
.getTrivialTypeSourceInfo(UB
.get()->getType()),
10210 DistEUBLoc
, NewPrevUB
.get());
10211 if (!NewPrevUB
.isUsable())
10214 ExprResult IsUBGreater
= SemaRef
.BuildBinOp(CurScope
, DistEUBLoc
, BO_GT
,
10215 UB
.get(), NewPrevUB
.get());
10216 ExprResult CondOp
= SemaRef
.ActOnConditionalOp(
10217 DistEUBLoc
, DistEUBLoc
, IsUBGreater
.get(), NewPrevUB
.get(), UB
.get());
10218 PrevEUB
= SemaRef
.BuildBinOp(CurScope
, DistIncLoc
, BO_Assign
, UB
.get(),
10221 SemaRef
.ActOnFinishFullExpr(PrevEUB
.get(), /*DiscardedValue*/ false);
10223 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10224 // parallel for is in combination with a distribute directive with
10225 // schedule(static, 1)
10226 Expr
*BoundPrevUB
= PrevUB
.get();
10227 if (UseStrictCompare
) {
10231 CurScope
, CondLoc
, BO_Add
, BoundPrevUB
,
10232 SemaRef
.ActOnIntegerConstant(SourceLocation(), 1).get())
10235 SemaRef
.ActOnFinishFullExpr(BoundPrevUB
, /*DiscardedValue*/ false)
10239 SemaRef
.BuildBinOp(CurScope
, CondLoc
, UseStrictCompare
? BO_LT
: BO_LE
,
10240 IV
.get(), BoundPrevUB
);
10243 // Build updates and final values of the loop counters.
10244 bool HasErrors
= false;
10245 Built
.Counters
.resize(NestedLoopCount
);
10246 Built
.Inits
.resize(NestedLoopCount
);
10247 Built
.Updates
.resize(NestedLoopCount
);
10248 Built
.Finals
.resize(NestedLoopCount
);
10249 Built
.DependentCounters
.resize(NestedLoopCount
);
10250 Built
.DependentInits
.resize(NestedLoopCount
);
10251 Built
.FinalsConditions
.resize(NestedLoopCount
);
10253 // We implement the following algorithm for obtaining the
10254 // original loop iteration variable values based on the
10255 // value of the collapsed loop iteration variable IV.
10257 // Let n+1 be the number of collapsed loops in the nest.
10258 // Iteration variables (I0, I1, .... In)
10259 // Iteration counts (N0, N1, ... Nn)
10263 // To compute Ik for loop k, 0 <= k <= n, generate:
10264 // Prod = N(k+1) * N(k+2) * ... * Nn;
10265 // Ik = Acc / Prod;
10266 // Acc -= Ik * Prod;
10268 ExprResult Acc
= IV
;
10269 for (unsigned int Cnt
= 0; Cnt
< NestedLoopCount
; ++Cnt
) {
10270 LoopIterationSpace
&IS
= IterSpaces
[Cnt
];
10271 SourceLocation UpdLoc
= IS
.IncSrcRange
.getBegin();
10275 ExprResult Prod
= SemaRef
.ActOnIntegerConstant(SourceLocation(), 1).get();
10276 for (unsigned int K
= Cnt
+ 1; K
< NestedLoopCount
; ++K
)
10277 Prod
= SemaRef
.BuildBinOp(CurScope
, UpdLoc
, BO_Mul
, Prod
.get(),
10278 IterSpaces
[K
].NumIterations
);
10280 // Iter = Acc / Prod
10281 // If there is at least one more inner loop to avoid
10282 // multiplication by 1.
10283 if (Cnt
+ 1 < NestedLoopCount
)
10285 SemaRef
.BuildBinOp(CurScope
, UpdLoc
, BO_Div
, Acc
.get(), Prod
.get());
10288 if (!Iter
.isUsable()) {
10294 // Acc -= Iter * Prod
10295 // Check if there is at least one more inner loop to avoid
10296 // multiplication by 1.
10297 if (Cnt
+ 1 < NestedLoopCount
)
10298 Prod
= SemaRef
.BuildBinOp(CurScope
, UpdLoc
, BO_Mul
, Iter
.get(),
10302 Acc
= SemaRef
.BuildBinOp(CurScope
, UpdLoc
, BO_Sub
, Acc
.get(), Prod
.get());
10304 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10305 auto *VD
= cast
<VarDecl
>(cast
<DeclRefExpr
>(IS
.CounterVar
)->getDecl());
10306 DeclRefExpr
*CounterVar
= buildDeclRefExpr(
10307 SemaRef
, VD
, IS
.CounterVar
->getType(), IS
.CounterVar
->getExprLoc(),
10308 /*RefersToCapture=*/true);
10310 buildCounterInit(SemaRef
, CurScope
, UpdLoc
, CounterVar
,
10311 IS
.CounterInit
, IS
.IsNonRectangularLB
, Captures
);
10312 if (!Init
.isUsable()) {
10316 ExprResult Update
= buildCounterUpdate(
10317 SemaRef
, CurScope
, UpdLoc
, CounterVar
, IS
.CounterInit
, Iter
,
10318 IS
.CounterStep
, IS
.Subtract
, IS
.IsNonRectangularLB
, &Captures
);
10319 if (!Update
.isUsable()) {
10324 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10326 buildCounterUpdate(SemaRef
, CurScope
, UpdLoc
, CounterVar
,
10327 IS
.CounterInit
, IS
.NumIterations
, IS
.CounterStep
,
10328 IS
.Subtract
, IS
.IsNonRectangularLB
, &Captures
);
10329 if (!Final
.isUsable()) {
10334 if (!Update
.isUsable() || !Final
.isUsable()) {
10339 Built
.Counters
[Cnt
] = IS
.CounterVar
;
10340 Built
.PrivateCounters
[Cnt
] = IS
.PrivateCounterVar
;
10341 Built
.Inits
[Cnt
] = Init
.get();
10342 Built
.Updates
[Cnt
] = Update
.get();
10343 Built
.Finals
[Cnt
] = Final
.get();
10344 Built
.DependentCounters
[Cnt
] = nullptr;
10345 Built
.DependentInits
[Cnt
] = nullptr;
10346 Built
.FinalsConditions
[Cnt
] = nullptr;
10347 if (IS
.IsNonRectangularLB
|| IS
.IsNonRectangularUB
) {
10348 Built
.DependentCounters
[Cnt
] = Built
.Counters
[IS
.LoopDependentIdx
- 1];
10349 Built
.DependentInits
[Cnt
] = Built
.Inits
[IS
.LoopDependentIdx
- 1];
10350 Built
.FinalsConditions
[Cnt
] = IS
.FinalCondition
;
10359 Built
.IterationVarRef
= IV
.get();
10360 Built
.LastIteration
= LastIteration
.get();
10361 Built
.NumIterations
= NumIterations
.get();
10362 Built
.CalcLastIteration
= SemaRef
10363 .ActOnFinishFullExpr(CalcLastIteration
.get(),
10364 /*DiscardedValue=*/false)
10366 Built
.PreCond
= PreCond
.get();
10367 Built
.PreInits
= buildPreInits(C
, Captures
);
10368 Built
.Cond
= Cond
.get();
10369 Built
.Init
= Init
.get();
10370 Built
.Inc
= Inc
.get();
10371 Built
.LB
= LB
.get();
10372 Built
.UB
= UB
.get();
10373 Built
.IL
= IL
.get();
10374 Built
.ST
= ST
.get();
10375 Built
.EUB
= EUB
.get();
10376 Built
.NLB
= NextLB
.get();
10377 Built
.NUB
= NextUB
.get();
10378 Built
.PrevLB
= PrevLB
.get();
10379 Built
.PrevUB
= PrevUB
.get();
10380 Built
.DistInc
= DistInc
.get();
10381 Built
.PrevEUB
= PrevEUB
.get();
10382 Built
.DistCombinedFields
.LB
= CombLB
.get();
10383 Built
.DistCombinedFields
.UB
= CombUB
.get();
10384 Built
.DistCombinedFields
.EUB
= CombEUB
.get();
10385 Built
.DistCombinedFields
.Init
= CombInit
.get();
10386 Built
.DistCombinedFields
.Cond
= CombCond
.get();
10387 Built
.DistCombinedFields
.NLB
= CombNextLB
.get();
10388 Built
.DistCombinedFields
.NUB
= CombNextUB
.get();
10389 Built
.DistCombinedFields
.DistCond
= CombDistCond
.get();
10390 Built
.DistCombinedFields
.ParForInDistCond
= ParForInDistCond
.get();
10392 return NestedLoopCount
;
10395 static Expr
*getCollapseNumberExpr(ArrayRef
<OMPClause
*> Clauses
) {
10396 auto CollapseClauses
=
10397 OMPExecutableDirective::getClausesOfKind
<OMPCollapseClause
>(Clauses
);
10398 if (CollapseClauses
.begin() != CollapseClauses
.end())
10399 return (*CollapseClauses
.begin())->getNumForLoops();
10403 static Expr
*getOrderedNumberExpr(ArrayRef
<OMPClause
*> Clauses
) {
10404 auto OrderedClauses
=
10405 OMPExecutableDirective::getClausesOfKind
<OMPOrderedClause
>(Clauses
);
10406 if (OrderedClauses
.begin() != OrderedClauses
.end())
10407 return (*OrderedClauses
.begin())->getNumForLoops();
10411 static bool checkSimdlenSafelenSpecified(Sema
&S
,
10412 const ArrayRef
<OMPClause
*> Clauses
) {
10413 const OMPSafelenClause
*Safelen
= nullptr;
10414 const OMPSimdlenClause
*Simdlen
= nullptr;
10416 for (const OMPClause
*Clause
: Clauses
) {
10417 if (Clause
->getClauseKind() == OMPC_safelen
)
10418 Safelen
= cast
<OMPSafelenClause
>(Clause
);
10419 else if (Clause
->getClauseKind() == OMPC_simdlen
)
10420 Simdlen
= cast
<OMPSimdlenClause
>(Clause
);
10421 if (Safelen
&& Simdlen
)
10425 if (Simdlen
&& Safelen
) {
10426 const Expr
*SimdlenLength
= Simdlen
->getSimdlen();
10427 const Expr
*SafelenLength
= Safelen
->getSafelen();
10428 if (SimdlenLength
->isValueDependent() || SimdlenLength
->isTypeDependent() ||
10429 SimdlenLength
->isInstantiationDependent() ||
10430 SimdlenLength
->containsUnexpandedParameterPack())
10432 if (SafelenLength
->isValueDependent() || SafelenLength
->isTypeDependent() ||
10433 SafelenLength
->isInstantiationDependent() ||
10434 SafelenLength
->containsUnexpandedParameterPack())
10436 Expr::EvalResult SimdlenResult
, SafelenResult
;
10437 SimdlenLength
->EvaluateAsInt(SimdlenResult
, S
.Context
);
10438 SafelenLength
->EvaluateAsInt(SafelenResult
, S
.Context
);
10439 llvm::APSInt SimdlenRes
= SimdlenResult
.Val
.getInt();
10440 llvm::APSInt SafelenRes
= SafelenResult
.Val
.getInt();
10441 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10442 // If both simdlen and safelen clauses are specified, the value of the
10443 // simdlen parameter must be less than or equal to the value of the safelen
10445 if (SimdlenRes
> SafelenRes
) {
10446 S
.Diag(SimdlenLength
->getExprLoc(),
10447 diag::err_omp_wrong_simdlen_safelen_values
)
10448 << SimdlenLength
->getSourceRange() << SafelenLength
->getSourceRange();
10455 static bool checkGenericLoopLastprivate(Sema
&S
, ArrayRef
<OMPClause
*> Clauses
,
10456 OpenMPDirectiveKind K
,
10457 DSAStackTy
*Stack
);
10459 bool Sema::checkLastPrivateForMappedDirectives(ArrayRef
<OMPClause
*> Clauses
) {
10461 // Check for syntax of lastprivate
10462 // Param of the lastprivate have different meanings in the mapped directives
10463 // e.g. "omp loop" Only loop iteration vars are allowed in lastprivate clause
10464 // "omp for" lastprivate vars must be shared
10465 if (getLangOpts().OpenMP
>= 50 &&
10466 DSAStack
->getMappedDirective() == OMPD_loop
&&
10467 checkGenericLoopLastprivate(*this, Clauses
, OMPD_loop
, DSAStack
)) {
10474 Sema::ActOnOpenMPSimdDirective(ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
,
10475 SourceLocation StartLoc
, SourceLocation EndLoc
,
10476 VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
10478 return StmtError();
10480 if (!checkLastPrivateForMappedDirectives(Clauses
))
10481 return StmtError();
10483 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
10484 OMPLoopBasedDirective::HelperExprs B
;
10485 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10486 // define the nested loops number.
10487 unsigned NestedLoopCount
= checkOpenMPLoop(
10488 OMPD_simd
, getCollapseNumberExpr(Clauses
), getOrderedNumberExpr(Clauses
),
10489 AStmt
, *this, *DSAStack
, VarsWithImplicitDSA
, B
);
10490 if (NestedLoopCount
== 0)
10491 return StmtError();
10493 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
10494 "omp simd loop exprs were not built");
10496 if (!CurContext
->isDependentContext()) {
10497 // Finalize the clauses that need pre-built expressions for CodeGen.
10498 for (OMPClause
*C
: Clauses
) {
10499 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
10500 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
10501 B
.NumIterations
, *this, CurScope
,
10503 return StmtError();
10507 if (checkSimdlenSafelenSpecified(*this, Clauses
))
10508 return StmtError();
10510 setFunctionHasBranchProtectedScope();
10511 auto *SimdDirective
= OMPSimdDirective::Create(
10512 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
,
10513 DSAStack
->getMappedDirective());
10514 return SimdDirective
;
10518 Sema::ActOnOpenMPForDirective(ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
,
10519 SourceLocation StartLoc
, SourceLocation EndLoc
,
10520 VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
10522 return StmtError();
10524 if (!checkLastPrivateForMappedDirectives(Clauses
))
10525 return StmtError();
10527 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
10528 OMPLoopBasedDirective::HelperExprs B
;
10529 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10530 // define the nested loops number.
10531 unsigned NestedLoopCount
= checkOpenMPLoop(
10532 OMPD_for
, getCollapseNumberExpr(Clauses
), getOrderedNumberExpr(Clauses
),
10533 AStmt
, *this, *DSAStack
, VarsWithImplicitDSA
, B
);
10534 if (NestedLoopCount
== 0)
10535 return StmtError();
10537 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
10538 "omp for loop exprs were not built");
10540 if (!CurContext
->isDependentContext()) {
10541 // Finalize the clauses that need pre-built expressions for CodeGen.
10542 for (OMPClause
*C
: Clauses
) {
10543 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
10544 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
10545 B
.NumIterations
, *this, CurScope
,
10547 return StmtError();
10551 auto *ForDirective
= OMPForDirective::Create(
10552 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
,
10553 DSAStack
->getTaskgroupReductionRef(), DSAStack
->isCancelRegion(),
10554 DSAStack
->getMappedDirective());
10555 return ForDirective
;
10558 StmtResult
Sema::ActOnOpenMPForSimdDirective(
10559 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
10560 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
10562 return StmtError();
10564 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
10565 OMPLoopBasedDirective::HelperExprs B
;
10566 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10567 // define the nested loops number.
10568 unsigned NestedLoopCount
=
10569 checkOpenMPLoop(OMPD_for_simd
, getCollapseNumberExpr(Clauses
),
10570 getOrderedNumberExpr(Clauses
), AStmt
, *this, *DSAStack
,
10571 VarsWithImplicitDSA
, B
);
10572 if (NestedLoopCount
== 0)
10573 return StmtError();
10575 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
10576 "omp for simd loop exprs were not built");
10578 if (!CurContext
->isDependentContext()) {
10579 // Finalize the clauses that need pre-built expressions for CodeGen.
10580 for (OMPClause
*C
: Clauses
) {
10581 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
10582 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
10583 B
.NumIterations
, *this, CurScope
,
10585 return StmtError();
10589 if (checkSimdlenSafelenSpecified(*this, Clauses
))
10590 return StmtError();
10592 setFunctionHasBranchProtectedScope();
10593 return OMPForSimdDirective::Create(Context
, StartLoc
, EndLoc
, NestedLoopCount
,
10594 Clauses
, AStmt
, B
);
10597 StmtResult
Sema::ActOnOpenMPSectionsDirective(ArrayRef
<OMPClause
*> Clauses
,
10599 SourceLocation StartLoc
,
10600 SourceLocation EndLoc
) {
10602 return StmtError();
10604 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
10605 auto BaseStmt
= AStmt
;
10606 while (auto *CS
= dyn_cast_or_null
<CapturedStmt
>(BaseStmt
))
10607 BaseStmt
= CS
->getCapturedStmt();
10608 if (auto *C
= dyn_cast_or_null
<CompoundStmt
>(BaseStmt
)) {
10609 auto S
= C
->children();
10610 if (S
.begin() == S
.end())
10611 return StmtError();
10612 // All associated statements must be '#pragma omp section' except for
10614 for (Stmt
*SectionStmt
: llvm::drop_begin(S
)) {
10615 if (!SectionStmt
|| !isa
<OMPSectionDirective
>(SectionStmt
)) {
10617 Diag(SectionStmt
->getBeginLoc(),
10618 diag::err_omp_sections_substmt_not_section
);
10619 return StmtError();
10621 cast
<OMPSectionDirective
>(SectionStmt
)
10622 ->setHasCancel(DSAStack
->isCancelRegion());
10625 Diag(AStmt
->getBeginLoc(), diag::err_omp_sections_not_compound_stmt
);
10626 return StmtError();
10629 setFunctionHasBranchProtectedScope();
10631 return OMPSectionsDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
10632 DSAStack
->getTaskgroupReductionRef(),
10633 DSAStack
->isCancelRegion());
10636 StmtResult
Sema::ActOnOpenMPSectionDirective(Stmt
*AStmt
,
10637 SourceLocation StartLoc
,
10638 SourceLocation EndLoc
) {
10640 return StmtError();
10642 setFunctionHasBranchProtectedScope();
10643 DSAStack
->setParentCancelRegion(DSAStack
->isCancelRegion());
10645 return OMPSectionDirective::Create(Context
, StartLoc
, EndLoc
, AStmt
,
10646 DSAStack
->isCancelRegion());
10649 static Expr
*getDirectCallExpr(Expr
*E
) {
10650 E
= E
->IgnoreParenCasts()->IgnoreImplicit();
10651 if (auto *CE
= dyn_cast
<CallExpr
>(E
))
10652 if (CE
->getDirectCallee())
10657 StmtResult
Sema::ActOnOpenMPDispatchDirective(ArrayRef
<OMPClause
*> Clauses
,
10659 SourceLocation StartLoc
,
10660 SourceLocation EndLoc
) {
10662 return StmtError();
10664 Stmt
*S
= cast
<CapturedStmt
>(AStmt
)->getCapturedStmt();
10667 // expression-stmt : an expression statement with one of the following forms:
10668 // expression = target-call ( [expression-list] );
10669 // target-call ( [expression-list] );
10671 SourceLocation TargetCallLoc
;
10673 if (!CurContext
->isDependentContext()) {
10674 Expr
*TargetCall
= nullptr;
10676 auto *E
= dyn_cast
<Expr
>(S
);
10678 Diag(S
->getBeginLoc(), diag::err_omp_dispatch_statement_call
);
10679 return StmtError();
10682 E
= E
->IgnoreParenCasts()->IgnoreImplicit();
10684 if (auto *BO
= dyn_cast
<BinaryOperator
>(E
)) {
10685 if (BO
->getOpcode() == BO_Assign
)
10686 TargetCall
= getDirectCallExpr(BO
->getRHS());
10688 if (auto *COCE
= dyn_cast
<CXXOperatorCallExpr
>(E
))
10689 if (COCE
->getOperator() == OO_Equal
)
10690 TargetCall
= getDirectCallExpr(COCE
->getArg(1));
10692 TargetCall
= getDirectCallExpr(E
);
10695 Diag(E
->getBeginLoc(), diag::err_omp_dispatch_statement_call
);
10696 return StmtError();
10698 TargetCallLoc
= TargetCall
->getExprLoc();
10701 setFunctionHasBranchProtectedScope();
10703 return OMPDispatchDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
10707 static bool checkGenericLoopLastprivate(Sema
&S
, ArrayRef
<OMPClause
*> Clauses
,
10708 OpenMPDirectiveKind K
,
10709 DSAStackTy
*Stack
) {
10710 bool ErrorFound
= false;
10711 for (OMPClause
*C
: Clauses
) {
10712 if (auto *LPC
= dyn_cast
<OMPLastprivateClause
>(C
)) {
10713 for (Expr
*RefExpr
: LPC
->varlists()) {
10714 SourceLocation ELoc
;
10715 SourceRange ERange
;
10716 Expr
*SimpleRefExpr
= RefExpr
;
10717 auto Res
= getPrivateItem(S
, SimpleRefExpr
, ELoc
, ERange
);
10718 if (ValueDecl
*D
= Res
.first
) {
10719 auto &&Info
= Stack
->isLoopControlVariable(D
);
10721 S
.Diag(ELoc
, diag::err_omp_lastprivate_loop_var_non_loop_iteration
)
10722 << getOpenMPDirectiveName(K
);
10732 StmtResult
Sema::ActOnOpenMPGenericLoopDirective(
10733 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
10734 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
10736 return StmtError();
10738 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10739 // A list item may not appear in a lastprivate clause unless it is the
10740 // loop iteration variable of a loop that is associated with the construct.
10741 if (checkGenericLoopLastprivate(*this, Clauses
, OMPD_loop
, DSAStack
))
10742 return StmtError();
10744 auto *CS
= cast
<CapturedStmt
>(AStmt
);
10745 // 1.2.2 OpenMP Language Terminology
10746 // Structured block - An executable statement with a single entry at the
10747 // top and a single exit at the bottom.
10748 // The point of exit cannot be a branch out of the structured block.
10749 // longjmp() and throw() must not violate the entry/exit criteria.
10750 CS
->getCapturedDecl()->setNothrow();
10752 OMPLoopDirective::HelperExprs B
;
10753 // In presence of clause 'collapse', it will define the nested loops number.
10754 unsigned NestedLoopCount
= checkOpenMPLoop(
10755 OMPD_loop
, getCollapseNumberExpr(Clauses
), getOrderedNumberExpr(Clauses
),
10756 AStmt
, *this, *DSAStack
, VarsWithImplicitDSA
, B
);
10757 if (NestedLoopCount
== 0)
10758 return StmtError();
10760 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
10761 "omp loop exprs were not built");
10763 setFunctionHasBranchProtectedScope();
10764 return OMPGenericLoopDirective::Create(Context
, StartLoc
, EndLoc
,
10765 NestedLoopCount
, Clauses
, AStmt
, B
);
10768 StmtResult
Sema::ActOnOpenMPTeamsGenericLoopDirective(
10769 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
10770 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
10772 return StmtError();
10774 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10775 // A list item may not appear in a lastprivate clause unless it is the
10776 // loop iteration variable of a loop that is associated with the construct.
10777 if (checkGenericLoopLastprivate(*this, Clauses
, OMPD_teams_loop
, DSAStack
))
10778 return StmtError();
10780 auto *CS
= cast
<CapturedStmt
>(AStmt
);
10781 // 1.2.2 OpenMP Language Terminology
10782 // Structured block - An executable statement with a single entry at the
10783 // top and a single exit at the bottom.
10784 // The point of exit cannot be a branch out of the structured block.
10785 // longjmp() and throw() must not violate the entry/exit criteria.
10786 CS
->getCapturedDecl()->setNothrow();
10787 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_teams_loop
);
10788 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
10789 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
10790 // 1.2.2 OpenMP Language Terminology
10791 // Structured block - An executable statement with a single entry at the
10792 // top and a single exit at the bottom.
10793 // The point of exit cannot be a branch out of the structured block.
10794 // longjmp() and throw() must not violate the entry/exit criteria.
10795 CS
->getCapturedDecl()->setNothrow();
10798 OMPLoopDirective::HelperExprs B
;
10799 // In presence of clause 'collapse', it will define the nested loops number.
10800 unsigned NestedLoopCount
=
10801 checkOpenMPLoop(OMPD_teams_loop
, getCollapseNumberExpr(Clauses
),
10802 /*OrderedLoopCountExpr=*/nullptr, CS
, *this, *DSAStack
,
10803 VarsWithImplicitDSA
, B
);
10804 if (NestedLoopCount
== 0)
10805 return StmtError();
10807 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
10808 "omp loop exprs were not built");
10810 setFunctionHasBranchProtectedScope();
10811 DSAStack
->setParentTeamsRegionLoc(StartLoc
);
10813 return OMPTeamsGenericLoopDirective::Create(
10814 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
10817 StmtResult
Sema::ActOnOpenMPTargetTeamsGenericLoopDirective(
10818 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
10819 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
10821 return StmtError();
10823 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10824 // A list item may not appear in a lastprivate clause unless it is the
10825 // loop iteration variable of a loop that is associated with the construct.
10826 if (checkGenericLoopLastprivate(*this, Clauses
, OMPD_target_teams_loop
,
10828 return StmtError();
10830 auto *CS
= cast
<CapturedStmt
>(AStmt
);
10831 // 1.2.2 OpenMP Language Terminology
10832 // Structured block - An executable statement with a single entry at the
10833 // top and a single exit at the bottom.
10834 // The point of exit cannot be a branch out of the structured block.
10835 // longjmp() and throw() must not violate the entry/exit criteria.
10836 CS
->getCapturedDecl()->setNothrow();
10837 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_teams_loop
);
10838 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
10839 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
10840 // 1.2.2 OpenMP Language Terminology
10841 // Structured block - An executable statement with a single entry at the
10842 // top and a single exit at the bottom.
10843 // The point of exit cannot be a branch out of the structured block.
10844 // longjmp() and throw() must not violate the entry/exit criteria.
10845 CS
->getCapturedDecl()->setNothrow();
10848 OMPLoopDirective::HelperExprs B
;
10849 // In presence of clause 'collapse', it will define the nested loops number.
10850 unsigned NestedLoopCount
=
10851 checkOpenMPLoop(OMPD_target_teams_loop
, getCollapseNumberExpr(Clauses
),
10852 /*OrderedLoopCountExpr=*/nullptr, CS
, *this, *DSAStack
,
10853 VarsWithImplicitDSA
, B
);
10854 if (NestedLoopCount
== 0)
10855 return StmtError();
10857 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
10858 "omp loop exprs were not built");
10860 setFunctionHasBranchProtectedScope();
10862 return OMPTargetTeamsGenericLoopDirective::Create(
10863 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
10866 StmtResult
Sema::ActOnOpenMPParallelGenericLoopDirective(
10867 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
10868 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
10870 return StmtError();
10872 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10873 // A list item may not appear in a lastprivate clause unless it is the
10874 // loop iteration variable of a loop that is associated with the construct.
10875 if (checkGenericLoopLastprivate(*this, Clauses
, OMPD_parallel_loop
, DSAStack
))
10876 return StmtError();
10878 auto *CS
= cast
<CapturedStmt
>(AStmt
);
10879 // 1.2.2 OpenMP Language Terminology
10880 // Structured block - An executable statement with a single entry at the
10881 // top and a single exit at the bottom.
10882 // The point of exit cannot be a branch out of the structured block.
10883 // longjmp() and throw() must not violate the entry/exit criteria.
10884 CS
->getCapturedDecl()->setNothrow();
10885 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_parallel_loop
);
10886 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
10887 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
10888 // 1.2.2 OpenMP Language Terminology
10889 // Structured block - An executable statement with a single entry at the
10890 // top and a single exit at the bottom.
10891 // The point of exit cannot be a branch out of the structured block.
10892 // longjmp() and throw() must not violate the entry/exit criteria.
10893 CS
->getCapturedDecl()->setNothrow();
10896 OMPLoopDirective::HelperExprs B
;
10897 // In presence of clause 'collapse', it will define the nested loops number.
10898 unsigned NestedLoopCount
=
10899 checkOpenMPLoop(OMPD_parallel_loop
, getCollapseNumberExpr(Clauses
),
10900 /*OrderedLoopCountExpr=*/nullptr, CS
, *this, *DSAStack
,
10901 VarsWithImplicitDSA
, B
);
10902 if (NestedLoopCount
== 0)
10903 return StmtError();
10905 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
10906 "omp loop exprs were not built");
10908 setFunctionHasBranchProtectedScope();
10910 return OMPParallelGenericLoopDirective::Create(
10911 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
10914 StmtResult
Sema::ActOnOpenMPTargetParallelGenericLoopDirective(
10915 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
10916 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
10918 return StmtError();
10920 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10921 // A list item may not appear in a lastprivate clause unless it is the
10922 // loop iteration variable of a loop that is associated with the construct.
10923 if (checkGenericLoopLastprivate(*this, Clauses
, OMPD_target_parallel_loop
,
10925 return StmtError();
10927 auto *CS
= cast
<CapturedStmt
>(AStmt
);
10928 // 1.2.2 OpenMP Language Terminology
10929 // Structured block - An executable statement with a single entry at the
10930 // top and a single exit at the bottom.
10931 // The point of exit cannot be a branch out of the structured block.
10932 // longjmp() and throw() must not violate the entry/exit criteria.
10933 CS
->getCapturedDecl()->setNothrow();
10934 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_parallel_loop
);
10935 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
10936 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
10937 // 1.2.2 OpenMP Language Terminology
10938 // Structured block - An executable statement with a single entry at the
10939 // top and a single exit at the bottom.
10940 // The point of exit cannot be a branch out of the structured block.
10941 // longjmp() and throw() must not violate the entry/exit criteria.
10942 CS
->getCapturedDecl()->setNothrow();
10945 OMPLoopDirective::HelperExprs B
;
10946 // In presence of clause 'collapse', it will define the nested loops number.
10947 unsigned NestedLoopCount
=
10948 checkOpenMPLoop(OMPD_target_parallel_loop
, getCollapseNumberExpr(Clauses
),
10949 /*OrderedLoopCountExpr=*/nullptr, CS
, *this, *DSAStack
,
10950 VarsWithImplicitDSA
, B
);
10951 if (NestedLoopCount
== 0)
10952 return StmtError();
10954 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
10955 "omp loop exprs were not built");
10957 setFunctionHasBranchProtectedScope();
10959 return OMPTargetParallelGenericLoopDirective::Create(
10960 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
10963 StmtResult
Sema::ActOnOpenMPSingleDirective(ArrayRef
<OMPClause
*> Clauses
,
10965 SourceLocation StartLoc
,
10966 SourceLocation EndLoc
) {
10968 return StmtError();
10970 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
10972 setFunctionHasBranchProtectedScope();
10974 // OpenMP [2.7.3, single Construct, Restrictions]
10975 // The copyprivate clause must not be used with the nowait clause.
10976 const OMPClause
*Nowait
= nullptr;
10977 const OMPClause
*Copyprivate
= nullptr;
10978 for (const OMPClause
*Clause
: Clauses
) {
10979 if (Clause
->getClauseKind() == OMPC_nowait
)
10981 else if (Clause
->getClauseKind() == OMPC_copyprivate
)
10982 Copyprivate
= Clause
;
10983 if (Copyprivate
&& Nowait
) {
10984 Diag(Copyprivate
->getBeginLoc(),
10985 diag::err_omp_single_copyprivate_with_nowait
);
10986 Diag(Nowait
->getBeginLoc(), diag::note_omp_nowait_clause_here
);
10987 return StmtError();
10991 return OMPSingleDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
);
10994 StmtResult
Sema::ActOnOpenMPMasterDirective(Stmt
*AStmt
,
10995 SourceLocation StartLoc
,
10996 SourceLocation EndLoc
) {
10998 return StmtError();
11000 setFunctionHasBranchProtectedScope();
11002 return OMPMasterDirective::Create(Context
, StartLoc
, EndLoc
, AStmt
);
11005 StmtResult
Sema::ActOnOpenMPMaskedDirective(ArrayRef
<OMPClause
*> Clauses
,
11007 SourceLocation StartLoc
,
11008 SourceLocation EndLoc
) {
11010 return StmtError();
11012 setFunctionHasBranchProtectedScope();
11014 return OMPMaskedDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
);
11017 StmtResult
Sema::ActOnOpenMPCriticalDirective(
11018 const DeclarationNameInfo
&DirName
, ArrayRef
<OMPClause
*> Clauses
,
11019 Stmt
*AStmt
, SourceLocation StartLoc
, SourceLocation EndLoc
) {
11021 return StmtError();
11023 bool ErrorFound
= false;
11025 SourceLocation HintLoc
;
11026 bool DependentHint
= false;
11027 for (const OMPClause
*C
: Clauses
) {
11028 if (C
->getClauseKind() == OMPC_hint
) {
11029 if (!DirName
.getName()) {
11030 Diag(C
->getBeginLoc(), diag::err_omp_hint_clause_no_name
);
11033 Expr
*E
= cast
<OMPHintClause
>(C
)->getHint();
11034 if (E
->isTypeDependent() || E
->isValueDependent() ||
11035 E
->isInstantiationDependent()) {
11036 DependentHint
= true;
11038 Hint
= E
->EvaluateKnownConstInt(Context
);
11039 HintLoc
= C
->getBeginLoc();
11044 return StmtError();
11045 const auto Pair
= DSAStack
->getCriticalWithHint(DirName
);
11046 if (Pair
.first
&& DirName
.getName() && !DependentHint
) {
11047 if (llvm::APSInt::compareValues(Hint
, Pair
.second
) != 0) {
11048 Diag(StartLoc
, diag::err_omp_critical_with_hint
);
11049 if (HintLoc
.isValid())
11050 Diag(HintLoc
, diag::note_omp_critical_hint_here
)
11051 << 0 << toString(Hint
, /*Radix=*/10, /*Signed=*/false);
11053 Diag(StartLoc
, diag::note_omp_critical_no_hint
) << 0;
11054 if (const auto *C
= Pair
.first
->getSingleClause
<OMPHintClause
>()) {
11055 Diag(C
->getBeginLoc(), diag::note_omp_critical_hint_here
)
11057 << toString(C
->getHint()->EvaluateKnownConstInt(Context
),
11058 /*Radix=*/10, /*Signed=*/false);
11060 Diag(Pair
.first
->getBeginLoc(), diag::note_omp_critical_no_hint
) << 1;
11065 setFunctionHasBranchProtectedScope();
11067 auto *Dir
= OMPCriticalDirective::Create(Context
, DirName
, StartLoc
, EndLoc
,
11069 if (!Pair
.first
&& DirName
.getName() && !DependentHint
)
11070 DSAStack
->addCriticalWithHint(Dir
, Hint
);
11074 StmtResult
Sema::ActOnOpenMPParallelForDirective(
11075 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
11076 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
11078 return StmtError();
11080 auto *CS
= cast
<CapturedStmt
>(AStmt
);
11081 // 1.2.2 OpenMP Language Terminology
11082 // Structured block - An executable statement with a single entry at the
11083 // top and a single exit at the bottom.
11084 // The point of exit cannot be a branch out of the structured block.
11085 // longjmp() and throw() must not violate the entry/exit criteria.
11086 CS
->getCapturedDecl()->setNothrow();
11088 OMPLoopBasedDirective::HelperExprs B
;
11089 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11090 // define the nested loops number.
11091 unsigned NestedLoopCount
=
11092 checkOpenMPLoop(OMPD_parallel_for
, getCollapseNumberExpr(Clauses
),
11093 getOrderedNumberExpr(Clauses
), AStmt
, *this, *DSAStack
,
11094 VarsWithImplicitDSA
, B
);
11095 if (NestedLoopCount
== 0)
11096 return StmtError();
11098 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
11099 "omp parallel for loop exprs were not built");
11101 if (!CurContext
->isDependentContext()) {
11102 // Finalize the clauses that need pre-built expressions for CodeGen.
11103 for (OMPClause
*C
: Clauses
) {
11104 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
11105 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
11106 B
.NumIterations
, *this, CurScope
,
11108 return StmtError();
11112 setFunctionHasBranchProtectedScope();
11113 return OMPParallelForDirective::Create(
11114 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
,
11115 DSAStack
->getTaskgroupReductionRef(), DSAStack
->isCancelRegion());
11118 StmtResult
Sema::ActOnOpenMPParallelForSimdDirective(
11119 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
11120 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
11122 return StmtError();
11124 auto *CS
= cast
<CapturedStmt
>(AStmt
);
11125 // 1.2.2 OpenMP Language Terminology
11126 // Structured block - An executable statement with a single entry at the
11127 // top and a single exit at the bottom.
11128 // The point of exit cannot be a branch out of the structured block.
11129 // longjmp() and throw() must not violate the entry/exit criteria.
11130 CS
->getCapturedDecl()->setNothrow();
11132 OMPLoopBasedDirective::HelperExprs B
;
11133 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11134 // define the nested loops number.
11135 unsigned NestedLoopCount
=
11136 checkOpenMPLoop(OMPD_parallel_for_simd
, getCollapseNumberExpr(Clauses
),
11137 getOrderedNumberExpr(Clauses
), AStmt
, *this, *DSAStack
,
11138 VarsWithImplicitDSA
, B
);
11139 if (NestedLoopCount
== 0)
11140 return StmtError();
11142 if (!CurContext
->isDependentContext()) {
11143 // Finalize the clauses that need pre-built expressions for CodeGen.
11144 for (OMPClause
*C
: Clauses
) {
11145 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
11146 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
11147 B
.NumIterations
, *this, CurScope
,
11149 return StmtError();
11153 if (checkSimdlenSafelenSpecified(*this, Clauses
))
11154 return StmtError();
11156 setFunctionHasBranchProtectedScope();
11157 return OMPParallelForSimdDirective::Create(
11158 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
11162 Sema::ActOnOpenMPParallelMasterDirective(ArrayRef
<OMPClause
*> Clauses
,
11163 Stmt
*AStmt
, SourceLocation StartLoc
,
11164 SourceLocation EndLoc
) {
11166 return StmtError();
11168 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
11169 auto *CS
= cast
<CapturedStmt
>(AStmt
);
11170 // 1.2.2 OpenMP Language Terminology
11171 // Structured block - An executable statement with a single entry at the
11172 // top and a single exit at the bottom.
11173 // The point of exit cannot be a branch out of the structured block.
11174 // longjmp() and throw() must not violate the entry/exit criteria.
11175 CS
->getCapturedDecl()->setNothrow();
11177 setFunctionHasBranchProtectedScope();
11179 return OMPParallelMasterDirective::Create(
11180 Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
11181 DSAStack
->getTaskgroupReductionRef());
11185 Sema::ActOnOpenMPParallelMaskedDirective(ArrayRef
<OMPClause
*> Clauses
,
11186 Stmt
*AStmt
, SourceLocation StartLoc
,
11187 SourceLocation EndLoc
) {
11189 return StmtError();
11191 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
11192 auto *CS
= cast
<CapturedStmt
>(AStmt
);
11193 // 1.2.2 OpenMP Language Terminology
11194 // Structured block - An executable statement with a single entry at the
11195 // top and a single exit at the bottom.
11196 // The point of exit cannot be a branch out of the structured block.
11197 // longjmp() and throw() must not violate the entry/exit criteria.
11198 CS
->getCapturedDecl()->setNothrow();
11200 setFunctionHasBranchProtectedScope();
11202 return OMPParallelMaskedDirective::Create(
11203 Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
11204 DSAStack
->getTaskgroupReductionRef());
11208 Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef
<OMPClause
*> Clauses
,
11209 Stmt
*AStmt
, SourceLocation StartLoc
,
11210 SourceLocation EndLoc
) {
11212 return StmtError();
11214 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
11215 auto BaseStmt
= AStmt
;
11216 while (auto *CS
= dyn_cast_or_null
<CapturedStmt
>(BaseStmt
))
11217 BaseStmt
= CS
->getCapturedStmt();
11218 if (auto *C
= dyn_cast_or_null
<CompoundStmt
>(BaseStmt
)) {
11219 auto S
= C
->children();
11220 if (S
.begin() == S
.end())
11221 return StmtError();
11222 // All associated statements must be '#pragma omp section' except for
11224 for (Stmt
*SectionStmt
: llvm::drop_begin(S
)) {
11225 if (!SectionStmt
|| !isa
<OMPSectionDirective
>(SectionStmt
)) {
11227 Diag(SectionStmt
->getBeginLoc(),
11228 diag::err_omp_parallel_sections_substmt_not_section
);
11229 return StmtError();
11231 cast
<OMPSectionDirective
>(SectionStmt
)
11232 ->setHasCancel(DSAStack
->isCancelRegion());
11235 Diag(AStmt
->getBeginLoc(),
11236 diag::err_omp_parallel_sections_not_compound_stmt
);
11237 return StmtError();
11240 setFunctionHasBranchProtectedScope();
11242 return OMPParallelSectionsDirective::Create(
11243 Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
11244 DSAStack
->getTaskgroupReductionRef(), DSAStack
->isCancelRegion());
11247 /// Find and diagnose mutually exclusive clause kinds.
11248 static bool checkMutuallyExclusiveClauses(
11249 Sema
&S
, ArrayRef
<OMPClause
*> Clauses
,
11250 ArrayRef
<OpenMPClauseKind
> MutuallyExclusiveClauses
) {
11251 const OMPClause
*PrevClause
= nullptr;
11252 bool ErrorFound
= false;
11253 for (const OMPClause
*C
: Clauses
) {
11254 if (llvm::is_contained(MutuallyExclusiveClauses
, C
->getClauseKind())) {
11257 } else if (PrevClause
->getClauseKind() != C
->getClauseKind()) {
11258 S
.Diag(C
->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive
)
11259 << getOpenMPClauseName(C
->getClauseKind())
11260 << getOpenMPClauseName(PrevClause
->getClauseKind());
11261 S
.Diag(PrevClause
->getBeginLoc(), diag::note_omp_previous_clause
)
11262 << getOpenMPClauseName(PrevClause
->getClauseKind());
11270 StmtResult
Sema::ActOnOpenMPTaskDirective(ArrayRef
<OMPClause
*> Clauses
,
11271 Stmt
*AStmt
, SourceLocation StartLoc
,
11272 SourceLocation EndLoc
) {
11274 return StmtError();
11276 // OpenMP 5.0, 2.10.1 task Construct
11277 // If a detach clause appears on the directive, then a mergeable clause cannot
11278 // appear on the same directive.
11279 if (checkMutuallyExclusiveClauses(*this, Clauses
,
11280 {OMPC_detach
, OMPC_mergeable
}))
11281 return StmtError();
11283 auto *CS
= cast
<CapturedStmt
>(AStmt
);
11284 // 1.2.2 OpenMP Language Terminology
11285 // Structured block - An executable statement with a single entry at the
11286 // top and a single exit at the bottom.
11287 // The point of exit cannot be a branch out of the structured block.
11288 // longjmp() and throw() must not violate the entry/exit criteria.
11289 CS
->getCapturedDecl()->setNothrow();
11291 setFunctionHasBranchProtectedScope();
11293 return OMPTaskDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
11294 DSAStack
->isCancelRegion());
11297 StmtResult
Sema::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc
,
11298 SourceLocation EndLoc
) {
11299 return OMPTaskyieldDirective::Create(Context
, StartLoc
, EndLoc
);
11302 StmtResult
Sema::ActOnOpenMPBarrierDirective(SourceLocation StartLoc
,
11303 SourceLocation EndLoc
) {
11304 return OMPBarrierDirective::Create(Context
, StartLoc
, EndLoc
);
11307 StmtResult
Sema::ActOnOpenMPErrorDirective(ArrayRef
<OMPClause
*> Clauses
,
11308 SourceLocation StartLoc
,
11309 SourceLocation EndLoc
,
11310 bool InExContext
) {
11311 const OMPAtClause
*AtC
=
11312 OMPExecutableDirective::getSingleClause
<OMPAtClause
>(Clauses
);
11314 if (AtC
&& !InExContext
&& AtC
->getAtKind() == OMPC_AT_execution
) {
11315 Diag(AtC
->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier
);
11316 return StmtError();
11319 const OMPSeverityClause
*SeverityC
=
11320 OMPExecutableDirective::getSingleClause
<OMPSeverityClause
>(Clauses
);
11321 const OMPMessageClause
*MessageC
=
11322 OMPExecutableDirective::getSingleClause
<OMPMessageClause
>(Clauses
);
11323 Expr
*ME
= MessageC
? MessageC
->getMessageString() : nullptr;
11325 if (!AtC
|| AtC
->getAtKind() == OMPC_AT_compilation
) {
11326 if (SeverityC
&& SeverityC
->getSeverityKind() == OMPC_SEVERITY_warning
)
11327 Diag(SeverityC
->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded
)
11328 << (ME
? cast
<StringLiteral
>(ME
)->getString() : "WARNING");
11330 Diag(StartLoc
, diag::err_diagnose_if_succeeded
)
11331 << (ME
? cast
<StringLiteral
>(ME
)->getString() : "ERROR");
11332 if (!SeverityC
|| SeverityC
->getSeverityKind() != OMPC_SEVERITY_warning
)
11333 return StmtError();
11335 return OMPErrorDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
);
11338 StmtResult
Sema::ActOnOpenMPTaskwaitDirective(ArrayRef
<OMPClause
*> Clauses
,
11339 SourceLocation StartLoc
,
11340 SourceLocation EndLoc
) {
11341 const OMPNowaitClause
*NowaitC
=
11342 OMPExecutableDirective::getSingleClause
<OMPNowaitClause
>(Clauses
);
11344 !OMPExecutableDirective::getClausesOfKind
<OMPDependClause
>(Clauses
)
11346 if (NowaitC
&& !HasDependC
) {
11347 Diag(StartLoc
, diag::err_omp_nowait_clause_without_depend
);
11348 return StmtError();
11351 return OMPTaskwaitDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
);
11354 StmtResult
Sema::ActOnOpenMPTaskgroupDirective(ArrayRef
<OMPClause
*> Clauses
,
11356 SourceLocation StartLoc
,
11357 SourceLocation EndLoc
) {
11359 return StmtError();
11361 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
11363 setFunctionHasBranchProtectedScope();
11365 return OMPTaskgroupDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
,
11367 DSAStack
->getTaskgroupReductionRef());
11370 StmtResult
Sema::ActOnOpenMPFlushDirective(ArrayRef
<OMPClause
*> Clauses
,
11371 SourceLocation StartLoc
,
11372 SourceLocation EndLoc
) {
11373 OMPFlushClause
*FC
= nullptr;
11374 OMPClause
*OrderClause
= nullptr;
11375 for (OMPClause
*C
: Clauses
) {
11376 if (C
->getClauseKind() == OMPC_flush
)
11377 FC
= cast
<OMPFlushClause
>(C
);
11381 OpenMPClauseKind MemOrderKind
= OMPC_unknown
;
11382 SourceLocation MemOrderLoc
;
11383 for (const OMPClause
*C
: Clauses
) {
11384 if (C
->getClauseKind() == OMPC_acq_rel
||
11385 C
->getClauseKind() == OMPC_acquire
||
11386 C
->getClauseKind() == OMPC_release
) {
11387 if (MemOrderKind
!= OMPC_unknown
) {
11388 Diag(C
->getBeginLoc(), diag::err_omp_several_mem_order_clauses
)
11389 << getOpenMPDirectiveName(OMPD_flush
) << 1
11390 << SourceRange(C
->getBeginLoc(), C
->getEndLoc());
11391 Diag(MemOrderLoc
, diag::note_omp_previous_mem_order_clause
)
11392 << getOpenMPClauseName(MemOrderKind
);
11394 MemOrderKind
= C
->getClauseKind();
11395 MemOrderLoc
= C
->getBeginLoc();
11399 if (FC
&& OrderClause
) {
11400 Diag(FC
->getLParenLoc(), diag::err_omp_flush_order_clause_and_list
)
11401 << getOpenMPClauseName(OrderClause
->getClauseKind());
11402 Diag(OrderClause
->getBeginLoc(), diag::note_omp_flush_order_clause_here
)
11403 << getOpenMPClauseName(OrderClause
->getClauseKind());
11404 return StmtError();
11406 return OMPFlushDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
);
11409 StmtResult
Sema::ActOnOpenMPDepobjDirective(ArrayRef
<OMPClause
*> Clauses
,
11410 SourceLocation StartLoc
,
11411 SourceLocation EndLoc
) {
11412 if (Clauses
.empty()) {
11413 Diag(StartLoc
, diag::err_omp_depobj_expected
);
11414 return StmtError();
11415 } else if (Clauses
[0]->getClauseKind() != OMPC_depobj
) {
11416 Diag(Clauses
[0]->getBeginLoc(), diag::err_omp_depobj_expected
);
11417 return StmtError();
11419 // Only depobj expression and another single clause is allowed.
11420 if (Clauses
.size() > 2) {
11421 Diag(Clauses
[2]->getBeginLoc(),
11422 diag::err_omp_depobj_single_clause_expected
);
11423 return StmtError();
11424 } else if (Clauses
.size() < 1) {
11425 Diag(Clauses
[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected
);
11426 return StmtError();
11428 return OMPDepobjDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
);
11431 StmtResult
Sema::ActOnOpenMPScanDirective(ArrayRef
<OMPClause
*> Clauses
,
11432 SourceLocation StartLoc
,
11433 SourceLocation EndLoc
) {
11434 // Check that exactly one clause is specified.
11435 if (Clauses
.size() != 1) {
11436 Diag(Clauses
.empty() ? EndLoc
: Clauses
[1]->getBeginLoc(),
11437 diag::err_omp_scan_single_clause_expected
);
11438 return StmtError();
11440 // Check that scan directive is used in the scopeof the OpenMP loop body.
11441 if (Scope
*S
= DSAStack
->getCurScope()) {
11442 Scope
*ParentS
= S
->getParent();
11443 if (!ParentS
|| ParentS
->getParent() != ParentS
->getBreakParent() ||
11444 !ParentS
->getBreakParent()->isOpenMPLoopScope())
11445 return StmtError(Diag(StartLoc
, diag::err_omp_orphaned_device_directive
)
11446 << getOpenMPDirectiveName(OMPD_scan
) << 5);
11448 // Check that only one instance of scan directives is used in the same outer
11450 if (DSAStack
->doesParentHasScanDirective()) {
11451 Diag(StartLoc
, diag::err_omp_several_directives_in_region
) << "scan";
11452 Diag(DSAStack
->getParentScanDirectiveLoc(),
11453 diag::note_omp_previous_directive
)
11455 return StmtError();
11457 DSAStack
->setParentHasScanDirective(StartLoc
);
11458 return OMPScanDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
);
11461 StmtResult
Sema::ActOnOpenMPOrderedDirective(ArrayRef
<OMPClause
*> Clauses
,
11463 SourceLocation StartLoc
,
11464 SourceLocation EndLoc
) {
11465 const OMPClause
*DependFound
= nullptr;
11466 const OMPClause
*DependSourceClause
= nullptr;
11467 const OMPClause
*DependSinkClause
= nullptr;
11468 const OMPClause
*DoacrossFound
= nullptr;
11469 const OMPClause
*DoacrossSourceClause
= nullptr;
11470 const OMPClause
*DoacrossSinkClause
= nullptr;
11471 bool ErrorFound
= false;
11472 const OMPThreadsClause
*TC
= nullptr;
11473 const OMPSIMDClause
*SC
= nullptr;
11474 for (const OMPClause
*C
: Clauses
) {
11475 auto DOC
= dyn_cast
<OMPDoacrossClause
>(C
);
11476 auto DC
= dyn_cast
<OMPDependClause
>(C
);
11478 DependFound
= DC
? C
: nullptr;
11479 DoacrossFound
= DOC
? C
: nullptr;
11480 OMPDoacrossKind ODK
;
11481 if ((DC
&& DC
->getDependencyKind() == OMPC_DEPEND_source
) ||
11482 (DOC
&& (ODK
.isSource(DOC
)))) {
11483 if ((DC
&& DependSourceClause
) || (DOC
&& DoacrossSourceClause
)) {
11484 Diag(C
->getBeginLoc(), diag::err_omp_more_one_clause
)
11485 << getOpenMPDirectiveName(OMPD_ordered
)
11486 << getOpenMPClauseName(DC
? OMPC_depend
: OMPC_doacross
) << 2;
11490 DependSourceClause
= C
;
11492 DoacrossSourceClause
= C
;
11494 if ((DC
&& DependSinkClause
) || (DOC
&& DoacrossSinkClause
)) {
11495 Diag(C
->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed
)
11496 << (DC
? "depend" : "doacross") << 0;
11499 } else if ((DC
&& DC
->getDependencyKind() == OMPC_DEPEND_sink
) ||
11500 (DOC
&& (ODK
.isSink(DOC
) || ODK
.isSinkIter(DOC
)))) {
11501 if (DependSourceClause
|| DoacrossSourceClause
) {
11502 Diag(C
->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed
)
11503 << (DC
? "depend" : "doacross") << 1;
11507 DependSinkClause
= C
;
11509 DoacrossSinkClause
= C
;
11511 } else if (C
->getClauseKind() == OMPC_threads
) {
11512 TC
= cast
<OMPThreadsClause
>(C
);
11513 } else if (C
->getClauseKind() == OMPC_simd
) {
11514 SC
= cast
<OMPSIMDClause
>(C
);
11517 if (!ErrorFound
&& !SC
&&
11518 isOpenMPSimdDirective(DSAStack
->getParentDirective())) {
11519 // OpenMP [2.8.1,simd Construct, Restrictions]
11520 // An ordered construct with the simd clause is the only OpenMP construct
11521 // that can appear in the simd region.
11522 Diag(StartLoc
, diag::err_omp_prohibited_region_simd
)
11523 << (LangOpts
.OpenMP
>= 50 ? 1 : 0);
11525 } else if ((DependFound
|| DoacrossFound
) && (TC
|| SC
)) {
11526 SourceLocation Loc
=
11527 DependFound
? DependFound
->getBeginLoc() : DoacrossFound
->getBeginLoc();
11528 Diag(Loc
, diag::err_omp_depend_clause_thread_simd
)
11529 << getOpenMPClauseName(DependFound
? OMPC_depend
: OMPC_doacross
)
11530 << getOpenMPClauseName(TC
? TC
->getClauseKind() : SC
->getClauseKind());
11532 } else if ((DependFound
|| DoacrossFound
) &&
11533 !DSAStack
->getParentOrderedRegionParam().first
) {
11534 SourceLocation Loc
=
11535 DependFound
? DependFound
->getBeginLoc() : DoacrossFound
->getBeginLoc();
11536 Diag(Loc
, diag::err_omp_ordered_directive_without_param
)
11537 << getOpenMPClauseName(DependFound
? OMPC_depend
: OMPC_doacross
);
11539 } else if (TC
|| Clauses
.empty()) {
11540 if (const Expr
*Param
= DSAStack
->getParentOrderedRegionParam().first
) {
11541 SourceLocation ErrLoc
= TC
? TC
->getBeginLoc() : StartLoc
;
11542 Diag(ErrLoc
, diag::err_omp_ordered_directive_with_param
)
11543 << (TC
!= nullptr);
11544 Diag(Param
->getBeginLoc(), diag::note_omp_ordered_param
) << 1;
11548 if ((!AStmt
&& !DependFound
&& !DoacrossFound
) || ErrorFound
)
11549 return StmtError();
11551 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11552 // During execution of an iteration of a worksharing-loop or a loop nest
11553 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11554 // must not execute more than one ordered region corresponding to an ordered
11555 // construct without a depend clause.
11556 if (!DependFound
&& !DoacrossFound
) {
11557 if (DSAStack
->doesParentHasOrderedDirective()) {
11558 Diag(StartLoc
, diag::err_omp_several_directives_in_region
) << "ordered";
11559 Diag(DSAStack
->getParentOrderedDirectiveLoc(),
11560 diag::note_omp_previous_directive
)
11562 return StmtError();
11564 DSAStack
->setParentHasOrderedDirective(StartLoc
);
11568 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
11570 setFunctionHasBranchProtectedScope();
11573 return OMPOrderedDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
);
11577 /// Helper class for checking expression in 'omp atomic [update]'
11579 class OpenMPAtomicUpdateChecker
{
11580 /// Error results for atomic update expressions.
11581 enum ExprAnalysisErrorCode
{
11582 /// A statement is not an expression statement.
11584 /// Expression is not builtin binary or unary operation.
11585 NotABinaryOrUnaryExpression
,
11586 /// Unary operation is not post-/pre- increment/decrement operation.
11587 NotAnUnaryIncDecExpression
,
11588 /// An expression is not of scalar type.
11590 /// A binary operation is not an assignment operation.
11592 /// RHS part of the binary operation is not a binary expression.
11593 NotABinaryExpression
,
11594 /// RHS part is not additive/multiplicative/shift/biwise binary
11596 NotABinaryOperator
,
11597 /// RHS binary operation does not have reference to the updated LHS
11599 NotAnUpdateExpression
,
11600 /// No errors is found.
11603 /// Reference to Sema.
11605 /// A location for note diagnostics (when error is found).
11606 SourceLocation NoteLoc
;
11607 /// 'x' lvalue part of the source atomic expression.
11609 /// 'expr' rvalue part of the source atomic expression.
11611 /// Helper expression of the form
11612 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11613 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11615 /// Is 'x' a LHS in a RHS part of full update expression. It is
11616 /// important for non-associative operations.
11617 bool IsXLHSInRHSPart
;
11618 BinaryOperatorKind Op
;
11619 SourceLocation OpLoc
;
11620 /// true if the source expression is a postfix unary operation, false
11621 /// if it is a prefix unary operation.
11622 bool IsPostfixUpdate
;
11625 OpenMPAtomicUpdateChecker(Sema
&SemaRef
)
11626 : SemaRef(SemaRef
), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11627 IsXLHSInRHSPart(false), Op(BO_PtrMemD
), IsPostfixUpdate(false) {}
11628 /// Check specified statement that it is suitable for 'atomic update'
11629 /// constructs and extract 'x', 'expr' and Operation from the original
11630 /// expression. If DiagId and NoteId == 0, then only check is performed
11631 /// without error notification.
11632 /// \param DiagId Diagnostic which should be emitted if error is found.
11633 /// \param NoteId Diagnostic note for the main error message.
11634 /// \return true if statement is not an update expression, false otherwise.
11635 bool checkStatement(Stmt
*S
, unsigned DiagId
= 0, unsigned NoteId
= 0);
11636 /// Return the 'x' lvalue part of the source atomic expression.
11637 Expr
*getX() const { return X
; }
11638 /// Return the 'expr' rvalue part of the source atomic expression.
11639 Expr
*getExpr() const { return E
; }
11640 /// Return the update expression used in calculation of the updated
11641 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11642 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11643 Expr
*getUpdateExpr() const { return UpdateExpr
; }
11644 /// Return true if 'x' is LHS in RHS part of full update expression,
11645 /// false otherwise.
11646 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart
; }
11648 /// true if the source expression is a postfix unary operation, false
11649 /// if it is a prefix unary operation.
11650 bool isPostfixUpdate() const { return IsPostfixUpdate
; }
11653 bool checkBinaryOperation(BinaryOperator
*AtomicBinOp
, unsigned DiagId
= 0,
11654 unsigned NoteId
= 0);
11657 bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11658 BinaryOperator
*AtomicBinOp
, unsigned DiagId
, unsigned NoteId
) {
11659 ExprAnalysisErrorCode ErrorFound
= NoError
;
11660 SourceLocation ErrorLoc
, NoteLoc
;
11661 SourceRange ErrorRange
, NoteRange
;
11662 // Allowed constructs are:
11663 // x = x binop expr;
11664 // x = expr binop x;
11665 if (AtomicBinOp
->getOpcode() == BO_Assign
) {
11666 X
= AtomicBinOp
->getLHS();
11667 if (const auto *AtomicInnerBinOp
= dyn_cast
<BinaryOperator
>(
11668 AtomicBinOp
->getRHS()->IgnoreParenImpCasts())) {
11669 if (AtomicInnerBinOp
->isMultiplicativeOp() ||
11670 AtomicInnerBinOp
->isAdditiveOp() || AtomicInnerBinOp
->isShiftOp() ||
11671 AtomicInnerBinOp
->isBitwiseOp()) {
11672 Op
= AtomicInnerBinOp
->getOpcode();
11673 OpLoc
= AtomicInnerBinOp
->getOperatorLoc();
11674 Expr
*LHS
= AtomicInnerBinOp
->getLHS();
11675 Expr
*RHS
= AtomicInnerBinOp
->getRHS();
11676 llvm::FoldingSetNodeID XId
, LHSId
, RHSId
;
11677 X
->IgnoreParenImpCasts()->Profile(XId
, SemaRef
.getASTContext(),
11678 /*Canonical=*/true);
11679 LHS
->IgnoreParenImpCasts()->Profile(LHSId
, SemaRef
.getASTContext(),
11680 /*Canonical=*/true);
11681 RHS
->IgnoreParenImpCasts()->Profile(RHSId
, SemaRef
.getASTContext(),
11682 /*Canonical=*/true);
11683 if (XId
== LHSId
) {
11685 IsXLHSInRHSPart
= true;
11686 } else if (XId
== RHSId
) {
11688 IsXLHSInRHSPart
= false;
11690 ErrorLoc
= AtomicInnerBinOp
->getExprLoc();
11691 ErrorRange
= AtomicInnerBinOp
->getSourceRange();
11692 NoteLoc
= X
->getExprLoc();
11693 NoteRange
= X
->getSourceRange();
11694 ErrorFound
= NotAnUpdateExpression
;
11697 ErrorLoc
= AtomicInnerBinOp
->getExprLoc();
11698 ErrorRange
= AtomicInnerBinOp
->getSourceRange();
11699 NoteLoc
= AtomicInnerBinOp
->getOperatorLoc();
11700 NoteRange
= SourceRange(NoteLoc
, NoteLoc
);
11701 ErrorFound
= NotABinaryOperator
;
11704 NoteLoc
= ErrorLoc
= AtomicBinOp
->getRHS()->getExprLoc();
11705 NoteRange
= ErrorRange
= AtomicBinOp
->getRHS()->getSourceRange();
11706 ErrorFound
= NotABinaryExpression
;
11709 ErrorLoc
= AtomicBinOp
->getExprLoc();
11710 ErrorRange
= AtomicBinOp
->getSourceRange();
11711 NoteLoc
= AtomicBinOp
->getOperatorLoc();
11712 NoteRange
= SourceRange(NoteLoc
, NoteLoc
);
11713 ErrorFound
= NotAnAssignmentOp
;
11715 if (ErrorFound
!= NoError
&& DiagId
!= 0 && NoteId
!= 0) {
11716 SemaRef
.Diag(ErrorLoc
, DiagId
) << ErrorRange
;
11717 SemaRef
.Diag(NoteLoc
, NoteId
) << ErrorFound
<< NoteRange
;
11720 if (SemaRef
.CurContext
->isDependentContext())
11721 E
= X
= UpdateExpr
= nullptr;
11722 return ErrorFound
!= NoError
;
11725 bool OpenMPAtomicUpdateChecker::checkStatement(Stmt
*S
, unsigned DiagId
,
11727 ExprAnalysisErrorCode ErrorFound
= NoError
;
11728 SourceLocation ErrorLoc
, NoteLoc
;
11729 SourceRange ErrorRange
, NoteRange
;
11730 // Allowed constructs are:
11736 // x = x binop expr;
11737 // x = expr binop x;
11738 if (auto *AtomicBody
= dyn_cast
<Expr
>(S
)) {
11739 AtomicBody
= AtomicBody
->IgnoreParenImpCasts();
11740 if (AtomicBody
->getType()->isScalarType() ||
11741 AtomicBody
->isInstantiationDependent()) {
11742 if (const auto *AtomicCompAssignOp
= dyn_cast
<CompoundAssignOperator
>(
11743 AtomicBody
->IgnoreParenImpCasts())) {
11744 // Check for Compound Assignment Operation
11745 Op
= BinaryOperator::getOpForCompoundAssignment(
11746 AtomicCompAssignOp
->getOpcode());
11747 OpLoc
= AtomicCompAssignOp
->getOperatorLoc();
11748 E
= AtomicCompAssignOp
->getRHS();
11749 X
= AtomicCompAssignOp
->getLHS()->IgnoreParens();
11750 IsXLHSInRHSPart
= true;
11751 } else if (auto *AtomicBinOp
= dyn_cast
<BinaryOperator
>(
11752 AtomicBody
->IgnoreParenImpCasts())) {
11753 // Check for Binary Operation
11754 if (checkBinaryOperation(AtomicBinOp
, DiagId
, NoteId
))
11756 } else if (const auto *AtomicUnaryOp
= dyn_cast
<UnaryOperator
>(
11757 AtomicBody
->IgnoreParenImpCasts())) {
11758 // Check for Unary Operation
11759 if (AtomicUnaryOp
->isIncrementDecrementOp()) {
11760 IsPostfixUpdate
= AtomicUnaryOp
->isPostfix();
11761 Op
= AtomicUnaryOp
->isIncrementOp() ? BO_Add
: BO_Sub
;
11762 OpLoc
= AtomicUnaryOp
->getOperatorLoc();
11763 X
= AtomicUnaryOp
->getSubExpr()->IgnoreParens();
11764 E
= SemaRef
.ActOnIntegerConstant(OpLoc
, /*uint64_t Val=*/1).get();
11765 IsXLHSInRHSPart
= true;
11767 ErrorFound
= NotAnUnaryIncDecExpression
;
11768 ErrorLoc
= AtomicUnaryOp
->getExprLoc();
11769 ErrorRange
= AtomicUnaryOp
->getSourceRange();
11770 NoteLoc
= AtomicUnaryOp
->getOperatorLoc();
11771 NoteRange
= SourceRange(NoteLoc
, NoteLoc
);
11773 } else if (!AtomicBody
->isInstantiationDependent()) {
11774 ErrorFound
= NotABinaryOrUnaryExpression
;
11775 NoteLoc
= ErrorLoc
= AtomicBody
->getExprLoc();
11776 NoteRange
= ErrorRange
= AtomicBody
->getSourceRange();
11779 ErrorFound
= NotAScalarType
;
11780 NoteLoc
= ErrorLoc
= AtomicBody
->getBeginLoc();
11781 NoteRange
= ErrorRange
= SourceRange(NoteLoc
, NoteLoc
);
11784 ErrorFound
= NotAnExpression
;
11785 NoteLoc
= ErrorLoc
= S
->getBeginLoc();
11786 NoteRange
= ErrorRange
= SourceRange(NoteLoc
, NoteLoc
);
11788 if (ErrorFound
!= NoError
&& DiagId
!= 0 && NoteId
!= 0) {
11789 SemaRef
.Diag(ErrorLoc
, DiagId
) << ErrorRange
;
11790 SemaRef
.Diag(NoteLoc
, NoteId
) << ErrorFound
<< NoteRange
;
11793 if (SemaRef
.CurContext
->isDependentContext())
11794 E
= X
= UpdateExpr
= nullptr;
11795 if (ErrorFound
== NoError
&& E
&& X
) {
11796 // Build an update expression of form 'OpaqueValueExpr(x) binop
11797 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11798 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11799 auto *OVEX
= new (SemaRef
.getASTContext())
11800 OpaqueValueExpr(X
->getExprLoc(), X
->getType(), VK_PRValue
);
11801 auto *OVEExpr
= new (SemaRef
.getASTContext())
11802 OpaqueValueExpr(E
->getExprLoc(), E
->getType(), VK_PRValue
);
11803 ExprResult Update
=
11804 SemaRef
.CreateBuiltinBinOp(OpLoc
, Op
, IsXLHSInRHSPart
? OVEX
: OVEExpr
,
11805 IsXLHSInRHSPart
? OVEExpr
: OVEX
);
11806 if (Update
.isInvalid())
11808 Update
= SemaRef
.PerformImplicitConversion(Update
.get(), X
->getType(),
11810 if (Update
.isInvalid())
11812 UpdateExpr
= Update
.get();
11814 return ErrorFound
!= NoError
;
11817 /// Get the node id of the fixed point of an expression \a S.
11818 llvm::FoldingSetNodeID
getNodeId(ASTContext
&Context
, const Expr
*S
) {
11819 llvm::FoldingSetNodeID Id
;
11820 S
->IgnoreParenImpCasts()->Profile(Id
, Context
, true);
11824 /// Check if two expressions are same.
11825 bool checkIfTwoExprsAreSame(ASTContext
&Context
, const Expr
*LHS
,
11827 return getNodeId(Context
, LHS
) == getNodeId(Context
, RHS
);
11830 class OpenMPAtomicCompareChecker
{
11832 /// All kinds of errors that can occur in `atomic compare`
11834 /// Empty compound statement.
11836 /// More than one statement in a compound statement.
11838 /// Not an assignment binary operator.
11840 /// Not a conditional operator.
11842 /// Wrong false expr. According to the spec, 'x' should be at the false
11843 /// expression of a conditional expression.
11845 /// The condition of a conditional expression is not a binary operator.
11847 /// Invalid binary operator (not <, >, or ==).
11849 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11851 /// X is not a lvalue.
11855 /// Not an integer.
11857 /// 'else' statement is not expected.
11859 /// Not an equality operator.
11861 /// Invalid assignment (not v == x).
11863 /// Not if statement
11865 /// More than two statements in a compund statement.
11867 /// Not a compound statement.
11869 /// No else statement.
11877 struct ErrorInfoTy
{
11879 SourceLocation ErrorLoc
;
11880 SourceRange ErrorRange
;
11881 SourceLocation NoteLoc
;
11882 SourceRange NoteRange
;
11885 OpenMPAtomicCompareChecker(Sema
&S
) : ContextRef(S
.getASTContext()) {}
11887 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11888 bool checkStmt(Stmt
*S
, ErrorInfoTy
&ErrorInfo
);
11890 Expr
*getX() const { return X
; }
11891 Expr
*getE() const { return E
; }
11892 Expr
*getD() const { return D
; }
11893 Expr
*getCond() const { return C
; }
11894 bool isXBinopExpr() const { return IsXBinopExpr
; }
11897 /// Reference to ASTContext
11898 ASTContext
&ContextRef
;
11899 /// 'x' lvalue part of the source atomic expression.
11901 /// 'expr' or 'e' rvalue part of the source atomic expression.
11903 /// 'd' rvalue part of the source atomic expression.
11905 /// 'cond' part of the source atomic expression. It is in one of the following
11912 /// True if the cond expr is in the form of 'x ordop expr'.
11913 bool IsXBinopExpr
= true;
11915 /// Check if it is a valid conditional update statement (cond-update-stmt).
11916 bool checkCondUpdateStmt(IfStmt
*S
, ErrorInfoTy
&ErrorInfo
);
11918 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11919 bool checkCondExprStmt(Stmt
*S
, ErrorInfoTy
&ErrorInfo
);
11921 /// Check if all captured values have right type.
11922 bool checkType(ErrorInfoTy
&ErrorInfo
) const;
11924 static bool CheckValue(const Expr
*E
, ErrorInfoTy
&ErrorInfo
,
11925 bool ShouldBeLValue
, bool ShouldBeInteger
= false) {
11926 if (E
->isInstantiationDependent())
11929 if (ShouldBeLValue
&& !E
->isLValue()) {
11930 ErrorInfo
.Error
= ErrorTy::XNotLValue
;
11931 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= E
->getExprLoc();
11932 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= E
->getSourceRange();
11936 QualType QTy
= E
->getType();
11937 if (!QTy
->isScalarType()) {
11938 ErrorInfo
.Error
= ErrorTy::NotScalar
;
11939 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= E
->getExprLoc();
11940 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= E
->getSourceRange();
11943 if (ShouldBeInteger
&& !QTy
->isIntegerType()) {
11944 ErrorInfo
.Error
= ErrorTy::NotInteger
;
11945 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= E
->getExprLoc();
11946 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= E
->getSourceRange();
11954 bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt
*S
,
11955 ErrorInfoTy
&ErrorInfo
) {
11956 auto *Then
= S
->getThen();
11957 if (auto *CS
= dyn_cast
<CompoundStmt
>(Then
)) {
11958 if (CS
->body_empty()) {
11959 ErrorInfo
.Error
= ErrorTy::NoStmt
;
11960 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
11961 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= CS
->getSourceRange();
11964 if (CS
->size() > 1) {
11965 ErrorInfo
.Error
= ErrorTy::MoreThanOneStmt
;
11966 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
11967 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S
->getSourceRange();
11970 Then
= CS
->body_front();
11973 auto *BO
= dyn_cast
<BinaryOperator
>(Then
);
11975 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
11976 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Then
->getBeginLoc();
11977 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Then
->getSourceRange();
11980 if (BO
->getOpcode() != BO_Assign
) {
11981 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
11982 ErrorInfo
.ErrorLoc
= BO
->getExprLoc();
11983 ErrorInfo
.NoteLoc
= BO
->getOperatorLoc();
11984 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= BO
->getSourceRange();
11990 auto *Cond
= dyn_cast
<BinaryOperator
>(S
->getCond());
11992 ErrorInfo
.Error
= ErrorTy::NotABinaryOp
;
11993 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= S
->getCond()->getExprLoc();
11994 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S
->getCond()->getSourceRange();
11998 switch (Cond
->getOpcode()) {
12002 if (checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getLHS())) {
12003 E
= Cond
->getRHS();
12004 } else if (checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getRHS())) {
12005 E
= Cond
->getLHS();
12007 ErrorInfo
.Error
= ErrorTy::InvalidComparison
;
12008 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Cond
->getExprLoc();
12009 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Cond
->getSourceRange();
12017 if (checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getLHS()) &&
12018 checkIfTwoExprsAreSame(ContextRef
, E
, Cond
->getRHS())) {
12020 } else if (checkIfTwoExprsAreSame(ContextRef
, E
, Cond
->getLHS()) &&
12021 checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getRHS())) {
12023 IsXBinopExpr
= false;
12025 ErrorInfo
.Error
= ErrorTy::InvalidComparison
;
12026 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Cond
->getExprLoc();
12027 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Cond
->getSourceRange();
12033 ErrorInfo
.Error
= ErrorTy::InvalidBinaryOp
;
12034 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Cond
->getExprLoc();
12035 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Cond
->getSourceRange();
12039 if (S
->getElse()) {
12040 ErrorInfo
.Error
= ErrorTy::UnexpectedElse
;
12041 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= S
->getElse()->getBeginLoc();
12042 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S
->getElse()->getSourceRange();
12049 bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt
*S
,
12050 ErrorInfoTy
&ErrorInfo
) {
12051 auto *BO
= dyn_cast
<BinaryOperator
>(S
);
12053 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12054 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= S
->getBeginLoc();
12055 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S
->getSourceRange();
12058 if (BO
->getOpcode() != BO_Assign
) {
12059 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12060 ErrorInfo
.ErrorLoc
= BO
->getExprLoc();
12061 ErrorInfo
.NoteLoc
= BO
->getOperatorLoc();
12062 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= BO
->getSourceRange();
12068 auto *CO
= dyn_cast
<ConditionalOperator
>(BO
->getRHS()->IgnoreParenImpCasts());
12070 ErrorInfo
.Error
= ErrorTy::NotCondOp
;
12071 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= BO
->getRHS()->getExprLoc();
12072 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= BO
->getRHS()->getSourceRange();
12076 if (!checkIfTwoExprsAreSame(ContextRef
, X
, CO
->getFalseExpr())) {
12077 ErrorInfo
.Error
= ErrorTy::WrongFalseExpr
;
12078 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CO
->getFalseExpr()->getExprLoc();
12079 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
=
12080 CO
->getFalseExpr()->getSourceRange();
12084 auto *Cond
= dyn_cast
<BinaryOperator
>(CO
->getCond());
12086 ErrorInfo
.Error
= ErrorTy::NotABinaryOp
;
12087 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CO
->getCond()->getExprLoc();
12088 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
=
12089 CO
->getCond()->getSourceRange();
12093 switch (Cond
->getOpcode()) {
12096 D
= CO
->getTrueExpr();
12097 if (checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getLHS())) {
12098 E
= Cond
->getRHS();
12099 } else if (checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getRHS())) {
12100 E
= Cond
->getLHS();
12102 ErrorInfo
.Error
= ErrorTy::InvalidComparison
;
12103 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Cond
->getExprLoc();
12104 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Cond
->getSourceRange();
12111 E
= CO
->getTrueExpr();
12112 if (checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getLHS()) &&
12113 checkIfTwoExprsAreSame(ContextRef
, E
, Cond
->getRHS())) {
12115 } else if (checkIfTwoExprsAreSame(ContextRef
, E
, Cond
->getLHS()) &&
12116 checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getRHS())) {
12118 IsXBinopExpr
= false;
12120 ErrorInfo
.Error
= ErrorTy::InvalidComparison
;
12121 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Cond
->getExprLoc();
12122 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Cond
->getSourceRange();
12128 ErrorInfo
.Error
= ErrorTy::InvalidBinaryOp
;
12129 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Cond
->getExprLoc();
12130 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Cond
->getSourceRange();
12137 bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy
&ErrorInfo
) const {
12138 // 'x' and 'e' cannot be nullptr
12139 assert(X
&& E
&& "X and E cannot be nullptr");
12141 if (!CheckValue(X
, ErrorInfo
, true))
12144 if (!CheckValue(E
, ErrorInfo
, false))
12147 if (D
&& !CheckValue(D
, ErrorInfo
, false))
12153 bool OpenMPAtomicCompareChecker::checkStmt(
12154 Stmt
*S
, OpenMPAtomicCompareChecker::ErrorInfoTy
&ErrorInfo
) {
12155 auto *CS
= dyn_cast
<CompoundStmt
>(S
);
12157 if (CS
->body_empty()) {
12158 ErrorInfo
.Error
= ErrorTy::NoStmt
;
12159 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
12160 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= CS
->getSourceRange();
12164 if (CS
->size() != 1) {
12165 ErrorInfo
.Error
= ErrorTy::MoreThanOneStmt
;
12166 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
12167 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= CS
->getSourceRange();
12170 S
= CS
->body_front();
12175 if (auto *IS
= dyn_cast
<IfStmt
>(S
)) {
12176 // Check if the statement is in one of the following forms
12177 // (cond-update-stmt):
12178 // if (expr ordop x) { x = expr; }
12179 // if (x ordop expr) { x = expr; }
12180 // if (x == e) { x = d; }
12181 Res
= checkCondUpdateStmt(IS
, ErrorInfo
);
12183 // Check if the statement is in one of the following forms (cond-expr-stmt):
12184 // x = expr ordop x ? expr : x;
12185 // x = x ordop expr ? expr : x;
12186 // x = x == e ? d : x;
12187 Res
= checkCondExprStmt(S
, ErrorInfo
);
12193 return checkType(ErrorInfo
);
12196 class OpenMPAtomicCompareCaptureChecker final
12197 : public OpenMPAtomicCompareChecker
{
12199 OpenMPAtomicCompareCaptureChecker(Sema
&S
) : OpenMPAtomicCompareChecker(S
) {}
12201 Expr
*getV() const { return V
; }
12202 Expr
*getR() const { return R
; }
12203 bool isFailOnly() const { return IsFailOnly
; }
12204 bool isPostfixUpdate() const { return IsPostfixUpdate
; }
12206 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
12207 bool checkStmt(Stmt
*S
, ErrorInfoTy
&ErrorInfo
);
12210 bool checkType(ErrorInfoTy
&ErrorInfo
);
12212 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
12213 // form of 'conditional-update-capture-atomic' structured block on the v5.2
12215 // (1) { v = x; cond-update-stmt }
12216 // (2) { cond-update-stmt v = x; }
12217 // (3) if(x == e) { x = d; } else { v = x; }
12218 // (4) { r = x == e; if(r) { x = d; } }
12219 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
12221 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
12222 bool checkForm3(IfStmt
*S
, ErrorInfoTy
&ErrorInfo
);
12224 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
12225 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
12226 bool checkForm45(Stmt
*S
, ErrorInfoTy
&ErrorInfo
);
12228 /// 'v' lvalue part of the source atomic expression.
12230 /// 'r' lvalue part of the source atomic expression.
12232 /// If 'v' is only updated when the comparison fails.
12233 bool IsFailOnly
= false;
12234 /// If original value of 'x' must be stored in 'v', not an updated one.
12235 bool IsPostfixUpdate
= false;
12238 bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy
&ErrorInfo
) {
12239 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo
))
12242 if (V
&& !CheckValue(V
, ErrorInfo
, true))
12245 if (R
&& !CheckValue(R
, ErrorInfo
, true, true))
12251 bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt
*S
,
12252 ErrorInfoTy
&ErrorInfo
) {
12255 auto *Then
= S
->getThen();
12256 if (auto *CS
= dyn_cast
<CompoundStmt
>(Then
)) {
12257 if (CS
->body_empty()) {
12258 ErrorInfo
.Error
= ErrorTy::NoStmt
;
12259 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
12260 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= CS
->getSourceRange();
12263 if (CS
->size() > 1) {
12264 ErrorInfo
.Error
= ErrorTy::MoreThanOneStmt
;
12265 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
12266 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= CS
->getSourceRange();
12269 Then
= CS
->body_front();
12272 auto *BO
= dyn_cast
<BinaryOperator
>(Then
);
12274 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12275 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Then
->getBeginLoc();
12276 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Then
->getSourceRange();
12279 if (BO
->getOpcode() != BO_Assign
) {
12280 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12281 ErrorInfo
.ErrorLoc
= BO
->getExprLoc();
12282 ErrorInfo
.NoteLoc
= BO
->getOperatorLoc();
12283 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= BO
->getSourceRange();
12290 auto *Cond
= dyn_cast
<BinaryOperator
>(S
->getCond());
12292 ErrorInfo
.Error
= ErrorTy::NotABinaryOp
;
12293 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= S
->getCond()->getExprLoc();
12294 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S
->getCond()->getSourceRange();
12297 if (Cond
->getOpcode() != BO_EQ
) {
12298 ErrorInfo
.Error
= ErrorTy::NotEQ
;
12299 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Cond
->getExprLoc();
12300 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Cond
->getSourceRange();
12304 if (checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getLHS())) {
12305 E
= Cond
->getRHS();
12306 } else if (checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getRHS())) {
12307 E
= Cond
->getLHS();
12309 ErrorInfo
.Error
= ErrorTy::InvalidComparison
;
12310 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Cond
->getExprLoc();
12311 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Cond
->getSourceRange();
12317 if (!S
->getElse()) {
12318 ErrorInfo
.Error
= ErrorTy::NoElse
;
12319 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= S
->getBeginLoc();
12320 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S
->getSourceRange();
12324 auto *Else
= S
->getElse();
12325 if (auto *CS
= dyn_cast
<CompoundStmt
>(Else
)) {
12326 if (CS
->body_empty()) {
12327 ErrorInfo
.Error
= ErrorTy::NoStmt
;
12328 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
12329 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= CS
->getSourceRange();
12332 if (CS
->size() > 1) {
12333 ErrorInfo
.Error
= ErrorTy::MoreThanOneStmt
;
12334 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
12335 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S
->getSourceRange();
12338 Else
= CS
->body_front();
12341 auto *ElseBO
= dyn_cast
<BinaryOperator
>(Else
);
12343 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12344 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Else
->getBeginLoc();
12345 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Else
->getSourceRange();
12348 if (ElseBO
->getOpcode() != BO_Assign
) {
12349 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12350 ErrorInfo
.ErrorLoc
= ElseBO
->getExprLoc();
12351 ErrorInfo
.NoteLoc
= ElseBO
->getOperatorLoc();
12352 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= ElseBO
->getSourceRange();
12356 if (!checkIfTwoExprsAreSame(ContextRef
, X
, ElseBO
->getRHS())) {
12357 ErrorInfo
.Error
= ErrorTy::InvalidAssignment
;
12358 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= ElseBO
->getRHS()->getExprLoc();
12359 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
=
12360 ElseBO
->getRHS()->getSourceRange();
12364 V
= ElseBO
->getLHS();
12366 return checkType(ErrorInfo
);
12369 bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt
*S
,
12370 ErrorInfoTy
&ErrorInfo
) {
12371 // We don't check here as they should be already done before call this
12373 auto *CS
= cast
<CompoundStmt
>(S
);
12374 assert(CS
->size() == 2 && "CompoundStmt size is not expected");
12375 auto *S1
= cast
<BinaryOperator
>(CS
->body_front());
12376 auto *S2
= cast
<IfStmt
>(CS
->body_back());
12377 assert(S1
->getOpcode() == BO_Assign
&& "unexpected binary operator");
12379 if (!checkIfTwoExprsAreSame(ContextRef
, S1
->getLHS(), S2
->getCond())) {
12380 ErrorInfo
.Error
= ErrorTy::InvalidCondition
;
12381 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= S2
->getCond()->getExprLoc();
12382 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S1
->getLHS()->getSourceRange();
12388 auto *Then
= S2
->getThen();
12389 if (auto *ThenCS
= dyn_cast
<CompoundStmt
>(Then
)) {
12390 if (ThenCS
->body_empty()) {
12391 ErrorInfo
.Error
= ErrorTy::NoStmt
;
12392 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= ThenCS
->getBeginLoc();
12393 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= ThenCS
->getSourceRange();
12396 if (ThenCS
->size() > 1) {
12397 ErrorInfo
.Error
= ErrorTy::MoreThanOneStmt
;
12398 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= ThenCS
->getBeginLoc();
12399 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= ThenCS
->getSourceRange();
12402 Then
= ThenCS
->body_front();
12405 auto *ThenBO
= dyn_cast
<BinaryOperator
>(Then
);
12407 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12408 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= S2
->getBeginLoc();
12409 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S2
->getSourceRange();
12412 if (ThenBO
->getOpcode() != BO_Assign
) {
12413 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12414 ErrorInfo
.ErrorLoc
= ThenBO
->getExprLoc();
12415 ErrorInfo
.NoteLoc
= ThenBO
->getOperatorLoc();
12416 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= ThenBO
->getSourceRange();
12420 X
= ThenBO
->getLHS();
12421 D
= ThenBO
->getRHS();
12423 auto *BO
= cast
<BinaryOperator
>(S1
->getRHS()->IgnoreImpCasts());
12424 if (BO
->getOpcode() != BO_EQ
) {
12425 ErrorInfo
.Error
= ErrorTy::NotEQ
;
12426 ErrorInfo
.ErrorLoc
= BO
->getExprLoc();
12427 ErrorInfo
.NoteLoc
= BO
->getOperatorLoc();
12428 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= BO
->getSourceRange();
12434 if (checkIfTwoExprsAreSame(ContextRef
, X
, BO
->getLHS())) {
12436 } else if (checkIfTwoExprsAreSame(ContextRef
, X
, BO
->getRHS())) {
12439 ErrorInfo
.Error
= ErrorTy::InvalidComparison
;
12440 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= BO
->getExprLoc();
12441 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= BO
->getSourceRange();
12445 if (S2
->getElse()) {
12448 auto *Else
= S2
->getElse();
12449 if (auto *ElseCS
= dyn_cast
<CompoundStmt
>(Else
)) {
12450 if (ElseCS
->body_empty()) {
12451 ErrorInfo
.Error
= ErrorTy::NoStmt
;
12452 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= ElseCS
->getBeginLoc();
12453 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= ElseCS
->getSourceRange();
12456 if (ElseCS
->size() > 1) {
12457 ErrorInfo
.Error
= ErrorTy::MoreThanOneStmt
;
12458 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= ElseCS
->getBeginLoc();
12459 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= ElseCS
->getSourceRange();
12462 Else
= ElseCS
->body_front();
12465 auto *ElseBO
= dyn_cast
<BinaryOperator
>(Else
);
12467 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12468 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Else
->getBeginLoc();
12469 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Else
->getSourceRange();
12472 if (ElseBO
->getOpcode() != BO_Assign
) {
12473 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12474 ErrorInfo
.ErrorLoc
= ElseBO
->getExprLoc();
12475 ErrorInfo
.NoteLoc
= ElseBO
->getOperatorLoc();
12476 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= ElseBO
->getSourceRange();
12479 if (!checkIfTwoExprsAreSame(ContextRef
, X
, ElseBO
->getRHS())) {
12480 ErrorInfo
.Error
= ErrorTy::InvalidAssignment
;
12481 ErrorInfo
.ErrorLoc
= ElseBO
->getRHS()->getExprLoc();
12482 ErrorInfo
.NoteLoc
= X
->getExprLoc();
12483 ErrorInfo
.ErrorRange
= ElseBO
->getRHS()->getSourceRange();
12484 ErrorInfo
.NoteRange
= X
->getSourceRange();
12488 V
= ElseBO
->getLHS();
12491 return checkType(ErrorInfo
);
12494 bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt
*S
,
12495 ErrorInfoTy
&ErrorInfo
) {
12496 // if(x == e) { x = d; } else { v = x; }
12497 if (auto *IS
= dyn_cast
<IfStmt
>(S
))
12498 return checkForm3(IS
, ErrorInfo
);
12500 auto *CS
= dyn_cast
<CompoundStmt
>(S
);
12502 ErrorInfo
.Error
= ErrorTy::NotCompoundStmt
;
12503 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= S
->getBeginLoc();
12504 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S
->getSourceRange();
12507 if (CS
->body_empty()) {
12508 ErrorInfo
.Error
= ErrorTy::NoStmt
;
12509 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
12510 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= CS
->getSourceRange();
12514 // { if(x == e) { x = d; } else { v = x; } }
12515 if (CS
->size() == 1) {
12516 auto *IS
= dyn_cast
<IfStmt
>(CS
->body_front());
12518 ErrorInfo
.Error
= ErrorTy::NotIfStmt
;
12519 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->body_front()->getBeginLoc();
12520 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
=
12521 CS
->body_front()->getSourceRange();
12525 return checkForm3(IS
, ErrorInfo
);
12526 } else if (CS
->size() == 2) {
12527 auto *S1
= CS
->body_front();
12528 auto *S2
= CS
->body_back();
12530 Stmt
*UpdateStmt
= nullptr;
12531 Stmt
*CondUpdateStmt
= nullptr;
12532 Stmt
*CondExprStmt
= nullptr;
12534 if (auto *BO
= dyn_cast
<BinaryOperator
>(S1
)) {
12535 // It could be one of the following cases:
12536 // { v = x; cond-update-stmt }
12537 // { v = x; cond-expr-stmt }
12538 // { cond-expr-stmt; v = x; }
12540 if (isa
<BinaryOperator
>(BO
->getRHS()->IgnoreImpCasts()) ||
12541 isa
<ConditionalOperator
>(BO
->getRHS()->IgnoreImpCasts())) {
12542 // check if form 45
12543 if (isa
<IfStmt
>(S2
))
12544 return checkForm45(CS
, ErrorInfo
);
12545 // { cond-expr-stmt; v = x; }
12549 IsPostfixUpdate
= true;
12551 if (isa
<IfStmt
>(S2
)) {
12552 // { v = x; cond-update-stmt }
12553 CondUpdateStmt
= S2
;
12555 // { v = x; cond-expr-stmt }
12560 // { cond-update-stmt v = x; }
12562 CondUpdateStmt
= S1
;
12565 auto CheckCondUpdateStmt
= [this, &ErrorInfo
](Stmt
*CUS
) {
12566 auto *IS
= dyn_cast
<IfStmt
>(CUS
);
12568 ErrorInfo
.Error
= ErrorTy::NotIfStmt
;
12569 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CUS
->getBeginLoc();
12570 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= CUS
->getSourceRange();
12574 return checkCondUpdateStmt(IS
, ErrorInfo
);
12577 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12578 auto CheckUpdateStmt
= [this, &ErrorInfo
](Stmt
*US
) {
12579 auto *BO
= dyn_cast
<BinaryOperator
>(US
);
12581 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12582 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= US
->getBeginLoc();
12583 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= US
->getSourceRange();
12586 if (BO
->getOpcode() != BO_Assign
) {
12587 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12588 ErrorInfo
.ErrorLoc
= BO
->getExprLoc();
12589 ErrorInfo
.NoteLoc
= BO
->getOperatorLoc();
12590 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= BO
->getSourceRange();
12593 if (!checkIfTwoExprsAreSame(ContextRef
, this->X
, BO
->getRHS())) {
12594 ErrorInfo
.Error
= ErrorTy::InvalidAssignment
;
12595 ErrorInfo
.ErrorLoc
= BO
->getRHS()->getExprLoc();
12596 ErrorInfo
.NoteLoc
= this->X
->getExprLoc();
12597 ErrorInfo
.ErrorRange
= BO
->getRHS()->getSourceRange();
12598 ErrorInfo
.NoteRange
= this->X
->getSourceRange();
12602 this->V
= BO
->getLHS();
12607 if (CondUpdateStmt
&& !CheckCondUpdateStmt(CondUpdateStmt
))
12609 if (CondExprStmt
&& !checkCondExprStmt(CondExprStmt
, ErrorInfo
))
12611 if (!CheckUpdateStmt(UpdateStmt
))
12614 ErrorInfo
.Error
= ErrorTy::MoreThanTwoStmts
;
12615 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
12616 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= CS
->getSourceRange();
12620 return checkType(ErrorInfo
);
12624 StmtResult
Sema::ActOnOpenMPAtomicDirective(ArrayRef
<OMPClause
*> Clauses
,
12626 SourceLocation StartLoc
,
12627 SourceLocation EndLoc
) {
12628 // Register location of the first atomic directive.
12629 DSAStack
->addAtomicDirectiveLoc(StartLoc
);
12631 return StmtError();
12633 // 1.2.2 OpenMP Language Terminology
12634 // Structured block - An executable statement with a single entry at the
12635 // top and a single exit at the bottom.
12636 // The point of exit cannot be a branch out of the structured block.
12637 // longjmp() and throw() must not violate the entry/exit criteria.
12638 OpenMPClauseKind AtomicKind
= OMPC_unknown
;
12639 SourceLocation AtomicKindLoc
;
12640 OpenMPClauseKind MemOrderKind
= OMPC_unknown
;
12641 SourceLocation MemOrderLoc
;
12642 bool MutexClauseEncountered
= false;
12643 llvm::SmallSet
<OpenMPClauseKind
, 2> EncounteredAtomicKinds
;
12644 for (const OMPClause
*C
: Clauses
) {
12645 switch (C
->getClauseKind()) {
12649 MutexClauseEncountered
= true;
12652 case OMPC_compare
: {
12653 if (AtomicKind
!= OMPC_unknown
&& MutexClauseEncountered
) {
12654 Diag(C
->getBeginLoc(), diag::err_omp_atomic_several_clauses
)
12655 << SourceRange(C
->getBeginLoc(), C
->getEndLoc());
12656 Diag(AtomicKindLoc
, diag::note_omp_previous_mem_order_clause
)
12657 << getOpenMPClauseName(AtomicKind
);
12659 AtomicKind
= C
->getClauseKind();
12660 AtomicKindLoc
= C
->getBeginLoc();
12661 if (!EncounteredAtomicKinds
.insert(C
->getClauseKind()).second
) {
12662 Diag(C
->getBeginLoc(), diag::err_omp_atomic_several_clauses
)
12663 << SourceRange(C
->getBeginLoc(), C
->getEndLoc());
12664 Diag(AtomicKindLoc
, diag::note_omp_previous_mem_order_clause
)
12665 << getOpenMPClauseName(AtomicKind
);
12674 case OMPC_relaxed
: {
12675 if (MemOrderKind
!= OMPC_unknown
) {
12676 Diag(C
->getBeginLoc(), diag::err_omp_several_mem_order_clauses
)
12677 << getOpenMPDirectiveName(OMPD_atomic
) << 0
12678 << SourceRange(C
->getBeginLoc(), C
->getEndLoc());
12679 Diag(MemOrderLoc
, diag::note_omp_previous_mem_order_clause
)
12680 << getOpenMPClauseName(MemOrderKind
);
12682 MemOrderKind
= C
->getClauseKind();
12683 MemOrderLoc
= C
->getBeginLoc();
12687 // The following clauses are allowed, but we don't need to do anything here.
12691 llvm_unreachable("unknown clause is encountered");
12694 bool IsCompareCapture
= false;
12695 if (EncounteredAtomicKinds
.contains(OMPC_compare
) &&
12696 EncounteredAtomicKinds
.contains(OMPC_capture
)) {
12697 IsCompareCapture
= true;
12698 AtomicKind
= OMPC_compare
;
12700 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12701 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12703 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12705 // If atomic-clause is update or not present then memory-order-clause must not
12706 // be acq_rel or acquire.
12707 if ((AtomicKind
== OMPC_read
&&
12708 (MemOrderKind
== OMPC_acq_rel
|| MemOrderKind
== OMPC_release
)) ||
12709 ((AtomicKind
== OMPC_write
|| AtomicKind
== OMPC_update
||
12710 AtomicKind
== OMPC_unknown
) &&
12711 (MemOrderKind
== OMPC_acq_rel
|| MemOrderKind
== OMPC_acquire
))) {
12712 SourceLocation Loc
= AtomicKindLoc
;
12713 if (AtomicKind
== OMPC_unknown
)
12715 Diag(Loc
, diag::err_omp_atomic_incompatible_mem_order_clause
)
12716 << getOpenMPClauseName(AtomicKind
)
12717 << (AtomicKind
== OMPC_unknown
? 1 : 0)
12718 << getOpenMPClauseName(MemOrderKind
);
12719 Diag(MemOrderLoc
, diag::note_omp_previous_mem_order_clause
)
12720 << getOpenMPClauseName(MemOrderKind
);
12723 Stmt
*Body
= AStmt
;
12724 if (auto *EWC
= dyn_cast
<ExprWithCleanups
>(Body
))
12725 Body
= EWC
->getSubExpr();
12730 Expr
*UE
= nullptr;
12732 Expr
*CE
= nullptr;
12734 bool IsXLHSInRHSPart
= false;
12735 bool IsPostfixUpdate
= false;
12736 bool IsFailOnly
= false;
12737 // OpenMP [2.12.6, atomic Construct]
12738 // In the next expressions:
12739 // * x and v (as applicable) are both l-value expressions with scalar type.
12740 // * During the execution of an atomic region, multiple syntactic
12741 // occurrences of x must designate the same storage location.
12742 // * Neither of v and expr (as applicable) may access the storage location
12743 // designated by x.
12744 // * Neither of x and expr (as applicable) may access the storage location
12745 // designated by v.
12746 // * expr is an expression with scalar type.
12747 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12748 // * binop, binop=, ++, and -- are not overloaded operators.
12749 // * The expression x binop expr must be numerically equivalent to x binop
12750 // (expr). This requirement is satisfied if the operators in expr have
12751 // precedence greater than binop, or by using parentheses around expr or
12752 // subexpressions of expr.
12753 // * The expression expr binop x must be numerically equivalent to (expr)
12754 // binop x. This requirement is satisfied if the operators in expr have
12755 // precedence equal to or greater than binop, or by using parentheses around
12756 // expr or subexpressions of expr.
12757 // * For forms that allow multiple occurrences of x, the number of times
12758 // that x is evaluated is unspecified.
12759 if (AtomicKind
== OMPC_read
) {
12766 } ErrorFound
= NoError
;
12767 SourceLocation ErrorLoc
, NoteLoc
;
12768 SourceRange ErrorRange
, NoteRange
;
12769 // If clause is read:
12771 if (const auto *AtomicBody
= dyn_cast
<Expr
>(Body
)) {
12772 const auto *AtomicBinOp
=
12773 dyn_cast
<BinaryOperator
>(AtomicBody
->IgnoreParenImpCasts());
12774 if (AtomicBinOp
&& AtomicBinOp
->getOpcode() == BO_Assign
) {
12775 X
= AtomicBinOp
->getRHS()->IgnoreParenImpCasts();
12776 V
= AtomicBinOp
->getLHS()->IgnoreParenImpCasts();
12777 if ((X
->isInstantiationDependent() || X
->getType()->isScalarType()) &&
12778 (V
->isInstantiationDependent() || V
->getType()->isScalarType())) {
12779 if (!X
->isLValue() || !V
->isLValue()) {
12780 const Expr
*NotLValueExpr
= X
->isLValue() ? V
: X
;
12781 ErrorFound
= NotAnLValue
;
12782 ErrorLoc
= AtomicBinOp
->getExprLoc();
12783 ErrorRange
= AtomicBinOp
->getSourceRange();
12784 NoteLoc
= NotLValueExpr
->getExprLoc();
12785 NoteRange
= NotLValueExpr
->getSourceRange();
12787 } else if (!X
->isInstantiationDependent() ||
12788 !V
->isInstantiationDependent()) {
12789 const Expr
*NotScalarExpr
=
12790 (X
->isInstantiationDependent() || X
->getType()->isScalarType())
12793 ErrorFound
= NotAScalarType
;
12794 ErrorLoc
= AtomicBinOp
->getExprLoc();
12795 ErrorRange
= AtomicBinOp
->getSourceRange();
12796 NoteLoc
= NotScalarExpr
->getExprLoc();
12797 NoteRange
= NotScalarExpr
->getSourceRange();
12799 } else if (!AtomicBody
->isInstantiationDependent()) {
12800 ErrorFound
= NotAnAssignmentOp
;
12801 ErrorLoc
= AtomicBody
->getExprLoc();
12802 ErrorRange
= AtomicBody
->getSourceRange();
12803 NoteLoc
= AtomicBinOp
? AtomicBinOp
->getOperatorLoc()
12804 : AtomicBody
->getExprLoc();
12805 NoteRange
= AtomicBinOp
? AtomicBinOp
->getSourceRange()
12806 : AtomicBody
->getSourceRange();
12809 ErrorFound
= NotAnExpression
;
12810 NoteLoc
= ErrorLoc
= Body
->getBeginLoc();
12811 NoteRange
= ErrorRange
= SourceRange(NoteLoc
, NoteLoc
);
12813 if (ErrorFound
!= NoError
) {
12814 Diag(ErrorLoc
, diag::err_omp_atomic_read_not_expression_statement
)
12816 Diag(NoteLoc
, diag::note_omp_atomic_read_write
)
12817 << ErrorFound
<< NoteRange
;
12818 return StmtError();
12820 if (CurContext
->isDependentContext())
12822 } else if (AtomicKind
== OMPC_write
) {
12829 } ErrorFound
= NoError
;
12830 SourceLocation ErrorLoc
, NoteLoc
;
12831 SourceRange ErrorRange
, NoteRange
;
12832 // If clause is write:
12834 if (const auto *AtomicBody
= dyn_cast
<Expr
>(Body
)) {
12835 const auto *AtomicBinOp
=
12836 dyn_cast
<BinaryOperator
>(AtomicBody
->IgnoreParenImpCasts());
12837 if (AtomicBinOp
&& AtomicBinOp
->getOpcode() == BO_Assign
) {
12838 X
= AtomicBinOp
->getLHS();
12839 E
= AtomicBinOp
->getRHS();
12840 if ((X
->isInstantiationDependent() || X
->getType()->isScalarType()) &&
12841 (E
->isInstantiationDependent() || E
->getType()->isScalarType())) {
12842 if (!X
->isLValue()) {
12843 ErrorFound
= NotAnLValue
;
12844 ErrorLoc
= AtomicBinOp
->getExprLoc();
12845 ErrorRange
= AtomicBinOp
->getSourceRange();
12846 NoteLoc
= X
->getExprLoc();
12847 NoteRange
= X
->getSourceRange();
12849 } else if (!X
->isInstantiationDependent() ||
12850 !E
->isInstantiationDependent()) {
12851 const Expr
*NotScalarExpr
=
12852 (X
->isInstantiationDependent() || X
->getType()->isScalarType())
12855 ErrorFound
= NotAScalarType
;
12856 ErrorLoc
= AtomicBinOp
->getExprLoc();
12857 ErrorRange
= AtomicBinOp
->getSourceRange();
12858 NoteLoc
= NotScalarExpr
->getExprLoc();
12859 NoteRange
= NotScalarExpr
->getSourceRange();
12861 } else if (!AtomicBody
->isInstantiationDependent()) {
12862 ErrorFound
= NotAnAssignmentOp
;
12863 ErrorLoc
= AtomicBody
->getExprLoc();
12864 ErrorRange
= AtomicBody
->getSourceRange();
12865 NoteLoc
= AtomicBinOp
? AtomicBinOp
->getOperatorLoc()
12866 : AtomicBody
->getExprLoc();
12867 NoteRange
= AtomicBinOp
? AtomicBinOp
->getSourceRange()
12868 : AtomicBody
->getSourceRange();
12871 ErrorFound
= NotAnExpression
;
12872 NoteLoc
= ErrorLoc
= Body
->getBeginLoc();
12873 NoteRange
= ErrorRange
= SourceRange(NoteLoc
, NoteLoc
);
12875 if (ErrorFound
!= NoError
) {
12876 Diag(ErrorLoc
, diag::err_omp_atomic_write_not_expression_statement
)
12878 Diag(NoteLoc
, diag::note_omp_atomic_read_write
)
12879 << ErrorFound
<< NoteRange
;
12880 return StmtError();
12882 if (CurContext
->isDependentContext())
12884 } else if (AtomicKind
== OMPC_update
|| AtomicKind
== OMPC_unknown
) {
12885 // If clause is update:
12891 // x = x binop expr;
12892 // x = expr binop x;
12893 OpenMPAtomicUpdateChecker
Checker(*this);
12894 if (Checker
.checkStatement(
12896 (AtomicKind
== OMPC_update
)
12897 ? diag::err_omp_atomic_update_not_expression_statement
12898 : diag::err_omp_atomic_not_expression_statement
,
12899 diag::note_omp_atomic_update
))
12900 return StmtError();
12901 if (!CurContext
->isDependentContext()) {
12902 E
= Checker
.getExpr();
12903 X
= Checker
.getX();
12904 UE
= Checker
.getUpdateExpr();
12905 IsXLHSInRHSPart
= Checker
.isXLHSInRHSPart();
12907 } else if (AtomicKind
== OMPC_capture
) {
12910 NotACompoundStatement
,
12911 NotTwoSubstatements
,
12912 NotASpecificExpression
,
12914 } ErrorFound
= NoError
;
12915 SourceLocation ErrorLoc
, NoteLoc
;
12916 SourceRange ErrorRange
, NoteRange
;
12917 if (const auto *AtomicBody
= dyn_cast
<Expr
>(Body
)) {
12918 // If clause is a capture:
12923 // v = x binop= expr;
12924 // v = x = x binop expr;
12925 // v = x = expr binop x;
12926 const auto *AtomicBinOp
=
12927 dyn_cast
<BinaryOperator
>(AtomicBody
->IgnoreParenImpCasts());
12928 if (AtomicBinOp
&& AtomicBinOp
->getOpcode() == BO_Assign
) {
12929 V
= AtomicBinOp
->getLHS();
12930 Body
= AtomicBinOp
->getRHS()->IgnoreParenImpCasts();
12931 OpenMPAtomicUpdateChecker
Checker(*this);
12932 if (Checker
.checkStatement(
12933 Body
, diag::err_omp_atomic_capture_not_expression_statement
,
12934 diag::note_omp_atomic_update
))
12935 return StmtError();
12936 E
= Checker
.getExpr();
12937 X
= Checker
.getX();
12938 UE
= Checker
.getUpdateExpr();
12939 IsXLHSInRHSPart
= Checker
.isXLHSInRHSPart();
12940 IsPostfixUpdate
= Checker
.isPostfixUpdate();
12941 } else if (!AtomicBody
->isInstantiationDependent()) {
12942 ErrorLoc
= AtomicBody
->getExprLoc();
12943 ErrorRange
= AtomicBody
->getSourceRange();
12944 NoteLoc
= AtomicBinOp
? AtomicBinOp
->getOperatorLoc()
12945 : AtomicBody
->getExprLoc();
12946 NoteRange
= AtomicBinOp
? AtomicBinOp
->getSourceRange()
12947 : AtomicBody
->getSourceRange();
12948 ErrorFound
= NotAnAssignmentOp
;
12950 if (ErrorFound
!= NoError
) {
12951 Diag(ErrorLoc
, diag::err_omp_atomic_capture_not_expression_statement
)
12953 Diag(NoteLoc
, diag::note_omp_atomic_capture
) << ErrorFound
<< NoteRange
;
12954 return StmtError();
12956 if (CurContext
->isDependentContext())
12957 UE
= V
= E
= X
= nullptr;
12959 // If clause is a capture:
12960 // { v = x; x = expr; }
12965 // { v = x; x binop= expr; }
12966 // { v = x; x = x binop expr; }
12967 // { v = x; x = expr binop x; }
12972 // { x binop= expr; v = x; }
12973 // { x = x binop expr; v = x; }
12974 // { x = expr binop x; v = x; }
12975 if (auto *CS
= dyn_cast
<CompoundStmt
>(Body
)) {
12976 // Check that this is { expr1; expr2; }
12977 if (CS
->size() == 2) {
12978 Stmt
*First
= CS
->body_front();
12979 Stmt
*Second
= CS
->body_back();
12980 if (auto *EWC
= dyn_cast
<ExprWithCleanups
>(First
))
12981 First
= EWC
->getSubExpr()->IgnoreParenImpCasts();
12982 if (auto *EWC
= dyn_cast
<ExprWithCleanups
>(Second
))
12983 Second
= EWC
->getSubExpr()->IgnoreParenImpCasts();
12984 // Need to find what subexpression is 'v' and what is 'x'.
12985 OpenMPAtomicUpdateChecker
Checker(*this);
12986 bool IsUpdateExprFound
= !Checker
.checkStatement(Second
);
12987 BinaryOperator
*BinOp
= nullptr;
12988 if (IsUpdateExprFound
) {
12989 BinOp
= dyn_cast
<BinaryOperator
>(First
);
12990 IsUpdateExprFound
= BinOp
&& BinOp
->getOpcode() == BO_Assign
;
12992 if (IsUpdateExprFound
&& !CurContext
->isDependentContext()) {
12997 // { v = x; x binop= expr; }
12998 // { v = x; x = x binop expr; }
12999 // { v = x; x = expr binop x; }
13000 // Check that the first expression has form v = x.
13001 Expr
*PossibleX
= BinOp
->getRHS()->IgnoreParenImpCasts();
13002 llvm::FoldingSetNodeID XId
, PossibleXId
;
13003 Checker
.getX()->Profile(XId
, Context
, /*Canonical=*/true);
13004 PossibleX
->Profile(PossibleXId
, Context
, /*Canonical=*/true);
13005 IsUpdateExprFound
= XId
== PossibleXId
;
13006 if (IsUpdateExprFound
) {
13007 V
= BinOp
->getLHS();
13008 X
= Checker
.getX();
13009 E
= Checker
.getExpr();
13010 UE
= Checker
.getUpdateExpr();
13011 IsXLHSInRHSPart
= Checker
.isXLHSInRHSPart();
13012 IsPostfixUpdate
= true;
13015 if (!IsUpdateExprFound
) {
13016 IsUpdateExprFound
= !Checker
.checkStatement(First
);
13018 if (IsUpdateExprFound
) {
13019 BinOp
= dyn_cast
<BinaryOperator
>(Second
);
13020 IsUpdateExprFound
= BinOp
&& BinOp
->getOpcode() == BO_Assign
;
13022 if (IsUpdateExprFound
&& !CurContext
->isDependentContext()) {
13027 // { x binop= expr; v = x; }
13028 // { x = x binop expr; v = x; }
13029 // { x = expr binop x; v = x; }
13030 // Check that the second expression has form v = x.
13031 Expr
*PossibleX
= BinOp
->getRHS()->IgnoreParenImpCasts();
13032 llvm::FoldingSetNodeID XId
, PossibleXId
;
13033 Checker
.getX()->Profile(XId
, Context
, /*Canonical=*/true);
13034 PossibleX
->Profile(PossibleXId
, Context
, /*Canonical=*/true);
13035 IsUpdateExprFound
= XId
== PossibleXId
;
13036 if (IsUpdateExprFound
) {
13037 V
= BinOp
->getLHS();
13038 X
= Checker
.getX();
13039 E
= Checker
.getExpr();
13040 UE
= Checker
.getUpdateExpr();
13041 IsXLHSInRHSPart
= Checker
.isXLHSInRHSPart();
13042 IsPostfixUpdate
= false;
13046 if (!IsUpdateExprFound
) {
13047 // { v = x; x = expr; }
13048 auto *FirstExpr
= dyn_cast
<Expr
>(First
);
13049 auto *SecondExpr
= dyn_cast
<Expr
>(Second
);
13050 if (!FirstExpr
|| !SecondExpr
||
13051 !(FirstExpr
->isInstantiationDependent() ||
13052 SecondExpr
->isInstantiationDependent())) {
13053 auto *FirstBinOp
= dyn_cast
<BinaryOperator
>(First
);
13054 if (!FirstBinOp
|| FirstBinOp
->getOpcode() != BO_Assign
) {
13055 ErrorFound
= NotAnAssignmentOp
;
13056 NoteLoc
= ErrorLoc
= FirstBinOp
? FirstBinOp
->getOperatorLoc()
13057 : First
->getBeginLoc();
13058 NoteRange
= ErrorRange
= FirstBinOp
13059 ? FirstBinOp
->getSourceRange()
13060 : SourceRange(ErrorLoc
, ErrorLoc
);
13062 auto *SecondBinOp
= dyn_cast
<BinaryOperator
>(Second
);
13063 if (!SecondBinOp
|| SecondBinOp
->getOpcode() != BO_Assign
) {
13064 ErrorFound
= NotAnAssignmentOp
;
13065 NoteLoc
= ErrorLoc
= SecondBinOp
13066 ? SecondBinOp
->getOperatorLoc()
13067 : Second
->getBeginLoc();
13068 NoteRange
= ErrorRange
=
13069 SecondBinOp
? SecondBinOp
->getSourceRange()
13070 : SourceRange(ErrorLoc
, ErrorLoc
);
13072 Expr
*PossibleXRHSInFirst
=
13073 FirstBinOp
->getRHS()->IgnoreParenImpCasts();
13074 Expr
*PossibleXLHSInSecond
=
13075 SecondBinOp
->getLHS()->IgnoreParenImpCasts();
13076 llvm::FoldingSetNodeID X1Id
, X2Id
;
13077 PossibleXRHSInFirst
->Profile(X1Id
, Context
,
13078 /*Canonical=*/true);
13079 PossibleXLHSInSecond
->Profile(X2Id
, Context
,
13080 /*Canonical=*/true);
13081 IsUpdateExprFound
= X1Id
== X2Id
;
13082 if (IsUpdateExprFound
) {
13083 V
= FirstBinOp
->getLHS();
13084 X
= SecondBinOp
->getLHS();
13085 E
= SecondBinOp
->getRHS();
13087 IsXLHSInRHSPart
= false;
13088 IsPostfixUpdate
= true;
13090 ErrorFound
= NotASpecificExpression
;
13091 ErrorLoc
= FirstBinOp
->getExprLoc();
13092 ErrorRange
= FirstBinOp
->getSourceRange();
13093 NoteLoc
= SecondBinOp
->getLHS()->getExprLoc();
13094 NoteRange
= SecondBinOp
->getRHS()->getSourceRange();
13101 NoteLoc
= ErrorLoc
= Body
->getBeginLoc();
13102 NoteRange
= ErrorRange
=
13103 SourceRange(Body
->getBeginLoc(), Body
->getBeginLoc());
13104 ErrorFound
= NotTwoSubstatements
;
13107 NoteLoc
= ErrorLoc
= Body
->getBeginLoc();
13108 NoteRange
= ErrorRange
=
13109 SourceRange(Body
->getBeginLoc(), Body
->getBeginLoc());
13110 ErrorFound
= NotACompoundStatement
;
13113 if (ErrorFound
!= NoError
) {
13114 Diag(ErrorLoc
, diag::err_omp_atomic_capture_not_compound_statement
)
13116 Diag(NoteLoc
, diag::note_omp_atomic_capture
) << ErrorFound
<< NoteRange
;
13117 return StmtError();
13119 if (CurContext
->isDependentContext())
13120 UE
= V
= E
= X
= nullptr;
13121 } else if (AtomicKind
== OMPC_compare
) {
13122 if (IsCompareCapture
) {
13123 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo
;
13124 OpenMPAtomicCompareCaptureChecker
Checker(*this);
13125 if (!Checker
.checkStmt(Body
, ErrorInfo
)) {
13126 Diag(ErrorInfo
.ErrorLoc
, diag::err_omp_atomic_compare_capture
)
13127 << ErrorInfo
.ErrorRange
;
13128 Diag(ErrorInfo
.NoteLoc
, diag::note_omp_atomic_compare
)
13129 << ErrorInfo
.Error
<< ErrorInfo
.NoteRange
;
13130 return StmtError();
13132 X
= Checker
.getX();
13133 E
= Checker
.getE();
13134 D
= Checker
.getD();
13135 CE
= Checker
.getCond();
13136 V
= Checker
.getV();
13137 R
= Checker
.getR();
13138 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13139 IsXLHSInRHSPart
= Checker
.isXBinopExpr();
13140 IsFailOnly
= Checker
.isFailOnly();
13141 IsPostfixUpdate
= Checker
.isPostfixUpdate();
13143 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo
;
13144 OpenMPAtomicCompareChecker
Checker(*this);
13145 if (!Checker
.checkStmt(Body
, ErrorInfo
)) {
13146 Diag(ErrorInfo
.ErrorLoc
, diag::err_omp_atomic_compare
)
13147 << ErrorInfo
.ErrorRange
;
13148 Diag(ErrorInfo
.NoteLoc
, diag::note_omp_atomic_compare
)
13149 << ErrorInfo
.Error
<< ErrorInfo
.NoteRange
;
13150 return StmtError();
13152 X
= Checker
.getX();
13153 E
= Checker
.getE();
13154 D
= Checker
.getD();
13155 CE
= Checker
.getCond();
13156 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13157 IsXLHSInRHSPart
= Checker
.isXBinopExpr();
13161 setFunctionHasBranchProtectedScope();
13163 return OMPAtomicDirective::Create(
13164 Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
13165 {X
, V
, R
, E
, UE
, D
, CE
, IsXLHSInRHSPart
, IsPostfixUpdate
, IsFailOnly
});
13168 StmtResult
Sema::ActOnOpenMPTargetDirective(ArrayRef
<OMPClause
*> Clauses
,
13170 SourceLocation StartLoc
,
13171 SourceLocation EndLoc
) {
13173 return StmtError();
13175 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13176 // 1.2.2 OpenMP Language Terminology
13177 // Structured block - An executable statement with a single entry at the
13178 // top and a single exit at the bottom.
13179 // The point of exit cannot be a branch out of the structured block.
13180 // longjmp() and throw() must not violate the entry/exit criteria.
13181 CS
->getCapturedDecl()->setNothrow();
13182 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target
);
13183 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
13184 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
13185 // 1.2.2 OpenMP Language Terminology
13186 // Structured block - An executable statement with a single entry at the
13187 // top and a single exit at the bottom.
13188 // The point of exit cannot be a branch out of the structured block.
13189 // longjmp() and throw() must not violate the entry/exit criteria.
13190 CS
->getCapturedDecl()->setNothrow();
13193 // OpenMP [2.16, Nesting of Regions]
13194 // If specified, a teams construct must be contained within a target
13195 // construct. That target construct must contain no statements or directives
13196 // outside of the teams construct.
13197 if (DSAStack
->hasInnerTeamsRegion()) {
13198 const Stmt
*S
= CS
->IgnoreContainers(/*IgnoreCaptured=*/true);
13199 bool OMPTeamsFound
= true;
13200 if (const auto *CS
= dyn_cast
<CompoundStmt
>(S
)) {
13201 auto I
= CS
->body_begin();
13202 while (I
!= CS
->body_end()) {
13203 const auto *OED
= dyn_cast
<OMPExecutableDirective
>(*I
);
13204 if (!OED
|| !isOpenMPTeamsDirective(OED
->getDirectiveKind()) ||
13207 OMPTeamsFound
= false;
13212 assert(I
!= CS
->body_end() && "Not found statement");
13215 const auto *OED
= dyn_cast
<OMPExecutableDirective
>(S
);
13216 OMPTeamsFound
= OED
&& isOpenMPTeamsDirective(OED
->getDirectiveKind());
13218 if (!OMPTeamsFound
) {
13219 Diag(StartLoc
, diag::err_omp_target_contains_not_only_teams
);
13220 Diag(DSAStack
->getInnerTeamsRegionLoc(),
13221 diag::note_omp_nested_teams_construct_here
);
13222 Diag(S
->getBeginLoc(), diag::note_omp_nested_statement_here
)
13223 << isa
<OMPExecutableDirective
>(S
);
13224 return StmtError();
13228 setFunctionHasBranchProtectedScope();
13230 return OMPTargetDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
);
13234 Sema::ActOnOpenMPTargetParallelDirective(ArrayRef
<OMPClause
*> Clauses
,
13235 Stmt
*AStmt
, SourceLocation StartLoc
,
13236 SourceLocation EndLoc
) {
13238 return StmtError();
13240 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13241 // 1.2.2 OpenMP Language Terminology
13242 // Structured block - An executable statement with a single entry at the
13243 // top and a single exit at the bottom.
13244 // The point of exit cannot be a branch out of the structured block.
13245 // longjmp() and throw() must not violate the entry/exit criteria.
13246 CS
->getCapturedDecl()->setNothrow();
13247 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_parallel
);
13248 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
13249 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
13250 // 1.2.2 OpenMP Language Terminology
13251 // Structured block - An executable statement with a single entry at the
13252 // top and a single exit at the bottom.
13253 // The point of exit cannot be a branch out of the structured block.
13254 // longjmp() and throw() must not violate the entry/exit criteria.
13255 CS
->getCapturedDecl()->setNothrow();
13258 setFunctionHasBranchProtectedScope();
13260 return OMPTargetParallelDirective::Create(
13261 Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
13262 DSAStack
->getTaskgroupReductionRef(), DSAStack
->isCancelRegion());
13265 StmtResult
Sema::ActOnOpenMPTargetParallelForDirective(
13266 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13267 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13269 return StmtError();
13271 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13272 // 1.2.2 OpenMP Language Terminology
13273 // Structured block - An executable statement with a single entry at the
13274 // top and a single exit at the bottom.
13275 // The point of exit cannot be a branch out of the structured block.
13276 // longjmp() and throw() must not violate the entry/exit criteria.
13277 CS
->getCapturedDecl()->setNothrow();
13278 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_parallel_for
);
13279 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
13280 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
13281 // 1.2.2 OpenMP Language Terminology
13282 // Structured block - An executable statement with a single entry at the
13283 // top and a single exit at the bottom.
13284 // The point of exit cannot be a branch out of the structured block.
13285 // longjmp() and throw() must not violate the entry/exit criteria.
13286 CS
->getCapturedDecl()->setNothrow();
13289 OMPLoopBasedDirective::HelperExprs B
;
13290 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13291 // define the nested loops number.
13292 unsigned NestedLoopCount
=
13293 checkOpenMPLoop(OMPD_target_parallel_for
, getCollapseNumberExpr(Clauses
),
13294 getOrderedNumberExpr(Clauses
), CS
, *this, *DSAStack
,
13295 VarsWithImplicitDSA
, B
);
13296 if (NestedLoopCount
== 0)
13297 return StmtError();
13299 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13300 "omp target parallel for loop exprs were not built");
13302 if (!CurContext
->isDependentContext()) {
13303 // Finalize the clauses that need pre-built expressions for CodeGen.
13304 for (OMPClause
*C
: Clauses
) {
13305 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
13306 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
13307 B
.NumIterations
, *this, CurScope
,
13309 return StmtError();
13313 setFunctionHasBranchProtectedScope();
13314 return OMPTargetParallelForDirective::Create(
13315 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
,
13316 DSAStack
->getTaskgroupReductionRef(), DSAStack
->isCancelRegion());
13319 /// Check for existence of a map clause in the list of clauses.
13320 static bool hasClauses(ArrayRef
<OMPClause
*> Clauses
,
13321 const OpenMPClauseKind K
) {
13322 return llvm::any_of(
13323 Clauses
, [K
](const OMPClause
*C
) { return C
->getClauseKind() == K
; });
13326 template <typename
... Params
>
13327 static bool hasClauses(ArrayRef
<OMPClause
*> Clauses
, const OpenMPClauseKind K
,
13328 const Params
... ClauseTypes
) {
13329 return hasClauses(Clauses
, K
) || hasClauses(Clauses
, ClauseTypes
...);
13332 /// Check if the variables in the mapping clause are externally visible.
13333 static bool isClauseMappable(ArrayRef
<OMPClause
*> Clauses
) {
13334 for (const OMPClause
*C
: Clauses
) {
13335 if (auto *TC
= dyn_cast
<OMPToClause
>(C
))
13336 return llvm::all_of(TC
->all_decls(), [](ValueDecl
*VD
) {
13337 return !VD
|| !VD
->hasAttr
<OMPDeclareTargetDeclAttr
>() ||
13338 (VD
->isExternallyVisible() &&
13339 VD
->getVisibility() != HiddenVisibility
);
13341 else if (auto *FC
= dyn_cast
<OMPFromClause
>(C
))
13342 return llvm::all_of(FC
->all_decls(), [](ValueDecl
*VD
) {
13343 return !VD
|| !VD
->hasAttr
<OMPDeclareTargetDeclAttr
>() ||
13344 (VD
->isExternallyVisible() &&
13345 VD
->getVisibility() != HiddenVisibility
);
13352 StmtResult
Sema::ActOnOpenMPTargetDataDirective(ArrayRef
<OMPClause
*> Clauses
,
13354 SourceLocation StartLoc
,
13355 SourceLocation EndLoc
) {
13357 return StmtError();
13359 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13361 // OpenMP [2.12.2, target data Construct, Restrictions]
13362 // At least one map, use_device_addr or use_device_ptr clause must appear on
13364 if (!hasClauses(Clauses
, OMPC_map
, OMPC_use_device_ptr
) &&
13365 (LangOpts
.OpenMP
< 50 || !hasClauses(Clauses
, OMPC_use_device_addr
))) {
13366 StringRef Expected
;
13367 if (LangOpts
.OpenMP
< 50)
13368 Expected
= "'map' or 'use_device_ptr'";
13370 Expected
= "'map', 'use_device_ptr', or 'use_device_addr'";
13371 Diag(StartLoc
, diag::err_omp_no_clause_for_directive
)
13372 << Expected
<< getOpenMPDirectiveName(OMPD_target_data
);
13373 return StmtError();
13376 setFunctionHasBranchProtectedScope();
13378 return OMPTargetDataDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
,
13383 Sema::ActOnOpenMPTargetEnterDataDirective(ArrayRef
<OMPClause
*> Clauses
,
13384 SourceLocation StartLoc
,
13385 SourceLocation EndLoc
, Stmt
*AStmt
) {
13387 return StmtError();
13389 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13390 // 1.2.2 OpenMP Language Terminology
13391 // Structured block - An executable statement with a single entry at the
13392 // top and a single exit at the bottom.
13393 // The point of exit cannot be a branch out of the structured block.
13394 // longjmp() and throw() must not violate the entry/exit criteria.
13395 CS
->getCapturedDecl()->setNothrow();
13396 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_enter_data
);
13397 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
13398 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
13399 // 1.2.2 OpenMP Language Terminology
13400 // Structured block - An executable statement with a single entry at the
13401 // top and a single exit at the bottom.
13402 // The point of exit cannot be a branch out of the structured block.
13403 // longjmp() and throw() must not violate the entry/exit criteria.
13404 CS
->getCapturedDecl()->setNothrow();
13407 // OpenMP [2.10.2, Restrictions, p. 99]
13408 // At least one map clause must appear on the directive.
13409 if (!hasClauses(Clauses
, OMPC_map
)) {
13410 Diag(StartLoc
, diag::err_omp_no_clause_for_directive
)
13411 << "'map'" << getOpenMPDirectiveName(OMPD_target_enter_data
);
13412 return StmtError();
13415 return OMPTargetEnterDataDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
,
13420 Sema::ActOnOpenMPTargetExitDataDirective(ArrayRef
<OMPClause
*> Clauses
,
13421 SourceLocation StartLoc
,
13422 SourceLocation EndLoc
, Stmt
*AStmt
) {
13424 return StmtError();
13426 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13427 // 1.2.2 OpenMP Language Terminology
13428 // Structured block - An executable statement with a single entry at the
13429 // top and a single exit at the bottom.
13430 // The point of exit cannot be a branch out of the structured block.
13431 // longjmp() and throw() must not violate the entry/exit criteria.
13432 CS
->getCapturedDecl()->setNothrow();
13433 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_exit_data
);
13434 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
13435 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
13436 // 1.2.2 OpenMP Language Terminology
13437 // Structured block - An executable statement with a single entry at the
13438 // top and a single exit at the bottom.
13439 // The point of exit cannot be a branch out of the structured block.
13440 // longjmp() and throw() must not violate the entry/exit criteria.
13441 CS
->getCapturedDecl()->setNothrow();
13444 // OpenMP [2.10.3, Restrictions, p. 102]
13445 // At least one map clause must appear on the directive.
13446 if (!hasClauses(Clauses
, OMPC_map
)) {
13447 Diag(StartLoc
, diag::err_omp_no_clause_for_directive
)
13448 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data
);
13449 return StmtError();
13452 return OMPTargetExitDataDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
,
13456 StmtResult
Sema::ActOnOpenMPTargetUpdateDirective(ArrayRef
<OMPClause
*> Clauses
,
13457 SourceLocation StartLoc
,
13458 SourceLocation EndLoc
,
13461 return StmtError();
13463 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13464 // 1.2.2 OpenMP Language Terminology
13465 // Structured block - An executable statement with a single entry at the
13466 // top and a single exit at the bottom.
13467 // The point of exit cannot be a branch out of the structured block.
13468 // longjmp() and throw() must not violate the entry/exit criteria.
13469 CS
->getCapturedDecl()->setNothrow();
13470 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_update
);
13471 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
13472 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
13473 // 1.2.2 OpenMP Language Terminology
13474 // Structured block - An executable statement with a single entry at the
13475 // top and a single exit at the bottom.
13476 // The point of exit cannot be a branch out of the structured block.
13477 // longjmp() and throw() must not violate the entry/exit criteria.
13478 CS
->getCapturedDecl()->setNothrow();
13481 if (!hasClauses(Clauses
, OMPC_to
, OMPC_from
)) {
13482 Diag(StartLoc
, diag::err_omp_at_least_one_motion_clause_required
);
13483 return StmtError();
13486 if (!isClauseMappable(Clauses
)) {
13487 Diag(StartLoc
, diag::err_omp_cannot_update_with_internal_linkage
);
13488 return StmtError();
13491 return OMPTargetUpdateDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
,
13495 StmtResult
Sema::ActOnOpenMPTeamsDirective(ArrayRef
<OMPClause
*> Clauses
,
13496 Stmt
*AStmt
, SourceLocation StartLoc
,
13497 SourceLocation EndLoc
) {
13499 return StmtError();
13501 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13502 if (getLangOpts().HIP
&& (DSAStack
->getParentDirective() == OMPD_target
))
13503 Diag(StartLoc
, diag::warn_hip_omp_target_directives
);
13505 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13506 // 1.2.2 OpenMP Language Terminology
13507 // Structured block - An executable statement with a single entry at the
13508 // top and a single exit at the bottom.
13509 // The point of exit cannot be a branch out of the structured block.
13510 // longjmp() and throw() must not violate the entry/exit criteria.
13511 CS
->getCapturedDecl()->setNothrow();
13513 setFunctionHasBranchProtectedScope();
13515 DSAStack
->setParentTeamsRegionLoc(StartLoc
);
13517 return OMPTeamsDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
);
13521 Sema::ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc
,
13522 SourceLocation EndLoc
,
13523 OpenMPDirectiveKind CancelRegion
) {
13524 if (DSAStack
->isParentNowaitRegion()) {
13525 Diag(StartLoc
, diag::err_omp_parent_cancel_region_nowait
) << 0;
13526 return StmtError();
13528 if (DSAStack
->isParentOrderedRegion()) {
13529 Diag(StartLoc
, diag::err_omp_parent_cancel_region_ordered
) << 0;
13530 return StmtError();
13532 return OMPCancellationPointDirective::Create(Context
, StartLoc
, EndLoc
,
13536 StmtResult
Sema::ActOnOpenMPCancelDirective(ArrayRef
<OMPClause
*> Clauses
,
13537 SourceLocation StartLoc
,
13538 SourceLocation EndLoc
,
13539 OpenMPDirectiveKind CancelRegion
) {
13540 if (DSAStack
->isParentNowaitRegion()) {
13541 Diag(StartLoc
, diag::err_omp_parent_cancel_region_nowait
) << 1;
13542 return StmtError();
13544 if (DSAStack
->isParentOrderedRegion()) {
13545 Diag(StartLoc
, diag::err_omp_parent_cancel_region_ordered
) << 1;
13546 return StmtError();
13548 DSAStack
->setParentCancelRegion(/*Cancel=*/true);
13549 return OMPCancelDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
,
13553 static bool checkReductionClauseWithNogroup(Sema
&S
,
13554 ArrayRef
<OMPClause
*> Clauses
) {
13555 const OMPClause
*ReductionClause
= nullptr;
13556 const OMPClause
*NogroupClause
= nullptr;
13557 for (const OMPClause
*C
: Clauses
) {
13558 if (C
->getClauseKind() == OMPC_reduction
) {
13559 ReductionClause
= C
;
13564 if (C
->getClauseKind() == OMPC_nogroup
) {
13566 if (ReductionClause
)
13571 if (ReductionClause
&& NogroupClause
) {
13572 S
.Diag(ReductionClause
->getBeginLoc(), diag::err_omp_reduction_with_nogroup
)
13573 << SourceRange(NogroupClause
->getBeginLoc(),
13574 NogroupClause
->getEndLoc());
13580 StmtResult
Sema::ActOnOpenMPTaskLoopDirective(
13581 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13582 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13584 return StmtError();
13586 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13587 OMPLoopBasedDirective::HelperExprs B
;
13588 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13589 // define the nested loops number.
13590 unsigned NestedLoopCount
=
13591 checkOpenMPLoop(OMPD_taskloop
, getCollapseNumberExpr(Clauses
),
13592 /*OrderedLoopCountExpr=*/nullptr, AStmt
, *this, *DSAStack
,
13593 VarsWithImplicitDSA
, B
);
13594 if (NestedLoopCount
== 0)
13595 return StmtError();
13597 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13598 "omp for loop exprs were not built");
13600 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13601 // The grainsize clause and num_tasks clause are mutually exclusive and may
13602 // not appear on the same taskloop directive.
13603 if (checkMutuallyExclusiveClauses(*this, Clauses
,
13604 {OMPC_grainsize
, OMPC_num_tasks
}))
13605 return StmtError();
13606 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13607 // If a reduction clause is present on the taskloop directive, the nogroup
13608 // clause must not be specified.
13609 if (checkReductionClauseWithNogroup(*this, Clauses
))
13610 return StmtError();
13612 setFunctionHasBranchProtectedScope();
13613 return OMPTaskLoopDirective::Create(Context
, StartLoc
, EndLoc
,
13614 NestedLoopCount
, Clauses
, AStmt
, B
,
13615 DSAStack
->isCancelRegion());
13618 StmtResult
Sema::ActOnOpenMPTaskLoopSimdDirective(
13619 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13620 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13622 return StmtError();
13624 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13625 OMPLoopBasedDirective::HelperExprs B
;
13626 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13627 // define the nested loops number.
13628 unsigned NestedLoopCount
=
13629 checkOpenMPLoop(OMPD_taskloop_simd
, getCollapseNumberExpr(Clauses
),
13630 /*OrderedLoopCountExpr=*/nullptr, AStmt
, *this, *DSAStack
,
13631 VarsWithImplicitDSA
, B
);
13632 if (NestedLoopCount
== 0)
13633 return StmtError();
13635 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13636 "omp for loop exprs were not built");
13638 if (!CurContext
->isDependentContext()) {
13639 // Finalize the clauses that need pre-built expressions for CodeGen.
13640 for (OMPClause
*C
: Clauses
) {
13641 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
13642 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
13643 B
.NumIterations
, *this, CurScope
,
13645 return StmtError();
13649 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13650 // The grainsize clause and num_tasks clause are mutually exclusive and may
13651 // not appear on the same taskloop directive.
13652 if (checkMutuallyExclusiveClauses(*this, Clauses
,
13653 {OMPC_grainsize
, OMPC_num_tasks
}))
13654 return StmtError();
13655 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13656 // If a reduction clause is present on the taskloop directive, the nogroup
13657 // clause must not be specified.
13658 if (checkReductionClauseWithNogroup(*this, Clauses
))
13659 return StmtError();
13660 if (checkSimdlenSafelenSpecified(*this, Clauses
))
13661 return StmtError();
13663 setFunctionHasBranchProtectedScope();
13664 return OMPTaskLoopSimdDirective::Create(Context
, StartLoc
, EndLoc
,
13665 NestedLoopCount
, Clauses
, AStmt
, B
);
13668 StmtResult
Sema::ActOnOpenMPMasterTaskLoopDirective(
13669 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13670 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13672 return StmtError();
13674 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13675 OMPLoopBasedDirective::HelperExprs B
;
13676 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13677 // define the nested loops number.
13678 unsigned NestedLoopCount
=
13679 checkOpenMPLoop(OMPD_master_taskloop
, getCollapseNumberExpr(Clauses
),
13680 /*OrderedLoopCountExpr=*/nullptr, AStmt
, *this, *DSAStack
,
13681 VarsWithImplicitDSA
, B
);
13682 if (NestedLoopCount
== 0)
13683 return StmtError();
13685 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13686 "omp for loop exprs were not built");
13688 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13689 // The grainsize clause and num_tasks clause are mutually exclusive and may
13690 // not appear on the same taskloop directive.
13691 if (checkMutuallyExclusiveClauses(*this, Clauses
,
13692 {OMPC_grainsize
, OMPC_num_tasks
}))
13693 return StmtError();
13694 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13695 // If a reduction clause is present on the taskloop directive, the nogroup
13696 // clause must not be specified.
13697 if (checkReductionClauseWithNogroup(*this, Clauses
))
13698 return StmtError();
13700 setFunctionHasBranchProtectedScope();
13701 return OMPMasterTaskLoopDirective::Create(Context
, StartLoc
, EndLoc
,
13702 NestedLoopCount
, Clauses
, AStmt
, B
,
13703 DSAStack
->isCancelRegion());
13706 StmtResult
Sema::ActOnOpenMPMaskedTaskLoopDirective(
13707 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13708 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13710 return StmtError();
13712 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13713 OMPLoopBasedDirective::HelperExprs B
;
13714 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13715 // define the nested loops number.
13716 unsigned NestedLoopCount
=
13717 checkOpenMPLoop(OMPD_masked_taskloop
, getCollapseNumberExpr(Clauses
),
13718 /*OrderedLoopCountExpr=*/nullptr, AStmt
, *this, *DSAStack
,
13719 VarsWithImplicitDSA
, B
);
13720 if (NestedLoopCount
== 0)
13721 return StmtError();
13723 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13724 "omp for loop exprs were not built");
13726 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13727 // The grainsize clause and num_tasks clause are mutually exclusive and may
13728 // not appear on the same taskloop directive.
13729 if (checkMutuallyExclusiveClauses(*this, Clauses
,
13730 {OMPC_grainsize
, OMPC_num_tasks
}))
13731 return StmtError();
13732 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13733 // If a reduction clause is present on the taskloop directive, the nogroup
13734 // clause must not be specified.
13735 if (checkReductionClauseWithNogroup(*this, Clauses
))
13736 return StmtError();
13738 setFunctionHasBranchProtectedScope();
13739 return OMPMaskedTaskLoopDirective::Create(Context
, StartLoc
, EndLoc
,
13740 NestedLoopCount
, Clauses
, AStmt
, B
,
13741 DSAStack
->isCancelRegion());
13744 StmtResult
Sema::ActOnOpenMPMasterTaskLoopSimdDirective(
13745 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13746 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13748 return StmtError();
13750 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13751 OMPLoopBasedDirective::HelperExprs B
;
13752 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13753 // define the nested loops number.
13754 unsigned NestedLoopCount
=
13755 checkOpenMPLoop(OMPD_master_taskloop_simd
, getCollapseNumberExpr(Clauses
),
13756 /*OrderedLoopCountExpr=*/nullptr, AStmt
, *this, *DSAStack
,
13757 VarsWithImplicitDSA
, B
);
13758 if (NestedLoopCount
== 0)
13759 return StmtError();
13761 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13762 "omp for loop exprs were not built");
13764 if (!CurContext
->isDependentContext()) {
13765 // Finalize the clauses that need pre-built expressions for CodeGen.
13766 for (OMPClause
*C
: Clauses
) {
13767 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
13768 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
13769 B
.NumIterations
, *this, CurScope
,
13771 return StmtError();
13775 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13776 // The grainsize clause and num_tasks clause are mutually exclusive and may
13777 // not appear on the same taskloop directive.
13778 if (checkMutuallyExclusiveClauses(*this, Clauses
,
13779 {OMPC_grainsize
, OMPC_num_tasks
}))
13780 return StmtError();
13781 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13782 // If a reduction clause is present on the taskloop directive, the nogroup
13783 // clause must not be specified.
13784 if (checkReductionClauseWithNogroup(*this, Clauses
))
13785 return StmtError();
13786 if (checkSimdlenSafelenSpecified(*this, Clauses
))
13787 return StmtError();
13789 setFunctionHasBranchProtectedScope();
13790 return OMPMasterTaskLoopSimdDirective::Create(
13791 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
13794 StmtResult
Sema::ActOnOpenMPMaskedTaskLoopSimdDirective(
13795 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13796 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13798 return StmtError();
13800 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13801 OMPLoopBasedDirective::HelperExprs B
;
13802 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13803 // define the nested loops number.
13804 unsigned NestedLoopCount
=
13805 checkOpenMPLoop(OMPD_masked_taskloop_simd
, getCollapseNumberExpr(Clauses
),
13806 /*OrderedLoopCountExpr=*/nullptr, AStmt
, *this, *DSAStack
,
13807 VarsWithImplicitDSA
, B
);
13808 if (NestedLoopCount
== 0)
13809 return StmtError();
13811 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13812 "omp for loop exprs were not built");
13814 if (!CurContext
->isDependentContext()) {
13815 // Finalize the clauses that need pre-built expressions for CodeGen.
13816 for (OMPClause
*C
: Clauses
) {
13817 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
13818 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
13819 B
.NumIterations
, *this, CurScope
,
13821 return StmtError();
13825 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13826 // The grainsize clause and num_tasks clause are mutually exclusive and may
13827 // not appear on the same taskloop directive.
13828 if (checkMutuallyExclusiveClauses(*this, Clauses
,
13829 {OMPC_grainsize
, OMPC_num_tasks
}))
13830 return StmtError();
13831 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13832 // If a reduction clause is present on the taskloop directive, the nogroup
13833 // clause must not be specified.
13834 if (checkReductionClauseWithNogroup(*this, Clauses
))
13835 return StmtError();
13836 if (checkSimdlenSafelenSpecified(*this, Clauses
))
13837 return StmtError();
13839 setFunctionHasBranchProtectedScope();
13840 return OMPMaskedTaskLoopSimdDirective::Create(
13841 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
13844 StmtResult
Sema::ActOnOpenMPParallelMasterTaskLoopDirective(
13845 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13846 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13848 return StmtError();
13850 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13851 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13852 // 1.2.2 OpenMP Language Terminology
13853 // Structured block - An executable statement with a single entry at the
13854 // top and a single exit at the bottom.
13855 // The point of exit cannot be a branch out of the structured block.
13856 // longjmp() and throw() must not violate the entry/exit criteria.
13857 CS
->getCapturedDecl()->setNothrow();
13858 for (int ThisCaptureLevel
=
13859 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop
);
13860 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
13861 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
13862 // 1.2.2 OpenMP Language Terminology
13863 // Structured block - An executable statement with a single entry at the
13864 // top and a single exit at the bottom.
13865 // The point of exit cannot be a branch out of the structured block.
13866 // longjmp() and throw() must not violate the entry/exit criteria.
13867 CS
->getCapturedDecl()->setNothrow();
13870 OMPLoopBasedDirective::HelperExprs B
;
13871 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13872 // define the nested loops number.
13873 unsigned NestedLoopCount
= checkOpenMPLoop(
13874 OMPD_parallel_master_taskloop
, getCollapseNumberExpr(Clauses
),
13875 /*OrderedLoopCountExpr=*/nullptr, CS
, *this, *DSAStack
,
13876 VarsWithImplicitDSA
, B
);
13877 if (NestedLoopCount
== 0)
13878 return StmtError();
13880 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13881 "omp for loop exprs were not built");
13883 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13884 // The grainsize clause and num_tasks clause are mutually exclusive and may
13885 // not appear on the same taskloop directive.
13886 if (checkMutuallyExclusiveClauses(*this, Clauses
,
13887 {OMPC_grainsize
, OMPC_num_tasks
}))
13888 return StmtError();
13889 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13890 // If a reduction clause is present on the taskloop directive, the nogroup
13891 // clause must not be specified.
13892 if (checkReductionClauseWithNogroup(*this, Clauses
))
13893 return StmtError();
13895 setFunctionHasBranchProtectedScope();
13896 return OMPParallelMasterTaskLoopDirective::Create(
13897 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
,
13898 DSAStack
->isCancelRegion());
13901 StmtResult
Sema::ActOnOpenMPParallelMaskedTaskLoopDirective(
13902 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13903 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13905 return StmtError();
13907 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13908 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13909 // 1.2.2 OpenMP Language Terminology
13910 // Structured block - An executable statement with a single entry at the
13911 // top and a single exit at the bottom.
13912 // The point of exit cannot be a branch out of the structured block.
13913 // longjmp() and throw() must not violate the entry/exit criteria.
13914 CS
->getCapturedDecl()->setNothrow();
13915 for (int ThisCaptureLevel
=
13916 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop
);
13917 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
13918 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
13919 // 1.2.2 OpenMP Language Terminology
13920 // Structured block - An executable statement with a single entry at the
13921 // top and a single exit at the bottom.
13922 // The point of exit cannot be a branch out of the structured block.
13923 // longjmp() and throw() must not violate the entry/exit criteria.
13924 CS
->getCapturedDecl()->setNothrow();
13927 OMPLoopBasedDirective::HelperExprs B
;
13928 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13929 // define the nested loops number.
13930 unsigned NestedLoopCount
= checkOpenMPLoop(
13931 OMPD_parallel_masked_taskloop
, getCollapseNumberExpr(Clauses
),
13932 /*OrderedLoopCountExpr=*/nullptr, CS
, *this, *DSAStack
,
13933 VarsWithImplicitDSA
, B
);
13934 if (NestedLoopCount
== 0)
13935 return StmtError();
13937 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13938 "omp for loop exprs were not built");
13940 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13941 // The grainsize clause and num_tasks clause are mutually exclusive and may
13942 // not appear on the same taskloop directive.
13943 if (checkMutuallyExclusiveClauses(*this, Clauses
,
13944 {OMPC_grainsize
, OMPC_num_tasks
}))
13945 return StmtError();
13946 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13947 // If a reduction clause is present on the taskloop directive, the nogroup
13948 // clause must not be specified.
13949 if (checkReductionClauseWithNogroup(*this, Clauses
))
13950 return StmtError();
13952 setFunctionHasBranchProtectedScope();
13953 return OMPParallelMaskedTaskLoopDirective::Create(
13954 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
,
13955 DSAStack
->isCancelRegion());
13958 StmtResult
Sema::ActOnOpenMPParallelMasterTaskLoopSimdDirective(
13959 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13960 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13962 return StmtError();
13964 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13965 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13966 // 1.2.2 OpenMP Language Terminology
13967 // Structured block - An executable statement with a single entry at the
13968 // top and a single exit at the bottom.
13969 // The point of exit cannot be a branch out of the structured block.
13970 // longjmp() and throw() must not violate the entry/exit criteria.
13971 CS
->getCapturedDecl()->setNothrow();
13972 for (int ThisCaptureLevel
=
13973 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop_simd
);
13974 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
13975 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
13976 // 1.2.2 OpenMP Language Terminology
13977 // Structured block - An executable statement with a single entry at the
13978 // top and a single exit at the bottom.
13979 // The point of exit cannot be a branch out of the structured block.
13980 // longjmp() and throw() must not violate the entry/exit criteria.
13981 CS
->getCapturedDecl()->setNothrow();
13984 OMPLoopBasedDirective::HelperExprs B
;
13985 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13986 // define the nested loops number.
13987 unsigned NestedLoopCount
= checkOpenMPLoop(
13988 OMPD_parallel_master_taskloop_simd
, getCollapseNumberExpr(Clauses
),
13989 /*OrderedLoopCountExpr=*/nullptr, CS
, *this, *DSAStack
,
13990 VarsWithImplicitDSA
, B
);
13991 if (NestedLoopCount
== 0)
13992 return StmtError();
13994 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13995 "omp for loop exprs were not built");
13997 if (!CurContext
->isDependentContext()) {
13998 // Finalize the clauses that need pre-built expressions for CodeGen.
13999 for (OMPClause
*C
: Clauses
) {
14000 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14001 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14002 B
.NumIterations
, *this, CurScope
,
14004 return StmtError();
14008 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14009 // The grainsize clause and num_tasks clause are mutually exclusive and may
14010 // not appear on the same taskloop directive.
14011 if (checkMutuallyExclusiveClauses(*this, Clauses
,
14012 {OMPC_grainsize
, OMPC_num_tasks
}))
14013 return StmtError();
14014 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14015 // If a reduction clause is present on the taskloop directive, the nogroup
14016 // clause must not be specified.
14017 if (checkReductionClauseWithNogroup(*this, Clauses
))
14018 return StmtError();
14019 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14020 return StmtError();
14022 setFunctionHasBranchProtectedScope();
14023 return OMPParallelMasterTaskLoopSimdDirective::Create(
14024 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14027 StmtResult
Sema::ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
14028 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14029 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14031 return StmtError();
14033 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
14034 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14035 // 1.2.2 OpenMP Language Terminology
14036 // Structured block - An executable statement with a single entry at the
14037 // top and a single exit at the bottom.
14038 // The point of exit cannot be a branch out of the structured block.
14039 // longjmp() and throw() must not violate the entry/exit criteria.
14040 CS
->getCapturedDecl()->setNothrow();
14041 for (int ThisCaptureLevel
=
14042 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop_simd
);
14043 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14044 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14045 // 1.2.2 OpenMP Language Terminology
14046 // Structured block - An executable statement with a single entry at the
14047 // top and a single exit at the bottom.
14048 // The point of exit cannot be a branch out of the structured block.
14049 // longjmp() and throw() must not violate the entry/exit criteria.
14050 CS
->getCapturedDecl()->setNothrow();
14053 OMPLoopBasedDirective::HelperExprs B
;
14054 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14055 // define the nested loops number.
14056 unsigned NestedLoopCount
= checkOpenMPLoop(
14057 OMPD_parallel_masked_taskloop_simd
, getCollapseNumberExpr(Clauses
),
14058 /*OrderedLoopCountExpr=*/nullptr, CS
, *this, *DSAStack
,
14059 VarsWithImplicitDSA
, B
);
14060 if (NestedLoopCount
== 0)
14061 return StmtError();
14063 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14064 "omp for loop exprs were not built");
14066 if (!CurContext
->isDependentContext()) {
14067 // Finalize the clauses that need pre-built expressions for CodeGen.
14068 for (OMPClause
*C
: Clauses
) {
14069 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14070 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14071 B
.NumIterations
, *this, CurScope
,
14073 return StmtError();
14077 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14078 // The grainsize clause and num_tasks clause are mutually exclusive and may
14079 // not appear on the same taskloop directive.
14080 if (checkMutuallyExclusiveClauses(*this, Clauses
,
14081 {OMPC_grainsize
, OMPC_num_tasks
}))
14082 return StmtError();
14083 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14084 // If a reduction clause is present on the taskloop directive, the nogroup
14085 // clause must not be specified.
14086 if (checkReductionClauseWithNogroup(*this, Clauses
))
14087 return StmtError();
14088 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14089 return StmtError();
14091 setFunctionHasBranchProtectedScope();
14092 return OMPParallelMaskedTaskLoopSimdDirective::Create(
14093 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14096 StmtResult
Sema::ActOnOpenMPDistributeDirective(
14097 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14098 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14100 return StmtError();
14102 if (!checkLastPrivateForMappedDirectives(Clauses
))
14103 return StmtError();
14105 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
14106 OMPLoopBasedDirective::HelperExprs B
;
14107 // In presence of clause 'collapse' with number of loops, it will
14108 // define the nested loops number.
14109 unsigned NestedLoopCount
=
14110 checkOpenMPLoop(OMPD_distribute
, getCollapseNumberExpr(Clauses
),
14111 nullptr /*ordered not a clause on distribute*/, AStmt
,
14112 *this, *DSAStack
, VarsWithImplicitDSA
, B
);
14113 if (NestedLoopCount
== 0)
14114 return StmtError();
14116 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14117 "omp for loop exprs were not built");
14119 setFunctionHasBranchProtectedScope();
14120 auto *DistributeDirective
= OMPDistributeDirective::Create(
14121 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
,
14122 DSAStack
->getMappedDirective());
14123 return DistributeDirective
;
14126 StmtResult
Sema::ActOnOpenMPDistributeParallelForDirective(
14127 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14128 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14130 return StmtError();
14132 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14133 // 1.2.2 OpenMP Language Terminology
14134 // Structured block - An executable statement with a single entry at the
14135 // top and a single exit at the bottom.
14136 // The point of exit cannot be a branch out of the structured block.
14137 // longjmp() and throw() must not violate the entry/exit criteria.
14138 CS
->getCapturedDecl()->setNothrow();
14139 for (int ThisCaptureLevel
=
14140 getOpenMPCaptureLevels(OMPD_distribute_parallel_for
);
14141 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14142 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14143 // 1.2.2 OpenMP Language Terminology
14144 // Structured block - An executable statement with a single entry at the
14145 // top and a single exit at the bottom.
14146 // The point of exit cannot be a branch out of the structured block.
14147 // longjmp() and throw() must not violate the entry/exit criteria.
14148 CS
->getCapturedDecl()->setNothrow();
14151 OMPLoopBasedDirective::HelperExprs B
;
14152 // In presence of clause 'collapse' with number of loops, it will
14153 // define the nested loops number.
14154 unsigned NestedLoopCount
= checkOpenMPLoop(
14155 OMPD_distribute_parallel_for
, getCollapseNumberExpr(Clauses
),
14156 nullptr /*ordered not a clause on distribute*/, CS
, *this, *DSAStack
,
14157 VarsWithImplicitDSA
, B
);
14158 if (NestedLoopCount
== 0)
14159 return StmtError();
14161 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14162 "omp for loop exprs were not built");
14164 setFunctionHasBranchProtectedScope();
14165 return OMPDistributeParallelForDirective::Create(
14166 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
,
14167 DSAStack
->getTaskgroupReductionRef(), DSAStack
->isCancelRegion());
14170 StmtResult
Sema::ActOnOpenMPDistributeParallelForSimdDirective(
14171 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14172 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14174 return StmtError();
14176 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14177 // 1.2.2 OpenMP Language Terminology
14178 // Structured block - An executable statement with a single entry at the
14179 // top and a single exit at the bottom.
14180 // The point of exit cannot be a branch out of the structured block.
14181 // longjmp() and throw() must not violate the entry/exit criteria.
14182 CS
->getCapturedDecl()->setNothrow();
14183 for (int ThisCaptureLevel
=
14184 getOpenMPCaptureLevels(OMPD_distribute_parallel_for_simd
);
14185 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14186 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14187 // 1.2.2 OpenMP Language Terminology
14188 // Structured block - An executable statement with a single entry at the
14189 // top and a single exit at the bottom.
14190 // The point of exit cannot be a branch out of the structured block.
14191 // longjmp() and throw() must not violate the entry/exit criteria.
14192 CS
->getCapturedDecl()->setNothrow();
14195 OMPLoopBasedDirective::HelperExprs B
;
14196 // In presence of clause 'collapse' with number of loops, it will
14197 // define the nested loops number.
14198 unsigned NestedLoopCount
= checkOpenMPLoop(
14199 OMPD_distribute_parallel_for_simd
, getCollapseNumberExpr(Clauses
),
14200 nullptr /*ordered not a clause on distribute*/, CS
, *this, *DSAStack
,
14201 VarsWithImplicitDSA
, B
);
14202 if (NestedLoopCount
== 0)
14203 return StmtError();
14205 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14206 "omp for loop exprs were not built");
14208 if (!CurContext
->isDependentContext()) {
14209 // Finalize the clauses that need pre-built expressions for CodeGen.
14210 for (OMPClause
*C
: Clauses
) {
14211 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14212 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14213 B
.NumIterations
, *this, CurScope
,
14215 return StmtError();
14219 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14220 return StmtError();
14222 setFunctionHasBranchProtectedScope();
14223 return OMPDistributeParallelForSimdDirective::Create(
14224 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14227 StmtResult
Sema::ActOnOpenMPDistributeSimdDirective(
14228 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14229 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14231 return StmtError();
14233 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14234 // 1.2.2 OpenMP Language Terminology
14235 // Structured block - An executable statement with a single entry at the
14236 // top and a single exit at the bottom.
14237 // The point of exit cannot be a branch out of the structured block.
14238 // longjmp() and throw() must not violate the entry/exit criteria.
14239 CS
->getCapturedDecl()->setNothrow();
14240 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_distribute_simd
);
14241 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14242 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14243 // 1.2.2 OpenMP Language Terminology
14244 // Structured block - An executable statement with a single entry at the
14245 // top and a single exit at the bottom.
14246 // The point of exit cannot be a branch out of the structured block.
14247 // longjmp() and throw() must not violate the entry/exit criteria.
14248 CS
->getCapturedDecl()->setNothrow();
14251 OMPLoopBasedDirective::HelperExprs B
;
14252 // In presence of clause 'collapse' with number of loops, it will
14253 // define the nested loops number.
14254 unsigned NestedLoopCount
=
14255 checkOpenMPLoop(OMPD_distribute_simd
, getCollapseNumberExpr(Clauses
),
14256 nullptr /*ordered not a clause on distribute*/, CS
, *this,
14257 *DSAStack
, VarsWithImplicitDSA
, B
);
14258 if (NestedLoopCount
== 0)
14259 return StmtError();
14261 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14262 "omp for loop exprs were not built");
14264 if (!CurContext
->isDependentContext()) {
14265 // Finalize the clauses that need pre-built expressions for CodeGen.
14266 for (OMPClause
*C
: Clauses
) {
14267 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14268 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14269 B
.NumIterations
, *this, CurScope
,
14271 return StmtError();
14275 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14276 return StmtError();
14278 setFunctionHasBranchProtectedScope();
14279 return OMPDistributeSimdDirective::Create(Context
, StartLoc
, EndLoc
,
14280 NestedLoopCount
, Clauses
, AStmt
, B
);
14283 StmtResult
Sema::ActOnOpenMPTargetParallelForSimdDirective(
14284 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14285 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14287 return StmtError();
14289 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14290 // 1.2.2 OpenMP Language Terminology
14291 // Structured block - An executable statement with a single entry at the
14292 // top and a single exit at the bottom.
14293 // The point of exit cannot be a branch out of the structured block.
14294 // longjmp() and throw() must not violate the entry/exit criteria.
14295 CS
->getCapturedDecl()->setNothrow();
14296 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_parallel_for
);
14297 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14298 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14299 // 1.2.2 OpenMP Language Terminology
14300 // Structured block - An executable statement with a single entry at the
14301 // top and a single exit at the bottom.
14302 // The point of exit cannot be a branch out of the structured block.
14303 // longjmp() and throw() must not violate the entry/exit criteria.
14304 CS
->getCapturedDecl()->setNothrow();
14307 OMPLoopBasedDirective::HelperExprs B
;
14308 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14309 // define the nested loops number.
14310 unsigned NestedLoopCount
= checkOpenMPLoop(
14311 OMPD_target_parallel_for_simd
, getCollapseNumberExpr(Clauses
),
14312 getOrderedNumberExpr(Clauses
), CS
, *this, *DSAStack
, VarsWithImplicitDSA
,
14314 if (NestedLoopCount
== 0)
14315 return StmtError();
14317 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14318 "omp target parallel for simd loop exprs were not built");
14320 if (!CurContext
->isDependentContext()) {
14321 // Finalize the clauses that need pre-built expressions for CodeGen.
14322 for (OMPClause
*C
: Clauses
) {
14323 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14324 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14325 B
.NumIterations
, *this, CurScope
,
14327 return StmtError();
14330 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14331 return StmtError();
14333 setFunctionHasBranchProtectedScope();
14334 return OMPTargetParallelForSimdDirective::Create(
14335 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14338 StmtResult
Sema::ActOnOpenMPTargetSimdDirective(
14339 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14340 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14342 return StmtError();
14344 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14345 // 1.2.2 OpenMP Language Terminology
14346 // Structured block - An executable statement with a single entry at the
14347 // top and a single exit at the bottom.
14348 // The point of exit cannot be a branch out of the structured block.
14349 // longjmp() and throw() must not violate the entry/exit criteria.
14350 CS
->getCapturedDecl()->setNothrow();
14351 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_simd
);
14352 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14353 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14354 // 1.2.2 OpenMP Language Terminology
14355 // Structured block - An executable statement with a single entry at the
14356 // top and a single exit at the bottom.
14357 // The point of exit cannot be a branch out of the structured block.
14358 // longjmp() and throw() must not violate the entry/exit criteria.
14359 CS
->getCapturedDecl()->setNothrow();
14362 OMPLoopBasedDirective::HelperExprs B
;
14363 // In presence of clause 'collapse' with number of loops, it will define the
14364 // nested loops number.
14365 unsigned NestedLoopCount
=
14366 checkOpenMPLoop(OMPD_target_simd
, getCollapseNumberExpr(Clauses
),
14367 getOrderedNumberExpr(Clauses
), CS
, *this, *DSAStack
,
14368 VarsWithImplicitDSA
, B
);
14369 if (NestedLoopCount
== 0)
14370 return StmtError();
14372 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14373 "omp target simd loop exprs were not built");
14375 if (!CurContext
->isDependentContext()) {
14376 // Finalize the clauses that need pre-built expressions for CodeGen.
14377 for (OMPClause
*C
: Clauses
) {
14378 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14379 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14380 B
.NumIterations
, *this, CurScope
,
14382 return StmtError();
14386 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14387 return StmtError();
14389 setFunctionHasBranchProtectedScope();
14390 return OMPTargetSimdDirective::Create(Context
, StartLoc
, EndLoc
,
14391 NestedLoopCount
, Clauses
, AStmt
, B
);
14394 StmtResult
Sema::ActOnOpenMPTeamsDistributeDirective(
14395 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14396 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14398 return StmtError();
14400 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14401 // 1.2.2 OpenMP Language Terminology
14402 // Structured block - An executable statement with a single entry at the
14403 // top and a single exit at the bottom.
14404 // The point of exit cannot be a branch out of the structured block.
14405 // longjmp() and throw() must not violate the entry/exit criteria.
14406 CS
->getCapturedDecl()->setNothrow();
14407 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_teams_distribute
);
14408 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14409 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14410 // 1.2.2 OpenMP Language Terminology
14411 // Structured block - An executable statement with a single entry at the
14412 // top and a single exit at the bottom.
14413 // The point of exit cannot be a branch out of the structured block.
14414 // longjmp() and throw() must not violate the entry/exit criteria.
14415 CS
->getCapturedDecl()->setNothrow();
14418 OMPLoopBasedDirective::HelperExprs B
;
14419 // In presence of clause 'collapse' with number of loops, it will
14420 // define the nested loops number.
14421 unsigned NestedLoopCount
=
14422 checkOpenMPLoop(OMPD_teams_distribute
, getCollapseNumberExpr(Clauses
),
14423 nullptr /*ordered not a clause on distribute*/, CS
, *this,
14424 *DSAStack
, VarsWithImplicitDSA
, B
);
14425 if (NestedLoopCount
== 0)
14426 return StmtError();
14428 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14429 "omp teams distribute loop exprs were not built");
14431 setFunctionHasBranchProtectedScope();
14433 DSAStack
->setParentTeamsRegionLoc(StartLoc
);
14435 return OMPTeamsDistributeDirective::Create(
14436 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14439 StmtResult
Sema::ActOnOpenMPTeamsDistributeSimdDirective(
14440 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14441 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14443 return StmtError();
14445 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14446 // 1.2.2 OpenMP Language Terminology
14447 // Structured block - An executable statement with a single entry at the
14448 // top and a single exit at the bottom.
14449 // The point of exit cannot be a branch out of the structured block.
14450 // longjmp() and throw() must not violate the entry/exit criteria.
14451 CS
->getCapturedDecl()->setNothrow();
14452 for (int ThisCaptureLevel
=
14453 getOpenMPCaptureLevels(OMPD_teams_distribute_simd
);
14454 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14455 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14456 // 1.2.2 OpenMP Language Terminology
14457 // Structured block - An executable statement with a single entry at the
14458 // top and a single exit at the bottom.
14459 // The point of exit cannot be a branch out of the structured block.
14460 // longjmp() and throw() must not violate the entry/exit criteria.
14461 CS
->getCapturedDecl()->setNothrow();
14464 OMPLoopBasedDirective::HelperExprs B
;
14465 // In presence of clause 'collapse' with number of loops, it will
14466 // define the nested loops number.
14467 unsigned NestedLoopCount
= checkOpenMPLoop(
14468 OMPD_teams_distribute_simd
, getCollapseNumberExpr(Clauses
),
14469 nullptr /*ordered not a clause on distribute*/, CS
, *this, *DSAStack
,
14470 VarsWithImplicitDSA
, B
);
14472 if (NestedLoopCount
== 0)
14473 return StmtError();
14475 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14476 "omp teams distribute simd loop exprs were not built");
14478 if (!CurContext
->isDependentContext()) {
14479 // Finalize the clauses that need pre-built expressions for CodeGen.
14480 for (OMPClause
*C
: Clauses
) {
14481 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14482 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14483 B
.NumIterations
, *this, CurScope
,
14485 return StmtError();
14489 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14490 return StmtError();
14492 setFunctionHasBranchProtectedScope();
14494 DSAStack
->setParentTeamsRegionLoc(StartLoc
);
14496 return OMPTeamsDistributeSimdDirective::Create(
14497 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14500 StmtResult
Sema::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
14501 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14502 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14504 return StmtError();
14506 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14507 // 1.2.2 OpenMP Language Terminology
14508 // Structured block - An executable statement with a single entry at the
14509 // top and a single exit at the bottom.
14510 // The point of exit cannot be a branch out of the structured block.
14511 // longjmp() and throw() must not violate the entry/exit criteria.
14512 CS
->getCapturedDecl()->setNothrow();
14514 for (int ThisCaptureLevel
=
14515 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for_simd
);
14516 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14517 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14518 // 1.2.2 OpenMP Language Terminology
14519 // Structured block - An executable statement with a single entry at the
14520 // top and a single exit at the bottom.
14521 // The point of exit cannot be a branch out of the structured block.
14522 // longjmp() and throw() must not violate the entry/exit criteria.
14523 CS
->getCapturedDecl()->setNothrow();
14526 OMPLoopBasedDirective::HelperExprs B
;
14527 // In presence of clause 'collapse' with number of loops, it will
14528 // define the nested loops number.
14529 unsigned NestedLoopCount
= checkOpenMPLoop(
14530 OMPD_teams_distribute_parallel_for_simd
, getCollapseNumberExpr(Clauses
),
14531 nullptr /*ordered not a clause on distribute*/, CS
, *this, *DSAStack
,
14532 VarsWithImplicitDSA
, B
);
14534 if (NestedLoopCount
== 0)
14535 return StmtError();
14537 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14538 "omp for loop exprs were not built");
14540 if (!CurContext
->isDependentContext()) {
14541 // Finalize the clauses that need pre-built expressions for CodeGen.
14542 for (OMPClause
*C
: Clauses
) {
14543 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14544 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14545 B
.NumIterations
, *this, CurScope
,
14547 return StmtError();
14551 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14552 return StmtError();
14554 setFunctionHasBranchProtectedScope();
14556 DSAStack
->setParentTeamsRegionLoc(StartLoc
);
14558 return OMPTeamsDistributeParallelForSimdDirective::Create(
14559 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14562 StmtResult
Sema::ActOnOpenMPTeamsDistributeParallelForDirective(
14563 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14564 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14566 return StmtError();
14568 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14569 // 1.2.2 OpenMP Language Terminology
14570 // Structured block - An executable statement with a single entry at the
14571 // top and a single exit at the bottom.
14572 // The point of exit cannot be a branch out of the structured block.
14573 // longjmp() and throw() must not violate the entry/exit criteria.
14574 CS
->getCapturedDecl()->setNothrow();
14576 for (int ThisCaptureLevel
=
14577 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for
);
14578 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14579 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14580 // 1.2.2 OpenMP Language Terminology
14581 // Structured block - An executable statement with a single entry at the
14582 // top and a single exit at the bottom.
14583 // The point of exit cannot be a branch out of the structured block.
14584 // longjmp() and throw() must not violate the entry/exit criteria.
14585 CS
->getCapturedDecl()->setNothrow();
14588 OMPLoopBasedDirective::HelperExprs B
;
14589 // In presence of clause 'collapse' with number of loops, it will
14590 // define the nested loops number.
14591 unsigned NestedLoopCount
= checkOpenMPLoop(
14592 OMPD_teams_distribute_parallel_for
, getCollapseNumberExpr(Clauses
),
14593 nullptr /*ordered not a clause on distribute*/, CS
, *this, *DSAStack
,
14594 VarsWithImplicitDSA
, B
);
14596 if (NestedLoopCount
== 0)
14597 return StmtError();
14599 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14600 "omp for loop exprs were not built");
14602 setFunctionHasBranchProtectedScope();
14604 DSAStack
->setParentTeamsRegionLoc(StartLoc
);
14606 return OMPTeamsDistributeParallelForDirective::Create(
14607 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
,
14608 DSAStack
->getTaskgroupReductionRef(), DSAStack
->isCancelRegion());
14611 StmtResult
Sema::ActOnOpenMPTargetTeamsDirective(ArrayRef
<OMPClause
*> Clauses
,
14613 SourceLocation StartLoc
,
14614 SourceLocation EndLoc
) {
14616 return StmtError();
14618 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14619 // 1.2.2 OpenMP Language Terminology
14620 // Structured block - An executable statement with a single entry at the
14621 // top and a single exit at the bottom.
14622 // The point of exit cannot be a branch out of the structured block.
14623 // longjmp() and throw() must not violate the entry/exit criteria.
14624 CS
->getCapturedDecl()->setNothrow();
14626 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_teams
);
14627 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14628 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14629 // 1.2.2 OpenMP Language Terminology
14630 // Structured block - An executable statement with a single entry at the
14631 // top and a single exit at the bottom.
14632 // The point of exit cannot be a branch out of the structured block.
14633 // longjmp() and throw() must not violate the entry/exit criteria.
14634 CS
->getCapturedDecl()->setNothrow();
14636 setFunctionHasBranchProtectedScope();
14638 return OMPTargetTeamsDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
,
14642 StmtResult
Sema::ActOnOpenMPTargetTeamsDistributeDirective(
14643 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14644 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14646 return StmtError();
14648 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14649 // 1.2.2 OpenMP Language Terminology
14650 // Structured block - An executable statement with a single entry at the
14651 // top and a single exit at the bottom.
14652 // The point of exit cannot be a branch out of the structured block.
14653 // longjmp() and throw() must not violate the entry/exit criteria.
14654 CS
->getCapturedDecl()->setNothrow();
14655 for (int ThisCaptureLevel
=
14656 getOpenMPCaptureLevels(OMPD_target_teams_distribute
);
14657 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14658 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14659 // 1.2.2 OpenMP Language Terminology
14660 // Structured block - An executable statement with a single entry at the
14661 // top and a single exit at the bottom.
14662 // The point of exit cannot be a branch out of the structured block.
14663 // longjmp() and throw() must not violate the entry/exit criteria.
14664 CS
->getCapturedDecl()->setNothrow();
14667 OMPLoopBasedDirective::HelperExprs B
;
14668 // In presence of clause 'collapse' with number of loops, it will
14669 // define the nested loops number.
14670 unsigned NestedLoopCount
= checkOpenMPLoop(
14671 OMPD_target_teams_distribute
, getCollapseNumberExpr(Clauses
),
14672 nullptr /*ordered not a clause on distribute*/, CS
, *this, *DSAStack
,
14673 VarsWithImplicitDSA
, B
);
14674 if (NestedLoopCount
== 0)
14675 return StmtError();
14677 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14678 "omp target teams distribute loop exprs were not built");
14680 setFunctionHasBranchProtectedScope();
14681 return OMPTargetTeamsDistributeDirective::Create(
14682 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14685 StmtResult
Sema::ActOnOpenMPTargetTeamsDistributeParallelForDirective(
14686 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14687 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14689 return StmtError();
14691 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14692 // 1.2.2 OpenMP Language Terminology
14693 // Structured block - An executable statement with a single entry at the
14694 // top and a single exit at the bottom.
14695 // The point of exit cannot be a branch out of the structured block.
14696 // longjmp() and throw() must not violate the entry/exit criteria.
14697 CS
->getCapturedDecl()->setNothrow();
14698 for (int ThisCaptureLevel
=
14699 getOpenMPCaptureLevels(OMPD_target_teams_distribute_parallel_for
);
14700 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14701 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14702 // 1.2.2 OpenMP Language Terminology
14703 // Structured block - An executable statement with a single entry at the
14704 // top and a single exit at the bottom.
14705 // The point of exit cannot be a branch out of the structured block.
14706 // longjmp() and throw() must not violate the entry/exit criteria.
14707 CS
->getCapturedDecl()->setNothrow();
14710 OMPLoopBasedDirective::HelperExprs B
;
14711 // In presence of clause 'collapse' with number of loops, it will
14712 // define the nested loops number.
14713 unsigned NestedLoopCount
= checkOpenMPLoop(
14714 OMPD_target_teams_distribute_parallel_for
, getCollapseNumberExpr(Clauses
),
14715 nullptr /*ordered not a clause on distribute*/, CS
, *this, *DSAStack
,
14716 VarsWithImplicitDSA
, B
);
14717 if (NestedLoopCount
== 0)
14718 return StmtError();
14720 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14721 "omp target teams distribute parallel for loop exprs were not built");
14723 if (!CurContext
->isDependentContext()) {
14724 // Finalize the clauses that need pre-built expressions for CodeGen.
14725 for (OMPClause
*C
: Clauses
) {
14726 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14727 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14728 B
.NumIterations
, *this, CurScope
,
14730 return StmtError();
14734 setFunctionHasBranchProtectedScope();
14735 return OMPTargetTeamsDistributeParallelForDirective::Create(
14736 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
,
14737 DSAStack
->getTaskgroupReductionRef(), DSAStack
->isCancelRegion());
14740 StmtResult
Sema::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
14741 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14742 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14744 return StmtError();
14746 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14747 // 1.2.2 OpenMP Language Terminology
14748 // Structured block - An executable statement with a single entry at the
14749 // top and a single exit at the bottom.
14750 // The point of exit cannot be a branch out of the structured block.
14751 // longjmp() and throw() must not violate the entry/exit criteria.
14752 CS
->getCapturedDecl()->setNothrow();
14753 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(
14754 OMPD_target_teams_distribute_parallel_for_simd
);
14755 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14756 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14757 // 1.2.2 OpenMP Language Terminology
14758 // Structured block - An executable statement with a single entry at the
14759 // top and a single exit at the bottom.
14760 // The point of exit cannot be a branch out of the structured block.
14761 // longjmp() and throw() must not violate the entry/exit criteria.
14762 CS
->getCapturedDecl()->setNothrow();
14765 OMPLoopBasedDirective::HelperExprs B
;
14766 // In presence of clause 'collapse' with number of loops, it will
14767 // define the nested loops number.
14768 unsigned NestedLoopCount
=
14769 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd
,
14770 getCollapseNumberExpr(Clauses
),
14771 nullptr /*ordered not a clause on distribute*/, CS
, *this,
14772 *DSAStack
, VarsWithImplicitDSA
, B
);
14773 if (NestedLoopCount
== 0)
14774 return StmtError();
14776 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14777 "omp target teams distribute parallel for simd loop exprs were not "
14780 if (!CurContext
->isDependentContext()) {
14781 // Finalize the clauses that need pre-built expressions for CodeGen.
14782 for (OMPClause
*C
: Clauses
) {
14783 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14784 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14785 B
.NumIterations
, *this, CurScope
,
14787 return StmtError();
14791 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14792 return StmtError();
14794 setFunctionHasBranchProtectedScope();
14795 return OMPTargetTeamsDistributeParallelForSimdDirective::Create(
14796 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14799 StmtResult
Sema::ActOnOpenMPTargetTeamsDistributeSimdDirective(
14800 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14801 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14803 return StmtError();
14805 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14806 // 1.2.2 OpenMP Language Terminology
14807 // Structured block - An executable statement with a single entry at the
14808 // top and a single exit at the bottom.
14809 // The point of exit cannot be a branch out of the structured block.
14810 // longjmp() and throw() must not violate the entry/exit criteria.
14811 CS
->getCapturedDecl()->setNothrow();
14812 for (int ThisCaptureLevel
=
14813 getOpenMPCaptureLevels(OMPD_target_teams_distribute_simd
);
14814 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14815 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14816 // 1.2.2 OpenMP Language Terminology
14817 // Structured block - An executable statement with a single entry at the
14818 // top and a single exit at the bottom.
14819 // The point of exit cannot be a branch out of the structured block.
14820 // longjmp() and throw() must not violate the entry/exit criteria.
14821 CS
->getCapturedDecl()->setNothrow();
14824 OMPLoopBasedDirective::HelperExprs B
;
14825 // In presence of clause 'collapse' with number of loops, it will
14826 // define the nested loops number.
14827 unsigned NestedLoopCount
= checkOpenMPLoop(
14828 OMPD_target_teams_distribute_simd
, getCollapseNumberExpr(Clauses
),
14829 nullptr /*ordered not a clause on distribute*/, CS
, *this, *DSAStack
,
14830 VarsWithImplicitDSA
, B
);
14831 if (NestedLoopCount
== 0)
14832 return StmtError();
14834 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14835 "omp target teams distribute simd loop exprs were not built");
14837 if (!CurContext
->isDependentContext()) {
14838 // Finalize the clauses that need pre-built expressions for CodeGen.
14839 for (OMPClause
*C
: Clauses
) {
14840 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14841 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14842 B
.NumIterations
, *this, CurScope
,
14844 return StmtError();
14848 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14849 return StmtError();
14851 setFunctionHasBranchProtectedScope();
14852 return OMPTargetTeamsDistributeSimdDirective::Create(
14853 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14856 bool Sema::checkTransformableLoopNest(
14857 OpenMPDirectiveKind Kind
, Stmt
*AStmt
, int NumLoops
,
14858 SmallVectorImpl
<OMPLoopBasedDirective::HelperExprs
> &LoopHelpers
,
14860 SmallVectorImpl
<SmallVector
<llvm::PointerUnion
<Stmt
*, Decl
*>, 0>>
14862 OriginalInits
.emplace_back();
14863 bool Result
= OMPLoopBasedDirective::doForAllLoops(
14864 AStmt
->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops
,
14865 [this, &LoopHelpers
, &Body
, &OriginalInits
, Kind
](unsigned Cnt
,
14867 VarsWithInheritedDSAType TmpDSA
;
14868 unsigned SingleNumLoops
=
14869 checkOpenMPLoop(Kind
, nullptr, nullptr, CurStmt
, *this, *DSAStack
,
14870 TmpDSA
, LoopHelpers
[Cnt
]);
14871 if (SingleNumLoops
== 0)
14873 assert(SingleNumLoops
== 1 && "Expect single loop iteration space");
14874 if (auto *For
= dyn_cast
<ForStmt
>(CurStmt
)) {
14875 OriginalInits
.back().push_back(For
->getInit());
14876 Body
= For
->getBody();
14878 assert(isa
<CXXForRangeStmt
>(CurStmt
) &&
14879 "Expected canonical for or range-based for loops.");
14880 auto *CXXFor
= cast
<CXXForRangeStmt
>(CurStmt
);
14881 OriginalInits
.back().push_back(CXXFor
->getBeginStmt());
14882 Body
= CXXFor
->getBody();
14884 OriginalInits
.emplace_back();
14887 [&OriginalInits
](OMPLoopBasedDirective
*Transform
) {
14888 Stmt
*DependentPreInits
;
14889 if (auto *Dir
= dyn_cast
<OMPTileDirective
>(Transform
))
14890 DependentPreInits
= Dir
->getPreInits();
14891 else if (auto *Dir
= dyn_cast
<OMPUnrollDirective
>(Transform
))
14892 DependentPreInits
= Dir
->getPreInits();
14894 llvm_unreachable("Unhandled loop transformation");
14895 if (!DependentPreInits
)
14897 llvm::append_range(OriginalInits
.back(),
14898 cast
<DeclStmt
>(DependentPreInits
)->getDeclGroup());
14900 assert(OriginalInits
.back().empty() && "No preinit after innermost loop");
14901 OriginalInits
.pop_back();
14905 StmtResult
Sema::ActOnOpenMPTileDirective(ArrayRef
<OMPClause
*> Clauses
,
14906 Stmt
*AStmt
, SourceLocation StartLoc
,
14907 SourceLocation EndLoc
) {
14908 auto SizesClauses
=
14909 OMPExecutableDirective::getClausesOfKind
<OMPSizesClause
>(Clauses
);
14910 if (SizesClauses
.empty()) {
14911 // A missing 'sizes' clause is already reported by the parser.
14912 return StmtError();
14914 const OMPSizesClause
*SizesClause
= *SizesClauses
.begin();
14915 unsigned NumLoops
= SizesClause
->getNumSizes();
14917 // Empty statement should only be possible if there already was an error.
14919 return StmtError();
14921 // Verify and diagnose loop nest.
14922 SmallVector
<OMPLoopBasedDirective::HelperExprs
, 4> LoopHelpers(NumLoops
);
14923 Stmt
*Body
= nullptr;
14924 SmallVector
<SmallVector
<llvm::PointerUnion
<Stmt
*, Decl
*>, 0>, 4>
14926 if (!checkTransformableLoopNest(OMPD_tile
, AStmt
, NumLoops
, LoopHelpers
, Body
,
14928 return StmtError();
14930 // Delay tiling to when template is completely instantiated.
14931 if (CurContext
->isDependentContext())
14932 return OMPTileDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
,
14933 NumLoops
, AStmt
, nullptr, nullptr);
14935 SmallVector
<Decl
*, 4> PreInits
;
14937 // Create iteration variables for the generated loops.
14938 SmallVector
<VarDecl
*, 4> FloorIndVars
;
14939 SmallVector
<VarDecl
*, 4> TileIndVars
;
14940 FloorIndVars
.resize(NumLoops
);
14941 TileIndVars
.resize(NumLoops
);
14942 for (unsigned I
= 0; I
< NumLoops
; ++I
) {
14943 OMPLoopBasedDirective::HelperExprs
&LoopHelper
= LoopHelpers
[I
];
14945 assert(LoopHelper
.Counters
.size() == 1 &&
14946 "Expect single-dimensional loop iteration space");
14947 auto *OrigCntVar
= cast
<DeclRefExpr
>(LoopHelper
.Counters
.front());
14948 std::string OrigVarName
= OrigCntVar
->getNameInfo().getAsString();
14949 DeclRefExpr
*IterVarRef
= cast
<DeclRefExpr
>(LoopHelper
.IterationVarRef
);
14950 QualType CntTy
= IterVarRef
->getType();
14952 // Iteration variable for the floor (i.e. outer) loop.
14954 std::string FloorCntName
=
14955 (Twine(".floor_") + llvm::utostr(I
) + ".iv." + OrigVarName
).str();
14956 VarDecl
*FloorCntDecl
=
14957 buildVarDecl(*this, {}, CntTy
, FloorCntName
, nullptr, OrigCntVar
);
14958 FloorIndVars
[I
] = FloorCntDecl
;
14961 // Iteration variable for the tile (i.e. inner) loop.
14963 std::string TileCntName
=
14964 (Twine(".tile_") + llvm::utostr(I
) + ".iv." + OrigVarName
).str();
14966 // Reuse the iteration variable created by checkOpenMPLoop. It is also
14967 // used by the expressions to derive the original iteration variable's
14968 // value from the logical iteration number.
14969 auto *TileCntDecl
= cast
<VarDecl
>(IterVarRef
->getDecl());
14970 TileCntDecl
->setDeclName(&PP
.getIdentifierTable().get(TileCntName
));
14971 TileIndVars
[I
] = TileCntDecl
;
14973 for (auto &P
: OriginalInits
[I
]) {
14974 if (auto *D
= P
.dyn_cast
<Decl
*>())
14975 PreInits
.push_back(D
);
14976 else if (auto *PI
= dyn_cast_or_null
<DeclStmt
>(P
.dyn_cast
<Stmt
*>()))
14977 PreInits
.append(PI
->decl_begin(), PI
->decl_end());
14979 if (auto *PI
= cast_or_null
<DeclStmt
>(LoopHelper
.PreInits
))
14980 PreInits
.append(PI
->decl_begin(), PI
->decl_end());
14981 // Gather declarations for the data members used as counters.
14982 for (Expr
*CounterRef
: LoopHelper
.Counters
) {
14983 auto *CounterDecl
= cast
<DeclRefExpr
>(CounterRef
)->getDecl();
14984 if (isa
<OMPCapturedExprDecl
>(CounterDecl
))
14985 PreInits
.push_back(CounterDecl
);
14989 // Once the original iteration values are set, append the innermost body.
14990 Stmt
*Inner
= Body
;
14992 // Create tile loops from the inside to the outside.
14993 for (int I
= NumLoops
- 1; I
>= 0; --I
) {
14994 OMPLoopBasedDirective::HelperExprs
&LoopHelper
= LoopHelpers
[I
];
14995 Expr
*NumIterations
= LoopHelper
.NumIterations
;
14996 auto *OrigCntVar
= cast
<DeclRefExpr
>(LoopHelper
.Counters
[0]);
14997 QualType CntTy
= OrigCntVar
->getType();
14998 Expr
*DimTileSize
= SizesClause
->getSizesRefs()[I
];
14999 Scope
*CurScope
= getCurScope();
15001 // Commonly used variables.
15002 DeclRefExpr
*TileIV
= buildDeclRefExpr(*this, TileIndVars
[I
], CntTy
,
15003 OrigCntVar
->getExprLoc());
15004 DeclRefExpr
*FloorIV
= buildDeclRefExpr(*this, FloorIndVars
[I
], CntTy
,
15005 OrigCntVar
->getExprLoc());
15007 // For init-statement: auto .tile.iv = .floor.iv
15008 AddInitializerToDecl(TileIndVars
[I
], DefaultLvalueConversion(FloorIV
).get(),
15009 /*DirectInit=*/false);
15010 Decl
*CounterDecl
= TileIndVars
[I
];
15011 StmtResult InitStmt
= new (Context
)
15012 DeclStmt(DeclGroupRef::Create(Context
, &CounterDecl
, 1),
15013 OrigCntVar
->getBeginLoc(), OrigCntVar
->getEndLoc());
15014 if (!InitStmt
.isUsable())
15015 return StmtError();
15017 // For cond-expression: .tile.iv < min(.floor.iv + DimTileSize,
15019 ExprResult EndOfTile
= BuildBinOp(CurScope
, LoopHelper
.Cond
->getExprLoc(),
15020 BO_Add
, FloorIV
, DimTileSize
);
15021 if (!EndOfTile
.isUsable())
15022 return StmtError();
15023 ExprResult IsPartialTile
=
15024 BuildBinOp(CurScope
, LoopHelper
.Cond
->getExprLoc(), BO_LT
,
15025 NumIterations
, EndOfTile
.get());
15026 if (!IsPartialTile
.isUsable())
15027 return StmtError();
15028 ExprResult MinTileAndIterSpace
= ActOnConditionalOp(
15029 LoopHelper
.Cond
->getBeginLoc(), LoopHelper
.Cond
->getEndLoc(),
15030 IsPartialTile
.get(), NumIterations
, EndOfTile
.get());
15031 if (!MinTileAndIterSpace
.isUsable())
15032 return StmtError();
15033 ExprResult CondExpr
= BuildBinOp(CurScope
, LoopHelper
.Cond
->getExprLoc(),
15034 BO_LT
, TileIV
, MinTileAndIterSpace
.get());
15035 if (!CondExpr
.isUsable())
15036 return StmtError();
15038 // For incr-statement: ++.tile.iv
15039 ExprResult IncrStmt
=
15040 BuildUnaryOp(CurScope
, LoopHelper
.Inc
->getExprLoc(), UO_PreInc
, TileIV
);
15041 if (!IncrStmt
.isUsable())
15042 return StmtError();
15044 // Statements to set the original iteration variable's value from the
15045 // logical iteration number.
15046 // Generated for loop is:
15047 // Original_for_init;
15048 // for (auto .tile.iv = .floor.iv; .tile.iv < min(.floor.iv + DimTileSize,
15049 // NumIterations); ++.tile.iv) {
15051 // Original_counter_update;
15053 // FIXME: If the innermost body is an loop itself, inserting these
15054 // statements stops it being recognized as a perfectly nested loop (e.g.
15055 // for applying tiling again). If this is the case, sink the expressions
15056 // further into the inner loop.
15057 SmallVector
<Stmt
*, 4> BodyParts
;
15058 BodyParts
.append(LoopHelper
.Updates
.begin(), LoopHelper
.Updates
.end());
15059 BodyParts
.push_back(Inner
);
15060 Inner
= CompoundStmt::Create(Context
, BodyParts
, FPOptionsOverride(),
15061 Inner
->getBeginLoc(), Inner
->getEndLoc());
15062 Inner
= new (Context
)
15063 ForStmt(Context
, InitStmt
.get(), CondExpr
.get(), nullptr,
15064 IncrStmt
.get(), Inner
, LoopHelper
.Init
->getBeginLoc(),
15065 LoopHelper
.Init
->getBeginLoc(), LoopHelper
.Inc
->getEndLoc());
15068 // Create floor loops from the inside to the outside.
15069 for (int I
= NumLoops
- 1; I
>= 0; --I
) {
15070 auto &LoopHelper
= LoopHelpers
[I
];
15071 Expr
*NumIterations
= LoopHelper
.NumIterations
;
15072 DeclRefExpr
*OrigCntVar
= cast
<DeclRefExpr
>(LoopHelper
.Counters
[0]);
15073 QualType CntTy
= OrigCntVar
->getType();
15074 Expr
*DimTileSize
= SizesClause
->getSizesRefs()[I
];
15075 Scope
*CurScope
= getCurScope();
15077 // Commonly used variables.
15078 DeclRefExpr
*FloorIV
= buildDeclRefExpr(*this, FloorIndVars
[I
], CntTy
,
15079 OrigCntVar
->getExprLoc());
15081 // For init-statement: auto .floor.iv = 0
15082 AddInitializerToDecl(
15084 ActOnIntegerConstant(LoopHelper
.Init
->getExprLoc(), 0).get(),
15085 /*DirectInit=*/false);
15086 Decl
*CounterDecl
= FloorIndVars
[I
];
15087 StmtResult InitStmt
= new (Context
)
15088 DeclStmt(DeclGroupRef::Create(Context
, &CounterDecl
, 1),
15089 OrigCntVar
->getBeginLoc(), OrigCntVar
->getEndLoc());
15090 if (!InitStmt
.isUsable())
15091 return StmtError();
15093 // For cond-expression: .floor.iv < NumIterations
15094 ExprResult CondExpr
= BuildBinOp(CurScope
, LoopHelper
.Cond
->getExprLoc(),
15095 BO_LT
, FloorIV
, NumIterations
);
15096 if (!CondExpr
.isUsable())
15097 return StmtError();
15099 // For incr-statement: .floor.iv += DimTileSize
15100 ExprResult IncrStmt
= BuildBinOp(CurScope
, LoopHelper
.Inc
->getExprLoc(),
15101 BO_AddAssign
, FloorIV
, DimTileSize
);
15102 if (!IncrStmt
.isUsable())
15103 return StmtError();
15105 Inner
= new (Context
)
15106 ForStmt(Context
, InitStmt
.get(), CondExpr
.get(), nullptr,
15107 IncrStmt
.get(), Inner
, LoopHelper
.Init
->getBeginLoc(),
15108 LoopHelper
.Init
->getBeginLoc(), LoopHelper
.Inc
->getEndLoc());
15111 return OMPTileDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, NumLoops
,
15113 buildPreInits(Context
, PreInits
));
15116 StmtResult
Sema::ActOnOpenMPUnrollDirective(ArrayRef
<OMPClause
*> Clauses
,
15118 SourceLocation StartLoc
,
15119 SourceLocation EndLoc
) {
15120 // Empty statement should only be possible if there already was an error.
15122 return StmtError();
15124 if (checkMutuallyExclusiveClauses(*this, Clauses
, {OMPC_partial
, OMPC_full
}))
15125 return StmtError();
15127 const OMPFullClause
*FullClause
=
15128 OMPExecutableDirective::getSingleClause
<OMPFullClause
>(Clauses
);
15129 const OMPPartialClause
*PartialClause
=
15130 OMPExecutableDirective::getSingleClause
<OMPPartialClause
>(Clauses
);
15131 assert(!(FullClause
&& PartialClause
) &&
15132 "mutual exclusivity must have been checked before");
15134 constexpr unsigned NumLoops
= 1;
15135 Stmt
*Body
= nullptr;
15136 SmallVector
<OMPLoopBasedDirective::HelperExprs
, NumLoops
> LoopHelpers(
15138 SmallVector
<SmallVector
<llvm::PointerUnion
<Stmt
*, Decl
*>, 0>, NumLoops
+ 1>
15140 if (!checkTransformableLoopNest(OMPD_unroll
, AStmt
, NumLoops
, LoopHelpers
,
15141 Body
, OriginalInits
))
15142 return StmtError();
15144 unsigned NumGeneratedLoops
= PartialClause
? 1 : 0;
15146 // Delay unrolling to when template is completely instantiated.
15147 if (CurContext
->isDependentContext())
15148 return OMPUnrollDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
15149 NumGeneratedLoops
, nullptr, nullptr);
15151 OMPLoopBasedDirective::HelperExprs
&LoopHelper
= LoopHelpers
.front();
15154 if (!VerifyPositiveIntegerConstantInClause(
15155 LoopHelper
.NumIterations
, OMPC_full
, /*StrictlyPositive=*/false,
15156 /*SuppressExprDiags=*/true)
15158 Diag(AStmt
->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count
);
15159 Diag(FullClause
->getBeginLoc(), diag::note_omp_directive_here
)
15160 << "#pragma omp unroll full";
15161 return StmtError();
15165 // The generated loop may only be passed to other loop-associated directive
15166 // when a partial clause is specified. Without the requirement it is
15167 // sufficient to generate loop unroll metadata at code-generation.
15168 if (NumGeneratedLoops
== 0)
15169 return OMPUnrollDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
15170 NumGeneratedLoops
, nullptr, nullptr);
15172 // Otherwise, we need to provide a de-sugared/transformed AST that can be
15173 // associated with another loop directive.
15175 // The canonical loop analysis return by checkTransformableLoopNest assumes
15176 // the following structure to be the same loop without transformations or
15177 // directives applied: \code OriginalInits; LoopHelper.PreInits;
15178 // LoopHelper.Counters;
15179 // for (; IV < LoopHelper.NumIterations; ++IV) {
15180 // LoopHelper.Updates;
15184 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
15185 // and referenced by LoopHelper.IterationVarRef.
15187 // The unrolling directive transforms this into the following loop:
15189 // OriginalInits; \
15190 // LoopHelper.PreInits; > NewPreInits
15191 // LoopHelper.Counters; /
15192 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
15193 // #pragma clang loop unroll_count(Factor)
15194 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
15196 // LoopHelper.Updates;
15201 // where UIV is a new logical iteration counter. IV must be the same VarDecl
15202 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
15203 // references it. If the partially unrolled loop is associated with another
15204 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
15205 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
15206 // OpenMP canonical loop. The inner loop is not an associable canonical loop
15207 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
15208 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
15209 // property of the OMPLoopBasedDirective instead of statements in
15210 // CompoundStatement. This is to allow the loop to become a non-outermost loop
15211 // of a canonical loop nest where these PreInits are emitted before the
15212 // outermost directive.
15214 // Determine the PreInit declarations.
15215 SmallVector
<Decl
*, 4> PreInits
;
15216 assert(OriginalInits
.size() == 1 &&
15217 "Expecting a single-dimensional loop iteration space");
15218 for (auto &P
: OriginalInits
[0]) {
15219 if (auto *D
= P
.dyn_cast
<Decl
*>())
15220 PreInits
.push_back(D
);
15221 else if (auto *PI
= dyn_cast_or_null
<DeclStmt
>(P
.dyn_cast
<Stmt
*>()))
15222 PreInits
.append(PI
->decl_begin(), PI
->decl_end());
15224 if (auto *PI
= cast_or_null
<DeclStmt
>(LoopHelper
.PreInits
))
15225 PreInits
.append(PI
->decl_begin(), PI
->decl_end());
15226 // Gather declarations for the data members used as counters.
15227 for (Expr
*CounterRef
: LoopHelper
.Counters
) {
15228 auto *CounterDecl
= cast
<DeclRefExpr
>(CounterRef
)->getDecl();
15229 if (isa
<OMPCapturedExprDecl
>(CounterDecl
))
15230 PreInits
.push_back(CounterDecl
);
15233 auto *IterationVarRef
= cast
<DeclRefExpr
>(LoopHelper
.IterationVarRef
);
15234 QualType IVTy
= IterationVarRef
->getType();
15235 assert(LoopHelper
.Counters
.size() == 1 &&
15236 "Expecting a single-dimensional loop iteration space");
15237 auto *OrigVar
= cast
<DeclRefExpr
>(LoopHelper
.Counters
.front());
15239 // Determine the unroll factor.
15241 SourceLocation FactorLoc
;
15242 if (Expr
*FactorVal
= PartialClause
->getFactor()) {
15243 Factor
= FactorVal
->getIntegerConstantExpr(Context
)->getZExtValue();
15244 FactorLoc
= FactorVal
->getExprLoc();
15246 // TODO: Use a better profitability model.
15249 assert(Factor
> 0 && "Expected positive unroll factor");
15250 auto MakeFactorExpr
= [this, Factor
, IVTy
, FactorLoc
]() {
15251 return IntegerLiteral::Create(
15252 Context
, llvm::APInt(Context
.getIntWidth(IVTy
), Factor
), IVTy
,
15256 // Iteration variable SourceLocations.
15257 SourceLocation OrigVarLoc
= OrigVar
->getExprLoc();
15258 SourceLocation OrigVarLocBegin
= OrigVar
->getBeginLoc();
15259 SourceLocation OrigVarLocEnd
= OrigVar
->getEndLoc();
15261 // Internal variable names.
15262 std::string OrigVarName
= OrigVar
->getNameInfo().getAsString();
15263 std::string OuterIVName
= (Twine(".unrolled.iv.") + OrigVarName
).str();
15264 std::string InnerIVName
= (Twine(".unroll_inner.iv.") + OrigVarName
).str();
15265 std::string InnerTripCountName
=
15266 (Twine(".unroll_inner.tripcount.") + OrigVarName
).str();
15268 // Create the iteration variable for the unrolled loop.
15269 VarDecl
*OuterIVDecl
=
15270 buildVarDecl(*this, {}, IVTy
, OuterIVName
, nullptr, OrigVar
);
15271 auto MakeOuterRef
= [this, OuterIVDecl
, IVTy
, OrigVarLoc
]() {
15272 return buildDeclRefExpr(*this, OuterIVDecl
, IVTy
, OrigVarLoc
);
15275 // Iteration variable for the inner loop: Reuse the iteration variable created
15276 // by checkOpenMPLoop.
15277 auto *InnerIVDecl
= cast
<VarDecl
>(IterationVarRef
->getDecl());
15278 InnerIVDecl
->setDeclName(&PP
.getIdentifierTable().get(InnerIVName
));
15279 auto MakeInnerRef
= [this, InnerIVDecl
, IVTy
, OrigVarLoc
]() {
15280 return buildDeclRefExpr(*this, InnerIVDecl
, IVTy
, OrigVarLoc
);
15283 // Make a copy of the NumIterations expression for each use: By the AST
15284 // constraints, every expression object in a DeclContext must be unique.
15285 CaptureVars
CopyTransformer(*this);
15286 auto MakeNumIterations
= [&CopyTransformer
, &LoopHelper
]() -> Expr
* {
15287 return AssertSuccess(
15288 CopyTransformer
.TransformExpr(LoopHelper
.NumIterations
));
15291 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
15292 ExprResult LValueConv
= DefaultLvalueConversion(MakeOuterRef());
15293 AddInitializerToDecl(InnerIVDecl
, LValueConv
.get(), /*DirectInit=*/false);
15294 StmtResult InnerInit
= new (Context
)
15295 DeclStmt(DeclGroupRef(InnerIVDecl
), OrigVarLocBegin
, OrigVarLocEnd
);
15296 if (!InnerInit
.isUsable())
15297 return StmtError();
15299 // Inner For cond-expression:
15301 // .unroll_inner.iv < .unrolled.iv + Factor &&
15302 // .unroll_inner.iv < NumIterations
15304 // This conjunction of two conditions allows ScalarEvolution to derive the
15305 // maximum trip count of the inner loop.
15306 ExprResult EndOfTile
= BuildBinOp(CurScope
, LoopHelper
.Cond
->getExprLoc(),
15307 BO_Add
, MakeOuterRef(), MakeFactorExpr());
15308 if (!EndOfTile
.isUsable())
15309 return StmtError();
15310 ExprResult InnerCond1
= BuildBinOp(CurScope
, LoopHelper
.Cond
->getExprLoc(),
15311 BO_LT
, MakeInnerRef(), EndOfTile
.get());
15312 if (!InnerCond1
.isUsable())
15313 return StmtError();
15314 ExprResult InnerCond2
=
15315 BuildBinOp(CurScope
, LoopHelper
.Cond
->getExprLoc(), BO_LT
, MakeInnerRef(),
15316 MakeNumIterations());
15317 if (!InnerCond2
.isUsable())
15318 return StmtError();
15319 ExprResult InnerCond
=
15320 BuildBinOp(CurScope
, LoopHelper
.Cond
->getExprLoc(), BO_LAnd
,
15321 InnerCond1
.get(), InnerCond2
.get());
15322 if (!InnerCond
.isUsable())
15323 return StmtError();
15325 // Inner For incr-statement: ++.unroll_inner.iv
15326 ExprResult InnerIncr
= BuildUnaryOp(CurScope
, LoopHelper
.Inc
->getExprLoc(),
15327 UO_PreInc
, MakeInnerRef());
15328 if (!InnerIncr
.isUsable())
15329 return StmtError();
15331 // Inner For statement.
15332 SmallVector
<Stmt
*> InnerBodyStmts
;
15333 InnerBodyStmts
.append(LoopHelper
.Updates
.begin(), LoopHelper
.Updates
.end());
15334 InnerBodyStmts
.push_back(Body
);
15335 CompoundStmt
*InnerBody
=
15336 CompoundStmt::Create(Context
, InnerBodyStmts
, FPOptionsOverride(),
15337 Body
->getBeginLoc(), Body
->getEndLoc());
15338 ForStmt
*InnerFor
= new (Context
)
15339 ForStmt(Context
, InnerInit
.get(), InnerCond
.get(), nullptr,
15340 InnerIncr
.get(), InnerBody
, LoopHelper
.Init
->getBeginLoc(),
15341 LoopHelper
.Init
->getBeginLoc(), LoopHelper
.Inc
->getEndLoc());
15343 // Unroll metadata for the inner loop.
15344 // This needs to take into account the remainder portion of the unrolled loop,
15345 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
15346 // supports multiple loop exits. Instead, unroll using a factor equivalent to
15347 // the maximum trip count, which will also generate a remainder loop. Just
15348 // `unroll(enable)` (which could have been useful if the user has not
15349 // specified a concrete factor; even though the outer loop cannot be
15350 // influenced anymore, would avoid more code bloat than necessary) will refuse
15351 // the loop because "Won't unroll; remainder loop could not be generated when
15352 // assuming runtime trip count". Even if it did work, it must not choose a
15353 // larger unroll factor than the maximum loop length, or it would always just
15354 // execute the remainder loop.
15355 LoopHintAttr
*UnrollHintAttr
=
15356 LoopHintAttr::CreateImplicit(Context
, LoopHintAttr::UnrollCount
,
15357 LoopHintAttr::Numeric
, MakeFactorExpr());
15358 AttributedStmt
*InnerUnrolled
=
15359 AttributedStmt::Create(Context
, StartLoc
, {UnrollHintAttr
}, InnerFor
);
15361 // Outer For init-statement: auto .unrolled.iv = 0
15362 AddInitializerToDecl(
15363 OuterIVDecl
, ActOnIntegerConstant(LoopHelper
.Init
->getExprLoc(), 0).get(),
15364 /*DirectInit=*/false);
15365 StmtResult OuterInit
= new (Context
)
15366 DeclStmt(DeclGroupRef(OuterIVDecl
), OrigVarLocBegin
, OrigVarLocEnd
);
15367 if (!OuterInit
.isUsable())
15368 return StmtError();
15370 // Outer For cond-expression: .unrolled.iv < NumIterations
15371 ExprResult OuterConde
=
15372 BuildBinOp(CurScope
, LoopHelper
.Cond
->getExprLoc(), BO_LT
, MakeOuterRef(),
15373 MakeNumIterations());
15374 if (!OuterConde
.isUsable())
15375 return StmtError();
15377 // Outer For incr-statement: .unrolled.iv += Factor
15378 ExprResult OuterIncr
=
15379 BuildBinOp(CurScope
, LoopHelper
.Inc
->getExprLoc(), BO_AddAssign
,
15380 MakeOuterRef(), MakeFactorExpr());
15381 if (!OuterIncr
.isUsable())
15382 return StmtError();
15384 // Outer For statement.
15385 ForStmt
*OuterFor
= new (Context
)
15386 ForStmt(Context
, OuterInit
.get(), OuterConde
.get(), nullptr,
15387 OuterIncr
.get(), InnerUnrolled
, LoopHelper
.Init
->getBeginLoc(),
15388 LoopHelper
.Init
->getBeginLoc(), LoopHelper
.Inc
->getEndLoc());
15390 return OMPUnrollDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
15391 NumGeneratedLoops
, OuterFor
,
15392 buildPreInits(Context
, PreInits
));
15395 OMPClause
*Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind
, Expr
*Expr
,
15396 SourceLocation StartLoc
,
15397 SourceLocation LParenLoc
,
15398 SourceLocation EndLoc
) {
15399 OMPClause
*Res
= nullptr;
15402 Res
= ActOnOpenMPFinalClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15404 case OMPC_num_threads
:
15405 Res
= ActOnOpenMPNumThreadsClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15408 Res
= ActOnOpenMPSafelenClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15411 Res
= ActOnOpenMPSimdlenClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15413 case OMPC_allocator
:
15414 Res
= ActOnOpenMPAllocatorClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15416 case OMPC_collapse
:
15417 Res
= ActOnOpenMPCollapseClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15420 Res
= ActOnOpenMPOrderedClause(StartLoc
, EndLoc
, LParenLoc
, Expr
);
15422 case OMPC_num_teams
:
15423 Res
= ActOnOpenMPNumTeamsClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15425 case OMPC_thread_limit
:
15426 Res
= ActOnOpenMPThreadLimitClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15428 case OMPC_priority
:
15429 Res
= ActOnOpenMPPriorityClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15432 Res
= ActOnOpenMPHintClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15435 Res
= ActOnOpenMPDepobjClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15438 Res
= ActOnOpenMPDetachClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15440 case OMPC_novariants
:
15441 Res
= ActOnOpenMPNovariantsClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15443 case OMPC_nocontext
:
15444 Res
= ActOnOpenMPNocontextClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15447 Res
= ActOnOpenMPFilterClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15450 Res
= ActOnOpenMPPartialClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15453 Res
= ActOnOpenMPMessageClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15456 Res
= ActOnOpenMPAlignClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15458 case OMPC_ompx_dyn_cgroup_mem
:
15459 Res
= ActOnOpenMPXDynCGroupMemClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15461 case OMPC_grainsize
:
15462 case OMPC_num_tasks
:
15466 case OMPC_proc_bind
:
15467 case OMPC_schedule
:
15469 case OMPC_firstprivate
:
15470 case OMPC_lastprivate
:
15472 case OMPC_reduction
:
15473 case OMPC_task_reduction
:
15474 case OMPC_in_reduction
:
15478 case OMPC_copyprivate
:
15481 case OMPC_mergeable
:
15482 case OMPC_threadprivate
:
15484 case OMPC_allocate
:
15501 case OMPC_dist_schedule
:
15502 case OMPC_defaultmap
:
15507 case OMPC_use_device_ptr
:
15508 case OMPC_use_device_addr
:
15509 case OMPC_is_device_ptr
:
15510 case OMPC_unified_address
:
15511 case OMPC_unified_shared_memory
:
15512 case OMPC_reverse_offload
:
15513 case OMPC_dynamic_allocators
:
15514 case OMPC_atomic_default_mem_order
:
15515 case OMPC_device_type
:
15517 case OMPC_nontemporal
:
15520 case OMPC_severity
:
15522 case OMPC_inclusive
:
15523 case OMPC_exclusive
:
15524 case OMPC_uses_allocators
:
15525 case OMPC_affinity
:
15529 llvm_unreachable("Clause is not allowed.");
15534 // An OpenMP directive such as 'target parallel' has two captured regions:
15535 // for the 'target' and 'parallel' respectively. This function returns
15536 // the region in which to capture expressions associated with a clause.
15537 // A return value of OMPD_unknown signifies that the expression should not
15539 static OpenMPDirectiveKind
getOpenMPCaptureRegionForClause(
15540 OpenMPDirectiveKind DKind
, OpenMPClauseKind CKind
, unsigned OpenMPVersion
,
15541 OpenMPDirectiveKind NameModifier
= OMPD_unknown
) {
15542 OpenMPDirectiveKind CaptureRegion
= OMPD_unknown
;
15546 case OMPD_target_parallel_for_simd
:
15547 if (OpenMPVersion
>= 50 &&
15548 (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
)) {
15549 CaptureRegion
= OMPD_parallel
;
15553 case OMPD_target_parallel
:
15554 case OMPD_target_parallel_for
:
15555 case OMPD_target_parallel_loop
:
15556 // If this clause applies to the nested 'parallel' region, capture within
15557 // the 'target' region, otherwise do not capture.
15558 if (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_parallel
)
15559 CaptureRegion
= OMPD_target
;
15561 case OMPD_target_teams_distribute_parallel_for_simd
:
15562 if (OpenMPVersion
>= 50 &&
15563 (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
)) {
15564 CaptureRegion
= OMPD_parallel
;
15568 case OMPD_target_teams_loop
:
15569 case OMPD_target_teams_distribute_parallel_for
:
15570 // If this clause applies to the nested 'parallel' region, capture within
15571 // the 'teams' region, otherwise do not capture.
15572 if (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_parallel
)
15573 CaptureRegion
= OMPD_teams
;
15575 case OMPD_teams_distribute_parallel_for_simd
:
15576 if (OpenMPVersion
>= 50 &&
15577 (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
)) {
15578 CaptureRegion
= OMPD_parallel
;
15582 case OMPD_teams_distribute_parallel_for
:
15583 CaptureRegion
= OMPD_teams
;
15585 case OMPD_target_update
:
15586 case OMPD_target_enter_data
:
15587 case OMPD_target_exit_data
:
15588 CaptureRegion
= OMPD_task
;
15590 case OMPD_parallel_masked_taskloop
:
15591 if (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_taskloop
)
15592 CaptureRegion
= OMPD_parallel
;
15594 case OMPD_parallel_master_taskloop
:
15595 if (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_taskloop
)
15596 CaptureRegion
= OMPD_parallel
;
15598 case OMPD_parallel_masked_taskloop_simd
:
15599 if ((OpenMPVersion
<= 45 && NameModifier
== OMPD_unknown
) ||
15600 NameModifier
== OMPD_taskloop
) {
15601 CaptureRegion
= OMPD_parallel
;
15604 if (OpenMPVersion
<= 45)
15606 if (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
)
15607 CaptureRegion
= OMPD_taskloop
;
15609 case OMPD_parallel_master_taskloop_simd
:
15610 if ((OpenMPVersion
<= 45 && NameModifier
== OMPD_unknown
) ||
15611 NameModifier
== OMPD_taskloop
) {
15612 CaptureRegion
= OMPD_parallel
;
15615 if (OpenMPVersion
<= 45)
15617 if (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
)
15618 CaptureRegion
= OMPD_taskloop
;
15620 case OMPD_parallel_for_simd
:
15621 if (OpenMPVersion
<= 45)
15623 if (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
)
15624 CaptureRegion
= OMPD_parallel
;
15626 case OMPD_taskloop_simd
:
15627 case OMPD_master_taskloop_simd
:
15628 case OMPD_masked_taskloop_simd
:
15629 if (OpenMPVersion
<= 45)
15631 if (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
)
15632 CaptureRegion
= OMPD_taskloop
;
15634 case OMPD_distribute_parallel_for_simd
:
15635 if (OpenMPVersion
<= 45)
15637 if (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
)
15638 CaptureRegion
= OMPD_parallel
;
15640 case OMPD_target_simd
:
15641 if (OpenMPVersion
>= 50 &&
15642 (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
))
15643 CaptureRegion
= OMPD_target
;
15645 case OMPD_teams_distribute_simd
:
15646 case OMPD_target_teams_distribute_simd
:
15647 if (OpenMPVersion
>= 50 &&
15648 (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
))
15649 CaptureRegion
= OMPD_teams
;
15652 case OMPD_parallel
:
15653 case OMPD_parallel_master
:
15654 case OMPD_parallel_masked
:
15655 case OMPD_parallel_sections
:
15656 case OMPD_parallel_for
:
15657 case OMPD_parallel_loop
:
15659 case OMPD_target_teams
:
15660 case OMPD_target_teams_distribute
:
15661 case OMPD_distribute_parallel_for
:
15663 case OMPD_taskloop
:
15664 case OMPD_master_taskloop
:
15665 case OMPD_masked_taskloop
:
15666 case OMPD_target_data
:
15668 case OMPD_for_simd
:
15669 case OMPD_distribute_simd
:
15670 // Do not capture if-clause expressions.
15672 case OMPD_threadprivate
:
15673 case OMPD_allocate
:
15674 case OMPD_taskyield
:
15677 case OMPD_taskwait
:
15678 case OMPD_cancellation_point
:
15682 case OMPD_declare_reduction
:
15683 case OMPD_declare_mapper
:
15684 case OMPD_declare_simd
:
15685 case OMPD_declare_variant
:
15686 case OMPD_begin_declare_variant
:
15687 case OMPD_end_declare_variant
:
15688 case OMPD_declare_target
:
15689 case OMPD_end_declare_target
:
15691 case OMPD_teams_loop
:
15696 case OMPD_sections
:
15701 case OMPD_critical
:
15702 case OMPD_taskgroup
:
15703 case OMPD_distribute
:
15706 case OMPD_teams_distribute
:
15707 case OMPD_requires
:
15708 case OMPD_metadirective
:
15709 llvm_unreachable("Unexpected OpenMP directive with if-clause");
15712 llvm_unreachable("Unknown OpenMP directive");
15715 case OMPC_num_threads
:
15717 case OMPD_target_parallel
:
15718 case OMPD_target_parallel_for
:
15719 case OMPD_target_parallel_for_simd
:
15720 case OMPD_target_parallel_loop
:
15721 CaptureRegion
= OMPD_target
;
15723 case OMPD_teams_distribute_parallel_for
:
15724 case OMPD_teams_distribute_parallel_for_simd
:
15725 case OMPD_target_teams_distribute_parallel_for
:
15726 case OMPD_target_teams_distribute_parallel_for_simd
:
15727 CaptureRegion
= OMPD_teams
;
15729 case OMPD_parallel
:
15730 case OMPD_parallel_master
:
15731 case OMPD_parallel_masked
:
15732 case OMPD_parallel_sections
:
15733 case OMPD_parallel_for
:
15734 case OMPD_parallel_for_simd
:
15735 case OMPD_parallel_loop
:
15736 case OMPD_distribute_parallel_for
:
15737 case OMPD_distribute_parallel_for_simd
:
15738 case OMPD_parallel_master_taskloop
:
15739 case OMPD_parallel_masked_taskloop
:
15740 case OMPD_parallel_master_taskloop_simd
:
15741 case OMPD_parallel_masked_taskloop_simd
:
15742 // Do not capture num_threads-clause expressions.
15744 case OMPD_target_data
:
15745 case OMPD_target_enter_data
:
15746 case OMPD_target_exit_data
:
15747 case OMPD_target_update
:
15749 case OMPD_target_simd
:
15750 case OMPD_target_teams
:
15751 case OMPD_target_teams_distribute
:
15752 case OMPD_target_teams_distribute_simd
:
15755 case OMPD_taskloop
:
15756 case OMPD_taskloop_simd
:
15757 case OMPD_master_taskloop
:
15758 case OMPD_masked_taskloop
:
15759 case OMPD_master_taskloop_simd
:
15760 case OMPD_masked_taskloop_simd
:
15761 case OMPD_threadprivate
:
15762 case OMPD_allocate
:
15763 case OMPD_taskyield
:
15766 case OMPD_taskwait
:
15767 case OMPD_cancellation_point
:
15771 case OMPD_declare_reduction
:
15772 case OMPD_declare_mapper
:
15773 case OMPD_declare_simd
:
15774 case OMPD_declare_variant
:
15775 case OMPD_begin_declare_variant
:
15776 case OMPD_end_declare_variant
:
15777 case OMPD_declare_target
:
15778 case OMPD_end_declare_target
:
15780 case OMPD_teams_loop
:
15781 case OMPD_target_teams_loop
:
15787 case OMPD_for_simd
:
15788 case OMPD_sections
:
15793 case OMPD_critical
:
15794 case OMPD_taskgroup
:
15795 case OMPD_distribute
:
15798 case OMPD_distribute_simd
:
15799 case OMPD_teams_distribute
:
15800 case OMPD_teams_distribute_simd
:
15801 case OMPD_requires
:
15802 case OMPD_metadirective
:
15803 llvm_unreachable("Unexpected OpenMP directive with num_threads-clause");
15806 llvm_unreachable("Unknown OpenMP directive");
15809 case OMPC_num_teams
:
15811 case OMPD_target_teams
:
15812 case OMPD_target_teams_distribute
:
15813 case OMPD_target_teams_distribute_simd
:
15814 case OMPD_target_teams_distribute_parallel_for
:
15815 case OMPD_target_teams_distribute_parallel_for_simd
:
15816 case OMPD_target_teams_loop
:
15817 CaptureRegion
= OMPD_target
;
15819 case OMPD_teams_distribute_parallel_for
:
15820 case OMPD_teams_distribute_parallel_for_simd
:
15822 case OMPD_teams_distribute
:
15823 case OMPD_teams_distribute_simd
:
15824 case OMPD_teams_loop
:
15825 // Do not capture num_teams-clause expressions.
15827 case OMPD_distribute_parallel_for
:
15828 case OMPD_distribute_parallel_for_simd
:
15830 case OMPD_taskloop
:
15831 case OMPD_taskloop_simd
:
15832 case OMPD_master_taskloop
:
15833 case OMPD_masked_taskloop
:
15834 case OMPD_master_taskloop_simd
:
15835 case OMPD_masked_taskloop_simd
:
15836 case OMPD_parallel_master_taskloop
:
15837 case OMPD_parallel_masked_taskloop
:
15838 case OMPD_parallel_master_taskloop_simd
:
15839 case OMPD_parallel_masked_taskloop_simd
:
15840 case OMPD_target_data
:
15841 case OMPD_target_enter_data
:
15842 case OMPD_target_exit_data
:
15843 case OMPD_target_update
:
15845 case OMPD_parallel
:
15846 case OMPD_parallel_master
:
15847 case OMPD_parallel_masked
:
15848 case OMPD_parallel_sections
:
15849 case OMPD_parallel_for
:
15850 case OMPD_parallel_for_simd
:
15851 case OMPD_parallel_loop
:
15853 case OMPD_target_simd
:
15854 case OMPD_target_parallel
:
15855 case OMPD_target_parallel_for
:
15856 case OMPD_target_parallel_for_simd
:
15857 case OMPD_target_parallel_loop
:
15858 case OMPD_threadprivate
:
15859 case OMPD_allocate
:
15860 case OMPD_taskyield
:
15863 case OMPD_taskwait
:
15864 case OMPD_cancellation_point
:
15868 case OMPD_declare_reduction
:
15869 case OMPD_declare_mapper
:
15870 case OMPD_declare_simd
:
15871 case OMPD_declare_variant
:
15872 case OMPD_begin_declare_variant
:
15873 case OMPD_end_declare_variant
:
15874 case OMPD_declare_target
:
15875 case OMPD_end_declare_target
:
15881 case OMPD_for_simd
:
15882 case OMPD_sections
:
15887 case OMPD_critical
:
15888 case OMPD_taskgroup
:
15889 case OMPD_distribute
:
15892 case OMPD_distribute_simd
:
15893 case OMPD_requires
:
15894 case OMPD_metadirective
:
15895 llvm_unreachable("Unexpected OpenMP directive with num_teams-clause");
15898 llvm_unreachable("Unknown OpenMP directive");
15901 case OMPC_thread_limit
:
15904 case OMPD_target_teams
:
15905 case OMPD_target_teams_distribute
:
15906 case OMPD_target_teams_distribute_simd
:
15907 case OMPD_target_teams_distribute_parallel_for
:
15908 case OMPD_target_teams_distribute_parallel_for_simd
:
15909 case OMPD_target_teams_loop
:
15910 CaptureRegion
= OMPD_target
;
15912 case OMPD_teams_distribute_parallel_for
:
15913 case OMPD_teams_distribute_parallel_for_simd
:
15915 case OMPD_teams_distribute
:
15916 case OMPD_teams_distribute_simd
:
15917 case OMPD_teams_loop
:
15918 // Do not capture thread_limit-clause expressions.
15920 case OMPD_distribute_parallel_for
:
15921 case OMPD_distribute_parallel_for_simd
:
15923 case OMPD_taskloop
:
15924 case OMPD_taskloop_simd
:
15925 case OMPD_master_taskloop
:
15926 case OMPD_masked_taskloop
:
15927 case OMPD_master_taskloop_simd
:
15928 case OMPD_masked_taskloop_simd
:
15929 case OMPD_parallel_master_taskloop
:
15930 case OMPD_parallel_masked_taskloop
:
15931 case OMPD_parallel_master_taskloop_simd
:
15932 case OMPD_parallel_masked_taskloop_simd
:
15933 case OMPD_target_data
:
15934 case OMPD_target_enter_data
:
15935 case OMPD_target_exit_data
:
15936 case OMPD_target_update
:
15938 case OMPD_parallel
:
15939 case OMPD_parallel_master
:
15940 case OMPD_parallel_masked
:
15941 case OMPD_parallel_sections
:
15942 case OMPD_parallel_for
:
15943 case OMPD_parallel_for_simd
:
15944 case OMPD_parallel_loop
:
15945 case OMPD_target_simd
:
15946 case OMPD_target_parallel
:
15947 case OMPD_target_parallel_for
:
15948 case OMPD_target_parallel_for_simd
:
15949 case OMPD_target_parallel_loop
:
15950 case OMPD_threadprivate
:
15951 case OMPD_allocate
:
15952 case OMPD_taskyield
:
15955 case OMPD_taskwait
:
15956 case OMPD_cancellation_point
:
15960 case OMPD_declare_reduction
:
15961 case OMPD_declare_mapper
:
15962 case OMPD_declare_simd
:
15963 case OMPD_declare_variant
:
15964 case OMPD_begin_declare_variant
:
15965 case OMPD_end_declare_variant
:
15966 case OMPD_declare_target
:
15967 case OMPD_end_declare_target
:
15973 case OMPD_for_simd
:
15974 case OMPD_sections
:
15979 case OMPD_critical
:
15980 case OMPD_taskgroup
:
15981 case OMPD_distribute
:
15984 case OMPD_distribute_simd
:
15985 case OMPD_requires
:
15986 case OMPD_metadirective
:
15987 llvm_unreachable("Unexpected OpenMP directive with thread_limit-clause");
15990 llvm_unreachable("Unknown OpenMP directive");
15993 case OMPC_schedule
:
15995 case OMPD_parallel_for
:
15996 case OMPD_parallel_for_simd
:
15997 case OMPD_distribute_parallel_for
:
15998 case OMPD_distribute_parallel_for_simd
:
15999 case OMPD_teams_distribute_parallel_for
:
16000 case OMPD_teams_distribute_parallel_for_simd
:
16001 case OMPD_target_parallel_for
:
16002 case OMPD_target_parallel_for_simd
:
16003 case OMPD_target_teams_distribute_parallel_for
:
16004 case OMPD_target_teams_distribute_parallel_for_simd
:
16005 CaptureRegion
= OMPD_parallel
;
16008 case OMPD_for_simd
:
16009 // Do not capture schedule-clause expressions.
16012 case OMPD_taskloop
:
16013 case OMPD_taskloop_simd
:
16014 case OMPD_master_taskloop
:
16015 case OMPD_masked_taskloop
:
16016 case OMPD_master_taskloop_simd
:
16017 case OMPD_masked_taskloop_simd
:
16018 case OMPD_parallel_master_taskloop
:
16019 case OMPD_parallel_masked_taskloop
:
16020 case OMPD_parallel_master_taskloop_simd
:
16021 case OMPD_parallel_masked_taskloop_simd
:
16022 case OMPD_target_data
:
16023 case OMPD_target_enter_data
:
16024 case OMPD_target_exit_data
:
16025 case OMPD_target_update
:
16027 case OMPD_teams_distribute
:
16028 case OMPD_teams_distribute_simd
:
16029 case OMPD_target_teams_distribute
:
16030 case OMPD_target_teams_distribute_simd
:
16032 case OMPD_target_simd
:
16033 case OMPD_target_parallel
:
16035 case OMPD_parallel
:
16036 case OMPD_parallel_master
:
16037 case OMPD_parallel_masked
:
16038 case OMPD_parallel_sections
:
16039 case OMPD_threadprivate
:
16040 case OMPD_allocate
:
16041 case OMPD_taskyield
:
16044 case OMPD_taskwait
:
16045 case OMPD_cancellation_point
:
16049 case OMPD_declare_reduction
:
16050 case OMPD_declare_mapper
:
16051 case OMPD_declare_simd
:
16052 case OMPD_declare_variant
:
16053 case OMPD_begin_declare_variant
:
16054 case OMPD_end_declare_variant
:
16055 case OMPD_declare_target
:
16056 case OMPD_end_declare_target
:
16058 case OMPD_teams_loop
:
16059 case OMPD_target_teams_loop
:
16060 case OMPD_parallel_loop
:
16061 case OMPD_target_parallel_loop
:
16065 case OMPD_sections
:
16070 case OMPD_critical
:
16071 case OMPD_taskgroup
:
16072 case OMPD_distribute
:
16075 case OMPD_distribute_simd
:
16076 case OMPD_target_teams
:
16077 case OMPD_requires
:
16078 case OMPD_metadirective
:
16079 llvm_unreachable("Unexpected OpenMP directive with schedule clause");
16082 llvm_unreachable("Unknown OpenMP directive");
16085 case OMPC_dist_schedule
:
16087 case OMPD_teams_distribute_parallel_for
:
16088 case OMPD_teams_distribute_parallel_for_simd
:
16089 case OMPD_teams_distribute
:
16090 case OMPD_teams_distribute_simd
:
16091 case OMPD_target_teams_distribute_parallel_for
:
16092 case OMPD_target_teams_distribute_parallel_for_simd
:
16093 case OMPD_target_teams_distribute
:
16094 case OMPD_target_teams_distribute_simd
:
16095 CaptureRegion
= OMPD_teams
;
16097 case OMPD_distribute_parallel_for
:
16098 case OMPD_distribute_parallel_for_simd
:
16099 case OMPD_distribute
:
16100 case OMPD_distribute_simd
:
16101 // Do not capture dist_schedule-clause expressions.
16103 case OMPD_parallel_for
:
16104 case OMPD_parallel_for_simd
:
16105 case OMPD_target_parallel_for_simd
:
16106 case OMPD_target_parallel_for
:
16108 case OMPD_taskloop
:
16109 case OMPD_taskloop_simd
:
16110 case OMPD_master_taskloop
:
16111 case OMPD_masked_taskloop
:
16112 case OMPD_master_taskloop_simd
:
16113 case OMPD_masked_taskloop_simd
:
16114 case OMPD_parallel_master_taskloop
:
16115 case OMPD_parallel_masked_taskloop
:
16116 case OMPD_parallel_master_taskloop_simd
:
16117 case OMPD_parallel_masked_taskloop_simd
:
16118 case OMPD_target_data
:
16119 case OMPD_target_enter_data
:
16120 case OMPD_target_exit_data
:
16121 case OMPD_target_update
:
16124 case OMPD_target_simd
:
16125 case OMPD_target_parallel
:
16127 case OMPD_parallel
:
16128 case OMPD_parallel_master
:
16129 case OMPD_parallel_masked
:
16130 case OMPD_parallel_sections
:
16131 case OMPD_threadprivate
:
16132 case OMPD_allocate
:
16133 case OMPD_taskyield
:
16136 case OMPD_taskwait
:
16137 case OMPD_cancellation_point
:
16141 case OMPD_declare_reduction
:
16142 case OMPD_declare_mapper
:
16143 case OMPD_declare_simd
:
16144 case OMPD_declare_variant
:
16145 case OMPD_begin_declare_variant
:
16146 case OMPD_end_declare_variant
:
16147 case OMPD_declare_target
:
16148 case OMPD_end_declare_target
:
16150 case OMPD_teams_loop
:
16151 case OMPD_target_teams_loop
:
16152 case OMPD_parallel_loop
:
16153 case OMPD_target_parallel_loop
:
16158 case OMPD_for_simd
:
16159 case OMPD_sections
:
16164 case OMPD_critical
:
16165 case OMPD_taskgroup
:
16168 case OMPD_target_teams
:
16169 case OMPD_requires
:
16170 case OMPD_metadirective
:
16171 llvm_unreachable("Unexpected OpenMP directive with dist_schedule clause");
16174 llvm_unreachable("Unknown OpenMP directive");
16177 case OMPC_ompx_dyn_cgroup_mem
:
16180 case OMPD_target_simd
:
16181 case OMPD_target_teams
:
16182 case OMPD_target_parallel
:
16183 case OMPD_target_teams_distribute
:
16184 case OMPD_target_teams_distribute_simd
:
16185 case OMPD_target_parallel_for
:
16186 case OMPD_target_parallel_for_simd
:
16187 case OMPD_target_parallel_loop
:
16188 case OMPD_target_teams_distribute_parallel_for
:
16189 case OMPD_target_teams_distribute_parallel_for_simd
:
16190 case OMPD_target_teams_loop
:
16191 CaptureRegion
= OMPD_target
;
16194 llvm_unreachable("Unknown OpenMP directive");
16199 case OMPD_target_update
:
16200 case OMPD_target_enter_data
:
16201 case OMPD_target_exit_data
:
16203 case OMPD_target_simd
:
16204 case OMPD_target_teams
:
16205 case OMPD_target_parallel
:
16206 case OMPD_target_teams_distribute
:
16207 case OMPD_target_teams_distribute_simd
:
16208 case OMPD_target_parallel_for
:
16209 case OMPD_target_parallel_for_simd
:
16210 case OMPD_target_parallel_loop
:
16211 case OMPD_target_teams_distribute_parallel_for
:
16212 case OMPD_target_teams_distribute_parallel_for_simd
:
16213 case OMPD_target_teams_loop
:
16214 case OMPD_dispatch
:
16215 CaptureRegion
= OMPD_task
;
16217 case OMPD_target_data
:
16219 // Do not capture device-clause expressions.
16221 case OMPD_teams_distribute_parallel_for
:
16222 case OMPD_teams_distribute_parallel_for_simd
:
16224 case OMPD_teams_distribute
:
16225 case OMPD_teams_distribute_simd
:
16226 case OMPD_distribute_parallel_for
:
16227 case OMPD_distribute_parallel_for_simd
:
16229 case OMPD_taskloop
:
16230 case OMPD_taskloop_simd
:
16231 case OMPD_master_taskloop
:
16232 case OMPD_masked_taskloop
:
16233 case OMPD_master_taskloop_simd
:
16234 case OMPD_masked_taskloop_simd
:
16235 case OMPD_parallel_master_taskloop
:
16236 case OMPD_parallel_masked_taskloop
:
16237 case OMPD_parallel_master_taskloop_simd
:
16238 case OMPD_parallel_masked_taskloop_simd
:
16240 case OMPD_parallel
:
16241 case OMPD_parallel_master
:
16242 case OMPD_parallel_masked
:
16243 case OMPD_parallel_sections
:
16244 case OMPD_parallel_for
:
16245 case OMPD_parallel_for_simd
:
16246 case OMPD_threadprivate
:
16247 case OMPD_allocate
:
16248 case OMPD_taskyield
:
16251 case OMPD_taskwait
:
16252 case OMPD_cancellation_point
:
16256 case OMPD_declare_reduction
:
16257 case OMPD_declare_mapper
:
16258 case OMPD_declare_simd
:
16259 case OMPD_declare_variant
:
16260 case OMPD_begin_declare_variant
:
16261 case OMPD_end_declare_variant
:
16262 case OMPD_declare_target
:
16263 case OMPD_end_declare_target
:
16265 case OMPD_teams_loop
:
16266 case OMPD_parallel_loop
:
16271 case OMPD_for_simd
:
16272 case OMPD_sections
:
16277 case OMPD_critical
:
16278 case OMPD_taskgroup
:
16279 case OMPD_distribute
:
16282 case OMPD_distribute_simd
:
16283 case OMPD_requires
:
16284 case OMPD_metadirective
:
16285 llvm_unreachable("Unexpected OpenMP directive with device-clause");
16288 llvm_unreachable("Unknown OpenMP directive");
16291 case OMPC_grainsize
:
16292 case OMPC_num_tasks
:
16294 case OMPC_priority
:
16297 case OMPD_taskloop
:
16298 case OMPD_taskloop_simd
:
16299 case OMPD_master_taskloop
:
16300 case OMPD_masked_taskloop
:
16301 case OMPD_master_taskloop_simd
:
16302 case OMPD_masked_taskloop_simd
:
16304 case OMPD_parallel_masked_taskloop
:
16305 case OMPD_parallel_masked_taskloop_simd
:
16306 case OMPD_parallel_master_taskloop
:
16307 case OMPD_parallel_master_taskloop_simd
:
16308 CaptureRegion
= OMPD_parallel
;
16310 case OMPD_target_update
:
16311 case OMPD_target_enter_data
:
16312 case OMPD_target_exit_data
:
16314 case OMPD_target_simd
:
16315 case OMPD_target_teams
:
16316 case OMPD_target_parallel
:
16317 case OMPD_target_teams_distribute
:
16318 case OMPD_target_teams_distribute_simd
:
16319 case OMPD_target_parallel_for
:
16320 case OMPD_target_parallel_for_simd
:
16321 case OMPD_target_teams_distribute_parallel_for
:
16322 case OMPD_target_teams_distribute_parallel_for_simd
:
16323 case OMPD_target_data
:
16324 case OMPD_teams_distribute_parallel_for
:
16325 case OMPD_teams_distribute_parallel_for_simd
:
16327 case OMPD_teams_distribute
:
16328 case OMPD_teams_distribute_simd
:
16329 case OMPD_distribute_parallel_for
:
16330 case OMPD_distribute_parallel_for_simd
:
16332 case OMPD_parallel
:
16333 case OMPD_parallel_master
:
16334 case OMPD_parallel_masked
:
16335 case OMPD_parallel_sections
:
16336 case OMPD_parallel_for
:
16337 case OMPD_parallel_for_simd
:
16338 case OMPD_threadprivate
:
16339 case OMPD_allocate
:
16340 case OMPD_taskyield
:
16343 case OMPD_taskwait
:
16344 case OMPD_cancellation_point
:
16348 case OMPD_declare_reduction
:
16349 case OMPD_declare_mapper
:
16350 case OMPD_declare_simd
:
16351 case OMPD_declare_variant
:
16352 case OMPD_begin_declare_variant
:
16353 case OMPD_end_declare_variant
:
16354 case OMPD_declare_target
:
16355 case OMPD_end_declare_target
:
16357 case OMPD_teams_loop
:
16358 case OMPD_target_teams_loop
:
16359 case OMPD_parallel_loop
:
16360 case OMPD_target_parallel_loop
:
16365 case OMPD_for_simd
:
16366 case OMPD_sections
:
16371 case OMPD_critical
:
16372 case OMPD_taskgroup
:
16373 case OMPD_distribute
:
16376 case OMPD_distribute_simd
:
16377 case OMPD_requires
:
16378 case OMPD_metadirective
:
16379 llvm_unreachable("Unexpected OpenMP directive with grainsize-clause");
16382 llvm_unreachable("Unknown OpenMP directive");
16385 case OMPC_novariants
:
16386 case OMPC_nocontext
:
16388 case OMPD_dispatch
:
16389 CaptureRegion
= OMPD_task
;
16392 llvm_unreachable("Unexpected OpenMP directive");
16396 // Do not capture filter-clause expressions.
16399 if (DKind
== OMPD_metadirective
) {
16400 CaptureRegion
= OMPD_metadirective
;
16401 } else if (DKind
== OMPD_unknown
) {
16402 llvm_unreachable("Unknown OpenMP directive");
16404 llvm_unreachable("Unexpected OpenMP directive with when clause");
16407 case OMPC_firstprivate
:
16408 case OMPC_lastprivate
:
16409 case OMPC_reduction
:
16410 case OMPC_task_reduction
:
16411 case OMPC_in_reduction
:
16414 case OMPC_proc_bind
:
16418 case OMPC_allocator
:
16419 case OMPC_collapse
:
16424 case OMPC_copyprivate
:
16428 case OMPC_mergeable
:
16429 case OMPC_threadprivate
:
16430 case OMPC_allocate
:
16449 case OMPC_defaultmap
:
16454 case OMPC_use_device_ptr
:
16455 case OMPC_use_device_addr
:
16456 case OMPC_is_device_ptr
:
16457 case OMPC_unified_address
:
16458 case OMPC_unified_shared_memory
:
16459 case OMPC_reverse_offload
:
16460 case OMPC_dynamic_allocators
:
16461 case OMPC_atomic_default_mem_order
:
16462 case OMPC_device_type
:
16464 case OMPC_nontemporal
:
16467 case OMPC_severity
:
16471 case OMPC_inclusive
:
16472 case OMPC_exclusive
:
16473 case OMPC_uses_allocators
:
16474 case OMPC_affinity
:
16477 llvm_unreachable("Unexpected OpenMP clause.");
16479 return CaptureRegion
;
16482 OMPClause
*Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier
,
16483 Expr
*Condition
, SourceLocation StartLoc
,
16484 SourceLocation LParenLoc
,
16485 SourceLocation NameModifierLoc
,
16486 SourceLocation ColonLoc
,
16487 SourceLocation EndLoc
) {
16488 Expr
*ValExpr
= Condition
;
16489 Stmt
*HelperValStmt
= nullptr;
16490 OpenMPDirectiveKind CaptureRegion
= OMPD_unknown
;
16491 if (!Condition
->isValueDependent() && !Condition
->isTypeDependent() &&
16492 !Condition
->isInstantiationDependent() &&
16493 !Condition
->containsUnexpandedParameterPack()) {
16494 ExprResult Val
= CheckBooleanCondition(StartLoc
, Condition
);
16495 if (Val
.isInvalid())
16498 ValExpr
= Val
.get();
16500 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
16501 CaptureRegion
= getOpenMPCaptureRegionForClause(
16502 DKind
, OMPC_if
, LangOpts
.OpenMP
, NameModifier
);
16503 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
16504 ValExpr
= MakeFullExpr(ValExpr
).get();
16505 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
16506 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
16507 HelperValStmt
= buildPreInits(Context
, Captures
);
16511 return new (Context
)
16512 OMPIfClause(NameModifier
, ValExpr
, HelperValStmt
, CaptureRegion
, StartLoc
,
16513 LParenLoc
, NameModifierLoc
, ColonLoc
, EndLoc
);
16516 OMPClause
*Sema::ActOnOpenMPFinalClause(Expr
*Condition
,
16517 SourceLocation StartLoc
,
16518 SourceLocation LParenLoc
,
16519 SourceLocation EndLoc
) {
16520 Expr
*ValExpr
= Condition
;
16521 Stmt
*HelperValStmt
= nullptr;
16522 OpenMPDirectiveKind CaptureRegion
= OMPD_unknown
;
16523 if (!Condition
->isValueDependent() && !Condition
->isTypeDependent() &&
16524 !Condition
->isInstantiationDependent() &&
16525 !Condition
->containsUnexpandedParameterPack()) {
16526 ExprResult Val
= CheckBooleanCondition(StartLoc
, Condition
);
16527 if (Val
.isInvalid())
16530 ValExpr
= MakeFullExpr(Val
.get()).get();
16532 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
16534 getOpenMPCaptureRegionForClause(DKind
, OMPC_final
, LangOpts
.OpenMP
);
16535 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
16536 ValExpr
= MakeFullExpr(ValExpr
).get();
16537 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
16538 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
16539 HelperValStmt
= buildPreInits(Context
, Captures
);
16543 return new (Context
) OMPFinalClause(ValExpr
, HelperValStmt
, CaptureRegion
,
16544 StartLoc
, LParenLoc
, EndLoc
);
16547 ExprResult
Sema::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc
,
16550 return ExprError();
16552 class IntConvertDiagnoser
: public ICEConvertDiagnoser
{
16554 IntConvertDiagnoser()
16555 : ICEConvertDiagnoser(/*AllowScopedEnumerations*/ false, false, true) {}
16556 SemaDiagnosticBuilder
diagnoseNotInt(Sema
&S
, SourceLocation Loc
,
16557 QualType T
) override
{
16558 return S
.Diag(Loc
, diag::err_omp_not_integral
) << T
;
16560 SemaDiagnosticBuilder
diagnoseIncomplete(Sema
&S
, SourceLocation Loc
,
16561 QualType T
) override
{
16562 return S
.Diag(Loc
, diag::err_omp_incomplete_type
) << T
;
16564 SemaDiagnosticBuilder
diagnoseExplicitConv(Sema
&S
, SourceLocation Loc
,
16566 QualType ConvTy
) override
{
16567 return S
.Diag(Loc
, diag::err_omp_explicit_conversion
) << T
<< ConvTy
;
16569 SemaDiagnosticBuilder
noteExplicitConv(Sema
&S
, CXXConversionDecl
*Conv
,
16570 QualType ConvTy
) override
{
16571 return S
.Diag(Conv
->getLocation(), diag::note_omp_conversion_here
)
16572 << ConvTy
->isEnumeralType() << ConvTy
;
16574 SemaDiagnosticBuilder
diagnoseAmbiguous(Sema
&S
, SourceLocation Loc
,
16575 QualType T
) override
{
16576 return S
.Diag(Loc
, diag::err_omp_ambiguous_conversion
) << T
;
16578 SemaDiagnosticBuilder
noteAmbiguous(Sema
&S
, CXXConversionDecl
*Conv
,
16579 QualType ConvTy
) override
{
16580 return S
.Diag(Conv
->getLocation(), diag::note_omp_conversion_here
)
16581 << ConvTy
->isEnumeralType() << ConvTy
;
16583 SemaDiagnosticBuilder
diagnoseConversion(Sema
&, SourceLocation
, QualType
,
16584 QualType
) override
{
16585 llvm_unreachable("conversion functions are permitted");
16587 } ConvertDiagnoser
;
16588 return PerformContextualImplicitConversion(Loc
, Op
, ConvertDiagnoser
);
16592 isNonNegativeIntegerValue(Expr
*&ValExpr
, Sema
&SemaRef
, OpenMPClauseKind CKind
,
16593 bool StrictlyPositive
, bool BuildCapture
= false,
16594 OpenMPDirectiveKind DKind
= OMPD_unknown
,
16595 OpenMPDirectiveKind
*CaptureRegion
= nullptr,
16596 Stmt
**HelperValStmt
= nullptr) {
16597 if (!ValExpr
->isTypeDependent() && !ValExpr
->isValueDependent() &&
16598 !ValExpr
->isInstantiationDependent()) {
16599 SourceLocation Loc
= ValExpr
->getExprLoc();
16601 SemaRef
.PerformOpenMPImplicitIntegerConversion(Loc
, ValExpr
);
16602 if (Value
.isInvalid())
16605 ValExpr
= Value
.get();
16606 // The expression must evaluate to a non-negative integer value.
16607 if (std::optional
<llvm::APSInt
> Result
=
16608 ValExpr
->getIntegerConstantExpr(SemaRef
.Context
)) {
16609 if (Result
->isSigned() &&
16610 !((!StrictlyPositive
&& Result
->isNonNegative()) ||
16611 (StrictlyPositive
&& Result
->isStrictlyPositive()))) {
16612 SemaRef
.Diag(Loc
, diag::err_omp_negative_expression_in_clause
)
16613 << getOpenMPClauseName(CKind
) << (StrictlyPositive
? 1 : 0)
16614 << ValExpr
->getSourceRange();
16621 getOpenMPCaptureRegionForClause(DKind
, CKind
, SemaRef
.LangOpts
.OpenMP
);
16622 if (*CaptureRegion
!= OMPD_unknown
&&
16623 !SemaRef
.CurContext
->isDependentContext()) {
16624 ValExpr
= SemaRef
.MakeFullExpr(ValExpr
).get();
16625 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
16626 ValExpr
= tryBuildCapture(SemaRef
, ValExpr
, Captures
).get();
16627 *HelperValStmt
= buildPreInits(SemaRef
.Context
, Captures
);
16633 OMPClause
*Sema::ActOnOpenMPNumThreadsClause(Expr
*NumThreads
,
16634 SourceLocation StartLoc
,
16635 SourceLocation LParenLoc
,
16636 SourceLocation EndLoc
) {
16637 Expr
*ValExpr
= NumThreads
;
16638 Stmt
*HelperValStmt
= nullptr;
16640 // OpenMP [2.5, Restrictions]
16641 // The num_threads expression must evaluate to a positive integer value.
16642 if (!isNonNegativeIntegerValue(ValExpr
, *this, OMPC_num_threads
,
16643 /*StrictlyPositive=*/true))
16646 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
16647 OpenMPDirectiveKind CaptureRegion
=
16648 getOpenMPCaptureRegionForClause(DKind
, OMPC_num_threads
, LangOpts
.OpenMP
);
16649 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
16650 ValExpr
= MakeFullExpr(ValExpr
).get();
16651 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
16652 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
16653 HelperValStmt
= buildPreInits(Context
, Captures
);
16656 return new (Context
) OMPNumThreadsClause(
16657 ValExpr
, HelperValStmt
, CaptureRegion
, StartLoc
, LParenLoc
, EndLoc
);
16660 ExprResult
Sema::VerifyPositiveIntegerConstantInClause(Expr
*E
,
16661 OpenMPClauseKind CKind
,
16662 bool StrictlyPositive
,
16663 bool SuppressExprDiags
) {
16665 return ExprError();
16666 if (E
->isValueDependent() || E
->isTypeDependent() ||
16667 E
->isInstantiationDependent() || E
->containsUnexpandedParameterPack())
16670 llvm::APSInt Result
;
16672 if (SuppressExprDiags
) {
16673 // Use a custom diagnoser that suppresses 'note' diagnostics about the
16675 struct SuppressedDiagnoser
: public Sema::VerifyICEDiagnoser
{
16676 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
16677 Sema::SemaDiagnosticBuilder
diagnoseNotICE(Sema
&S
,
16678 SourceLocation Loc
) override
{
16679 llvm_unreachable("Diagnostic suppressed");
16682 ICE
= VerifyIntegerConstantExpression(E
, &Result
, Diagnoser
, AllowFold
);
16684 ICE
= VerifyIntegerConstantExpression(E
, &Result
, /*FIXME*/ AllowFold
);
16686 if (ICE
.isInvalid())
16687 return ExprError();
16689 if ((StrictlyPositive
&& !Result
.isStrictlyPositive()) ||
16690 (!StrictlyPositive
&& !Result
.isNonNegative())) {
16691 Diag(E
->getExprLoc(), diag::err_omp_negative_expression_in_clause
)
16692 << getOpenMPClauseName(CKind
) << (StrictlyPositive
? 1 : 0)
16693 << E
->getSourceRange();
16694 return ExprError();
16696 if ((CKind
== OMPC_aligned
|| CKind
== OMPC_align
) && !Result
.isPowerOf2()) {
16697 Diag(E
->getExprLoc(), diag::warn_omp_alignment_not_power_of_two
)
16698 << E
->getSourceRange();
16699 return ExprError();
16701 if (CKind
== OMPC_collapse
&& DSAStack
->getAssociatedLoops() == 1)
16702 DSAStack
->setAssociatedLoops(Result
.getExtValue());
16703 else if (CKind
== OMPC_ordered
)
16704 DSAStack
->setAssociatedLoops(Result
.getExtValue());
16708 OMPClause
*Sema::ActOnOpenMPSafelenClause(Expr
*Len
, SourceLocation StartLoc
,
16709 SourceLocation LParenLoc
,
16710 SourceLocation EndLoc
) {
16711 // OpenMP [2.8.1, simd construct, Description]
16712 // The parameter of the safelen clause must be a constant
16713 // positive integer expression.
16714 ExprResult Safelen
= VerifyPositiveIntegerConstantInClause(Len
, OMPC_safelen
);
16715 if (Safelen
.isInvalid())
16717 return new (Context
)
16718 OMPSafelenClause(Safelen
.get(), StartLoc
, LParenLoc
, EndLoc
);
16721 OMPClause
*Sema::ActOnOpenMPSimdlenClause(Expr
*Len
, SourceLocation StartLoc
,
16722 SourceLocation LParenLoc
,
16723 SourceLocation EndLoc
) {
16724 // OpenMP [2.8.1, simd construct, Description]
16725 // The parameter of the simdlen clause must be a constant
16726 // positive integer expression.
16727 ExprResult Simdlen
= VerifyPositiveIntegerConstantInClause(Len
, OMPC_simdlen
);
16728 if (Simdlen
.isInvalid())
16730 return new (Context
)
16731 OMPSimdlenClause(Simdlen
.get(), StartLoc
, LParenLoc
, EndLoc
);
16734 /// Tries to find omp_allocator_handle_t type.
16735 static bool findOMPAllocatorHandleT(Sema
&S
, SourceLocation Loc
,
16736 DSAStackTy
*Stack
) {
16737 if (!Stack
->getOMPAllocatorHandleT().isNull())
16740 // Set the allocator handle type.
16741 IdentifierInfo
*II
= &S
.PP
.getIdentifierTable().get("omp_allocator_handle_t");
16742 ParsedType PT
= S
.getTypeName(*II
, Loc
, S
.getCurScope());
16743 if (!PT
.getAsOpaquePtr() || PT
.get().isNull()) {
16744 S
.Diag(Loc
, diag::err_omp_implied_type_not_found
)
16745 << "omp_allocator_handle_t";
16748 QualType AllocatorHandleEnumTy
= PT
.get();
16749 AllocatorHandleEnumTy
.addConst();
16750 Stack
->setOMPAllocatorHandleT(AllocatorHandleEnumTy
);
16752 // Fill the predefined allocator map.
16753 bool ErrorFound
= false;
16754 for (int I
= 0; I
< OMPAllocateDeclAttr::OMPUserDefinedMemAlloc
; ++I
) {
16755 auto AllocatorKind
= static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I
);
16756 StringRef Allocator
=
16757 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind
);
16758 DeclarationName AllocatorName
= &S
.getASTContext().Idents
.get(Allocator
);
16759 auto *VD
= dyn_cast_or_null
<ValueDecl
>(
16760 S
.LookupSingleName(S
.TUScope
, AllocatorName
, Loc
, Sema::LookupAnyName
));
16765 QualType AllocatorType
=
16766 VD
->getType().getNonLValueExprType(S
.getASTContext());
16767 ExprResult Res
= S
.BuildDeclRefExpr(VD
, AllocatorType
, VK_LValue
, Loc
);
16768 if (!Res
.isUsable()) {
16772 Res
= S
.PerformImplicitConversion(Res
.get(), AllocatorHandleEnumTy
,
16773 Sema::AA_Initializing
,
16774 /* AllowExplicit */ true);
16775 if (!Res
.isUsable()) {
16779 Stack
->setAllocator(AllocatorKind
, Res
.get());
16782 S
.Diag(Loc
, diag::err_omp_implied_type_not_found
)
16783 << "omp_allocator_handle_t";
16790 OMPClause
*Sema::ActOnOpenMPAllocatorClause(Expr
*A
, SourceLocation StartLoc
,
16791 SourceLocation LParenLoc
,
16792 SourceLocation EndLoc
) {
16793 // OpenMP [2.11.3, allocate Directive, Description]
16794 // allocator is an expression of omp_allocator_handle_t type.
16795 if (!findOMPAllocatorHandleT(*this, A
->getExprLoc(), DSAStack
))
16798 ExprResult Allocator
= DefaultLvalueConversion(A
);
16799 if (Allocator
.isInvalid())
16801 Allocator
= PerformImplicitConversion(Allocator
.get(),
16802 DSAStack
->getOMPAllocatorHandleT(),
16803 Sema::AA_Initializing
,
16804 /*AllowExplicit=*/true);
16805 if (Allocator
.isInvalid())
16807 return new (Context
)
16808 OMPAllocatorClause(Allocator
.get(), StartLoc
, LParenLoc
, EndLoc
);
16811 OMPClause
*Sema::ActOnOpenMPCollapseClause(Expr
*NumForLoops
,
16812 SourceLocation StartLoc
,
16813 SourceLocation LParenLoc
,
16814 SourceLocation EndLoc
) {
16815 // OpenMP [2.7.1, loop construct, Description]
16816 // OpenMP [2.8.1, simd construct, Description]
16817 // OpenMP [2.9.6, distribute construct, Description]
16818 // The parameter of the collapse clause must be a constant
16819 // positive integer expression.
16820 ExprResult NumForLoopsResult
=
16821 VerifyPositiveIntegerConstantInClause(NumForLoops
, OMPC_collapse
);
16822 if (NumForLoopsResult
.isInvalid())
16824 return new (Context
)
16825 OMPCollapseClause(NumForLoopsResult
.get(), StartLoc
, LParenLoc
, EndLoc
);
16828 OMPClause
*Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc
,
16829 SourceLocation EndLoc
,
16830 SourceLocation LParenLoc
,
16831 Expr
*NumForLoops
) {
16832 // OpenMP [2.7.1, loop construct, Description]
16833 // OpenMP [2.8.1, simd construct, Description]
16834 // OpenMP [2.9.6, distribute construct, Description]
16835 // The parameter of the ordered clause must be a constant
16836 // positive integer expression if any.
16837 if (NumForLoops
&& LParenLoc
.isValid()) {
16838 ExprResult NumForLoopsResult
=
16839 VerifyPositiveIntegerConstantInClause(NumForLoops
, OMPC_ordered
);
16840 if (NumForLoopsResult
.isInvalid())
16842 NumForLoops
= NumForLoopsResult
.get();
16844 NumForLoops
= nullptr;
16846 auto *Clause
= OMPOrderedClause::Create(
16847 Context
, NumForLoops
, NumForLoops
? DSAStack
->getAssociatedLoops() : 0,
16848 StartLoc
, LParenLoc
, EndLoc
);
16849 DSAStack
->setOrderedRegion(/*IsOrdered=*/true, NumForLoops
, Clause
);
16853 OMPClause
*Sema::ActOnOpenMPSimpleClause(
16854 OpenMPClauseKind Kind
, unsigned Argument
, SourceLocation ArgumentLoc
,
16855 SourceLocation StartLoc
, SourceLocation LParenLoc
, SourceLocation EndLoc
) {
16856 OMPClause
*Res
= nullptr;
16859 Res
= ActOnOpenMPDefaultClause(static_cast<DefaultKind
>(Argument
),
16860 ArgumentLoc
, StartLoc
, LParenLoc
, EndLoc
);
16862 case OMPC_proc_bind
:
16863 Res
= ActOnOpenMPProcBindClause(static_cast<ProcBindKind
>(Argument
),
16864 ArgumentLoc
, StartLoc
, LParenLoc
, EndLoc
);
16866 case OMPC_atomic_default_mem_order
:
16867 Res
= ActOnOpenMPAtomicDefaultMemOrderClause(
16868 static_cast<OpenMPAtomicDefaultMemOrderClauseKind
>(Argument
),
16869 ArgumentLoc
, StartLoc
, LParenLoc
, EndLoc
);
16872 Res
= ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind
>(Argument
),
16873 ArgumentLoc
, StartLoc
, LParenLoc
, EndLoc
);
16876 Res
= ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind
>(Argument
),
16877 ArgumentLoc
, StartLoc
, LParenLoc
, EndLoc
);
16880 Res
= ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind
>(Argument
),
16881 ArgumentLoc
, StartLoc
, LParenLoc
, EndLoc
);
16883 case OMPC_severity
:
16884 Res
= ActOnOpenMPSeverityClause(
16885 static_cast<OpenMPSeverityClauseKind
>(Argument
), ArgumentLoc
, StartLoc
,
16886 LParenLoc
, EndLoc
);
16890 case OMPC_num_threads
:
16894 case OMPC_allocator
:
16895 case OMPC_collapse
:
16896 case OMPC_schedule
:
16898 case OMPC_firstprivate
:
16899 case OMPC_lastprivate
:
16901 case OMPC_reduction
:
16902 case OMPC_task_reduction
:
16903 case OMPC_in_reduction
:
16907 case OMPC_copyprivate
:
16911 case OMPC_mergeable
:
16912 case OMPC_threadprivate
:
16913 case OMPC_allocate
:
16930 case OMPC_num_teams
:
16931 case OMPC_thread_limit
:
16932 case OMPC_priority
:
16933 case OMPC_grainsize
:
16935 case OMPC_num_tasks
:
16937 case OMPC_dist_schedule
:
16938 case OMPC_defaultmap
:
16943 case OMPC_use_device_ptr
:
16944 case OMPC_use_device_addr
:
16945 case OMPC_is_device_ptr
:
16946 case OMPC_has_device_addr
:
16947 case OMPC_unified_address
:
16948 case OMPC_unified_shared_memory
:
16949 case OMPC_reverse_offload
:
16950 case OMPC_dynamic_allocators
:
16951 case OMPC_device_type
:
16953 case OMPC_nontemporal
:
16955 case OMPC_novariants
:
16956 case OMPC_nocontext
:
16958 case OMPC_inclusive
:
16959 case OMPC_exclusive
:
16960 case OMPC_uses_allocators
:
16961 case OMPC_affinity
:
16965 llvm_unreachable("Clause is not allowed.");
16971 getListOfPossibleValues(OpenMPClauseKind K
, unsigned First
, unsigned Last
,
16972 ArrayRef
<unsigned> Exclude
= std::nullopt
) {
16973 SmallString
<256> Buffer
;
16974 llvm::raw_svector_ostream
Out(Buffer
);
16975 unsigned Skipped
= Exclude
.size();
16976 for (unsigned I
= First
; I
< Last
; ++I
) {
16977 if (llvm::is_contained(Exclude
, I
)) {
16981 Out
<< "'" << getOpenMPSimpleClauseTypeName(K
, I
) << "'";
16982 if (I
+ Skipped
+ 2 == Last
)
16984 else if (I
+ Skipped
+ 1 != Last
)
16987 return std::string(Out
.str());
16990 OMPClause
*Sema::ActOnOpenMPDefaultClause(DefaultKind Kind
,
16991 SourceLocation KindKwLoc
,
16992 SourceLocation StartLoc
,
16993 SourceLocation LParenLoc
,
16994 SourceLocation EndLoc
) {
16995 if (Kind
== OMP_DEFAULT_unknown
) {
16996 Diag(KindKwLoc
, diag::err_omp_unexpected_clause_value
)
16997 << getListOfPossibleValues(OMPC_default
, /*First=*/0,
16998 /*Last=*/unsigned(OMP_DEFAULT_unknown
))
16999 << getOpenMPClauseName(OMPC_default
);
17004 case OMP_DEFAULT_none
:
17005 DSAStack
->setDefaultDSANone(KindKwLoc
);
17007 case OMP_DEFAULT_shared
:
17008 DSAStack
->setDefaultDSAShared(KindKwLoc
);
17010 case OMP_DEFAULT_firstprivate
:
17011 DSAStack
->setDefaultDSAFirstPrivate(KindKwLoc
);
17013 case OMP_DEFAULT_private
:
17014 DSAStack
->setDefaultDSAPrivate(KindKwLoc
);
17017 llvm_unreachable("DSA unexpected in OpenMP default clause");
17020 return new (Context
)
17021 OMPDefaultClause(Kind
, KindKwLoc
, StartLoc
, LParenLoc
, EndLoc
);
17024 OMPClause
*Sema::ActOnOpenMPProcBindClause(ProcBindKind Kind
,
17025 SourceLocation KindKwLoc
,
17026 SourceLocation StartLoc
,
17027 SourceLocation LParenLoc
,
17028 SourceLocation EndLoc
) {
17029 if (Kind
== OMP_PROC_BIND_unknown
) {
17030 Diag(KindKwLoc
, diag::err_omp_unexpected_clause_value
)
17031 << getListOfPossibleValues(OMPC_proc_bind
,
17032 /*First=*/unsigned(OMP_PROC_BIND_master
),
17034 unsigned(LangOpts
.OpenMP
> 50
17035 ? OMP_PROC_BIND_primary
17036 : OMP_PROC_BIND_spread
) +
17038 << getOpenMPClauseName(OMPC_proc_bind
);
17041 if (Kind
== OMP_PROC_BIND_primary
&& LangOpts
.OpenMP
< 51)
17042 Diag(KindKwLoc
, diag::err_omp_unexpected_clause_value
)
17043 << getListOfPossibleValues(OMPC_proc_bind
,
17044 /*First=*/unsigned(OMP_PROC_BIND_master
),
17046 unsigned(OMP_PROC_BIND_spread
) + 1)
17047 << getOpenMPClauseName(OMPC_proc_bind
);
17048 return new (Context
)
17049 OMPProcBindClause(Kind
, KindKwLoc
, StartLoc
, LParenLoc
, EndLoc
);
17052 OMPClause
*Sema::ActOnOpenMPAtomicDefaultMemOrderClause(
17053 OpenMPAtomicDefaultMemOrderClauseKind Kind
, SourceLocation KindKwLoc
,
17054 SourceLocation StartLoc
, SourceLocation LParenLoc
, SourceLocation EndLoc
) {
17055 if (Kind
== OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
) {
17056 Diag(KindKwLoc
, diag::err_omp_unexpected_clause_value
)
17057 << getListOfPossibleValues(
17058 OMPC_atomic_default_mem_order
, /*First=*/0,
17059 /*Last=*/OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
)
17060 << getOpenMPClauseName(OMPC_atomic_default_mem_order
);
17063 return new (Context
) OMPAtomicDefaultMemOrderClause(Kind
, KindKwLoc
, StartLoc
,
17064 LParenLoc
, EndLoc
);
17067 OMPClause
*Sema::ActOnOpenMPAtClause(OpenMPAtClauseKind Kind
,
17068 SourceLocation KindKwLoc
,
17069 SourceLocation StartLoc
,
17070 SourceLocation LParenLoc
,
17071 SourceLocation EndLoc
) {
17072 if (Kind
== OMPC_AT_unknown
) {
17073 Diag(KindKwLoc
, diag::err_omp_unexpected_clause_value
)
17074 << getListOfPossibleValues(OMPC_at
, /*First=*/0,
17075 /*Last=*/OMPC_AT_unknown
)
17076 << getOpenMPClauseName(OMPC_at
);
17079 return new (Context
)
17080 OMPAtClause(Kind
, KindKwLoc
, StartLoc
, LParenLoc
, EndLoc
);
17083 OMPClause
*Sema::ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind
,
17084 SourceLocation KindKwLoc
,
17085 SourceLocation StartLoc
,
17086 SourceLocation LParenLoc
,
17087 SourceLocation EndLoc
) {
17088 if (Kind
== OMPC_SEVERITY_unknown
) {
17089 Diag(KindKwLoc
, diag::err_omp_unexpected_clause_value
)
17090 << getListOfPossibleValues(OMPC_severity
, /*First=*/0,
17091 /*Last=*/OMPC_SEVERITY_unknown
)
17092 << getOpenMPClauseName(OMPC_severity
);
17095 return new (Context
)
17096 OMPSeverityClause(Kind
, KindKwLoc
, StartLoc
, LParenLoc
, EndLoc
);
17099 OMPClause
*Sema::ActOnOpenMPMessageClause(Expr
*ME
, SourceLocation StartLoc
,
17100 SourceLocation LParenLoc
,
17101 SourceLocation EndLoc
) {
17102 assert(ME
&& "NULL expr in Message clause");
17103 if (!isa
<StringLiteral
>(ME
)) {
17104 Diag(ME
->getBeginLoc(), diag::warn_clause_expected_string
)
17105 << getOpenMPClauseName(OMPC_message
);
17108 return new (Context
) OMPMessageClause(ME
, StartLoc
, LParenLoc
, EndLoc
);
17111 OMPClause
*Sema::ActOnOpenMPOrderClause(
17112 OpenMPOrderClauseModifier Modifier
, OpenMPOrderClauseKind Kind
,
17113 SourceLocation StartLoc
, SourceLocation LParenLoc
, SourceLocation MLoc
,
17114 SourceLocation KindLoc
, SourceLocation EndLoc
) {
17115 if (Kind
!= OMPC_ORDER_concurrent
||
17116 (LangOpts
.OpenMP
< 51 && MLoc
.isValid())) {
17117 // Kind should be concurrent,
17118 // Modifiers introduced in OpenMP 5.1
17119 static_assert(OMPC_ORDER_unknown
> 0,
17120 "OMPC_ORDER_unknown not greater than 0");
17122 Diag(KindLoc
, diag::err_omp_unexpected_clause_value
)
17123 << getListOfPossibleValues(OMPC_order
,
17125 /*Last=*/OMPC_ORDER_unknown
)
17126 << getOpenMPClauseName(OMPC_order
);
17129 if (LangOpts
.OpenMP
>= 51) {
17130 if (Modifier
== OMPC_ORDER_MODIFIER_unknown
&& MLoc
.isValid()) {
17131 Diag(MLoc
, diag::err_omp_unexpected_clause_value
)
17132 << getListOfPossibleValues(OMPC_order
,
17133 /*First=*/OMPC_ORDER_MODIFIER_unknown
+ 1,
17134 /*Last=*/OMPC_ORDER_MODIFIER_last
)
17135 << getOpenMPClauseName(OMPC_order
);
17137 DSAStack
->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
17138 if (DSAStack
->getCurScope()) {
17139 // mark the current scope with 'order' flag
17140 unsigned existingFlags
= DSAStack
->getCurScope()->getFlags();
17141 DSAStack
->getCurScope()->setFlags(existingFlags
|
17142 Scope::OpenMPOrderClauseScope
);
17146 return new (Context
) OMPOrderClause(Kind
, KindLoc
, StartLoc
, LParenLoc
,
17147 EndLoc
, Modifier
, MLoc
);
17150 OMPClause
*Sema::ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind
,
17151 SourceLocation KindKwLoc
,
17152 SourceLocation StartLoc
,
17153 SourceLocation LParenLoc
,
17154 SourceLocation EndLoc
) {
17155 if (Kind
== OMPC_DEPEND_unknown
|| Kind
== OMPC_DEPEND_source
||
17156 Kind
== OMPC_DEPEND_sink
|| Kind
== OMPC_DEPEND_depobj
) {
17157 SmallVector
<unsigned> Except
= {
17158 OMPC_DEPEND_source
, OMPC_DEPEND_sink
, OMPC_DEPEND_depobj
,
17159 OMPC_DEPEND_outallmemory
, OMPC_DEPEND_inoutallmemory
};
17160 if (LangOpts
.OpenMP
< 51)
17161 Except
.push_back(OMPC_DEPEND_inoutset
);
17162 Diag(KindKwLoc
, diag::err_omp_unexpected_clause_value
)
17163 << getListOfPossibleValues(OMPC_depend
, /*First=*/0,
17164 /*Last=*/OMPC_DEPEND_unknown
, Except
)
17165 << getOpenMPClauseName(OMPC_update
);
17168 return OMPUpdateClause::Create(Context
, StartLoc
, LParenLoc
, KindKwLoc
, Kind
,
17172 OMPClause
*Sema::ActOnOpenMPSizesClause(ArrayRef
<Expr
*> SizeExprs
,
17173 SourceLocation StartLoc
,
17174 SourceLocation LParenLoc
,
17175 SourceLocation EndLoc
) {
17176 for (Expr
*SizeExpr
: SizeExprs
) {
17177 ExprResult NumForLoopsResult
= VerifyPositiveIntegerConstantInClause(
17178 SizeExpr
, OMPC_sizes
, /*StrictlyPositive=*/true);
17179 if (!NumForLoopsResult
.isUsable())
17183 DSAStack
->setAssociatedLoops(SizeExprs
.size());
17184 return OMPSizesClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
,
17188 OMPClause
*Sema::ActOnOpenMPFullClause(SourceLocation StartLoc
,
17189 SourceLocation EndLoc
) {
17190 return OMPFullClause::Create(Context
, StartLoc
, EndLoc
);
17193 OMPClause
*Sema::ActOnOpenMPPartialClause(Expr
*FactorExpr
,
17194 SourceLocation StartLoc
,
17195 SourceLocation LParenLoc
,
17196 SourceLocation EndLoc
) {
17198 // If an argument is specified, it must be a constant (or an unevaluated
17199 // template expression).
17200 ExprResult FactorResult
= VerifyPositiveIntegerConstantInClause(
17201 FactorExpr
, OMPC_partial
, /*StrictlyPositive=*/true);
17202 if (FactorResult
.isInvalid())
17204 FactorExpr
= FactorResult
.get();
17207 return OMPPartialClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
,
17211 OMPClause
*Sema::ActOnOpenMPAlignClause(Expr
*A
, SourceLocation StartLoc
,
17212 SourceLocation LParenLoc
,
17213 SourceLocation EndLoc
) {
17214 ExprResult AlignVal
;
17215 AlignVal
= VerifyPositiveIntegerConstantInClause(A
, OMPC_align
);
17216 if (AlignVal
.isInvalid())
17218 return OMPAlignClause::Create(Context
, AlignVal
.get(), StartLoc
, LParenLoc
,
17222 OMPClause
*Sema::ActOnOpenMPSingleExprWithArgClause(
17223 OpenMPClauseKind Kind
, ArrayRef
<unsigned> Argument
, Expr
*Expr
,
17224 SourceLocation StartLoc
, SourceLocation LParenLoc
,
17225 ArrayRef
<SourceLocation
> ArgumentLoc
, SourceLocation DelimLoc
,
17226 SourceLocation EndLoc
) {
17227 OMPClause
*Res
= nullptr;
17229 case OMPC_schedule
:
17230 enum { Modifier1
, Modifier2
, ScheduleKind
, NumberOfElements
};
17231 assert(Argument
.size() == NumberOfElements
&&
17232 ArgumentLoc
.size() == NumberOfElements
);
17233 Res
= ActOnOpenMPScheduleClause(
17234 static_cast<OpenMPScheduleClauseModifier
>(Argument
[Modifier1
]),
17235 static_cast<OpenMPScheduleClauseModifier
>(Argument
[Modifier2
]),
17236 static_cast<OpenMPScheduleClauseKind
>(Argument
[ScheduleKind
]), Expr
,
17237 StartLoc
, LParenLoc
, ArgumentLoc
[Modifier1
], ArgumentLoc
[Modifier2
],
17238 ArgumentLoc
[ScheduleKind
], DelimLoc
, EndLoc
);
17241 assert(Argument
.size() == 1 && ArgumentLoc
.size() == 1);
17242 Res
= ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind
>(Argument
.back()),
17243 Expr
, StartLoc
, LParenLoc
, ArgumentLoc
.back(),
17246 case OMPC_dist_schedule
:
17247 Res
= ActOnOpenMPDistScheduleClause(
17248 static_cast<OpenMPDistScheduleClauseKind
>(Argument
.back()), Expr
,
17249 StartLoc
, LParenLoc
, ArgumentLoc
.back(), DelimLoc
, EndLoc
);
17251 case OMPC_defaultmap
:
17252 enum { Modifier
, DefaultmapKind
};
17253 Res
= ActOnOpenMPDefaultmapClause(
17254 static_cast<OpenMPDefaultmapClauseModifier
>(Argument
[Modifier
]),
17255 static_cast<OpenMPDefaultmapClauseKind
>(Argument
[DefaultmapKind
]),
17256 StartLoc
, LParenLoc
, ArgumentLoc
[Modifier
], ArgumentLoc
[DefaultmapKind
],
17260 enum { OrderModifier
, OrderKind
};
17261 Res
= ActOnOpenMPOrderClause(
17262 static_cast<OpenMPOrderClauseModifier
>(Argument
[OrderModifier
]),
17263 static_cast<OpenMPOrderClauseKind
>(Argument
[OrderKind
]), StartLoc
,
17264 LParenLoc
, ArgumentLoc
[OrderModifier
], ArgumentLoc
[OrderKind
], EndLoc
);
17267 assert(Argument
.size() == 1 && ArgumentLoc
.size() == 1);
17268 Res
= ActOnOpenMPDeviceClause(
17269 static_cast<OpenMPDeviceClauseModifier
>(Argument
.back()), Expr
,
17270 StartLoc
, LParenLoc
, ArgumentLoc
.back(), EndLoc
);
17272 case OMPC_grainsize
:
17273 assert(Argument
.size() == 1 && ArgumentLoc
.size() == 1 &&
17274 "Modifier for grainsize clause and its location are expected.");
17275 Res
= ActOnOpenMPGrainsizeClause(
17276 static_cast<OpenMPGrainsizeClauseModifier
>(Argument
.back()), Expr
,
17277 StartLoc
, LParenLoc
, ArgumentLoc
.back(), EndLoc
);
17279 case OMPC_num_tasks
:
17280 assert(Argument
.size() == 1 && ArgumentLoc
.size() == 1 &&
17281 "Modifier for num_tasks clause and its location are expected.");
17282 Res
= ActOnOpenMPNumTasksClause(
17283 static_cast<OpenMPNumTasksClauseModifier
>(Argument
.back()), Expr
,
17284 StartLoc
, LParenLoc
, ArgumentLoc
.back(), EndLoc
);
17287 case OMPC_num_threads
:
17291 case OMPC_allocator
:
17292 case OMPC_collapse
:
17294 case OMPC_proc_bind
:
17296 case OMPC_firstprivate
:
17297 case OMPC_lastprivate
:
17299 case OMPC_reduction
:
17300 case OMPC_task_reduction
:
17301 case OMPC_in_reduction
:
17305 case OMPC_copyprivate
:
17309 case OMPC_mergeable
:
17310 case OMPC_threadprivate
:
17311 case OMPC_allocate
:
17328 case OMPC_num_teams
:
17329 case OMPC_thread_limit
:
17330 case OMPC_priority
:
17337 case OMPC_use_device_ptr
:
17338 case OMPC_use_device_addr
:
17339 case OMPC_is_device_ptr
:
17340 case OMPC_has_device_addr
:
17341 case OMPC_unified_address
:
17342 case OMPC_unified_shared_memory
:
17343 case OMPC_reverse_offload
:
17344 case OMPC_dynamic_allocators
:
17345 case OMPC_atomic_default_mem_order
:
17346 case OMPC_device_type
:
17348 case OMPC_nontemporal
:
17350 case OMPC_severity
:
17353 case OMPC_novariants
:
17354 case OMPC_nocontext
:
17356 case OMPC_inclusive
:
17357 case OMPC_exclusive
:
17358 case OMPC_uses_allocators
:
17359 case OMPC_affinity
:
17363 llvm_unreachable("Clause is not allowed.");
17368 static bool checkScheduleModifiers(Sema
&S
, OpenMPScheduleClauseModifier M1
,
17369 OpenMPScheduleClauseModifier M2
,
17370 SourceLocation M1Loc
, SourceLocation M2Loc
) {
17371 if (M1
== OMPC_SCHEDULE_MODIFIER_unknown
&& M1Loc
.isValid()) {
17372 SmallVector
<unsigned, 2> Excluded
;
17373 if (M2
!= OMPC_SCHEDULE_MODIFIER_unknown
)
17374 Excluded
.push_back(M2
);
17375 if (M2
== OMPC_SCHEDULE_MODIFIER_nonmonotonic
)
17376 Excluded
.push_back(OMPC_SCHEDULE_MODIFIER_monotonic
);
17377 if (M2
== OMPC_SCHEDULE_MODIFIER_monotonic
)
17378 Excluded
.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic
);
17379 S
.Diag(M1Loc
, diag::err_omp_unexpected_clause_value
)
17380 << getListOfPossibleValues(OMPC_schedule
,
17381 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown
+ 1,
17382 /*Last=*/OMPC_SCHEDULE_MODIFIER_last
,
17384 << getOpenMPClauseName(OMPC_schedule
);
17390 OMPClause
*Sema::ActOnOpenMPScheduleClause(
17391 OpenMPScheduleClauseModifier M1
, OpenMPScheduleClauseModifier M2
,
17392 OpenMPScheduleClauseKind Kind
, Expr
*ChunkSize
, SourceLocation StartLoc
,
17393 SourceLocation LParenLoc
, SourceLocation M1Loc
, SourceLocation M2Loc
,
17394 SourceLocation KindLoc
, SourceLocation CommaLoc
, SourceLocation EndLoc
) {
17395 if (checkScheduleModifiers(*this, M1
, M2
, M1Loc
, M2Loc
) ||
17396 checkScheduleModifiers(*this, M2
, M1
, M2Loc
, M1Loc
))
17398 // OpenMP, 2.7.1, Loop Construct, Restrictions
17399 // Either the monotonic modifier or the nonmonotonic modifier can be specified
17401 if ((M1
== M2
&& M1
!= OMPC_SCHEDULE_MODIFIER_unknown
) ||
17402 (M1
== OMPC_SCHEDULE_MODIFIER_monotonic
&&
17403 M2
== OMPC_SCHEDULE_MODIFIER_nonmonotonic
) ||
17404 (M1
== OMPC_SCHEDULE_MODIFIER_nonmonotonic
&&
17405 M2
== OMPC_SCHEDULE_MODIFIER_monotonic
)) {
17406 Diag(M2Loc
, diag::err_omp_unexpected_schedule_modifier
)
17407 << getOpenMPSimpleClauseTypeName(OMPC_schedule
, M2
)
17408 << getOpenMPSimpleClauseTypeName(OMPC_schedule
, M1
);
17411 if (Kind
== OMPC_SCHEDULE_unknown
) {
17412 std::string Values
;
17413 if (M1Loc
.isInvalid() && M2Loc
.isInvalid()) {
17414 unsigned Exclude
[] = {OMPC_SCHEDULE_unknown
};
17415 Values
= getListOfPossibleValues(OMPC_schedule
, /*First=*/0,
17416 /*Last=*/OMPC_SCHEDULE_MODIFIER_last
,
17419 Values
= getListOfPossibleValues(OMPC_schedule
, /*First=*/0,
17420 /*Last=*/OMPC_SCHEDULE_unknown
);
17422 Diag(KindLoc
, diag::err_omp_unexpected_clause_value
)
17423 << Values
<< getOpenMPClauseName(OMPC_schedule
);
17426 // OpenMP, 2.7.1, Loop Construct, Restrictions
17427 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
17428 // schedule(guided).
17429 // OpenMP 5.0 does not have this restriction.
17430 if (LangOpts
.OpenMP
< 50 &&
17431 (M1
== OMPC_SCHEDULE_MODIFIER_nonmonotonic
||
17432 M2
== OMPC_SCHEDULE_MODIFIER_nonmonotonic
) &&
17433 Kind
!= OMPC_SCHEDULE_dynamic
&& Kind
!= OMPC_SCHEDULE_guided
) {
17434 Diag(M1
== OMPC_SCHEDULE_MODIFIER_nonmonotonic
? M1Loc
: M2Loc
,
17435 diag::err_omp_schedule_nonmonotonic_static
);
17438 Expr
*ValExpr
= ChunkSize
;
17439 Stmt
*HelperValStmt
= nullptr;
17441 if (!ChunkSize
->isValueDependent() && !ChunkSize
->isTypeDependent() &&
17442 !ChunkSize
->isInstantiationDependent() &&
17443 !ChunkSize
->containsUnexpandedParameterPack()) {
17444 SourceLocation ChunkSizeLoc
= ChunkSize
->getBeginLoc();
17446 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc
, ChunkSize
);
17447 if (Val
.isInvalid())
17450 ValExpr
= Val
.get();
17452 // OpenMP [2.7.1, Restrictions]
17453 // chunk_size must be a loop invariant integer expression with a positive
17455 if (std::optional
<llvm::APSInt
> Result
=
17456 ValExpr
->getIntegerConstantExpr(Context
)) {
17457 if (Result
->isSigned() && !Result
->isStrictlyPositive()) {
17458 Diag(ChunkSizeLoc
, diag::err_omp_negative_expression_in_clause
)
17459 << "schedule" << 1 << ChunkSize
->getSourceRange();
17462 } else if (getOpenMPCaptureRegionForClause(
17463 DSAStack
->getCurrentDirective(), OMPC_schedule
,
17464 LangOpts
.OpenMP
) != OMPD_unknown
&&
17465 !CurContext
->isDependentContext()) {
17466 ValExpr
= MakeFullExpr(ValExpr
).get();
17467 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
17468 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
17469 HelperValStmt
= buildPreInits(Context
, Captures
);
17474 return new (Context
)
17475 OMPScheduleClause(StartLoc
, LParenLoc
, KindLoc
, CommaLoc
, EndLoc
, Kind
,
17476 ValExpr
, HelperValStmt
, M1
, M1Loc
, M2
, M2Loc
);
17479 OMPClause
*Sema::ActOnOpenMPClause(OpenMPClauseKind Kind
,
17480 SourceLocation StartLoc
,
17481 SourceLocation EndLoc
) {
17482 OMPClause
*Res
= nullptr;
17485 Res
= ActOnOpenMPOrderedClause(StartLoc
, EndLoc
);
17488 Res
= ActOnOpenMPNowaitClause(StartLoc
, EndLoc
);
17491 Res
= ActOnOpenMPUntiedClause(StartLoc
, EndLoc
);
17493 case OMPC_mergeable
:
17494 Res
= ActOnOpenMPMergeableClause(StartLoc
, EndLoc
);
17497 Res
= ActOnOpenMPReadClause(StartLoc
, EndLoc
);
17500 Res
= ActOnOpenMPWriteClause(StartLoc
, EndLoc
);
17503 Res
= ActOnOpenMPUpdateClause(StartLoc
, EndLoc
);
17506 Res
= ActOnOpenMPCaptureClause(StartLoc
, EndLoc
);
17509 Res
= ActOnOpenMPCompareClause(StartLoc
, EndLoc
);
17512 Res
= ActOnOpenMPSeqCstClause(StartLoc
, EndLoc
);
17515 Res
= ActOnOpenMPAcqRelClause(StartLoc
, EndLoc
);
17518 Res
= ActOnOpenMPAcquireClause(StartLoc
, EndLoc
);
17521 Res
= ActOnOpenMPReleaseClause(StartLoc
, EndLoc
);
17524 Res
= ActOnOpenMPRelaxedClause(StartLoc
, EndLoc
);
17527 Res
= ActOnOpenMPThreadsClause(StartLoc
, EndLoc
);
17530 Res
= ActOnOpenMPSIMDClause(StartLoc
, EndLoc
);
17533 Res
= ActOnOpenMPNogroupClause(StartLoc
, EndLoc
);
17535 case OMPC_unified_address
:
17536 Res
= ActOnOpenMPUnifiedAddressClause(StartLoc
, EndLoc
);
17538 case OMPC_unified_shared_memory
:
17539 Res
= ActOnOpenMPUnifiedSharedMemoryClause(StartLoc
, EndLoc
);
17541 case OMPC_reverse_offload
:
17542 Res
= ActOnOpenMPReverseOffloadClause(StartLoc
, EndLoc
);
17544 case OMPC_dynamic_allocators
:
17545 Res
= ActOnOpenMPDynamicAllocatorsClause(StartLoc
, EndLoc
);
17548 Res
= ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc
,
17549 /*LParenLoc=*/SourceLocation(),
17550 /*VarLoc=*/SourceLocation(), EndLoc
);
17553 Res
= ActOnOpenMPFullClause(StartLoc
, EndLoc
);
17556 Res
= ActOnOpenMPPartialClause(nullptr, StartLoc
, /*LParenLoc=*/{}, EndLoc
);
17560 case OMPC_num_threads
:
17564 case OMPC_allocator
:
17565 case OMPC_collapse
:
17566 case OMPC_schedule
:
17568 case OMPC_firstprivate
:
17569 case OMPC_lastprivate
:
17571 case OMPC_reduction
:
17572 case OMPC_task_reduction
:
17573 case OMPC_in_reduction
:
17577 case OMPC_copyprivate
:
17579 case OMPC_proc_bind
:
17580 case OMPC_threadprivate
:
17581 case OMPC_allocate
:
17587 case OMPC_num_teams
:
17588 case OMPC_thread_limit
:
17589 case OMPC_priority
:
17590 case OMPC_grainsize
:
17591 case OMPC_num_tasks
:
17593 case OMPC_dist_schedule
:
17594 case OMPC_defaultmap
:
17599 case OMPC_use_device_ptr
:
17600 case OMPC_use_device_addr
:
17601 case OMPC_is_device_ptr
:
17602 case OMPC_has_device_addr
:
17603 case OMPC_atomic_default_mem_order
:
17604 case OMPC_device_type
:
17606 case OMPC_nontemporal
:
17609 case OMPC_severity
:
17611 case OMPC_novariants
:
17612 case OMPC_nocontext
:
17614 case OMPC_inclusive
:
17615 case OMPC_exclusive
:
17616 case OMPC_uses_allocators
:
17617 case OMPC_affinity
:
17619 case OMPC_ompx_dyn_cgroup_mem
:
17621 llvm_unreachable("Clause is not allowed.");
17626 OMPClause
*Sema::ActOnOpenMPNowaitClause(SourceLocation StartLoc
,
17627 SourceLocation EndLoc
) {
17628 DSAStack
->setNowaitRegion();
17629 return new (Context
) OMPNowaitClause(StartLoc
, EndLoc
);
17632 OMPClause
*Sema::ActOnOpenMPUntiedClause(SourceLocation StartLoc
,
17633 SourceLocation EndLoc
) {
17634 DSAStack
->setUntiedRegion();
17635 return new (Context
) OMPUntiedClause(StartLoc
, EndLoc
);
17638 OMPClause
*Sema::ActOnOpenMPMergeableClause(SourceLocation StartLoc
,
17639 SourceLocation EndLoc
) {
17640 return new (Context
) OMPMergeableClause(StartLoc
, EndLoc
);
17643 OMPClause
*Sema::ActOnOpenMPReadClause(SourceLocation StartLoc
,
17644 SourceLocation EndLoc
) {
17645 return new (Context
) OMPReadClause(StartLoc
, EndLoc
);
17648 OMPClause
*Sema::ActOnOpenMPWriteClause(SourceLocation StartLoc
,
17649 SourceLocation EndLoc
) {
17650 return new (Context
) OMPWriteClause(StartLoc
, EndLoc
);
17653 OMPClause
*Sema::ActOnOpenMPUpdateClause(SourceLocation StartLoc
,
17654 SourceLocation EndLoc
) {
17655 return OMPUpdateClause::Create(Context
, StartLoc
, EndLoc
);
17658 OMPClause
*Sema::ActOnOpenMPCaptureClause(SourceLocation StartLoc
,
17659 SourceLocation EndLoc
) {
17660 return new (Context
) OMPCaptureClause(StartLoc
, EndLoc
);
17663 OMPClause
*Sema::ActOnOpenMPCompareClause(SourceLocation StartLoc
,
17664 SourceLocation EndLoc
) {
17665 return new (Context
) OMPCompareClause(StartLoc
, EndLoc
);
17668 OMPClause
*Sema::ActOnOpenMPSeqCstClause(SourceLocation StartLoc
,
17669 SourceLocation EndLoc
) {
17670 return new (Context
) OMPSeqCstClause(StartLoc
, EndLoc
);
17673 OMPClause
*Sema::ActOnOpenMPAcqRelClause(SourceLocation StartLoc
,
17674 SourceLocation EndLoc
) {
17675 return new (Context
) OMPAcqRelClause(StartLoc
, EndLoc
);
17678 OMPClause
*Sema::ActOnOpenMPAcquireClause(SourceLocation StartLoc
,
17679 SourceLocation EndLoc
) {
17680 return new (Context
) OMPAcquireClause(StartLoc
, EndLoc
);
17683 OMPClause
*Sema::ActOnOpenMPReleaseClause(SourceLocation StartLoc
,
17684 SourceLocation EndLoc
) {
17685 return new (Context
) OMPReleaseClause(StartLoc
, EndLoc
);
17688 OMPClause
*Sema::ActOnOpenMPRelaxedClause(SourceLocation StartLoc
,
17689 SourceLocation EndLoc
) {
17690 return new (Context
) OMPRelaxedClause(StartLoc
, EndLoc
);
17693 OMPClause
*Sema::ActOnOpenMPThreadsClause(SourceLocation StartLoc
,
17694 SourceLocation EndLoc
) {
17695 return new (Context
) OMPThreadsClause(StartLoc
, EndLoc
);
17698 OMPClause
*Sema::ActOnOpenMPSIMDClause(SourceLocation StartLoc
,
17699 SourceLocation EndLoc
) {
17700 return new (Context
) OMPSIMDClause(StartLoc
, EndLoc
);
17703 OMPClause
*Sema::ActOnOpenMPNogroupClause(SourceLocation StartLoc
,
17704 SourceLocation EndLoc
) {
17705 return new (Context
) OMPNogroupClause(StartLoc
, EndLoc
);
17708 OMPClause
*Sema::ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc
,
17709 SourceLocation EndLoc
) {
17710 return new (Context
) OMPUnifiedAddressClause(StartLoc
, EndLoc
);
17713 OMPClause
*Sema::ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc
,
17714 SourceLocation EndLoc
) {
17715 return new (Context
) OMPUnifiedSharedMemoryClause(StartLoc
, EndLoc
);
17718 OMPClause
*Sema::ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc
,
17719 SourceLocation EndLoc
) {
17720 return new (Context
) OMPReverseOffloadClause(StartLoc
, EndLoc
);
17723 OMPClause
*Sema::ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc
,
17724 SourceLocation EndLoc
) {
17725 return new (Context
) OMPDynamicAllocatorsClause(StartLoc
, EndLoc
);
17728 StmtResult
Sema::ActOnOpenMPInteropDirective(ArrayRef
<OMPClause
*> Clauses
,
17729 SourceLocation StartLoc
,
17730 SourceLocation EndLoc
) {
17732 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17733 // At least one action-clause must appear on a directive.
17734 if (!hasClauses(Clauses
, OMPC_init
, OMPC_use
, OMPC_destroy
, OMPC_nowait
)) {
17735 StringRef Expected
= "'init', 'use', 'destroy', or 'nowait'";
17736 Diag(StartLoc
, diag::err_omp_no_clause_for_directive
)
17737 << Expected
<< getOpenMPDirectiveName(OMPD_interop
);
17738 return StmtError();
17741 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17742 // A depend clause can only appear on the directive if a targetsync
17743 // interop-type is present or the interop-var was initialized with
17744 // the targetsync interop-type.
17746 // If there is any 'init' clause diagnose if there is no 'init' clause with
17747 // interop-type of 'targetsync'. Cases involving other directives cannot be
17749 const OMPDependClause
*DependClause
= nullptr;
17750 bool HasInitClause
= false;
17751 bool IsTargetSync
= false;
17752 for (const OMPClause
*C
: Clauses
) {
17755 if (const auto *InitClause
= dyn_cast
<OMPInitClause
>(C
)) {
17756 HasInitClause
= true;
17757 if (InitClause
->getIsTargetSync())
17758 IsTargetSync
= true;
17759 } else if (const auto *DC
= dyn_cast
<OMPDependClause
>(C
)) {
17763 if (DependClause
&& HasInitClause
&& !IsTargetSync
) {
17764 Diag(DependClause
->getBeginLoc(), diag::err_omp_interop_bad_depend_clause
);
17765 return StmtError();
17768 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17769 // Each interop-var may be specified for at most one action-clause of each
17770 // interop construct.
17771 llvm::SmallPtrSet
<const ValueDecl
*, 4> InteropVars
;
17772 for (OMPClause
*C
: Clauses
) {
17773 OpenMPClauseKind ClauseKind
= C
->getClauseKind();
17774 std::pair
<ValueDecl
*, bool> DeclResult
;
17775 SourceLocation ELoc
;
17776 SourceRange ERange
;
17778 if (ClauseKind
== OMPC_init
) {
17779 auto *E
= cast
<OMPInitClause
>(C
)->getInteropVar();
17780 DeclResult
= getPrivateItem(*this, E
, ELoc
, ERange
);
17781 } else if (ClauseKind
== OMPC_use
) {
17782 auto *E
= cast
<OMPUseClause
>(C
)->getInteropVar();
17783 DeclResult
= getPrivateItem(*this, E
, ELoc
, ERange
);
17784 } else if (ClauseKind
== OMPC_destroy
) {
17785 auto *E
= cast
<OMPDestroyClause
>(C
)->getInteropVar();
17786 DeclResult
= getPrivateItem(*this, E
, ELoc
, ERange
);
17789 if (DeclResult
.first
) {
17790 if (!InteropVars
.insert(DeclResult
.first
).second
) {
17791 Diag(ELoc
, diag::err_omp_interop_var_multiple_actions
)
17792 << DeclResult
.first
;
17793 return StmtError();
17798 return OMPInteropDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
);
17801 static bool isValidInteropVariable(Sema
&SemaRef
, Expr
*InteropVarExpr
,
17802 SourceLocation VarLoc
,
17803 OpenMPClauseKind Kind
) {
17804 SourceLocation ELoc
;
17805 SourceRange ERange
;
17806 Expr
*RefExpr
= InteropVarExpr
;
17808 getPrivateItem(SemaRef
, RefExpr
, ELoc
, ERange
,
17809 /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t");
17812 // It will be analyzed later.
17819 // Interop variable should be of type omp_interop_t.
17820 bool HasError
= false;
17821 QualType InteropType
;
17822 LookupResult
Result(SemaRef
, &SemaRef
.Context
.Idents
.get("omp_interop_t"),
17823 VarLoc
, Sema::LookupOrdinaryName
);
17824 if (SemaRef
.LookupName(Result
, SemaRef
.getCurScope())) {
17825 NamedDecl
*ND
= Result
.getFoundDecl();
17826 if (const auto *TD
= dyn_cast
<TypeDecl
>(ND
)) {
17827 InteropType
= QualType(TD
->getTypeForDecl(), 0);
17836 SemaRef
.Diag(VarLoc
, diag::err_omp_implied_type_not_found
)
17837 << "omp_interop_t";
17841 QualType VarType
= InteropVarExpr
->getType().getUnqualifiedType();
17842 if (!SemaRef
.Context
.hasSameType(InteropType
, VarType
)) {
17843 SemaRef
.Diag(VarLoc
, diag::err_omp_interop_variable_wrong_type
);
17847 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17848 // The interop-var passed to init or destroy must be non-const.
17849 if ((Kind
== OMPC_init
|| Kind
== OMPC_destroy
) &&
17850 isConstNotMutableType(SemaRef
, InteropVarExpr
->getType())) {
17851 SemaRef
.Diag(VarLoc
, diag::err_omp_interop_variable_expected
)
17852 << /*non-const*/ 1;
17859 Sema::ActOnOpenMPInitClause(Expr
*InteropVar
, OMPInteropInfo
&InteropInfo
,
17860 SourceLocation StartLoc
, SourceLocation LParenLoc
,
17861 SourceLocation VarLoc
, SourceLocation EndLoc
) {
17863 if (!isValidInteropVariable(*this, InteropVar
, VarLoc
, OMPC_init
))
17866 // Check prefer_type values. These foreign-runtime-id values are either
17867 // string literals or constant integral expressions.
17868 for (const Expr
*E
: InteropInfo
.PreferTypes
) {
17869 if (E
->isValueDependent() || E
->isTypeDependent() ||
17870 E
->isInstantiationDependent() || E
->containsUnexpandedParameterPack())
17872 if (E
->isIntegerConstantExpr(Context
))
17874 if (isa
<StringLiteral
>(E
))
17876 Diag(E
->getExprLoc(), diag::err_omp_interop_prefer_type
);
17880 return OMPInitClause::Create(Context
, InteropVar
, InteropInfo
, StartLoc
,
17881 LParenLoc
, VarLoc
, EndLoc
);
17884 OMPClause
*Sema::ActOnOpenMPUseClause(Expr
*InteropVar
, SourceLocation StartLoc
,
17885 SourceLocation LParenLoc
,
17886 SourceLocation VarLoc
,
17887 SourceLocation EndLoc
) {
17889 if (!isValidInteropVariable(*this, InteropVar
, VarLoc
, OMPC_use
))
17892 return new (Context
)
17893 OMPUseClause(InteropVar
, StartLoc
, LParenLoc
, VarLoc
, EndLoc
);
17896 OMPClause
*Sema::ActOnOpenMPDestroyClause(Expr
*InteropVar
,
17897 SourceLocation StartLoc
,
17898 SourceLocation LParenLoc
,
17899 SourceLocation VarLoc
,
17900 SourceLocation EndLoc
) {
17901 if (!InteropVar
&& LangOpts
.OpenMP
>= 52 &&
17902 DSAStack
->getCurrentDirective() == OMPD_depobj
) {
17903 Diag(StartLoc
, diag::err_omp_expected_clause_argument
)
17904 << getOpenMPClauseName(OMPC_destroy
)
17905 << getOpenMPDirectiveName(OMPD_depobj
);
17909 !isValidInteropVariable(*this, InteropVar
, VarLoc
, OMPC_destroy
))
17912 return new (Context
)
17913 OMPDestroyClause(InteropVar
, StartLoc
, LParenLoc
, VarLoc
, EndLoc
);
17916 OMPClause
*Sema::ActOnOpenMPNovariantsClause(Expr
*Condition
,
17917 SourceLocation StartLoc
,
17918 SourceLocation LParenLoc
,
17919 SourceLocation EndLoc
) {
17920 Expr
*ValExpr
= Condition
;
17921 Stmt
*HelperValStmt
= nullptr;
17922 OpenMPDirectiveKind CaptureRegion
= OMPD_unknown
;
17923 if (!Condition
->isValueDependent() && !Condition
->isTypeDependent() &&
17924 !Condition
->isInstantiationDependent() &&
17925 !Condition
->containsUnexpandedParameterPack()) {
17926 ExprResult Val
= CheckBooleanCondition(StartLoc
, Condition
);
17927 if (Val
.isInvalid())
17930 ValExpr
= MakeFullExpr(Val
.get()).get();
17932 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
17933 CaptureRegion
= getOpenMPCaptureRegionForClause(DKind
, OMPC_novariants
,
17935 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
17936 ValExpr
= MakeFullExpr(ValExpr
).get();
17937 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
17938 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
17939 HelperValStmt
= buildPreInits(Context
, Captures
);
17943 return new (Context
) OMPNovariantsClause(
17944 ValExpr
, HelperValStmt
, CaptureRegion
, StartLoc
, LParenLoc
, EndLoc
);
17947 OMPClause
*Sema::ActOnOpenMPNocontextClause(Expr
*Condition
,
17948 SourceLocation StartLoc
,
17949 SourceLocation LParenLoc
,
17950 SourceLocation EndLoc
) {
17951 Expr
*ValExpr
= Condition
;
17952 Stmt
*HelperValStmt
= nullptr;
17953 OpenMPDirectiveKind CaptureRegion
= OMPD_unknown
;
17954 if (!Condition
->isValueDependent() && !Condition
->isTypeDependent() &&
17955 !Condition
->isInstantiationDependent() &&
17956 !Condition
->containsUnexpandedParameterPack()) {
17957 ExprResult Val
= CheckBooleanCondition(StartLoc
, Condition
);
17958 if (Val
.isInvalid())
17961 ValExpr
= MakeFullExpr(Val
.get()).get();
17963 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
17965 getOpenMPCaptureRegionForClause(DKind
, OMPC_nocontext
, LangOpts
.OpenMP
);
17966 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
17967 ValExpr
= MakeFullExpr(ValExpr
).get();
17968 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
17969 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
17970 HelperValStmt
= buildPreInits(Context
, Captures
);
17974 return new (Context
) OMPNocontextClause(ValExpr
, HelperValStmt
, CaptureRegion
,
17975 StartLoc
, LParenLoc
, EndLoc
);
17978 OMPClause
*Sema::ActOnOpenMPFilterClause(Expr
*ThreadID
,
17979 SourceLocation StartLoc
,
17980 SourceLocation LParenLoc
,
17981 SourceLocation EndLoc
) {
17982 Expr
*ValExpr
= ThreadID
;
17983 Stmt
*HelperValStmt
= nullptr;
17985 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
17986 OpenMPDirectiveKind CaptureRegion
=
17987 getOpenMPCaptureRegionForClause(DKind
, OMPC_filter
, LangOpts
.OpenMP
);
17988 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
17989 ValExpr
= MakeFullExpr(ValExpr
).get();
17990 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
17991 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
17992 HelperValStmt
= buildPreInits(Context
, Captures
);
17995 return new (Context
) OMPFilterClause(ValExpr
, HelperValStmt
, CaptureRegion
,
17996 StartLoc
, LParenLoc
, EndLoc
);
17999 OMPClause
*Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind
,
18000 ArrayRef
<Expr
*> VarList
,
18001 const OMPVarListLocTy
&Locs
,
18002 OpenMPVarListDataTy
&Data
) {
18003 SourceLocation StartLoc
= Locs
.StartLoc
;
18004 SourceLocation LParenLoc
= Locs
.LParenLoc
;
18005 SourceLocation EndLoc
= Locs
.EndLoc
;
18006 OMPClause
*Res
= nullptr;
18007 int ExtraModifier
= Data
.ExtraModifier
;
18008 SourceLocation ExtraModifierLoc
= Data
.ExtraModifierLoc
;
18009 SourceLocation ColonLoc
= Data
.ColonLoc
;
18012 Res
= ActOnOpenMPPrivateClause(VarList
, StartLoc
, LParenLoc
, EndLoc
);
18014 case OMPC_firstprivate
:
18015 Res
= ActOnOpenMPFirstprivateClause(VarList
, StartLoc
, LParenLoc
, EndLoc
);
18017 case OMPC_lastprivate
:
18018 assert(0 <= ExtraModifier
&& ExtraModifier
<= OMPC_LASTPRIVATE_unknown
&&
18019 "Unexpected lastprivate modifier.");
18020 Res
= ActOnOpenMPLastprivateClause(
18021 VarList
, static_cast<OpenMPLastprivateModifier
>(ExtraModifier
),
18022 ExtraModifierLoc
, ColonLoc
, StartLoc
, LParenLoc
, EndLoc
);
18025 Res
= ActOnOpenMPSharedClause(VarList
, StartLoc
, LParenLoc
, EndLoc
);
18027 case OMPC_reduction
:
18028 assert(0 <= ExtraModifier
&& ExtraModifier
<= OMPC_REDUCTION_unknown
&&
18029 "Unexpected lastprivate modifier.");
18030 Res
= ActOnOpenMPReductionClause(
18031 VarList
, static_cast<OpenMPReductionClauseModifier
>(ExtraModifier
),
18032 StartLoc
, LParenLoc
, ExtraModifierLoc
, ColonLoc
, EndLoc
,
18033 Data
.ReductionOrMapperIdScopeSpec
, Data
.ReductionOrMapperId
);
18035 case OMPC_task_reduction
:
18036 Res
= ActOnOpenMPTaskReductionClause(
18037 VarList
, StartLoc
, LParenLoc
, ColonLoc
, EndLoc
,
18038 Data
.ReductionOrMapperIdScopeSpec
, Data
.ReductionOrMapperId
);
18040 case OMPC_in_reduction
:
18041 Res
= ActOnOpenMPInReductionClause(
18042 VarList
, StartLoc
, LParenLoc
, ColonLoc
, EndLoc
,
18043 Data
.ReductionOrMapperIdScopeSpec
, Data
.ReductionOrMapperId
);
18046 assert(0 <= ExtraModifier
&& ExtraModifier
<= OMPC_LINEAR_unknown
&&
18047 "Unexpected linear modifier.");
18048 Res
= ActOnOpenMPLinearClause(
18049 VarList
, Data
.DepModOrTailExpr
, StartLoc
, LParenLoc
,
18050 static_cast<OpenMPLinearClauseKind
>(ExtraModifier
), ExtraModifierLoc
,
18054 Res
= ActOnOpenMPAlignedClause(VarList
, Data
.DepModOrTailExpr
, StartLoc
,
18055 LParenLoc
, ColonLoc
, EndLoc
);
18058 Res
= ActOnOpenMPCopyinClause(VarList
, StartLoc
, LParenLoc
, EndLoc
);
18060 case OMPC_copyprivate
:
18061 Res
= ActOnOpenMPCopyprivateClause(VarList
, StartLoc
, LParenLoc
, EndLoc
);
18064 Res
= ActOnOpenMPFlushClause(VarList
, StartLoc
, LParenLoc
, EndLoc
);
18067 assert(0 <= ExtraModifier
&& ExtraModifier
<= OMPC_DEPEND_unknown
&&
18068 "Unexpected depend modifier.");
18069 Res
= ActOnOpenMPDependClause(
18070 {static_cast<OpenMPDependClauseKind
>(ExtraModifier
), ExtraModifierLoc
,
18071 ColonLoc
, Data
.OmpAllMemoryLoc
},
18072 Data
.DepModOrTailExpr
, VarList
, StartLoc
, LParenLoc
, EndLoc
);
18075 assert(0 <= ExtraModifier
&& ExtraModifier
<= OMPC_MAP_unknown
&&
18076 "Unexpected map modifier.");
18077 Res
= ActOnOpenMPMapClause(
18078 Data
.IteratorExpr
, Data
.MapTypeModifiers
, Data
.MapTypeModifiersLoc
,
18079 Data
.ReductionOrMapperIdScopeSpec
, Data
.ReductionOrMapperId
,
18080 static_cast<OpenMPMapClauseKind
>(ExtraModifier
), Data
.IsMapTypeImplicit
,
18081 ExtraModifierLoc
, ColonLoc
, VarList
, Locs
);
18085 ActOnOpenMPToClause(Data
.MotionModifiers
, Data
.MotionModifiersLoc
,
18086 Data
.ReductionOrMapperIdScopeSpec
,
18087 Data
.ReductionOrMapperId
, ColonLoc
, VarList
, Locs
);
18090 Res
= ActOnOpenMPFromClause(Data
.MotionModifiers
, Data
.MotionModifiersLoc
,
18091 Data
.ReductionOrMapperIdScopeSpec
,
18092 Data
.ReductionOrMapperId
, ColonLoc
, VarList
,
18095 case OMPC_use_device_ptr
:
18096 Res
= ActOnOpenMPUseDevicePtrClause(VarList
, Locs
);
18098 case OMPC_use_device_addr
:
18099 Res
= ActOnOpenMPUseDeviceAddrClause(VarList
, Locs
);
18101 case OMPC_is_device_ptr
:
18102 Res
= ActOnOpenMPIsDevicePtrClause(VarList
, Locs
);
18104 case OMPC_has_device_addr
:
18105 Res
= ActOnOpenMPHasDeviceAddrClause(VarList
, Locs
);
18107 case OMPC_allocate
:
18108 Res
= ActOnOpenMPAllocateClause(Data
.DepModOrTailExpr
, VarList
, StartLoc
,
18109 LParenLoc
, ColonLoc
, EndLoc
);
18111 case OMPC_nontemporal
:
18112 Res
= ActOnOpenMPNontemporalClause(VarList
, StartLoc
, LParenLoc
, EndLoc
);
18114 case OMPC_inclusive
:
18115 Res
= ActOnOpenMPInclusiveClause(VarList
, StartLoc
, LParenLoc
, EndLoc
);
18117 case OMPC_exclusive
:
18118 Res
= ActOnOpenMPExclusiveClause(VarList
, StartLoc
, LParenLoc
, EndLoc
);
18120 case OMPC_affinity
:
18121 Res
= ActOnOpenMPAffinityClause(StartLoc
, LParenLoc
, ColonLoc
, EndLoc
,
18122 Data
.DepModOrTailExpr
, VarList
);
18124 case OMPC_doacross
:
18125 Res
= ActOnOpenMPDoacrossClause(
18126 static_cast<OpenMPDoacrossClauseModifier
>(ExtraModifier
),
18127 ExtraModifierLoc
, ColonLoc
, VarList
, StartLoc
, LParenLoc
, EndLoc
);
18132 case OMPC_num_threads
:
18136 case OMPC_allocator
:
18137 case OMPC_collapse
:
18139 case OMPC_proc_bind
:
18140 case OMPC_schedule
:
18144 case OMPC_mergeable
:
18145 case OMPC_threadprivate
:
18159 case OMPC_num_teams
:
18160 case OMPC_thread_limit
:
18161 case OMPC_priority
:
18162 case OMPC_grainsize
:
18164 case OMPC_num_tasks
:
18166 case OMPC_dist_schedule
:
18167 case OMPC_defaultmap
:
18170 case OMPC_unified_address
:
18171 case OMPC_unified_shared_memory
:
18172 case OMPC_reverse_offload
:
18173 case OMPC_dynamic_allocators
:
18174 case OMPC_atomic_default_mem_order
:
18175 case OMPC_device_type
:
18179 case OMPC_severity
:
18182 case OMPC_novariants
:
18183 case OMPC_nocontext
:
18185 case OMPC_uses_allocators
:
18189 llvm_unreachable("Clause is not allowed.");
18194 ExprResult
Sema::getOpenMPCapturedExpr(VarDecl
*Capture
, ExprValueKind VK
,
18195 ExprObjectKind OK
, SourceLocation Loc
) {
18196 ExprResult Res
= BuildDeclRefExpr(
18197 Capture
, Capture
->getType().getNonReferenceType(), VK_LValue
, Loc
);
18198 if (!Res
.isUsable())
18199 return ExprError();
18200 if (OK
== OK_Ordinary
&& !getLangOpts().CPlusPlus
) {
18201 Res
= CreateBuiltinUnaryOp(Loc
, UO_Deref
, Res
.get());
18202 if (!Res
.isUsable())
18203 return ExprError();
18205 if (VK
!= VK_LValue
&& Res
.get()->isGLValue()) {
18206 Res
= DefaultLvalueConversion(Res
.get());
18207 if (!Res
.isUsable())
18208 return ExprError();
18213 OMPClause
*Sema::ActOnOpenMPPrivateClause(ArrayRef
<Expr
*> VarList
,
18214 SourceLocation StartLoc
,
18215 SourceLocation LParenLoc
,
18216 SourceLocation EndLoc
) {
18217 SmallVector
<Expr
*, 8> Vars
;
18218 SmallVector
<Expr
*, 8> PrivateCopies
;
18219 bool IsImplicitClause
=
18220 StartLoc
.isInvalid() && LParenLoc
.isInvalid() && EndLoc
.isInvalid();
18221 for (Expr
*RefExpr
: VarList
) {
18222 assert(RefExpr
&& "NULL expr in OpenMP private clause.");
18223 SourceLocation ELoc
;
18224 SourceRange ERange
;
18225 Expr
*SimpleRefExpr
= RefExpr
;
18226 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
18228 // It will be analyzed later.
18229 Vars
.push_back(RefExpr
);
18230 PrivateCopies
.push_back(nullptr);
18232 ValueDecl
*D
= Res
.first
;
18236 QualType Type
= D
->getType();
18237 auto *VD
= dyn_cast
<VarDecl
>(D
);
18239 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18240 // A variable that appears in a private clause must not have an incomplete
18241 // type or a reference type.
18242 if (RequireCompleteType(ELoc
, Type
, diag::err_omp_private_incomplete_type
))
18244 Type
= Type
.getNonReferenceType();
18246 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18247 // A variable that is privatized must not have a const-qualified type
18248 // unless it is of class type with a mutable member. This restriction does
18249 // not apply to the firstprivate clause.
18251 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
18252 // A variable that appears in a private clause must not have a
18253 // const-qualified type unless it is of class type with a mutable member.
18254 if (rejectConstNotMutableType(*this, D
, Type
, OMPC_private
, ELoc
))
18257 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18259 // Variables with the predetermined data-sharing attributes may not be
18260 // listed in data-sharing attributes clauses, except for the cases
18261 // listed below. For these exceptions only, listing a predetermined
18262 // variable in a data-sharing attribute clause is allowed and overrides
18263 // the variable's predetermined data-sharing attributes.
18264 DSAStackTy::DSAVarData DVar
= DSAStack
->getTopDSA(D
, /*FromParent=*/false);
18265 if (DVar
.CKind
!= OMPC_unknown
&& DVar
.CKind
!= OMPC_private
) {
18266 Diag(ELoc
, diag::err_omp_wrong_dsa
) << getOpenMPClauseName(DVar
.CKind
)
18267 << getOpenMPClauseName(OMPC_private
);
18268 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18272 OpenMPDirectiveKind CurrDir
= DSAStack
->getCurrentDirective();
18273 // Variably modified types are not supported for tasks.
18274 if (!Type
->isAnyPointerType() && Type
->isVariablyModifiedType() &&
18275 isOpenMPTaskingDirective(CurrDir
)) {
18276 Diag(ELoc
, diag::err_omp_variably_modified_type_not_supported
)
18277 << getOpenMPClauseName(OMPC_private
) << Type
18278 << getOpenMPDirectiveName(CurrDir
);
18279 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
18280 VarDecl::DeclarationOnly
;
18281 Diag(D
->getLocation(),
18282 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
18287 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18288 // A list item cannot appear in both a map clause and a data-sharing
18289 // attribute clause on the same construct
18291 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18292 // A list item cannot appear in both a map clause and a data-sharing
18293 // attribute clause on the same construct unless the construct is a
18294 // combined construct.
18295 if ((LangOpts
.OpenMP
<= 45 && isOpenMPTargetExecutionDirective(CurrDir
)) ||
18296 CurrDir
== OMPD_target
) {
18297 OpenMPClauseKind ConflictKind
;
18298 if (DSAStack
->checkMappableExprComponentListsForDecl(
18299 VD
, /*CurrentRegionOnly=*/true,
18300 [&](OMPClauseMappableExprCommon::MappableExprComponentListRef
,
18301 OpenMPClauseKind WhereFoundClauseKind
) -> bool {
18302 ConflictKind
= WhereFoundClauseKind
;
18305 Diag(ELoc
, diag::err_omp_variable_in_given_clause_and_dsa
)
18306 << getOpenMPClauseName(OMPC_private
)
18307 << getOpenMPClauseName(ConflictKind
)
18308 << getOpenMPDirectiveName(CurrDir
);
18309 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18314 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
18315 // A variable of class type (or array thereof) that appears in a private
18316 // clause requires an accessible, unambiguous default constructor for the
18318 // Generate helper private variable and initialize it with the default
18319 // value. The address of the original variable is replaced by the address of
18320 // the new private variable in CodeGen. This new variable is not added to
18321 // IdResolver, so the code in the OpenMP region uses original variable for
18322 // proper diagnostics.
18323 Type
= Type
.getUnqualifiedType();
18324 VarDecl
*VDPrivate
=
18325 buildVarDecl(*this, ELoc
, Type
, D
->getName(),
18326 D
->hasAttrs() ? &D
->getAttrs() : nullptr,
18327 VD
? cast
<DeclRefExpr
>(SimpleRefExpr
) : nullptr);
18328 ActOnUninitializedDecl(VDPrivate
);
18329 if (VDPrivate
->isInvalidDecl())
18331 DeclRefExpr
*VDPrivateRefExpr
= buildDeclRefExpr(
18332 *this, VDPrivate
, RefExpr
->getType().getUnqualifiedType(), ELoc
);
18334 DeclRefExpr
*Ref
= nullptr;
18335 if (!VD
&& !CurContext
->isDependentContext()) {
18336 auto *FD
= dyn_cast
<FieldDecl
>(D
);
18337 VarDecl
*VD
= FD
? DSAStack
->getImplicitFDCapExprDecl(FD
) : nullptr;
18339 Ref
= buildDeclRefExpr(*this, VD
, VD
->getType().getNonReferenceType(),
18340 RefExpr
->getExprLoc());
18342 Ref
= buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/false);
18344 if (!IsImplicitClause
)
18345 DSAStack
->addDSA(D
, RefExpr
->IgnoreParens(), OMPC_private
, Ref
);
18346 Vars
.push_back((VD
|| CurContext
->isDependentContext())
18347 ? RefExpr
->IgnoreParens()
18349 PrivateCopies
.push_back(VDPrivateRefExpr
);
18355 return OMPPrivateClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
, Vars
,
18359 OMPClause
*Sema::ActOnOpenMPFirstprivateClause(ArrayRef
<Expr
*> VarList
,
18360 SourceLocation StartLoc
,
18361 SourceLocation LParenLoc
,
18362 SourceLocation EndLoc
) {
18363 SmallVector
<Expr
*, 8> Vars
;
18364 SmallVector
<Expr
*, 8> PrivateCopies
;
18365 SmallVector
<Expr
*, 8> Inits
;
18366 SmallVector
<Decl
*, 4> ExprCaptures
;
18367 bool IsImplicitClause
=
18368 StartLoc
.isInvalid() && LParenLoc
.isInvalid() && EndLoc
.isInvalid();
18369 SourceLocation ImplicitClauseLoc
= DSAStack
->getConstructLoc();
18371 for (Expr
*RefExpr
: VarList
) {
18372 assert(RefExpr
&& "NULL expr in OpenMP firstprivate clause.");
18373 SourceLocation ELoc
;
18374 SourceRange ERange
;
18375 Expr
*SimpleRefExpr
= RefExpr
;
18376 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
18378 // It will be analyzed later.
18379 Vars
.push_back(RefExpr
);
18380 PrivateCopies
.push_back(nullptr);
18381 Inits
.push_back(nullptr);
18383 ValueDecl
*D
= Res
.first
;
18387 ELoc
= IsImplicitClause
? ImplicitClauseLoc
: ELoc
;
18388 QualType Type
= D
->getType();
18389 auto *VD
= dyn_cast
<VarDecl
>(D
);
18391 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18392 // A variable that appears in a private clause must not have an incomplete
18393 // type or a reference type.
18394 if (RequireCompleteType(ELoc
, Type
,
18395 diag::err_omp_firstprivate_incomplete_type
))
18397 Type
= Type
.getNonReferenceType();
18399 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
18400 // A variable of class type (or array thereof) that appears in a private
18401 // clause requires an accessible, unambiguous copy constructor for the
18403 QualType ElemType
= Context
.getBaseElementType(Type
).getNonReferenceType();
18405 // If an implicit firstprivate variable found it was checked already.
18406 DSAStackTy::DSAVarData TopDVar
;
18407 if (!IsImplicitClause
) {
18408 DSAStackTy::DSAVarData DVar
=
18409 DSAStack
->getTopDSA(D
, /*FromParent=*/false);
18411 OpenMPDirectiveKind CurrDir
= DSAStack
->getCurrentDirective();
18412 bool IsConstant
= ElemType
.isConstant(Context
);
18413 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
18414 // A list item that specifies a given variable may not appear in more
18415 // than one clause on the same directive, except that a variable may be
18416 // specified in both firstprivate and lastprivate clauses.
18417 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18418 // A list item may appear in a firstprivate or lastprivate clause but not
18420 if (DVar
.CKind
!= OMPC_unknown
&& DVar
.CKind
!= OMPC_firstprivate
&&
18421 (isOpenMPDistributeDirective(CurrDir
) ||
18422 DVar
.CKind
!= OMPC_lastprivate
) &&
18424 Diag(ELoc
, diag::err_omp_wrong_dsa
)
18425 << getOpenMPClauseName(DVar
.CKind
)
18426 << getOpenMPClauseName(OMPC_firstprivate
);
18427 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18431 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18433 // Variables with the predetermined data-sharing attributes may not be
18434 // listed in data-sharing attributes clauses, except for the cases
18435 // listed below. For these exceptions only, listing a predetermined
18436 // variable in a data-sharing attribute clause is allowed and overrides
18437 // the variable's predetermined data-sharing attributes.
18438 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18439 // in a Construct, C/C++, p.2]
18440 // Variables with const-qualified type having no mutable member may be
18441 // listed in a firstprivate clause, even if they are static data members.
18442 if (!(IsConstant
|| (VD
&& VD
->isStaticDataMember())) && !DVar
.RefExpr
&&
18443 DVar
.CKind
!= OMPC_unknown
&& DVar
.CKind
!= OMPC_shared
) {
18444 Diag(ELoc
, diag::err_omp_wrong_dsa
)
18445 << getOpenMPClauseName(DVar
.CKind
)
18446 << getOpenMPClauseName(OMPC_firstprivate
);
18447 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18451 // OpenMP [2.9.3.4, Restrictions, p.2]
18452 // A list item that is private within a parallel region must not appear
18453 // in a firstprivate clause on a worksharing construct if any of the
18454 // worksharing regions arising from the worksharing construct ever bind
18455 // to any of the parallel regions arising from the parallel construct.
18456 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18457 // A list item that is private within a teams region must not appear in a
18458 // firstprivate clause on a distribute construct if any of the distribute
18459 // regions arising from the distribute construct ever bind to any of the
18460 // teams regions arising from the teams construct.
18461 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18462 // A list item that appears in a reduction clause of a teams construct
18463 // must not appear in a firstprivate clause on a distribute construct if
18464 // any of the distribute regions arising from the distribute construct
18465 // ever bind to any of the teams regions arising from the teams construct.
18466 if ((isOpenMPWorksharingDirective(CurrDir
) ||
18467 isOpenMPDistributeDirective(CurrDir
)) &&
18468 !isOpenMPParallelDirective(CurrDir
) &&
18469 !isOpenMPTeamsDirective(CurrDir
)) {
18470 DVar
= DSAStack
->getImplicitDSA(D
, true);
18471 if (DVar
.CKind
!= OMPC_shared
&&
18472 (isOpenMPParallelDirective(DVar
.DKind
) ||
18473 isOpenMPTeamsDirective(DVar
.DKind
) ||
18474 DVar
.DKind
== OMPD_unknown
)) {
18475 Diag(ELoc
, diag::err_omp_required_access
)
18476 << getOpenMPClauseName(OMPC_firstprivate
)
18477 << getOpenMPClauseName(OMPC_shared
);
18478 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18482 // OpenMP [2.9.3.4, Restrictions, p.3]
18483 // A list item that appears in a reduction clause of a parallel construct
18484 // must not appear in a firstprivate clause on a worksharing or task
18485 // construct if any of the worksharing or task regions arising from the
18486 // worksharing or task construct ever bind to any of the parallel regions
18487 // arising from the parallel construct.
18488 // OpenMP [2.9.3.4, Restrictions, p.4]
18489 // A list item that appears in a reduction clause in worksharing
18490 // construct must not appear in a firstprivate clause in a task construct
18491 // encountered during execution of any of the worksharing regions arising
18492 // from the worksharing construct.
18493 if (isOpenMPTaskingDirective(CurrDir
)) {
18494 DVar
= DSAStack
->hasInnermostDSA(
18496 [](OpenMPClauseKind C
, bool AppliedToPointee
) {
18497 return C
== OMPC_reduction
&& !AppliedToPointee
;
18499 [](OpenMPDirectiveKind K
) {
18500 return isOpenMPParallelDirective(K
) ||
18501 isOpenMPWorksharingDirective(K
) ||
18502 isOpenMPTeamsDirective(K
);
18504 /*FromParent=*/true);
18505 if (DVar
.CKind
== OMPC_reduction
&&
18506 (isOpenMPParallelDirective(DVar
.DKind
) ||
18507 isOpenMPWorksharingDirective(DVar
.DKind
) ||
18508 isOpenMPTeamsDirective(DVar
.DKind
))) {
18509 Diag(ELoc
, diag::err_omp_parallel_reduction_in_task_firstprivate
)
18510 << getOpenMPDirectiveName(DVar
.DKind
);
18511 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18516 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18517 // A list item cannot appear in both a map clause and a data-sharing
18518 // attribute clause on the same construct
18520 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18521 // A list item cannot appear in both a map clause and a data-sharing
18522 // attribute clause on the same construct unless the construct is a
18523 // combined construct.
18524 if ((LangOpts
.OpenMP
<= 45 &&
18525 isOpenMPTargetExecutionDirective(CurrDir
)) ||
18526 CurrDir
== OMPD_target
) {
18527 OpenMPClauseKind ConflictKind
;
18528 if (DSAStack
->checkMappableExprComponentListsForDecl(
18529 VD
, /*CurrentRegionOnly=*/true,
18531 OMPClauseMappableExprCommon::MappableExprComponentListRef
,
18532 OpenMPClauseKind WhereFoundClauseKind
) {
18533 ConflictKind
= WhereFoundClauseKind
;
18536 Diag(ELoc
, diag::err_omp_variable_in_given_clause_and_dsa
)
18537 << getOpenMPClauseName(OMPC_firstprivate
)
18538 << getOpenMPClauseName(ConflictKind
)
18539 << getOpenMPDirectiveName(DSAStack
->getCurrentDirective());
18540 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18546 // Variably modified types are not supported for tasks.
18547 if (!Type
->isAnyPointerType() && Type
->isVariablyModifiedType() &&
18548 isOpenMPTaskingDirective(DSAStack
->getCurrentDirective())) {
18549 Diag(ELoc
, diag::err_omp_variably_modified_type_not_supported
)
18550 << getOpenMPClauseName(OMPC_firstprivate
) << Type
18551 << getOpenMPDirectiveName(DSAStack
->getCurrentDirective());
18552 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
18553 VarDecl::DeclarationOnly
;
18554 Diag(D
->getLocation(),
18555 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
18560 Type
= Type
.getUnqualifiedType();
18561 VarDecl
*VDPrivate
=
18562 buildVarDecl(*this, ELoc
, Type
, D
->getName(),
18563 D
->hasAttrs() ? &D
->getAttrs() : nullptr,
18564 VD
? cast
<DeclRefExpr
>(SimpleRefExpr
) : nullptr);
18565 // Generate helper private variable and initialize it with the value of the
18566 // original variable. The address of the original variable is replaced by
18567 // the address of the new private variable in the CodeGen. This new variable
18568 // is not added to IdResolver, so the code in the OpenMP region uses
18569 // original variable for proper diagnostics and variable capturing.
18570 Expr
*VDInitRefExpr
= nullptr;
18571 // For arrays generate initializer for single element and replace it by the
18572 // original array element in CodeGen.
18573 if (Type
->isArrayType()) {
18575 buildVarDecl(*this, RefExpr
->getExprLoc(), ElemType
, D
->getName());
18576 VDInitRefExpr
= buildDeclRefExpr(*this, VDInit
, ElemType
, ELoc
);
18577 Expr
*Init
= DefaultLvalueConversion(VDInitRefExpr
).get();
18578 ElemType
= ElemType
.getUnqualifiedType();
18579 VarDecl
*VDInitTemp
= buildVarDecl(*this, RefExpr
->getExprLoc(), ElemType
,
18580 ".firstprivate.temp");
18581 InitializedEntity Entity
=
18582 InitializedEntity::InitializeVariable(VDInitTemp
);
18583 InitializationKind Kind
= InitializationKind::CreateCopy(ELoc
, ELoc
);
18585 InitializationSequence
InitSeq(*this, Entity
, Kind
, Init
);
18586 ExprResult Result
= InitSeq
.Perform(*this, Entity
, Kind
, Init
);
18587 if (Result
.isInvalid())
18588 VDPrivate
->setInvalidDecl();
18590 VDPrivate
->setInit(Result
.getAs
<Expr
>());
18591 // Remove temp variable declaration.
18592 Context
.Deallocate(VDInitTemp
);
18594 VarDecl
*VDInit
= buildVarDecl(*this, RefExpr
->getExprLoc(), Type
,
18595 ".firstprivate.temp");
18596 VDInitRefExpr
= buildDeclRefExpr(*this, VDInit
, RefExpr
->getType(),
18597 RefExpr
->getExprLoc());
18598 AddInitializerToDecl(VDPrivate
,
18599 DefaultLvalueConversion(VDInitRefExpr
).get(),
18600 /*DirectInit=*/false);
18602 if (VDPrivate
->isInvalidDecl()) {
18603 if (IsImplicitClause
) {
18604 Diag(RefExpr
->getExprLoc(),
18605 diag::note_omp_task_predetermined_firstprivate_here
);
18609 CurContext
->addDecl(VDPrivate
);
18610 DeclRefExpr
*VDPrivateRefExpr
= buildDeclRefExpr(
18611 *this, VDPrivate
, RefExpr
->getType().getUnqualifiedType(),
18612 RefExpr
->getExprLoc());
18613 DeclRefExpr
*Ref
= nullptr;
18614 if (!VD
&& !CurContext
->isDependentContext()) {
18615 if (TopDVar
.CKind
== OMPC_lastprivate
) {
18616 Ref
= TopDVar
.PrivateCopy
;
18618 auto *FD
= dyn_cast
<FieldDecl
>(D
);
18619 VarDecl
*VD
= FD
? DSAStack
->getImplicitFDCapExprDecl(FD
) : nullptr;
18621 Ref
= buildDeclRefExpr(*this, VD
, VD
->getType().getNonReferenceType(),
18622 RefExpr
->getExprLoc());
18624 Ref
= buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/true);
18625 if (VD
|| !isOpenMPCapturedDecl(D
))
18626 ExprCaptures
.push_back(Ref
->getDecl());
18629 if (!IsImplicitClause
)
18630 DSAStack
->addDSA(D
, RefExpr
->IgnoreParens(), OMPC_firstprivate
, Ref
);
18631 Vars
.push_back((VD
|| CurContext
->isDependentContext())
18632 ? RefExpr
->IgnoreParens()
18634 PrivateCopies
.push_back(VDPrivateRefExpr
);
18635 Inits
.push_back(VDInitRefExpr
);
18641 return OMPFirstprivateClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
,
18642 Vars
, PrivateCopies
, Inits
,
18643 buildPreInits(Context
, ExprCaptures
));
18646 OMPClause
*Sema::ActOnOpenMPLastprivateClause(
18647 ArrayRef
<Expr
*> VarList
, OpenMPLastprivateModifier LPKind
,
18648 SourceLocation LPKindLoc
, SourceLocation ColonLoc
, SourceLocation StartLoc
,
18649 SourceLocation LParenLoc
, SourceLocation EndLoc
) {
18650 if (LPKind
== OMPC_LASTPRIVATE_unknown
&& LPKindLoc
.isValid()) {
18651 assert(ColonLoc
.isValid() && "Colon location must be valid.");
18652 Diag(LPKindLoc
, diag::err_omp_unexpected_clause_value
)
18653 << getListOfPossibleValues(OMPC_lastprivate
, /*First=*/0,
18654 /*Last=*/OMPC_LASTPRIVATE_unknown
)
18655 << getOpenMPClauseName(OMPC_lastprivate
);
18659 SmallVector
<Expr
*, 8> Vars
;
18660 SmallVector
<Expr
*, 8> SrcExprs
;
18661 SmallVector
<Expr
*, 8> DstExprs
;
18662 SmallVector
<Expr
*, 8> AssignmentOps
;
18663 SmallVector
<Decl
*, 4> ExprCaptures
;
18664 SmallVector
<Expr
*, 4> ExprPostUpdates
;
18665 for (Expr
*RefExpr
: VarList
) {
18666 assert(RefExpr
&& "NULL expr in OpenMP lastprivate clause.");
18667 SourceLocation ELoc
;
18668 SourceRange ERange
;
18669 Expr
*SimpleRefExpr
= RefExpr
;
18670 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
18672 // It will be analyzed later.
18673 Vars
.push_back(RefExpr
);
18674 SrcExprs
.push_back(nullptr);
18675 DstExprs
.push_back(nullptr);
18676 AssignmentOps
.push_back(nullptr);
18678 ValueDecl
*D
= Res
.first
;
18682 QualType Type
= D
->getType();
18683 auto *VD
= dyn_cast
<VarDecl
>(D
);
18685 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
18686 // A variable that appears in a lastprivate clause must not have an
18687 // incomplete type or a reference type.
18688 if (RequireCompleteType(ELoc
, Type
,
18689 diag::err_omp_lastprivate_incomplete_type
))
18691 Type
= Type
.getNonReferenceType();
18693 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18694 // A variable that is privatized must not have a const-qualified type
18695 // unless it is of class type with a mutable member. This restriction does
18696 // not apply to the firstprivate clause.
18698 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
18699 // A variable that appears in a lastprivate clause must not have a
18700 // const-qualified type unless it is of class type with a mutable member.
18701 if (rejectConstNotMutableType(*this, D
, Type
, OMPC_lastprivate
, ELoc
))
18704 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
18705 // A list item that appears in a lastprivate clause with the conditional
18706 // modifier must be a scalar variable.
18707 if (LPKind
== OMPC_LASTPRIVATE_conditional
&& !Type
->isScalarType()) {
18708 Diag(ELoc
, diag::err_omp_lastprivate_conditional_non_scalar
);
18709 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
18710 VarDecl::DeclarationOnly
;
18711 Diag(D
->getLocation(),
18712 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
18717 OpenMPDirectiveKind CurrDir
= DSAStack
->getCurrentDirective();
18718 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
18720 // Variables with the predetermined data-sharing attributes may not be
18721 // listed in data-sharing attributes clauses, except for the cases
18723 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18724 // A list item may appear in a firstprivate or lastprivate clause but not
18726 DSAStackTy::DSAVarData DVar
= DSAStack
->getTopDSA(D
, /*FromParent=*/false);
18727 if (DVar
.CKind
!= OMPC_unknown
&& DVar
.CKind
!= OMPC_lastprivate
&&
18728 (isOpenMPDistributeDirective(CurrDir
) ||
18729 DVar
.CKind
!= OMPC_firstprivate
) &&
18730 (DVar
.CKind
!= OMPC_private
|| DVar
.RefExpr
!= nullptr)) {
18731 Diag(ELoc
, diag::err_omp_wrong_dsa
)
18732 << getOpenMPClauseName(DVar
.CKind
)
18733 << getOpenMPClauseName(OMPC_lastprivate
);
18734 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18738 // OpenMP [2.14.3.5, Restrictions, p.2]
18739 // A list item that is private within a parallel region, or that appears in
18740 // the reduction clause of a parallel construct, must not appear in a
18741 // lastprivate clause on a worksharing construct if any of the corresponding
18742 // worksharing regions ever binds to any of the corresponding parallel
18744 DSAStackTy::DSAVarData TopDVar
= DVar
;
18745 if (isOpenMPWorksharingDirective(CurrDir
) &&
18746 !isOpenMPParallelDirective(CurrDir
) &&
18747 !isOpenMPTeamsDirective(CurrDir
)) {
18748 DVar
= DSAStack
->getImplicitDSA(D
, true);
18749 if (DVar
.CKind
!= OMPC_shared
) {
18750 Diag(ELoc
, diag::err_omp_required_access
)
18751 << getOpenMPClauseName(OMPC_lastprivate
)
18752 << getOpenMPClauseName(OMPC_shared
);
18753 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18758 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
18759 // A variable of class type (or array thereof) that appears in a
18760 // lastprivate clause requires an accessible, unambiguous default
18761 // constructor for the class type, unless the list item is also specified
18762 // in a firstprivate clause.
18763 // A variable of class type (or array thereof) that appears in a
18764 // lastprivate clause requires an accessible, unambiguous copy assignment
18765 // operator for the class type.
18766 Type
= Context
.getBaseElementType(Type
).getNonReferenceType();
18767 VarDecl
*SrcVD
= buildVarDecl(*this, ERange
.getBegin(),
18768 Type
.getUnqualifiedType(), ".lastprivate.src",
18769 D
->hasAttrs() ? &D
->getAttrs() : nullptr);
18770 DeclRefExpr
*PseudoSrcExpr
=
18771 buildDeclRefExpr(*this, SrcVD
, Type
.getUnqualifiedType(), ELoc
);
18773 buildVarDecl(*this, ERange
.getBegin(), Type
, ".lastprivate.dst",
18774 D
->hasAttrs() ? &D
->getAttrs() : nullptr);
18775 DeclRefExpr
*PseudoDstExpr
= buildDeclRefExpr(*this, DstVD
, Type
, ELoc
);
18776 // For arrays generate assignment operation for single element and replace
18777 // it by the original array element in CodeGen.
18778 ExprResult AssignmentOp
= BuildBinOp(/*S=*/nullptr, ELoc
, BO_Assign
,
18779 PseudoDstExpr
, PseudoSrcExpr
);
18780 if (AssignmentOp
.isInvalid())
18783 ActOnFinishFullExpr(AssignmentOp
.get(), ELoc
, /*DiscardedValue*/ false);
18784 if (AssignmentOp
.isInvalid())
18787 DeclRefExpr
*Ref
= nullptr;
18788 if (!VD
&& !CurContext
->isDependentContext()) {
18789 if (TopDVar
.CKind
== OMPC_firstprivate
) {
18790 Ref
= TopDVar
.PrivateCopy
;
18792 Ref
= buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/false);
18793 if (!isOpenMPCapturedDecl(D
))
18794 ExprCaptures
.push_back(Ref
->getDecl());
18796 if ((TopDVar
.CKind
== OMPC_firstprivate
&& !TopDVar
.PrivateCopy
) ||
18797 (!isOpenMPCapturedDecl(D
) &&
18798 Ref
->getDecl()->hasAttr
<OMPCaptureNoInitAttr
>())) {
18799 ExprResult RefRes
= DefaultLvalueConversion(Ref
);
18800 if (!RefRes
.isUsable())
18802 ExprResult PostUpdateRes
=
18803 BuildBinOp(DSAStack
->getCurScope(), ELoc
, BO_Assign
, SimpleRefExpr
,
18805 if (!PostUpdateRes
.isUsable())
18807 ExprPostUpdates
.push_back(
18808 IgnoredValueConversions(PostUpdateRes
.get()).get());
18811 DSAStack
->addDSA(D
, RefExpr
->IgnoreParens(), OMPC_lastprivate
, Ref
);
18812 Vars
.push_back((VD
|| CurContext
->isDependentContext())
18813 ? RefExpr
->IgnoreParens()
18815 SrcExprs
.push_back(PseudoSrcExpr
);
18816 DstExprs
.push_back(PseudoDstExpr
);
18817 AssignmentOps
.push_back(AssignmentOp
.get());
18823 return OMPLastprivateClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
,
18824 Vars
, SrcExprs
, DstExprs
, AssignmentOps
,
18825 LPKind
, LPKindLoc
, ColonLoc
,
18826 buildPreInits(Context
, ExprCaptures
),
18827 buildPostUpdate(*this, ExprPostUpdates
));
18830 OMPClause
*Sema::ActOnOpenMPSharedClause(ArrayRef
<Expr
*> VarList
,
18831 SourceLocation StartLoc
,
18832 SourceLocation LParenLoc
,
18833 SourceLocation EndLoc
) {
18834 SmallVector
<Expr
*, 8> Vars
;
18835 for (Expr
*RefExpr
: VarList
) {
18836 assert(RefExpr
&& "NULL expr in OpenMP lastprivate clause.");
18837 SourceLocation ELoc
;
18838 SourceRange ERange
;
18839 Expr
*SimpleRefExpr
= RefExpr
;
18840 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
18842 // It will be analyzed later.
18843 Vars
.push_back(RefExpr
);
18845 ValueDecl
*D
= Res
.first
;
18849 auto *VD
= dyn_cast
<VarDecl
>(D
);
18850 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18852 // Variables with the predetermined data-sharing attributes may not be
18853 // listed in data-sharing attributes clauses, except for the cases
18854 // listed below. For these exceptions only, listing a predetermined
18855 // variable in a data-sharing attribute clause is allowed and overrides
18856 // the variable's predetermined data-sharing attributes.
18857 DSAStackTy::DSAVarData DVar
= DSAStack
->getTopDSA(D
, /*FromParent=*/false);
18858 if (DVar
.CKind
!= OMPC_unknown
&& DVar
.CKind
!= OMPC_shared
&&
18860 Diag(ELoc
, diag::err_omp_wrong_dsa
) << getOpenMPClauseName(DVar
.CKind
)
18861 << getOpenMPClauseName(OMPC_shared
);
18862 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18866 DeclRefExpr
*Ref
= nullptr;
18867 if (!VD
&& isOpenMPCapturedDecl(D
) && !CurContext
->isDependentContext())
18868 Ref
= buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/true);
18869 DSAStack
->addDSA(D
, RefExpr
->IgnoreParens(), OMPC_shared
, Ref
);
18870 Vars
.push_back((VD
|| !Ref
|| CurContext
->isDependentContext())
18871 ? RefExpr
->IgnoreParens()
18878 return OMPSharedClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
, Vars
);
18882 class DSARefChecker
: public StmtVisitor
<DSARefChecker
, bool> {
18886 bool VisitDeclRefExpr(DeclRefExpr
*E
) {
18887 if (auto *VD
= dyn_cast
<VarDecl
>(E
->getDecl())) {
18888 DSAStackTy::DSAVarData DVar
= Stack
->getTopDSA(VD
, /*FromParent=*/false);
18889 if (DVar
.CKind
== OMPC_shared
&& !DVar
.RefExpr
)
18891 if (DVar
.CKind
!= OMPC_unknown
)
18893 DSAStackTy::DSAVarData DVarPrivate
= Stack
->hasDSA(
18895 [](OpenMPClauseKind C
, bool AppliedToPointee
, bool) {
18896 return isOpenMPPrivate(C
) && !AppliedToPointee
;
18898 [](OpenMPDirectiveKind
) { return true; },
18899 /*FromParent=*/true);
18900 return DVarPrivate
.CKind
!= OMPC_unknown
;
18904 bool VisitStmt(Stmt
*S
) {
18905 for (Stmt
*Child
: S
->children()) {
18906 if (Child
&& Visit(Child
))
18911 explicit DSARefChecker(DSAStackTy
*S
) : Stack(S
) {}
18916 // Transform MemberExpression for specified FieldDecl of current class to
18917 // DeclRefExpr to specified OMPCapturedExprDecl.
18918 class TransformExprToCaptures
: public TreeTransform
<TransformExprToCaptures
> {
18919 typedef TreeTransform
<TransformExprToCaptures
> BaseTransform
;
18920 ValueDecl
*Field
= nullptr;
18921 DeclRefExpr
*CapturedExpr
= nullptr;
18924 TransformExprToCaptures(Sema
&SemaRef
, ValueDecl
*FieldDecl
)
18925 : BaseTransform(SemaRef
), Field(FieldDecl
), CapturedExpr(nullptr) {}
18927 ExprResult
TransformMemberExpr(MemberExpr
*E
) {
18928 if (isa
<CXXThisExpr
>(E
->getBase()->IgnoreParenImpCasts()) &&
18929 E
->getMemberDecl() == Field
) {
18930 CapturedExpr
= buildCapture(SemaRef
, Field
, E
, /*WithInit=*/false);
18931 return CapturedExpr
;
18933 return BaseTransform::TransformMemberExpr(E
);
18935 DeclRefExpr
*getCapturedExpr() { return CapturedExpr
; }
18939 template <typename T
, typename U
>
18940 static T
filterLookupForUDReductionAndMapper(
18941 SmallVectorImpl
<U
> &Lookups
, const llvm::function_ref
<T(ValueDecl
*)> Gen
) {
18942 for (U
&Set
: Lookups
) {
18943 for (auto *D
: Set
) {
18944 if (T Res
= Gen(cast
<ValueDecl
>(D
)))
18951 static NamedDecl
*findAcceptableDecl(Sema
&SemaRef
, NamedDecl
*D
) {
18952 assert(!LookupResult::isVisible(SemaRef
, D
) && "not in slow case");
18954 for (auto *RD
: D
->redecls()) {
18955 // Don't bother with extra checks if we already know this one isn't visible.
18959 auto ND
= cast
<NamedDecl
>(RD
);
18960 if (LookupResult::isVisible(SemaRef
, ND
))
18968 argumentDependentLookup(Sema
&SemaRef
, const DeclarationNameInfo
&Id
,
18969 SourceLocation Loc
, QualType Ty
,
18970 SmallVectorImpl
<UnresolvedSet
<8>> &Lookups
) {
18971 // Find all of the associated namespaces and classes based on the
18972 // arguments we have.
18973 Sema::AssociatedNamespaceSet AssociatedNamespaces
;
18974 Sema::AssociatedClassSet AssociatedClasses
;
18975 OpaqueValueExpr
OVE(Loc
, Ty
, VK_LValue
);
18976 SemaRef
.FindAssociatedClassesAndNamespaces(Loc
, &OVE
, AssociatedNamespaces
,
18977 AssociatedClasses
);
18979 // C++ [basic.lookup.argdep]p3:
18980 // Let X be the lookup set produced by unqualified lookup (3.4.1)
18981 // and let Y be the lookup set produced by argument dependent
18982 // lookup (defined as follows). If X contains [...] then Y is
18983 // empty. Otherwise Y is the set of declarations found in the
18984 // namespaces associated with the argument types as described
18985 // below. The set of declarations found by the lookup of the name
18986 // is the union of X and Y.
18988 // Here, we compute Y and add its members to the overloaded
18990 for (auto *NS
: AssociatedNamespaces
) {
18991 // When considering an associated namespace, the lookup is the
18992 // same as the lookup performed when the associated namespace is
18993 // used as a qualifier (3.4.3.2) except that:
18995 // -- Any using-directives in the associated namespace are
18998 // -- Any namespace-scope friend functions declared in
18999 // associated classes are visible within their respective
19000 // namespaces even if they are not visible during an ordinary
19002 DeclContext::lookup_result R
= NS
->lookup(Id
.getName());
19003 for (auto *D
: R
) {
19004 auto *Underlying
= D
;
19005 if (auto *USD
= dyn_cast
<UsingShadowDecl
>(D
))
19006 Underlying
= USD
->getTargetDecl();
19008 if (!isa
<OMPDeclareReductionDecl
>(Underlying
) &&
19009 !isa
<OMPDeclareMapperDecl
>(Underlying
))
19012 if (!SemaRef
.isVisible(D
)) {
19013 D
= findAcceptableDecl(SemaRef
, D
);
19016 if (auto *USD
= dyn_cast
<UsingShadowDecl
>(D
))
19017 Underlying
= USD
->getTargetDecl();
19019 Lookups
.emplace_back();
19020 Lookups
.back().addDecl(Underlying
);
19026 buildDeclareReductionRef(Sema
&SemaRef
, SourceLocation Loc
, SourceRange Range
,
19027 Scope
*S
, CXXScopeSpec
&ReductionIdScopeSpec
,
19028 const DeclarationNameInfo
&ReductionId
, QualType Ty
,
19029 CXXCastPath
&BasePath
, Expr
*UnresolvedReduction
) {
19030 if (ReductionIdScopeSpec
.isInvalid())
19031 return ExprError();
19032 SmallVector
<UnresolvedSet
<8>, 4> Lookups
;
19034 LookupResult
Lookup(SemaRef
, ReductionId
, Sema::LookupOMPReductionName
);
19035 Lookup
.suppressDiagnostics();
19036 while (S
&& SemaRef
.LookupParsedName(Lookup
, S
, &ReductionIdScopeSpec
)) {
19037 NamedDecl
*D
= Lookup
.getRepresentativeDecl();
19039 S
= S
->getParent();
19040 } while (S
&& !S
->isDeclScope(D
));
19042 S
= S
->getParent();
19043 Lookups
.emplace_back();
19044 Lookups
.back().append(Lookup
.begin(), Lookup
.end());
19047 } else if (auto *ULE
=
19048 cast_or_null
<UnresolvedLookupExpr
>(UnresolvedReduction
)) {
19049 Lookups
.push_back(UnresolvedSet
<8>());
19050 Decl
*PrevD
= nullptr;
19051 for (NamedDecl
*D
: ULE
->decls()) {
19053 Lookups
.push_back(UnresolvedSet
<8>());
19054 else if (auto *DRD
= dyn_cast
<OMPDeclareReductionDecl
>(D
))
19055 Lookups
.back().addDecl(DRD
);
19059 if (SemaRef
.CurContext
->isDependentContext() || Ty
->isDependentType() ||
19060 Ty
->isInstantiationDependentType() ||
19061 Ty
->containsUnexpandedParameterPack() ||
19062 filterLookupForUDReductionAndMapper
<bool>(Lookups
, [](ValueDecl
*D
) {
19063 return !D
->isInvalidDecl() &&
19064 (D
->getType()->isDependentType() ||
19065 D
->getType()->isInstantiationDependentType() ||
19066 D
->getType()->containsUnexpandedParameterPack());
19068 UnresolvedSet
<8> ResSet
;
19069 for (const UnresolvedSet
<8> &Set
: Lookups
) {
19072 ResSet
.append(Set
.begin(), Set
.end());
19073 // The last item marks the end of all declarations at the specified scope.
19074 ResSet
.addDecl(Set
[Set
.size() - 1]);
19076 return UnresolvedLookupExpr::Create(
19077 SemaRef
.Context
, /*NamingClass=*/nullptr,
19078 ReductionIdScopeSpec
.getWithLocInContext(SemaRef
.Context
), ReductionId
,
19079 /*ADL=*/true, /*Overloaded=*/true, ResSet
.begin(), ResSet
.end());
19081 // Lookup inside the classes.
19082 // C++ [over.match.oper]p3:
19083 // For a unary operator @ with an operand of a type whose
19084 // cv-unqualified version is T1, and for a binary operator @ with
19085 // a left operand of a type whose cv-unqualified version is T1 and
19086 // a right operand of a type whose cv-unqualified version is T2,
19087 // three sets of candidate functions, designated member
19088 // candidates, non-member candidates and built-in candidates, are
19089 // constructed as follows:
19090 // -- If T1 is a complete class type or a class currently being
19091 // defined, the set of member candidates is the result of the
19092 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
19093 // the set of member candidates is empty.
19094 LookupResult
Lookup(SemaRef
, ReductionId
, Sema::LookupOMPReductionName
);
19095 Lookup
.suppressDiagnostics();
19096 if (const auto *TyRec
= Ty
->getAs
<RecordType
>()) {
19097 // Complete the type if it can be completed.
19098 // If the type is neither complete nor being defined, bail out now.
19099 if (SemaRef
.isCompleteType(Loc
, Ty
) || TyRec
->isBeingDefined() ||
19100 TyRec
->getDecl()->getDefinition()) {
19102 SemaRef
.LookupQualifiedName(Lookup
, TyRec
->getDecl());
19103 if (Lookup
.empty()) {
19104 Lookups
.emplace_back();
19105 Lookups
.back().append(Lookup
.begin(), Lookup
.end());
19110 if (SemaRef
.getLangOpts().CPlusPlus
)
19111 argumentDependentLookup(SemaRef
, ReductionId
, Loc
, Ty
, Lookups
);
19112 if (auto *VD
= filterLookupForUDReductionAndMapper
<ValueDecl
*>(
19113 Lookups
, [&SemaRef
, Ty
](ValueDecl
*D
) -> ValueDecl
* {
19114 if (!D
->isInvalidDecl() &&
19115 SemaRef
.Context
.hasSameType(D
->getType(), Ty
))
19119 return SemaRef
.BuildDeclRefExpr(VD
, VD
->getType().getNonReferenceType(),
19121 if (SemaRef
.getLangOpts().CPlusPlus
) {
19122 if (auto *VD
= filterLookupForUDReductionAndMapper
<ValueDecl
*>(
19123 Lookups
, [&SemaRef
, Ty
, Loc
](ValueDecl
*D
) -> ValueDecl
* {
19124 if (!D
->isInvalidDecl() &&
19125 SemaRef
.IsDerivedFrom(Loc
, Ty
, D
->getType()) &&
19126 !Ty
.isMoreQualifiedThan(D
->getType()))
19130 CXXBasePaths
Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
19131 /*DetectVirtual=*/false);
19132 if (SemaRef
.IsDerivedFrom(Loc
, Ty
, VD
->getType(), Paths
)) {
19133 if (!Paths
.isAmbiguous(SemaRef
.Context
.getCanonicalType(
19134 VD
->getType().getUnqualifiedType()))) {
19135 if (SemaRef
.CheckBaseClassAccess(
19136 Loc
, VD
->getType(), Ty
, Paths
.front(),
19137 /*DiagID=*/0) != Sema::AR_inaccessible
) {
19138 SemaRef
.BuildBasePathArray(Paths
, BasePath
);
19139 return SemaRef
.BuildDeclRefExpr(
19140 VD
, VD
->getType().getNonReferenceType(), VK_LValue
, Loc
);
19146 if (ReductionIdScopeSpec
.isSet()) {
19147 SemaRef
.Diag(Loc
, diag::err_omp_not_resolved_reduction_identifier
)
19149 return ExprError();
19151 return ExprEmpty();
19155 /// Data for the reduction-based clauses.
19156 struct ReductionData
{
19157 /// List of original reduction items.
19158 SmallVector
<Expr
*, 8> Vars
;
19159 /// List of private copies of the reduction items.
19160 SmallVector
<Expr
*, 8> Privates
;
19161 /// LHS expressions for the reduction_op expressions.
19162 SmallVector
<Expr
*, 8> LHSs
;
19163 /// RHS expressions for the reduction_op expressions.
19164 SmallVector
<Expr
*, 8> RHSs
;
19165 /// Reduction operation expression.
19166 SmallVector
<Expr
*, 8> ReductionOps
;
19167 /// inscan copy operation expressions.
19168 SmallVector
<Expr
*, 8> InscanCopyOps
;
19169 /// inscan copy temp array expressions for prefix sums.
19170 SmallVector
<Expr
*, 8> InscanCopyArrayTemps
;
19171 /// inscan copy temp array element expressions for prefix sums.
19172 SmallVector
<Expr
*, 8> InscanCopyArrayElems
;
19173 /// Taskgroup descriptors for the corresponding reduction items in
19174 /// in_reduction clauses.
19175 SmallVector
<Expr
*, 8> TaskgroupDescriptors
;
19176 /// List of captures for clause.
19177 SmallVector
<Decl
*, 4> ExprCaptures
;
19178 /// List of postupdate expressions.
19179 SmallVector
<Expr
*, 4> ExprPostUpdates
;
19180 /// Reduction modifier.
19181 unsigned RedModifier
= 0;
19182 ReductionData() = delete;
19183 /// Reserves required memory for the reduction data.
19184 ReductionData(unsigned Size
, unsigned Modifier
= 0) : RedModifier(Modifier
) {
19185 Vars
.reserve(Size
);
19186 Privates
.reserve(Size
);
19187 LHSs
.reserve(Size
);
19188 RHSs
.reserve(Size
);
19189 ReductionOps
.reserve(Size
);
19190 if (RedModifier
== OMPC_REDUCTION_inscan
) {
19191 InscanCopyOps
.reserve(Size
);
19192 InscanCopyArrayTemps
.reserve(Size
);
19193 InscanCopyArrayElems
.reserve(Size
);
19195 TaskgroupDescriptors
.reserve(Size
);
19196 ExprCaptures
.reserve(Size
);
19197 ExprPostUpdates
.reserve(Size
);
19199 /// Stores reduction item and reduction operation only (required for dependent
19200 /// reduction item).
19201 void push(Expr
*Item
, Expr
*ReductionOp
) {
19202 Vars
.emplace_back(Item
);
19203 Privates
.emplace_back(nullptr);
19204 LHSs
.emplace_back(nullptr);
19205 RHSs
.emplace_back(nullptr);
19206 ReductionOps
.emplace_back(ReductionOp
);
19207 TaskgroupDescriptors
.emplace_back(nullptr);
19208 if (RedModifier
== OMPC_REDUCTION_inscan
) {
19209 InscanCopyOps
.push_back(nullptr);
19210 InscanCopyArrayTemps
.push_back(nullptr);
19211 InscanCopyArrayElems
.push_back(nullptr);
19214 /// Stores reduction data.
19215 void push(Expr
*Item
, Expr
*Private
, Expr
*LHS
, Expr
*RHS
, Expr
*ReductionOp
,
19216 Expr
*TaskgroupDescriptor
, Expr
*CopyOp
, Expr
*CopyArrayTemp
,
19217 Expr
*CopyArrayElem
) {
19218 Vars
.emplace_back(Item
);
19219 Privates
.emplace_back(Private
);
19220 LHSs
.emplace_back(LHS
);
19221 RHSs
.emplace_back(RHS
);
19222 ReductionOps
.emplace_back(ReductionOp
);
19223 TaskgroupDescriptors
.emplace_back(TaskgroupDescriptor
);
19224 if (RedModifier
== OMPC_REDUCTION_inscan
) {
19225 InscanCopyOps
.push_back(CopyOp
);
19226 InscanCopyArrayTemps
.push_back(CopyArrayTemp
);
19227 InscanCopyArrayElems
.push_back(CopyArrayElem
);
19229 assert(CopyOp
== nullptr && CopyArrayTemp
== nullptr &&
19230 CopyArrayElem
== nullptr &&
19231 "Copy operation must be used for inscan reductions only.");
19237 static bool checkOMPArraySectionConstantForReduction(
19238 ASTContext
&Context
, const OMPArraySectionExpr
*OASE
, bool &SingleElement
,
19239 SmallVectorImpl
<llvm::APSInt
> &ArraySizes
) {
19240 const Expr
*Length
= OASE
->getLength();
19241 if (Length
== nullptr) {
19242 // For array sections of the form [1:] or [:], we would need to analyze
19243 // the lower bound...
19244 if (OASE
->getColonLocFirst().isValid())
19247 // This is an array subscript which has implicit length 1!
19248 SingleElement
= true;
19249 ArraySizes
.push_back(llvm::APSInt::get(1));
19251 Expr::EvalResult Result
;
19252 if (!Length
->EvaluateAsInt(Result
, Context
))
19255 llvm::APSInt ConstantLengthValue
= Result
.Val
.getInt();
19256 SingleElement
= (ConstantLengthValue
.getSExtValue() == 1);
19257 ArraySizes
.push_back(ConstantLengthValue
);
19260 // Get the base of this array section and walk up from there.
19261 const Expr
*Base
= OASE
->getBase()->IgnoreParenImpCasts();
19263 // We require length = 1 for all array sections except the right-most to
19264 // guarantee that the memory region is contiguous and has no holes in it.
19265 while (const auto *TempOASE
= dyn_cast
<OMPArraySectionExpr
>(Base
)) {
19266 Length
= TempOASE
->getLength();
19267 if (Length
== nullptr) {
19268 // For array sections of the form [1:] or [:], we would need to analyze
19269 // the lower bound...
19270 if (OASE
->getColonLocFirst().isValid())
19273 // This is an array subscript which has implicit length 1!
19274 ArraySizes
.push_back(llvm::APSInt::get(1));
19276 Expr::EvalResult Result
;
19277 if (!Length
->EvaluateAsInt(Result
, Context
))
19280 llvm::APSInt ConstantLengthValue
= Result
.Val
.getInt();
19281 if (ConstantLengthValue
.getSExtValue() != 1)
19284 ArraySizes
.push_back(ConstantLengthValue
);
19286 Base
= TempOASE
->getBase()->IgnoreParenImpCasts();
19289 // If we have a single element, we don't need to add the implicit lengths.
19290 if (!SingleElement
) {
19291 while (const auto *TempASE
= dyn_cast
<ArraySubscriptExpr
>(Base
)) {
19292 // Has implicit length 1!
19293 ArraySizes
.push_back(llvm::APSInt::get(1));
19294 Base
= TempASE
->getBase()->IgnoreParenImpCasts();
19298 // This array section can be privatized as a single value or as a constant
19303 static BinaryOperatorKind
19304 getRelatedCompoundReductionOp(BinaryOperatorKind BOK
) {
19306 return BO_AddAssign
;
19308 return BO_MulAssign
;
19310 return BO_AndAssign
;
19312 return BO_OrAssign
;
19314 return BO_XorAssign
;
19318 static bool actOnOMPReductionKindClause(
19319 Sema
&S
, DSAStackTy
*Stack
, OpenMPClauseKind ClauseKind
,
19320 ArrayRef
<Expr
*> VarList
, SourceLocation StartLoc
, SourceLocation LParenLoc
,
19321 SourceLocation ColonLoc
, SourceLocation EndLoc
,
19322 CXXScopeSpec
&ReductionIdScopeSpec
, const DeclarationNameInfo
&ReductionId
,
19323 ArrayRef
<Expr
*> UnresolvedReductions
, ReductionData
&RD
) {
19324 DeclarationName DN
= ReductionId
.getName();
19325 OverloadedOperatorKind OOK
= DN
.getCXXOverloadedOperator();
19326 BinaryOperatorKind BOK
= BO_Comma
;
19328 ASTContext
&Context
= S
.Context
;
19329 // OpenMP [2.14.3.6, reduction clause]
19331 // reduction-identifier is either an identifier or one of the following
19332 // operators: +, -, *, &, |, ^, && and ||
19334 // reduction-identifier is either an id-expression or one of the following
19335 // operators: +, -, *, &, |, ^, && and ||
19341 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
19342 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
19343 // reduction identifier.
19344 if (S
.LangOpts
.OpenMP
> 52)
19370 case OO_Array_Delete
:
19379 case OO_GreaterEqual
:
19381 case OO_MinusEqual
:
19383 case OO_SlashEqual
:
19384 case OO_PercentEqual
:
19385 case OO_CaretEqual
:
19389 case OO_GreaterGreater
:
19390 case OO_LessLessEqual
:
19391 case OO_GreaterGreaterEqual
:
19392 case OO_EqualEqual
:
19393 case OO_ExclaimEqual
:
19396 case OO_MinusMinus
:
19402 case OO_Conditional
:
19404 case NUM_OVERLOADED_OPERATORS
:
19405 llvm_unreachable("Unexpected reduction identifier");
19407 if (IdentifierInfo
*II
= DN
.getAsIdentifierInfo()) {
19408 if (II
->isStr("max"))
19410 else if (II
->isStr("min"))
19416 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
19417 // A reduction clause with the minus (-) operator was deprecated
19418 if (OOK
== OO_Minus
&& S
.LangOpts
.OpenMP
== 52)
19419 S
.Diag(ReductionId
.getLoc(), diag::warn_omp_minus_in_reduction_deprecated
);
19421 SourceRange ReductionIdRange
;
19422 if (ReductionIdScopeSpec
.isValid())
19423 ReductionIdRange
.setBegin(ReductionIdScopeSpec
.getBeginLoc());
19425 ReductionIdRange
.setBegin(ReductionId
.getBeginLoc());
19426 ReductionIdRange
.setEnd(ReductionId
.getEndLoc());
19428 auto IR
= UnresolvedReductions
.begin(), ER
= UnresolvedReductions
.end();
19429 bool FirstIter
= true;
19430 for (Expr
*RefExpr
: VarList
) {
19431 assert(RefExpr
&& "nullptr expr in OpenMP reduction clause.");
19432 // OpenMP [2.1, C/C++]
19433 // A list item is a variable or array section, subject to the restrictions
19434 // specified in Section 2.4 on page 42 and in each of the sections
19435 // describing clauses and directives for which a list appears.
19436 // OpenMP [2.14.3.3, Restrictions, p.1]
19437 // A variable that is part of another variable (as an array or
19438 // structure element) cannot appear in a private clause.
19439 if (!FirstIter
&& IR
!= ER
)
19442 SourceLocation ELoc
;
19443 SourceRange ERange
;
19444 Expr
*SimpleRefExpr
= RefExpr
;
19445 auto Res
= getPrivateItem(S
, SimpleRefExpr
, ELoc
, ERange
,
19446 /*AllowArraySection=*/true);
19448 // Try to find 'declare reduction' corresponding construct before using
19449 // builtin/overloaded operators.
19450 QualType Type
= Context
.DependentTy
;
19451 CXXCastPath BasePath
;
19452 ExprResult DeclareReductionRef
= buildDeclareReductionRef(
19453 S
, ELoc
, ERange
, Stack
->getCurScope(), ReductionIdScopeSpec
,
19454 ReductionId
, Type
, BasePath
, IR
== ER
? nullptr : *IR
);
19455 Expr
*ReductionOp
= nullptr;
19456 if (S
.CurContext
->isDependentContext() &&
19457 (DeclareReductionRef
.isUnset() ||
19458 isa
<UnresolvedLookupExpr
>(DeclareReductionRef
.get())))
19459 ReductionOp
= DeclareReductionRef
.get();
19460 // It will be analyzed later.
19461 RD
.push(RefExpr
, ReductionOp
);
19463 ValueDecl
*D
= Res
.first
;
19467 Expr
*TaskgroupDescriptor
= nullptr;
19469 auto *ASE
= dyn_cast
<ArraySubscriptExpr
>(RefExpr
->IgnoreParens());
19470 auto *OASE
= dyn_cast
<OMPArraySectionExpr
>(RefExpr
->IgnoreParens());
19472 Type
= ASE
->getType().getNonReferenceType();
19474 QualType BaseType
=
19475 OMPArraySectionExpr::getBaseOriginalType(OASE
->getBase());
19476 if (const auto *ATy
= BaseType
->getAsArrayTypeUnsafe())
19477 Type
= ATy
->getElementType();
19479 Type
= BaseType
->getPointeeType();
19480 Type
= Type
.getNonReferenceType();
19482 Type
= Context
.getBaseElementType(D
->getType().getNonReferenceType());
19484 auto *VD
= dyn_cast
<VarDecl
>(D
);
19486 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19487 // A variable that appears in a private clause must not have an incomplete
19488 // type or a reference type.
19489 if (S
.RequireCompleteType(ELoc
, D
->getType(),
19490 diag::err_omp_reduction_incomplete_type
))
19492 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19493 // A list item that appears in a reduction clause must not be
19494 // const-qualified.
19495 if (rejectConstNotMutableType(S
, D
, Type
, ClauseKind
, ELoc
,
19496 /*AcceptIfMutable*/ false, ASE
|| OASE
))
19499 OpenMPDirectiveKind CurrDir
= Stack
->getCurrentDirective();
19500 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
19501 // If a list-item is a reference type then it must bind to the same object
19502 // for all threads of the team.
19503 if (!ASE
&& !OASE
) {
19505 VarDecl
*VDDef
= VD
->getDefinition();
19506 if (VD
->getType()->isReferenceType() && VDDef
&& VDDef
->hasInit()) {
19507 DSARefChecker
Check(Stack
);
19508 if (Check
.Visit(VDDef
->getInit())) {
19509 S
.Diag(ELoc
, diag::err_omp_reduction_ref_type_arg
)
19510 << getOpenMPClauseName(ClauseKind
) << ERange
;
19511 S
.Diag(VDDef
->getLocation(), diag::note_defined_here
) << VDDef
;
19517 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
19519 // Variables with the predetermined data-sharing attributes may not be
19520 // listed in data-sharing attributes clauses, except for the cases
19521 // listed below. For these exceptions only, listing a predetermined
19522 // variable in a data-sharing attribute clause is allowed and overrides
19523 // the variable's predetermined data-sharing attributes.
19524 // OpenMP [2.14.3.6, Restrictions, p.3]
19525 // Any number of reduction clauses can be specified on the directive,
19526 // but a list item can appear only once in the reduction clauses for that
19528 DSAStackTy::DSAVarData DVar
= Stack
->getTopDSA(D
, /*FromParent=*/false);
19529 if (DVar
.CKind
== OMPC_reduction
) {
19530 S
.Diag(ELoc
, diag::err_omp_once_referenced
)
19531 << getOpenMPClauseName(ClauseKind
);
19533 S
.Diag(DVar
.RefExpr
->getExprLoc(), diag::note_omp_referenced
);
19536 if (DVar
.CKind
!= OMPC_unknown
) {
19537 S
.Diag(ELoc
, diag::err_omp_wrong_dsa
)
19538 << getOpenMPClauseName(DVar
.CKind
)
19539 << getOpenMPClauseName(OMPC_reduction
);
19540 reportOriginalDsa(S
, Stack
, D
, DVar
);
19544 // OpenMP [2.14.3.6, Restrictions, p.1]
19545 // A list item that appears in a reduction clause of a worksharing
19546 // construct must be shared in the parallel regions to which any of the
19547 // worksharing regions arising from the worksharing construct bind.
19548 if (isOpenMPWorksharingDirective(CurrDir
) &&
19549 !isOpenMPParallelDirective(CurrDir
) &&
19550 !isOpenMPTeamsDirective(CurrDir
)) {
19551 DVar
= Stack
->getImplicitDSA(D
, true);
19552 if (DVar
.CKind
!= OMPC_shared
) {
19553 S
.Diag(ELoc
, diag::err_omp_required_access
)
19554 << getOpenMPClauseName(OMPC_reduction
)
19555 << getOpenMPClauseName(OMPC_shared
);
19556 reportOriginalDsa(S
, Stack
, D
, DVar
);
19561 // Threadprivates cannot be shared between threads, so dignose if the base
19562 // is a threadprivate variable.
19563 DSAStackTy::DSAVarData DVar
= Stack
->getTopDSA(D
, /*FromParent=*/false);
19564 if (DVar
.CKind
== OMPC_threadprivate
) {
19565 S
.Diag(ELoc
, diag::err_omp_wrong_dsa
)
19566 << getOpenMPClauseName(DVar
.CKind
)
19567 << getOpenMPClauseName(OMPC_reduction
);
19568 reportOriginalDsa(S
, Stack
, D
, DVar
);
19573 // Try to find 'declare reduction' corresponding construct before using
19574 // builtin/overloaded operators.
19575 CXXCastPath BasePath
;
19576 ExprResult DeclareReductionRef
= buildDeclareReductionRef(
19577 S
, ELoc
, ERange
, Stack
->getCurScope(), ReductionIdScopeSpec
,
19578 ReductionId
, Type
, BasePath
, IR
== ER
? nullptr : *IR
);
19579 if (DeclareReductionRef
.isInvalid())
19581 if (S
.CurContext
->isDependentContext() &&
19582 (DeclareReductionRef
.isUnset() ||
19583 isa
<UnresolvedLookupExpr
>(DeclareReductionRef
.get()))) {
19584 RD
.push(RefExpr
, DeclareReductionRef
.get());
19587 if (BOK
== BO_Comma
&& DeclareReductionRef
.isUnset()) {
19588 // Not allowed reduction identifier is found.
19589 if (S
.LangOpts
.OpenMP
> 52)
19590 S
.Diag(ReductionId
.getBeginLoc(),
19591 diag::err_omp_unknown_reduction_identifier_since_omp_6_0
)
19592 << Type
<< ReductionIdRange
;
19594 S
.Diag(ReductionId
.getBeginLoc(),
19595 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0
)
19596 << Type
<< ReductionIdRange
;
19600 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19601 // The type of a list item that appears in a reduction clause must be valid
19602 // for the reduction-identifier. For a max or min reduction in C, the type
19603 // of the list item must be an allowed arithmetic data type: char, int,
19604 // float, double, or _Bool, possibly modified with long, short, signed, or
19605 // unsigned. For a max or min reduction in C++, the type of the list item
19606 // must be an allowed arithmetic data type: char, wchar_t, int, float,
19607 // double, or bool, possibly modified with long, short, signed, or unsigned.
19608 if (DeclareReductionRef
.isUnset()) {
19609 if ((BOK
== BO_GT
|| BOK
== BO_LT
) &&
19610 !(Type
->isScalarType() ||
19611 (S
.getLangOpts().CPlusPlus
&& Type
->isArithmeticType()))) {
19612 S
.Diag(ELoc
, diag::err_omp_clause_not_arithmetic_type_arg
)
19613 << getOpenMPClauseName(ClauseKind
) << S
.getLangOpts().CPlusPlus
;
19614 if (!ASE
&& !OASE
) {
19615 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
19616 VarDecl::DeclarationOnly
;
19617 S
.Diag(D
->getLocation(),
19618 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
19623 if ((BOK
== BO_OrAssign
|| BOK
== BO_AndAssign
|| BOK
== BO_XorAssign
) &&
19624 !S
.getLangOpts().CPlusPlus
&& Type
->isFloatingType()) {
19625 S
.Diag(ELoc
, diag::err_omp_clause_floating_type_arg
)
19626 << getOpenMPClauseName(ClauseKind
);
19627 if (!ASE
&& !OASE
) {
19628 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
19629 VarDecl::DeclarationOnly
;
19630 S
.Diag(D
->getLocation(),
19631 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
19638 Type
= Type
.getNonLValueExprType(Context
).getUnqualifiedType();
19639 VarDecl
*LHSVD
= buildVarDecl(S
, ELoc
, Type
, ".reduction.lhs",
19640 D
->hasAttrs() ? &D
->getAttrs() : nullptr);
19641 VarDecl
*RHSVD
= buildVarDecl(S
, ELoc
, Type
, D
->getName(),
19642 D
->hasAttrs() ? &D
->getAttrs() : nullptr);
19643 QualType PrivateTy
= Type
;
19645 // Try if we can determine constant lengths for all array sections and avoid
19647 bool ConstantLengthOASE
= false;
19649 bool SingleElement
;
19650 llvm::SmallVector
<llvm::APSInt
, 4> ArraySizes
;
19651 ConstantLengthOASE
= checkOMPArraySectionConstantForReduction(
19652 Context
, OASE
, SingleElement
, ArraySizes
);
19654 // If we don't have a single element, we must emit a constant array type.
19655 if (ConstantLengthOASE
&& !SingleElement
) {
19656 for (llvm::APSInt
&Size
: ArraySizes
)
19657 PrivateTy
= Context
.getConstantArrayType(PrivateTy
, Size
, nullptr,
19659 /*IndexTypeQuals=*/0);
19663 if ((OASE
&& !ConstantLengthOASE
) ||
19665 D
->getType().getNonReferenceType()->isVariablyModifiedType())) {
19666 if (!Context
.getTargetInfo().isVLASupported()) {
19667 if (isOpenMPTargetExecutionDirective(Stack
->getCurrentDirective())) {
19668 S
.Diag(ELoc
, diag::err_omp_reduction_vla_unsupported
) << !!OASE
;
19669 S
.Diag(ELoc
, diag::note_vla_unsupported
);
19672 S
.targetDiag(ELoc
, diag::err_omp_reduction_vla_unsupported
) << !!OASE
;
19673 S
.targetDiag(ELoc
, diag::note_vla_unsupported
);
19676 // For arrays/array sections only:
19677 // Create pseudo array type for private copy. The size for this array will
19678 // be generated during codegen.
19679 // For array subscripts or single variables Private Ty is the same as Type
19680 // (type of the variable or single array element).
19681 PrivateTy
= Context
.getVariableArrayType(
19684 OpaqueValueExpr(ELoc
, Context
.getSizeType(), VK_PRValue
),
19685 ArrayType::Normal
, /*IndexTypeQuals=*/0, SourceRange());
19686 } else if (!ASE
&& !OASE
&&
19687 Context
.getAsArrayType(D
->getType().getNonReferenceType())) {
19688 PrivateTy
= D
->getType().getNonReferenceType();
19691 VarDecl
*PrivateVD
=
19692 buildVarDecl(S
, ELoc
, PrivateTy
, D
->getName(),
19693 D
->hasAttrs() ? &D
->getAttrs() : nullptr,
19694 VD
? cast
<DeclRefExpr
>(SimpleRefExpr
) : nullptr);
19695 // Add initializer for private variable.
19696 Expr
*Init
= nullptr;
19697 DeclRefExpr
*LHSDRE
= buildDeclRefExpr(S
, LHSVD
, Type
, ELoc
);
19698 DeclRefExpr
*RHSDRE
= buildDeclRefExpr(S
, RHSVD
, Type
, ELoc
);
19699 if (DeclareReductionRef
.isUsable()) {
19700 auto *DRDRef
= DeclareReductionRef
.getAs
<DeclRefExpr
>();
19701 auto *DRD
= cast
<OMPDeclareReductionDecl
>(DRDRef
->getDecl());
19702 if (DRD
->getInitializer()) {
19704 RHSVD
->setInit(DRDRef
);
19705 RHSVD
->setInitStyle(VarDecl::CallInit
);
19713 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
19714 if (Type
->isScalarType() || Type
->isAnyComplexType())
19715 Init
= S
.ActOnIntegerConstant(ELoc
, /*Val=*/0).get();
19719 if (Type
->isScalarType() || Type
->isAnyComplexType()) {
19720 // '*' and '&&' reduction ops - initializer is '1'.
19721 Init
= S
.ActOnIntegerConstant(ELoc
, /*Val=*/1).get();
19725 // '&' reduction op - initializer is '~0'.
19726 QualType OrigType
= Type
;
19727 if (auto *ComplexTy
= OrigType
->getAs
<ComplexType
>())
19728 Type
= ComplexTy
->getElementType();
19729 if (Type
->isRealFloatingType()) {
19730 llvm::APFloat InitValue
= llvm::APFloat::getAllOnesValue(
19731 Context
.getFloatTypeSemantics(Type
));
19732 Init
= FloatingLiteral::Create(Context
, InitValue
, /*isexact=*/true,
19734 } else if (Type
->isScalarType()) {
19735 uint64_t Size
= Context
.getTypeSize(Type
);
19736 QualType IntTy
= Context
.getIntTypeForBitwidth(Size
, /*Signed=*/0);
19737 llvm::APInt InitValue
= llvm::APInt::getAllOnes(Size
);
19738 Init
= IntegerLiteral::Create(Context
, InitValue
, IntTy
, ELoc
);
19740 if (Init
&& OrigType
->isAnyComplexType()) {
19741 // Init = 0xFFFF + 0xFFFFi;
19742 auto *Im
= new (Context
) ImaginaryLiteral(Init
, OrigType
);
19743 Init
= S
.CreateBuiltinBinOp(ELoc
, BO_Add
, Init
, Im
).get();
19750 // 'min' reduction op - initializer is 'Largest representable number in
19751 // the reduction list item type'.
19752 // 'max' reduction op - initializer is 'Least representable number in
19753 // the reduction list item type'.
19754 if (Type
->isIntegerType() || Type
->isPointerType()) {
19755 bool IsSigned
= Type
->hasSignedIntegerRepresentation();
19756 uint64_t Size
= Context
.getTypeSize(Type
);
19758 Context
.getIntTypeForBitwidth(Size
, /*Signed=*/IsSigned
);
19759 llvm::APInt InitValue
=
19760 (BOK
!= BO_LT
) ? IsSigned
? llvm::APInt::getSignedMinValue(Size
)
19761 : llvm::APInt::getMinValue(Size
)
19762 : IsSigned
? llvm::APInt::getSignedMaxValue(Size
)
19763 : llvm::APInt::getMaxValue(Size
);
19764 Init
= IntegerLiteral::Create(Context
, InitValue
, IntTy
, ELoc
);
19765 if (Type
->isPointerType()) {
19766 // Cast to pointer type.
19767 ExprResult CastExpr
= S
.BuildCStyleCastExpr(
19768 ELoc
, Context
.getTrivialTypeSourceInfo(Type
, ELoc
), ELoc
, Init
);
19769 if (CastExpr
.isInvalid())
19771 Init
= CastExpr
.get();
19773 } else if (Type
->isRealFloatingType()) {
19774 llvm::APFloat InitValue
= llvm::APFloat::getLargest(
19775 Context
.getFloatTypeSemantics(Type
), BOK
!= BO_LT
);
19776 Init
= FloatingLiteral::Create(Context
, InitValue
, /*isexact=*/true,
19805 llvm_unreachable("Unexpected reduction operation");
19808 if (Init
&& DeclareReductionRef
.isUnset()) {
19809 S
.AddInitializerToDecl(RHSVD
, Init
, /*DirectInit=*/false);
19810 // Store initializer for single element in private copy. Will be used
19812 PrivateVD
->setInit(RHSVD
->getInit());
19813 PrivateVD
->setInitStyle(RHSVD
->getInitStyle());
19814 } else if (!Init
) {
19815 S
.ActOnUninitializedDecl(RHSVD
);
19816 // Store initializer for single element in private copy. Will be used
19818 PrivateVD
->setInit(RHSVD
->getInit());
19819 PrivateVD
->setInitStyle(RHSVD
->getInitStyle());
19821 if (RHSVD
->isInvalidDecl())
19823 if (!RHSVD
->hasInit() && DeclareReductionRef
.isUnset()) {
19824 S
.Diag(ELoc
, diag::err_omp_reduction_id_not_compatible
)
19825 << Type
<< ReductionIdRange
;
19826 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
19827 VarDecl::DeclarationOnly
;
19828 S
.Diag(D
->getLocation(),
19829 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
19833 DeclRefExpr
*PrivateDRE
= buildDeclRefExpr(S
, PrivateVD
, PrivateTy
, ELoc
);
19834 ExprResult ReductionOp
;
19835 if (DeclareReductionRef
.isUsable()) {
19836 QualType RedTy
= DeclareReductionRef
.get()->getType();
19837 QualType PtrRedTy
= Context
.getPointerType(RedTy
);
19838 ExprResult LHS
= S
.CreateBuiltinUnaryOp(ELoc
, UO_AddrOf
, LHSDRE
);
19839 ExprResult RHS
= S
.CreateBuiltinUnaryOp(ELoc
, UO_AddrOf
, RHSDRE
);
19840 if (!BasePath
.empty()) {
19841 LHS
= S
.DefaultLvalueConversion(LHS
.get());
19842 RHS
= S
.DefaultLvalueConversion(RHS
.get());
19843 LHS
= ImplicitCastExpr::Create(
19844 Context
, PtrRedTy
, CK_UncheckedDerivedToBase
, LHS
.get(), &BasePath
,
19845 LHS
.get()->getValueKind(), FPOptionsOverride());
19846 RHS
= ImplicitCastExpr::Create(
19847 Context
, PtrRedTy
, CK_UncheckedDerivedToBase
, RHS
.get(), &BasePath
,
19848 RHS
.get()->getValueKind(), FPOptionsOverride());
19850 FunctionProtoType::ExtProtoInfo EPI
;
19851 QualType Params
[] = {PtrRedTy
, PtrRedTy
};
19852 QualType FnTy
= Context
.getFunctionType(Context
.VoidTy
, Params
, EPI
);
19853 auto *OVE
= new (Context
) OpaqueValueExpr(
19854 ELoc
, Context
.getPointerType(FnTy
), VK_PRValue
, OK_Ordinary
,
19855 S
.DefaultLvalueConversion(DeclareReductionRef
.get()).get());
19856 Expr
*Args
[] = {LHS
.get(), RHS
.get()};
19858 CallExpr::Create(Context
, OVE
, Args
, Context
.VoidTy
, VK_PRValue
, ELoc
,
19859 S
.CurFPFeatureOverrides());
19861 BinaryOperatorKind CombBOK
= getRelatedCompoundReductionOp(BOK
);
19862 if (Type
->isRecordType() && CombBOK
!= BOK
) {
19863 Sema::TentativeAnalysisScope
Trap(S
);
19865 S
.BuildBinOp(Stack
->getCurScope(), ReductionId
.getBeginLoc(),
19866 CombBOK
, LHSDRE
, RHSDRE
);
19868 if (!ReductionOp
.isUsable()) {
19870 S
.BuildBinOp(Stack
->getCurScope(), ReductionId
.getBeginLoc(), BOK
,
19872 if (ReductionOp
.isUsable()) {
19873 if (BOK
!= BO_LT
&& BOK
!= BO_GT
) {
19875 S
.BuildBinOp(Stack
->getCurScope(), ReductionId
.getBeginLoc(),
19876 BO_Assign
, LHSDRE
, ReductionOp
.get());
19878 auto *ConditionalOp
= new (Context
)
19879 ConditionalOperator(ReductionOp
.get(), ELoc
, LHSDRE
, ELoc
,
19880 RHSDRE
, Type
, VK_LValue
, OK_Ordinary
);
19882 S
.BuildBinOp(Stack
->getCurScope(), ReductionId
.getBeginLoc(),
19883 BO_Assign
, LHSDRE
, ConditionalOp
);
19887 if (ReductionOp
.isUsable())
19888 ReductionOp
= S
.ActOnFinishFullExpr(ReductionOp
.get(),
19889 /*DiscardedValue*/ false);
19890 if (!ReductionOp
.isUsable())
19894 // Add copy operations for inscan reductions.
19896 ExprResult CopyOpRes
, TempArrayRes
, TempArrayElem
;
19897 if (ClauseKind
== OMPC_reduction
&&
19898 RD
.RedModifier
== OMPC_REDUCTION_inscan
) {
19899 ExprResult RHS
= S
.DefaultLvalueConversion(RHSDRE
);
19900 CopyOpRes
= S
.BuildBinOp(Stack
->getCurScope(), ELoc
, BO_Assign
, LHSDRE
,
19902 if (!CopyOpRes
.isUsable())
19905 S
.ActOnFinishFullExpr(CopyOpRes
.get(), /*DiscardedValue=*/true);
19906 if (!CopyOpRes
.isUsable())
19908 // For simd directive and simd-based directives in simd mode no need to
19909 // construct temp array, need just a single temp element.
19910 if (Stack
->getCurrentDirective() == OMPD_simd
||
19911 (S
.getLangOpts().OpenMPSimd
&&
19912 isOpenMPSimdDirective(Stack
->getCurrentDirective()))) {
19913 VarDecl
*TempArrayVD
=
19914 buildVarDecl(S
, ELoc
, PrivateTy
, D
->getName(),
19915 D
->hasAttrs() ? &D
->getAttrs() : nullptr);
19916 // Add a constructor to the temp decl.
19917 S
.ActOnUninitializedDecl(TempArrayVD
);
19918 TempArrayRes
= buildDeclRefExpr(S
, TempArrayVD
, PrivateTy
, ELoc
);
19920 // Build temp array for prefix sum.
19921 auto *Dim
= new (S
.Context
)
19922 OpaqueValueExpr(ELoc
, S
.Context
.getSizeType(), VK_PRValue
);
19924 S
.Context
.getVariableArrayType(PrivateTy
, Dim
, ArrayType::Normal
,
19925 /*IndexTypeQuals=*/0, {ELoc
, ELoc
});
19926 VarDecl
*TempArrayVD
=
19927 buildVarDecl(S
, ELoc
, ArrayTy
, D
->getName(),
19928 D
->hasAttrs() ? &D
->getAttrs() : nullptr);
19929 // Add a constructor to the temp decl.
19930 S
.ActOnUninitializedDecl(TempArrayVD
);
19931 TempArrayRes
= buildDeclRefExpr(S
, TempArrayVD
, ArrayTy
, ELoc
);
19933 S
.DefaultFunctionArrayLvalueConversion(TempArrayRes
.get());
19934 auto *Idx
= new (S
.Context
)
19935 OpaqueValueExpr(ELoc
, S
.Context
.getSizeType(), VK_PRValue
);
19936 TempArrayElem
= S
.CreateBuiltinArraySubscriptExpr(TempArrayElem
.get(),
19941 // OpenMP [2.15.4.6, Restrictions, p.2]
19942 // A list item that appears in an in_reduction clause of a task construct
19943 // must appear in a task_reduction clause of a construct associated with a
19944 // taskgroup region that includes the participating task in its taskgroup
19945 // set. The construct associated with the innermost region that meets this
19946 // condition must specify the same reduction-identifier as the in_reduction
19948 if (ClauseKind
== OMPC_in_reduction
) {
19949 SourceRange ParentSR
;
19950 BinaryOperatorKind ParentBOK
;
19951 const Expr
*ParentReductionOp
= nullptr;
19952 Expr
*ParentBOKTD
= nullptr, *ParentReductionOpTD
= nullptr;
19953 DSAStackTy::DSAVarData ParentBOKDSA
=
19954 Stack
->getTopMostTaskgroupReductionData(D
, ParentSR
, ParentBOK
,
19956 DSAStackTy::DSAVarData ParentReductionOpDSA
=
19957 Stack
->getTopMostTaskgroupReductionData(
19958 D
, ParentSR
, ParentReductionOp
, ParentReductionOpTD
);
19959 bool IsParentBOK
= ParentBOKDSA
.DKind
!= OMPD_unknown
;
19960 bool IsParentReductionOp
= ParentReductionOpDSA
.DKind
!= OMPD_unknown
;
19961 if ((DeclareReductionRef
.isUnset() && IsParentReductionOp
) ||
19962 (DeclareReductionRef
.isUsable() && IsParentBOK
) ||
19963 (IsParentBOK
&& BOK
!= ParentBOK
) || IsParentReductionOp
) {
19964 bool EmitError
= true;
19965 if (IsParentReductionOp
&& DeclareReductionRef
.isUsable()) {
19966 llvm::FoldingSetNodeID RedId
, ParentRedId
;
19967 ParentReductionOp
->Profile(ParentRedId
, Context
, /*Canonical=*/true);
19968 DeclareReductionRef
.get()->Profile(RedId
, Context
,
19969 /*Canonical=*/true);
19970 EmitError
= RedId
!= ParentRedId
;
19973 S
.Diag(ReductionId
.getBeginLoc(),
19974 diag::err_omp_reduction_identifier_mismatch
)
19975 << ReductionIdRange
<< RefExpr
->getSourceRange();
19976 S
.Diag(ParentSR
.getBegin(),
19977 diag::note_omp_previous_reduction_identifier
)
19979 << (IsParentBOK
? ParentBOKDSA
.RefExpr
19980 : ParentReductionOpDSA
.RefExpr
)
19981 ->getSourceRange();
19985 TaskgroupDescriptor
= IsParentBOK
? ParentBOKTD
: ParentReductionOpTD
;
19988 DeclRefExpr
*Ref
= nullptr;
19989 Expr
*VarsExpr
= RefExpr
->IgnoreParens();
19990 if (!VD
&& !S
.CurContext
->isDependentContext()) {
19992 TransformExprToCaptures
RebuildToCapture(S
, D
);
19994 RebuildToCapture
.TransformExpr(RefExpr
->IgnoreParens()).get();
19995 Ref
= RebuildToCapture
.getCapturedExpr();
19997 VarsExpr
= Ref
= buildCapture(S
, D
, SimpleRefExpr
, /*WithInit=*/false);
19999 if (!S
.isOpenMPCapturedDecl(D
)) {
20000 RD
.ExprCaptures
.emplace_back(Ref
->getDecl());
20001 if (Ref
->getDecl()->hasAttr
<OMPCaptureNoInitAttr
>()) {
20002 ExprResult RefRes
= S
.DefaultLvalueConversion(Ref
);
20003 if (!RefRes
.isUsable())
20005 ExprResult PostUpdateRes
=
20006 S
.BuildBinOp(Stack
->getCurScope(), ELoc
, BO_Assign
, SimpleRefExpr
,
20008 if (!PostUpdateRes
.isUsable())
20010 if (isOpenMPTaskingDirective(Stack
->getCurrentDirective()) ||
20011 Stack
->getCurrentDirective() == OMPD_taskgroup
) {
20012 S
.Diag(RefExpr
->getExprLoc(),
20013 diag::err_omp_reduction_non_addressable_expression
)
20014 << RefExpr
->getSourceRange();
20017 RD
.ExprPostUpdates
.emplace_back(
20018 S
.IgnoredValueConversions(PostUpdateRes
.get()).get());
20022 // All reduction items are still marked as reduction (to do not increase
20023 // code base size).
20024 unsigned Modifier
= RD
.RedModifier
;
20025 // Consider task_reductions as reductions with task modifier. Required for
20026 // correct analysis of in_reduction clauses.
20027 if (CurrDir
== OMPD_taskgroup
&& ClauseKind
== OMPC_task_reduction
)
20028 Modifier
= OMPC_REDUCTION_task
;
20029 Stack
->addDSA(D
, RefExpr
->IgnoreParens(), OMPC_reduction
, Ref
, Modifier
,
20031 if (Modifier
== OMPC_REDUCTION_task
&&
20032 (CurrDir
== OMPD_taskgroup
||
20033 ((isOpenMPParallelDirective(CurrDir
) ||
20034 isOpenMPWorksharingDirective(CurrDir
)) &&
20035 !isOpenMPSimdDirective(CurrDir
)))) {
20036 if (DeclareReductionRef
.isUsable())
20037 Stack
->addTaskgroupReductionData(D
, ReductionIdRange
,
20038 DeclareReductionRef
.get());
20040 Stack
->addTaskgroupReductionData(D
, ReductionIdRange
, BOK
);
20042 RD
.push(VarsExpr
, PrivateDRE
, LHSDRE
, RHSDRE
, ReductionOp
.get(),
20043 TaskgroupDescriptor
, CopyOpRes
.get(), TempArrayRes
.get(),
20044 TempArrayElem
.get());
20046 return RD
.Vars
.empty();
20049 OMPClause
*Sema::ActOnOpenMPReductionClause(
20050 ArrayRef
<Expr
*> VarList
, OpenMPReductionClauseModifier Modifier
,
20051 SourceLocation StartLoc
, SourceLocation LParenLoc
,
20052 SourceLocation ModifierLoc
, SourceLocation ColonLoc
, SourceLocation EndLoc
,
20053 CXXScopeSpec
&ReductionIdScopeSpec
, const DeclarationNameInfo
&ReductionId
,
20054 ArrayRef
<Expr
*> UnresolvedReductions
) {
20055 if (ModifierLoc
.isValid() && Modifier
== OMPC_REDUCTION_unknown
) {
20056 Diag(LParenLoc
, diag::err_omp_unexpected_clause_value
)
20057 << getListOfPossibleValues(OMPC_reduction
, /*First=*/0,
20058 /*Last=*/OMPC_REDUCTION_unknown
)
20059 << getOpenMPClauseName(OMPC_reduction
);
20062 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
20063 // A reduction clause with the inscan reduction-modifier may only appear on a
20064 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
20065 // construct, a parallel worksharing-loop construct or a parallel
20066 // worksharing-loop SIMD construct.
20067 if (Modifier
== OMPC_REDUCTION_inscan
&&
20068 (DSAStack
->getCurrentDirective() != OMPD_for
&&
20069 DSAStack
->getCurrentDirective() != OMPD_for_simd
&&
20070 DSAStack
->getCurrentDirective() != OMPD_simd
&&
20071 DSAStack
->getCurrentDirective() != OMPD_parallel_for
&&
20072 DSAStack
->getCurrentDirective() != OMPD_parallel_for_simd
)) {
20073 Diag(ModifierLoc
, diag::err_omp_wrong_inscan_reduction
);
20077 ReductionData
RD(VarList
.size(), Modifier
);
20078 if (actOnOMPReductionKindClause(*this, DSAStack
, OMPC_reduction
, VarList
,
20079 StartLoc
, LParenLoc
, ColonLoc
, EndLoc
,
20080 ReductionIdScopeSpec
, ReductionId
,
20081 UnresolvedReductions
, RD
))
20084 return OMPReductionClause::Create(
20085 Context
, StartLoc
, LParenLoc
, ModifierLoc
, ColonLoc
, EndLoc
, Modifier
,
20086 RD
.Vars
, ReductionIdScopeSpec
.getWithLocInContext(Context
), ReductionId
,
20087 RD
.Privates
, RD
.LHSs
, RD
.RHSs
, RD
.ReductionOps
, RD
.InscanCopyOps
,
20088 RD
.InscanCopyArrayTemps
, RD
.InscanCopyArrayElems
,
20089 buildPreInits(Context
, RD
.ExprCaptures
),
20090 buildPostUpdate(*this, RD
.ExprPostUpdates
));
20093 OMPClause
*Sema::ActOnOpenMPTaskReductionClause(
20094 ArrayRef
<Expr
*> VarList
, SourceLocation StartLoc
, SourceLocation LParenLoc
,
20095 SourceLocation ColonLoc
, SourceLocation EndLoc
,
20096 CXXScopeSpec
&ReductionIdScopeSpec
, const DeclarationNameInfo
&ReductionId
,
20097 ArrayRef
<Expr
*> UnresolvedReductions
) {
20098 ReductionData
RD(VarList
.size());
20099 if (actOnOMPReductionKindClause(*this, DSAStack
, OMPC_task_reduction
, VarList
,
20100 StartLoc
, LParenLoc
, ColonLoc
, EndLoc
,
20101 ReductionIdScopeSpec
, ReductionId
,
20102 UnresolvedReductions
, RD
))
20105 return OMPTaskReductionClause::Create(
20106 Context
, StartLoc
, LParenLoc
, ColonLoc
, EndLoc
, RD
.Vars
,
20107 ReductionIdScopeSpec
.getWithLocInContext(Context
), ReductionId
,
20108 RD
.Privates
, RD
.LHSs
, RD
.RHSs
, RD
.ReductionOps
,
20109 buildPreInits(Context
, RD
.ExprCaptures
),
20110 buildPostUpdate(*this, RD
.ExprPostUpdates
));
20113 OMPClause
*Sema::ActOnOpenMPInReductionClause(
20114 ArrayRef
<Expr
*> VarList
, SourceLocation StartLoc
, SourceLocation LParenLoc
,
20115 SourceLocation ColonLoc
, SourceLocation EndLoc
,
20116 CXXScopeSpec
&ReductionIdScopeSpec
, const DeclarationNameInfo
&ReductionId
,
20117 ArrayRef
<Expr
*> UnresolvedReductions
) {
20118 ReductionData
RD(VarList
.size());
20119 if (actOnOMPReductionKindClause(*this, DSAStack
, OMPC_in_reduction
, VarList
,
20120 StartLoc
, LParenLoc
, ColonLoc
, EndLoc
,
20121 ReductionIdScopeSpec
, ReductionId
,
20122 UnresolvedReductions
, RD
))
20125 return OMPInReductionClause::Create(
20126 Context
, StartLoc
, LParenLoc
, ColonLoc
, EndLoc
, RD
.Vars
,
20127 ReductionIdScopeSpec
.getWithLocInContext(Context
), ReductionId
,
20128 RD
.Privates
, RD
.LHSs
, RD
.RHSs
, RD
.ReductionOps
, RD
.TaskgroupDescriptors
,
20129 buildPreInits(Context
, RD
.ExprCaptures
),
20130 buildPostUpdate(*this, RD
.ExprPostUpdates
));
20133 bool Sema::CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind
,
20134 SourceLocation LinLoc
) {
20135 if ((!LangOpts
.CPlusPlus
&& LinKind
!= OMPC_LINEAR_val
) ||
20136 LinKind
== OMPC_LINEAR_unknown
) {
20137 Diag(LinLoc
, diag::err_omp_wrong_linear_modifier
) << LangOpts
.CPlusPlus
;
20143 bool Sema::CheckOpenMPLinearDecl(const ValueDecl
*D
, SourceLocation ELoc
,
20144 OpenMPLinearClauseKind LinKind
, QualType Type
,
20145 bool IsDeclareSimd
) {
20146 const auto *VD
= dyn_cast_or_null
<VarDecl
>(D
);
20147 // A variable must not have an incomplete type or a reference type.
20148 if (RequireCompleteType(ELoc
, Type
, diag::err_omp_linear_incomplete_type
))
20150 if ((LinKind
== OMPC_LINEAR_uval
|| LinKind
== OMPC_LINEAR_ref
) &&
20151 !Type
->isReferenceType()) {
20152 Diag(ELoc
, diag::err_omp_wrong_linear_modifier_non_reference
)
20153 << Type
<< getOpenMPSimpleClauseTypeName(OMPC_linear
, LinKind
);
20156 Type
= Type
.getNonReferenceType();
20158 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
20159 // A variable that is privatized must not have a const-qualified type
20160 // unless it is of class type with a mutable member. This restriction does
20161 // not apply to the firstprivate clause, nor to the linear clause on
20162 // declarative directives (like declare simd).
20163 if (!IsDeclareSimd
&&
20164 rejectConstNotMutableType(*this, D
, Type
, OMPC_linear
, ELoc
))
20167 // A list item must be of integral or pointer type.
20168 Type
= Type
.getUnqualifiedType().getCanonicalType();
20169 const auto *Ty
= Type
.getTypePtrOrNull();
20170 if (!Ty
|| (LinKind
!= OMPC_LINEAR_ref
&& !Ty
->isDependentType() &&
20171 !Ty
->isIntegralType(Context
) && !Ty
->isPointerType())) {
20172 Diag(ELoc
, diag::err_omp_linear_expected_int_or_ptr
) << Type
;
20174 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
20175 VarDecl::DeclarationOnly
;
20176 Diag(D
->getLocation(),
20177 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
20185 OMPClause
*Sema::ActOnOpenMPLinearClause(
20186 ArrayRef
<Expr
*> VarList
, Expr
*Step
, SourceLocation StartLoc
,
20187 SourceLocation LParenLoc
, OpenMPLinearClauseKind LinKind
,
20188 SourceLocation LinLoc
, SourceLocation ColonLoc
, SourceLocation EndLoc
) {
20189 SmallVector
<Expr
*, 8> Vars
;
20190 SmallVector
<Expr
*, 8> Privates
;
20191 SmallVector
<Expr
*, 8> Inits
;
20192 SmallVector
<Decl
*, 4> ExprCaptures
;
20193 SmallVector
<Expr
*, 4> ExprPostUpdates
;
20194 if (CheckOpenMPLinearModifier(LinKind
, LinLoc
))
20195 LinKind
= OMPC_LINEAR_val
;
20196 for (Expr
*RefExpr
: VarList
) {
20197 assert(RefExpr
&& "NULL expr in OpenMP linear clause.");
20198 SourceLocation ELoc
;
20199 SourceRange ERange
;
20200 Expr
*SimpleRefExpr
= RefExpr
;
20201 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
20203 // It will be analyzed later.
20204 Vars
.push_back(RefExpr
);
20205 Privates
.push_back(nullptr);
20206 Inits
.push_back(nullptr);
20208 ValueDecl
*D
= Res
.first
;
20212 QualType Type
= D
->getType();
20213 auto *VD
= dyn_cast
<VarDecl
>(D
);
20215 // OpenMP [2.14.3.7, linear clause]
20216 // A list-item cannot appear in more than one linear clause.
20217 // A list-item that appears in a linear clause cannot appear in any
20218 // other data-sharing attribute clause.
20219 DSAStackTy::DSAVarData DVar
= DSAStack
->getTopDSA(D
, /*FromParent=*/false);
20220 if (DVar
.RefExpr
) {
20221 Diag(ELoc
, diag::err_omp_wrong_dsa
) << getOpenMPClauseName(DVar
.CKind
)
20222 << getOpenMPClauseName(OMPC_linear
);
20223 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
20227 if (CheckOpenMPLinearDecl(D
, ELoc
, LinKind
, Type
))
20229 Type
= Type
.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20231 // Build private copy of original var.
20233 buildVarDecl(*this, ELoc
, Type
, D
->getName(),
20234 D
->hasAttrs() ? &D
->getAttrs() : nullptr,
20235 VD
? cast
<DeclRefExpr
>(SimpleRefExpr
) : nullptr);
20236 DeclRefExpr
*PrivateRef
= buildDeclRefExpr(*this, Private
, Type
, ELoc
);
20237 // Build var to save initial value.
20238 VarDecl
*Init
= buildVarDecl(*this, ELoc
, Type
, ".linear.start");
20240 DeclRefExpr
*Ref
= nullptr;
20241 if (!VD
&& !CurContext
->isDependentContext()) {
20242 Ref
= buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/false);
20243 if (!isOpenMPCapturedDecl(D
)) {
20244 ExprCaptures
.push_back(Ref
->getDecl());
20245 if (Ref
->getDecl()->hasAttr
<OMPCaptureNoInitAttr
>()) {
20246 ExprResult RefRes
= DefaultLvalueConversion(Ref
);
20247 if (!RefRes
.isUsable())
20249 ExprResult PostUpdateRes
=
20250 BuildBinOp(DSAStack
->getCurScope(), ELoc
, BO_Assign
,
20251 SimpleRefExpr
, RefRes
.get());
20252 if (!PostUpdateRes
.isUsable())
20254 ExprPostUpdates
.push_back(
20255 IgnoredValueConversions(PostUpdateRes
.get()).get());
20259 if (LinKind
== OMPC_LINEAR_uval
)
20260 InitExpr
= VD
? VD
->getInit() : SimpleRefExpr
;
20262 InitExpr
= VD
? SimpleRefExpr
: Ref
;
20263 AddInitializerToDecl(Init
, DefaultLvalueConversion(InitExpr
).get(),
20264 /*DirectInit=*/false);
20265 DeclRefExpr
*InitRef
= buildDeclRefExpr(*this, Init
, Type
, ELoc
);
20267 DSAStack
->addDSA(D
, RefExpr
->IgnoreParens(), OMPC_linear
, Ref
);
20268 Vars
.push_back((VD
|| CurContext
->isDependentContext())
20269 ? RefExpr
->IgnoreParens()
20271 Privates
.push_back(PrivateRef
);
20272 Inits
.push_back(InitRef
);
20278 Expr
*StepExpr
= Step
;
20279 Expr
*CalcStepExpr
= nullptr;
20280 if (Step
&& !Step
->isValueDependent() && !Step
->isTypeDependent() &&
20281 !Step
->isInstantiationDependent() &&
20282 !Step
->containsUnexpandedParameterPack()) {
20283 SourceLocation StepLoc
= Step
->getBeginLoc();
20284 ExprResult Val
= PerformOpenMPImplicitIntegerConversion(StepLoc
, Step
);
20285 if (Val
.isInvalid())
20287 StepExpr
= Val
.get();
20289 // Build var to save the step value.
20291 buildVarDecl(*this, StepLoc
, StepExpr
->getType(), ".linear.step");
20292 ExprResult SaveRef
=
20293 buildDeclRefExpr(*this, SaveVar
, StepExpr
->getType(), StepLoc
);
20294 ExprResult CalcStep
=
20295 BuildBinOp(CurScope
, StepLoc
, BO_Assign
, SaveRef
.get(), StepExpr
);
20296 CalcStep
= ActOnFinishFullExpr(CalcStep
.get(), /*DiscardedValue*/ false);
20298 // Warn about zero linear step (it would be probably better specified as
20299 // making corresponding variables 'const').
20300 if (std::optional
<llvm::APSInt
> Result
=
20301 StepExpr
->getIntegerConstantExpr(Context
)) {
20302 if (!Result
->isNegative() && !Result
->isStrictlyPositive())
20303 Diag(StepLoc
, diag::warn_omp_linear_step_zero
)
20304 << Vars
[0] << (Vars
.size() > 1);
20305 } else if (CalcStep
.isUsable()) {
20306 // Calculate the step beforehand instead of doing this on each iteration.
20307 // (This is not used if the number of iterations may be kfold-ed).
20308 CalcStepExpr
= CalcStep
.get();
20312 return OMPLinearClause::Create(Context
, StartLoc
, LParenLoc
, LinKind
, LinLoc
,
20313 ColonLoc
, EndLoc
, Vars
, Privates
, Inits
,
20314 StepExpr
, CalcStepExpr
,
20315 buildPreInits(Context
, ExprCaptures
),
20316 buildPostUpdate(*this, ExprPostUpdates
));
20319 static bool FinishOpenMPLinearClause(OMPLinearClause
&Clause
, DeclRefExpr
*IV
,
20320 Expr
*NumIterations
, Sema
&SemaRef
,
20321 Scope
*S
, DSAStackTy
*Stack
) {
20322 // Walk the vars and build update/final expressions for the CodeGen.
20323 SmallVector
<Expr
*, 8> Updates
;
20324 SmallVector
<Expr
*, 8> Finals
;
20325 SmallVector
<Expr
*, 8> UsedExprs
;
20326 Expr
*Step
= Clause
.getStep();
20327 Expr
*CalcStep
= Clause
.getCalcStep();
20328 // OpenMP [2.14.3.7, linear clause]
20329 // If linear-step is not specified it is assumed to be 1.
20331 Step
= SemaRef
.ActOnIntegerConstant(SourceLocation(), 1).get();
20333 Step
= cast
<BinaryOperator
>(CalcStep
)->getLHS();
20334 bool HasErrors
= false;
20335 auto CurInit
= Clause
.inits().begin();
20336 auto CurPrivate
= Clause
.privates().begin();
20337 OpenMPLinearClauseKind LinKind
= Clause
.getModifier();
20338 for (Expr
*RefExpr
: Clause
.varlists()) {
20339 SourceLocation ELoc
;
20340 SourceRange ERange
;
20341 Expr
*SimpleRefExpr
= RefExpr
;
20342 auto Res
= getPrivateItem(SemaRef
, SimpleRefExpr
, ELoc
, ERange
);
20343 ValueDecl
*D
= Res
.first
;
20344 if (Res
.second
|| !D
) {
20345 Updates
.push_back(nullptr);
20346 Finals
.push_back(nullptr);
20350 auto &&Info
= Stack
->isLoopControlVariable(D
);
20351 // OpenMP [2.15.11, distribute simd Construct]
20352 // A list item may not appear in a linear clause, unless it is the loop
20353 // iteration variable.
20354 if (isOpenMPDistributeDirective(Stack
->getCurrentDirective()) &&
20355 isOpenMPSimdDirective(Stack
->getCurrentDirective()) && !Info
.first
) {
20357 diag::err_omp_linear_distribute_var_non_loop_iteration
);
20358 Updates
.push_back(nullptr);
20359 Finals
.push_back(nullptr);
20363 Expr
*InitExpr
= *CurInit
;
20365 // Build privatized reference to the current linear var.
20366 auto *DE
= cast
<DeclRefExpr
>(SimpleRefExpr
);
20368 if (LinKind
== OMPC_LINEAR_uval
)
20369 CapturedRef
= cast
<VarDecl
>(DE
->getDecl())->getInit();
20372 buildDeclRefExpr(SemaRef
, cast
<VarDecl
>(DE
->getDecl()),
20373 DE
->getType().getUnqualifiedType(), DE
->getExprLoc(),
20374 /*RefersToCapture=*/true);
20376 // Build update: Var = InitExpr + IV * Step
20379 Update
= buildCounterUpdate(
20380 SemaRef
, S
, RefExpr
->getExprLoc(), *CurPrivate
, InitExpr
, IV
, Step
,
20381 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
20383 Update
= *CurPrivate
;
20384 Update
= SemaRef
.ActOnFinishFullExpr(Update
.get(), DE
->getBeginLoc(),
20385 /*DiscardedValue*/ false);
20387 // Build final: Var = PrivCopy;
20390 Final
= SemaRef
.BuildBinOp(
20391 S
, RefExpr
->getExprLoc(), BO_Assign
, CapturedRef
,
20392 SemaRef
.DefaultLvalueConversion(*CurPrivate
).get());
20394 Final
= *CurPrivate
;
20395 Final
= SemaRef
.ActOnFinishFullExpr(Final
.get(), DE
->getBeginLoc(),
20396 /*DiscardedValue*/ false);
20398 if (!Update
.isUsable() || !Final
.isUsable()) {
20399 Updates
.push_back(nullptr);
20400 Finals
.push_back(nullptr);
20401 UsedExprs
.push_back(nullptr);
20404 Updates
.push_back(Update
.get());
20405 Finals
.push_back(Final
.get());
20407 UsedExprs
.push_back(SimpleRefExpr
);
20412 if (Expr
*S
= Clause
.getStep())
20413 UsedExprs
.push_back(S
);
20414 // Fill the remaining part with the nullptr.
20415 UsedExprs
.append(Clause
.varlist_size() + 1 - UsedExprs
.size(), nullptr);
20416 Clause
.setUpdates(Updates
);
20417 Clause
.setFinals(Finals
);
20418 Clause
.setUsedExprs(UsedExprs
);
20422 OMPClause
*Sema::ActOnOpenMPAlignedClause(
20423 ArrayRef
<Expr
*> VarList
, Expr
*Alignment
, SourceLocation StartLoc
,
20424 SourceLocation LParenLoc
, SourceLocation ColonLoc
, SourceLocation EndLoc
) {
20425 SmallVector
<Expr
*, 8> Vars
;
20426 for (Expr
*RefExpr
: VarList
) {
20427 assert(RefExpr
&& "NULL expr in OpenMP linear clause.");
20428 SourceLocation ELoc
;
20429 SourceRange ERange
;
20430 Expr
*SimpleRefExpr
= RefExpr
;
20431 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
20433 // It will be analyzed later.
20434 Vars
.push_back(RefExpr
);
20436 ValueDecl
*D
= Res
.first
;
20440 QualType QType
= D
->getType();
20441 auto *VD
= dyn_cast
<VarDecl
>(D
);
20443 // OpenMP [2.8.1, simd construct, Restrictions]
20444 // The type of list items appearing in the aligned clause must be
20445 // array, pointer, reference to array, or reference to pointer.
20446 QType
= QType
.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20447 const Type
*Ty
= QType
.getTypePtrOrNull();
20448 if (!Ty
|| (!Ty
->isArrayType() && !Ty
->isPointerType())) {
20449 Diag(ELoc
, diag::err_omp_aligned_expected_array_or_ptr
)
20450 << QType
<< getLangOpts().CPlusPlus
<< ERange
;
20451 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
20452 VarDecl::DeclarationOnly
;
20453 Diag(D
->getLocation(),
20454 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
20459 // OpenMP [2.8.1, simd construct, Restrictions]
20460 // A list-item cannot appear in more than one aligned clause.
20461 if (const Expr
*PrevRef
= DSAStack
->addUniqueAligned(D
, SimpleRefExpr
)) {
20462 Diag(ELoc
, diag::err_omp_used_in_clause_twice
)
20463 << 0 << getOpenMPClauseName(OMPC_aligned
) << ERange
;
20464 Diag(PrevRef
->getExprLoc(), diag::note_omp_explicit_dsa
)
20465 << getOpenMPClauseName(OMPC_aligned
);
20469 DeclRefExpr
*Ref
= nullptr;
20470 if (!VD
&& isOpenMPCapturedDecl(D
))
20471 Ref
= buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/true);
20472 Vars
.push_back(DefaultFunctionArrayConversion(
20473 (VD
|| !Ref
) ? RefExpr
->IgnoreParens() : Ref
)
20477 // OpenMP [2.8.1, simd construct, Description]
20478 // The parameter of the aligned clause, alignment, must be a constant
20479 // positive integer expression.
20480 // If no optional parameter is specified, implementation-defined default
20481 // alignments for SIMD instructions on the target platforms are assumed.
20482 if (Alignment
!= nullptr) {
20483 ExprResult AlignResult
=
20484 VerifyPositiveIntegerConstantInClause(Alignment
, OMPC_aligned
);
20485 if (AlignResult
.isInvalid())
20487 Alignment
= AlignResult
.get();
20492 return OMPAlignedClause::Create(Context
, StartLoc
, LParenLoc
, ColonLoc
,
20493 EndLoc
, Vars
, Alignment
);
20496 OMPClause
*Sema::ActOnOpenMPCopyinClause(ArrayRef
<Expr
*> VarList
,
20497 SourceLocation StartLoc
,
20498 SourceLocation LParenLoc
,
20499 SourceLocation EndLoc
) {
20500 SmallVector
<Expr
*, 8> Vars
;
20501 SmallVector
<Expr
*, 8> SrcExprs
;
20502 SmallVector
<Expr
*, 8> DstExprs
;
20503 SmallVector
<Expr
*, 8> AssignmentOps
;
20504 for (Expr
*RefExpr
: VarList
) {
20505 assert(RefExpr
&& "NULL expr in OpenMP copyin clause.");
20506 if (isa
<DependentScopeDeclRefExpr
>(RefExpr
)) {
20507 // It will be analyzed later.
20508 Vars
.push_back(RefExpr
);
20509 SrcExprs
.push_back(nullptr);
20510 DstExprs
.push_back(nullptr);
20511 AssignmentOps
.push_back(nullptr);
20515 SourceLocation ELoc
= RefExpr
->getExprLoc();
20516 // OpenMP [2.1, C/C++]
20517 // A list item is a variable name.
20518 // OpenMP [2.14.4.1, Restrictions, p.1]
20519 // A list item that appears in a copyin clause must be threadprivate.
20520 auto *DE
= dyn_cast
<DeclRefExpr
>(RefExpr
);
20521 if (!DE
|| !isa
<VarDecl
>(DE
->getDecl())) {
20522 Diag(ELoc
, diag::err_omp_expected_var_name_member_expr
)
20523 << 0 << RefExpr
->getSourceRange();
20527 Decl
*D
= DE
->getDecl();
20528 auto *VD
= cast
<VarDecl
>(D
);
20530 QualType Type
= VD
->getType();
20531 if (Type
->isDependentType() || Type
->isInstantiationDependentType()) {
20532 // It will be analyzed later.
20533 Vars
.push_back(DE
);
20534 SrcExprs
.push_back(nullptr);
20535 DstExprs
.push_back(nullptr);
20536 AssignmentOps
.push_back(nullptr);
20540 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
20541 // A list item that appears in a copyin clause must be threadprivate.
20542 if (!DSAStack
->isThreadPrivate(VD
)) {
20543 Diag(ELoc
, diag::err_omp_required_access
)
20544 << getOpenMPClauseName(OMPC_copyin
)
20545 << getOpenMPDirectiveName(OMPD_threadprivate
);
20549 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20550 // A variable of class type (or array thereof) that appears in a
20551 // copyin clause requires an accessible, unambiguous copy assignment
20552 // operator for the class type.
20553 QualType ElemType
= Context
.getBaseElementType(Type
).getNonReferenceType();
20555 buildVarDecl(*this, DE
->getBeginLoc(), ElemType
.getUnqualifiedType(),
20556 ".copyin.src", VD
->hasAttrs() ? &VD
->getAttrs() : nullptr);
20557 DeclRefExpr
*PseudoSrcExpr
= buildDeclRefExpr(
20558 *this, SrcVD
, ElemType
.getUnqualifiedType(), DE
->getExprLoc());
20560 buildVarDecl(*this, DE
->getBeginLoc(), ElemType
, ".copyin.dst",
20561 VD
->hasAttrs() ? &VD
->getAttrs() : nullptr);
20562 DeclRefExpr
*PseudoDstExpr
=
20563 buildDeclRefExpr(*this, DstVD
, ElemType
, DE
->getExprLoc());
20564 // For arrays generate assignment operation for single element and replace
20565 // it by the original array element in CodeGen.
20566 ExprResult AssignmentOp
=
20567 BuildBinOp(/*S=*/nullptr, DE
->getExprLoc(), BO_Assign
, PseudoDstExpr
,
20569 if (AssignmentOp
.isInvalid())
20571 AssignmentOp
= ActOnFinishFullExpr(AssignmentOp
.get(), DE
->getExprLoc(),
20572 /*DiscardedValue*/ false);
20573 if (AssignmentOp
.isInvalid())
20576 DSAStack
->addDSA(VD
, DE
, OMPC_copyin
);
20577 Vars
.push_back(DE
);
20578 SrcExprs
.push_back(PseudoSrcExpr
);
20579 DstExprs
.push_back(PseudoDstExpr
);
20580 AssignmentOps
.push_back(AssignmentOp
.get());
20586 return OMPCopyinClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
, Vars
,
20587 SrcExprs
, DstExprs
, AssignmentOps
);
20590 OMPClause
*Sema::ActOnOpenMPCopyprivateClause(ArrayRef
<Expr
*> VarList
,
20591 SourceLocation StartLoc
,
20592 SourceLocation LParenLoc
,
20593 SourceLocation EndLoc
) {
20594 SmallVector
<Expr
*, 8> Vars
;
20595 SmallVector
<Expr
*, 8> SrcExprs
;
20596 SmallVector
<Expr
*, 8> DstExprs
;
20597 SmallVector
<Expr
*, 8> AssignmentOps
;
20598 for (Expr
*RefExpr
: VarList
) {
20599 assert(RefExpr
&& "NULL expr in OpenMP linear clause.");
20600 SourceLocation ELoc
;
20601 SourceRange ERange
;
20602 Expr
*SimpleRefExpr
= RefExpr
;
20603 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
20605 // It will be analyzed later.
20606 Vars
.push_back(RefExpr
);
20607 SrcExprs
.push_back(nullptr);
20608 DstExprs
.push_back(nullptr);
20609 AssignmentOps
.push_back(nullptr);
20611 ValueDecl
*D
= Res
.first
;
20615 QualType Type
= D
->getType();
20616 auto *VD
= dyn_cast
<VarDecl
>(D
);
20618 // OpenMP [2.14.4.2, Restrictions, p.2]
20619 // A list item that appears in a copyprivate clause may not appear in a
20620 // private or firstprivate clause on the single construct.
20621 if (!VD
|| !DSAStack
->isThreadPrivate(VD
)) {
20622 DSAStackTy::DSAVarData DVar
=
20623 DSAStack
->getTopDSA(D
, /*FromParent=*/false);
20624 if (DVar
.CKind
!= OMPC_unknown
&& DVar
.CKind
!= OMPC_copyprivate
&&
20626 Diag(ELoc
, diag::err_omp_wrong_dsa
)
20627 << getOpenMPClauseName(DVar
.CKind
)
20628 << getOpenMPClauseName(OMPC_copyprivate
);
20629 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
20633 // OpenMP [2.11.4.2, Restrictions, p.1]
20634 // All list items that appear in a copyprivate clause must be either
20635 // threadprivate or private in the enclosing context.
20636 if (DVar
.CKind
== OMPC_unknown
) {
20637 DVar
= DSAStack
->getImplicitDSA(D
, false);
20638 if (DVar
.CKind
== OMPC_shared
) {
20639 Diag(ELoc
, diag::err_omp_required_access
)
20640 << getOpenMPClauseName(OMPC_copyprivate
)
20641 << "threadprivate or private in the enclosing context";
20642 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
20648 // Variably modified types are not supported.
20649 if (!Type
->isAnyPointerType() && Type
->isVariablyModifiedType()) {
20650 Diag(ELoc
, diag::err_omp_variably_modified_type_not_supported
)
20651 << getOpenMPClauseName(OMPC_copyprivate
) << Type
20652 << getOpenMPDirectiveName(DSAStack
->getCurrentDirective());
20653 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
20654 VarDecl::DeclarationOnly
;
20655 Diag(D
->getLocation(),
20656 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
20661 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20662 // A variable of class type (or array thereof) that appears in a
20663 // copyin clause requires an accessible, unambiguous copy assignment
20664 // operator for the class type.
20665 Type
= Context
.getBaseElementType(Type
.getNonReferenceType())
20666 .getUnqualifiedType();
20668 buildVarDecl(*this, RefExpr
->getBeginLoc(), Type
, ".copyprivate.src",
20669 D
->hasAttrs() ? &D
->getAttrs() : nullptr);
20670 DeclRefExpr
*PseudoSrcExpr
= buildDeclRefExpr(*this, SrcVD
, Type
, ELoc
);
20672 buildVarDecl(*this, RefExpr
->getBeginLoc(), Type
, ".copyprivate.dst",
20673 D
->hasAttrs() ? &D
->getAttrs() : nullptr);
20674 DeclRefExpr
*PseudoDstExpr
= buildDeclRefExpr(*this, DstVD
, Type
, ELoc
);
20675 ExprResult AssignmentOp
= BuildBinOp(
20676 DSAStack
->getCurScope(), ELoc
, BO_Assign
, PseudoDstExpr
, PseudoSrcExpr
);
20677 if (AssignmentOp
.isInvalid())
20680 ActOnFinishFullExpr(AssignmentOp
.get(), ELoc
, /*DiscardedValue*/ false);
20681 if (AssignmentOp
.isInvalid())
20684 // No need to mark vars as copyprivate, they are already threadprivate or
20685 // implicitly private.
20686 assert(VD
|| isOpenMPCapturedDecl(D
));
20688 VD
? RefExpr
->IgnoreParens()
20689 : buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/false));
20690 SrcExprs
.push_back(PseudoSrcExpr
);
20691 DstExprs
.push_back(PseudoDstExpr
);
20692 AssignmentOps
.push_back(AssignmentOp
.get());
20698 return OMPCopyprivateClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
,
20699 Vars
, SrcExprs
, DstExprs
, AssignmentOps
);
20702 OMPClause
*Sema::ActOnOpenMPFlushClause(ArrayRef
<Expr
*> VarList
,
20703 SourceLocation StartLoc
,
20704 SourceLocation LParenLoc
,
20705 SourceLocation EndLoc
) {
20706 if (VarList
.empty())
20709 return OMPFlushClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
, VarList
);
20712 /// Tries to find omp_depend_t. type.
20713 static bool findOMPDependT(Sema
&S
, SourceLocation Loc
, DSAStackTy
*Stack
,
20714 bool Diagnose
= true) {
20715 QualType OMPDependT
= Stack
->getOMPDependT();
20716 if (!OMPDependT
.isNull())
20718 IdentifierInfo
*II
= &S
.PP
.getIdentifierTable().get("omp_depend_t");
20719 ParsedType PT
= S
.getTypeName(*II
, Loc
, S
.getCurScope());
20720 if (!PT
.getAsOpaquePtr() || PT
.get().isNull()) {
20722 S
.Diag(Loc
, diag::err_omp_implied_type_not_found
) << "omp_depend_t";
20725 Stack
->setOMPDependT(PT
.get());
20729 OMPClause
*Sema::ActOnOpenMPDepobjClause(Expr
*Depobj
, SourceLocation StartLoc
,
20730 SourceLocation LParenLoc
,
20731 SourceLocation EndLoc
) {
20735 bool OMPDependTFound
= findOMPDependT(*this, StartLoc
, DSAStack
);
20737 // OpenMP 5.0, 2.17.10.1 depobj Construct
20738 // depobj is an lvalue expression of type omp_depend_t.
20739 if (!Depobj
->isTypeDependent() && !Depobj
->isValueDependent() &&
20740 !Depobj
->isInstantiationDependent() &&
20741 !Depobj
->containsUnexpandedParameterPack() &&
20742 (OMPDependTFound
&&
20743 !Context
.typesAreCompatible(DSAStack
->getOMPDependT(), Depobj
->getType(),
20744 /*CompareUnqualified=*/true))) {
20745 Diag(Depobj
->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue
)
20746 << 0 << Depobj
->getType() << Depobj
->getSourceRange();
20749 if (!Depobj
->isLValue()) {
20750 Diag(Depobj
->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue
)
20751 << 1 << Depobj
->getSourceRange();
20754 return OMPDepobjClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
, Depobj
);
20758 // Utility struct that gathers the related info for doacross clause.
20759 struct DoacrossDataInfoTy
{
20760 // The list of expressions.
20761 SmallVector
<Expr
*, 8> Vars
;
20762 // The OperatorOffset for doacross loop.
20763 DSAStackTy::OperatorOffsetTy OpsOffs
;
20764 // The depended loop count.
20765 llvm::APSInt TotalDepCount
;
20768 static DoacrossDataInfoTy
20769 ProcessOpenMPDoacrossClauseCommon(Sema
&SemaRef
, bool IsSource
,
20770 ArrayRef
<Expr
*> VarList
, DSAStackTy
*Stack
,
20771 SourceLocation EndLoc
) {
20773 SmallVector
<Expr
*, 8> Vars
;
20774 DSAStackTy::OperatorOffsetTy OpsOffs
;
20775 llvm::APSInt
DepCounter(/*BitWidth=*/32);
20776 llvm::APSInt
TotalDepCount(/*BitWidth=*/32);
20778 if (const Expr
*OrderedCountExpr
=
20779 Stack
->getParentOrderedRegionParam().first
) {
20780 TotalDepCount
= OrderedCountExpr
->EvaluateKnownConstInt(SemaRef
.Context
);
20781 TotalDepCount
.setIsUnsigned(/*Val=*/true);
20784 for (Expr
*RefExpr
: VarList
) {
20785 assert(RefExpr
&& "NULL expr in OpenMP doacross clause.");
20786 if (isa
<DependentScopeDeclRefExpr
>(RefExpr
)) {
20787 // It will be analyzed later.
20788 Vars
.push_back(RefExpr
);
20792 SourceLocation ELoc
= RefExpr
->getExprLoc();
20793 Expr
*SimpleExpr
= RefExpr
->IgnoreParenCasts();
20795 if (Stack
->getParentOrderedRegionParam().first
&&
20796 DepCounter
>= TotalDepCount
) {
20797 SemaRef
.Diag(ELoc
, diag::err_omp_depend_sink_unexpected_expr
);
20801 // OpenMP [2.13.9, Summary]
20802 // depend(dependence-type : vec), where dependence-type is:
20803 // 'sink' and where vec is the iteration vector, which has the form:
20804 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
20805 // where n is the value specified by the ordered clause in the loop
20806 // directive, xi denotes the loop iteration variable of the i-th nested
20807 // loop associated with the loop directive, and di is a constant
20808 // non-negative integer.
20809 if (SemaRef
.CurContext
->isDependentContext()) {
20810 // It will be analyzed later.
20811 Vars
.push_back(RefExpr
);
20814 SimpleExpr
= SimpleExpr
->IgnoreImplicit();
20815 OverloadedOperatorKind OOK
= OO_None
;
20816 SourceLocation OOLoc
;
20817 Expr
*LHS
= SimpleExpr
;
20818 Expr
*RHS
= nullptr;
20819 if (auto *BO
= dyn_cast
<BinaryOperator
>(SimpleExpr
)) {
20820 OOK
= BinaryOperator::getOverloadedOperator(BO
->getOpcode());
20821 OOLoc
= BO
->getOperatorLoc();
20822 LHS
= BO
->getLHS()->IgnoreParenImpCasts();
20823 RHS
= BO
->getRHS()->IgnoreParenImpCasts();
20824 } else if (auto *OCE
= dyn_cast
<CXXOperatorCallExpr
>(SimpleExpr
)) {
20825 OOK
= OCE
->getOperator();
20826 OOLoc
= OCE
->getOperatorLoc();
20827 LHS
= OCE
->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20828 RHS
= OCE
->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
20829 } else if (auto *MCE
= dyn_cast
<CXXMemberCallExpr
>(SimpleExpr
)) {
20830 OOK
= MCE
->getMethodDecl()
20833 .getCXXOverloadedOperator();
20834 OOLoc
= MCE
->getCallee()->getExprLoc();
20835 LHS
= MCE
->getImplicitObjectArgument()->IgnoreParenImpCasts();
20836 RHS
= MCE
->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20838 SourceLocation ELoc
;
20839 SourceRange ERange
;
20840 auto Res
= getPrivateItem(SemaRef
, LHS
, ELoc
, ERange
);
20842 // It will be analyzed later.
20843 Vars
.push_back(RefExpr
);
20845 ValueDecl
*D
= Res
.first
;
20849 if (OOK
!= OO_Plus
&& OOK
!= OO_Minus
&& (RHS
|| OOK
!= OO_None
)) {
20850 SemaRef
.Diag(OOLoc
, diag::err_omp_depend_sink_expected_plus_minus
);
20854 ExprResult RHSRes
= SemaRef
.VerifyPositiveIntegerConstantInClause(
20855 RHS
, OMPC_depend
, /*StrictlyPositive=*/false);
20856 if (RHSRes
.isInvalid())
20859 if (!SemaRef
.CurContext
->isDependentContext() &&
20860 Stack
->getParentOrderedRegionParam().first
&&
20861 DepCounter
!= Stack
->isParentLoopControlVariable(D
).first
) {
20862 const ValueDecl
*VD
=
20863 Stack
->getParentLoopControlVariable(DepCounter
.getZExtValue());
20865 SemaRef
.Diag(ELoc
, diag::err_omp_depend_sink_expected_loop_iteration
)
20868 SemaRef
.Diag(ELoc
, diag::err_omp_depend_sink_expected_loop_iteration
)
20872 OpsOffs
.emplace_back(RHS
, OOK
);
20874 Vars
.push_back(RefExpr
->IgnoreParenImpCasts());
20876 if (!SemaRef
.CurContext
->isDependentContext() && !IsSource
&&
20877 TotalDepCount
> VarList
.size() &&
20878 Stack
->getParentOrderedRegionParam().first
&&
20879 Stack
->getParentLoopControlVariable(VarList
.size() + 1)) {
20880 SemaRef
.Diag(EndLoc
, diag::err_omp_depend_sink_expected_loop_iteration
)
20881 << 1 << Stack
->getParentLoopControlVariable(VarList
.size() + 1);
20883 return {Vars
, OpsOffs
, TotalDepCount
};
20887 Sema::ActOnOpenMPDependClause(const OMPDependClause::DependDataTy
&Data
,
20888 Expr
*DepModifier
, ArrayRef
<Expr
*> VarList
,
20889 SourceLocation StartLoc
, SourceLocation LParenLoc
,
20890 SourceLocation EndLoc
) {
20891 OpenMPDependClauseKind DepKind
= Data
.DepKind
;
20892 SourceLocation DepLoc
= Data
.DepLoc
;
20893 if (DSAStack
->getCurrentDirective() == OMPD_ordered
&&
20894 DepKind
!= OMPC_DEPEND_source
&& DepKind
!= OMPC_DEPEND_sink
) {
20895 Diag(DepLoc
, diag::err_omp_unexpected_clause_value
)
20896 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend
);
20899 if (DSAStack
->getCurrentDirective() == OMPD_taskwait
&&
20900 DepKind
== OMPC_DEPEND_mutexinoutset
) {
20901 Diag(DepLoc
, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed
);
20904 if ((DSAStack
->getCurrentDirective() != OMPD_ordered
||
20905 DSAStack
->getCurrentDirective() == OMPD_depobj
) &&
20906 (DepKind
== OMPC_DEPEND_unknown
|| DepKind
== OMPC_DEPEND_source
||
20907 DepKind
== OMPC_DEPEND_sink
||
20908 ((LangOpts
.OpenMP
< 50 ||
20909 DSAStack
->getCurrentDirective() == OMPD_depobj
) &&
20910 DepKind
== OMPC_DEPEND_depobj
))) {
20911 SmallVector
<unsigned, 6> Except
= {OMPC_DEPEND_source
, OMPC_DEPEND_sink
,
20912 OMPC_DEPEND_outallmemory
,
20913 OMPC_DEPEND_inoutallmemory
};
20914 if (LangOpts
.OpenMP
< 50 || DSAStack
->getCurrentDirective() == OMPD_depobj
)
20915 Except
.push_back(OMPC_DEPEND_depobj
);
20916 if (LangOpts
.OpenMP
< 51)
20917 Except
.push_back(OMPC_DEPEND_inoutset
);
20918 std::string Expected
= (LangOpts
.OpenMP
>= 50 && !DepModifier
)
20919 ? "depend modifier(iterator) or "
20921 Diag(DepLoc
, diag::err_omp_unexpected_clause_value
)
20922 << Expected
+ getListOfPossibleValues(OMPC_depend
, /*First=*/0,
20923 /*Last=*/OMPC_DEPEND_unknown
,
20925 << getOpenMPClauseName(OMPC_depend
);
20929 (DepKind
== OMPC_DEPEND_source
|| DepKind
== OMPC_DEPEND_sink
)) {
20930 Diag(DepModifier
->getExprLoc(),
20931 diag::err_omp_depend_sink_source_with_modifier
);
20935 !DepModifier
->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator
))
20936 Diag(DepModifier
->getExprLoc(), diag::err_omp_depend_modifier_not_iterator
);
20938 SmallVector
<Expr
*, 8> Vars
;
20939 DSAStackTy::OperatorOffsetTy OpsOffs
;
20940 llvm::APSInt
TotalDepCount(/*BitWidth=*/32);
20942 if (DepKind
== OMPC_DEPEND_sink
|| DepKind
== OMPC_DEPEND_source
) {
20943 DoacrossDataInfoTy VarOffset
= ProcessOpenMPDoacrossClauseCommon(
20944 *this, DepKind
== OMPC_DEPEND_source
, VarList
, DSAStack
, EndLoc
);
20945 Vars
= VarOffset
.Vars
;
20946 OpsOffs
= VarOffset
.OpsOffs
;
20947 TotalDepCount
= VarOffset
.TotalDepCount
;
20949 for (Expr
*RefExpr
: VarList
) {
20950 assert(RefExpr
&& "NULL expr in OpenMP shared clause.");
20951 if (isa
<DependentScopeDeclRefExpr
>(RefExpr
)) {
20952 // It will be analyzed later.
20953 Vars
.push_back(RefExpr
);
20957 SourceLocation ELoc
= RefExpr
->getExprLoc();
20958 Expr
*SimpleExpr
= RefExpr
->IgnoreParenCasts();
20959 if (DepKind
!= OMPC_DEPEND_sink
&& DepKind
!= OMPC_DEPEND_source
) {
20960 bool OMPDependTFound
= LangOpts
.OpenMP
>= 50;
20961 if (OMPDependTFound
)
20962 OMPDependTFound
= findOMPDependT(*this, StartLoc
, DSAStack
,
20963 DepKind
== OMPC_DEPEND_depobj
);
20964 if (DepKind
== OMPC_DEPEND_depobj
) {
20965 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20966 // List items used in depend clauses with the depobj dependence type
20967 // must be expressions of the omp_depend_t type.
20968 if (!RefExpr
->isValueDependent() && !RefExpr
->isTypeDependent() &&
20969 !RefExpr
->isInstantiationDependent() &&
20970 !RefExpr
->containsUnexpandedParameterPack() &&
20971 (OMPDependTFound
&&
20972 !Context
.hasSameUnqualifiedType(DSAStack
->getOMPDependT(),
20973 RefExpr
->getType()))) {
20974 Diag(ELoc
, diag::err_omp_expected_omp_depend_t_lvalue
)
20975 << 0 << RefExpr
->getType() << RefExpr
->getSourceRange();
20978 if (!RefExpr
->isLValue()) {
20979 Diag(ELoc
, diag::err_omp_expected_omp_depend_t_lvalue
)
20980 << 1 << RefExpr
->getType() << RefExpr
->getSourceRange();
20984 // OpenMP 5.0 [2.17.11, Restrictions]
20985 // List items used in depend clauses cannot be zero-length array
20987 QualType ExprTy
= RefExpr
->getType().getNonReferenceType();
20988 const auto *OASE
= dyn_cast
<OMPArraySectionExpr
>(SimpleExpr
);
20990 QualType BaseType
=
20991 OMPArraySectionExpr::getBaseOriginalType(OASE
->getBase());
20992 if (const auto *ATy
= BaseType
->getAsArrayTypeUnsafe())
20993 ExprTy
= ATy
->getElementType();
20995 ExprTy
= BaseType
->getPointeeType();
20996 ExprTy
= ExprTy
.getNonReferenceType();
20997 const Expr
*Length
= OASE
->getLength();
20998 Expr::EvalResult Result
;
20999 if (Length
&& !Length
->isValueDependent() &&
21000 Length
->EvaluateAsInt(Result
, Context
) &&
21001 Result
.Val
.getInt().isZero()) {
21003 diag::err_omp_depend_zero_length_array_section_not_allowed
)
21004 << SimpleExpr
->getSourceRange();
21009 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21010 // List items used in depend clauses with the in, out, inout,
21011 // inoutset, or mutexinoutset dependence types cannot be
21012 // expressions of the omp_depend_t type.
21013 if (!RefExpr
->isValueDependent() && !RefExpr
->isTypeDependent() &&
21014 !RefExpr
->isInstantiationDependent() &&
21015 !RefExpr
->containsUnexpandedParameterPack() &&
21016 (!RefExpr
->IgnoreParenImpCasts()->isLValue() ||
21017 (OMPDependTFound
&& DSAStack
->getOMPDependT().getTypePtr() ==
21018 ExprTy
.getTypePtr()))) {
21019 Diag(ELoc
, diag::err_omp_expected_addressable_lvalue_or_array_item
)
21020 << (LangOpts
.OpenMP
>= 50 ? 1 : 0)
21021 << (LangOpts
.OpenMP
>= 50 ? 1 : 0) << RefExpr
->getSourceRange();
21025 auto *ASE
= dyn_cast
<ArraySubscriptExpr
>(SimpleExpr
);
21026 if (ASE
&& !ASE
->getBase()->isTypeDependent() &&
21029 .getNonReferenceType()
21030 ->isPointerType() &&
21031 !ASE
->getBase()->getType().getNonReferenceType()->isArrayType()) {
21032 Diag(ELoc
, diag::err_omp_expected_addressable_lvalue_or_array_item
)
21033 << (LangOpts
.OpenMP
>= 50 ? 1 : 0)
21034 << (LangOpts
.OpenMP
>= 50 ? 1 : 0) << RefExpr
->getSourceRange();
21040 Sema::TentativeAnalysisScope
Trap(*this);
21041 Res
= CreateBuiltinUnaryOp(ELoc
, UO_AddrOf
,
21042 RefExpr
->IgnoreParenImpCasts());
21044 if (!Res
.isUsable() && !isa
<OMPArraySectionExpr
>(SimpleExpr
) &&
21045 !isa
<OMPArrayShapingExpr
>(SimpleExpr
)) {
21046 Diag(ELoc
, diag::err_omp_expected_addressable_lvalue_or_array_item
)
21047 << (LangOpts
.OpenMP
>= 50 ? 1 : 0)
21048 << (LangOpts
.OpenMP
>= 50 ? 1 : 0) << RefExpr
->getSourceRange();
21053 Vars
.push_back(RefExpr
->IgnoreParenImpCasts());
21057 if (DepKind
!= OMPC_DEPEND_source
&& DepKind
!= OMPC_DEPEND_sink
&&
21058 DepKind
!= OMPC_DEPEND_outallmemory
&&
21059 DepKind
!= OMPC_DEPEND_inoutallmemory
&& Vars
.empty())
21062 auto *C
= OMPDependClause::Create(
21063 Context
, StartLoc
, LParenLoc
, EndLoc
,
21064 {DepKind
, DepLoc
, Data
.ColonLoc
, Data
.OmpAllMemoryLoc
}, DepModifier
, Vars
,
21065 TotalDepCount
.getZExtValue());
21066 if ((DepKind
== OMPC_DEPEND_sink
|| DepKind
== OMPC_DEPEND_source
) &&
21067 DSAStack
->isParentOrderedRegion())
21068 DSAStack
->addDoacrossDependClause(C
, OpsOffs
);
21072 OMPClause
*Sema::ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier
,
21073 Expr
*Device
, SourceLocation StartLoc
,
21074 SourceLocation LParenLoc
,
21075 SourceLocation ModifierLoc
,
21076 SourceLocation EndLoc
) {
21077 assert((ModifierLoc
.isInvalid() || LangOpts
.OpenMP
>= 50) &&
21078 "Unexpected device modifier in OpenMP < 50.");
21080 bool ErrorFound
= false;
21081 if (ModifierLoc
.isValid() && Modifier
== OMPC_DEVICE_unknown
) {
21082 std::string Values
=
21083 getListOfPossibleValues(OMPC_device
, /*First=*/0, OMPC_DEVICE_unknown
);
21084 Diag(ModifierLoc
, diag::err_omp_unexpected_clause_value
)
21085 << Values
<< getOpenMPClauseName(OMPC_device
);
21089 Expr
*ValExpr
= Device
;
21090 Stmt
*HelperValStmt
= nullptr;
21092 // OpenMP [2.9.1, Restrictions]
21093 // The device expression must evaluate to a non-negative integer value.
21094 ErrorFound
= !isNonNegativeIntegerValue(ValExpr
, *this, OMPC_device
,
21095 /*StrictlyPositive=*/false) ||
21100 // OpenMP 5.0 [2.12.5, Restrictions]
21101 // In case of ancestor device-modifier, a requires directive with
21102 // the reverse_offload clause must be specified.
21103 if (Modifier
== OMPC_DEVICE_ancestor
) {
21104 if (!DSAStack
->hasRequiresDeclWithClause
<OMPReverseOffloadClause
>()) {
21107 diag::err_omp_device_ancestor_without_requires_reverse_offload
);
21112 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
21113 OpenMPDirectiveKind CaptureRegion
=
21114 getOpenMPCaptureRegionForClause(DKind
, OMPC_device
, LangOpts
.OpenMP
);
21115 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
21116 ValExpr
= MakeFullExpr(ValExpr
).get();
21117 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
21118 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
21119 HelperValStmt
= buildPreInits(Context
, Captures
);
21122 return new (Context
)
21123 OMPDeviceClause(Modifier
, ValExpr
, HelperValStmt
, CaptureRegion
, StartLoc
,
21124 LParenLoc
, ModifierLoc
, EndLoc
);
21127 static bool checkTypeMappable(SourceLocation SL
, SourceRange SR
, Sema
&SemaRef
,
21128 DSAStackTy
*Stack
, QualType QTy
,
21129 bool FullCheck
= true) {
21130 if (SemaRef
.RequireCompleteType(SL
, QTy
, diag::err_incomplete_type
))
21132 if (FullCheck
&& !SemaRef
.CurContext
->isDependentContext() &&
21133 !QTy
.isTriviallyCopyableType(SemaRef
.Context
))
21134 SemaRef
.Diag(SL
, diag::warn_omp_non_trivial_type_mapped
) << QTy
<< SR
;
21138 /// Return true if it can be proven that the provided array expression
21139 /// (array section or array subscript) does NOT specify the whole size of the
21140 /// array whose base type is \a BaseQTy.
21141 static bool checkArrayExpressionDoesNotReferToWholeSize(Sema
&SemaRef
,
21143 QualType BaseQTy
) {
21144 const auto *OASE
= dyn_cast
<OMPArraySectionExpr
>(E
);
21146 // If this is an array subscript, it refers to the whole size if the size of
21147 // the dimension is constant and equals 1. Also, an array section assumes the
21148 // format of an array subscript if no colon is used.
21149 if (isa
<ArraySubscriptExpr
>(E
) ||
21150 (OASE
&& OASE
->getColonLocFirst().isInvalid())) {
21151 if (const auto *ATy
= dyn_cast
<ConstantArrayType
>(BaseQTy
.getTypePtr()))
21152 return ATy
->getSize().getSExtValue() != 1;
21153 // Size can't be evaluated statically.
21157 assert(OASE
&& "Expecting array section if not an array subscript.");
21158 const Expr
*LowerBound
= OASE
->getLowerBound();
21159 const Expr
*Length
= OASE
->getLength();
21161 // If there is a lower bound that does not evaluates to zero, we are not
21162 // covering the whole dimension.
21164 Expr::EvalResult Result
;
21165 if (!LowerBound
->EvaluateAsInt(Result
, SemaRef
.getASTContext()))
21166 return false; // Can't get the integer value as a constant.
21168 llvm::APSInt ConstLowerBound
= Result
.Val
.getInt();
21169 if (ConstLowerBound
.getSExtValue())
21173 // If we don't have a length we covering the whole dimension.
21177 // If the base is a pointer, we don't have a way to get the size of the
21179 if (BaseQTy
->isPointerType())
21182 // We can only check if the length is the same as the size of the dimension
21183 // if we have a constant array.
21184 const auto *CATy
= dyn_cast
<ConstantArrayType
>(BaseQTy
.getTypePtr());
21188 Expr::EvalResult Result
;
21189 if (!Length
->EvaluateAsInt(Result
, SemaRef
.getASTContext()))
21190 return false; // Can't get the integer value as a constant.
21192 llvm::APSInt ConstLength
= Result
.Val
.getInt();
21193 return CATy
->getSize().getSExtValue() != ConstLength
.getSExtValue();
21196 // Return true if it can be proven that the provided array expression (array
21197 // section or array subscript) does NOT specify a single element of the array
21198 // whose base type is \a BaseQTy.
21199 static bool checkArrayExpressionDoesNotReferToUnitySize(Sema
&SemaRef
,
21201 QualType BaseQTy
) {
21202 const auto *OASE
= dyn_cast
<OMPArraySectionExpr
>(E
);
21204 // An array subscript always refer to a single element. Also, an array section
21205 // assumes the format of an array subscript if no colon is used.
21206 if (isa
<ArraySubscriptExpr
>(E
) ||
21207 (OASE
&& OASE
->getColonLocFirst().isInvalid()))
21210 assert(OASE
&& "Expecting array section if not an array subscript.");
21211 const Expr
*Length
= OASE
->getLength();
21213 // If we don't have a length we have to check if the array has unitary size
21214 // for this dimension. Also, we should always expect a length if the base type
21217 if (const auto *ATy
= dyn_cast
<ConstantArrayType
>(BaseQTy
.getTypePtr()))
21218 return ATy
->getSize().getSExtValue() != 1;
21219 // We cannot assume anything.
21223 // Check if the length evaluates to 1.
21224 Expr::EvalResult Result
;
21225 if (!Length
->EvaluateAsInt(Result
, SemaRef
.getASTContext()))
21226 return false; // Can't get the integer value as a constant.
21228 llvm::APSInt ConstLength
= Result
.Val
.getInt();
21229 return ConstLength
.getSExtValue() != 1;
21232 // The base of elements of list in a map clause have to be either:
21233 // - a reference to variable or field.
21234 // - a member expression.
21235 // - an array expression.
21237 // E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
21238 // reference to 'r'.
21245 // #pragma omp target map (S.Arr[:12]);
21249 // We want to retrieve the member expression 'this->S';
21251 // OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
21252 // If a list item is an array section, it must specify contiguous storage.
21254 // For this restriction it is sufficient that we make sure only references
21255 // to variables or fields and array expressions, and that no array sections
21256 // exist except in the rightmost expression (unless they cover the whole
21257 // dimension of the array). E.g. these would be invalid:
21259 // r.ArrS[3:5].Arr[6:7]
21263 // but these would be valid:
21264 // r.ArrS[3].Arr[6:7]
21268 class MapBaseChecker final
: public StmtVisitor
<MapBaseChecker
, bool> {
21270 OpenMPClauseKind CKind
= OMPC_unknown
;
21271 OpenMPDirectiveKind DKind
= OMPD_unknown
;
21272 OMPClauseMappableExprCommon::MappableExprComponentList
&Components
;
21273 bool IsNonContiguous
= false;
21274 bool NoDiagnose
= false;
21275 const Expr
*RelevantExpr
= nullptr;
21276 bool AllowUnitySizeArraySection
= true;
21277 bool AllowWholeSizeArraySection
= true;
21278 bool AllowAnotherPtr
= true;
21279 SourceLocation ELoc
;
21280 SourceRange ERange
;
21282 void emitErrorMsg() {
21283 // If nothing else worked, this is not a valid map clause expression.
21284 if (SemaRef
.getLangOpts().OpenMP
< 50) {
21286 diag::err_omp_expected_named_var_member_or_array_expression
)
21289 SemaRef
.Diag(ELoc
, diag::err_omp_non_lvalue_in_map_or_motion_clauses
)
21290 << getOpenMPClauseName(CKind
) << ERange
;
21295 bool VisitDeclRefExpr(DeclRefExpr
*DRE
) {
21296 if (!isa
<VarDecl
>(DRE
->getDecl())) {
21300 assert(!RelevantExpr
&& "RelevantExpr is expected to be nullptr");
21301 RelevantExpr
= DRE
;
21302 // Record the component.
21303 Components
.emplace_back(DRE
, DRE
->getDecl(), IsNonContiguous
);
21307 bool VisitMemberExpr(MemberExpr
*ME
) {
21309 Expr
*BaseE
= ME
->getBase()->IgnoreParenCasts();
21311 if (isa
<CXXThisExpr
>(BaseE
)) {
21312 assert(!RelevantExpr
&& "RelevantExpr is expected to be nullptr");
21313 // We found a base expression: this->Val.
21319 if (!isa
<FieldDecl
>(ME
->getMemberDecl())) {
21321 SemaRef
.Diag(ELoc
, diag::err_omp_expected_access_to_data_field
)
21322 << ME
->getSourceRange();
21330 auto *FD
= cast
<FieldDecl
>(ME
->getMemberDecl());
21332 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
21333 // A bit-field cannot appear in a map clause.
21335 if (FD
->isBitField()) {
21337 SemaRef
.Diag(ELoc
, diag::err_omp_bit_fields_forbidden_in_clause
)
21338 << ME
->getSourceRange() << getOpenMPClauseName(CKind
);
21346 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21347 // If the type of a list item is a reference to a type T then the type
21348 // will be considered to be T for all purposes of this clause.
21349 QualType CurType
= BaseE
->getType().getNonReferenceType();
21351 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
21352 // A list item cannot be a variable that is a member of a structure with
21355 if (CurType
->isUnionType()) {
21357 SemaRef
.Diag(ELoc
, diag::err_omp_union_type_not_allowed
)
21358 << ME
->getSourceRange();
21361 return RelevantExpr
|| Visit(E
);
21364 // If we got a member expression, we should not expect any array section
21367 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
21368 // If a list item is an element of a structure, only the rightmost symbol
21369 // of the variable reference can be an array section.
21371 AllowUnitySizeArraySection
= false;
21372 AllowWholeSizeArraySection
= false;
21374 // Record the component.
21375 Components
.emplace_back(ME
, FD
, IsNonContiguous
);
21376 return RelevantExpr
|| Visit(E
);
21379 bool VisitArraySubscriptExpr(ArraySubscriptExpr
*AE
) {
21380 Expr
*E
= AE
->getBase()->IgnoreParenImpCasts();
21382 if (!E
->getType()->isAnyPointerType() && !E
->getType()->isArrayType()) {
21384 SemaRef
.Diag(ELoc
, diag::err_omp_expected_base_var_name
)
21385 << 0 << AE
->getSourceRange();
21388 return RelevantExpr
|| Visit(E
);
21391 // If we got an array subscript that express the whole dimension we
21392 // can have any array expressions before. If it only expressing part of
21393 // the dimension, we can only have unitary-size array expressions.
21394 if (checkArrayExpressionDoesNotReferToWholeSize(SemaRef
, AE
, E
->getType()))
21395 AllowWholeSizeArraySection
= false;
21397 if (const auto *TE
= dyn_cast
<CXXThisExpr
>(E
->IgnoreParenCasts())) {
21398 Expr::EvalResult Result
;
21399 if (!AE
->getIdx()->isValueDependent() &&
21400 AE
->getIdx()->EvaluateAsInt(Result
, SemaRef
.getASTContext()) &&
21401 !Result
.Val
.getInt().isZero()) {
21402 SemaRef
.Diag(AE
->getIdx()->getExprLoc(),
21403 diag::err_omp_invalid_map_this_expr
);
21404 SemaRef
.Diag(AE
->getIdx()->getExprLoc(),
21405 diag::note_omp_invalid_subscript_on_this_ptr_map
);
21407 assert(!RelevantExpr
&& "RelevantExpr is expected to be nullptr");
21411 // Record the component - we don't have any declaration associated.
21412 Components
.emplace_back(AE
, nullptr, IsNonContiguous
);
21414 return RelevantExpr
|| Visit(E
);
21417 bool VisitOMPArraySectionExpr(OMPArraySectionExpr
*OASE
) {
21418 // After OMP 5.0 Array section in reduction clause will be implicitly
21420 assert(!(SemaRef
.getLangOpts().OpenMP
< 50 && NoDiagnose
) &&
21421 "Array sections cannot be implicitly mapped.");
21422 Expr
*E
= OASE
->getBase()->IgnoreParenImpCasts();
21424 OMPArraySectionExpr::getBaseOriginalType(E
).getCanonicalType();
21426 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21427 // If the type of a list item is a reference to a type T then the type
21428 // will be considered to be T for all purposes of this clause.
21429 if (CurType
->isReferenceType())
21430 CurType
= CurType
->getPointeeType();
21432 bool IsPointer
= CurType
->isAnyPointerType();
21434 if (!IsPointer
&& !CurType
->isArrayType()) {
21435 SemaRef
.Diag(ELoc
, diag::err_omp_expected_base_var_name
)
21436 << 0 << OASE
->getSourceRange();
21441 checkArrayExpressionDoesNotReferToWholeSize(SemaRef
, OASE
, CurType
);
21443 checkArrayExpressionDoesNotReferToUnitySize(SemaRef
, OASE
, CurType
);
21445 if (AllowWholeSizeArraySection
) {
21446 // Any array section is currently allowed. Allowing a whole size array
21447 // section implies allowing a unity array section as well.
21449 // If this array section refers to the whole dimension we can still
21450 // accept other array sections before this one, except if the base is a
21451 // pointer. Otherwise, only unitary sections are accepted.
21452 if (NotWhole
|| IsPointer
)
21453 AllowWholeSizeArraySection
= false;
21454 } else if (DKind
== OMPD_target_update
&&
21455 SemaRef
.getLangOpts().OpenMP
>= 50) {
21456 if (IsPointer
&& !AllowAnotherPtr
)
21457 SemaRef
.Diag(ELoc
, diag::err_omp_section_length_undefined
)
21458 << /*array of unknown bound */ 1;
21460 IsNonContiguous
= true;
21461 } else if (AllowUnitySizeArraySection
&& NotUnity
) {
21462 // A unity or whole array section is not allowed and that is not
21463 // compatible with the properties of the current array section.
21467 diag::err_array_section_does_not_specify_contiguous_storage
)
21468 << OASE
->getSourceRange();
21473 AllowAnotherPtr
= false;
21475 if (const auto *TE
= dyn_cast
<CXXThisExpr
>(E
)) {
21476 Expr::EvalResult ResultR
;
21477 Expr::EvalResult ResultL
;
21478 if (!OASE
->getLength()->isValueDependent() &&
21479 OASE
->getLength()->EvaluateAsInt(ResultR
, SemaRef
.getASTContext()) &&
21480 !ResultR
.Val
.getInt().isOne()) {
21481 SemaRef
.Diag(OASE
->getLength()->getExprLoc(),
21482 diag::err_omp_invalid_map_this_expr
);
21483 SemaRef
.Diag(OASE
->getLength()->getExprLoc(),
21484 diag::note_omp_invalid_length_on_this_ptr_mapping
);
21486 if (OASE
->getLowerBound() && !OASE
->getLowerBound()->isValueDependent() &&
21487 OASE
->getLowerBound()->EvaluateAsInt(ResultL
,
21488 SemaRef
.getASTContext()) &&
21489 !ResultL
.Val
.getInt().isZero()) {
21490 SemaRef
.Diag(OASE
->getLowerBound()->getExprLoc(),
21491 diag::err_omp_invalid_map_this_expr
);
21492 SemaRef
.Diag(OASE
->getLowerBound()->getExprLoc(),
21493 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping
);
21495 assert(!RelevantExpr
&& "RelevantExpr is expected to be nullptr");
21499 // Record the component - we don't have any declaration associated.
21500 Components
.emplace_back(OASE
, nullptr, /*IsNonContiguous=*/false);
21501 return RelevantExpr
|| Visit(E
);
21503 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr
*E
) {
21504 Expr
*Base
= E
->getBase();
21506 // Record the component - we don't have any declaration associated.
21507 Components
.emplace_back(E
, nullptr, IsNonContiguous
);
21509 return Visit(Base
->IgnoreParenImpCasts());
21512 bool VisitUnaryOperator(UnaryOperator
*UO
) {
21513 if (SemaRef
.getLangOpts().OpenMP
< 50 || !UO
->isLValue() ||
21514 UO
->getOpcode() != UO_Deref
) {
21518 if (!RelevantExpr
) {
21519 // Record the component if haven't found base decl.
21520 Components
.emplace_back(UO
, nullptr, /*IsNonContiguous=*/false);
21522 return RelevantExpr
|| Visit(UO
->getSubExpr()->IgnoreParenImpCasts());
21524 bool VisitBinaryOperator(BinaryOperator
*BO
) {
21525 if (SemaRef
.getLangOpts().OpenMP
< 50 || !BO
->getType()->isPointerType()) {
21530 // Pointer arithmetic is the only thing we expect to happen here so after we
21531 // make sure the binary operator is a pointer type, the only thing we need
21532 // to do is to visit the subtree that has the same type as root (so that we
21533 // know the other subtree is just an offset)
21534 Expr
*LE
= BO
->getLHS()->IgnoreParenImpCasts();
21535 Expr
*RE
= BO
->getRHS()->IgnoreParenImpCasts();
21536 Components
.emplace_back(BO
, nullptr, false);
21537 assert((LE
->getType().getTypePtr() == BO
->getType().getTypePtr() ||
21538 RE
->getType().getTypePtr() == BO
->getType().getTypePtr()) &&
21539 "Either LHS or RHS have base decl inside");
21540 if (BO
->getType().getTypePtr() == LE
->getType().getTypePtr())
21541 return RelevantExpr
|| Visit(LE
);
21542 return RelevantExpr
|| Visit(RE
);
21544 bool VisitCXXThisExpr(CXXThisExpr
*CTE
) {
21545 assert(!RelevantExpr
&& "RelevantExpr is expected to be nullptr");
21546 RelevantExpr
= CTE
;
21547 Components
.emplace_back(CTE
, nullptr, IsNonContiguous
);
21550 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr
*COCE
) {
21551 assert(!RelevantExpr
&& "RelevantExpr is expected to be nullptr");
21552 Components
.emplace_back(COCE
, nullptr, IsNonContiguous
);
21555 bool VisitOpaqueValueExpr(OpaqueValueExpr
*E
) {
21556 Expr
*Source
= E
->getSourceExpr();
21561 return Visit(Source
);
21563 bool VisitStmt(Stmt
*) {
21567 const Expr
*getFoundBase() const { return RelevantExpr
; }
21568 explicit MapBaseChecker(
21569 Sema
&SemaRef
, OpenMPClauseKind CKind
, OpenMPDirectiveKind DKind
,
21570 OMPClauseMappableExprCommon::MappableExprComponentList
&Components
,
21571 bool NoDiagnose
, SourceLocation
&ELoc
, SourceRange
&ERange
)
21572 : SemaRef(SemaRef
), CKind(CKind
), DKind(DKind
), Components(Components
),
21573 NoDiagnose(NoDiagnose
), ELoc(ELoc
), ERange(ERange
) {}
21577 /// Return the expression of the base of the mappable expression or null if it
21578 /// cannot be determined and do all the necessary checks to see if the
21579 /// expression is valid as a standalone mappable expression. In the process,
21580 /// record all the components of the expression.
21581 static const Expr
*checkMapClauseExpressionBase(
21582 Sema
&SemaRef
, Expr
*E
,
21583 OMPClauseMappableExprCommon::MappableExprComponentList
&CurComponents
,
21584 OpenMPClauseKind CKind
, OpenMPDirectiveKind DKind
, bool NoDiagnose
) {
21585 SourceLocation ELoc
= E
->getExprLoc();
21586 SourceRange ERange
= E
->getSourceRange();
21587 MapBaseChecker
Checker(SemaRef
, CKind
, DKind
, CurComponents
, NoDiagnose
, ELoc
,
21589 if (Checker
.Visit(E
->IgnoreParens())) {
21590 // Check if the highest dimension array section has length specified
21591 if (SemaRef
.getLangOpts().OpenMP
>= 50 && !CurComponents
.empty() &&
21592 (CKind
== OMPC_to
|| CKind
== OMPC_from
)) {
21593 auto CI
= CurComponents
.rbegin();
21594 auto CE
= CurComponents
.rend();
21595 for (; CI
!= CE
; ++CI
) {
21597 dyn_cast
<OMPArraySectionExpr
>(CI
->getAssociatedExpression());
21600 if (OASE
&& OASE
->getLength())
21602 SemaRef
.Diag(ELoc
, diag::err_array_section_does_not_specify_length
)
21606 return Checker
.getFoundBase();
21611 // Return true if expression E associated with value VD has conflicts with other
21612 // map information.
21613 static bool checkMapConflicts(
21614 Sema
&SemaRef
, DSAStackTy
*DSAS
, const ValueDecl
*VD
, const Expr
*E
,
21615 bool CurrentRegionOnly
,
21616 OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents
,
21617 OpenMPClauseKind CKind
) {
21619 SourceLocation ELoc
= E
->getExprLoc();
21620 SourceRange ERange
= E
->getSourceRange();
21622 // In order to easily check the conflicts we need to match each component of
21623 // the expression under test with the components of the expressions that are
21624 // already in the stack.
21626 assert(!CurComponents
.empty() && "Map clause expression with no components!");
21627 assert(CurComponents
.back().getAssociatedDeclaration() == VD
&&
21628 "Map clause expression with unexpected base!");
21630 // Variables to help detecting enclosing problems in data environment nests.
21631 bool IsEnclosedByDataEnvironmentExpr
= false;
21632 const Expr
*EnclosingExpr
= nullptr;
21634 bool FoundError
= DSAS
->checkMappableExprComponentListsForDecl(
21635 VD
, CurrentRegionOnly
,
21636 [&IsEnclosedByDataEnvironmentExpr
, &SemaRef
, VD
, CurrentRegionOnly
, ELoc
,
21637 ERange
, CKind
, &EnclosingExpr
,
21638 CurComponents
](OMPClauseMappableExprCommon::MappableExprComponentListRef
21640 OpenMPClauseKind Kind
) {
21641 if (CKind
== Kind
&& SemaRef
.LangOpts
.OpenMP
>= 50)
21643 assert(!StackComponents
.empty() &&
21644 "Map clause expression with no components!");
21645 assert(StackComponents
.back().getAssociatedDeclaration() == VD
&&
21646 "Map clause expression with unexpected base!");
21649 // The whole expression in the stack.
21650 const Expr
*RE
= StackComponents
.front().getAssociatedExpression();
21652 // Expressions must start from the same base. Here we detect at which
21653 // point both expressions diverge from each other and see if we can
21654 // detect if the memory referred to both expressions is contiguous and
21656 auto CI
= CurComponents
.rbegin();
21657 auto CE
= CurComponents
.rend();
21658 auto SI
= StackComponents
.rbegin();
21659 auto SE
= StackComponents
.rend();
21660 for (; CI
!= CE
&& SI
!= SE
; ++CI
, ++SI
) {
21662 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
21663 // At most one list item can be an array item derived from a given
21664 // variable in map clauses of the same construct.
21665 if (CurrentRegionOnly
&&
21666 (isa
<ArraySubscriptExpr
>(CI
->getAssociatedExpression()) ||
21667 isa
<OMPArraySectionExpr
>(CI
->getAssociatedExpression()) ||
21668 isa
<OMPArrayShapingExpr
>(CI
->getAssociatedExpression())) &&
21669 (isa
<ArraySubscriptExpr
>(SI
->getAssociatedExpression()) ||
21670 isa
<OMPArraySectionExpr
>(SI
->getAssociatedExpression()) ||
21671 isa
<OMPArrayShapingExpr
>(SI
->getAssociatedExpression()))) {
21672 SemaRef
.Diag(CI
->getAssociatedExpression()->getExprLoc(),
21673 diag::err_omp_multiple_array_items_in_map_clause
)
21674 << CI
->getAssociatedExpression()->getSourceRange();
21675 SemaRef
.Diag(SI
->getAssociatedExpression()->getExprLoc(),
21676 diag::note_used_here
)
21677 << SI
->getAssociatedExpression()->getSourceRange();
21681 // Do both expressions have the same kind?
21682 if (CI
->getAssociatedExpression()->getStmtClass() !=
21683 SI
->getAssociatedExpression()->getStmtClass())
21686 // Are we dealing with different variables/fields?
21687 if (CI
->getAssociatedDeclaration() != SI
->getAssociatedDeclaration())
21690 // Check if the extra components of the expressions in the enclosing
21691 // data environment are redundant for the current base declaration.
21692 // If they are, the maps completely overlap, which is legal.
21693 for (; SI
!= SE
; ++SI
) {
21695 if (const auto *ASE
=
21696 dyn_cast
<ArraySubscriptExpr
>(SI
->getAssociatedExpression())) {
21697 Type
= ASE
->getBase()->IgnoreParenImpCasts()->getType();
21698 } else if (const auto *OASE
= dyn_cast
<OMPArraySectionExpr
>(
21699 SI
->getAssociatedExpression())) {
21700 const Expr
*E
= OASE
->getBase()->IgnoreParenImpCasts();
21702 OMPArraySectionExpr::getBaseOriginalType(E
).getCanonicalType();
21703 } else if (const auto *OASE
= dyn_cast
<OMPArrayShapingExpr
>(
21704 SI
->getAssociatedExpression())) {
21705 Type
= OASE
->getBase()->getType()->getPointeeType();
21707 if (Type
.isNull() || Type
->isAnyPointerType() ||
21708 checkArrayExpressionDoesNotReferToWholeSize(
21709 SemaRef
, SI
->getAssociatedExpression(), Type
))
21713 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21714 // List items of map clauses in the same construct must not share
21715 // original storage.
21717 // If the expressions are exactly the same or one is a subset of the
21718 // other, it means they are sharing storage.
21719 if (CI
== CE
&& SI
== SE
) {
21720 if (CurrentRegionOnly
) {
21721 if (CKind
== OMPC_map
) {
21722 SemaRef
.Diag(ELoc
, diag::err_omp_map_shared_storage
) << ERange
;
21724 assert(CKind
== OMPC_to
|| CKind
== OMPC_from
);
21725 SemaRef
.Diag(ELoc
, diag::err_omp_once_referenced_in_target_update
)
21728 SemaRef
.Diag(RE
->getExprLoc(), diag::note_used_here
)
21729 << RE
->getSourceRange();
21732 // If we find the same expression in the enclosing data environment,
21734 IsEnclosedByDataEnvironmentExpr
= true;
21738 QualType DerivedType
=
21739 std::prev(CI
)->getAssociatedDeclaration()->getType();
21740 SourceLocation DerivedLoc
=
21741 std::prev(CI
)->getAssociatedExpression()->getExprLoc();
21743 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21744 // If the type of a list item is a reference to a type T then the type
21745 // will be considered to be T for all purposes of this clause.
21746 DerivedType
= DerivedType
.getNonReferenceType();
21748 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
21749 // A variable for which the type is pointer and an array section
21750 // derived from that variable must not appear as list items of map
21751 // clauses of the same construct.
21753 // Also, cover one of the cases in:
21754 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21755 // If any part of the original storage of a list item has corresponding
21756 // storage in the device data environment, all of the original storage
21757 // must have corresponding storage in the device data environment.
21759 if (DerivedType
->isAnyPointerType()) {
21760 if (CI
== CE
|| SI
== SE
) {
21763 diag::err_omp_pointer_mapped_along_with_derived_section
)
21765 SemaRef
.Diag(RE
->getExprLoc(), diag::note_used_here
)
21766 << RE
->getSourceRange();
21769 if (CI
->getAssociatedExpression()->getStmtClass() !=
21770 SI
->getAssociatedExpression()->getStmtClass() ||
21771 CI
->getAssociatedDeclaration()->getCanonicalDecl() ==
21772 SI
->getAssociatedDeclaration()->getCanonicalDecl()) {
21773 assert(CI
!= CE
&& SI
!= SE
);
21774 SemaRef
.Diag(DerivedLoc
, diag::err_omp_same_pointer_dereferenced
)
21776 SemaRef
.Diag(RE
->getExprLoc(), diag::note_used_here
)
21777 << RE
->getSourceRange();
21782 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21783 // List items of map clauses in the same construct must not share
21784 // original storage.
21786 // An expression is a subset of the other.
21787 if (CurrentRegionOnly
&& (CI
== CE
|| SI
== SE
)) {
21788 if (CKind
== OMPC_map
) {
21789 if (CI
!= CE
|| SI
!= SE
) {
21790 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
21793 CI
!= CE
? CurComponents
.begin() : StackComponents
.begin();
21794 auto End
= CI
!= CE
? CurComponents
.end() : StackComponents
.end();
21796 while (It
!= End
&& !It
->getAssociatedDeclaration())
21797 std::advance(It
, 1);
21798 assert(It
!= End
&&
21799 "Expected at least one component with the declaration.");
21800 if (It
!= Begin
&& It
->getAssociatedDeclaration()
21802 .getCanonicalType()
21803 ->isAnyPointerType()) {
21804 IsEnclosedByDataEnvironmentExpr
= false;
21805 EnclosingExpr
= nullptr;
21809 SemaRef
.Diag(ELoc
, diag::err_omp_map_shared_storage
) << ERange
;
21811 assert(CKind
== OMPC_to
|| CKind
== OMPC_from
);
21812 SemaRef
.Diag(ELoc
, diag::err_omp_once_referenced_in_target_update
)
21815 SemaRef
.Diag(RE
->getExprLoc(), diag::note_used_here
)
21816 << RE
->getSourceRange();
21820 // The current expression uses the same base as other expression in the
21821 // data environment but does not contain it completely.
21822 if (!CurrentRegionOnly
&& SI
!= SE
)
21823 EnclosingExpr
= RE
;
21825 // The current expression is a subset of the expression in the data
21827 IsEnclosedByDataEnvironmentExpr
|=
21828 (!CurrentRegionOnly
&& CI
!= CE
&& SI
== SE
);
21833 if (CurrentRegionOnly
)
21836 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21837 // If any part of the original storage of a list item has corresponding
21838 // storage in the device data environment, all of the original storage must
21839 // have corresponding storage in the device data environment.
21840 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
21841 // If a list item is an element of a structure, and a different element of
21842 // the structure has a corresponding list item in the device data environment
21843 // prior to a task encountering the construct associated with the map clause,
21844 // then the list item must also have a corresponding list item in the device
21845 // data environment prior to the task encountering the construct.
21847 if (EnclosingExpr
&& !IsEnclosedByDataEnvironmentExpr
) {
21849 diag::err_omp_original_storage_is_shared_and_does_not_contain
)
21851 SemaRef
.Diag(EnclosingExpr
->getExprLoc(), diag::note_used_here
)
21852 << EnclosingExpr
->getSourceRange();
21859 // Look up the user-defined mapper given the mapper name and mapped type, and
21860 // build a reference to it.
21861 static ExprResult
buildUserDefinedMapperRef(Sema
&SemaRef
, Scope
*S
,
21862 CXXScopeSpec
&MapperIdScopeSpec
,
21863 const DeclarationNameInfo
&MapperId
,
21865 Expr
*UnresolvedMapper
) {
21866 if (MapperIdScopeSpec
.isInvalid())
21867 return ExprError();
21868 // Get the actual type for the array type.
21869 if (Type
->isArrayType()) {
21870 assert(Type
->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
21871 Type
= Type
->getAsArrayTypeUnsafe()->getElementType().getCanonicalType();
21873 // Find all user-defined mappers with the given MapperId.
21874 SmallVector
<UnresolvedSet
<8>, 4> Lookups
;
21875 LookupResult
Lookup(SemaRef
, MapperId
, Sema::LookupOMPMapperName
);
21876 Lookup
.suppressDiagnostics();
21878 while (S
&& SemaRef
.LookupParsedName(Lookup
, S
, &MapperIdScopeSpec
)) {
21879 NamedDecl
*D
= Lookup
.getRepresentativeDecl();
21880 while (S
&& !S
->isDeclScope(D
))
21881 S
= S
->getParent();
21883 S
= S
->getParent();
21884 Lookups
.emplace_back();
21885 Lookups
.back().append(Lookup
.begin(), Lookup
.end());
21888 } else if (auto *ULE
= cast_or_null
<UnresolvedLookupExpr
>(UnresolvedMapper
)) {
21889 // Extract the user-defined mappers with the given MapperId.
21890 Lookups
.push_back(UnresolvedSet
<8>());
21891 for (NamedDecl
*D
: ULE
->decls()) {
21892 auto *DMD
= cast
<OMPDeclareMapperDecl
>(D
);
21893 assert(DMD
&& "Expect valid OMPDeclareMapperDecl during instantiation.");
21894 Lookups
.back().addDecl(DMD
);
21897 // Defer the lookup for dependent types. The results will be passed through
21898 // UnresolvedMapper on instantiation.
21899 if (SemaRef
.CurContext
->isDependentContext() || Type
->isDependentType() ||
21900 Type
->isInstantiationDependentType() ||
21901 Type
->containsUnexpandedParameterPack() ||
21902 filterLookupForUDReductionAndMapper
<bool>(Lookups
, [](ValueDecl
*D
) {
21903 return !D
->isInvalidDecl() &&
21904 (D
->getType()->isDependentType() ||
21905 D
->getType()->isInstantiationDependentType() ||
21906 D
->getType()->containsUnexpandedParameterPack());
21908 UnresolvedSet
<8> URS
;
21909 for (const UnresolvedSet
<8> &Set
: Lookups
) {
21912 URS
.append(Set
.begin(), Set
.end());
21914 return UnresolvedLookupExpr::Create(
21915 SemaRef
.Context
, /*NamingClass=*/nullptr,
21916 MapperIdScopeSpec
.getWithLocInContext(SemaRef
.Context
), MapperId
,
21917 /*ADL=*/false, /*Overloaded=*/true, URS
.begin(), URS
.end());
21919 SourceLocation Loc
= MapperId
.getLoc();
21920 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21921 // The type must be of struct, union or class type in C and C++
21922 if (!Type
->isStructureOrClassType() && !Type
->isUnionType() &&
21923 (MapperIdScopeSpec
.isSet() || MapperId
.getAsString() != "default")) {
21924 SemaRef
.Diag(Loc
, diag::err_omp_mapper_wrong_type
);
21925 return ExprError();
21927 // Perform argument dependent lookup.
21928 if (SemaRef
.getLangOpts().CPlusPlus
&& !MapperIdScopeSpec
.isSet())
21929 argumentDependentLookup(SemaRef
, MapperId
, Loc
, Type
, Lookups
);
21930 // Return the first user-defined mapper with the desired type.
21931 if (auto *VD
= filterLookupForUDReductionAndMapper
<ValueDecl
*>(
21932 Lookups
, [&SemaRef
, Type
](ValueDecl
*D
) -> ValueDecl
* {
21933 if (!D
->isInvalidDecl() &&
21934 SemaRef
.Context
.hasSameType(D
->getType(), Type
))
21938 return SemaRef
.BuildDeclRefExpr(VD
, Type
, VK_LValue
, Loc
);
21939 // Find the first user-defined mapper with a type derived from the desired
21941 if (auto *VD
= filterLookupForUDReductionAndMapper
<ValueDecl
*>(
21942 Lookups
, [&SemaRef
, Type
, Loc
](ValueDecl
*D
) -> ValueDecl
* {
21943 if (!D
->isInvalidDecl() &&
21944 SemaRef
.IsDerivedFrom(Loc
, Type
, D
->getType()) &&
21945 !Type
.isMoreQualifiedThan(D
->getType()))
21949 CXXBasePaths
Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
21950 /*DetectVirtual=*/false);
21951 if (SemaRef
.IsDerivedFrom(Loc
, Type
, VD
->getType(), Paths
)) {
21952 if (!Paths
.isAmbiguous(SemaRef
.Context
.getCanonicalType(
21953 VD
->getType().getUnqualifiedType()))) {
21954 if (SemaRef
.CheckBaseClassAccess(
21955 Loc
, VD
->getType(), Type
, Paths
.front(),
21956 /*DiagID=*/0) != Sema::AR_inaccessible
) {
21957 return SemaRef
.BuildDeclRefExpr(VD
, Type
, VK_LValue
, Loc
);
21962 // Report error if a mapper is specified, but cannot be found.
21963 if (MapperIdScopeSpec
.isSet() || MapperId
.getAsString() != "default") {
21964 SemaRef
.Diag(Loc
, diag::err_omp_invalid_mapper
)
21965 << Type
<< MapperId
.getName();
21966 return ExprError();
21968 return ExprEmpty();
21972 // Utility struct that gathers all the related lists associated with a mappable
21974 struct MappableVarListInfo
{
21975 // The list of expressions.
21976 ArrayRef
<Expr
*> VarList
;
21977 // The list of processed expressions.
21978 SmallVector
<Expr
*, 16> ProcessedVarList
;
21979 // The mappble components for each expression.
21980 OMPClauseMappableExprCommon::MappableExprComponentLists VarComponents
;
21981 // The base declaration of the variable.
21982 SmallVector
<ValueDecl
*, 16> VarBaseDeclarations
;
21983 // The reference to the user-defined mapper associated with every expression.
21984 SmallVector
<Expr
*, 16> UDMapperList
;
21986 MappableVarListInfo(ArrayRef
<Expr
*> VarList
) : VarList(VarList
) {
21987 // We have a list of components and base declarations for each entry in the
21989 VarComponents
.reserve(VarList
.size());
21990 VarBaseDeclarations
.reserve(VarList
.size());
21995 // Check the validity of the provided variable list for the provided clause kind
21996 // \a CKind. In the check process the valid expressions, mappable expression
21997 // components, variables, and user-defined mappers are extracted and used to
21998 // fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
21999 // UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
22000 // and \a MapperId are expected to be valid if the clause kind is 'map'.
22001 static void checkMappableExpressionList(
22002 Sema
&SemaRef
, DSAStackTy
*DSAS
, OpenMPClauseKind CKind
,
22003 MappableVarListInfo
&MVLI
, SourceLocation StartLoc
,
22004 CXXScopeSpec
&MapperIdScopeSpec
, DeclarationNameInfo MapperId
,
22005 ArrayRef
<Expr
*> UnresolvedMappers
,
22006 OpenMPMapClauseKind MapType
= OMPC_MAP_unknown
,
22007 ArrayRef
<OpenMPMapModifierKind
> Modifiers
= std::nullopt
,
22008 bool IsMapTypeImplicit
= false, bool NoDiagnose
= false) {
22009 // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
22010 assert((CKind
== OMPC_map
|| CKind
== OMPC_to
|| CKind
== OMPC_from
) &&
22011 "Unexpected clause kind with mappable expressions!");
22013 // If the identifier of user-defined mapper is not specified, it is "default".
22014 // We do not change the actual name in this clause to distinguish whether a
22015 // mapper is specified explicitly, i.e., it is not explicitly specified when
22016 // MapperId.getName() is empty.
22017 if (!MapperId
.getName() || MapperId
.getName().isEmpty()) {
22018 auto &DeclNames
= SemaRef
.getASTContext().DeclarationNames
;
22019 MapperId
.setName(DeclNames
.getIdentifier(
22020 &SemaRef
.getASTContext().Idents
.get("default")));
22021 MapperId
.setLoc(StartLoc
);
22024 // Iterators to find the current unresolved mapper expression.
22025 auto UMIt
= UnresolvedMappers
.begin(), UMEnd
= UnresolvedMappers
.end();
22026 bool UpdateUMIt
= false;
22027 Expr
*UnresolvedMapper
= nullptr;
22029 bool HasHoldModifier
=
22030 llvm::is_contained(Modifiers
, OMPC_MAP_MODIFIER_ompx_hold
);
22032 // Keep track of the mappable components and base declarations in this clause.
22033 // Each entry in the list is going to have a list of components associated. We
22034 // record each set of the components so that we can build the clause later on.
22035 // In the end we should have the same amount of declarations and component
22038 for (Expr
*RE
: MVLI
.VarList
) {
22039 assert(RE
&& "Null expr in omp to/from/map clause");
22040 SourceLocation ELoc
= RE
->getExprLoc();
22042 // Find the current unresolved mapper expression.
22043 if (UpdateUMIt
&& UMIt
!= UMEnd
) {
22047 "Expect the size of UnresolvedMappers to match with that of VarList");
22051 UnresolvedMapper
= *UMIt
;
22053 const Expr
*VE
= RE
->IgnoreParenLValueCasts();
22055 if (VE
->isValueDependent() || VE
->isTypeDependent() ||
22056 VE
->isInstantiationDependent() ||
22057 VE
->containsUnexpandedParameterPack()) {
22058 // Try to find the associated user-defined mapper.
22059 ExprResult ER
= buildUserDefinedMapperRef(
22060 SemaRef
, DSAS
->getCurScope(), MapperIdScopeSpec
, MapperId
,
22061 VE
->getType().getCanonicalType(), UnresolvedMapper
);
22062 if (ER
.isInvalid())
22064 MVLI
.UDMapperList
.push_back(ER
.get());
22065 // We can only analyze this information once the missing information is
22067 MVLI
.ProcessedVarList
.push_back(RE
);
22071 Expr
*SimpleExpr
= RE
->IgnoreParenCasts();
22073 if (!RE
->isLValue()) {
22074 if (SemaRef
.getLangOpts().OpenMP
< 50) {
22076 ELoc
, diag::err_omp_expected_named_var_member_or_array_expression
)
22077 << RE
->getSourceRange();
22079 SemaRef
.Diag(ELoc
, diag::err_omp_non_lvalue_in_map_or_motion_clauses
)
22080 << getOpenMPClauseName(CKind
) << RE
->getSourceRange();
22085 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents
;
22086 ValueDecl
*CurDeclaration
= nullptr;
22088 // Obtain the array or member expression bases if required. Also, fill the
22089 // components array with all the components identified in the process.
22091 checkMapClauseExpressionBase(SemaRef
, SimpleExpr
, CurComponents
, CKind
,
22092 DSAS
->getCurrentDirective(), NoDiagnose
);
22096 assert(!CurComponents
.empty() &&
22097 "Invalid mappable expression information.");
22099 if (const auto *TE
= dyn_cast
<CXXThisExpr
>(BE
)) {
22100 // Add store "this" pointer to class in DSAStackTy for future checking
22101 DSAS
->addMappedClassesQualTypes(TE
->getType());
22102 // Try to find the associated user-defined mapper.
22103 ExprResult ER
= buildUserDefinedMapperRef(
22104 SemaRef
, DSAS
->getCurScope(), MapperIdScopeSpec
, MapperId
,
22105 VE
->getType().getCanonicalType(), UnresolvedMapper
);
22106 if (ER
.isInvalid())
22108 MVLI
.UDMapperList
.push_back(ER
.get());
22109 // Skip restriction checking for variable or field declarations
22110 MVLI
.ProcessedVarList
.push_back(RE
);
22111 MVLI
.VarComponents
.resize(MVLI
.VarComponents
.size() + 1);
22112 MVLI
.VarComponents
.back().append(CurComponents
.begin(),
22113 CurComponents
.end());
22114 MVLI
.VarBaseDeclarations
.push_back(nullptr);
22118 // For the following checks, we rely on the base declaration which is
22119 // expected to be associated with the last component. The declaration is
22120 // expected to be a variable or a field (if 'this' is being mapped).
22121 CurDeclaration
= CurComponents
.back().getAssociatedDeclaration();
22122 assert(CurDeclaration
&& "Null decl on map clause.");
22124 CurDeclaration
->isCanonicalDecl() &&
22125 "Expecting components to have associated only canonical declarations.");
22127 auto *VD
= dyn_cast
<VarDecl
>(CurDeclaration
);
22128 const auto *FD
= dyn_cast
<FieldDecl
>(CurDeclaration
);
22130 assert((VD
|| FD
) && "Only variables or fields are expected here!");
22133 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
22134 // threadprivate variables cannot appear in a map clause.
22135 // OpenMP 4.5 [2.10.5, target update Construct]
22136 // threadprivate variables cannot appear in a from clause.
22137 if (VD
&& DSAS
->isThreadPrivate(VD
)) {
22140 DSAStackTy::DSAVarData DVar
= DSAS
->getTopDSA(VD
, /*FromParent=*/false);
22141 SemaRef
.Diag(ELoc
, diag::err_omp_threadprivate_in_clause
)
22142 << getOpenMPClauseName(CKind
);
22143 reportOriginalDsa(SemaRef
, DSAS
, VD
, DVar
);
22147 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
22148 // A list item cannot appear in both a map clause and a data-sharing
22149 // attribute clause on the same construct.
22151 // Check conflicts with other map clause expressions. We check the conflicts
22152 // with the current construct separately from the enclosing data
22153 // environment, because the restrictions are different. We only have to
22154 // check conflicts across regions for the map clauses.
22155 if (checkMapConflicts(SemaRef
, DSAS
, CurDeclaration
, SimpleExpr
,
22156 /*CurrentRegionOnly=*/true, CurComponents
, CKind
))
22158 if (CKind
== OMPC_map
&&
22159 (SemaRef
.getLangOpts().OpenMP
<= 45 || StartLoc
.isValid()) &&
22160 checkMapConflicts(SemaRef
, DSAS
, CurDeclaration
, SimpleExpr
,
22161 /*CurrentRegionOnly=*/false, CurComponents
, CKind
))
22164 // OpenMP 4.5 [2.10.5, target update Construct]
22165 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22166 // If the type of a list item is a reference to a type T then the type will
22167 // be considered to be T for all purposes of this clause.
22168 auto I
= llvm::find_if(
22170 [](const OMPClauseMappableExprCommon::MappableComponent
&MC
) {
22171 return MC
.getAssociatedDeclaration();
22173 assert(I
!= CurComponents
.end() && "Null decl on map clause.");
22176 auto *ASE
= dyn_cast
<ArraySubscriptExpr
>(VE
->IgnoreParens());
22177 auto *OASE
= dyn_cast
<OMPArraySectionExpr
>(VE
->IgnoreParens());
22178 auto *OAShE
= dyn_cast
<OMPArrayShapingExpr
>(VE
->IgnoreParens());
22180 Type
= ASE
->getType().getNonReferenceType();
22182 QualType BaseType
=
22183 OMPArraySectionExpr::getBaseOriginalType(OASE
->getBase());
22184 if (const auto *ATy
= BaseType
->getAsArrayTypeUnsafe())
22185 Type
= ATy
->getElementType();
22187 Type
= BaseType
->getPointeeType();
22188 Type
= Type
.getNonReferenceType();
22189 } else if (OAShE
) {
22190 Type
= OAShE
->getBase()->getType()->getPointeeType();
22192 Type
= VE
->getType();
22195 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
22196 // A list item in a to or from clause must have a mappable type.
22197 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
22198 // A list item must have a mappable type.
22199 if (!checkTypeMappable(VE
->getExprLoc(), VE
->getSourceRange(), SemaRef
,
22200 DSAS
, Type
, /*FullCheck=*/true))
22203 if (CKind
== OMPC_map
) {
22204 // target enter data
22205 // OpenMP [2.10.2, Restrictions, p. 99]
22206 // A map-type must be specified in all map clauses and must be either
22207 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
22208 // no map type is present.
22209 OpenMPDirectiveKind DKind
= DSAS
->getCurrentDirective();
22210 if (DKind
== OMPD_target_enter_data
&&
22211 !(MapType
== OMPC_MAP_to
|| MapType
== OMPC_MAP_alloc
||
22212 SemaRef
.getLangOpts().OpenMP
>= 52)) {
22213 SemaRef
.Diag(StartLoc
, diag::err_omp_invalid_map_type_for_directive
)
22214 << (IsMapTypeImplicit
? 1 : 0)
22215 << getOpenMPSimpleClauseTypeName(OMPC_map
, MapType
)
22216 << getOpenMPDirectiveName(DKind
);
22220 // target exit_data
22221 // OpenMP [2.10.3, Restrictions, p. 102]
22222 // A map-type must be specified in all map clauses and must be either
22223 // from, release, or delete. Starting with OpenMP 5.2 the default map
22224 // type is `from` if no map type is present.
22225 if (DKind
== OMPD_target_exit_data
&&
22226 !(MapType
== OMPC_MAP_from
|| MapType
== OMPC_MAP_release
||
22227 MapType
== OMPC_MAP_delete
|| SemaRef
.getLangOpts().OpenMP
>= 52)) {
22228 SemaRef
.Diag(StartLoc
, diag::err_omp_invalid_map_type_for_directive
)
22229 << (IsMapTypeImplicit
? 1 : 0)
22230 << getOpenMPSimpleClauseTypeName(OMPC_map
, MapType
)
22231 << getOpenMPDirectiveName(DKind
);
22235 // The 'ompx_hold' modifier is specifically intended to be used on a
22236 // 'target' or 'target data' directive to prevent data from being unmapped
22237 // during the associated statement. It is not permitted on a 'target
22238 // enter data' or 'target exit data' directive, which have no associated
22240 if ((DKind
== OMPD_target_enter_data
|| DKind
== OMPD_target_exit_data
) &&
22242 SemaRef
.Diag(StartLoc
,
22243 diag::err_omp_invalid_map_type_modifier_for_directive
)
22244 << getOpenMPSimpleClauseTypeName(OMPC_map
,
22245 OMPC_MAP_MODIFIER_ompx_hold
)
22246 << getOpenMPDirectiveName(DKind
);
22250 // target, target data
22251 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
22252 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
22253 // A map-type in a map clause must be to, from, tofrom or alloc
22254 if ((DKind
== OMPD_target_data
||
22255 isOpenMPTargetExecutionDirective(DKind
)) &&
22256 !(MapType
== OMPC_MAP_to
|| MapType
== OMPC_MAP_from
||
22257 MapType
== OMPC_MAP_tofrom
|| MapType
== OMPC_MAP_alloc
)) {
22258 SemaRef
.Diag(StartLoc
, diag::err_omp_invalid_map_type_for_directive
)
22259 << (IsMapTypeImplicit
? 1 : 0)
22260 << getOpenMPSimpleClauseTypeName(OMPC_map
, MapType
)
22261 << getOpenMPDirectiveName(DKind
);
22265 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
22266 // A list item cannot appear in both a map clause and a data-sharing
22267 // attribute clause on the same construct
22269 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
22270 // A list item cannot appear in both a map clause and a data-sharing
22271 // attribute clause on the same construct unless the construct is a
22272 // combined construct.
22273 if (VD
&& ((SemaRef
.LangOpts
.OpenMP
<= 45 &&
22274 isOpenMPTargetExecutionDirective(DKind
)) ||
22275 DKind
== OMPD_target
)) {
22276 DSAStackTy::DSAVarData DVar
= DSAS
->getTopDSA(VD
, /*FromParent=*/false);
22277 if (isOpenMPPrivate(DVar
.CKind
)) {
22278 SemaRef
.Diag(ELoc
, diag::err_omp_variable_in_given_clause_and_dsa
)
22279 << getOpenMPClauseName(DVar
.CKind
)
22280 << getOpenMPClauseName(OMPC_map
)
22281 << getOpenMPDirectiveName(DSAS
->getCurrentDirective());
22282 reportOriginalDsa(SemaRef
, DSAS
, CurDeclaration
, DVar
);
22288 // Try to find the associated user-defined mapper.
22289 ExprResult ER
= buildUserDefinedMapperRef(
22290 SemaRef
, DSAS
->getCurScope(), MapperIdScopeSpec
, MapperId
,
22291 Type
.getCanonicalType(), UnresolvedMapper
);
22292 if (ER
.isInvalid())
22294 MVLI
.UDMapperList
.push_back(ER
.get());
22296 // Save the current expression.
22297 MVLI
.ProcessedVarList
.push_back(RE
);
22299 // Store the components in the stack so that they can be used to check
22300 // against other clauses later on.
22301 DSAS
->addMappableExpressionComponents(CurDeclaration
, CurComponents
,
22302 /*WhereFoundClauseKind=*/OMPC_map
);
22304 // Save the components and declaration to create the clause. For purposes of
22305 // the clause creation, any component list that has base 'this' uses
22306 // null as base declaration.
22307 MVLI
.VarComponents
.resize(MVLI
.VarComponents
.size() + 1);
22308 MVLI
.VarComponents
.back().append(CurComponents
.begin(),
22309 CurComponents
.end());
22310 MVLI
.VarBaseDeclarations
.push_back(isa
<MemberExpr
>(BE
) ? nullptr
22315 OMPClause
*Sema::ActOnOpenMPMapClause(
22316 Expr
*IteratorModifier
, ArrayRef
<OpenMPMapModifierKind
> MapTypeModifiers
,
22317 ArrayRef
<SourceLocation
> MapTypeModifiersLoc
,
22318 CXXScopeSpec
&MapperIdScopeSpec
, DeclarationNameInfo
&MapperId
,
22319 OpenMPMapClauseKind MapType
, bool IsMapTypeImplicit
, SourceLocation MapLoc
,
22320 SourceLocation ColonLoc
, ArrayRef
<Expr
*> VarList
,
22321 const OMPVarListLocTy
&Locs
, bool NoDiagnose
,
22322 ArrayRef
<Expr
*> UnresolvedMappers
) {
22323 OpenMPMapModifierKind Modifiers
[] = {
22324 OMPC_MAP_MODIFIER_unknown
, OMPC_MAP_MODIFIER_unknown
,
22325 OMPC_MAP_MODIFIER_unknown
, OMPC_MAP_MODIFIER_unknown
,
22326 OMPC_MAP_MODIFIER_unknown
, OMPC_MAP_MODIFIER_unknown
};
22327 SourceLocation ModifiersLoc
[NumberOfOMPMapClauseModifiers
];
22329 if (IteratorModifier
&& !IteratorModifier
->getType()->isSpecificBuiltinType(
22330 BuiltinType::OMPIterator
))
22331 Diag(IteratorModifier
->getExprLoc(),
22332 diag::err_omp_map_modifier_not_iterator
);
22334 // Process map-type-modifiers, flag errors for duplicate modifiers.
22335 unsigned Count
= 0;
22336 for (unsigned I
= 0, E
= MapTypeModifiers
.size(); I
< E
; ++I
) {
22337 if (MapTypeModifiers
[I
] != OMPC_MAP_MODIFIER_unknown
&&
22338 llvm::is_contained(Modifiers
, MapTypeModifiers
[I
])) {
22339 Diag(MapTypeModifiersLoc
[I
], diag::err_omp_duplicate_map_type_modifier
);
22342 assert(Count
< NumberOfOMPMapClauseModifiers
&&
22343 "Modifiers exceed the allowed number of map type modifiers");
22344 Modifiers
[Count
] = MapTypeModifiers
[I
];
22345 ModifiersLoc
[Count
] = MapTypeModifiersLoc
[I
];
22349 MappableVarListInfo
MVLI(VarList
);
22350 checkMappableExpressionList(*this, DSAStack
, OMPC_map
, MVLI
, Locs
.StartLoc
,
22351 MapperIdScopeSpec
, MapperId
, UnresolvedMappers
,
22352 MapType
, Modifiers
, IsMapTypeImplicit
,
22355 // We need to produce a map clause even if we don't have variables so that
22356 // other diagnostics related with non-existing map clauses are accurate.
22357 return OMPMapClause::Create(
22358 Context
, Locs
, MVLI
.ProcessedVarList
, MVLI
.VarBaseDeclarations
,
22359 MVLI
.VarComponents
, MVLI
.UDMapperList
, IteratorModifier
, Modifiers
,
22360 ModifiersLoc
, MapperIdScopeSpec
.getWithLocInContext(Context
), MapperId
,
22361 MapType
, IsMapTypeImplicit
, MapLoc
);
22364 QualType
Sema::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc
,
22365 TypeResult ParsedType
) {
22366 assert(ParsedType
.isUsable());
22368 QualType ReductionType
= GetTypeFromParser(ParsedType
.get());
22369 if (ReductionType
.isNull())
22372 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
22373 // A type name in a declare reduction directive cannot be a function type, an
22374 // array type, a reference type, or a type qualified with const, volatile or
22376 if (ReductionType
.hasQualifiers()) {
22377 Diag(TyLoc
, diag::err_omp_reduction_wrong_type
) << 0;
22381 if (ReductionType
->isFunctionType()) {
22382 Diag(TyLoc
, diag::err_omp_reduction_wrong_type
) << 1;
22385 if (ReductionType
->isReferenceType()) {
22386 Diag(TyLoc
, diag::err_omp_reduction_wrong_type
) << 2;
22389 if (ReductionType
->isArrayType()) {
22390 Diag(TyLoc
, diag::err_omp_reduction_wrong_type
) << 3;
22393 return ReductionType
;
22396 Sema::DeclGroupPtrTy
Sema::ActOnOpenMPDeclareReductionDirectiveStart(
22397 Scope
*S
, DeclContext
*DC
, DeclarationName Name
,
22398 ArrayRef
<std::pair
<QualType
, SourceLocation
>> ReductionTypes
,
22399 AccessSpecifier AS
, Decl
*PrevDeclInScope
) {
22400 SmallVector
<Decl
*, 8> Decls
;
22401 Decls
.reserve(ReductionTypes
.size());
22403 LookupResult
Lookup(*this, Name
, SourceLocation(), LookupOMPReductionName
,
22404 forRedeclarationInCurContext());
22405 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
22406 // A reduction-identifier may not be re-declared in the current scope for the
22407 // same type or for a type that is compatible according to the base language
22409 llvm::DenseMap
<QualType
, SourceLocation
> PreviousRedeclTypes
;
22410 OMPDeclareReductionDecl
*PrevDRD
= nullptr;
22411 bool InCompoundScope
= true;
22412 if (S
!= nullptr) {
22413 // Find previous declaration with the same name not referenced in other
22415 FunctionScopeInfo
*ParentFn
= getEnclosingFunction();
22417 (ParentFn
!= nullptr) && !ParentFn
->CompoundScopes
.empty();
22418 LookupName(Lookup
, S
);
22419 FilterLookupForScope(Lookup
, DC
, S
, /*ConsiderLinkage=*/false,
22420 /*AllowInlineNamespace=*/false);
22421 llvm::DenseMap
<OMPDeclareReductionDecl
*, bool> UsedAsPrevious
;
22422 LookupResult::Filter Filter
= Lookup
.makeFilter();
22423 while (Filter
.hasNext()) {
22424 auto *PrevDecl
= cast
<OMPDeclareReductionDecl
>(Filter
.next());
22425 if (InCompoundScope
) {
22426 auto I
= UsedAsPrevious
.find(PrevDecl
);
22427 if (I
== UsedAsPrevious
.end())
22428 UsedAsPrevious
[PrevDecl
] = false;
22429 if (OMPDeclareReductionDecl
*D
= PrevDecl
->getPrevDeclInScope())
22430 UsedAsPrevious
[D
] = true;
22432 PreviousRedeclTypes
[PrevDecl
->getType().getCanonicalType()] =
22433 PrevDecl
->getLocation();
22436 if (InCompoundScope
) {
22437 for (const auto &PrevData
: UsedAsPrevious
) {
22438 if (!PrevData
.second
) {
22439 PrevDRD
= PrevData
.first
;
22444 } else if (PrevDeclInScope
!= nullptr) {
22445 auto *PrevDRDInScope
= PrevDRD
=
22446 cast
<OMPDeclareReductionDecl
>(PrevDeclInScope
);
22448 PreviousRedeclTypes
[PrevDRDInScope
->getType().getCanonicalType()] =
22449 PrevDRDInScope
->getLocation();
22450 PrevDRDInScope
= PrevDRDInScope
->getPrevDeclInScope();
22451 } while (PrevDRDInScope
!= nullptr);
22453 for (const auto &TyData
: ReductionTypes
) {
22454 const auto I
= PreviousRedeclTypes
.find(TyData
.first
.getCanonicalType());
22455 bool Invalid
= false;
22456 if (I
!= PreviousRedeclTypes
.end()) {
22457 Diag(TyData
.second
, diag::err_omp_declare_reduction_redefinition
)
22459 Diag(I
->second
, diag::note_previous_definition
);
22462 PreviousRedeclTypes
[TyData
.first
.getCanonicalType()] = TyData
.second
;
22463 auto *DRD
= OMPDeclareReductionDecl::Create(Context
, DC
, TyData
.second
,
22464 Name
, TyData
.first
, PrevDRD
);
22466 DRD
->setAccess(AS
);
22467 Decls
.push_back(DRD
);
22469 DRD
->setInvalidDecl();
22474 return DeclGroupPtrTy::make(
22475 DeclGroupRef::Create(Context
, Decls
.begin(), Decls
.size()));
22478 void Sema::ActOnOpenMPDeclareReductionCombinerStart(Scope
*S
, Decl
*D
) {
22479 auto *DRD
= cast
<OMPDeclareReductionDecl
>(D
);
22481 // Enter new function scope.
22482 PushFunctionScope();
22483 setFunctionHasBranchProtectedScope();
22484 getCurFunction()->setHasOMPDeclareReductionCombiner();
22487 PushDeclContext(S
, DRD
);
22491 PushExpressionEvaluationContext(
22492 ExpressionEvaluationContext::PotentiallyEvaluated
);
22494 QualType ReductionType
= DRD
->getType();
22495 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
22496 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
22497 // uses semantics of argument handles by value, but it should be passed by
22498 // reference. C lang does not support references, so pass all parameters as
22500 // Create 'T omp_in;' variable.
22501 VarDecl
*OmpInParm
=
22502 buildVarDecl(*this, D
->getLocation(), ReductionType
, "omp_in");
22503 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
22504 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
22505 // uses semantics of argument handles by value, but it should be passed by
22506 // reference. C lang does not support references, so pass all parameters as
22508 // Create 'T omp_out;' variable.
22509 VarDecl
*OmpOutParm
=
22510 buildVarDecl(*this, D
->getLocation(), ReductionType
, "omp_out");
22511 if (S
!= nullptr) {
22512 PushOnScopeChains(OmpInParm
, S
);
22513 PushOnScopeChains(OmpOutParm
, S
);
22515 DRD
->addDecl(OmpInParm
);
22516 DRD
->addDecl(OmpOutParm
);
22519 ::buildDeclRefExpr(*this, OmpInParm
, ReductionType
, D
->getLocation());
22521 ::buildDeclRefExpr(*this, OmpOutParm
, ReductionType
, D
->getLocation());
22522 DRD
->setCombinerData(InE
, OutE
);
22525 void Sema::ActOnOpenMPDeclareReductionCombinerEnd(Decl
*D
, Expr
*Combiner
) {
22526 auto *DRD
= cast
<OMPDeclareReductionDecl
>(D
);
22527 DiscardCleanupsInEvaluationContext();
22528 PopExpressionEvaluationContext();
22531 PopFunctionScopeInfo();
22533 if (Combiner
!= nullptr)
22534 DRD
->setCombiner(Combiner
);
22536 DRD
->setInvalidDecl();
22539 VarDecl
*Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope
*S
, Decl
*D
) {
22540 auto *DRD
= cast
<OMPDeclareReductionDecl
>(D
);
22542 // Enter new function scope.
22543 PushFunctionScope();
22544 setFunctionHasBranchProtectedScope();
22547 PushDeclContext(S
, DRD
);
22551 PushExpressionEvaluationContext(
22552 ExpressionEvaluationContext::PotentiallyEvaluated
);
22554 QualType ReductionType
= DRD
->getType();
22555 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
22556 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
22557 // uses semantics of argument handles by value, but it should be passed by
22558 // reference. C lang does not support references, so pass all parameters as
22560 // Create 'T omp_priv;' variable.
22561 VarDecl
*OmpPrivParm
=
22562 buildVarDecl(*this, D
->getLocation(), ReductionType
, "omp_priv");
22563 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
22564 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
22565 // uses semantics of argument handles by value, but it should be passed by
22566 // reference. C lang does not support references, so pass all parameters as
22568 // Create 'T omp_orig;' variable.
22569 VarDecl
*OmpOrigParm
=
22570 buildVarDecl(*this, D
->getLocation(), ReductionType
, "omp_orig");
22571 if (S
!= nullptr) {
22572 PushOnScopeChains(OmpPrivParm
, S
);
22573 PushOnScopeChains(OmpOrigParm
, S
);
22575 DRD
->addDecl(OmpPrivParm
);
22576 DRD
->addDecl(OmpOrigParm
);
22579 ::buildDeclRefExpr(*this, OmpOrigParm
, ReductionType
, D
->getLocation());
22581 ::buildDeclRefExpr(*this, OmpPrivParm
, ReductionType
, D
->getLocation());
22582 DRD
->setInitializerData(OrigE
, PrivE
);
22583 return OmpPrivParm
;
22586 void Sema::ActOnOpenMPDeclareReductionInitializerEnd(Decl
*D
, Expr
*Initializer
,
22587 VarDecl
*OmpPrivParm
) {
22588 auto *DRD
= cast
<OMPDeclareReductionDecl
>(D
);
22589 DiscardCleanupsInEvaluationContext();
22590 PopExpressionEvaluationContext();
22593 PopFunctionScopeInfo();
22595 if (Initializer
!= nullptr) {
22596 DRD
->setInitializer(Initializer
, OMPDeclareReductionDecl::CallInit
);
22597 } else if (OmpPrivParm
->hasInit()) {
22598 DRD
->setInitializer(OmpPrivParm
->getInit(),
22599 OmpPrivParm
->isDirectInit()
22600 ? OMPDeclareReductionDecl::DirectInit
22601 : OMPDeclareReductionDecl::CopyInit
);
22603 DRD
->setInvalidDecl();
22607 Sema::DeclGroupPtrTy
Sema::ActOnOpenMPDeclareReductionDirectiveEnd(
22608 Scope
*S
, DeclGroupPtrTy DeclReductions
, bool IsValid
) {
22609 for (Decl
*D
: DeclReductions
.get()) {
22612 PushOnScopeChains(cast
<OMPDeclareReductionDecl
>(D
), S
,
22613 /*AddToContext=*/false);
22615 D
->setInvalidDecl();
22618 return DeclReductions
;
22621 TypeResult
Sema::ActOnOpenMPDeclareMapperVarDecl(Scope
*S
, Declarator
&D
) {
22622 TypeSourceInfo
*TInfo
= GetTypeForDeclarator(D
, S
);
22623 QualType T
= TInfo
->getType();
22624 if (D
.isInvalidType())
22627 if (getLangOpts().CPlusPlus
) {
22628 // Check that there are no default arguments (C++ only).
22629 CheckExtraCXXDefaultArguments(D
);
22632 return CreateParsedType(T
, TInfo
);
22635 QualType
Sema::ActOnOpenMPDeclareMapperType(SourceLocation TyLoc
,
22636 TypeResult ParsedType
) {
22637 assert(ParsedType
.isUsable() && "Expect usable parsed mapper type");
22639 QualType MapperType
= GetTypeFromParser(ParsedType
.get());
22640 assert(!MapperType
.isNull() && "Expect valid mapper type");
22642 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22643 // The type must be of struct, union or class type in C and C++
22644 if (!MapperType
->isStructureOrClassType() && !MapperType
->isUnionType()) {
22645 Diag(TyLoc
, diag::err_omp_mapper_wrong_type
);
22651 Sema::DeclGroupPtrTy
Sema::ActOnOpenMPDeclareMapperDirective(
22652 Scope
*S
, DeclContext
*DC
, DeclarationName Name
, QualType MapperType
,
22653 SourceLocation StartLoc
, DeclarationName VN
, AccessSpecifier AS
,
22654 Expr
*MapperVarRef
, ArrayRef
<OMPClause
*> Clauses
, Decl
*PrevDeclInScope
) {
22655 LookupResult
Lookup(*this, Name
, SourceLocation(), LookupOMPMapperName
,
22656 forRedeclarationInCurContext());
22657 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22658 // A mapper-identifier may not be redeclared in the current scope for the
22659 // same type or for a type that is compatible according to the base language
22661 llvm::DenseMap
<QualType
, SourceLocation
> PreviousRedeclTypes
;
22662 OMPDeclareMapperDecl
*PrevDMD
= nullptr;
22663 bool InCompoundScope
= true;
22664 if (S
!= nullptr) {
22665 // Find previous declaration with the same name not referenced in other
22667 FunctionScopeInfo
*ParentFn
= getEnclosingFunction();
22669 (ParentFn
!= nullptr) && !ParentFn
->CompoundScopes
.empty();
22670 LookupName(Lookup
, S
);
22671 FilterLookupForScope(Lookup
, DC
, S
, /*ConsiderLinkage=*/false,
22672 /*AllowInlineNamespace=*/false);
22673 llvm::DenseMap
<OMPDeclareMapperDecl
*, bool> UsedAsPrevious
;
22674 LookupResult::Filter Filter
= Lookup
.makeFilter();
22675 while (Filter
.hasNext()) {
22676 auto *PrevDecl
= cast
<OMPDeclareMapperDecl
>(Filter
.next());
22677 if (InCompoundScope
) {
22678 auto I
= UsedAsPrevious
.find(PrevDecl
);
22679 if (I
== UsedAsPrevious
.end())
22680 UsedAsPrevious
[PrevDecl
] = false;
22681 if (OMPDeclareMapperDecl
*D
= PrevDecl
->getPrevDeclInScope())
22682 UsedAsPrevious
[D
] = true;
22684 PreviousRedeclTypes
[PrevDecl
->getType().getCanonicalType()] =
22685 PrevDecl
->getLocation();
22688 if (InCompoundScope
) {
22689 for (const auto &PrevData
: UsedAsPrevious
) {
22690 if (!PrevData
.second
) {
22691 PrevDMD
= PrevData
.first
;
22696 } else if (PrevDeclInScope
) {
22697 auto *PrevDMDInScope
= PrevDMD
=
22698 cast
<OMPDeclareMapperDecl
>(PrevDeclInScope
);
22700 PreviousRedeclTypes
[PrevDMDInScope
->getType().getCanonicalType()] =
22701 PrevDMDInScope
->getLocation();
22702 PrevDMDInScope
= PrevDMDInScope
->getPrevDeclInScope();
22703 } while (PrevDMDInScope
!= nullptr);
22705 const auto I
= PreviousRedeclTypes
.find(MapperType
.getCanonicalType());
22706 bool Invalid
= false;
22707 if (I
!= PreviousRedeclTypes
.end()) {
22708 Diag(StartLoc
, diag::err_omp_declare_mapper_redefinition
)
22709 << MapperType
<< Name
;
22710 Diag(I
->second
, diag::note_previous_definition
);
22713 // Build expressions for implicit maps of data members with 'default'
22715 SmallVector
<OMPClause
*, 4> ClausesWithImplicit(Clauses
.begin(),
22717 if (LangOpts
.OpenMP
>= 50)
22718 processImplicitMapsWithDefaultMappers(*this, DSAStack
, ClausesWithImplicit
);
22720 OMPDeclareMapperDecl::Create(Context
, DC
, StartLoc
, Name
, MapperType
, VN
,
22721 ClausesWithImplicit
, PrevDMD
);
22723 PushOnScopeChains(DMD
, S
);
22726 DMD
->setAccess(AS
);
22728 DMD
->setInvalidDecl();
22730 auto *VD
= cast
<DeclRefExpr
>(MapperVarRef
)->getDecl();
22731 VD
->setDeclContext(DMD
);
22732 VD
->setLexicalDeclContext(DMD
);
22734 DMD
->setMapperVarRef(MapperVarRef
);
22736 return DeclGroupPtrTy::make(DeclGroupRef(DMD
));
22740 Sema::ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope
*S
, QualType MapperType
,
22741 SourceLocation StartLoc
,
22742 DeclarationName VN
) {
22743 TypeSourceInfo
*TInfo
=
22744 Context
.getTrivialTypeSourceInfo(MapperType
, StartLoc
);
22745 auto *VD
= VarDecl::Create(Context
, Context
.getTranslationUnitDecl(),
22746 StartLoc
, StartLoc
, VN
.getAsIdentifierInfo(),
22747 MapperType
, TInfo
, SC_None
);
22749 PushOnScopeChains(VD
, S
, /*AddToContext=*/false);
22750 Expr
*E
= buildDeclRefExpr(*this, VD
, MapperType
, StartLoc
);
22751 DSAStack
->addDeclareMapperVarRef(E
);
22755 void Sema::ActOnOpenMPIteratorVarDecl(VarDecl
*VD
) {
22756 if (DSAStack
->getDeclareMapperVarRef())
22757 DSAStack
->addIteratorVarDecl(VD
);
22760 bool Sema::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl
*VD
) const {
22761 assert(LangOpts
.OpenMP
&& "Expected OpenMP mode.");
22762 const Expr
*Ref
= DSAStack
->getDeclareMapperVarRef();
22763 if (const auto *DRE
= cast_or_null
<DeclRefExpr
>(Ref
)) {
22764 if (VD
->getCanonicalDecl() == DRE
->getDecl()->getCanonicalDecl())
22766 if (VD
->isUsableInConstantExpressions(Context
))
22768 if (LangOpts
.OpenMP
>= 52 && DSAStack
->isIteratorVarDecl(VD
))
22775 const ValueDecl
*Sema::getOpenMPDeclareMapperVarName() const {
22776 assert(LangOpts
.OpenMP
&& "Expected OpenMP mode.");
22777 return cast
<DeclRefExpr
>(DSAStack
->getDeclareMapperVarRef())->getDecl();
22780 OMPClause
*Sema::ActOnOpenMPNumTeamsClause(Expr
*NumTeams
,
22781 SourceLocation StartLoc
,
22782 SourceLocation LParenLoc
,
22783 SourceLocation EndLoc
) {
22784 Expr
*ValExpr
= NumTeams
;
22785 Stmt
*HelperValStmt
= nullptr;
22787 // OpenMP [teams Constrcut, Restrictions]
22788 // The num_teams expression must evaluate to a positive integer value.
22789 if (!isNonNegativeIntegerValue(ValExpr
, *this, OMPC_num_teams
,
22790 /*StrictlyPositive=*/true))
22793 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
22794 OpenMPDirectiveKind CaptureRegion
=
22795 getOpenMPCaptureRegionForClause(DKind
, OMPC_num_teams
, LangOpts
.OpenMP
);
22796 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
22797 ValExpr
= MakeFullExpr(ValExpr
).get();
22798 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
22799 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
22800 HelperValStmt
= buildPreInits(Context
, Captures
);
22803 return new (Context
) OMPNumTeamsClause(ValExpr
, HelperValStmt
, CaptureRegion
,
22804 StartLoc
, LParenLoc
, EndLoc
);
22807 OMPClause
*Sema::ActOnOpenMPThreadLimitClause(Expr
*ThreadLimit
,
22808 SourceLocation StartLoc
,
22809 SourceLocation LParenLoc
,
22810 SourceLocation EndLoc
) {
22811 Expr
*ValExpr
= ThreadLimit
;
22812 Stmt
*HelperValStmt
= nullptr;
22814 // OpenMP [teams Constrcut, Restrictions]
22815 // The thread_limit expression must evaluate to a positive integer value.
22816 if (!isNonNegativeIntegerValue(ValExpr
, *this, OMPC_thread_limit
,
22817 /*StrictlyPositive=*/true))
22820 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
22821 OpenMPDirectiveKind CaptureRegion
= getOpenMPCaptureRegionForClause(
22822 DKind
, OMPC_thread_limit
, LangOpts
.OpenMP
);
22823 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
22824 ValExpr
= MakeFullExpr(ValExpr
).get();
22825 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
22826 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
22827 HelperValStmt
= buildPreInits(Context
, Captures
);
22830 return new (Context
) OMPThreadLimitClause(
22831 ValExpr
, HelperValStmt
, CaptureRegion
, StartLoc
, LParenLoc
, EndLoc
);
22834 OMPClause
*Sema::ActOnOpenMPPriorityClause(Expr
*Priority
,
22835 SourceLocation StartLoc
,
22836 SourceLocation LParenLoc
,
22837 SourceLocation EndLoc
) {
22838 Expr
*ValExpr
= Priority
;
22839 Stmt
*HelperValStmt
= nullptr;
22840 OpenMPDirectiveKind CaptureRegion
= OMPD_unknown
;
22842 // OpenMP [2.9.1, task Constrcut]
22843 // The priority-value is a non-negative numerical scalar expression.
22844 if (!isNonNegativeIntegerValue(
22845 ValExpr
, *this, OMPC_priority
,
22846 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
22847 DSAStack
->getCurrentDirective(), &CaptureRegion
, &HelperValStmt
))
22850 return new (Context
) OMPPriorityClause(ValExpr
, HelperValStmt
, CaptureRegion
,
22851 StartLoc
, LParenLoc
, EndLoc
);
22854 OMPClause
*Sema::ActOnOpenMPGrainsizeClause(
22855 OpenMPGrainsizeClauseModifier Modifier
, Expr
*Grainsize
,
22856 SourceLocation StartLoc
, SourceLocation LParenLoc
,
22857 SourceLocation ModifierLoc
, SourceLocation EndLoc
) {
22858 assert((ModifierLoc
.isInvalid() || LangOpts
.OpenMP
>= 51) &&
22859 "Unexpected grainsize modifier in OpenMP < 51.");
22861 if (ModifierLoc
.isValid() && Modifier
== OMPC_GRAINSIZE_unknown
) {
22862 std::string Values
= getListOfPossibleValues(OMPC_grainsize
, /*First=*/0,
22863 OMPC_GRAINSIZE_unknown
);
22864 Diag(ModifierLoc
, diag::err_omp_unexpected_clause_value
)
22865 << Values
<< getOpenMPClauseName(OMPC_grainsize
);
22869 Expr
*ValExpr
= Grainsize
;
22870 Stmt
*HelperValStmt
= nullptr;
22871 OpenMPDirectiveKind CaptureRegion
= OMPD_unknown
;
22873 // OpenMP [2.9.2, taskloop Constrcut]
22874 // The parameter of the grainsize clause must be a positive integer
22876 if (!isNonNegativeIntegerValue(ValExpr
, *this, OMPC_grainsize
,
22877 /*StrictlyPositive=*/true,
22878 /*BuildCapture=*/true,
22879 DSAStack
->getCurrentDirective(),
22880 &CaptureRegion
, &HelperValStmt
))
22883 return new (Context
)
22884 OMPGrainsizeClause(Modifier
, ValExpr
, HelperValStmt
, CaptureRegion
,
22885 StartLoc
, LParenLoc
, ModifierLoc
, EndLoc
);
22888 OMPClause
*Sema::ActOnOpenMPNumTasksClause(
22889 OpenMPNumTasksClauseModifier Modifier
, Expr
*NumTasks
,
22890 SourceLocation StartLoc
, SourceLocation LParenLoc
,
22891 SourceLocation ModifierLoc
, SourceLocation EndLoc
) {
22892 assert((ModifierLoc
.isInvalid() || LangOpts
.OpenMP
>= 51) &&
22893 "Unexpected num_tasks modifier in OpenMP < 51.");
22895 if (ModifierLoc
.isValid() && Modifier
== OMPC_NUMTASKS_unknown
) {
22896 std::string Values
= getListOfPossibleValues(OMPC_num_tasks
, /*First=*/0,
22897 OMPC_NUMTASKS_unknown
);
22898 Diag(ModifierLoc
, diag::err_omp_unexpected_clause_value
)
22899 << Values
<< getOpenMPClauseName(OMPC_num_tasks
);
22903 Expr
*ValExpr
= NumTasks
;
22904 Stmt
*HelperValStmt
= nullptr;
22905 OpenMPDirectiveKind CaptureRegion
= OMPD_unknown
;
22907 // OpenMP [2.9.2, taskloop Constrcut]
22908 // The parameter of the num_tasks clause must be a positive integer
22910 if (!isNonNegativeIntegerValue(
22911 ValExpr
, *this, OMPC_num_tasks
,
22912 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
22913 DSAStack
->getCurrentDirective(), &CaptureRegion
, &HelperValStmt
))
22916 return new (Context
)
22917 OMPNumTasksClause(Modifier
, ValExpr
, HelperValStmt
, CaptureRegion
,
22918 StartLoc
, LParenLoc
, ModifierLoc
, EndLoc
);
22921 OMPClause
*Sema::ActOnOpenMPHintClause(Expr
*Hint
, SourceLocation StartLoc
,
22922 SourceLocation LParenLoc
,
22923 SourceLocation EndLoc
) {
22924 // OpenMP [2.13.2, critical construct, Description]
22925 // ... where hint-expression is an integer constant expression that evaluates
22926 // to a valid lock hint.
22927 ExprResult HintExpr
=
22928 VerifyPositiveIntegerConstantInClause(Hint
, OMPC_hint
, false);
22929 if (HintExpr
.isInvalid())
22931 return new (Context
)
22932 OMPHintClause(HintExpr
.get(), StartLoc
, LParenLoc
, EndLoc
);
22935 /// Tries to find omp_event_handle_t type.
22936 static bool findOMPEventHandleT(Sema
&S
, SourceLocation Loc
,
22937 DSAStackTy
*Stack
) {
22938 QualType OMPEventHandleT
= Stack
->getOMPEventHandleT();
22939 if (!OMPEventHandleT
.isNull())
22941 IdentifierInfo
*II
= &S
.PP
.getIdentifierTable().get("omp_event_handle_t");
22942 ParsedType PT
= S
.getTypeName(*II
, Loc
, S
.getCurScope());
22943 if (!PT
.getAsOpaquePtr() || PT
.get().isNull()) {
22944 S
.Diag(Loc
, diag::err_omp_implied_type_not_found
) << "omp_event_handle_t";
22947 Stack
->setOMPEventHandleT(PT
.get());
22951 OMPClause
*Sema::ActOnOpenMPDetachClause(Expr
*Evt
, SourceLocation StartLoc
,
22952 SourceLocation LParenLoc
,
22953 SourceLocation EndLoc
) {
22954 if (!Evt
->isValueDependent() && !Evt
->isTypeDependent() &&
22955 !Evt
->isInstantiationDependent() &&
22956 !Evt
->containsUnexpandedParameterPack()) {
22957 if (!findOMPEventHandleT(*this, Evt
->getExprLoc(), DSAStack
))
22959 // OpenMP 5.0, 2.10.1 task Construct.
22960 // event-handle is a variable of the omp_event_handle_t type.
22961 auto *Ref
= dyn_cast
<DeclRefExpr
>(Evt
->IgnoreParenImpCasts());
22963 Diag(Evt
->getExprLoc(), diag::err_omp_var_expected
)
22964 << "omp_event_handle_t" << 0 << Evt
->getSourceRange();
22967 auto *VD
= dyn_cast_or_null
<VarDecl
>(Ref
->getDecl());
22969 Diag(Evt
->getExprLoc(), diag::err_omp_var_expected
)
22970 << "omp_event_handle_t" << 0 << Evt
->getSourceRange();
22973 if (!Context
.hasSameUnqualifiedType(DSAStack
->getOMPEventHandleT(),
22975 VD
->getType().isConstant(Context
)) {
22976 Diag(Evt
->getExprLoc(), diag::err_omp_var_expected
)
22977 << "omp_event_handle_t" << 1 << VD
->getType()
22978 << Evt
->getSourceRange();
22981 // OpenMP 5.0, 2.10.1 task Construct
22982 // [detach clause]... The event-handle will be considered as if it was
22983 // specified on a firstprivate clause.
22984 DSAStackTy::DSAVarData DVar
= DSAStack
->getTopDSA(VD
, /*FromParent=*/false);
22985 if (DVar
.CKind
!= OMPC_unknown
&& DVar
.CKind
!= OMPC_firstprivate
&&
22987 Diag(Evt
->getExprLoc(), diag::err_omp_wrong_dsa
)
22988 << getOpenMPClauseName(DVar
.CKind
)
22989 << getOpenMPClauseName(OMPC_firstprivate
);
22990 reportOriginalDsa(*this, DSAStack
, VD
, DVar
);
22995 return new (Context
) OMPDetachClause(Evt
, StartLoc
, LParenLoc
, EndLoc
);
22998 OMPClause
*Sema::ActOnOpenMPDistScheduleClause(
22999 OpenMPDistScheduleClauseKind Kind
, Expr
*ChunkSize
, SourceLocation StartLoc
,
23000 SourceLocation LParenLoc
, SourceLocation KindLoc
, SourceLocation CommaLoc
,
23001 SourceLocation EndLoc
) {
23002 if (Kind
== OMPC_DIST_SCHEDULE_unknown
) {
23003 std::string Values
;
23005 Values
+= getOpenMPSimpleClauseTypeName(OMPC_dist_schedule
, 0);
23007 Diag(KindLoc
, diag::err_omp_unexpected_clause_value
)
23008 << Values
<< getOpenMPClauseName(OMPC_dist_schedule
);
23011 Expr
*ValExpr
= ChunkSize
;
23012 Stmt
*HelperValStmt
= nullptr;
23014 if (!ChunkSize
->isValueDependent() && !ChunkSize
->isTypeDependent() &&
23015 !ChunkSize
->isInstantiationDependent() &&
23016 !ChunkSize
->containsUnexpandedParameterPack()) {
23017 SourceLocation ChunkSizeLoc
= ChunkSize
->getBeginLoc();
23019 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc
, ChunkSize
);
23020 if (Val
.isInvalid())
23023 ValExpr
= Val
.get();
23025 // OpenMP [2.7.1, Restrictions]
23026 // chunk_size must be a loop invariant integer expression with a positive
23028 if (std::optional
<llvm::APSInt
> Result
=
23029 ValExpr
->getIntegerConstantExpr(Context
)) {
23030 if (Result
->isSigned() && !Result
->isStrictlyPositive()) {
23031 Diag(ChunkSizeLoc
, diag::err_omp_negative_expression_in_clause
)
23032 << "dist_schedule" << ChunkSize
->getSourceRange();
23035 } else if (getOpenMPCaptureRegionForClause(
23036 DSAStack
->getCurrentDirective(), OMPC_dist_schedule
,
23037 LangOpts
.OpenMP
) != OMPD_unknown
&&
23038 !CurContext
->isDependentContext()) {
23039 ValExpr
= MakeFullExpr(ValExpr
).get();
23040 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
23041 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
23042 HelperValStmt
= buildPreInits(Context
, Captures
);
23047 return new (Context
)
23048 OMPDistScheduleClause(StartLoc
, LParenLoc
, KindLoc
, CommaLoc
, EndLoc
,
23049 Kind
, ValExpr
, HelperValStmt
);
23052 OMPClause
*Sema::ActOnOpenMPDefaultmapClause(
23053 OpenMPDefaultmapClauseModifier M
, OpenMPDefaultmapClauseKind Kind
,
23054 SourceLocation StartLoc
, SourceLocation LParenLoc
, SourceLocation MLoc
,
23055 SourceLocation KindLoc
, SourceLocation EndLoc
) {
23056 if (getLangOpts().OpenMP
< 50) {
23057 if (M
!= OMPC_DEFAULTMAP_MODIFIER_tofrom
||
23058 Kind
!= OMPC_DEFAULTMAP_scalar
) {
23060 SourceLocation Loc
;
23062 if (M
!= OMPC_DEFAULTMAP_MODIFIER_tofrom
) {
23063 Value
+= getOpenMPSimpleClauseTypeName(OMPC_defaultmap
,
23064 OMPC_DEFAULTMAP_MODIFIER_tofrom
);
23067 Value
+= getOpenMPSimpleClauseTypeName(OMPC_defaultmap
,
23068 OMPC_DEFAULTMAP_scalar
);
23072 Diag(Loc
, diag::err_omp_unexpected_clause_value
)
23073 << Value
<< getOpenMPClauseName(OMPC_defaultmap
);
23077 bool isDefaultmapModifier
= (M
!= OMPC_DEFAULTMAP_MODIFIER_unknown
);
23078 bool isDefaultmapKind
= (Kind
!= OMPC_DEFAULTMAP_unknown
) ||
23079 (LangOpts
.OpenMP
>= 50 && KindLoc
.isInvalid());
23080 if (!isDefaultmapKind
|| !isDefaultmapModifier
) {
23081 StringRef KindValue
= "'scalar', 'aggregate', 'pointer'";
23082 if (LangOpts
.OpenMP
== 50) {
23083 StringRef ModifierValue
= "'alloc', 'from', 'to', 'tofrom', "
23084 "'firstprivate', 'none', 'default'";
23085 if (!isDefaultmapKind
&& isDefaultmapModifier
) {
23086 Diag(KindLoc
, diag::err_omp_unexpected_clause_value
)
23087 << KindValue
<< getOpenMPClauseName(OMPC_defaultmap
);
23088 } else if (isDefaultmapKind
&& !isDefaultmapModifier
) {
23089 Diag(MLoc
, diag::err_omp_unexpected_clause_value
)
23090 << ModifierValue
<< getOpenMPClauseName(OMPC_defaultmap
);
23092 Diag(MLoc
, diag::err_omp_unexpected_clause_value
)
23093 << ModifierValue
<< getOpenMPClauseName(OMPC_defaultmap
);
23094 Diag(KindLoc
, diag::err_omp_unexpected_clause_value
)
23095 << KindValue
<< getOpenMPClauseName(OMPC_defaultmap
);
23098 StringRef ModifierValue
=
23099 "'alloc', 'from', 'to', 'tofrom', "
23100 "'firstprivate', 'none', 'default', 'present'";
23101 if (!isDefaultmapKind
&& isDefaultmapModifier
) {
23102 Diag(KindLoc
, diag::err_omp_unexpected_clause_value
)
23103 << KindValue
<< getOpenMPClauseName(OMPC_defaultmap
);
23104 } else if (isDefaultmapKind
&& !isDefaultmapModifier
) {
23105 Diag(MLoc
, diag::err_omp_unexpected_clause_value
)
23106 << ModifierValue
<< getOpenMPClauseName(OMPC_defaultmap
);
23108 Diag(MLoc
, diag::err_omp_unexpected_clause_value
)
23109 << ModifierValue
<< getOpenMPClauseName(OMPC_defaultmap
);
23110 Diag(KindLoc
, diag::err_omp_unexpected_clause_value
)
23111 << KindValue
<< getOpenMPClauseName(OMPC_defaultmap
);
23117 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
23118 // At most one defaultmap clause for each category can appear on the
23120 if (DSAStack
->checkDefaultmapCategory(Kind
)) {
23121 Diag(StartLoc
, diag::err_omp_one_defaultmap_each_category
);
23125 if (Kind
== OMPC_DEFAULTMAP_unknown
) {
23126 // Variable category is not specified - mark all categories.
23127 DSAStack
->setDefaultDMAAttr(M
, OMPC_DEFAULTMAP_aggregate
, StartLoc
);
23128 DSAStack
->setDefaultDMAAttr(M
, OMPC_DEFAULTMAP_scalar
, StartLoc
);
23129 DSAStack
->setDefaultDMAAttr(M
, OMPC_DEFAULTMAP_pointer
, StartLoc
);
23131 DSAStack
->setDefaultDMAAttr(M
, Kind
, StartLoc
);
23134 return new (Context
)
23135 OMPDefaultmapClause(StartLoc
, LParenLoc
, MLoc
, KindLoc
, EndLoc
, Kind
, M
);
23138 bool Sema::ActOnStartOpenMPDeclareTargetContext(
23139 DeclareTargetContextInfo
&DTCI
) {
23140 DeclContext
*CurLexicalContext
= getCurLexicalContext();
23141 if (!CurLexicalContext
->isFileContext() &&
23142 !CurLexicalContext
->isExternCContext() &&
23143 !CurLexicalContext
->isExternCXXContext() &&
23144 !isa
<CXXRecordDecl
>(CurLexicalContext
) &&
23145 !isa
<ClassTemplateDecl
>(CurLexicalContext
) &&
23146 !isa
<ClassTemplatePartialSpecializationDecl
>(CurLexicalContext
) &&
23147 !isa
<ClassTemplateSpecializationDecl
>(CurLexicalContext
)) {
23148 Diag(DTCI
.Loc
, diag::err_omp_region_not_file_context
);
23152 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
23153 if (getLangOpts().HIP
)
23154 Diag(DTCI
.Loc
, diag::warn_hip_omp_target_directives
);
23156 DeclareTargetNesting
.push_back(DTCI
);
23160 const Sema::DeclareTargetContextInfo
23161 Sema::ActOnOpenMPEndDeclareTargetDirective() {
23162 assert(!DeclareTargetNesting
.empty() &&
23163 "check isInOpenMPDeclareTargetContext() first!");
23164 return DeclareTargetNesting
.pop_back_val();
23167 void Sema::ActOnFinishedOpenMPDeclareTargetContext(
23168 DeclareTargetContextInfo
&DTCI
) {
23169 for (auto &It
: DTCI
.ExplicitlyMapped
)
23170 ActOnOpenMPDeclareTargetName(It
.first
, It
.second
.Loc
, It
.second
.MT
, DTCI
);
23173 void Sema::DiagnoseUnterminatedOpenMPDeclareTarget() {
23174 if (DeclareTargetNesting
.empty())
23176 DeclareTargetContextInfo
&DTCI
= DeclareTargetNesting
.back();
23177 Diag(DTCI
.Loc
, diag::warn_omp_unterminated_declare_target
)
23178 << getOpenMPDirectiveName(DTCI
.Kind
);
23181 NamedDecl
*Sema::lookupOpenMPDeclareTargetName(Scope
*CurScope
,
23182 CXXScopeSpec
&ScopeSpec
,
23183 const DeclarationNameInfo
&Id
) {
23184 LookupResult
Lookup(*this, Id
, LookupOrdinaryName
);
23185 LookupParsedName(Lookup
, CurScope
, &ScopeSpec
, true);
23187 if (Lookup
.isAmbiguous())
23189 Lookup
.suppressDiagnostics();
23191 if (!Lookup
.isSingleResult()) {
23192 VarOrFuncDeclFilterCCC
CCC(*this);
23193 if (TypoCorrection Corrected
=
23194 CorrectTypo(Id
, LookupOrdinaryName
, CurScope
, nullptr, CCC
,
23195 CTK_ErrorRecovery
)) {
23196 diagnoseTypo(Corrected
, PDiag(diag::err_undeclared_var_use_suggest
)
23198 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected
.getCorrectionDecl());
23202 Diag(Id
.getLoc(), diag::err_undeclared_var_use
) << Id
.getName();
23206 NamedDecl
*ND
= Lookup
.getAsSingle
<NamedDecl
>();
23207 if (!isa
<VarDecl
>(ND
) && !isa
<FunctionDecl
>(ND
) &&
23208 !isa
<FunctionTemplateDecl
>(ND
)) {
23209 Diag(Id
.getLoc(), diag::err_omp_invalid_target_decl
) << Id
.getName();
23215 void Sema::ActOnOpenMPDeclareTargetName(NamedDecl
*ND
, SourceLocation Loc
,
23216 OMPDeclareTargetDeclAttr::MapTypeTy MT
,
23217 DeclareTargetContextInfo
&DTCI
) {
23218 assert((isa
<VarDecl
>(ND
) || isa
<FunctionDecl
>(ND
) ||
23219 isa
<FunctionTemplateDecl
>(ND
)) &&
23220 "Expected variable, function or function template.");
23222 // Diagnose marking after use as it may lead to incorrect diagnosis and
23224 if (LangOpts
.OpenMP
>= 50 &&
23225 (ND
->isUsed(/*CheckUsedAttr=*/false) || ND
->isReferenced()))
23226 Diag(Loc
, diag::warn_omp_declare_target_after_first_use
);
23228 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
23229 if (getLangOpts().HIP
)
23230 Diag(Loc
, diag::warn_hip_omp_target_directives
);
23232 // Explicit declare target lists have precedence.
23233 const unsigned Level
= -1;
23235 auto *VD
= cast
<ValueDecl
>(ND
);
23236 std::optional
<OMPDeclareTargetDeclAttr
*> ActiveAttr
=
23237 OMPDeclareTargetDeclAttr::getActiveAttr(VD
);
23238 if (ActiveAttr
&& (*ActiveAttr
)->getDevType() != DTCI
.DT
&&
23239 (*ActiveAttr
)->getLevel() == Level
) {
23240 Diag(Loc
, diag::err_omp_device_type_mismatch
)
23241 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI
.DT
)
23242 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
23243 (*ActiveAttr
)->getDevType());
23246 if (ActiveAttr
&& (*ActiveAttr
)->getMapType() != MT
&&
23247 (*ActiveAttr
)->getLevel() == Level
) {
23248 Diag(Loc
, diag::err_omp_declare_target_to_and_link
) << ND
;
23252 if (ActiveAttr
&& (*ActiveAttr
)->getLevel() == Level
)
23255 Expr
*IndirectE
= nullptr;
23256 bool IsIndirect
= false;
23257 if (DTCI
.Indirect
) {
23258 IndirectE
= *DTCI
.Indirect
;
23262 auto *A
= OMPDeclareTargetDeclAttr::CreateImplicit(
23263 Context
, MT
, DTCI
.DT
, IndirectE
, IsIndirect
, Level
,
23264 SourceRange(Loc
, Loc
));
23266 if (ASTMutationListener
*ML
= Context
.getASTMutationListener())
23267 ML
->DeclarationMarkedOpenMPDeclareTarget(ND
, A
);
23268 checkDeclIsAllowedInOpenMPTarget(nullptr, ND
, Loc
);
23269 if (auto *VD
= dyn_cast
<VarDecl
>(ND
);
23270 LangOpts
.OpenMP
&& VD
&& VD
->hasAttr
<OMPDeclareTargetDeclAttr
>() &&
23271 VD
->hasGlobalStorage())
23272 ActOnOpenMPDeclareTargetInitializer(ND
);
23275 static void checkDeclInTargetContext(SourceLocation SL
, SourceRange SR
,
23276 Sema
&SemaRef
, Decl
*D
) {
23277 if (!D
|| !isa
<VarDecl
>(D
))
23279 auto *VD
= cast
<VarDecl
>(D
);
23280 std::optional
<OMPDeclareTargetDeclAttr::MapTypeTy
> MapTy
=
23281 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD
);
23282 if (SemaRef
.LangOpts
.OpenMP
>= 50 &&
23283 (SemaRef
.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
23284 SemaRef
.getCurBlock() || SemaRef
.getCurCapturedRegion()) &&
23285 VD
->hasGlobalStorage()) {
23286 if (!MapTy
|| (*MapTy
!= OMPDeclareTargetDeclAttr::MT_To
&&
23287 *MapTy
!= OMPDeclareTargetDeclAttr::MT_Enter
)) {
23288 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
23289 // If a lambda declaration and definition appears between a
23290 // declare target directive and the matching end declare target
23291 // directive, all variables that are captured by the lambda
23292 // expression must also appear in a to clause.
23293 SemaRef
.Diag(VD
->getLocation(),
23294 diag::err_omp_lambda_capture_in_declare_target_not_to
);
23295 SemaRef
.Diag(SL
, diag::note_var_explicitly_captured_here
)
23302 SemaRef
.Diag(VD
->getLocation(), diag::warn_omp_not_in_target_context
);
23303 SemaRef
.Diag(SL
, diag::note_used_here
) << SR
;
23306 static bool checkValueDeclInTarget(SourceLocation SL
, SourceRange SR
,
23307 Sema
&SemaRef
, DSAStackTy
*Stack
,
23309 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD
) ||
23310 checkTypeMappable(SL
, SR
, SemaRef
, Stack
, VD
->getType(),
23311 /*FullCheck=*/false);
23314 void Sema::checkDeclIsAllowedInOpenMPTarget(Expr
*E
, Decl
*D
,
23315 SourceLocation IdLoc
) {
23316 if (!D
|| D
->isInvalidDecl())
23318 SourceRange SR
= E
? E
->getSourceRange() : D
->getSourceRange();
23319 SourceLocation SL
= E
? E
->getBeginLoc() : D
->getLocation();
23320 if (auto *VD
= dyn_cast
<VarDecl
>(D
)) {
23321 // Only global variables can be marked as declare target.
23322 if (!VD
->isFileVarDecl() && !VD
->isStaticLocal() &&
23323 !VD
->isStaticDataMember())
23325 // 2.10.6: threadprivate variable cannot appear in a declare target
23327 if (DSAStack
->isThreadPrivate(VD
)) {
23328 Diag(SL
, diag::err_omp_threadprivate_in_target
);
23329 reportOriginalDsa(*this, DSAStack
, VD
, DSAStack
->getTopDSA(VD
, false));
23333 if (const auto *FTD
= dyn_cast
<FunctionTemplateDecl
>(D
))
23334 D
= FTD
->getTemplatedDecl();
23335 if (auto *FD
= dyn_cast
<FunctionDecl
>(D
)) {
23336 std::optional
<OMPDeclareTargetDeclAttr::MapTypeTy
> Res
=
23337 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD
);
23338 if (IdLoc
.isValid() && Res
&& *Res
== OMPDeclareTargetDeclAttr::MT_Link
) {
23339 Diag(IdLoc
, diag::err_omp_function_in_link_clause
);
23340 Diag(FD
->getLocation(), diag::note_defined_here
) << FD
;
23344 if (auto *VD
= dyn_cast
<ValueDecl
>(D
)) {
23345 // Problem if any with var declared with incomplete type will be reported
23346 // as normal, so no need to check it here.
23347 if ((E
|| !VD
->getType()->isIncompleteType()) &&
23348 !checkValueDeclInTarget(SL
, SR
, *this, DSAStack
, VD
))
23350 if (!E
&& isInOpenMPDeclareTargetContext()) {
23351 // Checking declaration inside declare target region.
23352 if (isa
<VarDecl
>(D
) || isa
<FunctionDecl
>(D
) ||
23353 isa
<FunctionTemplateDecl
>(D
)) {
23354 std::optional
<OMPDeclareTargetDeclAttr
*> ActiveAttr
=
23355 OMPDeclareTargetDeclAttr::getActiveAttr(VD
);
23356 unsigned Level
= DeclareTargetNesting
.size();
23357 if (ActiveAttr
&& (*ActiveAttr
)->getLevel() >= Level
)
23359 DeclareTargetContextInfo
&DTCI
= DeclareTargetNesting
.back();
23360 Expr
*IndirectE
= nullptr;
23361 bool IsIndirect
= false;
23362 if (DTCI
.Indirect
) {
23363 IndirectE
= *DTCI
.Indirect
;
23367 auto *A
= OMPDeclareTargetDeclAttr::CreateImplicit(
23369 getLangOpts().OpenMP
>= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
23370 : OMPDeclareTargetDeclAttr::MT_To
,
23371 DTCI
.DT
, IndirectE
, IsIndirect
, Level
,
23372 SourceRange(DTCI
.Loc
, DTCI
.Loc
));
23374 if (ASTMutationListener
*ML
= Context
.getASTMutationListener())
23375 ML
->DeclarationMarkedOpenMPDeclareTarget(D
, A
);
23382 checkDeclInTargetContext(E
->getExprLoc(), E
->getSourceRange(), *this, D
);
23385 /// This class visits every VarDecl that the initializer references and adds
23386 /// OMPDeclareTargetDeclAttr to each of them.
23387 class GlobalDeclRefChecker final
23388 : public StmtVisitor
<GlobalDeclRefChecker
> {
23389 SmallVector
<VarDecl
*> DeclVector
;
23393 /// A StmtVisitor class function that visits all DeclRefExpr and adds
23394 /// OMPDeclareTargetDeclAttr to them.
23395 void VisitDeclRefExpr(DeclRefExpr
*Node
) {
23396 if (auto *VD
= dyn_cast
<VarDecl
>(Node
->getDecl())) {
23398 DeclVector
.push_back(VD
);
23401 /// A function that iterates across each of the Expr's children.
23402 void VisitExpr(Expr
*Ex
) {
23403 for (auto *Child
: Ex
->children()) {
23407 /// A function that keeps a record of all the Decls that are variables, has
23408 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
23409 /// each Decl one at a time and use the inherited 'visit' functions to look
23410 /// for DeclRefExpr.
23411 void declareTargetInitializer(Decl
*TD
) {
23412 A
= TD
->getAttr
<OMPDeclareTargetDeclAttr
>();
23413 DeclVector
.push_back(cast
<VarDecl
>(TD
));
23414 while (!DeclVector
.empty()) {
23415 VarDecl
*TargetVarDecl
= DeclVector
.pop_back_val();
23416 if (TargetVarDecl
->hasAttr
<OMPDeclareTargetDeclAttr
>() &&
23417 TargetVarDecl
->hasInit() && TargetVarDecl
->hasGlobalStorage()) {
23418 if (Expr
*Ex
= TargetVarDecl
->getInit())
23425 /// Adding OMPDeclareTargetDeclAttr to variables with static storage
23426 /// duration that are referenced in the initializer expression list of
23427 /// variables with static storage duration in declare target directive.
23428 void Sema::ActOnOpenMPDeclareTargetInitializer(Decl
*TargetDecl
) {
23429 GlobalDeclRefChecker Checker
;
23430 if (isa
<VarDecl
>(TargetDecl
))
23431 Checker
.declareTargetInitializer(TargetDecl
);
23434 OMPClause
*Sema::ActOnOpenMPToClause(
23435 ArrayRef
<OpenMPMotionModifierKind
> MotionModifiers
,
23436 ArrayRef
<SourceLocation
> MotionModifiersLoc
,
23437 CXXScopeSpec
&MapperIdScopeSpec
, DeclarationNameInfo
&MapperId
,
23438 SourceLocation ColonLoc
, ArrayRef
<Expr
*> VarList
,
23439 const OMPVarListLocTy
&Locs
, ArrayRef
<Expr
*> UnresolvedMappers
) {
23440 OpenMPMotionModifierKind Modifiers
[] = {OMPC_MOTION_MODIFIER_unknown
,
23441 OMPC_MOTION_MODIFIER_unknown
};
23442 SourceLocation ModifiersLoc
[NumberOfOMPMotionModifiers
];
23444 // Process motion-modifiers, flag errors for duplicate modifiers.
23445 unsigned Count
= 0;
23446 for (unsigned I
= 0, E
= MotionModifiers
.size(); I
< E
; ++I
) {
23447 if (MotionModifiers
[I
] != OMPC_MOTION_MODIFIER_unknown
&&
23448 llvm::is_contained(Modifiers
, MotionModifiers
[I
])) {
23449 Diag(MotionModifiersLoc
[I
], diag::err_omp_duplicate_motion_modifier
);
23452 assert(Count
< NumberOfOMPMotionModifiers
&&
23453 "Modifiers exceed the allowed number of motion modifiers");
23454 Modifiers
[Count
] = MotionModifiers
[I
];
23455 ModifiersLoc
[Count
] = MotionModifiersLoc
[I
];
23459 MappableVarListInfo
MVLI(VarList
);
23460 checkMappableExpressionList(*this, DSAStack
, OMPC_to
, MVLI
, Locs
.StartLoc
,
23461 MapperIdScopeSpec
, MapperId
, UnresolvedMappers
);
23462 if (MVLI
.ProcessedVarList
.empty())
23465 return OMPToClause::Create(
23466 Context
, Locs
, MVLI
.ProcessedVarList
, MVLI
.VarBaseDeclarations
,
23467 MVLI
.VarComponents
, MVLI
.UDMapperList
, Modifiers
, ModifiersLoc
,
23468 MapperIdScopeSpec
.getWithLocInContext(Context
), MapperId
);
23471 OMPClause
*Sema::ActOnOpenMPFromClause(
23472 ArrayRef
<OpenMPMotionModifierKind
> MotionModifiers
,
23473 ArrayRef
<SourceLocation
> MotionModifiersLoc
,
23474 CXXScopeSpec
&MapperIdScopeSpec
, DeclarationNameInfo
&MapperId
,
23475 SourceLocation ColonLoc
, ArrayRef
<Expr
*> VarList
,
23476 const OMPVarListLocTy
&Locs
, ArrayRef
<Expr
*> UnresolvedMappers
) {
23477 OpenMPMotionModifierKind Modifiers
[] = {OMPC_MOTION_MODIFIER_unknown
,
23478 OMPC_MOTION_MODIFIER_unknown
};
23479 SourceLocation ModifiersLoc
[NumberOfOMPMotionModifiers
];
23481 // Process motion-modifiers, flag errors for duplicate modifiers.
23482 unsigned Count
= 0;
23483 for (unsigned I
= 0, E
= MotionModifiers
.size(); I
< E
; ++I
) {
23484 if (MotionModifiers
[I
] != OMPC_MOTION_MODIFIER_unknown
&&
23485 llvm::is_contained(Modifiers
, MotionModifiers
[I
])) {
23486 Diag(MotionModifiersLoc
[I
], diag::err_omp_duplicate_motion_modifier
);
23489 assert(Count
< NumberOfOMPMotionModifiers
&&
23490 "Modifiers exceed the allowed number of motion modifiers");
23491 Modifiers
[Count
] = MotionModifiers
[I
];
23492 ModifiersLoc
[Count
] = MotionModifiersLoc
[I
];
23496 MappableVarListInfo
MVLI(VarList
);
23497 checkMappableExpressionList(*this, DSAStack
, OMPC_from
, MVLI
, Locs
.StartLoc
,
23498 MapperIdScopeSpec
, MapperId
, UnresolvedMappers
);
23499 if (MVLI
.ProcessedVarList
.empty())
23502 return OMPFromClause::Create(
23503 Context
, Locs
, MVLI
.ProcessedVarList
, MVLI
.VarBaseDeclarations
,
23504 MVLI
.VarComponents
, MVLI
.UDMapperList
, Modifiers
, ModifiersLoc
,
23505 MapperIdScopeSpec
.getWithLocInContext(Context
), MapperId
);
23508 OMPClause
*Sema::ActOnOpenMPUseDevicePtrClause(ArrayRef
<Expr
*> VarList
,
23509 const OMPVarListLocTy
&Locs
) {
23510 MappableVarListInfo
MVLI(VarList
);
23511 SmallVector
<Expr
*, 8> PrivateCopies
;
23512 SmallVector
<Expr
*, 8> Inits
;
23514 for (Expr
*RefExpr
: VarList
) {
23515 assert(RefExpr
&& "NULL expr in OpenMP use_device_ptr clause.");
23516 SourceLocation ELoc
;
23517 SourceRange ERange
;
23518 Expr
*SimpleRefExpr
= RefExpr
;
23519 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
23521 // It will be analyzed later.
23522 MVLI
.ProcessedVarList
.push_back(RefExpr
);
23523 PrivateCopies
.push_back(nullptr);
23524 Inits
.push_back(nullptr);
23526 ValueDecl
*D
= Res
.first
;
23530 QualType Type
= D
->getType();
23531 Type
= Type
.getNonReferenceType().getUnqualifiedType();
23533 auto *VD
= dyn_cast
<VarDecl
>(D
);
23535 // Item should be a pointer or reference to pointer.
23536 if (!Type
->isPointerType()) {
23537 Diag(ELoc
, diag::err_omp_usedeviceptr_not_a_pointer
)
23538 << 0 << RefExpr
->getSourceRange();
23542 // Build the private variable and the expression that refers to it.
23544 buildVarDecl(*this, ELoc
, Type
, D
->getName(),
23545 D
->hasAttrs() ? &D
->getAttrs() : nullptr,
23546 VD
? cast
<DeclRefExpr
>(SimpleRefExpr
) : nullptr);
23547 if (VDPrivate
->isInvalidDecl())
23550 CurContext
->addDecl(VDPrivate
);
23551 DeclRefExpr
*VDPrivateRefExpr
= buildDeclRefExpr(
23552 *this, VDPrivate
, RefExpr
->getType().getUnqualifiedType(), ELoc
);
23554 // Add temporary variable to initialize the private copy of the pointer.
23556 buildVarDecl(*this, RefExpr
->getExprLoc(), Type
, ".devptr.temp");
23557 DeclRefExpr
*VDInitRefExpr
= buildDeclRefExpr(
23558 *this, VDInit
, RefExpr
->getType(), RefExpr
->getExprLoc());
23559 AddInitializerToDecl(VDPrivate
,
23560 DefaultLvalueConversion(VDInitRefExpr
).get(),
23561 /*DirectInit=*/false);
23563 // If required, build a capture to implement the privatization initialized
23564 // with the current list item value.
23565 DeclRefExpr
*Ref
= nullptr;
23567 Ref
= buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/true);
23568 MVLI
.ProcessedVarList
.push_back(VD
? RefExpr
->IgnoreParens() : Ref
);
23569 PrivateCopies
.push_back(VDPrivateRefExpr
);
23570 Inits
.push_back(VDInitRefExpr
);
23572 // We need to add a data sharing attribute for this variable to make sure it
23573 // is correctly captured. A variable that shows up in a use_device_ptr has
23574 // similar properties of a first private variable.
23575 DSAStack
->addDSA(D
, RefExpr
->IgnoreParens(), OMPC_firstprivate
, Ref
);
23577 // Create a mappable component for the list item. List items in this clause
23578 // only need a component.
23579 MVLI
.VarBaseDeclarations
.push_back(D
);
23580 MVLI
.VarComponents
.resize(MVLI
.VarComponents
.size() + 1);
23581 MVLI
.VarComponents
.back().emplace_back(SimpleRefExpr
, D
,
23582 /*IsNonContiguous=*/false);
23585 if (MVLI
.ProcessedVarList
.empty())
23588 return OMPUseDevicePtrClause::Create(
23589 Context
, Locs
, MVLI
.ProcessedVarList
, PrivateCopies
, Inits
,
23590 MVLI
.VarBaseDeclarations
, MVLI
.VarComponents
);
23593 OMPClause
*Sema::ActOnOpenMPUseDeviceAddrClause(ArrayRef
<Expr
*> VarList
,
23594 const OMPVarListLocTy
&Locs
) {
23595 MappableVarListInfo
MVLI(VarList
);
23597 for (Expr
*RefExpr
: VarList
) {
23598 assert(RefExpr
&& "NULL expr in OpenMP use_device_addr clause.");
23599 SourceLocation ELoc
;
23600 SourceRange ERange
;
23601 Expr
*SimpleRefExpr
= RefExpr
;
23602 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
,
23603 /*AllowArraySection=*/true);
23605 // It will be analyzed later.
23606 MVLI
.ProcessedVarList
.push_back(RefExpr
);
23608 ValueDecl
*D
= Res
.first
;
23611 auto *VD
= dyn_cast
<VarDecl
>(D
);
23613 // If required, build a capture to implement the privatization initialized
23614 // with the current list item value.
23615 DeclRefExpr
*Ref
= nullptr;
23617 Ref
= buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/true);
23618 MVLI
.ProcessedVarList
.push_back(VD
? RefExpr
->IgnoreParens() : Ref
);
23620 // We need to add a data sharing attribute for this variable to make sure it
23621 // is correctly captured. A variable that shows up in a use_device_addr has
23622 // similar properties of a first private variable.
23623 DSAStack
->addDSA(D
, RefExpr
->IgnoreParens(), OMPC_firstprivate
, Ref
);
23625 // Create a mappable component for the list item. List items in this clause
23626 // only need a component.
23627 MVLI
.VarBaseDeclarations
.push_back(D
);
23628 MVLI
.VarComponents
.emplace_back();
23629 Expr
*Component
= SimpleRefExpr
;
23630 if (VD
&& (isa
<OMPArraySectionExpr
>(RefExpr
->IgnoreParenImpCasts()) ||
23631 isa
<ArraySubscriptExpr
>(RefExpr
->IgnoreParenImpCasts())))
23632 Component
= DefaultFunctionArrayLvalueConversion(SimpleRefExpr
).get();
23633 MVLI
.VarComponents
.back().emplace_back(Component
, D
,
23634 /*IsNonContiguous=*/false);
23637 if (MVLI
.ProcessedVarList
.empty())
23640 return OMPUseDeviceAddrClause::Create(Context
, Locs
, MVLI
.ProcessedVarList
,
23641 MVLI
.VarBaseDeclarations
,
23642 MVLI
.VarComponents
);
23645 OMPClause
*Sema::ActOnOpenMPIsDevicePtrClause(ArrayRef
<Expr
*> VarList
,
23646 const OMPVarListLocTy
&Locs
) {
23647 MappableVarListInfo
MVLI(VarList
);
23648 for (Expr
*RefExpr
: VarList
) {
23649 assert(RefExpr
&& "NULL expr in OpenMP is_device_ptr clause.");
23650 SourceLocation ELoc
;
23651 SourceRange ERange
;
23652 Expr
*SimpleRefExpr
= RefExpr
;
23653 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
23655 // It will be analyzed later.
23656 MVLI
.ProcessedVarList
.push_back(RefExpr
);
23658 ValueDecl
*D
= Res
.first
;
23662 QualType Type
= D
->getType();
23663 // item should be a pointer or array or reference to pointer or array
23664 if (!Type
.getNonReferenceType()->isPointerType() &&
23665 !Type
.getNonReferenceType()->isArrayType()) {
23666 Diag(ELoc
, diag::err_omp_argument_type_isdeviceptr
)
23667 << 0 << RefExpr
->getSourceRange();
23671 // Check if the declaration in the clause does not show up in any data
23672 // sharing attribute.
23673 DSAStackTy::DSAVarData DVar
= DSAStack
->getTopDSA(D
, /*FromParent=*/false);
23674 if (isOpenMPPrivate(DVar
.CKind
)) {
23675 Diag(ELoc
, diag::err_omp_variable_in_given_clause_and_dsa
)
23676 << getOpenMPClauseName(DVar
.CKind
)
23677 << getOpenMPClauseName(OMPC_is_device_ptr
)
23678 << getOpenMPDirectiveName(DSAStack
->getCurrentDirective());
23679 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
23683 const Expr
*ConflictExpr
;
23684 if (DSAStack
->checkMappableExprComponentListsForDecl(
23685 D
, /*CurrentRegionOnly=*/true,
23687 OMPClauseMappableExprCommon::MappableExprComponentListRef R
,
23688 OpenMPClauseKind
) -> bool {
23689 ConflictExpr
= R
.front().getAssociatedExpression();
23692 Diag(ELoc
, diag::err_omp_map_shared_storage
) << RefExpr
->getSourceRange();
23693 Diag(ConflictExpr
->getExprLoc(), diag::note_used_here
)
23694 << ConflictExpr
->getSourceRange();
23698 // Store the components in the stack so that they can be used to check
23699 // against other clauses later on.
23700 OMPClauseMappableExprCommon::MappableComponent
MC(
23701 SimpleRefExpr
, D
, /*IsNonContiguous=*/false);
23702 DSAStack
->addMappableExpressionComponents(
23703 D
, MC
, /*WhereFoundClauseKind=*/OMPC_is_device_ptr
);
23705 // Record the expression we've just processed.
23706 MVLI
.ProcessedVarList
.push_back(SimpleRefExpr
);
23708 // Create a mappable component for the list item. List items in this clause
23709 // only need a component. We use a null declaration to signal fields in
23711 assert((isa
<DeclRefExpr
>(SimpleRefExpr
) ||
23712 isa
<CXXThisExpr
>(cast
<MemberExpr
>(SimpleRefExpr
)->getBase())) &&
23713 "Unexpected device pointer expression!");
23714 MVLI
.VarBaseDeclarations
.push_back(
23715 isa
<DeclRefExpr
>(SimpleRefExpr
) ? D
: nullptr);
23716 MVLI
.VarComponents
.resize(MVLI
.VarComponents
.size() + 1);
23717 MVLI
.VarComponents
.back().push_back(MC
);
23720 if (MVLI
.ProcessedVarList
.empty())
23723 return OMPIsDevicePtrClause::Create(Context
, Locs
, MVLI
.ProcessedVarList
,
23724 MVLI
.VarBaseDeclarations
,
23725 MVLI
.VarComponents
);
23728 OMPClause
*Sema::ActOnOpenMPHasDeviceAddrClause(ArrayRef
<Expr
*> VarList
,
23729 const OMPVarListLocTy
&Locs
) {
23730 MappableVarListInfo
MVLI(VarList
);
23731 for (Expr
*RefExpr
: VarList
) {
23732 assert(RefExpr
&& "NULL expr in OpenMP has_device_addr clause.");
23733 SourceLocation ELoc
;
23734 SourceRange ERange
;
23735 Expr
*SimpleRefExpr
= RefExpr
;
23736 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
,
23737 /*AllowArraySection=*/true);
23739 // It will be analyzed later.
23740 MVLI
.ProcessedVarList
.push_back(RefExpr
);
23742 ValueDecl
*D
= Res
.first
;
23746 // Check if the declaration in the clause does not show up in any data
23747 // sharing attribute.
23748 DSAStackTy::DSAVarData DVar
= DSAStack
->getTopDSA(D
, /*FromParent=*/false);
23749 if (isOpenMPPrivate(DVar
.CKind
)) {
23750 Diag(ELoc
, diag::err_omp_variable_in_given_clause_and_dsa
)
23751 << getOpenMPClauseName(DVar
.CKind
)
23752 << getOpenMPClauseName(OMPC_has_device_addr
)
23753 << getOpenMPDirectiveName(DSAStack
->getCurrentDirective());
23754 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
23758 const Expr
*ConflictExpr
;
23759 if (DSAStack
->checkMappableExprComponentListsForDecl(
23760 D
, /*CurrentRegionOnly=*/true,
23762 OMPClauseMappableExprCommon::MappableExprComponentListRef R
,
23763 OpenMPClauseKind
) -> bool {
23764 ConflictExpr
= R
.front().getAssociatedExpression();
23767 Diag(ELoc
, diag::err_omp_map_shared_storage
) << RefExpr
->getSourceRange();
23768 Diag(ConflictExpr
->getExprLoc(), diag::note_used_here
)
23769 << ConflictExpr
->getSourceRange();
23773 // Store the components in the stack so that they can be used to check
23774 // against other clauses later on.
23775 Expr
*Component
= SimpleRefExpr
;
23776 auto *VD
= dyn_cast
<VarDecl
>(D
);
23777 if (VD
&& (isa
<OMPArraySectionExpr
>(RefExpr
->IgnoreParenImpCasts()) ||
23778 isa
<ArraySubscriptExpr
>(RefExpr
->IgnoreParenImpCasts())))
23779 Component
= DefaultFunctionArrayLvalueConversion(SimpleRefExpr
).get();
23780 OMPClauseMappableExprCommon::MappableComponent
MC(
23781 Component
, D
, /*IsNonContiguous=*/false);
23782 DSAStack
->addMappableExpressionComponents(
23783 D
, MC
, /*WhereFoundClauseKind=*/OMPC_has_device_addr
);
23785 // Record the expression we've just processed.
23786 if (!VD
&& !CurContext
->isDependentContext()) {
23788 buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/true);
23789 assert(Ref
&& "has_device_addr capture failed");
23790 MVLI
.ProcessedVarList
.push_back(Ref
);
23792 MVLI
.ProcessedVarList
.push_back(RefExpr
->IgnoreParens());
23794 // Create a mappable component for the list item. List items in this clause
23795 // only need a component. We use a null declaration to signal fields in
23797 assert((isa
<DeclRefExpr
>(SimpleRefExpr
) ||
23798 isa
<CXXThisExpr
>(cast
<MemberExpr
>(SimpleRefExpr
)->getBase())) &&
23799 "Unexpected device pointer expression!");
23800 MVLI
.VarBaseDeclarations
.push_back(
23801 isa
<DeclRefExpr
>(SimpleRefExpr
) ? D
: nullptr);
23802 MVLI
.VarComponents
.resize(MVLI
.VarComponents
.size() + 1);
23803 MVLI
.VarComponents
.back().push_back(MC
);
23806 if (MVLI
.ProcessedVarList
.empty())
23809 return OMPHasDeviceAddrClause::Create(Context
, Locs
, MVLI
.ProcessedVarList
,
23810 MVLI
.VarBaseDeclarations
,
23811 MVLI
.VarComponents
);
23814 OMPClause
*Sema::ActOnOpenMPAllocateClause(
23815 Expr
*Allocator
, ArrayRef
<Expr
*> VarList
, SourceLocation StartLoc
,
23816 SourceLocation ColonLoc
, SourceLocation LParenLoc
, SourceLocation EndLoc
) {
23818 // OpenMP [2.11.4 allocate Clause, Description]
23819 // allocator is an expression of omp_allocator_handle_t type.
23820 if (!findOMPAllocatorHandleT(*this, Allocator
->getExprLoc(), DSAStack
))
23823 ExprResult AllocatorRes
= DefaultLvalueConversion(Allocator
);
23824 if (AllocatorRes
.isInvalid())
23826 AllocatorRes
= PerformImplicitConversion(AllocatorRes
.get(),
23827 DSAStack
->getOMPAllocatorHandleT(),
23828 Sema::AA_Initializing
,
23829 /*AllowExplicit=*/true);
23830 if (AllocatorRes
.isInvalid())
23832 Allocator
= AllocatorRes
.get();
23834 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
23835 // allocate clauses that appear on a target construct or on constructs in a
23836 // target region must specify an allocator expression unless a requires
23837 // directive with the dynamic_allocators clause is present in the same
23838 // compilation unit.
23839 if (LangOpts
.OpenMPIsTargetDevice
&&
23840 !DSAStack
->hasRequiresDeclWithClause
<OMPDynamicAllocatorsClause
>())
23841 targetDiag(StartLoc
, diag::err_expected_allocator_expression
);
23843 // Analyze and build list of variables.
23844 SmallVector
<Expr
*, 8> Vars
;
23845 for (Expr
*RefExpr
: VarList
) {
23846 assert(RefExpr
&& "NULL expr in OpenMP private clause.");
23847 SourceLocation ELoc
;
23848 SourceRange ERange
;
23849 Expr
*SimpleRefExpr
= RefExpr
;
23850 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
23852 // It will be analyzed later.
23853 Vars
.push_back(RefExpr
);
23855 ValueDecl
*D
= Res
.first
;
23859 auto *VD
= dyn_cast
<VarDecl
>(D
);
23860 DeclRefExpr
*Ref
= nullptr;
23861 if (!VD
&& !CurContext
->isDependentContext())
23862 Ref
= buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/false);
23863 Vars
.push_back((VD
|| CurContext
->isDependentContext())
23864 ? RefExpr
->IgnoreParens()
23872 DSAStack
->addInnerAllocatorExpr(Allocator
);
23873 return OMPAllocateClause::Create(Context
, StartLoc
, LParenLoc
, Allocator
,
23874 ColonLoc
, EndLoc
, Vars
);
23877 OMPClause
*Sema::ActOnOpenMPNontemporalClause(ArrayRef
<Expr
*> VarList
,
23878 SourceLocation StartLoc
,
23879 SourceLocation LParenLoc
,
23880 SourceLocation EndLoc
) {
23881 SmallVector
<Expr
*, 8> Vars
;
23882 for (Expr
*RefExpr
: VarList
) {
23883 assert(RefExpr
&& "NULL expr in OpenMP nontemporal clause.");
23884 SourceLocation ELoc
;
23885 SourceRange ERange
;
23886 Expr
*SimpleRefExpr
= RefExpr
;
23887 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
23889 // It will be analyzed later.
23890 Vars
.push_back(RefExpr
);
23891 ValueDecl
*D
= Res
.first
;
23895 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
23896 // A list-item cannot appear in more than one nontemporal clause.
23897 if (const Expr
*PrevRef
=
23898 DSAStack
->addUniqueNontemporal(D
, SimpleRefExpr
)) {
23899 Diag(ELoc
, diag::err_omp_used_in_clause_twice
)
23900 << 0 << getOpenMPClauseName(OMPC_nontemporal
) << ERange
;
23901 Diag(PrevRef
->getExprLoc(), diag::note_omp_explicit_dsa
)
23902 << getOpenMPClauseName(OMPC_nontemporal
);
23906 Vars
.push_back(RefExpr
);
23912 return OMPNontemporalClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
,
23916 StmtResult
Sema::ActOnOpenMPScopeDirective(ArrayRef
<OMPClause
*> Clauses
,
23917 Stmt
*AStmt
, SourceLocation StartLoc
,
23918 SourceLocation EndLoc
) {
23920 return StmtError();
23922 setFunctionHasBranchProtectedScope();
23924 return OMPScopeDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
);
23927 OMPClause
*Sema::ActOnOpenMPInclusiveClause(ArrayRef
<Expr
*> VarList
,
23928 SourceLocation StartLoc
,
23929 SourceLocation LParenLoc
,
23930 SourceLocation EndLoc
) {
23931 SmallVector
<Expr
*, 8> Vars
;
23932 for (Expr
*RefExpr
: VarList
) {
23933 assert(RefExpr
&& "NULL expr in OpenMP nontemporal clause.");
23934 SourceLocation ELoc
;
23935 SourceRange ERange
;
23936 Expr
*SimpleRefExpr
= RefExpr
;
23937 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
,
23938 /*AllowArraySection=*/true);
23940 // It will be analyzed later.
23941 Vars
.push_back(RefExpr
);
23942 ValueDecl
*D
= Res
.first
;
23946 const DSAStackTy::DSAVarData DVar
=
23947 DSAStack
->getTopDSA(D
, /*FromParent=*/true);
23948 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23949 // A list item that appears in the inclusive or exclusive clause must appear
23950 // in a reduction clause with the inscan modifier on the enclosing
23951 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23952 if (DVar
.CKind
!= OMPC_reduction
|| DVar
.Modifier
!= OMPC_REDUCTION_inscan
)
23953 Diag(ELoc
, diag::err_omp_inclusive_exclusive_not_reduction
)
23954 << RefExpr
->getSourceRange();
23956 if (DSAStack
->getParentDirective() != OMPD_unknown
)
23957 DSAStack
->markDeclAsUsedInScanDirective(D
);
23958 Vars
.push_back(RefExpr
);
23964 return OMPInclusiveClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
, Vars
);
23967 OMPClause
*Sema::ActOnOpenMPExclusiveClause(ArrayRef
<Expr
*> VarList
,
23968 SourceLocation StartLoc
,
23969 SourceLocation LParenLoc
,
23970 SourceLocation EndLoc
) {
23971 SmallVector
<Expr
*, 8> Vars
;
23972 for (Expr
*RefExpr
: VarList
) {
23973 assert(RefExpr
&& "NULL expr in OpenMP nontemporal clause.");
23974 SourceLocation ELoc
;
23975 SourceRange ERange
;
23976 Expr
*SimpleRefExpr
= RefExpr
;
23977 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
,
23978 /*AllowArraySection=*/true);
23980 // It will be analyzed later.
23981 Vars
.push_back(RefExpr
);
23982 ValueDecl
*D
= Res
.first
;
23986 OpenMPDirectiveKind ParentDirective
= DSAStack
->getParentDirective();
23987 DSAStackTy::DSAVarData DVar
;
23988 if (ParentDirective
!= OMPD_unknown
)
23989 DVar
= DSAStack
->getTopDSA(D
, /*FromParent=*/true);
23990 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23991 // A list item that appears in the inclusive or exclusive clause must appear
23992 // in a reduction clause with the inscan modifier on the enclosing
23993 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23994 if (ParentDirective
== OMPD_unknown
|| DVar
.CKind
!= OMPC_reduction
||
23995 DVar
.Modifier
!= OMPC_REDUCTION_inscan
) {
23996 Diag(ELoc
, diag::err_omp_inclusive_exclusive_not_reduction
)
23997 << RefExpr
->getSourceRange();
23999 DSAStack
->markDeclAsUsedInScanDirective(D
);
24001 Vars
.push_back(RefExpr
);
24007 return OMPExclusiveClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
, Vars
);
24010 /// Tries to find omp_alloctrait_t type.
24011 static bool findOMPAlloctraitT(Sema
&S
, SourceLocation Loc
, DSAStackTy
*Stack
) {
24012 QualType OMPAlloctraitT
= Stack
->getOMPAlloctraitT();
24013 if (!OMPAlloctraitT
.isNull())
24015 IdentifierInfo
&II
= S
.PP
.getIdentifierTable().get("omp_alloctrait_t");
24016 ParsedType PT
= S
.getTypeName(II
, Loc
, S
.getCurScope());
24017 if (!PT
.getAsOpaquePtr() || PT
.get().isNull()) {
24018 S
.Diag(Loc
, diag::err_omp_implied_type_not_found
) << "omp_alloctrait_t";
24021 Stack
->setOMPAlloctraitT(PT
.get());
24025 OMPClause
*Sema::ActOnOpenMPUsesAllocatorClause(
24026 SourceLocation StartLoc
, SourceLocation LParenLoc
, SourceLocation EndLoc
,
24027 ArrayRef
<UsesAllocatorsData
> Data
) {
24028 // OpenMP [2.12.5, target Construct]
24029 // allocator is an identifier of omp_allocator_handle_t type.
24030 if (!findOMPAllocatorHandleT(*this, StartLoc
, DSAStack
))
24032 // OpenMP [2.12.5, target Construct]
24033 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
24036 [](const UsesAllocatorsData
&D
) { return D
.AllocatorTraits
; }) &&
24037 !findOMPAlloctraitT(*this, StartLoc
, DSAStack
))
24039 llvm::SmallPtrSet
<CanonicalDeclPtr
<Decl
>, 4> PredefinedAllocators
;
24040 for (int I
= 0; I
< OMPAllocateDeclAttr::OMPUserDefinedMemAlloc
; ++I
) {
24041 auto AllocatorKind
= static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I
);
24042 StringRef Allocator
=
24043 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind
);
24044 DeclarationName AllocatorName
= &Context
.Idents
.get(Allocator
);
24045 PredefinedAllocators
.insert(LookupSingleName(
24046 TUScope
, AllocatorName
, StartLoc
, Sema::LookupAnyName
));
24049 SmallVector
<OMPUsesAllocatorsClause::Data
, 4> NewData
;
24050 for (const UsesAllocatorsData
&D
: Data
) {
24051 Expr
*AllocatorExpr
= nullptr;
24052 // Check allocator expression.
24053 if (D
.Allocator
->isTypeDependent()) {
24054 AllocatorExpr
= D
.Allocator
;
24056 // Traits were specified - need to assign new allocator to the specified
24057 // allocator, so it must be an lvalue.
24058 AllocatorExpr
= D
.Allocator
->IgnoreParenImpCasts();
24059 auto *DRE
= dyn_cast
<DeclRefExpr
>(AllocatorExpr
);
24060 bool IsPredefinedAllocator
= false;
24062 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy
=
24063 getAllocatorKind(*this, DSAStack
, AllocatorExpr
);
24064 IsPredefinedAllocator
=
24066 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc
;
24068 QualType OMPAllocatorHandleT
= DSAStack
->getOMPAllocatorHandleT();
24069 QualType AllocatorExprType
= AllocatorExpr
->getType();
24070 bool IsTypeCompatible
= IsPredefinedAllocator
;
24071 IsTypeCompatible
= IsTypeCompatible
||
24072 Context
.hasSameUnqualifiedType(AllocatorExprType
,
24073 OMPAllocatorHandleT
);
24075 IsTypeCompatible
||
24076 Context
.typesAreCompatible(AllocatorExprType
, OMPAllocatorHandleT
);
24077 bool IsNonConstantLValue
=
24078 !AllocatorExprType
.isConstant(Context
) && AllocatorExpr
->isLValue();
24079 if (!DRE
|| !IsTypeCompatible
||
24080 (!IsPredefinedAllocator
&& !IsNonConstantLValue
)) {
24081 Diag(D
.Allocator
->getExprLoc(), diag::err_omp_var_expected
)
24082 << "omp_allocator_handle_t" << (DRE
? 1 : 0)
24083 << AllocatorExpr
->getType() << D
.Allocator
->getSourceRange();
24086 // OpenMP [2.12.5, target Construct]
24087 // Predefined allocators appearing in a uses_allocators clause cannot have
24088 // traits specified.
24089 if (IsPredefinedAllocator
&& D
.AllocatorTraits
) {
24090 Diag(D
.AllocatorTraits
->getExprLoc(),
24091 diag::err_omp_predefined_allocator_with_traits
)
24092 << D
.AllocatorTraits
->getSourceRange();
24093 Diag(D
.Allocator
->getExprLoc(), diag::note_omp_predefined_allocator
)
24094 << cast
<NamedDecl
>(DRE
->getDecl())->getName()
24095 << D
.Allocator
->getSourceRange();
24098 // OpenMP [2.12.5, target Construct]
24099 // Non-predefined allocators appearing in a uses_allocators clause must
24100 // have traits specified.
24101 if (!IsPredefinedAllocator
&& !D
.AllocatorTraits
) {
24102 Diag(D
.Allocator
->getExprLoc(),
24103 diag::err_omp_nonpredefined_allocator_without_traits
);
24106 // No allocator traits - just convert it to rvalue.
24107 if (!D
.AllocatorTraits
)
24108 AllocatorExpr
= DefaultLvalueConversion(AllocatorExpr
).get();
24109 DSAStack
->addUsesAllocatorsDecl(
24111 IsPredefinedAllocator
24112 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
24113 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator
);
24115 Expr
*AllocatorTraitsExpr
= nullptr;
24116 if (D
.AllocatorTraits
) {
24117 if (D
.AllocatorTraits
->isTypeDependent()) {
24118 AllocatorTraitsExpr
= D
.AllocatorTraits
;
24120 // OpenMP [2.12.5, target Construct]
24121 // Arrays that contain allocator traits that appear in a uses_allocators
24122 // clause must be constant arrays, have constant values and be defined
24123 // in the same scope as the construct in which the clause appears.
24124 AllocatorTraitsExpr
= D
.AllocatorTraits
->IgnoreParenImpCasts();
24125 // Check that traits expr is a constant array.
24127 if (const ArrayType
*Ty
=
24128 AllocatorTraitsExpr
->getType()->getAsArrayTypeUnsafe())
24129 if (const auto *ConstArrayTy
= dyn_cast
<ConstantArrayType
>(Ty
))
24130 TraitTy
= ConstArrayTy
->getElementType();
24131 if (TraitTy
.isNull() ||
24132 !(Context
.hasSameUnqualifiedType(TraitTy
,
24133 DSAStack
->getOMPAlloctraitT()) ||
24134 Context
.typesAreCompatible(TraitTy
, DSAStack
->getOMPAlloctraitT(),
24135 /*CompareUnqualified=*/true))) {
24136 Diag(D
.AllocatorTraits
->getExprLoc(),
24137 diag::err_omp_expected_array_alloctraits
)
24138 << AllocatorTraitsExpr
->getType();
24141 // Do not map by default allocator traits if it is a standalone
24143 if (auto *DRE
= dyn_cast
<DeclRefExpr
>(AllocatorTraitsExpr
))
24144 DSAStack
->addUsesAllocatorsDecl(
24146 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait
);
24149 OMPUsesAllocatorsClause::Data
&NewD
= NewData
.emplace_back();
24150 NewD
.Allocator
= AllocatorExpr
;
24151 NewD
.AllocatorTraits
= AllocatorTraitsExpr
;
24152 NewD
.LParenLoc
= D
.LParenLoc
;
24153 NewD
.RParenLoc
= D
.RParenLoc
;
24155 return OMPUsesAllocatorsClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
,
24159 OMPClause
*Sema::ActOnOpenMPAffinityClause(
24160 SourceLocation StartLoc
, SourceLocation LParenLoc
, SourceLocation ColonLoc
,
24161 SourceLocation EndLoc
, Expr
*Modifier
, ArrayRef
<Expr
*> Locators
) {
24162 SmallVector
<Expr
*, 8> Vars
;
24163 for (Expr
*RefExpr
: Locators
) {
24164 assert(RefExpr
&& "NULL expr in OpenMP shared clause.");
24165 if (isa
<DependentScopeDeclRefExpr
>(RefExpr
) || RefExpr
->isTypeDependent()) {
24166 // It will be analyzed later.
24167 Vars
.push_back(RefExpr
);
24171 SourceLocation ELoc
= RefExpr
->getExprLoc();
24172 Expr
*SimpleExpr
= RefExpr
->IgnoreParenImpCasts();
24174 if (!SimpleExpr
->isLValue()) {
24175 Diag(ELoc
, diag::err_omp_expected_addressable_lvalue_or_array_item
)
24176 << 1 << 0 << RefExpr
->getSourceRange();
24182 Sema::TentativeAnalysisScope
Trap(*this);
24183 Res
= CreateBuiltinUnaryOp(ELoc
, UO_AddrOf
, SimpleExpr
);
24185 if (!Res
.isUsable() && !isa
<OMPArraySectionExpr
>(SimpleExpr
) &&
24186 !isa
<OMPArrayShapingExpr
>(SimpleExpr
)) {
24187 Diag(ELoc
, diag::err_omp_expected_addressable_lvalue_or_array_item
)
24188 << 1 << 0 << RefExpr
->getSourceRange();
24191 Vars
.push_back(SimpleExpr
);
24194 return OMPAffinityClause::Create(Context
, StartLoc
, LParenLoc
, ColonLoc
,
24195 EndLoc
, Modifier
, Vars
);
24198 OMPClause
*Sema::ActOnOpenMPBindClause(OpenMPBindClauseKind Kind
,
24199 SourceLocation KindLoc
,
24200 SourceLocation StartLoc
,
24201 SourceLocation LParenLoc
,
24202 SourceLocation EndLoc
) {
24203 if (Kind
== OMPC_BIND_unknown
) {
24204 Diag(KindLoc
, diag::err_omp_unexpected_clause_value
)
24205 << getListOfPossibleValues(OMPC_bind
, /*First=*/0,
24206 /*Last=*/unsigned(OMPC_BIND_unknown
))
24207 << getOpenMPClauseName(OMPC_bind
);
24211 return OMPBindClause::Create(Context
, Kind
, KindLoc
, StartLoc
, LParenLoc
,
24215 OMPClause
*Sema::ActOnOpenMPXDynCGroupMemClause(Expr
*Size
,
24216 SourceLocation StartLoc
,
24217 SourceLocation LParenLoc
,
24218 SourceLocation EndLoc
) {
24219 Expr
*ValExpr
= Size
;
24220 Stmt
*HelperValStmt
= nullptr;
24222 // OpenMP [2.5, Restrictions]
24223 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
24225 if (!isNonNegativeIntegerValue(ValExpr
, *this, OMPC_ompx_dyn_cgroup_mem
,
24226 /*StrictlyPositive=*/false))
24229 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
24230 OpenMPDirectiveKind CaptureRegion
= getOpenMPCaptureRegionForClause(
24231 DKind
, OMPC_ompx_dyn_cgroup_mem
, LangOpts
.OpenMP
);
24232 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
24233 ValExpr
= MakeFullExpr(ValExpr
).get();
24234 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
24235 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
24236 HelperValStmt
= buildPreInits(Context
, Captures
);
24239 return new (Context
) OMPXDynCGroupMemClause(
24240 ValExpr
, HelperValStmt
, CaptureRegion
, StartLoc
, LParenLoc
, EndLoc
);
24243 OMPClause
*Sema::ActOnOpenMPDoacrossClause(
24244 OpenMPDoacrossClauseModifier DepType
, SourceLocation DepLoc
,
24245 SourceLocation ColonLoc
, ArrayRef
<Expr
*> VarList
, SourceLocation StartLoc
,
24246 SourceLocation LParenLoc
, SourceLocation EndLoc
) {
24248 if (DSAStack
->getCurrentDirective() == OMPD_ordered
&&
24249 DepType
!= OMPC_DOACROSS_source
&& DepType
!= OMPC_DOACROSS_sink
&&
24250 DepType
!= OMPC_DOACROSS_sink_omp_cur_iteration
&&
24251 DepType
!= OMPC_DOACROSS_source_omp_cur_iteration
&&
24252 DepType
!= OMPC_DOACROSS_source
) {
24253 Diag(DepLoc
, diag::err_omp_unexpected_clause_value
)
24254 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_doacross
);
24258 SmallVector
<Expr
*, 8> Vars
;
24259 DSAStackTy::OperatorOffsetTy OpsOffs
;
24260 llvm::APSInt
TotalDepCount(/*BitWidth=*/32);
24261 DoacrossDataInfoTy VarOffset
= ProcessOpenMPDoacrossClauseCommon(
24263 DepType
== OMPC_DOACROSS_source
||
24264 DepType
== OMPC_DOACROSS_source_omp_cur_iteration
||
24265 DepType
== OMPC_DOACROSS_sink_omp_cur_iteration
,
24266 VarList
, DSAStack
, EndLoc
);
24267 Vars
= VarOffset
.Vars
;
24268 OpsOffs
= VarOffset
.OpsOffs
;
24269 TotalDepCount
= VarOffset
.TotalDepCount
;
24270 auto *C
= OMPDoacrossClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
,
24271 DepType
, DepLoc
, ColonLoc
, Vars
,
24272 TotalDepCount
.getZExtValue());
24273 if (DSAStack
->isParentOrderedRegion())
24274 DSAStack
->addDoacrossDependClause(C
, OpsOffs
);
24278 OMPClause
*Sema::ActOnOpenMPXAttributeClause(ArrayRef
<const Attr
*> Attrs
,
24279 SourceLocation StartLoc
,
24280 SourceLocation LParenLoc
,
24281 SourceLocation EndLoc
) {
24282 return new (Context
) OMPXAttributeClause(Attrs
, StartLoc
, LParenLoc
, EndLoc
);