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::is_contained(Top
->IteratorVarDecls
, VD
->getCanonicalDecl());
1192 /// get captured field from ImplicitDefaultFirstprivateFDs
1193 VarDecl
*getImplicitFDCapExprDecl(const FieldDecl
*FD
) const {
1194 const_iterator I
= begin();
1195 const_iterator EndI
= end();
1196 size_t StackLevel
= getStackSize();
1197 for (; I
!= EndI
; ++I
) {
1198 if (I
->DefaultAttr
== DSA_firstprivate
|| I
->DefaultAttr
== DSA_private
)
1202 assert((StackLevel
> 0 && I
!= EndI
) || (StackLevel
== 0 && I
== EndI
));
1205 for (const auto &IFD
: I
->ImplicitDefaultFirstprivateFDs
)
1206 if (IFD
.FD
== FD
&& IFD
.StackLevel
== StackLevel
)
1210 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
1211 bool isImplicitDefaultFirstprivateFD(VarDecl
*VD
) const {
1212 const_iterator I
= begin();
1213 const_iterator EndI
= end();
1214 for (; I
!= EndI
; ++I
)
1215 if (I
->DefaultAttr
== DSA_firstprivate
|| I
->DefaultAttr
== DSA_private
)
1219 for (const auto &IFD
: I
->ImplicitDefaultFirstprivateFDs
)
1224 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
1225 void addImplicitDefaultFirstprivateFD(const FieldDecl
*FD
, VarDecl
*VD
) {
1226 iterator I
= begin();
1227 const_iterator EndI
= end();
1228 size_t StackLevel
= getStackSize();
1229 for (; I
!= EndI
; ++I
) {
1230 if (I
->DefaultAttr
== DSA_private
|| I
->DefaultAttr
== DSA_firstprivate
) {
1231 I
->ImplicitDefaultFirstprivateFDs
.emplace_back(FD
, StackLevel
, VD
);
1236 assert((StackLevel
> 0 && I
!= EndI
) || (StackLevel
== 0 && I
== EndI
));
1240 bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind
) {
1241 return isOpenMPParallelDirective(DKind
) || isOpenMPTeamsDirective(DKind
);
1244 bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind
) {
1245 return isImplicitTaskingRegion(DKind
) || isOpenMPTaskingDirective(DKind
) ||
1246 DKind
== OMPD_unknown
;
1251 static const Expr
*getExprAsWritten(const Expr
*E
) {
1252 if (const auto *FE
= dyn_cast
<FullExpr
>(E
))
1253 E
= FE
->getSubExpr();
1255 if (const auto *MTE
= dyn_cast
<MaterializeTemporaryExpr
>(E
))
1256 E
= MTE
->getSubExpr();
1258 while (const auto *Binder
= dyn_cast
<CXXBindTemporaryExpr
>(E
))
1259 E
= Binder
->getSubExpr();
1261 if (const auto *ICE
= dyn_cast
<ImplicitCastExpr
>(E
))
1262 E
= ICE
->getSubExprAsWritten();
1263 return E
->IgnoreParens();
1266 static Expr
*getExprAsWritten(Expr
*E
) {
1267 return const_cast<Expr
*>(getExprAsWritten(const_cast<const Expr
*>(E
)));
1270 static const ValueDecl
*getCanonicalDecl(const ValueDecl
*D
) {
1271 if (const auto *CED
= dyn_cast
<OMPCapturedExprDecl
>(D
))
1272 if (const auto *ME
= dyn_cast
<MemberExpr
>(getExprAsWritten(CED
->getInit())))
1273 D
= ME
->getMemberDecl();
1274 const auto *VD
= dyn_cast
<VarDecl
>(D
);
1275 const auto *FD
= dyn_cast
<FieldDecl
>(D
);
1276 if (VD
!= nullptr) {
1277 VD
= VD
->getCanonicalDecl();
1281 FD
= FD
->getCanonicalDecl();
1287 static ValueDecl
*getCanonicalDecl(ValueDecl
*D
) {
1288 return const_cast<ValueDecl
*>(
1289 getCanonicalDecl(const_cast<const ValueDecl
*>(D
)));
1292 DSAStackTy::DSAVarData
DSAStackTy::getDSA(const_iterator
&Iter
,
1293 ValueDecl
*D
) const {
1294 D
= getCanonicalDecl(D
);
1295 auto *VD
= dyn_cast
<VarDecl
>(D
);
1296 const auto *FD
= dyn_cast
<FieldDecl
>(D
);
1298 if (Iter
== end()) {
1299 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1300 // in a region but not in construct]
1301 // File-scope or namespace-scope variables referenced in called routines
1302 // in the region are shared unless they appear in a threadprivate
1304 if (VD
&& !VD
->isFunctionOrMethodVarDecl() && !isa
<ParmVarDecl
>(VD
))
1305 DVar
.CKind
= OMPC_shared
;
1307 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1308 // in a region but not in construct]
1309 // Variables with static storage duration that are declared in called
1310 // routines in the region are shared.
1311 if (VD
&& VD
->hasGlobalStorage())
1312 DVar
.CKind
= OMPC_shared
;
1314 // Non-static data members are shared by default.
1316 DVar
.CKind
= OMPC_shared
;
1321 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1322 // in a Construct, C/C++, predetermined, p.1]
1323 // Variables with automatic storage duration that are declared in a scope
1324 // inside the construct are private.
1325 if (VD
&& isOpenMPLocal(VD
, Iter
) && VD
->isLocalVarDecl() &&
1326 (VD
->getStorageClass() == SC_Auto
|| VD
->getStorageClass() == SC_None
)) {
1327 DVar
.CKind
= OMPC_private
;
1331 DVar
.DKind
= Iter
->Directive
;
1332 // Explicitly specified attributes and local variables with predetermined
1334 if (Iter
->SharingMap
.count(D
)) {
1335 const DSAInfo
&Data
= Iter
->SharingMap
.lookup(D
);
1336 DVar
.RefExpr
= Data
.RefExpr
.getPointer();
1337 DVar
.PrivateCopy
= Data
.PrivateCopy
;
1338 DVar
.CKind
= Data
.Attributes
;
1339 DVar
.ImplicitDSALoc
= Iter
->DefaultAttrLoc
;
1340 DVar
.Modifier
= Data
.Modifier
;
1341 DVar
.AppliedToPointee
= Data
.AppliedToPointee
;
1345 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1346 // in a Construct, C/C++, implicitly determined, p.1]
1347 // In a parallel or task construct, the data-sharing attributes of these
1348 // variables are determined by the default clause, if present.
1349 switch (Iter
->DefaultAttr
) {
1351 DVar
.CKind
= OMPC_shared
;
1352 DVar
.ImplicitDSALoc
= Iter
->DefaultAttrLoc
;
1356 case DSA_firstprivate
:
1357 if (VD
&& VD
->getStorageDuration() == SD_Static
&&
1358 VD
->getDeclContext()->isFileContext()) {
1359 DVar
.CKind
= OMPC_unknown
;
1361 DVar
.CKind
= OMPC_firstprivate
;
1363 DVar
.ImplicitDSALoc
= Iter
->DefaultAttrLoc
;
1366 // each variable with static storage duration that is declared
1367 // in a namespace or global scope and referenced in the construct,
1368 // and that does not have a predetermined data-sharing attribute
1369 if (VD
&& VD
->getStorageDuration() == SD_Static
&&
1370 VD
->getDeclContext()->isFileContext()) {
1371 DVar
.CKind
= OMPC_unknown
;
1373 DVar
.CKind
= OMPC_private
;
1375 DVar
.ImplicitDSALoc
= Iter
->DefaultAttrLoc
;
1377 case DSA_unspecified
:
1378 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1379 // in a Construct, implicitly determined, p.2]
1380 // In a parallel construct, if no default clause is present, these
1381 // variables are shared.
1382 DVar
.ImplicitDSALoc
= Iter
->DefaultAttrLoc
;
1383 if ((isOpenMPParallelDirective(DVar
.DKind
) &&
1384 !isOpenMPTaskLoopDirective(DVar
.DKind
)) ||
1385 isOpenMPTeamsDirective(DVar
.DKind
)) {
1386 DVar
.CKind
= OMPC_shared
;
1390 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1391 // in a Construct, implicitly determined, p.4]
1392 // In a task construct, if no default clause is present, a variable that in
1393 // the enclosing context is determined to be shared by all implicit tasks
1394 // bound to the current team is shared.
1395 if (isOpenMPTaskingDirective(DVar
.DKind
)) {
1396 DSAVarData DVarTemp
;
1397 const_iterator I
= Iter
, E
= end();
1400 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1401 // Referenced in a Construct, implicitly determined, p.6]
1402 // In a task construct, if no default clause is present, a variable
1403 // whose data-sharing attribute is not determined by the rules above is
1405 DVarTemp
= getDSA(I
, D
);
1406 if (DVarTemp
.CKind
!= OMPC_shared
) {
1407 DVar
.RefExpr
= nullptr;
1408 DVar
.CKind
= OMPC_firstprivate
;
1411 } while (I
!= E
&& !isImplicitTaskingRegion(I
->Directive
));
1413 (DVarTemp
.CKind
== OMPC_unknown
) ? OMPC_firstprivate
: OMPC_shared
;
1417 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1418 // in a Construct, implicitly determined, p.3]
1419 // For constructs other than task, if no default clause is present, these
1420 // variables inherit their data-sharing attributes from the enclosing
1422 return getDSA(++Iter
, D
);
1425 const Expr
*DSAStackTy::addUniqueAligned(const ValueDecl
*D
,
1426 const Expr
*NewDE
) {
1427 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1428 D
= getCanonicalDecl(D
);
1429 SharingMapTy
&StackElem
= getTopOfStack();
1430 auto It
= StackElem
.AlignedMap
.find(D
);
1431 if (It
== StackElem
.AlignedMap
.end()) {
1432 assert(NewDE
&& "Unexpected nullptr expr to be added into aligned map");
1433 StackElem
.AlignedMap
[D
] = NewDE
;
1436 assert(It
->second
&& "Unexpected nullptr expr in the aligned map");
1440 const Expr
*DSAStackTy::addUniqueNontemporal(const ValueDecl
*D
,
1441 const Expr
*NewDE
) {
1442 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1443 D
= getCanonicalDecl(D
);
1444 SharingMapTy
&StackElem
= getTopOfStack();
1445 auto It
= StackElem
.NontemporalMap
.find(D
);
1446 if (It
== StackElem
.NontemporalMap
.end()) {
1447 assert(NewDE
&& "Unexpected nullptr expr to be added into aligned map");
1448 StackElem
.NontemporalMap
[D
] = NewDE
;
1451 assert(It
->second
&& "Unexpected nullptr expr in the aligned map");
1455 void DSAStackTy::addLoopControlVariable(const ValueDecl
*D
, VarDecl
*Capture
) {
1456 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1457 D
= getCanonicalDecl(D
);
1458 SharingMapTy
&StackElem
= getTopOfStack();
1459 StackElem
.LCVMap
.try_emplace(
1460 D
, LCDeclInfo(StackElem
.LCVMap
.size() + 1, Capture
));
1463 const DSAStackTy::LCDeclInfo
1464 DSAStackTy::isLoopControlVariable(const ValueDecl
*D
) const {
1465 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1466 D
= getCanonicalDecl(D
);
1467 const SharingMapTy
&StackElem
= getTopOfStack();
1468 auto It
= StackElem
.LCVMap
.find(D
);
1469 if (It
!= StackElem
.LCVMap
.end())
1471 return {0, nullptr};
1474 const DSAStackTy::LCDeclInfo
1475 DSAStackTy::isLoopControlVariable(const ValueDecl
*D
, unsigned Level
) const {
1476 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1477 D
= getCanonicalDecl(D
);
1478 for (unsigned I
= Level
+ 1; I
> 0; --I
) {
1479 const SharingMapTy
&StackElem
= getStackElemAtLevel(I
- 1);
1480 auto It
= StackElem
.LCVMap
.find(D
);
1481 if (It
!= StackElem
.LCVMap
.end())
1484 return {0, nullptr};
1487 const DSAStackTy::LCDeclInfo
1488 DSAStackTy::isParentLoopControlVariable(const ValueDecl
*D
) const {
1489 const SharingMapTy
*Parent
= getSecondOnStackOrNull();
1490 assert(Parent
&& "Data-sharing attributes stack is empty");
1491 D
= getCanonicalDecl(D
);
1492 auto It
= Parent
->LCVMap
.find(D
);
1493 if (It
!= Parent
->LCVMap
.end())
1495 return {0, nullptr};
1498 const ValueDecl
*DSAStackTy::getParentLoopControlVariable(unsigned I
) const {
1499 const SharingMapTy
*Parent
= getSecondOnStackOrNull();
1500 assert(Parent
&& "Data-sharing attributes stack is empty");
1501 if (Parent
->LCVMap
.size() < I
)
1503 for (const auto &Pair
: Parent
->LCVMap
)
1504 if (Pair
.second
.first
== I
)
1509 void DSAStackTy::addDSA(const ValueDecl
*D
, const Expr
*E
, OpenMPClauseKind A
,
1510 DeclRefExpr
*PrivateCopy
, unsigned Modifier
,
1511 bool AppliedToPointee
) {
1512 D
= getCanonicalDecl(D
);
1513 if (A
== OMPC_threadprivate
) {
1514 DSAInfo
&Data
= Threadprivates
[D
];
1515 Data
.Attributes
= A
;
1516 Data
.RefExpr
.setPointer(E
);
1517 Data
.PrivateCopy
= nullptr;
1518 Data
.Modifier
= Modifier
;
1520 DSAInfo
&Data
= getTopOfStack().SharingMap
[D
];
1521 assert(Data
.Attributes
== OMPC_unknown
|| (A
== Data
.Attributes
) ||
1522 (A
== OMPC_firstprivate
&& Data
.Attributes
== OMPC_lastprivate
) ||
1523 (A
== OMPC_lastprivate
&& Data
.Attributes
== OMPC_firstprivate
) ||
1524 (isLoopControlVariable(D
).first
&& A
== OMPC_private
));
1525 Data
.Modifier
= Modifier
;
1526 if (A
== OMPC_lastprivate
&& Data
.Attributes
== OMPC_firstprivate
) {
1527 Data
.RefExpr
.setInt(/*IntVal=*/true);
1530 const bool IsLastprivate
=
1531 A
== OMPC_lastprivate
|| Data
.Attributes
== OMPC_lastprivate
;
1532 Data
.Attributes
= A
;
1533 Data
.RefExpr
.setPointerAndInt(E
, IsLastprivate
);
1534 Data
.PrivateCopy
= PrivateCopy
;
1535 Data
.AppliedToPointee
= AppliedToPointee
;
1537 DSAInfo
&Data
= getTopOfStack().SharingMap
[PrivateCopy
->getDecl()];
1538 Data
.Modifier
= Modifier
;
1539 Data
.Attributes
= A
;
1540 Data
.RefExpr
.setPointerAndInt(PrivateCopy
, IsLastprivate
);
1541 Data
.PrivateCopy
= nullptr;
1542 Data
.AppliedToPointee
= AppliedToPointee
;
1547 /// Build a variable declaration for OpenMP loop iteration variable.
1548 static VarDecl
*buildVarDecl(Sema
&SemaRef
, SourceLocation Loc
, QualType Type
,
1549 StringRef Name
, const AttrVec
*Attrs
= nullptr,
1550 DeclRefExpr
*OrigRef
= nullptr) {
1551 DeclContext
*DC
= SemaRef
.CurContext
;
1552 IdentifierInfo
*II
= &SemaRef
.PP
.getIdentifierTable().get(Name
);
1553 TypeSourceInfo
*TInfo
= SemaRef
.Context
.getTrivialTypeSourceInfo(Type
, Loc
);
1555 VarDecl::Create(SemaRef
.Context
, DC
, Loc
, Loc
, II
, Type
, TInfo
, SC_None
);
1557 for (specific_attr_iterator
<AlignedAttr
> I(Attrs
->begin()), E(Attrs
->end());
1561 Decl
->setImplicit();
1564 OMPReferencedVarAttr::CreateImplicit(SemaRef
.Context
, OrigRef
));
1569 static DeclRefExpr
*buildDeclRefExpr(Sema
&S
, VarDecl
*D
, QualType Ty
,
1571 bool RefersToCapture
= false) {
1573 D
->markUsed(S
.Context
);
1574 return DeclRefExpr::Create(S
.getASTContext(), NestedNameSpecifierLoc(),
1575 SourceLocation(), D
, RefersToCapture
, Loc
, Ty
,
1579 void DSAStackTy::addTaskgroupReductionData(const ValueDecl
*D
, SourceRange SR
,
1580 BinaryOperatorKind BOK
) {
1581 D
= getCanonicalDecl(D
);
1582 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1584 getTopOfStack().SharingMap
[D
].Attributes
== OMPC_reduction
&&
1585 "Additional reduction info may be specified only for reduction items.");
1586 ReductionData
&ReductionData
= getTopOfStack().ReductionMap
[D
];
1587 assert(ReductionData
.ReductionRange
.isInvalid() &&
1588 (getTopOfStack().Directive
== OMPD_taskgroup
||
1589 ((isOpenMPParallelDirective(getTopOfStack().Directive
) ||
1590 isOpenMPWorksharingDirective(getTopOfStack().Directive
)) &&
1591 !isOpenMPSimdDirective(getTopOfStack().Directive
))) &&
1592 "Additional reduction info may be specified only once for reduction "
1594 ReductionData
.set(BOK
, SR
);
1595 Expr
*&TaskgroupReductionRef
= getTopOfStack().TaskgroupReductionRef
;
1596 if (!TaskgroupReductionRef
) {
1597 VarDecl
*VD
= buildVarDecl(SemaRef
, SR
.getBegin(),
1598 SemaRef
.Context
.VoidPtrTy
, ".task_red.");
1599 TaskgroupReductionRef
=
1600 buildDeclRefExpr(SemaRef
, VD
, SemaRef
.Context
.VoidPtrTy
, SR
.getBegin());
1604 void DSAStackTy::addTaskgroupReductionData(const ValueDecl
*D
, SourceRange SR
,
1605 const Expr
*ReductionRef
) {
1606 D
= getCanonicalDecl(D
);
1607 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1609 getTopOfStack().SharingMap
[D
].Attributes
== OMPC_reduction
&&
1610 "Additional reduction info may be specified only for reduction items.");
1611 ReductionData
&ReductionData
= getTopOfStack().ReductionMap
[D
];
1612 assert(ReductionData
.ReductionRange
.isInvalid() &&
1613 (getTopOfStack().Directive
== OMPD_taskgroup
||
1614 ((isOpenMPParallelDirective(getTopOfStack().Directive
) ||
1615 isOpenMPWorksharingDirective(getTopOfStack().Directive
)) &&
1616 !isOpenMPSimdDirective(getTopOfStack().Directive
))) &&
1617 "Additional reduction info may be specified only once for reduction "
1619 ReductionData
.set(ReductionRef
, SR
);
1620 Expr
*&TaskgroupReductionRef
= getTopOfStack().TaskgroupReductionRef
;
1621 if (!TaskgroupReductionRef
) {
1622 VarDecl
*VD
= buildVarDecl(SemaRef
, SR
.getBegin(),
1623 SemaRef
.Context
.VoidPtrTy
, ".task_red.");
1624 TaskgroupReductionRef
=
1625 buildDeclRefExpr(SemaRef
, VD
, SemaRef
.Context
.VoidPtrTy
, SR
.getBegin());
1629 const DSAStackTy::DSAVarData
DSAStackTy::getTopMostTaskgroupReductionData(
1630 const ValueDecl
*D
, SourceRange
&SR
, BinaryOperatorKind
&BOK
,
1631 Expr
*&TaskgroupDescriptor
) const {
1632 D
= getCanonicalDecl(D
);
1633 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1634 for (const_iterator I
= begin() + 1, E
= end(); I
!= E
; ++I
) {
1635 const DSAInfo
&Data
= I
->SharingMap
.lookup(D
);
1636 if (Data
.Attributes
!= OMPC_reduction
||
1637 Data
.Modifier
!= OMPC_REDUCTION_task
)
1639 const ReductionData
&ReductionData
= I
->ReductionMap
.lookup(D
);
1640 if (!ReductionData
.ReductionOp
||
1641 ReductionData
.ReductionOp
.is
<const Expr
*>())
1642 return DSAVarData();
1643 SR
= ReductionData
.ReductionRange
;
1644 BOK
= ReductionData
.ReductionOp
.get
<ReductionData::BOKPtrType
>();
1645 assert(I
->TaskgroupReductionRef
&& "taskgroup reduction reference "
1646 "expression for the descriptor is not "
1648 TaskgroupDescriptor
= I
->TaskgroupReductionRef
;
1649 return DSAVarData(I
->Directive
, OMPC_reduction
, Data
.RefExpr
.getPointer(),
1650 Data
.PrivateCopy
, I
->DefaultAttrLoc
, OMPC_REDUCTION_task
,
1651 /*AppliedToPointee=*/false);
1653 return DSAVarData();
1656 const DSAStackTy::DSAVarData
DSAStackTy::getTopMostTaskgroupReductionData(
1657 const ValueDecl
*D
, SourceRange
&SR
, const Expr
*&ReductionRef
,
1658 Expr
*&TaskgroupDescriptor
) const {
1659 D
= getCanonicalDecl(D
);
1660 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1661 for (const_iterator I
= begin() + 1, E
= end(); I
!= E
; ++I
) {
1662 const DSAInfo
&Data
= I
->SharingMap
.lookup(D
);
1663 if (Data
.Attributes
!= OMPC_reduction
||
1664 Data
.Modifier
!= OMPC_REDUCTION_task
)
1666 const ReductionData
&ReductionData
= I
->ReductionMap
.lookup(D
);
1667 if (!ReductionData
.ReductionOp
||
1668 !ReductionData
.ReductionOp
.is
<const Expr
*>())
1669 return DSAVarData();
1670 SR
= ReductionData
.ReductionRange
;
1671 ReductionRef
= ReductionData
.ReductionOp
.get
<const Expr
*>();
1672 assert(I
->TaskgroupReductionRef
&& "taskgroup reduction reference "
1673 "expression for the descriptor is not "
1675 TaskgroupDescriptor
= I
->TaskgroupReductionRef
;
1676 return DSAVarData(I
->Directive
, OMPC_reduction
, Data
.RefExpr
.getPointer(),
1677 Data
.PrivateCopy
, I
->DefaultAttrLoc
, OMPC_REDUCTION_task
,
1678 /*AppliedToPointee=*/false);
1680 return DSAVarData();
1683 bool DSAStackTy::isOpenMPLocal(VarDecl
*D
, const_iterator I
) const {
1684 D
= D
->getCanonicalDecl();
1685 for (const_iterator E
= end(); I
!= E
; ++I
) {
1686 if (isImplicitOrExplicitTaskingRegion(I
->Directive
) ||
1687 isOpenMPTargetExecutionDirective(I
->Directive
)) {
1689 Scope
*TopScope
= I
->CurScope
->getParent();
1690 Scope
*CurScope
= getCurScope();
1691 while (CurScope
&& CurScope
!= TopScope
&& !CurScope
->isDeclScope(D
))
1692 CurScope
= CurScope
->getParent();
1693 return CurScope
!= TopScope
;
1695 for (DeclContext
*DC
= D
->getDeclContext(); DC
; DC
= DC
->getParent())
1696 if (I
->Context
== DC
)
1704 static bool isConstNotMutableType(Sema
&SemaRef
, QualType Type
,
1705 bool AcceptIfMutable
= true,
1706 bool *IsClassType
= nullptr) {
1707 ASTContext
&Context
= SemaRef
.getASTContext();
1708 Type
= Type
.getNonReferenceType().getCanonicalType();
1709 bool IsConstant
= Type
.isConstant(Context
);
1710 Type
= Context
.getBaseElementType(Type
);
1711 const CXXRecordDecl
*RD
= AcceptIfMutable
&& SemaRef
.getLangOpts().CPlusPlus
1712 ? Type
->getAsCXXRecordDecl()
1714 if (const auto *CTSD
= dyn_cast_or_null
<ClassTemplateSpecializationDecl
>(RD
))
1715 if (const ClassTemplateDecl
*CTD
= CTSD
->getSpecializedTemplate())
1716 RD
= CTD
->getTemplatedDecl();
1719 return IsConstant
&& !(SemaRef
.getLangOpts().CPlusPlus
&& RD
&&
1720 RD
->hasDefinition() && RD
->hasMutableFields());
1723 static bool rejectConstNotMutableType(Sema
&SemaRef
, const ValueDecl
*D
,
1724 QualType Type
, OpenMPClauseKind CKind
,
1725 SourceLocation ELoc
,
1726 bool AcceptIfMutable
= true,
1727 bool ListItemNotVar
= false) {
1728 ASTContext
&Context
= SemaRef
.getASTContext();
1730 if (isConstNotMutableType(SemaRef
, Type
, AcceptIfMutable
, &IsClassType
)) {
1731 unsigned Diag
= ListItemNotVar
? diag::err_omp_const_list_item
1732 : IsClassType
? diag::err_omp_const_not_mutable_variable
1733 : diag::err_omp_const_variable
;
1734 SemaRef
.Diag(ELoc
, Diag
) << getOpenMPClauseName(CKind
);
1735 if (!ListItemNotVar
&& D
) {
1736 const VarDecl
*VD
= dyn_cast
<VarDecl
>(D
);
1737 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
1738 VarDecl::DeclarationOnly
;
1739 SemaRef
.Diag(D
->getLocation(),
1740 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
1748 const DSAStackTy::DSAVarData
DSAStackTy::getTopDSA(ValueDecl
*D
,
1750 D
= getCanonicalDecl(D
);
1753 auto *VD
= dyn_cast
<VarDecl
>(D
);
1754 auto TI
= Threadprivates
.find(D
);
1755 if (TI
!= Threadprivates
.end()) {
1756 DVar
.RefExpr
= TI
->getSecond().RefExpr
.getPointer();
1757 DVar
.CKind
= OMPC_threadprivate
;
1758 DVar
.Modifier
= TI
->getSecond().Modifier
;
1761 if (VD
&& VD
->hasAttr
<OMPThreadPrivateDeclAttr
>()) {
1762 DVar
.RefExpr
= buildDeclRefExpr(
1763 SemaRef
, VD
, D
->getType().getNonReferenceType(),
1764 VD
->getAttr
<OMPThreadPrivateDeclAttr
>()->getLocation());
1765 DVar
.CKind
= OMPC_threadprivate
;
1766 addDSA(D
, DVar
.RefExpr
, OMPC_threadprivate
);
1769 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1770 // in a Construct, C/C++, predetermined, p.1]
1771 // Variables appearing in threadprivate directives are threadprivate.
1772 if ((VD
&& VD
->getTLSKind() != VarDecl::TLS_None
&&
1773 !(VD
->hasAttr
<OMPThreadPrivateDeclAttr
>() &&
1774 SemaRef
.getLangOpts().OpenMPUseTLS
&&
1775 SemaRef
.getASTContext().getTargetInfo().isTLSSupported())) ||
1776 (VD
&& VD
->getStorageClass() == SC_Register
&&
1777 VD
->hasAttr
<AsmLabelAttr
>() && !VD
->isLocalVarDecl())) {
1778 DVar
.RefExpr
= buildDeclRefExpr(
1779 SemaRef
, VD
, D
->getType().getNonReferenceType(), D
->getLocation());
1780 DVar
.CKind
= OMPC_threadprivate
;
1781 addDSA(D
, DVar
.RefExpr
, OMPC_threadprivate
);
1784 if (SemaRef
.getLangOpts().OpenMPCUDAMode
&& VD
&&
1785 VD
->isLocalVarDeclOrParm() && !isStackEmpty() &&
1786 !isLoopControlVariable(D
).first
) {
1787 const_iterator IterTarget
=
1788 std::find_if(begin(), end(), [](const SharingMapTy
&Data
) {
1789 return isOpenMPTargetExecutionDirective(Data
.Directive
);
1791 if (IterTarget
!= end()) {
1792 const_iterator ParentIterTarget
= IterTarget
+ 1;
1793 for (const_iterator Iter
= begin(); Iter
!= ParentIterTarget
; ++Iter
) {
1794 if (isOpenMPLocal(VD
, Iter
)) {
1796 buildDeclRefExpr(SemaRef
, VD
, D
->getType().getNonReferenceType(),
1798 DVar
.CKind
= OMPC_threadprivate
;
1802 if (!isClauseParsingMode() || IterTarget
!= begin()) {
1803 auto DSAIter
= IterTarget
->SharingMap
.find(D
);
1804 if (DSAIter
!= IterTarget
->SharingMap
.end() &&
1805 isOpenMPPrivate(DSAIter
->getSecond().Attributes
)) {
1806 DVar
.RefExpr
= DSAIter
->getSecond().RefExpr
.getPointer();
1807 DVar
.CKind
= OMPC_threadprivate
;
1810 const_iterator End
= end();
1811 if (!SemaRef
.isOpenMPCapturedByRef(D
,
1812 std::distance(ParentIterTarget
, End
),
1813 /*OpenMPCaptureLevel=*/0)) {
1815 buildDeclRefExpr(SemaRef
, VD
, D
->getType().getNonReferenceType(),
1816 IterTarget
->ConstructLoc
);
1817 DVar
.CKind
= OMPC_threadprivate
;
1825 // Not in OpenMP execution region and top scope was already checked.
1828 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1829 // in a Construct, C/C++, predetermined, p.4]
1830 // Static data members are shared.
1831 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1832 // in a Construct, C/C++, predetermined, p.7]
1833 // Variables with static storage duration that are declared in a scope
1834 // inside the construct are shared.
1835 if (VD
&& VD
->isStaticDataMember()) {
1836 // Check for explicitly specified attributes.
1837 const_iterator I
= begin();
1838 const_iterator EndI
= end();
1839 if (FromParent
&& I
!= EndI
)
1842 auto It
= I
->SharingMap
.find(D
);
1843 if (It
!= I
->SharingMap
.end()) {
1844 const DSAInfo
&Data
= It
->getSecond();
1845 DVar
.RefExpr
= Data
.RefExpr
.getPointer();
1846 DVar
.PrivateCopy
= Data
.PrivateCopy
;
1847 DVar
.CKind
= Data
.Attributes
;
1848 DVar
.ImplicitDSALoc
= I
->DefaultAttrLoc
;
1849 DVar
.DKind
= I
->Directive
;
1850 DVar
.Modifier
= Data
.Modifier
;
1851 DVar
.AppliedToPointee
= Data
.AppliedToPointee
;
1856 DVar
.CKind
= OMPC_shared
;
1860 auto &&MatchesAlways
= [](OpenMPDirectiveKind
) { return true; };
1861 // The predetermined shared attribute for const-qualified types having no
1862 // mutable members was removed after OpenMP 3.1.
1863 if (SemaRef
.LangOpts
.OpenMP
<= 31) {
1864 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1865 // in a Construct, C/C++, predetermined, p.6]
1866 // Variables with const qualified type having no mutable member are
1868 if (isConstNotMutableType(SemaRef
, D
->getType())) {
1869 // Variables with const-qualified type having no mutable member may be
1870 // listed in a firstprivate clause, even if they are static data members.
1871 DSAVarData DVarTemp
= hasInnermostDSA(
1873 [](OpenMPClauseKind C
, bool) {
1874 return C
== OMPC_firstprivate
|| C
== OMPC_shared
;
1876 MatchesAlways
, FromParent
);
1877 if (DVarTemp
.CKind
!= OMPC_unknown
&& DVarTemp
.RefExpr
)
1880 DVar
.CKind
= OMPC_shared
;
1885 // Explicitly specified attributes and local variables with predetermined
1887 const_iterator I
= begin();
1888 const_iterator EndI
= end();
1889 if (FromParent
&& I
!= EndI
)
1893 auto It
= I
->SharingMap
.find(D
);
1894 if (It
!= I
->SharingMap
.end()) {
1895 const DSAInfo
&Data
= It
->getSecond();
1896 DVar
.RefExpr
= Data
.RefExpr
.getPointer();
1897 DVar
.PrivateCopy
= Data
.PrivateCopy
;
1898 DVar
.CKind
= Data
.Attributes
;
1899 DVar
.ImplicitDSALoc
= I
->DefaultAttrLoc
;
1900 DVar
.DKind
= I
->Directive
;
1901 DVar
.Modifier
= Data
.Modifier
;
1902 DVar
.AppliedToPointee
= Data
.AppliedToPointee
;
1908 const DSAStackTy::DSAVarData
DSAStackTy::getImplicitDSA(ValueDecl
*D
,
1909 bool FromParent
) const {
1910 if (isStackEmpty()) {
1912 return getDSA(I
, D
);
1914 D
= getCanonicalDecl(D
);
1915 const_iterator StartI
= begin();
1916 const_iterator EndI
= end();
1917 if (FromParent
&& StartI
!= EndI
)
1919 return getDSA(StartI
, D
);
1922 const DSAStackTy::DSAVarData
DSAStackTy::getImplicitDSA(ValueDecl
*D
,
1923 unsigned Level
) const {
1924 if (getStackSize() <= Level
)
1925 return DSAVarData();
1926 D
= getCanonicalDecl(D
);
1927 const_iterator StartI
= std::next(begin(), getStackSize() - 1 - Level
);
1928 return getDSA(StartI
, D
);
1931 const DSAStackTy::DSAVarData
1932 DSAStackTy::hasDSA(ValueDecl
*D
,
1933 const llvm::function_ref
<bool(OpenMPClauseKind
, bool,
1934 DefaultDataSharingAttributes
)>
1936 const llvm::function_ref
<bool(OpenMPDirectiveKind
)> DPred
,
1937 bool FromParent
) const {
1940 D
= getCanonicalDecl(D
);
1941 const_iterator I
= begin();
1942 const_iterator EndI
= end();
1943 if (FromParent
&& I
!= EndI
)
1945 for (; I
!= EndI
; ++I
) {
1946 if (!DPred(I
->Directive
) &&
1947 !isImplicitOrExplicitTaskingRegion(I
->Directive
))
1949 const_iterator NewI
= I
;
1950 DSAVarData DVar
= getDSA(NewI
, D
);
1951 if (I
== NewI
&& CPred(DVar
.CKind
, DVar
.AppliedToPointee
, I
->DefaultAttr
))
1957 const DSAStackTy::DSAVarData
DSAStackTy::hasInnermostDSA(
1958 ValueDecl
*D
, const llvm::function_ref
<bool(OpenMPClauseKind
, bool)> CPred
,
1959 const llvm::function_ref
<bool(OpenMPDirectiveKind
)> DPred
,
1960 bool FromParent
) const {
1963 D
= getCanonicalDecl(D
);
1964 const_iterator StartI
= begin();
1965 const_iterator EndI
= end();
1966 if (FromParent
&& StartI
!= EndI
)
1968 if (StartI
== EndI
|| !DPred(StartI
->Directive
))
1970 const_iterator NewI
= StartI
;
1971 DSAVarData DVar
= getDSA(NewI
, D
);
1972 return (NewI
== StartI
&& CPred(DVar
.CKind
, DVar
.AppliedToPointee
))
1977 bool DSAStackTy::hasExplicitDSA(
1979 const llvm::function_ref
<bool(OpenMPClauseKind
, bool)> CPred
,
1980 unsigned Level
, bool NotLastprivate
) const {
1981 if (getStackSize() <= Level
)
1983 D
= getCanonicalDecl(D
);
1984 const SharingMapTy
&StackElem
= getStackElemAtLevel(Level
);
1985 auto I
= StackElem
.SharingMap
.find(D
);
1986 if (I
!= StackElem
.SharingMap
.end() && I
->getSecond().RefExpr
.getPointer() &&
1987 CPred(I
->getSecond().Attributes
, I
->getSecond().AppliedToPointee
) &&
1988 (!NotLastprivate
|| !I
->getSecond().RefExpr
.getInt()))
1990 // Check predetermined rules for the loop control variables.
1991 auto LI
= StackElem
.LCVMap
.find(D
);
1992 if (LI
!= StackElem
.LCVMap
.end())
1993 return CPred(OMPC_private
, /*AppliedToPointee=*/false);
1997 bool DSAStackTy::hasExplicitDirective(
1998 const llvm::function_ref
<bool(OpenMPDirectiveKind
)> DPred
,
1999 unsigned Level
) const {
2000 if (getStackSize() <= Level
)
2002 const SharingMapTy
&StackElem
= getStackElemAtLevel(Level
);
2003 return DPred(StackElem
.Directive
);
2006 bool DSAStackTy::hasDirective(
2007 const llvm::function_ref
<bool(OpenMPDirectiveKind
,
2008 const DeclarationNameInfo
&, SourceLocation
)>
2010 bool FromParent
) const {
2011 // We look only in the enclosing region.
2012 size_t Skip
= FromParent
? 2 : 1;
2013 for (const_iterator I
= begin() + std::min(Skip
, getStackSize()), E
= end();
2015 if (DPred(I
->Directive
, I
->DirectiveName
, I
->ConstructLoc
))
2021 void Sema::InitDataSharingAttributesStack() {
2022 VarDataSharingAttributesStack
= new DSAStackTy(*this);
2025 #define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2027 void Sema::pushOpenMPFunctionRegion() { DSAStack
->pushFunction(); }
2029 void Sema::popOpenMPFunctionRegion(const FunctionScopeInfo
*OldFSI
) {
2030 DSAStack
->popFunction(OldFSI
);
2033 static bool isOpenMPDeviceDelayedContext(Sema
&S
) {
2034 assert(S
.LangOpts
.OpenMP
&& S
.LangOpts
.OpenMPIsTargetDevice
&&
2035 "Expected OpenMP device compilation.");
2036 return !S
.isInOpenMPTargetExecutionDirective();
2040 /// Status of the function emission on the host/device.
2041 enum class FunctionEmissionStatus
{
2046 } // anonymous namespace
2048 Sema::SemaDiagnosticBuilder
2049 Sema::diagIfOpenMPDeviceCode(SourceLocation Loc
, unsigned DiagID
,
2050 const FunctionDecl
*FD
) {
2051 assert(LangOpts
.OpenMP
&& LangOpts
.OpenMPIsTargetDevice
&&
2052 "Expected OpenMP device compilation.");
2054 SemaDiagnosticBuilder::Kind Kind
= SemaDiagnosticBuilder::K_Nop
;
2056 FunctionEmissionStatus FES
= getEmissionStatus(FD
);
2058 case FunctionEmissionStatus::Emitted
:
2059 Kind
= SemaDiagnosticBuilder::K_Immediate
;
2061 case FunctionEmissionStatus::Unknown
:
2062 // TODO: We should always delay diagnostics here in case a target
2063 // region is in a function we do not emit. However, as the
2064 // current diagnostics are associated with the function containing
2065 // the target region and we do not emit that one, we would miss out
2066 // on diagnostics for the target region itself. We need to anchor
2067 // the diagnostics with the new generated function *or* ensure we
2068 // emit diagnostics associated with the surrounding function.
2069 Kind
= isOpenMPDeviceDelayedContext(*this)
2070 ? SemaDiagnosticBuilder::K_Deferred
2071 : SemaDiagnosticBuilder::K_Immediate
;
2073 case FunctionEmissionStatus::TemplateDiscarded
:
2074 case FunctionEmissionStatus::OMPDiscarded
:
2075 Kind
= SemaDiagnosticBuilder::K_Nop
;
2077 case FunctionEmissionStatus::CUDADiscarded
:
2078 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2083 return SemaDiagnosticBuilder(Kind
, Loc
, DiagID
, FD
, *this);
2086 Sema::SemaDiagnosticBuilder
Sema::diagIfOpenMPHostCode(SourceLocation Loc
,
2088 const FunctionDecl
*FD
) {
2089 assert(LangOpts
.OpenMP
&& !LangOpts
.OpenMPIsTargetDevice
&&
2090 "Expected OpenMP host compilation.");
2092 SemaDiagnosticBuilder::Kind Kind
= SemaDiagnosticBuilder::K_Nop
;
2094 FunctionEmissionStatus FES
= getEmissionStatus(FD
);
2096 case FunctionEmissionStatus::Emitted
:
2097 Kind
= SemaDiagnosticBuilder::K_Immediate
;
2099 case FunctionEmissionStatus::Unknown
:
2100 Kind
= SemaDiagnosticBuilder::K_Deferred
;
2102 case FunctionEmissionStatus::TemplateDiscarded
:
2103 case FunctionEmissionStatus::OMPDiscarded
:
2104 case FunctionEmissionStatus::CUDADiscarded
:
2105 Kind
= SemaDiagnosticBuilder::K_Nop
;
2110 return SemaDiagnosticBuilder(Kind
, Loc
, DiagID
, FD
, *this);
2113 static OpenMPDefaultmapClauseKind
2114 getVariableCategoryFromDecl(const LangOptions
&LO
, const ValueDecl
*VD
) {
2115 if (LO
.OpenMP
<= 45) {
2116 if (VD
->getType().getNonReferenceType()->isScalarType())
2117 return OMPC_DEFAULTMAP_scalar
;
2118 return OMPC_DEFAULTMAP_aggregate
;
2120 if (VD
->getType().getNonReferenceType()->isAnyPointerType())
2121 return OMPC_DEFAULTMAP_pointer
;
2122 if (VD
->getType().getNonReferenceType()->isScalarType())
2123 return OMPC_DEFAULTMAP_scalar
;
2124 return OMPC_DEFAULTMAP_aggregate
;
2127 bool Sema::isOpenMPCapturedByRef(const ValueDecl
*D
, unsigned Level
,
2128 unsigned OpenMPCaptureLevel
) const {
2129 assert(LangOpts
.OpenMP
&& "OpenMP is not allowed");
2131 ASTContext
&Ctx
= getASTContext();
2132 bool IsByRef
= true;
2134 // Find the directive that is associated with the provided scope.
2135 D
= cast
<ValueDecl
>(D
->getCanonicalDecl());
2136 QualType Ty
= D
->getType();
2138 bool IsVariableUsedInMapClause
= false;
2139 if (DSAStack
->hasExplicitDirective(isOpenMPTargetExecutionDirective
, Level
)) {
2140 // This table summarizes how a given variable should be passed to the device
2141 // given its type and the clauses where it appears. This table is based on
2142 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2143 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2145 // =========================================================================
2146 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2147 // | |(tofrom:scalar)| | pvt | |has_dv_adr| |
2148 // =========================================================================
2149 // | scl | | | | - | | bycopy|
2150 // | scl | | - | x | - | - | bycopy|
2151 // | scl | | x | - | - | - | null |
2152 // | scl | x | | | - | | byref |
2153 // | scl | x | - | x | - | - | bycopy|
2154 // | scl | x | x | - | - | - | null |
2155 // | scl | | - | - | - | x | byref |
2156 // | scl | x | - | - | - | x | byref |
2158 // | agg | n.a. | | | - | | byref |
2159 // | agg | n.a. | - | x | - | - | byref |
2160 // | agg | n.a. | x | - | - | - | null |
2161 // | agg | n.a. | - | - | - | x | byref |
2162 // | agg | n.a. | - | - | - | x[] | byref |
2164 // | ptr | n.a. | | | - | | bycopy|
2165 // | ptr | n.a. | - | x | - | - | bycopy|
2166 // | ptr | n.a. | x | - | - | - | null |
2167 // | ptr | n.a. | - | - | - | x | byref |
2168 // | ptr | n.a. | - | - | - | x[] | bycopy|
2169 // | ptr | n.a. | - | - | x | | bycopy|
2170 // | ptr | n.a. | - | - | x | x | bycopy|
2171 // | ptr | n.a. | - | - | x | x[] | bycopy|
2172 // =========================================================================
2178 // - - invalid in this combination
2179 // [] - mapped with an array section
2180 // byref - should be mapped by reference
2181 // byval - should be mapped by value
2182 // null - initialize a local variable to null on the device
2185 // - All scalar declarations that show up in a map clause have to be passed
2186 // by reference, because they may have been mapped in the enclosing data
2188 // - If the scalar value does not fit the size of uintptr, it has to be
2189 // passed by reference, regardless the result in the table above.
2190 // - For pointers mapped by value that have either an implicit map or an
2191 // array section, the runtime library may pass the NULL value to the
2192 // device instead of the value passed to it by the compiler.
2194 if (Ty
->isReferenceType())
2195 Ty
= Ty
->castAs
<ReferenceType
>()->getPointeeType();
2197 // Locate map clauses and see if the variable being captured is referred to
2198 // in any of those clauses. Here we only care about variables, not fields,
2199 // because fields are part of aggregates.
2200 bool IsVariableAssociatedWithSection
= false;
2202 DSAStack
->checkMappableExprComponentListsForDeclAtLevel(
2204 [&IsVariableUsedInMapClause
, &IsVariableAssociatedWithSection
,
2205 D
](OMPClauseMappableExprCommon::MappableExprComponentListRef
2207 OpenMPClauseKind WhereFoundClauseKind
) {
2208 // Both map and has_device_addr clauses information influences how a
2209 // variable is captured. E.g. is_device_ptr does not require changing
2210 // the default behavior.
2211 if (WhereFoundClauseKind
!= OMPC_map
&&
2212 WhereFoundClauseKind
!= OMPC_has_device_addr
)
2215 auto EI
= MapExprComponents
.rbegin();
2216 auto EE
= MapExprComponents
.rend();
2218 assert(EI
!= EE
&& "Invalid map expression!");
2220 if (isa
<DeclRefExpr
>(EI
->getAssociatedExpression()))
2221 IsVariableUsedInMapClause
|= EI
->getAssociatedDeclaration() == D
;
2226 auto Last
= std::prev(EE
);
2228 dyn_cast
<UnaryOperator
>(Last
->getAssociatedExpression());
2229 if ((UO
&& UO
->getOpcode() == UO_Deref
) ||
2230 isa
<ArraySubscriptExpr
>(Last
->getAssociatedExpression()) ||
2231 isa
<OMPArraySectionExpr
>(Last
->getAssociatedExpression()) ||
2232 isa
<MemberExpr
>(EI
->getAssociatedExpression()) ||
2233 isa
<OMPArrayShapingExpr
>(Last
->getAssociatedExpression())) {
2234 IsVariableAssociatedWithSection
= true;
2235 // There is nothing more we need to know about this variable.
2239 // Keep looking for more map info.
2243 if (IsVariableUsedInMapClause
) {
2244 // If variable is identified in a map clause it is always captured by
2245 // reference except if it is a pointer that is dereferenced somehow.
2246 IsByRef
= !(Ty
->isPointerType() && IsVariableAssociatedWithSection
);
2248 // By default, all the data that has a scalar type is mapped by copy
2249 // (except for reduction variables).
2250 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2251 IsByRef
= (DSAStack
->isForceCaptureByReferenceInTargetExecutable() &&
2252 !Ty
->isAnyPointerType()) ||
2253 !Ty
->isScalarType() ||
2254 DSAStack
->isDefaultmapCapturedByRef(
2255 Level
, getVariableCategoryFromDecl(LangOpts
, D
)) ||
2256 DSAStack
->hasExplicitDSA(
2258 [](OpenMPClauseKind K
, bool AppliedToPointee
) {
2259 return K
== OMPC_reduction
&& !AppliedToPointee
;
2265 if (IsByRef
&& Ty
.getNonReferenceType()->isScalarType()) {
2267 ((IsVariableUsedInMapClause
&&
2268 DSAStack
->getCaptureRegion(Level
, OpenMPCaptureLevel
) ==
2270 !(DSAStack
->hasExplicitDSA(
2272 [](OpenMPClauseKind K
, bool AppliedToPointee
) -> bool {
2273 return K
== OMPC_firstprivate
||
2274 (K
== OMPC_reduction
&& AppliedToPointee
);
2276 Level
, /*NotLastprivate=*/true) ||
2277 DSAStack
->isUsesAllocatorsDecl(Level
, D
))) &&
2278 // If the variable is artificial and must be captured by value - try to
2279 // capture by value.
2280 !(isa
<OMPCapturedExprDecl
>(D
) && !D
->hasAttr
<OMPCaptureNoInitAttr
>() &&
2281 !cast
<OMPCapturedExprDecl
>(D
)->getInit()->isGLValue()) &&
2282 // If the variable is implicitly firstprivate and scalar - capture by
2284 !((DSAStack
->getDefaultDSA() == DSA_firstprivate
||
2285 DSAStack
->getDefaultDSA() == DSA_private
) &&
2286 !DSAStack
->hasExplicitDSA(
2287 D
, [](OpenMPClauseKind K
, bool) { return K
!= OMPC_unknown
; },
2289 !DSAStack
->isLoopControlVariable(D
, Level
).first
);
2292 // When passing data by copy, we need to make sure it fits the uintptr size
2293 // and alignment, because the runtime library only deals with uintptr types.
2294 // If it does not fit the uintptr size, we need to pass the data by reference
2296 if (!IsByRef
&& (Ctx
.getTypeSizeInChars(Ty
) >
2297 Ctx
.getTypeSizeInChars(Ctx
.getUIntPtrType()) ||
2298 Ctx
.getAlignOfGlobalVarInChars(Ty
) >
2299 Ctx
.getTypeAlignInChars(Ctx
.getUIntPtrType()))) {
2306 unsigned Sema::getOpenMPNestingLevel() const {
2307 assert(getLangOpts().OpenMP
);
2308 return DSAStack
->getNestingLevel();
2311 bool Sema::isInOpenMPTaskUntiedContext() const {
2312 return isOpenMPTaskingDirective(DSAStack
->getCurrentDirective()) &&
2313 DSAStack
->isUntiedRegion();
2316 bool Sema::isInOpenMPTargetExecutionDirective() const {
2317 return (isOpenMPTargetExecutionDirective(DSAStack
->getCurrentDirective()) &&
2318 !DSAStack
->isClauseParsingMode()) ||
2319 DSAStack
->hasDirective(
2320 [](OpenMPDirectiveKind K
, const DeclarationNameInfo
&,
2321 SourceLocation
) -> bool {
2322 return isOpenMPTargetExecutionDirective(K
);
2327 bool Sema::isOpenMPRebuildMemberExpr(ValueDecl
*D
) {
2328 // Only rebuild for Field.
2329 if (!dyn_cast
<FieldDecl
>(D
))
2331 DSAStackTy::DSAVarData DVarPrivate
= DSAStack
->hasDSA(
2333 [](OpenMPClauseKind C
, bool AppliedToPointee
,
2334 DefaultDataSharingAttributes DefaultAttr
) {
2335 return isOpenMPPrivate(C
) && !AppliedToPointee
&&
2336 (DefaultAttr
== DSA_firstprivate
|| DefaultAttr
== DSA_private
);
2338 [](OpenMPDirectiveKind
) { return true; },
2339 DSAStack
->isClauseParsingMode());
2340 if (DVarPrivate
.CKind
!= OMPC_unknown
)
2345 static OMPCapturedExprDecl
*buildCaptureDecl(Sema
&S
, IdentifierInfo
*Id
,
2346 Expr
*CaptureExpr
, bool WithInit
,
2347 DeclContext
*CurContext
,
2350 VarDecl
*Sema::isOpenMPCapturedDecl(ValueDecl
*D
, bool CheckScopeInfo
,
2352 assert(LangOpts
.OpenMP
&& "OpenMP is not allowed");
2353 D
= getCanonicalDecl(D
);
2355 auto *VD
= dyn_cast
<VarDecl
>(D
);
2356 // Do not capture constexpr variables.
2357 if (VD
&& VD
->isConstexpr())
2360 // If we want to determine whether the variable should be captured from the
2361 // perspective of the current capturing scope, and we've already left all the
2362 // capturing scopes of the top directive on the stack, check from the
2363 // perspective of its parent directive (if any) instead.
2364 DSAStackTy::ParentDirectiveScope
InParentDirectiveRAII(
2365 *DSAStack
, CheckScopeInfo
&& DSAStack
->isBodyComplete());
2367 // If we are attempting to capture a global variable in a directive with
2368 // 'target' we return true so that this global is also mapped to the device.
2370 if (VD
&& !VD
->hasLocalStorage() &&
2371 (getCurCapturedRegion() || getCurBlock() || getCurLambda())) {
2372 if (isInOpenMPTargetExecutionDirective()) {
2373 DSAStackTy::DSAVarData DVarTop
=
2374 DSAStack
->getTopDSA(D
, DSAStack
->isClauseParsingMode());
2375 if (DVarTop
.CKind
!= OMPC_unknown
&& DVarTop
.RefExpr
)
2377 // If the declaration is enclosed in a 'declare target' directive,
2378 // then it should not be captured.
2380 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD
))
2382 CapturedRegionScopeInfo
*CSI
= nullptr;
2383 for (FunctionScopeInfo
*FSI
: llvm::drop_begin(
2384 llvm::reverse(FunctionScopes
),
2385 CheckScopeInfo
? (FunctionScopes
.size() - (StopAt
+ 1)) : 0)) {
2386 if (!isa
<CapturingScopeInfo
>(FSI
))
2388 if (auto *RSI
= dyn_cast
<CapturedRegionScopeInfo
>(FSI
))
2389 if (RSI
->CapRegionKind
== CR_OpenMP
) {
2394 assert(CSI
&& "Failed to find CapturedRegionScopeInfo");
2395 SmallVector
<OpenMPDirectiveKind
, 4> Regions
;
2396 getOpenMPCaptureRegions(Regions
,
2397 DSAStack
->getDirective(CSI
->OpenMPLevel
));
2398 if (Regions
[CSI
->OpenMPCaptureLevel
] != OMPD_task
)
2401 if (isInOpenMPDeclareTargetContext()) {
2402 // Try to mark variable as declare target if it is used in capturing
2404 if (LangOpts
.OpenMP
<= 45 &&
2405 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD
))
2406 checkDeclIsAllowedInOpenMPTarget(nullptr, VD
);
2411 if (CheckScopeInfo
) {
2412 bool OpenMPFound
= false;
2413 for (unsigned I
= StopAt
+ 1; I
> 0; --I
) {
2414 FunctionScopeInfo
*FSI
= FunctionScopes
[I
- 1];
2415 if (!isa
<CapturingScopeInfo
>(FSI
))
2417 if (auto *RSI
= dyn_cast
<CapturedRegionScopeInfo
>(FSI
))
2418 if (RSI
->CapRegionKind
== CR_OpenMP
) {
2427 if (DSAStack
->getCurrentDirective() != OMPD_unknown
&&
2428 (!DSAStack
->isClauseParsingMode() ||
2429 DSAStack
->getParentDirective() != OMPD_unknown
)) {
2430 auto &&Info
= DSAStack
->isLoopControlVariable(D
);
2432 (VD
&& VD
->hasLocalStorage() &&
2433 isImplicitOrExplicitTaskingRegion(DSAStack
->getCurrentDirective())) ||
2434 (VD
&& DSAStack
->isForceVarCapturing()))
2435 return VD
? VD
: Info
.second
;
2436 DSAStackTy::DSAVarData DVarTop
=
2437 DSAStack
->getTopDSA(D
, DSAStack
->isClauseParsingMode());
2438 if (DVarTop
.CKind
!= OMPC_unknown
&& isOpenMPPrivate(DVarTop
.CKind
) &&
2439 (!VD
|| VD
->hasLocalStorage() || !DVarTop
.AppliedToPointee
))
2440 return VD
? VD
: cast
<VarDecl
>(DVarTop
.PrivateCopy
->getDecl());
2441 // Threadprivate variables must not be captured.
2442 if (isOpenMPThreadPrivate(DVarTop
.CKind
))
2444 // The variable is not private or it is the variable in the directive with
2445 // default(none) clause and not used in any clause.
2446 DSAStackTy::DSAVarData DVarPrivate
= DSAStack
->hasDSA(
2448 [](OpenMPClauseKind C
, bool AppliedToPointee
, bool) {
2449 return isOpenMPPrivate(C
) && !AppliedToPointee
;
2451 [](OpenMPDirectiveKind
) { return true; },
2452 DSAStack
->isClauseParsingMode());
2453 // Global shared must not be captured.
2454 if (VD
&& !VD
->hasLocalStorage() && DVarPrivate
.CKind
== OMPC_unknown
&&
2455 ((DSAStack
->getDefaultDSA() != DSA_none
&&
2456 DSAStack
->getDefaultDSA() != DSA_private
&&
2457 DSAStack
->getDefaultDSA() != DSA_firstprivate
) ||
2458 DVarTop
.CKind
== OMPC_shared
))
2460 auto *FD
= dyn_cast
<FieldDecl
>(D
);
2461 if (DVarPrivate
.CKind
!= OMPC_unknown
&& !VD
&& FD
&&
2462 !DVarPrivate
.PrivateCopy
) {
2463 DSAStackTy::DSAVarData DVarPrivate
= DSAStack
->hasDSA(
2465 [](OpenMPClauseKind C
, bool AppliedToPointee
,
2466 DefaultDataSharingAttributes DefaultAttr
) {
2467 return isOpenMPPrivate(C
) && !AppliedToPointee
&&
2468 (DefaultAttr
== DSA_firstprivate
||
2469 DefaultAttr
== DSA_private
);
2471 [](OpenMPDirectiveKind
) { return true; },
2472 DSAStack
->isClauseParsingMode());
2473 if (DVarPrivate
.CKind
== OMPC_unknown
)
2476 VarDecl
*VD
= DSAStack
->getImplicitFDCapExprDecl(FD
);
2479 if (getCurrentThisType().isNull())
2481 Expr
*ThisExpr
= BuildCXXThisExpr(SourceLocation(), getCurrentThisType(),
2482 /*IsImplicit=*/true);
2483 const CXXScopeSpec CS
= CXXScopeSpec();
2484 Expr
*ME
= BuildMemberExpr(ThisExpr
, /*IsArrow=*/true, SourceLocation(),
2485 NestedNameSpecifierLoc(), SourceLocation(), FD
,
2486 DeclAccessPair::make(FD
, FD
->getAccess()),
2487 /*HadMultipleCandidates=*/false,
2488 DeclarationNameInfo(), FD
->getType(),
2489 VK_LValue
, OK_Ordinary
);
2490 OMPCapturedExprDecl
*CD
= buildCaptureDecl(
2491 *this, FD
->getIdentifier(), ME
, DVarPrivate
.CKind
!= OMPC_private
,
2492 CurContext
->getParent(), /*AsExpression=*/false);
2493 DeclRefExpr
*VDPrivateRefExpr
= buildDeclRefExpr(
2494 *this, CD
, CD
->getType().getNonReferenceType(), SourceLocation());
2495 VD
= cast
<VarDecl
>(VDPrivateRefExpr
->getDecl());
2496 DSAStack
->addImplicitDefaultFirstprivateFD(FD
, VD
);
2499 if (DVarPrivate
.CKind
!= OMPC_unknown
||
2500 (VD
&& (DSAStack
->getDefaultDSA() == DSA_none
||
2501 DSAStack
->getDefaultDSA() == DSA_private
||
2502 DSAStack
->getDefaultDSA() == DSA_firstprivate
)))
2503 return VD
? VD
: cast
<VarDecl
>(DVarPrivate
.PrivateCopy
->getDecl());
2508 void Sema::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex
,
2509 unsigned Level
) const {
2510 FunctionScopesIndex
-= getOpenMPCaptureLevels(DSAStack
->getDirective(Level
));
2513 void Sema::startOpenMPLoop() {
2514 assert(LangOpts
.OpenMP
&& "OpenMP must be enabled.");
2515 if (isOpenMPLoopDirective(DSAStack
->getCurrentDirective()))
2516 DSAStack
->loopInit();
2519 void Sema::startOpenMPCXXRangeFor() {
2520 assert(LangOpts
.OpenMP
&& "OpenMP must be enabled.");
2521 if (isOpenMPLoopDirective(DSAStack
->getCurrentDirective())) {
2522 DSAStack
->resetPossibleLoopCounter();
2523 DSAStack
->loopStart();
2527 OpenMPClauseKind
Sema::isOpenMPPrivateDecl(ValueDecl
*D
, unsigned Level
,
2528 unsigned CapLevel
) const {
2529 assert(LangOpts
.OpenMP
&& "OpenMP is not allowed");
2530 if (DSAStack
->getCurrentDirective() != OMPD_unknown
&&
2531 (!DSAStack
->isClauseParsingMode() ||
2532 DSAStack
->getParentDirective() != OMPD_unknown
)) {
2533 DSAStackTy::DSAVarData DVarPrivate
= DSAStack
->hasDSA(
2535 [](OpenMPClauseKind C
, bool AppliedToPointee
,
2536 DefaultDataSharingAttributes DefaultAttr
) {
2537 return isOpenMPPrivate(C
) && !AppliedToPointee
&&
2538 DefaultAttr
== DSA_private
;
2540 [](OpenMPDirectiveKind
) { return true; },
2541 DSAStack
->isClauseParsingMode());
2542 if (DVarPrivate
.CKind
== OMPC_private
&& isa
<OMPCapturedExprDecl
>(D
) &&
2543 DSAStack
->isImplicitDefaultFirstprivateFD(cast
<VarDecl
>(D
)) &&
2544 !DSAStack
->isLoopControlVariable(D
).first
)
2545 return OMPC_private
;
2547 if (DSAStack
->hasExplicitDirective(isOpenMPTaskingDirective
, Level
)) {
2548 bool IsTriviallyCopyable
=
2549 D
->getType().getNonReferenceType().isTriviallyCopyableType(Context
) &&
2551 .getNonReferenceType()
2553 ->getAsCXXRecordDecl();
2554 OpenMPDirectiveKind DKind
= DSAStack
->getDirective(Level
);
2555 SmallVector
<OpenMPDirectiveKind
, 4> CaptureRegions
;
2556 getOpenMPCaptureRegions(CaptureRegions
, DKind
);
2557 if (isOpenMPTaskingDirective(CaptureRegions
[CapLevel
]) &&
2558 (IsTriviallyCopyable
||
2559 !isOpenMPTaskLoopDirective(CaptureRegions
[CapLevel
]))) {
2560 if (DSAStack
->hasExplicitDSA(
2562 [](OpenMPClauseKind K
, bool) { return K
== OMPC_firstprivate
; },
2563 Level
, /*NotLastprivate=*/true))
2564 return OMPC_firstprivate
;
2565 DSAStackTy::DSAVarData DVar
= DSAStack
->getImplicitDSA(D
, Level
);
2566 if (DVar
.CKind
!= OMPC_shared
&&
2567 !DSAStack
->isLoopControlVariable(D
, Level
).first
&& !DVar
.RefExpr
) {
2568 DSAStack
->addImplicitTaskFirstprivate(Level
, D
);
2569 return OMPC_firstprivate
;
2573 if (isOpenMPLoopDirective(DSAStack
->getCurrentDirective()) &&
2574 !isOpenMPLoopTransformationDirective(DSAStack
->getCurrentDirective())) {
2575 if (DSAStack
->getAssociatedLoops() > 0 && !DSAStack
->isLoopStarted()) {
2576 DSAStack
->resetPossibleLoopCounter(D
);
2577 DSAStack
->loopStart();
2578 return OMPC_private
;
2580 if ((DSAStack
->getPossiblyLoopCunter() == D
->getCanonicalDecl() ||
2581 DSAStack
->isLoopControlVariable(D
).first
) &&
2582 !DSAStack
->hasExplicitDSA(
2583 D
, [](OpenMPClauseKind K
, bool) { return K
!= OMPC_private
; },
2585 !isOpenMPSimdDirective(DSAStack
->getCurrentDirective()))
2586 return OMPC_private
;
2588 if (const auto *VD
= dyn_cast
<VarDecl
>(D
)) {
2589 if (DSAStack
->isThreadPrivate(const_cast<VarDecl
*>(VD
)) &&
2590 DSAStack
->isForceVarCapturing() &&
2591 !DSAStack
->hasExplicitDSA(
2592 D
, [](OpenMPClauseKind K
, bool) { return K
== OMPC_copyin
; },
2594 return OMPC_private
;
2596 // User-defined allocators are private since they must be defined in the
2597 // context of target region.
2598 if (DSAStack
->hasExplicitDirective(isOpenMPTargetExecutionDirective
, Level
) &&
2599 DSAStack
->isUsesAllocatorsDecl(Level
, D
).value_or(
2600 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait
) ==
2601 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator
)
2602 return OMPC_private
;
2603 return (DSAStack
->hasExplicitDSA(
2604 D
, [](OpenMPClauseKind K
, bool) { return K
== OMPC_private
; },
2606 (DSAStack
->isClauseParsingMode() &&
2607 DSAStack
->getClauseParsingMode() == OMPC_private
) ||
2608 // Consider taskgroup reduction descriptor variable a private
2609 // to avoid possible capture in the region.
2610 (DSAStack
->hasExplicitDirective(
2611 [](OpenMPDirectiveKind K
) {
2612 return K
== OMPD_taskgroup
||
2613 ((isOpenMPParallelDirective(K
) ||
2614 isOpenMPWorksharingDirective(K
)) &&
2615 !isOpenMPSimdDirective(K
));
2618 DSAStack
->isTaskgroupReductionRef(D
, Level
)))
2623 void Sema::setOpenMPCaptureKind(FieldDecl
*FD
, const ValueDecl
*D
,
2625 assert(LangOpts
.OpenMP
&& "OpenMP is not allowed");
2626 D
= getCanonicalDecl(D
);
2627 OpenMPClauseKind OMPC
= OMPC_unknown
;
2628 for (unsigned I
= DSAStack
->getNestingLevel() + 1; I
> Level
; --I
) {
2629 const unsigned NewLevel
= I
- 1;
2630 if (DSAStack
->hasExplicitDSA(
2632 [&OMPC
](const OpenMPClauseKind K
, bool AppliedToPointee
) {
2633 if (isOpenMPPrivate(K
) && !AppliedToPointee
) {
2641 if (DSAStack
->checkMappableExprComponentListsForDeclAtLevel(
2643 [](OMPClauseMappableExprCommon::MappableExprComponentListRef
,
2644 OpenMPClauseKind
) { return true; })) {
2648 if (DSAStack
->hasExplicitDirective(isOpenMPTargetExecutionDirective
,
2651 if (DSAStack
->mustBeFirstprivateAtLevel(
2652 NewLevel
, getVariableCategoryFromDecl(LangOpts
, D
)))
2653 OMPC
= OMPC_firstprivate
;
2657 if (OMPC
!= OMPC_unknown
)
2658 FD
->addAttr(OMPCaptureKindAttr::CreateImplicit(Context
, unsigned(OMPC
)));
2661 bool Sema::isOpenMPTargetCapturedDecl(const ValueDecl
*D
, unsigned Level
,
2662 unsigned CaptureLevel
) const {
2663 assert(LangOpts
.OpenMP
&& "OpenMP is not allowed");
2664 // Return true if the current level is no longer enclosed in a target region.
2666 SmallVector
<OpenMPDirectiveKind
, 4> Regions
;
2667 getOpenMPCaptureRegions(Regions
, DSAStack
->getDirective(Level
));
2668 const auto *VD
= dyn_cast
<VarDecl
>(D
);
2669 return VD
&& !VD
->hasLocalStorage() &&
2670 DSAStack
->hasExplicitDirective(isOpenMPTargetExecutionDirective
,
2672 Regions
[CaptureLevel
] != OMPD_task
;
2675 bool Sema::isOpenMPGlobalCapturedDecl(ValueDecl
*D
, unsigned Level
,
2676 unsigned CaptureLevel
) const {
2677 assert(LangOpts
.OpenMP
&& "OpenMP is not allowed");
2678 // Return true if the current level is no longer enclosed in a target region.
2680 if (const auto *VD
= dyn_cast
<VarDecl
>(D
)) {
2681 if (!VD
->hasLocalStorage()) {
2682 if (isInOpenMPTargetExecutionDirective())
2684 DSAStackTy::DSAVarData TopDVar
=
2685 DSAStack
->getTopDSA(D
, /*FromParent=*/false);
2686 unsigned NumLevels
=
2687 getOpenMPCaptureLevels(DSAStack
->getDirective(Level
));
2689 // non-file scope static variale with default(firstprivate)
2690 // should be gloabal captured.
2691 return (NumLevels
== CaptureLevel
+ 1 &&
2692 (TopDVar
.CKind
!= OMPC_shared
||
2693 DSAStack
->getDefaultDSA() == DSA_firstprivate
));
2696 DSAStackTy::DSAVarData DVar
= DSAStack
->getImplicitDSA(D
, Level
);
2697 if (DVar
.CKind
!= OMPC_shared
)
2699 } while (Level
> 0);
2705 void Sema::DestroyDataSharingAttributesStack() { delete DSAStack
; }
2707 void Sema::ActOnOpenMPBeginDeclareVariant(SourceLocation Loc
,
2709 OMPDeclareVariantScopes
.push_back(OMPDeclareVariantScope(TI
));
2712 void Sema::ActOnOpenMPEndDeclareVariant() {
2713 assert(isInOpenMPDeclareVariantScope() &&
2714 "Not in OpenMP declare variant scope!");
2716 OMPDeclareVariantScopes
.pop_back();
2719 void Sema::finalizeOpenMPDelayedAnalysis(const FunctionDecl
*Caller
,
2720 const FunctionDecl
*Callee
,
2721 SourceLocation Loc
) {
2722 assert(LangOpts
.OpenMP
&& "Expected OpenMP compilation mode.");
2723 std::optional
<OMPDeclareTargetDeclAttr::DevTypeTy
> DevTy
=
2724 OMPDeclareTargetDeclAttr::getDeviceType(Caller
->getMostRecentDecl());
2725 // Ignore host functions during device analyzis.
2726 if (LangOpts
.OpenMPIsTargetDevice
&&
2727 (!DevTy
|| *DevTy
== OMPDeclareTargetDeclAttr::DT_Host
))
2729 // Ignore nohost functions during host analyzis.
2730 if (!LangOpts
.OpenMPIsTargetDevice
&& DevTy
&&
2731 *DevTy
== OMPDeclareTargetDeclAttr::DT_NoHost
)
2733 const FunctionDecl
*FD
= Callee
->getMostRecentDecl();
2734 DevTy
= OMPDeclareTargetDeclAttr::getDeviceType(FD
);
2735 if (LangOpts
.OpenMPIsTargetDevice
&& DevTy
&&
2736 *DevTy
== OMPDeclareTargetDeclAttr::DT_Host
) {
2737 // Diagnose host function called during device codegen.
2738 StringRef HostDevTy
=
2739 getOpenMPSimpleClauseTypeName(OMPC_device_type
, OMPC_DEVICE_TYPE_host
);
2740 Diag(Loc
, diag::err_omp_wrong_device_function_call
) << HostDevTy
<< 0;
2741 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD
),
2742 diag::note_omp_marked_device_type_here
)
2746 if (!LangOpts
.OpenMPIsTargetDevice
&& !LangOpts
.OpenMPOffloadMandatory
&&
2747 DevTy
&& *DevTy
== OMPDeclareTargetDeclAttr::DT_NoHost
) {
2748 // In OpenMP 5.2 or later, if the function has a host variant then allow
2749 // that to be called instead
2750 auto &&HasHostAttr
= [](const FunctionDecl
*Callee
) {
2751 for (OMPDeclareVariantAttr
*A
:
2752 Callee
->specific_attrs
<OMPDeclareVariantAttr
>()) {
2753 auto *DeclRefVariant
= cast
<DeclRefExpr
>(A
->getVariantFuncRef());
2754 auto *VariantFD
= cast
<FunctionDecl
>(DeclRefVariant
->getDecl());
2755 std::optional
<OMPDeclareTargetDeclAttr::DevTypeTy
> DevTy
=
2756 OMPDeclareTargetDeclAttr::getDeviceType(
2757 VariantFD
->getMostRecentDecl());
2758 if (!DevTy
|| *DevTy
== OMPDeclareTargetDeclAttr::DT_Host
)
2763 if (getLangOpts().OpenMP
>= 52 &&
2764 Callee
->hasAttr
<OMPDeclareVariantAttr
>() && HasHostAttr(Callee
))
2766 // Diagnose nohost function called during host codegen.
2767 StringRef NoHostDevTy
= getOpenMPSimpleClauseTypeName(
2768 OMPC_device_type
, OMPC_DEVICE_TYPE_nohost
);
2769 Diag(Loc
, diag::err_omp_wrong_device_function_call
) << NoHostDevTy
<< 1;
2770 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD
),
2771 diag::note_omp_marked_device_type_here
)
2776 void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind
,
2777 const DeclarationNameInfo
&DirName
,
2778 Scope
*CurScope
, SourceLocation Loc
) {
2779 DSAStack
->push(DKind
, DirName
, CurScope
, Loc
);
2780 PushExpressionEvaluationContext(
2781 ExpressionEvaluationContext::PotentiallyEvaluated
);
2784 void Sema::StartOpenMPClause(OpenMPClauseKind K
) {
2785 DSAStack
->setClauseParsingMode(K
);
2788 void Sema::EndOpenMPClause() {
2789 DSAStack
->setClauseParsingMode(/*K=*/OMPC_unknown
);
2790 CleanupVarDeclMarking();
2793 static std::pair
<ValueDecl
*, bool>
2794 getPrivateItem(Sema
&S
, Expr
*&RefExpr
, SourceLocation
&ELoc
,
2795 SourceRange
&ERange
, bool AllowArraySection
= false,
2796 StringRef DiagType
= "");
2798 /// Check consistency of the reduction clauses.
2799 static void checkReductionClauses(Sema
&S
, DSAStackTy
*Stack
,
2800 ArrayRef
<OMPClause
*> Clauses
) {
2801 bool InscanFound
= false;
2802 SourceLocation InscanLoc
;
2803 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2804 // A reduction clause without the inscan reduction-modifier may not appear on
2805 // a construct on which a reduction clause with the inscan reduction-modifier
2807 for (OMPClause
*C
: Clauses
) {
2808 if (C
->getClauseKind() != OMPC_reduction
)
2810 auto *RC
= cast
<OMPReductionClause
>(C
);
2811 if (RC
->getModifier() == OMPC_REDUCTION_inscan
) {
2813 InscanLoc
= RC
->getModifierLoc();
2816 if (RC
->getModifier() == OMPC_REDUCTION_task
) {
2817 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2818 // A reduction clause with the task reduction-modifier may only appear on
2819 // a parallel construct, a worksharing construct or a combined or
2820 // composite construct for which any of the aforementioned constructs is a
2821 // constituent construct and simd or loop are not constituent constructs.
2822 OpenMPDirectiveKind CurDir
= Stack
->getCurrentDirective();
2823 if (!(isOpenMPParallelDirective(CurDir
) ||
2824 isOpenMPWorksharingDirective(CurDir
)) ||
2825 isOpenMPSimdDirective(CurDir
))
2826 S
.Diag(RC
->getModifierLoc(),
2827 diag::err_omp_reduction_task_not_parallel_or_worksharing
);
2832 for (OMPClause
*C
: Clauses
) {
2833 if (C
->getClauseKind() != OMPC_reduction
)
2835 auto *RC
= cast
<OMPReductionClause
>(C
);
2836 if (RC
->getModifier() != OMPC_REDUCTION_inscan
) {
2837 S
.Diag(RC
->getModifier() == OMPC_REDUCTION_unknown
2839 : RC
->getModifierLoc(),
2840 diag::err_omp_inscan_reduction_expected
);
2841 S
.Diag(InscanLoc
, diag::note_omp_previous_inscan_reduction
);
2844 for (Expr
*Ref
: RC
->varlists()) {
2845 assert(Ref
&& "NULL expr in OpenMP nontemporal clause.");
2846 SourceLocation ELoc
;
2848 Expr
*SimpleRefExpr
= Ref
;
2849 auto Res
= getPrivateItem(S
, SimpleRefExpr
, ELoc
, ERange
,
2850 /*AllowArraySection=*/true);
2851 ValueDecl
*D
= Res
.first
;
2854 if (!Stack
->isUsedInScanDirective(getCanonicalDecl(D
))) {
2855 S
.Diag(Ref
->getExprLoc(),
2856 diag::err_omp_reduction_not_inclusive_exclusive
)
2857 << Ref
->getSourceRange();
2864 static void checkAllocateClauses(Sema
&S
, DSAStackTy
*Stack
,
2865 ArrayRef
<OMPClause
*> Clauses
);
2866 static DeclRefExpr
*buildCapture(Sema
&S
, ValueDecl
*D
, Expr
*CaptureExpr
,
2869 static void reportOriginalDsa(Sema
&SemaRef
, const DSAStackTy
*Stack
,
2871 const DSAStackTy::DSAVarData
&DVar
,
2872 bool IsLoopIterVar
= false);
2874 void Sema::EndOpenMPDSABlock(Stmt
*CurDirective
) {
2875 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2876 // A variable of class type (or array thereof) that appears in a lastprivate
2877 // clause requires an accessible, unambiguous default constructor for the
2878 // class type, unless the list item is also specified in a firstprivate
2880 if (const auto *D
= dyn_cast_or_null
<OMPExecutableDirective
>(CurDirective
)) {
2881 for (OMPClause
*C
: D
->clauses()) {
2882 if (auto *Clause
= dyn_cast
<OMPLastprivateClause
>(C
)) {
2883 SmallVector
<Expr
*, 8> PrivateCopies
;
2884 for (Expr
*DE
: Clause
->varlists()) {
2885 if (DE
->isValueDependent() || DE
->isTypeDependent()) {
2886 PrivateCopies
.push_back(nullptr);
2889 auto *DRE
= cast
<DeclRefExpr
>(DE
->IgnoreParens());
2890 auto *VD
= cast
<VarDecl
>(DRE
->getDecl());
2891 QualType Type
= VD
->getType().getNonReferenceType();
2892 const DSAStackTy::DSAVarData DVar
=
2893 DSAStack
->getTopDSA(VD
, /*FromParent=*/false);
2894 if (DVar
.CKind
== OMPC_lastprivate
) {
2895 // Generate helper private variable and initialize it with the
2896 // default value. The address of the original variable is replaced
2897 // by the address of the new private variable in CodeGen. This new
2898 // variable is not added to IdResolver, so the code in the OpenMP
2899 // region uses original variable for proper diagnostics.
2900 VarDecl
*VDPrivate
= buildVarDecl(
2901 *this, DE
->getExprLoc(), Type
.getUnqualifiedType(),
2902 VD
->getName(), VD
->hasAttrs() ? &VD
->getAttrs() : nullptr, DRE
);
2903 ActOnUninitializedDecl(VDPrivate
);
2904 if (VDPrivate
->isInvalidDecl()) {
2905 PrivateCopies
.push_back(nullptr);
2908 PrivateCopies
.push_back(buildDeclRefExpr(
2909 *this, VDPrivate
, DE
->getType(), DE
->getExprLoc()));
2911 // The variable is also a firstprivate, so initialization sequence
2912 // for private copy is generated already.
2913 PrivateCopies
.push_back(nullptr);
2916 Clause
->setPrivateCopies(PrivateCopies
);
2919 // Finalize nontemporal clause by handling private copies, if any.
2920 if (auto *Clause
= dyn_cast
<OMPNontemporalClause
>(C
)) {
2921 SmallVector
<Expr
*, 8> PrivateRefs
;
2922 for (Expr
*RefExpr
: Clause
->varlists()) {
2923 assert(RefExpr
&& "NULL expr in OpenMP nontemporal clause.");
2924 SourceLocation ELoc
;
2926 Expr
*SimpleRefExpr
= RefExpr
;
2927 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
2929 // It will be analyzed later.
2930 PrivateRefs
.push_back(RefExpr
);
2931 ValueDecl
*D
= Res
.first
;
2935 const DSAStackTy::DSAVarData DVar
=
2936 DSAStack
->getTopDSA(D
, /*FromParent=*/false);
2937 PrivateRefs
.push_back(DVar
.PrivateCopy
? DVar
.PrivateCopy
2940 Clause
->setPrivateRefs(PrivateRefs
);
2943 if (auto *Clause
= dyn_cast
<OMPUsesAllocatorsClause
>(C
)) {
2944 for (unsigned I
= 0, E
= Clause
->getNumberOfAllocators(); I
< E
; ++I
) {
2945 OMPUsesAllocatorsClause::Data D
= Clause
->getAllocatorData(I
);
2946 auto *DRE
= dyn_cast
<DeclRefExpr
>(D
.Allocator
->IgnoreParenImpCasts());
2949 ValueDecl
*VD
= DRE
->getDecl();
2950 if (!VD
|| !isa
<VarDecl
>(VD
))
2952 DSAStackTy::DSAVarData DVar
=
2953 DSAStack
->getTopDSA(VD
, /*FromParent=*/false);
2954 // OpenMP [2.12.5, target Construct]
2955 // Memory allocators that appear in a uses_allocators clause cannot
2956 // appear in other data-sharing attribute clauses or data-mapping
2957 // attribute clauses in the same construct.
2958 Expr
*MapExpr
= nullptr;
2960 DSAStack
->checkMappableExprComponentListsForDecl(
2961 VD
, /*CurrentRegionOnly=*/true,
2963 OMPClauseMappableExprCommon::MappableExprComponentListRef
2965 OpenMPClauseKind C
) {
2966 auto MI
= MapExprComponents
.rbegin();
2967 auto ME
= MapExprComponents
.rend();
2969 MI
->getAssociatedDeclaration()->getCanonicalDecl() ==
2970 VD
->getCanonicalDecl()) {
2971 MapExpr
= MI
->getAssociatedExpression();
2976 Diag(D
.Allocator
->getExprLoc(),
2977 diag::err_omp_allocator_used_in_clauses
)
2978 << D
.Allocator
->getSourceRange();
2980 reportOriginalDsa(*this, DSAStack
, VD
, DVar
);
2982 Diag(MapExpr
->getExprLoc(), diag::note_used_here
)
2983 << MapExpr
->getSourceRange();
2989 // Check allocate clauses.
2990 if (!CurContext
->isDependentContext())
2991 checkAllocateClauses(*this, DSAStack
, D
->clauses());
2992 checkReductionClauses(*this, DSAStack
, D
->clauses());
2996 DiscardCleanupsInEvaluationContext();
2997 PopExpressionEvaluationContext();
3000 static bool FinishOpenMPLinearClause(OMPLinearClause
&Clause
, DeclRefExpr
*IV
,
3001 Expr
*NumIterations
, Sema
&SemaRef
,
3002 Scope
*S
, DSAStackTy
*Stack
);
3006 class VarDeclFilterCCC final
: public CorrectionCandidateCallback
{
3011 explicit VarDeclFilterCCC(Sema
&S
) : SemaRef(S
) {}
3012 bool ValidateCandidate(const TypoCorrection
&Candidate
) override
{
3013 NamedDecl
*ND
= Candidate
.getCorrectionDecl();
3014 if (const auto *VD
= dyn_cast_or_null
<VarDecl
>(ND
)) {
3015 return VD
->hasGlobalStorage() &&
3016 SemaRef
.isDeclInScope(ND
, SemaRef
.getCurLexicalContext(),
3017 SemaRef
.getCurScope());
3022 std::unique_ptr
<CorrectionCandidateCallback
> clone() override
{
3023 return std::make_unique
<VarDeclFilterCCC
>(*this);
3027 class VarOrFuncDeclFilterCCC final
: public CorrectionCandidateCallback
{
3032 explicit VarOrFuncDeclFilterCCC(Sema
&S
) : SemaRef(S
) {}
3033 bool ValidateCandidate(const TypoCorrection
&Candidate
) override
{
3034 NamedDecl
*ND
= Candidate
.getCorrectionDecl();
3035 if (ND
&& ((isa
<VarDecl
>(ND
) && ND
->getKind() == Decl::Var
) ||
3036 isa
<FunctionDecl
>(ND
))) {
3037 return SemaRef
.isDeclInScope(ND
, SemaRef
.getCurLexicalContext(),
3038 SemaRef
.getCurScope());
3043 std::unique_ptr
<CorrectionCandidateCallback
> clone() override
{
3044 return std::make_unique
<VarOrFuncDeclFilterCCC
>(*this);
3050 ExprResult
Sema::ActOnOpenMPIdExpression(Scope
*CurScope
,
3051 CXXScopeSpec
&ScopeSpec
,
3052 const DeclarationNameInfo
&Id
,
3053 OpenMPDirectiveKind Kind
) {
3054 LookupResult
Lookup(*this, Id
, LookupOrdinaryName
);
3055 LookupParsedName(Lookup
, CurScope
, &ScopeSpec
, true);
3057 if (Lookup
.isAmbiguous())
3061 if (!Lookup
.isSingleResult()) {
3062 VarDeclFilterCCC
CCC(*this);
3063 if (TypoCorrection Corrected
=
3064 CorrectTypo(Id
, LookupOrdinaryName
, CurScope
, nullptr, CCC
,
3065 CTK_ErrorRecovery
)) {
3066 diagnoseTypo(Corrected
,
3067 PDiag(Lookup
.empty()
3068 ? diag::err_undeclared_var_use_suggest
3069 : diag::err_omp_expected_var_arg_suggest
)
3071 VD
= Corrected
.getCorrectionDeclAs
<VarDecl
>();
3073 Diag(Id
.getLoc(), Lookup
.empty() ? diag::err_undeclared_var_use
3074 : diag::err_omp_expected_var_arg
)
3078 } else if (!(VD
= Lookup
.getAsSingle
<VarDecl
>())) {
3079 Diag(Id
.getLoc(), diag::err_omp_expected_var_arg
) << Id
.getName();
3080 Diag(Lookup
.getFoundDecl()->getLocation(), diag::note_declared_at
);
3083 Lookup
.suppressDiagnostics();
3085 // OpenMP [2.9.2, Syntax, C/C++]
3086 // Variables must be file-scope, namespace-scope, or static block-scope.
3087 if (Kind
== OMPD_threadprivate
&& !VD
->hasGlobalStorage()) {
3088 Diag(Id
.getLoc(), diag::err_omp_global_var_arg
)
3089 << getOpenMPDirectiveName(Kind
) << !VD
->isStaticLocal();
3091 VD
->isThisDeclarationADefinition(Context
) == VarDecl::DeclarationOnly
;
3092 Diag(VD
->getLocation(),
3093 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
3098 VarDecl
*CanonicalVD
= VD
->getCanonicalDecl();
3099 NamedDecl
*ND
= CanonicalVD
;
3100 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3101 // A threadprivate directive for file-scope variables must appear outside
3102 // any definition or declaration.
3103 if (CanonicalVD
->getDeclContext()->isTranslationUnit() &&
3104 !getCurLexicalContext()->isTranslationUnit()) {
3105 Diag(Id
.getLoc(), diag::err_omp_var_scope
)
3106 << getOpenMPDirectiveName(Kind
) << VD
;
3108 VD
->isThisDeclarationADefinition(Context
) == VarDecl::DeclarationOnly
;
3109 Diag(VD
->getLocation(),
3110 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
3114 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3115 // A threadprivate directive for static class member variables must appear
3116 // in the class definition, in the same scope in which the member
3117 // variables are declared.
3118 if (CanonicalVD
->isStaticDataMember() &&
3119 !CanonicalVD
->getDeclContext()->Equals(getCurLexicalContext())) {
3120 Diag(Id
.getLoc(), diag::err_omp_var_scope
)
3121 << getOpenMPDirectiveName(Kind
) << VD
;
3123 VD
->isThisDeclarationADefinition(Context
) == VarDecl::DeclarationOnly
;
3124 Diag(VD
->getLocation(),
3125 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
3129 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3130 // A threadprivate directive for namespace-scope variables must appear
3131 // outside any definition or declaration other than the namespace
3132 // definition itself.
3133 if (CanonicalVD
->getDeclContext()->isNamespace() &&
3134 (!getCurLexicalContext()->isFileContext() ||
3135 !getCurLexicalContext()->Encloses(CanonicalVD
->getDeclContext()))) {
3136 Diag(Id
.getLoc(), diag::err_omp_var_scope
)
3137 << getOpenMPDirectiveName(Kind
) << VD
;
3139 VD
->isThisDeclarationADefinition(Context
) == VarDecl::DeclarationOnly
;
3140 Diag(VD
->getLocation(),
3141 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
3145 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3146 // A threadprivate directive for static block-scope variables must appear
3147 // in the scope of the variable and not in a nested scope.
3148 if (CanonicalVD
->isLocalVarDecl() && CurScope
&&
3149 !isDeclInScope(ND
, getCurLexicalContext(), CurScope
)) {
3150 Diag(Id
.getLoc(), diag::err_omp_var_scope
)
3151 << getOpenMPDirectiveName(Kind
) << VD
;
3153 VD
->isThisDeclarationADefinition(Context
) == VarDecl::DeclarationOnly
;
3154 Diag(VD
->getLocation(),
3155 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
3160 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3161 // A threadprivate directive must lexically precede all references to any
3162 // of the variables in its list.
3163 if (Kind
== OMPD_threadprivate
&& VD
->isUsed() &&
3164 !DSAStack
->isThreadPrivate(VD
)) {
3165 Diag(Id
.getLoc(), diag::err_omp_var_used
)
3166 << getOpenMPDirectiveName(Kind
) << VD
;
3170 QualType ExprType
= VD
->getType().getNonReferenceType();
3171 return DeclRefExpr::Create(Context
, NestedNameSpecifierLoc(),
3172 SourceLocation(), VD
,
3173 /*RefersToEnclosingVariableOrCapture=*/false,
3174 Id
.getLoc(), ExprType
, VK_LValue
);
3177 Sema::DeclGroupPtrTy
3178 Sema::ActOnOpenMPThreadprivateDirective(SourceLocation Loc
,
3179 ArrayRef
<Expr
*> VarList
) {
3180 if (OMPThreadPrivateDecl
*D
= CheckOMPThreadPrivateDecl(Loc
, VarList
)) {
3181 CurContext
->addDecl(D
);
3182 return DeclGroupPtrTy::make(DeclGroupRef(D
));
3188 class LocalVarRefChecker final
3189 : public ConstStmtVisitor
<LocalVarRefChecker
, bool> {
3193 bool VisitDeclRefExpr(const DeclRefExpr
*E
) {
3194 if (const auto *VD
= dyn_cast
<VarDecl
>(E
->getDecl())) {
3195 if (VD
->hasLocalStorage()) {
3196 SemaRef
.Diag(E
->getBeginLoc(),
3197 diag::err_omp_local_var_in_threadprivate_init
)
3198 << E
->getSourceRange();
3199 SemaRef
.Diag(VD
->getLocation(), diag::note_defined_here
)
3200 << VD
<< VD
->getSourceRange();
3206 bool VisitStmt(const Stmt
*S
) {
3207 for (const Stmt
*Child
: S
->children()) {
3208 if (Child
&& Visit(Child
))
3213 explicit LocalVarRefChecker(Sema
&SemaRef
) : SemaRef(SemaRef
) {}
3217 OMPThreadPrivateDecl
*
3218 Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc
, ArrayRef
<Expr
*> VarList
) {
3219 SmallVector
<Expr
*, 8> Vars
;
3220 for (Expr
*RefExpr
: VarList
) {
3221 auto *DE
= cast
<DeclRefExpr
>(RefExpr
);
3222 auto *VD
= cast
<VarDecl
>(DE
->getDecl());
3223 SourceLocation ILoc
= DE
->getExprLoc();
3225 // Mark variable as used.
3226 VD
->setReferenced();
3227 VD
->markUsed(Context
);
3229 QualType QType
= VD
->getType();
3230 if (QType
->isDependentType() || QType
->isInstantiationDependentType()) {
3231 // It will be analyzed later.
3236 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3237 // A threadprivate variable must not have an incomplete type.
3238 if (RequireCompleteType(ILoc
, VD
->getType(),
3239 diag::err_omp_threadprivate_incomplete_type
)) {
3243 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3244 // A threadprivate variable must not have a reference type.
3245 if (VD
->getType()->isReferenceType()) {
3246 Diag(ILoc
, diag::err_omp_ref_type_arg
)
3247 << getOpenMPDirectiveName(OMPD_threadprivate
) << VD
->getType();
3249 VD
->isThisDeclarationADefinition(Context
) == VarDecl::DeclarationOnly
;
3250 Diag(VD
->getLocation(),
3251 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
3256 // Check if this is a TLS variable. If TLS is not being supported, produce
3257 // the corresponding diagnostic.
3258 if ((VD
->getTLSKind() != VarDecl::TLS_None
&&
3259 !(VD
->hasAttr
<OMPThreadPrivateDeclAttr
>() &&
3260 getLangOpts().OpenMPUseTLS
&&
3261 getASTContext().getTargetInfo().isTLSSupported())) ||
3262 (VD
->getStorageClass() == SC_Register
&& VD
->hasAttr
<AsmLabelAttr
>() &&
3263 !VD
->isLocalVarDecl())) {
3264 Diag(ILoc
, diag::err_omp_var_thread_local
)
3265 << VD
<< ((VD
->getTLSKind() != VarDecl::TLS_None
) ? 0 : 1);
3267 VD
->isThisDeclarationADefinition(Context
) == VarDecl::DeclarationOnly
;
3268 Diag(VD
->getLocation(),
3269 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
3274 // Check if initial value of threadprivate variable reference variable with
3275 // local storage (it is not supported by runtime).
3276 if (const Expr
*Init
= VD
->getAnyInitializer()) {
3277 LocalVarRefChecker
Checker(*this);
3278 if (Checker
.Visit(Init
))
3282 Vars
.push_back(RefExpr
);
3283 DSAStack
->addDSA(VD
, DE
, OMPC_threadprivate
);
3284 VD
->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3285 Context
, SourceRange(Loc
, Loc
)));
3286 if (ASTMutationListener
*ML
= Context
.getASTMutationListener())
3287 ML
->DeclarationMarkedOpenMPThreadPrivate(VD
);
3289 OMPThreadPrivateDecl
*D
= nullptr;
3290 if (!Vars
.empty()) {
3291 D
= OMPThreadPrivateDecl::Create(Context
, getCurLexicalContext(), Loc
,
3293 D
->setAccess(AS_public
);
3298 static OMPAllocateDeclAttr::AllocatorTypeTy
3299 getAllocatorKind(Sema
&S
, DSAStackTy
*Stack
, Expr
*Allocator
) {
3301 return OMPAllocateDeclAttr::OMPNullMemAlloc
;
3302 if (Allocator
->isTypeDependent() || Allocator
->isValueDependent() ||
3303 Allocator
->isInstantiationDependent() ||
3304 Allocator
->containsUnexpandedParameterPack())
3305 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc
;
3306 auto AllocatorKindRes
= OMPAllocateDeclAttr::OMPUserDefinedMemAlloc
;
3307 llvm::FoldingSetNodeID AEId
;
3308 const Expr
*AE
= Allocator
->IgnoreParenImpCasts();
3309 AE
->IgnoreImpCasts()->Profile(AEId
, S
.getASTContext(), /*Canonical=*/true);
3310 for (int I
= 0; I
< OMPAllocateDeclAttr::OMPUserDefinedMemAlloc
; ++I
) {
3311 auto AllocatorKind
= static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I
);
3312 const Expr
*DefAllocator
= Stack
->getAllocator(AllocatorKind
);
3313 llvm::FoldingSetNodeID DAEId
;
3314 DefAllocator
->IgnoreImpCasts()->Profile(DAEId
, S
.getASTContext(),
3315 /*Canonical=*/true);
3316 if (AEId
== DAEId
) {
3317 AllocatorKindRes
= AllocatorKind
;
3321 return AllocatorKindRes
;
3324 static bool checkPreviousOMPAllocateAttribute(
3325 Sema
&S
, DSAStackTy
*Stack
, Expr
*RefExpr
, VarDecl
*VD
,
3326 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind
, Expr
*Allocator
) {
3327 if (!VD
->hasAttr
<OMPAllocateDeclAttr
>())
3329 const auto *A
= VD
->getAttr
<OMPAllocateDeclAttr
>();
3330 Expr
*PrevAllocator
= A
->getAllocator();
3331 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind
=
3332 getAllocatorKind(S
, Stack
, PrevAllocator
);
3333 bool AllocatorsMatch
= AllocatorKind
== PrevAllocatorKind
;
3334 if (AllocatorsMatch
&&
3335 AllocatorKind
== OMPAllocateDeclAttr::OMPUserDefinedMemAlloc
&&
3336 Allocator
&& PrevAllocator
) {
3337 const Expr
*AE
= Allocator
->IgnoreParenImpCasts();
3338 const Expr
*PAE
= PrevAllocator
->IgnoreParenImpCasts();
3339 llvm::FoldingSetNodeID AEId
, PAEId
;
3340 AE
->Profile(AEId
, S
.Context
, /*Canonical=*/true);
3341 PAE
->Profile(PAEId
, S
.Context
, /*Canonical=*/true);
3342 AllocatorsMatch
= AEId
== PAEId
;
3344 if (!AllocatorsMatch
) {
3345 SmallString
<256> AllocatorBuffer
;
3346 llvm::raw_svector_ostream
AllocatorStream(AllocatorBuffer
);
3348 Allocator
->printPretty(AllocatorStream
, nullptr, S
.getPrintingPolicy());
3349 SmallString
<256> PrevAllocatorBuffer
;
3350 llvm::raw_svector_ostream
PrevAllocatorStream(PrevAllocatorBuffer
);
3352 PrevAllocator
->printPretty(PrevAllocatorStream
, nullptr,
3353 S
.getPrintingPolicy());
3355 SourceLocation AllocatorLoc
=
3356 Allocator
? Allocator
->getExprLoc() : RefExpr
->getExprLoc();
3357 SourceRange AllocatorRange
=
3358 Allocator
? Allocator
->getSourceRange() : RefExpr
->getSourceRange();
3359 SourceLocation PrevAllocatorLoc
=
3360 PrevAllocator
? PrevAllocator
->getExprLoc() : A
->getLocation();
3361 SourceRange PrevAllocatorRange
=
3362 PrevAllocator
? PrevAllocator
->getSourceRange() : A
->getRange();
3363 S
.Diag(AllocatorLoc
, diag::warn_omp_used_different_allocator
)
3364 << (Allocator
? 1 : 0) << AllocatorStream
.str()
3365 << (PrevAllocator
? 1 : 0) << PrevAllocatorStream
.str()
3367 S
.Diag(PrevAllocatorLoc
, diag::note_omp_previous_allocator
)
3368 << PrevAllocatorRange
;
3375 applyOMPAllocateAttribute(Sema
&S
, VarDecl
*VD
,
3376 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind
,
3377 Expr
*Allocator
, Expr
*Alignment
, SourceRange SR
) {
3378 if (VD
->hasAttr
<OMPAllocateDeclAttr
>())
3381 (Alignment
->isTypeDependent() || Alignment
->isValueDependent() ||
3382 Alignment
->isInstantiationDependent() ||
3383 Alignment
->containsUnexpandedParameterPack()))
3384 // Apply later when we have a usable value.
3387 (Allocator
->isTypeDependent() || Allocator
->isValueDependent() ||
3388 Allocator
->isInstantiationDependent() ||
3389 Allocator
->containsUnexpandedParameterPack()))
3391 auto *A
= OMPAllocateDeclAttr::CreateImplicit(S
.Context
, AllocatorKind
,
3392 Allocator
, Alignment
, SR
);
3394 if (ASTMutationListener
*ML
= S
.Context
.getASTMutationListener())
3395 ML
->DeclarationMarkedOpenMPAllocate(VD
, A
);
3398 Sema::DeclGroupPtrTy
3399 Sema::ActOnOpenMPAllocateDirective(SourceLocation Loc
, ArrayRef
<Expr
*> VarList
,
3400 ArrayRef
<OMPClause
*> Clauses
,
3401 DeclContext
*Owner
) {
3402 assert(Clauses
.size() <= 2 && "Expected at most two clauses.");
3403 Expr
*Alignment
= nullptr;
3404 Expr
*Allocator
= nullptr;
3405 if (Clauses
.empty()) {
3406 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3407 // allocate directives that appear in a target region must specify an
3408 // allocator clause unless a requires directive with the dynamic_allocators
3409 // clause is present in the same compilation unit.
3410 if (LangOpts
.OpenMPIsTargetDevice
&&
3411 !DSAStack
->hasRequiresDeclWithClause
<OMPDynamicAllocatorsClause
>())
3412 targetDiag(Loc
, diag::err_expected_allocator_clause
);
3414 for (const OMPClause
*C
: Clauses
)
3415 if (const auto *AC
= dyn_cast
<OMPAllocatorClause
>(C
))
3416 Allocator
= AC
->getAllocator();
3417 else if (const auto *AC
= dyn_cast
<OMPAlignClause
>(C
))
3418 Alignment
= AC
->getAlignment();
3420 llvm_unreachable("Unexpected clause on allocate directive");
3422 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind
=
3423 getAllocatorKind(*this, DSAStack
, Allocator
);
3424 SmallVector
<Expr
*, 8> Vars
;
3425 for (Expr
*RefExpr
: VarList
) {
3426 auto *DE
= cast
<DeclRefExpr
>(RefExpr
);
3427 auto *VD
= cast
<VarDecl
>(DE
->getDecl());
3429 // Check if this is a TLS variable or global register.
3430 if (VD
->getTLSKind() != VarDecl::TLS_None
||
3431 VD
->hasAttr
<OMPThreadPrivateDeclAttr
>() ||
3432 (VD
->getStorageClass() == SC_Register
&& VD
->hasAttr
<AsmLabelAttr
>() &&
3433 !VD
->isLocalVarDecl()))
3436 // If the used several times in the allocate directive, the same allocator
3438 if (checkPreviousOMPAllocateAttribute(*this, DSAStack
, RefExpr
, VD
,
3439 AllocatorKind
, Allocator
))
3442 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3443 // If a list item has a static storage type, the allocator expression in the
3444 // allocator clause must be a constant expression that evaluates to one of
3445 // the predefined memory allocator values.
3446 if (Allocator
&& VD
->hasGlobalStorage()) {
3447 if (AllocatorKind
== OMPAllocateDeclAttr::OMPUserDefinedMemAlloc
) {
3448 Diag(Allocator
->getExprLoc(),
3449 diag::err_omp_expected_predefined_allocator
)
3450 << Allocator
->getSourceRange();
3451 bool IsDecl
= VD
->isThisDeclarationADefinition(Context
) ==
3452 VarDecl::DeclarationOnly
;
3453 Diag(VD
->getLocation(),
3454 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
3460 Vars
.push_back(RefExpr
);
3461 applyOMPAllocateAttribute(*this, VD
, AllocatorKind
, Allocator
, Alignment
,
3462 DE
->getSourceRange());
3467 Owner
= getCurLexicalContext();
3468 auto *D
= OMPAllocateDecl::Create(Context
, Owner
, Loc
, Vars
, Clauses
);
3469 D
->setAccess(AS_public
);
3471 return DeclGroupPtrTy::make(DeclGroupRef(D
));
3474 Sema::DeclGroupPtrTy
3475 Sema::ActOnOpenMPRequiresDirective(SourceLocation Loc
,
3476 ArrayRef
<OMPClause
*> ClauseList
) {
3477 OMPRequiresDecl
*D
= nullptr;
3478 if (!CurContext
->isFileContext()) {
3479 Diag(Loc
, diag::err_omp_invalid_scope
) << "requires";
3481 D
= CheckOMPRequiresDecl(Loc
, ClauseList
);
3483 CurContext
->addDecl(D
);
3484 DSAStack
->addRequiresDecl(D
);
3487 return DeclGroupPtrTy::make(DeclGroupRef(D
));
3490 void Sema::ActOnOpenMPAssumesDirective(SourceLocation Loc
,
3491 OpenMPDirectiveKind DKind
,
3492 ArrayRef
<std::string
> Assumptions
,
3493 bool SkippedClauses
) {
3494 if (!SkippedClauses
&& Assumptions
.empty())
3495 Diag(Loc
, diag::err_omp_no_clause_for_directive
)
3496 << llvm::omp::getAllAssumeClauseOptions()
3497 << llvm::omp::getOpenMPDirectiveName(DKind
);
3499 auto *AA
= AssumptionAttr::Create(Context
, llvm::join(Assumptions
, ","), Loc
);
3500 if (DKind
== llvm::omp::Directive::OMPD_begin_assumes
) {
3501 OMPAssumeScoped
.push_back(AA
);
3505 // Global assumes without assumption clauses are ignored.
3506 if (Assumptions
.empty())
3509 assert(DKind
== llvm::omp::Directive::OMPD_assumes
&&
3510 "Unexpected omp assumption directive!");
3511 OMPAssumeGlobal
.push_back(AA
);
3513 // The OMPAssumeGlobal scope above will take care of new declarations but
3514 // we also want to apply the assumption to existing ones, e.g., to
3515 // declarations in included headers. To this end, we traverse all existing
3516 // declaration contexts and annotate function declarations here.
3517 SmallVector
<DeclContext
*, 8> DeclContexts
;
3518 auto *Ctx
= CurContext
;
3519 while (Ctx
->getLexicalParent())
3520 Ctx
= Ctx
->getLexicalParent();
3521 DeclContexts
.push_back(Ctx
);
3522 while (!DeclContexts
.empty()) {
3523 DeclContext
*DC
= DeclContexts
.pop_back_val();
3524 for (auto *SubDC
: DC
->decls()) {
3525 if (SubDC
->isInvalidDecl())
3527 if (auto *CTD
= dyn_cast
<ClassTemplateDecl
>(SubDC
)) {
3528 DeclContexts
.push_back(CTD
->getTemplatedDecl());
3529 llvm::append_range(DeclContexts
, CTD
->specializations());
3532 if (auto *DC
= dyn_cast
<DeclContext
>(SubDC
))
3533 DeclContexts
.push_back(DC
);
3534 if (auto *F
= dyn_cast
<FunctionDecl
>(SubDC
)) {
3542 void Sema::ActOnOpenMPEndAssumesDirective() {
3543 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3544 OMPAssumeScoped
.pop_back();
3547 OMPRequiresDecl
*Sema::CheckOMPRequiresDecl(SourceLocation Loc
,
3548 ArrayRef
<OMPClause
*> ClauseList
) {
3549 /// For target specific clauses, the requires directive cannot be
3550 /// specified after the handling of any of the target regions in the
3551 /// current compilation unit.
3552 ArrayRef
<SourceLocation
> TargetLocations
=
3553 DSAStack
->getEncounteredTargetLocs();
3554 SourceLocation AtomicLoc
= DSAStack
->getAtomicDirectiveLoc();
3555 if (!TargetLocations
.empty() || !AtomicLoc
.isInvalid()) {
3556 for (const OMPClause
*CNew
: ClauseList
) {
3557 // Check if any of the requires clauses affect target regions.
3558 if (isa
<OMPUnifiedSharedMemoryClause
>(CNew
) ||
3559 isa
<OMPUnifiedAddressClause
>(CNew
) ||
3560 isa
<OMPReverseOffloadClause
>(CNew
) ||
3561 isa
<OMPDynamicAllocatorsClause
>(CNew
)) {
3562 Diag(Loc
, diag::err_omp_directive_before_requires
)
3563 << "target" << getOpenMPClauseName(CNew
->getClauseKind());
3564 for (SourceLocation TargetLoc
: TargetLocations
) {
3565 Diag(TargetLoc
, diag::note_omp_requires_encountered_directive
)
3568 } else if (!AtomicLoc
.isInvalid() &&
3569 isa
<OMPAtomicDefaultMemOrderClause
>(CNew
)) {
3570 Diag(Loc
, diag::err_omp_directive_before_requires
)
3571 << "atomic" << getOpenMPClauseName(CNew
->getClauseKind());
3572 Diag(AtomicLoc
, diag::note_omp_requires_encountered_directive
)
3578 if (!DSAStack
->hasDuplicateRequiresClause(ClauseList
))
3579 return OMPRequiresDecl::Create(Context
, getCurLexicalContext(), Loc
,
3584 static void reportOriginalDsa(Sema
&SemaRef
, const DSAStackTy
*Stack
,
3586 const DSAStackTy::DSAVarData
&DVar
,
3587 bool IsLoopIterVar
) {
3589 SemaRef
.Diag(DVar
.RefExpr
->getExprLoc(), diag::note_omp_explicit_dsa
)
3590 << getOpenMPClauseName(DVar
.CKind
);
3594 PDSA_StaticMemberShared
,
3595 PDSA_StaticLocalVarShared
,
3596 PDSA_LoopIterVarPrivate
,
3597 PDSA_LoopIterVarLinear
,
3598 PDSA_LoopIterVarLastprivate
,
3599 PDSA_ConstVarShared
,
3600 PDSA_GlobalVarShared
,
3601 PDSA_TaskVarFirstprivate
,
3602 PDSA_LocalVarPrivate
,
3604 } Reason
= PDSA_Implicit
;
3605 bool ReportHint
= false;
3606 auto ReportLoc
= D
->getLocation();
3607 auto *VD
= dyn_cast
<VarDecl
>(D
);
3608 if (IsLoopIterVar
) {
3609 if (DVar
.CKind
== OMPC_private
)
3610 Reason
= PDSA_LoopIterVarPrivate
;
3611 else if (DVar
.CKind
== OMPC_lastprivate
)
3612 Reason
= PDSA_LoopIterVarLastprivate
;
3614 Reason
= PDSA_LoopIterVarLinear
;
3615 } else if (isOpenMPTaskingDirective(DVar
.DKind
) &&
3616 DVar
.CKind
== OMPC_firstprivate
) {
3617 Reason
= PDSA_TaskVarFirstprivate
;
3618 ReportLoc
= DVar
.ImplicitDSALoc
;
3619 } else if (VD
&& VD
->isStaticLocal())
3620 Reason
= PDSA_StaticLocalVarShared
;
3621 else if (VD
&& VD
->isStaticDataMember())
3622 Reason
= PDSA_StaticMemberShared
;
3623 else if (VD
&& VD
->isFileVarDecl())
3624 Reason
= PDSA_GlobalVarShared
;
3625 else if (D
->getType().isConstant(SemaRef
.getASTContext()))
3626 Reason
= PDSA_ConstVarShared
;
3627 else if (VD
&& VD
->isLocalVarDecl() && DVar
.CKind
== OMPC_private
) {
3629 Reason
= PDSA_LocalVarPrivate
;
3631 if (Reason
!= PDSA_Implicit
) {
3632 SemaRef
.Diag(ReportLoc
, diag::note_omp_predetermined_dsa
)
3633 << Reason
<< ReportHint
3634 << getOpenMPDirectiveName(Stack
->getCurrentDirective());
3635 } else if (DVar
.ImplicitDSALoc
.isValid()) {
3636 SemaRef
.Diag(DVar
.ImplicitDSALoc
, diag::note_omp_implicit_dsa
)
3637 << getOpenMPClauseName(DVar
.CKind
);
3641 static OpenMPMapClauseKind
3642 getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M
,
3643 bool IsAggregateOrDeclareTarget
) {
3644 OpenMPMapClauseKind Kind
= OMPC_MAP_unknown
;
3646 case OMPC_DEFAULTMAP_MODIFIER_alloc
:
3647 Kind
= OMPC_MAP_alloc
;
3649 case OMPC_DEFAULTMAP_MODIFIER_to
:
3652 case OMPC_DEFAULTMAP_MODIFIER_from
:
3653 Kind
= OMPC_MAP_from
;
3655 case OMPC_DEFAULTMAP_MODIFIER_tofrom
:
3656 Kind
= OMPC_MAP_tofrom
;
3658 case OMPC_DEFAULTMAP_MODIFIER_present
:
3659 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3660 // If implicit-behavior is present, each variable referenced in the
3661 // construct in the category specified by variable-category is treated as if
3662 // it had been listed in a map clause with the map-type of alloc and
3663 // map-type-modifier of present.
3664 Kind
= OMPC_MAP_alloc
;
3666 case OMPC_DEFAULTMAP_MODIFIER_firstprivate
:
3667 case OMPC_DEFAULTMAP_MODIFIER_last
:
3668 llvm_unreachable("Unexpected defaultmap implicit behavior");
3669 case OMPC_DEFAULTMAP_MODIFIER_none
:
3670 case OMPC_DEFAULTMAP_MODIFIER_default
:
3671 case OMPC_DEFAULTMAP_MODIFIER_unknown
:
3672 // IsAggregateOrDeclareTarget could be true if:
3673 // 1. the implicit behavior for aggregate is tofrom
3674 // 2. it's a declare target link
3675 if (IsAggregateOrDeclareTarget
) {
3676 Kind
= OMPC_MAP_tofrom
;
3679 llvm_unreachable("Unexpected defaultmap implicit behavior");
3681 assert(Kind
!= OMPC_MAP_unknown
&& "Expect map kind to be known");
3686 class DSAAttrChecker final
: public StmtVisitor
<DSAAttrChecker
, void> {
3689 bool ErrorFound
= false;
3690 bool TryCaptureCXXThisMembers
= false;
3691 CapturedStmt
*CS
= nullptr;
3692 const static unsigned DefaultmapKindNum
= OMPC_DEFAULTMAP_pointer
+ 1;
3693 llvm::SmallVector
<Expr
*, 4> ImplicitFirstprivate
;
3694 llvm::SmallVector
<Expr
*, 4> ImplicitPrivate
;
3695 llvm::SmallVector
<Expr
*, 4> ImplicitMap
[DefaultmapKindNum
][OMPC_MAP_delete
];
3696 llvm::SmallVector
<OpenMPMapModifierKind
, NumberOfOMPMapClauseModifiers
>
3697 ImplicitMapModifier
[DefaultmapKindNum
];
3698 Sema::VarsWithInheritedDSAType VarsWithInheritedDSA
;
3699 llvm::SmallDenseSet
<const ValueDecl
*, 4> ImplicitDeclarations
;
3701 void VisitSubCaptures(OMPExecutableDirective
*S
) {
3702 // Check implicitly captured variables.
3703 if (!S
->hasAssociatedStmt() || !S
->getAssociatedStmt())
3705 if (S
->getDirectiveKind() == OMPD_atomic
||
3706 S
->getDirectiveKind() == OMPD_critical
||
3707 S
->getDirectiveKind() == OMPD_section
||
3708 S
->getDirectiveKind() == OMPD_master
||
3709 S
->getDirectiveKind() == OMPD_masked
||
3710 S
->getDirectiveKind() == OMPD_scope
||
3711 isOpenMPLoopTransformationDirective(S
->getDirectiveKind())) {
3712 Visit(S
->getAssociatedStmt());
3715 visitSubCaptures(S
->getInnermostCapturedStmt());
3716 // Try to capture inner this->member references to generate correct mappings
3718 if (TryCaptureCXXThisMembers
||
3719 (isOpenMPTargetExecutionDirective(Stack
->getCurrentDirective()) &&
3720 llvm::any_of(S
->getInnermostCapturedStmt()->captures(),
3721 [](const CapturedStmt::Capture
&C
) {
3722 return C
.capturesThis();
3724 bool SavedTryCaptureCXXThisMembers
= TryCaptureCXXThisMembers
;
3725 TryCaptureCXXThisMembers
= true;
3726 Visit(S
->getInnermostCapturedStmt()->getCapturedStmt());
3727 TryCaptureCXXThisMembers
= SavedTryCaptureCXXThisMembers
;
3729 // In tasks firstprivates are not captured anymore, need to analyze them
3731 if (isOpenMPTaskingDirective(S
->getDirectiveKind()) &&
3732 !isOpenMPTaskLoopDirective(S
->getDirectiveKind())) {
3733 for (OMPClause
*C
: S
->clauses())
3734 if (auto *FC
= dyn_cast
<OMPFirstprivateClause
>(C
)) {
3735 for (Expr
*Ref
: FC
->varlists())
3742 void VisitDeclRefExpr(DeclRefExpr
*E
) {
3743 if (TryCaptureCXXThisMembers
|| E
->isTypeDependent() ||
3744 E
->isValueDependent() || E
->containsUnexpandedParameterPack() ||
3745 E
->isInstantiationDependent())
3747 if (auto *VD
= dyn_cast
<VarDecl
>(E
->getDecl())) {
3748 // Check the datasharing rules for the expressions in the clauses.
3749 if (!CS
|| (isa
<OMPCapturedExprDecl
>(VD
) && !CS
->capturesVariable(VD
) &&
3750 !Stack
->getTopDSA(VD
, /*FromParent=*/false).RefExpr
&&
3751 !Stack
->isImplicitDefaultFirstprivateFD(VD
))) {
3752 if (auto *CED
= dyn_cast
<OMPCapturedExprDecl
>(VD
))
3753 if (!CED
->hasAttr
<OMPCaptureNoInitAttr
>()) {
3754 Visit(CED
->getInit());
3757 } else if (VD
->isImplicit() || isa
<OMPCapturedExprDecl
>(VD
))
3758 // Do not analyze internal variables and do not enclose them into
3759 // implicit clauses.
3760 if (!Stack
->isImplicitDefaultFirstprivateFD(VD
))
3762 VD
= VD
->getCanonicalDecl();
3763 // Skip internally declared variables.
3764 if (VD
->hasLocalStorage() && CS
&& !CS
->capturesVariable(VD
) &&
3765 !Stack
->isImplicitDefaultFirstprivateFD(VD
) &&
3766 !Stack
->isImplicitTaskFirstprivate(VD
))
3768 // Skip allocators in uses_allocators clauses.
3769 if (Stack
->isUsesAllocatorsDecl(VD
))
3772 DSAStackTy::DSAVarData DVar
= Stack
->getTopDSA(VD
, /*FromParent=*/false);
3773 // Check if the variable has explicit DSA set and stop analysis if it so.
3774 if (DVar
.RefExpr
|| !ImplicitDeclarations
.insert(VD
).second
)
3777 // Skip internally declared static variables.
3778 std::optional
<OMPDeclareTargetDeclAttr::MapTypeTy
> Res
=
3779 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD
);
3780 if (VD
->hasGlobalStorage() && CS
&& !CS
->capturesVariable(VD
) &&
3781 (Stack
->hasRequiresDeclWithClause
<OMPUnifiedSharedMemoryClause
>() ||
3782 !Res
|| *Res
!= OMPDeclareTargetDeclAttr::MT_Link
) &&
3783 !Stack
->isImplicitDefaultFirstprivateFD(VD
) &&
3784 !Stack
->isImplicitTaskFirstprivate(VD
))
3787 SourceLocation ELoc
= E
->getExprLoc();
3788 OpenMPDirectiveKind DKind
= Stack
->getCurrentDirective();
3789 // The default(none) clause requires that each variable that is referenced
3790 // in the construct, and does not have a predetermined data-sharing
3791 // attribute, must have its data-sharing attribute explicitly determined
3792 // by being listed in a data-sharing attribute clause.
3793 if (DVar
.CKind
== OMPC_unknown
&&
3794 (Stack
->getDefaultDSA() == DSA_none
||
3795 Stack
->getDefaultDSA() == DSA_private
||
3796 Stack
->getDefaultDSA() == DSA_firstprivate
) &&
3797 isImplicitOrExplicitTaskingRegion(DKind
) &&
3798 VarsWithInheritedDSA
.count(VD
) == 0) {
3799 bool InheritedDSA
= Stack
->getDefaultDSA() == DSA_none
;
3800 if (!InheritedDSA
&& (Stack
->getDefaultDSA() == DSA_firstprivate
||
3801 Stack
->getDefaultDSA() == DSA_private
)) {
3802 DSAStackTy::DSAVarData DVar
=
3803 Stack
->getImplicitDSA(VD
, /*FromParent=*/false);
3804 InheritedDSA
= DVar
.CKind
== OMPC_unknown
;
3807 VarsWithInheritedDSA
[VD
] = E
;
3808 if (Stack
->getDefaultDSA() == DSA_none
)
3812 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
3813 // If implicit-behavior is none, each variable referenced in the
3814 // construct that does not have a predetermined data-sharing attribute
3815 // and does not appear in a to or link clause on a declare target
3816 // directive must be listed in a data-mapping attribute clause, a
3817 // data-sharing attribute clause (including a data-sharing attribute
3818 // clause on a combined construct where target. is one of the
3819 // constituent constructs), or an is_device_ptr clause.
3820 OpenMPDefaultmapClauseKind ClauseKind
=
3821 getVariableCategoryFromDecl(SemaRef
.getLangOpts(), VD
);
3822 if (SemaRef
.getLangOpts().OpenMP
>= 50) {
3823 bool IsModifierNone
= Stack
->getDefaultmapModifier(ClauseKind
) ==
3824 OMPC_DEFAULTMAP_MODIFIER_none
;
3825 if (DVar
.CKind
== OMPC_unknown
&& IsModifierNone
&&
3826 VarsWithInheritedDSA
.count(VD
) == 0 && !Res
) {
3827 // Only check for data-mapping attribute and is_device_ptr here
3828 // since we have already make sure that the declaration does not
3829 // have a data-sharing attribute above
3830 if (!Stack
->checkMappableExprComponentListsForDecl(
3831 VD
, /*CurrentRegionOnly=*/true,
3832 [VD
](OMPClauseMappableExprCommon::MappableExprComponentListRef
3835 auto MI
= MapExprComponents
.rbegin();
3836 auto ME
= MapExprComponents
.rend();
3837 return MI
!= ME
&& MI
->getAssociatedDeclaration() == VD
;
3839 VarsWithInheritedDSA
[VD
] = E
;
3844 if (SemaRef
.getLangOpts().OpenMP
> 50) {
3845 bool IsModifierPresent
= Stack
->getDefaultmapModifier(ClauseKind
) ==
3846 OMPC_DEFAULTMAP_MODIFIER_present
;
3847 if (IsModifierPresent
) {
3848 if (!llvm::is_contained(ImplicitMapModifier
[ClauseKind
],
3849 OMPC_MAP_MODIFIER_present
)) {
3850 ImplicitMapModifier
[ClauseKind
].push_back(
3851 OMPC_MAP_MODIFIER_present
);
3856 if (isOpenMPTargetExecutionDirective(DKind
) &&
3857 !Stack
->isLoopControlVariable(VD
).first
) {
3858 if (!Stack
->checkMappableExprComponentListsForDecl(
3859 VD
, /*CurrentRegionOnly=*/true,
3860 [this](OMPClauseMappableExprCommon::MappableExprComponentListRef
3863 if (SemaRef
.LangOpts
.OpenMP
>= 50)
3864 return !StackComponents
.empty();
3865 // Variable is used if it has been marked as an array, array
3866 // section, array shaping or the variable iself.
3867 return StackComponents
.size() == 1 ||
3869 llvm::drop_begin(llvm::reverse(StackComponents
)),
3870 [](const OMPClauseMappableExprCommon::
3871 MappableComponent
&MC
) {
3872 return MC
.getAssociatedDeclaration() ==
3874 (isa
<OMPArraySectionExpr
>(
3875 MC
.getAssociatedExpression()) ||
3876 isa
<OMPArrayShapingExpr
>(
3877 MC
.getAssociatedExpression()) ||
3878 isa
<ArraySubscriptExpr
>(
3879 MC
.getAssociatedExpression()));
3882 bool IsFirstprivate
= false;
3883 // By default lambdas are captured as firstprivates.
3884 if (const auto *RD
=
3885 VD
->getType().getNonReferenceType()->getAsCXXRecordDecl())
3886 IsFirstprivate
= RD
->isLambda();
3888 IsFirstprivate
|| (Stack
->mustBeFirstprivate(ClauseKind
) && !Res
);
3889 if (IsFirstprivate
) {
3890 ImplicitFirstprivate
.emplace_back(E
);
3892 OpenMPDefaultmapClauseModifier M
=
3893 Stack
->getDefaultmapModifier(ClauseKind
);
3894 OpenMPMapClauseKind Kind
= getMapClauseKindFromModifier(
3895 M
, ClauseKind
== OMPC_DEFAULTMAP_aggregate
|| Res
);
3896 ImplicitMap
[ClauseKind
][Kind
].emplace_back(E
);
3902 // OpenMP [2.9.3.6, Restrictions, p.2]
3903 // A list item that appears in a reduction clause of the innermost
3904 // enclosing worksharing or parallel construct may not be accessed in an
3906 DVar
= Stack
->hasInnermostDSA(
3908 [](OpenMPClauseKind C
, bool AppliedToPointee
) {
3909 return C
== OMPC_reduction
&& !AppliedToPointee
;
3911 [](OpenMPDirectiveKind K
) {
3912 return isOpenMPParallelDirective(K
) ||
3913 isOpenMPWorksharingDirective(K
) || isOpenMPTeamsDirective(K
);
3915 /*FromParent=*/true);
3916 if (isOpenMPTaskingDirective(DKind
) && DVar
.CKind
== OMPC_reduction
) {
3918 SemaRef
.Diag(ELoc
, diag::err_omp_reduction_in_task
);
3919 reportOriginalDsa(SemaRef
, Stack
, VD
, DVar
);
3923 // Define implicit data-sharing attributes for task.
3924 DVar
= Stack
->getImplicitDSA(VD
, /*FromParent=*/false);
3925 if (((isOpenMPTaskingDirective(DKind
) && DVar
.CKind
!= OMPC_shared
) ||
3926 (((Stack
->getDefaultDSA() == DSA_firstprivate
&&
3927 DVar
.CKind
== OMPC_firstprivate
) ||
3928 (Stack
->getDefaultDSA() == DSA_private
&&
3929 DVar
.CKind
== OMPC_private
)) &&
3931 !Stack
->isLoopControlVariable(VD
).first
) {
3932 if (Stack
->getDefaultDSA() == DSA_private
)
3933 ImplicitPrivate
.push_back(E
);
3935 ImplicitFirstprivate
.push_back(E
);
3939 // Store implicitly used globals with declare target link for parent
3941 if (!isOpenMPTargetExecutionDirective(DKind
) && Res
&&
3942 *Res
== OMPDeclareTargetDeclAttr::MT_Link
) {
3943 Stack
->addToParentTargetRegionLinkGlobals(E
);
3948 void VisitMemberExpr(MemberExpr
*E
) {
3949 if (E
->isTypeDependent() || E
->isValueDependent() ||
3950 E
->containsUnexpandedParameterPack() || E
->isInstantiationDependent())
3952 auto *FD
= dyn_cast
<FieldDecl
>(E
->getMemberDecl());
3953 OpenMPDirectiveKind DKind
= Stack
->getCurrentDirective();
3954 if (auto *TE
= dyn_cast
<CXXThisExpr
>(E
->getBase()->IgnoreParenCasts())) {
3957 DSAStackTy::DSAVarData DVar
= Stack
->getTopDSA(FD
, /*FromParent=*/false);
3958 // Check if the variable has explicit DSA set and stop analysis if it
3960 if (DVar
.RefExpr
|| !ImplicitDeclarations
.insert(FD
).second
)
3963 if (isOpenMPTargetExecutionDirective(DKind
) &&
3964 !Stack
->isLoopControlVariable(FD
).first
&&
3965 !Stack
->checkMappableExprComponentListsForDecl(
3966 FD
, /*CurrentRegionOnly=*/true,
3967 [](OMPClauseMappableExprCommon::MappableExprComponentListRef
3970 return isa
<CXXThisExpr
>(
3972 StackComponents
.back().getAssociatedExpression())
3976 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
3977 // A bit-field cannot appear in a map clause.
3979 if (FD
->isBitField())
3982 // Check to see if the member expression is referencing a class that
3983 // has already been explicitly mapped
3984 if (Stack
->isClassPreviouslyMapped(TE
->getType()))
3987 OpenMPDefaultmapClauseModifier Modifier
=
3988 Stack
->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate
);
3989 OpenMPDefaultmapClauseKind ClauseKind
=
3990 getVariableCategoryFromDecl(SemaRef
.getLangOpts(), FD
);
3991 OpenMPMapClauseKind Kind
= getMapClauseKindFromModifier(
3992 Modifier
, /*IsAggregateOrDeclareTarget*/ true);
3993 ImplicitMap
[ClauseKind
][Kind
].emplace_back(E
);
3997 SourceLocation ELoc
= E
->getExprLoc();
3998 // OpenMP [2.9.3.6, Restrictions, p.2]
3999 // A list item that appears in a reduction clause of the innermost
4000 // enclosing worksharing or parallel construct may not be accessed in
4001 // an explicit task.
4002 DVar
= Stack
->hasInnermostDSA(
4004 [](OpenMPClauseKind C
, bool AppliedToPointee
) {
4005 return C
== OMPC_reduction
&& !AppliedToPointee
;
4007 [](OpenMPDirectiveKind K
) {
4008 return isOpenMPParallelDirective(K
) ||
4009 isOpenMPWorksharingDirective(K
) || isOpenMPTeamsDirective(K
);
4011 /*FromParent=*/true);
4012 if (isOpenMPTaskingDirective(DKind
) && DVar
.CKind
== OMPC_reduction
) {
4014 SemaRef
.Diag(ELoc
, diag::err_omp_reduction_in_task
);
4015 reportOriginalDsa(SemaRef
, Stack
, FD
, DVar
);
4019 // Define implicit data-sharing attributes for task.
4020 DVar
= Stack
->getImplicitDSA(FD
, /*FromParent=*/false);
4021 if (isOpenMPTaskingDirective(DKind
) && DVar
.CKind
!= OMPC_shared
&&
4022 !Stack
->isLoopControlVariable(FD
).first
) {
4023 // Check if there is a captured expression for the current field in the
4024 // region. Do not mark it as firstprivate unless there is no captured
4026 // TODO: try to make it firstprivate.
4027 if (DVar
.CKind
!= OMPC_unknown
)
4028 ImplicitFirstprivate
.push_back(E
);
4032 if (isOpenMPTargetExecutionDirective(DKind
)) {
4033 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents
;
4034 if (!checkMapClauseExpressionBase(SemaRef
, E
, CurComponents
, OMPC_map
,
4035 Stack
->getCurrentDirective(),
4036 /*NoDiagnose=*/true))
4038 const auto *VD
= cast
<ValueDecl
>(
4039 CurComponents
.back().getAssociatedDeclaration()->getCanonicalDecl());
4040 if (!Stack
->checkMappableExprComponentListsForDecl(
4041 VD
, /*CurrentRegionOnly=*/true,
4043 OMPClauseMappableExprCommon::MappableExprComponentListRef
4046 auto CCI
= CurComponents
.rbegin();
4047 auto CCE
= CurComponents
.rend();
4048 for (const auto &SC
: llvm::reverse(StackComponents
)) {
4049 // Do both expressions have the same kind?
4050 if (CCI
->getAssociatedExpression()->getStmtClass() !=
4051 SC
.getAssociatedExpression()->getStmtClass())
4052 if (!((isa
<OMPArraySectionExpr
>(
4053 SC
.getAssociatedExpression()) ||
4054 isa
<OMPArrayShapingExpr
>(
4055 SC
.getAssociatedExpression())) &&
4056 isa
<ArraySubscriptExpr
>(
4057 CCI
->getAssociatedExpression())))
4060 const Decl
*CCD
= CCI
->getAssociatedDeclaration();
4061 const Decl
*SCD
= SC
.getAssociatedDeclaration();
4062 CCD
= CCD
? CCD
->getCanonicalDecl() : nullptr;
4063 SCD
= SCD
? SCD
->getCanonicalDecl() : nullptr;
4066 std::advance(CCI
, 1);
4072 Visit(E
->getBase());
4074 } else if (!TryCaptureCXXThisMembers
) {
4075 Visit(E
->getBase());
4078 void VisitOMPExecutableDirective(OMPExecutableDirective
*S
) {
4079 for (OMPClause
*C
: S
->clauses()) {
4080 // Skip analysis of arguments of private clauses for task|target
4082 if (isa_and_nonnull
<OMPPrivateClause
>(C
))
4084 // Skip analysis of arguments of implicitly defined firstprivate clause
4085 // for task|target directives.
4086 // Skip analysis of arguments of implicitly defined map clause for target
4088 if (C
&& !((isa
<OMPFirstprivateClause
>(C
) || isa
<OMPMapClause
>(C
)) &&
4090 !isOpenMPTaskingDirective(Stack
->getCurrentDirective()))) {
4091 for (Stmt
*CC
: C
->children()) {
4097 // Check implicitly captured variables.
4098 VisitSubCaptures(S
);
4101 void VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective
*S
) {
4102 // Loop transformation directives do not introduce data sharing
4106 void VisitCallExpr(CallExpr
*S
) {
4107 for (Stmt
*C
: S
->arguments()) {
4109 // Check implicitly captured variables in the task-based directives to
4110 // check if they must be firstprivatized.
4114 if (Expr
*Callee
= S
->getCallee()) {
4115 auto *CI
= Callee
->IgnoreParenImpCasts();
4116 if (auto *CE
= dyn_cast
<MemberExpr
>(CI
))
4117 Visit(CE
->getBase());
4118 else if (auto *CE
= dyn_cast
<DeclRefExpr
>(CI
))
4122 void VisitStmt(Stmt
*S
) {
4123 for (Stmt
*C
: S
->children()) {
4125 // Check implicitly captured variables in the task-based directives to
4126 // check if they must be firstprivatized.
4132 void visitSubCaptures(CapturedStmt
*S
) {
4133 for (const CapturedStmt::Capture
&Cap
: S
->captures()) {
4134 if (!Cap
.capturesVariable() && !Cap
.capturesVariableByCopy())
4136 VarDecl
*VD
= Cap
.getCapturedVar();
4137 // Do not try to map the variable if it or its sub-component was mapped
4139 if (isOpenMPTargetExecutionDirective(Stack
->getCurrentDirective()) &&
4140 Stack
->checkMappableExprComponentListsForDecl(
4141 VD
, /*CurrentRegionOnly=*/true,
4142 [](OMPClauseMappableExprCommon::MappableExprComponentListRef
,
4143 OpenMPClauseKind
) { return true; }))
4145 DeclRefExpr
*DRE
= buildDeclRefExpr(
4146 SemaRef
, VD
, VD
->getType().getNonLValueExprType(SemaRef
.Context
),
4147 Cap
.getLocation(), /*RefersToCapture=*/true);
4151 bool isErrorFound() const { return ErrorFound
; }
4152 ArrayRef
<Expr
*> getImplicitFirstprivate() const {
4153 return ImplicitFirstprivate
;
4155 ArrayRef
<Expr
*> getImplicitPrivate() const { return ImplicitPrivate
; }
4156 ArrayRef
<Expr
*> getImplicitMap(OpenMPDefaultmapClauseKind DK
,
4157 OpenMPMapClauseKind MK
) const {
4158 return ImplicitMap
[DK
][MK
];
4160 ArrayRef
<OpenMPMapModifierKind
>
4161 getImplicitMapModifier(OpenMPDefaultmapClauseKind Kind
) const {
4162 return ImplicitMapModifier
[Kind
];
4164 const Sema::VarsWithInheritedDSAType
&getVarsWithInheritedDSA() const {
4165 return VarsWithInheritedDSA
;
4168 DSAAttrChecker(DSAStackTy
*S
, Sema
&SemaRef
, CapturedStmt
*CS
)
4169 : Stack(S
), SemaRef(SemaRef
), ErrorFound(false), CS(CS
) {
4170 // Process declare target link variables for the target directives.
4171 if (isOpenMPTargetExecutionDirective(S
->getCurrentDirective())) {
4172 for (DeclRefExpr
*E
: Stack
->getLinkGlobals())
4179 static void handleDeclareVariantConstructTrait(DSAStackTy
*Stack
,
4180 OpenMPDirectiveKind DKind
,
4182 SmallVector
<llvm::omp::TraitProperty
, 8> Traits
;
4183 if (isOpenMPTargetExecutionDirective(DKind
))
4184 Traits
.emplace_back(llvm::omp::TraitProperty::construct_target_target
);
4185 if (isOpenMPTeamsDirective(DKind
))
4186 Traits
.emplace_back(llvm::omp::TraitProperty::construct_teams_teams
);
4187 if (isOpenMPParallelDirective(DKind
))
4188 Traits
.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel
);
4189 if (isOpenMPWorksharingDirective(DKind
))
4190 Traits
.emplace_back(llvm::omp::TraitProperty::construct_for_for
);
4191 if (isOpenMPSimdDirective(DKind
))
4192 Traits
.emplace_back(llvm::omp::TraitProperty::construct_simd_simd
);
4193 Stack
->handleConstructTrait(Traits
, ScopeEntry
);
4196 void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind
, Scope
*CurScope
) {
4199 case OMPD_parallel_for
:
4200 case OMPD_parallel_for_simd
:
4201 case OMPD_parallel_sections
:
4202 case OMPD_parallel_master
:
4203 case OMPD_parallel_masked
:
4204 case OMPD_parallel_loop
:
4206 case OMPD_teams_distribute
:
4207 case OMPD_teams_distribute_simd
: {
4208 QualType KmpInt32Ty
= Context
.getIntTypeForBitwidth(32, 1).withConst();
4209 QualType KmpInt32PtrTy
=
4210 Context
.getPointerType(KmpInt32Ty
).withConst().withRestrict();
4211 Sema::CapturedParamNameType Params
[] = {
4212 std::make_pair(".global_tid.", KmpInt32PtrTy
),
4213 std::make_pair(".bound_tid.", KmpInt32PtrTy
),
4214 std::make_pair(StringRef(), QualType()) // __context with shared vars
4216 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4220 case OMPD_target_teams
:
4221 case OMPD_target_parallel
:
4222 case OMPD_target_parallel_for
:
4223 case OMPD_target_parallel_for_simd
:
4224 case OMPD_target_parallel_loop
:
4225 case OMPD_target_teams_distribute
:
4226 case OMPD_target_teams_distribute_simd
: {
4227 QualType KmpInt32Ty
= Context
.getIntTypeForBitwidth(32, 1).withConst();
4228 QualType VoidPtrTy
= Context
.VoidPtrTy
.withConst().withRestrict();
4229 QualType KmpInt32PtrTy
=
4230 Context
.getPointerType(KmpInt32Ty
).withConst().withRestrict();
4231 QualType Args
[] = {VoidPtrTy
};
4232 FunctionProtoType::ExtProtoInfo EPI
;
4233 EPI
.Variadic
= true;
4234 QualType CopyFnType
= Context
.getFunctionType(Context
.VoidTy
, Args
, EPI
);
4235 Sema::CapturedParamNameType Params
[] = {
4236 std::make_pair(".global_tid.", KmpInt32Ty
),
4237 std::make_pair(".part_id.", KmpInt32PtrTy
),
4238 std::make_pair(".privates.", VoidPtrTy
),
4241 Context
.getPointerType(CopyFnType
).withConst().withRestrict()),
4242 std::make_pair(".task_t.", Context
.VoidPtrTy
.withConst()),
4243 std::make_pair(StringRef(), QualType()) // __context with shared vars
4245 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4246 Params
, /*OpenMPCaptureLevel=*/0);
4247 // Mark this captured region as inlined, because we don't use outlined
4248 // function directly.
4249 getCurCapturedRegion()->TheCapturedDecl
->addAttr(
4250 AlwaysInlineAttr::CreateImplicit(
4251 Context
, {}, AlwaysInlineAttr::Keyword_forceinline
));
4252 SmallVector
<Sema::CapturedParamNameType
, 2> ParamsTarget
;
4253 if (getLangOpts().OpenMPIsTargetDevice
)
4254 ParamsTarget
.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy
));
4255 ParamsTarget
.push_back(
4256 std::make_pair(StringRef(), QualType())); // __context with shared vars;
4257 // Start a captured region for 'target' with no implicit parameters.
4258 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4260 /*OpenMPCaptureLevel=*/1);
4261 Sema::CapturedParamNameType ParamsTeamsOrParallel
[] = {
4262 std::make_pair(".global_tid.", KmpInt32PtrTy
),
4263 std::make_pair(".bound_tid.", KmpInt32PtrTy
),
4264 std::make_pair(StringRef(), QualType()) // __context with shared vars
4266 // Start a captured region for 'teams' or 'parallel'. Both regions have
4267 // the same implicit parameters.
4268 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4269 ParamsTeamsOrParallel
, /*OpenMPCaptureLevel=*/2);
4273 case OMPD_target_simd
: {
4274 QualType KmpInt32Ty
= Context
.getIntTypeForBitwidth(32, 1).withConst();
4275 QualType VoidPtrTy
= Context
.VoidPtrTy
.withConst().withRestrict();
4276 QualType KmpInt32PtrTy
=
4277 Context
.getPointerType(KmpInt32Ty
).withConst().withRestrict();
4278 QualType Args
[] = {VoidPtrTy
};
4279 FunctionProtoType::ExtProtoInfo EPI
;
4280 EPI
.Variadic
= true;
4281 QualType CopyFnType
= Context
.getFunctionType(Context
.VoidTy
, Args
, EPI
);
4282 Sema::CapturedParamNameType Params
[] = {
4283 std::make_pair(".global_tid.", KmpInt32Ty
),
4284 std::make_pair(".part_id.", KmpInt32PtrTy
),
4285 std::make_pair(".privates.", VoidPtrTy
),
4288 Context
.getPointerType(CopyFnType
).withConst().withRestrict()),
4289 std::make_pair(".task_t.", Context
.VoidPtrTy
.withConst()),
4290 std::make_pair(StringRef(), QualType()) // __context with shared vars
4292 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4293 Params
, /*OpenMPCaptureLevel=*/0);
4294 // Mark this captured region as inlined, because we don't use outlined
4295 // function directly.
4296 getCurCapturedRegion()->TheCapturedDecl
->addAttr(
4297 AlwaysInlineAttr::CreateImplicit(
4298 Context
, {}, AlwaysInlineAttr::Keyword_forceinline
));
4299 SmallVector
<Sema::CapturedParamNameType
, 2> ParamsTarget
;
4300 if (getLangOpts().OpenMPIsTargetDevice
)
4301 ParamsTarget
.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy
));
4302 ParamsTarget
.push_back(
4303 std::make_pair(StringRef(), QualType())); // __context with shared vars;
4304 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4306 /*OpenMPCaptureLevel=*/1);
4318 // TODO: 'loop' may require additional parameters depending on the binding.
4319 // Treat similar to OMPD_simd/OMPD_for for now.
4325 case OMPD_taskgroup
:
4326 case OMPD_distribute
:
4327 case OMPD_distribute_simd
:
4330 case OMPD_target_data
:
4331 case OMPD_dispatch
: {
4332 Sema::CapturedParamNameType Params
[] = {
4333 std::make_pair(StringRef(), QualType()) // __context with shared vars
4335 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4340 QualType KmpInt32Ty
= Context
.getIntTypeForBitwidth(32, 1).withConst();
4341 QualType VoidPtrTy
= Context
.VoidPtrTy
.withConst().withRestrict();
4342 QualType KmpInt32PtrTy
=
4343 Context
.getPointerType(KmpInt32Ty
).withConst().withRestrict();
4344 QualType Args
[] = {VoidPtrTy
};
4345 FunctionProtoType::ExtProtoInfo EPI
;
4346 EPI
.Variadic
= true;
4347 QualType CopyFnType
= Context
.getFunctionType(Context
.VoidTy
, Args
, EPI
);
4348 Sema::CapturedParamNameType Params
[] = {
4349 std::make_pair(".global_tid.", KmpInt32Ty
),
4350 std::make_pair(".part_id.", KmpInt32PtrTy
),
4351 std::make_pair(".privates.", VoidPtrTy
),
4354 Context
.getPointerType(CopyFnType
).withConst().withRestrict()),
4355 std::make_pair(".task_t.", Context
.VoidPtrTy
.withConst()),
4356 std::make_pair(StringRef(), QualType()) // __context with shared vars
4358 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4360 // Mark this captured region as inlined, because we don't use outlined
4361 // function directly.
4362 getCurCapturedRegion()->TheCapturedDecl
->addAttr(
4363 AlwaysInlineAttr::CreateImplicit(
4364 Context
, {}, AlwaysInlineAttr::Keyword_forceinline
));
4368 case OMPD_taskloop_simd
:
4369 case OMPD_master_taskloop
:
4370 case OMPD_masked_taskloop
:
4371 case OMPD_masked_taskloop_simd
:
4372 case OMPD_master_taskloop_simd
: {
4373 QualType KmpInt32Ty
=
4374 Context
.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
4376 QualType KmpUInt64Ty
=
4377 Context
.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
4379 QualType KmpInt64Ty
=
4380 Context
.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
4382 QualType VoidPtrTy
= Context
.VoidPtrTy
.withConst().withRestrict();
4383 QualType KmpInt32PtrTy
=
4384 Context
.getPointerType(KmpInt32Ty
).withConst().withRestrict();
4385 QualType Args
[] = {VoidPtrTy
};
4386 FunctionProtoType::ExtProtoInfo EPI
;
4387 EPI
.Variadic
= true;
4388 QualType CopyFnType
= Context
.getFunctionType(Context
.VoidTy
, Args
, EPI
);
4389 Sema::CapturedParamNameType Params
[] = {
4390 std::make_pair(".global_tid.", KmpInt32Ty
),
4391 std::make_pair(".part_id.", KmpInt32PtrTy
),
4392 std::make_pair(".privates.", VoidPtrTy
),
4395 Context
.getPointerType(CopyFnType
).withConst().withRestrict()),
4396 std::make_pair(".task_t.", Context
.VoidPtrTy
.withConst()),
4397 std::make_pair(".lb.", KmpUInt64Ty
),
4398 std::make_pair(".ub.", KmpUInt64Ty
),
4399 std::make_pair(".st.", KmpInt64Ty
),
4400 std::make_pair(".liter.", KmpInt32Ty
),
4401 std::make_pair(".reductions.", VoidPtrTy
),
4402 std::make_pair(StringRef(), QualType()) // __context with shared vars
4404 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4406 // Mark this captured region as inlined, because we don't use outlined
4407 // function directly.
4408 getCurCapturedRegion()->TheCapturedDecl
->addAttr(
4409 AlwaysInlineAttr::CreateImplicit(
4410 Context
, {}, AlwaysInlineAttr::Keyword_forceinline
));
4413 case OMPD_parallel_masked_taskloop
:
4414 case OMPD_parallel_masked_taskloop_simd
:
4415 case OMPD_parallel_master_taskloop
:
4416 case OMPD_parallel_master_taskloop_simd
: {
4417 QualType KmpInt32Ty
=
4418 Context
.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
4420 QualType KmpUInt64Ty
=
4421 Context
.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
4423 QualType KmpInt64Ty
=
4424 Context
.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
4426 QualType VoidPtrTy
= Context
.VoidPtrTy
.withConst().withRestrict();
4427 QualType KmpInt32PtrTy
=
4428 Context
.getPointerType(KmpInt32Ty
).withConst().withRestrict();
4429 Sema::CapturedParamNameType ParamsParallel
[] = {
4430 std::make_pair(".global_tid.", KmpInt32PtrTy
),
4431 std::make_pair(".bound_tid.", KmpInt32PtrTy
),
4432 std::make_pair(StringRef(), QualType()) // __context with shared vars
4434 // Start a captured region for 'parallel'.
4435 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4436 ParamsParallel
, /*OpenMPCaptureLevel=*/0);
4437 QualType Args
[] = {VoidPtrTy
};
4438 FunctionProtoType::ExtProtoInfo EPI
;
4439 EPI
.Variadic
= true;
4440 QualType CopyFnType
= Context
.getFunctionType(Context
.VoidTy
, Args
, EPI
);
4441 Sema::CapturedParamNameType Params
[] = {
4442 std::make_pair(".global_tid.", KmpInt32Ty
),
4443 std::make_pair(".part_id.", KmpInt32PtrTy
),
4444 std::make_pair(".privates.", VoidPtrTy
),
4447 Context
.getPointerType(CopyFnType
).withConst().withRestrict()),
4448 std::make_pair(".task_t.", Context
.VoidPtrTy
.withConst()),
4449 std::make_pair(".lb.", KmpUInt64Ty
),
4450 std::make_pair(".ub.", KmpUInt64Ty
),
4451 std::make_pair(".st.", KmpInt64Ty
),
4452 std::make_pair(".liter.", KmpInt32Ty
),
4453 std::make_pair(".reductions.", VoidPtrTy
),
4454 std::make_pair(StringRef(), QualType()) // __context with shared vars
4456 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4457 Params
, /*OpenMPCaptureLevel=*/1);
4458 // Mark this captured region as inlined, because we don't use outlined
4459 // function directly.
4460 getCurCapturedRegion()->TheCapturedDecl
->addAttr(
4461 AlwaysInlineAttr::CreateImplicit(
4462 Context
, {}, AlwaysInlineAttr::Keyword_forceinline
));
4465 case OMPD_distribute_parallel_for_simd
:
4466 case OMPD_distribute_parallel_for
: {
4467 QualType KmpInt32Ty
= Context
.getIntTypeForBitwidth(32, 1).withConst();
4468 QualType KmpInt32PtrTy
=
4469 Context
.getPointerType(KmpInt32Ty
).withConst().withRestrict();
4470 Sema::CapturedParamNameType Params
[] = {
4471 std::make_pair(".global_tid.", KmpInt32PtrTy
),
4472 std::make_pair(".bound_tid.", KmpInt32PtrTy
),
4473 std::make_pair(".previous.lb.", Context
.getSizeType().withConst()),
4474 std::make_pair(".previous.ub.", Context
.getSizeType().withConst()),
4475 std::make_pair(StringRef(), QualType()) // __context with shared vars
4477 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4481 case OMPD_target_teams_loop
:
4482 case OMPD_target_teams_distribute_parallel_for
:
4483 case OMPD_target_teams_distribute_parallel_for_simd
: {
4484 QualType KmpInt32Ty
= Context
.getIntTypeForBitwidth(32, 1).withConst();
4485 QualType KmpInt32PtrTy
=
4486 Context
.getPointerType(KmpInt32Ty
).withConst().withRestrict();
4487 QualType VoidPtrTy
= Context
.VoidPtrTy
.withConst().withRestrict();
4489 QualType Args
[] = {VoidPtrTy
};
4490 FunctionProtoType::ExtProtoInfo EPI
;
4491 EPI
.Variadic
= true;
4492 QualType CopyFnType
= Context
.getFunctionType(Context
.VoidTy
, Args
, EPI
);
4493 Sema::CapturedParamNameType Params
[] = {
4494 std::make_pair(".global_tid.", KmpInt32Ty
),
4495 std::make_pair(".part_id.", KmpInt32PtrTy
),
4496 std::make_pair(".privates.", VoidPtrTy
),
4499 Context
.getPointerType(CopyFnType
).withConst().withRestrict()),
4500 std::make_pair(".task_t.", Context
.VoidPtrTy
.withConst()),
4501 std::make_pair(StringRef(), QualType()) // __context with shared vars
4503 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4504 Params
, /*OpenMPCaptureLevel=*/0);
4505 // Mark this captured region as inlined, because we don't use outlined
4506 // function directly.
4507 getCurCapturedRegion()->TheCapturedDecl
->addAttr(
4508 AlwaysInlineAttr::CreateImplicit(
4509 Context
, {}, AlwaysInlineAttr::Keyword_forceinline
));
4510 SmallVector
<Sema::CapturedParamNameType
, 2> ParamsTarget
;
4511 if (getLangOpts().OpenMPIsTargetDevice
)
4512 ParamsTarget
.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy
));
4513 ParamsTarget
.push_back(
4514 std::make_pair(StringRef(), QualType())); // __context with shared vars;
4515 // Start a captured region for 'target' with no implicit parameters.
4516 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4517 ParamsTarget
, /*OpenMPCaptureLevel=*/1);
4519 Sema::CapturedParamNameType ParamsTeams
[] = {
4520 std::make_pair(".global_tid.", KmpInt32PtrTy
),
4521 std::make_pair(".bound_tid.", KmpInt32PtrTy
),
4522 std::make_pair(StringRef(), QualType()) // __context with shared vars
4524 // Start a captured region for 'target' with no implicit parameters.
4525 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4526 ParamsTeams
, /*OpenMPCaptureLevel=*/2);
4528 Sema::CapturedParamNameType ParamsParallel
[] = {
4529 std::make_pair(".global_tid.", KmpInt32PtrTy
),
4530 std::make_pair(".bound_tid.", KmpInt32PtrTy
),
4531 std::make_pair(".previous.lb.", Context
.getSizeType().withConst()),
4532 std::make_pair(".previous.ub.", Context
.getSizeType().withConst()),
4533 std::make_pair(StringRef(), QualType()) // __context with shared vars
4535 // Start a captured region for 'teams' or 'parallel'. Both regions have
4536 // the same implicit parameters.
4537 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4538 ParamsParallel
, /*OpenMPCaptureLevel=*/3);
4542 case OMPD_teams_loop
:
4543 case OMPD_teams_distribute_parallel_for
:
4544 case OMPD_teams_distribute_parallel_for_simd
: {
4545 QualType KmpInt32Ty
= Context
.getIntTypeForBitwidth(32, 1).withConst();
4546 QualType KmpInt32PtrTy
=
4547 Context
.getPointerType(KmpInt32Ty
).withConst().withRestrict();
4549 Sema::CapturedParamNameType ParamsTeams
[] = {
4550 std::make_pair(".global_tid.", KmpInt32PtrTy
),
4551 std::make_pair(".bound_tid.", KmpInt32PtrTy
),
4552 std::make_pair(StringRef(), QualType()) // __context with shared vars
4554 // Start a captured region for 'target' with no implicit parameters.
4555 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4556 ParamsTeams
, /*OpenMPCaptureLevel=*/0);
4558 Sema::CapturedParamNameType ParamsParallel
[] = {
4559 std::make_pair(".global_tid.", KmpInt32PtrTy
),
4560 std::make_pair(".bound_tid.", KmpInt32PtrTy
),
4561 std::make_pair(".previous.lb.", Context
.getSizeType().withConst()),
4562 std::make_pair(".previous.ub.", Context
.getSizeType().withConst()),
4563 std::make_pair(StringRef(), QualType()) // __context with shared vars
4565 // Start a captured region for 'teams' or 'parallel'. Both regions have
4566 // the same implicit parameters.
4567 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4568 ParamsParallel
, /*OpenMPCaptureLevel=*/1);
4571 case OMPD_target_update
:
4572 case OMPD_target_enter_data
:
4573 case OMPD_target_exit_data
: {
4574 QualType KmpInt32Ty
= Context
.getIntTypeForBitwidth(32, 1).withConst();
4575 QualType VoidPtrTy
= Context
.VoidPtrTy
.withConst().withRestrict();
4576 QualType KmpInt32PtrTy
=
4577 Context
.getPointerType(KmpInt32Ty
).withConst().withRestrict();
4578 QualType Args
[] = {VoidPtrTy
};
4579 FunctionProtoType::ExtProtoInfo EPI
;
4580 EPI
.Variadic
= true;
4581 QualType CopyFnType
= Context
.getFunctionType(Context
.VoidTy
, Args
, EPI
);
4582 Sema::CapturedParamNameType Params
[] = {
4583 std::make_pair(".global_tid.", KmpInt32Ty
),
4584 std::make_pair(".part_id.", KmpInt32PtrTy
),
4585 std::make_pair(".privates.", VoidPtrTy
),
4588 Context
.getPointerType(CopyFnType
).withConst().withRestrict()),
4589 std::make_pair(".task_t.", Context
.VoidPtrTy
.withConst()),
4590 std::make_pair(StringRef(), QualType()) // __context with shared vars
4592 ActOnCapturedRegionStart(DSAStack
->getConstructLoc(), CurScope
, CR_OpenMP
,
4594 // Mark this captured region as inlined, because we don't use outlined
4595 // function directly.
4596 getCurCapturedRegion()->TheCapturedDecl
->addAttr(
4597 AlwaysInlineAttr::CreateImplicit(
4598 Context
, {}, AlwaysInlineAttr::Keyword_forceinline
));
4601 case OMPD_threadprivate
:
4603 case OMPD_taskyield
:
4607 case OMPD_cancellation_point
:
4612 case OMPD_declare_reduction
:
4613 case OMPD_declare_mapper
:
4614 case OMPD_declare_simd
:
4615 case OMPD_declare_target
:
4616 case OMPD_end_declare_target
:
4618 case OMPD_declare_variant
:
4619 case OMPD_begin_declare_variant
:
4620 case OMPD_end_declare_variant
:
4621 case OMPD_metadirective
:
4622 llvm_unreachable("OpenMP Directive is not allowed");
4625 llvm_unreachable("Unknown OpenMP directive");
4627 DSAStack
->setContext(CurContext
);
4628 handleDeclareVariantConstructTrait(DSAStack
, DKind
, /* ScopeEntry */ true);
4631 int Sema::getNumberOfConstructScopes(unsigned Level
) const {
4632 return getOpenMPCaptureLevels(DSAStack
->getDirective(Level
));
4635 int Sema::getOpenMPCaptureLevels(OpenMPDirectiveKind DKind
) {
4636 SmallVector
<OpenMPDirectiveKind
, 4> CaptureRegions
;
4637 getOpenMPCaptureRegions(CaptureRegions
, DKind
);
4638 return CaptureRegions
.size();
4641 static OMPCapturedExprDecl
*buildCaptureDecl(Sema
&S
, IdentifierInfo
*Id
,
4642 Expr
*CaptureExpr
, bool WithInit
,
4643 DeclContext
*CurContext
,
4644 bool AsExpression
) {
4645 assert(CaptureExpr
);
4646 ASTContext
&C
= S
.getASTContext();
4647 Expr
*Init
= AsExpression
? CaptureExpr
: CaptureExpr
->IgnoreImpCasts();
4648 QualType Ty
= Init
->getType();
4649 if (CaptureExpr
->getObjectKind() == OK_Ordinary
&& CaptureExpr
->isGLValue()) {
4650 if (S
.getLangOpts().CPlusPlus
) {
4651 Ty
= C
.getLValueReferenceType(Ty
);
4653 Ty
= C
.getPointerType(Ty
);
4655 S
.CreateBuiltinUnaryOp(CaptureExpr
->getExprLoc(), UO_AddrOf
, Init
);
4656 if (!Res
.isUsable())
4662 auto *CED
= OMPCapturedExprDecl::Create(C
, CurContext
, Id
, Ty
,
4663 CaptureExpr
->getBeginLoc());
4665 CED
->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C
));
4666 CurContext
->addHiddenDecl(CED
);
4667 Sema::TentativeAnalysisScope
Trap(S
);
4668 S
.AddInitializerToDecl(CED
, Init
, /*DirectInit=*/false);
4672 static DeclRefExpr
*buildCapture(Sema
&S
, ValueDecl
*D
, Expr
*CaptureExpr
,
4674 OMPCapturedExprDecl
*CD
;
4675 if (VarDecl
*VD
= S
.isOpenMPCapturedDecl(D
))
4676 CD
= cast
<OMPCapturedExprDecl
>(VD
);
4678 CD
= buildCaptureDecl(S
, D
->getIdentifier(), CaptureExpr
, WithInit
,
4680 /*AsExpression=*/false);
4681 return buildDeclRefExpr(S
, CD
, CD
->getType().getNonReferenceType(),
4682 CaptureExpr
->getExprLoc());
4685 static ExprResult
buildCapture(Sema
&S
, Expr
*CaptureExpr
, DeclRefExpr
*&Ref
,
4687 CaptureExpr
= S
.DefaultLvalueConversion(CaptureExpr
).get();
4689 OMPCapturedExprDecl
*CD
= buildCaptureDecl(
4690 S
, &S
.getASTContext().Idents
.get(Name
), CaptureExpr
,
4691 /*WithInit=*/true, S
.CurContext
, /*AsExpression=*/true);
4692 Ref
= buildDeclRefExpr(S
, CD
, CD
->getType().getNonReferenceType(),
4693 CaptureExpr
->getExprLoc());
4695 ExprResult Res
= Ref
;
4696 if (!S
.getLangOpts().CPlusPlus
&&
4697 CaptureExpr
->getObjectKind() == OK_Ordinary
&& CaptureExpr
->isGLValue() &&
4698 Ref
->getType()->isPointerType()) {
4699 Res
= S
.CreateBuiltinUnaryOp(CaptureExpr
->getExprLoc(), UO_Deref
, Ref
);
4700 if (!Res
.isUsable())
4703 return S
.DefaultLvalueConversion(Res
.get());
4707 // OpenMP directives parsed in this section are represented as a
4708 // CapturedStatement with an associated statement. If a syntax error
4709 // is detected during the parsing of the associated statement, the
4710 // compiler must abort processing and close the CapturedStatement.
4712 // Combined directives such as 'target parallel' have more than one
4713 // nested CapturedStatements. This RAII ensures that we unwind out
4714 // of all the nested CapturedStatements when an error is found.
4715 class CaptureRegionUnwinderRAII
{
4719 OpenMPDirectiveKind DKind
= OMPD_unknown
;
4722 CaptureRegionUnwinderRAII(Sema
&S
, bool &ErrorFound
,
4723 OpenMPDirectiveKind DKind
)
4724 : S(S
), ErrorFound(ErrorFound
), DKind(DKind
) {}
4725 ~CaptureRegionUnwinderRAII() {
4727 int ThisCaptureLevel
= S
.getOpenMPCaptureLevels(DKind
);
4728 while (--ThisCaptureLevel
>= 0)
4729 S
.ActOnCapturedRegionError();
4735 void Sema::tryCaptureOpenMPLambdas(ValueDecl
*V
) {
4736 // Capture variables captured by reference in lambdas for target-based
4738 if (!CurContext
->isDependentContext() &&
4739 (isOpenMPTargetExecutionDirective(DSAStack
->getCurrentDirective()) ||
4740 isOpenMPTargetDataManagementDirective(
4741 DSAStack
->getCurrentDirective()))) {
4742 QualType Type
= V
->getType();
4743 if (const auto *RD
= Type
.getCanonicalType()
4744 .getNonReferenceType()
4745 ->getAsCXXRecordDecl()) {
4746 bool SavedForceCaptureByReferenceInTargetExecutable
=
4747 DSAStack
->isForceCaptureByReferenceInTargetExecutable();
4748 DSAStack
->setForceCaptureByReferenceInTargetExecutable(
4750 if (RD
->isLambda()) {
4751 llvm::DenseMap
<const ValueDecl
*, FieldDecl
*> Captures
;
4752 FieldDecl
*ThisCapture
;
4753 RD
->getCaptureFields(Captures
, ThisCapture
);
4754 for (const LambdaCapture
&LC
: RD
->captures()) {
4755 if (LC
.getCaptureKind() == LCK_ByRef
) {
4756 VarDecl
*VD
= cast
<VarDecl
>(LC
.getCapturedVar());
4757 DeclContext
*VDC
= VD
->getDeclContext();
4758 if (!VDC
->Encloses(CurContext
))
4760 MarkVariableReferenced(LC
.getLocation(), VD
);
4761 } else if (LC
.getCaptureKind() == LCK_This
) {
4762 QualType ThisTy
= getCurrentThisType();
4763 if (!ThisTy
.isNull() &&
4764 Context
.typesAreCompatible(ThisTy
, ThisCapture
->getType()))
4765 CheckCXXThisCapture(LC
.getLocation());
4769 DSAStack
->setForceCaptureByReferenceInTargetExecutable(
4770 SavedForceCaptureByReferenceInTargetExecutable
);
4775 static bool checkOrderedOrderSpecified(Sema
&S
,
4776 const ArrayRef
<OMPClause
*> Clauses
) {
4777 const OMPOrderedClause
*Ordered
= nullptr;
4778 const OMPOrderClause
*Order
= nullptr;
4780 for (const OMPClause
*Clause
: Clauses
) {
4781 if (Clause
->getClauseKind() == OMPC_ordered
)
4782 Ordered
= cast
<OMPOrderedClause
>(Clause
);
4783 else if (Clause
->getClauseKind() == OMPC_order
) {
4784 Order
= cast
<OMPOrderClause
>(Clause
);
4785 if (Order
->getKind() != OMPC_ORDER_concurrent
)
4788 if (Ordered
&& Order
)
4792 if (Ordered
&& Order
) {
4793 S
.Diag(Order
->getKindKwLoc(),
4794 diag::err_omp_simple_clause_incompatible_with_ordered
)
4795 << getOpenMPClauseName(OMPC_order
)
4796 << getOpenMPSimpleClauseTypeName(OMPC_order
, OMPC_ORDER_concurrent
)
4797 << SourceRange(Order
->getBeginLoc(), Order
->getEndLoc());
4798 S
.Diag(Ordered
->getBeginLoc(), diag::note_omp_ordered_param
)
4799 << 0 << SourceRange(Ordered
->getBeginLoc(), Ordered
->getEndLoc());
4805 StmtResult
Sema::ActOnOpenMPRegionEnd(StmtResult S
,
4806 ArrayRef
<OMPClause
*> Clauses
) {
4807 handleDeclareVariantConstructTrait(DSAStack
, DSAStack
->getCurrentDirective(),
4808 /* ScopeEntry */ false);
4809 if (DSAStack
->getCurrentDirective() == OMPD_atomic
||
4810 DSAStack
->getCurrentDirective() == OMPD_critical
||
4811 DSAStack
->getCurrentDirective() == OMPD_section
||
4812 DSAStack
->getCurrentDirective() == OMPD_master
||
4813 DSAStack
->getCurrentDirective() == OMPD_masked
)
4816 bool ErrorFound
= false;
4817 CaptureRegionUnwinderRAII
CaptureRegionUnwinder(
4818 *this, ErrorFound
, DSAStack
->getCurrentDirective());
4819 if (!S
.isUsable()) {
4824 SmallVector
<OpenMPDirectiveKind
, 4> CaptureRegions
;
4825 getOpenMPCaptureRegions(CaptureRegions
, DSAStack
->getCurrentDirective());
4826 OMPOrderedClause
*OC
= nullptr;
4827 OMPScheduleClause
*SC
= nullptr;
4828 SmallVector
<const OMPLinearClause
*, 4> LCs
;
4829 SmallVector
<const OMPClauseWithPreInit
*, 4> PICs
;
4830 // This is required for proper codegen.
4831 for (OMPClause
*Clause
: Clauses
) {
4832 if (!LangOpts
.OpenMPSimd
&&
4833 (isOpenMPTaskingDirective(DSAStack
->getCurrentDirective()) ||
4834 DSAStack
->getCurrentDirective() == OMPD_target
) &&
4835 Clause
->getClauseKind() == OMPC_in_reduction
) {
4836 // Capture taskgroup task_reduction descriptors inside the tasking regions
4837 // with the corresponding in_reduction items.
4838 auto *IRC
= cast
<OMPInReductionClause
>(Clause
);
4839 for (Expr
*E
: IRC
->taskgroup_descriptors())
4841 MarkDeclarationsReferencedInExpr(E
);
4843 if (isOpenMPPrivate(Clause
->getClauseKind()) ||
4844 Clause
->getClauseKind() == OMPC_copyprivate
||
4845 (getLangOpts().OpenMPUseTLS
&&
4846 getASTContext().getTargetInfo().isTLSSupported() &&
4847 Clause
->getClauseKind() == OMPC_copyin
)) {
4848 DSAStack
->setForceVarCapturing(Clause
->getClauseKind() == OMPC_copyin
);
4849 // Mark all variables in private list clauses as used in inner region.
4850 for (Stmt
*VarRef
: Clause
->children()) {
4851 if (auto *E
= cast_or_null
<Expr
>(VarRef
)) {
4852 MarkDeclarationsReferencedInExpr(E
);
4855 DSAStack
->setForceVarCapturing(/*V=*/false);
4856 } else if (isOpenMPLoopTransformationDirective(
4857 DSAStack
->getCurrentDirective())) {
4858 assert(CaptureRegions
.empty() &&
4859 "No captured regions in loop transformation directives.");
4860 } else if (CaptureRegions
.size() > 1 ||
4861 CaptureRegions
.back() != OMPD_unknown
) {
4862 if (auto *C
= OMPClauseWithPreInit::get(Clause
))
4864 if (auto *C
= OMPClauseWithPostUpdate::get(Clause
)) {
4865 if (Expr
*E
= C
->getPostUpdateExpr())
4866 MarkDeclarationsReferencedInExpr(E
);
4869 if (Clause
->getClauseKind() == OMPC_schedule
)
4870 SC
= cast
<OMPScheduleClause
>(Clause
);
4871 else if (Clause
->getClauseKind() == OMPC_ordered
)
4872 OC
= cast
<OMPOrderedClause
>(Clause
);
4873 else if (Clause
->getClauseKind() == OMPC_linear
)
4874 LCs
.push_back(cast
<OMPLinearClause
>(Clause
));
4876 // Capture allocator expressions if used.
4877 for (Expr
*E
: DSAStack
->getInnerAllocators())
4878 MarkDeclarationsReferencedInExpr(E
);
4879 // OpenMP, 2.7.1 Loop Construct, Restrictions
4880 // The nonmonotonic modifier cannot be specified if an ordered clause is
4883 (SC
->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
||
4884 SC
->getSecondScheduleModifier() ==
4885 OMPC_SCHEDULE_MODIFIER_nonmonotonic
) &&
4887 Diag(SC
->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4888 ? SC
->getFirstScheduleModifierLoc()
4889 : SC
->getSecondScheduleModifierLoc(),
4890 diag::err_omp_simple_clause_incompatible_with_ordered
)
4891 << getOpenMPClauseName(OMPC_schedule
)
4892 << getOpenMPSimpleClauseTypeName(OMPC_schedule
,
4893 OMPC_SCHEDULE_MODIFIER_nonmonotonic
)
4894 << SourceRange(OC
->getBeginLoc(), OC
->getEndLoc());
4897 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4898 // If an order(concurrent) clause is present, an ordered clause may not appear
4899 // on the same directive.
4900 if (checkOrderedOrderSpecified(*this, Clauses
))
4902 if (!LCs
.empty() && OC
&& OC
->getNumForLoops()) {
4903 for (const OMPLinearClause
*C
: LCs
) {
4904 Diag(C
->getBeginLoc(), diag::err_omp_linear_ordered
)
4905 << SourceRange(OC
->getBeginLoc(), OC
->getEndLoc());
4909 if (isOpenMPWorksharingDirective(DSAStack
->getCurrentDirective()) &&
4910 isOpenMPSimdDirective(DSAStack
->getCurrentDirective()) && OC
&&
4911 OC
->getNumForLoops()) {
4912 Diag(OC
->getBeginLoc(), diag::err_omp_ordered_simd
)
4913 << getOpenMPDirectiveName(DSAStack
->getCurrentDirective());
4920 unsigned CompletedRegions
= 0;
4921 for (OpenMPDirectiveKind ThisCaptureRegion
: llvm::reverse(CaptureRegions
)) {
4922 // Mark all variables in private list clauses as used in inner region.
4923 // Required for proper codegen of combined directives.
4924 // TODO: add processing for other clauses.
4925 if (ThisCaptureRegion
!= OMPD_unknown
) {
4926 for (const clang::OMPClauseWithPreInit
*C
: PICs
) {
4927 OpenMPDirectiveKind CaptureRegion
= C
->getCaptureRegion();
4928 // Find the particular capture region for the clause if the
4929 // directive is a combined one with multiple capture regions.
4930 // If the directive is not a combined one, the capture region
4931 // associated with the clause is OMPD_unknown and is generated
4933 if (CaptureRegion
== ThisCaptureRegion
||
4934 CaptureRegion
== OMPD_unknown
) {
4935 if (auto *DS
= cast_or_null
<DeclStmt
>(C
->getPreInitStmt())) {
4936 for (Decl
*D
: DS
->decls())
4937 MarkVariableReferenced(D
->getLocation(), cast
<VarDecl
>(D
));
4942 if (ThisCaptureRegion
== OMPD_target
) {
4943 // Capture allocator traits in the target region. They are used implicitly
4944 // and, thus, are not captured by default.
4945 for (OMPClause
*C
: Clauses
) {
4946 if (const auto *UAC
= dyn_cast
<OMPUsesAllocatorsClause
>(C
)) {
4947 for (unsigned I
= 0, End
= UAC
->getNumberOfAllocators(); I
< End
;
4949 OMPUsesAllocatorsClause::Data D
= UAC
->getAllocatorData(I
);
4950 if (Expr
*E
= D
.AllocatorTraits
)
4951 MarkDeclarationsReferencedInExpr(E
);
4957 if (ThisCaptureRegion
== OMPD_parallel
) {
4958 // Capture temp arrays for inscan reductions and locals in aligned
4960 for (OMPClause
*C
: Clauses
) {
4961 if (auto *RC
= dyn_cast
<OMPReductionClause
>(C
)) {
4962 if (RC
->getModifier() != OMPC_REDUCTION_inscan
)
4964 for (Expr
*E
: RC
->copy_array_temps())
4965 MarkDeclarationsReferencedInExpr(E
);
4967 if (auto *AC
= dyn_cast
<OMPAlignedClause
>(C
)) {
4968 for (Expr
*E
: AC
->varlists())
4969 MarkDeclarationsReferencedInExpr(E
);
4973 if (++CompletedRegions
== CaptureRegions
.size())
4974 DSAStack
->setBodyComplete();
4975 SR
= ActOnCapturedRegionEnd(SR
.get());
4980 static bool checkCancelRegion(Sema
&SemaRef
, OpenMPDirectiveKind CurrentRegion
,
4981 OpenMPDirectiveKind CancelRegion
,
4982 SourceLocation StartLoc
) {
4983 // CancelRegion is only needed for cancel and cancellation_point.
4984 if (CurrentRegion
!= OMPD_cancel
&& CurrentRegion
!= OMPD_cancellation_point
)
4987 if (CancelRegion
== OMPD_parallel
|| CancelRegion
== OMPD_for
||
4988 CancelRegion
== OMPD_sections
|| CancelRegion
== OMPD_taskgroup
)
4991 SemaRef
.Diag(StartLoc
, diag::err_omp_wrong_cancel_region
)
4992 << getOpenMPDirectiveName(CancelRegion
);
4996 static bool checkNestingOfRegions(Sema
&SemaRef
, const DSAStackTy
*Stack
,
4997 OpenMPDirectiveKind CurrentRegion
,
4998 const DeclarationNameInfo
&CurrentName
,
4999 OpenMPDirectiveKind CancelRegion
,
5000 OpenMPBindClauseKind BindKind
,
5001 SourceLocation StartLoc
) {
5002 if (Stack
->getCurScope()) {
5003 OpenMPDirectiveKind ParentRegion
= Stack
->getParentDirective();
5004 OpenMPDirectiveKind OffendingRegion
= ParentRegion
;
5005 bool NestingProhibited
= false;
5006 bool CloseNesting
= true;
5007 bool OrphanSeen
= false;
5010 ShouldBeInParallelRegion
,
5011 ShouldBeInOrderedRegion
,
5012 ShouldBeInTargetRegion
,
5013 ShouldBeInTeamsRegion
,
5014 ShouldBeInLoopSimdRegion
,
5015 } Recommend
= NoRecommend
;
5016 if (SemaRef
.LangOpts
.OpenMP
>= 51 && Stack
->isParentOrderConcurrent() &&
5017 CurrentRegion
!= OMPD_simd
&& CurrentRegion
!= OMPD_loop
&&
5018 CurrentRegion
!= OMPD_parallel
&&
5019 !isOpenMPCombinedParallelADirective(CurrentRegion
)) {
5020 SemaRef
.Diag(StartLoc
, diag::err_omp_prohibited_region_order
)
5021 << getOpenMPDirectiveName(CurrentRegion
);
5024 if (isOpenMPSimdDirective(ParentRegion
) &&
5025 ((SemaRef
.LangOpts
.OpenMP
<= 45 && CurrentRegion
!= OMPD_ordered
) ||
5026 (SemaRef
.LangOpts
.OpenMP
>= 50 && CurrentRegion
!= OMPD_ordered
&&
5027 CurrentRegion
!= OMPD_simd
&& CurrentRegion
!= OMPD_atomic
&&
5028 CurrentRegion
!= OMPD_scan
))) {
5029 // OpenMP [2.16, Nesting of Regions]
5030 // OpenMP constructs may not be nested inside a simd region.
5031 // OpenMP [2.8.1,simd Construct, Restrictions]
5032 // An ordered construct with the simd clause is the only OpenMP
5033 // construct that can appear in the simd region.
5034 // Allowing a SIMD construct nested in another SIMD construct is an
5035 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
5037 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
5038 // The only OpenMP constructs that can be encountered during execution of
5039 // a simd region are the atomic construct, the loop construct, the simd
5040 // construct and the ordered construct with the simd clause.
5041 SemaRef
.Diag(StartLoc
, (CurrentRegion
!= OMPD_simd
)
5042 ? diag::err_omp_prohibited_region_simd
5043 : diag::warn_omp_nesting_simd
)
5044 << (SemaRef
.LangOpts
.OpenMP
>= 50 ? 1 : 0);
5045 return CurrentRegion
!= OMPD_simd
;
5047 if (ParentRegion
== OMPD_atomic
) {
5048 // OpenMP [2.16, Nesting of Regions]
5049 // OpenMP constructs may not be nested inside an atomic region.
5050 SemaRef
.Diag(StartLoc
, diag::err_omp_prohibited_region_atomic
);
5053 if (CurrentRegion
== OMPD_section
) {
5054 // OpenMP [2.7.2, sections Construct, Restrictions]
5055 // Orphaned section directives are prohibited. That is, the section
5056 // directives must appear within the sections construct and must not be
5057 // encountered elsewhere in the sections region.
5058 if (ParentRegion
!= OMPD_sections
&&
5059 ParentRegion
!= OMPD_parallel_sections
) {
5060 SemaRef
.Diag(StartLoc
, diag::err_omp_orphaned_section_directive
)
5061 << (ParentRegion
!= OMPD_unknown
)
5062 << getOpenMPDirectiveName(ParentRegion
);
5067 // Allow some constructs (except teams and cancellation constructs) to be
5068 // orphaned (they could be used in functions, called from OpenMP regions
5069 // with the required preconditions).
5070 if (ParentRegion
== OMPD_unknown
&&
5071 !isOpenMPNestingTeamsDirective(CurrentRegion
) &&
5072 CurrentRegion
!= OMPD_cancellation_point
&&
5073 CurrentRegion
!= OMPD_cancel
&& CurrentRegion
!= OMPD_scan
)
5075 if (CurrentRegion
== OMPD_cancellation_point
||
5076 CurrentRegion
== OMPD_cancel
) {
5077 // OpenMP [2.16, Nesting of Regions]
5078 // A cancellation point construct for which construct-type-clause is
5079 // taskgroup must be nested inside a task construct. A cancellation
5080 // point construct for which construct-type-clause is not taskgroup must
5081 // be closely nested inside an OpenMP construct that matches the type
5082 // specified in construct-type-clause.
5083 // A cancel construct for which construct-type-clause is taskgroup must be
5084 // nested inside a task construct. A cancel construct for which
5085 // construct-type-clause is not taskgroup must be closely nested inside an
5086 // OpenMP construct that matches the type specified in
5087 // construct-type-clause.
5089 !((CancelRegion
== OMPD_parallel
&&
5090 (ParentRegion
== OMPD_parallel
||
5091 ParentRegion
== OMPD_target_parallel
)) ||
5092 (CancelRegion
== OMPD_for
&&
5093 (ParentRegion
== OMPD_for
|| ParentRegion
== OMPD_parallel_for
||
5094 ParentRegion
== OMPD_target_parallel_for
||
5095 ParentRegion
== OMPD_distribute_parallel_for
||
5096 ParentRegion
== OMPD_teams_distribute_parallel_for
||
5097 ParentRegion
== OMPD_target_teams_distribute_parallel_for
)) ||
5098 (CancelRegion
== OMPD_taskgroup
&&
5099 (ParentRegion
== OMPD_task
||
5100 (SemaRef
.getLangOpts().OpenMP
>= 50 &&
5101 (ParentRegion
== OMPD_taskloop
||
5102 ParentRegion
== OMPD_master_taskloop
||
5103 ParentRegion
== OMPD_masked_taskloop
||
5104 ParentRegion
== OMPD_parallel_masked_taskloop
||
5105 ParentRegion
== OMPD_parallel_master_taskloop
)))) ||
5106 (CancelRegion
== OMPD_sections
&&
5107 (ParentRegion
== OMPD_section
|| ParentRegion
== OMPD_sections
||
5108 ParentRegion
== OMPD_parallel_sections
)));
5109 OrphanSeen
= ParentRegion
== OMPD_unknown
;
5110 } else if (CurrentRegion
== OMPD_master
|| CurrentRegion
== OMPD_masked
) {
5111 // OpenMP 5.1 [2.22, Nesting of Regions]
5112 // A masked region may not be closely nested inside a worksharing, loop,
5113 // atomic, task, or taskloop region.
5114 NestingProhibited
= isOpenMPWorksharingDirective(ParentRegion
) ||
5115 isOpenMPGenericLoopDirective(ParentRegion
) ||
5116 isOpenMPTaskingDirective(ParentRegion
);
5117 } else if (CurrentRegion
== OMPD_critical
&& CurrentName
.getName()) {
5118 // OpenMP [2.16, Nesting of Regions]
5119 // A critical region may not be nested (closely or otherwise) inside a
5120 // critical region with the same name. Note that this restriction is not
5121 // sufficient to prevent deadlock.
5122 SourceLocation PreviousCriticalLoc
;
5123 bool DeadLock
= Stack
->hasDirective(
5124 [CurrentName
, &PreviousCriticalLoc
](OpenMPDirectiveKind K
,
5125 const DeclarationNameInfo
&DNI
,
5126 SourceLocation Loc
) {
5127 if (K
== OMPD_critical
&& DNI
.getName() == CurrentName
.getName()) {
5128 PreviousCriticalLoc
= Loc
;
5133 false /* skip top directive */);
5135 SemaRef
.Diag(StartLoc
,
5136 diag::err_omp_prohibited_region_critical_same_name
)
5137 << CurrentName
.getName();
5138 if (PreviousCriticalLoc
.isValid())
5139 SemaRef
.Diag(PreviousCriticalLoc
,
5140 diag::note_omp_previous_critical_region
);
5143 } else if (CurrentRegion
== OMPD_barrier
|| CurrentRegion
== OMPD_scope
) {
5144 // OpenMP 5.1 [2.22, Nesting of Regions]
5145 // A scope region may not be closely nested inside a worksharing, loop,
5146 // task, taskloop, critical, ordered, atomic, or masked region.
5147 // OpenMP 5.1 [2.22, Nesting of Regions]
5148 // A barrier region may not be closely nested inside a worksharing, loop,
5149 // task, taskloop, critical, ordered, atomic, or masked region.
5151 isOpenMPWorksharingDirective(ParentRegion
) ||
5152 isOpenMPGenericLoopDirective(ParentRegion
) ||
5153 isOpenMPTaskingDirective(ParentRegion
) ||
5154 ParentRegion
== OMPD_master
|| ParentRegion
== OMPD_masked
||
5155 ParentRegion
== OMPD_parallel_master
||
5156 ParentRegion
== OMPD_parallel_masked
||
5157 ParentRegion
== OMPD_critical
|| ParentRegion
== OMPD_ordered
;
5158 } else if (isOpenMPWorksharingDirective(CurrentRegion
) &&
5159 !isOpenMPParallelDirective(CurrentRegion
) &&
5160 !isOpenMPTeamsDirective(CurrentRegion
)) {
5161 // OpenMP 5.1 [2.22, Nesting of Regions]
5162 // A loop region that binds to a parallel region or a worksharing region
5163 // may not be closely nested inside a worksharing, loop, task, taskloop,
5164 // critical, ordered, atomic, or masked region.
5166 isOpenMPWorksharingDirective(ParentRegion
) ||
5167 isOpenMPGenericLoopDirective(ParentRegion
) ||
5168 isOpenMPTaskingDirective(ParentRegion
) ||
5169 ParentRegion
== OMPD_master
|| ParentRegion
== OMPD_masked
||
5170 ParentRegion
== OMPD_parallel_master
||
5171 ParentRegion
== OMPD_parallel_masked
||
5172 ParentRegion
== OMPD_critical
|| ParentRegion
== OMPD_ordered
;
5173 Recommend
= ShouldBeInParallelRegion
;
5174 } else if (CurrentRegion
== OMPD_ordered
) {
5175 // OpenMP [2.16, Nesting of Regions]
5176 // An ordered region may not be closely nested inside a critical,
5177 // atomic, or explicit task region.
5178 // An ordered region must be closely nested inside a loop region (or
5179 // parallel loop region) with an ordered clause.
5180 // OpenMP [2.8.1,simd Construct, Restrictions]
5181 // An ordered construct with the simd clause is the only OpenMP construct
5182 // that can appear in the simd region.
5183 NestingProhibited
= ParentRegion
== OMPD_critical
||
5184 isOpenMPTaskingDirective(ParentRegion
) ||
5185 !(isOpenMPSimdDirective(ParentRegion
) ||
5186 Stack
->isParentOrderedRegion());
5187 Recommend
= ShouldBeInOrderedRegion
;
5188 } else if (isOpenMPNestingTeamsDirective(CurrentRegion
)) {
5189 // OpenMP [2.16, Nesting of Regions]
5190 // If specified, a teams construct must be contained within a target
5193 (SemaRef
.LangOpts
.OpenMP
<= 45 && ParentRegion
!= OMPD_target
) ||
5194 (SemaRef
.LangOpts
.OpenMP
>= 50 && ParentRegion
!= OMPD_unknown
&&
5195 ParentRegion
!= OMPD_target
);
5196 OrphanSeen
= ParentRegion
== OMPD_unknown
;
5197 Recommend
= ShouldBeInTargetRegion
;
5198 } else if (CurrentRegion
== OMPD_scan
) {
5199 // OpenMP [2.16, Nesting of Regions]
5200 // If specified, a teams construct must be contained within a target
5203 SemaRef
.LangOpts
.OpenMP
< 50 ||
5204 (ParentRegion
!= OMPD_simd
&& ParentRegion
!= OMPD_for
&&
5205 ParentRegion
!= OMPD_for_simd
&& ParentRegion
!= OMPD_parallel_for
&&
5206 ParentRegion
!= OMPD_parallel_for_simd
);
5207 OrphanSeen
= ParentRegion
== OMPD_unknown
;
5208 Recommend
= ShouldBeInLoopSimdRegion
;
5210 if (!NestingProhibited
&&
5211 !isOpenMPTargetExecutionDirective(CurrentRegion
) &&
5212 !isOpenMPTargetDataManagementDirective(CurrentRegion
) &&
5213 (ParentRegion
== OMPD_teams
|| ParentRegion
== OMPD_target_teams
)) {
5214 // OpenMP [5.1, 2.22, Nesting of Regions]
5215 // distribute, distribute simd, distribute parallel worksharing-loop,
5216 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5217 // including any parallel regions arising from combined constructs,
5218 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5219 // only OpenMP regions that may be strictly nested inside the teams
5222 // As an extension, we permit atomic within teams as well.
5223 NestingProhibited
= !isOpenMPParallelDirective(CurrentRegion
) &&
5224 !isOpenMPDistributeDirective(CurrentRegion
) &&
5225 CurrentRegion
!= OMPD_loop
&&
5226 !(SemaRef
.getLangOpts().OpenMPExtensions
&&
5227 CurrentRegion
== OMPD_atomic
);
5228 Recommend
= ShouldBeInParallelRegion
;
5230 if (!NestingProhibited
&& CurrentRegion
== OMPD_loop
) {
5231 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5232 // If the bind clause is present on the loop construct and binding is
5233 // teams then the corresponding loop region must be strictly nested inside
5235 NestingProhibited
= BindKind
== OMPC_BIND_teams
&&
5236 ParentRegion
!= OMPD_teams
&&
5237 ParentRegion
!= OMPD_target_teams
;
5238 Recommend
= ShouldBeInTeamsRegion
;
5240 if (!NestingProhibited
&&
5241 isOpenMPNestingDistributeDirective(CurrentRegion
)) {
5242 // OpenMP 4.5 [2.17 Nesting of Regions]
5243 // The region associated with the distribute construct must be strictly
5244 // nested inside a teams region
5246 (ParentRegion
!= OMPD_teams
&& ParentRegion
!= OMPD_target_teams
);
5247 Recommend
= ShouldBeInTeamsRegion
;
5249 if (!NestingProhibited
&&
5250 (isOpenMPTargetExecutionDirective(CurrentRegion
) ||
5251 isOpenMPTargetDataManagementDirective(CurrentRegion
))) {
5252 // OpenMP 4.5 [2.17 Nesting of Regions]
5253 // If a target, target update, target data, target enter data, or
5254 // target exit data construct is encountered during execution of a
5255 // target region, the behavior is unspecified.
5256 NestingProhibited
= Stack
->hasDirective(
5257 [&OffendingRegion
](OpenMPDirectiveKind K
, const DeclarationNameInfo
&,
5259 if (isOpenMPTargetExecutionDirective(K
)) {
5260 OffendingRegion
= K
;
5265 false /* don't skip top directive */);
5266 CloseNesting
= false;
5268 if (NestingProhibited
) {
5270 SemaRef
.Diag(StartLoc
, diag::err_omp_orphaned_device_directive
)
5271 << getOpenMPDirectiveName(CurrentRegion
) << Recommend
;
5273 SemaRef
.Diag(StartLoc
, diag::err_omp_prohibited_region
)
5274 << CloseNesting
<< getOpenMPDirectiveName(OffendingRegion
)
5275 << Recommend
<< getOpenMPDirectiveName(CurrentRegion
);
5283 struct Kind2Unsigned
{
5284 using argument_type
= OpenMPDirectiveKind
;
5285 unsigned operator()(argument_type DK
) { return unsigned(DK
); }
5287 static bool checkIfClauses(Sema
&S
, OpenMPDirectiveKind Kind
,
5288 ArrayRef
<OMPClause
*> Clauses
,
5289 ArrayRef
<OpenMPDirectiveKind
> AllowedNameModifiers
) {
5290 bool ErrorFound
= false;
5291 unsigned NamedModifiersNumber
= 0;
5292 llvm::IndexedMap
<const OMPIfClause
*, Kind2Unsigned
> FoundNameModifiers
;
5293 FoundNameModifiers
.resize(llvm::omp::Directive_enumSize
+ 1);
5294 SmallVector
<SourceLocation
, 4> NameModifierLoc
;
5295 for (const OMPClause
*C
: Clauses
) {
5296 if (const auto *IC
= dyn_cast_or_null
<OMPIfClause
>(C
)) {
5297 // At most one if clause without a directive-name-modifier can appear on
5299 OpenMPDirectiveKind CurNM
= IC
->getNameModifier();
5300 if (FoundNameModifiers
[CurNM
]) {
5301 S
.Diag(C
->getBeginLoc(), diag::err_omp_more_one_clause
)
5302 << getOpenMPDirectiveName(Kind
) << getOpenMPClauseName(OMPC_if
)
5303 << (CurNM
!= OMPD_unknown
) << getOpenMPDirectiveName(CurNM
);
5305 } else if (CurNM
!= OMPD_unknown
) {
5306 NameModifierLoc
.push_back(IC
->getNameModifierLoc());
5307 ++NamedModifiersNumber
;
5309 FoundNameModifiers
[CurNM
] = IC
;
5310 if (CurNM
== OMPD_unknown
)
5312 // Check if the specified name modifier is allowed for the current
5314 // At most one if clause with the particular directive-name-modifier can
5315 // appear on the directive.
5316 if (!llvm::is_contained(AllowedNameModifiers
, CurNM
)) {
5317 S
.Diag(IC
->getNameModifierLoc(),
5318 diag::err_omp_wrong_if_directive_name_modifier
)
5319 << getOpenMPDirectiveName(CurNM
) << getOpenMPDirectiveName(Kind
);
5324 // If any if clause on the directive includes a directive-name-modifier then
5325 // all if clauses on the directive must include a directive-name-modifier.
5326 if (FoundNameModifiers
[OMPD_unknown
] && NamedModifiersNumber
> 0) {
5327 if (NamedModifiersNumber
== AllowedNameModifiers
.size()) {
5328 S
.Diag(FoundNameModifiers
[OMPD_unknown
]->getBeginLoc(),
5329 diag::err_omp_no_more_if_clause
);
5332 std::string
Sep(", ");
5333 unsigned AllowedCnt
= 0;
5334 unsigned TotalAllowedNum
=
5335 AllowedNameModifiers
.size() - NamedModifiersNumber
;
5336 for (unsigned Cnt
= 0, End
= AllowedNameModifiers
.size(); Cnt
< End
;
5338 OpenMPDirectiveKind NM
= AllowedNameModifiers
[Cnt
];
5339 if (!FoundNameModifiers
[NM
]) {
5341 Values
+= getOpenMPDirectiveName(NM
);
5343 if (AllowedCnt
+ 2 == TotalAllowedNum
)
5345 else if (AllowedCnt
+ 1 != TotalAllowedNum
)
5350 S
.Diag(FoundNameModifiers
[OMPD_unknown
]->getCondition()->getBeginLoc(),
5351 diag::err_omp_unnamed_if_clause
)
5352 << (TotalAllowedNum
> 1) << Values
;
5354 for (SourceLocation Loc
: NameModifierLoc
) {
5355 S
.Diag(Loc
, diag::note_omp_previous_named_if_clause
);
5362 static std::pair
<ValueDecl
*, bool> getPrivateItem(Sema
&S
, Expr
*&RefExpr
,
5363 SourceLocation
&ELoc
,
5364 SourceRange
&ERange
,
5365 bool AllowArraySection
,
5366 StringRef DiagType
) {
5367 if (RefExpr
->isTypeDependent() || RefExpr
->isValueDependent() ||
5368 RefExpr
->containsUnexpandedParameterPack())
5369 return std::make_pair(nullptr, true);
5371 // OpenMP [3.1, C/C++]
5372 // A list item is a variable name.
5373 // OpenMP [2.9.3.3, Restrictions, p.1]
5374 // A variable that is part of another variable (as an array or
5375 // structure element) cannot appear in a private clause.
5376 RefExpr
= RefExpr
->IgnoreParens();
5381 } IsArrayExpr
= NoArrayExpr
;
5382 if (AllowArraySection
) {
5383 if (auto *ASE
= dyn_cast_or_null
<ArraySubscriptExpr
>(RefExpr
)) {
5384 Expr
*Base
= ASE
->getBase()->IgnoreParenImpCasts();
5385 while (auto *TempASE
= dyn_cast
<ArraySubscriptExpr
>(Base
))
5386 Base
= TempASE
->getBase()->IgnoreParenImpCasts();
5388 IsArrayExpr
= ArraySubscript
;
5389 } else if (auto *OASE
= dyn_cast_or_null
<OMPArraySectionExpr
>(RefExpr
)) {
5390 Expr
*Base
= OASE
->getBase()->IgnoreParenImpCasts();
5391 while (auto *TempOASE
= dyn_cast
<OMPArraySectionExpr
>(Base
))
5392 Base
= TempOASE
->getBase()->IgnoreParenImpCasts();
5393 while (auto *TempASE
= dyn_cast
<ArraySubscriptExpr
>(Base
))
5394 Base
= TempASE
->getBase()->IgnoreParenImpCasts();
5396 IsArrayExpr
= OMPArraySection
;
5399 ELoc
= RefExpr
->getExprLoc();
5400 ERange
= RefExpr
->getSourceRange();
5401 RefExpr
= RefExpr
->IgnoreParenImpCasts();
5402 auto *DE
= dyn_cast_or_null
<DeclRefExpr
>(RefExpr
);
5403 auto *ME
= dyn_cast_or_null
<MemberExpr
>(RefExpr
);
5404 if ((!DE
|| !isa
<VarDecl
>(DE
->getDecl())) &&
5405 (S
.getCurrentThisType().isNull() || !ME
||
5406 !isa
<CXXThisExpr
>(ME
->getBase()->IgnoreParenImpCasts()) ||
5407 !isa
<FieldDecl
>(ME
->getMemberDecl()))) {
5408 if (IsArrayExpr
!= NoArrayExpr
) {
5409 S
.Diag(ELoc
, diag::err_omp_expected_base_var_name
)
5410 << IsArrayExpr
<< ERange
;
5411 } else if (!DiagType
.empty()) {
5412 unsigned DiagSelect
= S
.getLangOpts().CPlusPlus
5413 ? (S
.getCurrentThisType().isNull() ? 1 : 2)
5415 S
.Diag(ELoc
, diag::err_omp_expected_var_name_member_expr_with_type
)
5416 << DiagSelect
<< DiagType
<< ERange
;
5420 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5421 : diag::err_omp_expected_var_name_member_expr
)
5422 << (S
.getCurrentThisType().isNull() ? 0 : 1) << ERange
;
5424 return std::make_pair(nullptr, false);
5426 return std::make_pair(
5427 getCanonicalDecl(DE
? DE
->getDecl() : ME
->getMemberDecl()), false);
5431 /// Checks if the allocator is used in uses_allocators clause to be allowed in
5433 class AllocatorChecker final
: public ConstStmtVisitor
<AllocatorChecker
, bool> {
5434 DSAStackTy
*S
= nullptr;
5437 bool VisitDeclRefExpr(const DeclRefExpr
*E
) {
5438 return S
->isUsesAllocatorsDecl(E
->getDecl())
5439 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait
) ==
5440 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait
;
5442 bool VisitStmt(const Stmt
*S
) {
5443 for (const Stmt
*Child
: S
->children()) {
5444 if (Child
&& Visit(Child
))
5449 explicit AllocatorChecker(DSAStackTy
*S
) : S(S
) {}
5453 static void checkAllocateClauses(Sema
&S
, DSAStackTy
*Stack
,
5454 ArrayRef
<OMPClause
*> Clauses
) {
5455 assert(!S
.CurContext
->isDependentContext() &&
5456 "Expected non-dependent context.");
5457 auto AllocateRange
=
5458 llvm::make_filter_range(Clauses
, OMPAllocateClause::classof
);
5459 llvm::DenseMap
<CanonicalDeclPtr
<Decl
>, CanonicalDeclPtr
<VarDecl
>> DeclToCopy
;
5460 auto PrivateRange
= llvm::make_filter_range(Clauses
, [](const OMPClause
*C
) {
5461 return isOpenMPPrivate(C
->getClauseKind());
5463 for (OMPClause
*Cl
: PrivateRange
) {
5464 MutableArrayRef
<Expr
*>::iterator I
, It
, Et
;
5465 if (Cl
->getClauseKind() == OMPC_private
) {
5466 auto *PC
= cast
<OMPPrivateClause
>(Cl
);
5467 I
= PC
->private_copies().begin();
5468 It
= PC
->varlist_begin();
5469 Et
= PC
->varlist_end();
5470 } else if (Cl
->getClauseKind() == OMPC_firstprivate
) {
5471 auto *PC
= cast
<OMPFirstprivateClause
>(Cl
);
5472 I
= PC
->private_copies().begin();
5473 It
= PC
->varlist_begin();
5474 Et
= PC
->varlist_end();
5475 } else if (Cl
->getClauseKind() == OMPC_lastprivate
) {
5476 auto *PC
= cast
<OMPLastprivateClause
>(Cl
);
5477 I
= PC
->private_copies().begin();
5478 It
= PC
->varlist_begin();
5479 Et
= PC
->varlist_end();
5480 } else if (Cl
->getClauseKind() == OMPC_linear
) {
5481 auto *PC
= cast
<OMPLinearClause
>(Cl
);
5482 I
= PC
->privates().begin();
5483 It
= PC
->varlist_begin();
5484 Et
= PC
->varlist_end();
5485 } else if (Cl
->getClauseKind() == OMPC_reduction
) {
5486 auto *PC
= cast
<OMPReductionClause
>(Cl
);
5487 I
= PC
->privates().begin();
5488 It
= PC
->varlist_begin();
5489 Et
= PC
->varlist_end();
5490 } else if (Cl
->getClauseKind() == OMPC_task_reduction
) {
5491 auto *PC
= cast
<OMPTaskReductionClause
>(Cl
);
5492 I
= PC
->privates().begin();
5493 It
= PC
->varlist_begin();
5494 Et
= PC
->varlist_end();
5495 } else if (Cl
->getClauseKind() == OMPC_in_reduction
) {
5496 auto *PC
= cast
<OMPInReductionClause
>(Cl
);
5497 I
= PC
->privates().begin();
5498 It
= PC
->varlist_begin();
5499 Et
= PC
->varlist_end();
5501 llvm_unreachable("Expected private clause.");
5503 for (Expr
*E
: llvm::make_range(It
, Et
)) {
5508 SourceLocation ELoc
;
5510 Expr
*SimpleRefExpr
= E
;
5511 auto Res
= getPrivateItem(S
, SimpleRefExpr
, ELoc
, ERange
,
5512 /*AllowArraySection=*/true);
5513 DeclToCopy
.try_emplace(Res
.first
,
5514 cast
<VarDecl
>(cast
<DeclRefExpr
>(*I
)->getDecl()));
5518 for (OMPClause
*C
: AllocateRange
) {
5519 auto *AC
= cast
<OMPAllocateClause
>(C
);
5520 if (S
.getLangOpts().OpenMP
>= 50 &&
5521 !Stack
->hasRequiresDeclWithClause
<OMPDynamicAllocatorsClause
>() &&
5522 isOpenMPTargetExecutionDirective(Stack
->getCurrentDirective()) &&
5523 AC
->getAllocator()) {
5524 Expr
*Allocator
= AC
->getAllocator();
5525 // OpenMP, 2.12.5 target Construct
5526 // Memory allocators that do not appear in a uses_allocators clause cannot
5527 // appear as an allocator in an allocate clause or be used in the target
5528 // region unless a requires directive with the dynamic_allocators clause
5529 // is present in the same compilation unit.
5530 AllocatorChecker
Checker(Stack
);
5531 if (Checker
.Visit(Allocator
))
5532 S
.Diag(Allocator
->getExprLoc(),
5533 diag::err_omp_allocator_not_in_uses_allocators
)
5534 << Allocator
->getSourceRange();
5536 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind
=
5537 getAllocatorKind(S
, Stack
, AC
->getAllocator());
5538 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5539 // For task, taskloop or target directives, allocation requests to memory
5540 // allocators with the trait access set to thread result in unspecified
5542 if (AllocatorKind
== OMPAllocateDeclAttr::OMPThreadMemAlloc
&&
5543 (isOpenMPTaskingDirective(Stack
->getCurrentDirective()) ||
5544 isOpenMPTargetExecutionDirective(Stack
->getCurrentDirective()))) {
5545 S
.Diag(AC
->getAllocator()->getExprLoc(),
5546 diag::warn_omp_allocate_thread_on_task_target_directive
)
5547 << getOpenMPDirectiveName(Stack
->getCurrentDirective());
5549 for (Expr
*E
: AC
->varlists()) {
5550 SourceLocation ELoc
;
5552 Expr
*SimpleRefExpr
= E
;
5553 auto Res
= getPrivateItem(S
, SimpleRefExpr
, ELoc
, ERange
);
5554 ValueDecl
*VD
= Res
.first
;
5555 DSAStackTy::DSAVarData Data
= Stack
->getTopDSA(VD
, /*FromParent=*/false);
5556 if (!isOpenMPPrivate(Data
.CKind
)) {
5557 S
.Diag(E
->getExprLoc(),
5558 diag::err_omp_expected_private_copy_for_allocate
);
5561 VarDecl
*PrivateVD
= DeclToCopy
[VD
];
5562 if (checkPreviousOMPAllocateAttribute(S
, Stack
, E
, PrivateVD
,
5563 AllocatorKind
, AC
->getAllocator()))
5565 // Placeholder until allocate clause supports align modifier.
5566 Expr
*Alignment
= nullptr;
5567 applyOMPAllocateAttribute(S
, PrivateVD
, AllocatorKind
, AC
->getAllocator(),
5568 Alignment
, E
->getSourceRange());
5574 /// Rewrite statements and expressions for Sema \p Actions CurContext.
5576 /// Used to wrap already parsed statements/expressions into a new CapturedStmt
5577 /// context. DeclRefExpr used inside the new context are changed to refer to the
5578 /// captured variable instead.
5579 class CaptureVars
: public TreeTransform
<CaptureVars
> {
5580 using BaseTransform
= TreeTransform
<CaptureVars
>;
5583 CaptureVars(Sema
&Actions
) : BaseTransform(Actions
) {}
5585 bool AlwaysRebuild() { return true; }
5589 static VarDecl
*precomputeExpr(Sema
&Actions
,
5590 SmallVectorImpl
<Stmt
*> &BodyStmts
, Expr
*E
,
5592 Expr
*NewE
= AssertSuccess(CaptureVars(Actions
).TransformExpr(E
));
5593 VarDecl
*NewVar
= buildVarDecl(Actions
, {}, NewE
->getType(), Name
, nullptr,
5594 dyn_cast
<DeclRefExpr
>(E
->IgnoreImplicit()));
5595 auto *NewDeclStmt
= cast
<DeclStmt
>(AssertSuccess(
5596 Actions
.ActOnDeclStmt(Actions
.ConvertDeclToDeclGroup(NewVar
), {}, {})));
5597 Actions
.AddInitializerToDecl(NewDeclStmt
->getSingleDecl(), NewE
, false);
5598 BodyStmts
.push_back(NewDeclStmt
);
5602 /// Create a closure that computes the number of iterations of a loop.
5604 /// \param Actions The Sema object.
5605 /// \param LogicalTy Type for the logical iteration number.
5606 /// \param Rel Comparison operator of the loop condition.
5607 /// \param StartExpr Value of the loop counter at the first iteration.
5608 /// \param StopExpr Expression the loop counter is compared against in the loop
5609 /// condition. \param StepExpr Amount of increment after each iteration.
5611 /// \return Closure (CapturedStmt) of the distance calculation.
5612 static CapturedStmt
*buildDistanceFunc(Sema
&Actions
, QualType LogicalTy
,
5613 BinaryOperator::Opcode Rel
,
5614 Expr
*StartExpr
, Expr
*StopExpr
,
5616 ASTContext
&Ctx
= Actions
.getASTContext();
5617 TypeSourceInfo
*LogicalTSI
= Ctx
.getTrivialTypeSourceInfo(LogicalTy
);
5619 // Captured regions currently don't support return values, we use an
5620 // out-parameter instead. All inputs are implicit captures.
5621 // TODO: Instead of capturing each DeclRefExpr occurring in
5622 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5623 QualType ResultTy
= Ctx
.getLValueReferenceType(LogicalTy
);
5624 Sema::CapturedParamNameType Params
[] = {{"Distance", ResultTy
},
5625 {StringRef(), QualType()}};
5626 Actions
.ActOnCapturedRegionStart({}, nullptr, CR_Default
, Params
);
5630 Sema::CompoundScopeRAII
CompoundScope(Actions
);
5631 CapturedDecl
*CS
= cast
<CapturedDecl
>(Actions
.CurContext
);
5633 // Get the LValue expression for the result.
5634 ImplicitParamDecl
*DistParam
= CS
->getParam(0);
5635 DeclRefExpr
*DistRef
= Actions
.BuildDeclRefExpr(
5636 DistParam
, LogicalTy
, VK_LValue
, {}, nullptr, nullptr, {}, nullptr);
5638 SmallVector
<Stmt
*, 4> BodyStmts
;
5640 // Capture all referenced variable references.
5641 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5642 // CapturedStmt, we could compute them before and capture the result, to be
5643 // used jointly with the LoopVar function.
5644 VarDecl
*NewStart
= precomputeExpr(Actions
, BodyStmts
, StartExpr
, ".start");
5645 VarDecl
*NewStop
= precomputeExpr(Actions
, BodyStmts
, StopExpr
, ".stop");
5646 VarDecl
*NewStep
= precomputeExpr(Actions
, BodyStmts
, StepExpr
, ".step");
5647 auto BuildVarRef
= [&](VarDecl
*VD
) {
5648 return buildDeclRefExpr(Actions
, VD
, VD
->getType(), {});
5651 IntegerLiteral
*Zero
= IntegerLiteral::Create(
5652 Ctx
, llvm::APInt(Ctx
.getIntWidth(LogicalTy
), 0), LogicalTy
, {});
5653 IntegerLiteral
*One
= IntegerLiteral::Create(
5654 Ctx
, llvm::APInt(Ctx
.getIntWidth(LogicalTy
), 1), LogicalTy
, {});
5657 // When using a != comparison, the increment can be +1 or -1. This can be
5658 // dynamic at runtime, so we need to check for the direction.
5659 Expr
*IsNegStep
= AssertSuccess(
5660 Actions
.BuildBinOp(nullptr, {}, BO_LT
, BuildVarRef(NewStep
), Zero
));
5662 // Positive increment.
5663 Expr
*ForwardRange
= AssertSuccess(Actions
.BuildBinOp(
5664 nullptr, {}, BO_Sub
, BuildVarRef(NewStop
), BuildVarRef(NewStart
)));
5665 ForwardRange
= AssertSuccess(
5666 Actions
.BuildCStyleCastExpr({}, LogicalTSI
, {}, ForwardRange
));
5667 Expr
*ForwardDist
= AssertSuccess(Actions
.BuildBinOp(
5668 nullptr, {}, BO_Div
, ForwardRange
, BuildVarRef(NewStep
)));
5670 // Negative increment.
5671 Expr
*BackwardRange
= AssertSuccess(Actions
.BuildBinOp(
5672 nullptr, {}, BO_Sub
, BuildVarRef(NewStart
), BuildVarRef(NewStop
)));
5673 BackwardRange
= AssertSuccess(
5674 Actions
.BuildCStyleCastExpr({}, LogicalTSI
, {}, BackwardRange
));
5675 Expr
*NegIncAmount
= AssertSuccess(
5676 Actions
.BuildUnaryOp(nullptr, {}, UO_Minus
, BuildVarRef(NewStep
)));
5677 Expr
*BackwardDist
= AssertSuccess(
5678 Actions
.BuildBinOp(nullptr, {}, BO_Div
, BackwardRange
, NegIncAmount
));
5680 // Use the appropriate case.
5681 Dist
= AssertSuccess(Actions
.ActOnConditionalOp(
5682 {}, {}, IsNegStep
, BackwardDist
, ForwardDist
));
5684 assert((Rel
== BO_LT
|| Rel
== BO_LE
|| Rel
== BO_GE
|| Rel
== BO_GT
) &&
5685 "Expected one of these relational operators");
5687 // We can derive the direction from any other comparison operator. It is
5688 // non well-formed OpenMP if Step increments/decrements in the other
5689 // directions. Whether at least the first iteration passes the loop
5691 Expr
*HasAnyIteration
= AssertSuccess(Actions
.BuildBinOp(
5692 nullptr, {}, Rel
, BuildVarRef(NewStart
), BuildVarRef(NewStop
)));
5694 // Compute the range between first and last counter value.
5696 if (Rel
== BO_GE
|| Rel
== BO_GT
)
5697 Range
= AssertSuccess(Actions
.BuildBinOp(
5698 nullptr, {}, BO_Sub
, BuildVarRef(NewStart
), BuildVarRef(NewStop
)));
5700 Range
= AssertSuccess(Actions
.BuildBinOp(
5701 nullptr, {}, BO_Sub
, BuildVarRef(NewStop
), BuildVarRef(NewStart
)));
5703 // Ensure unsigned range space.
5705 AssertSuccess(Actions
.BuildCStyleCastExpr({}, LogicalTSI
, {}, Range
));
5707 if (Rel
== BO_LE
|| Rel
== BO_GE
) {
5708 // Add one to the range if the relational operator is inclusive.
5710 AssertSuccess(Actions
.BuildBinOp(nullptr, {}, BO_Add
, Range
, One
));
5713 // Divide by the absolute step amount. If the range is not a multiple of
5714 // the step size, rounding-up the effective upper bound ensures that the
5715 // last iteration is included.
5716 // Note that the rounding-up may cause an overflow in a temporry that
5717 // could be avoided, but would have occurred in a C-style for-loop as
5719 Expr
*Divisor
= BuildVarRef(NewStep
);
5720 if (Rel
== BO_GE
|| Rel
== BO_GT
)
5722 AssertSuccess(Actions
.BuildUnaryOp(nullptr, {}, UO_Minus
, Divisor
));
5723 Expr
*DivisorMinusOne
=
5724 AssertSuccess(Actions
.BuildBinOp(nullptr, {}, BO_Sub
, Divisor
, One
));
5725 Expr
*RangeRoundUp
= AssertSuccess(
5726 Actions
.BuildBinOp(nullptr, {}, BO_Add
, Range
, DivisorMinusOne
));
5727 Dist
= AssertSuccess(
5728 Actions
.BuildBinOp(nullptr, {}, BO_Div
, RangeRoundUp
, Divisor
));
5730 // If there is not at least one iteration, the range contains garbage. Fix
5731 // to zero in this case.
5732 Dist
= AssertSuccess(
5733 Actions
.ActOnConditionalOp({}, {}, HasAnyIteration
, Dist
, Zero
));
5736 // Assign the result to the out-parameter.
5737 Stmt
*ResultAssign
= AssertSuccess(Actions
.BuildBinOp(
5738 Actions
.getCurScope(), {}, BO_Assign
, DistRef
, Dist
));
5739 BodyStmts
.push_back(ResultAssign
);
5741 Body
= AssertSuccess(Actions
.ActOnCompoundStmt({}, {}, BodyStmts
, false));
5744 return cast
<CapturedStmt
>(
5745 AssertSuccess(Actions
.ActOnCapturedRegionEnd(Body
)));
5748 /// Create a closure that computes the loop variable from the logical iteration
5751 /// \param Actions The Sema object.
5752 /// \param LoopVarTy Type for the loop variable used for result value.
5753 /// \param LogicalTy Type for the logical iteration number.
5754 /// \param StartExpr Value of the loop counter at the first iteration.
5755 /// \param Step Amount of increment after each iteration.
5756 /// \param Deref Whether the loop variable is a dereference of the loop
5757 /// counter variable.
5759 /// \return Closure (CapturedStmt) of the loop value calculation.
5760 static CapturedStmt
*buildLoopVarFunc(Sema
&Actions
, QualType LoopVarTy
,
5762 DeclRefExpr
*StartExpr
, Expr
*Step
,
5764 ASTContext
&Ctx
= Actions
.getASTContext();
5766 // Pass the result as an out-parameter. Passing as return value would require
5767 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5768 // invoke a copy constructor.
5769 QualType TargetParamTy
= Ctx
.getLValueReferenceType(LoopVarTy
);
5770 Sema::CapturedParamNameType Params
[] = {{"LoopVar", TargetParamTy
},
5771 {"Logical", LogicalTy
},
5772 {StringRef(), QualType()}};
5773 Actions
.ActOnCapturedRegionStart({}, nullptr, CR_Default
, Params
);
5775 // Capture the initial iterator which represents the LoopVar value at the
5776 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5777 // it in every iteration, capture it by value before it is modified.
5778 VarDecl
*StartVar
= cast
<VarDecl
>(StartExpr
->getDecl());
5779 bool Invalid
= Actions
.tryCaptureVariable(StartVar
, {},
5780 Sema::TryCapture_ExplicitByVal
, {});
5782 assert(!Invalid
&& "Expecting capture-by-value to work.");
5786 Sema::CompoundScopeRAII
CompoundScope(Actions
);
5787 auto *CS
= cast
<CapturedDecl
>(Actions
.CurContext
);
5789 ImplicitParamDecl
*TargetParam
= CS
->getParam(0);
5790 DeclRefExpr
*TargetRef
= Actions
.BuildDeclRefExpr(
5791 TargetParam
, LoopVarTy
, VK_LValue
, {}, nullptr, nullptr, {}, nullptr);
5792 ImplicitParamDecl
*IndvarParam
= CS
->getParam(1);
5793 DeclRefExpr
*LogicalRef
= Actions
.BuildDeclRefExpr(
5794 IndvarParam
, LogicalTy
, VK_LValue
, {}, nullptr, nullptr, {}, nullptr);
5796 // Capture the Start expression.
5797 CaptureVars
Recap(Actions
);
5798 Expr
*NewStart
= AssertSuccess(Recap
.TransformExpr(StartExpr
));
5799 Expr
*NewStep
= AssertSuccess(Recap
.TransformExpr(Step
));
5801 Expr
*Skip
= AssertSuccess(
5802 Actions
.BuildBinOp(nullptr, {}, BO_Mul
, NewStep
, LogicalRef
));
5803 // TODO: Explicitly cast to the iterator's difference_type instead of
5804 // relying on implicit conversion.
5806 AssertSuccess(Actions
.BuildBinOp(nullptr, {}, BO_Add
, NewStart
, Skip
));
5809 // For range-based for-loops convert the loop counter value to a concrete
5810 // loop variable value by dereferencing the iterator.
5812 AssertSuccess(Actions
.BuildUnaryOp(nullptr, {}, UO_Deref
, Advanced
));
5815 // Assign the result to the output parameter.
5816 Body
= AssertSuccess(Actions
.BuildBinOp(Actions
.getCurScope(), {},
5817 BO_Assign
, TargetRef
, Advanced
));
5819 return cast
<CapturedStmt
>(
5820 AssertSuccess(Actions
.ActOnCapturedRegionEnd(Body
)));
5823 StmtResult
Sema::ActOnOpenMPCanonicalLoop(Stmt
*AStmt
) {
5824 ASTContext
&Ctx
= getASTContext();
5826 // Extract the common elements of ForStmt and CXXForRangeStmt:
5827 // Loop variable, repeat condition, increment
5829 VarDecl
*LIVDecl
, *LUVDecl
;
5830 if (auto *For
= dyn_cast
<ForStmt
>(AStmt
)) {
5831 Stmt
*Init
= For
->getInit();
5832 if (auto *LCVarDeclStmt
= dyn_cast
<DeclStmt
>(Init
)) {
5833 // For statement declares loop variable.
5834 LIVDecl
= cast
<VarDecl
>(LCVarDeclStmt
->getSingleDecl());
5835 } else if (auto *LCAssign
= dyn_cast
<BinaryOperator
>(Init
)) {
5836 // For statement reuses variable.
5837 assert(LCAssign
->getOpcode() == BO_Assign
&&
5838 "init part must be a loop variable assignment");
5839 auto *CounterRef
= cast
<DeclRefExpr
>(LCAssign
->getLHS());
5840 LIVDecl
= cast
<VarDecl
>(CounterRef
->getDecl());
5842 llvm_unreachable("Cannot determine loop variable");
5845 Cond
= For
->getCond();
5846 Inc
= For
->getInc();
5847 } else if (auto *RangeFor
= dyn_cast
<CXXForRangeStmt
>(AStmt
)) {
5848 DeclStmt
*BeginStmt
= RangeFor
->getBeginStmt();
5849 LIVDecl
= cast
<VarDecl
>(BeginStmt
->getSingleDecl());
5850 LUVDecl
= RangeFor
->getLoopVariable();
5852 Cond
= RangeFor
->getCond();
5853 Inc
= RangeFor
->getInc();
5855 llvm_unreachable("unhandled kind of loop");
5857 QualType CounterTy
= LIVDecl
->getType();
5858 QualType LVTy
= LUVDecl
->getType();
5860 // Analyze the loop condition.
5862 BinaryOperator::Opcode CondRel
;
5863 Cond
= Cond
->IgnoreImplicit();
5864 if (auto *CondBinExpr
= dyn_cast
<BinaryOperator
>(Cond
)) {
5865 LHS
= CondBinExpr
->getLHS();
5866 RHS
= CondBinExpr
->getRHS();
5867 CondRel
= CondBinExpr
->getOpcode();
5868 } else if (auto *CondCXXOp
= dyn_cast
<CXXOperatorCallExpr
>(Cond
)) {
5869 assert(CondCXXOp
->getNumArgs() == 2 && "Comparison should have 2 operands");
5870 LHS
= CondCXXOp
->getArg(0);
5871 RHS
= CondCXXOp
->getArg(1);
5872 switch (CondCXXOp
->getOperator()) {
5873 case OO_ExclaimEqual
:
5885 case OO_GreaterEqual
:
5889 llvm_unreachable("unexpected iterator operator");
5892 llvm_unreachable("unexpected loop condition");
5894 // Normalize such that the loop counter is on the LHS.
5895 if (!isa
<DeclRefExpr
>(LHS
->IgnoreImplicit()) ||
5896 cast
<DeclRefExpr
>(LHS
->IgnoreImplicit())->getDecl() != LIVDecl
) {
5897 std::swap(LHS
, RHS
);
5898 CondRel
= BinaryOperator::reverseComparisonOp(CondRel
);
5900 auto *CounterRef
= cast
<DeclRefExpr
>(LHS
->IgnoreImplicit());
5902 // Decide the bit width for the logical iteration counter. By default use the
5903 // unsigned ptrdiff_t integer size (for iterators and pointers).
5904 // TODO: For iterators, use iterator::difference_type,
5905 // std::iterator_traits<>::difference_type or decltype(it - end).
5906 QualType LogicalTy
= Ctx
.getUnsignedPointerDiffType();
5907 if (CounterTy
->isIntegerType()) {
5908 unsigned BitWidth
= Ctx
.getIntWidth(CounterTy
);
5909 LogicalTy
= Ctx
.getIntTypeForBitwidth(BitWidth
, false);
5912 // Analyze the loop increment.
5914 if (auto *IncUn
= dyn_cast
<UnaryOperator
>(Inc
)) {
5916 switch (IncUn
->getOpcode()) {
5926 llvm_unreachable("unhandled unary increment operator");
5928 Step
= IntegerLiteral::Create(
5929 Ctx
, llvm::APInt(Ctx
.getIntWidth(LogicalTy
), Direction
), LogicalTy
, {});
5930 } else if (auto *IncBin
= dyn_cast
<BinaryOperator
>(Inc
)) {
5931 if (IncBin
->getOpcode() == BO_AddAssign
) {
5932 Step
= IncBin
->getRHS();
5933 } else if (IncBin
->getOpcode() == BO_SubAssign
) {
5935 AssertSuccess(BuildUnaryOp(nullptr, {}, UO_Minus
, IncBin
->getRHS()));
5937 llvm_unreachable("unhandled binary increment operator");
5938 } else if (auto *CondCXXOp
= dyn_cast
<CXXOperatorCallExpr
>(Inc
)) {
5939 switch (CondCXXOp
->getOperator()) {
5941 Step
= IntegerLiteral::Create(
5942 Ctx
, llvm::APInt(Ctx
.getIntWidth(LogicalTy
), 1), LogicalTy
, {});
5945 Step
= IntegerLiteral::Create(
5946 Ctx
, llvm::APInt(Ctx
.getIntWidth(LogicalTy
), -1), LogicalTy
, {});
5949 Step
= CondCXXOp
->getArg(1);
5952 Step
= AssertSuccess(
5953 BuildUnaryOp(nullptr, {}, UO_Minus
, CondCXXOp
->getArg(1)));
5956 llvm_unreachable("unhandled overloaded increment operator");
5959 llvm_unreachable("unknown increment expression");
5961 CapturedStmt
*DistanceFunc
=
5962 buildDistanceFunc(*this, LogicalTy
, CondRel
, LHS
, RHS
, Step
);
5963 CapturedStmt
*LoopVarFunc
= buildLoopVarFunc(
5964 *this, LVTy
, LogicalTy
, CounterRef
, Step
, isa
<CXXForRangeStmt
>(AStmt
));
5965 DeclRefExpr
*LVRef
= BuildDeclRefExpr(LUVDecl
, LUVDecl
->getType(), VK_LValue
,
5966 {}, nullptr, nullptr, {}, nullptr);
5967 return OMPCanonicalLoop::create(getASTContext(), AStmt
, DistanceFunc
,
5968 LoopVarFunc
, LVRef
);
5971 StmtResult
Sema::ActOnOpenMPLoopnest(Stmt
*AStmt
) {
5972 // Handle a literal loop.
5973 if (isa
<ForStmt
>(AStmt
) || isa
<CXXForRangeStmt
>(AStmt
))
5974 return ActOnOpenMPCanonicalLoop(AStmt
);
5976 // If not a literal loop, it must be the result of a loop transformation.
5977 OMPExecutableDirective
*LoopTransform
= cast
<OMPExecutableDirective
>(AStmt
);
5979 isOpenMPLoopTransformationDirective(LoopTransform
->getDirectiveKind()) &&
5980 "Loop transformation directive expected");
5981 return LoopTransform
;
5984 static ExprResult
buildUserDefinedMapperRef(Sema
&SemaRef
, Scope
*S
,
5985 CXXScopeSpec
&MapperIdScopeSpec
,
5986 const DeclarationNameInfo
&MapperId
,
5988 Expr
*UnresolvedMapper
);
5990 /// Perform DFS through the structure/class data members trying to find
5991 /// member(s) with user-defined 'default' mapper and generate implicit map
5992 /// clauses for such members with the found 'default' mapper.
5994 processImplicitMapsWithDefaultMappers(Sema
&S
, DSAStackTy
*Stack
,
5995 SmallVectorImpl
<OMPClause
*> &Clauses
) {
5996 // Check for the deault mapper for data members.
5997 if (S
.getLangOpts().OpenMP
< 50)
5999 SmallVector
<OMPClause
*, 4> ImplicitMaps
;
6000 for (int Cnt
= 0, EndCnt
= Clauses
.size(); Cnt
< EndCnt
; ++Cnt
) {
6001 auto *C
= dyn_cast
<OMPMapClause
>(Clauses
[Cnt
]);
6004 SmallVector
<Expr
*, 4> SubExprs
;
6005 auto *MI
= C
->mapperlist_begin();
6006 for (auto I
= C
->varlist_begin(), End
= C
->varlist_end(); I
!= End
;
6008 // Expression is mapped using mapper - skip it.
6012 // Expression is dependent - skip it, build the mapper when it gets
6014 if (E
->isTypeDependent() || E
->isValueDependent() ||
6015 E
->containsUnexpandedParameterPack())
6017 // Array section - need to check for the mapping of the array section
6019 QualType CanonType
= E
->getType().getCanonicalType();
6020 if (CanonType
->isSpecificBuiltinType(BuiltinType::OMPArraySection
)) {
6021 const auto *OASE
= cast
<OMPArraySectionExpr
>(E
->IgnoreParenImpCasts());
6023 OMPArraySectionExpr::getBaseOriginalType(OASE
->getBase());
6025 if (const auto *ATy
= BaseType
->getAsArrayTypeUnsafe())
6026 ElemType
= ATy
->getElementType();
6028 ElemType
= BaseType
->getPointeeType();
6029 CanonType
= ElemType
;
6032 // DFS over data members in structures/classes.
6033 SmallVector
<std::pair
<QualType
, FieldDecl
*>, 4> Types(
6034 1, {CanonType
, nullptr});
6035 llvm::DenseMap
<const Type
*, Expr
*> Visited
;
6036 SmallVector
<std::pair
<FieldDecl
*, unsigned>, 4> ParentChain(
6038 while (!Types
.empty()) {
6041 std::tie(BaseType
, CurFD
) = Types
.pop_back_val();
6042 while (ParentChain
.back().second
== 0)
6043 ParentChain
.pop_back();
6044 --ParentChain
.back().second
;
6045 if (BaseType
.isNull())
6047 // Only structs/classes are allowed to have mappers.
6048 const RecordDecl
*RD
= BaseType
.getCanonicalType()->getAsRecordDecl();
6051 auto It
= Visited
.find(BaseType
.getTypePtr());
6052 if (It
== Visited
.end()) {
6053 // Try to find the associated user-defined mapper.
6054 CXXScopeSpec MapperIdScopeSpec
;
6055 DeclarationNameInfo DefaultMapperId
;
6056 DefaultMapperId
.setName(S
.Context
.DeclarationNames
.getIdentifier(
6057 &S
.Context
.Idents
.get("default")));
6058 DefaultMapperId
.setLoc(E
->getExprLoc());
6059 ExprResult ER
= buildUserDefinedMapperRef(
6060 S
, Stack
->getCurScope(), MapperIdScopeSpec
, DefaultMapperId
,
6061 BaseType
, /*UnresolvedMapper=*/nullptr);
6064 It
= Visited
.try_emplace(BaseType
.getTypePtr(), ER
.get()).first
;
6066 // Found default mapper.
6068 auto *OE
= new (S
.Context
) OpaqueValueExpr(E
->getExprLoc(), CanonType
,
6069 VK_LValue
, OK_Ordinary
, E
);
6070 OE
->setIsUnique(/*V=*/true);
6071 Expr
*BaseExpr
= OE
;
6072 for (const auto &P
: ParentChain
) {
6074 BaseExpr
= S
.BuildMemberExpr(
6075 BaseExpr
, /*IsArrow=*/false, E
->getExprLoc(),
6076 NestedNameSpecifierLoc(), SourceLocation(), P
.first
,
6077 DeclAccessPair::make(P
.first
, P
.first
->getAccess()),
6078 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6079 P
.first
->getType(), VK_LValue
, OK_Ordinary
);
6080 BaseExpr
= S
.DefaultLvalueConversion(BaseExpr
).get();
6084 BaseExpr
= S
.BuildMemberExpr(
6085 BaseExpr
, /*IsArrow=*/false, E
->getExprLoc(),
6086 NestedNameSpecifierLoc(), SourceLocation(), CurFD
,
6087 DeclAccessPair::make(CurFD
, CurFD
->getAccess()),
6088 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6089 CurFD
->getType(), VK_LValue
, OK_Ordinary
);
6090 SubExprs
.push_back(BaseExpr
);
6093 // Check for the "default" mapper for data members.
6094 bool FirstIter
= true;
6095 for (FieldDecl
*FD
: RD
->fields()) {
6098 QualType FieldTy
= FD
->getType();
6099 if (FieldTy
.isNull() ||
6100 !(FieldTy
->isStructureOrClassType() || FieldTy
->isUnionType()))
6104 ParentChain
.emplace_back(CurFD
, 1);
6106 ++ParentChain
.back().second
;
6108 Types
.emplace_back(FieldTy
, FD
);
6112 if (SubExprs
.empty())
6114 CXXScopeSpec MapperIdScopeSpec
;
6115 DeclarationNameInfo MapperId
;
6116 if (OMPClause
*NewClause
= S
.ActOnOpenMPMapClause(
6117 nullptr, C
->getMapTypeModifiers(), C
->getMapTypeModifiersLoc(),
6118 MapperIdScopeSpec
, MapperId
, C
->getMapType(),
6119 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6120 SubExprs
, OMPVarListLocTy()))
6121 Clauses
.push_back(NewClause
);
6125 bool Sema::mapLoopConstruct(llvm::SmallVector
<OMPClause
*> &ClausesWithoutBind
,
6126 ArrayRef
<OMPClause
*> Clauses
,
6127 OpenMPBindClauseKind BindKind
,
6128 OpenMPDirectiveKind
&Kind
,
6129 OpenMPDirectiveKind
&PrevMappedDirective
) {
6131 bool UseClausesWithoutBind
= false;
6133 // Restricting to "#pragma omp loop bind"
6134 if (getLangOpts().OpenMP
>= 50 && Kind
== OMPD_loop
) {
6135 if (BindKind
== OMPC_BIND_unknown
) {
6136 // Setting the enclosing teams or parallel construct for the loop
6137 // directive without bind clause.
6138 BindKind
= OMPC_BIND_thread
; // Default bind(thread) if binding is unknown
6140 const OpenMPDirectiveKind ParentDirective
=
6141 DSAStack
->getParentDirective();
6142 if (ParentDirective
== OMPD_unknown
) {
6143 Diag(DSAStack
->getDefaultDSALocation(),
6144 diag::err_omp_bind_required_on_loop
);
6145 } else if (ParentDirective
== OMPD_parallel
||
6146 ParentDirective
== OMPD_target_parallel
) {
6147 BindKind
= OMPC_BIND_parallel
;
6148 } else if (ParentDirective
== OMPD_teams
||
6149 ParentDirective
== OMPD_target_teams
) {
6150 BindKind
= OMPC_BIND_teams
;
6153 // bind clause is present, so we should set flag indicating to only
6154 // use the clauses that aren't the bind clause for the new directive that
6155 // loop is lowered to.
6156 UseClausesWithoutBind
= true;
6159 for (OMPClause
*C
: Clauses
) {
6160 // Spec restriction : bind(teams) and reduction not permitted.
6161 if (BindKind
== OMPC_BIND_teams
&&
6162 C
->getClauseKind() == llvm::omp::Clause::OMPC_reduction
)
6163 Diag(DSAStack
->getDefaultDSALocation(),
6164 diag::err_omp_loop_reduction_clause
);
6166 // A new Vector ClausesWithoutBind, which does not contain the bind
6167 // clause, for passing to new directive.
6168 if (C
->getClauseKind() != llvm::omp::Clause::OMPC_bind
)
6169 ClausesWithoutBind
.push_back(C
);
6173 case OMPC_BIND_parallel
:
6175 DSAStack
->setCurrentDirective(OMPD_for
);
6176 DSAStack
->setMappedDirective(OMPD_loop
);
6177 PrevMappedDirective
= OMPD_loop
;
6179 case OMPC_BIND_teams
:
6180 Kind
= OMPD_distribute
;
6181 DSAStack
->setCurrentDirective(OMPD_distribute
);
6182 DSAStack
->setMappedDirective(OMPD_loop
);
6183 PrevMappedDirective
= OMPD_loop
;
6185 case OMPC_BIND_thread
:
6187 DSAStack
->setCurrentDirective(OMPD_simd
);
6188 DSAStack
->setMappedDirective(OMPD_loop
);
6189 PrevMappedDirective
= OMPD_loop
;
6191 case OMPC_BIND_unknown
:
6194 } else if (PrevMappedDirective
== OMPD_loop
) {
6195 /// An initial pass after recognizing all the statements is done in the
6196 /// Parser when the directive OMPD_loop is mapped to OMPD_for,
6197 /// OMPD_distribute or OMPD_simd. A second transform pass with call from
6198 /// clang::TreeTransform::TransformOMPExecutableDirective() is done
6199 /// with the Directive as one of the above mapped directive without
6200 /// the bind clause. Then "PrevMappedDirective" stored in the
6201 /// OMPExecutableDirective is accessed and hence this else statement.
6203 DSAStack
->setMappedDirective(OMPD_loop
);
6206 return UseClausesWithoutBind
;
6209 StmtResult
Sema::ActOnOpenMPExecutableDirective(
6210 OpenMPDirectiveKind Kind
, const DeclarationNameInfo
&DirName
,
6211 OpenMPDirectiveKind CancelRegion
, ArrayRef
<OMPClause
*> Clauses
,
6212 Stmt
*AStmt
, SourceLocation StartLoc
, SourceLocation EndLoc
,
6213 OpenMPDirectiveKind PrevMappedDirective
) {
6214 StmtResult Res
= StmtError();
6215 OpenMPBindClauseKind BindKind
= OMPC_BIND_unknown
;
6216 if (const OMPBindClause
*BC
=
6217 OMPExecutableDirective::getSingleClause
<OMPBindClause
>(Clauses
))
6218 BindKind
= BC
->getBindKind();
6219 // First check CancelRegion which is then used in checkNestingOfRegions.
6220 if (checkCancelRegion(*this, Kind
, CancelRegion
, StartLoc
) ||
6221 checkNestingOfRegions(*this, DSAStack
, Kind
, DirName
, CancelRegion
,
6222 BindKind
, StartLoc
))
6225 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6226 if (getLangOpts().HIP
&& (isOpenMPTargetExecutionDirective(Kind
) ||
6227 isOpenMPTargetDataManagementDirective(Kind
)))
6228 Diag(StartLoc
, diag::warn_hip_omp_target_directives
);
6230 llvm::SmallVector
<OMPClause
*> ClausesWithoutBind
;
6231 bool UseClausesWithoutBind
= false;
6233 UseClausesWithoutBind
= mapLoopConstruct(ClausesWithoutBind
, Clauses
,
6234 BindKind
, Kind
, PrevMappedDirective
);
6236 llvm::SmallVector
<OMPClause
*, 8> ClausesWithImplicit
;
6237 VarsWithInheritedDSAType VarsWithInheritedDSA
;
6238 bool ErrorFound
= false;
6239 if (getLangOpts().OpenMP
>= 50 && UseClausesWithoutBind
) {
6240 ClausesWithImplicit
.append(ClausesWithoutBind
.begin(),
6241 ClausesWithoutBind
.end());
6243 ClausesWithImplicit
.append(Clauses
.begin(), Clauses
.end());
6245 if (AStmt
&& !CurContext
->isDependentContext() && Kind
!= OMPD_atomic
&&
6246 Kind
!= OMPD_critical
&& Kind
!= OMPD_section
&& Kind
!= OMPD_master
&&
6247 Kind
!= OMPD_masked
&& !isOpenMPLoopTransformationDirective(Kind
)) {
6248 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
6250 // Check default data sharing attributes for referenced variables.
6251 DSAAttrChecker
DSAChecker(DSAStack
, *this, cast
<CapturedStmt
>(AStmt
));
6252 int ThisCaptureLevel
= getOpenMPCaptureLevels(Kind
);
6254 while (--ThisCaptureLevel
>= 0)
6255 S
= cast
<CapturedStmt
>(S
)->getCapturedStmt();
6256 DSAChecker
.Visit(S
);
6257 if (!isOpenMPTargetDataManagementDirective(Kind
) &&
6258 !isOpenMPTaskingDirective(Kind
)) {
6259 // Visit subcaptures to generate implicit clauses for captured vars.
6260 auto *CS
= cast
<CapturedStmt
>(AStmt
);
6261 SmallVector
<OpenMPDirectiveKind
, 4> CaptureRegions
;
6262 getOpenMPCaptureRegions(CaptureRegions
, Kind
);
6263 // Ignore outer tasking regions for target directives.
6264 if (CaptureRegions
.size() > 1 && CaptureRegions
.front() == OMPD_task
)
6265 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
6266 DSAChecker
.visitSubCaptures(CS
);
6268 if (DSAChecker
.isErrorFound())
6270 // Generate list of implicitly defined firstprivate variables.
6271 VarsWithInheritedDSA
= DSAChecker
.getVarsWithInheritedDSA();
6273 SmallVector
<Expr
*, 4> ImplicitFirstprivates(
6274 DSAChecker
.getImplicitFirstprivate().begin(),
6275 DSAChecker
.getImplicitFirstprivate().end());
6276 SmallVector
<Expr
*, 4> ImplicitPrivates(
6277 DSAChecker
.getImplicitPrivate().begin(),
6278 DSAChecker
.getImplicitPrivate().end());
6279 const unsigned DefaultmapKindNum
= OMPC_DEFAULTMAP_pointer
+ 1;
6280 SmallVector
<Expr
*, 4> ImplicitMaps
[DefaultmapKindNum
][OMPC_MAP_delete
];
6281 SmallVector
<OpenMPMapModifierKind
, NumberOfOMPMapClauseModifiers
>
6282 ImplicitMapModifiers
[DefaultmapKindNum
];
6283 SmallVector
<SourceLocation
, NumberOfOMPMapClauseModifiers
>
6284 ImplicitMapModifiersLoc
[DefaultmapKindNum
];
6285 // Get the original location of present modifier from Defaultmap clause.
6286 SourceLocation PresentModifierLocs
[DefaultmapKindNum
];
6287 for (OMPClause
*C
: Clauses
) {
6288 if (auto *DMC
= dyn_cast
<OMPDefaultmapClause
>(C
))
6289 if (DMC
->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present
)
6290 PresentModifierLocs
[DMC
->getDefaultmapKind()] =
6291 DMC
->getDefaultmapModifierLoc();
6293 for (unsigned VC
= 0; VC
< DefaultmapKindNum
; ++VC
) {
6294 auto Kind
= static_cast<OpenMPDefaultmapClauseKind
>(VC
);
6295 for (unsigned I
= 0; I
< OMPC_MAP_delete
; ++I
) {
6296 ArrayRef
<Expr
*> ImplicitMap
= DSAChecker
.getImplicitMap(
6297 Kind
, static_cast<OpenMPMapClauseKind
>(I
));
6298 ImplicitMaps
[VC
][I
].append(ImplicitMap
.begin(), ImplicitMap
.end());
6300 ArrayRef
<OpenMPMapModifierKind
> ImplicitModifier
=
6301 DSAChecker
.getImplicitMapModifier(Kind
);
6302 ImplicitMapModifiers
[VC
].append(ImplicitModifier
.begin(),
6303 ImplicitModifier
.end());
6304 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc
[VC
]),
6305 ImplicitModifier
.size(), PresentModifierLocs
[VC
]);
6307 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6308 for (OMPClause
*C
: Clauses
) {
6309 if (auto *IRC
= dyn_cast
<OMPInReductionClause
>(C
)) {
6310 for (Expr
*E
: IRC
->taskgroup_descriptors())
6312 ImplicitFirstprivates
.emplace_back(E
);
6314 // OpenMP 5.0, 2.10.1 task Construct
6315 // [detach clause]... The event-handle will be considered as if it was
6316 // specified on a firstprivate clause.
6317 if (auto *DC
= dyn_cast
<OMPDetachClause
>(C
))
6318 ImplicitFirstprivates
.push_back(DC
->getEventHandler());
6320 if (!ImplicitFirstprivates
.empty()) {
6321 if (OMPClause
*Implicit
= ActOnOpenMPFirstprivateClause(
6322 ImplicitFirstprivates
, SourceLocation(), SourceLocation(),
6323 SourceLocation())) {
6324 ClausesWithImplicit
.push_back(Implicit
);
6325 ErrorFound
= cast
<OMPFirstprivateClause
>(Implicit
)->varlist_size() !=
6326 ImplicitFirstprivates
.size();
6331 if (!ImplicitPrivates
.empty()) {
6332 if (OMPClause
*Implicit
=
6333 ActOnOpenMPPrivateClause(ImplicitPrivates
, SourceLocation(),
6334 SourceLocation(), SourceLocation())) {
6335 ClausesWithImplicit
.push_back(Implicit
);
6336 ErrorFound
= cast
<OMPPrivateClause
>(Implicit
)->varlist_size() !=
6337 ImplicitPrivates
.size();
6342 // OpenMP 5.0 [2.19.7]
6343 // If a list item appears in a reduction, lastprivate or linear
6344 // clause on a combined target construct then it is treated as
6345 // if it also appears in a map clause with a map-type of tofrom
6346 if (getLangOpts().OpenMP
>= 50 && Kind
!= OMPD_target
&&
6347 isOpenMPTargetExecutionDirective(Kind
)) {
6348 SmallVector
<Expr
*, 4> ImplicitExprs
;
6349 for (OMPClause
*C
: Clauses
) {
6350 if (auto *RC
= dyn_cast
<OMPReductionClause
>(C
))
6351 for (Expr
*E
: RC
->varlists())
6352 if (!isa
<DeclRefExpr
>(E
->IgnoreParenImpCasts()))
6353 ImplicitExprs
.emplace_back(E
);
6355 if (!ImplicitExprs
.empty()) {
6356 ArrayRef
<Expr
*> Exprs
= ImplicitExprs
;
6357 CXXScopeSpec MapperIdScopeSpec
;
6358 DeclarationNameInfo MapperId
;
6359 if (OMPClause
*Implicit
= ActOnOpenMPMapClause(
6360 nullptr, OMPC_MAP_MODIFIER_unknown
, SourceLocation(),
6361 MapperIdScopeSpec
, MapperId
, OMPC_MAP_tofrom
,
6362 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6363 Exprs
, OMPVarListLocTy(), /*NoDiagnose=*/true))
6364 ClausesWithImplicit
.emplace_back(Implicit
);
6367 for (unsigned I
= 0, E
= DefaultmapKindNum
; I
< E
; ++I
) {
6368 int ClauseKindCnt
= -1;
6369 for (ArrayRef
<Expr
*> ImplicitMap
: ImplicitMaps
[I
]) {
6371 if (ImplicitMap
.empty())
6373 CXXScopeSpec MapperIdScopeSpec
;
6374 DeclarationNameInfo MapperId
;
6375 auto Kind
= static_cast<OpenMPMapClauseKind
>(ClauseKindCnt
);
6376 if (OMPClause
*Implicit
= ActOnOpenMPMapClause(
6377 nullptr, ImplicitMapModifiers
[I
], ImplicitMapModifiersLoc
[I
],
6378 MapperIdScopeSpec
, MapperId
, Kind
, /*IsMapTypeImplicit=*/true,
6379 SourceLocation(), SourceLocation(), ImplicitMap
,
6380 OMPVarListLocTy())) {
6381 ClausesWithImplicit
.emplace_back(Implicit
);
6382 ErrorFound
|= cast
<OMPMapClause
>(Implicit
)->varlist_size() !=
6389 // Build expressions for implicit maps of data members with 'default'
6391 if (LangOpts
.OpenMP
>= 50)
6392 processImplicitMapsWithDefaultMappers(*this, DSAStack
,
6393 ClausesWithImplicit
);
6396 llvm::SmallVector
<OpenMPDirectiveKind
, 4> AllowedNameModifiers
;
6399 Res
= ActOnOpenMPParallelDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6401 AllowedNameModifiers
.push_back(OMPD_parallel
);
6404 Res
= ActOnOpenMPSimdDirective(ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
,
6405 VarsWithInheritedDSA
);
6406 if (LangOpts
.OpenMP
>= 50)
6407 AllowedNameModifiers
.push_back(OMPD_simd
);
6411 ActOnOpenMPTileDirective(ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
);
6414 Res
= ActOnOpenMPUnrollDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6418 Res
= ActOnOpenMPForDirective(ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
,
6419 VarsWithInheritedDSA
);
6422 Res
= ActOnOpenMPForSimdDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6423 EndLoc
, VarsWithInheritedDSA
);
6424 if (LangOpts
.OpenMP
>= 50)
6425 AllowedNameModifiers
.push_back(OMPD_simd
);
6428 Res
= ActOnOpenMPSectionsDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6432 assert(ClausesWithImplicit
.empty() &&
6433 "No clauses are allowed for 'omp section' directive");
6434 Res
= ActOnOpenMPSectionDirective(AStmt
, StartLoc
, EndLoc
);
6437 Res
= ActOnOpenMPSingleDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6441 assert(ClausesWithImplicit
.empty() &&
6442 "No clauses are allowed for 'omp master' directive");
6443 Res
= ActOnOpenMPMasterDirective(AStmt
, StartLoc
, EndLoc
);
6446 Res
= ActOnOpenMPMaskedDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6450 Res
= ActOnOpenMPCriticalDirective(DirName
, ClausesWithImplicit
, AStmt
,
6453 case OMPD_parallel_for
:
6454 Res
= ActOnOpenMPParallelForDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6455 EndLoc
, VarsWithInheritedDSA
);
6456 AllowedNameModifiers
.push_back(OMPD_parallel
);
6458 case OMPD_parallel_for_simd
:
6459 Res
= ActOnOpenMPParallelForSimdDirective(
6460 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6461 AllowedNameModifiers
.push_back(OMPD_parallel
);
6462 if (LangOpts
.OpenMP
>= 50)
6463 AllowedNameModifiers
.push_back(OMPD_simd
);
6467 ActOnOpenMPScopeDirective(ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
);
6469 case OMPD_parallel_master
:
6470 Res
= ActOnOpenMPParallelMasterDirective(ClausesWithImplicit
, AStmt
,
6472 AllowedNameModifiers
.push_back(OMPD_parallel
);
6474 case OMPD_parallel_masked
:
6475 Res
= ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit
, AStmt
,
6477 AllowedNameModifiers
.push_back(OMPD_parallel
);
6479 case OMPD_parallel_sections
:
6480 Res
= ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit
, AStmt
,
6482 AllowedNameModifiers
.push_back(OMPD_parallel
);
6486 ActOnOpenMPTaskDirective(ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
);
6487 AllowedNameModifiers
.push_back(OMPD_task
);
6489 case OMPD_taskyield
:
6490 assert(ClausesWithImplicit
.empty() &&
6491 "No clauses are allowed for 'omp taskyield' directive");
6492 assert(AStmt
== nullptr &&
6493 "No associated statement allowed for 'omp taskyield' directive");
6494 Res
= ActOnOpenMPTaskyieldDirective(StartLoc
, EndLoc
);
6497 assert(AStmt
== nullptr &&
6498 "No associated statement allowed for 'omp error' directive");
6499 Res
= ActOnOpenMPErrorDirective(ClausesWithImplicit
, StartLoc
, EndLoc
);
6502 assert(ClausesWithImplicit
.empty() &&
6503 "No clauses are allowed for 'omp barrier' directive");
6504 assert(AStmt
== nullptr &&
6505 "No associated statement allowed for 'omp barrier' directive");
6506 Res
= ActOnOpenMPBarrierDirective(StartLoc
, EndLoc
);
6509 assert(AStmt
== nullptr &&
6510 "No associated statement allowed for 'omp taskwait' directive");
6511 Res
= ActOnOpenMPTaskwaitDirective(ClausesWithImplicit
, StartLoc
, EndLoc
);
6513 case OMPD_taskgroup
:
6514 Res
= ActOnOpenMPTaskgroupDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6518 assert(AStmt
== nullptr &&
6519 "No associated statement allowed for 'omp flush' directive");
6520 Res
= ActOnOpenMPFlushDirective(ClausesWithImplicit
, StartLoc
, EndLoc
);
6523 assert(AStmt
== nullptr &&
6524 "No associated statement allowed for 'omp depobj' directive");
6525 Res
= ActOnOpenMPDepobjDirective(ClausesWithImplicit
, StartLoc
, EndLoc
);
6528 assert(AStmt
== nullptr &&
6529 "No associated statement allowed for 'omp scan' directive");
6530 Res
= ActOnOpenMPScanDirective(ClausesWithImplicit
, StartLoc
, EndLoc
);
6533 Res
= ActOnOpenMPOrderedDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6537 Res
= ActOnOpenMPAtomicDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6542 ActOnOpenMPTeamsDirective(ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
);
6545 Res
= ActOnOpenMPTargetDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6547 AllowedNameModifiers
.push_back(OMPD_target
);
6549 case OMPD_target_parallel
:
6550 Res
= ActOnOpenMPTargetParallelDirective(ClausesWithImplicit
, AStmt
,
6552 AllowedNameModifiers
.push_back(OMPD_target
);
6553 AllowedNameModifiers
.push_back(OMPD_parallel
);
6555 case OMPD_target_parallel_for
:
6556 Res
= ActOnOpenMPTargetParallelForDirective(
6557 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6558 AllowedNameModifiers
.push_back(OMPD_target
);
6559 AllowedNameModifiers
.push_back(OMPD_parallel
);
6561 case OMPD_cancellation_point
:
6562 assert(ClausesWithImplicit
.empty() &&
6563 "No clauses are allowed for 'omp cancellation point' directive");
6564 assert(AStmt
== nullptr && "No associated statement allowed for 'omp "
6565 "cancellation point' directive");
6566 Res
= ActOnOpenMPCancellationPointDirective(StartLoc
, EndLoc
, CancelRegion
);
6569 assert(AStmt
== nullptr &&
6570 "No associated statement allowed for 'omp cancel' directive");
6571 Res
= ActOnOpenMPCancelDirective(ClausesWithImplicit
, StartLoc
, EndLoc
,
6573 AllowedNameModifiers
.push_back(OMPD_cancel
);
6575 case OMPD_target_data
:
6576 Res
= ActOnOpenMPTargetDataDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6578 AllowedNameModifiers
.push_back(OMPD_target_data
);
6580 case OMPD_target_enter_data
:
6581 Res
= ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit
, StartLoc
,
6583 AllowedNameModifiers
.push_back(OMPD_target_enter_data
);
6585 case OMPD_target_exit_data
:
6586 Res
= ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit
, StartLoc
,
6588 AllowedNameModifiers
.push_back(OMPD_target_exit_data
);
6591 Res
= ActOnOpenMPTaskLoopDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6592 EndLoc
, VarsWithInheritedDSA
);
6593 AllowedNameModifiers
.push_back(OMPD_taskloop
);
6595 case OMPD_taskloop_simd
:
6596 Res
= ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6597 EndLoc
, VarsWithInheritedDSA
);
6598 AllowedNameModifiers
.push_back(OMPD_taskloop
);
6599 if (LangOpts
.OpenMP
>= 50)
6600 AllowedNameModifiers
.push_back(OMPD_simd
);
6602 case OMPD_master_taskloop
:
6603 Res
= ActOnOpenMPMasterTaskLoopDirective(
6604 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6605 AllowedNameModifiers
.push_back(OMPD_taskloop
);
6607 case OMPD_masked_taskloop
:
6608 Res
= ActOnOpenMPMaskedTaskLoopDirective(
6609 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6610 AllowedNameModifiers
.push_back(OMPD_taskloop
);
6612 case OMPD_master_taskloop_simd
:
6613 Res
= ActOnOpenMPMasterTaskLoopSimdDirective(
6614 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6615 AllowedNameModifiers
.push_back(OMPD_taskloop
);
6616 if (LangOpts
.OpenMP
>= 50)
6617 AllowedNameModifiers
.push_back(OMPD_simd
);
6619 case OMPD_masked_taskloop_simd
:
6620 Res
= ActOnOpenMPMaskedTaskLoopSimdDirective(
6621 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6622 if (LangOpts
.OpenMP
>= 51) {
6623 AllowedNameModifiers
.push_back(OMPD_taskloop
);
6624 AllowedNameModifiers
.push_back(OMPD_simd
);
6627 case OMPD_parallel_master_taskloop
:
6628 Res
= ActOnOpenMPParallelMasterTaskLoopDirective(
6629 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6630 AllowedNameModifiers
.push_back(OMPD_taskloop
);
6631 AllowedNameModifiers
.push_back(OMPD_parallel
);
6633 case OMPD_parallel_masked_taskloop
:
6634 Res
= ActOnOpenMPParallelMaskedTaskLoopDirective(
6635 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6636 if (LangOpts
.OpenMP
>= 51) {
6637 AllowedNameModifiers
.push_back(OMPD_taskloop
);
6638 AllowedNameModifiers
.push_back(OMPD_parallel
);
6641 case OMPD_parallel_master_taskloop_simd
:
6642 Res
= ActOnOpenMPParallelMasterTaskLoopSimdDirective(
6643 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6644 AllowedNameModifiers
.push_back(OMPD_taskloop
);
6645 AllowedNameModifiers
.push_back(OMPD_parallel
);
6646 if (LangOpts
.OpenMP
>= 50)
6647 AllowedNameModifiers
.push_back(OMPD_simd
);
6649 case OMPD_parallel_masked_taskloop_simd
:
6650 Res
= ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
6651 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6652 if (LangOpts
.OpenMP
>= 51) {
6653 AllowedNameModifiers
.push_back(OMPD_taskloop
);
6654 AllowedNameModifiers
.push_back(OMPD_parallel
);
6655 AllowedNameModifiers
.push_back(OMPD_simd
);
6658 case OMPD_distribute
:
6659 Res
= ActOnOpenMPDistributeDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6660 EndLoc
, VarsWithInheritedDSA
);
6662 case OMPD_target_update
:
6663 Res
= ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit
, StartLoc
,
6665 AllowedNameModifiers
.push_back(OMPD_target_update
);
6667 case OMPD_distribute_parallel_for
:
6668 Res
= ActOnOpenMPDistributeParallelForDirective(
6669 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6670 AllowedNameModifiers
.push_back(OMPD_parallel
);
6672 case OMPD_distribute_parallel_for_simd
:
6673 Res
= ActOnOpenMPDistributeParallelForSimdDirective(
6674 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6675 AllowedNameModifiers
.push_back(OMPD_parallel
);
6676 if (LangOpts
.OpenMP
>= 50)
6677 AllowedNameModifiers
.push_back(OMPD_simd
);
6679 case OMPD_distribute_simd
:
6680 Res
= ActOnOpenMPDistributeSimdDirective(
6681 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6682 if (LangOpts
.OpenMP
>= 50)
6683 AllowedNameModifiers
.push_back(OMPD_simd
);
6685 case OMPD_target_parallel_for_simd
:
6686 Res
= ActOnOpenMPTargetParallelForSimdDirective(
6687 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6688 AllowedNameModifiers
.push_back(OMPD_target
);
6689 AllowedNameModifiers
.push_back(OMPD_parallel
);
6690 if (LangOpts
.OpenMP
>= 50)
6691 AllowedNameModifiers
.push_back(OMPD_simd
);
6693 case OMPD_target_simd
:
6694 Res
= ActOnOpenMPTargetSimdDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6695 EndLoc
, VarsWithInheritedDSA
);
6696 AllowedNameModifiers
.push_back(OMPD_target
);
6697 if (LangOpts
.OpenMP
>= 50)
6698 AllowedNameModifiers
.push_back(OMPD_simd
);
6700 case OMPD_teams_distribute
:
6701 Res
= ActOnOpenMPTeamsDistributeDirective(
6702 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6704 case OMPD_teams_distribute_simd
:
6705 Res
= ActOnOpenMPTeamsDistributeSimdDirective(
6706 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6707 if (LangOpts
.OpenMP
>= 50)
6708 AllowedNameModifiers
.push_back(OMPD_simd
);
6710 case OMPD_teams_distribute_parallel_for_simd
:
6711 Res
= ActOnOpenMPTeamsDistributeParallelForSimdDirective(
6712 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6713 AllowedNameModifiers
.push_back(OMPD_parallel
);
6714 if (LangOpts
.OpenMP
>= 50)
6715 AllowedNameModifiers
.push_back(OMPD_simd
);
6717 case OMPD_teams_distribute_parallel_for
:
6718 Res
= ActOnOpenMPTeamsDistributeParallelForDirective(
6719 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6720 AllowedNameModifiers
.push_back(OMPD_parallel
);
6722 case OMPD_target_teams
:
6723 Res
= ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6725 AllowedNameModifiers
.push_back(OMPD_target
);
6727 case OMPD_target_teams_distribute
:
6728 Res
= ActOnOpenMPTargetTeamsDistributeDirective(
6729 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6730 AllowedNameModifiers
.push_back(OMPD_target
);
6732 case OMPD_target_teams_distribute_parallel_for
:
6733 Res
= ActOnOpenMPTargetTeamsDistributeParallelForDirective(
6734 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6735 AllowedNameModifiers
.push_back(OMPD_target
);
6736 AllowedNameModifiers
.push_back(OMPD_parallel
);
6738 case OMPD_target_teams_distribute_parallel_for_simd
:
6739 Res
= ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
6740 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6741 AllowedNameModifiers
.push_back(OMPD_target
);
6742 AllowedNameModifiers
.push_back(OMPD_parallel
);
6743 if (LangOpts
.OpenMP
>= 50)
6744 AllowedNameModifiers
.push_back(OMPD_simd
);
6746 case OMPD_target_teams_distribute_simd
:
6747 Res
= ActOnOpenMPTargetTeamsDistributeSimdDirective(
6748 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6749 AllowedNameModifiers
.push_back(OMPD_target
);
6750 if (LangOpts
.OpenMP
>= 50)
6751 AllowedNameModifiers
.push_back(OMPD_simd
);
6754 assert(AStmt
== nullptr &&
6755 "No associated statement allowed for 'omp interop' directive");
6756 Res
= ActOnOpenMPInteropDirective(ClausesWithImplicit
, StartLoc
, EndLoc
);
6759 Res
= ActOnOpenMPDispatchDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6763 Res
= ActOnOpenMPGenericLoopDirective(ClausesWithImplicit
, AStmt
, StartLoc
,
6764 EndLoc
, VarsWithInheritedDSA
);
6766 case OMPD_teams_loop
:
6767 Res
= ActOnOpenMPTeamsGenericLoopDirective(
6768 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6770 case OMPD_target_teams_loop
:
6771 Res
= ActOnOpenMPTargetTeamsGenericLoopDirective(
6772 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6773 AllowedNameModifiers
.push_back(OMPD_target
);
6775 case OMPD_parallel_loop
:
6776 Res
= ActOnOpenMPParallelGenericLoopDirective(
6777 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6779 case OMPD_target_parallel_loop
:
6780 Res
= ActOnOpenMPTargetParallelGenericLoopDirective(
6781 ClausesWithImplicit
, AStmt
, StartLoc
, EndLoc
, VarsWithInheritedDSA
);
6783 case OMPD_declare_target
:
6784 case OMPD_end_declare_target
:
6785 case OMPD_threadprivate
:
6787 case OMPD_declare_reduction
:
6788 case OMPD_declare_mapper
:
6789 case OMPD_declare_simd
:
6791 case OMPD_declare_variant
:
6792 case OMPD_begin_declare_variant
:
6793 case OMPD_end_declare_variant
:
6794 llvm_unreachable("OpenMP Directive is not allowed");
6797 llvm_unreachable("Unknown OpenMP directive");
6800 ErrorFound
= Res
.isInvalid() || ErrorFound
;
6802 // Check variables in the clauses if default(none) or
6803 // default(firstprivate) was specified.
6804 if (DSAStack
->getDefaultDSA() == DSA_none
||
6805 DSAStack
->getDefaultDSA() == DSA_private
||
6806 DSAStack
->getDefaultDSA() == DSA_firstprivate
) {
6807 DSAAttrChecker
DSAChecker(DSAStack
, *this, nullptr);
6808 for (OMPClause
*C
: Clauses
) {
6809 switch (C
->getClauseKind()) {
6810 case OMPC_num_threads
:
6811 case OMPC_dist_schedule
:
6812 // Do not analyse if no parent teams directive.
6813 if (isOpenMPTeamsDirective(Kind
))
6817 if (isOpenMPTeamsDirective(Kind
) &&
6818 cast
<OMPIfClause
>(C
)->getNameModifier() != OMPD_target
)
6820 if (isOpenMPParallelDirective(Kind
) &&
6821 isOpenMPTaskLoopDirective(Kind
) &&
6822 cast
<OMPIfClause
>(C
)->getNameModifier() != OMPD_parallel
)
6828 case OMPC_grainsize
:
6829 case OMPC_num_tasks
:
6832 case OMPC_novariants
:
6833 case OMPC_nocontext
:
6834 // Do not analyze if no parent parallel directive.
6835 if (isOpenMPParallelDirective(Kind
))
6840 case OMPC_num_teams
:
6841 case OMPC_thread_limit
:
6848 case OMPC_proc_bind
:
6850 case OMPC_firstprivate
:
6851 case OMPC_lastprivate
:
6853 case OMPC_reduction
:
6854 case OMPC_task_reduction
:
6855 case OMPC_in_reduction
:
6859 case OMPC_copyprivate
:
6862 case OMPC_mergeable
:
6879 case OMPC_defaultmap
:
6882 case OMPC_use_device_ptr
:
6883 case OMPC_use_device_addr
:
6884 case OMPC_is_device_ptr
:
6885 case OMPC_has_device_addr
:
6886 case OMPC_nontemporal
:
6889 case OMPC_inclusive
:
6890 case OMPC_exclusive
:
6891 case OMPC_uses_allocators
:
6896 case OMPC_allocator
:
6899 case OMPC_threadprivate
:
6902 case OMPC_unified_address
:
6903 case OMPC_unified_shared_memory
:
6904 case OMPC_reverse_offload
:
6905 case OMPC_dynamic_allocators
:
6906 case OMPC_atomic_default_mem_order
:
6907 case OMPC_device_type
:
6914 llvm_unreachable("Unexpected clause");
6916 for (Stmt
*CC
: C
->children()) {
6918 DSAChecker
.Visit(CC
);
6921 for (const auto &P
: DSAChecker
.getVarsWithInheritedDSA())
6922 VarsWithInheritedDSA
[P
.getFirst()] = P
.getSecond();
6924 for (const auto &P
: VarsWithInheritedDSA
) {
6925 if (P
.getFirst()->isImplicit() || isa
<OMPCapturedExprDecl
>(P
.getFirst()))
6928 if (DSAStack
->getDefaultDSA() == DSA_none
||
6929 DSAStack
->getDefaultDSA() == DSA_private
||
6930 DSAStack
->getDefaultDSA() == DSA_firstprivate
) {
6931 Diag(P
.second
->getExprLoc(), diag::err_omp_no_dsa_for_variable
)
6932 << P
.first
<< P
.second
->getSourceRange();
6933 Diag(DSAStack
->getDefaultDSALocation(), diag::note_omp_default_dsa_none
);
6934 } else if (getLangOpts().OpenMP
>= 50) {
6935 Diag(P
.second
->getExprLoc(),
6936 diag::err_omp_defaultmap_no_attr_for_variable
)
6937 << P
.first
<< P
.second
->getSourceRange();
6938 Diag(DSAStack
->getDefaultDSALocation(),
6939 diag::note_omp_defaultmap_attr_none
);
6943 if (!AllowedNameModifiers
.empty())
6944 ErrorFound
= checkIfClauses(*this, Kind
, Clauses
, AllowedNameModifiers
) ||
6950 if (!CurContext
->isDependentContext() &&
6951 isOpenMPTargetExecutionDirective(Kind
) &&
6952 !(DSAStack
->hasRequiresDeclWithClause
<OMPUnifiedSharedMemoryClause
>() ||
6953 DSAStack
->hasRequiresDeclWithClause
<OMPUnifiedAddressClause
>() ||
6954 DSAStack
->hasRequiresDeclWithClause
<OMPReverseOffloadClause
>() ||
6955 DSAStack
->hasRequiresDeclWithClause
<OMPDynamicAllocatorsClause
>())) {
6956 // Register target to DSA Stack.
6957 DSAStack
->addTargetDirLocation(StartLoc
);
6963 Sema::DeclGroupPtrTy
Sema::ActOnOpenMPDeclareSimdDirective(
6964 DeclGroupPtrTy DG
, OMPDeclareSimdDeclAttr::BranchStateTy BS
, Expr
*Simdlen
,
6965 ArrayRef
<Expr
*> Uniforms
, ArrayRef
<Expr
*> Aligneds
,
6966 ArrayRef
<Expr
*> Alignments
, ArrayRef
<Expr
*> Linears
,
6967 ArrayRef
<unsigned> LinModifiers
, ArrayRef
<Expr
*> Steps
, SourceRange SR
) {
6968 assert(Aligneds
.size() == Alignments
.size());
6969 assert(Linears
.size() == LinModifiers
.size());
6970 assert(Linears
.size() == Steps
.size());
6971 if (!DG
|| DG
.get().isNull())
6972 return DeclGroupPtrTy();
6974 const int SimdId
= 0;
6975 if (!DG
.get().isSingleDecl()) {
6976 Diag(SR
.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant
)
6980 Decl
*ADecl
= DG
.get().getSingleDecl();
6981 if (auto *FTD
= dyn_cast
<FunctionTemplateDecl
>(ADecl
))
6982 ADecl
= FTD
->getTemplatedDecl();
6984 auto *FD
= dyn_cast
<FunctionDecl
>(ADecl
);
6986 Diag(ADecl
->getLocation(), diag::err_omp_function_expected
) << SimdId
;
6987 return DeclGroupPtrTy();
6990 // OpenMP [2.8.2, declare simd construct, Description]
6991 // The parameter of the simdlen clause must be a constant positive integer
6995 SL
= VerifyPositiveIntegerConstantInClause(Simdlen
, OMPC_simdlen
);
6996 // OpenMP [2.8.2, declare simd construct, Description]
6997 // The special this pointer can be used as if was one of the arguments to the
6998 // function in any of the linear, aligned, or uniform clauses.
6999 // The uniform clause declares one or more arguments to have an invariant
7000 // value for all concurrent invocations of the function in the execution of a
7001 // single SIMD loop.
7002 llvm::DenseMap
<const Decl
*, const Expr
*> UniformedArgs
;
7003 const Expr
*UniformedLinearThis
= nullptr;
7004 for (const Expr
*E
: Uniforms
) {
7005 E
= E
->IgnoreParenImpCasts();
7006 if (const auto *DRE
= dyn_cast
<DeclRefExpr
>(E
))
7007 if (const auto *PVD
= dyn_cast
<ParmVarDecl
>(DRE
->getDecl()))
7008 if (FD
->getNumParams() > PVD
->getFunctionScopeIndex() &&
7009 FD
->getParamDecl(PVD
->getFunctionScopeIndex())
7010 ->getCanonicalDecl() == PVD
->getCanonicalDecl()) {
7011 UniformedArgs
.try_emplace(PVD
->getCanonicalDecl(), E
);
7014 if (isa
<CXXThisExpr
>(E
)) {
7015 UniformedLinearThis
= E
;
7018 Diag(E
->getExprLoc(), diag::err_omp_param_or_this_in_clause
)
7019 << FD
->getDeclName() << (isa
<CXXMethodDecl
>(ADecl
) ? 1 : 0);
7021 // OpenMP [2.8.2, declare simd construct, Description]
7022 // The aligned clause declares that the object to which each list item points
7023 // is aligned to the number of bytes expressed in the optional parameter of
7024 // the aligned clause.
7025 // The special this pointer can be used as if was one of the arguments to the
7026 // function in any of the linear, aligned, or uniform clauses.
7027 // The type of list items appearing in the aligned clause must be array,
7028 // pointer, reference to array, or reference to pointer.
7029 llvm::DenseMap
<const Decl
*, const Expr
*> AlignedArgs
;
7030 const Expr
*AlignedThis
= nullptr;
7031 for (const Expr
*E
: Aligneds
) {
7032 E
= E
->IgnoreParenImpCasts();
7033 if (const auto *DRE
= dyn_cast
<DeclRefExpr
>(E
))
7034 if (const auto *PVD
= dyn_cast
<ParmVarDecl
>(DRE
->getDecl())) {
7035 const VarDecl
*CanonPVD
= PVD
->getCanonicalDecl();
7036 if (FD
->getNumParams() > PVD
->getFunctionScopeIndex() &&
7037 FD
->getParamDecl(PVD
->getFunctionScopeIndex())
7038 ->getCanonicalDecl() == CanonPVD
) {
7039 // OpenMP [2.8.1, simd construct, Restrictions]
7040 // A list-item cannot appear in more than one aligned clause.
7041 if (AlignedArgs
.count(CanonPVD
) > 0) {
7042 Diag(E
->getExprLoc(), diag::err_omp_used_in_clause_twice
)
7043 << 1 << getOpenMPClauseName(OMPC_aligned
)
7044 << E
->getSourceRange();
7045 Diag(AlignedArgs
[CanonPVD
]->getExprLoc(),
7046 diag::note_omp_explicit_dsa
)
7047 << getOpenMPClauseName(OMPC_aligned
);
7050 AlignedArgs
[CanonPVD
] = E
;
7051 QualType QTy
= PVD
->getType()
7052 .getNonReferenceType()
7053 .getUnqualifiedType()
7054 .getCanonicalType();
7055 const Type
*Ty
= QTy
.getTypePtrOrNull();
7056 if (!Ty
|| (!Ty
->isArrayType() && !Ty
->isPointerType())) {
7057 Diag(E
->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr
)
7058 << QTy
<< getLangOpts().CPlusPlus
<< E
->getSourceRange();
7059 Diag(PVD
->getLocation(), diag::note_previous_decl
) << PVD
;
7064 if (isa
<CXXThisExpr
>(E
)) {
7066 Diag(E
->getExprLoc(), diag::err_omp_used_in_clause_twice
)
7067 << 2 << getOpenMPClauseName(OMPC_aligned
) << E
->getSourceRange();
7068 Diag(AlignedThis
->getExprLoc(), diag::note_omp_explicit_dsa
)
7069 << getOpenMPClauseName(OMPC_aligned
);
7074 Diag(E
->getExprLoc(), diag::err_omp_param_or_this_in_clause
)
7075 << FD
->getDeclName() << (isa
<CXXMethodDecl
>(ADecl
) ? 1 : 0);
7077 // The optional parameter of the aligned clause, alignment, must be a constant
7078 // positive integer expression. If no optional parameter is specified,
7079 // implementation-defined default alignments for SIMD instructions on the
7080 // target platforms are assumed.
7081 SmallVector
<const Expr
*, 4> NewAligns
;
7082 for (Expr
*E
: Alignments
) {
7085 Align
= VerifyPositiveIntegerConstantInClause(E
, OMPC_aligned
);
7086 NewAligns
.push_back(Align
.get());
7088 // OpenMP [2.8.2, declare simd construct, Description]
7089 // The linear clause declares one or more list items to be private to a SIMD
7090 // lane and to have a linear relationship with respect to the iteration space
7092 // The special this pointer can be used as if was one of the arguments to the
7093 // function in any of the linear, aligned, or uniform clauses.
7094 // When a linear-step expression is specified in a linear clause it must be
7095 // either a constant integer expression or an integer-typed parameter that is
7096 // specified in a uniform clause on the directive.
7097 llvm::DenseMap
<const Decl
*, const Expr
*> LinearArgs
;
7098 const bool IsUniformedThis
= UniformedLinearThis
!= nullptr;
7099 auto MI
= LinModifiers
.begin();
7100 for (const Expr
*E
: Linears
) {
7101 auto LinKind
= static_cast<OpenMPLinearClauseKind
>(*MI
);
7103 E
= E
->IgnoreParenImpCasts();
7104 if (const auto *DRE
= dyn_cast
<DeclRefExpr
>(E
))
7105 if (const auto *PVD
= dyn_cast
<ParmVarDecl
>(DRE
->getDecl())) {
7106 const VarDecl
*CanonPVD
= PVD
->getCanonicalDecl();
7107 if (FD
->getNumParams() > PVD
->getFunctionScopeIndex() &&
7108 FD
->getParamDecl(PVD
->getFunctionScopeIndex())
7109 ->getCanonicalDecl() == CanonPVD
) {
7110 // OpenMP [2.15.3.7, linear Clause, Restrictions]
7111 // A list-item cannot appear in more than one linear clause.
7112 if (LinearArgs
.count(CanonPVD
) > 0) {
7113 Diag(E
->getExprLoc(), diag::err_omp_wrong_dsa
)
7114 << getOpenMPClauseName(OMPC_linear
)
7115 << getOpenMPClauseName(OMPC_linear
) << E
->getSourceRange();
7116 Diag(LinearArgs
[CanonPVD
]->getExprLoc(),
7117 diag::note_omp_explicit_dsa
)
7118 << getOpenMPClauseName(OMPC_linear
);
7121 // Each argument can appear in at most one uniform or linear clause.
7122 if (UniformedArgs
.count(CanonPVD
) > 0) {
7123 Diag(E
->getExprLoc(), diag::err_omp_wrong_dsa
)
7124 << getOpenMPClauseName(OMPC_linear
)
7125 << getOpenMPClauseName(OMPC_uniform
) << E
->getSourceRange();
7126 Diag(UniformedArgs
[CanonPVD
]->getExprLoc(),
7127 diag::note_omp_explicit_dsa
)
7128 << getOpenMPClauseName(OMPC_uniform
);
7131 LinearArgs
[CanonPVD
] = E
;
7132 if (E
->isValueDependent() || E
->isTypeDependent() ||
7133 E
->isInstantiationDependent() ||
7134 E
->containsUnexpandedParameterPack())
7136 (void)CheckOpenMPLinearDecl(CanonPVD
, E
->getExprLoc(), LinKind
,
7137 PVD
->getOriginalType(),
7138 /*IsDeclareSimd=*/true);
7142 if (isa
<CXXThisExpr
>(E
)) {
7143 if (UniformedLinearThis
) {
7144 Diag(E
->getExprLoc(), diag::err_omp_wrong_dsa
)
7145 << getOpenMPClauseName(OMPC_linear
)
7146 << getOpenMPClauseName(IsUniformedThis
? OMPC_uniform
: OMPC_linear
)
7147 << E
->getSourceRange();
7148 Diag(UniformedLinearThis
->getExprLoc(), diag::note_omp_explicit_dsa
)
7149 << getOpenMPClauseName(IsUniformedThis
? OMPC_uniform
7153 UniformedLinearThis
= E
;
7154 if (E
->isValueDependent() || E
->isTypeDependent() ||
7155 E
->isInstantiationDependent() || E
->containsUnexpandedParameterPack())
7157 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E
->getExprLoc(), LinKind
,
7158 E
->getType(), /*IsDeclareSimd=*/true);
7161 Diag(E
->getExprLoc(), diag::err_omp_param_or_this_in_clause
)
7162 << FD
->getDeclName() << (isa
<CXXMethodDecl
>(ADecl
) ? 1 : 0);
7164 Expr
*Step
= nullptr;
7165 Expr
*NewStep
= nullptr;
7166 SmallVector
<Expr
*, 4> NewSteps
;
7167 for (Expr
*E
: Steps
) {
7168 // Skip the same step expression, it was checked already.
7169 if (Step
== E
|| !E
) {
7170 NewSteps
.push_back(E
? NewStep
: nullptr);
7174 if (const auto *DRE
= dyn_cast
<DeclRefExpr
>(Step
))
7175 if (const auto *PVD
= dyn_cast
<ParmVarDecl
>(DRE
->getDecl())) {
7176 const VarDecl
*CanonPVD
= PVD
->getCanonicalDecl();
7177 if (UniformedArgs
.count(CanonPVD
) == 0) {
7178 Diag(Step
->getExprLoc(), diag::err_omp_expected_uniform_param
)
7179 << Step
->getSourceRange();
7180 } else if (E
->isValueDependent() || E
->isTypeDependent() ||
7181 E
->isInstantiationDependent() ||
7182 E
->containsUnexpandedParameterPack() ||
7183 CanonPVD
->getType()->hasIntegerRepresentation()) {
7184 NewSteps
.push_back(Step
);
7186 Diag(Step
->getExprLoc(), diag::err_omp_expected_int_param
)
7187 << Step
->getSourceRange();
7192 if (Step
&& !Step
->isValueDependent() && !Step
->isTypeDependent() &&
7193 !Step
->isInstantiationDependent() &&
7194 !Step
->containsUnexpandedParameterPack()) {
7195 NewStep
= PerformOpenMPImplicitIntegerConversion(Step
->getExprLoc(), Step
)
7199 VerifyIntegerConstantExpression(NewStep
, /*FIXME*/ AllowFold
).get();
7201 NewSteps
.push_back(NewStep
);
7203 auto *NewAttr
= OMPDeclareSimdDeclAttr::CreateImplicit(
7204 Context
, BS
, SL
.get(), const_cast<Expr
**>(Uniforms
.data()),
7205 Uniforms
.size(), const_cast<Expr
**>(Aligneds
.data()), Aligneds
.size(),
7206 const_cast<Expr
**>(NewAligns
.data()), NewAligns
.size(),
7207 const_cast<Expr
**>(Linears
.data()), Linears
.size(),
7208 const_cast<unsigned *>(LinModifiers
.data()), LinModifiers
.size(),
7209 NewSteps
.data(), NewSteps
.size(), SR
);
7210 ADecl
->addAttr(NewAttr
);
7214 static void setPrototype(Sema
&S
, FunctionDecl
*FD
, FunctionDecl
*FDWithProto
,
7216 assert(NewType
->isFunctionProtoType() &&
7217 "Expected function type with prototype.");
7218 assert(FD
->getType()->isFunctionNoProtoType() &&
7219 "Expected function with type with no prototype.");
7220 assert(FDWithProto
->getType()->isFunctionProtoType() &&
7221 "Expected function with prototype.");
7222 // Synthesize parameters with the same types.
7223 FD
->setType(NewType
);
7224 SmallVector
<ParmVarDecl
*, 16> Params
;
7225 for (const ParmVarDecl
*P
: FDWithProto
->parameters()) {
7226 auto *Param
= ParmVarDecl::Create(S
.getASTContext(), FD
, SourceLocation(),
7227 SourceLocation(), nullptr, P
->getType(),
7228 /*TInfo=*/nullptr, SC_None
, nullptr);
7229 Param
->setScopeInfo(0, Params
.size());
7230 Param
->setImplicit();
7231 Params
.push_back(Param
);
7234 FD
->setParams(Params
);
7237 void Sema::ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl
*D
) {
7238 if (D
->isInvalidDecl())
7240 FunctionDecl
*FD
= nullptr;
7241 if (auto *UTemplDecl
= dyn_cast
<FunctionTemplateDecl
>(D
))
7242 FD
= UTemplDecl
->getTemplatedDecl();
7244 FD
= cast
<FunctionDecl
>(D
);
7245 assert(FD
&& "Expected a function declaration!");
7247 // If we are instantiating templates we do *not* apply scoped assumptions but
7248 // only global ones. We apply scoped assumption to the template definition
7250 if (!inTemplateInstantiation()) {
7251 for (AssumptionAttr
*AA
: OMPAssumeScoped
)
7254 for (AssumptionAttr
*AA
: OMPAssumeGlobal
)
7258 Sema::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo
&TI
)
7259 : TI(&TI
), NameSuffix(TI
.getMangledName()) {}
7261 void Sema::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(
7262 Scope
*S
, Declarator
&D
, MultiTemplateParamsArg TemplateParamLists
,
7263 SmallVectorImpl
<FunctionDecl
*> &Bases
) {
7264 if (!D
.getIdentifier())
7267 OMPDeclareVariantScope
&DVScope
= OMPDeclareVariantScopes
.back();
7269 // Template specialization is an extension, check if we do it.
7270 bool IsTemplated
= !TemplateParamLists
.empty();
7272 !DVScope
.TI
->isExtensionActive(
7273 llvm::omp::TraitProperty::implementation_extension_allow_templates
))
7276 IdentifierInfo
*BaseII
= D
.getIdentifier();
7277 LookupResult
Lookup(*this, DeclarationName(BaseII
), D
.getIdentifierLoc(),
7278 LookupOrdinaryName
);
7279 LookupParsedName(Lookup
, S
, &D
.getCXXScopeSpec());
7281 TypeSourceInfo
*TInfo
= GetTypeForDeclarator(D
, S
);
7282 QualType FType
= TInfo
->getType();
7285 D
.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr
;
7287 D
.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Consteval
;
7289 for (auto *Candidate
: Lookup
) {
7290 auto *CandidateDecl
= Candidate
->getUnderlyingDecl();
7291 FunctionDecl
*UDecl
= nullptr;
7292 if (IsTemplated
&& isa
<FunctionTemplateDecl
>(CandidateDecl
)) {
7293 auto *FTD
= cast
<FunctionTemplateDecl
>(CandidateDecl
);
7294 if (FTD
->getTemplateParameters()->size() == TemplateParamLists
.size())
7295 UDecl
= FTD
->getTemplatedDecl();
7296 } else if (!IsTemplated
)
7297 UDecl
= dyn_cast
<FunctionDecl
>(CandidateDecl
);
7301 // Don't specialize constexpr/consteval functions with
7302 // non-constexpr/consteval functions.
7303 if (UDecl
->isConstexpr() && !IsConstexpr
)
7305 if (UDecl
->isConsteval() && !IsConsteval
)
7308 QualType UDeclTy
= UDecl
->getType();
7309 if (!UDeclTy
->isDependentType()) {
7310 QualType NewType
= Context
.mergeFunctionTypes(
7311 FType
, UDeclTy
, /* OfBlockPointer */ false,
7312 /* Unqualified */ false, /* AllowCXX */ true);
7313 if (NewType
.isNull())
7318 Bases
.push_back(UDecl
);
7321 bool UseImplicitBase
= !DVScope
.TI
->isExtensionActive(
7322 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base
);
7323 // If no base was found we create a declaration that we use as base.
7324 if (Bases
.empty() && UseImplicitBase
) {
7325 D
.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration
);
7326 Decl
*BaseD
= HandleDeclarator(S
, D
, TemplateParamLists
);
7327 BaseD
->setImplicit(true);
7328 if (auto *BaseTemplD
= dyn_cast
<FunctionTemplateDecl
>(BaseD
))
7329 Bases
.push_back(BaseTemplD
->getTemplatedDecl());
7331 Bases
.push_back(cast
<FunctionDecl
>(BaseD
));
7334 std::string MangledName
;
7335 MangledName
+= D
.getIdentifier()->getName();
7336 MangledName
+= getOpenMPVariantManglingSeparatorStr();
7337 MangledName
+= DVScope
.NameSuffix
;
7338 IdentifierInfo
&VariantII
= Context
.Idents
.get(MangledName
);
7340 VariantII
.setMangledOpenMPVariantName(true);
7341 D
.SetIdentifier(&VariantII
, D
.getBeginLoc());
7344 void Sema::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
7345 Decl
*D
, SmallVectorImpl
<FunctionDecl
*> &Bases
) {
7346 // Do not mark function as is used to prevent its emission if this is the
7347 // only place where it is used.
7348 EnterExpressionEvaluationContext
Unevaluated(
7349 *this, Sema::ExpressionEvaluationContext::Unevaluated
);
7351 FunctionDecl
*FD
= nullptr;
7352 if (auto *UTemplDecl
= dyn_cast
<FunctionTemplateDecl
>(D
))
7353 FD
= UTemplDecl
->getTemplatedDecl();
7355 FD
= cast
<FunctionDecl
>(D
);
7356 auto *VariantFuncRef
= DeclRefExpr::Create(
7357 Context
, NestedNameSpecifierLoc(), SourceLocation(), FD
,
7358 /* RefersToEnclosingVariableOrCapture */ false,
7359 /* NameLoc */ FD
->getLocation(), FD
->getType(),
7360 ExprValueKind::VK_PRValue
);
7362 OMPDeclareVariantScope
&DVScope
= OMPDeclareVariantScopes
.back();
7363 auto *OMPDeclareVariantA
= OMPDeclareVariantAttr::CreateImplicit(
7364 Context
, VariantFuncRef
, DVScope
.TI
,
7365 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7366 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7367 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7368 for (FunctionDecl
*BaseFD
: Bases
)
7369 BaseFD
->addAttr(OMPDeclareVariantA
);
7372 ExprResult
Sema::ActOnOpenMPCall(ExprResult Call
, Scope
*Scope
,
7373 SourceLocation LParenLoc
,
7374 MultiExprArg ArgExprs
,
7375 SourceLocation RParenLoc
, Expr
*ExecConfig
) {
7376 // The common case is a regular call we do not want to specialize at all. Try
7377 // to make that case fast by bailing early.
7378 CallExpr
*CE
= dyn_cast
<CallExpr
>(Call
.get());
7382 FunctionDecl
*CalleeFnDecl
= CE
->getDirectCallee();
7386 if (LangOpts
.OpenMP
>= 51 && CalleeFnDecl
->getIdentifier() &&
7387 CalleeFnDecl
->getName().starts_with_insensitive("omp_")) {
7388 // checking for any calls inside an Order region
7389 if (Scope
&& Scope
->isOpenMPOrderClauseScope())
7390 Diag(LParenLoc
, diag::err_omp_unexpected_call_to_omp_runtime_api
);
7393 if (!CalleeFnDecl
->hasAttr
<OMPDeclareVariantAttr
>())
7396 ASTContext
&Context
= getASTContext();
7397 std::function
<void(StringRef
)> DiagUnknownTrait
= [this,
7398 CE
](StringRef ISATrait
) {
7399 // TODO Track the selector locations in a way that is accessible here to
7400 // improve the diagnostic location.
7401 Diag(CE
->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait
)
7404 TargetOMPContext
OMPCtx(Context
, std::move(DiagUnknownTrait
),
7405 getCurFunctionDecl(), DSAStack
->getConstructTraits());
7407 QualType CalleeFnType
= CalleeFnDecl
->getType();
7409 SmallVector
<Expr
*, 4> Exprs
;
7410 SmallVector
<VariantMatchInfo
, 4> VMIs
;
7411 while (CalleeFnDecl
) {
7412 for (OMPDeclareVariantAttr
*A
:
7413 CalleeFnDecl
->specific_attrs
<OMPDeclareVariantAttr
>()) {
7414 Expr
*VariantRef
= A
->getVariantFuncRef();
7416 VariantMatchInfo VMI
;
7417 OMPTraitInfo
&TI
= A
->getTraitInfo();
7418 TI
.getAsVariantMatchInfo(Context
, VMI
);
7419 if (!isVariantApplicableInContext(VMI
, OMPCtx
,
7420 /* DeviceSetOnly */ false))
7423 VMIs
.push_back(VMI
);
7424 Exprs
.push_back(VariantRef
);
7427 CalleeFnDecl
= CalleeFnDecl
->getPreviousDecl();
7432 int BestIdx
= getBestVariantMatchForContext(VMIs
, OMPCtx
);
7435 Expr
*BestExpr
= cast
<DeclRefExpr
>(Exprs
[BestIdx
]);
7436 Decl
*BestDecl
= cast
<DeclRefExpr
>(BestExpr
)->getDecl();
7439 // Try to build a (member) call expression for the current best applicable
7440 // variant expression. We allow this to fail in which case we continue
7441 // with the next best variant expression. The fail case is part of the
7442 // implementation defined behavior in the OpenMP standard when it talks
7443 // about what differences in the function prototypes: "Any differences
7444 // that the specific OpenMP context requires in the prototype of the
7445 // variant from the base function prototype are implementation defined."
7446 // This wording is there to allow the specialized variant to have a
7447 // different type than the base function. This is intended and OK but if
7448 // we cannot create a call the difference is not in the "implementation
7449 // defined range" we allow.
7450 Sema::TentativeAnalysisScope
Trap(*this);
7452 if (auto *SpecializedMethod
= dyn_cast
<CXXMethodDecl
>(BestDecl
)) {
7453 auto *MemberCall
= dyn_cast
<CXXMemberCallExpr
>(CE
);
7454 BestExpr
= MemberExpr::CreateImplicit(
7455 Context
, MemberCall
->getImplicitObjectArgument(),
7456 /* IsArrow */ false, SpecializedMethod
, Context
.BoundMemberTy
,
7457 MemberCall
->getValueKind(), MemberCall
->getObjectKind());
7459 NewCall
= BuildCallExpr(Scope
, BestExpr
, LParenLoc
, ArgExprs
, RParenLoc
,
7461 if (NewCall
.isUsable()) {
7462 if (CallExpr
*NCE
= dyn_cast
<CallExpr
>(NewCall
.get())) {
7463 FunctionDecl
*NewCalleeFnDecl
= NCE
->getDirectCallee();
7464 QualType NewType
= Context
.mergeFunctionTypes(
7465 CalleeFnType
, NewCalleeFnDecl
->getType(),
7466 /* OfBlockPointer */ false,
7467 /* Unqualified */ false, /* AllowCXX */ true);
7468 if (!NewType
.isNull())
7470 // Don't use the call if the function type was not compatible.
7476 VMIs
.erase(VMIs
.begin() + BestIdx
);
7477 Exprs
.erase(Exprs
.begin() + BestIdx
);
7478 } while (!VMIs
.empty());
7480 if (!NewCall
.isUsable())
7482 return PseudoObjectExpr::Create(Context
, CE
, {NewCall
.get()}, 0);
7485 std::optional
<std::pair
<FunctionDecl
*, Expr
*>>
7486 Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG
,
7487 Expr
*VariantRef
, OMPTraitInfo
&TI
,
7488 unsigned NumAppendArgs
,
7490 if (!DG
|| DG
.get().isNull())
7491 return std::nullopt
;
7493 const int VariantId
= 1;
7494 // Must be applied only to single decl.
7495 if (!DG
.get().isSingleDecl()) {
7496 Diag(SR
.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant
)
7498 return std::nullopt
;
7500 Decl
*ADecl
= DG
.get().getSingleDecl();
7501 if (auto *FTD
= dyn_cast
<FunctionTemplateDecl
>(ADecl
))
7502 ADecl
= FTD
->getTemplatedDecl();
7504 // Decl must be a function.
7505 auto *FD
= dyn_cast
<FunctionDecl
>(ADecl
);
7507 Diag(ADecl
->getLocation(), diag::err_omp_function_expected
)
7509 return std::nullopt
;
7512 auto &&HasMultiVersionAttributes
= [](const FunctionDecl
*FD
) {
7513 // The 'target' attribute needs to be separately checked because it does
7514 // not always signify a multiversion function declaration.
7515 return FD
->isMultiVersion() || FD
->hasAttr
<TargetAttr
>();
7517 // OpenMP is not compatible with multiversion function attributes.
7518 if (HasMultiVersionAttributes(FD
)) {
7519 Diag(FD
->getLocation(), diag::err_omp_declare_variant_incompat_attributes
)
7521 return std::nullopt
;
7524 // Allow #pragma omp declare variant only if the function is not used.
7525 if (FD
->isUsed(false))
7526 Diag(SR
.getBegin(), diag::warn_omp_declare_variant_after_used
)
7527 << FD
->getLocation();
7529 // Check if the function was emitted already.
7530 const FunctionDecl
*Definition
;
7531 if (!FD
->isThisDeclarationADefinition() && FD
->isDefined(Definition
) &&
7532 (LangOpts
.EmitAllDecls
|| Context
.DeclMustBeEmitted(Definition
)))
7533 Diag(SR
.getBegin(), diag::warn_omp_declare_variant_after_emitted
)
7534 << FD
->getLocation();
7536 // The VariantRef must point to function.
7538 Diag(SR
.getBegin(), diag::err_omp_function_expected
) << VariantId
;
7539 return std::nullopt
;
7542 auto ShouldDelayChecks
= [](Expr
*&E
, bool) {
7543 return E
&& (E
->isTypeDependent() || E
->isValueDependent() ||
7544 E
->containsUnexpandedParameterPack() ||
7545 E
->isInstantiationDependent());
7547 // Do not check templates, wait until instantiation.
7548 if (FD
->isDependentContext() || ShouldDelayChecks(VariantRef
, false) ||
7549 TI
.anyScoreOrCondition(ShouldDelayChecks
))
7550 return std::make_pair(FD
, VariantRef
);
7552 // Deal with non-constant score and user condition expressions.
7553 auto HandleNonConstantScoresAndConditions
= [this](Expr
*&E
,
7554 bool IsScore
) -> bool {
7555 if (!E
|| E
->isIntegerConstantExpr(Context
))
7559 // We warn on non-constant scores and pretend they were not present.
7560 Diag(E
->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant
)
7564 // We could replace a non-constant user condition with "false" but we
7565 // will soon need to handle these anyway for the dynamic version of
7566 // OpenMP context selectors.
7567 Diag(E
->getExprLoc(),
7568 diag::err_omp_declare_variant_user_condition_not_constant
)
7573 if (TI
.anyScoreOrCondition(HandleNonConstantScoresAndConditions
))
7574 return std::nullopt
;
7576 QualType AdjustedFnType
= FD
->getType();
7577 if (NumAppendArgs
) {
7578 const auto *PTy
= AdjustedFnType
->getAsAdjusted
<FunctionProtoType
>();
7580 Diag(FD
->getLocation(), diag::err_omp_declare_variant_prototype_required
)
7582 return std::nullopt
;
7584 // Adjust the function type to account for an extra omp_interop_t for each
7585 // specified in the append_args clause.
7586 const TypeDecl
*TD
= nullptr;
7587 LookupResult
Result(*this, &Context
.Idents
.get("omp_interop_t"),
7588 SR
.getBegin(), Sema::LookupOrdinaryName
);
7589 if (LookupName(Result
, getCurScope())) {
7590 NamedDecl
*ND
= Result
.getFoundDecl();
7591 TD
= dyn_cast_or_null
<TypeDecl
>(ND
);
7594 Diag(SR
.getBegin(), diag::err_omp_interop_type_not_found
) << SR
;
7595 return std::nullopt
;
7597 QualType InteropType
= Context
.getTypeDeclType(TD
);
7598 if (PTy
->isVariadic()) {
7599 Diag(FD
->getLocation(), diag::err_omp_append_args_with_varargs
) << SR
;
7600 return std::nullopt
;
7602 llvm::SmallVector
<QualType
, 8> Params
;
7603 Params
.append(PTy
->param_type_begin(), PTy
->param_type_end());
7604 Params
.insert(Params
.end(), NumAppendArgs
, InteropType
);
7605 AdjustedFnType
= Context
.getFunctionType(PTy
->getReturnType(), Params
,
7606 PTy
->getExtProtoInfo());
7609 // Convert VariantRef expression to the type of the original function to
7610 // resolve possible conflicts.
7611 ExprResult VariantRefCast
= VariantRef
;
7612 if (LangOpts
.CPlusPlus
) {
7614 auto *Method
= dyn_cast
<CXXMethodDecl
>(FD
);
7615 if (Method
&& !Method
->isStatic()) {
7616 const Type
*ClassType
=
7617 Context
.getTypeDeclType(Method
->getParent()).getTypePtr();
7618 FnPtrType
= Context
.getMemberPointerType(AdjustedFnType
, ClassType
);
7621 // Build adrr_of unary op to correctly handle type checks for member
7623 Sema::TentativeAnalysisScope
Trap(*this);
7624 ER
= CreateBuiltinUnaryOp(VariantRef
->getBeginLoc(), UO_AddrOf
,
7627 if (!ER
.isUsable()) {
7628 Diag(VariantRef
->getExprLoc(), diag::err_omp_function_expected
)
7629 << VariantId
<< VariantRef
->getSourceRange();
7630 return std::nullopt
;
7632 VariantRef
= ER
.get();
7634 FnPtrType
= Context
.getPointerType(AdjustedFnType
);
7636 QualType VarianPtrType
= Context
.getPointerType(VariantRef
->getType());
7637 if (VarianPtrType
.getUnqualifiedType() != FnPtrType
.getUnqualifiedType()) {
7638 ImplicitConversionSequence ICS
= TryImplicitConversion(
7639 VariantRef
, FnPtrType
.getUnqualifiedType(),
7640 /*SuppressUserConversions=*/false, AllowedExplicit::None
,
7641 /*InOverloadResolution=*/false,
7643 /*AllowObjCWritebackConversion=*/false);
7644 if (ICS
.isFailure()) {
7645 Diag(VariantRef
->getExprLoc(),
7646 diag::err_omp_declare_variant_incompat_types
)
7647 << VariantRef
->getType()
7648 << ((Method
&& !Method
->isStatic()) ? FnPtrType
: FD
->getType())
7649 << (NumAppendArgs
? 1 : 0) << VariantRef
->getSourceRange();
7650 return std::nullopt
;
7652 VariantRefCast
= PerformImplicitConversion(
7653 VariantRef
, FnPtrType
.getUnqualifiedType(), AA_Converting
);
7654 if (!VariantRefCast
.isUsable())
7655 return std::nullopt
;
7657 // Drop previously built artificial addr_of unary op for member functions.
7658 if (Method
&& !Method
->isStatic()) {
7659 Expr
*PossibleAddrOfVariantRef
= VariantRefCast
.get();
7660 if (auto *UO
= dyn_cast
<UnaryOperator
>(
7661 PossibleAddrOfVariantRef
->IgnoreImplicit()))
7662 VariantRefCast
= UO
->getSubExpr();
7666 ExprResult ER
= CheckPlaceholderExpr(VariantRefCast
.get());
7667 if (!ER
.isUsable() ||
7668 !ER
.get()->IgnoreParenImpCasts()->getType()->isFunctionType()) {
7669 Diag(VariantRef
->getExprLoc(), diag::err_omp_function_expected
)
7670 << VariantId
<< VariantRef
->getSourceRange();
7671 return std::nullopt
;
7674 // The VariantRef must point to function.
7675 auto *DRE
= dyn_cast
<DeclRefExpr
>(ER
.get()->IgnoreParenImpCasts());
7677 Diag(VariantRef
->getExprLoc(), diag::err_omp_function_expected
)
7678 << VariantId
<< VariantRef
->getSourceRange();
7679 return std::nullopt
;
7681 auto *NewFD
= dyn_cast_or_null
<FunctionDecl
>(DRE
->getDecl());
7683 Diag(VariantRef
->getExprLoc(), diag::err_omp_function_expected
)
7684 << VariantId
<< VariantRef
->getSourceRange();
7685 return std::nullopt
;
7688 if (FD
->getCanonicalDecl() == NewFD
->getCanonicalDecl()) {
7689 Diag(VariantRef
->getExprLoc(),
7690 diag::err_omp_declare_variant_same_base_function
)
7691 << VariantRef
->getSourceRange();
7692 return std::nullopt
;
7695 // Check if function types are compatible in C.
7696 if (!LangOpts
.CPlusPlus
) {
7698 Context
.mergeFunctionTypes(AdjustedFnType
, NewFD
->getType());
7699 if (NewType
.isNull()) {
7700 Diag(VariantRef
->getExprLoc(),
7701 diag::err_omp_declare_variant_incompat_types
)
7702 << NewFD
->getType() << FD
->getType() << (NumAppendArgs
? 1 : 0)
7703 << VariantRef
->getSourceRange();
7704 return std::nullopt
;
7706 if (NewType
->isFunctionProtoType()) {
7707 if (FD
->getType()->isFunctionNoProtoType())
7708 setPrototype(*this, FD
, NewFD
, NewType
);
7709 else if (NewFD
->getType()->isFunctionNoProtoType())
7710 setPrototype(*this, NewFD
, FD
, NewType
);
7714 // Check if variant function is not marked with declare variant directive.
7715 if (NewFD
->hasAttrs() && NewFD
->hasAttr
<OMPDeclareVariantAttr
>()) {
7716 Diag(VariantRef
->getExprLoc(),
7717 diag::warn_omp_declare_variant_marked_as_declare_variant
)
7718 << VariantRef
->getSourceRange();
7720 NewFD
->specific_attr_begin
<OMPDeclareVariantAttr
>()->getRange();
7721 Diag(SR
.getBegin(), diag::note_omp_marked_declare_variant_here
) << SR
;
7722 return std::nullopt
;
7725 enum DoesntSupport
{
7734 if (const auto *CXXFD
= dyn_cast
<CXXMethodDecl
>(FD
)) {
7735 if (CXXFD
->isVirtual()) {
7736 Diag(FD
->getLocation(), diag::err_omp_declare_variant_doesnt_support
)
7738 return std::nullopt
;
7741 if (isa
<CXXConstructorDecl
>(FD
)) {
7742 Diag(FD
->getLocation(), diag::err_omp_declare_variant_doesnt_support
)
7744 return std::nullopt
;
7747 if (isa
<CXXDestructorDecl
>(FD
)) {
7748 Diag(FD
->getLocation(), diag::err_omp_declare_variant_doesnt_support
)
7750 return std::nullopt
;
7754 if (FD
->isDeleted()) {
7755 Diag(FD
->getLocation(), diag::err_omp_declare_variant_doesnt_support
)
7757 return std::nullopt
;
7760 if (FD
->isDefaulted()) {
7761 Diag(FD
->getLocation(), diag::err_omp_declare_variant_doesnt_support
)
7763 return std::nullopt
;
7766 if (FD
->isConstexpr()) {
7767 Diag(FD
->getLocation(), diag::err_omp_declare_variant_doesnt_support
)
7768 << (NewFD
->isConsteval() ? ConstevalFuncs
: ConstexprFuncs
);
7769 return std::nullopt
;
7772 // Check general compatibility.
7773 if (areMultiversionVariantFunctionsCompatible(
7774 FD
, NewFD
, PartialDiagnostic::NullDiagnostic(),
7775 PartialDiagnosticAt(SourceLocation(),
7776 PartialDiagnostic::NullDiagnostic()),
7777 PartialDiagnosticAt(
7778 VariantRef
->getExprLoc(),
7779 PDiag(diag::err_omp_declare_variant_doesnt_support
)),
7780 PartialDiagnosticAt(VariantRef
->getExprLoc(),
7781 PDiag(diag::err_omp_declare_variant_diff
)
7782 << FD
->getLocation()),
7783 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7784 /*CLinkageMayDiffer=*/true))
7785 return std::nullopt
;
7786 return std::make_pair(FD
, cast
<Expr
>(DRE
));
7789 void Sema::ActOnOpenMPDeclareVariantDirective(
7790 FunctionDecl
*FD
, Expr
*VariantRef
, OMPTraitInfo
&TI
,
7791 ArrayRef
<Expr
*> AdjustArgsNothing
,
7792 ArrayRef
<Expr
*> AdjustArgsNeedDevicePtr
,
7793 ArrayRef
<OMPInteropInfo
> AppendArgs
, SourceLocation AdjustArgsLoc
,
7794 SourceLocation AppendArgsLoc
, SourceRange SR
) {
7796 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7797 // An adjust_args clause or append_args clause can only be specified if the
7798 // dispatch selector of the construct selector set appears in the match
7801 SmallVector
<Expr
*, 8> AllAdjustArgs
;
7802 llvm::append_range(AllAdjustArgs
, AdjustArgsNothing
);
7803 llvm::append_range(AllAdjustArgs
, AdjustArgsNeedDevicePtr
);
7805 if (!AllAdjustArgs
.empty() || !AppendArgs
.empty()) {
7806 VariantMatchInfo VMI
;
7807 TI
.getAsVariantMatchInfo(Context
, VMI
);
7808 if (!llvm::is_contained(
7809 VMI
.ConstructTraits
,
7810 llvm::omp::TraitProperty::construct_dispatch_dispatch
)) {
7811 if (!AllAdjustArgs
.empty())
7812 Diag(AdjustArgsLoc
, diag::err_omp_clause_requires_dispatch_construct
)
7813 << getOpenMPClauseName(OMPC_adjust_args
);
7814 if (!AppendArgs
.empty())
7815 Diag(AppendArgsLoc
, diag::err_omp_clause_requires_dispatch_construct
)
7816 << getOpenMPClauseName(OMPC_append_args
);
7821 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7822 // Each argument can only appear in a single adjust_args clause for each
7823 // declare variant directive.
7824 llvm::SmallPtrSet
<const VarDecl
*, 4> AdjustVars
;
7826 for (Expr
*E
: AllAdjustArgs
) {
7827 E
= E
->IgnoreParenImpCasts();
7828 if (const auto *DRE
= dyn_cast
<DeclRefExpr
>(E
)) {
7829 if (const auto *PVD
= dyn_cast
<ParmVarDecl
>(DRE
->getDecl())) {
7830 const VarDecl
*CanonPVD
= PVD
->getCanonicalDecl();
7831 if (FD
->getNumParams() > PVD
->getFunctionScopeIndex() &&
7832 FD
->getParamDecl(PVD
->getFunctionScopeIndex())
7833 ->getCanonicalDecl() == CanonPVD
) {
7834 // It's a parameter of the function, check duplicates.
7835 if (!AdjustVars
.insert(CanonPVD
).second
) {
7836 Diag(DRE
->getLocation(), diag::err_omp_adjust_arg_multiple_clauses
)
7844 // Anything that is not a function parameter is an error.
7845 Diag(E
->getExprLoc(), diag::err_omp_param_or_this_in_clause
) << FD
<< 0;
7849 auto *NewAttr
= OMPDeclareVariantAttr::CreateImplicit(
7850 Context
, VariantRef
, &TI
, const_cast<Expr
**>(AdjustArgsNothing
.data()),
7851 AdjustArgsNothing
.size(),
7852 const_cast<Expr
**>(AdjustArgsNeedDevicePtr
.data()),
7853 AdjustArgsNeedDevicePtr
.size(),
7854 const_cast<OMPInteropInfo
*>(AppendArgs
.data()), AppendArgs
.size(), SR
);
7855 FD
->addAttr(NewAttr
);
7858 StmtResult
Sema::ActOnOpenMPParallelDirective(ArrayRef
<OMPClause
*> Clauses
,
7860 SourceLocation StartLoc
,
7861 SourceLocation EndLoc
) {
7865 auto *CS
= cast
<CapturedStmt
>(AStmt
);
7866 // 1.2.2 OpenMP Language Terminology
7867 // Structured block - An executable statement with a single entry at the
7868 // top and a single exit at the bottom.
7869 // The point of exit cannot be a branch out of the structured block.
7870 // longjmp() and throw() must not violate the entry/exit criteria.
7871 CS
->getCapturedDecl()->setNothrow();
7873 setFunctionHasBranchProtectedScope();
7875 return OMPParallelDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
7876 DSAStack
->getTaskgroupReductionRef(),
7877 DSAStack
->isCancelRegion());
7881 /// Iteration space of a single for loop.
7882 struct LoopIterationSpace final
{
7883 /// True if the condition operator is the strict compare operator (<, > or
7885 bool IsStrictCompare
= false;
7886 /// Condition of the loop.
7887 Expr
*PreCond
= nullptr;
7888 /// This expression calculates the number of iterations in the loop.
7889 /// It is always possible to calculate it before starting the loop.
7890 Expr
*NumIterations
= nullptr;
7891 /// The loop counter variable.
7892 Expr
*CounterVar
= nullptr;
7893 /// Private loop counter variable.
7894 Expr
*PrivateCounterVar
= nullptr;
7895 /// This is initializer for the initial value of #CounterVar.
7896 Expr
*CounterInit
= nullptr;
7897 /// This is step for the #CounterVar used to generate its update:
7898 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7899 Expr
*CounterStep
= nullptr;
7900 /// Should step be subtracted?
7901 bool Subtract
= false;
7902 /// Source range of the loop init.
7903 SourceRange InitSrcRange
;
7904 /// Source range of the loop condition.
7905 SourceRange CondSrcRange
;
7906 /// Source range of the loop increment.
7907 SourceRange IncSrcRange
;
7908 /// Minimum value that can have the loop control variable. Used to support
7909 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
7910 /// since only such variables can be used in non-loop invariant expressions.
7911 Expr
*MinValue
= nullptr;
7912 /// Maximum value that can have the loop control variable. Used to support
7913 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
7914 /// since only such variables can be used in non-loop invariant expressions.
7915 Expr
*MaxValue
= nullptr;
7916 /// true, if the lower bound depends on the outer loop control var.
7917 bool IsNonRectangularLB
= false;
7918 /// true, if the upper bound depends on the outer loop control var.
7919 bool IsNonRectangularUB
= false;
7920 /// Index of the loop this loop depends on and forms non-rectangular loop
7922 unsigned LoopDependentIdx
= 0;
7923 /// Final condition for the non-rectangular loop nest support. It is used to
7924 /// check that the number of iterations for this particular counter must be
7926 Expr
*FinalCondition
= nullptr;
7929 /// Helper class for checking canonical form of the OpenMP loops and
7930 /// extracting iteration space of each loop in the loop nest, that will be used
7931 /// for IR generation.
7932 class OpenMPIterationSpaceChecker
{
7933 /// Reference to Sema.
7935 /// Does the loop associated directive support non-rectangular loops?
7936 bool SupportsNonRectangular
;
7937 /// Data-sharing stack.
7939 /// A location for diagnostics (when there is no some better location).
7940 SourceLocation DefaultLoc
;
7941 /// A location for diagnostics (when increment is not compatible).
7942 SourceLocation ConditionLoc
;
7943 /// A source location for referring to loop init later.
7944 SourceRange InitSrcRange
;
7945 /// A source location for referring to condition later.
7946 SourceRange ConditionSrcRange
;
7947 /// A source location for referring to increment later.
7948 SourceRange IncrementSrcRange
;
7950 ValueDecl
*LCDecl
= nullptr;
7951 /// Reference to loop variable.
7952 Expr
*LCRef
= nullptr;
7953 /// Lower bound (initializer for the var).
7957 /// Loop step (increment).
7958 Expr
*Step
= nullptr;
7959 /// This flag is true when condition is one of:
7964 /// This will have no value when the condition is !=
7965 std::optional
<bool> TestIsLessOp
;
7966 /// This flag is true when condition is strict ( < or > ).
7967 bool TestIsStrictOp
= false;
7968 /// This flag is true when step is subtracted on each iteration.
7969 bool SubtractStep
= false;
7970 /// The outer loop counter this loop depends on (if any).
7971 const ValueDecl
*DepDecl
= nullptr;
7972 /// Contains number of loop (starts from 1) on which loop counter init
7973 /// expression of this loop depends on.
7974 std::optional
<unsigned> InitDependOnLC
;
7975 /// Contains number of loop (starts from 1) on which loop counter condition
7976 /// expression of this loop depends on.
7977 std::optional
<unsigned> CondDependOnLC
;
7978 /// Checks if the provide statement depends on the loop counter.
7979 std::optional
<unsigned> doesDependOnLoopCounter(const Stmt
*S
,
7980 bool IsInitializer
);
7981 /// Original condition required for checking of the exit condition for
7982 /// non-rectangular loop.
7983 Expr
*Condition
= nullptr;
7986 OpenMPIterationSpaceChecker(Sema
&SemaRef
, bool SupportsNonRectangular
,
7987 DSAStackTy
&Stack
, SourceLocation DefaultLoc
)
7988 : SemaRef(SemaRef
), SupportsNonRectangular(SupportsNonRectangular
),
7989 Stack(Stack
), DefaultLoc(DefaultLoc
), ConditionLoc(DefaultLoc
) {}
7990 /// Check init-expr for canonical loop form and save loop counter
7991 /// variable - #Var and its initialization value - #LB.
7992 bool checkAndSetInit(Stmt
*S
, bool EmitDiags
= true);
7993 /// Check test-expr for canonical form, save upper-bound (#UB), flags
7994 /// for less/greater and for strict/non-strict comparison.
7995 bool checkAndSetCond(Expr
*S
);
7996 /// Check incr-expr for canonical loop form and return true if it
7997 /// does not conform, otherwise save loop step (#Step).
7998 bool checkAndSetInc(Expr
*S
);
7999 /// Return the loop counter variable.
8000 ValueDecl
*getLoopDecl() const { return LCDecl
; }
8001 /// Return the reference expression to loop counter variable.
8002 Expr
*getLoopDeclRefExpr() const { return LCRef
; }
8003 /// Source range of the loop init.
8004 SourceRange
getInitSrcRange() const { return InitSrcRange
; }
8005 /// Source range of the loop condition.
8006 SourceRange
getConditionSrcRange() const { return ConditionSrcRange
; }
8007 /// Source range of the loop increment.
8008 SourceRange
getIncrementSrcRange() const { return IncrementSrcRange
; }
8009 /// True if the step should be subtracted.
8010 bool shouldSubtractStep() const { return SubtractStep
; }
8011 /// True, if the compare operator is strict (<, > or !=).
8012 bool isStrictTestOp() const { return TestIsStrictOp
; }
8013 /// Build the expression to calculate the number of iterations.
8014 Expr
*buildNumIterations(
8015 Scope
*S
, ArrayRef
<LoopIterationSpace
> ResultIterSpaces
, bool LimitedType
,
8016 llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
) const;
8017 /// Build the precondition expression for the loops.
8019 buildPreCond(Scope
*S
, Expr
*Cond
,
8020 llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
) const;
8021 /// Build reference expression to the counter be used for codegen.
8023 buildCounterVar(llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
,
8024 DSAStackTy
&DSA
) const;
8025 /// Build reference expression to the private counter be used for
8027 Expr
*buildPrivateCounterVar() const;
8028 /// Build initialization of the counter be used for codegen.
8029 Expr
*buildCounterInit() const;
8030 /// Build step of the counter be used for codegen.
8031 Expr
*buildCounterStep() const;
8032 /// Build loop data with counter value for depend clauses in ordered
8035 buildOrderedLoopData(Scope
*S
, Expr
*Counter
,
8036 llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
,
8037 SourceLocation Loc
, Expr
*Inc
= nullptr,
8038 OverloadedOperatorKind OOK
= OO_Amp
);
8039 /// Builds the minimum value for the loop counter.
8040 std::pair
<Expr
*, Expr
*> buildMinMaxValues(
8041 Scope
*S
, llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
) const;
8042 /// Builds final condition for the non-rectangular loops.
8043 Expr
*buildFinalCondition(Scope
*S
) const;
8044 /// Return true if any expression is dependent.
8045 bool dependent() const;
8046 /// Returns true if the initializer forms non-rectangular loop.
8047 bool doesInitDependOnLC() const { return InitDependOnLC
.has_value(); }
8048 /// Returns true if the condition forms non-rectangular loop.
8049 bool doesCondDependOnLC() const { return CondDependOnLC
.has_value(); }
8050 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
8051 unsigned getLoopDependentIdx() const {
8052 return InitDependOnLC
.value_or(CondDependOnLC
.value_or(0));
8056 /// Check the right-hand side of an assignment in the increment
8058 bool checkAndSetIncRHS(Expr
*RHS
);
8059 /// Helper to set loop counter variable and its initializer.
8060 bool setLCDeclAndLB(ValueDecl
*NewLCDecl
, Expr
*NewDeclRefExpr
, Expr
*NewLB
,
8062 /// Helper to set upper bound.
8063 bool setUB(Expr
*NewUB
, std::optional
<bool> LessOp
, bool StrictOp
,
8064 SourceRange SR
, SourceLocation SL
);
8065 /// Helper to set loop increment.
8066 bool setStep(Expr
*NewStep
, bool Subtract
);
8069 bool OpenMPIterationSpaceChecker::dependent() const {
8071 assert(!LB
&& !UB
&& !Step
);
8074 return LCDecl
->getType()->isDependentType() ||
8075 (LB
&& LB
->isValueDependent()) || (UB
&& UB
->isValueDependent()) ||
8076 (Step
&& Step
->isValueDependent());
8079 bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl
*NewLCDecl
,
8081 Expr
*NewLB
, bool EmitDiags
) {
8082 // State consistency checking to ensure correct usage.
8083 assert(LCDecl
== nullptr && LB
== nullptr && LCRef
== nullptr &&
8084 UB
== nullptr && Step
== nullptr && !TestIsLessOp
&& !TestIsStrictOp
);
8085 if (!NewLCDecl
|| !NewLB
|| NewLB
->containsErrors())
8087 LCDecl
= getCanonicalDecl(NewLCDecl
);
8088 LCRef
= NewLCRefExpr
;
8089 if (auto *CE
= dyn_cast_or_null
<CXXConstructExpr
>(NewLB
))
8090 if (const CXXConstructorDecl
*Ctor
= CE
->getConstructor())
8091 if ((Ctor
->isCopyOrMoveConstructor() ||
8092 Ctor
->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8093 CE
->getNumArgs() > 0 && CE
->getArg(0) != nullptr)
8094 NewLB
= CE
->getArg(0)->IgnoreParenImpCasts();
8097 InitDependOnLC
= doesDependOnLoopCounter(LB
, /*IsInitializer=*/true);
8101 bool OpenMPIterationSpaceChecker::setUB(Expr
*NewUB
, std::optional
<bool> LessOp
,
8102 bool StrictOp
, SourceRange SR
,
8103 SourceLocation SL
) {
8104 // State consistency checking to ensure correct usage.
8105 assert(LCDecl
!= nullptr && LB
!= nullptr && UB
== nullptr &&
8106 Step
== nullptr && !TestIsLessOp
&& !TestIsStrictOp
);
8107 if (!NewUB
|| NewUB
->containsErrors())
8111 TestIsLessOp
= LessOp
;
8112 TestIsStrictOp
= StrictOp
;
8113 ConditionSrcRange
= SR
;
8115 CondDependOnLC
= doesDependOnLoopCounter(UB
, /*IsInitializer=*/false);
8119 bool OpenMPIterationSpaceChecker::setStep(Expr
*NewStep
, bool Subtract
) {
8120 // State consistency checking to ensure correct usage.
8121 assert(LCDecl
!= nullptr && LB
!= nullptr && Step
== nullptr);
8122 if (!NewStep
|| NewStep
->containsErrors())
8124 if (!NewStep
->isValueDependent()) {
8125 // Check that the step is integer expression.
8126 SourceLocation StepLoc
= NewStep
->getBeginLoc();
8127 ExprResult Val
= SemaRef
.PerformOpenMPImplicitIntegerConversion(
8128 StepLoc
, getExprAsWritten(NewStep
));
8129 if (Val
.isInvalid())
8131 NewStep
= Val
.get();
8133 // OpenMP [2.6, Canonical Loop Form, Restrictions]
8134 // If test-expr is of form var relational-op b and relational-op is < or
8135 // <= then incr-expr must cause var to increase on each iteration of the
8136 // loop. If test-expr is of form var relational-op b and relational-op is
8137 // > or >= then incr-expr must cause var to decrease on each iteration of
8139 // If test-expr is of form b relational-op var and relational-op is < or
8140 // <= then incr-expr must cause var to decrease on each iteration of the
8141 // loop. If test-expr is of form b relational-op var and relational-op is
8142 // > or >= then incr-expr must cause var to increase on each iteration of
8144 std::optional
<llvm::APSInt
> Result
=
8145 NewStep
->getIntegerConstantExpr(SemaRef
.Context
);
8146 bool IsUnsigned
= !NewStep
->getType()->hasSignedIntegerRepresentation();
8148 Result
&& Result
->isSigned() && (Subtract
!= Result
->isNegative());
8150 Result
&& Result
->isSigned() && (Subtract
== Result
->isNegative());
8151 bool IsConstZero
= Result
&& !Result
->getBoolValue();
8153 // != with increment is treated as <; != with decrement is treated as >
8155 TestIsLessOp
= IsConstPos
|| (IsUnsigned
&& !Subtract
);
8156 if (UB
&& (IsConstZero
||
8157 (*TestIsLessOp
? (IsConstNeg
|| (IsUnsigned
&& Subtract
))
8158 : (IsConstPos
|| (IsUnsigned
&& !Subtract
))))) {
8159 SemaRef
.Diag(NewStep
->getExprLoc(),
8160 diag::err_omp_loop_incr_not_compatible
)
8161 << LCDecl
<< *TestIsLessOp
<< NewStep
->getSourceRange();
8162 SemaRef
.Diag(ConditionLoc
,
8163 diag::note_omp_loop_cond_requres_compatible_incr
)
8164 << *TestIsLessOp
<< ConditionSrcRange
;
8167 if (*TestIsLessOp
== Subtract
) {
8169 SemaRef
.CreateBuiltinUnaryOp(NewStep
->getExprLoc(), UO_Minus
, NewStep
)
8171 Subtract
= !Subtract
;
8176 SubtractStep
= Subtract
;
8181 /// Checker for the non-rectangular loops. Checks if the initializer or
8182 /// condition expression references loop counter variable.
8183 class LoopCounterRefChecker final
8184 : public ConstStmtVisitor
<LoopCounterRefChecker
, bool> {
8187 const ValueDecl
*CurLCDecl
= nullptr;
8188 const ValueDecl
*DepDecl
= nullptr;
8189 const ValueDecl
*PrevDepDecl
= nullptr;
8190 bool IsInitializer
= true;
8191 bool SupportsNonRectangular
;
8192 unsigned BaseLoopId
= 0;
8193 bool checkDecl(const Expr
*E
, const ValueDecl
*VD
) {
8194 if (getCanonicalDecl(VD
) == getCanonicalDecl(CurLCDecl
)) {
8195 SemaRef
.Diag(E
->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter
)
8196 << (IsInitializer
? 0 : 1);
8199 const auto &&Data
= Stack
.isLoopControlVariable(VD
);
8200 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8201 // The type of the loop iterator on which we depend may not have a random
8202 // access iterator type.
8203 if (Data
.first
&& VD
->getType()->isRecordType()) {
8204 SmallString
<128> Name
;
8205 llvm::raw_svector_ostream
OS(Name
);
8206 VD
->getNameForDiagnostic(OS
, SemaRef
.getPrintingPolicy(),
8207 /*Qualified=*/true);
8208 SemaRef
.Diag(E
->getExprLoc(),
8209 diag::err_omp_wrong_dependency_iterator_type
)
8211 SemaRef
.Diag(VD
->getLocation(), diag::note_previous_decl
) << VD
;
8214 if (Data
.first
&& !SupportsNonRectangular
) {
8215 SemaRef
.Diag(E
->getExprLoc(), diag::err_omp_invariant_dependency
);
8219 (DepDecl
|| (PrevDepDecl
&&
8220 getCanonicalDecl(VD
) != getCanonicalDecl(PrevDepDecl
)))) {
8221 if (!DepDecl
&& PrevDepDecl
)
8222 DepDecl
= PrevDepDecl
;
8223 SmallString
<128> Name
;
8224 llvm::raw_svector_ostream
OS(Name
);
8225 DepDecl
->getNameForDiagnostic(OS
, SemaRef
.getPrintingPolicy(),
8226 /*Qualified=*/true);
8227 SemaRef
.Diag(E
->getExprLoc(),
8228 diag::err_omp_invariant_or_linear_dependency
)
8234 BaseLoopId
= Data
.first
;
8240 bool VisitDeclRefExpr(const DeclRefExpr
*E
) {
8241 const ValueDecl
*VD
= E
->getDecl();
8242 if (isa
<VarDecl
>(VD
))
8243 return checkDecl(E
, VD
);
8246 bool VisitMemberExpr(const MemberExpr
*E
) {
8247 if (isa
<CXXThisExpr
>(E
->getBase()->IgnoreParens())) {
8248 const ValueDecl
*VD
= E
->getMemberDecl();
8249 if (isa
<VarDecl
>(VD
) || isa
<FieldDecl
>(VD
))
8250 return checkDecl(E
, VD
);
8254 bool VisitStmt(const Stmt
*S
) {
8256 for (const Stmt
*Child
: S
->children())
8257 Res
= (Child
&& Visit(Child
)) || Res
;
8260 explicit LoopCounterRefChecker(Sema
&SemaRef
, DSAStackTy
&Stack
,
8261 const ValueDecl
*CurLCDecl
, bool IsInitializer
,
8262 const ValueDecl
*PrevDepDecl
= nullptr,
8263 bool SupportsNonRectangular
= true)
8264 : SemaRef(SemaRef
), Stack(Stack
), CurLCDecl(CurLCDecl
),
8265 PrevDepDecl(PrevDepDecl
), IsInitializer(IsInitializer
),
8266 SupportsNonRectangular(SupportsNonRectangular
) {}
8267 unsigned getBaseLoopId() const {
8268 assert(CurLCDecl
&& "Expected loop dependency.");
8271 const ValueDecl
*getDepDecl() const {
8272 assert(CurLCDecl
&& "Expected loop dependency.");
8278 std::optional
<unsigned>
8279 OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt
*S
,
8280 bool IsInitializer
) {
8281 // Check for the non-rectangular loops.
8282 LoopCounterRefChecker
LoopStmtChecker(SemaRef
, Stack
, LCDecl
, IsInitializer
,
8283 DepDecl
, SupportsNonRectangular
);
8284 if (LoopStmtChecker
.Visit(S
)) {
8285 DepDecl
= LoopStmtChecker
.getDepDecl();
8286 return LoopStmtChecker
.getBaseLoopId();
8288 return std::nullopt
;
8291 bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt
*S
, bool EmitDiags
) {
8292 // Check init-expr for canonical loop form and save loop counter
8293 // variable - #Var and its initialization value - #LB.
8294 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8296 // integer-type var = lb
8297 // random-access-iterator-type var = lb
8298 // pointer-type var = lb
8302 SemaRef
.Diag(DefaultLoc
, diag::err_omp_loop_not_canonical_init
);
8306 if (auto *ExprTemp
= dyn_cast
<ExprWithCleanups
>(S
))
8307 if (!ExprTemp
->cleanupsHaveSideEffects())
8308 S
= ExprTemp
->getSubExpr();
8310 InitSrcRange
= S
->getSourceRange();
8311 if (Expr
*E
= dyn_cast
<Expr
>(S
))
8312 S
= E
->IgnoreParens();
8313 if (auto *BO
= dyn_cast
<BinaryOperator
>(S
)) {
8314 if (BO
->getOpcode() == BO_Assign
) {
8315 Expr
*LHS
= BO
->getLHS()->IgnoreParens();
8316 if (auto *DRE
= dyn_cast
<DeclRefExpr
>(LHS
)) {
8317 if (auto *CED
= dyn_cast
<OMPCapturedExprDecl
>(DRE
->getDecl()))
8318 if (auto *ME
= dyn_cast
<MemberExpr
>(getExprAsWritten(CED
->getInit())))
8319 return setLCDeclAndLB(ME
->getMemberDecl(), ME
, BO
->getRHS(),
8321 return setLCDeclAndLB(DRE
->getDecl(), DRE
, BO
->getRHS(), EmitDiags
);
8323 if (auto *ME
= dyn_cast
<MemberExpr
>(LHS
)) {
8324 if (ME
->isArrow() &&
8325 isa
<CXXThisExpr
>(ME
->getBase()->IgnoreParenImpCasts()))
8326 return setLCDeclAndLB(ME
->getMemberDecl(), ME
, BO
->getRHS(),
8330 } else if (auto *DS
= dyn_cast
<DeclStmt
>(S
)) {
8331 if (DS
->isSingleDecl()) {
8332 if (auto *Var
= dyn_cast_or_null
<VarDecl
>(DS
->getSingleDecl())) {
8333 if (Var
->hasInit() && !Var
->getType()->isReferenceType()) {
8334 // Accept non-canonical init form here but emit ext. warning.
8335 if (Var
->getInitStyle() != VarDecl::CInit
&& EmitDiags
)
8336 SemaRef
.Diag(S
->getBeginLoc(),
8337 diag::ext_omp_loop_not_canonical_init
)
8338 << S
->getSourceRange();
8339 return setLCDeclAndLB(
8341 buildDeclRefExpr(SemaRef
, Var
,
8342 Var
->getType().getNonReferenceType(),
8344 Var
->getInit(), EmitDiags
);
8348 } else if (auto *CE
= dyn_cast
<CXXOperatorCallExpr
>(S
)) {
8349 if (CE
->getOperator() == OO_Equal
) {
8350 Expr
*LHS
= CE
->getArg(0);
8351 if (auto *DRE
= dyn_cast
<DeclRefExpr
>(LHS
)) {
8352 if (auto *CED
= dyn_cast
<OMPCapturedExprDecl
>(DRE
->getDecl()))
8353 if (auto *ME
= dyn_cast
<MemberExpr
>(getExprAsWritten(CED
->getInit())))
8354 return setLCDeclAndLB(ME
->getMemberDecl(), ME
, BO
->getRHS(),
8356 return setLCDeclAndLB(DRE
->getDecl(), DRE
, CE
->getArg(1), EmitDiags
);
8358 if (auto *ME
= dyn_cast
<MemberExpr
>(LHS
)) {
8359 if (ME
->isArrow() &&
8360 isa
<CXXThisExpr
>(ME
->getBase()->IgnoreParenImpCasts()))
8361 return setLCDeclAndLB(ME
->getMemberDecl(), ME
, BO
->getRHS(),
8367 if (dependent() || SemaRef
.CurContext
->isDependentContext())
8370 SemaRef
.Diag(S
->getBeginLoc(), diag::err_omp_loop_not_canonical_init
)
8371 << S
->getSourceRange();
8376 /// Ignore parenthesizes, implicit casts, copy constructor and return the
8377 /// variable (which may be the loop variable) if possible.
8378 static const ValueDecl
*getInitLCDecl(const Expr
*E
) {
8381 E
= getExprAsWritten(E
);
8382 if (const auto *CE
= dyn_cast_or_null
<CXXConstructExpr
>(E
))
8383 if (const CXXConstructorDecl
*Ctor
= CE
->getConstructor())
8384 if ((Ctor
->isCopyOrMoveConstructor() ||
8385 Ctor
->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8386 CE
->getNumArgs() > 0 && CE
->getArg(0) != nullptr)
8387 E
= CE
->getArg(0)->IgnoreParenImpCasts();
8388 if (const auto *DRE
= dyn_cast_or_null
<DeclRefExpr
>(E
)) {
8389 if (const auto *VD
= dyn_cast
<VarDecl
>(DRE
->getDecl()))
8390 return getCanonicalDecl(VD
);
8392 if (const auto *ME
= dyn_cast_or_null
<MemberExpr
>(E
))
8393 if (ME
->isArrow() && isa
<CXXThisExpr
>(ME
->getBase()->IgnoreParenImpCasts()))
8394 return getCanonicalDecl(ME
->getMemberDecl());
8398 bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr
*S
) {
8399 // Check test-expr for canonical form, save upper-bound UB, flags for
8400 // less/greater and for strict/non-strict comparison.
8401 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8402 // var relational-op b
8403 // b relational-op var
8405 bool IneqCondIsCanonical
= SemaRef
.getLangOpts().OpenMP
>= 50;
8407 SemaRef
.Diag(DefaultLoc
, diag::err_omp_loop_not_canonical_cond
)
8408 << (IneqCondIsCanonical
? 1 : 0) << LCDecl
;
8412 S
= getExprAsWritten(S
);
8413 SourceLocation CondLoc
= S
->getBeginLoc();
8414 auto &&CheckAndSetCond
=
8415 [this, IneqCondIsCanonical
](BinaryOperatorKind Opcode
, const Expr
*LHS
,
8416 const Expr
*RHS
, SourceRange SR
,
8417 SourceLocation OpLoc
) -> std::optional
<bool> {
8418 if (BinaryOperator::isRelationalOp(Opcode
)) {
8419 if (getInitLCDecl(LHS
) == LCDecl
)
8420 return setUB(const_cast<Expr
*>(RHS
),
8421 (Opcode
== BO_LT
|| Opcode
== BO_LE
),
8422 (Opcode
== BO_LT
|| Opcode
== BO_GT
), SR
, OpLoc
);
8423 if (getInitLCDecl(RHS
) == LCDecl
)
8424 return setUB(const_cast<Expr
*>(LHS
),
8425 (Opcode
== BO_GT
|| Opcode
== BO_GE
),
8426 (Opcode
== BO_LT
|| Opcode
== BO_GT
), SR
, OpLoc
);
8427 } else if (IneqCondIsCanonical
&& Opcode
== BO_NE
) {
8428 return setUB(const_cast<Expr
*>(getInitLCDecl(LHS
) == LCDecl
? RHS
: LHS
),
8429 /*LessOp=*/std::nullopt
,
8430 /*StrictOp=*/true, SR
, OpLoc
);
8432 return std::nullopt
;
8434 std::optional
<bool> Res
;
8435 if (auto *RBO
= dyn_cast
<CXXRewrittenBinaryOperator
>(S
)) {
8436 CXXRewrittenBinaryOperator::DecomposedForm DF
= RBO
->getDecomposedForm();
8437 Res
= CheckAndSetCond(DF
.Opcode
, DF
.LHS
, DF
.RHS
, RBO
->getSourceRange(),
8438 RBO
->getOperatorLoc());
8439 } else if (auto *BO
= dyn_cast
<BinaryOperator
>(S
)) {
8440 Res
= CheckAndSetCond(BO
->getOpcode(), BO
->getLHS(), BO
->getRHS(),
8441 BO
->getSourceRange(), BO
->getOperatorLoc());
8442 } else if (auto *CE
= dyn_cast
<CXXOperatorCallExpr
>(S
)) {
8443 if (CE
->getNumArgs() == 2) {
8444 Res
= CheckAndSetCond(
8445 BinaryOperator::getOverloadedOpcode(CE
->getOperator()), CE
->getArg(0),
8446 CE
->getArg(1), CE
->getSourceRange(), CE
->getOperatorLoc());
8451 if (dependent() || SemaRef
.CurContext
->isDependentContext())
8453 SemaRef
.Diag(CondLoc
, diag::err_omp_loop_not_canonical_cond
)
8454 << (IneqCondIsCanonical
? 1 : 0) << S
->getSourceRange() << LCDecl
;
8458 bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr
*RHS
) {
8459 // RHS of canonical loop form increment can be:
8464 RHS
= RHS
->IgnoreParenImpCasts();
8465 if (auto *BO
= dyn_cast
<BinaryOperator
>(RHS
)) {
8466 if (BO
->isAdditiveOp()) {
8467 bool IsAdd
= BO
->getOpcode() == BO_Add
;
8468 if (getInitLCDecl(BO
->getLHS()) == LCDecl
)
8469 return setStep(BO
->getRHS(), !IsAdd
);
8470 if (IsAdd
&& getInitLCDecl(BO
->getRHS()) == LCDecl
)
8471 return setStep(BO
->getLHS(), /*Subtract=*/false);
8473 } else if (auto *CE
= dyn_cast
<CXXOperatorCallExpr
>(RHS
)) {
8474 bool IsAdd
= CE
->getOperator() == OO_Plus
;
8475 if ((IsAdd
|| CE
->getOperator() == OO_Minus
) && CE
->getNumArgs() == 2) {
8476 if (getInitLCDecl(CE
->getArg(0)) == LCDecl
)
8477 return setStep(CE
->getArg(1), !IsAdd
);
8478 if (IsAdd
&& getInitLCDecl(CE
->getArg(1)) == LCDecl
)
8479 return setStep(CE
->getArg(0), /*Subtract=*/false);
8482 if (dependent() || SemaRef
.CurContext
->isDependentContext())
8484 SemaRef
.Diag(RHS
->getBeginLoc(), diag::err_omp_loop_not_canonical_incr
)
8485 << RHS
->getSourceRange() << LCDecl
;
8489 bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr
*S
) {
8490 // Check incr-expr for canonical loop form and return true if it
8491 // does not conform.
8492 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8504 SemaRef
.Diag(DefaultLoc
, diag::err_omp_loop_not_canonical_incr
) << LCDecl
;
8507 if (auto *ExprTemp
= dyn_cast
<ExprWithCleanups
>(S
))
8508 if (!ExprTemp
->cleanupsHaveSideEffects())
8509 S
= ExprTemp
->getSubExpr();
8511 IncrementSrcRange
= S
->getSourceRange();
8512 S
= S
->IgnoreParens();
8513 if (auto *UO
= dyn_cast
<UnaryOperator
>(S
)) {
8514 if (UO
->isIncrementDecrementOp() &&
8515 getInitLCDecl(UO
->getSubExpr()) == LCDecl
)
8516 return setStep(SemaRef
8517 .ActOnIntegerConstant(UO
->getBeginLoc(),
8518 (UO
->isDecrementOp() ? -1 : 1))
8520 /*Subtract=*/false);
8521 } else if (auto *BO
= dyn_cast
<BinaryOperator
>(S
)) {
8522 switch (BO
->getOpcode()) {
8525 if (getInitLCDecl(BO
->getLHS()) == LCDecl
)
8526 return setStep(BO
->getRHS(), BO
->getOpcode() == BO_SubAssign
);
8529 if (getInitLCDecl(BO
->getLHS()) == LCDecl
)
8530 return checkAndSetIncRHS(BO
->getRHS());
8535 } else if (auto *CE
= dyn_cast
<CXXOperatorCallExpr
>(S
)) {
8536 switch (CE
->getOperator()) {
8539 if (getInitLCDecl(CE
->getArg(0)) == LCDecl
)
8540 return setStep(SemaRef
8541 .ActOnIntegerConstant(
8543 ((CE
->getOperator() == OO_MinusMinus
) ? -1 : 1))
8545 /*Subtract=*/false);
8549 if (getInitLCDecl(CE
->getArg(0)) == LCDecl
)
8550 return setStep(CE
->getArg(1), CE
->getOperator() == OO_MinusEqual
);
8553 if (getInitLCDecl(CE
->getArg(0)) == LCDecl
)
8554 return checkAndSetIncRHS(CE
->getArg(1));
8560 if (dependent() || SemaRef
.CurContext
->isDependentContext())
8562 SemaRef
.Diag(S
->getBeginLoc(), diag::err_omp_loop_not_canonical_incr
)
8563 << S
->getSourceRange() << LCDecl
;
8568 tryBuildCapture(Sema
&SemaRef
, Expr
*Capture
,
8569 llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
,
8570 StringRef Name
= ".capture_expr.") {
8571 if (SemaRef
.CurContext
->isDependentContext() || Capture
->containsErrors())
8573 if (Capture
->isEvaluatable(SemaRef
.Context
, Expr::SE_AllowSideEffects
))
8574 return SemaRef
.PerformImplicitConversion(
8575 Capture
->IgnoreImpCasts(), Capture
->getType(), Sema::AA_Converting
,
8576 /*AllowExplicit=*/true);
8577 auto I
= Captures
.find(Capture
);
8578 if (I
!= Captures
.end())
8579 return buildCapture(SemaRef
, Capture
, I
->second
, Name
);
8580 DeclRefExpr
*Ref
= nullptr;
8581 ExprResult Res
= buildCapture(SemaRef
, Capture
, Ref
, Name
);
8582 Captures
[Capture
] = Ref
;
8586 /// Calculate number of iterations, transforming to unsigned, if number of
8587 /// iterations may be larger than the original type.
8589 calculateNumIters(Sema
&SemaRef
, Scope
*S
, SourceLocation DefaultLoc
,
8590 Expr
*Lower
, Expr
*Upper
, Expr
*Step
, QualType LCTy
,
8591 bool TestIsStrictOp
, bool RoundToStep
,
8592 llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
) {
8593 ExprResult NewStep
= tryBuildCapture(SemaRef
, Step
, Captures
, ".new_step");
8594 if (!NewStep
.isUsable())
8596 llvm::APSInt LRes
, SRes
;
8597 bool IsLowerConst
= false, IsStepConst
= false;
8598 if (std::optional
<llvm::APSInt
> Res
=
8599 Lower
->getIntegerConstantExpr(SemaRef
.Context
)) {
8601 IsLowerConst
= true;
8603 if (std::optional
<llvm::APSInt
> Res
=
8604 Step
->getIntegerConstantExpr(SemaRef
.Context
)) {
8608 bool NoNeedToConvert
= IsLowerConst
&& !RoundToStep
&&
8609 ((!TestIsStrictOp
&& LRes
.isNonNegative()) ||
8610 (TestIsStrictOp
&& LRes
.isStrictlyPositive()));
8611 bool NeedToReorganize
= false;
8612 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8613 if (!NoNeedToConvert
&& IsLowerConst
&&
8614 (TestIsStrictOp
|| (RoundToStep
&& IsStepConst
))) {
8615 NoNeedToConvert
= true;
8617 unsigned BW
= LRes
.getBitWidth() > SRes
.getBitWidth()
8618 ? LRes
.getBitWidth()
8619 : SRes
.getBitWidth();
8620 LRes
= LRes
.extend(BW
+ 1);
8621 LRes
.setIsSigned(true);
8622 SRes
= SRes
.extend(BW
+ 1);
8623 SRes
.setIsSigned(true);
8625 NoNeedToConvert
= LRes
.trunc(BW
).extend(BW
+ 1) == LRes
;
8626 LRes
= LRes
.trunc(BW
);
8628 if (TestIsStrictOp
) {
8629 unsigned BW
= LRes
.getBitWidth();
8630 LRes
= LRes
.extend(BW
+ 1);
8631 LRes
.setIsSigned(true);
8634 NoNeedToConvert
&& LRes
.trunc(BW
).extend(BW
+ 1) == LRes
;
8635 // truncate to the original bitwidth.
8636 LRes
= LRes
.trunc(BW
);
8638 NeedToReorganize
= NoNeedToConvert
;
8641 bool IsUpperConst
= false;
8642 if (std::optional
<llvm::APSInt
> Res
=
8643 Upper
->getIntegerConstantExpr(SemaRef
.Context
)) {
8645 IsUpperConst
= true;
8647 if (NoNeedToConvert
&& IsLowerConst
&& IsUpperConst
&&
8648 (!RoundToStep
|| IsStepConst
)) {
8649 unsigned BW
= LRes
.getBitWidth() > URes
.getBitWidth() ? LRes
.getBitWidth()
8650 : URes
.getBitWidth();
8651 LRes
= LRes
.extend(BW
+ 1);
8652 LRes
.setIsSigned(true);
8653 URes
= URes
.extend(BW
+ 1);
8654 URes
.setIsSigned(true);
8656 NoNeedToConvert
= URes
.trunc(BW
).extend(BW
+ 1) == URes
;
8657 NeedToReorganize
= NoNeedToConvert
;
8659 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8660 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8662 if ((!NoNeedToConvert
|| (LRes
.isNegative() && !IsUpperConst
)) &&
8663 !LCTy
->isDependentType() && LCTy
->isIntegerType()) {
8664 QualType LowerTy
= Lower
->getType();
8665 QualType UpperTy
= Upper
->getType();
8666 uint64_t LowerSize
= SemaRef
.Context
.getTypeSize(LowerTy
);
8667 uint64_t UpperSize
= SemaRef
.Context
.getTypeSize(UpperTy
);
8668 if ((LowerSize
<= UpperSize
&& UpperTy
->hasSignedIntegerRepresentation()) ||
8669 (LowerSize
> UpperSize
&& LowerTy
->hasSignedIntegerRepresentation())) {
8670 QualType CastType
= SemaRef
.Context
.getIntTypeForBitwidth(
8671 LowerSize
> UpperSize
? LowerSize
: UpperSize
, /*Signed=*/0);
8674 .PerformImplicitConversion(
8675 SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, Upper
).get(),
8676 CastType
, Sema::AA_Converting
)
8678 Lower
= SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, Lower
).get();
8679 NewStep
= SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, NewStep
.get());
8682 if (!Lower
|| !Upper
|| NewStep
.isInvalid())
8686 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8688 if (NeedToReorganize
) {
8694 SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Sub
, Diff
.get(), NewStep
.get());
8695 if (!Diff
.isUsable())
8699 // Lower - Step [+ 1]
8701 Diff
= SemaRef
.BuildBinOp(
8702 S
, DefaultLoc
, BO_Add
, Diff
.get(),
8703 SemaRef
.ActOnIntegerConstant(SourceLocation(), 1).get());
8704 if (!Diff
.isUsable())
8707 Diff
= SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, Diff
.get());
8708 if (!Diff
.isUsable())
8711 // Upper - (Lower - Step [+ 1]).
8712 Diff
= SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Sub
, Upper
, Diff
.get());
8713 if (!Diff
.isUsable())
8716 Diff
= SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Sub
, Upper
, Lower
);
8718 if (!Diff
.isUsable() && LCTy
->getAsCXXRecordDecl()) {
8719 // BuildBinOp already emitted error, this one is to point user to upper
8720 // and lower bound, and to tell what is passed to 'operator-'.
8721 SemaRef
.Diag(Upper
->getBeginLoc(), diag::err_omp_loop_diff_cxx
)
8722 << Upper
->getSourceRange() << Lower
->getSourceRange();
8726 if (!Diff
.isUsable())
8729 // Upper - Lower [- 1]
8731 Diff
= SemaRef
.BuildBinOp(
8732 S
, DefaultLoc
, BO_Sub
, Diff
.get(),
8733 SemaRef
.ActOnIntegerConstant(SourceLocation(), 1).get());
8734 if (!Diff
.isUsable())
8738 // Upper - Lower [- 1] + Step
8740 SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Add
, Diff
.get(), NewStep
.get());
8741 if (!Diff
.isUsable())
8746 // Parentheses (for dumping/debugging purposes only).
8747 Diff
= SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, Diff
.get());
8748 if (!Diff
.isUsable())
8751 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8752 Diff
= SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Div
, Diff
.get(), NewStep
.get());
8753 if (!Diff
.isUsable())
8759 /// Build the expression to calculate the number of iterations.
8760 Expr
*OpenMPIterationSpaceChecker::buildNumIterations(
8761 Scope
*S
, ArrayRef
<LoopIterationSpace
> ResultIterSpaces
, bool LimitedType
,
8762 llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
) const {
8763 QualType VarType
= LCDecl
->getType().getNonReferenceType();
8764 if (!VarType
->isIntegerType() && !VarType
->isPointerType() &&
8765 !SemaRef
.getLangOpts().CPlusPlus
)
8769 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8770 // max(LB(MinVal), LB(MaxVal)))
8771 if (InitDependOnLC
) {
8772 const LoopIterationSpace
&IS
= ResultIterSpaces
[*InitDependOnLC
- 1];
8773 if (!IS
.MinValue
|| !IS
.MaxValue
)
8776 ExprResult MinValue
=
8777 SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, IS
.MinValue
);
8778 if (!MinValue
.isUsable())
8781 ExprResult LBMinVal
= SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Assign
,
8782 IS
.CounterVar
, MinValue
.get());
8783 if (!LBMinVal
.isUsable())
8785 // OuterVar = Min, LBVal
8787 SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Comma
, LBMinVal
.get(), LBVal
);
8788 if (!LBMinVal
.isUsable())
8790 // (OuterVar = Min, LBVal)
8791 LBMinVal
= SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, LBMinVal
.get());
8792 if (!LBMinVal
.isUsable())
8796 ExprResult MaxValue
=
8797 SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, IS
.MaxValue
);
8798 if (!MaxValue
.isUsable())
8801 ExprResult LBMaxVal
= SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Assign
,
8802 IS
.CounterVar
, MaxValue
.get());
8803 if (!LBMaxVal
.isUsable())
8805 // OuterVar = Max, LBVal
8807 SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Comma
, LBMaxVal
.get(), LBVal
);
8808 if (!LBMaxVal
.isUsable())
8810 // (OuterVar = Max, LBVal)
8811 LBMaxVal
= SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, LBMaxVal
.get());
8812 if (!LBMaxVal
.isUsable())
8816 tryBuildCapture(SemaRef
, LBMinVal
.get(), Captures
, ".lb_min").get();
8818 tryBuildCapture(SemaRef
, LBMaxVal
.get(), Captures
, ".lb_max").get();
8819 if (!LBMin
|| !LBMax
)
8821 // LB(MinVal) < LB(MaxVal)
8822 ExprResult MinLessMaxRes
=
8823 SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_LT
, LBMin
, LBMax
);
8824 if (!MinLessMaxRes
.isUsable())
8827 tryBuildCapture(SemaRef
, MinLessMaxRes
.get(), Captures
, ".min_less_max")
8831 if (*TestIsLessOp
) {
8832 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8834 ExprResult MinLB
= SemaRef
.ActOnConditionalOp(DefaultLoc
, DefaultLoc
,
8835 MinLessMax
, LBMin
, LBMax
);
8836 if (!MinLB
.isUsable())
8838 LBVal
= MinLB
.get();
8840 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8842 ExprResult MaxLB
= SemaRef
.ActOnConditionalOp(DefaultLoc
, DefaultLoc
,
8843 MinLessMax
, LBMax
, LBMin
);
8844 if (!MaxLB
.isUsable())
8846 LBVal
= MaxLB
.get();
8850 SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Assign
, IS
.CounterVar
, LBVal
);
8851 if (!LBMinVal
.isUsable())
8853 LBVal
= LBMinVal
.get();
8855 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8856 // min(UB(MinVal), UB(MaxVal))
8857 if (CondDependOnLC
) {
8858 const LoopIterationSpace
&IS
= ResultIterSpaces
[*CondDependOnLC
- 1];
8859 if (!IS
.MinValue
|| !IS
.MaxValue
)
8862 ExprResult MinValue
=
8863 SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, IS
.MinValue
);
8864 if (!MinValue
.isUsable())
8867 ExprResult UBMinVal
= SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Assign
,
8868 IS
.CounterVar
, MinValue
.get());
8869 if (!UBMinVal
.isUsable())
8871 // OuterVar = Min, UBVal
8873 SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Comma
, UBMinVal
.get(), UBVal
);
8874 if (!UBMinVal
.isUsable())
8876 // (OuterVar = Min, UBVal)
8877 UBMinVal
= SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, UBMinVal
.get());
8878 if (!UBMinVal
.isUsable())
8882 ExprResult MaxValue
=
8883 SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, IS
.MaxValue
);
8884 if (!MaxValue
.isUsable())
8887 ExprResult UBMaxVal
= SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Assign
,
8888 IS
.CounterVar
, MaxValue
.get());
8889 if (!UBMaxVal
.isUsable())
8891 // OuterVar = Max, UBVal
8893 SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Comma
, UBMaxVal
.get(), UBVal
);
8894 if (!UBMaxVal
.isUsable())
8896 // (OuterVar = Max, UBVal)
8897 UBMaxVal
= SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, UBMaxVal
.get());
8898 if (!UBMaxVal
.isUsable())
8902 tryBuildCapture(SemaRef
, UBMinVal
.get(), Captures
, ".ub_min").get();
8904 tryBuildCapture(SemaRef
, UBMaxVal
.get(), Captures
, ".ub_max").get();
8905 if (!UBMin
|| !UBMax
)
8907 // UB(MinVal) > UB(MaxVal)
8908 ExprResult MinGreaterMaxRes
=
8909 SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_GT
, UBMin
, UBMax
);
8910 if (!MinGreaterMaxRes
.isUsable())
8912 Expr
*MinGreaterMax
= tryBuildCapture(SemaRef
, MinGreaterMaxRes
.get(),
8913 Captures
, ".min_greater_max")
8917 if (*TestIsLessOp
) {
8918 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
8920 ExprResult MaxUB
= SemaRef
.ActOnConditionalOp(
8921 DefaultLoc
, DefaultLoc
, MinGreaterMax
, UBMin
, UBMax
);
8922 if (!MaxUB
.isUsable())
8924 UBVal
= MaxUB
.get();
8926 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
8928 ExprResult MinUB
= SemaRef
.ActOnConditionalOp(
8929 DefaultLoc
, DefaultLoc
, MinGreaterMax
, UBMax
, UBMin
);
8930 if (!MinUB
.isUsable())
8932 UBVal
= MinUB
.get();
8935 Expr
*UBExpr
= *TestIsLessOp
? UBVal
: LBVal
;
8936 Expr
*LBExpr
= *TestIsLessOp
? LBVal
: UBVal
;
8937 Expr
*Upper
= tryBuildCapture(SemaRef
, UBExpr
, Captures
, ".upper").get();
8938 Expr
*Lower
= tryBuildCapture(SemaRef
, LBExpr
, Captures
, ".lower").get();
8939 if (!Upper
|| !Lower
)
8942 ExprResult Diff
= calculateNumIters(SemaRef
, S
, DefaultLoc
, Lower
, Upper
,
8943 Step
, VarType
, TestIsStrictOp
,
8944 /*RoundToStep=*/true, Captures
);
8945 if (!Diff
.isUsable())
8948 // OpenMP runtime requires 32-bit or 64-bit loop variables.
8949 QualType Type
= Diff
.get()->getType();
8950 ASTContext
&C
= SemaRef
.Context
;
8951 bool UseVarType
= VarType
->hasIntegerRepresentation() &&
8952 C
.getTypeSize(Type
) > C
.getTypeSize(VarType
);
8953 if (!Type
->isIntegerType() || UseVarType
) {
8955 UseVarType
? C
.getTypeSize(VarType
) : C
.getTypeSize(Type
);
8956 bool IsSigned
= UseVarType
? VarType
->hasSignedIntegerRepresentation()
8957 : Type
->hasSignedIntegerRepresentation();
8958 Type
= C
.getIntTypeForBitwidth(NewSize
, IsSigned
);
8959 if (!SemaRef
.Context
.hasSameType(Diff
.get()->getType(), Type
)) {
8960 Diff
= SemaRef
.PerformImplicitConversion(
8961 Diff
.get(), Type
, Sema::AA_Converting
, /*AllowExplicit=*/true);
8962 if (!Diff
.isUsable())
8967 unsigned NewSize
= (C
.getTypeSize(Type
) > 32) ? 64 : 32;
8968 if (NewSize
!= C
.getTypeSize(Type
)) {
8969 if (NewSize
< C
.getTypeSize(Type
)) {
8970 assert(NewSize
== 64 && "incorrect loop var size");
8971 SemaRef
.Diag(DefaultLoc
, diag::warn_omp_loop_64_bit_var
)
8972 << InitSrcRange
<< ConditionSrcRange
;
8974 QualType NewType
= C
.getIntTypeForBitwidth(
8975 NewSize
, Type
->hasSignedIntegerRepresentation() ||
8976 C
.getTypeSize(Type
) < NewSize
);
8977 if (!SemaRef
.Context
.hasSameType(Diff
.get()->getType(), NewType
)) {
8978 Diff
= SemaRef
.PerformImplicitConversion(Diff
.get(), NewType
,
8979 Sema::AA_Converting
, true);
8980 if (!Diff
.isUsable())
8989 std::pair
<Expr
*, Expr
*> OpenMPIterationSpaceChecker::buildMinMaxValues(
8990 Scope
*S
, llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
) const {
8991 // Do not build for iterators, they cannot be used in non-rectangular loop
8993 if (LCDecl
->getType()->isRecordType())
8994 return std::make_pair(nullptr, nullptr);
8995 // If we subtract, the min is in the condition, otherwise the min is in the
8997 Expr
*MinExpr
= nullptr;
8998 Expr
*MaxExpr
= nullptr;
8999 Expr
*LBExpr
= *TestIsLessOp
? LB
: UB
;
9000 Expr
*UBExpr
= *TestIsLessOp
? UB
: LB
;
9002 *TestIsLessOp
? InitDependOnLC
.has_value() : CondDependOnLC
.has_value();
9004 *TestIsLessOp
? CondDependOnLC
.has_value() : InitDependOnLC
.has_value();
9006 LBNonRect
? LBExpr
: tryBuildCapture(SemaRef
, LBExpr
, Captures
).get();
9008 UBNonRect
? UBExpr
: tryBuildCapture(SemaRef
, UBExpr
, Captures
).get();
9009 if (!Upper
|| !Lower
)
9010 return std::make_pair(nullptr, nullptr);
9017 // Build minimum/maximum value based on number of iterations.
9018 QualType VarType
= LCDecl
->getType().getNonReferenceType();
9020 ExprResult Diff
= calculateNumIters(SemaRef
, S
, DefaultLoc
, Lower
, Upper
,
9021 Step
, VarType
, TestIsStrictOp
,
9022 /*RoundToStep=*/false, Captures
);
9023 if (!Diff
.isUsable())
9024 return std::make_pair(nullptr, nullptr);
9026 // ((Upper - Lower [- 1]) / Step) * Step
9027 // Parentheses (for dumping/debugging purposes only).
9028 Diff
= SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, Diff
.get());
9029 if (!Diff
.isUsable())
9030 return std::make_pair(nullptr, nullptr);
9032 ExprResult NewStep
= tryBuildCapture(SemaRef
, Step
, Captures
, ".new_step");
9033 if (!NewStep
.isUsable())
9034 return std::make_pair(nullptr, nullptr);
9035 Diff
= SemaRef
.BuildBinOp(S
, DefaultLoc
, BO_Mul
, Diff
.get(), NewStep
.get());
9036 if (!Diff
.isUsable())
9037 return std::make_pair(nullptr, nullptr);
9039 // Parentheses (for dumping/debugging purposes only).
9040 Diff
= SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, Diff
.get());
9041 if (!Diff
.isUsable())
9042 return std::make_pair(nullptr, nullptr);
9044 // Convert to the ptrdiff_t, if original type is pointer.
9045 if (VarType
->isAnyPointerType() &&
9046 !SemaRef
.Context
.hasSameType(
9047 Diff
.get()->getType(),
9048 SemaRef
.Context
.getUnsignedPointerDiffType())) {
9049 Diff
= SemaRef
.PerformImplicitConversion(
9050 Diff
.get(), SemaRef
.Context
.getUnsignedPointerDiffType(),
9051 Sema::AA_Converting
, /*AllowExplicit=*/true);
9053 if (!Diff
.isUsable())
9054 return std::make_pair(nullptr, nullptr);
9056 if (*TestIsLessOp
) {
9058 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
9059 Diff
= SemaRef
.BuildBinOp(
9060 S
, DefaultLoc
, BO_Add
,
9061 SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, Lower
).get(),
9063 if (!Diff
.isUsable())
9064 return std::make_pair(nullptr, nullptr);
9067 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
9068 Diff
= SemaRef
.BuildBinOp(
9069 S
, DefaultLoc
, BO_Sub
,
9070 SemaRef
.ActOnParenExpr(DefaultLoc
, DefaultLoc
, Upper
).get(),
9072 if (!Diff
.isUsable())
9073 return std::make_pair(nullptr, nullptr);
9076 // Convert to the original type.
9077 if (SemaRef
.Context
.hasSameType(Diff
.get()->getType(), VarType
))
9078 Diff
= SemaRef
.PerformImplicitConversion(Diff
.get(), VarType
,
9079 Sema::AA_Converting
,
9080 /*AllowExplicit=*/true);
9081 if (!Diff
.isUsable())
9082 return std::make_pair(nullptr, nullptr);
9084 Sema::TentativeAnalysisScope
Trap(SemaRef
);
9085 Diff
= SemaRef
.ActOnFinishFullExpr(Diff
.get(), /*DiscardedValue=*/false);
9086 if (!Diff
.isUsable())
9087 return std::make_pair(nullptr, nullptr);
9090 MaxExpr
= Diff
.get();
9092 MinExpr
= Diff
.get();
9094 return std::make_pair(MinExpr
, MaxExpr
);
9097 Expr
*OpenMPIterationSpaceChecker::buildFinalCondition(Scope
*S
) const {
9098 if (InitDependOnLC
|| CondDependOnLC
)
9103 Expr
*OpenMPIterationSpaceChecker::buildPreCond(
9104 Scope
*S
, Expr
*Cond
,
9105 llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
) const {
9106 // Do not build a precondition when the condition/initialization is dependent
9107 // to prevent pessimistic early loop exit.
9108 // TODO: this can be improved by calculating min/max values but not sure that
9109 // it will be very effective.
9110 if (CondDependOnLC
|| InitDependOnLC
)
9112 .PerformImplicitConversion(
9113 SemaRef
.ActOnIntegerConstant(SourceLocation(), 1).get(),
9114 SemaRef
.Context
.BoolTy
, /*Action=*/Sema::AA_Casting
,
9115 /*AllowExplicit=*/true)
9118 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
9119 Sema::TentativeAnalysisScope
Trap(SemaRef
);
9121 ExprResult NewLB
= tryBuildCapture(SemaRef
, LB
, Captures
);
9122 ExprResult NewUB
= tryBuildCapture(SemaRef
, UB
, Captures
);
9123 if (!NewLB
.isUsable() || !NewUB
.isUsable())
9126 ExprResult CondExpr
=
9127 SemaRef
.BuildBinOp(S
, DefaultLoc
,
9128 *TestIsLessOp
? (TestIsStrictOp
? BO_LT
: BO_LE
)
9129 : (TestIsStrictOp
? BO_GT
: BO_GE
),
9130 NewLB
.get(), NewUB
.get());
9131 if (CondExpr
.isUsable()) {
9132 if (!SemaRef
.Context
.hasSameUnqualifiedType(CondExpr
.get()->getType(),
9133 SemaRef
.Context
.BoolTy
))
9134 CondExpr
= SemaRef
.PerformImplicitConversion(
9135 CondExpr
.get(), SemaRef
.Context
.BoolTy
, /*Action=*/Sema::AA_Casting
,
9136 /*AllowExplicit=*/true);
9139 // Otherwise use original loop condition and evaluate it in runtime.
9140 return CondExpr
.isUsable() ? CondExpr
.get() : Cond
;
9143 /// Build reference expression to the counter be used for codegen.
9144 DeclRefExpr
*OpenMPIterationSpaceChecker::buildCounterVar(
9145 llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
,
9146 DSAStackTy
&DSA
) const {
9147 auto *VD
= dyn_cast
<VarDecl
>(LCDecl
);
9149 VD
= SemaRef
.isOpenMPCapturedDecl(LCDecl
);
9150 DeclRefExpr
*Ref
= buildDeclRefExpr(
9151 SemaRef
, VD
, VD
->getType().getNonReferenceType(), DefaultLoc
);
9152 const DSAStackTy::DSAVarData Data
=
9153 DSA
.getTopDSA(LCDecl
, /*FromParent=*/false);
9154 // If the loop control decl is explicitly marked as private, do not mark it
9155 // as captured again.
9156 if (!isOpenMPPrivate(Data
.CKind
) || !Data
.RefExpr
)
9157 Captures
.insert(std::make_pair(LCRef
, Ref
));
9160 return cast
<DeclRefExpr
>(LCRef
);
9163 Expr
*OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9164 if (LCDecl
&& !LCDecl
->isInvalidDecl()) {
9165 QualType Type
= LCDecl
->getType().getNonReferenceType();
9166 VarDecl
*PrivateVar
= buildVarDecl(
9167 SemaRef
, DefaultLoc
, Type
, LCDecl
->getName(),
9168 LCDecl
->hasAttrs() ? &LCDecl
->getAttrs() : nullptr,
9169 isa
<VarDecl
>(LCDecl
)
9170 ? buildDeclRefExpr(SemaRef
, cast
<VarDecl
>(LCDecl
), Type
, DefaultLoc
)
9172 if (PrivateVar
->isInvalidDecl())
9174 return buildDeclRefExpr(SemaRef
, PrivateVar
, Type
, DefaultLoc
);
9179 /// Build initialization of the counter to be used for codegen.
9180 Expr
*OpenMPIterationSpaceChecker::buildCounterInit() const { return LB
; }
9182 /// Build step of the counter be used for codegen.
9183 Expr
*OpenMPIterationSpaceChecker::buildCounterStep() const { return Step
; }
9185 Expr
*OpenMPIterationSpaceChecker::buildOrderedLoopData(
9186 Scope
*S
, Expr
*Counter
,
9187 llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
, SourceLocation Loc
,
9188 Expr
*Inc
, OverloadedOperatorKind OOK
) {
9189 Expr
*Cnt
= SemaRef
.DefaultLvalueConversion(Counter
).get();
9193 assert((OOK
== OO_Plus
|| OOK
== OO_Minus
) &&
9194 "Expected only + or - operations for depend clauses.");
9195 BinaryOperatorKind BOK
= (OOK
== OO_Plus
) ? BO_Add
: BO_Sub
;
9196 Cnt
= SemaRef
.BuildBinOp(S
, Loc
, BOK
, Cnt
, Inc
).get();
9200 QualType VarType
= LCDecl
->getType().getNonReferenceType();
9201 if (!VarType
->isIntegerType() && !VarType
->isPointerType() &&
9202 !SemaRef
.getLangOpts().CPlusPlus
)
9206 *TestIsLessOp
? Cnt
: tryBuildCapture(SemaRef
, LB
, Captures
).get();
9208 *TestIsLessOp
? tryBuildCapture(SemaRef
, LB
, Captures
).get() : Cnt
;
9209 if (!Upper
|| !Lower
)
9212 ExprResult Diff
= calculateNumIters(
9213 SemaRef
, S
, DefaultLoc
, Lower
, Upper
, Step
, VarType
,
9214 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures
);
9215 if (!Diff
.isUsable())
9222 void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc
, Stmt
*Init
) {
9223 assert(getLangOpts().OpenMP
&& "OpenMP is not active.");
9224 assert(Init
&& "Expected loop in canonical form.");
9225 unsigned AssociatedLoops
= DSAStack
->getAssociatedLoops();
9226 if (AssociatedLoops
> 0 &&
9227 isOpenMPLoopDirective(DSAStack
->getCurrentDirective())) {
9228 DSAStack
->loopStart();
9229 OpenMPIterationSpaceChecker
ISC(*this, /*SupportsNonRectangular=*/true,
9231 if (!ISC
.checkAndSetInit(Init
, /*EmitDiags=*/false)) {
9232 if (ValueDecl
*D
= ISC
.getLoopDecl()) {
9233 auto *VD
= dyn_cast
<VarDecl
>(D
);
9234 DeclRefExpr
*PrivateRef
= nullptr;
9236 if (VarDecl
*Private
= isOpenMPCapturedDecl(D
)) {
9239 PrivateRef
= buildCapture(*this, D
, ISC
.getLoopDeclRefExpr(),
9240 /*WithInit=*/false);
9241 VD
= cast
<VarDecl
>(PrivateRef
->getDecl());
9244 DSAStack
->addLoopControlVariable(D
, VD
);
9245 const Decl
*LD
= DSAStack
->getPossiblyLoopCunter();
9246 if (LD
!= D
->getCanonicalDecl()) {
9247 DSAStack
->resetPossibleLoopCounter();
9248 if (auto *Var
= dyn_cast_or_null
<VarDecl
>(LD
))
9249 MarkDeclarationsReferencedInExpr(
9250 buildDeclRefExpr(*this, const_cast<VarDecl
*>(Var
),
9251 Var
->getType().getNonLValueExprType(Context
),
9252 ForLoc
, /*RefersToCapture=*/true));
9254 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
9255 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9256 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9257 // associated for-loop of a simd construct with just one associated
9258 // for-loop may be listed in a linear clause with a constant-linear-step
9259 // that is the increment of the associated for-loop. The loop iteration
9260 // variable(s) in the associated for-loop(s) of a for or parallel for
9261 // construct may be listed in a private or lastprivate clause.
9262 DSAStackTy::DSAVarData DVar
=
9263 DSAStack
->getTopDSA(D
, /*FromParent=*/false);
9264 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9265 // is declared in the loop and it is predetermined as a private.
9266 Expr
*LoopDeclRefExpr
= ISC
.getLoopDeclRefExpr();
9267 OpenMPClauseKind PredeterminedCKind
=
9268 isOpenMPSimdDirective(DKind
)
9269 ? (DSAStack
->hasMutipleLoops() ? OMPC_lastprivate
: OMPC_linear
)
9271 if (((isOpenMPSimdDirective(DKind
) && DVar
.CKind
!= OMPC_unknown
&&
9272 DVar
.CKind
!= PredeterminedCKind
&& DVar
.RefExpr
&&
9273 (LangOpts
.OpenMP
<= 45 || (DVar
.CKind
!= OMPC_lastprivate
&&
9274 DVar
.CKind
!= OMPC_private
))) ||
9275 ((isOpenMPWorksharingDirective(DKind
) || DKind
== OMPD_taskloop
||
9276 DKind
== OMPD_master_taskloop
|| DKind
== OMPD_masked_taskloop
||
9277 DKind
== OMPD_parallel_master_taskloop
||
9278 DKind
== OMPD_parallel_masked_taskloop
||
9279 isOpenMPDistributeDirective(DKind
)) &&
9280 !isOpenMPSimdDirective(DKind
) && DVar
.CKind
!= OMPC_unknown
&&
9281 DVar
.CKind
!= OMPC_private
&& DVar
.CKind
!= OMPC_lastprivate
)) &&
9282 (DVar
.CKind
!= OMPC_private
|| DVar
.RefExpr
)) {
9283 Diag(Init
->getBeginLoc(), diag::err_omp_loop_var_dsa
)
9284 << getOpenMPClauseName(DVar
.CKind
)
9285 << getOpenMPDirectiveName(DKind
)
9286 << getOpenMPClauseName(PredeterminedCKind
);
9287 if (DVar
.RefExpr
== nullptr)
9288 DVar
.CKind
= PredeterminedCKind
;
9289 reportOriginalDsa(*this, DSAStack
, D
, DVar
,
9290 /*IsLoopIterVar=*/true);
9291 } else if (LoopDeclRefExpr
) {
9292 // Make the loop iteration variable private (for worksharing
9293 // constructs), linear (for simd directives with the only one
9294 // associated loop) or lastprivate (for simd directives with several
9295 // collapsed or ordered loops).
9296 if (DVar
.CKind
== OMPC_unknown
)
9297 DSAStack
->addDSA(D
, LoopDeclRefExpr
, PredeterminedCKind
,
9302 DSAStack
->setAssociatedLoops(AssociatedLoops
- 1);
9307 // Utility for openmp doacross clause kind
9308 class OMPDoacrossKind
{
9310 bool isSource(const OMPDoacrossClause
*C
) {
9311 return C
->getDependenceType() == OMPC_DOACROSS_source
||
9312 C
->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration
;
9314 bool isSink(const OMPDoacrossClause
*C
) {
9315 return C
->getDependenceType() == OMPC_DOACROSS_sink
;
9317 bool isSinkIter(const OMPDoacrossClause
*C
) {
9318 return C
->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration
;
9322 /// Called on a for stmt to check and extract its iteration space
9323 /// for further processing (such as collapsing).
9324 static bool checkOpenMPIterationSpace(
9325 OpenMPDirectiveKind DKind
, Stmt
*S
, Sema
&SemaRef
, DSAStackTy
&DSA
,
9326 unsigned CurrentNestedLoopCount
, unsigned NestedLoopCount
,
9327 unsigned TotalNestedLoopCount
, Expr
*CollapseLoopCountExpr
,
9328 Expr
*OrderedLoopCountExpr
,
9329 Sema::VarsWithInheritedDSAType
&VarsWithImplicitDSA
,
9330 llvm::MutableArrayRef
<LoopIterationSpace
> ResultIterSpaces
,
9331 llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
) {
9332 bool SupportsNonRectangular
= !isOpenMPLoopTransformationDirective(DKind
);
9333 // OpenMP [2.9.1, Canonical Loop Form]
9334 // for (init-expr; test-expr; incr-expr) structured-block
9335 // for (range-decl: range-expr) structured-block
9336 if (auto *CanonLoop
= dyn_cast_or_null
<OMPCanonicalLoop
>(S
))
9337 S
= CanonLoop
->getLoopStmt();
9338 auto *For
= dyn_cast_or_null
<ForStmt
>(S
);
9339 auto *CXXFor
= dyn_cast_or_null
<CXXForRangeStmt
>(S
);
9340 // Ranged for is supported only in OpenMP 5.0.
9341 if (!For
&& (SemaRef
.LangOpts
.OpenMP
<= 45 || !CXXFor
)) {
9342 OpenMPDirectiveKind DK
= (SemaRef
.getLangOpts().OpenMP
< 50 ||
9343 DSA
.getMappedDirective() == OMPD_unknown
)
9345 : DSA
.getMappedDirective();
9346 SemaRef
.Diag(S
->getBeginLoc(), diag::err_omp_not_for
)
9347 << (CollapseLoopCountExpr
!= nullptr || OrderedLoopCountExpr
!= nullptr)
9348 << getOpenMPDirectiveName(DK
) << TotalNestedLoopCount
9349 << (CurrentNestedLoopCount
> 0) << CurrentNestedLoopCount
;
9350 if (TotalNestedLoopCount
> 1) {
9351 if (CollapseLoopCountExpr
&& OrderedLoopCountExpr
)
9352 SemaRef
.Diag(DSA
.getConstructLoc(),
9353 diag::note_omp_collapse_ordered_expr
)
9354 << 2 << CollapseLoopCountExpr
->getSourceRange()
9355 << OrderedLoopCountExpr
->getSourceRange();
9356 else if (CollapseLoopCountExpr
)
9357 SemaRef
.Diag(CollapseLoopCountExpr
->getExprLoc(),
9358 diag::note_omp_collapse_ordered_expr
)
9359 << 0 << CollapseLoopCountExpr
->getSourceRange();
9361 SemaRef
.Diag(OrderedLoopCountExpr
->getExprLoc(),
9362 diag::note_omp_collapse_ordered_expr
)
9363 << 1 << OrderedLoopCountExpr
->getSourceRange();
9367 assert(((For
&& For
->getBody()) || (CXXFor
&& CXXFor
->getBody())) &&
9369 // Postpone analysis in dependent contexts for ranged for loops.
9370 if (CXXFor
&& SemaRef
.CurContext
->isDependentContext())
9373 OpenMPIterationSpaceChecker
ISC(SemaRef
, SupportsNonRectangular
, DSA
,
9374 For
? For
->getForLoc() : CXXFor
->getForLoc());
9377 Stmt
*Init
= For
? For
->getInit() : CXXFor
->getBeginStmt();
9378 if (ISC
.checkAndSetInit(Init
))
9381 bool HasErrors
= false;
9383 // Check loop variable's type.
9384 if (ValueDecl
*LCDecl
= ISC
.getLoopDecl()) {
9385 // OpenMP [2.6, Canonical Loop Form]
9386 // Var is one of the following:
9387 // A variable of signed or unsigned integer type.
9388 // For C++, a variable of a random access iterator type.
9389 // For C, a variable of a pointer type.
9390 QualType VarType
= LCDecl
->getType().getNonReferenceType();
9391 if (!VarType
->isDependentType() && !VarType
->isIntegerType() &&
9392 !VarType
->isPointerType() &&
9393 !(SemaRef
.getLangOpts().CPlusPlus
&& VarType
->isOverloadableType())) {
9394 SemaRef
.Diag(Init
->getBeginLoc(), diag::err_omp_loop_variable_type
)
9395 << SemaRef
.getLangOpts().CPlusPlus
;
9399 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9401 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9402 // parallel for construct is (are) private.
9403 // The loop iteration variable in the associated for-loop of a simd
9404 // construct with just one associated for-loop is linear with a
9405 // constant-linear-step that is the increment of the associated for-loop.
9406 // Exclude loop var from the list of variables with implicitly defined data
9407 // sharing attributes.
9408 VarsWithImplicitDSA
.erase(LCDecl
);
9410 assert(isOpenMPLoopDirective(DKind
) && "DSA for non-loop vars");
9413 HasErrors
|= ISC
.checkAndSetCond(For
? For
->getCond() : CXXFor
->getCond());
9416 HasErrors
|= ISC
.checkAndSetInc(For
? For
->getInc() : CXXFor
->getInc());
9419 if (ISC
.dependent() || SemaRef
.CurContext
->isDependentContext() || HasErrors
)
9422 // Build the loop's iteration space representation.
9423 ResultIterSpaces
[CurrentNestedLoopCount
].PreCond
= ISC
.buildPreCond(
9424 DSA
.getCurScope(), For
? For
->getCond() : CXXFor
->getCond(), Captures
);
9425 ResultIterSpaces
[CurrentNestedLoopCount
].NumIterations
=
9426 ISC
.buildNumIterations(DSA
.getCurScope(), ResultIterSpaces
,
9427 (isOpenMPWorksharingDirective(DKind
) ||
9428 isOpenMPGenericLoopDirective(DKind
) ||
9429 isOpenMPTaskLoopDirective(DKind
) ||
9430 isOpenMPDistributeDirective(DKind
) ||
9431 isOpenMPLoopTransformationDirective(DKind
)),
9433 ResultIterSpaces
[CurrentNestedLoopCount
].CounterVar
=
9434 ISC
.buildCounterVar(Captures
, DSA
);
9435 ResultIterSpaces
[CurrentNestedLoopCount
].PrivateCounterVar
=
9436 ISC
.buildPrivateCounterVar();
9437 ResultIterSpaces
[CurrentNestedLoopCount
].CounterInit
= ISC
.buildCounterInit();
9438 ResultIterSpaces
[CurrentNestedLoopCount
].CounterStep
= ISC
.buildCounterStep();
9439 ResultIterSpaces
[CurrentNestedLoopCount
].InitSrcRange
= ISC
.getInitSrcRange();
9440 ResultIterSpaces
[CurrentNestedLoopCount
].CondSrcRange
=
9441 ISC
.getConditionSrcRange();
9442 ResultIterSpaces
[CurrentNestedLoopCount
].IncSrcRange
=
9443 ISC
.getIncrementSrcRange();
9444 ResultIterSpaces
[CurrentNestedLoopCount
].Subtract
= ISC
.shouldSubtractStep();
9445 ResultIterSpaces
[CurrentNestedLoopCount
].IsStrictCompare
=
9446 ISC
.isStrictTestOp();
9447 std::tie(ResultIterSpaces
[CurrentNestedLoopCount
].MinValue
,
9448 ResultIterSpaces
[CurrentNestedLoopCount
].MaxValue
) =
9449 ISC
.buildMinMaxValues(DSA
.getCurScope(), Captures
);
9450 ResultIterSpaces
[CurrentNestedLoopCount
].FinalCondition
=
9451 ISC
.buildFinalCondition(DSA
.getCurScope());
9452 ResultIterSpaces
[CurrentNestedLoopCount
].IsNonRectangularLB
=
9453 ISC
.doesInitDependOnLC();
9454 ResultIterSpaces
[CurrentNestedLoopCount
].IsNonRectangularUB
=
9455 ISC
.doesCondDependOnLC();
9456 ResultIterSpaces
[CurrentNestedLoopCount
].LoopDependentIdx
=
9457 ISC
.getLoopDependentIdx();
9460 (ResultIterSpaces
[CurrentNestedLoopCount
].PreCond
== nullptr ||
9461 ResultIterSpaces
[CurrentNestedLoopCount
].NumIterations
== nullptr ||
9462 ResultIterSpaces
[CurrentNestedLoopCount
].CounterVar
== nullptr ||
9463 ResultIterSpaces
[CurrentNestedLoopCount
].PrivateCounterVar
== nullptr ||
9464 ResultIterSpaces
[CurrentNestedLoopCount
].CounterInit
== nullptr ||
9465 ResultIterSpaces
[CurrentNestedLoopCount
].CounterStep
== nullptr);
9466 if (!HasErrors
&& DSA
.isOrderedRegion()) {
9467 if (DSA
.getOrderedRegionParam().second
->getNumForLoops()) {
9468 if (CurrentNestedLoopCount
<
9469 DSA
.getOrderedRegionParam().second
->getLoopNumIterations().size()) {
9470 DSA
.getOrderedRegionParam().second
->setLoopNumIterations(
9471 CurrentNestedLoopCount
,
9472 ResultIterSpaces
[CurrentNestedLoopCount
].NumIterations
);
9473 DSA
.getOrderedRegionParam().second
->setLoopCounter(
9474 CurrentNestedLoopCount
,
9475 ResultIterSpaces
[CurrentNestedLoopCount
].CounterVar
);
9478 for (auto &Pair
: DSA
.getDoacrossDependClauses()) {
9479 auto *DependC
= dyn_cast
<OMPDependClause
>(Pair
.first
);
9480 auto *DoacrossC
= dyn_cast
<OMPDoacrossClause
>(Pair
.first
);
9482 DependC
? DependC
->getNumLoops() : DoacrossC
->getNumLoops();
9483 if (CurrentNestedLoopCount
>= NumLoops
) {
9484 // Erroneous case - clause has some problems.
9487 if (DependC
&& DependC
->getDependencyKind() == OMPC_DEPEND_sink
&&
9488 Pair
.second
.size() <= CurrentNestedLoopCount
) {
9489 // Erroneous case - clause has some problems.
9490 DependC
->setLoopData(CurrentNestedLoopCount
, nullptr);
9493 OMPDoacrossKind ODK
;
9494 if (DoacrossC
&& ODK
.isSink(DoacrossC
) &&
9495 Pair
.second
.size() <= CurrentNestedLoopCount
) {
9496 // Erroneous case - clause has some problems.
9497 DoacrossC
->setLoopData(CurrentNestedLoopCount
, nullptr);
9501 SourceLocation DepLoc
=
9502 DependC
? DependC
->getDependencyLoc() : DoacrossC
->getDependenceLoc();
9503 if ((DependC
&& DependC
->getDependencyKind() == OMPC_DEPEND_source
) ||
9504 (DoacrossC
&& ODK
.isSource(DoacrossC
)))
9505 CntValue
= ISC
.buildOrderedLoopData(
9507 ResultIterSpaces
[CurrentNestedLoopCount
].CounterVar
, Captures
,
9509 else if (DoacrossC
&& ODK
.isSinkIter(DoacrossC
)) {
9511 .DefaultLvalueConversion(
9512 ResultIterSpaces
[CurrentNestedLoopCount
].CounterVar
)
9516 // build CounterVar - 1
9518 SemaRef
.ActOnIntegerConstant(DoacrossC
->getColonLoc(), /*Val=*/1)
9520 CntValue
= ISC
.buildOrderedLoopData(
9522 ResultIterSpaces
[CurrentNestedLoopCount
].CounterVar
, Captures
,
9523 DepLoc
, Inc
, clang::OO_Minus
);
9525 CntValue
= ISC
.buildOrderedLoopData(
9527 ResultIterSpaces
[CurrentNestedLoopCount
].CounterVar
, Captures
,
9528 DepLoc
, Pair
.second
[CurrentNestedLoopCount
].first
,
9529 Pair
.second
[CurrentNestedLoopCount
].second
);
9531 DependC
->setLoopData(CurrentNestedLoopCount
, CntValue
);
9533 DoacrossC
->setLoopData(CurrentNestedLoopCount
, CntValue
);
9540 /// Build 'VarRef = Start.
9542 buildCounterInit(Sema
&SemaRef
, Scope
*S
, SourceLocation Loc
, ExprResult VarRef
,
9543 ExprResult Start
, bool IsNonRectangularLB
,
9544 llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
) {
9545 // Build 'VarRef = Start.
9546 ExprResult NewStart
= IsNonRectangularLB
9548 : tryBuildCapture(SemaRef
, Start
.get(), Captures
);
9549 if (!NewStart
.isUsable())
9551 if (!SemaRef
.Context
.hasSameType(NewStart
.get()->getType(),
9552 VarRef
.get()->getType())) {
9553 NewStart
= SemaRef
.PerformImplicitConversion(
9554 NewStart
.get(), VarRef
.get()->getType(), Sema::AA_Converting
,
9555 /*AllowExplicit=*/true);
9556 if (!NewStart
.isUsable())
9561 SemaRef
.BuildBinOp(S
, Loc
, BO_Assign
, VarRef
.get(), NewStart
.get());
9565 /// Build 'VarRef = Start + Iter * Step'.
9566 static ExprResult
buildCounterUpdate(
9567 Sema
&SemaRef
, Scope
*S
, SourceLocation Loc
, ExprResult VarRef
,
9568 ExprResult Start
, ExprResult Iter
, ExprResult Step
, bool Subtract
,
9569 bool IsNonRectangularLB
,
9570 llvm::MapVector
<const Expr
*, DeclRefExpr
*> *Captures
= nullptr) {
9571 // Add parentheses (for debugging purposes only).
9572 Iter
= SemaRef
.ActOnParenExpr(Loc
, Loc
, Iter
.get());
9573 if (!VarRef
.isUsable() || !Start
.isUsable() || !Iter
.isUsable() ||
9577 ExprResult NewStep
= Step
;
9579 NewStep
= tryBuildCapture(SemaRef
, Step
.get(), *Captures
);
9580 if (NewStep
.isInvalid())
9583 SemaRef
.BuildBinOp(S
, Loc
, BO_Mul
, Iter
.get(), NewStep
.get());
9584 if (!Update
.isUsable())
9587 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9588 // 'VarRef = Start (+|-) Iter * Step'.
9589 if (!Start
.isUsable())
9591 ExprResult NewStart
= SemaRef
.ActOnParenExpr(Loc
, Loc
, Start
.get());
9592 if (!NewStart
.isUsable())
9594 if (Captures
&& !IsNonRectangularLB
)
9595 NewStart
= tryBuildCapture(SemaRef
, Start
.get(), *Captures
);
9596 if (NewStart
.isInvalid())
9599 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9600 ExprResult SavedUpdate
= Update
;
9601 ExprResult UpdateVal
;
9602 if (VarRef
.get()->getType()->isOverloadableType() ||
9603 NewStart
.get()->getType()->isOverloadableType() ||
9604 Update
.get()->getType()->isOverloadableType()) {
9605 Sema::TentativeAnalysisScope
Trap(SemaRef
);
9608 SemaRef
.BuildBinOp(S
, Loc
, BO_Assign
, VarRef
.get(), NewStart
.get());
9609 if (Update
.isUsable()) {
9611 SemaRef
.BuildBinOp(S
, Loc
, Subtract
? BO_SubAssign
: BO_AddAssign
,
9612 VarRef
.get(), SavedUpdate
.get());
9613 if (UpdateVal
.isUsable()) {
9614 Update
= SemaRef
.CreateBuiltinBinOp(Loc
, BO_Comma
, Update
.get(),
9620 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9621 if (!Update
.isUsable() || !UpdateVal
.isUsable()) {
9622 Update
= SemaRef
.BuildBinOp(S
, Loc
, Subtract
? BO_Sub
: BO_Add
,
9623 NewStart
.get(), SavedUpdate
.get());
9624 if (!Update
.isUsable())
9627 if (!SemaRef
.Context
.hasSameType(Update
.get()->getType(),
9628 VarRef
.get()->getType())) {
9629 Update
= SemaRef
.PerformImplicitConversion(
9630 Update
.get(), VarRef
.get()->getType(), Sema::AA_Converting
, true);
9631 if (!Update
.isUsable())
9635 Update
= SemaRef
.BuildBinOp(S
, Loc
, BO_Assign
, VarRef
.get(), Update
.get());
9640 /// Convert integer expression \a E to make it have at least \a Bits
9642 static ExprResult
widenIterationCount(unsigned Bits
, Expr
*E
, Sema
&SemaRef
) {
9645 ASTContext
&C
= SemaRef
.Context
;
9646 QualType OldType
= E
->getType();
9647 unsigned HasBits
= C
.getTypeSize(OldType
);
9648 if (HasBits
>= Bits
)
9649 return ExprResult(E
);
9650 // OK to convert to signed, because new type has more bits than old.
9651 QualType NewType
= C
.getIntTypeForBitwidth(Bits
, /* Signed */ true);
9652 return SemaRef
.PerformImplicitConversion(E
, NewType
, Sema::AA_Converting
,
9656 /// Check if the given expression \a E is a constant integer that fits
9657 /// into \a Bits bits.
9658 static bool fitsInto(unsigned Bits
, bool Signed
, const Expr
*E
, Sema
&SemaRef
) {
9661 if (std::optional
<llvm::APSInt
> Result
=
9662 E
->getIntegerConstantExpr(SemaRef
.Context
))
9663 return Signed
? Result
->isSignedIntN(Bits
) : Result
->isIntN(Bits
);
9667 /// Build preinits statement for the given declarations.
9668 static Stmt
*buildPreInits(ASTContext
&Context
,
9669 MutableArrayRef
<Decl
*> PreInits
) {
9670 if (!PreInits
.empty()) {
9671 return new (Context
) DeclStmt(
9672 DeclGroupRef::Create(Context
, PreInits
.begin(), PreInits
.size()),
9673 SourceLocation(), SourceLocation());
9678 /// Build preinits statement for the given declarations.
9680 buildPreInits(ASTContext
&Context
,
9681 const llvm::MapVector
<const Expr
*, DeclRefExpr
*> &Captures
) {
9682 if (!Captures
.empty()) {
9683 SmallVector
<Decl
*, 16> PreInits
;
9684 for (const auto &Pair
: Captures
)
9685 PreInits
.push_back(Pair
.second
->getDecl());
9686 return buildPreInits(Context
, PreInits
);
9691 /// Build postupdate expression for the given list of postupdates expressions.
9692 static Expr
*buildPostUpdate(Sema
&S
, ArrayRef
<Expr
*> PostUpdates
) {
9693 Expr
*PostUpdate
= nullptr;
9694 if (!PostUpdates
.empty()) {
9695 for (Expr
*E
: PostUpdates
) {
9696 Expr
*ConvE
= S
.BuildCStyleCastExpr(
9698 S
.Context
.getTrivialTypeSourceInfo(S
.Context
.VoidTy
),
9701 PostUpdate
= PostUpdate
9702 ? S
.CreateBuiltinBinOp(ConvE
->getExprLoc(), BO_Comma
,
9711 /// Called on a for stmt to check itself and nested loops (if any).
9712 /// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9713 /// number of collapsed loops otherwise.
9715 checkOpenMPLoop(OpenMPDirectiveKind DKind
, Expr
*CollapseLoopCountExpr
,
9716 Expr
*OrderedLoopCountExpr
, Stmt
*AStmt
, Sema
&SemaRef
,
9718 Sema::VarsWithInheritedDSAType
&VarsWithImplicitDSA
,
9719 OMPLoopBasedDirective::HelperExprs
&Built
) {
9720 unsigned NestedLoopCount
= 1;
9721 bool SupportsNonPerfectlyNested
= (SemaRef
.LangOpts
.OpenMP
>= 50) &&
9722 !isOpenMPLoopTransformationDirective(DKind
);
9724 if (CollapseLoopCountExpr
) {
9725 // Found 'collapse' clause - calculate collapse number.
9726 Expr::EvalResult Result
;
9727 if (!CollapseLoopCountExpr
->isValueDependent() &&
9728 CollapseLoopCountExpr
->EvaluateAsInt(Result
, SemaRef
.getASTContext())) {
9729 NestedLoopCount
= Result
.Val
.getInt().getLimitedValue();
9731 Built
.clear(/*Size=*/1);
9735 unsigned OrderedLoopCount
= 1;
9736 if (OrderedLoopCountExpr
) {
9737 // Found 'ordered' clause - calculate collapse number.
9738 Expr::EvalResult EVResult
;
9739 if (!OrderedLoopCountExpr
->isValueDependent() &&
9740 OrderedLoopCountExpr
->EvaluateAsInt(EVResult
,
9741 SemaRef
.getASTContext())) {
9742 llvm::APSInt Result
= EVResult
.Val
.getInt();
9743 if (Result
.getLimitedValue() < NestedLoopCount
) {
9744 SemaRef
.Diag(OrderedLoopCountExpr
->getExprLoc(),
9745 diag::err_omp_wrong_ordered_loop_count
)
9746 << OrderedLoopCountExpr
->getSourceRange();
9747 SemaRef
.Diag(CollapseLoopCountExpr
->getExprLoc(),
9748 diag::note_collapse_loop_count
)
9749 << CollapseLoopCountExpr
->getSourceRange();
9751 OrderedLoopCount
= Result
.getLimitedValue();
9753 Built
.clear(/*Size=*/1);
9757 // This is helper routine for loop directives (e.g., 'for', 'simd',
9758 // 'for simd', etc.).
9759 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
9760 unsigned NumLoops
= std::max(OrderedLoopCount
, NestedLoopCount
);
9761 SmallVector
<LoopIterationSpace
, 4> IterSpaces(NumLoops
);
9762 if (!OMPLoopBasedDirective::doForAllLoops(
9763 AStmt
->IgnoreContainers(!isOpenMPLoopTransformationDirective(DKind
)),
9764 SupportsNonPerfectlyNested
, NumLoops
,
9765 [DKind
, &SemaRef
, &DSA
, NumLoops
, NestedLoopCount
,
9766 CollapseLoopCountExpr
, OrderedLoopCountExpr
, &VarsWithImplicitDSA
,
9767 &IterSpaces
, &Captures
](unsigned Cnt
, Stmt
*CurStmt
) {
9768 if (checkOpenMPIterationSpace(
9769 DKind
, CurStmt
, SemaRef
, DSA
, Cnt
, NestedLoopCount
,
9770 NumLoops
, CollapseLoopCountExpr
, OrderedLoopCountExpr
,
9771 VarsWithImplicitDSA
, IterSpaces
, Captures
))
9773 if (Cnt
> 0 && Cnt
>= NestedLoopCount
&&
9774 IterSpaces
[Cnt
].CounterVar
) {
9775 // Handle initialization of captured loop iterator variables.
9776 auto *DRE
= cast
<DeclRefExpr
>(IterSpaces
[Cnt
].CounterVar
);
9777 if (isa
<OMPCapturedExprDecl
>(DRE
->getDecl())) {
9778 Captures
[DRE
] = DRE
;
9783 [&SemaRef
, &Captures
](OMPLoopTransformationDirective
*Transform
) {
9784 Stmt
*DependentPreInits
= Transform
->getPreInits();
9785 if (!DependentPreInits
)
9787 for (Decl
*C
: cast
<DeclStmt
>(DependentPreInits
)->getDeclGroup()) {
9788 auto *D
= cast
<VarDecl
>(C
);
9789 DeclRefExpr
*Ref
= buildDeclRefExpr(SemaRef
, D
, D
->getType(),
9790 Transform
->getBeginLoc());
9791 Captures
[Ref
] = Ref
;
9796 Built
.clear(/* size */ NestedLoopCount
);
9798 if (SemaRef
.CurContext
->isDependentContext())
9799 return NestedLoopCount
;
9801 // An example of what is generated for the following code:
9803 // #pragma omp simd collapse(2) ordered(2)
9804 // for (i = 0; i < NI; ++i)
9805 // for (k = 0; k < NK; ++k)
9806 // for (j = J0; j < NJ; j+=2) {
9810 // We generate the code below.
9811 // Note: the loop body may be outlined in CodeGen.
9812 // Note: some counters may be C++ classes, operator- is used to find number of
9813 // iterations and operator+= to calculate counter value.
9814 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
9815 // or i64 is currently supported).
9817 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
9818 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
9819 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
9820 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
9821 // // similar updates for vars in clauses (e.g. 'linear')
9822 // <loop body (using local i and j)>
9824 // i = NI; // assign final values of counters
9828 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
9829 // the iteration counts of the collapsed for loops.
9830 // Precondition tests if there is at least one iteration (all conditions are
9832 auto PreCond
= ExprResult(IterSpaces
[0].PreCond
);
9833 Expr
*N0
= IterSpaces
[0].NumIterations
;
9834 ExprResult LastIteration32
=
9835 widenIterationCount(/*Bits=*/32,
9837 .PerformImplicitConversion(
9838 N0
->IgnoreImpCasts(), N0
->getType(),
9839 Sema::AA_Converting
, /*AllowExplicit=*/true)
9842 ExprResult LastIteration64
= widenIterationCount(
9845 .PerformImplicitConversion(N0
->IgnoreImpCasts(), N0
->getType(),
9846 Sema::AA_Converting
,
9847 /*AllowExplicit=*/true)
9851 if (!LastIteration32
.isUsable() || !LastIteration64
.isUsable())
9852 return NestedLoopCount
;
9854 ASTContext
&C
= SemaRef
.Context
;
9855 bool AllCountsNeedLessThan32Bits
= C
.getTypeSize(N0
->getType()) < 32;
9857 Scope
*CurScope
= DSA
.getCurScope();
9858 for (unsigned Cnt
= 1; Cnt
< NestedLoopCount
; ++Cnt
) {
9859 if (PreCond
.isUsable()) {
9861 SemaRef
.BuildBinOp(CurScope
, PreCond
.get()->getExprLoc(), BO_LAnd
,
9862 PreCond
.get(), IterSpaces
[Cnt
].PreCond
);
9864 Expr
*N
= IterSpaces
[Cnt
].NumIterations
;
9865 SourceLocation Loc
= N
->getExprLoc();
9866 AllCountsNeedLessThan32Bits
&= C
.getTypeSize(N
->getType()) < 32;
9867 if (LastIteration32
.isUsable())
9868 LastIteration32
= SemaRef
.BuildBinOp(
9869 CurScope
, Loc
, BO_Mul
, LastIteration32
.get(),
9871 .PerformImplicitConversion(N
->IgnoreImpCasts(), N
->getType(),
9872 Sema::AA_Converting
,
9873 /*AllowExplicit=*/true)
9875 if (LastIteration64
.isUsable())
9876 LastIteration64
= SemaRef
.BuildBinOp(
9877 CurScope
, Loc
, BO_Mul
, LastIteration64
.get(),
9879 .PerformImplicitConversion(N
->IgnoreImpCasts(), N
->getType(),
9880 Sema::AA_Converting
,
9881 /*AllowExplicit=*/true)
9885 // Choose either the 32-bit or 64-bit version.
9886 ExprResult LastIteration
= LastIteration64
;
9887 if (SemaRef
.getLangOpts().OpenMPOptimisticCollapse
||
9888 (LastIteration32
.isUsable() &&
9889 C
.getTypeSize(LastIteration32
.get()->getType()) == 32 &&
9890 (AllCountsNeedLessThan32Bits
|| NestedLoopCount
== 1 ||
9893 LastIteration32
.get()->getType()->hasSignedIntegerRepresentation(),
9894 LastIteration64
.get(), SemaRef
))))
9895 LastIteration
= LastIteration32
;
9896 QualType VType
= LastIteration
.get()->getType();
9897 QualType RealVType
= VType
;
9898 QualType StrideVType
= VType
;
9899 if (isOpenMPTaskLoopDirective(DKind
)) {
9901 SemaRef
.Context
.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
9903 SemaRef
.Context
.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
9906 if (!LastIteration
.isUsable())
9909 // Save the number of iterations.
9910 ExprResult NumIterations
= LastIteration
;
9912 LastIteration
= SemaRef
.BuildBinOp(
9913 CurScope
, LastIteration
.get()->getExprLoc(), BO_Sub
,
9914 LastIteration
.get(),
9915 SemaRef
.ActOnIntegerConstant(SourceLocation(), 1).get());
9916 if (!LastIteration
.isUsable())
9920 // Calculate the last iteration number beforehand instead of doing this on
9921 // each iteration. Do not do this if the number of iterations may be kfold-ed.
9922 bool IsConstant
= LastIteration
.get()->isIntegerConstantExpr(SemaRef
.Context
);
9923 ExprResult CalcLastIteration
;
9925 ExprResult SaveRef
=
9926 tryBuildCapture(SemaRef
, LastIteration
.get(), Captures
);
9927 LastIteration
= SaveRef
;
9929 // Prepare SaveRef + 1.
9930 NumIterations
= SemaRef
.BuildBinOp(
9931 CurScope
, SaveRef
.get()->getExprLoc(), BO_Add
, SaveRef
.get(),
9932 SemaRef
.ActOnIntegerConstant(SourceLocation(), 1).get());
9933 if (!NumIterations
.isUsable())
9937 SourceLocation InitLoc
= IterSpaces
[0].InitSrcRange
.getBegin();
9939 // Build variables passed into runtime, necessary for worksharing directives.
9940 ExprResult LB
, UB
, IL
, ST
, EUB
, CombLB
, CombUB
, PrevLB
, PrevUB
, CombEUB
;
9941 if (isOpenMPWorksharingDirective(DKind
) || isOpenMPTaskLoopDirective(DKind
) ||
9942 isOpenMPDistributeDirective(DKind
) ||
9943 isOpenMPGenericLoopDirective(DKind
) ||
9944 isOpenMPLoopTransformationDirective(DKind
)) {
9945 // Lower bound variable, initialized with zero.
9946 VarDecl
*LBDecl
= buildVarDecl(SemaRef
, InitLoc
, VType
, ".omp.lb");
9947 LB
= buildDeclRefExpr(SemaRef
, LBDecl
, VType
, InitLoc
);
9948 SemaRef
.AddInitializerToDecl(LBDecl
,
9949 SemaRef
.ActOnIntegerConstant(InitLoc
, 0).get(),
9950 /*DirectInit*/ false);
9952 // Upper bound variable, initialized with last iteration number.
9953 VarDecl
*UBDecl
= buildVarDecl(SemaRef
, InitLoc
, VType
, ".omp.ub");
9954 UB
= buildDeclRefExpr(SemaRef
, UBDecl
, VType
, InitLoc
);
9955 SemaRef
.AddInitializerToDecl(UBDecl
, LastIteration
.get(),
9956 /*DirectInit*/ false);
9958 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
9959 // This will be used to implement clause 'lastprivate'.
9960 QualType Int32Ty
= SemaRef
.Context
.getIntTypeForBitwidth(32, true);
9961 VarDecl
*ILDecl
= buildVarDecl(SemaRef
, InitLoc
, Int32Ty
, ".omp.is_last");
9962 IL
= buildDeclRefExpr(SemaRef
, ILDecl
, Int32Ty
, InitLoc
);
9963 SemaRef
.AddInitializerToDecl(ILDecl
,
9964 SemaRef
.ActOnIntegerConstant(InitLoc
, 0).get(),
9965 /*DirectInit*/ false);
9967 // Stride variable returned by runtime (we initialize it to 1 by default).
9969 buildVarDecl(SemaRef
, InitLoc
, StrideVType
, ".omp.stride");
9970 ST
= buildDeclRefExpr(SemaRef
, STDecl
, StrideVType
, InitLoc
);
9971 SemaRef
.AddInitializerToDecl(STDecl
,
9972 SemaRef
.ActOnIntegerConstant(InitLoc
, 1).get(),
9973 /*DirectInit*/ false);
9975 // Build expression: UB = min(UB, LastIteration)
9976 // It is necessary for CodeGen of directives with static scheduling.
9977 ExprResult IsUBGreater
= SemaRef
.BuildBinOp(CurScope
, InitLoc
, BO_GT
,
9978 UB
.get(), LastIteration
.get());
9979 ExprResult CondOp
= SemaRef
.ActOnConditionalOp(
9980 LastIteration
.get()->getExprLoc(), InitLoc
, IsUBGreater
.get(),
9981 LastIteration
.get(), UB
.get());
9982 EUB
= SemaRef
.BuildBinOp(CurScope
, InitLoc
, BO_Assign
, UB
.get(),
9984 EUB
= SemaRef
.ActOnFinishFullExpr(EUB
.get(), /*DiscardedValue*/ false);
9986 // If we have a combined directive that combines 'distribute', 'for' or
9987 // 'simd' we need to be able to access the bounds of the schedule of the
9988 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
9989 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
9990 if (isOpenMPLoopBoundSharingDirective(DKind
)) {
9991 // Lower bound variable, initialized with zero.
9992 VarDecl
*CombLBDecl
=
9993 buildVarDecl(SemaRef
, InitLoc
, VType
, ".omp.comb.lb");
9994 CombLB
= buildDeclRefExpr(SemaRef
, CombLBDecl
, VType
, InitLoc
);
9995 SemaRef
.AddInitializerToDecl(
9996 CombLBDecl
, SemaRef
.ActOnIntegerConstant(InitLoc
, 0).get(),
9997 /*DirectInit*/ false);
9999 // Upper bound variable, initialized with last iteration number.
10000 VarDecl
*CombUBDecl
=
10001 buildVarDecl(SemaRef
, InitLoc
, VType
, ".omp.comb.ub");
10002 CombUB
= buildDeclRefExpr(SemaRef
, CombUBDecl
, VType
, InitLoc
);
10003 SemaRef
.AddInitializerToDecl(CombUBDecl
, LastIteration
.get(),
10004 /*DirectInit*/ false);
10006 ExprResult CombIsUBGreater
= SemaRef
.BuildBinOp(
10007 CurScope
, InitLoc
, BO_GT
, CombUB
.get(), LastIteration
.get());
10008 ExprResult CombCondOp
=
10009 SemaRef
.ActOnConditionalOp(InitLoc
, InitLoc
, CombIsUBGreater
.get(),
10010 LastIteration
.get(), CombUB
.get());
10011 CombEUB
= SemaRef
.BuildBinOp(CurScope
, InitLoc
, BO_Assign
, CombUB
.get(),
10014 SemaRef
.ActOnFinishFullExpr(CombEUB
.get(), /*DiscardedValue*/ false);
10016 const CapturedDecl
*CD
= cast
<CapturedStmt
>(AStmt
)->getCapturedDecl();
10017 // We expect to have at least 2 more parameters than the 'parallel'
10018 // directive does - the lower and upper bounds of the previous schedule.
10019 assert(CD
->getNumParams() >= 4 &&
10020 "Unexpected number of parameters in loop combined directive");
10022 // Set the proper type for the bounds given what we learned from the
10024 ImplicitParamDecl
*PrevLBDecl
= CD
->getParam(/*PrevLB=*/2);
10025 ImplicitParamDecl
*PrevUBDecl
= CD
->getParam(/*PrevUB=*/3);
10027 // Previous lower and upper bounds are obtained from the region
10030 buildDeclRefExpr(SemaRef
, PrevLBDecl
, PrevLBDecl
->getType(), InitLoc
);
10032 buildDeclRefExpr(SemaRef
, PrevUBDecl
, PrevUBDecl
->getType(), InitLoc
);
10036 // Build the iteration variable and its initialization before loop.
10038 ExprResult Init
, CombInit
;
10040 VarDecl
*IVDecl
= buildVarDecl(SemaRef
, InitLoc
, RealVType
, ".omp.iv");
10041 IV
= buildDeclRefExpr(SemaRef
, IVDecl
, RealVType
, InitLoc
);
10042 Expr
*RHS
= (isOpenMPWorksharingDirective(DKind
) ||
10043 isOpenMPGenericLoopDirective(DKind
) ||
10044 isOpenMPTaskLoopDirective(DKind
) ||
10045 isOpenMPDistributeDirective(DKind
) ||
10046 isOpenMPLoopTransformationDirective(DKind
))
10048 : SemaRef
.ActOnIntegerConstant(SourceLocation(), 0).get();
10049 Init
= SemaRef
.BuildBinOp(CurScope
, InitLoc
, BO_Assign
, IV
.get(), RHS
);
10050 Init
= SemaRef
.ActOnFinishFullExpr(Init
.get(), /*DiscardedValue*/ false);
10052 if (isOpenMPLoopBoundSharingDirective(DKind
)) {
10054 (isOpenMPWorksharingDirective(DKind
) ||
10055 isOpenMPGenericLoopDirective(DKind
) ||
10056 isOpenMPTaskLoopDirective(DKind
) ||
10057 isOpenMPDistributeDirective(DKind
))
10059 : SemaRef
.ActOnIntegerConstant(SourceLocation(), 0).get();
10061 SemaRef
.BuildBinOp(CurScope
, InitLoc
, BO_Assign
, IV
.get(), CombRHS
);
10063 SemaRef
.ActOnFinishFullExpr(CombInit
.get(), /*DiscardedValue*/ false);
10067 bool UseStrictCompare
=
10068 RealVType
->hasUnsignedIntegerRepresentation() &&
10069 llvm::all_of(IterSpaces
, [](const LoopIterationSpace
&LIS
) {
10070 return LIS
.IsStrictCompare
;
10072 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
10073 // unsigned IV)) for worksharing loops.
10074 SourceLocation CondLoc
= AStmt
->getBeginLoc();
10075 Expr
*BoundUB
= UB
.get();
10076 if (UseStrictCompare
) {
10079 .BuildBinOp(CurScope
, CondLoc
, BO_Add
, BoundUB
,
10080 SemaRef
.ActOnIntegerConstant(SourceLocation(), 1).get())
10083 SemaRef
.ActOnFinishFullExpr(BoundUB
, /*DiscardedValue*/ false).get();
10086 (isOpenMPWorksharingDirective(DKind
) ||
10087 isOpenMPGenericLoopDirective(DKind
) ||
10088 isOpenMPTaskLoopDirective(DKind
) || isOpenMPDistributeDirective(DKind
) ||
10089 isOpenMPLoopTransformationDirective(DKind
))
10090 ? SemaRef
.BuildBinOp(CurScope
, CondLoc
,
10091 UseStrictCompare
? BO_LT
: BO_LE
, IV
.get(),
10093 : SemaRef
.BuildBinOp(CurScope
, CondLoc
, BO_LT
, IV
.get(),
10094 NumIterations
.get());
10095 ExprResult CombDistCond
;
10096 if (isOpenMPLoopBoundSharingDirective(DKind
)) {
10097 CombDistCond
= SemaRef
.BuildBinOp(CurScope
, CondLoc
, BO_LT
, IV
.get(),
10098 NumIterations
.get());
10101 ExprResult CombCond
;
10102 if (isOpenMPLoopBoundSharingDirective(DKind
)) {
10103 Expr
*BoundCombUB
= CombUB
.get();
10104 if (UseStrictCompare
) {
10108 CurScope
, CondLoc
, BO_Add
, BoundCombUB
,
10109 SemaRef
.ActOnIntegerConstant(SourceLocation(), 1).get())
10112 SemaRef
.ActOnFinishFullExpr(BoundCombUB
, /*DiscardedValue*/ false)
10116 SemaRef
.BuildBinOp(CurScope
, CondLoc
, UseStrictCompare
? BO_LT
: BO_LE
,
10117 IV
.get(), BoundCombUB
);
10119 // Loop increment (IV = IV + 1)
10120 SourceLocation IncLoc
= AStmt
->getBeginLoc();
10122 SemaRef
.BuildBinOp(CurScope
, IncLoc
, BO_Add
, IV
.get(),
10123 SemaRef
.ActOnIntegerConstant(IncLoc
, 1).get());
10124 if (!Inc
.isUsable())
10126 Inc
= SemaRef
.BuildBinOp(CurScope
, IncLoc
, BO_Assign
, IV
.get(), Inc
.get());
10127 Inc
= SemaRef
.ActOnFinishFullExpr(Inc
.get(), /*DiscardedValue*/ false);
10128 if (!Inc
.isUsable())
10131 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
10132 // Used for directives with static scheduling.
10133 // In combined construct, add combined version that use CombLB and CombUB
10134 // base variables for the update
10135 ExprResult NextLB
, NextUB
, CombNextLB
, CombNextUB
;
10136 if (isOpenMPWorksharingDirective(DKind
) || isOpenMPTaskLoopDirective(DKind
) ||
10137 isOpenMPGenericLoopDirective(DKind
) ||
10138 isOpenMPDistributeDirective(DKind
) ||
10139 isOpenMPLoopTransformationDirective(DKind
)) {
10141 NextLB
= SemaRef
.BuildBinOp(CurScope
, IncLoc
, BO_Add
, LB
.get(), ST
.get());
10142 if (!NextLB
.isUsable())
10146 SemaRef
.BuildBinOp(CurScope
, IncLoc
, BO_Assign
, LB
.get(), NextLB
.get());
10148 SemaRef
.ActOnFinishFullExpr(NextLB
.get(), /*DiscardedValue*/ false);
10149 if (!NextLB
.isUsable())
10152 NextUB
= SemaRef
.BuildBinOp(CurScope
, IncLoc
, BO_Add
, UB
.get(), ST
.get());
10153 if (!NextUB
.isUsable())
10157 SemaRef
.BuildBinOp(CurScope
, IncLoc
, BO_Assign
, UB
.get(), NextUB
.get());
10159 SemaRef
.ActOnFinishFullExpr(NextUB
.get(), /*DiscardedValue*/ false);
10160 if (!NextUB
.isUsable())
10162 if (isOpenMPLoopBoundSharingDirective(DKind
)) {
10164 SemaRef
.BuildBinOp(CurScope
, IncLoc
, BO_Add
, CombLB
.get(), ST
.get());
10165 if (!NextLB
.isUsable())
10168 CombNextLB
= SemaRef
.BuildBinOp(CurScope
, IncLoc
, BO_Assign
, CombLB
.get(),
10170 CombNextLB
= SemaRef
.ActOnFinishFullExpr(CombNextLB
.get(),
10171 /*DiscardedValue*/ false);
10172 if (!CombNextLB
.isUsable())
10176 SemaRef
.BuildBinOp(CurScope
, IncLoc
, BO_Add
, CombUB
.get(), ST
.get());
10177 if (!CombNextUB
.isUsable())
10180 CombNextUB
= SemaRef
.BuildBinOp(CurScope
, IncLoc
, BO_Assign
, CombUB
.get(),
10182 CombNextUB
= SemaRef
.ActOnFinishFullExpr(CombNextUB
.get(),
10183 /*DiscardedValue*/ false);
10184 if (!CombNextUB
.isUsable())
10189 // Create increment expression for distribute loop when combined in a same
10190 // directive with for as IV = IV + ST; ensure upper bound expression based
10191 // on PrevUB instead of NumIterations - used to implement 'for' when found
10192 // in combination with 'distribute', like in 'distribute parallel for'
10193 SourceLocation DistIncLoc
= AStmt
->getBeginLoc();
10194 ExprResult DistCond
, DistInc
, PrevEUB
, ParForInDistCond
;
10195 if (isOpenMPLoopBoundSharingDirective(DKind
)) {
10196 DistCond
= SemaRef
.BuildBinOp(
10197 CurScope
, CondLoc
, UseStrictCompare
? BO_LT
: BO_LE
, IV
.get(), BoundUB
);
10198 assert(DistCond
.isUsable() && "distribute cond expr was not built");
10201 SemaRef
.BuildBinOp(CurScope
, DistIncLoc
, BO_Add
, IV
.get(), ST
.get());
10202 assert(DistInc
.isUsable() && "distribute inc expr was not built");
10203 DistInc
= SemaRef
.BuildBinOp(CurScope
, DistIncLoc
, BO_Assign
, IV
.get(),
10206 SemaRef
.ActOnFinishFullExpr(DistInc
.get(), /*DiscardedValue*/ false);
10207 assert(DistInc
.isUsable() && "distribute inc expr was not built");
10209 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10211 ExprResult NewPrevUB
= PrevUB
;
10212 SourceLocation DistEUBLoc
= AStmt
->getBeginLoc();
10213 if (!SemaRef
.Context
.hasSameType(UB
.get()->getType(),
10214 PrevUB
.get()->getType())) {
10215 NewPrevUB
= SemaRef
.BuildCStyleCastExpr(
10217 SemaRef
.Context
.getTrivialTypeSourceInfo(UB
.get()->getType()),
10218 DistEUBLoc
, NewPrevUB
.get());
10219 if (!NewPrevUB
.isUsable())
10222 ExprResult IsUBGreater
= SemaRef
.BuildBinOp(CurScope
, DistEUBLoc
, BO_GT
,
10223 UB
.get(), NewPrevUB
.get());
10224 ExprResult CondOp
= SemaRef
.ActOnConditionalOp(
10225 DistEUBLoc
, DistEUBLoc
, IsUBGreater
.get(), NewPrevUB
.get(), UB
.get());
10226 PrevEUB
= SemaRef
.BuildBinOp(CurScope
, DistIncLoc
, BO_Assign
, UB
.get(),
10229 SemaRef
.ActOnFinishFullExpr(PrevEUB
.get(), /*DiscardedValue*/ false);
10231 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10232 // parallel for is in combination with a distribute directive with
10233 // schedule(static, 1)
10234 Expr
*BoundPrevUB
= PrevUB
.get();
10235 if (UseStrictCompare
) {
10239 CurScope
, CondLoc
, BO_Add
, BoundPrevUB
,
10240 SemaRef
.ActOnIntegerConstant(SourceLocation(), 1).get())
10243 SemaRef
.ActOnFinishFullExpr(BoundPrevUB
, /*DiscardedValue*/ false)
10247 SemaRef
.BuildBinOp(CurScope
, CondLoc
, UseStrictCompare
? BO_LT
: BO_LE
,
10248 IV
.get(), BoundPrevUB
);
10251 // Build updates and final values of the loop counters.
10252 bool HasErrors
= false;
10253 Built
.Counters
.resize(NestedLoopCount
);
10254 Built
.Inits
.resize(NestedLoopCount
);
10255 Built
.Updates
.resize(NestedLoopCount
);
10256 Built
.Finals
.resize(NestedLoopCount
);
10257 Built
.DependentCounters
.resize(NestedLoopCount
);
10258 Built
.DependentInits
.resize(NestedLoopCount
);
10259 Built
.FinalsConditions
.resize(NestedLoopCount
);
10261 // We implement the following algorithm for obtaining the
10262 // original loop iteration variable values based on the
10263 // value of the collapsed loop iteration variable IV.
10265 // Let n+1 be the number of collapsed loops in the nest.
10266 // Iteration variables (I0, I1, .... In)
10267 // Iteration counts (N0, N1, ... Nn)
10271 // To compute Ik for loop k, 0 <= k <= n, generate:
10272 // Prod = N(k+1) * N(k+2) * ... * Nn;
10273 // Ik = Acc / Prod;
10274 // Acc -= Ik * Prod;
10276 ExprResult Acc
= IV
;
10277 for (unsigned int Cnt
= 0; Cnt
< NestedLoopCount
; ++Cnt
) {
10278 LoopIterationSpace
&IS
= IterSpaces
[Cnt
];
10279 SourceLocation UpdLoc
= IS
.IncSrcRange
.getBegin();
10283 ExprResult Prod
= SemaRef
.ActOnIntegerConstant(SourceLocation(), 1).get();
10284 for (unsigned int K
= Cnt
+ 1; K
< NestedLoopCount
; ++K
)
10285 Prod
= SemaRef
.BuildBinOp(CurScope
, UpdLoc
, BO_Mul
, Prod
.get(),
10286 IterSpaces
[K
].NumIterations
);
10288 // Iter = Acc / Prod
10289 // If there is at least one more inner loop to avoid
10290 // multiplication by 1.
10291 if (Cnt
+ 1 < NestedLoopCount
)
10293 SemaRef
.BuildBinOp(CurScope
, UpdLoc
, BO_Div
, Acc
.get(), Prod
.get());
10296 if (!Iter
.isUsable()) {
10302 // Acc -= Iter * Prod
10303 // Check if there is at least one more inner loop to avoid
10304 // multiplication by 1.
10305 if (Cnt
+ 1 < NestedLoopCount
)
10306 Prod
= SemaRef
.BuildBinOp(CurScope
, UpdLoc
, BO_Mul
, Iter
.get(),
10310 Acc
= SemaRef
.BuildBinOp(CurScope
, UpdLoc
, BO_Sub
, Acc
.get(), Prod
.get());
10312 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10313 auto *VD
= cast
<VarDecl
>(cast
<DeclRefExpr
>(IS
.CounterVar
)->getDecl());
10314 DeclRefExpr
*CounterVar
= buildDeclRefExpr(
10315 SemaRef
, VD
, IS
.CounterVar
->getType(), IS
.CounterVar
->getExprLoc(),
10316 /*RefersToCapture=*/true);
10318 buildCounterInit(SemaRef
, CurScope
, UpdLoc
, CounterVar
,
10319 IS
.CounterInit
, IS
.IsNonRectangularLB
, Captures
);
10320 if (!Init
.isUsable()) {
10324 ExprResult Update
= buildCounterUpdate(
10325 SemaRef
, CurScope
, UpdLoc
, CounterVar
, IS
.CounterInit
, Iter
,
10326 IS
.CounterStep
, IS
.Subtract
, IS
.IsNonRectangularLB
, &Captures
);
10327 if (!Update
.isUsable()) {
10332 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10334 buildCounterUpdate(SemaRef
, CurScope
, UpdLoc
, CounterVar
,
10335 IS
.CounterInit
, IS
.NumIterations
, IS
.CounterStep
,
10336 IS
.Subtract
, IS
.IsNonRectangularLB
, &Captures
);
10337 if (!Final
.isUsable()) {
10342 if (!Update
.isUsable() || !Final
.isUsable()) {
10347 Built
.Counters
[Cnt
] = IS
.CounterVar
;
10348 Built
.PrivateCounters
[Cnt
] = IS
.PrivateCounterVar
;
10349 Built
.Inits
[Cnt
] = Init
.get();
10350 Built
.Updates
[Cnt
] = Update
.get();
10351 Built
.Finals
[Cnt
] = Final
.get();
10352 Built
.DependentCounters
[Cnt
] = nullptr;
10353 Built
.DependentInits
[Cnt
] = nullptr;
10354 Built
.FinalsConditions
[Cnt
] = nullptr;
10355 if (IS
.IsNonRectangularLB
|| IS
.IsNonRectangularUB
) {
10356 Built
.DependentCounters
[Cnt
] = Built
.Counters
[IS
.LoopDependentIdx
- 1];
10357 Built
.DependentInits
[Cnt
] = Built
.Inits
[IS
.LoopDependentIdx
- 1];
10358 Built
.FinalsConditions
[Cnt
] = IS
.FinalCondition
;
10367 Built
.IterationVarRef
= IV
.get();
10368 Built
.LastIteration
= LastIteration
.get();
10369 Built
.NumIterations
= NumIterations
.get();
10370 Built
.CalcLastIteration
= SemaRef
10371 .ActOnFinishFullExpr(CalcLastIteration
.get(),
10372 /*DiscardedValue=*/false)
10374 Built
.PreCond
= PreCond
.get();
10375 Built
.PreInits
= buildPreInits(C
, Captures
);
10376 Built
.Cond
= Cond
.get();
10377 Built
.Init
= Init
.get();
10378 Built
.Inc
= Inc
.get();
10379 Built
.LB
= LB
.get();
10380 Built
.UB
= UB
.get();
10381 Built
.IL
= IL
.get();
10382 Built
.ST
= ST
.get();
10383 Built
.EUB
= EUB
.get();
10384 Built
.NLB
= NextLB
.get();
10385 Built
.NUB
= NextUB
.get();
10386 Built
.PrevLB
= PrevLB
.get();
10387 Built
.PrevUB
= PrevUB
.get();
10388 Built
.DistInc
= DistInc
.get();
10389 Built
.PrevEUB
= PrevEUB
.get();
10390 Built
.DistCombinedFields
.LB
= CombLB
.get();
10391 Built
.DistCombinedFields
.UB
= CombUB
.get();
10392 Built
.DistCombinedFields
.EUB
= CombEUB
.get();
10393 Built
.DistCombinedFields
.Init
= CombInit
.get();
10394 Built
.DistCombinedFields
.Cond
= CombCond
.get();
10395 Built
.DistCombinedFields
.NLB
= CombNextLB
.get();
10396 Built
.DistCombinedFields
.NUB
= CombNextUB
.get();
10397 Built
.DistCombinedFields
.DistCond
= CombDistCond
.get();
10398 Built
.DistCombinedFields
.ParForInDistCond
= ParForInDistCond
.get();
10400 return NestedLoopCount
;
10403 static Expr
*getCollapseNumberExpr(ArrayRef
<OMPClause
*> Clauses
) {
10404 auto CollapseClauses
=
10405 OMPExecutableDirective::getClausesOfKind
<OMPCollapseClause
>(Clauses
);
10406 if (CollapseClauses
.begin() != CollapseClauses
.end())
10407 return (*CollapseClauses
.begin())->getNumForLoops();
10411 static Expr
*getOrderedNumberExpr(ArrayRef
<OMPClause
*> Clauses
) {
10412 auto OrderedClauses
=
10413 OMPExecutableDirective::getClausesOfKind
<OMPOrderedClause
>(Clauses
);
10414 if (OrderedClauses
.begin() != OrderedClauses
.end())
10415 return (*OrderedClauses
.begin())->getNumForLoops();
10419 static bool checkSimdlenSafelenSpecified(Sema
&S
,
10420 const ArrayRef
<OMPClause
*> Clauses
) {
10421 const OMPSafelenClause
*Safelen
= nullptr;
10422 const OMPSimdlenClause
*Simdlen
= nullptr;
10424 for (const OMPClause
*Clause
: Clauses
) {
10425 if (Clause
->getClauseKind() == OMPC_safelen
)
10426 Safelen
= cast
<OMPSafelenClause
>(Clause
);
10427 else if (Clause
->getClauseKind() == OMPC_simdlen
)
10428 Simdlen
= cast
<OMPSimdlenClause
>(Clause
);
10429 if (Safelen
&& Simdlen
)
10433 if (Simdlen
&& Safelen
) {
10434 const Expr
*SimdlenLength
= Simdlen
->getSimdlen();
10435 const Expr
*SafelenLength
= Safelen
->getSafelen();
10436 if (SimdlenLength
->isValueDependent() || SimdlenLength
->isTypeDependent() ||
10437 SimdlenLength
->isInstantiationDependent() ||
10438 SimdlenLength
->containsUnexpandedParameterPack())
10440 if (SafelenLength
->isValueDependent() || SafelenLength
->isTypeDependent() ||
10441 SafelenLength
->isInstantiationDependent() ||
10442 SafelenLength
->containsUnexpandedParameterPack())
10444 Expr::EvalResult SimdlenResult
, SafelenResult
;
10445 SimdlenLength
->EvaluateAsInt(SimdlenResult
, S
.Context
);
10446 SafelenLength
->EvaluateAsInt(SafelenResult
, S
.Context
);
10447 llvm::APSInt SimdlenRes
= SimdlenResult
.Val
.getInt();
10448 llvm::APSInt SafelenRes
= SafelenResult
.Val
.getInt();
10449 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10450 // If both simdlen and safelen clauses are specified, the value of the
10451 // simdlen parameter must be less than or equal to the value of the safelen
10453 if (SimdlenRes
> SafelenRes
) {
10454 S
.Diag(SimdlenLength
->getExprLoc(),
10455 diag::err_omp_wrong_simdlen_safelen_values
)
10456 << SimdlenLength
->getSourceRange() << SafelenLength
->getSourceRange();
10463 static bool checkGenericLoopLastprivate(Sema
&S
, ArrayRef
<OMPClause
*> Clauses
,
10464 OpenMPDirectiveKind K
,
10465 DSAStackTy
*Stack
);
10467 bool Sema::checkLastPrivateForMappedDirectives(ArrayRef
<OMPClause
*> Clauses
) {
10469 // Check for syntax of lastprivate
10470 // Param of the lastprivate have different meanings in the mapped directives
10471 // e.g. "omp loop" Only loop iteration vars are allowed in lastprivate clause
10472 // "omp for" lastprivate vars must be shared
10473 if (getLangOpts().OpenMP
>= 50 &&
10474 DSAStack
->getMappedDirective() == OMPD_loop
&&
10475 checkGenericLoopLastprivate(*this, Clauses
, OMPD_loop
, DSAStack
)) {
10482 Sema::ActOnOpenMPSimdDirective(ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
,
10483 SourceLocation StartLoc
, SourceLocation EndLoc
,
10484 VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
10486 return StmtError();
10488 if (!checkLastPrivateForMappedDirectives(Clauses
))
10489 return StmtError();
10491 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
10492 OMPLoopBasedDirective::HelperExprs B
;
10493 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10494 // define the nested loops number.
10495 unsigned NestedLoopCount
= checkOpenMPLoop(
10496 OMPD_simd
, getCollapseNumberExpr(Clauses
), getOrderedNumberExpr(Clauses
),
10497 AStmt
, *this, *DSAStack
, VarsWithImplicitDSA
, B
);
10498 if (NestedLoopCount
== 0)
10499 return StmtError();
10501 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
10502 "omp simd loop exprs were not built");
10504 if (!CurContext
->isDependentContext()) {
10505 // Finalize the clauses that need pre-built expressions for CodeGen.
10506 for (OMPClause
*C
: Clauses
) {
10507 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
10508 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
10509 B
.NumIterations
, *this, CurScope
,
10511 return StmtError();
10515 if (checkSimdlenSafelenSpecified(*this, Clauses
))
10516 return StmtError();
10518 setFunctionHasBranchProtectedScope();
10519 auto *SimdDirective
= OMPSimdDirective::Create(
10520 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
,
10521 DSAStack
->getMappedDirective());
10522 return SimdDirective
;
10526 Sema::ActOnOpenMPForDirective(ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
,
10527 SourceLocation StartLoc
, SourceLocation EndLoc
,
10528 VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
10530 return StmtError();
10532 if (!checkLastPrivateForMappedDirectives(Clauses
))
10533 return StmtError();
10535 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
10536 OMPLoopBasedDirective::HelperExprs B
;
10537 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10538 // define the nested loops number.
10539 unsigned NestedLoopCount
= checkOpenMPLoop(
10540 OMPD_for
, getCollapseNumberExpr(Clauses
), getOrderedNumberExpr(Clauses
),
10541 AStmt
, *this, *DSAStack
, VarsWithImplicitDSA
, B
);
10542 if (NestedLoopCount
== 0)
10543 return StmtError();
10545 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
10546 "omp for loop exprs were not built");
10548 if (!CurContext
->isDependentContext()) {
10549 // Finalize the clauses that need pre-built expressions for CodeGen.
10550 for (OMPClause
*C
: Clauses
) {
10551 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
10552 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
10553 B
.NumIterations
, *this, CurScope
,
10555 return StmtError();
10559 auto *ForDirective
= OMPForDirective::Create(
10560 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
,
10561 DSAStack
->getTaskgroupReductionRef(), DSAStack
->isCancelRegion(),
10562 DSAStack
->getMappedDirective());
10563 return ForDirective
;
10566 StmtResult
Sema::ActOnOpenMPForSimdDirective(
10567 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
10568 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
10570 return StmtError();
10572 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
10573 OMPLoopBasedDirective::HelperExprs B
;
10574 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10575 // define the nested loops number.
10576 unsigned NestedLoopCount
=
10577 checkOpenMPLoop(OMPD_for_simd
, getCollapseNumberExpr(Clauses
),
10578 getOrderedNumberExpr(Clauses
), AStmt
, *this, *DSAStack
,
10579 VarsWithImplicitDSA
, B
);
10580 if (NestedLoopCount
== 0)
10581 return StmtError();
10583 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
10584 "omp for simd loop exprs were not built");
10586 if (!CurContext
->isDependentContext()) {
10587 // Finalize the clauses that need pre-built expressions for CodeGen.
10588 for (OMPClause
*C
: Clauses
) {
10589 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
10590 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
10591 B
.NumIterations
, *this, CurScope
,
10593 return StmtError();
10597 if (checkSimdlenSafelenSpecified(*this, Clauses
))
10598 return StmtError();
10600 setFunctionHasBranchProtectedScope();
10601 return OMPForSimdDirective::Create(Context
, StartLoc
, EndLoc
, NestedLoopCount
,
10602 Clauses
, AStmt
, B
);
10605 StmtResult
Sema::ActOnOpenMPSectionsDirective(ArrayRef
<OMPClause
*> Clauses
,
10607 SourceLocation StartLoc
,
10608 SourceLocation EndLoc
) {
10610 return StmtError();
10612 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
10613 auto BaseStmt
= AStmt
;
10614 while (auto *CS
= dyn_cast_or_null
<CapturedStmt
>(BaseStmt
))
10615 BaseStmt
= CS
->getCapturedStmt();
10616 if (auto *C
= dyn_cast_or_null
<CompoundStmt
>(BaseStmt
)) {
10617 auto S
= C
->children();
10618 if (S
.begin() == S
.end())
10619 return StmtError();
10620 // All associated statements must be '#pragma omp section' except for
10622 for (Stmt
*SectionStmt
: llvm::drop_begin(S
)) {
10623 if (!SectionStmt
|| !isa
<OMPSectionDirective
>(SectionStmt
)) {
10625 Diag(SectionStmt
->getBeginLoc(),
10626 diag::err_omp_sections_substmt_not_section
);
10627 return StmtError();
10629 cast
<OMPSectionDirective
>(SectionStmt
)
10630 ->setHasCancel(DSAStack
->isCancelRegion());
10633 Diag(AStmt
->getBeginLoc(), diag::err_omp_sections_not_compound_stmt
);
10634 return StmtError();
10637 setFunctionHasBranchProtectedScope();
10639 return OMPSectionsDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
10640 DSAStack
->getTaskgroupReductionRef(),
10641 DSAStack
->isCancelRegion());
10644 StmtResult
Sema::ActOnOpenMPSectionDirective(Stmt
*AStmt
,
10645 SourceLocation StartLoc
,
10646 SourceLocation EndLoc
) {
10648 return StmtError();
10650 setFunctionHasBranchProtectedScope();
10651 DSAStack
->setParentCancelRegion(DSAStack
->isCancelRegion());
10653 return OMPSectionDirective::Create(Context
, StartLoc
, EndLoc
, AStmt
,
10654 DSAStack
->isCancelRegion());
10657 static Expr
*getDirectCallExpr(Expr
*E
) {
10658 E
= E
->IgnoreParenCasts()->IgnoreImplicit();
10659 if (auto *CE
= dyn_cast
<CallExpr
>(E
))
10660 if (CE
->getDirectCallee())
10665 StmtResult
Sema::ActOnOpenMPDispatchDirective(ArrayRef
<OMPClause
*> Clauses
,
10667 SourceLocation StartLoc
,
10668 SourceLocation EndLoc
) {
10670 return StmtError();
10672 Stmt
*S
= cast
<CapturedStmt
>(AStmt
)->getCapturedStmt();
10675 // expression-stmt : an expression statement with one of the following forms:
10676 // expression = target-call ( [expression-list] );
10677 // target-call ( [expression-list] );
10679 SourceLocation TargetCallLoc
;
10681 if (!CurContext
->isDependentContext()) {
10682 Expr
*TargetCall
= nullptr;
10684 auto *E
= dyn_cast
<Expr
>(S
);
10686 Diag(S
->getBeginLoc(), diag::err_omp_dispatch_statement_call
);
10687 return StmtError();
10690 E
= E
->IgnoreParenCasts()->IgnoreImplicit();
10692 if (auto *BO
= dyn_cast
<BinaryOperator
>(E
)) {
10693 if (BO
->getOpcode() == BO_Assign
)
10694 TargetCall
= getDirectCallExpr(BO
->getRHS());
10696 if (auto *COCE
= dyn_cast
<CXXOperatorCallExpr
>(E
))
10697 if (COCE
->getOperator() == OO_Equal
)
10698 TargetCall
= getDirectCallExpr(COCE
->getArg(1));
10700 TargetCall
= getDirectCallExpr(E
);
10703 Diag(E
->getBeginLoc(), diag::err_omp_dispatch_statement_call
);
10704 return StmtError();
10706 TargetCallLoc
= TargetCall
->getExprLoc();
10709 setFunctionHasBranchProtectedScope();
10711 return OMPDispatchDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
10715 static bool checkGenericLoopLastprivate(Sema
&S
, ArrayRef
<OMPClause
*> Clauses
,
10716 OpenMPDirectiveKind K
,
10717 DSAStackTy
*Stack
) {
10718 bool ErrorFound
= false;
10719 for (OMPClause
*C
: Clauses
) {
10720 if (auto *LPC
= dyn_cast
<OMPLastprivateClause
>(C
)) {
10721 for (Expr
*RefExpr
: LPC
->varlists()) {
10722 SourceLocation ELoc
;
10723 SourceRange ERange
;
10724 Expr
*SimpleRefExpr
= RefExpr
;
10725 auto Res
= getPrivateItem(S
, SimpleRefExpr
, ELoc
, ERange
);
10726 if (ValueDecl
*D
= Res
.first
) {
10727 auto &&Info
= Stack
->isLoopControlVariable(D
);
10729 S
.Diag(ELoc
, diag::err_omp_lastprivate_loop_var_non_loop_iteration
)
10730 << getOpenMPDirectiveName(K
);
10740 StmtResult
Sema::ActOnOpenMPGenericLoopDirective(
10741 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
10742 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
10744 return StmtError();
10746 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10747 // A list item may not appear in a lastprivate clause unless it is the
10748 // loop iteration variable of a loop that is associated with the construct.
10749 if (checkGenericLoopLastprivate(*this, Clauses
, OMPD_loop
, DSAStack
))
10750 return StmtError();
10752 auto *CS
= cast
<CapturedStmt
>(AStmt
);
10753 // 1.2.2 OpenMP Language Terminology
10754 // Structured block - An executable statement with a single entry at the
10755 // top and a single exit at the bottom.
10756 // The point of exit cannot be a branch out of the structured block.
10757 // longjmp() and throw() must not violate the entry/exit criteria.
10758 CS
->getCapturedDecl()->setNothrow();
10760 OMPLoopDirective::HelperExprs B
;
10761 // In presence of clause 'collapse', it will define the nested loops number.
10762 unsigned NestedLoopCount
= checkOpenMPLoop(
10763 OMPD_loop
, getCollapseNumberExpr(Clauses
), getOrderedNumberExpr(Clauses
),
10764 AStmt
, *this, *DSAStack
, VarsWithImplicitDSA
, B
);
10765 if (NestedLoopCount
== 0)
10766 return StmtError();
10768 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
10769 "omp loop exprs were not built");
10771 setFunctionHasBranchProtectedScope();
10772 return OMPGenericLoopDirective::Create(Context
, StartLoc
, EndLoc
,
10773 NestedLoopCount
, Clauses
, AStmt
, B
);
10776 StmtResult
Sema::ActOnOpenMPTeamsGenericLoopDirective(
10777 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
10778 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
10780 return StmtError();
10782 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10783 // A list item may not appear in a lastprivate clause unless it is the
10784 // loop iteration variable of a loop that is associated with the construct.
10785 if (checkGenericLoopLastprivate(*this, Clauses
, OMPD_teams_loop
, DSAStack
))
10786 return StmtError();
10788 auto *CS
= cast
<CapturedStmt
>(AStmt
);
10789 // 1.2.2 OpenMP Language Terminology
10790 // Structured block - An executable statement with a single entry at the
10791 // top and a single exit at the bottom.
10792 // The point of exit cannot be a branch out of the structured block.
10793 // longjmp() and throw() must not violate the entry/exit criteria.
10794 CS
->getCapturedDecl()->setNothrow();
10795 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_teams_loop
);
10796 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
10797 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
10798 // 1.2.2 OpenMP Language Terminology
10799 // Structured block - An executable statement with a single entry at the
10800 // top and a single exit at the bottom.
10801 // The point of exit cannot be a branch out of the structured block.
10802 // longjmp() and throw() must not violate the entry/exit criteria.
10803 CS
->getCapturedDecl()->setNothrow();
10806 OMPLoopDirective::HelperExprs B
;
10807 // In presence of clause 'collapse', it will define the nested loops number.
10808 unsigned NestedLoopCount
=
10809 checkOpenMPLoop(OMPD_teams_loop
, getCollapseNumberExpr(Clauses
),
10810 /*OrderedLoopCountExpr=*/nullptr, CS
, *this, *DSAStack
,
10811 VarsWithImplicitDSA
, B
);
10812 if (NestedLoopCount
== 0)
10813 return StmtError();
10815 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
10816 "omp loop exprs were not built");
10818 setFunctionHasBranchProtectedScope();
10819 DSAStack
->setParentTeamsRegionLoc(StartLoc
);
10821 return OMPTeamsGenericLoopDirective::Create(
10822 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
10825 StmtResult
Sema::ActOnOpenMPTargetTeamsGenericLoopDirective(
10826 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
10827 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
10829 return StmtError();
10831 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10832 // A list item may not appear in a lastprivate clause unless it is the
10833 // loop iteration variable of a loop that is associated with the construct.
10834 if (checkGenericLoopLastprivate(*this, Clauses
, OMPD_target_teams_loop
,
10836 return StmtError();
10838 auto *CS
= cast
<CapturedStmt
>(AStmt
);
10839 // 1.2.2 OpenMP Language Terminology
10840 // Structured block - An executable statement with a single entry at the
10841 // top and a single exit at the bottom.
10842 // The point of exit cannot be a branch out of the structured block.
10843 // longjmp() and throw() must not violate the entry/exit criteria.
10844 CS
->getCapturedDecl()->setNothrow();
10845 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_teams_loop
);
10846 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
10847 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
10848 // 1.2.2 OpenMP Language Terminology
10849 // Structured block - An executable statement with a single entry at the
10850 // top and a single exit at the bottom.
10851 // The point of exit cannot be a branch out of the structured block.
10852 // longjmp() and throw() must not violate the entry/exit criteria.
10853 CS
->getCapturedDecl()->setNothrow();
10856 OMPLoopDirective::HelperExprs B
;
10857 // In presence of clause 'collapse', it will define the nested loops number.
10858 unsigned NestedLoopCount
=
10859 checkOpenMPLoop(OMPD_target_teams_loop
, getCollapseNumberExpr(Clauses
),
10860 /*OrderedLoopCountExpr=*/nullptr, CS
, *this, *DSAStack
,
10861 VarsWithImplicitDSA
, B
);
10862 if (NestedLoopCount
== 0)
10863 return StmtError();
10865 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
10866 "omp loop exprs were not built");
10868 setFunctionHasBranchProtectedScope();
10870 return OMPTargetTeamsGenericLoopDirective::Create(
10871 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
10874 StmtResult
Sema::ActOnOpenMPParallelGenericLoopDirective(
10875 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
10876 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
10878 return StmtError();
10880 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10881 // A list item may not appear in a lastprivate clause unless it is the
10882 // loop iteration variable of a loop that is associated with the construct.
10883 if (checkGenericLoopLastprivate(*this, Clauses
, OMPD_parallel_loop
, DSAStack
))
10884 return StmtError();
10886 auto *CS
= cast
<CapturedStmt
>(AStmt
);
10887 // 1.2.2 OpenMP Language Terminology
10888 // Structured block - An executable statement with a single entry at the
10889 // top and a single exit at the bottom.
10890 // The point of exit cannot be a branch out of the structured block.
10891 // longjmp() and throw() must not violate the entry/exit criteria.
10892 CS
->getCapturedDecl()->setNothrow();
10893 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_parallel_loop
);
10894 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
10895 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
10896 // 1.2.2 OpenMP Language Terminology
10897 // Structured block - An executable statement with a single entry at the
10898 // top and a single exit at the bottom.
10899 // The point of exit cannot be a branch out of the structured block.
10900 // longjmp() and throw() must not violate the entry/exit criteria.
10901 CS
->getCapturedDecl()->setNothrow();
10904 OMPLoopDirective::HelperExprs B
;
10905 // In presence of clause 'collapse', it will define the nested loops number.
10906 unsigned NestedLoopCount
=
10907 checkOpenMPLoop(OMPD_parallel_loop
, getCollapseNumberExpr(Clauses
),
10908 /*OrderedLoopCountExpr=*/nullptr, CS
, *this, *DSAStack
,
10909 VarsWithImplicitDSA
, B
);
10910 if (NestedLoopCount
== 0)
10911 return StmtError();
10913 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
10914 "omp loop exprs were not built");
10916 setFunctionHasBranchProtectedScope();
10918 return OMPParallelGenericLoopDirective::Create(
10919 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
10922 StmtResult
Sema::ActOnOpenMPTargetParallelGenericLoopDirective(
10923 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
10924 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
10926 return StmtError();
10928 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10929 // A list item may not appear in a lastprivate clause unless it is the
10930 // loop iteration variable of a loop that is associated with the construct.
10931 if (checkGenericLoopLastprivate(*this, Clauses
, OMPD_target_parallel_loop
,
10933 return StmtError();
10935 auto *CS
= cast
<CapturedStmt
>(AStmt
);
10936 // 1.2.2 OpenMP Language Terminology
10937 // Structured block - An executable statement with a single entry at the
10938 // top and a single exit at the bottom.
10939 // The point of exit cannot be a branch out of the structured block.
10940 // longjmp() and throw() must not violate the entry/exit criteria.
10941 CS
->getCapturedDecl()->setNothrow();
10942 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_parallel_loop
);
10943 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
10944 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
10945 // 1.2.2 OpenMP Language Terminology
10946 // Structured block - An executable statement with a single entry at the
10947 // top and a single exit at the bottom.
10948 // The point of exit cannot be a branch out of the structured block.
10949 // longjmp() and throw() must not violate the entry/exit criteria.
10950 CS
->getCapturedDecl()->setNothrow();
10953 OMPLoopDirective::HelperExprs B
;
10954 // In presence of clause 'collapse', it will define the nested loops number.
10955 unsigned NestedLoopCount
=
10956 checkOpenMPLoop(OMPD_target_parallel_loop
, getCollapseNumberExpr(Clauses
),
10957 /*OrderedLoopCountExpr=*/nullptr, CS
, *this, *DSAStack
,
10958 VarsWithImplicitDSA
, B
);
10959 if (NestedLoopCount
== 0)
10960 return StmtError();
10962 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
10963 "omp loop exprs were not built");
10965 setFunctionHasBranchProtectedScope();
10967 return OMPTargetParallelGenericLoopDirective::Create(
10968 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
10971 StmtResult
Sema::ActOnOpenMPSingleDirective(ArrayRef
<OMPClause
*> Clauses
,
10973 SourceLocation StartLoc
,
10974 SourceLocation EndLoc
) {
10976 return StmtError();
10978 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
10980 setFunctionHasBranchProtectedScope();
10982 // OpenMP [2.7.3, single Construct, Restrictions]
10983 // The copyprivate clause must not be used with the nowait clause.
10984 const OMPClause
*Nowait
= nullptr;
10985 const OMPClause
*Copyprivate
= nullptr;
10986 for (const OMPClause
*Clause
: Clauses
) {
10987 if (Clause
->getClauseKind() == OMPC_nowait
)
10989 else if (Clause
->getClauseKind() == OMPC_copyprivate
)
10990 Copyprivate
= Clause
;
10991 if (Copyprivate
&& Nowait
) {
10992 Diag(Copyprivate
->getBeginLoc(),
10993 diag::err_omp_single_copyprivate_with_nowait
);
10994 Diag(Nowait
->getBeginLoc(), diag::note_omp_nowait_clause_here
);
10995 return StmtError();
10999 return OMPSingleDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
);
11002 StmtResult
Sema::ActOnOpenMPMasterDirective(Stmt
*AStmt
,
11003 SourceLocation StartLoc
,
11004 SourceLocation EndLoc
) {
11006 return StmtError();
11008 setFunctionHasBranchProtectedScope();
11010 return OMPMasterDirective::Create(Context
, StartLoc
, EndLoc
, AStmt
);
11013 StmtResult
Sema::ActOnOpenMPMaskedDirective(ArrayRef
<OMPClause
*> Clauses
,
11015 SourceLocation StartLoc
,
11016 SourceLocation EndLoc
) {
11018 return StmtError();
11020 setFunctionHasBranchProtectedScope();
11022 return OMPMaskedDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
);
11025 StmtResult
Sema::ActOnOpenMPCriticalDirective(
11026 const DeclarationNameInfo
&DirName
, ArrayRef
<OMPClause
*> Clauses
,
11027 Stmt
*AStmt
, SourceLocation StartLoc
, SourceLocation EndLoc
) {
11029 return StmtError();
11031 bool ErrorFound
= false;
11033 SourceLocation HintLoc
;
11034 bool DependentHint
= false;
11035 for (const OMPClause
*C
: Clauses
) {
11036 if (C
->getClauseKind() == OMPC_hint
) {
11037 if (!DirName
.getName()) {
11038 Diag(C
->getBeginLoc(), diag::err_omp_hint_clause_no_name
);
11041 Expr
*E
= cast
<OMPHintClause
>(C
)->getHint();
11042 if (E
->isTypeDependent() || E
->isValueDependent() ||
11043 E
->isInstantiationDependent()) {
11044 DependentHint
= true;
11046 Hint
= E
->EvaluateKnownConstInt(Context
);
11047 HintLoc
= C
->getBeginLoc();
11052 return StmtError();
11053 const auto Pair
= DSAStack
->getCriticalWithHint(DirName
);
11054 if (Pair
.first
&& DirName
.getName() && !DependentHint
) {
11055 if (llvm::APSInt::compareValues(Hint
, Pair
.second
) != 0) {
11056 Diag(StartLoc
, diag::err_omp_critical_with_hint
);
11057 if (HintLoc
.isValid())
11058 Diag(HintLoc
, diag::note_omp_critical_hint_here
)
11059 << 0 << toString(Hint
, /*Radix=*/10, /*Signed=*/false);
11061 Diag(StartLoc
, diag::note_omp_critical_no_hint
) << 0;
11062 if (const auto *C
= Pair
.first
->getSingleClause
<OMPHintClause
>()) {
11063 Diag(C
->getBeginLoc(), diag::note_omp_critical_hint_here
)
11065 << toString(C
->getHint()->EvaluateKnownConstInt(Context
),
11066 /*Radix=*/10, /*Signed=*/false);
11068 Diag(Pair
.first
->getBeginLoc(), diag::note_omp_critical_no_hint
) << 1;
11073 setFunctionHasBranchProtectedScope();
11075 auto *Dir
= OMPCriticalDirective::Create(Context
, DirName
, StartLoc
, EndLoc
,
11077 if (!Pair
.first
&& DirName
.getName() && !DependentHint
)
11078 DSAStack
->addCriticalWithHint(Dir
, Hint
);
11082 StmtResult
Sema::ActOnOpenMPParallelForDirective(
11083 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
11084 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
11086 return StmtError();
11088 auto *CS
= cast
<CapturedStmt
>(AStmt
);
11089 // 1.2.2 OpenMP Language Terminology
11090 // Structured block - An executable statement with a single entry at the
11091 // top and a single exit at the bottom.
11092 // The point of exit cannot be a branch out of the structured block.
11093 // longjmp() and throw() must not violate the entry/exit criteria.
11094 CS
->getCapturedDecl()->setNothrow();
11096 OMPLoopBasedDirective::HelperExprs B
;
11097 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11098 // define the nested loops number.
11099 unsigned NestedLoopCount
=
11100 checkOpenMPLoop(OMPD_parallel_for
, getCollapseNumberExpr(Clauses
),
11101 getOrderedNumberExpr(Clauses
), AStmt
, *this, *DSAStack
,
11102 VarsWithImplicitDSA
, B
);
11103 if (NestedLoopCount
== 0)
11104 return StmtError();
11106 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
11107 "omp parallel for loop exprs were not built");
11109 if (!CurContext
->isDependentContext()) {
11110 // Finalize the clauses that need pre-built expressions for CodeGen.
11111 for (OMPClause
*C
: Clauses
) {
11112 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
11113 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
11114 B
.NumIterations
, *this, CurScope
,
11116 return StmtError();
11120 setFunctionHasBranchProtectedScope();
11121 return OMPParallelForDirective::Create(
11122 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
,
11123 DSAStack
->getTaskgroupReductionRef(), DSAStack
->isCancelRegion());
11126 StmtResult
Sema::ActOnOpenMPParallelForSimdDirective(
11127 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
11128 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
11130 return StmtError();
11132 auto *CS
= cast
<CapturedStmt
>(AStmt
);
11133 // 1.2.2 OpenMP Language Terminology
11134 // Structured block - An executable statement with a single entry at the
11135 // top and a single exit at the bottom.
11136 // The point of exit cannot be a branch out of the structured block.
11137 // longjmp() and throw() must not violate the entry/exit criteria.
11138 CS
->getCapturedDecl()->setNothrow();
11140 OMPLoopBasedDirective::HelperExprs B
;
11141 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11142 // define the nested loops number.
11143 unsigned NestedLoopCount
=
11144 checkOpenMPLoop(OMPD_parallel_for_simd
, getCollapseNumberExpr(Clauses
),
11145 getOrderedNumberExpr(Clauses
), AStmt
, *this, *DSAStack
,
11146 VarsWithImplicitDSA
, B
);
11147 if (NestedLoopCount
== 0)
11148 return StmtError();
11150 if (!CurContext
->isDependentContext()) {
11151 // Finalize the clauses that need pre-built expressions for CodeGen.
11152 for (OMPClause
*C
: Clauses
) {
11153 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
11154 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
11155 B
.NumIterations
, *this, CurScope
,
11157 return StmtError();
11161 if (checkSimdlenSafelenSpecified(*this, Clauses
))
11162 return StmtError();
11164 setFunctionHasBranchProtectedScope();
11165 return OMPParallelForSimdDirective::Create(
11166 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
11170 Sema::ActOnOpenMPParallelMasterDirective(ArrayRef
<OMPClause
*> Clauses
,
11171 Stmt
*AStmt
, SourceLocation StartLoc
,
11172 SourceLocation EndLoc
) {
11174 return StmtError();
11176 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
11177 auto *CS
= cast
<CapturedStmt
>(AStmt
);
11178 // 1.2.2 OpenMP Language Terminology
11179 // Structured block - An executable statement with a single entry at the
11180 // top and a single exit at the bottom.
11181 // The point of exit cannot be a branch out of the structured block.
11182 // longjmp() and throw() must not violate the entry/exit criteria.
11183 CS
->getCapturedDecl()->setNothrow();
11185 setFunctionHasBranchProtectedScope();
11187 return OMPParallelMasterDirective::Create(
11188 Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
11189 DSAStack
->getTaskgroupReductionRef());
11193 Sema::ActOnOpenMPParallelMaskedDirective(ArrayRef
<OMPClause
*> Clauses
,
11194 Stmt
*AStmt
, SourceLocation StartLoc
,
11195 SourceLocation EndLoc
) {
11197 return StmtError();
11199 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
11200 auto *CS
= cast
<CapturedStmt
>(AStmt
);
11201 // 1.2.2 OpenMP Language Terminology
11202 // Structured block - An executable statement with a single entry at the
11203 // top and a single exit at the bottom.
11204 // The point of exit cannot be a branch out of the structured block.
11205 // longjmp() and throw() must not violate the entry/exit criteria.
11206 CS
->getCapturedDecl()->setNothrow();
11208 setFunctionHasBranchProtectedScope();
11210 return OMPParallelMaskedDirective::Create(
11211 Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
11212 DSAStack
->getTaskgroupReductionRef());
11216 Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef
<OMPClause
*> Clauses
,
11217 Stmt
*AStmt
, SourceLocation StartLoc
,
11218 SourceLocation EndLoc
) {
11220 return StmtError();
11222 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
11223 auto BaseStmt
= AStmt
;
11224 while (auto *CS
= dyn_cast_or_null
<CapturedStmt
>(BaseStmt
))
11225 BaseStmt
= CS
->getCapturedStmt();
11226 if (auto *C
= dyn_cast_or_null
<CompoundStmt
>(BaseStmt
)) {
11227 auto S
= C
->children();
11228 if (S
.begin() == S
.end())
11229 return StmtError();
11230 // All associated statements must be '#pragma omp section' except for
11232 for (Stmt
*SectionStmt
: llvm::drop_begin(S
)) {
11233 if (!SectionStmt
|| !isa
<OMPSectionDirective
>(SectionStmt
)) {
11235 Diag(SectionStmt
->getBeginLoc(),
11236 diag::err_omp_parallel_sections_substmt_not_section
);
11237 return StmtError();
11239 cast
<OMPSectionDirective
>(SectionStmt
)
11240 ->setHasCancel(DSAStack
->isCancelRegion());
11243 Diag(AStmt
->getBeginLoc(),
11244 diag::err_omp_parallel_sections_not_compound_stmt
);
11245 return StmtError();
11248 setFunctionHasBranchProtectedScope();
11250 return OMPParallelSectionsDirective::Create(
11251 Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
11252 DSAStack
->getTaskgroupReductionRef(), DSAStack
->isCancelRegion());
11255 /// Find and diagnose mutually exclusive clause kinds.
11256 static bool checkMutuallyExclusiveClauses(
11257 Sema
&S
, ArrayRef
<OMPClause
*> Clauses
,
11258 ArrayRef
<OpenMPClauseKind
> MutuallyExclusiveClauses
) {
11259 const OMPClause
*PrevClause
= nullptr;
11260 bool ErrorFound
= false;
11261 for (const OMPClause
*C
: Clauses
) {
11262 if (llvm::is_contained(MutuallyExclusiveClauses
, C
->getClauseKind())) {
11265 } else if (PrevClause
->getClauseKind() != C
->getClauseKind()) {
11266 S
.Diag(C
->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive
)
11267 << getOpenMPClauseName(C
->getClauseKind())
11268 << getOpenMPClauseName(PrevClause
->getClauseKind());
11269 S
.Diag(PrevClause
->getBeginLoc(), diag::note_omp_previous_clause
)
11270 << getOpenMPClauseName(PrevClause
->getClauseKind());
11278 StmtResult
Sema::ActOnOpenMPTaskDirective(ArrayRef
<OMPClause
*> Clauses
,
11279 Stmt
*AStmt
, SourceLocation StartLoc
,
11280 SourceLocation EndLoc
) {
11282 return StmtError();
11284 // OpenMP 5.0, 2.10.1 task Construct
11285 // If a detach clause appears on the directive, then a mergeable clause cannot
11286 // appear on the same directive.
11287 if (checkMutuallyExclusiveClauses(*this, Clauses
,
11288 {OMPC_detach
, OMPC_mergeable
}))
11289 return StmtError();
11291 auto *CS
= cast
<CapturedStmt
>(AStmt
);
11292 // 1.2.2 OpenMP Language Terminology
11293 // Structured block - An executable statement with a single entry at the
11294 // top and a single exit at the bottom.
11295 // The point of exit cannot be a branch out of the structured block.
11296 // longjmp() and throw() must not violate the entry/exit criteria.
11297 CS
->getCapturedDecl()->setNothrow();
11299 setFunctionHasBranchProtectedScope();
11301 return OMPTaskDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
11302 DSAStack
->isCancelRegion());
11305 StmtResult
Sema::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc
,
11306 SourceLocation EndLoc
) {
11307 return OMPTaskyieldDirective::Create(Context
, StartLoc
, EndLoc
);
11310 StmtResult
Sema::ActOnOpenMPBarrierDirective(SourceLocation StartLoc
,
11311 SourceLocation EndLoc
) {
11312 return OMPBarrierDirective::Create(Context
, StartLoc
, EndLoc
);
11315 StmtResult
Sema::ActOnOpenMPErrorDirective(ArrayRef
<OMPClause
*> Clauses
,
11316 SourceLocation StartLoc
,
11317 SourceLocation EndLoc
,
11318 bool InExContext
) {
11319 const OMPAtClause
*AtC
=
11320 OMPExecutableDirective::getSingleClause
<OMPAtClause
>(Clauses
);
11322 if (AtC
&& !InExContext
&& AtC
->getAtKind() == OMPC_AT_execution
) {
11323 Diag(AtC
->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier
);
11324 return StmtError();
11327 const OMPSeverityClause
*SeverityC
=
11328 OMPExecutableDirective::getSingleClause
<OMPSeverityClause
>(Clauses
);
11329 const OMPMessageClause
*MessageC
=
11330 OMPExecutableDirective::getSingleClause
<OMPMessageClause
>(Clauses
);
11331 Expr
*ME
= MessageC
? MessageC
->getMessageString() : nullptr;
11333 if (!AtC
|| AtC
->getAtKind() == OMPC_AT_compilation
) {
11334 if (SeverityC
&& SeverityC
->getSeverityKind() == OMPC_SEVERITY_warning
)
11335 Diag(SeverityC
->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded
)
11336 << (ME
? cast
<StringLiteral
>(ME
)->getString() : "WARNING");
11338 Diag(StartLoc
, diag::err_diagnose_if_succeeded
)
11339 << (ME
? cast
<StringLiteral
>(ME
)->getString() : "ERROR");
11340 if (!SeverityC
|| SeverityC
->getSeverityKind() != OMPC_SEVERITY_warning
)
11341 return StmtError();
11343 return OMPErrorDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
);
11346 StmtResult
Sema::ActOnOpenMPTaskwaitDirective(ArrayRef
<OMPClause
*> Clauses
,
11347 SourceLocation StartLoc
,
11348 SourceLocation EndLoc
) {
11349 const OMPNowaitClause
*NowaitC
=
11350 OMPExecutableDirective::getSingleClause
<OMPNowaitClause
>(Clauses
);
11352 !OMPExecutableDirective::getClausesOfKind
<OMPDependClause
>(Clauses
)
11354 if (NowaitC
&& !HasDependC
) {
11355 Diag(StartLoc
, diag::err_omp_nowait_clause_without_depend
);
11356 return StmtError();
11359 return OMPTaskwaitDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
);
11362 StmtResult
Sema::ActOnOpenMPTaskgroupDirective(ArrayRef
<OMPClause
*> Clauses
,
11364 SourceLocation StartLoc
,
11365 SourceLocation EndLoc
) {
11367 return StmtError();
11369 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
11371 setFunctionHasBranchProtectedScope();
11373 return OMPTaskgroupDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
,
11375 DSAStack
->getTaskgroupReductionRef());
11378 StmtResult
Sema::ActOnOpenMPFlushDirective(ArrayRef
<OMPClause
*> Clauses
,
11379 SourceLocation StartLoc
,
11380 SourceLocation EndLoc
) {
11381 OMPFlushClause
*FC
= nullptr;
11382 OMPClause
*OrderClause
= nullptr;
11383 for (OMPClause
*C
: Clauses
) {
11384 if (C
->getClauseKind() == OMPC_flush
)
11385 FC
= cast
<OMPFlushClause
>(C
);
11389 OpenMPClauseKind MemOrderKind
= OMPC_unknown
;
11390 SourceLocation MemOrderLoc
;
11391 for (const OMPClause
*C
: Clauses
) {
11392 if (C
->getClauseKind() == OMPC_acq_rel
||
11393 C
->getClauseKind() == OMPC_acquire
||
11394 C
->getClauseKind() == OMPC_release
) {
11395 if (MemOrderKind
!= OMPC_unknown
) {
11396 Diag(C
->getBeginLoc(), diag::err_omp_several_mem_order_clauses
)
11397 << getOpenMPDirectiveName(OMPD_flush
) << 1
11398 << SourceRange(C
->getBeginLoc(), C
->getEndLoc());
11399 Diag(MemOrderLoc
, diag::note_omp_previous_mem_order_clause
)
11400 << getOpenMPClauseName(MemOrderKind
);
11402 MemOrderKind
= C
->getClauseKind();
11403 MemOrderLoc
= C
->getBeginLoc();
11407 if (FC
&& OrderClause
) {
11408 Diag(FC
->getLParenLoc(), diag::err_omp_flush_order_clause_and_list
)
11409 << getOpenMPClauseName(OrderClause
->getClauseKind());
11410 Diag(OrderClause
->getBeginLoc(), diag::note_omp_flush_order_clause_here
)
11411 << getOpenMPClauseName(OrderClause
->getClauseKind());
11412 return StmtError();
11414 return OMPFlushDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
);
11417 StmtResult
Sema::ActOnOpenMPDepobjDirective(ArrayRef
<OMPClause
*> Clauses
,
11418 SourceLocation StartLoc
,
11419 SourceLocation EndLoc
) {
11420 if (Clauses
.empty()) {
11421 Diag(StartLoc
, diag::err_omp_depobj_expected
);
11422 return StmtError();
11423 } else if (Clauses
[0]->getClauseKind() != OMPC_depobj
) {
11424 Diag(Clauses
[0]->getBeginLoc(), diag::err_omp_depobj_expected
);
11425 return StmtError();
11427 // Only depobj expression and another single clause is allowed.
11428 if (Clauses
.size() > 2) {
11429 Diag(Clauses
[2]->getBeginLoc(),
11430 diag::err_omp_depobj_single_clause_expected
);
11431 return StmtError();
11432 } else if (Clauses
.size() < 1) {
11433 Diag(Clauses
[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected
);
11434 return StmtError();
11436 return OMPDepobjDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
);
11439 StmtResult
Sema::ActOnOpenMPScanDirective(ArrayRef
<OMPClause
*> Clauses
,
11440 SourceLocation StartLoc
,
11441 SourceLocation EndLoc
) {
11442 // Check that exactly one clause is specified.
11443 if (Clauses
.size() != 1) {
11444 Diag(Clauses
.empty() ? EndLoc
: Clauses
[1]->getBeginLoc(),
11445 diag::err_omp_scan_single_clause_expected
);
11446 return StmtError();
11448 // Check that scan directive is used in the scopeof the OpenMP loop body.
11449 if (Scope
*S
= DSAStack
->getCurScope()) {
11450 Scope
*ParentS
= S
->getParent();
11451 if (!ParentS
|| ParentS
->getParent() != ParentS
->getBreakParent() ||
11452 !ParentS
->getBreakParent()->isOpenMPLoopScope())
11453 return StmtError(Diag(StartLoc
, diag::err_omp_orphaned_device_directive
)
11454 << getOpenMPDirectiveName(OMPD_scan
) << 5);
11456 // Check that only one instance of scan directives is used in the same outer
11458 if (DSAStack
->doesParentHasScanDirective()) {
11459 Diag(StartLoc
, diag::err_omp_several_directives_in_region
) << "scan";
11460 Diag(DSAStack
->getParentScanDirectiveLoc(),
11461 diag::note_omp_previous_directive
)
11463 return StmtError();
11465 DSAStack
->setParentHasScanDirective(StartLoc
);
11466 return OMPScanDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
);
11469 StmtResult
Sema::ActOnOpenMPOrderedDirective(ArrayRef
<OMPClause
*> Clauses
,
11471 SourceLocation StartLoc
,
11472 SourceLocation EndLoc
) {
11473 const OMPClause
*DependFound
= nullptr;
11474 const OMPClause
*DependSourceClause
= nullptr;
11475 const OMPClause
*DependSinkClause
= nullptr;
11476 const OMPClause
*DoacrossFound
= nullptr;
11477 const OMPClause
*DoacrossSourceClause
= nullptr;
11478 const OMPClause
*DoacrossSinkClause
= nullptr;
11479 bool ErrorFound
= false;
11480 const OMPThreadsClause
*TC
= nullptr;
11481 const OMPSIMDClause
*SC
= nullptr;
11482 for (const OMPClause
*C
: Clauses
) {
11483 auto DOC
= dyn_cast
<OMPDoacrossClause
>(C
);
11484 auto DC
= dyn_cast
<OMPDependClause
>(C
);
11486 DependFound
= DC
? C
: nullptr;
11487 DoacrossFound
= DOC
? C
: nullptr;
11488 OMPDoacrossKind ODK
;
11489 if ((DC
&& DC
->getDependencyKind() == OMPC_DEPEND_source
) ||
11490 (DOC
&& (ODK
.isSource(DOC
)))) {
11491 if ((DC
&& DependSourceClause
) || (DOC
&& DoacrossSourceClause
)) {
11492 Diag(C
->getBeginLoc(), diag::err_omp_more_one_clause
)
11493 << getOpenMPDirectiveName(OMPD_ordered
)
11494 << getOpenMPClauseName(DC
? OMPC_depend
: OMPC_doacross
) << 2;
11498 DependSourceClause
= C
;
11500 DoacrossSourceClause
= C
;
11502 if ((DC
&& DependSinkClause
) || (DOC
&& DoacrossSinkClause
)) {
11503 Diag(C
->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed
)
11504 << (DC
? "depend" : "doacross") << 0;
11507 } else if ((DC
&& DC
->getDependencyKind() == OMPC_DEPEND_sink
) ||
11508 (DOC
&& (ODK
.isSink(DOC
) || ODK
.isSinkIter(DOC
)))) {
11509 if (DependSourceClause
|| DoacrossSourceClause
) {
11510 Diag(C
->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed
)
11511 << (DC
? "depend" : "doacross") << 1;
11515 DependSinkClause
= C
;
11517 DoacrossSinkClause
= C
;
11519 } else if (C
->getClauseKind() == OMPC_threads
) {
11520 TC
= cast
<OMPThreadsClause
>(C
);
11521 } else if (C
->getClauseKind() == OMPC_simd
) {
11522 SC
= cast
<OMPSIMDClause
>(C
);
11525 if (!ErrorFound
&& !SC
&&
11526 isOpenMPSimdDirective(DSAStack
->getParentDirective())) {
11527 // OpenMP [2.8.1,simd Construct, Restrictions]
11528 // An ordered construct with the simd clause is the only OpenMP construct
11529 // that can appear in the simd region.
11530 Diag(StartLoc
, diag::err_omp_prohibited_region_simd
)
11531 << (LangOpts
.OpenMP
>= 50 ? 1 : 0);
11533 } else if ((DependFound
|| DoacrossFound
) && (TC
|| SC
)) {
11534 SourceLocation Loc
=
11535 DependFound
? DependFound
->getBeginLoc() : DoacrossFound
->getBeginLoc();
11536 Diag(Loc
, diag::err_omp_depend_clause_thread_simd
)
11537 << getOpenMPClauseName(DependFound
? OMPC_depend
: OMPC_doacross
)
11538 << getOpenMPClauseName(TC
? TC
->getClauseKind() : SC
->getClauseKind());
11540 } else if ((DependFound
|| DoacrossFound
) &&
11541 !DSAStack
->getParentOrderedRegionParam().first
) {
11542 SourceLocation Loc
=
11543 DependFound
? DependFound
->getBeginLoc() : DoacrossFound
->getBeginLoc();
11544 Diag(Loc
, diag::err_omp_ordered_directive_without_param
)
11545 << getOpenMPClauseName(DependFound
? OMPC_depend
: OMPC_doacross
);
11547 } else if (TC
|| Clauses
.empty()) {
11548 if (const Expr
*Param
= DSAStack
->getParentOrderedRegionParam().first
) {
11549 SourceLocation ErrLoc
= TC
? TC
->getBeginLoc() : StartLoc
;
11550 Diag(ErrLoc
, diag::err_omp_ordered_directive_with_param
)
11551 << (TC
!= nullptr);
11552 Diag(Param
->getBeginLoc(), diag::note_omp_ordered_param
) << 1;
11556 if ((!AStmt
&& !DependFound
&& !DoacrossFound
) || ErrorFound
)
11557 return StmtError();
11559 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11560 // During execution of an iteration of a worksharing-loop or a loop nest
11561 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11562 // must not execute more than one ordered region corresponding to an ordered
11563 // construct without a depend clause.
11564 if (!DependFound
&& !DoacrossFound
) {
11565 if (DSAStack
->doesParentHasOrderedDirective()) {
11566 Diag(StartLoc
, diag::err_omp_several_directives_in_region
) << "ordered";
11567 Diag(DSAStack
->getParentOrderedDirectiveLoc(),
11568 diag::note_omp_previous_directive
)
11570 return StmtError();
11572 DSAStack
->setParentHasOrderedDirective(StartLoc
);
11576 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
11578 setFunctionHasBranchProtectedScope();
11581 return OMPOrderedDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
);
11585 /// Helper class for checking expression in 'omp atomic [update]'
11587 class OpenMPAtomicUpdateChecker
{
11588 /// Error results for atomic update expressions.
11589 enum ExprAnalysisErrorCode
{
11590 /// A statement is not an expression statement.
11592 /// Expression is not builtin binary or unary operation.
11593 NotABinaryOrUnaryExpression
,
11594 /// Unary operation is not post-/pre- increment/decrement operation.
11595 NotAnUnaryIncDecExpression
,
11596 /// An expression is not of scalar type.
11598 /// A binary operation is not an assignment operation.
11600 /// RHS part of the binary operation is not a binary expression.
11601 NotABinaryExpression
,
11602 /// RHS part is not additive/multiplicative/shift/biwise binary
11604 NotABinaryOperator
,
11605 /// RHS binary operation does not have reference to the updated LHS
11607 NotAnUpdateExpression
,
11608 /// No errors is found.
11611 /// Reference to Sema.
11613 /// A location for note diagnostics (when error is found).
11614 SourceLocation NoteLoc
;
11615 /// 'x' lvalue part of the source atomic expression.
11617 /// 'expr' rvalue part of the source atomic expression.
11619 /// Helper expression of the form
11620 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11621 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11623 /// Is 'x' a LHS in a RHS part of full update expression. It is
11624 /// important for non-associative operations.
11625 bool IsXLHSInRHSPart
;
11626 BinaryOperatorKind Op
;
11627 SourceLocation OpLoc
;
11628 /// true if the source expression is a postfix unary operation, false
11629 /// if it is a prefix unary operation.
11630 bool IsPostfixUpdate
;
11633 OpenMPAtomicUpdateChecker(Sema
&SemaRef
)
11634 : SemaRef(SemaRef
), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11635 IsXLHSInRHSPart(false), Op(BO_PtrMemD
), IsPostfixUpdate(false) {}
11636 /// Check specified statement that it is suitable for 'atomic update'
11637 /// constructs and extract 'x', 'expr' and Operation from the original
11638 /// expression. If DiagId and NoteId == 0, then only check is performed
11639 /// without error notification.
11640 /// \param DiagId Diagnostic which should be emitted if error is found.
11641 /// \param NoteId Diagnostic note for the main error message.
11642 /// \return true if statement is not an update expression, false otherwise.
11643 bool checkStatement(Stmt
*S
, unsigned DiagId
= 0, unsigned NoteId
= 0);
11644 /// Return the 'x' lvalue part of the source atomic expression.
11645 Expr
*getX() const { return X
; }
11646 /// Return the 'expr' rvalue part of the source atomic expression.
11647 Expr
*getExpr() const { return E
; }
11648 /// Return the update expression used in calculation of the updated
11649 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11650 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11651 Expr
*getUpdateExpr() const { return UpdateExpr
; }
11652 /// Return true if 'x' is LHS in RHS part of full update expression,
11653 /// false otherwise.
11654 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart
; }
11656 /// true if the source expression is a postfix unary operation, false
11657 /// if it is a prefix unary operation.
11658 bool isPostfixUpdate() const { return IsPostfixUpdate
; }
11661 bool checkBinaryOperation(BinaryOperator
*AtomicBinOp
, unsigned DiagId
= 0,
11662 unsigned NoteId
= 0);
11665 bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11666 BinaryOperator
*AtomicBinOp
, unsigned DiagId
, unsigned NoteId
) {
11667 ExprAnalysisErrorCode ErrorFound
= NoError
;
11668 SourceLocation ErrorLoc
, NoteLoc
;
11669 SourceRange ErrorRange
, NoteRange
;
11670 // Allowed constructs are:
11671 // x = x binop expr;
11672 // x = expr binop x;
11673 if (AtomicBinOp
->getOpcode() == BO_Assign
) {
11674 X
= AtomicBinOp
->getLHS();
11675 if (const auto *AtomicInnerBinOp
= dyn_cast
<BinaryOperator
>(
11676 AtomicBinOp
->getRHS()->IgnoreParenImpCasts())) {
11677 if (AtomicInnerBinOp
->isMultiplicativeOp() ||
11678 AtomicInnerBinOp
->isAdditiveOp() || AtomicInnerBinOp
->isShiftOp() ||
11679 AtomicInnerBinOp
->isBitwiseOp()) {
11680 Op
= AtomicInnerBinOp
->getOpcode();
11681 OpLoc
= AtomicInnerBinOp
->getOperatorLoc();
11682 Expr
*LHS
= AtomicInnerBinOp
->getLHS();
11683 Expr
*RHS
= AtomicInnerBinOp
->getRHS();
11684 llvm::FoldingSetNodeID XId
, LHSId
, RHSId
;
11685 X
->IgnoreParenImpCasts()->Profile(XId
, SemaRef
.getASTContext(),
11686 /*Canonical=*/true);
11687 LHS
->IgnoreParenImpCasts()->Profile(LHSId
, SemaRef
.getASTContext(),
11688 /*Canonical=*/true);
11689 RHS
->IgnoreParenImpCasts()->Profile(RHSId
, SemaRef
.getASTContext(),
11690 /*Canonical=*/true);
11691 if (XId
== LHSId
) {
11693 IsXLHSInRHSPart
= true;
11694 } else if (XId
== RHSId
) {
11696 IsXLHSInRHSPart
= false;
11698 ErrorLoc
= AtomicInnerBinOp
->getExprLoc();
11699 ErrorRange
= AtomicInnerBinOp
->getSourceRange();
11700 NoteLoc
= X
->getExprLoc();
11701 NoteRange
= X
->getSourceRange();
11702 ErrorFound
= NotAnUpdateExpression
;
11705 ErrorLoc
= AtomicInnerBinOp
->getExprLoc();
11706 ErrorRange
= AtomicInnerBinOp
->getSourceRange();
11707 NoteLoc
= AtomicInnerBinOp
->getOperatorLoc();
11708 NoteRange
= SourceRange(NoteLoc
, NoteLoc
);
11709 ErrorFound
= NotABinaryOperator
;
11712 NoteLoc
= ErrorLoc
= AtomicBinOp
->getRHS()->getExprLoc();
11713 NoteRange
= ErrorRange
= AtomicBinOp
->getRHS()->getSourceRange();
11714 ErrorFound
= NotABinaryExpression
;
11717 ErrorLoc
= AtomicBinOp
->getExprLoc();
11718 ErrorRange
= AtomicBinOp
->getSourceRange();
11719 NoteLoc
= AtomicBinOp
->getOperatorLoc();
11720 NoteRange
= SourceRange(NoteLoc
, NoteLoc
);
11721 ErrorFound
= NotAnAssignmentOp
;
11723 if (ErrorFound
!= NoError
&& DiagId
!= 0 && NoteId
!= 0) {
11724 SemaRef
.Diag(ErrorLoc
, DiagId
) << ErrorRange
;
11725 SemaRef
.Diag(NoteLoc
, NoteId
) << ErrorFound
<< NoteRange
;
11728 if (SemaRef
.CurContext
->isDependentContext())
11729 E
= X
= UpdateExpr
= nullptr;
11730 return ErrorFound
!= NoError
;
11733 bool OpenMPAtomicUpdateChecker::checkStatement(Stmt
*S
, unsigned DiagId
,
11735 ExprAnalysisErrorCode ErrorFound
= NoError
;
11736 SourceLocation ErrorLoc
, NoteLoc
;
11737 SourceRange ErrorRange
, NoteRange
;
11738 // Allowed constructs are:
11744 // x = x binop expr;
11745 // x = expr binop x;
11746 if (auto *AtomicBody
= dyn_cast
<Expr
>(S
)) {
11747 AtomicBody
= AtomicBody
->IgnoreParenImpCasts();
11748 if (AtomicBody
->getType()->isScalarType() ||
11749 AtomicBody
->isInstantiationDependent()) {
11750 if (const auto *AtomicCompAssignOp
= dyn_cast
<CompoundAssignOperator
>(
11751 AtomicBody
->IgnoreParenImpCasts())) {
11752 // Check for Compound Assignment Operation
11753 Op
= BinaryOperator::getOpForCompoundAssignment(
11754 AtomicCompAssignOp
->getOpcode());
11755 OpLoc
= AtomicCompAssignOp
->getOperatorLoc();
11756 E
= AtomicCompAssignOp
->getRHS();
11757 X
= AtomicCompAssignOp
->getLHS()->IgnoreParens();
11758 IsXLHSInRHSPart
= true;
11759 } else if (auto *AtomicBinOp
= dyn_cast
<BinaryOperator
>(
11760 AtomicBody
->IgnoreParenImpCasts())) {
11761 // Check for Binary Operation
11762 if (checkBinaryOperation(AtomicBinOp
, DiagId
, NoteId
))
11764 } else if (const auto *AtomicUnaryOp
= dyn_cast
<UnaryOperator
>(
11765 AtomicBody
->IgnoreParenImpCasts())) {
11766 // Check for Unary Operation
11767 if (AtomicUnaryOp
->isIncrementDecrementOp()) {
11768 IsPostfixUpdate
= AtomicUnaryOp
->isPostfix();
11769 Op
= AtomicUnaryOp
->isIncrementOp() ? BO_Add
: BO_Sub
;
11770 OpLoc
= AtomicUnaryOp
->getOperatorLoc();
11771 X
= AtomicUnaryOp
->getSubExpr()->IgnoreParens();
11772 E
= SemaRef
.ActOnIntegerConstant(OpLoc
, /*uint64_t Val=*/1).get();
11773 IsXLHSInRHSPart
= true;
11775 ErrorFound
= NotAnUnaryIncDecExpression
;
11776 ErrorLoc
= AtomicUnaryOp
->getExprLoc();
11777 ErrorRange
= AtomicUnaryOp
->getSourceRange();
11778 NoteLoc
= AtomicUnaryOp
->getOperatorLoc();
11779 NoteRange
= SourceRange(NoteLoc
, NoteLoc
);
11781 } else if (!AtomicBody
->isInstantiationDependent()) {
11782 ErrorFound
= NotABinaryOrUnaryExpression
;
11783 NoteLoc
= ErrorLoc
= AtomicBody
->getExprLoc();
11784 NoteRange
= ErrorRange
= AtomicBody
->getSourceRange();
11787 ErrorFound
= NotAScalarType
;
11788 NoteLoc
= ErrorLoc
= AtomicBody
->getBeginLoc();
11789 NoteRange
= ErrorRange
= SourceRange(NoteLoc
, NoteLoc
);
11792 ErrorFound
= NotAnExpression
;
11793 NoteLoc
= ErrorLoc
= S
->getBeginLoc();
11794 NoteRange
= ErrorRange
= SourceRange(NoteLoc
, NoteLoc
);
11796 if (ErrorFound
!= NoError
&& DiagId
!= 0 && NoteId
!= 0) {
11797 SemaRef
.Diag(ErrorLoc
, DiagId
) << ErrorRange
;
11798 SemaRef
.Diag(NoteLoc
, NoteId
) << ErrorFound
<< NoteRange
;
11801 if (SemaRef
.CurContext
->isDependentContext())
11802 E
= X
= UpdateExpr
= nullptr;
11803 if (ErrorFound
== NoError
&& E
&& X
) {
11804 // Build an update expression of form 'OpaqueValueExpr(x) binop
11805 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11806 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11807 auto *OVEX
= new (SemaRef
.getASTContext())
11808 OpaqueValueExpr(X
->getExprLoc(), X
->getType(), VK_PRValue
);
11809 auto *OVEExpr
= new (SemaRef
.getASTContext())
11810 OpaqueValueExpr(E
->getExprLoc(), E
->getType(), VK_PRValue
);
11811 ExprResult Update
=
11812 SemaRef
.CreateBuiltinBinOp(OpLoc
, Op
, IsXLHSInRHSPart
? OVEX
: OVEExpr
,
11813 IsXLHSInRHSPart
? OVEExpr
: OVEX
);
11814 if (Update
.isInvalid())
11816 Update
= SemaRef
.PerformImplicitConversion(Update
.get(), X
->getType(),
11818 if (Update
.isInvalid())
11820 UpdateExpr
= Update
.get();
11822 return ErrorFound
!= NoError
;
11825 /// Get the node id of the fixed point of an expression \a S.
11826 llvm::FoldingSetNodeID
getNodeId(ASTContext
&Context
, const Expr
*S
) {
11827 llvm::FoldingSetNodeID Id
;
11828 S
->IgnoreParenImpCasts()->Profile(Id
, Context
, true);
11832 /// Check if two expressions are same.
11833 bool checkIfTwoExprsAreSame(ASTContext
&Context
, const Expr
*LHS
,
11835 return getNodeId(Context
, LHS
) == getNodeId(Context
, RHS
);
11838 class OpenMPAtomicCompareChecker
{
11840 /// All kinds of errors that can occur in `atomic compare`
11842 /// Empty compound statement.
11844 /// More than one statement in a compound statement.
11846 /// Not an assignment binary operator.
11848 /// Not a conditional operator.
11850 /// Wrong false expr. According to the spec, 'x' should be at the false
11851 /// expression of a conditional expression.
11853 /// The condition of a conditional expression is not a binary operator.
11855 /// Invalid binary operator (not <, >, or ==).
11857 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11859 /// X is not a lvalue.
11863 /// Not an integer.
11865 /// 'else' statement is not expected.
11867 /// Not an equality operator.
11869 /// Invalid assignment (not v == x).
11871 /// Not if statement
11873 /// More than two statements in a compund statement.
11875 /// Not a compound statement.
11877 /// No else statement.
11885 struct ErrorInfoTy
{
11887 SourceLocation ErrorLoc
;
11888 SourceRange ErrorRange
;
11889 SourceLocation NoteLoc
;
11890 SourceRange NoteRange
;
11893 OpenMPAtomicCompareChecker(Sema
&S
) : ContextRef(S
.getASTContext()) {}
11895 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11896 bool checkStmt(Stmt
*S
, ErrorInfoTy
&ErrorInfo
);
11898 Expr
*getX() const { return X
; }
11899 Expr
*getE() const { return E
; }
11900 Expr
*getD() const { return D
; }
11901 Expr
*getCond() const { return C
; }
11902 bool isXBinopExpr() const { return IsXBinopExpr
; }
11905 /// Reference to ASTContext
11906 ASTContext
&ContextRef
;
11907 /// 'x' lvalue part of the source atomic expression.
11909 /// 'expr' or 'e' rvalue part of the source atomic expression.
11911 /// 'd' rvalue part of the source atomic expression.
11913 /// 'cond' part of the source atomic expression. It is in one of the following
11920 /// True if the cond expr is in the form of 'x ordop expr'.
11921 bool IsXBinopExpr
= true;
11923 /// Check if it is a valid conditional update statement (cond-update-stmt).
11924 bool checkCondUpdateStmt(IfStmt
*S
, ErrorInfoTy
&ErrorInfo
);
11926 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11927 bool checkCondExprStmt(Stmt
*S
, ErrorInfoTy
&ErrorInfo
);
11929 /// Check if all captured values have right type.
11930 bool checkType(ErrorInfoTy
&ErrorInfo
) const;
11932 static bool CheckValue(const Expr
*E
, ErrorInfoTy
&ErrorInfo
,
11933 bool ShouldBeLValue
, bool ShouldBeInteger
= false) {
11934 if (E
->isInstantiationDependent())
11937 if (ShouldBeLValue
&& !E
->isLValue()) {
11938 ErrorInfo
.Error
= ErrorTy::XNotLValue
;
11939 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= E
->getExprLoc();
11940 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= E
->getSourceRange();
11944 QualType QTy
= E
->getType();
11945 if (!QTy
->isScalarType()) {
11946 ErrorInfo
.Error
= ErrorTy::NotScalar
;
11947 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= E
->getExprLoc();
11948 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= E
->getSourceRange();
11951 if (ShouldBeInteger
&& !QTy
->isIntegerType()) {
11952 ErrorInfo
.Error
= ErrorTy::NotInteger
;
11953 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= E
->getExprLoc();
11954 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= E
->getSourceRange();
11962 bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt
*S
,
11963 ErrorInfoTy
&ErrorInfo
) {
11964 auto *Then
= S
->getThen();
11965 if (auto *CS
= dyn_cast
<CompoundStmt
>(Then
)) {
11966 if (CS
->body_empty()) {
11967 ErrorInfo
.Error
= ErrorTy::NoStmt
;
11968 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
11969 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= CS
->getSourceRange();
11972 if (CS
->size() > 1) {
11973 ErrorInfo
.Error
= ErrorTy::MoreThanOneStmt
;
11974 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
11975 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S
->getSourceRange();
11978 Then
= CS
->body_front();
11981 auto *BO
= dyn_cast
<BinaryOperator
>(Then
);
11983 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
11984 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Then
->getBeginLoc();
11985 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Then
->getSourceRange();
11988 if (BO
->getOpcode() != BO_Assign
) {
11989 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
11990 ErrorInfo
.ErrorLoc
= BO
->getExprLoc();
11991 ErrorInfo
.NoteLoc
= BO
->getOperatorLoc();
11992 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= BO
->getSourceRange();
11998 auto *Cond
= dyn_cast
<BinaryOperator
>(S
->getCond());
12000 ErrorInfo
.Error
= ErrorTy::NotABinaryOp
;
12001 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= S
->getCond()->getExprLoc();
12002 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S
->getCond()->getSourceRange();
12006 switch (Cond
->getOpcode()) {
12010 if (checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getLHS())) {
12011 E
= Cond
->getRHS();
12012 } else if (checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getRHS())) {
12013 E
= Cond
->getLHS();
12015 ErrorInfo
.Error
= ErrorTy::InvalidComparison
;
12016 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Cond
->getExprLoc();
12017 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Cond
->getSourceRange();
12025 if (checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getLHS()) &&
12026 checkIfTwoExprsAreSame(ContextRef
, E
, Cond
->getRHS())) {
12028 } else if (checkIfTwoExprsAreSame(ContextRef
, E
, Cond
->getLHS()) &&
12029 checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getRHS())) {
12031 IsXBinopExpr
= false;
12033 ErrorInfo
.Error
= ErrorTy::InvalidComparison
;
12034 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Cond
->getExprLoc();
12035 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Cond
->getSourceRange();
12041 ErrorInfo
.Error
= ErrorTy::InvalidBinaryOp
;
12042 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Cond
->getExprLoc();
12043 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Cond
->getSourceRange();
12047 if (S
->getElse()) {
12048 ErrorInfo
.Error
= ErrorTy::UnexpectedElse
;
12049 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= S
->getElse()->getBeginLoc();
12050 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S
->getElse()->getSourceRange();
12057 bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt
*S
,
12058 ErrorInfoTy
&ErrorInfo
) {
12059 auto *BO
= dyn_cast
<BinaryOperator
>(S
);
12061 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12062 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= S
->getBeginLoc();
12063 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S
->getSourceRange();
12066 if (BO
->getOpcode() != BO_Assign
) {
12067 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12068 ErrorInfo
.ErrorLoc
= BO
->getExprLoc();
12069 ErrorInfo
.NoteLoc
= BO
->getOperatorLoc();
12070 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= BO
->getSourceRange();
12076 auto *CO
= dyn_cast
<ConditionalOperator
>(BO
->getRHS()->IgnoreParenImpCasts());
12078 ErrorInfo
.Error
= ErrorTy::NotCondOp
;
12079 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= BO
->getRHS()->getExprLoc();
12080 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= BO
->getRHS()->getSourceRange();
12084 if (!checkIfTwoExprsAreSame(ContextRef
, X
, CO
->getFalseExpr())) {
12085 ErrorInfo
.Error
= ErrorTy::WrongFalseExpr
;
12086 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CO
->getFalseExpr()->getExprLoc();
12087 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
=
12088 CO
->getFalseExpr()->getSourceRange();
12092 auto *Cond
= dyn_cast
<BinaryOperator
>(CO
->getCond());
12094 ErrorInfo
.Error
= ErrorTy::NotABinaryOp
;
12095 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CO
->getCond()->getExprLoc();
12096 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
=
12097 CO
->getCond()->getSourceRange();
12101 switch (Cond
->getOpcode()) {
12104 D
= CO
->getTrueExpr();
12105 if (checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getLHS())) {
12106 E
= Cond
->getRHS();
12107 } else if (checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getRHS())) {
12108 E
= Cond
->getLHS();
12110 ErrorInfo
.Error
= ErrorTy::InvalidComparison
;
12111 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Cond
->getExprLoc();
12112 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Cond
->getSourceRange();
12119 E
= CO
->getTrueExpr();
12120 if (checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getLHS()) &&
12121 checkIfTwoExprsAreSame(ContextRef
, E
, Cond
->getRHS())) {
12123 } else if (checkIfTwoExprsAreSame(ContextRef
, E
, Cond
->getLHS()) &&
12124 checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getRHS())) {
12126 IsXBinopExpr
= false;
12128 ErrorInfo
.Error
= ErrorTy::InvalidComparison
;
12129 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Cond
->getExprLoc();
12130 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Cond
->getSourceRange();
12136 ErrorInfo
.Error
= ErrorTy::InvalidBinaryOp
;
12137 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Cond
->getExprLoc();
12138 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Cond
->getSourceRange();
12145 bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy
&ErrorInfo
) const {
12146 // 'x' and 'e' cannot be nullptr
12147 assert(X
&& E
&& "X and E cannot be nullptr");
12149 if (!CheckValue(X
, ErrorInfo
, true))
12152 if (!CheckValue(E
, ErrorInfo
, false))
12155 if (D
&& !CheckValue(D
, ErrorInfo
, false))
12161 bool OpenMPAtomicCompareChecker::checkStmt(
12162 Stmt
*S
, OpenMPAtomicCompareChecker::ErrorInfoTy
&ErrorInfo
) {
12163 auto *CS
= dyn_cast
<CompoundStmt
>(S
);
12165 if (CS
->body_empty()) {
12166 ErrorInfo
.Error
= ErrorTy::NoStmt
;
12167 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
12168 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= CS
->getSourceRange();
12172 if (CS
->size() != 1) {
12173 ErrorInfo
.Error
= ErrorTy::MoreThanOneStmt
;
12174 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
12175 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= CS
->getSourceRange();
12178 S
= CS
->body_front();
12183 if (auto *IS
= dyn_cast
<IfStmt
>(S
)) {
12184 // Check if the statement is in one of the following forms
12185 // (cond-update-stmt):
12186 // if (expr ordop x) { x = expr; }
12187 // if (x ordop expr) { x = expr; }
12188 // if (x == e) { x = d; }
12189 Res
= checkCondUpdateStmt(IS
, ErrorInfo
);
12191 // Check if the statement is in one of the following forms (cond-expr-stmt):
12192 // x = expr ordop x ? expr : x;
12193 // x = x ordop expr ? expr : x;
12194 // x = x == e ? d : x;
12195 Res
= checkCondExprStmt(S
, ErrorInfo
);
12201 return checkType(ErrorInfo
);
12204 class OpenMPAtomicCompareCaptureChecker final
12205 : public OpenMPAtomicCompareChecker
{
12207 OpenMPAtomicCompareCaptureChecker(Sema
&S
) : OpenMPAtomicCompareChecker(S
) {}
12209 Expr
*getV() const { return V
; }
12210 Expr
*getR() const { return R
; }
12211 bool isFailOnly() const { return IsFailOnly
; }
12212 bool isPostfixUpdate() const { return IsPostfixUpdate
; }
12214 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
12215 bool checkStmt(Stmt
*S
, ErrorInfoTy
&ErrorInfo
);
12218 bool checkType(ErrorInfoTy
&ErrorInfo
);
12220 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
12221 // form of 'conditional-update-capture-atomic' structured block on the v5.2
12223 // (1) { v = x; cond-update-stmt }
12224 // (2) { cond-update-stmt v = x; }
12225 // (3) if(x == e) { x = d; } else { v = x; }
12226 // (4) { r = x == e; if(r) { x = d; } }
12227 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
12229 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
12230 bool checkForm3(IfStmt
*S
, ErrorInfoTy
&ErrorInfo
);
12232 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
12233 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
12234 bool checkForm45(Stmt
*S
, ErrorInfoTy
&ErrorInfo
);
12236 /// 'v' lvalue part of the source atomic expression.
12238 /// 'r' lvalue part of the source atomic expression.
12240 /// If 'v' is only updated when the comparison fails.
12241 bool IsFailOnly
= false;
12242 /// If original value of 'x' must be stored in 'v', not an updated one.
12243 bool IsPostfixUpdate
= false;
12246 bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy
&ErrorInfo
) {
12247 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo
))
12250 if (V
&& !CheckValue(V
, ErrorInfo
, true))
12253 if (R
&& !CheckValue(R
, ErrorInfo
, true, true))
12259 bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt
*S
,
12260 ErrorInfoTy
&ErrorInfo
) {
12263 auto *Then
= S
->getThen();
12264 if (auto *CS
= dyn_cast
<CompoundStmt
>(Then
)) {
12265 if (CS
->body_empty()) {
12266 ErrorInfo
.Error
= ErrorTy::NoStmt
;
12267 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
12268 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= CS
->getSourceRange();
12271 if (CS
->size() > 1) {
12272 ErrorInfo
.Error
= ErrorTy::MoreThanOneStmt
;
12273 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
12274 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= CS
->getSourceRange();
12277 Then
= CS
->body_front();
12280 auto *BO
= dyn_cast
<BinaryOperator
>(Then
);
12282 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12283 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Then
->getBeginLoc();
12284 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Then
->getSourceRange();
12287 if (BO
->getOpcode() != BO_Assign
) {
12288 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12289 ErrorInfo
.ErrorLoc
= BO
->getExprLoc();
12290 ErrorInfo
.NoteLoc
= BO
->getOperatorLoc();
12291 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= BO
->getSourceRange();
12298 auto *Cond
= dyn_cast
<BinaryOperator
>(S
->getCond());
12300 ErrorInfo
.Error
= ErrorTy::NotABinaryOp
;
12301 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= S
->getCond()->getExprLoc();
12302 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S
->getCond()->getSourceRange();
12305 if (Cond
->getOpcode() != BO_EQ
) {
12306 ErrorInfo
.Error
= ErrorTy::NotEQ
;
12307 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Cond
->getExprLoc();
12308 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Cond
->getSourceRange();
12312 if (checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getLHS())) {
12313 E
= Cond
->getRHS();
12314 } else if (checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getRHS())) {
12315 E
= Cond
->getLHS();
12317 ErrorInfo
.Error
= ErrorTy::InvalidComparison
;
12318 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Cond
->getExprLoc();
12319 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Cond
->getSourceRange();
12325 if (!S
->getElse()) {
12326 ErrorInfo
.Error
= ErrorTy::NoElse
;
12327 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= S
->getBeginLoc();
12328 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S
->getSourceRange();
12332 auto *Else
= S
->getElse();
12333 if (auto *CS
= dyn_cast
<CompoundStmt
>(Else
)) {
12334 if (CS
->body_empty()) {
12335 ErrorInfo
.Error
= ErrorTy::NoStmt
;
12336 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
12337 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= CS
->getSourceRange();
12340 if (CS
->size() > 1) {
12341 ErrorInfo
.Error
= ErrorTy::MoreThanOneStmt
;
12342 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
12343 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S
->getSourceRange();
12346 Else
= CS
->body_front();
12349 auto *ElseBO
= dyn_cast
<BinaryOperator
>(Else
);
12351 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12352 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Else
->getBeginLoc();
12353 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Else
->getSourceRange();
12356 if (ElseBO
->getOpcode() != BO_Assign
) {
12357 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12358 ErrorInfo
.ErrorLoc
= ElseBO
->getExprLoc();
12359 ErrorInfo
.NoteLoc
= ElseBO
->getOperatorLoc();
12360 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= ElseBO
->getSourceRange();
12364 if (!checkIfTwoExprsAreSame(ContextRef
, X
, ElseBO
->getRHS())) {
12365 ErrorInfo
.Error
= ErrorTy::InvalidAssignment
;
12366 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= ElseBO
->getRHS()->getExprLoc();
12367 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
=
12368 ElseBO
->getRHS()->getSourceRange();
12372 V
= ElseBO
->getLHS();
12374 return checkType(ErrorInfo
);
12377 bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt
*S
,
12378 ErrorInfoTy
&ErrorInfo
) {
12379 // We don't check here as they should be already done before call this
12381 auto *CS
= cast
<CompoundStmt
>(S
);
12382 assert(CS
->size() == 2 && "CompoundStmt size is not expected");
12383 auto *S1
= cast
<BinaryOperator
>(CS
->body_front());
12384 auto *S2
= cast
<IfStmt
>(CS
->body_back());
12385 assert(S1
->getOpcode() == BO_Assign
&& "unexpected binary operator");
12387 if (!checkIfTwoExprsAreSame(ContextRef
, S1
->getLHS(), S2
->getCond())) {
12388 ErrorInfo
.Error
= ErrorTy::InvalidCondition
;
12389 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= S2
->getCond()->getExprLoc();
12390 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S1
->getLHS()->getSourceRange();
12396 auto *Then
= S2
->getThen();
12397 if (auto *ThenCS
= dyn_cast
<CompoundStmt
>(Then
)) {
12398 if (ThenCS
->body_empty()) {
12399 ErrorInfo
.Error
= ErrorTy::NoStmt
;
12400 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= ThenCS
->getBeginLoc();
12401 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= ThenCS
->getSourceRange();
12404 if (ThenCS
->size() > 1) {
12405 ErrorInfo
.Error
= ErrorTy::MoreThanOneStmt
;
12406 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= ThenCS
->getBeginLoc();
12407 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= ThenCS
->getSourceRange();
12410 Then
= ThenCS
->body_front();
12413 auto *ThenBO
= dyn_cast
<BinaryOperator
>(Then
);
12415 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12416 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= S2
->getBeginLoc();
12417 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S2
->getSourceRange();
12420 if (ThenBO
->getOpcode() != BO_Assign
) {
12421 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12422 ErrorInfo
.ErrorLoc
= ThenBO
->getExprLoc();
12423 ErrorInfo
.NoteLoc
= ThenBO
->getOperatorLoc();
12424 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= ThenBO
->getSourceRange();
12428 X
= ThenBO
->getLHS();
12429 D
= ThenBO
->getRHS();
12431 auto *BO
= cast
<BinaryOperator
>(S1
->getRHS()->IgnoreImpCasts());
12432 if (BO
->getOpcode() != BO_EQ
) {
12433 ErrorInfo
.Error
= ErrorTy::NotEQ
;
12434 ErrorInfo
.ErrorLoc
= BO
->getExprLoc();
12435 ErrorInfo
.NoteLoc
= BO
->getOperatorLoc();
12436 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= BO
->getSourceRange();
12442 if (checkIfTwoExprsAreSame(ContextRef
, X
, BO
->getLHS())) {
12444 } else if (checkIfTwoExprsAreSame(ContextRef
, X
, BO
->getRHS())) {
12447 ErrorInfo
.Error
= ErrorTy::InvalidComparison
;
12448 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= BO
->getExprLoc();
12449 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= BO
->getSourceRange();
12453 if (S2
->getElse()) {
12456 auto *Else
= S2
->getElse();
12457 if (auto *ElseCS
= dyn_cast
<CompoundStmt
>(Else
)) {
12458 if (ElseCS
->body_empty()) {
12459 ErrorInfo
.Error
= ErrorTy::NoStmt
;
12460 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= ElseCS
->getBeginLoc();
12461 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= ElseCS
->getSourceRange();
12464 if (ElseCS
->size() > 1) {
12465 ErrorInfo
.Error
= ErrorTy::MoreThanOneStmt
;
12466 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= ElseCS
->getBeginLoc();
12467 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= ElseCS
->getSourceRange();
12470 Else
= ElseCS
->body_front();
12473 auto *ElseBO
= dyn_cast
<BinaryOperator
>(Else
);
12475 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12476 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Else
->getBeginLoc();
12477 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Else
->getSourceRange();
12480 if (ElseBO
->getOpcode() != BO_Assign
) {
12481 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12482 ErrorInfo
.ErrorLoc
= ElseBO
->getExprLoc();
12483 ErrorInfo
.NoteLoc
= ElseBO
->getOperatorLoc();
12484 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= ElseBO
->getSourceRange();
12487 if (!checkIfTwoExprsAreSame(ContextRef
, X
, ElseBO
->getRHS())) {
12488 ErrorInfo
.Error
= ErrorTy::InvalidAssignment
;
12489 ErrorInfo
.ErrorLoc
= ElseBO
->getRHS()->getExprLoc();
12490 ErrorInfo
.NoteLoc
= X
->getExprLoc();
12491 ErrorInfo
.ErrorRange
= ElseBO
->getRHS()->getSourceRange();
12492 ErrorInfo
.NoteRange
= X
->getSourceRange();
12496 V
= ElseBO
->getLHS();
12499 return checkType(ErrorInfo
);
12502 bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt
*S
,
12503 ErrorInfoTy
&ErrorInfo
) {
12504 // if(x == e) { x = d; } else { v = x; }
12505 if (auto *IS
= dyn_cast
<IfStmt
>(S
))
12506 return checkForm3(IS
, ErrorInfo
);
12508 auto *CS
= dyn_cast
<CompoundStmt
>(S
);
12510 ErrorInfo
.Error
= ErrorTy::NotCompoundStmt
;
12511 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= S
->getBeginLoc();
12512 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S
->getSourceRange();
12515 if (CS
->body_empty()) {
12516 ErrorInfo
.Error
= ErrorTy::NoStmt
;
12517 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
12518 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= CS
->getSourceRange();
12522 // { if(x == e) { x = d; } else { v = x; } }
12523 if (CS
->size() == 1) {
12524 auto *IS
= dyn_cast
<IfStmt
>(CS
->body_front());
12526 ErrorInfo
.Error
= ErrorTy::NotIfStmt
;
12527 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->body_front()->getBeginLoc();
12528 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
=
12529 CS
->body_front()->getSourceRange();
12533 return checkForm3(IS
, ErrorInfo
);
12534 } else if (CS
->size() == 2) {
12535 auto *S1
= CS
->body_front();
12536 auto *S2
= CS
->body_back();
12538 Stmt
*UpdateStmt
= nullptr;
12539 Stmt
*CondUpdateStmt
= nullptr;
12540 Stmt
*CondExprStmt
= nullptr;
12542 if (auto *BO
= dyn_cast
<BinaryOperator
>(S1
)) {
12543 // It could be one of the following cases:
12544 // { v = x; cond-update-stmt }
12545 // { v = x; cond-expr-stmt }
12546 // { cond-expr-stmt; v = x; }
12548 if (isa
<BinaryOperator
>(BO
->getRHS()->IgnoreImpCasts()) ||
12549 isa
<ConditionalOperator
>(BO
->getRHS()->IgnoreImpCasts())) {
12550 // check if form 45
12551 if (isa
<IfStmt
>(S2
))
12552 return checkForm45(CS
, ErrorInfo
);
12553 // { cond-expr-stmt; v = x; }
12557 IsPostfixUpdate
= true;
12559 if (isa
<IfStmt
>(S2
)) {
12560 // { v = x; cond-update-stmt }
12561 CondUpdateStmt
= S2
;
12563 // { v = x; cond-expr-stmt }
12568 // { cond-update-stmt v = x; }
12570 CondUpdateStmt
= S1
;
12573 auto CheckCondUpdateStmt
= [this, &ErrorInfo
](Stmt
*CUS
) {
12574 auto *IS
= dyn_cast
<IfStmt
>(CUS
);
12576 ErrorInfo
.Error
= ErrorTy::NotIfStmt
;
12577 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CUS
->getBeginLoc();
12578 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= CUS
->getSourceRange();
12582 return checkCondUpdateStmt(IS
, ErrorInfo
);
12585 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12586 auto CheckUpdateStmt
= [this, &ErrorInfo
](Stmt
*US
) {
12587 auto *BO
= dyn_cast
<BinaryOperator
>(US
);
12589 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12590 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= US
->getBeginLoc();
12591 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= US
->getSourceRange();
12594 if (BO
->getOpcode() != BO_Assign
) {
12595 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12596 ErrorInfo
.ErrorLoc
= BO
->getExprLoc();
12597 ErrorInfo
.NoteLoc
= BO
->getOperatorLoc();
12598 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= BO
->getSourceRange();
12601 if (!checkIfTwoExprsAreSame(ContextRef
, this->X
, BO
->getRHS())) {
12602 ErrorInfo
.Error
= ErrorTy::InvalidAssignment
;
12603 ErrorInfo
.ErrorLoc
= BO
->getRHS()->getExprLoc();
12604 ErrorInfo
.NoteLoc
= this->X
->getExprLoc();
12605 ErrorInfo
.ErrorRange
= BO
->getRHS()->getSourceRange();
12606 ErrorInfo
.NoteRange
= this->X
->getSourceRange();
12610 this->V
= BO
->getLHS();
12615 if (CondUpdateStmt
&& !CheckCondUpdateStmt(CondUpdateStmt
))
12617 if (CondExprStmt
&& !checkCondExprStmt(CondExprStmt
, ErrorInfo
))
12619 if (!CheckUpdateStmt(UpdateStmt
))
12622 ErrorInfo
.Error
= ErrorTy::MoreThanTwoStmts
;
12623 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
12624 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= CS
->getSourceRange();
12628 return checkType(ErrorInfo
);
12632 StmtResult
Sema::ActOnOpenMPAtomicDirective(ArrayRef
<OMPClause
*> Clauses
,
12634 SourceLocation StartLoc
,
12635 SourceLocation EndLoc
) {
12636 // Register location of the first atomic directive.
12637 DSAStack
->addAtomicDirectiveLoc(StartLoc
);
12639 return StmtError();
12641 // 1.2.2 OpenMP Language Terminology
12642 // Structured block - An executable statement with a single entry at the
12643 // top and a single exit at the bottom.
12644 // The point of exit cannot be a branch out of the structured block.
12645 // longjmp() and throw() must not violate the entry/exit criteria.
12646 OpenMPClauseKind AtomicKind
= OMPC_unknown
;
12647 SourceLocation AtomicKindLoc
;
12648 OpenMPClauseKind MemOrderKind
= OMPC_unknown
;
12649 SourceLocation MemOrderLoc
;
12650 bool MutexClauseEncountered
= false;
12651 llvm::SmallSet
<OpenMPClauseKind
, 2> EncounteredAtomicKinds
;
12652 for (const OMPClause
*C
: Clauses
) {
12653 switch (C
->getClauseKind()) {
12657 MutexClauseEncountered
= true;
12660 case OMPC_compare
: {
12661 if (AtomicKind
!= OMPC_unknown
&& MutexClauseEncountered
) {
12662 Diag(C
->getBeginLoc(), diag::err_omp_atomic_several_clauses
)
12663 << SourceRange(C
->getBeginLoc(), C
->getEndLoc());
12664 Diag(AtomicKindLoc
, diag::note_omp_previous_mem_order_clause
)
12665 << getOpenMPClauseName(AtomicKind
);
12667 AtomicKind
= C
->getClauseKind();
12668 AtomicKindLoc
= C
->getBeginLoc();
12669 if (!EncounteredAtomicKinds
.insert(C
->getClauseKind()).second
) {
12670 Diag(C
->getBeginLoc(), diag::err_omp_atomic_several_clauses
)
12671 << SourceRange(C
->getBeginLoc(), C
->getEndLoc());
12672 Diag(AtomicKindLoc
, diag::note_omp_previous_mem_order_clause
)
12673 << getOpenMPClauseName(AtomicKind
);
12682 case OMPC_relaxed
: {
12683 if (MemOrderKind
!= OMPC_unknown
) {
12684 Diag(C
->getBeginLoc(), diag::err_omp_several_mem_order_clauses
)
12685 << getOpenMPDirectiveName(OMPD_atomic
) << 0
12686 << SourceRange(C
->getBeginLoc(), C
->getEndLoc());
12687 Diag(MemOrderLoc
, diag::note_omp_previous_mem_order_clause
)
12688 << getOpenMPClauseName(MemOrderKind
);
12690 MemOrderKind
= C
->getClauseKind();
12691 MemOrderLoc
= C
->getBeginLoc();
12695 // The following clauses are allowed, but we don't need to do anything here.
12699 llvm_unreachable("unknown clause is encountered");
12702 bool IsCompareCapture
= false;
12703 if (EncounteredAtomicKinds
.contains(OMPC_compare
) &&
12704 EncounteredAtomicKinds
.contains(OMPC_capture
)) {
12705 IsCompareCapture
= true;
12706 AtomicKind
= OMPC_compare
;
12708 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12709 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12711 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12713 // If atomic-clause is update or not present then memory-order-clause must not
12714 // be acq_rel or acquire.
12715 if ((AtomicKind
== OMPC_read
&&
12716 (MemOrderKind
== OMPC_acq_rel
|| MemOrderKind
== OMPC_release
)) ||
12717 ((AtomicKind
== OMPC_write
|| AtomicKind
== OMPC_update
||
12718 AtomicKind
== OMPC_unknown
) &&
12719 (MemOrderKind
== OMPC_acq_rel
|| MemOrderKind
== OMPC_acquire
))) {
12720 SourceLocation Loc
= AtomicKindLoc
;
12721 if (AtomicKind
== OMPC_unknown
)
12723 Diag(Loc
, diag::err_omp_atomic_incompatible_mem_order_clause
)
12724 << getOpenMPClauseName(AtomicKind
)
12725 << (AtomicKind
== OMPC_unknown
? 1 : 0)
12726 << getOpenMPClauseName(MemOrderKind
);
12727 Diag(MemOrderLoc
, diag::note_omp_previous_mem_order_clause
)
12728 << getOpenMPClauseName(MemOrderKind
);
12731 Stmt
*Body
= AStmt
;
12732 if (auto *EWC
= dyn_cast
<ExprWithCleanups
>(Body
))
12733 Body
= EWC
->getSubExpr();
12738 Expr
*UE
= nullptr;
12740 Expr
*CE
= nullptr;
12742 bool IsXLHSInRHSPart
= false;
12743 bool IsPostfixUpdate
= false;
12744 bool IsFailOnly
= false;
12745 // OpenMP [2.12.6, atomic Construct]
12746 // In the next expressions:
12747 // * x and v (as applicable) are both l-value expressions with scalar type.
12748 // * During the execution of an atomic region, multiple syntactic
12749 // occurrences of x must designate the same storage location.
12750 // * Neither of v and expr (as applicable) may access the storage location
12751 // designated by x.
12752 // * Neither of x and expr (as applicable) may access the storage location
12753 // designated by v.
12754 // * expr is an expression with scalar type.
12755 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12756 // * binop, binop=, ++, and -- are not overloaded operators.
12757 // * The expression x binop expr must be numerically equivalent to x binop
12758 // (expr). This requirement is satisfied if the operators in expr have
12759 // precedence greater than binop, or by using parentheses around expr or
12760 // subexpressions of expr.
12761 // * The expression expr binop x must be numerically equivalent to (expr)
12762 // binop x. This requirement is satisfied if the operators in expr have
12763 // precedence equal to or greater than binop, or by using parentheses around
12764 // expr or subexpressions of expr.
12765 // * For forms that allow multiple occurrences of x, the number of times
12766 // that x is evaluated is unspecified.
12767 if (AtomicKind
== OMPC_read
) {
12774 } ErrorFound
= NoError
;
12775 SourceLocation ErrorLoc
, NoteLoc
;
12776 SourceRange ErrorRange
, NoteRange
;
12777 // If clause is read:
12779 if (const auto *AtomicBody
= dyn_cast
<Expr
>(Body
)) {
12780 const auto *AtomicBinOp
=
12781 dyn_cast
<BinaryOperator
>(AtomicBody
->IgnoreParenImpCasts());
12782 if (AtomicBinOp
&& AtomicBinOp
->getOpcode() == BO_Assign
) {
12783 X
= AtomicBinOp
->getRHS()->IgnoreParenImpCasts();
12784 V
= AtomicBinOp
->getLHS()->IgnoreParenImpCasts();
12785 if ((X
->isInstantiationDependent() || X
->getType()->isScalarType()) &&
12786 (V
->isInstantiationDependent() || V
->getType()->isScalarType())) {
12787 if (!X
->isLValue() || !V
->isLValue()) {
12788 const Expr
*NotLValueExpr
= X
->isLValue() ? V
: X
;
12789 ErrorFound
= NotAnLValue
;
12790 ErrorLoc
= AtomicBinOp
->getExprLoc();
12791 ErrorRange
= AtomicBinOp
->getSourceRange();
12792 NoteLoc
= NotLValueExpr
->getExprLoc();
12793 NoteRange
= NotLValueExpr
->getSourceRange();
12795 } else if (!X
->isInstantiationDependent() ||
12796 !V
->isInstantiationDependent()) {
12797 const Expr
*NotScalarExpr
=
12798 (X
->isInstantiationDependent() || X
->getType()->isScalarType())
12801 ErrorFound
= NotAScalarType
;
12802 ErrorLoc
= AtomicBinOp
->getExprLoc();
12803 ErrorRange
= AtomicBinOp
->getSourceRange();
12804 NoteLoc
= NotScalarExpr
->getExprLoc();
12805 NoteRange
= NotScalarExpr
->getSourceRange();
12807 } else if (!AtomicBody
->isInstantiationDependent()) {
12808 ErrorFound
= NotAnAssignmentOp
;
12809 ErrorLoc
= AtomicBody
->getExprLoc();
12810 ErrorRange
= AtomicBody
->getSourceRange();
12811 NoteLoc
= AtomicBinOp
? AtomicBinOp
->getOperatorLoc()
12812 : AtomicBody
->getExprLoc();
12813 NoteRange
= AtomicBinOp
? AtomicBinOp
->getSourceRange()
12814 : AtomicBody
->getSourceRange();
12817 ErrorFound
= NotAnExpression
;
12818 NoteLoc
= ErrorLoc
= Body
->getBeginLoc();
12819 NoteRange
= ErrorRange
= SourceRange(NoteLoc
, NoteLoc
);
12821 if (ErrorFound
!= NoError
) {
12822 Diag(ErrorLoc
, diag::err_omp_atomic_read_not_expression_statement
)
12824 Diag(NoteLoc
, diag::note_omp_atomic_read_write
)
12825 << ErrorFound
<< NoteRange
;
12826 return StmtError();
12828 if (CurContext
->isDependentContext())
12830 } else if (AtomicKind
== OMPC_write
) {
12837 } ErrorFound
= NoError
;
12838 SourceLocation ErrorLoc
, NoteLoc
;
12839 SourceRange ErrorRange
, NoteRange
;
12840 // If clause is write:
12842 if (const auto *AtomicBody
= dyn_cast
<Expr
>(Body
)) {
12843 const auto *AtomicBinOp
=
12844 dyn_cast
<BinaryOperator
>(AtomicBody
->IgnoreParenImpCasts());
12845 if (AtomicBinOp
&& AtomicBinOp
->getOpcode() == BO_Assign
) {
12846 X
= AtomicBinOp
->getLHS();
12847 E
= AtomicBinOp
->getRHS();
12848 if ((X
->isInstantiationDependent() || X
->getType()->isScalarType()) &&
12849 (E
->isInstantiationDependent() || E
->getType()->isScalarType())) {
12850 if (!X
->isLValue()) {
12851 ErrorFound
= NotAnLValue
;
12852 ErrorLoc
= AtomicBinOp
->getExprLoc();
12853 ErrorRange
= AtomicBinOp
->getSourceRange();
12854 NoteLoc
= X
->getExprLoc();
12855 NoteRange
= X
->getSourceRange();
12857 } else if (!X
->isInstantiationDependent() ||
12858 !E
->isInstantiationDependent()) {
12859 const Expr
*NotScalarExpr
=
12860 (X
->isInstantiationDependent() || X
->getType()->isScalarType())
12863 ErrorFound
= NotAScalarType
;
12864 ErrorLoc
= AtomicBinOp
->getExprLoc();
12865 ErrorRange
= AtomicBinOp
->getSourceRange();
12866 NoteLoc
= NotScalarExpr
->getExprLoc();
12867 NoteRange
= NotScalarExpr
->getSourceRange();
12869 } else if (!AtomicBody
->isInstantiationDependent()) {
12870 ErrorFound
= NotAnAssignmentOp
;
12871 ErrorLoc
= AtomicBody
->getExprLoc();
12872 ErrorRange
= AtomicBody
->getSourceRange();
12873 NoteLoc
= AtomicBinOp
? AtomicBinOp
->getOperatorLoc()
12874 : AtomicBody
->getExprLoc();
12875 NoteRange
= AtomicBinOp
? AtomicBinOp
->getSourceRange()
12876 : AtomicBody
->getSourceRange();
12879 ErrorFound
= NotAnExpression
;
12880 NoteLoc
= ErrorLoc
= Body
->getBeginLoc();
12881 NoteRange
= ErrorRange
= SourceRange(NoteLoc
, NoteLoc
);
12883 if (ErrorFound
!= NoError
) {
12884 Diag(ErrorLoc
, diag::err_omp_atomic_write_not_expression_statement
)
12886 Diag(NoteLoc
, diag::note_omp_atomic_read_write
)
12887 << ErrorFound
<< NoteRange
;
12888 return StmtError();
12890 if (CurContext
->isDependentContext())
12892 } else if (AtomicKind
== OMPC_update
|| AtomicKind
== OMPC_unknown
) {
12893 // If clause is update:
12899 // x = x binop expr;
12900 // x = expr binop x;
12901 OpenMPAtomicUpdateChecker
Checker(*this);
12902 if (Checker
.checkStatement(
12904 (AtomicKind
== OMPC_update
)
12905 ? diag::err_omp_atomic_update_not_expression_statement
12906 : diag::err_omp_atomic_not_expression_statement
,
12907 diag::note_omp_atomic_update
))
12908 return StmtError();
12909 if (!CurContext
->isDependentContext()) {
12910 E
= Checker
.getExpr();
12911 X
= Checker
.getX();
12912 UE
= Checker
.getUpdateExpr();
12913 IsXLHSInRHSPart
= Checker
.isXLHSInRHSPart();
12915 } else if (AtomicKind
== OMPC_capture
) {
12918 NotACompoundStatement
,
12919 NotTwoSubstatements
,
12920 NotASpecificExpression
,
12922 } ErrorFound
= NoError
;
12923 SourceLocation ErrorLoc
, NoteLoc
;
12924 SourceRange ErrorRange
, NoteRange
;
12925 if (const auto *AtomicBody
= dyn_cast
<Expr
>(Body
)) {
12926 // If clause is a capture:
12931 // v = x binop= expr;
12932 // v = x = x binop expr;
12933 // v = x = expr binop x;
12934 const auto *AtomicBinOp
=
12935 dyn_cast
<BinaryOperator
>(AtomicBody
->IgnoreParenImpCasts());
12936 if (AtomicBinOp
&& AtomicBinOp
->getOpcode() == BO_Assign
) {
12937 V
= AtomicBinOp
->getLHS();
12938 Body
= AtomicBinOp
->getRHS()->IgnoreParenImpCasts();
12939 OpenMPAtomicUpdateChecker
Checker(*this);
12940 if (Checker
.checkStatement(
12941 Body
, diag::err_omp_atomic_capture_not_expression_statement
,
12942 diag::note_omp_atomic_update
))
12943 return StmtError();
12944 E
= Checker
.getExpr();
12945 X
= Checker
.getX();
12946 UE
= Checker
.getUpdateExpr();
12947 IsXLHSInRHSPart
= Checker
.isXLHSInRHSPart();
12948 IsPostfixUpdate
= Checker
.isPostfixUpdate();
12949 } else if (!AtomicBody
->isInstantiationDependent()) {
12950 ErrorLoc
= AtomicBody
->getExprLoc();
12951 ErrorRange
= AtomicBody
->getSourceRange();
12952 NoteLoc
= AtomicBinOp
? AtomicBinOp
->getOperatorLoc()
12953 : AtomicBody
->getExprLoc();
12954 NoteRange
= AtomicBinOp
? AtomicBinOp
->getSourceRange()
12955 : AtomicBody
->getSourceRange();
12956 ErrorFound
= NotAnAssignmentOp
;
12958 if (ErrorFound
!= NoError
) {
12959 Diag(ErrorLoc
, diag::err_omp_atomic_capture_not_expression_statement
)
12961 Diag(NoteLoc
, diag::note_omp_atomic_capture
) << ErrorFound
<< NoteRange
;
12962 return StmtError();
12964 if (CurContext
->isDependentContext())
12965 UE
= V
= E
= X
= nullptr;
12967 // If clause is a capture:
12968 // { v = x; x = expr; }
12973 // { v = x; x binop= expr; }
12974 // { v = x; x = x binop expr; }
12975 // { v = x; x = expr binop x; }
12980 // { x binop= expr; v = x; }
12981 // { x = x binop expr; v = x; }
12982 // { x = expr binop x; v = x; }
12983 if (auto *CS
= dyn_cast
<CompoundStmt
>(Body
)) {
12984 // Check that this is { expr1; expr2; }
12985 if (CS
->size() == 2) {
12986 Stmt
*First
= CS
->body_front();
12987 Stmt
*Second
= CS
->body_back();
12988 if (auto *EWC
= dyn_cast
<ExprWithCleanups
>(First
))
12989 First
= EWC
->getSubExpr()->IgnoreParenImpCasts();
12990 if (auto *EWC
= dyn_cast
<ExprWithCleanups
>(Second
))
12991 Second
= EWC
->getSubExpr()->IgnoreParenImpCasts();
12992 // Need to find what subexpression is 'v' and what is 'x'.
12993 OpenMPAtomicUpdateChecker
Checker(*this);
12994 bool IsUpdateExprFound
= !Checker
.checkStatement(Second
);
12995 BinaryOperator
*BinOp
= nullptr;
12996 if (IsUpdateExprFound
) {
12997 BinOp
= dyn_cast
<BinaryOperator
>(First
);
12998 IsUpdateExprFound
= BinOp
&& BinOp
->getOpcode() == BO_Assign
;
13000 if (IsUpdateExprFound
&& !CurContext
->isDependentContext()) {
13005 // { v = x; x binop= expr; }
13006 // { v = x; x = x binop expr; }
13007 // { v = x; x = expr binop x; }
13008 // Check that the first expression has form v = x.
13009 Expr
*PossibleX
= BinOp
->getRHS()->IgnoreParenImpCasts();
13010 llvm::FoldingSetNodeID XId
, PossibleXId
;
13011 Checker
.getX()->Profile(XId
, Context
, /*Canonical=*/true);
13012 PossibleX
->Profile(PossibleXId
, Context
, /*Canonical=*/true);
13013 IsUpdateExprFound
= XId
== PossibleXId
;
13014 if (IsUpdateExprFound
) {
13015 V
= BinOp
->getLHS();
13016 X
= Checker
.getX();
13017 E
= Checker
.getExpr();
13018 UE
= Checker
.getUpdateExpr();
13019 IsXLHSInRHSPart
= Checker
.isXLHSInRHSPart();
13020 IsPostfixUpdate
= true;
13023 if (!IsUpdateExprFound
) {
13024 IsUpdateExprFound
= !Checker
.checkStatement(First
);
13026 if (IsUpdateExprFound
) {
13027 BinOp
= dyn_cast
<BinaryOperator
>(Second
);
13028 IsUpdateExprFound
= BinOp
&& BinOp
->getOpcode() == BO_Assign
;
13030 if (IsUpdateExprFound
&& !CurContext
->isDependentContext()) {
13035 // { x binop= expr; v = x; }
13036 // { x = x binop expr; v = x; }
13037 // { x = expr binop x; v = x; }
13038 // Check that the second expression has form v = x.
13039 Expr
*PossibleX
= BinOp
->getRHS()->IgnoreParenImpCasts();
13040 llvm::FoldingSetNodeID XId
, PossibleXId
;
13041 Checker
.getX()->Profile(XId
, Context
, /*Canonical=*/true);
13042 PossibleX
->Profile(PossibleXId
, Context
, /*Canonical=*/true);
13043 IsUpdateExprFound
= XId
== PossibleXId
;
13044 if (IsUpdateExprFound
) {
13045 V
= BinOp
->getLHS();
13046 X
= Checker
.getX();
13047 E
= Checker
.getExpr();
13048 UE
= Checker
.getUpdateExpr();
13049 IsXLHSInRHSPart
= Checker
.isXLHSInRHSPart();
13050 IsPostfixUpdate
= false;
13054 if (!IsUpdateExprFound
) {
13055 // { v = x; x = expr; }
13056 auto *FirstExpr
= dyn_cast
<Expr
>(First
);
13057 auto *SecondExpr
= dyn_cast
<Expr
>(Second
);
13058 if (!FirstExpr
|| !SecondExpr
||
13059 !(FirstExpr
->isInstantiationDependent() ||
13060 SecondExpr
->isInstantiationDependent())) {
13061 auto *FirstBinOp
= dyn_cast
<BinaryOperator
>(First
);
13062 if (!FirstBinOp
|| FirstBinOp
->getOpcode() != BO_Assign
) {
13063 ErrorFound
= NotAnAssignmentOp
;
13064 NoteLoc
= ErrorLoc
= FirstBinOp
? FirstBinOp
->getOperatorLoc()
13065 : First
->getBeginLoc();
13066 NoteRange
= ErrorRange
= FirstBinOp
13067 ? FirstBinOp
->getSourceRange()
13068 : SourceRange(ErrorLoc
, ErrorLoc
);
13070 auto *SecondBinOp
= dyn_cast
<BinaryOperator
>(Second
);
13071 if (!SecondBinOp
|| SecondBinOp
->getOpcode() != BO_Assign
) {
13072 ErrorFound
= NotAnAssignmentOp
;
13073 NoteLoc
= ErrorLoc
= SecondBinOp
13074 ? SecondBinOp
->getOperatorLoc()
13075 : Second
->getBeginLoc();
13076 NoteRange
= ErrorRange
=
13077 SecondBinOp
? SecondBinOp
->getSourceRange()
13078 : SourceRange(ErrorLoc
, ErrorLoc
);
13080 Expr
*PossibleXRHSInFirst
=
13081 FirstBinOp
->getRHS()->IgnoreParenImpCasts();
13082 Expr
*PossibleXLHSInSecond
=
13083 SecondBinOp
->getLHS()->IgnoreParenImpCasts();
13084 llvm::FoldingSetNodeID X1Id
, X2Id
;
13085 PossibleXRHSInFirst
->Profile(X1Id
, Context
,
13086 /*Canonical=*/true);
13087 PossibleXLHSInSecond
->Profile(X2Id
, Context
,
13088 /*Canonical=*/true);
13089 IsUpdateExprFound
= X1Id
== X2Id
;
13090 if (IsUpdateExprFound
) {
13091 V
= FirstBinOp
->getLHS();
13092 X
= SecondBinOp
->getLHS();
13093 E
= SecondBinOp
->getRHS();
13095 IsXLHSInRHSPart
= false;
13096 IsPostfixUpdate
= true;
13098 ErrorFound
= NotASpecificExpression
;
13099 ErrorLoc
= FirstBinOp
->getExprLoc();
13100 ErrorRange
= FirstBinOp
->getSourceRange();
13101 NoteLoc
= SecondBinOp
->getLHS()->getExprLoc();
13102 NoteRange
= SecondBinOp
->getRHS()->getSourceRange();
13109 NoteLoc
= ErrorLoc
= Body
->getBeginLoc();
13110 NoteRange
= ErrorRange
=
13111 SourceRange(Body
->getBeginLoc(), Body
->getBeginLoc());
13112 ErrorFound
= NotTwoSubstatements
;
13115 NoteLoc
= ErrorLoc
= Body
->getBeginLoc();
13116 NoteRange
= ErrorRange
=
13117 SourceRange(Body
->getBeginLoc(), Body
->getBeginLoc());
13118 ErrorFound
= NotACompoundStatement
;
13121 if (ErrorFound
!= NoError
) {
13122 Diag(ErrorLoc
, diag::err_omp_atomic_capture_not_compound_statement
)
13124 Diag(NoteLoc
, diag::note_omp_atomic_capture
) << ErrorFound
<< NoteRange
;
13125 return StmtError();
13127 if (CurContext
->isDependentContext())
13128 UE
= V
= E
= X
= nullptr;
13129 } else if (AtomicKind
== OMPC_compare
) {
13130 if (IsCompareCapture
) {
13131 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo
;
13132 OpenMPAtomicCompareCaptureChecker
Checker(*this);
13133 if (!Checker
.checkStmt(Body
, ErrorInfo
)) {
13134 Diag(ErrorInfo
.ErrorLoc
, diag::err_omp_atomic_compare_capture
)
13135 << ErrorInfo
.ErrorRange
;
13136 Diag(ErrorInfo
.NoteLoc
, diag::note_omp_atomic_compare
)
13137 << ErrorInfo
.Error
<< ErrorInfo
.NoteRange
;
13138 return StmtError();
13140 X
= Checker
.getX();
13141 E
= Checker
.getE();
13142 D
= Checker
.getD();
13143 CE
= Checker
.getCond();
13144 V
= Checker
.getV();
13145 R
= Checker
.getR();
13146 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13147 IsXLHSInRHSPart
= Checker
.isXBinopExpr();
13148 IsFailOnly
= Checker
.isFailOnly();
13149 IsPostfixUpdate
= Checker
.isPostfixUpdate();
13151 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo
;
13152 OpenMPAtomicCompareChecker
Checker(*this);
13153 if (!Checker
.checkStmt(Body
, ErrorInfo
)) {
13154 Diag(ErrorInfo
.ErrorLoc
, diag::err_omp_atomic_compare
)
13155 << ErrorInfo
.ErrorRange
;
13156 Diag(ErrorInfo
.NoteLoc
, diag::note_omp_atomic_compare
)
13157 << ErrorInfo
.Error
<< ErrorInfo
.NoteRange
;
13158 return StmtError();
13160 X
= Checker
.getX();
13161 E
= Checker
.getE();
13162 D
= Checker
.getD();
13163 CE
= Checker
.getCond();
13164 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13165 IsXLHSInRHSPart
= Checker
.isXBinopExpr();
13169 setFunctionHasBranchProtectedScope();
13171 return OMPAtomicDirective::Create(
13172 Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
13173 {X
, V
, R
, E
, UE
, D
, CE
, IsXLHSInRHSPart
, IsPostfixUpdate
, IsFailOnly
});
13176 StmtResult
Sema::ActOnOpenMPTargetDirective(ArrayRef
<OMPClause
*> Clauses
,
13178 SourceLocation StartLoc
,
13179 SourceLocation EndLoc
) {
13181 return StmtError();
13183 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13184 // 1.2.2 OpenMP Language Terminology
13185 // Structured block - An executable statement with a single entry at the
13186 // top and a single exit at the bottom.
13187 // The point of exit cannot be a branch out of the structured block.
13188 // longjmp() and throw() must not violate the entry/exit criteria.
13189 CS
->getCapturedDecl()->setNothrow();
13190 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target
);
13191 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
13192 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
13193 // 1.2.2 OpenMP Language Terminology
13194 // Structured block - An executable statement with a single entry at the
13195 // top and a single exit at the bottom.
13196 // The point of exit cannot be a branch out of the structured block.
13197 // longjmp() and throw() must not violate the entry/exit criteria.
13198 CS
->getCapturedDecl()->setNothrow();
13201 // OpenMP [2.16, Nesting of Regions]
13202 // If specified, a teams construct must be contained within a target
13203 // construct. That target construct must contain no statements or directives
13204 // outside of the teams construct.
13205 if (DSAStack
->hasInnerTeamsRegion()) {
13206 const Stmt
*S
= CS
->IgnoreContainers(/*IgnoreCaptured=*/true);
13207 bool OMPTeamsFound
= true;
13208 if (const auto *CS
= dyn_cast
<CompoundStmt
>(S
)) {
13209 auto I
= CS
->body_begin();
13210 while (I
!= CS
->body_end()) {
13211 const auto *OED
= dyn_cast
<OMPExecutableDirective
>(*I
);
13212 if (!OED
|| !isOpenMPTeamsDirective(OED
->getDirectiveKind()) ||
13215 OMPTeamsFound
= false;
13220 assert(I
!= CS
->body_end() && "Not found statement");
13223 const auto *OED
= dyn_cast
<OMPExecutableDirective
>(S
);
13224 OMPTeamsFound
= OED
&& isOpenMPTeamsDirective(OED
->getDirectiveKind());
13226 if (!OMPTeamsFound
) {
13227 Diag(StartLoc
, diag::err_omp_target_contains_not_only_teams
);
13228 Diag(DSAStack
->getInnerTeamsRegionLoc(),
13229 diag::note_omp_nested_teams_construct_here
);
13230 Diag(S
->getBeginLoc(), diag::note_omp_nested_statement_here
)
13231 << isa
<OMPExecutableDirective
>(S
);
13232 return StmtError();
13236 setFunctionHasBranchProtectedScope();
13238 return OMPTargetDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
);
13242 Sema::ActOnOpenMPTargetParallelDirective(ArrayRef
<OMPClause
*> Clauses
,
13243 Stmt
*AStmt
, SourceLocation StartLoc
,
13244 SourceLocation EndLoc
) {
13246 return StmtError();
13248 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13249 // 1.2.2 OpenMP Language Terminology
13250 // Structured block - An executable statement with a single entry at the
13251 // top and a single exit at the bottom.
13252 // The point of exit cannot be a branch out of the structured block.
13253 // longjmp() and throw() must not violate the entry/exit criteria.
13254 CS
->getCapturedDecl()->setNothrow();
13255 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_parallel
);
13256 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
13257 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
13258 // 1.2.2 OpenMP Language Terminology
13259 // Structured block - An executable statement with a single entry at the
13260 // top and a single exit at the bottom.
13261 // The point of exit cannot be a branch out of the structured block.
13262 // longjmp() and throw() must not violate the entry/exit criteria.
13263 CS
->getCapturedDecl()->setNothrow();
13266 setFunctionHasBranchProtectedScope();
13268 return OMPTargetParallelDirective::Create(
13269 Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
13270 DSAStack
->getTaskgroupReductionRef(), DSAStack
->isCancelRegion());
13273 StmtResult
Sema::ActOnOpenMPTargetParallelForDirective(
13274 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13275 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13277 return StmtError();
13279 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13280 // 1.2.2 OpenMP Language Terminology
13281 // Structured block - An executable statement with a single entry at the
13282 // top and a single exit at the bottom.
13283 // The point of exit cannot be a branch out of the structured block.
13284 // longjmp() and throw() must not violate the entry/exit criteria.
13285 CS
->getCapturedDecl()->setNothrow();
13286 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_parallel_for
);
13287 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
13288 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
13289 // 1.2.2 OpenMP Language Terminology
13290 // Structured block - An executable statement with a single entry at the
13291 // top and a single exit at the bottom.
13292 // The point of exit cannot be a branch out of the structured block.
13293 // longjmp() and throw() must not violate the entry/exit criteria.
13294 CS
->getCapturedDecl()->setNothrow();
13297 OMPLoopBasedDirective::HelperExprs B
;
13298 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13299 // define the nested loops number.
13300 unsigned NestedLoopCount
=
13301 checkOpenMPLoop(OMPD_target_parallel_for
, getCollapseNumberExpr(Clauses
),
13302 getOrderedNumberExpr(Clauses
), CS
, *this, *DSAStack
,
13303 VarsWithImplicitDSA
, B
);
13304 if (NestedLoopCount
== 0)
13305 return StmtError();
13307 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13308 "omp target parallel for loop exprs were not built");
13310 if (!CurContext
->isDependentContext()) {
13311 // Finalize the clauses that need pre-built expressions for CodeGen.
13312 for (OMPClause
*C
: Clauses
) {
13313 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
13314 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
13315 B
.NumIterations
, *this, CurScope
,
13317 return StmtError();
13321 setFunctionHasBranchProtectedScope();
13322 return OMPTargetParallelForDirective::Create(
13323 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
,
13324 DSAStack
->getTaskgroupReductionRef(), DSAStack
->isCancelRegion());
13327 /// Check for existence of a map clause in the list of clauses.
13328 static bool hasClauses(ArrayRef
<OMPClause
*> Clauses
,
13329 const OpenMPClauseKind K
) {
13330 return llvm::any_of(
13331 Clauses
, [K
](const OMPClause
*C
) { return C
->getClauseKind() == K
; });
13334 template <typename
... Params
>
13335 static bool hasClauses(ArrayRef
<OMPClause
*> Clauses
, const OpenMPClauseKind K
,
13336 const Params
... ClauseTypes
) {
13337 return hasClauses(Clauses
, K
) || hasClauses(Clauses
, ClauseTypes
...);
13340 /// Check if the variables in the mapping clause are externally visible.
13341 static bool isClauseMappable(ArrayRef
<OMPClause
*> Clauses
) {
13342 for (const OMPClause
*C
: Clauses
) {
13343 if (auto *TC
= dyn_cast
<OMPToClause
>(C
))
13344 return llvm::all_of(TC
->all_decls(), [](ValueDecl
*VD
) {
13345 return !VD
|| !VD
->hasAttr
<OMPDeclareTargetDeclAttr
>() ||
13346 (VD
->isExternallyVisible() &&
13347 VD
->getVisibility() != HiddenVisibility
);
13349 else if (auto *FC
= dyn_cast
<OMPFromClause
>(C
))
13350 return llvm::all_of(FC
->all_decls(), [](ValueDecl
*VD
) {
13351 return !VD
|| !VD
->hasAttr
<OMPDeclareTargetDeclAttr
>() ||
13352 (VD
->isExternallyVisible() &&
13353 VD
->getVisibility() != HiddenVisibility
);
13360 StmtResult
Sema::ActOnOpenMPTargetDataDirective(ArrayRef
<OMPClause
*> Clauses
,
13362 SourceLocation StartLoc
,
13363 SourceLocation EndLoc
) {
13365 return StmtError();
13367 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13369 // OpenMP [2.12.2, target data Construct, Restrictions]
13370 // At least one map, use_device_addr or use_device_ptr clause must appear on
13372 if (!hasClauses(Clauses
, OMPC_map
, OMPC_use_device_ptr
) &&
13373 (LangOpts
.OpenMP
< 50 || !hasClauses(Clauses
, OMPC_use_device_addr
))) {
13374 StringRef Expected
;
13375 if (LangOpts
.OpenMP
< 50)
13376 Expected
= "'map' or 'use_device_ptr'";
13378 Expected
= "'map', 'use_device_ptr', or 'use_device_addr'";
13379 Diag(StartLoc
, diag::err_omp_no_clause_for_directive
)
13380 << Expected
<< getOpenMPDirectiveName(OMPD_target_data
);
13381 return StmtError();
13384 setFunctionHasBranchProtectedScope();
13386 return OMPTargetDataDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
,
13391 Sema::ActOnOpenMPTargetEnterDataDirective(ArrayRef
<OMPClause
*> Clauses
,
13392 SourceLocation StartLoc
,
13393 SourceLocation EndLoc
, Stmt
*AStmt
) {
13395 return StmtError();
13397 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13398 // 1.2.2 OpenMP Language Terminology
13399 // Structured block - An executable statement with a single entry at the
13400 // top and a single exit at the bottom.
13401 // The point of exit cannot be a branch out of the structured block.
13402 // longjmp() and throw() must not violate the entry/exit criteria.
13403 CS
->getCapturedDecl()->setNothrow();
13404 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_enter_data
);
13405 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
13406 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
13407 // 1.2.2 OpenMP Language Terminology
13408 // Structured block - An executable statement with a single entry at the
13409 // top and a single exit at the bottom.
13410 // The point of exit cannot be a branch out of the structured block.
13411 // longjmp() and throw() must not violate the entry/exit criteria.
13412 CS
->getCapturedDecl()->setNothrow();
13415 // OpenMP [2.10.2, Restrictions, p. 99]
13416 // At least one map clause must appear on the directive.
13417 if (!hasClauses(Clauses
, OMPC_map
)) {
13418 Diag(StartLoc
, diag::err_omp_no_clause_for_directive
)
13419 << "'map'" << getOpenMPDirectiveName(OMPD_target_enter_data
);
13420 return StmtError();
13423 return OMPTargetEnterDataDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
,
13428 Sema::ActOnOpenMPTargetExitDataDirective(ArrayRef
<OMPClause
*> Clauses
,
13429 SourceLocation StartLoc
,
13430 SourceLocation EndLoc
, Stmt
*AStmt
) {
13432 return StmtError();
13434 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13435 // 1.2.2 OpenMP Language Terminology
13436 // Structured block - An executable statement with a single entry at the
13437 // top and a single exit at the bottom.
13438 // The point of exit cannot be a branch out of the structured block.
13439 // longjmp() and throw() must not violate the entry/exit criteria.
13440 CS
->getCapturedDecl()->setNothrow();
13441 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_exit_data
);
13442 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
13443 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
13444 // 1.2.2 OpenMP Language Terminology
13445 // Structured block - An executable statement with a single entry at the
13446 // top and a single exit at the bottom.
13447 // The point of exit cannot be a branch out of the structured block.
13448 // longjmp() and throw() must not violate the entry/exit criteria.
13449 CS
->getCapturedDecl()->setNothrow();
13452 // OpenMP [2.10.3, Restrictions, p. 102]
13453 // At least one map clause must appear on the directive.
13454 if (!hasClauses(Clauses
, OMPC_map
)) {
13455 Diag(StartLoc
, diag::err_omp_no_clause_for_directive
)
13456 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data
);
13457 return StmtError();
13460 return OMPTargetExitDataDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
,
13464 StmtResult
Sema::ActOnOpenMPTargetUpdateDirective(ArrayRef
<OMPClause
*> Clauses
,
13465 SourceLocation StartLoc
,
13466 SourceLocation EndLoc
,
13469 return StmtError();
13471 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13472 // 1.2.2 OpenMP Language Terminology
13473 // Structured block - An executable statement with a single entry at the
13474 // top and a single exit at the bottom.
13475 // The point of exit cannot be a branch out of the structured block.
13476 // longjmp() and throw() must not violate the entry/exit criteria.
13477 CS
->getCapturedDecl()->setNothrow();
13478 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_update
);
13479 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
13480 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
13481 // 1.2.2 OpenMP Language Terminology
13482 // Structured block - An executable statement with a single entry at the
13483 // top and a single exit at the bottom.
13484 // The point of exit cannot be a branch out of the structured block.
13485 // longjmp() and throw() must not violate the entry/exit criteria.
13486 CS
->getCapturedDecl()->setNothrow();
13489 if (!hasClauses(Clauses
, OMPC_to
, OMPC_from
)) {
13490 Diag(StartLoc
, diag::err_omp_at_least_one_motion_clause_required
);
13491 return StmtError();
13494 if (!isClauseMappable(Clauses
)) {
13495 Diag(StartLoc
, diag::err_omp_cannot_update_with_internal_linkage
);
13496 return StmtError();
13499 return OMPTargetUpdateDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
,
13503 StmtResult
Sema::ActOnOpenMPTeamsDirective(ArrayRef
<OMPClause
*> Clauses
,
13504 Stmt
*AStmt
, SourceLocation StartLoc
,
13505 SourceLocation EndLoc
) {
13507 return StmtError();
13509 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13510 if (getLangOpts().HIP
&& (DSAStack
->getParentDirective() == OMPD_target
))
13511 Diag(StartLoc
, diag::warn_hip_omp_target_directives
);
13513 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13514 // 1.2.2 OpenMP Language Terminology
13515 // Structured block - An executable statement with a single entry at the
13516 // top and a single exit at the bottom.
13517 // The point of exit cannot be a branch out of the structured block.
13518 // longjmp() and throw() must not violate the entry/exit criteria.
13519 CS
->getCapturedDecl()->setNothrow();
13521 setFunctionHasBranchProtectedScope();
13523 DSAStack
->setParentTeamsRegionLoc(StartLoc
);
13525 return OMPTeamsDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
);
13529 Sema::ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc
,
13530 SourceLocation EndLoc
,
13531 OpenMPDirectiveKind CancelRegion
) {
13532 if (DSAStack
->isParentNowaitRegion()) {
13533 Diag(StartLoc
, diag::err_omp_parent_cancel_region_nowait
) << 0;
13534 return StmtError();
13536 if (DSAStack
->isParentOrderedRegion()) {
13537 Diag(StartLoc
, diag::err_omp_parent_cancel_region_ordered
) << 0;
13538 return StmtError();
13540 return OMPCancellationPointDirective::Create(Context
, StartLoc
, EndLoc
,
13544 StmtResult
Sema::ActOnOpenMPCancelDirective(ArrayRef
<OMPClause
*> Clauses
,
13545 SourceLocation StartLoc
,
13546 SourceLocation EndLoc
,
13547 OpenMPDirectiveKind CancelRegion
) {
13548 if (DSAStack
->isParentNowaitRegion()) {
13549 Diag(StartLoc
, diag::err_omp_parent_cancel_region_nowait
) << 1;
13550 return StmtError();
13552 if (DSAStack
->isParentOrderedRegion()) {
13553 Diag(StartLoc
, diag::err_omp_parent_cancel_region_ordered
) << 1;
13554 return StmtError();
13556 DSAStack
->setParentCancelRegion(/*Cancel=*/true);
13557 return OMPCancelDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
,
13561 static bool checkReductionClauseWithNogroup(Sema
&S
,
13562 ArrayRef
<OMPClause
*> Clauses
) {
13563 const OMPClause
*ReductionClause
= nullptr;
13564 const OMPClause
*NogroupClause
= nullptr;
13565 for (const OMPClause
*C
: Clauses
) {
13566 if (C
->getClauseKind() == OMPC_reduction
) {
13567 ReductionClause
= C
;
13572 if (C
->getClauseKind() == OMPC_nogroup
) {
13574 if (ReductionClause
)
13579 if (ReductionClause
&& NogroupClause
) {
13580 S
.Diag(ReductionClause
->getBeginLoc(), diag::err_omp_reduction_with_nogroup
)
13581 << SourceRange(NogroupClause
->getBeginLoc(),
13582 NogroupClause
->getEndLoc());
13588 StmtResult
Sema::ActOnOpenMPTaskLoopDirective(
13589 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13590 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13592 return StmtError();
13594 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13595 OMPLoopBasedDirective::HelperExprs B
;
13596 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13597 // define the nested loops number.
13598 unsigned NestedLoopCount
=
13599 checkOpenMPLoop(OMPD_taskloop
, getCollapseNumberExpr(Clauses
),
13600 /*OrderedLoopCountExpr=*/nullptr, AStmt
, *this, *DSAStack
,
13601 VarsWithImplicitDSA
, B
);
13602 if (NestedLoopCount
== 0)
13603 return StmtError();
13605 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13606 "omp for loop exprs were not built");
13608 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13609 // The grainsize clause and num_tasks clause are mutually exclusive and may
13610 // not appear on the same taskloop directive.
13611 if (checkMutuallyExclusiveClauses(*this, Clauses
,
13612 {OMPC_grainsize
, OMPC_num_tasks
}))
13613 return StmtError();
13614 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13615 // If a reduction clause is present on the taskloop directive, the nogroup
13616 // clause must not be specified.
13617 if (checkReductionClauseWithNogroup(*this, Clauses
))
13618 return StmtError();
13620 setFunctionHasBranchProtectedScope();
13621 return OMPTaskLoopDirective::Create(Context
, StartLoc
, EndLoc
,
13622 NestedLoopCount
, Clauses
, AStmt
, B
,
13623 DSAStack
->isCancelRegion());
13626 StmtResult
Sema::ActOnOpenMPTaskLoopSimdDirective(
13627 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13628 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13630 return StmtError();
13632 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13633 OMPLoopBasedDirective::HelperExprs B
;
13634 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13635 // define the nested loops number.
13636 unsigned NestedLoopCount
=
13637 checkOpenMPLoop(OMPD_taskloop_simd
, getCollapseNumberExpr(Clauses
),
13638 /*OrderedLoopCountExpr=*/nullptr, AStmt
, *this, *DSAStack
,
13639 VarsWithImplicitDSA
, B
);
13640 if (NestedLoopCount
== 0)
13641 return StmtError();
13643 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13644 "omp for loop exprs were not built");
13646 if (!CurContext
->isDependentContext()) {
13647 // Finalize the clauses that need pre-built expressions for CodeGen.
13648 for (OMPClause
*C
: Clauses
) {
13649 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
13650 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
13651 B
.NumIterations
, *this, CurScope
,
13653 return StmtError();
13657 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13658 // The grainsize clause and num_tasks clause are mutually exclusive and may
13659 // not appear on the same taskloop directive.
13660 if (checkMutuallyExclusiveClauses(*this, Clauses
,
13661 {OMPC_grainsize
, OMPC_num_tasks
}))
13662 return StmtError();
13663 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13664 // If a reduction clause is present on the taskloop directive, the nogroup
13665 // clause must not be specified.
13666 if (checkReductionClauseWithNogroup(*this, Clauses
))
13667 return StmtError();
13668 if (checkSimdlenSafelenSpecified(*this, Clauses
))
13669 return StmtError();
13671 setFunctionHasBranchProtectedScope();
13672 return OMPTaskLoopSimdDirective::Create(Context
, StartLoc
, EndLoc
,
13673 NestedLoopCount
, Clauses
, AStmt
, B
);
13676 StmtResult
Sema::ActOnOpenMPMasterTaskLoopDirective(
13677 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13678 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13680 return StmtError();
13682 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13683 OMPLoopBasedDirective::HelperExprs B
;
13684 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13685 // define the nested loops number.
13686 unsigned NestedLoopCount
=
13687 checkOpenMPLoop(OMPD_master_taskloop
, getCollapseNumberExpr(Clauses
),
13688 /*OrderedLoopCountExpr=*/nullptr, AStmt
, *this, *DSAStack
,
13689 VarsWithImplicitDSA
, B
);
13690 if (NestedLoopCount
== 0)
13691 return StmtError();
13693 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13694 "omp for loop exprs were not built");
13696 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13697 // The grainsize clause and num_tasks clause are mutually exclusive and may
13698 // not appear on the same taskloop directive.
13699 if (checkMutuallyExclusiveClauses(*this, Clauses
,
13700 {OMPC_grainsize
, OMPC_num_tasks
}))
13701 return StmtError();
13702 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13703 // If a reduction clause is present on the taskloop directive, the nogroup
13704 // clause must not be specified.
13705 if (checkReductionClauseWithNogroup(*this, Clauses
))
13706 return StmtError();
13708 setFunctionHasBranchProtectedScope();
13709 return OMPMasterTaskLoopDirective::Create(Context
, StartLoc
, EndLoc
,
13710 NestedLoopCount
, Clauses
, AStmt
, B
,
13711 DSAStack
->isCancelRegion());
13714 StmtResult
Sema::ActOnOpenMPMaskedTaskLoopDirective(
13715 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13716 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13718 return StmtError();
13720 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13721 OMPLoopBasedDirective::HelperExprs B
;
13722 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13723 // define the nested loops number.
13724 unsigned NestedLoopCount
=
13725 checkOpenMPLoop(OMPD_masked_taskloop
, getCollapseNumberExpr(Clauses
),
13726 /*OrderedLoopCountExpr=*/nullptr, AStmt
, *this, *DSAStack
,
13727 VarsWithImplicitDSA
, B
);
13728 if (NestedLoopCount
== 0)
13729 return StmtError();
13731 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13732 "omp for loop exprs were not built");
13734 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13735 // The grainsize clause and num_tasks clause are mutually exclusive and may
13736 // not appear on the same taskloop directive.
13737 if (checkMutuallyExclusiveClauses(*this, Clauses
,
13738 {OMPC_grainsize
, OMPC_num_tasks
}))
13739 return StmtError();
13740 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13741 // If a reduction clause is present on the taskloop directive, the nogroup
13742 // clause must not be specified.
13743 if (checkReductionClauseWithNogroup(*this, Clauses
))
13744 return StmtError();
13746 setFunctionHasBranchProtectedScope();
13747 return OMPMaskedTaskLoopDirective::Create(Context
, StartLoc
, EndLoc
,
13748 NestedLoopCount
, Clauses
, AStmt
, B
,
13749 DSAStack
->isCancelRegion());
13752 StmtResult
Sema::ActOnOpenMPMasterTaskLoopSimdDirective(
13753 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13754 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13756 return StmtError();
13758 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13759 OMPLoopBasedDirective::HelperExprs B
;
13760 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13761 // define the nested loops number.
13762 unsigned NestedLoopCount
=
13763 checkOpenMPLoop(OMPD_master_taskloop_simd
, getCollapseNumberExpr(Clauses
),
13764 /*OrderedLoopCountExpr=*/nullptr, AStmt
, *this, *DSAStack
,
13765 VarsWithImplicitDSA
, B
);
13766 if (NestedLoopCount
== 0)
13767 return StmtError();
13769 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13770 "omp for loop exprs were not built");
13772 if (!CurContext
->isDependentContext()) {
13773 // Finalize the clauses that need pre-built expressions for CodeGen.
13774 for (OMPClause
*C
: Clauses
) {
13775 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
13776 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
13777 B
.NumIterations
, *this, CurScope
,
13779 return StmtError();
13783 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13784 // The grainsize clause and num_tasks clause are mutually exclusive and may
13785 // not appear on the same taskloop directive.
13786 if (checkMutuallyExclusiveClauses(*this, Clauses
,
13787 {OMPC_grainsize
, OMPC_num_tasks
}))
13788 return StmtError();
13789 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13790 // If a reduction clause is present on the taskloop directive, the nogroup
13791 // clause must not be specified.
13792 if (checkReductionClauseWithNogroup(*this, Clauses
))
13793 return StmtError();
13794 if (checkSimdlenSafelenSpecified(*this, Clauses
))
13795 return StmtError();
13797 setFunctionHasBranchProtectedScope();
13798 return OMPMasterTaskLoopSimdDirective::Create(
13799 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
13802 StmtResult
Sema::ActOnOpenMPMaskedTaskLoopSimdDirective(
13803 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13804 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13806 return StmtError();
13808 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13809 OMPLoopBasedDirective::HelperExprs B
;
13810 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13811 // define the nested loops number.
13812 unsigned NestedLoopCount
=
13813 checkOpenMPLoop(OMPD_masked_taskloop_simd
, getCollapseNumberExpr(Clauses
),
13814 /*OrderedLoopCountExpr=*/nullptr, AStmt
, *this, *DSAStack
,
13815 VarsWithImplicitDSA
, B
);
13816 if (NestedLoopCount
== 0)
13817 return StmtError();
13819 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13820 "omp for loop exprs were not built");
13822 if (!CurContext
->isDependentContext()) {
13823 // Finalize the clauses that need pre-built expressions for CodeGen.
13824 for (OMPClause
*C
: Clauses
) {
13825 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
13826 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
13827 B
.NumIterations
, *this, CurScope
,
13829 return StmtError();
13833 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13834 // The grainsize clause and num_tasks clause are mutually exclusive and may
13835 // not appear on the same taskloop directive.
13836 if (checkMutuallyExclusiveClauses(*this, Clauses
,
13837 {OMPC_grainsize
, OMPC_num_tasks
}))
13838 return StmtError();
13839 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13840 // If a reduction clause is present on the taskloop directive, the nogroup
13841 // clause must not be specified.
13842 if (checkReductionClauseWithNogroup(*this, Clauses
))
13843 return StmtError();
13844 if (checkSimdlenSafelenSpecified(*this, Clauses
))
13845 return StmtError();
13847 setFunctionHasBranchProtectedScope();
13848 return OMPMaskedTaskLoopSimdDirective::Create(
13849 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
13852 StmtResult
Sema::ActOnOpenMPParallelMasterTaskLoopDirective(
13853 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13854 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13856 return StmtError();
13858 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13859 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13860 // 1.2.2 OpenMP Language Terminology
13861 // Structured block - An executable statement with a single entry at the
13862 // top and a single exit at the bottom.
13863 // The point of exit cannot be a branch out of the structured block.
13864 // longjmp() and throw() must not violate the entry/exit criteria.
13865 CS
->getCapturedDecl()->setNothrow();
13866 for (int ThisCaptureLevel
=
13867 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop
);
13868 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
13869 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
13870 // 1.2.2 OpenMP Language Terminology
13871 // Structured block - An executable statement with a single entry at the
13872 // top and a single exit at the bottom.
13873 // The point of exit cannot be a branch out of the structured block.
13874 // longjmp() and throw() must not violate the entry/exit criteria.
13875 CS
->getCapturedDecl()->setNothrow();
13878 OMPLoopBasedDirective::HelperExprs B
;
13879 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13880 // define the nested loops number.
13881 unsigned NestedLoopCount
= checkOpenMPLoop(
13882 OMPD_parallel_master_taskloop
, getCollapseNumberExpr(Clauses
),
13883 /*OrderedLoopCountExpr=*/nullptr, CS
, *this, *DSAStack
,
13884 VarsWithImplicitDSA
, B
);
13885 if (NestedLoopCount
== 0)
13886 return StmtError();
13888 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13889 "omp for loop exprs were not built");
13891 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13892 // The grainsize clause and num_tasks clause are mutually exclusive and may
13893 // not appear on the same taskloop directive.
13894 if (checkMutuallyExclusiveClauses(*this, Clauses
,
13895 {OMPC_grainsize
, OMPC_num_tasks
}))
13896 return StmtError();
13897 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13898 // If a reduction clause is present on the taskloop directive, the nogroup
13899 // clause must not be specified.
13900 if (checkReductionClauseWithNogroup(*this, Clauses
))
13901 return StmtError();
13903 setFunctionHasBranchProtectedScope();
13904 return OMPParallelMasterTaskLoopDirective::Create(
13905 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
,
13906 DSAStack
->isCancelRegion());
13909 StmtResult
Sema::ActOnOpenMPParallelMaskedTaskLoopDirective(
13910 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13911 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13913 return StmtError();
13915 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13916 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13917 // 1.2.2 OpenMP Language Terminology
13918 // Structured block - An executable statement with a single entry at the
13919 // top and a single exit at the bottom.
13920 // The point of exit cannot be a branch out of the structured block.
13921 // longjmp() and throw() must not violate the entry/exit criteria.
13922 CS
->getCapturedDecl()->setNothrow();
13923 for (int ThisCaptureLevel
=
13924 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop
);
13925 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
13926 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
13927 // 1.2.2 OpenMP Language Terminology
13928 // Structured block - An executable statement with a single entry at the
13929 // top and a single exit at the bottom.
13930 // The point of exit cannot be a branch out of the structured block.
13931 // longjmp() and throw() must not violate the entry/exit criteria.
13932 CS
->getCapturedDecl()->setNothrow();
13935 OMPLoopBasedDirective::HelperExprs B
;
13936 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13937 // define the nested loops number.
13938 unsigned NestedLoopCount
= checkOpenMPLoop(
13939 OMPD_parallel_masked_taskloop
, getCollapseNumberExpr(Clauses
),
13940 /*OrderedLoopCountExpr=*/nullptr, CS
, *this, *DSAStack
,
13941 VarsWithImplicitDSA
, B
);
13942 if (NestedLoopCount
== 0)
13943 return StmtError();
13945 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13946 "omp for loop exprs were not built");
13948 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13949 // The grainsize clause and num_tasks clause are mutually exclusive and may
13950 // not appear on the same taskloop directive.
13951 if (checkMutuallyExclusiveClauses(*this, Clauses
,
13952 {OMPC_grainsize
, OMPC_num_tasks
}))
13953 return StmtError();
13954 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13955 // If a reduction clause is present on the taskloop directive, the nogroup
13956 // clause must not be specified.
13957 if (checkReductionClauseWithNogroup(*this, Clauses
))
13958 return StmtError();
13960 setFunctionHasBranchProtectedScope();
13961 return OMPParallelMaskedTaskLoopDirective::Create(
13962 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
,
13963 DSAStack
->isCancelRegion());
13966 StmtResult
Sema::ActOnOpenMPParallelMasterTaskLoopSimdDirective(
13967 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13968 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13970 return StmtError();
13972 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13973 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13974 // 1.2.2 OpenMP Language Terminology
13975 // Structured block - An executable statement with a single entry at the
13976 // top and a single exit at the bottom.
13977 // The point of exit cannot be a branch out of the structured block.
13978 // longjmp() and throw() must not violate the entry/exit criteria.
13979 CS
->getCapturedDecl()->setNothrow();
13980 for (int ThisCaptureLevel
=
13981 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop_simd
);
13982 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
13983 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
13984 // 1.2.2 OpenMP Language Terminology
13985 // Structured block - An executable statement with a single entry at the
13986 // top and a single exit at the bottom.
13987 // The point of exit cannot be a branch out of the structured block.
13988 // longjmp() and throw() must not violate the entry/exit criteria.
13989 CS
->getCapturedDecl()->setNothrow();
13992 OMPLoopBasedDirective::HelperExprs B
;
13993 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13994 // define the nested loops number.
13995 unsigned NestedLoopCount
= checkOpenMPLoop(
13996 OMPD_parallel_master_taskloop_simd
, getCollapseNumberExpr(Clauses
),
13997 /*OrderedLoopCountExpr=*/nullptr, CS
, *this, *DSAStack
,
13998 VarsWithImplicitDSA
, B
);
13999 if (NestedLoopCount
== 0)
14000 return StmtError();
14002 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14003 "omp for loop exprs were not built");
14005 if (!CurContext
->isDependentContext()) {
14006 // Finalize the clauses that need pre-built expressions for CodeGen.
14007 for (OMPClause
*C
: Clauses
) {
14008 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14009 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14010 B
.NumIterations
, *this, CurScope
,
14012 return StmtError();
14016 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14017 // The grainsize clause and num_tasks clause are mutually exclusive and may
14018 // not appear on the same taskloop directive.
14019 if (checkMutuallyExclusiveClauses(*this, Clauses
,
14020 {OMPC_grainsize
, OMPC_num_tasks
}))
14021 return StmtError();
14022 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14023 // If a reduction clause is present on the taskloop directive, the nogroup
14024 // clause must not be specified.
14025 if (checkReductionClauseWithNogroup(*this, Clauses
))
14026 return StmtError();
14027 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14028 return StmtError();
14030 setFunctionHasBranchProtectedScope();
14031 return OMPParallelMasterTaskLoopSimdDirective::Create(
14032 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14035 StmtResult
Sema::ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
14036 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14037 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14039 return StmtError();
14041 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
14042 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14043 // 1.2.2 OpenMP Language Terminology
14044 // Structured block - An executable statement with a single entry at the
14045 // top and a single exit at the bottom.
14046 // The point of exit cannot be a branch out of the structured block.
14047 // longjmp() and throw() must not violate the entry/exit criteria.
14048 CS
->getCapturedDecl()->setNothrow();
14049 for (int ThisCaptureLevel
=
14050 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop_simd
);
14051 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14052 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14053 // 1.2.2 OpenMP Language Terminology
14054 // Structured block - An executable statement with a single entry at the
14055 // top and a single exit at the bottom.
14056 // The point of exit cannot be a branch out of the structured block.
14057 // longjmp() and throw() must not violate the entry/exit criteria.
14058 CS
->getCapturedDecl()->setNothrow();
14061 OMPLoopBasedDirective::HelperExprs B
;
14062 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14063 // define the nested loops number.
14064 unsigned NestedLoopCount
= checkOpenMPLoop(
14065 OMPD_parallel_masked_taskloop_simd
, getCollapseNumberExpr(Clauses
),
14066 /*OrderedLoopCountExpr=*/nullptr, CS
, *this, *DSAStack
,
14067 VarsWithImplicitDSA
, B
);
14068 if (NestedLoopCount
== 0)
14069 return StmtError();
14071 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14072 "omp for loop exprs were not built");
14074 if (!CurContext
->isDependentContext()) {
14075 // Finalize the clauses that need pre-built expressions for CodeGen.
14076 for (OMPClause
*C
: Clauses
) {
14077 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14078 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14079 B
.NumIterations
, *this, CurScope
,
14081 return StmtError();
14085 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14086 // The grainsize clause and num_tasks clause are mutually exclusive and may
14087 // not appear on the same taskloop directive.
14088 if (checkMutuallyExclusiveClauses(*this, Clauses
,
14089 {OMPC_grainsize
, OMPC_num_tasks
}))
14090 return StmtError();
14091 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14092 // If a reduction clause is present on the taskloop directive, the nogroup
14093 // clause must not be specified.
14094 if (checkReductionClauseWithNogroup(*this, Clauses
))
14095 return StmtError();
14096 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14097 return StmtError();
14099 setFunctionHasBranchProtectedScope();
14100 return OMPParallelMaskedTaskLoopSimdDirective::Create(
14101 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14104 StmtResult
Sema::ActOnOpenMPDistributeDirective(
14105 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14106 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14108 return StmtError();
14110 if (!checkLastPrivateForMappedDirectives(Clauses
))
14111 return StmtError();
14113 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
14114 OMPLoopBasedDirective::HelperExprs B
;
14115 // In presence of clause 'collapse' with number of loops, it will
14116 // define the nested loops number.
14117 unsigned NestedLoopCount
=
14118 checkOpenMPLoop(OMPD_distribute
, getCollapseNumberExpr(Clauses
),
14119 nullptr /*ordered not a clause on distribute*/, AStmt
,
14120 *this, *DSAStack
, VarsWithImplicitDSA
, B
);
14121 if (NestedLoopCount
== 0)
14122 return StmtError();
14124 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14125 "omp for loop exprs were not built");
14127 setFunctionHasBranchProtectedScope();
14128 auto *DistributeDirective
= OMPDistributeDirective::Create(
14129 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
,
14130 DSAStack
->getMappedDirective());
14131 return DistributeDirective
;
14134 StmtResult
Sema::ActOnOpenMPDistributeParallelForDirective(
14135 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14136 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14138 return StmtError();
14140 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14141 // 1.2.2 OpenMP Language Terminology
14142 // Structured block - An executable statement with a single entry at the
14143 // top and a single exit at the bottom.
14144 // The point of exit cannot be a branch out of the structured block.
14145 // longjmp() and throw() must not violate the entry/exit criteria.
14146 CS
->getCapturedDecl()->setNothrow();
14147 for (int ThisCaptureLevel
=
14148 getOpenMPCaptureLevels(OMPD_distribute_parallel_for
);
14149 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14150 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14151 // 1.2.2 OpenMP Language Terminology
14152 // Structured block - An executable statement with a single entry at the
14153 // top and a single exit at the bottom.
14154 // The point of exit cannot be a branch out of the structured block.
14155 // longjmp() and throw() must not violate the entry/exit criteria.
14156 CS
->getCapturedDecl()->setNothrow();
14159 OMPLoopBasedDirective::HelperExprs B
;
14160 // In presence of clause 'collapse' with number of loops, it will
14161 // define the nested loops number.
14162 unsigned NestedLoopCount
= checkOpenMPLoop(
14163 OMPD_distribute_parallel_for
, getCollapseNumberExpr(Clauses
),
14164 nullptr /*ordered not a clause on distribute*/, CS
, *this, *DSAStack
,
14165 VarsWithImplicitDSA
, B
);
14166 if (NestedLoopCount
== 0)
14167 return StmtError();
14169 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14170 "omp for loop exprs were not built");
14172 setFunctionHasBranchProtectedScope();
14173 return OMPDistributeParallelForDirective::Create(
14174 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
,
14175 DSAStack
->getTaskgroupReductionRef(), DSAStack
->isCancelRegion());
14178 StmtResult
Sema::ActOnOpenMPDistributeParallelForSimdDirective(
14179 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14180 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14182 return StmtError();
14184 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14185 // 1.2.2 OpenMP Language Terminology
14186 // Structured block - An executable statement with a single entry at the
14187 // top and a single exit at the bottom.
14188 // The point of exit cannot be a branch out of the structured block.
14189 // longjmp() and throw() must not violate the entry/exit criteria.
14190 CS
->getCapturedDecl()->setNothrow();
14191 for (int ThisCaptureLevel
=
14192 getOpenMPCaptureLevels(OMPD_distribute_parallel_for_simd
);
14193 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14194 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14195 // 1.2.2 OpenMP Language Terminology
14196 // Structured block - An executable statement with a single entry at the
14197 // top and a single exit at the bottom.
14198 // The point of exit cannot be a branch out of the structured block.
14199 // longjmp() and throw() must not violate the entry/exit criteria.
14200 CS
->getCapturedDecl()->setNothrow();
14203 OMPLoopBasedDirective::HelperExprs B
;
14204 // In presence of clause 'collapse' with number of loops, it will
14205 // define the nested loops number.
14206 unsigned NestedLoopCount
= checkOpenMPLoop(
14207 OMPD_distribute_parallel_for_simd
, getCollapseNumberExpr(Clauses
),
14208 nullptr /*ordered not a clause on distribute*/, CS
, *this, *DSAStack
,
14209 VarsWithImplicitDSA
, B
);
14210 if (NestedLoopCount
== 0)
14211 return StmtError();
14213 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14214 "omp for loop exprs were not built");
14216 if (!CurContext
->isDependentContext()) {
14217 // Finalize the clauses that need pre-built expressions for CodeGen.
14218 for (OMPClause
*C
: Clauses
) {
14219 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14220 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14221 B
.NumIterations
, *this, CurScope
,
14223 return StmtError();
14227 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14228 return StmtError();
14230 setFunctionHasBranchProtectedScope();
14231 return OMPDistributeParallelForSimdDirective::Create(
14232 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14235 StmtResult
Sema::ActOnOpenMPDistributeSimdDirective(
14236 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14237 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14239 return StmtError();
14241 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14242 // 1.2.2 OpenMP Language Terminology
14243 // Structured block - An executable statement with a single entry at the
14244 // top and a single exit at the bottom.
14245 // The point of exit cannot be a branch out of the structured block.
14246 // longjmp() and throw() must not violate the entry/exit criteria.
14247 CS
->getCapturedDecl()->setNothrow();
14248 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_distribute_simd
);
14249 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14250 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14251 // 1.2.2 OpenMP Language Terminology
14252 // Structured block - An executable statement with a single entry at the
14253 // top and a single exit at the bottom.
14254 // The point of exit cannot be a branch out of the structured block.
14255 // longjmp() and throw() must not violate the entry/exit criteria.
14256 CS
->getCapturedDecl()->setNothrow();
14259 OMPLoopBasedDirective::HelperExprs B
;
14260 // In presence of clause 'collapse' with number of loops, it will
14261 // define the nested loops number.
14262 unsigned NestedLoopCount
=
14263 checkOpenMPLoop(OMPD_distribute_simd
, getCollapseNumberExpr(Clauses
),
14264 nullptr /*ordered not a clause on distribute*/, CS
, *this,
14265 *DSAStack
, VarsWithImplicitDSA
, B
);
14266 if (NestedLoopCount
== 0)
14267 return StmtError();
14269 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14270 "omp for loop exprs were not built");
14272 if (!CurContext
->isDependentContext()) {
14273 // Finalize the clauses that need pre-built expressions for CodeGen.
14274 for (OMPClause
*C
: Clauses
) {
14275 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14276 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14277 B
.NumIterations
, *this, CurScope
,
14279 return StmtError();
14283 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14284 return StmtError();
14286 setFunctionHasBranchProtectedScope();
14287 return OMPDistributeSimdDirective::Create(Context
, StartLoc
, EndLoc
,
14288 NestedLoopCount
, Clauses
, AStmt
, B
);
14291 StmtResult
Sema::ActOnOpenMPTargetParallelForSimdDirective(
14292 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14293 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14295 return StmtError();
14297 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14298 // 1.2.2 OpenMP Language Terminology
14299 // Structured block - An executable statement with a single entry at the
14300 // top and a single exit at the bottom.
14301 // The point of exit cannot be a branch out of the structured block.
14302 // longjmp() and throw() must not violate the entry/exit criteria.
14303 CS
->getCapturedDecl()->setNothrow();
14304 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_parallel_for
);
14305 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14306 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14307 // 1.2.2 OpenMP Language Terminology
14308 // Structured block - An executable statement with a single entry at the
14309 // top and a single exit at the bottom.
14310 // The point of exit cannot be a branch out of the structured block.
14311 // longjmp() and throw() must not violate the entry/exit criteria.
14312 CS
->getCapturedDecl()->setNothrow();
14315 OMPLoopBasedDirective::HelperExprs B
;
14316 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14317 // define the nested loops number.
14318 unsigned NestedLoopCount
= checkOpenMPLoop(
14319 OMPD_target_parallel_for_simd
, getCollapseNumberExpr(Clauses
),
14320 getOrderedNumberExpr(Clauses
), CS
, *this, *DSAStack
, VarsWithImplicitDSA
,
14322 if (NestedLoopCount
== 0)
14323 return StmtError();
14325 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14326 "omp target parallel for simd loop exprs were not built");
14328 if (!CurContext
->isDependentContext()) {
14329 // Finalize the clauses that need pre-built expressions for CodeGen.
14330 for (OMPClause
*C
: Clauses
) {
14331 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14332 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14333 B
.NumIterations
, *this, CurScope
,
14335 return StmtError();
14338 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14339 return StmtError();
14341 setFunctionHasBranchProtectedScope();
14342 return OMPTargetParallelForSimdDirective::Create(
14343 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14346 StmtResult
Sema::ActOnOpenMPTargetSimdDirective(
14347 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14348 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14350 return StmtError();
14352 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14353 // 1.2.2 OpenMP Language Terminology
14354 // Structured block - An executable statement with a single entry at the
14355 // top and a single exit at the bottom.
14356 // The point of exit cannot be a branch out of the structured block.
14357 // longjmp() and throw() must not violate the entry/exit criteria.
14358 CS
->getCapturedDecl()->setNothrow();
14359 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_simd
);
14360 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14361 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14362 // 1.2.2 OpenMP Language Terminology
14363 // Structured block - An executable statement with a single entry at the
14364 // top and a single exit at the bottom.
14365 // The point of exit cannot be a branch out of the structured block.
14366 // longjmp() and throw() must not violate the entry/exit criteria.
14367 CS
->getCapturedDecl()->setNothrow();
14370 OMPLoopBasedDirective::HelperExprs B
;
14371 // In presence of clause 'collapse' with number of loops, it will define the
14372 // nested loops number.
14373 unsigned NestedLoopCount
=
14374 checkOpenMPLoop(OMPD_target_simd
, getCollapseNumberExpr(Clauses
),
14375 getOrderedNumberExpr(Clauses
), CS
, *this, *DSAStack
,
14376 VarsWithImplicitDSA
, B
);
14377 if (NestedLoopCount
== 0)
14378 return StmtError();
14380 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14381 "omp target simd loop exprs were not built");
14383 if (!CurContext
->isDependentContext()) {
14384 // Finalize the clauses that need pre-built expressions for CodeGen.
14385 for (OMPClause
*C
: Clauses
) {
14386 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14387 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14388 B
.NumIterations
, *this, CurScope
,
14390 return StmtError();
14394 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14395 return StmtError();
14397 setFunctionHasBranchProtectedScope();
14398 return OMPTargetSimdDirective::Create(Context
, StartLoc
, EndLoc
,
14399 NestedLoopCount
, Clauses
, AStmt
, B
);
14402 StmtResult
Sema::ActOnOpenMPTeamsDistributeDirective(
14403 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14404 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14406 return StmtError();
14408 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14409 // 1.2.2 OpenMP Language Terminology
14410 // Structured block - An executable statement with a single entry at the
14411 // top and a single exit at the bottom.
14412 // The point of exit cannot be a branch out of the structured block.
14413 // longjmp() and throw() must not violate the entry/exit criteria.
14414 CS
->getCapturedDecl()->setNothrow();
14415 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_teams_distribute
);
14416 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14417 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14418 // 1.2.2 OpenMP Language Terminology
14419 // Structured block - An executable statement with a single entry at the
14420 // top and a single exit at the bottom.
14421 // The point of exit cannot be a branch out of the structured block.
14422 // longjmp() and throw() must not violate the entry/exit criteria.
14423 CS
->getCapturedDecl()->setNothrow();
14426 OMPLoopBasedDirective::HelperExprs B
;
14427 // In presence of clause 'collapse' with number of loops, it will
14428 // define the nested loops number.
14429 unsigned NestedLoopCount
=
14430 checkOpenMPLoop(OMPD_teams_distribute
, getCollapseNumberExpr(Clauses
),
14431 nullptr /*ordered not a clause on distribute*/, CS
, *this,
14432 *DSAStack
, VarsWithImplicitDSA
, B
);
14433 if (NestedLoopCount
== 0)
14434 return StmtError();
14436 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14437 "omp teams distribute loop exprs were not built");
14439 setFunctionHasBranchProtectedScope();
14441 DSAStack
->setParentTeamsRegionLoc(StartLoc
);
14443 return OMPTeamsDistributeDirective::Create(
14444 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14447 StmtResult
Sema::ActOnOpenMPTeamsDistributeSimdDirective(
14448 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14449 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14451 return StmtError();
14453 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14454 // 1.2.2 OpenMP Language Terminology
14455 // Structured block - An executable statement with a single entry at the
14456 // top and a single exit at the bottom.
14457 // The point of exit cannot be a branch out of the structured block.
14458 // longjmp() and throw() must not violate the entry/exit criteria.
14459 CS
->getCapturedDecl()->setNothrow();
14460 for (int ThisCaptureLevel
=
14461 getOpenMPCaptureLevels(OMPD_teams_distribute_simd
);
14462 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14463 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14464 // 1.2.2 OpenMP Language Terminology
14465 // Structured block - An executable statement with a single entry at the
14466 // top and a single exit at the bottom.
14467 // The point of exit cannot be a branch out of the structured block.
14468 // longjmp() and throw() must not violate the entry/exit criteria.
14469 CS
->getCapturedDecl()->setNothrow();
14472 OMPLoopBasedDirective::HelperExprs B
;
14473 // In presence of clause 'collapse' with number of loops, it will
14474 // define the nested loops number.
14475 unsigned NestedLoopCount
= checkOpenMPLoop(
14476 OMPD_teams_distribute_simd
, getCollapseNumberExpr(Clauses
),
14477 nullptr /*ordered not a clause on distribute*/, CS
, *this, *DSAStack
,
14478 VarsWithImplicitDSA
, B
);
14480 if (NestedLoopCount
== 0)
14481 return StmtError();
14483 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14484 "omp teams distribute simd loop exprs were not built");
14486 if (!CurContext
->isDependentContext()) {
14487 // Finalize the clauses that need pre-built expressions for CodeGen.
14488 for (OMPClause
*C
: Clauses
) {
14489 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14490 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14491 B
.NumIterations
, *this, CurScope
,
14493 return StmtError();
14497 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14498 return StmtError();
14500 setFunctionHasBranchProtectedScope();
14502 DSAStack
->setParentTeamsRegionLoc(StartLoc
);
14504 return OMPTeamsDistributeSimdDirective::Create(
14505 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14508 StmtResult
Sema::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
14509 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14510 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14512 return StmtError();
14514 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14515 // 1.2.2 OpenMP Language Terminology
14516 // Structured block - An executable statement with a single entry at the
14517 // top and a single exit at the bottom.
14518 // The point of exit cannot be a branch out of the structured block.
14519 // longjmp() and throw() must not violate the entry/exit criteria.
14520 CS
->getCapturedDecl()->setNothrow();
14522 for (int ThisCaptureLevel
=
14523 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for_simd
);
14524 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14525 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14526 // 1.2.2 OpenMP Language Terminology
14527 // Structured block - An executable statement with a single entry at the
14528 // top and a single exit at the bottom.
14529 // The point of exit cannot be a branch out of the structured block.
14530 // longjmp() and throw() must not violate the entry/exit criteria.
14531 CS
->getCapturedDecl()->setNothrow();
14534 OMPLoopBasedDirective::HelperExprs B
;
14535 // In presence of clause 'collapse' with number of loops, it will
14536 // define the nested loops number.
14537 unsigned NestedLoopCount
= checkOpenMPLoop(
14538 OMPD_teams_distribute_parallel_for_simd
, getCollapseNumberExpr(Clauses
),
14539 nullptr /*ordered not a clause on distribute*/, CS
, *this, *DSAStack
,
14540 VarsWithImplicitDSA
, B
);
14542 if (NestedLoopCount
== 0)
14543 return StmtError();
14545 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14546 "omp for loop exprs were not built");
14548 if (!CurContext
->isDependentContext()) {
14549 // Finalize the clauses that need pre-built expressions for CodeGen.
14550 for (OMPClause
*C
: Clauses
) {
14551 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14552 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14553 B
.NumIterations
, *this, CurScope
,
14555 return StmtError();
14559 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14560 return StmtError();
14562 setFunctionHasBranchProtectedScope();
14564 DSAStack
->setParentTeamsRegionLoc(StartLoc
);
14566 return OMPTeamsDistributeParallelForSimdDirective::Create(
14567 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14570 StmtResult
Sema::ActOnOpenMPTeamsDistributeParallelForDirective(
14571 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14572 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14574 return StmtError();
14576 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14577 // 1.2.2 OpenMP Language Terminology
14578 // Structured block - An executable statement with a single entry at the
14579 // top and a single exit at the bottom.
14580 // The point of exit cannot be a branch out of the structured block.
14581 // longjmp() and throw() must not violate the entry/exit criteria.
14582 CS
->getCapturedDecl()->setNothrow();
14584 for (int ThisCaptureLevel
=
14585 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for
);
14586 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14587 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14588 // 1.2.2 OpenMP Language Terminology
14589 // Structured block - An executable statement with a single entry at the
14590 // top and a single exit at the bottom.
14591 // The point of exit cannot be a branch out of the structured block.
14592 // longjmp() and throw() must not violate the entry/exit criteria.
14593 CS
->getCapturedDecl()->setNothrow();
14596 OMPLoopBasedDirective::HelperExprs B
;
14597 // In presence of clause 'collapse' with number of loops, it will
14598 // define the nested loops number.
14599 unsigned NestedLoopCount
= checkOpenMPLoop(
14600 OMPD_teams_distribute_parallel_for
, getCollapseNumberExpr(Clauses
),
14601 nullptr /*ordered not a clause on distribute*/, CS
, *this, *DSAStack
,
14602 VarsWithImplicitDSA
, B
);
14604 if (NestedLoopCount
== 0)
14605 return StmtError();
14607 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14608 "omp for loop exprs were not built");
14610 setFunctionHasBranchProtectedScope();
14612 DSAStack
->setParentTeamsRegionLoc(StartLoc
);
14614 return OMPTeamsDistributeParallelForDirective::Create(
14615 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
,
14616 DSAStack
->getTaskgroupReductionRef(), DSAStack
->isCancelRegion());
14619 StmtResult
Sema::ActOnOpenMPTargetTeamsDirective(ArrayRef
<OMPClause
*> Clauses
,
14621 SourceLocation StartLoc
,
14622 SourceLocation EndLoc
) {
14624 return StmtError();
14626 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14627 // 1.2.2 OpenMP Language Terminology
14628 // Structured block - An executable statement with a single entry at the
14629 // top and a single exit at the bottom.
14630 // The point of exit cannot be a branch out of the structured block.
14631 // longjmp() and throw() must not violate the entry/exit criteria.
14632 CS
->getCapturedDecl()->setNothrow();
14634 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_teams
);
14635 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14636 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14637 // 1.2.2 OpenMP Language Terminology
14638 // Structured block - An executable statement with a single entry at the
14639 // top and a single exit at the bottom.
14640 // The point of exit cannot be a branch out of the structured block.
14641 // longjmp() and throw() must not violate the entry/exit criteria.
14642 CS
->getCapturedDecl()->setNothrow();
14644 setFunctionHasBranchProtectedScope();
14646 return OMPTargetTeamsDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
,
14650 StmtResult
Sema::ActOnOpenMPTargetTeamsDistributeDirective(
14651 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14652 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14654 return StmtError();
14656 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14657 // 1.2.2 OpenMP Language Terminology
14658 // Structured block - An executable statement with a single entry at the
14659 // top and a single exit at the bottom.
14660 // The point of exit cannot be a branch out of the structured block.
14661 // longjmp() and throw() must not violate the entry/exit criteria.
14662 CS
->getCapturedDecl()->setNothrow();
14663 for (int ThisCaptureLevel
=
14664 getOpenMPCaptureLevels(OMPD_target_teams_distribute
);
14665 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14666 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14667 // 1.2.2 OpenMP Language Terminology
14668 // Structured block - An executable statement with a single entry at the
14669 // top and a single exit at the bottom.
14670 // The point of exit cannot be a branch out of the structured block.
14671 // longjmp() and throw() must not violate the entry/exit criteria.
14672 CS
->getCapturedDecl()->setNothrow();
14675 OMPLoopBasedDirective::HelperExprs B
;
14676 // In presence of clause 'collapse' with number of loops, it will
14677 // define the nested loops number.
14678 unsigned NestedLoopCount
= checkOpenMPLoop(
14679 OMPD_target_teams_distribute
, getCollapseNumberExpr(Clauses
),
14680 nullptr /*ordered not a clause on distribute*/, CS
, *this, *DSAStack
,
14681 VarsWithImplicitDSA
, B
);
14682 if (NestedLoopCount
== 0)
14683 return StmtError();
14685 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14686 "omp target teams distribute loop exprs were not built");
14688 setFunctionHasBranchProtectedScope();
14689 return OMPTargetTeamsDistributeDirective::Create(
14690 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14693 StmtResult
Sema::ActOnOpenMPTargetTeamsDistributeParallelForDirective(
14694 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14695 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14697 return StmtError();
14699 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14700 // 1.2.2 OpenMP Language Terminology
14701 // Structured block - An executable statement with a single entry at the
14702 // top and a single exit at the bottom.
14703 // The point of exit cannot be a branch out of the structured block.
14704 // longjmp() and throw() must not violate the entry/exit criteria.
14705 CS
->getCapturedDecl()->setNothrow();
14706 for (int ThisCaptureLevel
=
14707 getOpenMPCaptureLevels(OMPD_target_teams_distribute_parallel_for
);
14708 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14709 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14710 // 1.2.2 OpenMP Language Terminology
14711 // Structured block - An executable statement with a single entry at the
14712 // top and a single exit at the bottom.
14713 // The point of exit cannot be a branch out of the structured block.
14714 // longjmp() and throw() must not violate the entry/exit criteria.
14715 CS
->getCapturedDecl()->setNothrow();
14718 OMPLoopBasedDirective::HelperExprs B
;
14719 // In presence of clause 'collapse' with number of loops, it will
14720 // define the nested loops number.
14721 unsigned NestedLoopCount
= checkOpenMPLoop(
14722 OMPD_target_teams_distribute_parallel_for
, getCollapseNumberExpr(Clauses
),
14723 nullptr /*ordered not a clause on distribute*/, CS
, *this, *DSAStack
,
14724 VarsWithImplicitDSA
, B
);
14725 if (NestedLoopCount
== 0)
14726 return StmtError();
14728 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14729 "omp target teams distribute parallel for loop exprs were not built");
14731 if (!CurContext
->isDependentContext()) {
14732 // Finalize the clauses that need pre-built expressions for CodeGen.
14733 for (OMPClause
*C
: Clauses
) {
14734 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14735 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14736 B
.NumIterations
, *this, CurScope
,
14738 return StmtError();
14742 setFunctionHasBranchProtectedScope();
14743 return OMPTargetTeamsDistributeParallelForDirective::Create(
14744 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
,
14745 DSAStack
->getTaskgroupReductionRef(), DSAStack
->isCancelRegion());
14748 StmtResult
Sema::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
14749 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14750 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14752 return StmtError();
14754 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14755 // 1.2.2 OpenMP Language Terminology
14756 // Structured block - An executable statement with a single entry at the
14757 // top and a single exit at the bottom.
14758 // The point of exit cannot be a branch out of the structured block.
14759 // longjmp() and throw() must not violate the entry/exit criteria.
14760 CS
->getCapturedDecl()->setNothrow();
14761 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(
14762 OMPD_target_teams_distribute_parallel_for_simd
);
14763 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14764 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14765 // 1.2.2 OpenMP Language Terminology
14766 // Structured block - An executable statement with a single entry at the
14767 // top and a single exit at the bottom.
14768 // The point of exit cannot be a branch out of the structured block.
14769 // longjmp() and throw() must not violate the entry/exit criteria.
14770 CS
->getCapturedDecl()->setNothrow();
14773 OMPLoopBasedDirective::HelperExprs B
;
14774 // In presence of clause 'collapse' with number of loops, it will
14775 // define the nested loops number.
14776 unsigned NestedLoopCount
=
14777 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd
,
14778 getCollapseNumberExpr(Clauses
),
14779 nullptr /*ordered not a clause on distribute*/, CS
, *this,
14780 *DSAStack
, VarsWithImplicitDSA
, B
);
14781 if (NestedLoopCount
== 0)
14782 return StmtError();
14784 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14785 "omp target teams distribute parallel for simd loop exprs were not "
14788 if (!CurContext
->isDependentContext()) {
14789 // Finalize the clauses that need pre-built expressions for CodeGen.
14790 for (OMPClause
*C
: Clauses
) {
14791 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14792 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14793 B
.NumIterations
, *this, CurScope
,
14795 return StmtError();
14799 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14800 return StmtError();
14802 setFunctionHasBranchProtectedScope();
14803 return OMPTargetTeamsDistributeParallelForSimdDirective::Create(
14804 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14807 StmtResult
Sema::ActOnOpenMPTargetTeamsDistributeSimdDirective(
14808 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14809 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14811 return StmtError();
14813 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14814 // 1.2.2 OpenMP Language Terminology
14815 // Structured block - An executable statement with a single entry at the
14816 // top and a single exit at the bottom.
14817 // The point of exit cannot be a branch out of the structured block.
14818 // longjmp() and throw() must not violate the entry/exit criteria.
14819 CS
->getCapturedDecl()->setNothrow();
14820 for (int ThisCaptureLevel
=
14821 getOpenMPCaptureLevels(OMPD_target_teams_distribute_simd
);
14822 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14823 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14824 // 1.2.2 OpenMP Language Terminology
14825 // Structured block - An executable statement with a single entry at the
14826 // top and a single exit at the bottom.
14827 // The point of exit cannot be a branch out of the structured block.
14828 // longjmp() and throw() must not violate the entry/exit criteria.
14829 CS
->getCapturedDecl()->setNothrow();
14832 OMPLoopBasedDirective::HelperExprs B
;
14833 // In presence of clause 'collapse' with number of loops, it will
14834 // define the nested loops number.
14835 unsigned NestedLoopCount
= checkOpenMPLoop(
14836 OMPD_target_teams_distribute_simd
, getCollapseNumberExpr(Clauses
),
14837 nullptr /*ordered not a clause on distribute*/, CS
, *this, *DSAStack
,
14838 VarsWithImplicitDSA
, B
);
14839 if (NestedLoopCount
== 0)
14840 return StmtError();
14842 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14843 "omp target teams distribute simd loop exprs were not built");
14845 if (!CurContext
->isDependentContext()) {
14846 // Finalize the clauses that need pre-built expressions for CodeGen.
14847 for (OMPClause
*C
: Clauses
) {
14848 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14849 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14850 B
.NumIterations
, *this, CurScope
,
14852 return StmtError();
14856 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14857 return StmtError();
14859 setFunctionHasBranchProtectedScope();
14860 return OMPTargetTeamsDistributeSimdDirective::Create(
14861 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14864 bool Sema::checkTransformableLoopNest(
14865 OpenMPDirectiveKind Kind
, Stmt
*AStmt
, int NumLoops
,
14866 SmallVectorImpl
<OMPLoopBasedDirective::HelperExprs
> &LoopHelpers
,
14868 SmallVectorImpl
<SmallVector
<llvm::PointerUnion
<Stmt
*, Decl
*>, 0>>
14870 OriginalInits
.emplace_back();
14871 bool Result
= OMPLoopBasedDirective::doForAllLoops(
14872 AStmt
->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops
,
14873 [this, &LoopHelpers
, &Body
, &OriginalInits
, Kind
](unsigned Cnt
,
14875 VarsWithInheritedDSAType TmpDSA
;
14876 unsigned SingleNumLoops
=
14877 checkOpenMPLoop(Kind
, nullptr, nullptr, CurStmt
, *this, *DSAStack
,
14878 TmpDSA
, LoopHelpers
[Cnt
]);
14879 if (SingleNumLoops
== 0)
14881 assert(SingleNumLoops
== 1 && "Expect single loop iteration space");
14882 if (auto *For
= dyn_cast
<ForStmt
>(CurStmt
)) {
14883 OriginalInits
.back().push_back(For
->getInit());
14884 Body
= For
->getBody();
14886 assert(isa
<CXXForRangeStmt
>(CurStmt
) &&
14887 "Expected canonical for or range-based for loops.");
14888 auto *CXXFor
= cast
<CXXForRangeStmt
>(CurStmt
);
14889 OriginalInits
.back().push_back(CXXFor
->getBeginStmt());
14890 Body
= CXXFor
->getBody();
14892 OriginalInits
.emplace_back();
14895 [&OriginalInits
](OMPLoopBasedDirective
*Transform
) {
14896 Stmt
*DependentPreInits
;
14897 if (auto *Dir
= dyn_cast
<OMPTileDirective
>(Transform
))
14898 DependentPreInits
= Dir
->getPreInits();
14899 else if (auto *Dir
= dyn_cast
<OMPUnrollDirective
>(Transform
))
14900 DependentPreInits
= Dir
->getPreInits();
14902 llvm_unreachable("Unhandled loop transformation");
14903 if (!DependentPreInits
)
14905 llvm::append_range(OriginalInits
.back(),
14906 cast
<DeclStmt
>(DependentPreInits
)->getDeclGroup());
14908 assert(OriginalInits
.back().empty() && "No preinit after innermost loop");
14909 OriginalInits
.pop_back();
14913 StmtResult
Sema::ActOnOpenMPTileDirective(ArrayRef
<OMPClause
*> Clauses
,
14914 Stmt
*AStmt
, SourceLocation StartLoc
,
14915 SourceLocation EndLoc
) {
14916 auto SizesClauses
=
14917 OMPExecutableDirective::getClausesOfKind
<OMPSizesClause
>(Clauses
);
14918 if (SizesClauses
.empty()) {
14919 // A missing 'sizes' clause is already reported by the parser.
14920 return StmtError();
14922 const OMPSizesClause
*SizesClause
= *SizesClauses
.begin();
14923 unsigned NumLoops
= SizesClause
->getNumSizes();
14925 // Empty statement should only be possible if there already was an error.
14927 return StmtError();
14929 // Verify and diagnose loop nest.
14930 SmallVector
<OMPLoopBasedDirective::HelperExprs
, 4> LoopHelpers(NumLoops
);
14931 Stmt
*Body
= nullptr;
14932 SmallVector
<SmallVector
<llvm::PointerUnion
<Stmt
*, Decl
*>, 0>, 4>
14934 if (!checkTransformableLoopNest(OMPD_tile
, AStmt
, NumLoops
, LoopHelpers
, Body
,
14936 return StmtError();
14938 // Delay tiling to when template is completely instantiated.
14939 if (CurContext
->isDependentContext())
14940 return OMPTileDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
,
14941 NumLoops
, AStmt
, nullptr, nullptr);
14943 SmallVector
<Decl
*, 4> PreInits
;
14945 // Create iteration variables for the generated loops.
14946 SmallVector
<VarDecl
*, 4> FloorIndVars
;
14947 SmallVector
<VarDecl
*, 4> TileIndVars
;
14948 FloorIndVars
.resize(NumLoops
);
14949 TileIndVars
.resize(NumLoops
);
14950 for (unsigned I
= 0; I
< NumLoops
; ++I
) {
14951 OMPLoopBasedDirective::HelperExprs
&LoopHelper
= LoopHelpers
[I
];
14953 assert(LoopHelper
.Counters
.size() == 1 &&
14954 "Expect single-dimensional loop iteration space");
14955 auto *OrigCntVar
= cast
<DeclRefExpr
>(LoopHelper
.Counters
.front());
14956 std::string OrigVarName
= OrigCntVar
->getNameInfo().getAsString();
14957 DeclRefExpr
*IterVarRef
= cast
<DeclRefExpr
>(LoopHelper
.IterationVarRef
);
14958 QualType CntTy
= IterVarRef
->getType();
14960 // Iteration variable for the floor (i.e. outer) loop.
14962 std::string FloorCntName
=
14963 (Twine(".floor_") + llvm::utostr(I
) + ".iv." + OrigVarName
).str();
14964 VarDecl
*FloorCntDecl
=
14965 buildVarDecl(*this, {}, CntTy
, FloorCntName
, nullptr, OrigCntVar
);
14966 FloorIndVars
[I
] = FloorCntDecl
;
14969 // Iteration variable for the tile (i.e. inner) loop.
14971 std::string TileCntName
=
14972 (Twine(".tile_") + llvm::utostr(I
) + ".iv." + OrigVarName
).str();
14974 // Reuse the iteration variable created by checkOpenMPLoop. It is also
14975 // used by the expressions to derive the original iteration variable's
14976 // value from the logical iteration number.
14977 auto *TileCntDecl
= cast
<VarDecl
>(IterVarRef
->getDecl());
14978 TileCntDecl
->setDeclName(&PP
.getIdentifierTable().get(TileCntName
));
14979 TileIndVars
[I
] = TileCntDecl
;
14981 for (auto &P
: OriginalInits
[I
]) {
14982 if (auto *D
= P
.dyn_cast
<Decl
*>())
14983 PreInits
.push_back(D
);
14984 else if (auto *PI
= dyn_cast_or_null
<DeclStmt
>(P
.dyn_cast
<Stmt
*>()))
14985 PreInits
.append(PI
->decl_begin(), PI
->decl_end());
14987 if (auto *PI
= cast_or_null
<DeclStmt
>(LoopHelper
.PreInits
))
14988 PreInits
.append(PI
->decl_begin(), PI
->decl_end());
14989 // Gather declarations for the data members used as counters.
14990 for (Expr
*CounterRef
: LoopHelper
.Counters
) {
14991 auto *CounterDecl
= cast
<DeclRefExpr
>(CounterRef
)->getDecl();
14992 if (isa
<OMPCapturedExprDecl
>(CounterDecl
))
14993 PreInits
.push_back(CounterDecl
);
14997 // Once the original iteration values are set, append the innermost body.
14998 Stmt
*Inner
= Body
;
15000 // Create tile loops from the inside to the outside.
15001 for (int I
= NumLoops
- 1; I
>= 0; --I
) {
15002 OMPLoopBasedDirective::HelperExprs
&LoopHelper
= LoopHelpers
[I
];
15003 Expr
*NumIterations
= LoopHelper
.NumIterations
;
15004 auto *OrigCntVar
= cast
<DeclRefExpr
>(LoopHelper
.Counters
[0]);
15005 QualType CntTy
= OrigCntVar
->getType();
15006 Expr
*DimTileSize
= SizesClause
->getSizesRefs()[I
];
15007 Scope
*CurScope
= getCurScope();
15009 // Commonly used variables.
15010 DeclRefExpr
*TileIV
= buildDeclRefExpr(*this, TileIndVars
[I
], CntTy
,
15011 OrigCntVar
->getExprLoc());
15012 DeclRefExpr
*FloorIV
= buildDeclRefExpr(*this, FloorIndVars
[I
], CntTy
,
15013 OrigCntVar
->getExprLoc());
15015 // For init-statement: auto .tile.iv = .floor.iv
15016 AddInitializerToDecl(TileIndVars
[I
], DefaultLvalueConversion(FloorIV
).get(),
15017 /*DirectInit=*/false);
15018 Decl
*CounterDecl
= TileIndVars
[I
];
15019 StmtResult InitStmt
= new (Context
)
15020 DeclStmt(DeclGroupRef::Create(Context
, &CounterDecl
, 1),
15021 OrigCntVar
->getBeginLoc(), OrigCntVar
->getEndLoc());
15022 if (!InitStmt
.isUsable())
15023 return StmtError();
15025 // For cond-expression: .tile.iv < min(.floor.iv + DimTileSize,
15027 ExprResult EndOfTile
= BuildBinOp(CurScope
, LoopHelper
.Cond
->getExprLoc(),
15028 BO_Add
, FloorIV
, DimTileSize
);
15029 if (!EndOfTile
.isUsable())
15030 return StmtError();
15031 ExprResult IsPartialTile
=
15032 BuildBinOp(CurScope
, LoopHelper
.Cond
->getExprLoc(), BO_LT
,
15033 NumIterations
, EndOfTile
.get());
15034 if (!IsPartialTile
.isUsable())
15035 return StmtError();
15036 ExprResult MinTileAndIterSpace
= ActOnConditionalOp(
15037 LoopHelper
.Cond
->getBeginLoc(), LoopHelper
.Cond
->getEndLoc(),
15038 IsPartialTile
.get(), NumIterations
, EndOfTile
.get());
15039 if (!MinTileAndIterSpace
.isUsable())
15040 return StmtError();
15041 ExprResult CondExpr
= BuildBinOp(CurScope
, LoopHelper
.Cond
->getExprLoc(),
15042 BO_LT
, TileIV
, MinTileAndIterSpace
.get());
15043 if (!CondExpr
.isUsable())
15044 return StmtError();
15046 // For incr-statement: ++.tile.iv
15047 ExprResult IncrStmt
=
15048 BuildUnaryOp(CurScope
, LoopHelper
.Inc
->getExprLoc(), UO_PreInc
, TileIV
);
15049 if (!IncrStmt
.isUsable())
15050 return StmtError();
15052 // Statements to set the original iteration variable's value from the
15053 // logical iteration number.
15054 // Generated for loop is:
15055 // Original_for_init;
15056 // for (auto .tile.iv = .floor.iv; .tile.iv < min(.floor.iv + DimTileSize,
15057 // NumIterations); ++.tile.iv) {
15059 // Original_counter_update;
15061 // FIXME: If the innermost body is an loop itself, inserting these
15062 // statements stops it being recognized as a perfectly nested loop (e.g.
15063 // for applying tiling again). If this is the case, sink the expressions
15064 // further into the inner loop.
15065 SmallVector
<Stmt
*, 4> BodyParts
;
15066 BodyParts
.append(LoopHelper
.Updates
.begin(), LoopHelper
.Updates
.end());
15067 BodyParts
.push_back(Inner
);
15068 Inner
= CompoundStmt::Create(Context
, BodyParts
, FPOptionsOverride(),
15069 Inner
->getBeginLoc(), Inner
->getEndLoc());
15070 Inner
= new (Context
)
15071 ForStmt(Context
, InitStmt
.get(), CondExpr
.get(), nullptr,
15072 IncrStmt
.get(), Inner
, LoopHelper
.Init
->getBeginLoc(),
15073 LoopHelper
.Init
->getBeginLoc(), LoopHelper
.Inc
->getEndLoc());
15076 // Create floor loops from the inside to the outside.
15077 for (int I
= NumLoops
- 1; I
>= 0; --I
) {
15078 auto &LoopHelper
= LoopHelpers
[I
];
15079 Expr
*NumIterations
= LoopHelper
.NumIterations
;
15080 DeclRefExpr
*OrigCntVar
= cast
<DeclRefExpr
>(LoopHelper
.Counters
[0]);
15081 QualType CntTy
= OrigCntVar
->getType();
15082 Expr
*DimTileSize
= SizesClause
->getSizesRefs()[I
];
15083 Scope
*CurScope
= getCurScope();
15085 // Commonly used variables.
15086 DeclRefExpr
*FloorIV
= buildDeclRefExpr(*this, FloorIndVars
[I
], CntTy
,
15087 OrigCntVar
->getExprLoc());
15089 // For init-statement: auto .floor.iv = 0
15090 AddInitializerToDecl(
15092 ActOnIntegerConstant(LoopHelper
.Init
->getExprLoc(), 0).get(),
15093 /*DirectInit=*/false);
15094 Decl
*CounterDecl
= FloorIndVars
[I
];
15095 StmtResult InitStmt
= new (Context
)
15096 DeclStmt(DeclGroupRef::Create(Context
, &CounterDecl
, 1),
15097 OrigCntVar
->getBeginLoc(), OrigCntVar
->getEndLoc());
15098 if (!InitStmt
.isUsable())
15099 return StmtError();
15101 // For cond-expression: .floor.iv < NumIterations
15102 ExprResult CondExpr
= BuildBinOp(CurScope
, LoopHelper
.Cond
->getExprLoc(),
15103 BO_LT
, FloorIV
, NumIterations
);
15104 if (!CondExpr
.isUsable())
15105 return StmtError();
15107 // For incr-statement: .floor.iv += DimTileSize
15108 ExprResult IncrStmt
= BuildBinOp(CurScope
, LoopHelper
.Inc
->getExprLoc(),
15109 BO_AddAssign
, FloorIV
, DimTileSize
);
15110 if (!IncrStmt
.isUsable())
15111 return StmtError();
15113 Inner
= new (Context
)
15114 ForStmt(Context
, InitStmt
.get(), CondExpr
.get(), nullptr,
15115 IncrStmt
.get(), Inner
, LoopHelper
.Init
->getBeginLoc(),
15116 LoopHelper
.Init
->getBeginLoc(), LoopHelper
.Inc
->getEndLoc());
15119 return OMPTileDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, NumLoops
,
15121 buildPreInits(Context
, PreInits
));
15124 StmtResult
Sema::ActOnOpenMPUnrollDirective(ArrayRef
<OMPClause
*> Clauses
,
15126 SourceLocation StartLoc
,
15127 SourceLocation EndLoc
) {
15128 // Empty statement should only be possible if there already was an error.
15130 return StmtError();
15132 if (checkMutuallyExclusiveClauses(*this, Clauses
, {OMPC_partial
, OMPC_full
}))
15133 return StmtError();
15135 const OMPFullClause
*FullClause
=
15136 OMPExecutableDirective::getSingleClause
<OMPFullClause
>(Clauses
);
15137 const OMPPartialClause
*PartialClause
=
15138 OMPExecutableDirective::getSingleClause
<OMPPartialClause
>(Clauses
);
15139 assert(!(FullClause
&& PartialClause
) &&
15140 "mutual exclusivity must have been checked before");
15142 constexpr unsigned NumLoops
= 1;
15143 Stmt
*Body
= nullptr;
15144 SmallVector
<OMPLoopBasedDirective::HelperExprs
, NumLoops
> LoopHelpers(
15146 SmallVector
<SmallVector
<llvm::PointerUnion
<Stmt
*, Decl
*>, 0>, NumLoops
+ 1>
15148 if (!checkTransformableLoopNest(OMPD_unroll
, AStmt
, NumLoops
, LoopHelpers
,
15149 Body
, OriginalInits
))
15150 return StmtError();
15152 unsigned NumGeneratedLoops
= PartialClause
? 1 : 0;
15154 // Delay unrolling to when template is completely instantiated.
15155 if (CurContext
->isDependentContext())
15156 return OMPUnrollDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
15157 NumGeneratedLoops
, nullptr, nullptr);
15159 OMPLoopBasedDirective::HelperExprs
&LoopHelper
= LoopHelpers
.front();
15162 if (!VerifyPositiveIntegerConstantInClause(
15163 LoopHelper
.NumIterations
, OMPC_full
, /*StrictlyPositive=*/false,
15164 /*SuppressExprDiags=*/true)
15166 Diag(AStmt
->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count
);
15167 Diag(FullClause
->getBeginLoc(), diag::note_omp_directive_here
)
15168 << "#pragma omp unroll full";
15169 return StmtError();
15173 // The generated loop may only be passed to other loop-associated directive
15174 // when a partial clause is specified. Without the requirement it is
15175 // sufficient to generate loop unroll metadata at code-generation.
15176 if (NumGeneratedLoops
== 0)
15177 return OMPUnrollDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
15178 NumGeneratedLoops
, nullptr, nullptr);
15180 // Otherwise, we need to provide a de-sugared/transformed AST that can be
15181 // associated with another loop directive.
15183 // The canonical loop analysis return by checkTransformableLoopNest assumes
15184 // the following structure to be the same loop without transformations or
15185 // directives applied: \code OriginalInits; LoopHelper.PreInits;
15186 // LoopHelper.Counters;
15187 // for (; IV < LoopHelper.NumIterations; ++IV) {
15188 // LoopHelper.Updates;
15192 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
15193 // and referenced by LoopHelper.IterationVarRef.
15195 // The unrolling directive transforms this into the following loop:
15197 // OriginalInits; \
15198 // LoopHelper.PreInits; > NewPreInits
15199 // LoopHelper.Counters; /
15200 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
15201 // #pragma clang loop unroll_count(Factor)
15202 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
15204 // LoopHelper.Updates;
15209 // where UIV is a new logical iteration counter. IV must be the same VarDecl
15210 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
15211 // references it. If the partially unrolled loop is associated with another
15212 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
15213 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
15214 // OpenMP canonical loop. The inner loop is not an associable canonical loop
15215 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
15216 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
15217 // property of the OMPLoopBasedDirective instead of statements in
15218 // CompoundStatement. This is to allow the loop to become a non-outermost loop
15219 // of a canonical loop nest where these PreInits are emitted before the
15220 // outermost directive.
15222 // Determine the PreInit declarations.
15223 SmallVector
<Decl
*, 4> PreInits
;
15224 assert(OriginalInits
.size() == 1 &&
15225 "Expecting a single-dimensional loop iteration space");
15226 for (auto &P
: OriginalInits
[0]) {
15227 if (auto *D
= P
.dyn_cast
<Decl
*>())
15228 PreInits
.push_back(D
);
15229 else if (auto *PI
= dyn_cast_or_null
<DeclStmt
>(P
.dyn_cast
<Stmt
*>()))
15230 PreInits
.append(PI
->decl_begin(), PI
->decl_end());
15232 if (auto *PI
= cast_or_null
<DeclStmt
>(LoopHelper
.PreInits
))
15233 PreInits
.append(PI
->decl_begin(), PI
->decl_end());
15234 // Gather declarations for the data members used as counters.
15235 for (Expr
*CounterRef
: LoopHelper
.Counters
) {
15236 auto *CounterDecl
= cast
<DeclRefExpr
>(CounterRef
)->getDecl();
15237 if (isa
<OMPCapturedExprDecl
>(CounterDecl
))
15238 PreInits
.push_back(CounterDecl
);
15241 auto *IterationVarRef
= cast
<DeclRefExpr
>(LoopHelper
.IterationVarRef
);
15242 QualType IVTy
= IterationVarRef
->getType();
15243 assert(LoopHelper
.Counters
.size() == 1 &&
15244 "Expecting a single-dimensional loop iteration space");
15245 auto *OrigVar
= cast
<DeclRefExpr
>(LoopHelper
.Counters
.front());
15247 // Determine the unroll factor.
15249 SourceLocation FactorLoc
;
15250 if (Expr
*FactorVal
= PartialClause
->getFactor()) {
15251 Factor
= FactorVal
->getIntegerConstantExpr(Context
)->getZExtValue();
15252 FactorLoc
= FactorVal
->getExprLoc();
15254 // TODO: Use a better profitability model.
15257 assert(Factor
> 0 && "Expected positive unroll factor");
15258 auto MakeFactorExpr
= [this, Factor
, IVTy
, FactorLoc
]() {
15259 return IntegerLiteral::Create(
15260 Context
, llvm::APInt(Context
.getIntWidth(IVTy
), Factor
), IVTy
,
15264 // Iteration variable SourceLocations.
15265 SourceLocation OrigVarLoc
= OrigVar
->getExprLoc();
15266 SourceLocation OrigVarLocBegin
= OrigVar
->getBeginLoc();
15267 SourceLocation OrigVarLocEnd
= OrigVar
->getEndLoc();
15269 // Internal variable names.
15270 std::string OrigVarName
= OrigVar
->getNameInfo().getAsString();
15271 std::string OuterIVName
= (Twine(".unrolled.iv.") + OrigVarName
).str();
15272 std::string InnerIVName
= (Twine(".unroll_inner.iv.") + OrigVarName
).str();
15273 std::string InnerTripCountName
=
15274 (Twine(".unroll_inner.tripcount.") + OrigVarName
).str();
15276 // Create the iteration variable for the unrolled loop.
15277 VarDecl
*OuterIVDecl
=
15278 buildVarDecl(*this, {}, IVTy
, OuterIVName
, nullptr, OrigVar
);
15279 auto MakeOuterRef
= [this, OuterIVDecl
, IVTy
, OrigVarLoc
]() {
15280 return buildDeclRefExpr(*this, OuterIVDecl
, IVTy
, OrigVarLoc
);
15283 // Iteration variable for the inner loop: Reuse the iteration variable created
15284 // by checkOpenMPLoop.
15285 auto *InnerIVDecl
= cast
<VarDecl
>(IterationVarRef
->getDecl());
15286 InnerIVDecl
->setDeclName(&PP
.getIdentifierTable().get(InnerIVName
));
15287 auto MakeInnerRef
= [this, InnerIVDecl
, IVTy
, OrigVarLoc
]() {
15288 return buildDeclRefExpr(*this, InnerIVDecl
, IVTy
, OrigVarLoc
);
15291 // Make a copy of the NumIterations expression for each use: By the AST
15292 // constraints, every expression object in a DeclContext must be unique.
15293 CaptureVars
CopyTransformer(*this);
15294 auto MakeNumIterations
= [&CopyTransformer
, &LoopHelper
]() -> Expr
* {
15295 return AssertSuccess(
15296 CopyTransformer
.TransformExpr(LoopHelper
.NumIterations
));
15299 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
15300 ExprResult LValueConv
= DefaultLvalueConversion(MakeOuterRef());
15301 AddInitializerToDecl(InnerIVDecl
, LValueConv
.get(), /*DirectInit=*/false);
15302 StmtResult InnerInit
= new (Context
)
15303 DeclStmt(DeclGroupRef(InnerIVDecl
), OrigVarLocBegin
, OrigVarLocEnd
);
15304 if (!InnerInit
.isUsable())
15305 return StmtError();
15307 // Inner For cond-expression:
15309 // .unroll_inner.iv < .unrolled.iv + Factor &&
15310 // .unroll_inner.iv < NumIterations
15312 // This conjunction of two conditions allows ScalarEvolution to derive the
15313 // maximum trip count of the inner loop.
15314 ExprResult EndOfTile
= BuildBinOp(CurScope
, LoopHelper
.Cond
->getExprLoc(),
15315 BO_Add
, MakeOuterRef(), MakeFactorExpr());
15316 if (!EndOfTile
.isUsable())
15317 return StmtError();
15318 ExprResult InnerCond1
= BuildBinOp(CurScope
, LoopHelper
.Cond
->getExprLoc(),
15319 BO_LT
, MakeInnerRef(), EndOfTile
.get());
15320 if (!InnerCond1
.isUsable())
15321 return StmtError();
15322 ExprResult InnerCond2
=
15323 BuildBinOp(CurScope
, LoopHelper
.Cond
->getExprLoc(), BO_LT
, MakeInnerRef(),
15324 MakeNumIterations());
15325 if (!InnerCond2
.isUsable())
15326 return StmtError();
15327 ExprResult InnerCond
=
15328 BuildBinOp(CurScope
, LoopHelper
.Cond
->getExprLoc(), BO_LAnd
,
15329 InnerCond1
.get(), InnerCond2
.get());
15330 if (!InnerCond
.isUsable())
15331 return StmtError();
15333 // Inner For incr-statement: ++.unroll_inner.iv
15334 ExprResult InnerIncr
= BuildUnaryOp(CurScope
, LoopHelper
.Inc
->getExprLoc(),
15335 UO_PreInc
, MakeInnerRef());
15336 if (!InnerIncr
.isUsable())
15337 return StmtError();
15339 // Inner For statement.
15340 SmallVector
<Stmt
*> InnerBodyStmts
;
15341 InnerBodyStmts
.append(LoopHelper
.Updates
.begin(), LoopHelper
.Updates
.end());
15342 InnerBodyStmts
.push_back(Body
);
15343 CompoundStmt
*InnerBody
=
15344 CompoundStmt::Create(Context
, InnerBodyStmts
, FPOptionsOverride(),
15345 Body
->getBeginLoc(), Body
->getEndLoc());
15346 ForStmt
*InnerFor
= new (Context
)
15347 ForStmt(Context
, InnerInit
.get(), InnerCond
.get(), nullptr,
15348 InnerIncr
.get(), InnerBody
, LoopHelper
.Init
->getBeginLoc(),
15349 LoopHelper
.Init
->getBeginLoc(), LoopHelper
.Inc
->getEndLoc());
15351 // Unroll metadata for the inner loop.
15352 // This needs to take into account the remainder portion of the unrolled loop,
15353 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
15354 // supports multiple loop exits. Instead, unroll using a factor equivalent to
15355 // the maximum trip count, which will also generate a remainder loop. Just
15356 // `unroll(enable)` (which could have been useful if the user has not
15357 // specified a concrete factor; even though the outer loop cannot be
15358 // influenced anymore, would avoid more code bloat than necessary) will refuse
15359 // the loop because "Won't unroll; remainder loop could not be generated when
15360 // assuming runtime trip count". Even if it did work, it must not choose a
15361 // larger unroll factor than the maximum loop length, or it would always just
15362 // execute the remainder loop.
15363 LoopHintAttr
*UnrollHintAttr
=
15364 LoopHintAttr::CreateImplicit(Context
, LoopHintAttr::UnrollCount
,
15365 LoopHintAttr::Numeric
, MakeFactorExpr());
15366 AttributedStmt
*InnerUnrolled
=
15367 AttributedStmt::Create(Context
, StartLoc
, {UnrollHintAttr
}, InnerFor
);
15369 // Outer For init-statement: auto .unrolled.iv = 0
15370 AddInitializerToDecl(
15371 OuterIVDecl
, ActOnIntegerConstant(LoopHelper
.Init
->getExprLoc(), 0).get(),
15372 /*DirectInit=*/false);
15373 StmtResult OuterInit
= new (Context
)
15374 DeclStmt(DeclGroupRef(OuterIVDecl
), OrigVarLocBegin
, OrigVarLocEnd
);
15375 if (!OuterInit
.isUsable())
15376 return StmtError();
15378 // Outer For cond-expression: .unrolled.iv < NumIterations
15379 ExprResult OuterConde
=
15380 BuildBinOp(CurScope
, LoopHelper
.Cond
->getExprLoc(), BO_LT
, MakeOuterRef(),
15381 MakeNumIterations());
15382 if (!OuterConde
.isUsable())
15383 return StmtError();
15385 // Outer For incr-statement: .unrolled.iv += Factor
15386 ExprResult OuterIncr
=
15387 BuildBinOp(CurScope
, LoopHelper
.Inc
->getExprLoc(), BO_AddAssign
,
15388 MakeOuterRef(), MakeFactorExpr());
15389 if (!OuterIncr
.isUsable())
15390 return StmtError();
15392 // Outer For statement.
15393 ForStmt
*OuterFor
= new (Context
)
15394 ForStmt(Context
, OuterInit
.get(), OuterConde
.get(), nullptr,
15395 OuterIncr
.get(), InnerUnrolled
, LoopHelper
.Init
->getBeginLoc(),
15396 LoopHelper
.Init
->getBeginLoc(), LoopHelper
.Inc
->getEndLoc());
15398 return OMPUnrollDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
15399 NumGeneratedLoops
, OuterFor
,
15400 buildPreInits(Context
, PreInits
));
15403 OMPClause
*Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind
, Expr
*Expr
,
15404 SourceLocation StartLoc
,
15405 SourceLocation LParenLoc
,
15406 SourceLocation EndLoc
) {
15407 OMPClause
*Res
= nullptr;
15410 Res
= ActOnOpenMPFinalClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15412 case OMPC_num_threads
:
15413 Res
= ActOnOpenMPNumThreadsClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15416 Res
= ActOnOpenMPSafelenClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15419 Res
= ActOnOpenMPSimdlenClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15421 case OMPC_allocator
:
15422 Res
= ActOnOpenMPAllocatorClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15424 case OMPC_collapse
:
15425 Res
= ActOnOpenMPCollapseClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15428 Res
= ActOnOpenMPOrderedClause(StartLoc
, EndLoc
, LParenLoc
, Expr
);
15430 case OMPC_num_teams
:
15431 Res
= ActOnOpenMPNumTeamsClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15433 case OMPC_thread_limit
:
15434 Res
= ActOnOpenMPThreadLimitClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15436 case OMPC_priority
:
15437 Res
= ActOnOpenMPPriorityClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15440 Res
= ActOnOpenMPHintClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15443 Res
= ActOnOpenMPDepobjClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15446 Res
= ActOnOpenMPDetachClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15448 case OMPC_novariants
:
15449 Res
= ActOnOpenMPNovariantsClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15451 case OMPC_nocontext
:
15452 Res
= ActOnOpenMPNocontextClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15455 Res
= ActOnOpenMPFilterClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15458 Res
= ActOnOpenMPPartialClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15461 Res
= ActOnOpenMPMessageClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15464 Res
= ActOnOpenMPAlignClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15466 case OMPC_ompx_dyn_cgroup_mem
:
15467 Res
= ActOnOpenMPXDynCGroupMemClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15469 case OMPC_grainsize
:
15470 case OMPC_num_tasks
:
15474 case OMPC_proc_bind
:
15475 case OMPC_schedule
:
15477 case OMPC_firstprivate
:
15478 case OMPC_lastprivate
:
15480 case OMPC_reduction
:
15481 case OMPC_task_reduction
:
15482 case OMPC_in_reduction
:
15486 case OMPC_copyprivate
:
15489 case OMPC_mergeable
:
15490 case OMPC_threadprivate
:
15492 case OMPC_allocate
:
15509 case OMPC_dist_schedule
:
15510 case OMPC_defaultmap
:
15515 case OMPC_use_device_ptr
:
15516 case OMPC_use_device_addr
:
15517 case OMPC_is_device_ptr
:
15518 case OMPC_unified_address
:
15519 case OMPC_unified_shared_memory
:
15520 case OMPC_reverse_offload
:
15521 case OMPC_dynamic_allocators
:
15522 case OMPC_atomic_default_mem_order
:
15523 case OMPC_device_type
:
15525 case OMPC_nontemporal
:
15528 case OMPC_severity
:
15530 case OMPC_inclusive
:
15531 case OMPC_exclusive
:
15532 case OMPC_uses_allocators
:
15533 case OMPC_affinity
:
15537 llvm_unreachable("Clause is not allowed.");
15542 // An OpenMP directive such as 'target parallel' has two captured regions:
15543 // for the 'target' and 'parallel' respectively. This function returns
15544 // the region in which to capture expressions associated with a clause.
15545 // A return value of OMPD_unknown signifies that the expression should not
15547 static OpenMPDirectiveKind
getOpenMPCaptureRegionForClause(
15548 OpenMPDirectiveKind DKind
, OpenMPClauseKind CKind
, unsigned OpenMPVersion
,
15549 OpenMPDirectiveKind NameModifier
= OMPD_unknown
) {
15550 OpenMPDirectiveKind CaptureRegion
= OMPD_unknown
;
15554 case OMPD_target_parallel_for_simd
:
15555 if (OpenMPVersion
>= 50 &&
15556 (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
)) {
15557 CaptureRegion
= OMPD_parallel
;
15561 case OMPD_target_parallel
:
15562 case OMPD_target_parallel_for
:
15563 case OMPD_target_parallel_loop
:
15564 // If this clause applies to the nested 'parallel' region, capture within
15565 // the 'target' region, otherwise do not capture.
15566 if (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_parallel
)
15567 CaptureRegion
= OMPD_target
;
15569 case OMPD_target_teams_distribute_parallel_for_simd
:
15570 if (OpenMPVersion
>= 50 &&
15571 (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
)) {
15572 CaptureRegion
= OMPD_parallel
;
15576 case OMPD_target_teams_loop
:
15577 case OMPD_target_teams_distribute_parallel_for
:
15578 // If this clause applies to the nested 'parallel' region, capture within
15579 // the 'teams' region, otherwise do not capture.
15580 if (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_parallel
)
15581 CaptureRegion
= OMPD_teams
;
15583 case OMPD_teams_distribute_parallel_for_simd
:
15584 if (OpenMPVersion
>= 50 &&
15585 (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
)) {
15586 CaptureRegion
= OMPD_parallel
;
15590 case OMPD_teams_distribute_parallel_for
:
15591 CaptureRegion
= OMPD_teams
;
15593 case OMPD_target_update
:
15594 case OMPD_target_enter_data
:
15595 case OMPD_target_exit_data
:
15596 CaptureRegion
= OMPD_task
;
15598 case OMPD_parallel_masked_taskloop
:
15599 if (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_taskloop
)
15600 CaptureRegion
= OMPD_parallel
;
15602 case OMPD_parallel_master_taskloop
:
15603 if (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_taskloop
)
15604 CaptureRegion
= OMPD_parallel
;
15606 case OMPD_parallel_masked_taskloop_simd
:
15607 if ((OpenMPVersion
<= 45 && NameModifier
== OMPD_unknown
) ||
15608 NameModifier
== OMPD_taskloop
) {
15609 CaptureRegion
= OMPD_parallel
;
15612 if (OpenMPVersion
<= 45)
15614 if (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
)
15615 CaptureRegion
= OMPD_taskloop
;
15617 case OMPD_parallel_master_taskloop_simd
:
15618 if ((OpenMPVersion
<= 45 && NameModifier
== OMPD_unknown
) ||
15619 NameModifier
== OMPD_taskloop
) {
15620 CaptureRegion
= OMPD_parallel
;
15623 if (OpenMPVersion
<= 45)
15625 if (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
)
15626 CaptureRegion
= OMPD_taskloop
;
15628 case OMPD_parallel_for_simd
:
15629 if (OpenMPVersion
<= 45)
15631 if (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
)
15632 CaptureRegion
= OMPD_parallel
;
15634 case OMPD_taskloop_simd
:
15635 case OMPD_master_taskloop_simd
:
15636 case OMPD_masked_taskloop_simd
:
15637 if (OpenMPVersion
<= 45)
15639 if (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
)
15640 CaptureRegion
= OMPD_taskloop
;
15642 case OMPD_distribute_parallel_for_simd
:
15643 if (OpenMPVersion
<= 45)
15645 if (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
)
15646 CaptureRegion
= OMPD_parallel
;
15648 case OMPD_target_simd
:
15649 if (OpenMPVersion
>= 50 &&
15650 (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
))
15651 CaptureRegion
= OMPD_target
;
15653 case OMPD_teams_distribute_simd
:
15654 case OMPD_target_teams_distribute_simd
:
15655 if (OpenMPVersion
>= 50 &&
15656 (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
))
15657 CaptureRegion
= OMPD_teams
;
15660 case OMPD_parallel
:
15661 case OMPD_parallel_master
:
15662 case OMPD_parallel_masked
:
15663 case OMPD_parallel_sections
:
15664 case OMPD_parallel_for
:
15665 case OMPD_parallel_loop
:
15667 case OMPD_target_teams
:
15668 case OMPD_target_teams_distribute
:
15669 case OMPD_distribute_parallel_for
:
15671 case OMPD_taskloop
:
15672 case OMPD_master_taskloop
:
15673 case OMPD_masked_taskloop
:
15674 case OMPD_target_data
:
15676 case OMPD_for_simd
:
15677 case OMPD_distribute_simd
:
15678 // Do not capture if-clause expressions.
15680 case OMPD_threadprivate
:
15681 case OMPD_allocate
:
15682 case OMPD_taskyield
:
15685 case OMPD_taskwait
:
15686 case OMPD_cancellation_point
:
15690 case OMPD_declare_reduction
:
15691 case OMPD_declare_mapper
:
15692 case OMPD_declare_simd
:
15693 case OMPD_declare_variant
:
15694 case OMPD_begin_declare_variant
:
15695 case OMPD_end_declare_variant
:
15696 case OMPD_declare_target
:
15697 case OMPD_end_declare_target
:
15699 case OMPD_teams_loop
:
15704 case OMPD_sections
:
15709 case OMPD_critical
:
15710 case OMPD_taskgroup
:
15711 case OMPD_distribute
:
15714 case OMPD_teams_distribute
:
15715 case OMPD_requires
:
15716 case OMPD_metadirective
:
15717 llvm_unreachable("Unexpected OpenMP directive with if-clause");
15720 llvm_unreachable("Unknown OpenMP directive");
15723 case OMPC_num_threads
:
15725 case OMPD_target_parallel
:
15726 case OMPD_target_parallel_for
:
15727 case OMPD_target_parallel_for_simd
:
15728 case OMPD_target_parallel_loop
:
15729 CaptureRegion
= OMPD_target
;
15731 case OMPD_teams_distribute_parallel_for
:
15732 case OMPD_teams_distribute_parallel_for_simd
:
15733 case OMPD_target_teams_distribute_parallel_for
:
15734 case OMPD_target_teams_distribute_parallel_for_simd
:
15735 CaptureRegion
= OMPD_teams
;
15737 case OMPD_parallel
:
15738 case OMPD_parallel_master
:
15739 case OMPD_parallel_masked
:
15740 case OMPD_parallel_sections
:
15741 case OMPD_parallel_for
:
15742 case OMPD_parallel_for_simd
:
15743 case OMPD_parallel_loop
:
15744 case OMPD_distribute_parallel_for
:
15745 case OMPD_distribute_parallel_for_simd
:
15746 case OMPD_parallel_master_taskloop
:
15747 case OMPD_parallel_masked_taskloop
:
15748 case OMPD_parallel_master_taskloop_simd
:
15749 case OMPD_parallel_masked_taskloop_simd
:
15750 // Do not capture num_threads-clause expressions.
15752 case OMPD_target_data
:
15753 case OMPD_target_enter_data
:
15754 case OMPD_target_exit_data
:
15755 case OMPD_target_update
:
15757 case OMPD_target_simd
:
15758 case OMPD_target_teams
:
15759 case OMPD_target_teams_distribute
:
15760 case OMPD_target_teams_distribute_simd
:
15763 case OMPD_taskloop
:
15764 case OMPD_taskloop_simd
:
15765 case OMPD_master_taskloop
:
15766 case OMPD_masked_taskloop
:
15767 case OMPD_master_taskloop_simd
:
15768 case OMPD_masked_taskloop_simd
:
15769 case OMPD_threadprivate
:
15770 case OMPD_allocate
:
15771 case OMPD_taskyield
:
15774 case OMPD_taskwait
:
15775 case OMPD_cancellation_point
:
15779 case OMPD_declare_reduction
:
15780 case OMPD_declare_mapper
:
15781 case OMPD_declare_simd
:
15782 case OMPD_declare_variant
:
15783 case OMPD_begin_declare_variant
:
15784 case OMPD_end_declare_variant
:
15785 case OMPD_declare_target
:
15786 case OMPD_end_declare_target
:
15788 case OMPD_teams_loop
:
15789 case OMPD_target_teams_loop
:
15795 case OMPD_for_simd
:
15796 case OMPD_sections
:
15801 case OMPD_critical
:
15802 case OMPD_taskgroup
:
15803 case OMPD_distribute
:
15806 case OMPD_distribute_simd
:
15807 case OMPD_teams_distribute
:
15808 case OMPD_teams_distribute_simd
:
15809 case OMPD_requires
:
15810 case OMPD_metadirective
:
15811 llvm_unreachable("Unexpected OpenMP directive with num_threads-clause");
15814 llvm_unreachable("Unknown OpenMP directive");
15817 case OMPC_num_teams
:
15819 case OMPD_target_teams
:
15820 case OMPD_target_teams_distribute
:
15821 case OMPD_target_teams_distribute_simd
:
15822 case OMPD_target_teams_distribute_parallel_for
:
15823 case OMPD_target_teams_distribute_parallel_for_simd
:
15824 case OMPD_target_teams_loop
:
15825 CaptureRegion
= OMPD_target
;
15827 case OMPD_teams_distribute_parallel_for
:
15828 case OMPD_teams_distribute_parallel_for_simd
:
15830 case OMPD_teams_distribute
:
15831 case OMPD_teams_distribute_simd
:
15832 case OMPD_teams_loop
:
15833 // Do not capture num_teams-clause expressions.
15835 case OMPD_distribute_parallel_for
:
15836 case OMPD_distribute_parallel_for_simd
:
15838 case OMPD_taskloop
:
15839 case OMPD_taskloop_simd
:
15840 case OMPD_master_taskloop
:
15841 case OMPD_masked_taskloop
:
15842 case OMPD_master_taskloop_simd
:
15843 case OMPD_masked_taskloop_simd
:
15844 case OMPD_parallel_master_taskloop
:
15845 case OMPD_parallel_masked_taskloop
:
15846 case OMPD_parallel_master_taskloop_simd
:
15847 case OMPD_parallel_masked_taskloop_simd
:
15848 case OMPD_target_data
:
15849 case OMPD_target_enter_data
:
15850 case OMPD_target_exit_data
:
15851 case OMPD_target_update
:
15853 case OMPD_parallel
:
15854 case OMPD_parallel_master
:
15855 case OMPD_parallel_masked
:
15856 case OMPD_parallel_sections
:
15857 case OMPD_parallel_for
:
15858 case OMPD_parallel_for_simd
:
15859 case OMPD_parallel_loop
:
15861 case OMPD_target_simd
:
15862 case OMPD_target_parallel
:
15863 case OMPD_target_parallel_for
:
15864 case OMPD_target_parallel_for_simd
:
15865 case OMPD_target_parallel_loop
:
15866 case OMPD_threadprivate
:
15867 case OMPD_allocate
:
15868 case OMPD_taskyield
:
15871 case OMPD_taskwait
:
15872 case OMPD_cancellation_point
:
15876 case OMPD_declare_reduction
:
15877 case OMPD_declare_mapper
:
15878 case OMPD_declare_simd
:
15879 case OMPD_declare_variant
:
15880 case OMPD_begin_declare_variant
:
15881 case OMPD_end_declare_variant
:
15882 case OMPD_declare_target
:
15883 case OMPD_end_declare_target
:
15889 case OMPD_for_simd
:
15890 case OMPD_sections
:
15895 case OMPD_critical
:
15896 case OMPD_taskgroup
:
15897 case OMPD_distribute
:
15900 case OMPD_distribute_simd
:
15901 case OMPD_requires
:
15902 case OMPD_metadirective
:
15903 llvm_unreachable("Unexpected OpenMP directive with num_teams-clause");
15906 llvm_unreachable("Unknown OpenMP directive");
15909 case OMPC_thread_limit
:
15912 case OMPD_target_teams
:
15913 case OMPD_target_teams_distribute
:
15914 case OMPD_target_teams_distribute_simd
:
15915 case OMPD_target_teams_distribute_parallel_for
:
15916 case OMPD_target_teams_distribute_parallel_for_simd
:
15917 case OMPD_target_teams_loop
:
15918 case OMPD_target_simd
:
15919 case OMPD_target_parallel
:
15920 case OMPD_target_parallel_for
:
15921 case OMPD_target_parallel_for_simd
:
15922 case OMPD_target_parallel_loop
:
15923 CaptureRegion
= OMPD_target
;
15925 case OMPD_teams_distribute_parallel_for
:
15926 case OMPD_teams_distribute_parallel_for_simd
:
15928 case OMPD_teams_distribute
:
15929 case OMPD_teams_distribute_simd
:
15930 case OMPD_teams_loop
:
15931 // Do not capture thread_limit-clause expressions.
15933 case OMPD_distribute_parallel_for
:
15934 case OMPD_distribute_parallel_for_simd
:
15936 case OMPD_taskloop
:
15937 case OMPD_taskloop_simd
:
15938 case OMPD_master_taskloop
:
15939 case OMPD_masked_taskloop
:
15940 case OMPD_master_taskloop_simd
:
15941 case OMPD_masked_taskloop_simd
:
15942 case OMPD_parallel_master_taskloop
:
15943 case OMPD_parallel_masked_taskloop
:
15944 case OMPD_parallel_master_taskloop_simd
:
15945 case OMPD_parallel_masked_taskloop_simd
:
15946 case OMPD_target_data
:
15947 case OMPD_target_enter_data
:
15948 case OMPD_target_exit_data
:
15949 case OMPD_target_update
:
15951 case OMPD_parallel
:
15952 case OMPD_parallel_master
:
15953 case OMPD_parallel_masked
:
15954 case OMPD_parallel_sections
:
15955 case OMPD_parallel_for
:
15956 case OMPD_parallel_for_simd
:
15957 case OMPD_parallel_loop
:
15958 case OMPD_threadprivate
:
15959 case OMPD_allocate
:
15960 case OMPD_taskyield
:
15963 case OMPD_taskwait
:
15964 case OMPD_cancellation_point
:
15968 case OMPD_declare_reduction
:
15969 case OMPD_declare_mapper
:
15970 case OMPD_declare_simd
:
15971 case OMPD_declare_variant
:
15972 case OMPD_begin_declare_variant
:
15973 case OMPD_end_declare_variant
:
15974 case OMPD_declare_target
:
15975 case OMPD_end_declare_target
:
15981 case OMPD_for_simd
:
15982 case OMPD_sections
:
15987 case OMPD_critical
:
15988 case OMPD_taskgroup
:
15989 case OMPD_distribute
:
15992 case OMPD_distribute_simd
:
15993 case OMPD_requires
:
15994 case OMPD_metadirective
:
15995 llvm_unreachable("Unexpected OpenMP directive with thread_limit-clause");
15998 llvm_unreachable("Unknown OpenMP directive");
16001 case OMPC_schedule
:
16003 case OMPD_parallel_for
:
16004 case OMPD_parallel_for_simd
:
16005 case OMPD_distribute_parallel_for
:
16006 case OMPD_distribute_parallel_for_simd
:
16007 case OMPD_teams_distribute_parallel_for
:
16008 case OMPD_teams_distribute_parallel_for_simd
:
16009 case OMPD_target_parallel_for
:
16010 case OMPD_target_parallel_for_simd
:
16011 case OMPD_target_teams_distribute_parallel_for
:
16012 case OMPD_target_teams_distribute_parallel_for_simd
:
16013 CaptureRegion
= OMPD_parallel
;
16016 case OMPD_for_simd
:
16017 // Do not capture schedule-clause expressions.
16020 case OMPD_taskloop
:
16021 case OMPD_taskloop_simd
:
16022 case OMPD_master_taskloop
:
16023 case OMPD_masked_taskloop
:
16024 case OMPD_master_taskloop_simd
:
16025 case OMPD_masked_taskloop_simd
:
16026 case OMPD_parallel_master_taskloop
:
16027 case OMPD_parallel_masked_taskloop
:
16028 case OMPD_parallel_master_taskloop_simd
:
16029 case OMPD_parallel_masked_taskloop_simd
:
16030 case OMPD_target_data
:
16031 case OMPD_target_enter_data
:
16032 case OMPD_target_exit_data
:
16033 case OMPD_target_update
:
16035 case OMPD_teams_distribute
:
16036 case OMPD_teams_distribute_simd
:
16037 case OMPD_target_teams_distribute
:
16038 case OMPD_target_teams_distribute_simd
:
16040 case OMPD_target_simd
:
16041 case OMPD_target_parallel
:
16043 case OMPD_parallel
:
16044 case OMPD_parallel_master
:
16045 case OMPD_parallel_masked
:
16046 case OMPD_parallel_sections
:
16047 case OMPD_threadprivate
:
16048 case OMPD_allocate
:
16049 case OMPD_taskyield
:
16052 case OMPD_taskwait
:
16053 case OMPD_cancellation_point
:
16057 case OMPD_declare_reduction
:
16058 case OMPD_declare_mapper
:
16059 case OMPD_declare_simd
:
16060 case OMPD_declare_variant
:
16061 case OMPD_begin_declare_variant
:
16062 case OMPD_end_declare_variant
:
16063 case OMPD_declare_target
:
16064 case OMPD_end_declare_target
:
16066 case OMPD_teams_loop
:
16067 case OMPD_target_teams_loop
:
16068 case OMPD_parallel_loop
:
16069 case OMPD_target_parallel_loop
:
16073 case OMPD_sections
:
16078 case OMPD_critical
:
16079 case OMPD_taskgroup
:
16080 case OMPD_distribute
:
16083 case OMPD_distribute_simd
:
16084 case OMPD_target_teams
:
16085 case OMPD_requires
:
16086 case OMPD_metadirective
:
16087 llvm_unreachable("Unexpected OpenMP directive with schedule clause");
16090 llvm_unreachable("Unknown OpenMP directive");
16093 case OMPC_dist_schedule
:
16095 case OMPD_teams_distribute_parallel_for
:
16096 case OMPD_teams_distribute_parallel_for_simd
:
16097 case OMPD_teams_distribute
:
16098 case OMPD_teams_distribute_simd
:
16099 case OMPD_target_teams_distribute_parallel_for
:
16100 case OMPD_target_teams_distribute_parallel_for_simd
:
16101 case OMPD_target_teams_distribute
:
16102 case OMPD_target_teams_distribute_simd
:
16103 CaptureRegion
= OMPD_teams
;
16105 case OMPD_distribute_parallel_for
:
16106 case OMPD_distribute_parallel_for_simd
:
16107 case OMPD_distribute
:
16108 case OMPD_distribute_simd
:
16109 // Do not capture dist_schedule-clause expressions.
16111 case OMPD_parallel_for
:
16112 case OMPD_parallel_for_simd
:
16113 case OMPD_target_parallel_for_simd
:
16114 case OMPD_target_parallel_for
:
16116 case OMPD_taskloop
:
16117 case OMPD_taskloop_simd
:
16118 case OMPD_master_taskloop
:
16119 case OMPD_masked_taskloop
:
16120 case OMPD_master_taskloop_simd
:
16121 case OMPD_masked_taskloop_simd
:
16122 case OMPD_parallel_master_taskloop
:
16123 case OMPD_parallel_masked_taskloop
:
16124 case OMPD_parallel_master_taskloop_simd
:
16125 case OMPD_parallel_masked_taskloop_simd
:
16126 case OMPD_target_data
:
16127 case OMPD_target_enter_data
:
16128 case OMPD_target_exit_data
:
16129 case OMPD_target_update
:
16132 case OMPD_target_simd
:
16133 case OMPD_target_parallel
:
16135 case OMPD_parallel
:
16136 case OMPD_parallel_master
:
16137 case OMPD_parallel_masked
:
16138 case OMPD_parallel_sections
:
16139 case OMPD_threadprivate
:
16140 case OMPD_allocate
:
16141 case OMPD_taskyield
:
16144 case OMPD_taskwait
:
16145 case OMPD_cancellation_point
:
16149 case OMPD_declare_reduction
:
16150 case OMPD_declare_mapper
:
16151 case OMPD_declare_simd
:
16152 case OMPD_declare_variant
:
16153 case OMPD_begin_declare_variant
:
16154 case OMPD_end_declare_variant
:
16155 case OMPD_declare_target
:
16156 case OMPD_end_declare_target
:
16158 case OMPD_teams_loop
:
16159 case OMPD_target_teams_loop
:
16160 case OMPD_parallel_loop
:
16161 case OMPD_target_parallel_loop
:
16166 case OMPD_for_simd
:
16167 case OMPD_sections
:
16172 case OMPD_critical
:
16173 case OMPD_taskgroup
:
16176 case OMPD_target_teams
:
16177 case OMPD_requires
:
16178 case OMPD_metadirective
:
16179 llvm_unreachable("Unexpected OpenMP directive with dist_schedule clause");
16182 llvm_unreachable("Unknown OpenMP directive");
16185 case OMPC_ompx_dyn_cgroup_mem
:
16188 case OMPD_target_simd
:
16189 case OMPD_target_teams
:
16190 case OMPD_target_parallel
:
16191 case OMPD_target_teams_distribute
:
16192 case OMPD_target_teams_distribute_simd
:
16193 case OMPD_target_parallel_for
:
16194 case OMPD_target_parallel_for_simd
:
16195 case OMPD_target_parallel_loop
:
16196 case OMPD_target_teams_distribute_parallel_for
:
16197 case OMPD_target_teams_distribute_parallel_for_simd
:
16198 case OMPD_target_teams_loop
:
16199 CaptureRegion
= OMPD_target
;
16202 llvm_unreachable("Unknown OpenMP directive");
16207 case OMPD_target_update
:
16208 case OMPD_target_enter_data
:
16209 case OMPD_target_exit_data
:
16211 case OMPD_target_simd
:
16212 case OMPD_target_teams
:
16213 case OMPD_target_parallel
:
16214 case OMPD_target_teams_distribute
:
16215 case OMPD_target_teams_distribute_simd
:
16216 case OMPD_target_parallel_for
:
16217 case OMPD_target_parallel_for_simd
:
16218 case OMPD_target_parallel_loop
:
16219 case OMPD_target_teams_distribute_parallel_for
:
16220 case OMPD_target_teams_distribute_parallel_for_simd
:
16221 case OMPD_target_teams_loop
:
16222 case OMPD_dispatch
:
16223 CaptureRegion
= OMPD_task
;
16225 case OMPD_target_data
:
16227 // Do not capture device-clause expressions.
16229 case OMPD_teams_distribute_parallel_for
:
16230 case OMPD_teams_distribute_parallel_for_simd
:
16232 case OMPD_teams_distribute
:
16233 case OMPD_teams_distribute_simd
:
16234 case OMPD_distribute_parallel_for
:
16235 case OMPD_distribute_parallel_for_simd
:
16237 case OMPD_taskloop
:
16238 case OMPD_taskloop_simd
:
16239 case OMPD_master_taskloop
:
16240 case OMPD_masked_taskloop
:
16241 case OMPD_master_taskloop_simd
:
16242 case OMPD_masked_taskloop_simd
:
16243 case OMPD_parallel_master_taskloop
:
16244 case OMPD_parallel_masked_taskloop
:
16245 case OMPD_parallel_master_taskloop_simd
:
16246 case OMPD_parallel_masked_taskloop_simd
:
16248 case OMPD_parallel
:
16249 case OMPD_parallel_master
:
16250 case OMPD_parallel_masked
:
16251 case OMPD_parallel_sections
:
16252 case OMPD_parallel_for
:
16253 case OMPD_parallel_for_simd
:
16254 case OMPD_threadprivate
:
16255 case OMPD_allocate
:
16256 case OMPD_taskyield
:
16259 case OMPD_taskwait
:
16260 case OMPD_cancellation_point
:
16264 case OMPD_declare_reduction
:
16265 case OMPD_declare_mapper
:
16266 case OMPD_declare_simd
:
16267 case OMPD_declare_variant
:
16268 case OMPD_begin_declare_variant
:
16269 case OMPD_end_declare_variant
:
16270 case OMPD_declare_target
:
16271 case OMPD_end_declare_target
:
16273 case OMPD_teams_loop
:
16274 case OMPD_parallel_loop
:
16279 case OMPD_for_simd
:
16280 case OMPD_sections
:
16285 case OMPD_critical
:
16286 case OMPD_taskgroup
:
16287 case OMPD_distribute
:
16290 case OMPD_distribute_simd
:
16291 case OMPD_requires
:
16292 case OMPD_metadirective
:
16293 llvm_unreachable("Unexpected OpenMP directive with device-clause");
16296 llvm_unreachable("Unknown OpenMP directive");
16299 case OMPC_grainsize
:
16300 case OMPC_num_tasks
:
16302 case OMPC_priority
:
16305 case OMPD_taskloop
:
16306 case OMPD_taskloop_simd
:
16307 case OMPD_master_taskloop
:
16308 case OMPD_masked_taskloop
:
16309 case OMPD_master_taskloop_simd
:
16310 case OMPD_masked_taskloop_simd
:
16312 case OMPD_parallel_masked_taskloop
:
16313 case OMPD_parallel_masked_taskloop_simd
:
16314 case OMPD_parallel_master_taskloop
:
16315 case OMPD_parallel_master_taskloop_simd
:
16316 CaptureRegion
= OMPD_parallel
;
16318 case OMPD_target_update
:
16319 case OMPD_target_enter_data
:
16320 case OMPD_target_exit_data
:
16322 case OMPD_target_simd
:
16323 case OMPD_target_teams
:
16324 case OMPD_target_parallel
:
16325 case OMPD_target_teams_distribute
:
16326 case OMPD_target_teams_distribute_simd
:
16327 case OMPD_target_parallel_for
:
16328 case OMPD_target_parallel_for_simd
:
16329 case OMPD_target_teams_distribute_parallel_for
:
16330 case OMPD_target_teams_distribute_parallel_for_simd
:
16331 case OMPD_target_data
:
16332 case OMPD_teams_distribute_parallel_for
:
16333 case OMPD_teams_distribute_parallel_for_simd
:
16335 case OMPD_teams_distribute
:
16336 case OMPD_teams_distribute_simd
:
16337 case OMPD_distribute_parallel_for
:
16338 case OMPD_distribute_parallel_for_simd
:
16340 case OMPD_parallel
:
16341 case OMPD_parallel_master
:
16342 case OMPD_parallel_masked
:
16343 case OMPD_parallel_sections
:
16344 case OMPD_parallel_for
:
16345 case OMPD_parallel_for_simd
:
16346 case OMPD_threadprivate
:
16347 case OMPD_allocate
:
16348 case OMPD_taskyield
:
16351 case OMPD_taskwait
:
16352 case OMPD_cancellation_point
:
16356 case OMPD_declare_reduction
:
16357 case OMPD_declare_mapper
:
16358 case OMPD_declare_simd
:
16359 case OMPD_declare_variant
:
16360 case OMPD_begin_declare_variant
:
16361 case OMPD_end_declare_variant
:
16362 case OMPD_declare_target
:
16363 case OMPD_end_declare_target
:
16365 case OMPD_teams_loop
:
16366 case OMPD_target_teams_loop
:
16367 case OMPD_parallel_loop
:
16368 case OMPD_target_parallel_loop
:
16373 case OMPD_for_simd
:
16374 case OMPD_sections
:
16379 case OMPD_critical
:
16380 case OMPD_taskgroup
:
16381 case OMPD_distribute
:
16384 case OMPD_distribute_simd
:
16385 case OMPD_requires
:
16386 case OMPD_metadirective
:
16387 llvm_unreachable("Unexpected OpenMP directive with grainsize-clause");
16390 llvm_unreachable("Unknown OpenMP directive");
16393 case OMPC_novariants
:
16394 case OMPC_nocontext
:
16396 case OMPD_dispatch
:
16397 CaptureRegion
= OMPD_task
;
16400 llvm_unreachable("Unexpected OpenMP directive");
16404 // Do not capture filter-clause expressions.
16407 if (DKind
== OMPD_metadirective
) {
16408 CaptureRegion
= OMPD_metadirective
;
16409 } else if (DKind
== OMPD_unknown
) {
16410 llvm_unreachable("Unknown OpenMP directive");
16412 llvm_unreachable("Unexpected OpenMP directive with when clause");
16415 case OMPC_firstprivate
:
16416 case OMPC_lastprivate
:
16417 case OMPC_reduction
:
16418 case OMPC_task_reduction
:
16419 case OMPC_in_reduction
:
16422 case OMPC_proc_bind
:
16426 case OMPC_allocator
:
16427 case OMPC_collapse
:
16432 case OMPC_copyprivate
:
16436 case OMPC_mergeable
:
16437 case OMPC_threadprivate
:
16438 case OMPC_allocate
:
16457 case OMPC_defaultmap
:
16462 case OMPC_use_device_ptr
:
16463 case OMPC_use_device_addr
:
16464 case OMPC_is_device_ptr
:
16465 case OMPC_unified_address
:
16466 case OMPC_unified_shared_memory
:
16467 case OMPC_reverse_offload
:
16468 case OMPC_dynamic_allocators
:
16469 case OMPC_atomic_default_mem_order
:
16470 case OMPC_device_type
:
16472 case OMPC_nontemporal
:
16475 case OMPC_severity
:
16479 case OMPC_inclusive
:
16480 case OMPC_exclusive
:
16481 case OMPC_uses_allocators
:
16482 case OMPC_affinity
:
16485 llvm_unreachable("Unexpected OpenMP clause.");
16487 return CaptureRegion
;
16490 OMPClause
*Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier
,
16491 Expr
*Condition
, SourceLocation StartLoc
,
16492 SourceLocation LParenLoc
,
16493 SourceLocation NameModifierLoc
,
16494 SourceLocation ColonLoc
,
16495 SourceLocation EndLoc
) {
16496 Expr
*ValExpr
= Condition
;
16497 Stmt
*HelperValStmt
= nullptr;
16498 OpenMPDirectiveKind CaptureRegion
= OMPD_unknown
;
16499 if (!Condition
->isValueDependent() && !Condition
->isTypeDependent() &&
16500 !Condition
->isInstantiationDependent() &&
16501 !Condition
->containsUnexpandedParameterPack()) {
16502 ExprResult Val
= CheckBooleanCondition(StartLoc
, Condition
);
16503 if (Val
.isInvalid())
16506 ValExpr
= Val
.get();
16508 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
16509 CaptureRegion
= getOpenMPCaptureRegionForClause(
16510 DKind
, OMPC_if
, LangOpts
.OpenMP
, NameModifier
);
16511 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
16512 ValExpr
= MakeFullExpr(ValExpr
).get();
16513 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
16514 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
16515 HelperValStmt
= buildPreInits(Context
, Captures
);
16519 return new (Context
)
16520 OMPIfClause(NameModifier
, ValExpr
, HelperValStmt
, CaptureRegion
, StartLoc
,
16521 LParenLoc
, NameModifierLoc
, ColonLoc
, EndLoc
);
16524 OMPClause
*Sema::ActOnOpenMPFinalClause(Expr
*Condition
,
16525 SourceLocation StartLoc
,
16526 SourceLocation LParenLoc
,
16527 SourceLocation EndLoc
) {
16528 Expr
*ValExpr
= Condition
;
16529 Stmt
*HelperValStmt
= nullptr;
16530 OpenMPDirectiveKind CaptureRegion
= OMPD_unknown
;
16531 if (!Condition
->isValueDependent() && !Condition
->isTypeDependent() &&
16532 !Condition
->isInstantiationDependent() &&
16533 !Condition
->containsUnexpandedParameterPack()) {
16534 ExprResult Val
= CheckBooleanCondition(StartLoc
, Condition
);
16535 if (Val
.isInvalid())
16538 ValExpr
= MakeFullExpr(Val
.get()).get();
16540 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
16542 getOpenMPCaptureRegionForClause(DKind
, OMPC_final
, LangOpts
.OpenMP
);
16543 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
16544 ValExpr
= MakeFullExpr(ValExpr
).get();
16545 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
16546 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
16547 HelperValStmt
= buildPreInits(Context
, Captures
);
16551 return new (Context
) OMPFinalClause(ValExpr
, HelperValStmt
, CaptureRegion
,
16552 StartLoc
, LParenLoc
, EndLoc
);
16555 ExprResult
Sema::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc
,
16558 return ExprError();
16560 class IntConvertDiagnoser
: public ICEConvertDiagnoser
{
16562 IntConvertDiagnoser()
16563 : ICEConvertDiagnoser(/*AllowScopedEnumerations*/ false, false, true) {}
16564 SemaDiagnosticBuilder
diagnoseNotInt(Sema
&S
, SourceLocation Loc
,
16565 QualType T
) override
{
16566 return S
.Diag(Loc
, diag::err_omp_not_integral
) << T
;
16568 SemaDiagnosticBuilder
diagnoseIncomplete(Sema
&S
, SourceLocation Loc
,
16569 QualType T
) override
{
16570 return S
.Diag(Loc
, diag::err_omp_incomplete_type
) << T
;
16572 SemaDiagnosticBuilder
diagnoseExplicitConv(Sema
&S
, SourceLocation Loc
,
16574 QualType ConvTy
) override
{
16575 return S
.Diag(Loc
, diag::err_omp_explicit_conversion
) << T
<< ConvTy
;
16577 SemaDiagnosticBuilder
noteExplicitConv(Sema
&S
, CXXConversionDecl
*Conv
,
16578 QualType ConvTy
) override
{
16579 return S
.Diag(Conv
->getLocation(), diag::note_omp_conversion_here
)
16580 << ConvTy
->isEnumeralType() << ConvTy
;
16582 SemaDiagnosticBuilder
diagnoseAmbiguous(Sema
&S
, SourceLocation Loc
,
16583 QualType T
) override
{
16584 return S
.Diag(Loc
, diag::err_omp_ambiguous_conversion
) << T
;
16586 SemaDiagnosticBuilder
noteAmbiguous(Sema
&S
, CXXConversionDecl
*Conv
,
16587 QualType ConvTy
) override
{
16588 return S
.Diag(Conv
->getLocation(), diag::note_omp_conversion_here
)
16589 << ConvTy
->isEnumeralType() << ConvTy
;
16591 SemaDiagnosticBuilder
diagnoseConversion(Sema
&, SourceLocation
, QualType
,
16592 QualType
) override
{
16593 llvm_unreachable("conversion functions are permitted");
16595 } ConvertDiagnoser
;
16596 return PerformContextualImplicitConversion(Loc
, Op
, ConvertDiagnoser
);
16600 isNonNegativeIntegerValue(Expr
*&ValExpr
, Sema
&SemaRef
, OpenMPClauseKind CKind
,
16601 bool StrictlyPositive
, bool BuildCapture
= false,
16602 OpenMPDirectiveKind DKind
= OMPD_unknown
,
16603 OpenMPDirectiveKind
*CaptureRegion
= nullptr,
16604 Stmt
**HelperValStmt
= nullptr) {
16605 if (!ValExpr
->isTypeDependent() && !ValExpr
->isValueDependent() &&
16606 !ValExpr
->isInstantiationDependent()) {
16607 SourceLocation Loc
= ValExpr
->getExprLoc();
16609 SemaRef
.PerformOpenMPImplicitIntegerConversion(Loc
, ValExpr
);
16610 if (Value
.isInvalid())
16613 ValExpr
= Value
.get();
16614 // The expression must evaluate to a non-negative integer value.
16615 if (std::optional
<llvm::APSInt
> Result
=
16616 ValExpr
->getIntegerConstantExpr(SemaRef
.Context
)) {
16617 if (Result
->isSigned() &&
16618 !((!StrictlyPositive
&& Result
->isNonNegative()) ||
16619 (StrictlyPositive
&& Result
->isStrictlyPositive()))) {
16620 SemaRef
.Diag(Loc
, diag::err_omp_negative_expression_in_clause
)
16621 << getOpenMPClauseName(CKind
) << (StrictlyPositive
? 1 : 0)
16622 << ValExpr
->getSourceRange();
16629 getOpenMPCaptureRegionForClause(DKind
, CKind
, SemaRef
.LangOpts
.OpenMP
);
16630 if (*CaptureRegion
!= OMPD_unknown
&&
16631 !SemaRef
.CurContext
->isDependentContext()) {
16632 ValExpr
= SemaRef
.MakeFullExpr(ValExpr
).get();
16633 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
16634 ValExpr
= tryBuildCapture(SemaRef
, ValExpr
, Captures
).get();
16635 *HelperValStmt
= buildPreInits(SemaRef
.Context
, Captures
);
16641 OMPClause
*Sema::ActOnOpenMPNumThreadsClause(Expr
*NumThreads
,
16642 SourceLocation StartLoc
,
16643 SourceLocation LParenLoc
,
16644 SourceLocation EndLoc
) {
16645 Expr
*ValExpr
= NumThreads
;
16646 Stmt
*HelperValStmt
= nullptr;
16648 // OpenMP [2.5, Restrictions]
16649 // The num_threads expression must evaluate to a positive integer value.
16650 if (!isNonNegativeIntegerValue(ValExpr
, *this, OMPC_num_threads
,
16651 /*StrictlyPositive=*/true))
16654 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
16655 OpenMPDirectiveKind CaptureRegion
=
16656 getOpenMPCaptureRegionForClause(DKind
, OMPC_num_threads
, LangOpts
.OpenMP
);
16657 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
16658 ValExpr
= MakeFullExpr(ValExpr
).get();
16659 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
16660 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
16661 HelperValStmt
= buildPreInits(Context
, Captures
);
16664 return new (Context
) OMPNumThreadsClause(
16665 ValExpr
, HelperValStmt
, CaptureRegion
, StartLoc
, LParenLoc
, EndLoc
);
16668 ExprResult
Sema::VerifyPositiveIntegerConstantInClause(Expr
*E
,
16669 OpenMPClauseKind CKind
,
16670 bool StrictlyPositive
,
16671 bool SuppressExprDiags
) {
16673 return ExprError();
16674 if (E
->isValueDependent() || E
->isTypeDependent() ||
16675 E
->isInstantiationDependent() || E
->containsUnexpandedParameterPack())
16678 llvm::APSInt Result
;
16680 if (SuppressExprDiags
) {
16681 // Use a custom diagnoser that suppresses 'note' diagnostics about the
16683 struct SuppressedDiagnoser
: public Sema::VerifyICEDiagnoser
{
16684 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
16685 Sema::SemaDiagnosticBuilder
diagnoseNotICE(Sema
&S
,
16686 SourceLocation Loc
) override
{
16687 llvm_unreachable("Diagnostic suppressed");
16690 ICE
= VerifyIntegerConstantExpression(E
, &Result
, Diagnoser
, AllowFold
);
16692 ICE
= VerifyIntegerConstantExpression(E
, &Result
, /*FIXME*/ AllowFold
);
16694 if (ICE
.isInvalid())
16695 return ExprError();
16697 if ((StrictlyPositive
&& !Result
.isStrictlyPositive()) ||
16698 (!StrictlyPositive
&& !Result
.isNonNegative())) {
16699 Diag(E
->getExprLoc(), diag::err_omp_negative_expression_in_clause
)
16700 << getOpenMPClauseName(CKind
) << (StrictlyPositive
? 1 : 0)
16701 << E
->getSourceRange();
16702 return ExprError();
16704 if ((CKind
== OMPC_aligned
|| CKind
== OMPC_align
) && !Result
.isPowerOf2()) {
16705 Diag(E
->getExprLoc(), diag::warn_omp_alignment_not_power_of_two
)
16706 << E
->getSourceRange();
16707 return ExprError();
16709 if (CKind
== OMPC_collapse
&& DSAStack
->getAssociatedLoops() == 1)
16710 DSAStack
->setAssociatedLoops(Result
.getExtValue());
16711 else if (CKind
== OMPC_ordered
)
16712 DSAStack
->setAssociatedLoops(Result
.getExtValue());
16716 OMPClause
*Sema::ActOnOpenMPSafelenClause(Expr
*Len
, SourceLocation StartLoc
,
16717 SourceLocation LParenLoc
,
16718 SourceLocation EndLoc
) {
16719 // OpenMP [2.8.1, simd construct, Description]
16720 // The parameter of the safelen clause must be a constant
16721 // positive integer expression.
16722 ExprResult Safelen
= VerifyPositiveIntegerConstantInClause(Len
, OMPC_safelen
);
16723 if (Safelen
.isInvalid())
16725 return new (Context
)
16726 OMPSafelenClause(Safelen
.get(), StartLoc
, LParenLoc
, EndLoc
);
16729 OMPClause
*Sema::ActOnOpenMPSimdlenClause(Expr
*Len
, SourceLocation StartLoc
,
16730 SourceLocation LParenLoc
,
16731 SourceLocation EndLoc
) {
16732 // OpenMP [2.8.1, simd construct, Description]
16733 // The parameter of the simdlen clause must be a constant
16734 // positive integer expression.
16735 ExprResult Simdlen
= VerifyPositiveIntegerConstantInClause(Len
, OMPC_simdlen
);
16736 if (Simdlen
.isInvalid())
16738 return new (Context
)
16739 OMPSimdlenClause(Simdlen
.get(), StartLoc
, LParenLoc
, EndLoc
);
16742 /// Tries to find omp_allocator_handle_t type.
16743 static bool findOMPAllocatorHandleT(Sema
&S
, SourceLocation Loc
,
16744 DSAStackTy
*Stack
) {
16745 if (!Stack
->getOMPAllocatorHandleT().isNull())
16748 // Set the allocator handle type.
16749 IdentifierInfo
*II
= &S
.PP
.getIdentifierTable().get("omp_allocator_handle_t");
16750 ParsedType PT
= S
.getTypeName(*II
, Loc
, S
.getCurScope());
16751 if (!PT
.getAsOpaquePtr() || PT
.get().isNull()) {
16752 S
.Diag(Loc
, diag::err_omp_implied_type_not_found
)
16753 << "omp_allocator_handle_t";
16756 QualType AllocatorHandleEnumTy
= PT
.get();
16757 AllocatorHandleEnumTy
.addConst();
16758 Stack
->setOMPAllocatorHandleT(AllocatorHandleEnumTy
);
16760 // Fill the predefined allocator map.
16761 bool ErrorFound
= false;
16762 for (int I
= 0; I
< OMPAllocateDeclAttr::OMPUserDefinedMemAlloc
; ++I
) {
16763 auto AllocatorKind
= static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I
);
16764 StringRef Allocator
=
16765 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind
);
16766 DeclarationName AllocatorName
= &S
.getASTContext().Idents
.get(Allocator
);
16767 auto *VD
= dyn_cast_or_null
<ValueDecl
>(
16768 S
.LookupSingleName(S
.TUScope
, AllocatorName
, Loc
, Sema::LookupAnyName
));
16773 QualType AllocatorType
=
16774 VD
->getType().getNonLValueExprType(S
.getASTContext());
16775 ExprResult Res
= S
.BuildDeclRefExpr(VD
, AllocatorType
, VK_LValue
, Loc
);
16776 if (!Res
.isUsable()) {
16780 Res
= S
.PerformImplicitConversion(Res
.get(), AllocatorHandleEnumTy
,
16781 Sema::AA_Initializing
,
16782 /* AllowExplicit */ true);
16783 if (!Res
.isUsable()) {
16787 Stack
->setAllocator(AllocatorKind
, Res
.get());
16790 S
.Diag(Loc
, diag::err_omp_implied_type_not_found
)
16791 << "omp_allocator_handle_t";
16798 OMPClause
*Sema::ActOnOpenMPAllocatorClause(Expr
*A
, SourceLocation StartLoc
,
16799 SourceLocation LParenLoc
,
16800 SourceLocation EndLoc
) {
16801 // OpenMP [2.11.3, allocate Directive, Description]
16802 // allocator is an expression of omp_allocator_handle_t type.
16803 if (!findOMPAllocatorHandleT(*this, A
->getExprLoc(), DSAStack
))
16806 ExprResult Allocator
= DefaultLvalueConversion(A
);
16807 if (Allocator
.isInvalid())
16809 Allocator
= PerformImplicitConversion(Allocator
.get(),
16810 DSAStack
->getOMPAllocatorHandleT(),
16811 Sema::AA_Initializing
,
16812 /*AllowExplicit=*/true);
16813 if (Allocator
.isInvalid())
16815 return new (Context
)
16816 OMPAllocatorClause(Allocator
.get(), StartLoc
, LParenLoc
, EndLoc
);
16819 OMPClause
*Sema::ActOnOpenMPCollapseClause(Expr
*NumForLoops
,
16820 SourceLocation StartLoc
,
16821 SourceLocation LParenLoc
,
16822 SourceLocation EndLoc
) {
16823 // OpenMP [2.7.1, loop construct, Description]
16824 // OpenMP [2.8.1, simd construct, Description]
16825 // OpenMP [2.9.6, distribute construct, Description]
16826 // The parameter of the collapse clause must be a constant
16827 // positive integer expression.
16828 ExprResult NumForLoopsResult
=
16829 VerifyPositiveIntegerConstantInClause(NumForLoops
, OMPC_collapse
);
16830 if (NumForLoopsResult
.isInvalid())
16832 return new (Context
)
16833 OMPCollapseClause(NumForLoopsResult
.get(), StartLoc
, LParenLoc
, EndLoc
);
16836 OMPClause
*Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc
,
16837 SourceLocation EndLoc
,
16838 SourceLocation LParenLoc
,
16839 Expr
*NumForLoops
) {
16840 // OpenMP [2.7.1, loop construct, Description]
16841 // OpenMP [2.8.1, simd construct, Description]
16842 // OpenMP [2.9.6, distribute construct, Description]
16843 // The parameter of the ordered clause must be a constant
16844 // positive integer expression if any.
16845 if (NumForLoops
&& LParenLoc
.isValid()) {
16846 ExprResult NumForLoopsResult
=
16847 VerifyPositiveIntegerConstantInClause(NumForLoops
, OMPC_ordered
);
16848 if (NumForLoopsResult
.isInvalid())
16850 NumForLoops
= NumForLoopsResult
.get();
16852 NumForLoops
= nullptr;
16854 auto *Clause
= OMPOrderedClause::Create(
16855 Context
, NumForLoops
, NumForLoops
? DSAStack
->getAssociatedLoops() : 0,
16856 StartLoc
, LParenLoc
, EndLoc
);
16857 DSAStack
->setOrderedRegion(/*IsOrdered=*/true, NumForLoops
, Clause
);
16861 OMPClause
*Sema::ActOnOpenMPSimpleClause(
16862 OpenMPClauseKind Kind
, unsigned Argument
, SourceLocation ArgumentLoc
,
16863 SourceLocation StartLoc
, SourceLocation LParenLoc
, SourceLocation EndLoc
) {
16864 OMPClause
*Res
= nullptr;
16867 Res
= ActOnOpenMPDefaultClause(static_cast<DefaultKind
>(Argument
),
16868 ArgumentLoc
, StartLoc
, LParenLoc
, EndLoc
);
16870 case OMPC_proc_bind
:
16871 Res
= ActOnOpenMPProcBindClause(static_cast<ProcBindKind
>(Argument
),
16872 ArgumentLoc
, StartLoc
, LParenLoc
, EndLoc
);
16874 case OMPC_atomic_default_mem_order
:
16875 Res
= ActOnOpenMPAtomicDefaultMemOrderClause(
16876 static_cast<OpenMPAtomicDefaultMemOrderClauseKind
>(Argument
),
16877 ArgumentLoc
, StartLoc
, LParenLoc
, EndLoc
);
16880 Res
= ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind
>(Argument
),
16881 ArgumentLoc
, StartLoc
, LParenLoc
, EndLoc
);
16884 Res
= ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind
>(Argument
),
16885 ArgumentLoc
, StartLoc
, LParenLoc
, EndLoc
);
16888 Res
= ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind
>(Argument
),
16889 ArgumentLoc
, StartLoc
, LParenLoc
, EndLoc
);
16891 case OMPC_severity
:
16892 Res
= ActOnOpenMPSeverityClause(
16893 static_cast<OpenMPSeverityClauseKind
>(Argument
), ArgumentLoc
, StartLoc
,
16894 LParenLoc
, EndLoc
);
16898 case OMPC_num_threads
:
16902 case OMPC_allocator
:
16903 case OMPC_collapse
:
16904 case OMPC_schedule
:
16906 case OMPC_firstprivate
:
16907 case OMPC_lastprivate
:
16909 case OMPC_reduction
:
16910 case OMPC_task_reduction
:
16911 case OMPC_in_reduction
:
16915 case OMPC_copyprivate
:
16919 case OMPC_mergeable
:
16920 case OMPC_threadprivate
:
16921 case OMPC_allocate
:
16938 case OMPC_num_teams
:
16939 case OMPC_thread_limit
:
16940 case OMPC_priority
:
16941 case OMPC_grainsize
:
16943 case OMPC_num_tasks
:
16945 case OMPC_dist_schedule
:
16946 case OMPC_defaultmap
:
16951 case OMPC_use_device_ptr
:
16952 case OMPC_use_device_addr
:
16953 case OMPC_is_device_ptr
:
16954 case OMPC_has_device_addr
:
16955 case OMPC_unified_address
:
16956 case OMPC_unified_shared_memory
:
16957 case OMPC_reverse_offload
:
16958 case OMPC_dynamic_allocators
:
16959 case OMPC_device_type
:
16961 case OMPC_nontemporal
:
16963 case OMPC_novariants
:
16964 case OMPC_nocontext
:
16966 case OMPC_inclusive
:
16967 case OMPC_exclusive
:
16968 case OMPC_uses_allocators
:
16969 case OMPC_affinity
:
16973 llvm_unreachable("Clause is not allowed.");
16979 getListOfPossibleValues(OpenMPClauseKind K
, unsigned First
, unsigned Last
,
16980 ArrayRef
<unsigned> Exclude
= std::nullopt
) {
16981 SmallString
<256> Buffer
;
16982 llvm::raw_svector_ostream
Out(Buffer
);
16983 unsigned Skipped
= Exclude
.size();
16984 for (unsigned I
= First
; I
< Last
; ++I
) {
16985 if (llvm::is_contained(Exclude
, I
)) {
16989 Out
<< "'" << getOpenMPSimpleClauseTypeName(K
, I
) << "'";
16990 if (I
+ Skipped
+ 2 == Last
)
16992 else if (I
+ Skipped
+ 1 != Last
)
16995 return std::string(Out
.str());
16998 OMPClause
*Sema::ActOnOpenMPDefaultClause(DefaultKind Kind
,
16999 SourceLocation KindKwLoc
,
17000 SourceLocation StartLoc
,
17001 SourceLocation LParenLoc
,
17002 SourceLocation EndLoc
) {
17003 if (Kind
== OMP_DEFAULT_unknown
) {
17004 Diag(KindKwLoc
, diag::err_omp_unexpected_clause_value
)
17005 << getListOfPossibleValues(OMPC_default
, /*First=*/0,
17006 /*Last=*/unsigned(OMP_DEFAULT_unknown
))
17007 << getOpenMPClauseName(OMPC_default
);
17012 case OMP_DEFAULT_none
:
17013 DSAStack
->setDefaultDSANone(KindKwLoc
);
17015 case OMP_DEFAULT_shared
:
17016 DSAStack
->setDefaultDSAShared(KindKwLoc
);
17018 case OMP_DEFAULT_firstprivate
:
17019 DSAStack
->setDefaultDSAFirstPrivate(KindKwLoc
);
17021 case OMP_DEFAULT_private
:
17022 DSAStack
->setDefaultDSAPrivate(KindKwLoc
);
17025 llvm_unreachable("DSA unexpected in OpenMP default clause");
17028 return new (Context
)
17029 OMPDefaultClause(Kind
, KindKwLoc
, StartLoc
, LParenLoc
, EndLoc
);
17032 OMPClause
*Sema::ActOnOpenMPProcBindClause(ProcBindKind Kind
,
17033 SourceLocation KindKwLoc
,
17034 SourceLocation StartLoc
,
17035 SourceLocation LParenLoc
,
17036 SourceLocation EndLoc
) {
17037 if (Kind
== OMP_PROC_BIND_unknown
) {
17038 Diag(KindKwLoc
, diag::err_omp_unexpected_clause_value
)
17039 << getListOfPossibleValues(OMPC_proc_bind
,
17040 /*First=*/unsigned(OMP_PROC_BIND_master
),
17042 unsigned(LangOpts
.OpenMP
> 50
17043 ? OMP_PROC_BIND_primary
17044 : OMP_PROC_BIND_spread
) +
17046 << getOpenMPClauseName(OMPC_proc_bind
);
17049 if (Kind
== OMP_PROC_BIND_primary
&& LangOpts
.OpenMP
< 51)
17050 Diag(KindKwLoc
, diag::err_omp_unexpected_clause_value
)
17051 << getListOfPossibleValues(OMPC_proc_bind
,
17052 /*First=*/unsigned(OMP_PROC_BIND_master
),
17054 unsigned(OMP_PROC_BIND_spread
) + 1)
17055 << getOpenMPClauseName(OMPC_proc_bind
);
17056 return new (Context
)
17057 OMPProcBindClause(Kind
, KindKwLoc
, StartLoc
, LParenLoc
, EndLoc
);
17060 OMPClause
*Sema::ActOnOpenMPAtomicDefaultMemOrderClause(
17061 OpenMPAtomicDefaultMemOrderClauseKind Kind
, SourceLocation KindKwLoc
,
17062 SourceLocation StartLoc
, SourceLocation LParenLoc
, SourceLocation EndLoc
) {
17063 if (Kind
== OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
) {
17064 Diag(KindKwLoc
, diag::err_omp_unexpected_clause_value
)
17065 << getListOfPossibleValues(
17066 OMPC_atomic_default_mem_order
, /*First=*/0,
17067 /*Last=*/OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
)
17068 << getOpenMPClauseName(OMPC_atomic_default_mem_order
);
17071 return new (Context
) OMPAtomicDefaultMemOrderClause(Kind
, KindKwLoc
, StartLoc
,
17072 LParenLoc
, EndLoc
);
17075 OMPClause
*Sema::ActOnOpenMPAtClause(OpenMPAtClauseKind Kind
,
17076 SourceLocation KindKwLoc
,
17077 SourceLocation StartLoc
,
17078 SourceLocation LParenLoc
,
17079 SourceLocation EndLoc
) {
17080 if (Kind
== OMPC_AT_unknown
) {
17081 Diag(KindKwLoc
, diag::err_omp_unexpected_clause_value
)
17082 << getListOfPossibleValues(OMPC_at
, /*First=*/0,
17083 /*Last=*/OMPC_AT_unknown
)
17084 << getOpenMPClauseName(OMPC_at
);
17087 return new (Context
)
17088 OMPAtClause(Kind
, KindKwLoc
, StartLoc
, LParenLoc
, EndLoc
);
17091 OMPClause
*Sema::ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind
,
17092 SourceLocation KindKwLoc
,
17093 SourceLocation StartLoc
,
17094 SourceLocation LParenLoc
,
17095 SourceLocation EndLoc
) {
17096 if (Kind
== OMPC_SEVERITY_unknown
) {
17097 Diag(KindKwLoc
, diag::err_omp_unexpected_clause_value
)
17098 << getListOfPossibleValues(OMPC_severity
, /*First=*/0,
17099 /*Last=*/OMPC_SEVERITY_unknown
)
17100 << getOpenMPClauseName(OMPC_severity
);
17103 return new (Context
)
17104 OMPSeverityClause(Kind
, KindKwLoc
, StartLoc
, LParenLoc
, EndLoc
);
17107 OMPClause
*Sema::ActOnOpenMPMessageClause(Expr
*ME
, SourceLocation StartLoc
,
17108 SourceLocation LParenLoc
,
17109 SourceLocation EndLoc
) {
17110 assert(ME
&& "NULL expr in Message clause");
17111 if (!isa
<StringLiteral
>(ME
)) {
17112 Diag(ME
->getBeginLoc(), diag::warn_clause_expected_string
)
17113 << getOpenMPClauseName(OMPC_message
);
17116 return new (Context
) OMPMessageClause(ME
, StartLoc
, LParenLoc
, EndLoc
);
17119 OMPClause
*Sema::ActOnOpenMPOrderClause(
17120 OpenMPOrderClauseModifier Modifier
, OpenMPOrderClauseKind Kind
,
17121 SourceLocation StartLoc
, SourceLocation LParenLoc
, SourceLocation MLoc
,
17122 SourceLocation KindLoc
, SourceLocation EndLoc
) {
17123 if (Kind
!= OMPC_ORDER_concurrent
||
17124 (LangOpts
.OpenMP
< 51 && MLoc
.isValid())) {
17125 // Kind should be concurrent,
17126 // Modifiers introduced in OpenMP 5.1
17127 static_assert(OMPC_ORDER_unknown
> 0,
17128 "OMPC_ORDER_unknown not greater than 0");
17130 Diag(KindLoc
, diag::err_omp_unexpected_clause_value
)
17131 << getListOfPossibleValues(OMPC_order
,
17133 /*Last=*/OMPC_ORDER_unknown
)
17134 << getOpenMPClauseName(OMPC_order
);
17137 if (LangOpts
.OpenMP
>= 51) {
17138 if (Modifier
== OMPC_ORDER_MODIFIER_unknown
&& MLoc
.isValid()) {
17139 Diag(MLoc
, diag::err_omp_unexpected_clause_value
)
17140 << getListOfPossibleValues(OMPC_order
,
17141 /*First=*/OMPC_ORDER_MODIFIER_unknown
+ 1,
17142 /*Last=*/OMPC_ORDER_MODIFIER_last
)
17143 << getOpenMPClauseName(OMPC_order
);
17145 DSAStack
->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
17146 if (DSAStack
->getCurScope()) {
17147 // mark the current scope with 'order' flag
17148 unsigned existingFlags
= DSAStack
->getCurScope()->getFlags();
17149 DSAStack
->getCurScope()->setFlags(existingFlags
|
17150 Scope::OpenMPOrderClauseScope
);
17154 return new (Context
) OMPOrderClause(Kind
, KindLoc
, StartLoc
, LParenLoc
,
17155 EndLoc
, Modifier
, MLoc
);
17158 OMPClause
*Sema::ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind
,
17159 SourceLocation KindKwLoc
,
17160 SourceLocation StartLoc
,
17161 SourceLocation LParenLoc
,
17162 SourceLocation EndLoc
) {
17163 if (Kind
== OMPC_DEPEND_unknown
|| Kind
== OMPC_DEPEND_source
||
17164 Kind
== OMPC_DEPEND_sink
|| Kind
== OMPC_DEPEND_depobj
) {
17165 SmallVector
<unsigned> Except
= {
17166 OMPC_DEPEND_source
, OMPC_DEPEND_sink
, OMPC_DEPEND_depobj
,
17167 OMPC_DEPEND_outallmemory
, OMPC_DEPEND_inoutallmemory
};
17168 if (LangOpts
.OpenMP
< 51)
17169 Except
.push_back(OMPC_DEPEND_inoutset
);
17170 Diag(KindKwLoc
, diag::err_omp_unexpected_clause_value
)
17171 << getListOfPossibleValues(OMPC_depend
, /*First=*/0,
17172 /*Last=*/OMPC_DEPEND_unknown
, Except
)
17173 << getOpenMPClauseName(OMPC_update
);
17176 return OMPUpdateClause::Create(Context
, StartLoc
, LParenLoc
, KindKwLoc
, Kind
,
17180 OMPClause
*Sema::ActOnOpenMPSizesClause(ArrayRef
<Expr
*> SizeExprs
,
17181 SourceLocation StartLoc
,
17182 SourceLocation LParenLoc
,
17183 SourceLocation EndLoc
) {
17184 for (Expr
*SizeExpr
: SizeExprs
) {
17185 ExprResult NumForLoopsResult
= VerifyPositiveIntegerConstantInClause(
17186 SizeExpr
, OMPC_sizes
, /*StrictlyPositive=*/true);
17187 if (!NumForLoopsResult
.isUsable())
17191 DSAStack
->setAssociatedLoops(SizeExprs
.size());
17192 return OMPSizesClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
,
17196 OMPClause
*Sema::ActOnOpenMPFullClause(SourceLocation StartLoc
,
17197 SourceLocation EndLoc
) {
17198 return OMPFullClause::Create(Context
, StartLoc
, EndLoc
);
17201 OMPClause
*Sema::ActOnOpenMPPartialClause(Expr
*FactorExpr
,
17202 SourceLocation StartLoc
,
17203 SourceLocation LParenLoc
,
17204 SourceLocation EndLoc
) {
17206 // If an argument is specified, it must be a constant (or an unevaluated
17207 // template expression).
17208 ExprResult FactorResult
= VerifyPositiveIntegerConstantInClause(
17209 FactorExpr
, OMPC_partial
, /*StrictlyPositive=*/true);
17210 if (FactorResult
.isInvalid())
17212 FactorExpr
= FactorResult
.get();
17215 return OMPPartialClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
,
17219 OMPClause
*Sema::ActOnOpenMPAlignClause(Expr
*A
, SourceLocation StartLoc
,
17220 SourceLocation LParenLoc
,
17221 SourceLocation EndLoc
) {
17222 ExprResult AlignVal
;
17223 AlignVal
= VerifyPositiveIntegerConstantInClause(A
, OMPC_align
);
17224 if (AlignVal
.isInvalid())
17226 return OMPAlignClause::Create(Context
, AlignVal
.get(), StartLoc
, LParenLoc
,
17230 OMPClause
*Sema::ActOnOpenMPSingleExprWithArgClause(
17231 OpenMPClauseKind Kind
, ArrayRef
<unsigned> Argument
, Expr
*Expr
,
17232 SourceLocation StartLoc
, SourceLocation LParenLoc
,
17233 ArrayRef
<SourceLocation
> ArgumentLoc
, SourceLocation DelimLoc
,
17234 SourceLocation EndLoc
) {
17235 OMPClause
*Res
= nullptr;
17237 case OMPC_schedule
:
17238 enum { Modifier1
, Modifier2
, ScheduleKind
, NumberOfElements
};
17239 assert(Argument
.size() == NumberOfElements
&&
17240 ArgumentLoc
.size() == NumberOfElements
);
17241 Res
= ActOnOpenMPScheduleClause(
17242 static_cast<OpenMPScheduleClauseModifier
>(Argument
[Modifier1
]),
17243 static_cast<OpenMPScheduleClauseModifier
>(Argument
[Modifier2
]),
17244 static_cast<OpenMPScheduleClauseKind
>(Argument
[ScheduleKind
]), Expr
,
17245 StartLoc
, LParenLoc
, ArgumentLoc
[Modifier1
], ArgumentLoc
[Modifier2
],
17246 ArgumentLoc
[ScheduleKind
], DelimLoc
, EndLoc
);
17249 assert(Argument
.size() == 1 && ArgumentLoc
.size() == 1);
17250 Res
= ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind
>(Argument
.back()),
17251 Expr
, StartLoc
, LParenLoc
, ArgumentLoc
.back(),
17254 case OMPC_dist_schedule
:
17255 Res
= ActOnOpenMPDistScheduleClause(
17256 static_cast<OpenMPDistScheduleClauseKind
>(Argument
.back()), Expr
,
17257 StartLoc
, LParenLoc
, ArgumentLoc
.back(), DelimLoc
, EndLoc
);
17259 case OMPC_defaultmap
:
17260 enum { Modifier
, DefaultmapKind
};
17261 Res
= ActOnOpenMPDefaultmapClause(
17262 static_cast<OpenMPDefaultmapClauseModifier
>(Argument
[Modifier
]),
17263 static_cast<OpenMPDefaultmapClauseKind
>(Argument
[DefaultmapKind
]),
17264 StartLoc
, LParenLoc
, ArgumentLoc
[Modifier
], ArgumentLoc
[DefaultmapKind
],
17268 enum { OrderModifier
, OrderKind
};
17269 Res
= ActOnOpenMPOrderClause(
17270 static_cast<OpenMPOrderClauseModifier
>(Argument
[OrderModifier
]),
17271 static_cast<OpenMPOrderClauseKind
>(Argument
[OrderKind
]), StartLoc
,
17272 LParenLoc
, ArgumentLoc
[OrderModifier
], ArgumentLoc
[OrderKind
], EndLoc
);
17275 assert(Argument
.size() == 1 && ArgumentLoc
.size() == 1);
17276 Res
= ActOnOpenMPDeviceClause(
17277 static_cast<OpenMPDeviceClauseModifier
>(Argument
.back()), Expr
,
17278 StartLoc
, LParenLoc
, ArgumentLoc
.back(), EndLoc
);
17280 case OMPC_grainsize
:
17281 assert(Argument
.size() == 1 && ArgumentLoc
.size() == 1 &&
17282 "Modifier for grainsize clause and its location are expected.");
17283 Res
= ActOnOpenMPGrainsizeClause(
17284 static_cast<OpenMPGrainsizeClauseModifier
>(Argument
.back()), Expr
,
17285 StartLoc
, LParenLoc
, ArgumentLoc
.back(), EndLoc
);
17287 case OMPC_num_tasks
:
17288 assert(Argument
.size() == 1 && ArgumentLoc
.size() == 1 &&
17289 "Modifier for num_tasks clause and its location are expected.");
17290 Res
= ActOnOpenMPNumTasksClause(
17291 static_cast<OpenMPNumTasksClauseModifier
>(Argument
.back()), Expr
,
17292 StartLoc
, LParenLoc
, ArgumentLoc
.back(), EndLoc
);
17295 case OMPC_num_threads
:
17299 case OMPC_allocator
:
17300 case OMPC_collapse
:
17302 case OMPC_proc_bind
:
17304 case OMPC_firstprivate
:
17305 case OMPC_lastprivate
:
17307 case OMPC_reduction
:
17308 case OMPC_task_reduction
:
17309 case OMPC_in_reduction
:
17313 case OMPC_copyprivate
:
17317 case OMPC_mergeable
:
17318 case OMPC_threadprivate
:
17319 case OMPC_allocate
:
17336 case OMPC_num_teams
:
17337 case OMPC_thread_limit
:
17338 case OMPC_priority
:
17345 case OMPC_use_device_ptr
:
17346 case OMPC_use_device_addr
:
17347 case OMPC_is_device_ptr
:
17348 case OMPC_has_device_addr
:
17349 case OMPC_unified_address
:
17350 case OMPC_unified_shared_memory
:
17351 case OMPC_reverse_offload
:
17352 case OMPC_dynamic_allocators
:
17353 case OMPC_atomic_default_mem_order
:
17354 case OMPC_device_type
:
17356 case OMPC_nontemporal
:
17358 case OMPC_severity
:
17361 case OMPC_novariants
:
17362 case OMPC_nocontext
:
17364 case OMPC_inclusive
:
17365 case OMPC_exclusive
:
17366 case OMPC_uses_allocators
:
17367 case OMPC_affinity
:
17371 llvm_unreachable("Clause is not allowed.");
17376 static bool checkScheduleModifiers(Sema
&S
, OpenMPScheduleClauseModifier M1
,
17377 OpenMPScheduleClauseModifier M2
,
17378 SourceLocation M1Loc
, SourceLocation M2Loc
) {
17379 if (M1
== OMPC_SCHEDULE_MODIFIER_unknown
&& M1Loc
.isValid()) {
17380 SmallVector
<unsigned, 2> Excluded
;
17381 if (M2
!= OMPC_SCHEDULE_MODIFIER_unknown
)
17382 Excluded
.push_back(M2
);
17383 if (M2
== OMPC_SCHEDULE_MODIFIER_nonmonotonic
)
17384 Excluded
.push_back(OMPC_SCHEDULE_MODIFIER_monotonic
);
17385 if (M2
== OMPC_SCHEDULE_MODIFIER_monotonic
)
17386 Excluded
.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic
);
17387 S
.Diag(M1Loc
, diag::err_omp_unexpected_clause_value
)
17388 << getListOfPossibleValues(OMPC_schedule
,
17389 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown
+ 1,
17390 /*Last=*/OMPC_SCHEDULE_MODIFIER_last
,
17392 << getOpenMPClauseName(OMPC_schedule
);
17398 OMPClause
*Sema::ActOnOpenMPScheduleClause(
17399 OpenMPScheduleClauseModifier M1
, OpenMPScheduleClauseModifier M2
,
17400 OpenMPScheduleClauseKind Kind
, Expr
*ChunkSize
, SourceLocation StartLoc
,
17401 SourceLocation LParenLoc
, SourceLocation M1Loc
, SourceLocation M2Loc
,
17402 SourceLocation KindLoc
, SourceLocation CommaLoc
, SourceLocation EndLoc
) {
17403 if (checkScheduleModifiers(*this, M1
, M2
, M1Loc
, M2Loc
) ||
17404 checkScheduleModifiers(*this, M2
, M1
, M2Loc
, M1Loc
))
17406 // OpenMP, 2.7.1, Loop Construct, Restrictions
17407 // Either the monotonic modifier or the nonmonotonic modifier can be specified
17409 if ((M1
== M2
&& M1
!= OMPC_SCHEDULE_MODIFIER_unknown
) ||
17410 (M1
== OMPC_SCHEDULE_MODIFIER_monotonic
&&
17411 M2
== OMPC_SCHEDULE_MODIFIER_nonmonotonic
) ||
17412 (M1
== OMPC_SCHEDULE_MODIFIER_nonmonotonic
&&
17413 M2
== OMPC_SCHEDULE_MODIFIER_monotonic
)) {
17414 Diag(M2Loc
, diag::err_omp_unexpected_schedule_modifier
)
17415 << getOpenMPSimpleClauseTypeName(OMPC_schedule
, M2
)
17416 << getOpenMPSimpleClauseTypeName(OMPC_schedule
, M1
);
17419 if (Kind
== OMPC_SCHEDULE_unknown
) {
17420 std::string Values
;
17421 if (M1Loc
.isInvalid() && M2Loc
.isInvalid()) {
17422 unsigned Exclude
[] = {OMPC_SCHEDULE_unknown
};
17423 Values
= getListOfPossibleValues(OMPC_schedule
, /*First=*/0,
17424 /*Last=*/OMPC_SCHEDULE_MODIFIER_last
,
17427 Values
= getListOfPossibleValues(OMPC_schedule
, /*First=*/0,
17428 /*Last=*/OMPC_SCHEDULE_unknown
);
17430 Diag(KindLoc
, diag::err_omp_unexpected_clause_value
)
17431 << Values
<< getOpenMPClauseName(OMPC_schedule
);
17434 // OpenMP, 2.7.1, Loop Construct, Restrictions
17435 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
17436 // schedule(guided).
17437 // OpenMP 5.0 does not have this restriction.
17438 if (LangOpts
.OpenMP
< 50 &&
17439 (M1
== OMPC_SCHEDULE_MODIFIER_nonmonotonic
||
17440 M2
== OMPC_SCHEDULE_MODIFIER_nonmonotonic
) &&
17441 Kind
!= OMPC_SCHEDULE_dynamic
&& Kind
!= OMPC_SCHEDULE_guided
) {
17442 Diag(M1
== OMPC_SCHEDULE_MODIFIER_nonmonotonic
? M1Loc
: M2Loc
,
17443 diag::err_omp_schedule_nonmonotonic_static
);
17446 Expr
*ValExpr
= ChunkSize
;
17447 Stmt
*HelperValStmt
= nullptr;
17449 if (!ChunkSize
->isValueDependent() && !ChunkSize
->isTypeDependent() &&
17450 !ChunkSize
->isInstantiationDependent() &&
17451 !ChunkSize
->containsUnexpandedParameterPack()) {
17452 SourceLocation ChunkSizeLoc
= ChunkSize
->getBeginLoc();
17454 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc
, ChunkSize
);
17455 if (Val
.isInvalid())
17458 ValExpr
= Val
.get();
17460 // OpenMP [2.7.1, Restrictions]
17461 // chunk_size must be a loop invariant integer expression with a positive
17463 if (std::optional
<llvm::APSInt
> Result
=
17464 ValExpr
->getIntegerConstantExpr(Context
)) {
17465 if (Result
->isSigned() && !Result
->isStrictlyPositive()) {
17466 Diag(ChunkSizeLoc
, diag::err_omp_negative_expression_in_clause
)
17467 << "schedule" << 1 << ChunkSize
->getSourceRange();
17470 } else if (getOpenMPCaptureRegionForClause(
17471 DSAStack
->getCurrentDirective(), OMPC_schedule
,
17472 LangOpts
.OpenMP
) != OMPD_unknown
&&
17473 !CurContext
->isDependentContext()) {
17474 ValExpr
= MakeFullExpr(ValExpr
).get();
17475 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
17476 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
17477 HelperValStmt
= buildPreInits(Context
, Captures
);
17482 return new (Context
)
17483 OMPScheduleClause(StartLoc
, LParenLoc
, KindLoc
, CommaLoc
, EndLoc
, Kind
,
17484 ValExpr
, HelperValStmt
, M1
, M1Loc
, M2
, M2Loc
);
17487 OMPClause
*Sema::ActOnOpenMPClause(OpenMPClauseKind Kind
,
17488 SourceLocation StartLoc
,
17489 SourceLocation EndLoc
) {
17490 OMPClause
*Res
= nullptr;
17493 Res
= ActOnOpenMPOrderedClause(StartLoc
, EndLoc
);
17496 Res
= ActOnOpenMPNowaitClause(StartLoc
, EndLoc
);
17499 Res
= ActOnOpenMPUntiedClause(StartLoc
, EndLoc
);
17501 case OMPC_mergeable
:
17502 Res
= ActOnOpenMPMergeableClause(StartLoc
, EndLoc
);
17505 Res
= ActOnOpenMPReadClause(StartLoc
, EndLoc
);
17508 Res
= ActOnOpenMPWriteClause(StartLoc
, EndLoc
);
17511 Res
= ActOnOpenMPUpdateClause(StartLoc
, EndLoc
);
17514 Res
= ActOnOpenMPCaptureClause(StartLoc
, EndLoc
);
17517 Res
= ActOnOpenMPCompareClause(StartLoc
, EndLoc
);
17520 Res
= ActOnOpenMPSeqCstClause(StartLoc
, EndLoc
);
17523 Res
= ActOnOpenMPAcqRelClause(StartLoc
, EndLoc
);
17526 Res
= ActOnOpenMPAcquireClause(StartLoc
, EndLoc
);
17529 Res
= ActOnOpenMPReleaseClause(StartLoc
, EndLoc
);
17532 Res
= ActOnOpenMPRelaxedClause(StartLoc
, EndLoc
);
17535 Res
= ActOnOpenMPThreadsClause(StartLoc
, EndLoc
);
17538 Res
= ActOnOpenMPSIMDClause(StartLoc
, EndLoc
);
17541 Res
= ActOnOpenMPNogroupClause(StartLoc
, EndLoc
);
17543 case OMPC_unified_address
:
17544 Res
= ActOnOpenMPUnifiedAddressClause(StartLoc
, EndLoc
);
17546 case OMPC_unified_shared_memory
:
17547 Res
= ActOnOpenMPUnifiedSharedMemoryClause(StartLoc
, EndLoc
);
17549 case OMPC_reverse_offload
:
17550 Res
= ActOnOpenMPReverseOffloadClause(StartLoc
, EndLoc
);
17552 case OMPC_dynamic_allocators
:
17553 Res
= ActOnOpenMPDynamicAllocatorsClause(StartLoc
, EndLoc
);
17556 Res
= ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc
,
17557 /*LParenLoc=*/SourceLocation(),
17558 /*VarLoc=*/SourceLocation(), EndLoc
);
17561 Res
= ActOnOpenMPFullClause(StartLoc
, EndLoc
);
17564 Res
= ActOnOpenMPPartialClause(nullptr, StartLoc
, /*LParenLoc=*/{}, EndLoc
);
17566 case OMPC_ompx_bare
:
17567 Res
= ActOnOpenMPXBareClause(StartLoc
, EndLoc
);
17571 case OMPC_num_threads
:
17575 case OMPC_allocator
:
17576 case OMPC_collapse
:
17577 case OMPC_schedule
:
17579 case OMPC_firstprivate
:
17580 case OMPC_lastprivate
:
17582 case OMPC_reduction
:
17583 case OMPC_task_reduction
:
17584 case OMPC_in_reduction
:
17588 case OMPC_copyprivate
:
17590 case OMPC_proc_bind
:
17591 case OMPC_threadprivate
:
17592 case OMPC_allocate
:
17598 case OMPC_num_teams
:
17599 case OMPC_thread_limit
:
17600 case OMPC_priority
:
17601 case OMPC_grainsize
:
17602 case OMPC_num_tasks
:
17604 case OMPC_dist_schedule
:
17605 case OMPC_defaultmap
:
17610 case OMPC_use_device_ptr
:
17611 case OMPC_use_device_addr
:
17612 case OMPC_is_device_ptr
:
17613 case OMPC_has_device_addr
:
17614 case OMPC_atomic_default_mem_order
:
17615 case OMPC_device_type
:
17617 case OMPC_nontemporal
:
17620 case OMPC_severity
:
17622 case OMPC_novariants
:
17623 case OMPC_nocontext
:
17625 case OMPC_inclusive
:
17626 case OMPC_exclusive
:
17627 case OMPC_uses_allocators
:
17628 case OMPC_affinity
:
17630 case OMPC_ompx_dyn_cgroup_mem
:
17632 llvm_unreachable("Clause is not allowed.");
17637 OMPClause
*Sema::ActOnOpenMPNowaitClause(SourceLocation StartLoc
,
17638 SourceLocation EndLoc
) {
17639 DSAStack
->setNowaitRegion();
17640 return new (Context
) OMPNowaitClause(StartLoc
, EndLoc
);
17643 OMPClause
*Sema::ActOnOpenMPUntiedClause(SourceLocation StartLoc
,
17644 SourceLocation EndLoc
) {
17645 DSAStack
->setUntiedRegion();
17646 return new (Context
) OMPUntiedClause(StartLoc
, EndLoc
);
17649 OMPClause
*Sema::ActOnOpenMPMergeableClause(SourceLocation StartLoc
,
17650 SourceLocation EndLoc
) {
17651 return new (Context
) OMPMergeableClause(StartLoc
, EndLoc
);
17654 OMPClause
*Sema::ActOnOpenMPReadClause(SourceLocation StartLoc
,
17655 SourceLocation EndLoc
) {
17656 return new (Context
) OMPReadClause(StartLoc
, EndLoc
);
17659 OMPClause
*Sema::ActOnOpenMPWriteClause(SourceLocation StartLoc
,
17660 SourceLocation EndLoc
) {
17661 return new (Context
) OMPWriteClause(StartLoc
, EndLoc
);
17664 OMPClause
*Sema::ActOnOpenMPUpdateClause(SourceLocation StartLoc
,
17665 SourceLocation EndLoc
) {
17666 return OMPUpdateClause::Create(Context
, StartLoc
, EndLoc
);
17669 OMPClause
*Sema::ActOnOpenMPCaptureClause(SourceLocation StartLoc
,
17670 SourceLocation EndLoc
) {
17671 return new (Context
) OMPCaptureClause(StartLoc
, EndLoc
);
17674 OMPClause
*Sema::ActOnOpenMPCompareClause(SourceLocation StartLoc
,
17675 SourceLocation EndLoc
) {
17676 return new (Context
) OMPCompareClause(StartLoc
, EndLoc
);
17679 OMPClause
*Sema::ActOnOpenMPSeqCstClause(SourceLocation StartLoc
,
17680 SourceLocation EndLoc
) {
17681 return new (Context
) OMPSeqCstClause(StartLoc
, EndLoc
);
17684 OMPClause
*Sema::ActOnOpenMPAcqRelClause(SourceLocation StartLoc
,
17685 SourceLocation EndLoc
) {
17686 return new (Context
) OMPAcqRelClause(StartLoc
, EndLoc
);
17689 OMPClause
*Sema::ActOnOpenMPAcquireClause(SourceLocation StartLoc
,
17690 SourceLocation EndLoc
) {
17691 return new (Context
) OMPAcquireClause(StartLoc
, EndLoc
);
17694 OMPClause
*Sema::ActOnOpenMPReleaseClause(SourceLocation StartLoc
,
17695 SourceLocation EndLoc
) {
17696 return new (Context
) OMPReleaseClause(StartLoc
, EndLoc
);
17699 OMPClause
*Sema::ActOnOpenMPRelaxedClause(SourceLocation StartLoc
,
17700 SourceLocation EndLoc
) {
17701 return new (Context
) OMPRelaxedClause(StartLoc
, EndLoc
);
17704 OMPClause
*Sema::ActOnOpenMPThreadsClause(SourceLocation StartLoc
,
17705 SourceLocation EndLoc
) {
17706 return new (Context
) OMPThreadsClause(StartLoc
, EndLoc
);
17709 OMPClause
*Sema::ActOnOpenMPSIMDClause(SourceLocation StartLoc
,
17710 SourceLocation EndLoc
) {
17711 return new (Context
) OMPSIMDClause(StartLoc
, EndLoc
);
17714 OMPClause
*Sema::ActOnOpenMPNogroupClause(SourceLocation StartLoc
,
17715 SourceLocation EndLoc
) {
17716 return new (Context
) OMPNogroupClause(StartLoc
, EndLoc
);
17719 OMPClause
*Sema::ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc
,
17720 SourceLocation EndLoc
) {
17721 return new (Context
) OMPUnifiedAddressClause(StartLoc
, EndLoc
);
17724 OMPClause
*Sema::ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc
,
17725 SourceLocation EndLoc
) {
17726 return new (Context
) OMPUnifiedSharedMemoryClause(StartLoc
, EndLoc
);
17729 OMPClause
*Sema::ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc
,
17730 SourceLocation EndLoc
) {
17731 return new (Context
) OMPReverseOffloadClause(StartLoc
, EndLoc
);
17734 OMPClause
*Sema::ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc
,
17735 SourceLocation EndLoc
) {
17736 return new (Context
) OMPDynamicAllocatorsClause(StartLoc
, EndLoc
);
17739 StmtResult
Sema::ActOnOpenMPInteropDirective(ArrayRef
<OMPClause
*> Clauses
,
17740 SourceLocation StartLoc
,
17741 SourceLocation EndLoc
) {
17743 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17744 // At least one action-clause must appear on a directive.
17745 if (!hasClauses(Clauses
, OMPC_init
, OMPC_use
, OMPC_destroy
, OMPC_nowait
)) {
17746 StringRef Expected
= "'init', 'use', 'destroy', or 'nowait'";
17747 Diag(StartLoc
, diag::err_omp_no_clause_for_directive
)
17748 << Expected
<< getOpenMPDirectiveName(OMPD_interop
);
17749 return StmtError();
17752 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17753 // A depend clause can only appear on the directive if a targetsync
17754 // interop-type is present or the interop-var was initialized with
17755 // the targetsync interop-type.
17757 // If there is any 'init' clause diagnose if there is no 'init' clause with
17758 // interop-type of 'targetsync'. Cases involving other directives cannot be
17760 const OMPDependClause
*DependClause
= nullptr;
17761 bool HasInitClause
= false;
17762 bool IsTargetSync
= false;
17763 for (const OMPClause
*C
: Clauses
) {
17766 if (const auto *InitClause
= dyn_cast
<OMPInitClause
>(C
)) {
17767 HasInitClause
= true;
17768 if (InitClause
->getIsTargetSync())
17769 IsTargetSync
= true;
17770 } else if (const auto *DC
= dyn_cast
<OMPDependClause
>(C
)) {
17774 if (DependClause
&& HasInitClause
&& !IsTargetSync
) {
17775 Diag(DependClause
->getBeginLoc(), diag::err_omp_interop_bad_depend_clause
);
17776 return StmtError();
17779 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17780 // Each interop-var may be specified for at most one action-clause of each
17781 // interop construct.
17782 llvm::SmallPtrSet
<const ValueDecl
*, 4> InteropVars
;
17783 for (OMPClause
*C
: Clauses
) {
17784 OpenMPClauseKind ClauseKind
= C
->getClauseKind();
17785 std::pair
<ValueDecl
*, bool> DeclResult
;
17786 SourceLocation ELoc
;
17787 SourceRange ERange
;
17789 if (ClauseKind
== OMPC_init
) {
17790 auto *E
= cast
<OMPInitClause
>(C
)->getInteropVar();
17791 DeclResult
= getPrivateItem(*this, E
, ELoc
, ERange
);
17792 } else if (ClauseKind
== OMPC_use
) {
17793 auto *E
= cast
<OMPUseClause
>(C
)->getInteropVar();
17794 DeclResult
= getPrivateItem(*this, E
, ELoc
, ERange
);
17795 } else if (ClauseKind
== OMPC_destroy
) {
17796 auto *E
= cast
<OMPDestroyClause
>(C
)->getInteropVar();
17797 DeclResult
= getPrivateItem(*this, E
, ELoc
, ERange
);
17800 if (DeclResult
.first
) {
17801 if (!InteropVars
.insert(DeclResult
.first
).second
) {
17802 Diag(ELoc
, diag::err_omp_interop_var_multiple_actions
)
17803 << DeclResult
.first
;
17804 return StmtError();
17809 return OMPInteropDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
);
17812 static bool isValidInteropVariable(Sema
&SemaRef
, Expr
*InteropVarExpr
,
17813 SourceLocation VarLoc
,
17814 OpenMPClauseKind Kind
) {
17815 SourceLocation ELoc
;
17816 SourceRange ERange
;
17817 Expr
*RefExpr
= InteropVarExpr
;
17819 getPrivateItem(SemaRef
, RefExpr
, ELoc
, ERange
,
17820 /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t");
17823 // It will be analyzed later.
17830 // Interop variable should be of type omp_interop_t.
17831 bool HasError
= false;
17832 QualType InteropType
;
17833 LookupResult
Result(SemaRef
, &SemaRef
.Context
.Idents
.get("omp_interop_t"),
17834 VarLoc
, Sema::LookupOrdinaryName
);
17835 if (SemaRef
.LookupName(Result
, SemaRef
.getCurScope())) {
17836 NamedDecl
*ND
= Result
.getFoundDecl();
17837 if (const auto *TD
= dyn_cast
<TypeDecl
>(ND
)) {
17838 InteropType
= QualType(TD
->getTypeForDecl(), 0);
17847 SemaRef
.Diag(VarLoc
, diag::err_omp_implied_type_not_found
)
17848 << "omp_interop_t";
17852 QualType VarType
= InteropVarExpr
->getType().getUnqualifiedType();
17853 if (!SemaRef
.Context
.hasSameType(InteropType
, VarType
)) {
17854 SemaRef
.Diag(VarLoc
, diag::err_omp_interop_variable_wrong_type
);
17858 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17859 // The interop-var passed to init or destroy must be non-const.
17860 if ((Kind
== OMPC_init
|| Kind
== OMPC_destroy
) &&
17861 isConstNotMutableType(SemaRef
, InteropVarExpr
->getType())) {
17862 SemaRef
.Diag(VarLoc
, diag::err_omp_interop_variable_expected
)
17863 << /*non-const*/ 1;
17870 Sema::ActOnOpenMPInitClause(Expr
*InteropVar
, OMPInteropInfo
&InteropInfo
,
17871 SourceLocation StartLoc
, SourceLocation LParenLoc
,
17872 SourceLocation VarLoc
, SourceLocation EndLoc
) {
17874 if (!isValidInteropVariable(*this, InteropVar
, VarLoc
, OMPC_init
))
17877 // Check prefer_type values. These foreign-runtime-id values are either
17878 // string literals or constant integral expressions.
17879 for (const Expr
*E
: InteropInfo
.PreferTypes
) {
17880 if (E
->isValueDependent() || E
->isTypeDependent() ||
17881 E
->isInstantiationDependent() || E
->containsUnexpandedParameterPack())
17883 if (E
->isIntegerConstantExpr(Context
))
17885 if (isa
<StringLiteral
>(E
))
17887 Diag(E
->getExprLoc(), diag::err_omp_interop_prefer_type
);
17891 return OMPInitClause::Create(Context
, InteropVar
, InteropInfo
, StartLoc
,
17892 LParenLoc
, VarLoc
, EndLoc
);
17895 OMPClause
*Sema::ActOnOpenMPUseClause(Expr
*InteropVar
, SourceLocation StartLoc
,
17896 SourceLocation LParenLoc
,
17897 SourceLocation VarLoc
,
17898 SourceLocation EndLoc
) {
17900 if (!isValidInteropVariable(*this, InteropVar
, VarLoc
, OMPC_use
))
17903 return new (Context
)
17904 OMPUseClause(InteropVar
, StartLoc
, LParenLoc
, VarLoc
, EndLoc
);
17907 OMPClause
*Sema::ActOnOpenMPDestroyClause(Expr
*InteropVar
,
17908 SourceLocation StartLoc
,
17909 SourceLocation LParenLoc
,
17910 SourceLocation VarLoc
,
17911 SourceLocation EndLoc
) {
17912 if (!InteropVar
&& LangOpts
.OpenMP
>= 52 &&
17913 DSAStack
->getCurrentDirective() == OMPD_depobj
) {
17914 Diag(StartLoc
, diag::err_omp_expected_clause_argument
)
17915 << getOpenMPClauseName(OMPC_destroy
)
17916 << getOpenMPDirectiveName(OMPD_depobj
);
17920 !isValidInteropVariable(*this, InteropVar
, VarLoc
, OMPC_destroy
))
17923 return new (Context
)
17924 OMPDestroyClause(InteropVar
, StartLoc
, LParenLoc
, VarLoc
, EndLoc
);
17927 OMPClause
*Sema::ActOnOpenMPNovariantsClause(Expr
*Condition
,
17928 SourceLocation StartLoc
,
17929 SourceLocation LParenLoc
,
17930 SourceLocation EndLoc
) {
17931 Expr
*ValExpr
= Condition
;
17932 Stmt
*HelperValStmt
= nullptr;
17933 OpenMPDirectiveKind CaptureRegion
= OMPD_unknown
;
17934 if (!Condition
->isValueDependent() && !Condition
->isTypeDependent() &&
17935 !Condition
->isInstantiationDependent() &&
17936 !Condition
->containsUnexpandedParameterPack()) {
17937 ExprResult Val
= CheckBooleanCondition(StartLoc
, Condition
);
17938 if (Val
.isInvalid())
17941 ValExpr
= MakeFullExpr(Val
.get()).get();
17943 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
17944 CaptureRegion
= getOpenMPCaptureRegionForClause(DKind
, OMPC_novariants
,
17946 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
17947 ValExpr
= MakeFullExpr(ValExpr
).get();
17948 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
17949 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
17950 HelperValStmt
= buildPreInits(Context
, Captures
);
17954 return new (Context
) OMPNovariantsClause(
17955 ValExpr
, HelperValStmt
, CaptureRegion
, StartLoc
, LParenLoc
, EndLoc
);
17958 OMPClause
*Sema::ActOnOpenMPNocontextClause(Expr
*Condition
,
17959 SourceLocation StartLoc
,
17960 SourceLocation LParenLoc
,
17961 SourceLocation EndLoc
) {
17962 Expr
*ValExpr
= Condition
;
17963 Stmt
*HelperValStmt
= nullptr;
17964 OpenMPDirectiveKind CaptureRegion
= OMPD_unknown
;
17965 if (!Condition
->isValueDependent() && !Condition
->isTypeDependent() &&
17966 !Condition
->isInstantiationDependent() &&
17967 !Condition
->containsUnexpandedParameterPack()) {
17968 ExprResult Val
= CheckBooleanCondition(StartLoc
, Condition
);
17969 if (Val
.isInvalid())
17972 ValExpr
= MakeFullExpr(Val
.get()).get();
17974 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
17976 getOpenMPCaptureRegionForClause(DKind
, OMPC_nocontext
, LangOpts
.OpenMP
);
17977 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
17978 ValExpr
= MakeFullExpr(ValExpr
).get();
17979 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
17980 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
17981 HelperValStmt
= buildPreInits(Context
, Captures
);
17985 return new (Context
) OMPNocontextClause(ValExpr
, HelperValStmt
, CaptureRegion
,
17986 StartLoc
, LParenLoc
, EndLoc
);
17989 OMPClause
*Sema::ActOnOpenMPFilterClause(Expr
*ThreadID
,
17990 SourceLocation StartLoc
,
17991 SourceLocation LParenLoc
,
17992 SourceLocation EndLoc
) {
17993 Expr
*ValExpr
= ThreadID
;
17994 Stmt
*HelperValStmt
= nullptr;
17996 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
17997 OpenMPDirectiveKind CaptureRegion
=
17998 getOpenMPCaptureRegionForClause(DKind
, OMPC_filter
, LangOpts
.OpenMP
);
17999 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
18000 ValExpr
= MakeFullExpr(ValExpr
).get();
18001 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
18002 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
18003 HelperValStmt
= buildPreInits(Context
, Captures
);
18006 return new (Context
) OMPFilterClause(ValExpr
, HelperValStmt
, CaptureRegion
,
18007 StartLoc
, LParenLoc
, EndLoc
);
18010 OMPClause
*Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind
,
18011 ArrayRef
<Expr
*> VarList
,
18012 const OMPVarListLocTy
&Locs
,
18013 OpenMPVarListDataTy
&Data
) {
18014 SourceLocation StartLoc
= Locs
.StartLoc
;
18015 SourceLocation LParenLoc
= Locs
.LParenLoc
;
18016 SourceLocation EndLoc
= Locs
.EndLoc
;
18017 OMPClause
*Res
= nullptr;
18018 int ExtraModifier
= Data
.ExtraModifier
;
18019 SourceLocation ExtraModifierLoc
= Data
.ExtraModifierLoc
;
18020 SourceLocation ColonLoc
= Data
.ColonLoc
;
18023 Res
= ActOnOpenMPPrivateClause(VarList
, StartLoc
, LParenLoc
, EndLoc
);
18025 case OMPC_firstprivate
:
18026 Res
= ActOnOpenMPFirstprivateClause(VarList
, StartLoc
, LParenLoc
, EndLoc
);
18028 case OMPC_lastprivate
:
18029 assert(0 <= ExtraModifier
&& ExtraModifier
<= OMPC_LASTPRIVATE_unknown
&&
18030 "Unexpected lastprivate modifier.");
18031 Res
= ActOnOpenMPLastprivateClause(
18032 VarList
, static_cast<OpenMPLastprivateModifier
>(ExtraModifier
),
18033 ExtraModifierLoc
, ColonLoc
, StartLoc
, LParenLoc
, EndLoc
);
18036 Res
= ActOnOpenMPSharedClause(VarList
, StartLoc
, LParenLoc
, EndLoc
);
18038 case OMPC_reduction
:
18039 assert(0 <= ExtraModifier
&& ExtraModifier
<= OMPC_REDUCTION_unknown
&&
18040 "Unexpected lastprivate modifier.");
18041 Res
= ActOnOpenMPReductionClause(
18042 VarList
, static_cast<OpenMPReductionClauseModifier
>(ExtraModifier
),
18043 StartLoc
, LParenLoc
, ExtraModifierLoc
, ColonLoc
, EndLoc
,
18044 Data
.ReductionOrMapperIdScopeSpec
, Data
.ReductionOrMapperId
);
18046 case OMPC_task_reduction
:
18047 Res
= ActOnOpenMPTaskReductionClause(
18048 VarList
, StartLoc
, LParenLoc
, ColonLoc
, EndLoc
,
18049 Data
.ReductionOrMapperIdScopeSpec
, Data
.ReductionOrMapperId
);
18051 case OMPC_in_reduction
:
18052 Res
= ActOnOpenMPInReductionClause(
18053 VarList
, StartLoc
, LParenLoc
, ColonLoc
, EndLoc
,
18054 Data
.ReductionOrMapperIdScopeSpec
, Data
.ReductionOrMapperId
);
18057 assert(0 <= ExtraModifier
&& ExtraModifier
<= OMPC_LINEAR_unknown
&&
18058 "Unexpected linear modifier.");
18059 Res
= ActOnOpenMPLinearClause(
18060 VarList
, Data
.DepModOrTailExpr
, StartLoc
, LParenLoc
,
18061 static_cast<OpenMPLinearClauseKind
>(ExtraModifier
), ExtraModifierLoc
,
18062 ColonLoc
, Data
.StepModifierLoc
, EndLoc
);
18065 Res
= ActOnOpenMPAlignedClause(VarList
, Data
.DepModOrTailExpr
, StartLoc
,
18066 LParenLoc
, ColonLoc
, EndLoc
);
18069 Res
= ActOnOpenMPCopyinClause(VarList
, StartLoc
, LParenLoc
, EndLoc
);
18071 case OMPC_copyprivate
:
18072 Res
= ActOnOpenMPCopyprivateClause(VarList
, StartLoc
, LParenLoc
, EndLoc
);
18075 Res
= ActOnOpenMPFlushClause(VarList
, StartLoc
, LParenLoc
, EndLoc
);
18078 assert(0 <= ExtraModifier
&& ExtraModifier
<= OMPC_DEPEND_unknown
&&
18079 "Unexpected depend modifier.");
18080 Res
= ActOnOpenMPDependClause(
18081 {static_cast<OpenMPDependClauseKind
>(ExtraModifier
), ExtraModifierLoc
,
18082 ColonLoc
, Data
.OmpAllMemoryLoc
},
18083 Data
.DepModOrTailExpr
, VarList
, StartLoc
, LParenLoc
, EndLoc
);
18086 assert(0 <= ExtraModifier
&& ExtraModifier
<= OMPC_MAP_unknown
&&
18087 "Unexpected map modifier.");
18088 Res
= ActOnOpenMPMapClause(
18089 Data
.IteratorExpr
, Data
.MapTypeModifiers
, Data
.MapTypeModifiersLoc
,
18090 Data
.ReductionOrMapperIdScopeSpec
, Data
.ReductionOrMapperId
,
18091 static_cast<OpenMPMapClauseKind
>(ExtraModifier
), Data
.IsMapTypeImplicit
,
18092 ExtraModifierLoc
, ColonLoc
, VarList
, Locs
);
18096 ActOnOpenMPToClause(Data
.MotionModifiers
, Data
.MotionModifiersLoc
,
18097 Data
.ReductionOrMapperIdScopeSpec
,
18098 Data
.ReductionOrMapperId
, ColonLoc
, VarList
, Locs
);
18101 Res
= ActOnOpenMPFromClause(Data
.MotionModifiers
, Data
.MotionModifiersLoc
,
18102 Data
.ReductionOrMapperIdScopeSpec
,
18103 Data
.ReductionOrMapperId
, ColonLoc
, VarList
,
18106 case OMPC_use_device_ptr
:
18107 Res
= ActOnOpenMPUseDevicePtrClause(VarList
, Locs
);
18109 case OMPC_use_device_addr
:
18110 Res
= ActOnOpenMPUseDeviceAddrClause(VarList
, Locs
);
18112 case OMPC_is_device_ptr
:
18113 Res
= ActOnOpenMPIsDevicePtrClause(VarList
, Locs
);
18115 case OMPC_has_device_addr
:
18116 Res
= ActOnOpenMPHasDeviceAddrClause(VarList
, Locs
);
18118 case OMPC_allocate
:
18119 Res
= ActOnOpenMPAllocateClause(Data
.DepModOrTailExpr
, VarList
, StartLoc
,
18120 LParenLoc
, ColonLoc
, EndLoc
);
18122 case OMPC_nontemporal
:
18123 Res
= ActOnOpenMPNontemporalClause(VarList
, StartLoc
, LParenLoc
, EndLoc
);
18125 case OMPC_inclusive
:
18126 Res
= ActOnOpenMPInclusiveClause(VarList
, StartLoc
, LParenLoc
, EndLoc
);
18128 case OMPC_exclusive
:
18129 Res
= ActOnOpenMPExclusiveClause(VarList
, StartLoc
, LParenLoc
, EndLoc
);
18131 case OMPC_affinity
:
18132 Res
= ActOnOpenMPAffinityClause(StartLoc
, LParenLoc
, ColonLoc
, EndLoc
,
18133 Data
.DepModOrTailExpr
, VarList
);
18135 case OMPC_doacross
:
18136 Res
= ActOnOpenMPDoacrossClause(
18137 static_cast<OpenMPDoacrossClauseModifier
>(ExtraModifier
),
18138 ExtraModifierLoc
, ColonLoc
, VarList
, StartLoc
, LParenLoc
, EndLoc
);
18143 case OMPC_num_threads
:
18147 case OMPC_allocator
:
18148 case OMPC_collapse
:
18150 case OMPC_proc_bind
:
18151 case OMPC_schedule
:
18155 case OMPC_mergeable
:
18156 case OMPC_threadprivate
:
18170 case OMPC_num_teams
:
18171 case OMPC_thread_limit
:
18172 case OMPC_priority
:
18173 case OMPC_grainsize
:
18175 case OMPC_num_tasks
:
18177 case OMPC_dist_schedule
:
18178 case OMPC_defaultmap
:
18181 case OMPC_unified_address
:
18182 case OMPC_unified_shared_memory
:
18183 case OMPC_reverse_offload
:
18184 case OMPC_dynamic_allocators
:
18185 case OMPC_atomic_default_mem_order
:
18186 case OMPC_device_type
:
18190 case OMPC_severity
:
18193 case OMPC_novariants
:
18194 case OMPC_nocontext
:
18196 case OMPC_uses_allocators
:
18200 llvm_unreachable("Clause is not allowed.");
18205 ExprResult
Sema::getOpenMPCapturedExpr(VarDecl
*Capture
, ExprValueKind VK
,
18206 ExprObjectKind OK
, SourceLocation Loc
) {
18207 ExprResult Res
= BuildDeclRefExpr(
18208 Capture
, Capture
->getType().getNonReferenceType(), VK_LValue
, Loc
);
18209 if (!Res
.isUsable())
18210 return ExprError();
18211 if (OK
== OK_Ordinary
&& !getLangOpts().CPlusPlus
) {
18212 Res
= CreateBuiltinUnaryOp(Loc
, UO_Deref
, Res
.get());
18213 if (!Res
.isUsable())
18214 return ExprError();
18216 if (VK
!= VK_LValue
&& Res
.get()->isGLValue()) {
18217 Res
= DefaultLvalueConversion(Res
.get());
18218 if (!Res
.isUsable())
18219 return ExprError();
18224 OMPClause
*Sema::ActOnOpenMPPrivateClause(ArrayRef
<Expr
*> VarList
,
18225 SourceLocation StartLoc
,
18226 SourceLocation LParenLoc
,
18227 SourceLocation EndLoc
) {
18228 SmallVector
<Expr
*, 8> Vars
;
18229 SmallVector
<Expr
*, 8> PrivateCopies
;
18230 bool IsImplicitClause
=
18231 StartLoc
.isInvalid() && LParenLoc
.isInvalid() && EndLoc
.isInvalid();
18232 for (Expr
*RefExpr
: VarList
) {
18233 assert(RefExpr
&& "NULL expr in OpenMP private clause.");
18234 SourceLocation ELoc
;
18235 SourceRange ERange
;
18236 Expr
*SimpleRefExpr
= RefExpr
;
18237 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
18239 // It will be analyzed later.
18240 Vars
.push_back(RefExpr
);
18241 PrivateCopies
.push_back(nullptr);
18243 ValueDecl
*D
= Res
.first
;
18247 QualType Type
= D
->getType();
18248 auto *VD
= dyn_cast
<VarDecl
>(D
);
18250 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18251 // A variable that appears in a private clause must not have an incomplete
18252 // type or a reference type.
18253 if (RequireCompleteType(ELoc
, Type
, diag::err_omp_private_incomplete_type
))
18255 Type
= Type
.getNonReferenceType();
18257 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18258 // A variable that is privatized must not have a const-qualified type
18259 // unless it is of class type with a mutable member. This restriction does
18260 // not apply to the firstprivate clause.
18262 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
18263 // A variable that appears in a private clause must not have a
18264 // const-qualified type unless it is of class type with a mutable member.
18265 if (rejectConstNotMutableType(*this, D
, Type
, OMPC_private
, ELoc
))
18268 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18270 // Variables with the predetermined data-sharing attributes may not be
18271 // listed in data-sharing attributes clauses, except for the cases
18272 // listed below. For these exceptions only, listing a predetermined
18273 // variable in a data-sharing attribute clause is allowed and overrides
18274 // the variable's predetermined data-sharing attributes.
18275 DSAStackTy::DSAVarData DVar
= DSAStack
->getTopDSA(D
, /*FromParent=*/false);
18276 if (DVar
.CKind
!= OMPC_unknown
&& DVar
.CKind
!= OMPC_private
) {
18277 Diag(ELoc
, diag::err_omp_wrong_dsa
) << getOpenMPClauseName(DVar
.CKind
)
18278 << getOpenMPClauseName(OMPC_private
);
18279 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18283 OpenMPDirectiveKind CurrDir
= DSAStack
->getCurrentDirective();
18284 // Variably modified types are not supported for tasks.
18285 if (!Type
->isAnyPointerType() && Type
->isVariablyModifiedType() &&
18286 isOpenMPTaskingDirective(CurrDir
)) {
18287 Diag(ELoc
, diag::err_omp_variably_modified_type_not_supported
)
18288 << getOpenMPClauseName(OMPC_private
) << Type
18289 << getOpenMPDirectiveName(CurrDir
);
18290 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
18291 VarDecl::DeclarationOnly
;
18292 Diag(D
->getLocation(),
18293 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
18298 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18299 // A list item cannot appear in both a map clause and a data-sharing
18300 // attribute clause on the same construct
18302 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18303 // A list item cannot appear in both a map clause and a data-sharing
18304 // attribute clause on the same construct unless the construct is a
18305 // combined construct.
18306 if ((LangOpts
.OpenMP
<= 45 && isOpenMPTargetExecutionDirective(CurrDir
)) ||
18307 CurrDir
== OMPD_target
) {
18308 OpenMPClauseKind ConflictKind
;
18309 if (DSAStack
->checkMappableExprComponentListsForDecl(
18310 VD
, /*CurrentRegionOnly=*/true,
18311 [&](OMPClauseMappableExprCommon::MappableExprComponentListRef
,
18312 OpenMPClauseKind WhereFoundClauseKind
) -> bool {
18313 ConflictKind
= WhereFoundClauseKind
;
18316 Diag(ELoc
, diag::err_omp_variable_in_given_clause_and_dsa
)
18317 << getOpenMPClauseName(OMPC_private
)
18318 << getOpenMPClauseName(ConflictKind
)
18319 << getOpenMPDirectiveName(CurrDir
);
18320 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18325 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
18326 // A variable of class type (or array thereof) that appears in a private
18327 // clause requires an accessible, unambiguous default constructor for the
18329 // Generate helper private variable and initialize it with the default
18330 // value. The address of the original variable is replaced by the address of
18331 // the new private variable in CodeGen. This new variable is not added to
18332 // IdResolver, so the code in the OpenMP region uses original variable for
18333 // proper diagnostics.
18334 Type
= Type
.getUnqualifiedType();
18335 VarDecl
*VDPrivate
=
18336 buildVarDecl(*this, ELoc
, Type
, D
->getName(),
18337 D
->hasAttrs() ? &D
->getAttrs() : nullptr,
18338 VD
? cast
<DeclRefExpr
>(SimpleRefExpr
) : nullptr);
18339 ActOnUninitializedDecl(VDPrivate
);
18340 if (VDPrivate
->isInvalidDecl())
18342 DeclRefExpr
*VDPrivateRefExpr
= buildDeclRefExpr(
18343 *this, VDPrivate
, RefExpr
->getType().getUnqualifiedType(), ELoc
);
18345 DeclRefExpr
*Ref
= nullptr;
18346 if (!VD
&& !CurContext
->isDependentContext()) {
18347 auto *FD
= dyn_cast
<FieldDecl
>(D
);
18348 VarDecl
*VD
= FD
? DSAStack
->getImplicitFDCapExprDecl(FD
) : nullptr;
18350 Ref
= buildDeclRefExpr(*this, VD
, VD
->getType().getNonReferenceType(),
18351 RefExpr
->getExprLoc());
18353 Ref
= buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/false);
18355 if (!IsImplicitClause
)
18356 DSAStack
->addDSA(D
, RefExpr
->IgnoreParens(), OMPC_private
, Ref
);
18357 Vars
.push_back((VD
|| CurContext
->isDependentContext())
18358 ? RefExpr
->IgnoreParens()
18360 PrivateCopies
.push_back(VDPrivateRefExpr
);
18366 return OMPPrivateClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
, Vars
,
18370 OMPClause
*Sema::ActOnOpenMPFirstprivateClause(ArrayRef
<Expr
*> VarList
,
18371 SourceLocation StartLoc
,
18372 SourceLocation LParenLoc
,
18373 SourceLocation EndLoc
) {
18374 SmallVector
<Expr
*, 8> Vars
;
18375 SmallVector
<Expr
*, 8> PrivateCopies
;
18376 SmallVector
<Expr
*, 8> Inits
;
18377 SmallVector
<Decl
*, 4> ExprCaptures
;
18378 bool IsImplicitClause
=
18379 StartLoc
.isInvalid() && LParenLoc
.isInvalid() && EndLoc
.isInvalid();
18380 SourceLocation ImplicitClauseLoc
= DSAStack
->getConstructLoc();
18382 for (Expr
*RefExpr
: VarList
) {
18383 assert(RefExpr
&& "NULL expr in OpenMP firstprivate clause.");
18384 SourceLocation ELoc
;
18385 SourceRange ERange
;
18386 Expr
*SimpleRefExpr
= RefExpr
;
18387 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
18389 // It will be analyzed later.
18390 Vars
.push_back(RefExpr
);
18391 PrivateCopies
.push_back(nullptr);
18392 Inits
.push_back(nullptr);
18394 ValueDecl
*D
= Res
.first
;
18398 ELoc
= IsImplicitClause
? ImplicitClauseLoc
: ELoc
;
18399 QualType Type
= D
->getType();
18400 auto *VD
= dyn_cast
<VarDecl
>(D
);
18402 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18403 // A variable that appears in a private clause must not have an incomplete
18404 // type or a reference type.
18405 if (RequireCompleteType(ELoc
, Type
,
18406 diag::err_omp_firstprivate_incomplete_type
))
18408 Type
= Type
.getNonReferenceType();
18410 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
18411 // A variable of class type (or array thereof) that appears in a private
18412 // clause requires an accessible, unambiguous copy constructor for the
18414 QualType ElemType
= Context
.getBaseElementType(Type
).getNonReferenceType();
18416 // If an implicit firstprivate variable found it was checked already.
18417 DSAStackTy::DSAVarData TopDVar
;
18418 if (!IsImplicitClause
) {
18419 DSAStackTy::DSAVarData DVar
=
18420 DSAStack
->getTopDSA(D
, /*FromParent=*/false);
18422 OpenMPDirectiveKind CurrDir
= DSAStack
->getCurrentDirective();
18423 bool IsConstant
= ElemType
.isConstant(Context
);
18424 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
18425 // A list item that specifies a given variable may not appear in more
18426 // than one clause on the same directive, except that a variable may be
18427 // specified in both firstprivate and lastprivate clauses.
18428 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18429 // A list item may appear in a firstprivate or lastprivate clause but not
18431 if (DVar
.CKind
!= OMPC_unknown
&& DVar
.CKind
!= OMPC_firstprivate
&&
18432 (isOpenMPDistributeDirective(CurrDir
) ||
18433 DVar
.CKind
!= OMPC_lastprivate
) &&
18435 Diag(ELoc
, diag::err_omp_wrong_dsa
)
18436 << getOpenMPClauseName(DVar
.CKind
)
18437 << getOpenMPClauseName(OMPC_firstprivate
);
18438 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18442 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18444 // Variables with the predetermined data-sharing attributes may not be
18445 // listed in data-sharing attributes clauses, except for the cases
18446 // listed below. For these exceptions only, listing a predetermined
18447 // variable in a data-sharing attribute clause is allowed and overrides
18448 // the variable's predetermined data-sharing attributes.
18449 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18450 // in a Construct, C/C++, p.2]
18451 // Variables with const-qualified type having no mutable member may be
18452 // listed in a firstprivate clause, even if they are static data members.
18453 if (!(IsConstant
|| (VD
&& VD
->isStaticDataMember())) && !DVar
.RefExpr
&&
18454 DVar
.CKind
!= OMPC_unknown
&& DVar
.CKind
!= OMPC_shared
) {
18455 Diag(ELoc
, diag::err_omp_wrong_dsa
)
18456 << getOpenMPClauseName(DVar
.CKind
)
18457 << getOpenMPClauseName(OMPC_firstprivate
);
18458 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18462 // OpenMP [2.9.3.4, Restrictions, p.2]
18463 // A list item that is private within a parallel region must not appear
18464 // in a firstprivate clause on a worksharing construct if any of the
18465 // worksharing regions arising from the worksharing construct ever bind
18466 // to any of the parallel regions arising from the parallel construct.
18467 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18468 // A list item that is private within a teams region must not appear in a
18469 // firstprivate clause on a distribute construct if any of the distribute
18470 // regions arising from the distribute construct ever bind to any of the
18471 // teams regions arising from the teams construct.
18472 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18473 // A list item that appears in a reduction clause of a teams construct
18474 // must not appear in a firstprivate clause on a distribute construct if
18475 // any of the distribute regions arising from the distribute construct
18476 // ever bind to any of the teams regions arising from the teams construct.
18477 if ((isOpenMPWorksharingDirective(CurrDir
) ||
18478 isOpenMPDistributeDirective(CurrDir
)) &&
18479 !isOpenMPParallelDirective(CurrDir
) &&
18480 !isOpenMPTeamsDirective(CurrDir
)) {
18481 DVar
= DSAStack
->getImplicitDSA(D
, true);
18482 if (DVar
.CKind
!= OMPC_shared
&&
18483 (isOpenMPParallelDirective(DVar
.DKind
) ||
18484 isOpenMPTeamsDirective(DVar
.DKind
) ||
18485 DVar
.DKind
== OMPD_unknown
)) {
18486 Diag(ELoc
, diag::err_omp_required_access
)
18487 << getOpenMPClauseName(OMPC_firstprivate
)
18488 << getOpenMPClauseName(OMPC_shared
);
18489 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18493 // OpenMP [2.9.3.4, Restrictions, p.3]
18494 // A list item that appears in a reduction clause of a parallel construct
18495 // must not appear in a firstprivate clause on a worksharing or task
18496 // construct if any of the worksharing or task regions arising from the
18497 // worksharing or task construct ever bind to any of the parallel regions
18498 // arising from the parallel construct.
18499 // OpenMP [2.9.3.4, Restrictions, p.4]
18500 // A list item that appears in a reduction clause in worksharing
18501 // construct must not appear in a firstprivate clause in a task construct
18502 // encountered during execution of any of the worksharing regions arising
18503 // from the worksharing construct.
18504 if (isOpenMPTaskingDirective(CurrDir
)) {
18505 DVar
= DSAStack
->hasInnermostDSA(
18507 [](OpenMPClauseKind C
, bool AppliedToPointee
) {
18508 return C
== OMPC_reduction
&& !AppliedToPointee
;
18510 [](OpenMPDirectiveKind K
) {
18511 return isOpenMPParallelDirective(K
) ||
18512 isOpenMPWorksharingDirective(K
) ||
18513 isOpenMPTeamsDirective(K
);
18515 /*FromParent=*/true);
18516 if (DVar
.CKind
== OMPC_reduction
&&
18517 (isOpenMPParallelDirective(DVar
.DKind
) ||
18518 isOpenMPWorksharingDirective(DVar
.DKind
) ||
18519 isOpenMPTeamsDirective(DVar
.DKind
))) {
18520 Diag(ELoc
, diag::err_omp_parallel_reduction_in_task_firstprivate
)
18521 << getOpenMPDirectiveName(DVar
.DKind
);
18522 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18527 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18528 // A list item cannot appear in both a map clause and a data-sharing
18529 // attribute clause on the same construct
18531 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18532 // A list item cannot appear in both a map clause and a data-sharing
18533 // attribute clause on the same construct unless the construct is a
18534 // combined construct.
18535 if ((LangOpts
.OpenMP
<= 45 &&
18536 isOpenMPTargetExecutionDirective(CurrDir
)) ||
18537 CurrDir
== OMPD_target
) {
18538 OpenMPClauseKind ConflictKind
;
18539 if (DSAStack
->checkMappableExprComponentListsForDecl(
18540 VD
, /*CurrentRegionOnly=*/true,
18542 OMPClauseMappableExprCommon::MappableExprComponentListRef
,
18543 OpenMPClauseKind WhereFoundClauseKind
) {
18544 ConflictKind
= WhereFoundClauseKind
;
18547 Diag(ELoc
, diag::err_omp_variable_in_given_clause_and_dsa
)
18548 << getOpenMPClauseName(OMPC_firstprivate
)
18549 << getOpenMPClauseName(ConflictKind
)
18550 << getOpenMPDirectiveName(DSAStack
->getCurrentDirective());
18551 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18557 // Variably modified types are not supported for tasks.
18558 if (!Type
->isAnyPointerType() && Type
->isVariablyModifiedType() &&
18559 isOpenMPTaskingDirective(DSAStack
->getCurrentDirective())) {
18560 Diag(ELoc
, diag::err_omp_variably_modified_type_not_supported
)
18561 << getOpenMPClauseName(OMPC_firstprivate
) << Type
18562 << getOpenMPDirectiveName(DSAStack
->getCurrentDirective());
18563 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
18564 VarDecl::DeclarationOnly
;
18565 Diag(D
->getLocation(),
18566 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
18571 Type
= Type
.getUnqualifiedType();
18572 VarDecl
*VDPrivate
=
18573 buildVarDecl(*this, ELoc
, Type
, D
->getName(),
18574 D
->hasAttrs() ? &D
->getAttrs() : nullptr,
18575 VD
? cast
<DeclRefExpr
>(SimpleRefExpr
) : nullptr);
18576 // Generate helper private variable and initialize it with the value of the
18577 // original variable. The address of the original variable is replaced by
18578 // the address of the new private variable in the CodeGen. This new variable
18579 // is not added to IdResolver, so the code in the OpenMP region uses
18580 // original variable for proper diagnostics and variable capturing.
18581 Expr
*VDInitRefExpr
= nullptr;
18582 // For arrays generate initializer for single element and replace it by the
18583 // original array element in CodeGen.
18584 if (Type
->isArrayType()) {
18586 buildVarDecl(*this, RefExpr
->getExprLoc(), ElemType
, D
->getName());
18587 VDInitRefExpr
= buildDeclRefExpr(*this, VDInit
, ElemType
, ELoc
);
18588 Expr
*Init
= DefaultLvalueConversion(VDInitRefExpr
).get();
18589 ElemType
= ElemType
.getUnqualifiedType();
18590 VarDecl
*VDInitTemp
= buildVarDecl(*this, RefExpr
->getExprLoc(), ElemType
,
18591 ".firstprivate.temp");
18592 InitializedEntity Entity
=
18593 InitializedEntity::InitializeVariable(VDInitTemp
);
18594 InitializationKind Kind
= InitializationKind::CreateCopy(ELoc
, ELoc
);
18596 InitializationSequence
InitSeq(*this, Entity
, Kind
, Init
);
18597 ExprResult Result
= InitSeq
.Perform(*this, Entity
, Kind
, Init
);
18598 if (Result
.isInvalid())
18599 VDPrivate
->setInvalidDecl();
18601 VDPrivate
->setInit(Result
.getAs
<Expr
>());
18602 // Remove temp variable declaration.
18603 Context
.Deallocate(VDInitTemp
);
18605 VarDecl
*VDInit
= buildVarDecl(*this, RefExpr
->getExprLoc(), Type
,
18606 ".firstprivate.temp");
18607 VDInitRefExpr
= buildDeclRefExpr(*this, VDInit
, RefExpr
->getType(),
18608 RefExpr
->getExprLoc());
18609 AddInitializerToDecl(VDPrivate
,
18610 DefaultLvalueConversion(VDInitRefExpr
).get(),
18611 /*DirectInit=*/false);
18613 if (VDPrivate
->isInvalidDecl()) {
18614 if (IsImplicitClause
) {
18615 Diag(RefExpr
->getExprLoc(),
18616 diag::note_omp_task_predetermined_firstprivate_here
);
18620 CurContext
->addDecl(VDPrivate
);
18621 DeclRefExpr
*VDPrivateRefExpr
= buildDeclRefExpr(
18622 *this, VDPrivate
, RefExpr
->getType().getUnqualifiedType(),
18623 RefExpr
->getExprLoc());
18624 DeclRefExpr
*Ref
= nullptr;
18625 if (!VD
&& !CurContext
->isDependentContext()) {
18626 if (TopDVar
.CKind
== OMPC_lastprivate
) {
18627 Ref
= TopDVar
.PrivateCopy
;
18629 auto *FD
= dyn_cast
<FieldDecl
>(D
);
18630 VarDecl
*VD
= FD
? DSAStack
->getImplicitFDCapExprDecl(FD
) : nullptr;
18632 Ref
= buildDeclRefExpr(*this, VD
, VD
->getType().getNonReferenceType(),
18633 RefExpr
->getExprLoc());
18635 Ref
= buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/true);
18636 if (VD
|| !isOpenMPCapturedDecl(D
))
18637 ExprCaptures
.push_back(Ref
->getDecl());
18640 if (!IsImplicitClause
)
18641 DSAStack
->addDSA(D
, RefExpr
->IgnoreParens(), OMPC_firstprivate
, Ref
);
18642 Vars
.push_back((VD
|| CurContext
->isDependentContext())
18643 ? RefExpr
->IgnoreParens()
18645 PrivateCopies
.push_back(VDPrivateRefExpr
);
18646 Inits
.push_back(VDInitRefExpr
);
18652 return OMPFirstprivateClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
,
18653 Vars
, PrivateCopies
, Inits
,
18654 buildPreInits(Context
, ExprCaptures
));
18657 OMPClause
*Sema::ActOnOpenMPLastprivateClause(
18658 ArrayRef
<Expr
*> VarList
, OpenMPLastprivateModifier LPKind
,
18659 SourceLocation LPKindLoc
, SourceLocation ColonLoc
, SourceLocation StartLoc
,
18660 SourceLocation LParenLoc
, SourceLocation EndLoc
) {
18661 if (LPKind
== OMPC_LASTPRIVATE_unknown
&& LPKindLoc
.isValid()) {
18662 assert(ColonLoc
.isValid() && "Colon location must be valid.");
18663 Diag(LPKindLoc
, diag::err_omp_unexpected_clause_value
)
18664 << getListOfPossibleValues(OMPC_lastprivate
, /*First=*/0,
18665 /*Last=*/OMPC_LASTPRIVATE_unknown
)
18666 << getOpenMPClauseName(OMPC_lastprivate
);
18670 SmallVector
<Expr
*, 8> Vars
;
18671 SmallVector
<Expr
*, 8> SrcExprs
;
18672 SmallVector
<Expr
*, 8> DstExprs
;
18673 SmallVector
<Expr
*, 8> AssignmentOps
;
18674 SmallVector
<Decl
*, 4> ExprCaptures
;
18675 SmallVector
<Expr
*, 4> ExprPostUpdates
;
18676 for (Expr
*RefExpr
: VarList
) {
18677 assert(RefExpr
&& "NULL expr in OpenMP lastprivate clause.");
18678 SourceLocation ELoc
;
18679 SourceRange ERange
;
18680 Expr
*SimpleRefExpr
= RefExpr
;
18681 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
18683 // It will be analyzed later.
18684 Vars
.push_back(RefExpr
);
18685 SrcExprs
.push_back(nullptr);
18686 DstExprs
.push_back(nullptr);
18687 AssignmentOps
.push_back(nullptr);
18689 ValueDecl
*D
= Res
.first
;
18693 QualType Type
= D
->getType();
18694 auto *VD
= dyn_cast
<VarDecl
>(D
);
18696 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
18697 // A variable that appears in a lastprivate clause must not have an
18698 // incomplete type or a reference type.
18699 if (RequireCompleteType(ELoc
, Type
,
18700 diag::err_omp_lastprivate_incomplete_type
))
18702 Type
= Type
.getNonReferenceType();
18704 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18705 // A variable that is privatized must not have a const-qualified type
18706 // unless it is of class type with a mutable member. This restriction does
18707 // not apply to the firstprivate clause.
18709 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
18710 // A variable that appears in a lastprivate clause must not have a
18711 // const-qualified type unless it is of class type with a mutable member.
18712 if (rejectConstNotMutableType(*this, D
, Type
, OMPC_lastprivate
, ELoc
))
18715 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
18716 // A list item that appears in a lastprivate clause with the conditional
18717 // modifier must be a scalar variable.
18718 if (LPKind
== OMPC_LASTPRIVATE_conditional
&& !Type
->isScalarType()) {
18719 Diag(ELoc
, diag::err_omp_lastprivate_conditional_non_scalar
);
18720 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
18721 VarDecl::DeclarationOnly
;
18722 Diag(D
->getLocation(),
18723 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
18728 OpenMPDirectiveKind CurrDir
= DSAStack
->getCurrentDirective();
18729 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
18731 // Variables with the predetermined data-sharing attributes may not be
18732 // listed in data-sharing attributes clauses, except for the cases
18734 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18735 // A list item may appear in a firstprivate or lastprivate clause but not
18737 DSAStackTy::DSAVarData DVar
= DSAStack
->getTopDSA(D
, /*FromParent=*/false);
18738 if (DVar
.CKind
!= OMPC_unknown
&& DVar
.CKind
!= OMPC_lastprivate
&&
18739 (isOpenMPDistributeDirective(CurrDir
) ||
18740 DVar
.CKind
!= OMPC_firstprivate
) &&
18741 (DVar
.CKind
!= OMPC_private
|| DVar
.RefExpr
!= nullptr)) {
18742 Diag(ELoc
, diag::err_omp_wrong_dsa
)
18743 << getOpenMPClauseName(DVar
.CKind
)
18744 << getOpenMPClauseName(OMPC_lastprivate
);
18745 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18749 // OpenMP [2.14.3.5, Restrictions, p.2]
18750 // A list item that is private within a parallel region, or that appears in
18751 // the reduction clause of a parallel construct, must not appear in a
18752 // lastprivate clause on a worksharing construct if any of the corresponding
18753 // worksharing regions ever binds to any of the corresponding parallel
18755 DSAStackTy::DSAVarData TopDVar
= DVar
;
18756 if (isOpenMPWorksharingDirective(CurrDir
) &&
18757 !isOpenMPParallelDirective(CurrDir
) &&
18758 !isOpenMPTeamsDirective(CurrDir
)) {
18759 DVar
= DSAStack
->getImplicitDSA(D
, true);
18760 if (DVar
.CKind
!= OMPC_shared
) {
18761 Diag(ELoc
, diag::err_omp_required_access
)
18762 << getOpenMPClauseName(OMPC_lastprivate
)
18763 << getOpenMPClauseName(OMPC_shared
);
18764 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18769 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
18770 // A variable of class type (or array thereof) that appears in a
18771 // lastprivate clause requires an accessible, unambiguous default
18772 // constructor for the class type, unless the list item is also specified
18773 // in a firstprivate clause.
18774 // A variable of class type (or array thereof) that appears in a
18775 // lastprivate clause requires an accessible, unambiguous copy assignment
18776 // operator for the class type.
18777 Type
= Context
.getBaseElementType(Type
).getNonReferenceType();
18778 VarDecl
*SrcVD
= buildVarDecl(*this, ERange
.getBegin(),
18779 Type
.getUnqualifiedType(), ".lastprivate.src",
18780 D
->hasAttrs() ? &D
->getAttrs() : nullptr);
18781 DeclRefExpr
*PseudoSrcExpr
=
18782 buildDeclRefExpr(*this, SrcVD
, Type
.getUnqualifiedType(), ELoc
);
18784 buildVarDecl(*this, ERange
.getBegin(), Type
, ".lastprivate.dst",
18785 D
->hasAttrs() ? &D
->getAttrs() : nullptr);
18786 DeclRefExpr
*PseudoDstExpr
= buildDeclRefExpr(*this, DstVD
, Type
, ELoc
);
18787 // For arrays generate assignment operation for single element and replace
18788 // it by the original array element in CodeGen.
18789 ExprResult AssignmentOp
= BuildBinOp(/*S=*/nullptr, ELoc
, BO_Assign
,
18790 PseudoDstExpr
, PseudoSrcExpr
);
18791 if (AssignmentOp
.isInvalid())
18794 ActOnFinishFullExpr(AssignmentOp
.get(), ELoc
, /*DiscardedValue*/ false);
18795 if (AssignmentOp
.isInvalid())
18798 DeclRefExpr
*Ref
= nullptr;
18799 if (!VD
&& !CurContext
->isDependentContext()) {
18800 if (TopDVar
.CKind
== OMPC_firstprivate
) {
18801 Ref
= TopDVar
.PrivateCopy
;
18803 Ref
= buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/false);
18804 if (!isOpenMPCapturedDecl(D
))
18805 ExprCaptures
.push_back(Ref
->getDecl());
18807 if ((TopDVar
.CKind
== OMPC_firstprivate
&& !TopDVar
.PrivateCopy
) ||
18808 (!isOpenMPCapturedDecl(D
) &&
18809 Ref
->getDecl()->hasAttr
<OMPCaptureNoInitAttr
>())) {
18810 ExprResult RefRes
= DefaultLvalueConversion(Ref
);
18811 if (!RefRes
.isUsable())
18813 ExprResult PostUpdateRes
=
18814 BuildBinOp(DSAStack
->getCurScope(), ELoc
, BO_Assign
, SimpleRefExpr
,
18816 if (!PostUpdateRes
.isUsable())
18818 ExprPostUpdates
.push_back(
18819 IgnoredValueConversions(PostUpdateRes
.get()).get());
18822 DSAStack
->addDSA(D
, RefExpr
->IgnoreParens(), OMPC_lastprivate
, Ref
);
18823 Vars
.push_back((VD
|| CurContext
->isDependentContext())
18824 ? RefExpr
->IgnoreParens()
18826 SrcExprs
.push_back(PseudoSrcExpr
);
18827 DstExprs
.push_back(PseudoDstExpr
);
18828 AssignmentOps
.push_back(AssignmentOp
.get());
18834 return OMPLastprivateClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
,
18835 Vars
, SrcExprs
, DstExprs
, AssignmentOps
,
18836 LPKind
, LPKindLoc
, ColonLoc
,
18837 buildPreInits(Context
, ExprCaptures
),
18838 buildPostUpdate(*this, ExprPostUpdates
));
18841 OMPClause
*Sema::ActOnOpenMPSharedClause(ArrayRef
<Expr
*> VarList
,
18842 SourceLocation StartLoc
,
18843 SourceLocation LParenLoc
,
18844 SourceLocation EndLoc
) {
18845 SmallVector
<Expr
*, 8> Vars
;
18846 for (Expr
*RefExpr
: VarList
) {
18847 assert(RefExpr
&& "NULL expr in OpenMP lastprivate clause.");
18848 SourceLocation ELoc
;
18849 SourceRange ERange
;
18850 Expr
*SimpleRefExpr
= RefExpr
;
18851 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
18853 // It will be analyzed later.
18854 Vars
.push_back(RefExpr
);
18856 ValueDecl
*D
= Res
.first
;
18860 auto *VD
= dyn_cast
<VarDecl
>(D
);
18861 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18863 // Variables with the predetermined data-sharing attributes may not be
18864 // listed in data-sharing attributes clauses, except for the cases
18865 // listed below. For these exceptions only, listing a predetermined
18866 // variable in a data-sharing attribute clause is allowed and overrides
18867 // the variable's predetermined data-sharing attributes.
18868 DSAStackTy::DSAVarData DVar
= DSAStack
->getTopDSA(D
, /*FromParent=*/false);
18869 if (DVar
.CKind
!= OMPC_unknown
&& DVar
.CKind
!= OMPC_shared
&&
18871 Diag(ELoc
, diag::err_omp_wrong_dsa
) << getOpenMPClauseName(DVar
.CKind
)
18872 << getOpenMPClauseName(OMPC_shared
);
18873 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18877 DeclRefExpr
*Ref
= nullptr;
18878 if (!VD
&& isOpenMPCapturedDecl(D
) && !CurContext
->isDependentContext())
18879 Ref
= buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/true);
18880 DSAStack
->addDSA(D
, RefExpr
->IgnoreParens(), OMPC_shared
, Ref
);
18881 Vars
.push_back((VD
|| !Ref
|| CurContext
->isDependentContext())
18882 ? RefExpr
->IgnoreParens()
18889 return OMPSharedClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
, Vars
);
18893 class DSARefChecker
: public StmtVisitor
<DSARefChecker
, bool> {
18897 bool VisitDeclRefExpr(DeclRefExpr
*E
) {
18898 if (auto *VD
= dyn_cast
<VarDecl
>(E
->getDecl())) {
18899 DSAStackTy::DSAVarData DVar
= Stack
->getTopDSA(VD
, /*FromParent=*/false);
18900 if (DVar
.CKind
== OMPC_shared
&& !DVar
.RefExpr
)
18902 if (DVar
.CKind
!= OMPC_unknown
)
18904 DSAStackTy::DSAVarData DVarPrivate
= Stack
->hasDSA(
18906 [](OpenMPClauseKind C
, bool AppliedToPointee
, bool) {
18907 return isOpenMPPrivate(C
) && !AppliedToPointee
;
18909 [](OpenMPDirectiveKind
) { return true; },
18910 /*FromParent=*/true);
18911 return DVarPrivate
.CKind
!= OMPC_unknown
;
18915 bool VisitStmt(Stmt
*S
) {
18916 for (Stmt
*Child
: S
->children()) {
18917 if (Child
&& Visit(Child
))
18922 explicit DSARefChecker(DSAStackTy
*S
) : Stack(S
) {}
18927 // Transform MemberExpression for specified FieldDecl of current class to
18928 // DeclRefExpr to specified OMPCapturedExprDecl.
18929 class TransformExprToCaptures
: public TreeTransform
<TransformExprToCaptures
> {
18930 typedef TreeTransform
<TransformExprToCaptures
> BaseTransform
;
18931 ValueDecl
*Field
= nullptr;
18932 DeclRefExpr
*CapturedExpr
= nullptr;
18935 TransformExprToCaptures(Sema
&SemaRef
, ValueDecl
*FieldDecl
)
18936 : BaseTransform(SemaRef
), Field(FieldDecl
), CapturedExpr(nullptr) {}
18938 ExprResult
TransformMemberExpr(MemberExpr
*E
) {
18939 if (isa
<CXXThisExpr
>(E
->getBase()->IgnoreParenImpCasts()) &&
18940 E
->getMemberDecl() == Field
) {
18941 CapturedExpr
= buildCapture(SemaRef
, Field
, E
, /*WithInit=*/false);
18942 return CapturedExpr
;
18944 return BaseTransform::TransformMemberExpr(E
);
18946 DeclRefExpr
*getCapturedExpr() { return CapturedExpr
; }
18950 template <typename T
, typename U
>
18951 static T
filterLookupForUDReductionAndMapper(
18952 SmallVectorImpl
<U
> &Lookups
, const llvm::function_ref
<T(ValueDecl
*)> Gen
) {
18953 for (U
&Set
: Lookups
) {
18954 for (auto *D
: Set
) {
18955 if (T Res
= Gen(cast
<ValueDecl
>(D
)))
18962 static NamedDecl
*findAcceptableDecl(Sema
&SemaRef
, NamedDecl
*D
) {
18963 assert(!LookupResult::isVisible(SemaRef
, D
) && "not in slow case");
18965 for (auto *RD
: D
->redecls()) {
18966 // Don't bother with extra checks if we already know this one isn't visible.
18970 auto ND
= cast
<NamedDecl
>(RD
);
18971 if (LookupResult::isVisible(SemaRef
, ND
))
18979 argumentDependentLookup(Sema
&SemaRef
, const DeclarationNameInfo
&Id
,
18980 SourceLocation Loc
, QualType Ty
,
18981 SmallVectorImpl
<UnresolvedSet
<8>> &Lookups
) {
18982 // Find all of the associated namespaces and classes based on the
18983 // arguments we have.
18984 Sema::AssociatedNamespaceSet AssociatedNamespaces
;
18985 Sema::AssociatedClassSet AssociatedClasses
;
18986 OpaqueValueExpr
OVE(Loc
, Ty
, VK_LValue
);
18987 SemaRef
.FindAssociatedClassesAndNamespaces(Loc
, &OVE
, AssociatedNamespaces
,
18988 AssociatedClasses
);
18990 // C++ [basic.lookup.argdep]p3:
18991 // Let X be the lookup set produced by unqualified lookup (3.4.1)
18992 // and let Y be the lookup set produced by argument dependent
18993 // lookup (defined as follows). If X contains [...] then Y is
18994 // empty. Otherwise Y is the set of declarations found in the
18995 // namespaces associated with the argument types as described
18996 // below. The set of declarations found by the lookup of the name
18997 // is the union of X and Y.
18999 // Here, we compute Y and add its members to the overloaded
19001 for (auto *NS
: AssociatedNamespaces
) {
19002 // When considering an associated namespace, the lookup is the
19003 // same as the lookup performed when the associated namespace is
19004 // used as a qualifier (3.4.3.2) except that:
19006 // -- Any using-directives in the associated namespace are
19009 // -- Any namespace-scope friend functions declared in
19010 // associated classes are visible within their respective
19011 // namespaces even if they are not visible during an ordinary
19013 DeclContext::lookup_result R
= NS
->lookup(Id
.getName());
19014 for (auto *D
: R
) {
19015 auto *Underlying
= D
;
19016 if (auto *USD
= dyn_cast
<UsingShadowDecl
>(D
))
19017 Underlying
= USD
->getTargetDecl();
19019 if (!isa
<OMPDeclareReductionDecl
>(Underlying
) &&
19020 !isa
<OMPDeclareMapperDecl
>(Underlying
))
19023 if (!SemaRef
.isVisible(D
)) {
19024 D
= findAcceptableDecl(SemaRef
, D
);
19027 if (auto *USD
= dyn_cast
<UsingShadowDecl
>(D
))
19028 Underlying
= USD
->getTargetDecl();
19030 Lookups
.emplace_back();
19031 Lookups
.back().addDecl(Underlying
);
19037 buildDeclareReductionRef(Sema
&SemaRef
, SourceLocation Loc
, SourceRange Range
,
19038 Scope
*S
, CXXScopeSpec
&ReductionIdScopeSpec
,
19039 const DeclarationNameInfo
&ReductionId
, QualType Ty
,
19040 CXXCastPath
&BasePath
, Expr
*UnresolvedReduction
) {
19041 if (ReductionIdScopeSpec
.isInvalid())
19042 return ExprError();
19043 SmallVector
<UnresolvedSet
<8>, 4> Lookups
;
19045 LookupResult
Lookup(SemaRef
, ReductionId
, Sema::LookupOMPReductionName
);
19046 Lookup
.suppressDiagnostics();
19047 while (S
&& SemaRef
.LookupParsedName(Lookup
, S
, &ReductionIdScopeSpec
)) {
19048 NamedDecl
*D
= Lookup
.getRepresentativeDecl();
19050 S
= S
->getParent();
19051 } while (S
&& !S
->isDeclScope(D
));
19053 S
= S
->getParent();
19054 Lookups
.emplace_back();
19055 Lookups
.back().append(Lookup
.begin(), Lookup
.end());
19058 } else if (auto *ULE
=
19059 cast_or_null
<UnresolvedLookupExpr
>(UnresolvedReduction
)) {
19060 Lookups
.push_back(UnresolvedSet
<8>());
19061 Decl
*PrevD
= nullptr;
19062 for (NamedDecl
*D
: ULE
->decls()) {
19064 Lookups
.push_back(UnresolvedSet
<8>());
19065 else if (auto *DRD
= dyn_cast
<OMPDeclareReductionDecl
>(D
))
19066 Lookups
.back().addDecl(DRD
);
19070 if (SemaRef
.CurContext
->isDependentContext() || Ty
->isDependentType() ||
19071 Ty
->isInstantiationDependentType() ||
19072 Ty
->containsUnexpandedParameterPack() ||
19073 filterLookupForUDReductionAndMapper
<bool>(Lookups
, [](ValueDecl
*D
) {
19074 return !D
->isInvalidDecl() &&
19075 (D
->getType()->isDependentType() ||
19076 D
->getType()->isInstantiationDependentType() ||
19077 D
->getType()->containsUnexpandedParameterPack());
19079 UnresolvedSet
<8> ResSet
;
19080 for (const UnresolvedSet
<8> &Set
: Lookups
) {
19083 ResSet
.append(Set
.begin(), Set
.end());
19084 // The last item marks the end of all declarations at the specified scope.
19085 ResSet
.addDecl(Set
[Set
.size() - 1]);
19087 return UnresolvedLookupExpr::Create(
19088 SemaRef
.Context
, /*NamingClass=*/nullptr,
19089 ReductionIdScopeSpec
.getWithLocInContext(SemaRef
.Context
), ReductionId
,
19090 /*ADL=*/true, /*Overloaded=*/true, ResSet
.begin(), ResSet
.end());
19092 // Lookup inside the classes.
19093 // C++ [over.match.oper]p3:
19094 // For a unary operator @ with an operand of a type whose
19095 // cv-unqualified version is T1, and for a binary operator @ with
19096 // a left operand of a type whose cv-unqualified version is T1 and
19097 // a right operand of a type whose cv-unqualified version is T2,
19098 // three sets of candidate functions, designated member
19099 // candidates, non-member candidates and built-in candidates, are
19100 // constructed as follows:
19101 // -- If T1 is a complete class type or a class currently being
19102 // defined, the set of member candidates is the result of the
19103 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
19104 // the set of member candidates is empty.
19105 LookupResult
Lookup(SemaRef
, ReductionId
, Sema::LookupOMPReductionName
);
19106 Lookup
.suppressDiagnostics();
19107 if (const auto *TyRec
= Ty
->getAs
<RecordType
>()) {
19108 // Complete the type if it can be completed.
19109 // If the type is neither complete nor being defined, bail out now.
19110 if (SemaRef
.isCompleteType(Loc
, Ty
) || TyRec
->isBeingDefined() ||
19111 TyRec
->getDecl()->getDefinition()) {
19113 SemaRef
.LookupQualifiedName(Lookup
, TyRec
->getDecl());
19114 if (Lookup
.empty()) {
19115 Lookups
.emplace_back();
19116 Lookups
.back().append(Lookup
.begin(), Lookup
.end());
19121 if (SemaRef
.getLangOpts().CPlusPlus
)
19122 argumentDependentLookup(SemaRef
, ReductionId
, Loc
, Ty
, Lookups
);
19123 if (auto *VD
= filterLookupForUDReductionAndMapper
<ValueDecl
*>(
19124 Lookups
, [&SemaRef
, Ty
](ValueDecl
*D
) -> ValueDecl
* {
19125 if (!D
->isInvalidDecl() &&
19126 SemaRef
.Context
.hasSameType(D
->getType(), Ty
))
19130 return SemaRef
.BuildDeclRefExpr(VD
, VD
->getType().getNonReferenceType(),
19132 if (SemaRef
.getLangOpts().CPlusPlus
) {
19133 if (auto *VD
= filterLookupForUDReductionAndMapper
<ValueDecl
*>(
19134 Lookups
, [&SemaRef
, Ty
, Loc
](ValueDecl
*D
) -> ValueDecl
* {
19135 if (!D
->isInvalidDecl() &&
19136 SemaRef
.IsDerivedFrom(Loc
, Ty
, D
->getType()) &&
19137 !Ty
.isMoreQualifiedThan(D
->getType()))
19141 CXXBasePaths
Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
19142 /*DetectVirtual=*/false);
19143 if (SemaRef
.IsDerivedFrom(Loc
, Ty
, VD
->getType(), Paths
)) {
19144 if (!Paths
.isAmbiguous(SemaRef
.Context
.getCanonicalType(
19145 VD
->getType().getUnqualifiedType()))) {
19146 if (SemaRef
.CheckBaseClassAccess(
19147 Loc
, VD
->getType(), Ty
, Paths
.front(),
19148 /*DiagID=*/0) != Sema::AR_inaccessible
) {
19149 SemaRef
.BuildBasePathArray(Paths
, BasePath
);
19150 return SemaRef
.BuildDeclRefExpr(
19151 VD
, VD
->getType().getNonReferenceType(), VK_LValue
, Loc
);
19157 if (ReductionIdScopeSpec
.isSet()) {
19158 SemaRef
.Diag(Loc
, diag::err_omp_not_resolved_reduction_identifier
)
19160 return ExprError();
19162 return ExprEmpty();
19166 /// Data for the reduction-based clauses.
19167 struct ReductionData
{
19168 /// List of original reduction items.
19169 SmallVector
<Expr
*, 8> Vars
;
19170 /// List of private copies of the reduction items.
19171 SmallVector
<Expr
*, 8> Privates
;
19172 /// LHS expressions for the reduction_op expressions.
19173 SmallVector
<Expr
*, 8> LHSs
;
19174 /// RHS expressions for the reduction_op expressions.
19175 SmallVector
<Expr
*, 8> RHSs
;
19176 /// Reduction operation expression.
19177 SmallVector
<Expr
*, 8> ReductionOps
;
19178 /// inscan copy operation expressions.
19179 SmallVector
<Expr
*, 8> InscanCopyOps
;
19180 /// inscan copy temp array expressions for prefix sums.
19181 SmallVector
<Expr
*, 8> InscanCopyArrayTemps
;
19182 /// inscan copy temp array element expressions for prefix sums.
19183 SmallVector
<Expr
*, 8> InscanCopyArrayElems
;
19184 /// Taskgroup descriptors for the corresponding reduction items in
19185 /// in_reduction clauses.
19186 SmallVector
<Expr
*, 8> TaskgroupDescriptors
;
19187 /// List of captures for clause.
19188 SmallVector
<Decl
*, 4> ExprCaptures
;
19189 /// List of postupdate expressions.
19190 SmallVector
<Expr
*, 4> ExprPostUpdates
;
19191 /// Reduction modifier.
19192 unsigned RedModifier
= 0;
19193 ReductionData() = delete;
19194 /// Reserves required memory for the reduction data.
19195 ReductionData(unsigned Size
, unsigned Modifier
= 0) : RedModifier(Modifier
) {
19196 Vars
.reserve(Size
);
19197 Privates
.reserve(Size
);
19198 LHSs
.reserve(Size
);
19199 RHSs
.reserve(Size
);
19200 ReductionOps
.reserve(Size
);
19201 if (RedModifier
== OMPC_REDUCTION_inscan
) {
19202 InscanCopyOps
.reserve(Size
);
19203 InscanCopyArrayTemps
.reserve(Size
);
19204 InscanCopyArrayElems
.reserve(Size
);
19206 TaskgroupDescriptors
.reserve(Size
);
19207 ExprCaptures
.reserve(Size
);
19208 ExprPostUpdates
.reserve(Size
);
19210 /// Stores reduction item and reduction operation only (required for dependent
19211 /// reduction item).
19212 void push(Expr
*Item
, Expr
*ReductionOp
) {
19213 Vars
.emplace_back(Item
);
19214 Privates
.emplace_back(nullptr);
19215 LHSs
.emplace_back(nullptr);
19216 RHSs
.emplace_back(nullptr);
19217 ReductionOps
.emplace_back(ReductionOp
);
19218 TaskgroupDescriptors
.emplace_back(nullptr);
19219 if (RedModifier
== OMPC_REDUCTION_inscan
) {
19220 InscanCopyOps
.push_back(nullptr);
19221 InscanCopyArrayTemps
.push_back(nullptr);
19222 InscanCopyArrayElems
.push_back(nullptr);
19225 /// Stores reduction data.
19226 void push(Expr
*Item
, Expr
*Private
, Expr
*LHS
, Expr
*RHS
, Expr
*ReductionOp
,
19227 Expr
*TaskgroupDescriptor
, Expr
*CopyOp
, Expr
*CopyArrayTemp
,
19228 Expr
*CopyArrayElem
) {
19229 Vars
.emplace_back(Item
);
19230 Privates
.emplace_back(Private
);
19231 LHSs
.emplace_back(LHS
);
19232 RHSs
.emplace_back(RHS
);
19233 ReductionOps
.emplace_back(ReductionOp
);
19234 TaskgroupDescriptors
.emplace_back(TaskgroupDescriptor
);
19235 if (RedModifier
== OMPC_REDUCTION_inscan
) {
19236 InscanCopyOps
.push_back(CopyOp
);
19237 InscanCopyArrayTemps
.push_back(CopyArrayTemp
);
19238 InscanCopyArrayElems
.push_back(CopyArrayElem
);
19240 assert(CopyOp
== nullptr && CopyArrayTemp
== nullptr &&
19241 CopyArrayElem
== nullptr &&
19242 "Copy operation must be used for inscan reductions only.");
19248 static bool checkOMPArraySectionConstantForReduction(
19249 ASTContext
&Context
, const OMPArraySectionExpr
*OASE
, bool &SingleElement
,
19250 SmallVectorImpl
<llvm::APSInt
> &ArraySizes
) {
19251 const Expr
*Length
= OASE
->getLength();
19252 if (Length
== nullptr) {
19253 // For array sections of the form [1:] or [:], we would need to analyze
19254 // the lower bound...
19255 if (OASE
->getColonLocFirst().isValid())
19258 // This is an array subscript which has implicit length 1!
19259 SingleElement
= true;
19260 ArraySizes
.push_back(llvm::APSInt::get(1));
19262 Expr::EvalResult Result
;
19263 if (!Length
->EvaluateAsInt(Result
, Context
))
19266 llvm::APSInt ConstantLengthValue
= Result
.Val
.getInt();
19267 SingleElement
= (ConstantLengthValue
.getSExtValue() == 1);
19268 ArraySizes
.push_back(ConstantLengthValue
);
19271 // Get the base of this array section and walk up from there.
19272 const Expr
*Base
= OASE
->getBase()->IgnoreParenImpCasts();
19274 // We require length = 1 for all array sections except the right-most to
19275 // guarantee that the memory region is contiguous and has no holes in it.
19276 while (const auto *TempOASE
= dyn_cast
<OMPArraySectionExpr
>(Base
)) {
19277 Length
= TempOASE
->getLength();
19278 if (Length
== nullptr) {
19279 // For array sections of the form [1:] or [:], we would need to analyze
19280 // the lower bound...
19281 if (OASE
->getColonLocFirst().isValid())
19284 // This is an array subscript which has implicit length 1!
19285 ArraySizes
.push_back(llvm::APSInt::get(1));
19287 Expr::EvalResult Result
;
19288 if (!Length
->EvaluateAsInt(Result
, Context
))
19291 llvm::APSInt ConstantLengthValue
= Result
.Val
.getInt();
19292 if (ConstantLengthValue
.getSExtValue() != 1)
19295 ArraySizes
.push_back(ConstantLengthValue
);
19297 Base
= TempOASE
->getBase()->IgnoreParenImpCasts();
19300 // If we have a single element, we don't need to add the implicit lengths.
19301 if (!SingleElement
) {
19302 while (const auto *TempASE
= dyn_cast
<ArraySubscriptExpr
>(Base
)) {
19303 // Has implicit length 1!
19304 ArraySizes
.push_back(llvm::APSInt::get(1));
19305 Base
= TempASE
->getBase()->IgnoreParenImpCasts();
19309 // This array section can be privatized as a single value or as a constant
19314 static BinaryOperatorKind
19315 getRelatedCompoundReductionOp(BinaryOperatorKind BOK
) {
19317 return BO_AddAssign
;
19319 return BO_MulAssign
;
19321 return BO_AndAssign
;
19323 return BO_OrAssign
;
19325 return BO_XorAssign
;
19329 static bool actOnOMPReductionKindClause(
19330 Sema
&S
, DSAStackTy
*Stack
, OpenMPClauseKind ClauseKind
,
19331 ArrayRef
<Expr
*> VarList
, SourceLocation StartLoc
, SourceLocation LParenLoc
,
19332 SourceLocation ColonLoc
, SourceLocation EndLoc
,
19333 CXXScopeSpec
&ReductionIdScopeSpec
, const DeclarationNameInfo
&ReductionId
,
19334 ArrayRef
<Expr
*> UnresolvedReductions
, ReductionData
&RD
) {
19335 DeclarationName DN
= ReductionId
.getName();
19336 OverloadedOperatorKind OOK
= DN
.getCXXOverloadedOperator();
19337 BinaryOperatorKind BOK
= BO_Comma
;
19339 ASTContext
&Context
= S
.Context
;
19340 // OpenMP [2.14.3.6, reduction clause]
19342 // reduction-identifier is either an identifier or one of the following
19343 // operators: +, -, *, &, |, ^, && and ||
19345 // reduction-identifier is either an id-expression or one of the following
19346 // operators: +, -, *, &, |, ^, && and ||
19352 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
19353 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
19354 // reduction identifier.
19355 if (S
.LangOpts
.OpenMP
> 52)
19381 case OO_Array_Delete
:
19390 case OO_GreaterEqual
:
19392 case OO_MinusEqual
:
19394 case OO_SlashEqual
:
19395 case OO_PercentEqual
:
19396 case OO_CaretEqual
:
19400 case OO_GreaterGreater
:
19401 case OO_LessLessEqual
:
19402 case OO_GreaterGreaterEqual
:
19403 case OO_EqualEqual
:
19404 case OO_ExclaimEqual
:
19407 case OO_MinusMinus
:
19413 case OO_Conditional
:
19415 case NUM_OVERLOADED_OPERATORS
:
19416 llvm_unreachable("Unexpected reduction identifier");
19418 if (IdentifierInfo
*II
= DN
.getAsIdentifierInfo()) {
19419 if (II
->isStr("max"))
19421 else if (II
->isStr("min"))
19427 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
19428 // A reduction clause with the minus (-) operator was deprecated
19429 if (OOK
== OO_Minus
&& S
.LangOpts
.OpenMP
== 52)
19430 S
.Diag(ReductionId
.getLoc(), diag::warn_omp_minus_in_reduction_deprecated
);
19432 SourceRange ReductionIdRange
;
19433 if (ReductionIdScopeSpec
.isValid())
19434 ReductionIdRange
.setBegin(ReductionIdScopeSpec
.getBeginLoc());
19436 ReductionIdRange
.setBegin(ReductionId
.getBeginLoc());
19437 ReductionIdRange
.setEnd(ReductionId
.getEndLoc());
19439 auto IR
= UnresolvedReductions
.begin(), ER
= UnresolvedReductions
.end();
19440 bool FirstIter
= true;
19441 for (Expr
*RefExpr
: VarList
) {
19442 assert(RefExpr
&& "nullptr expr in OpenMP reduction clause.");
19443 // OpenMP [2.1, C/C++]
19444 // A list item is a variable or array section, subject to the restrictions
19445 // specified in Section 2.4 on page 42 and in each of the sections
19446 // describing clauses and directives for which a list appears.
19447 // OpenMP [2.14.3.3, Restrictions, p.1]
19448 // A variable that is part of another variable (as an array or
19449 // structure element) cannot appear in a private clause.
19450 if (!FirstIter
&& IR
!= ER
)
19453 SourceLocation ELoc
;
19454 SourceRange ERange
;
19455 Expr
*SimpleRefExpr
= RefExpr
;
19456 auto Res
= getPrivateItem(S
, SimpleRefExpr
, ELoc
, ERange
,
19457 /*AllowArraySection=*/true);
19459 // Try to find 'declare reduction' corresponding construct before using
19460 // builtin/overloaded operators.
19461 QualType Type
= Context
.DependentTy
;
19462 CXXCastPath BasePath
;
19463 ExprResult DeclareReductionRef
= buildDeclareReductionRef(
19464 S
, ELoc
, ERange
, Stack
->getCurScope(), ReductionIdScopeSpec
,
19465 ReductionId
, Type
, BasePath
, IR
== ER
? nullptr : *IR
);
19466 Expr
*ReductionOp
= nullptr;
19467 if (S
.CurContext
->isDependentContext() &&
19468 (DeclareReductionRef
.isUnset() ||
19469 isa
<UnresolvedLookupExpr
>(DeclareReductionRef
.get())))
19470 ReductionOp
= DeclareReductionRef
.get();
19471 // It will be analyzed later.
19472 RD
.push(RefExpr
, ReductionOp
);
19474 ValueDecl
*D
= Res
.first
;
19478 Expr
*TaskgroupDescriptor
= nullptr;
19480 auto *ASE
= dyn_cast
<ArraySubscriptExpr
>(RefExpr
->IgnoreParens());
19481 auto *OASE
= dyn_cast
<OMPArraySectionExpr
>(RefExpr
->IgnoreParens());
19483 Type
= ASE
->getType().getNonReferenceType();
19485 QualType BaseType
=
19486 OMPArraySectionExpr::getBaseOriginalType(OASE
->getBase());
19487 if (const auto *ATy
= BaseType
->getAsArrayTypeUnsafe())
19488 Type
= ATy
->getElementType();
19490 Type
= BaseType
->getPointeeType();
19491 Type
= Type
.getNonReferenceType();
19493 Type
= Context
.getBaseElementType(D
->getType().getNonReferenceType());
19495 auto *VD
= dyn_cast
<VarDecl
>(D
);
19497 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19498 // A variable that appears in a private clause must not have an incomplete
19499 // type or a reference type.
19500 if (S
.RequireCompleteType(ELoc
, D
->getType(),
19501 diag::err_omp_reduction_incomplete_type
))
19503 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19504 // A list item that appears in a reduction clause must not be
19505 // const-qualified.
19506 if (rejectConstNotMutableType(S
, D
, Type
, ClauseKind
, ELoc
,
19507 /*AcceptIfMutable*/ false, ASE
|| OASE
))
19510 OpenMPDirectiveKind CurrDir
= Stack
->getCurrentDirective();
19511 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
19512 // If a list-item is a reference type then it must bind to the same object
19513 // for all threads of the team.
19514 if (!ASE
&& !OASE
) {
19516 VarDecl
*VDDef
= VD
->getDefinition();
19517 if (VD
->getType()->isReferenceType() && VDDef
&& VDDef
->hasInit()) {
19518 DSARefChecker
Check(Stack
);
19519 if (Check
.Visit(VDDef
->getInit())) {
19520 S
.Diag(ELoc
, diag::err_omp_reduction_ref_type_arg
)
19521 << getOpenMPClauseName(ClauseKind
) << ERange
;
19522 S
.Diag(VDDef
->getLocation(), diag::note_defined_here
) << VDDef
;
19528 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
19530 // Variables with the predetermined data-sharing attributes may not be
19531 // listed in data-sharing attributes clauses, except for the cases
19532 // listed below. For these exceptions only, listing a predetermined
19533 // variable in a data-sharing attribute clause is allowed and overrides
19534 // the variable's predetermined data-sharing attributes.
19535 // OpenMP [2.14.3.6, Restrictions, p.3]
19536 // Any number of reduction clauses can be specified on the directive,
19537 // but a list item can appear only once in the reduction clauses for that
19539 DSAStackTy::DSAVarData DVar
= Stack
->getTopDSA(D
, /*FromParent=*/false);
19540 if (DVar
.CKind
== OMPC_reduction
) {
19541 S
.Diag(ELoc
, diag::err_omp_once_referenced
)
19542 << getOpenMPClauseName(ClauseKind
);
19544 S
.Diag(DVar
.RefExpr
->getExprLoc(), diag::note_omp_referenced
);
19547 if (DVar
.CKind
!= OMPC_unknown
) {
19548 S
.Diag(ELoc
, diag::err_omp_wrong_dsa
)
19549 << getOpenMPClauseName(DVar
.CKind
)
19550 << getOpenMPClauseName(OMPC_reduction
);
19551 reportOriginalDsa(S
, Stack
, D
, DVar
);
19555 // OpenMP [2.14.3.6, Restrictions, p.1]
19556 // A list item that appears in a reduction clause of a worksharing
19557 // construct must be shared in the parallel regions to which any of the
19558 // worksharing regions arising from the worksharing construct bind.
19559 if (isOpenMPWorksharingDirective(CurrDir
) &&
19560 !isOpenMPParallelDirective(CurrDir
) &&
19561 !isOpenMPTeamsDirective(CurrDir
)) {
19562 DVar
= Stack
->getImplicitDSA(D
, true);
19563 if (DVar
.CKind
!= OMPC_shared
) {
19564 S
.Diag(ELoc
, diag::err_omp_required_access
)
19565 << getOpenMPClauseName(OMPC_reduction
)
19566 << getOpenMPClauseName(OMPC_shared
);
19567 reportOriginalDsa(S
, Stack
, D
, DVar
);
19572 // Threadprivates cannot be shared between threads, so dignose if the base
19573 // is a threadprivate variable.
19574 DSAStackTy::DSAVarData DVar
= Stack
->getTopDSA(D
, /*FromParent=*/false);
19575 if (DVar
.CKind
== OMPC_threadprivate
) {
19576 S
.Diag(ELoc
, diag::err_omp_wrong_dsa
)
19577 << getOpenMPClauseName(DVar
.CKind
)
19578 << getOpenMPClauseName(OMPC_reduction
);
19579 reportOriginalDsa(S
, Stack
, D
, DVar
);
19584 // Try to find 'declare reduction' corresponding construct before using
19585 // builtin/overloaded operators.
19586 CXXCastPath BasePath
;
19587 ExprResult DeclareReductionRef
= buildDeclareReductionRef(
19588 S
, ELoc
, ERange
, Stack
->getCurScope(), ReductionIdScopeSpec
,
19589 ReductionId
, Type
, BasePath
, IR
== ER
? nullptr : *IR
);
19590 if (DeclareReductionRef
.isInvalid())
19592 if (S
.CurContext
->isDependentContext() &&
19593 (DeclareReductionRef
.isUnset() ||
19594 isa
<UnresolvedLookupExpr
>(DeclareReductionRef
.get()))) {
19595 RD
.push(RefExpr
, DeclareReductionRef
.get());
19598 if (BOK
== BO_Comma
&& DeclareReductionRef
.isUnset()) {
19599 // Not allowed reduction identifier is found.
19600 if (S
.LangOpts
.OpenMP
> 52)
19601 S
.Diag(ReductionId
.getBeginLoc(),
19602 diag::err_omp_unknown_reduction_identifier_since_omp_6_0
)
19603 << Type
<< ReductionIdRange
;
19605 S
.Diag(ReductionId
.getBeginLoc(),
19606 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0
)
19607 << Type
<< ReductionIdRange
;
19611 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19612 // The type of a list item that appears in a reduction clause must be valid
19613 // for the reduction-identifier. For a max or min reduction in C, the type
19614 // of the list item must be an allowed arithmetic data type: char, int,
19615 // float, double, or _Bool, possibly modified with long, short, signed, or
19616 // unsigned. For a max or min reduction in C++, the type of the list item
19617 // must be an allowed arithmetic data type: char, wchar_t, int, float,
19618 // double, or bool, possibly modified with long, short, signed, or unsigned.
19619 if (DeclareReductionRef
.isUnset()) {
19620 if ((BOK
== BO_GT
|| BOK
== BO_LT
) &&
19621 !(Type
->isScalarType() ||
19622 (S
.getLangOpts().CPlusPlus
&& Type
->isArithmeticType()))) {
19623 S
.Diag(ELoc
, diag::err_omp_clause_not_arithmetic_type_arg
)
19624 << getOpenMPClauseName(ClauseKind
) << S
.getLangOpts().CPlusPlus
;
19625 if (!ASE
&& !OASE
) {
19626 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
19627 VarDecl::DeclarationOnly
;
19628 S
.Diag(D
->getLocation(),
19629 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
19634 if ((BOK
== BO_OrAssign
|| BOK
== BO_AndAssign
|| BOK
== BO_XorAssign
) &&
19635 !S
.getLangOpts().CPlusPlus
&& Type
->isFloatingType()) {
19636 S
.Diag(ELoc
, diag::err_omp_clause_floating_type_arg
)
19637 << getOpenMPClauseName(ClauseKind
);
19638 if (!ASE
&& !OASE
) {
19639 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
19640 VarDecl::DeclarationOnly
;
19641 S
.Diag(D
->getLocation(),
19642 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
19649 Type
= Type
.getNonLValueExprType(Context
).getUnqualifiedType();
19650 VarDecl
*LHSVD
= buildVarDecl(S
, ELoc
, Type
, ".reduction.lhs",
19651 D
->hasAttrs() ? &D
->getAttrs() : nullptr);
19652 VarDecl
*RHSVD
= buildVarDecl(S
, ELoc
, Type
, D
->getName(),
19653 D
->hasAttrs() ? &D
->getAttrs() : nullptr);
19654 QualType PrivateTy
= Type
;
19656 // Try if we can determine constant lengths for all array sections and avoid
19658 bool ConstantLengthOASE
= false;
19660 bool SingleElement
;
19661 llvm::SmallVector
<llvm::APSInt
, 4> ArraySizes
;
19662 ConstantLengthOASE
= checkOMPArraySectionConstantForReduction(
19663 Context
, OASE
, SingleElement
, ArraySizes
);
19665 // If we don't have a single element, we must emit a constant array type.
19666 if (ConstantLengthOASE
&& !SingleElement
) {
19667 for (llvm::APSInt
&Size
: ArraySizes
)
19668 PrivateTy
= Context
.getConstantArrayType(PrivateTy
, Size
, nullptr,
19669 ArraySizeModifier::Normal
,
19670 /*IndexTypeQuals=*/0);
19674 if ((OASE
&& !ConstantLengthOASE
) ||
19676 D
->getType().getNonReferenceType()->isVariablyModifiedType())) {
19677 if (!Context
.getTargetInfo().isVLASupported()) {
19678 if (isOpenMPTargetExecutionDirective(Stack
->getCurrentDirective())) {
19679 S
.Diag(ELoc
, diag::err_omp_reduction_vla_unsupported
) << !!OASE
;
19680 S
.Diag(ELoc
, diag::note_vla_unsupported
);
19683 S
.targetDiag(ELoc
, diag::err_omp_reduction_vla_unsupported
) << !!OASE
;
19684 S
.targetDiag(ELoc
, diag::note_vla_unsupported
);
19687 // For arrays/array sections only:
19688 // Create pseudo array type for private copy. The size for this array will
19689 // be generated during codegen.
19690 // For array subscripts or single variables Private Ty is the same as Type
19691 // (type of the variable or single array element).
19692 PrivateTy
= Context
.getVariableArrayType(
19695 OpaqueValueExpr(ELoc
, Context
.getSizeType(), VK_PRValue
),
19696 ArraySizeModifier::Normal
, /*IndexTypeQuals=*/0, SourceRange());
19697 } else if (!ASE
&& !OASE
&&
19698 Context
.getAsArrayType(D
->getType().getNonReferenceType())) {
19699 PrivateTy
= D
->getType().getNonReferenceType();
19702 VarDecl
*PrivateVD
=
19703 buildVarDecl(S
, ELoc
, PrivateTy
, D
->getName(),
19704 D
->hasAttrs() ? &D
->getAttrs() : nullptr,
19705 VD
? cast
<DeclRefExpr
>(SimpleRefExpr
) : nullptr);
19706 // Add initializer for private variable.
19707 Expr
*Init
= nullptr;
19708 DeclRefExpr
*LHSDRE
= buildDeclRefExpr(S
, LHSVD
, Type
, ELoc
);
19709 DeclRefExpr
*RHSDRE
= buildDeclRefExpr(S
, RHSVD
, Type
, ELoc
);
19710 if (DeclareReductionRef
.isUsable()) {
19711 auto *DRDRef
= DeclareReductionRef
.getAs
<DeclRefExpr
>();
19712 auto *DRD
= cast
<OMPDeclareReductionDecl
>(DRDRef
->getDecl());
19713 if (DRD
->getInitializer()) {
19715 RHSVD
->setInit(DRDRef
);
19716 RHSVD
->setInitStyle(VarDecl::CallInit
);
19724 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
19725 if (Type
->isScalarType() || Type
->isAnyComplexType())
19726 Init
= S
.ActOnIntegerConstant(ELoc
, /*Val=*/0).get();
19730 if (Type
->isScalarType() || Type
->isAnyComplexType()) {
19731 // '*' and '&&' reduction ops - initializer is '1'.
19732 Init
= S
.ActOnIntegerConstant(ELoc
, /*Val=*/1).get();
19736 // '&' reduction op - initializer is '~0'.
19737 QualType OrigType
= Type
;
19738 if (auto *ComplexTy
= OrigType
->getAs
<ComplexType
>())
19739 Type
= ComplexTy
->getElementType();
19740 if (Type
->isRealFloatingType()) {
19741 llvm::APFloat InitValue
= llvm::APFloat::getAllOnesValue(
19742 Context
.getFloatTypeSemantics(Type
));
19743 Init
= FloatingLiteral::Create(Context
, InitValue
, /*isexact=*/true,
19745 } else if (Type
->isScalarType()) {
19746 uint64_t Size
= Context
.getTypeSize(Type
);
19747 QualType IntTy
= Context
.getIntTypeForBitwidth(Size
, /*Signed=*/0);
19748 llvm::APInt InitValue
= llvm::APInt::getAllOnes(Size
);
19749 Init
= IntegerLiteral::Create(Context
, InitValue
, IntTy
, ELoc
);
19751 if (Init
&& OrigType
->isAnyComplexType()) {
19752 // Init = 0xFFFF + 0xFFFFi;
19753 auto *Im
= new (Context
) ImaginaryLiteral(Init
, OrigType
);
19754 Init
= S
.CreateBuiltinBinOp(ELoc
, BO_Add
, Init
, Im
).get();
19761 // 'min' reduction op - initializer is 'Largest representable number in
19762 // the reduction list item type'.
19763 // 'max' reduction op - initializer is 'Least representable number in
19764 // the reduction list item type'.
19765 if (Type
->isIntegerType() || Type
->isPointerType()) {
19766 bool IsSigned
= Type
->hasSignedIntegerRepresentation();
19767 uint64_t Size
= Context
.getTypeSize(Type
);
19769 Context
.getIntTypeForBitwidth(Size
, /*Signed=*/IsSigned
);
19770 llvm::APInt InitValue
=
19771 (BOK
!= BO_LT
) ? IsSigned
? llvm::APInt::getSignedMinValue(Size
)
19772 : llvm::APInt::getMinValue(Size
)
19773 : IsSigned
? llvm::APInt::getSignedMaxValue(Size
)
19774 : llvm::APInt::getMaxValue(Size
);
19775 Init
= IntegerLiteral::Create(Context
, InitValue
, IntTy
, ELoc
);
19776 if (Type
->isPointerType()) {
19777 // Cast to pointer type.
19778 ExprResult CastExpr
= S
.BuildCStyleCastExpr(
19779 ELoc
, Context
.getTrivialTypeSourceInfo(Type
, ELoc
), ELoc
, Init
);
19780 if (CastExpr
.isInvalid())
19782 Init
= CastExpr
.get();
19784 } else if (Type
->isRealFloatingType()) {
19785 llvm::APFloat InitValue
= llvm::APFloat::getLargest(
19786 Context
.getFloatTypeSemantics(Type
), BOK
!= BO_LT
);
19787 Init
= FloatingLiteral::Create(Context
, InitValue
, /*isexact=*/true,
19816 llvm_unreachable("Unexpected reduction operation");
19819 if (Init
&& DeclareReductionRef
.isUnset()) {
19820 S
.AddInitializerToDecl(RHSVD
, Init
, /*DirectInit=*/false);
19821 // Store initializer for single element in private copy. Will be used
19823 PrivateVD
->setInit(RHSVD
->getInit());
19824 PrivateVD
->setInitStyle(RHSVD
->getInitStyle());
19825 } else if (!Init
) {
19826 S
.ActOnUninitializedDecl(RHSVD
);
19827 // Store initializer for single element in private copy. Will be used
19829 PrivateVD
->setInit(RHSVD
->getInit());
19830 PrivateVD
->setInitStyle(RHSVD
->getInitStyle());
19832 if (RHSVD
->isInvalidDecl())
19834 if (!RHSVD
->hasInit() && DeclareReductionRef
.isUnset()) {
19835 S
.Diag(ELoc
, diag::err_omp_reduction_id_not_compatible
)
19836 << Type
<< ReductionIdRange
;
19837 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
19838 VarDecl::DeclarationOnly
;
19839 S
.Diag(D
->getLocation(),
19840 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
19844 DeclRefExpr
*PrivateDRE
= buildDeclRefExpr(S
, PrivateVD
, PrivateTy
, ELoc
);
19845 ExprResult ReductionOp
;
19846 if (DeclareReductionRef
.isUsable()) {
19847 QualType RedTy
= DeclareReductionRef
.get()->getType();
19848 QualType PtrRedTy
= Context
.getPointerType(RedTy
);
19849 ExprResult LHS
= S
.CreateBuiltinUnaryOp(ELoc
, UO_AddrOf
, LHSDRE
);
19850 ExprResult RHS
= S
.CreateBuiltinUnaryOp(ELoc
, UO_AddrOf
, RHSDRE
);
19851 if (!BasePath
.empty()) {
19852 LHS
= S
.DefaultLvalueConversion(LHS
.get());
19853 RHS
= S
.DefaultLvalueConversion(RHS
.get());
19854 LHS
= ImplicitCastExpr::Create(
19855 Context
, PtrRedTy
, CK_UncheckedDerivedToBase
, LHS
.get(), &BasePath
,
19856 LHS
.get()->getValueKind(), FPOptionsOverride());
19857 RHS
= ImplicitCastExpr::Create(
19858 Context
, PtrRedTy
, CK_UncheckedDerivedToBase
, RHS
.get(), &BasePath
,
19859 RHS
.get()->getValueKind(), FPOptionsOverride());
19861 FunctionProtoType::ExtProtoInfo EPI
;
19862 QualType Params
[] = {PtrRedTy
, PtrRedTy
};
19863 QualType FnTy
= Context
.getFunctionType(Context
.VoidTy
, Params
, EPI
);
19864 auto *OVE
= new (Context
) OpaqueValueExpr(
19865 ELoc
, Context
.getPointerType(FnTy
), VK_PRValue
, OK_Ordinary
,
19866 S
.DefaultLvalueConversion(DeclareReductionRef
.get()).get());
19867 Expr
*Args
[] = {LHS
.get(), RHS
.get()};
19869 CallExpr::Create(Context
, OVE
, Args
, Context
.VoidTy
, VK_PRValue
, ELoc
,
19870 S
.CurFPFeatureOverrides());
19872 BinaryOperatorKind CombBOK
= getRelatedCompoundReductionOp(BOK
);
19873 if (Type
->isRecordType() && CombBOK
!= BOK
) {
19874 Sema::TentativeAnalysisScope
Trap(S
);
19876 S
.BuildBinOp(Stack
->getCurScope(), ReductionId
.getBeginLoc(),
19877 CombBOK
, LHSDRE
, RHSDRE
);
19879 if (!ReductionOp
.isUsable()) {
19881 S
.BuildBinOp(Stack
->getCurScope(), ReductionId
.getBeginLoc(), BOK
,
19883 if (ReductionOp
.isUsable()) {
19884 if (BOK
!= BO_LT
&& BOK
!= BO_GT
) {
19886 S
.BuildBinOp(Stack
->getCurScope(), ReductionId
.getBeginLoc(),
19887 BO_Assign
, LHSDRE
, ReductionOp
.get());
19889 auto *ConditionalOp
= new (Context
)
19890 ConditionalOperator(ReductionOp
.get(), ELoc
, LHSDRE
, ELoc
,
19891 RHSDRE
, Type
, VK_LValue
, OK_Ordinary
);
19893 S
.BuildBinOp(Stack
->getCurScope(), ReductionId
.getBeginLoc(),
19894 BO_Assign
, LHSDRE
, ConditionalOp
);
19898 if (ReductionOp
.isUsable())
19899 ReductionOp
= S
.ActOnFinishFullExpr(ReductionOp
.get(),
19900 /*DiscardedValue*/ false);
19901 if (!ReductionOp
.isUsable())
19905 // Add copy operations for inscan reductions.
19907 ExprResult CopyOpRes
, TempArrayRes
, TempArrayElem
;
19908 if (ClauseKind
== OMPC_reduction
&&
19909 RD
.RedModifier
== OMPC_REDUCTION_inscan
) {
19910 ExprResult RHS
= S
.DefaultLvalueConversion(RHSDRE
);
19911 CopyOpRes
= S
.BuildBinOp(Stack
->getCurScope(), ELoc
, BO_Assign
, LHSDRE
,
19913 if (!CopyOpRes
.isUsable())
19916 S
.ActOnFinishFullExpr(CopyOpRes
.get(), /*DiscardedValue=*/true);
19917 if (!CopyOpRes
.isUsable())
19919 // For simd directive and simd-based directives in simd mode no need to
19920 // construct temp array, need just a single temp element.
19921 if (Stack
->getCurrentDirective() == OMPD_simd
||
19922 (S
.getLangOpts().OpenMPSimd
&&
19923 isOpenMPSimdDirective(Stack
->getCurrentDirective()))) {
19924 VarDecl
*TempArrayVD
=
19925 buildVarDecl(S
, ELoc
, PrivateTy
, D
->getName(),
19926 D
->hasAttrs() ? &D
->getAttrs() : nullptr);
19927 // Add a constructor to the temp decl.
19928 S
.ActOnUninitializedDecl(TempArrayVD
);
19929 TempArrayRes
= buildDeclRefExpr(S
, TempArrayVD
, PrivateTy
, ELoc
);
19931 // Build temp array for prefix sum.
19932 auto *Dim
= new (S
.Context
)
19933 OpaqueValueExpr(ELoc
, S
.Context
.getSizeType(), VK_PRValue
);
19934 QualType ArrayTy
= S
.Context
.getVariableArrayType(
19935 PrivateTy
, Dim
, ArraySizeModifier::Normal
,
19936 /*IndexTypeQuals=*/0, {ELoc
, ELoc
});
19937 VarDecl
*TempArrayVD
=
19938 buildVarDecl(S
, ELoc
, ArrayTy
, D
->getName(),
19939 D
->hasAttrs() ? &D
->getAttrs() : nullptr);
19940 // Add a constructor to the temp decl.
19941 S
.ActOnUninitializedDecl(TempArrayVD
);
19942 TempArrayRes
= buildDeclRefExpr(S
, TempArrayVD
, ArrayTy
, ELoc
);
19944 S
.DefaultFunctionArrayLvalueConversion(TempArrayRes
.get());
19945 auto *Idx
= new (S
.Context
)
19946 OpaqueValueExpr(ELoc
, S
.Context
.getSizeType(), VK_PRValue
);
19947 TempArrayElem
= S
.CreateBuiltinArraySubscriptExpr(TempArrayElem
.get(),
19952 // OpenMP [2.15.4.6, Restrictions, p.2]
19953 // A list item that appears in an in_reduction clause of a task construct
19954 // must appear in a task_reduction clause of a construct associated with a
19955 // taskgroup region that includes the participating task in its taskgroup
19956 // set. The construct associated with the innermost region that meets this
19957 // condition must specify the same reduction-identifier as the in_reduction
19959 if (ClauseKind
== OMPC_in_reduction
) {
19960 SourceRange ParentSR
;
19961 BinaryOperatorKind ParentBOK
;
19962 const Expr
*ParentReductionOp
= nullptr;
19963 Expr
*ParentBOKTD
= nullptr, *ParentReductionOpTD
= nullptr;
19964 DSAStackTy::DSAVarData ParentBOKDSA
=
19965 Stack
->getTopMostTaskgroupReductionData(D
, ParentSR
, ParentBOK
,
19967 DSAStackTy::DSAVarData ParentReductionOpDSA
=
19968 Stack
->getTopMostTaskgroupReductionData(
19969 D
, ParentSR
, ParentReductionOp
, ParentReductionOpTD
);
19970 bool IsParentBOK
= ParentBOKDSA
.DKind
!= OMPD_unknown
;
19971 bool IsParentReductionOp
= ParentReductionOpDSA
.DKind
!= OMPD_unknown
;
19972 if ((DeclareReductionRef
.isUnset() && IsParentReductionOp
) ||
19973 (DeclareReductionRef
.isUsable() && IsParentBOK
) ||
19974 (IsParentBOK
&& BOK
!= ParentBOK
) || IsParentReductionOp
) {
19975 bool EmitError
= true;
19976 if (IsParentReductionOp
&& DeclareReductionRef
.isUsable()) {
19977 llvm::FoldingSetNodeID RedId
, ParentRedId
;
19978 ParentReductionOp
->Profile(ParentRedId
, Context
, /*Canonical=*/true);
19979 DeclareReductionRef
.get()->Profile(RedId
, Context
,
19980 /*Canonical=*/true);
19981 EmitError
= RedId
!= ParentRedId
;
19984 S
.Diag(ReductionId
.getBeginLoc(),
19985 diag::err_omp_reduction_identifier_mismatch
)
19986 << ReductionIdRange
<< RefExpr
->getSourceRange();
19987 S
.Diag(ParentSR
.getBegin(),
19988 diag::note_omp_previous_reduction_identifier
)
19990 << (IsParentBOK
? ParentBOKDSA
.RefExpr
19991 : ParentReductionOpDSA
.RefExpr
)
19992 ->getSourceRange();
19996 TaskgroupDescriptor
= IsParentBOK
? ParentBOKTD
: ParentReductionOpTD
;
19999 DeclRefExpr
*Ref
= nullptr;
20000 Expr
*VarsExpr
= RefExpr
->IgnoreParens();
20001 if (!VD
&& !S
.CurContext
->isDependentContext()) {
20003 TransformExprToCaptures
RebuildToCapture(S
, D
);
20005 RebuildToCapture
.TransformExpr(RefExpr
->IgnoreParens()).get();
20006 Ref
= RebuildToCapture
.getCapturedExpr();
20008 VarsExpr
= Ref
= buildCapture(S
, D
, SimpleRefExpr
, /*WithInit=*/false);
20010 if (!S
.isOpenMPCapturedDecl(D
)) {
20011 RD
.ExprCaptures
.emplace_back(Ref
->getDecl());
20012 if (Ref
->getDecl()->hasAttr
<OMPCaptureNoInitAttr
>()) {
20013 ExprResult RefRes
= S
.DefaultLvalueConversion(Ref
);
20014 if (!RefRes
.isUsable())
20016 ExprResult PostUpdateRes
=
20017 S
.BuildBinOp(Stack
->getCurScope(), ELoc
, BO_Assign
, SimpleRefExpr
,
20019 if (!PostUpdateRes
.isUsable())
20021 if (isOpenMPTaskingDirective(Stack
->getCurrentDirective()) ||
20022 Stack
->getCurrentDirective() == OMPD_taskgroup
) {
20023 S
.Diag(RefExpr
->getExprLoc(),
20024 diag::err_omp_reduction_non_addressable_expression
)
20025 << RefExpr
->getSourceRange();
20028 RD
.ExprPostUpdates
.emplace_back(
20029 S
.IgnoredValueConversions(PostUpdateRes
.get()).get());
20033 // All reduction items are still marked as reduction (to do not increase
20034 // code base size).
20035 unsigned Modifier
= RD
.RedModifier
;
20036 // Consider task_reductions as reductions with task modifier. Required for
20037 // correct analysis of in_reduction clauses.
20038 if (CurrDir
== OMPD_taskgroup
&& ClauseKind
== OMPC_task_reduction
)
20039 Modifier
= OMPC_REDUCTION_task
;
20040 Stack
->addDSA(D
, RefExpr
->IgnoreParens(), OMPC_reduction
, Ref
, Modifier
,
20042 if (Modifier
== OMPC_REDUCTION_task
&&
20043 (CurrDir
== OMPD_taskgroup
||
20044 ((isOpenMPParallelDirective(CurrDir
) ||
20045 isOpenMPWorksharingDirective(CurrDir
)) &&
20046 !isOpenMPSimdDirective(CurrDir
)))) {
20047 if (DeclareReductionRef
.isUsable())
20048 Stack
->addTaskgroupReductionData(D
, ReductionIdRange
,
20049 DeclareReductionRef
.get());
20051 Stack
->addTaskgroupReductionData(D
, ReductionIdRange
, BOK
);
20053 RD
.push(VarsExpr
, PrivateDRE
, LHSDRE
, RHSDRE
, ReductionOp
.get(),
20054 TaskgroupDescriptor
, CopyOpRes
.get(), TempArrayRes
.get(),
20055 TempArrayElem
.get());
20057 return RD
.Vars
.empty();
20060 OMPClause
*Sema::ActOnOpenMPReductionClause(
20061 ArrayRef
<Expr
*> VarList
, OpenMPReductionClauseModifier Modifier
,
20062 SourceLocation StartLoc
, SourceLocation LParenLoc
,
20063 SourceLocation ModifierLoc
, SourceLocation ColonLoc
, SourceLocation EndLoc
,
20064 CXXScopeSpec
&ReductionIdScopeSpec
, const DeclarationNameInfo
&ReductionId
,
20065 ArrayRef
<Expr
*> UnresolvedReductions
) {
20066 if (ModifierLoc
.isValid() && Modifier
== OMPC_REDUCTION_unknown
) {
20067 Diag(LParenLoc
, diag::err_omp_unexpected_clause_value
)
20068 << getListOfPossibleValues(OMPC_reduction
, /*First=*/0,
20069 /*Last=*/OMPC_REDUCTION_unknown
)
20070 << getOpenMPClauseName(OMPC_reduction
);
20073 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
20074 // A reduction clause with the inscan reduction-modifier may only appear on a
20075 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
20076 // construct, a parallel worksharing-loop construct or a parallel
20077 // worksharing-loop SIMD construct.
20078 if (Modifier
== OMPC_REDUCTION_inscan
&&
20079 (DSAStack
->getCurrentDirective() != OMPD_for
&&
20080 DSAStack
->getCurrentDirective() != OMPD_for_simd
&&
20081 DSAStack
->getCurrentDirective() != OMPD_simd
&&
20082 DSAStack
->getCurrentDirective() != OMPD_parallel_for
&&
20083 DSAStack
->getCurrentDirective() != OMPD_parallel_for_simd
)) {
20084 Diag(ModifierLoc
, diag::err_omp_wrong_inscan_reduction
);
20088 ReductionData
RD(VarList
.size(), Modifier
);
20089 if (actOnOMPReductionKindClause(*this, DSAStack
, OMPC_reduction
, VarList
,
20090 StartLoc
, LParenLoc
, ColonLoc
, EndLoc
,
20091 ReductionIdScopeSpec
, ReductionId
,
20092 UnresolvedReductions
, RD
))
20095 return OMPReductionClause::Create(
20096 Context
, StartLoc
, LParenLoc
, ModifierLoc
, ColonLoc
, EndLoc
, Modifier
,
20097 RD
.Vars
, ReductionIdScopeSpec
.getWithLocInContext(Context
), ReductionId
,
20098 RD
.Privates
, RD
.LHSs
, RD
.RHSs
, RD
.ReductionOps
, RD
.InscanCopyOps
,
20099 RD
.InscanCopyArrayTemps
, RD
.InscanCopyArrayElems
,
20100 buildPreInits(Context
, RD
.ExprCaptures
),
20101 buildPostUpdate(*this, RD
.ExprPostUpdates
));
20104 OMPClause
*Sema::ActOnOpenMPTaskReductionClause(
20105 ArrayRef
<Expr
*> VarList
, SourceLocation StartLoc
, SourceLocation LParenLoc
,
20106 SourceLocation ColonLoc
, SourceLocation EndLoc
,
20107 CXXScopeSpec
&ReductionIdScopeSpec
, const DeclarationNameInfo
&ReductionId
,
20108 ArrayRef
<Expr
*> UnresolvedReductions
) {
20109 ReductionData
RD(VarList
.size());
20110 if (actOnOMPReductionKindClause(*this, DSAStack
, OMPC_task_reduction
, VarList
,
20111 StartLoc
, LParenLoc
, ColonLoc
, EndLoc
,
20112 ReductionIdScopeSpec
, ReductionId
,
20113 UnresolvedReductions
, RD
))
20116 return OMPTaskReductionClause::Create(
20117 Context
, StartLoc
, LParenLoc
, ColonLoc
, EndLoc
, RD
.Vars
,
20118 ReductionIdScopeSpec
.getWithLocInContext(Context
), ReductionId
,
20119 RD
.Privates
, RD
.LHSs
, RD
.RHSs
, RD
.ReductionOps
,
20120 buildPreInits(Context
, RD
.ExprCaptures
),
20121 buildPostUpdate(*this, RD
.ExprPostUpdates
));
20124 OMPClause
*Sema::ActOnOpenMPInReductionClause(
20125 ArrayRef
<Expr
*> VarList
, SourceLocation StartLoc
, SourceLocation LParenLoc
,
20126 SourceLocation ColonLoc
, SourceLocation EndLoc
,
20127 CXXScopeSpec
&ReductionIdScopeSpec
, const DeclarationNameInfo
&ReductionId
,
20128 ArrayRef
<Expr
*> UnresolvedReductions
) {
20129 ReductionData
RD(VarList
.size());
20130 if (actOnOMPReductionKindClause(*this, DSAStack
, OMPC_in_reduction
, VarList
,
20131 StartLoc
, LParenLoc
, ColonLoc
, EndLoc
,
20132 ReductionIdScopeSpec
, ReductionId
,
20133 UnresolvedReductions
, RD
))
20136 return OMPInReductionClause::Create(
20137 Context
, StartLoc
, LParenLoc
, ColonLoc
, EndLoc
, RD
.Vars
,
20138 ReductionIdScopeSpec
.getWithLocInContext(Context
), ReductionId
,
20139 RD
.Privates
, RD
.LHSs
, RD
.RHSs
, RD
.ReductionOps
, RD
.TaskgroupDescriptors
,
20140 buildPreInits(Context
, RD
.ExprCaptures
),
20141 buildPostUpdate(*this, RD
.ExprPostUpdates
));
20144 bool Sema::CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind
,
20145 SourceLocation LinLoc
) {
20146 if ((!LangOpts
.CPlusPlus
&& LinKind
!= OMPC_LINEAR_val
) ||
20147 LinKind
== OMPC_LINEAR_unknown
|| LinKind
== OMPC_LINEAR_step
) {
20148 Diag(LinLoc
, diag::err_omp_wrong_linear_modifier
) << LangOpts
.CPlusPlus
;
20154 bool Sema::CheckOpenMPLinearDecl(const ValueDecl
*D
, SourceLocation ELoc
,
20155 OpenMPLinearClauseKind LinKind
, QualType Type
,
20156 bool IsDeclareSimd
) {
20157 const auto *VD
= dyn_cast_or_null
<VarDecl
>(D
);
20158 // A variable must not have an incomplete type or a reference type.
20159 if (RequireCompleteType(ELoc
, Type
, diag::err_omp_linear_incomplete_type
))
20161 if ((LinKind
== OMPC_LINEAR_uval
|| LinKind
== OMPC_LINEAR_ref
) &&
20162 !Type
->isReferenceType()) {
20163 Diag(ELoc
, diag::err_omp_wrong_linear_modifier_non_reference
)
20164 << Type
<< getOpenMPSimpleClauseTypeName(OMPC_linear
, LinKind
);
20167 Type
= Type
.getNonReferenceType();
20169 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
20170 // A variable that is privatized must not have a const-qualified type
20171 // unless it is of class type with a mutable member. This restriction does
20172 // not apply to the firstprivate clause, nor to the linear clause on
20173 // declarative directives (like declare simd).
20174 if (!IsDeclareSimd
&&
20175 rejectConstNotMutableType(*this, D
, Type
, OMPC_linear
, ELoc
))
20178 // A list item must be of integral or pointer type.
20179 Type
= Type
.getUnqualifiedType().getCanonicalType();
20180 const auto *Ty
= Type
.getTypePtrOrNull();
20181 if (!Ty
|| (LinKind
!= OMPC_LINEAR_ref
&& !Ty
->isDependentType() &&
20182 !Ty
->isIntegralType(Context
) && !Ty
->isPointerType())) {
20183 Diag(ELoc
, diag::err_omp_linear_expected_int_or_ptr
) << Type
;
20185 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
20186 VarDecl::DeclarationOnly
;
20187 Diag(D
->getLocation(),
20188 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
20196 OMPClause
*Sema::ActOnOpenMPLinearClause(
20197 ArrayRef
<Expr
*> VarList
, Expr
*Step
, SourceLocation StartLoc
,
20198 SourceLocation LParenLoc
, OpenMPLinearClauseKind LinKind
,
20199 SourceLocation LinLoc
, SourceLocation ColonLoc
,
20200 SourceLocation StepModifierLoc
, SourceLocation EndLoc
) {
20201 SmallVector
<Expr
*, 8> Vars
;
20202 SmallVector
<Expr
*, 8> Privates
;
20203 SmallVector
<Expr
*, 8> Inits
;
20204 SmallVector
<Decl
*, 4> ExprCaptures
;
20205 SmallVector
<Expr
*, 4> ExprPostUpdates
;
20206 // OpenMP 5.2 [Section 5.4.6, linear clause]
20207 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
20209 if (LinLoc
.isValid() && StepModifierLoc
.isInvalid() && Step
&&
20210 getLangOpts().OpenMP
>= 52)
20211 Diag(Step
->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive
);
20212 if (CheckOpenMPLinearModifier(LinKind
, LinLoc
))
20213 LinKind
= OMPC_LINEAR_val
;
20214 for (Expr
*RefExpr
: VarList
) {
20215 assert(RefExpr
&& "NULL expr in OpenMP linear clause.");
20216 SourceLocation ELoc
;
20217 SourceRange ERange
;
20218 Expr
*SimpleRefExpr
= RefExpr
;
20219 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
20221 // It will be analyzed later.
20222 Vars
.push_back(RefExpr
);
20223 Privates
.push_back(nullptr);
20224 Inits
.push_back(nullptr);
20226 ValueDecl
*D
= Res
.first
;
20230 QualType Type
= D
->getType();
20231 auto *VD
= dyn_cast
<VarDecl
>(D
);
20233 // OpenMP [2.14.3.7, linear clause]
20234 // A list-item cannot appear in more than one linear clause.
20235 // A list-item that appears in a linear clause cannot appear in any
20236 // other data-sharing attribute clause.
20237 DSAStackTy::DSAVarData DVar
= DSAStack
->getTopDSA(D
, /*FromParent=*/false);
20238 if (DVar
.RefExpr
) {
20239 Diag(ELoc
, diag::err_omp_wrong_dsa
) << getOpenMPClauseName(DVar
.CKind
)
20240 << getOpenMPClauseName(OMPC_linear
);
20241 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
20245 if (CheckOpenMPLinearDecl(D
, ELoc
, LinKind
, Type
))
20247 Type
= Type
.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20249 // Build private copy of original var.
20251 buildVarDecl(*this, ELoc
, Type
, D
->getName(),
20252 D
->hasAttrs() ? &D
->getAttrs() : nullptr,
20253 VD
? cast
<DeclRefExpr
>(SimpleRefExpr
) : nullptr);
20254 DeclRefExpr
*PrivateRef
= buildDeclRefExpr(*this, Private
, Type
, ELoc
);
20255 // Build var to save initial value.
20256 VarDecl
*Init
= buildVarDecl(*this, ELoc
, Type
, ".linear.start");
20258 DeclRefExpr
*Ref
= nullptr;
20259 if (!VD
&& !CurContext
->isDependentContext()) {
20260 Ref
= buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/false);
20261 if (!isOpenMPCapturedDecl(D
)) {
20262 ExprCaptures
.push_back(Ref
->getDecl());
20263 if (Ref
->getDecl()->hasAttr
<OMPCaptureNoInitAttr
>()) {
20264 ExprResult RefRes
= DefaultLvalueConversion(Ref
);
20265 if (!RefRes
.isUsable())
20267 ExprResult PostUpdateRes
=
20268 BuildBinOp(DSAStack
->getCurScope(), ELoc
, BO_Assign
,
20269 SimpleRefExpr
, RefRes
.get());
20270 if (!PostUpdateRes
.isUsable())
20272 ExprPostUpdates
.push_back(
20273 IgnoredValueConversions(PostUpdateRes
.get()).get());
20277 if (LinKind
== OMPC_LINEAR_uval
)
20278 InitExpr
= VD
? VD
->getInit() : SimpleRefExpr
;
20280 InitExpr
= VD
? SimpleRefExpr
: Ref
;
20281 AddInitializerToDecl(Init
, DefaultLvalueConversion(InitExpr
).get(),
20282 /*DirectInit=*/false);
20283 DeclRefExpr
*InitRef
= buildDeclRefExpr(*this, Init
, Type
, ELoc
);
20285 DSAStack
->addDSA(D
, RefExpr
->IgnoreParens(), OMPC_linear
, Ref
);
20286 Vars
.push_back((VD
|| CurContext
->isDependentContext())
20287 ? RefExpr
->IgnoreParens()
20289 Privates
.push_back(PrivateRef
);
20290 Inits
.push_back(InitRef
);
20296 Expr
*StepExpr
= Step
;
20297 Expr
*CalcStepExpr
= nullptr;
20298 if (Step
&& !Step
->isValueDependent() && !Step
->isTypeDependent() &&
20299 !Step
->isInstantiationDependent() &&
20300 !Step
->containsUnexpandedParameterPack()) {
20301 SourceLocation StepLoc
= Step
->getBeginLoc();
20302 ExprResult Val
= PerformOpenMPImplicitIntegerConversion(StepLoc
, Step
);
20303 if (Val
.isInvalid())
20305 StepExpr
= Val
.get();
20307 // Build var to save the step value.
20309 buildVarDecl(*this, StepLoc
, StepExpr
->getType(), ".linear.step");
20310 ExprResult SaveRef
=
20311 buildDeclRefExpr(*this, SaveVar
, StepExpr
->getType(), StepLoc
);
20312 ExprResult CalcStep
=
20313 BuildBinOp(CurScope
, StepLoc
, BO_Assign
, SaveRef
.get(), StepExpr
);
20314 CalcStep
= ActOnFinishFullExpr(CalcStep
.get(), /*DiscardedValue*/ false);
20316 // Warn about zero linear step (it would be probably better specified as
20317 // making corresponding variables 'const').
20318 if (std::optional
<llvm::APSInt
> Result
=
20319 StepExpr
->getIntegerConstantExpr(Context
)) {
20320 if (!Result
->isNegative() && !Result
->isStrictlyPositive())
20321 Diag(StepLoc
, diag::warn_omp_linear_step_zero
)
20322 << Vars
[0] << (Vars
.size() > 1);
20323 } else if (CalcStep
.isUsable()) {
20324 // Calculate the step beforehand instead of doing this on each iteration.
20325 // (This is not used if the number of iterations may be kfold-ed).
20326 CalcStepExpr
= CalcStep
.get();
20330 return OMPLinearClause::Create(Context
, StartLoc
, LParenLoc
, LinKind
, LinLoc
,
20331 ColonLoc
, StepModifierLoc
, EndLoc
, Vars
,
20332 Privates
, Inits
, StepExpr
, CalcStepExpr
,
20333 buildPreInits(Context
, ExprCaptures
),
20334 buildPostUpdate(*this, ExprPostUpdates
));
20337 static bool FinishOpenMPLinearClause(OMPLinearClause
&Clause
, DeclRefExpr
*IV
,
20338 Expr
*NumIterations
, Sema
&SemaRef
,
20339 Scope
*S
, DSAStackTy
*Stack
) {
20340 // Walk the vars and build update/final expressions for the CodeGen.
20341 SmallVector
<Expr
*, 8> Updates
;
20342 SmallVector
<Expr
*, 8> Finals
;
20343 SmallVector
<Expr
*, 8> UsedExprs
;
20344 Expr
*Step
= Clause
.getStep();
20345 Expr
*CalcStep
= Clause
.getCalcStep();
20346 // OpenMP [2.14.3.7, linear clause]
20347 // If linear-step is not specified it is assumed to be 1.
20349 Step
= SemaRef
.ActOnIntegerConstant(SourceLocation(), 1).get();
20351 Step
= cast
<BinaryOperator
>(CalcStep
)->getLHS();
20352 bool HasErrors
= false;
20353 auto CurInit
= Clause
.inits().begin();
20354 auto CurPrivate
= Clause
.privates().begin();
20355 OpenMPLinearClauseKind LinKind
= Clause
.getModifier();
20356 for (Expr
*RefExpr
: Clause
.varlists()) {
20357 SourceLocation ELoc
;
20358 SourceRange ERange
;
20359 Expr
*SimpleRefExpr
= RefExpr
;
20360 auto Res
= getPrivateItem(SemaRef
, SimpleRefExpr
, ELoc
, ERange
);
20361 ValueDecl
*D
= Res
.first
;
20362 if (Res
.second
|| !D
) {
20363 Updates
.push_back(nullptr);
20364 Finals
.push_back(nullptr);
20368 auto &&Info
= Stack
->isLoopControlVariable(D
);
20369 // OpenMP [2.15.11, distribute simd Construct]
20370 // A list item may not appear in a linear clause, unless it is the loop
20371 // iteration variable.
20372 if (isOpenMPDistributeDirective(Stack
->getCurrentDirective()) &&
20373 isOpenMPSimdDirective(Stack
->getCurrentDirective()) && !Info
.first
) {
20375 diag::err_omp_linear_distribute_var_non_loop_iteration
);
20376 Updates
.push_back(nullptr);
20377 Finals
.push_back(nullptr);
20381 Expr
*InitExpr
= *CurInit
;
20383 // Build privatized reference to the current linear var.
20384 auto *DE
= cast
<DeclRefExpr
>(SimpleRefExpr
);
20386 if (LinKind
== OMPC_LINEAR_uval
)
20387 CapturedRef
= cast
<VarDecl
>(DE
->getDecl())->getInit();
20390 buildDeclRefExpr(SemaRef
, cast
<VarDecl
>(DE
->getDecl()),
20391 DE
->getType().getUnqualifiedType(), DE
->getExprLoc(),
20392 /*RefersToCapture=*/true);
20394 // Build update: Var = InitExpr + IV * Step
20397 Update
= buildCounterUpdate(
20398 SemaRef
, S
, RefExpr
->getExprLoc(), *CurPrivate
, InitExpr
, IV
, Step
,
20399 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
20401 Update
= *CurPrivate
;
20402 Update
= SemaRef
.ActOnFinishFullExpr(Update
.get(), DE
->getBeginLoc(),
20403 /*DiscardedValue*/ false);
20405 // Build final: Var = PrivCopy;
20408 Final
= SemaRef
.BuildBinOp(
20409 S
, RefExpr
->getExprLoc(), BO_Assign
, CapturedRef
,
20410 SemaRef
.DefaultLvalueConversion(*CurPrivate
).get());
20412 Final
= *CurPrivate
;
20413 Final
= SemaRef
.ActOnFinishFullExpr(Final
.get(), DE
->getBeginLoc(),
20414 /*DiscardedValue*/ false);
20416 if (!Update
.isUsable() || !Final
.isUsable()) {
20417 Updates
.push_back(nullptr);
20418 Finals
.push_back(nullptr);
20419 UsedExprs
.push_back(nullptr);
20422 Updates
.push_back(Update
.get());
20423 Finals
.push_back(Final
.get());
20425 UsedExprs
.push_back(SimpleRefExpr
);
20430 if (Expr
*S
= Clause
.getStep())
20431 UsedExprs
.push_back(S
);
20432 // Fill the remaining part with the nullptr.
20433 UsedExprs
.append(Clause
.varlist_size() + 1 - UsedExprs
.size(), nullptr);
20434 Clause
.setUpdates(Updates
);
20435 Clause
.setFinals(Finals
);
20436 Clause
.setUsedExprs(UsedExprs
);
20440 OMPClause
*Sema::ActOnOpenMPAlignedClause(
20441 ArrayRef
<Expr
*> VarList
, Expr
*Alignment
, SourceLocation StartLoc
,
20442 SourceLocation LParenLoc
, SourceLocation ColonLoc
, SourceLocation EndLoc
) {
20443 SmallVector
<Expr
*, 8> Vars
;
20444 for (Expr
*RefExpr
: VarList
) {
20445 assert(RefExpr
&& "NULL expr in OpenMP linear clause.");
20446 SourceLocation ELoc
;
20447 SourceRange ERange
;
20448 Expr
*SimpleRefExpr
= RefExpr
;
20449 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
20451 // It will be analyzed later.
20452 Vars
.push_back(RefExpr
);
20454 ValueDecl
*D
= Res
.first
;
20458 QualType QType
= D
->getType();
20459 auto *VD
= dyn_cast
<VarDecl
>(D
);
20461 // OpenMP [2.8.1, simd construct, Restrictions]
20462 // The type of list items appearing in the aligned clause must be
20463 // array, pointer, reference to array, or reference to pointer.
20464 QType
= QType
.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20465 const Type
*Ty
= QType
.getTypePtrOrNull();
20466 if (!Ty
|| (!Ty
->isArrayType() && !Ty
->isPointerType())) {
20467 Diag(ELoc
, diag::err_omp_aligned_expected_array_or_ptr
)
20468 << QType
<< getLangOpts().CPlusPlus
<< ERange
;
20469 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
20470 VarDecl::DeclarationOnly
;
20471 Diag(D
->getLocation(),
20472 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
20477 // OpenMP [2.8.1, simd construct, Restrictions]
20478 // A list-item cannot appear in more than one aligned clause.
20479 if (const Expr
*PrevRef
= DSAStack
->addUniqueAligned(D
, SimpleRefExpr
)) {
20480 Diag(ELoc
, diag::err_omp_used_in_clause_twice
)
20481 << 0 << getOpenMPClauseName(OMPC_aligned
) << ERange
;
20482 Diag(PrevRef
->getExprLoc(), diag::note_omp_explicit_dsa
)
20483 << getOpenMPClauseName(OMPC_aligned
);
20487 DeclRefExpr
*Ref
= nullptr;
20488 if (!VD
&& isOpenMPCapturedDecl(D
))
20489 Ref
= buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/true);
20490 Vars
.push_back(DefaultFunctionArrayConversion(
20491 (VD
|| !Ref
) ? RefExpr
->IgnoreParens() : Ref
)
20495 // OpenMP [2.8.1, simd construct, Description]
20496 // The parameter of the aligned clause, alignment, must be a constant
20497 // positive integer expression.
20498 // If no optional parameter is specified, implementation-defined default
20499 // alignments for SIMD instructions on the target platforms are assumed.
20500 if (Alignment
!= nullptr) {
20501 ExprResult AlignResult
=
20502 VerifyPositiveIntegerConstantInClause(Alignment
, OMPC_aligned
);
20503 if (AlignResult
.isInvalid())
20505 Alignment
= AlignResult
.get();
20510 return OMPAlignedClause::Create(Context
, StartLoc
, LParenLoc
, ColonLoc
,
20511 EndLoc
, Vars
, Alignment
);
20514 OMPClause
*Sema::ActOnOpenMPCopyinClause(ArrayRef
<Expr
*> VarList
,
20515 SourceLocation StartLoc
,
20516 SourceLocation LParenLoc
,
20517 SourceLocation EndLoc
) {
20518 SmallVector
<Expr
*, 8> Vars
;
20519 SmallVector
<Expr
*, 8> SrcExprs
;
20520 SmallVector
<Expr
*, 8> DstExprs
;
20521 SmallVector
<Expr
*, 8> AssignmentOps
;
20522 for (Expr
*RefExpr
: VarList
) {
20523 assert(RefExpr
&& "NULL expr in OpenMP copyin clause.");
20524 if (isa
<DependentScopeDeclRefExpr
>(RefExpr
)) {
20525 // It will be analyzed later.
20526 Vars
.push_back(RefExpr
);
20527 SrcExprs
.push_back(nullptr);
20528 DstExprs
.push_back(nullptr);
20529 AssignmentOps
.push_back(nullptr);
20533 SourceLocation ELoc
= RefExpr
->getExprLoc();
20534 // OpenMP [2.1, C/C++]
20535 // A list item is a variable name.
20536 // OpenMP [2.14.4.1, Restrictions, p.1]
20537 // A list item that appears in a copyin clause must be threadprivate.
20538 auto *DE
= dyn_cast
<DeclRefExpr
>(RefExpr
);
20539 if (!DE
|| !isa
<VarDecl
>(DE
->getDecl())) {
20540 Diag(ELoc
, diag::err_omp_expected_var_name_member_expr
)
20541 << 0 << RefExpr
->getSourceRange();
20545 Decl
*D
= DE
->getDecl();
20546 auto *VD
= cast
<VarDecl
>(D
);
20548 QualType Type
= VD
->getType();
20549 if (Type
->isDependentType() || Type
->isInstantiationDependentType()) {
20550 // It will be analyzed later.
20551 Vars
.push_back(DE
);
20552 SrcExprs
.push_back(nullptr);
20553 DstExprs
.push_back(nullptr);
20554 AssignmentOps
.push_back(nullptr);
20558 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
20559 // A list item that appears in a copyin clause must be threadprivate.
20560 if (!DSAStack
->isThreadPrivate(VD
)) {
20561 Diag(ELoc
, diag::err_omp_required_access
)
20562 << getOpenMPClauseName(OMPC_copyin
)
20563 << getOpenMPDirectiveName(OMPD_threadprivate
);
20567 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20568 // A variable of class type (or array thereof) that appears in a
20569 // copyin clause requires an accessible, unambiguous copy assignment
20570 // operator for the class type.
20571 QualType ElemType
= Context
.getBaseElementType(Type
).getNonReferenceType();
20573 buildVarDecl(*this, DE
->getBeginLoc(), ElemType
.getUnqualifiedType(),
20574 ".copyin.src", VD
->hasAttrs() ? &VD
->getAttrs() : nullptr);
20575 DeclRefExpr
*PseudoSrcExpr
= buildDeclRefExpr(
20576 *this, SrcVD
, ElemType
.getUnqualifiedType(), DE
->getExprLoc());
20578 buildVarDecl(*this, DE
->getBeginLoc(), ElemType
, ".copyin.dst",
20579 VD
->hasAttrs() ? &VD
->getAttrs() : nullptr);
20580 DeclRefExpr
*PseudoDstExpr
=
20581 buildDeclRefExpr(*this, DstVD
, ElemType
, DE
->getExprLoc());
20582 // For arrays generate assignment operation for single element and replace
20583 // it by the original array element in CodeGen.
20584 ExprResult AssignmentOp
=
20585 BuildBinOp(/*S=*/nullptr, DE
->getExprLoc(), BO_Assign
, PseudoDstExpr
,
20587 if (AssignmentOp
.isInvalid())
20589 AssignmentOp
= ActOnFinishFullExpr(AssignmentOp
.get(), DE
->getExprLoc(),
20590 /*DiscardedValue*/ false);
20591 if (AssignmentOp
.isInvalid())
20594 DSAStack
->addDSA(VD
, DE
, OMPC_copyin
);
20595 Vars
.push_back(DE
);
20596 SrcExprs
.push_back(PseudoSrcExpr
);
20597 DstExprs
.push_back(PseudoDstExpr
);
20598 AssignmentOps
.push_back(AssignmentOp
.get());
20604 return OMPCopyinClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
, Vars
,
20605 SrcExprs
, DstExprs
, AssignmentOps
);
20608 OMPClause
*Sema::ActOnOpenMPCopyprivateClause(ArrayRef
<Expr
*> VarList
,
20609 SourceLocation StartLoc
,
20610 SourceLocation LParenLoc
,
20611 SourceLocation EndLoc
) {
20612 SmallVector
<Expr
*, 8> Vars
;
20613 SmallVector
<Expr
*, 8> SrcExprs
;
20614 SmallVector
<Expr
*, 8> DstExprs
;
20615 SmallVector
<Expr
*, 8> AssignmentOps
;
20616 for (Expr
*RefExpr
: VarList
) {
20617 assert(RefExpr
&& "NULL expr in OpenMP linear clause.");
20618 SourceLocation ELoc
;
20619 SourceRange ERange
;
20620 Expr
*SimpleRefExpr
= RefExpr
;
20621 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
20623 // It will be analyzed later.
20624 Vars
.push_back(RefExpr
);
20625 SrcExprs
.push_back(nullptr);
20626 DstExprs
.push_back(nullptr);
20627 AssignmentOps
.push_back(nullptr);
20629 ValueDecl
*D
= Res
.first
;
20633 QualType Type
= D
->getType();
20634 auto *VD
= dyn_cast
<VarDecl
>(D
);
20636 // OpenMP [2.14.4.2, Restrictions, p.2]
20637 // A list item that appears in a copyprivate clause may not appear in a
20638 // private or firstprivate clause on the single construct.
20639 if (!VD
|| !DSAStack
->isThreadPrivate(VD
)) {
20640 DSAStackTy::DSAVarData DVar
=
20641 DSAStack
->getTopDSA(D
, /*FromParent=*/false);
20642 if (DVar
.CKind
!= OMPC_unknown
&& DVar
.CKind
!= OMPC_copyprivate
&&
20644 Diag(ELoc
, diag::err_omp_wrong_dsa
)
20645 << getOpenMPClauseName(DVar
.CKind
)
20646 << getOpenMPClauseName(OMPC_copyprivate
);
20647 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
20651 // OpenMP [2.11.4.2, Restrictions, p.1]
20652 // All list items that appear in a copyprivate clause must be either
20653 // threadprivate or private in the enclosing context.
20654 if (DVar
.CKind
== OMPC_unknown
) {
20655 DVar
= DSAStack
->getImplicitDSA(D
, false);
20656 if (DVar
.CKind
== OMPC_shared
) {
20657 Diag(ELoc
, diag::err_omp_required_access
)
20658 << getOpenMPClauseName(OMPC_copyprivate
)
20659 << "threadprivate or private in the enclosing context";
20660 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
20666 // Variably modified types are not supported.
20667 if (!Type
->isAnyPointerType() && Type
->isVariablyModifiedType()) {
20668 Diag(ELoc
, diag::err_omp_variably_modified_type_not_supported
)
20669 << getOpenMPClauseName(OMPC_copyprivate
) << Type
20670 << getOpenMPDirectiveName(DSAStack
->getCurrentDirective());
20671 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
20672 VarDecl::DeclarationOnly
;
20673 Diag(D
->getLocation(),
20674 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
20679 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20680 // A variable of class type (or array thereof) that appears in a
20681 // copyin clause requires an accessible, unambiguous copy assignment
20682 // operator for the class type.
20683 Type
= Context
.getBaseElementType(Type
.getNonReferenceType())
20684 .getUnqualifiedType();
20686 buildVarDecl(*this, RefExpr
->getBeginLoc(), Type
, ".copyprivate.src",
20687 D
->hasAttrs() ? &D
->getAttrs() : nullptr);
20688 DeclRefExpr
*PseudoSrcExpr
= buildDeclRefExpr(*this, SrcVD
, Type
, ELoc
);
20690 buildVarDecl(*this, RefExpr
->getBeginLoc(), Type
, ".copyprivate.dst",
20691 D
->hasAttrs() ? &D
->getAttrs() : nullptr);
20692 DeclRefExpr
*PseudoDstExpr
= buildDeclRefExpr(*this, DstVD
, Type
, ELoc
);
20693 ExprResult AssignmentOp
= BuildBinOp(
20694 DSAStack
->getCurScope(), ELoc
, BO_Assign
, PseudoDstExpr
, PseudoSrcExpr
);
20695 if (AssignmentOp
.isInvalid())
20698 ActOnFinishFullExpr(AssignmentOp
.get(), ELoc
, /*DiscardedValue*/ false);
20699 if (AssignmentOp
.isInvalid())
20702 // No need to mark vars as copyprivate, they are already threadprivate or
20703 // implicitly private.
20704 assert(VD
|| isOpenMPCapturedDecl(D
));
20706 VD
? RefExpr
->IgnoreParens()
20707 : buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/false));
20708 SrcExprs
.push_back(PseudoSrcExpr
);
20709 DstExprs
.push_back(PseudoDstExpr
);
20710 AssignmentOps
.push_back(AssignmentOp
.get());
20716 return OMPCopyprivateClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
,
20717 Vars
, SrcExprs
, DstExprs
, AssignmentOps
);
20720 OMPClause
*Sema::ActOnOpenMPFlushClause(ArrayRef
<Expr
*> VarList
,
20721 SourceLocation StartLoc
,
20722 SourceLocation LParenLoc
,
20723 SourceLocation EndLoc
) {
20724 if (VarList
.empty())
20727 return OMPFlushClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
, VarList
);
20730 /// Tries to find omp_depend_t. type.
20731 static bool findOMPDependT(Sema
&S
, SourceLocation Loc
, DSAStackTy
*Stack
,
20732 bool Diagnose
= true) {
20733 QualType OMPDependT
= Stack
->getOMPDependT();
20734 if (!OMPDependT
.isNull())
20736 IdentifierInfo
*II
= &S
.PP
.getIdentifierTable().get("omp_depend_t");
20737 ParsedType PT
= S
.getTypeName(*II
, Loc
, S
.getCurScope());
20738 if (!PT
.getAsOpaquePtr() || PT
.get().isNull()) {
20740 S
.Diag(Loc
, diag::err_omp_implied_type_not_found
) << "omp_depend_t";
20743 Stack
->setOMPDependT(PT
.get());
20747 OMPClause
*Sema::ActOnOpenMPDepobjClause(Expr
*Depobj
, SourceLocation StartLoc
,
20748 SourceLocation LParenLoc
,
20749 SourceLocation EndLoc
) {
20753 bool OMPDependTFound
= findOMPDependT(*this, StartLoc
, DSAStack
);
20755 // OpenMP 5.0, 2.17.10.1 depobj Construct
20756 // depobj is an lvalue expression of type omp_depend_t.
20757 if (!Depobj
->isTypeDependent() && !Depobj
->isValueDependent() &&
20758 !Depobj
->isInstantiationDependent() &&
20759 !Depobj
->containsUnexpandedParameterPack() &&
20760 (OMPDependTFound
&&
20761 !Context
.typesAreCompatible(DSAStack
->getOMPDependT(), Depobj
->getType(),
20762 /*CompareUnqualified=*/true))) {
20763 Diag(Depobj
->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue
)
20764 << 0 << Depobj
->getType() << Depobj
->getSourceRange();
20767 if (!Depobj
->isLValue()) {
20768 Diag(Depobj
->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue
)
20769 << 1 << Depobj
->getSourceRange();
20772 return OMPDepobjClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
, Depobj
);
20776 // Utility struct that gathers the related info for doacross clause.
20777 struct DoacrossDataInfoTy
{
20778 // The list of expressions.
20779 SmallVector
<Expr
*, 8> Vars
;
20780 // The OperatorOffset for doacross loop.
20781 DSAStackTy::OperatorOffsetTy OpsOffs
;
20782 // The depended loop count.
20783 llvm::APSInt TotalDepCount
;
20786 static DoacrossDataInfoTy
20787 ProcessOpenMPDoacrossClauseCommon(Sema
&SemaRef
, bool IsSource
,
20788 ArrayRef
<Expr
*> VarList
, DSAStackTy
*Stack
,
20789 SourceLocation EndLoc
) {
20791 SmallVector
<Expr
*, 8> Vars
;
20792 DSAStackTy::OperatorOffsetTy OpsOffs
;
20793 llvm::APSInt
DepCounter(/*BitWidth=*/32);
20794 llvm::APSInt
TotalDepCount(/*BitWidth=*/32);
20796 if (const Expr
*OrderedCountExpr
=
20797 Stack
->getParentOrderedRegionParam().first
) {
20798 TotalDepCount
= OrderedCountExpr
->EvaluateKnownConstInt(SemaRef
.Context
);
20799 TotalDepCount
.setIsUnsigned(/*Val=*/true);
20802 for (Expr
*RefExpr
: VarList
) {
20803 assert(RefExpr
&& "NULL expr in OpenMP doacross clause.");
20804 if (isa
<DependentScopeDeclRefExpr
>(RefExpr
)) {
20805 // It will be analyzed later.
20806 Vars
.push_back(RefExpr
);
20810 SourceLocation ELoc
= RefExpr
->getExprLoc();
20811 Expr
*SimpleExpr
= RefExpr
->IgnoreParenCasts();
20813 if (Stack
->getParentOrderedRegionParam().first
&&
20814 DepCounter
>= TotalDepCount
) {
20815 SemaRef
.Diag(ELoc
, diag::err_omp_depend_sink_unexpected_expr
);
20819 // OpenMP [2.13.9, Summary]
20820 // depend(dependence-type : vec), where dependence-type is:
20821 // 'sink' and where vec is the iteration vector, which has the form:
20822 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
20823 // where n is the value specified by the ordered clause in the loop
20824 // directive, xi denotes the loop iteration variable of the i-th nested
20825 // loop associated with the loop directive, and di is a constant
20826 // non-negative integer.
20827 if (SemaRef
.CurContext
->isDependentContext()) {
20828 // It will be analyzed later.
20829 Vars
.push_back(RefExpr
);
20832 SimpleExpr
= SimpleExpr
->IgnoreImplicit();
20833 OverloadedOperatorKind OOK
= OO_None
;
20834 SourceLocation OOLoc
;
20835 Expr
*LHS
= SimpleExpr
;
20836 Expr
*RHS
= nullptr;
20837 if (auto *BO
= dyn_cast
<BinaryOperator
>(SimpleExpr
)) {
20838 OOK
= BinaryOperator::getOverloadedOperator(BO
->getOpcode());
20839 OOLoc
= BO
->getOperatorLoc();
20840 LHS
= BO
->getLHS()->IgnoreParenImpCasts();
20841 RHS
= BO
->getRHS()->IgnoreParenImpCasts();
20842 } else if (auto *OCE
= dyn_cast
<CXXOperatorCallExpr
>(SimpleExpr
)) {
20843 OOK
= OCE
->getOperator();
20844 OOLoc
= OCE
->getOperatorLoc();
20845 LHS
= OCE
->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20846 RHS
= OCE
->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
20847 } else if (auto *MCE
= dyn_cast
<CXXMemberCallExpr
>(SimpleExpr
)) {
20848 OOK
= MCE
->getMethodDecl()
20851 .getCXXOverloadedOperator();
20852 OOLoc
= MCE
->getCallee()->getExprLoc();
20853 LHS
= MCE
->getImplicitObjectArgument()->IgnoreParenImpCasts();
20854 RHS
= MCE
->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20856 SourceLocation ELoc
;
20857 SourceRange ERange
;
20858 auto Res
= getPrivateItem(SemaRef
, LHS
, ELoc
, ERange
);
20860 // It will be analyzed later.
20861 Vars
.push_back(RefExpr
);
20863 ValueDecl
*D
= Res
.first
;
20867 if (OOK
!= OO_Plus
&& OOK
!= OO_Minus
&& (RHS
|| OOK
!= OO_None
)) {
20868 SemaRef
.Diag(OOLoc
, diag::err_omp_depend_sink_expected_plus_minus
);
20872 ExprResult RHSRes
= SemaRef
.VerifyPositiveIntegerConstantInClause(
20873 RHS
, OMPC_depend
, /*StrictlyPositive=*/false);
20874 if (RHSRes
.isInvalid())
20877 if (!SemaRef
.CurContext
->isDependentContext() &&
20878 Stack
->getParentOrderedRegionParam().first
&&
20879 DepCounter
!= Stack
->isParentLoopControlVariable(D
).first
) {
20880 const ValueDecl
*VD
=
20881 Stack
->getParentLoopControlVariable(DepCounter
.getZExtValue());
20883 SemaRef
.Diag(ELoc
, diag::err_omp_depend_sink_expected_loop_iteration
)
20886 SemaRef
.Diag(ELoc
, diag::err_omp_depend_sink_expected_loop_iteration
)
20890 OpsOffs
.emplace_back(RHS
, OOK
);
20892 Vars
.push_back(RefExpr
->IgnoreParenImpCasts());
20894 if (!SemaRef
.CurContext
->isDependentContext() && !IsSource
&&
20895 TotalDepCount
> VarList
.size() &&
20896 Stack
->getParentOrderedRegionParam().first
&&
20897 Stack
->getParentLoopControlVariable(VarList
.size() + 1)) {
20898 SemaRef
.Diag(EndLoc
, diag::err_omp_depend_sink_expected_loop_iteration
)
20899 << 1 << Stack
->getParentLoopControlVariable(VarList
.size() + 1);
20901 return {Vars
, OpsOffs
, TotalDepCount
};
20905 Sema::ActOnOpenMPDependClause(const OMPDependClause::DependDataTy
&Data
,
20906 Expr
*DepModifier
, ArrayRef
<Expr
*> VarList
,
20907 SourceLocation StartLoc
, SourceLocation LParenLoc
,
20908 SourceLocation EndLoc
) {
20909 OpenMPDependClauseKind DepKind
= Data
.DepKind
;
20910 SourceLocation DepLoc
= Data
.DepLoc
;
20911 if (DSAStack
->getCurrentDirective() == OMPD_ordered
&&
20912 DepKind
!= OMPC_DEPEND_source
&& DepKind
!= OMPC_DEPEND_sink
) {
20913 Diag(DepLoc
, diag::err_omp_unexpected_clause_value
)
20914 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend
);
20917 if (DSAStack
->getCurrentDirective() == OMPD_taskwait
&&
20918 DepKind
== OMPC_DEPEND_mutexinoutset
) {
20919 Diag(DepLoc
, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed
);
20922 if ((DSAStack
->getCurrentDirective() != OMPD_ordered
||
20923 DSAStack
->getCurrentDirective() == OMPD_depobj
) &&
20924 (DepKind
== OMPC_DEPEND_unknown
|| DepKind
== OMPC_DEPEND_source
||
20925 DepKind
== OMPC_DEPEND_sink
||
20926 ((LangOpts
.OpenMP
< 50 ||
20927 DSAStack
->getCurrentDirective() == OMPD_depobj
) &&
20928 DepKind
== OMPC_DEPEND_depobj
))) {
20929 SmallVector
<unsigned, 6> Except
= {OMPC_DEPEND_source
, OMPC_DEPEND_sink
,
20930 OMPC_DEPEND_outallmemory
,
20931 OMPC_DEPEND_inoutallmemory
};
20932 if (LangOpts
.OpenMP
< 50 || DSAStack
->getCurrentDirective() == OMPD_depobj
)
20933 Except
.push_back(OMPC_DEPEND_depobj
);
20934 if (LangOpts
.OpenMP
< 51)
20935 Except
.push_back(OMPC_DEPEND_inoutset
);
20936 std::string Expected
= (LangOpts
.OpenMP
>= 50 && !DepModifier
)
20937 ? "depend modifier(iterator) or "
20939 Diag(DepLoc
, diag::err_omp_unexpected_clause_value
)
20940 << Expected
+ getListOfPossibleValues(OMPC_depend
, /*First=*/0,
20941 /*Last=*/OMPC_DEPEND_unknown
,
20943 << getOpenMPClauseName(OMPC_depend
);
20947 (DepKind
== OMPC_DEPEND_source
|| DepKind
== OMPC_DEPEND_sink
)) {
20948 Diag(DepModifier
->getExprLoc(),
20949 diag::err_omp_depend_sink_source_with_modifier
);
20953 !DepModifier
->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator
))
20954 Diag(DepModifier
->getExprLoc(), diag::err_omp_depend_modifier_not_iterator
);
20956 SmallVector
<Expr
*, 8> Vars
;
20957 DSAStackTy::OperatorOffsetTy OpsOffs
;
20958 llvm::APSInt
TotalDepCount(/*BitWidth=*/32);
20960 if (DepKind
== OMPC_DEPEND_sink
|| DepKind
== OMPC_DEPEND_source
) {
20961 DoacrossDataInfoTy VarOffset
= ProcessOpenMPDoacrossClauseCommon(
20962 *this, DepKind
== OMPC_DEPEND_source
, VarList
, DSAStack
, EndLoc
);
20963 Vars
= VarOffset
.Vars
;
20964 OpsOffs
= VarOffset
.OpsOffs
;
20965 TotalDepCount
= VarOffset
.TotalDepCount
;
20967 for (Expr
*RefExpr
: VarList
) {
20968 assert(RefExpr
&& "NULL expr in OpenMP shared clause.");
20969 if (isa
<DependentScopeDeclRefExpr
>(RefExpr
)) {
20970 // It will be analyzed later.
20971 Vars
.push_back(RefExpr
);
20975 SourceLocation ELoc
= RefExpr
->getExprLoc();
20976 Expr
*SimpleExpr
= RefExpr
->IgnoreParenCasts();
20977 if (DepKind
!= OMPC_DEPEND_sink
&& DepKind
!= OMPC_DEPEND_source
) {
20978 bool OMPDependTFound
= LangOpts
.OpenMP
>= 50;
20979 if (OMPDependTFound
)
20980 OMPDependTFound
= findOMPDependT(*this, StartLoc
, DSAStack
,
20981 DepKind
== OMPC_DEPEND_depobj
);
20982 if (DepKind
== OMPC_DEPEND_depobj
) {
20983 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20984 // List items used in depend clauses with the depobj dependence type
20985 // must be expressions of the omp_depend_t type.
20986 if (!RefExpr
->isValueDependent() && !RefExpr
->isTypeDependent() &&
20987 !RefExpr
->isInstantiationDependent() &&
20988 !RefExpr
->containsUnexpandedParameterPack() &&
20989 (OMPDependTFound
&&
20990 !Context
.hasSameUnqualifiedType(DSAStack
->getOMPDependT(),
20991 RefExpr
->getType()))) {
20992 Diag(ELoc
, diag::err_omp_expected_omp_depend_t_lvalue
)
20993 << 0 << RefExpr
->getType() << RefExpr
->getSourceRange();
20996 if (!RefExpr
->isLValue()) {
20997 Diag(ELoc
, diag::err_omp_expected_omp_depend_t_lvalue
)
20998 << 1 << RefExpr
->getType() << RefExpr
->getSourceRange();
21002 // OpenMP 5.0 [2.17.11, Restrictions]
21003 // List items used in depend clauses cannot be zero-length array
21005 QualType ExprTy
= RefExpr
->getType().getNonReferenceType();
21006 const auto *OASE
= dyn_cast
<OMPArraySectionExpr
>(SimpleExpr
);
21008 QualType BaseType
=
21009 OMPArraySectionExpr::getBaseOriginalType(OASE
->getBase());
21010 if (const auto *ATy
= BaseType
->getAsArrayTypeUnsafe())
21011 ExprTy
= ATy
->getElementType();
21013 ExprTy
= BaseType
->getPointeeType();
21014 ExprTy
= ExprTy
.getNonReferenceType();
21015 const Expr
*Length
= OASE
->getLength();
21016 Expr::EvalResult Result
;
21017 if (Length
&& !Length
->isValueDependent() &&
21018 Length
->EvaluateAsInt(Result
, Context
) &&
21019 Result
.Val
.getInt().isZero()) {
21021 diag::err_omp_depend_zero_length_array_section_not_allowed
)
21022 << SimpleExpr
->getSourceRange();
21027 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21028 // List items used in depend clauses with the in, out, inout,
21029 // inoutset, or mutexinoutset dependence types cannot be
21030 // expressions of the omp_depend_t type.
21031 if (!RefExpr
->isValueDependent() && !RefExpr
->isTypeDependent() &&
21032 !RefExpr
->isInstantiationDependent() &&
21033 !RefExpr
->containsUnexpandedParameterPack() &&
21034 (!RefExpr
->IgnoreParenImpCasts()->isLValue() ||
21035 (OMPDependTFound
&& DSAStack
->getOMPDependT().getTypePtr() ==
21036 ExprTy
.getTypePtr()))) {
21037 Diag(ELoc
, diag::err_omp_expected_addressable_lvalue_or_array_item
)
21038 << (LangOpts
.OpenMP
>= 50 ? 1 : 0)
21039 << (LangOpts
.OpenMP
>= 50 ? 1 : 0) << RefExpr
->getSourceRange();
21043 auto *ASE
= dyn_cast
<ArraySubscriptExpr
>(SimpleExpr
);
21044 if (ASE
&& !ASE
->getBase()->isTypeDependent() &&
21047 .getNonReferenceType()
21048 ->isPointerType() &&
21049 !ASE
->getBase()->getType().getNonReferenceType()->isArrayType()) {
21050 Diag(ELoc
, diag::err_omp_expected_addressable_lvalue_or_array_item
)
21051 << (LangOpts
.OpenMP
>= 50 ? 1 : 0)
21052 << (LangOpts
.OpenMP
>= 50 ? 1 : 0) << RefExpr
->getSourceRange();
21058 Sema::TentativeAnalysisScope
Trap(*this);
21059 Res
= CreateBuiltinUnaryOp(ELoc
, UO_AddrOf
,
21060 RefExpr
->IgnoreParenImpCasts());
21062 if (!Res
.isUsable() && !isa
<OMPArraySectionExpr
>(SimpleExpr
) &&
21063 !isa
<OMPArrayShapingExpr
>(SimpleExpr
)) {
21064 Diag(ELoc
, diag::err_omp_expected_addressable_lvalue_or_array_item
)
21065 << (LangOpts
.OpenMP
>= 50 ? 1 : 0)
21066 << (LangOpts
.OpenMP
>= 50 ? 1 : 0) << RefExpr
->getSourceRange();
21071 Vars
.push_back(RefExpr
->IgnoreParenImpCasts());
21075 if (DepKind
!= OMPC_DEPEND_source
&& DepKind
!= OMPC_DEPEND_sink
&&
21076 DepKind
!= OMPC_DEPEND_outallmemory
&&
21077 DepKind
!= OMPC_DEPEND_inoutallmemory
&& Vars
.empty())
21080 auto *C
= OMPDependClause::Create(
21081 Context
, StartLoc
, LParenLoc
, EndLoc
,
21082 {DepKind
, DepLoc
, Data
.ColonLoc
, Data
.OmpAllMemoryLoc
}, DepModifier
, Vars
,
21083 TotalDepCount
.getZExtValue());
21084 if ((DepKind
== OMPC_DEPEND_sink
|| DepKind
== OMPC_DEPEND_source
) &&
21085 DSAStack
->isParentOrderedRegion())
21086 DSAStack
->addDoacrossDependClause(C
, OpsOffs
);
21090 OMPClause
*Sema::ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier
,
21091 Expr
*Device
, SourceLocation StartLoc
,
21092 SourceLocation LParenLoc
,
21093 SourceLocation ModifierLoc
,
21094 SourceLocation EndLoc
) {
21095 assert((ModifierLoc
.isInvalid() || LangOpts
.OpenMP
>= 50) &&
21096 "Unexpected device modifier in OpenMP < 50.");
21098 bool ErrorFound
= false;
21099 if (ModifierLoc
.isValid() && Modifier
== OMPC_DEVICE_unknown
) {
21100 std::string Values
=
21101 getListOfPossibleValues(OMPC_device
, /*First=*/0, OMPC_DEVICE_unknown
);
21102 Diag(ModifierLoc
, diag::err_omp_unexpected_clause_value
)
21103 << Values
<< getOpenMPClauseName(OMPC_device
);
21107 Expr
*ValExpr
= Device
;
21108 Stmt
*HelperValStmt
= nullptr;
21110 // OpenMP [2.9.1, Restrictions]
21111 // The device expression must evaluate to a non-negative integer value.
21112 ErrorFound
= !isNonNegativeIntegerValue(ValExpr
, *this, OMPC_device
,
21113 /*StrictlyPositive=*/false) ||
21118 // OpenMP 5.0 [2.12.5, Restrictions]
21119 // In case of ancestor device-modifier, a requires directive with
21120 // the reverse_offload clause must be specified.
21121 if (Modifier
== OMPC_DEVICE_ancestor
) {
21122 if (!DSAStack
->hasRequiresDeclWithClause
<OMPReverseOffloadClause
>()) {
21125 diag::err_omp_device_ancestor_without_requires_reverse_offload
);
21130 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
21131 OpenMPDirectiveKind CaptureRegion
=
21132 getOpenMPCaptureRegionForClause(DKind
, OMPC_device
, LangOpts
.OpenMP
);
21133 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
21134 ValExpr
= MakeFullExpr(ValExpr
).get();
21135 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
21136 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
21137 HelperValStmt
= buildPreInits(Context
, Captures
);
21140 return new (Context
)
21141 OMPDeviceClause(Modifier
, ValExpr
, HelperValStmt
, CaptureRegion
, StartLoc
,
21142 LParenLoc
, ModifierLoc
, EndLoc
);
21145 static bool checkTypeMappable(SourceLocation SL
, SourceRange SR
, Sema
&SemaRef
,
21146 DSAStackTy
*Stack
, QualType QTy
,
21147 bool FullCheck
= true) {
21148 if (SemaRef
.RequireCompleteType(SL
, QTy
, diag::err_incomplete_type
))
21150 if (FullCheck
&& !SemaRef
.CurContext
->isDependentContext() &&
21151 !QTy
.isTriviallyCopyableType(SemaRef
.Context
))
21152 SemaRef
.Diag(SL
, diag::warn_omp_non_trivial_type_mapped
) << QTy
<< SR
;
21156 /// Return true if it can be proven that the provided array expression
21157 /// (array section or array subscript) does NOT specify the whole size of the
21158 /// array whose base type is \a BaseQTy.
21159 static bool checkArrayExpressionDoesNotReferToWholeSize(Sema
&SemaRef
,
21161 QualType BaseQTy
) {
21162 const auto *OASE
= dyn_cast
<OMPArraySectionExpr
>(E
);
21164 // If this is an array subscript, it refers to the whole size if the size of
21165 // the dimension is constant and equals 1. Also, an array section assumes the
21166 // format of an array subscript if no colon is used.
21167 if (isa
<ArraySubscriptExpr
>(E
) ||
21168 (OASE
&& OASE
->getColonLocFirst().isInvalid())) {
21169 if (const auto *ATy
= dyn_cast
<ConstantArrayType
>(BaseQTy
.getTypePtr()))
21170 return ATy
->getSize().getSExtValue() != 1;
21171 // Size can't be evaluated statically.
21175 assert(OASE
&& "Expecting array section if not an array subscript.");
21176 const Expr
*LowerBound
= OASE
->getLowerBound();
21177 const Expr
*Length
= OASE
->getLength();
21179 // If there is a lower bound that does not evaluates to zero, we are not
21180 // covering the whole dimension.
21182 Expr::EvalResult Result
;
21183 if (!LowerBound
->EvaluateAsInt(Result
, SemaRef
.getASTContext()))
21184 return false; // Can't get the integer value as a constant.
21186 llvm::APSInt ConstLowerBound
= Result
.Val
.getInt();
21187 if (ConstLowerBound
.getSExtValue())
21191 // If we don't have a length we covering the whole dimension.
21195 // If the base is a pointer, we don't have a way to get the size of the
21197 if (BaseQTy
->isPointerType())
21200 // We can only check if the length is the same as the size of the dimension
21201 // if we have a constant array.
21202 const auto *CATy
= dyn_cast
<ConstantArrayType
>(BaseQTy
.getTypePtr());
21206 Expr::EvalResult Result
;
21207 if (!Length
->EvaluateAsInt(Result
, SemaRef
.getASTContext()))
21208 return false; // Can't get the integer value as a constant.
21210 llvm::APSInt ConstLength
= Result
.Val
.getInt();
21211 return CATy
->getSize().getSExtValue() != ConstLength
.getSExtValue();
21214 // Return true if it can be proven that the provided array expression (array
21215 // section or array subscript) does NOT specify a single element of the array
21216 // whose base type is \a BaseQTy.
21217 static bool checkArrayExpressionDoesNotReferToUnitySize(Sema
&SemaRef
,
21219 QualType BaseQTy
) {
21220 const auto *OASE
= dyn_cast
<OMPArraySectionExpr
>(E
);
21222 // An array subscript always refer to a single element. Also, an array section
21223 // assumes the format of an array subscript if no colon is used.
21224 if (isa
<ArraySubscriptExpr
>(E
) ||
21225 (OASE
&& OASE
->getColonLocFirst().isInvalid()))
21228 assert(OASE
&& "Expecting array section if not an array subscript.");
21229 const Expr
*Length
= OASE
->getLength();
21231 // If we don't have a length we have to check if the array has unitary size
21232 // for this dimension. Also, we should always expect a length if the base type
21235 if (const auto *ATy
= dyn_cast
<ConstantArrayType
>(BaseQTy
.getTypePtr()))
21236 return ATy
->getSize().getSExtValue() != 1;
21237 // We cannot assume anything.
21241 // Check if the length evaluates to 1.
21242 Expr::EvalResult Result
;
21243 if (!Length
->EvaluateAsInt(Result
, SemaRef
.getASTContext()))
21244 return false; // Can't get the integer value as a constant.
21246 llvm::APSInt ConstLength
= Result
.Val
.getInt();
21247 return ConstLength
.getSExtValue() != 1;
21250 // The base of elements of list in a map clause have to be either:
21251 // - a reference to variable or field.
21252 // - a member expression.
21253 // - an array expression.
21255 // E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
21256 // reference to 'r'.
21263 // #pragma omp target map (S.Arr[:12]);
21267 // We want to retrieve the member expression 'this->S';
21269 // OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
21270 // If a list item is an array section, it must specify contiguous storage.
21272 // For this restriction it is sufficient that we make sure only references
21273 // to variables or fields and array expressions, and that no array sections
21274 // exist except in the rightmost expression (unless they cover the whole
21275 // dimension of the array). E.g. these would be invalid:
21277 // r.ArrS[3:5].Arr[6:7]
21281 // but these would be valid:
21282 // r.ArrS[3].Arr[6:7]
21286 class MapBaseChecker final
: public StmtVisitor
<MapBaseChecker
, bool> {
21288 OpenMPClauseKind CKind
= OMPC_unknown
;
21289 OpenMPDirectiveKind DKind
= OMPD_unknown
;
21290 OMPClauseMappableExprCommon::MappableExprComponentList
&Components
;
21291 bool IsNonContiguous
= false;
21292 bool NoDiagnose
= false;
21293 const Expr
*RelevantExpr
= nullptr;
21294 bool AllowUnitySizeArraySection
= true;
21295 bool AllowWholeSizeArraySection
= true;
21296 bool AllowAnotherPtr
= true;
21297 SourceLocation ELoc
;
21298 SourceRange ERange
;
21300 void emitErrorMsg() {
21301 // If nothing else worked, this is not a valid map clause expression.
21302 if (SemaRef
.getLangOpts().OpenMP
< 50) {
21304 diag::err_omp_expected_named_var_member_or_array_expression
)
21307 SemaRef
.Diag(ELoc
, diag::err_omp_non_lvalue_in_map_or_motion_clauses
)
21308 << getOpenMPClauseName(CKind
) << ERange
;
21313 bool VisitDeclRefExpr(DeclRefExpr
*DRE
) {
21314 if (!isa
<VarDecl
>(DRE
->getDecl())) {
21318 assert(!RelevantExpr
&& "RelevantExpr is expected to be nullptr");
21319 RelevantExpr
= DRE
;
21320 // Record the component.
21321 Components
.emplace_back(DRE
, DRE
->getDecl(), IsNonContiguous
);
21325 bool VisitMemberExpr(MemberExpr
*ME
) {
21327 Expr
*BaseE
= ME
->getBase()->IgnoreParenCasts();
21329 if (isa
<CXXThisExpr
>(BaseE
)) {
21330 assert(!RelevantExpr
&& "RelevantExpr is expected to be nullptr");
21331 // We found a base expression: this->Val.
21337 if (!isa
<FieldDecl
>(ME
->getMemberDecl())) {
21339 SemaRef
.Diag(ELoc
, diag::err_omp_expected_access_to_data_field
)
21340 << ME
->getSourceRange();
21348 auto *FD
= cast
<FieldDecl
>(ME
->getMemberDecl());
21350 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
21351 // A bit-field cannot appear in a map clause.
21353 if (FD
->isBitField()) {
21355 SemaRef
.Diag(ELoc
, diag::err_omp_bit_fields_forbidden_in_clause
)
21356 << ME
->getSourceRange() << getOpenMPClauseName(CKind
);
21364 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21365 // If the type of a list item is a reference to a type T then the type
21366 // will be considered to be T for all purposes of this clause.
21367 QualType CurType
= BaseE
->getType().getNonReferenceType();
21369 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
21370 // A list item cannot be a variable that is a member of a structure with
21373 if (CurType
->isUnionType()) {
21375 SemaRef
.Diag(ELoc
, diag::err_omp_union_type_not_allowed
)
21376 << ME
->getSourceRange();
21379 return RelevantExpr
|| Visit(E
);
21382 // If we got a member expression, we should not expect any array section
21385 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
21386 // If a list item is an element of a structure, only the rightmost symbol
21387 // of the variable reference can be an array section.
21389 AllowUnitySizeArraySection
= false;
21390 AllowWholeSizeArraySection
= false;
21392 // Record the component.
21393 Components
.emplace_back(ME
, FD
, IsNonContiguous
);
21394 return RelevantExpr
|| Visit(E
);
21397 bool VisitArraySubscriptExpr(ArraySubscriptExpr
*AE
) {
21398 Expr
*E
= AE
->getBase()->IgnoreParenImpCasts();
21400 if (!E
->getType()->isAnyPointerType() && !E
->getType()->isArrayType()) {
21402 SemaRef
.Diag(ELoc
, diag::err_omp_expected_base_var_name
)
21403 << 0 << AE
->getSourceRange();
21406 return RelevantExpr
|| Visit(E
);
21409 // If we got an array subscript that express the whole dimension we
21410 // can have any array expressions before. If it only expressing part of
21411 // the dimension, we can only have unitary-size array expressions.
21412 if (checkArrayExpressionDoesNotReferToWholeSize(SemaRef
, AE
, E
->getType()))
21413 AllowWholeSizeArraySection
= false;
21415 if (const auto *TE
= dyn_cast
<CXXThisExpr
>(E
->IgnoreParenCasts())) {
21416 Expr::EvalResult Result
;
21417 if (!AE
->getIdx()->isValueDependent() &&
21418 AE
->getIdx()->EvaluateAsInt(Result
, SemaRef
.getASTContext()) &&
21419 !Result
.Val
.getInt().isZero()) {
21420 SemaRef
.Diag(AE
->getIdx()->getExprLoc(),
21421 diag::err_omp_invalid_map_this_expr
);
21422 SemaRef
.Diag(AE
->getIdx()->getExprLoc(),
21423 diag::note_omp_invalid_subscript_on_this_ptr_map
);
21425 assert(!RelevantExpr
&& "RelevantExpr is expected to be nullptr");
21429 // Record the component - we don't have any declaration associated.
21430 Components
.emplace_back(AE
, nullptr, IsNonContiguous
);
21432 return RelevantExpr
|| Visit(E
);
21435 bool VisitOMPArraySectionExpr(OMPArraySectionExpr
*OASE
) {
21436 // After OMP 5.0 Array section in reduction clause will be implicitly
21438 assert(!(SemaRef
.getLangOpts().OpenMP
< 50 && NoDiagnose
) &&
21439 "Array sections cannot be implicitly mapped.");
21440 Expr
*E
= OASE
->getBase()->IgnoreParenImpCasts();
21442 OMPArraySectionExpr::getBaseOriginalType(E
).getCanonicalType();
21444 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21445 // If the type of a list item is a reference to a type T then the type
21446 // will be considered to be T for all purposes of this clause.
21447 if (CurType
->isReferenceType())
21448 CurType
= CurType
->getPointeeType();
21450 bool IsPointer
= CurType
->isAnyPointerType();
21452 if (!IsPointer
&& !CurType
->isArrayType()) {
21453 SemaRef
.Diag(ELoc
, diag::err_omp_expected_base_var_name
)
21454 << 0 << OASE
->getSourceRange();
21459 checkArrayExpressionDoesNotReferToWholeSize(SemaRef
, OASE
, CurType
);
21461 checkArrayExpressionDoesNotReferToUnitySize(SemaRef
, OASE
, CurType
);
21463 if (AllowWholeSizeArraySection
) {
21464 // Any array section is currently allowed. Allowing a whole size array
21465 // section implies allowing a unity array section as well.
21467 // If this array section refers to the whole dimension we can still
21468 // accept other array sections before this one, except if the base is a
21469 // pointer. Otherwise, only unitary sections are accepted.
21470 if (NotWhole
|| IsPointer
)
21471 AllowWholeSizeArraySection
= false;
21472 } else if (DKind
== OMPD_target_update
&&
21473 SemaRef
.getLangOpts().OpenMP
>= 50) {
21474 if (IsPointer
&& !AllowAnotherPtr
)
21475 SemaRef
.Diag(ELoc
, diag::err_omp_section_length_undefined
)
21476 << /*array of unknown bound */ 1;
21478 IsNonContiguous
= true;
21479 } else if (AllowUnitySizeArraySection
&& NotUnity
) {
21480 // A unity or whole array section is not allowed and that is not
21481 // compatible with the properties of the current array section.
21485 diag::err_array_section_does_not_specify_contiguous_storage
)
21486 << OASE
->getSourceRange();
21491 AllowAnotherPtr
= false;
21493 if (const auto *TE
= dyn_cast
<CXXThisExpr
>(E
)) {
21494 Expr::EvalResult ResultR
;
21495 Expr::EvalResult ResultL
;
21496 if (!OASE
->getLength()->isValueDependent() &&
21497 OASE
->getLength()->EvaluateAsInt(ResultR
, SemaRef
.getASTContext()) &&
21498 !ResultR
.Val
.getInt().isOne()) {
21499 SemaRef
.Diag(OASE
->getLength()->getExprLoc(),
21500 diag::err_omp_invalid_map_this_expr
);
21501 SemaRef
.Diag(OASE
->getLength()->getExprLoc(),
21502 diag::note_omp_invalid_length_on_this_ptr_mapping
);
21504 if (OASE
->getLowerBound() && !OASE
->getLowerBound()->isValueDependent() &&
21505 OASE
->getLowerBound()->EvaluateAsInt(ResultL
,
21506 SemaRef
.getASTContext()) &&
21507 !ResultL
.Val
.getInt().isZero()) {
21508 SemaRef
.Diag(OASE
->getLowerBound()->getExprLoc(),
21509 diag::err_omp_invalid_map_this_expr
);
21510 SemaRef
.Diag(OASE
->getLowerBound()->getExprLoc(),
21511 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping
);
21513 assert(!RelevantExpr
&& "RelevantExpr is expected to be nullptr");
21517 // Record the component - we don't have any declaration associated.
21518 Components
.emplace_back(OASE
, nullptr, /*IsNonContiguous=*/false);
21519 return RelevantExpr
|| Visit(E
);
21521 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr
*E
) {
21522 Expr
*Base
= E
->getBase();
21524 // Record the component - we don't have any declaration associated.
21525 Components
.emplace_back(E
, nullptr, IsNonContiguous
);
21527 return Visit(Base
->IgnoreParenImpCasts());
21530 bool VisitUnaryOperator(UnaryOperator
*UO
) {
21531 if (SemaRef
.getLangOpts().OpenMP
< 50 || !UO
->isLValue() ||
21532 UO
->getOpcode() != UO_Deref
) {
21536 if (!RelevantExpr
) {
21537 // Record the component if haven't found base decl.
21538 Components
.emplace_back(UO
, nullptr, /*IsNonContiguous=*/false);
21540 return RelevantExpr
|| Visit(UO
->getSubExpr()->IgnoreParenImpCasts());
21542 bool VisitBinaryOperator(BinaryOperator
*BO
) {
21543 if (SemaRef
.getLangOpts().OpenMP
< 50 || !BO
->getType()->isPointerType()) {
21548 // Pointer arithmetic is the only thing we expect to happen here so after we
21549 // make sure the binary operator is a pointer type, the only thing we need
21550 // to do is to visit the subtree that has the same type as root (so that we
21551 // know the other subtree is just an offset)
21552 Expr
*LE
= BO
->getLHS()->IgnoreParenImpCasts();
21553 Expr
*RE
= BO
->getRHS()->IgnoreParenImpCasts();
21554 Components
.emplace_back(BO
, nullptr, false);
21555 assert((LE
->getType().getTypePtr() == BO
->getType().getTypePtr() ||
21556 RE
->getType().getTypePtr() == BO
->getType().getTypePtr()) &&
21557 "Either LHS or RHS have base decl inside");
21558 if (BO
->getType().getTypePtr() == LE
->getType().getTypePtr())
21559 return RelevantExpr
|| Visit(LE
);
21560 return RelevantExpr
|| Visit(RE
);
21562 bool VisitCXXThisExpr(CXXThisExpr
*CTE
) {
21563 assert(!RelevantExpr
&& "RelevantExpr is expected to be nullptr");
21564 RelevantExpr
= CTE
;
21565 Components
.emplace_back(CTE
, nullptr, IsNonContiguous
);
21568 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr
*COCE
) {
21569 assert(!RelevantExpr
&& "RelevantExpr is expected to be nullptr");
21570 Components
.emplace_back(COCE
, nullptr, IsNonContiguous
);
21573 bool VisitOpaqueValueExpr(OpaqueValueExpr
*E
) {
21574 Expr
*Source
= E
->getSourceExpr();
21579 return Visit(Source
);
21581 bool VisitStmt(Stmt
*) {
21585 const Expr
*getFoundBase() const { return RelevantExpr
; }
21586 explicit MapBaseChecker(
21587 Sema
&SemaRef
, OpenMPClauseKind CKind
, OpenMPDirectiveKind DKind
,
21588 OMPClauseMappableExprCommon::MappableExprComponentList
&Components
,
21589 bool NoDiagnose
, SourceLocation
&ELoc
, SourceRange
&ERange
)
21590 : SemaRef(SemaRef
), CKind(CKind
), DKind(DKind
), Components(Components
),
21591 NoDiagnose(NoDiagnose
), ELoc(ELoc
), ERange(ERange
) {}
21595 /// Return the expression of the base of the mappable expression or null if it
21596 /// cannot be determined and do all the necessary checks to see if the
21597 /// expression is valid as a standalone mappable expression. In the process,
21598 /// record all the components of the expression.
21599 static const Expr
*checkMapClauseExpressionBase(
21600 Sema
&SemaRef
, Expr
*E
,
21601 OMPClauseMappableExprCommon::MappableExprComponentList
&CurComponents
,
21602 OpenMPClauseKind CKind
, OpenMPDirectiveKind DKind
, bool NoDiagnose
) {
21603 SourceLocation ELoc
= E
->getExprLoc();
21604 SourceRange ERange
= E
->getSourceRange();
21605 MapBaseChecker
Checker(SemaRef
, CKind
, DKind
, CurComponents
, NoDiagnose
, ELoc
,
21607 if (Checker
.Visit(E
->IgnoreParens())) {
21608 // Check if the highest dimension array section has length specified
21609 if (SemaRef
.getLangOpts().OpenMP
>= 50 && !CurComponents
.empty() &&
21610 (CKind
== OMPC_to
|| CKind
== OMPC_from
)) {
21611 auto CI
= CurComponents
.rbegin();
21612 auto CE
= CurComponents
.rend();
21613 for (; CI
!= CE
; ++CI
) {
21615 dyn_cast
<OMPArraySectionExpr
>(CI
->getAssociatedExpression());
21618 if (OASE
&& OASE
->getLength())
21620 SemaRef
.Diag(ELoc
, diag::err_array_section_does_not_specify_length
)
21624 return Checker
.getFoundBase();
21629 // Return true if expression E associated with value VD has conflicts with other
21630 // map information.
21631 static bool checkMapConflicts(
21632 Sema
&SemaRef
, DSAStackTy
*DSAS
, const ValueDecl
*VD
, const Expr
*E
,
21633 bool CurrentRegionOnly
,
21634 OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents
,
21635 OpenMPClauseKind CKind
) {
21637 SourceLocation ELoc
= E
->getExprLoc();
21638 SourceRange ERange
= E
->getSourceRange();
21640 // In order to easily check the conflicts we need to match each component of
21641 // the expression under test with the components of the expressions that are
21642 // already in the stack.
21644 assert(!CurComponents
.empty() && "Map clause expression with no components!");
21645 assert(CurComponents
.back().getAssociatedDeclaration() == VD
&&
21646 "Map clause expression with unexpected base!");
21648 // Variables to help detecting enclosing problems in data environment nests.
21649 bool IsEnclosedByDataEnvironmentExpr
= false;
21650 const Expr
*EnclosingExpr
= nullptr;
21652 bool FoundError
= DSAS
->checkMappableExprComponentListsForDecl(
21653 VD
, CurrentRegionOnly
,
21654 [&IsEnclosedByDataEnvironmentExpr
, &SemaRef
, VD
, CurrentRegionOnly
, ELoc
,
21655 ERange
, CKind
, &EnclosingExpr
,
21656 CurComponents
](OMPClauseMappableExprCommon::MappableExprComponentListRef
21658 OpenMPClauseKind Kind
) {
21659 if (CKind
== Kind
&& SemaRef
.LangOpts
.OpenMP
>= 50)
21661 assert(!StackComponents
.empty() &&
21662 "Map clause expression with no components!");
21663 assert(StackComponents
.back().getAssociatedDeclaration() == VD
&&
21664 "Map clause expression with unexpected base!");
21667 // The whole expression in the stack.
21668 const Expr
*RE
= StackComponents
.front().getAssociatedExpression();
21670 // Expressions must start from the same base. Here we detect at which
21671 // point both expressions diverge from each other and see if we can
21672 // detect if the memory referred to both expressions is contiguous and
21674 auto CI
= CurComponents
.rbegin();
21675 auto CE
= CurComponents
.rend();
21676 auto SI
= StackComponents
.rbegin();
21677 auto SE
= StackComponents
.rend();
21678 for (; CI
!= CE
&& SI
!= SE
; ++CI
, ++SI
) {
21680 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
21681 // At most one list item can be an array item derived from a given
21682 // variable in map clauses of the same construct.
21683 if (CurrentRegionOnly
&&
21684 (isa
<ArraySubscriptExpr
>(CI
->getAssociatedExpression()) ||
21685 isa
<OMPArraySectionExpr
>(CI
->getAssociatedExpression()) ||
21686 isa
<OMPArrayShapingExpr
>(CI
->getAssociatedExpression())) &&
21687 (isa
<ArraySubscriptExpr
>(SI
->getAssociatedExpression()) ||
21688 isa
<OMPArraySectionExpr
>(SI
->getAssociatedExpression()) ||
21689 isa
<OMPArrayShapingExpr
>(SI
->getAssociatedExpression()))) {
21690 SemaRef
.Diag(CI
->getAssociatedExpression()->getExprLoc(),
21691 diag::err_omp_multiple_array_items_in_map_clause
)
21692 << CI
->getAssociatedExpression()->getSourceRange();
21693 SemaRef
.Diag(SI
->getAssociatedExpression()->getExprLoc(),
21694 diag::note_used_here
)
21695 << SI
->getAssociatedExpression()->getSourceRange();
21699 // Do both expressions have the same kind?
21700 if (CI
->getAssociatedExpression()->getStmtClass() !=
21701 SI
->getAssociatedExpression()->getStmtClass())
21704 // Are we dealing with different variables/fields?
21705 if (CI
->getAssociatedDeclaration() != SI
->getAssociatedDeclaration())
21708 // Check if the extra components of the expressions in the enclosing
21709 // data environment are redundant for the current base declaration.
21710 // If they are, the maps completely overlap, which is legal.
21711 for (; SI
!= SE
; ++SI
) {
21713 if (const auto *ASE
=
21714 dyn_cast
<ArraySubscriptExpr
>(SI
->getAssociatedExpression())) {
21715 Type
= ASE
->getBase()->IgnoreParenImpCasts()->getType();
21716 } else if (const auto *OASE
= dyn_cast
<OMPArraySectionExpr
>(
21717 SI
->getAssociatedExpression())) {
21718 const Expr
*E
= OASE
->getBase()->IgnoreParenImpCasts();
21720 OMPArraySectionExpr::getBaseOriginalType(E
).getCanonicalType();
21721 } else if (const auto *OASE
= dyn_cast
<OMPArrayShapingExpr
>(
21722 SI
->getAssociatedExpression())) {
21723 Type
= OASE
->getBase()->getType()->getPointeeType();
21725 if (Type
.isNull() || Type
->isAnyPointerType() ||
21726 checkArrayExpressionDoesNotReferToWholeSize(
21727 SemaRef
, SI
->getAssociatedExpression(), Type
))
21731 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21732 // List items of map clauses in the same construct must not share
21733 // original storage.
21735 // If the expressions are exactly the same or one is a subset of the
21736 // other, it means they are sharing storage.
21737 if (CI
== CE
&& SI
== SE
) {
21738 if (CurrentRegionOnly
) {
21739 if (CKind
== OMPC_map
) {
21740 SemaRef
.Diag(ELoc
, diag::err_omp_map_shared_storage
) << ERange
;
21742 assert(CKind
== OMPC_to
|| CKind
== OMPC_from
);
21743 SemaRef
.Diag(ELoc
, diag::err_omp_once_referenced_in_target_update
)
21746 SemaRef
.Diag(RE
->getExprLoc(), diag::note_used_here
)
21747 << RE
->getSourceRange();
21750 // If we find the same expression in the enclosing data environment,
21752 IsEnclosedByDataEnvironmentExpr
= true;
21756 QualType DerivedType
=
21757 std::prev(CI
)->getAssociatedDeclaration()->getType();
21758 SourceLocation DerivedLoc
=
21759 std::prev(CI
)->getAssociatedExpression()->getExprLoc();
21761 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21762 // If the type of a list item is a reference to a type T then the type
21763 // will be considered to be T for all purposes of this clause.
21764 DerivedType
= DerivedType
.getNonReferenceType();
21766 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
21767 // A variable for which the type is pointer and an array section
21768 // derived from that variable must not appear as list items of map
21769 // clauses of the same construct.
21771 // Also, cover one of the cases in:
21772 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21773 // If any part of the original storage of a list item has corresponding
21774 // storage in the device data environment, all of the original storage
21775 // must have corresponding storage in the device data environment.
21777 if (DerivedType
->isAnyPointerType()) {
21778 if (CI
== CE
|| SI
== SE
) {
21781 diag::err_omp_pointer_mapped_along_with_derived_section
)
21783 SemaRef
.Diag(RE
->getExprLoc(), diag::note_used_here
)
21784 << RE
->getSourceRange();
21787 if (CI
->getAssociatedExpression()->getStmtClass() !=
21788 SI
->getAssociatedExpression()->getStmtClass() ||
21789 CI
->getAssociatedDeclaration()->getCanonicalDecl() ==
21790 SI
->getAssociatedDeclaration()->getCanonicalDecl()) {
21791 assert(CI
!= CE
&& SI
!= SE
);
21792 SemaRef
.Diag(DerivedLoc
, diag::err_omp_same_pointer_dereferenced
)
21794 SemaRef
.Diag(RE
->getExprLoc(), diag::note_used_here
)
21795 << RE
->getSourceRange();
21800 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21801 // List items of map clauses in the same construct must not share
21802 // original storage.
21804 // An expression is a subset of the other.
21805 if (CurrentRegionOnly
&& (CI
== CE
|| SI
== SE
)) {
21806 if (CKind
== OMPC_map
) {
21807 if (CI
!= CE
|| SI
!= SE
) {
21808 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
21811 CI
!= CE
? CurComponents
.begin() : StackComponents
.begin();
21812 auto End
= CI
!= CE
? CurComponents
.end() : StackComponents
.end();
21814 while (It
!= End
&& !It
->getAssociatedDeclaration())
21815 std::advance(It
, 1);
21816 assert(It
!= End
&&
21817 "Expected at least one component with the declaration.");
21818 if (It
!= Begin
&& It
->getAssociatedDeclaration()
21820 .getCanonicalType()
21821 ->isAnyPointerType()) {
21822 IsEnclosedByDataEnvironmentExpr
= false;
21823 EnclosingExpr
= nullptr;
21827 SemaRef
.Diag(ELoc
, diag::err_omp_map_shared_storage
) << ERange
;
21829 assert(CKind
== OMPC_to
|| CKind
== OMPC_from
);
21830 SemaRef
.Diag(ELoc
, diag::err_omp_once_referenced_in_target_update
)
21833 SemaRef
.Diag(RE
->getExprLoc(), diag::note_used_here
)
21834 << RE
->getSourceRange();
21838 // The current expression uses the same base as other expression in the
21839 // data environment but does not contain it completely.
21840 if (!CurrentRegionOnly
&& SI
!= SE
)
21841 EnclosingExpr
= RE
;
21843 // The current expression is a subset of the expression in the data
21845 IsEnclosedByDataEnvironmentExpr
|=
21846 (!CurrentRegionOnly
&& CI
!= CE
&& SI
== SE
);
21851 if (CurrentRegionOnly
)
21854 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21855 // If any part of the original storage of a list item has corresponding
21856 // storage in the device data environment, all of the original storage must
21857 // have corresponding storage in the device data environment.
21858 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
21859 // If a list item is an element of a structure, and a different element of
21860 // the structure has a corresponding list item in the device data environment
21861 // prior to a task encountering the construct associated with the map clause,
21862 // then the list item must also have a corresponding list item in the device
21863 // data environment prior to the task encountering the construct.
21865 if (EnclosingExpr
&& !IsEnclosedByDataEnvironmentExpr
) {
21867 diag::err_omp_original_storage_is_shared_and_does_not_contain
)
21869 SemaRef
.Diag(EnclosingExpr
->getExprLoc(), diag::note_used_here
)
21870 << EnclosingExpr
->getSourceRange();
21877 // Look up the user-defined mapper given the mapper name and mapped type, and
21878 // build a reference to it.
21879 static ExprResult
buildUserDefinedMapperRef(Sema
&SemaRef
, Scope
*S
,
21880 CXXScopeSpec
&MapperIdScopeSpec
,
21881 const DeclarationNameInfo
&MapperId
,
21883 Expr
*UnresolvedMapper
) {
21884 if (MapperIdScopeSpec
.isInvalid())
21885 return ExprError();
21886 // Get the actual type for the array type.
21887 if (Type
->isArrayType()) {
21888 assert(Type
->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
21889 Type
= Type
->getAsArrayTypeUnsafe()->getElementType().getCanonicalType();
21891 // Find all user-defined mappers with the given MapperId.
21892 SmallVector
<UnresolvedSet
<8>, 4> Lookups
;
21893 LookupResult
Lookup(SemaRef
, MapperId
, Sema::LookupOMPMapperName
);
21894 Lookup
.suppressDiagnostics();
21896 while (S
&& SemaRef
.LookupParsedName(Lookup
, S
, &MapperIdScopeSpec
)) {
21897 NamedDecl
*D
= Lookup
.getRepresentativeDecl();
21898 while (S
&& !S
->isDeclScope(D
))
21899 S
= S
->getParent();
21901 S
= S
->getParent();
21902 Lookups
.emplace_back();
21903 Lookups
.back().append(Lookup
.begin(), Lookup
.end());
21906 } else if (auto *ULE
= cast_or_null
<UnresolvedLookupExpr
>(UnresolvedMapper
)) {
21907 // Extract the user-defined mappers with the given MapperId.
21908 Lookups
.push_back(UnresolvedSet
<8>());
21909 for (NamedDecl
*D
: ULE
->decls()) {
21910 auto *DMD
= cast
<OMPDeclareMapperDecl
>(D
);
21911 assert(DMD
&& "Expect valid OMPDeclareMapperDecl during instantiation.");
21912 Lookups
.back().addDecl(DMD
);
21915 // Defer the lookup for dependent types. The results will be passed through
21916 // UnresolvedMapper on instantiation.
21917 if (SemaRef
.CurContext
->isDependentContext() || Type
->isDependentType() ||
21918 Type
->isInstantiationDependentType() ||
21919 Type
->containsUnexpandedParameterPack() ||
21920 filterLookupForUDReductionAndMapper
<bool>(Lookups
, [](ValueDecl
*D
) {
21921 return !D
->isInvalidDecl() &&
21922 (D
->getType()->isDependentType() ||
21923 D
->getType()->isInstantiationDependentType() ||
21924 D
->getType()->containsUnexpandedParameterPack());
21926 UnresolvedSet
<8> URS
;
21927 for (const UnresolvedSet
<8> &Set
: Lookups
) {
21930 URS
.append(Set
.begin(), Set
.end());
21932 return UnresolvedLookupExpr::Create(
21933 SemaRef
.Context
, /*NamingClass=*/nullptr,
21934 MapperIdScopeSpec
.getWithLocInContext(SemaRef
.Context
), MapperId
,
21935 /*ADL=*/false, /*Overloaded=*/true, URS
.begin(), URS
.end());
21937 SourceLocation Loc
= MapperId
.getLoc();
21938 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21939 // The type must be of struct, union or class type in C and C++
21940 if (!Type
->isStructureOrClassType() && !Type
->isUnionType() &&
21941 (MapperIdScopeSpec
.isSet() || MapperId
.getAsString() != "default")) {
21942 SemaRef
.Diag(Loc
, diag::err_omp_mapper_wrong_type
);
21943 return ExprError();
21945 // Perform argument dependent lookup.
21946 if (SemaRef
.getLangOpts().CPlusPlus
&& !MapperIdScopeSpec
.isSet())
21947 argumentDependentLookup(SemaRef
, MapperId
, Loc
, Type
, Lookups
);
21948 // Return the first user-defined mapper with the desired type.
21949 if (auto *VD
= filterLookupForUDReductionAndMapper
<ValueDecl
*>(
21950 Lookups
, [&SemaRef
, Type
](ValueDecl
*D
) -> ValueDecl
* {
21951 if (!D
->isInvalidDecl() &&
21952 SemaRef
.Context
.hasSameType(D
->getType(), Type
))
21956 return SemaRef
.BuildDeclRefExpr(VD
, Type
, VK_LValue
, Loc
);
21957 // Find the first user-defined mapper with a type derived from the desired
21959 if (auto *VD
= filterLookupForUDReductionAndMapper
<ValueDecl
*>(
21960 Lookups
, [&SemaRef
, Type
, Loc
](ValueDecl
*D
) -> ValueDecl
* {
21961 if (!D
->isInvalidDecl() &&
21962 SemaRef
.IsDerivedFrom(Loc
, Type
, D
->getType()) &&
21963 !Type
.isMoreQualifiedThan(D
->getType()))
21967 CXXBasePaths
Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
21968 /*DetectVirtual=*/false);
21969 if (SemaRef
.IsDerivedFrom(Loc
, Type
, VD
->getType(), Paths
)) {
21970 if (!Paths
.isAmbiguous(SemaRef
.Context
.getCanonicalType(
21971 VD
->getType().getUnqualifiedType()))) {
21972 if (SemaRef
.CheckBaseClassAccess(
21973 Loc
, VD
->getType(), Type
, Paths
.front(),
21974 /*DiagID=*/0) != Sema::AR_inaccessible
) {
21975 return SemaRef
.BuildDeclRefExpr(VD
, Type
, VK_LValue
, Loc
);
21980 // Report error if a mapper is specified, but cannot be found.
21981 if (MapperIdScopeSpec
.isSet() || MapperId
.getAsString() != "default") {
21982 SemaRef
.Diag(Loc
, diag::err_omp_invalid_mapper
)
21983 << Type
<< MapperId
.getName();
21984 return ExprError();
21986 return ExprEmpty();
21990 // Utility struct that gathers all the related lists associated with a mappable
21992 struct MappableVarListInfo
{
21993 // The list of expressions.
21994 ArrayRef
<Expr
*> VarList
;
21995 // The list of processed expressions.
21996 SmallVector
<Expr
*, 16> ProcessedVarList
;
21997 // The mappble components for each expression.
21998 OMPClauseMappableExprCommon::MappableExprComponentLists VarComponents
;
21999 // The base declaration of the variable.
22000 SmallVector
<ValueDecl
*, 16> VarBaseDeclarations
;
22001 // The reference to the user-defined mapper associated with every expression.
22002 SmallVector
<Expr
*, 16> UDMapperList
;
22004 MappableVarListInfo(ArrayRef
<Expr
*> VarList
) : VarList(VarList
) {
22005 // We have a list of components and base declarations for each entry in the
22007 VarComponents
.reserve(VarList
.size());
22008 VarBaseDeclarations
.reserve(VarList
.size());
22013 // Check the validity of the provided variable list for the provided clause kind
22014 // \a CKind. In the check process the valid expressions, mappable expression
22015 // components, variables, and user-defined mappers are extracted and used to
22016 // fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
22017 // UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
22018 // and \a MapperId are expected to be valid if the clause kind is 'map'.
22019 static void checkMappableExpressionList(
22020 Sema
&SemaRef
, DSAStackTy
*DSAS
, OpenMPClauseKind CKind
,
22021 MappableVarListInfo
&MVLI
, SourceLocation StartLoc
,
22022 CXXScopeSpec
&MapperIdScopeSpec
, DeclarationNameInfo MapperId
,
22023 ArrayRef
<Expr
*> UnresolvedMappers
,
22024 OpenMPMapClauseKind MapType
= OMPC_MAP_unknown
,
22025 ArrayRef
<OpenMPMapModifierKind
> Modifiers
= std::nullopt
,
22026 bool IsMapTypeImplicit
= false, bool NoDiagnose
= false) {
22027 // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
22028 assert((CKind
== OMPC_map
|| CKind
== OMPC_to
|| CKind
== OMPC_from
) &&
22029 "Unexpected clause kind with mappable expressions!");
22031 // If the identifier of user-defined mapper is not specified, it is "default".
22032 // We do not change the actual name in this clause to distinguish whether a
22033 // mapper is specified explicitly, i.e., it is not explicitly specified when
22034 // MapperId.getName() is empty.
22035 if (!MapperId
.getName() || MapperId
.getName().isEmpty()) {
22036 auto &DeclNames
= SemaRef
.getASTContext().DeclarationNames
;
22037 MapperId
.setName(DeclNames
.getIdentifier(
22038 &SemaRef
.getASTContext().Idents
.get("default")));
22039 MapperId
.setLoc(StartLoc
);
22042 // Iterators to find the current unresolved mapper expression.
22043 auto UMIt
= UnresolvedMappers
.begin(), UMEnd
= UnresolvedMappers
.end();
22044 bool UpdateUMIt
= false;
22045 Expr
*UnresolvedMapper
= nullptr;
22047 bool HasHoldModifier
=
22048 llvm::is_contained(Modifiers
, OMPC_MAP_MODIFIER_ompx_hold
);
22050 // Keep track of the mappable components and base declarations in this clause.
22051 // Each entry in the list is going to have a list of components associated. We
22052 // record each set of the components so that we can build the clause later on.
22053 // In the end we should have the same amount of declarations and component
22056 for (Expr
*RE
: MVLI
.VarList
) {
22057 assert(RE
&& "Null expr in omp to/from/map clause");
22058 SourceLocation ELoc
= RE
->getExprLoc();
22060 // Find the current unresolved mapper expression.
22061 if (UpdateUMIt
&& UMIt
!= UMEnd
) {
22065 "Expect the size of UnresolvedMappers to match with that of VarList");
22069 UnresolvedMapper
= *UMIt
;
22071 const Expr
*VE
= RE
->IgnoreParenLValueCasts();
22073 if (VE
->isValueDependent() || VE
->isTypeDependent() ||
22074 VE
->isInstantiationDependent() ||
22075 VE
->containsUnexpandedParameterPack()) {
22076 // Try to find the associated user-defined mapper.
22077 ExprResult ER
= buildUserDefinedMapperRef(
22078 SemaRef
, DSAS
->getCurScope(), MapperIdScopeSpec
, MapperId
,
22079 VE
->getType().getCanonicalType(), UnresolvedMapper
);
22080 if (ER
.isInvalid())
22082 MVLI
.UDMapperList
.push_back(ER
.get());
22083 // We can only analyze this information once the missing information is
22085 MVLI
.ProcessedVarList
.push_back(RE
);
22089 Expr
*SimpleExpr
= RE
->IgnoreParenCasts();
22091 if (!RE
->isLValue()) {
22092 if (SemaRef
.getLangOpts().OpenMP
< 50) {
22094 ELoc
, diag::err_omp_expected_named_var_member_or_array_expression
)
22095 << RE
->getSourceRange();
22097 SemaRef
.Diag(ELoc
, diag::err_omp_non_lvalue_in_map_or_motion_clauses
)
22098 << getOpenMPClauseName(CKind
) << RE
->getSourceRange();
22103 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents
;
22104 ValueDecl
*CurDeclaration
= nullptr;
22106 // Obtain the array or member expression bases if required. Also, fill the
22107 // components array with all the components identified in the process.
22109 checkMapClauseExpressionBase(SemaRef
, SimpleExpr
, CurComponents
, CKind
,
22110 DSAS
->getCurrentDirective(), NoDiagnose
);
22114 assert(!CurComponents
.empty() &&
22115 "Invalid mappable expression information.");
22117 if (const auto *TE
= dyn_cast
<CXXThisExpr
>(BE
)) {
22118 // Add store "this" pointer to class in DSAStackTy for future checking
22119 DSAS
->addMappedClassesQualTypes(TE
->getType());
22120 // Try to find the associated user-defined mapper.
22121 ExprResult ER
= buildUserDefinedMapperRef(
22122 SemaRef
, DSAS
->getCurScope(), MapperIdScopeSpec
, MapperId
,
22123 VE
->getType().getCanonicalType(), UnresolvedMapper
);
22124 if (ER
.isInvalid())
22126 MVLI
.UDMapperList
.push_back(ER
.get());
22127 // Skip restriction checking for variable or field declarations
22128 MVLI
.ProcessedVarList
.push_back(RE
);
22129 MVLI
.VarComponents
.resize(MVLI
.VarComponents
.size() + 1);
22130 MVLI
.VarComponents
.back().append(CurComponents
.begin(),
22131 CurComponents
.end());
22132 MVLI
.VarBaseDeclarations
.push_back(nullptr);
22136 // For the following checks, we rely on the base declaration which is
22137 // expected to be associated with the last component. The declaration is
22138 // expected to be a variable or a field (if 'this' is being mapped).
22139 CurDeclaration
= CurComponents
.back().getAssociatedDeclaration();
22140 assert(CurDeclaration
&& "Null decl on map clause.");
22142 CurDeclaration
->isCanonicalDecl() &&
22143 "Expecting components to have associated only canonical declarations.");
22145 auto *VD
= dyn_cast
<VarDecl
>(CurDeclaration
);
22146 const auto *FD
= dyn_cast
<FieldDecl
>(CurDeclaration
);
22148 assert((VD
|| FD
) && "Only variables or fields are expected here!");
22151 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
22152 // threadprivate variables cannot appear in a map clause.
22153 // OpenMP 4.5 [2.10.5, target update Construct]
22154 // threadprivate variables cannot appear in a from clause.
22155 if (VD
&& DSAS
->isThreadPrivate(VD
)) {
22158 DSAStackTy::DSAVarData DVar
= DSAS
->getTopDSA(VD
, /*FromParent=*/false);
22159 SemaRef
.Diag(ELoc
, diag::err_omp_threadprivate_in_clause
)
22160 << getOpenMPClauseName(CKind
);
22161 reportOriginalDsa(SemaRef
, DSAS
, VD
, DVar
);
22165 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
22166 // A list item cannot appear in both a map clause and a data-sharing
22167 // attribute clause on the same construct.
22169 // Check conflicts with other map clause expressions. We check the conflicts
22170 // with the current construct separately from the enclosing data
22171 // environment, because the restrictions are different. We only have to
22172 // check conflicts across regions for the map clauses.
22173 if (checkMapConflicts(SemaRef
, DSAS
, CurDeclaration
, SimpleExpr
,
22174 /*CurrentRegionOnly=*/true, CurComponents
, CKind
))
22176 if (CKind
== OMPC_map
&&
22177 (SemaRef
.getLangOpts().OpenMP
<= 45 || StartLoc
.isValid()) &&
22178 checkMapConflicts(SemaRef
, DSAS
, CurDeclaration
, SimpleExpr
,
22179 /*CurrentRegionOnly=*/false, CurComponents
, CKind
))
22182 // OpenMP 4.5 [2.10.5, target update Construct]
22183 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22184 // If the type of a list item is a reference to a type T then the type will
22185 // be considered to be T for all purposes of this clause.
22186 auto I
= llvm::find_if(
22188 [](const OMPClauseMappableExprCommon::MappableComponent
&MC
) {
22189 return MC
.getAssociatedDeclaration();
22191 assert(I
!= CurComponents
.end() && "Null decl on map clause.");
22194 auto *ASE
= dyn_cast
<ArraySubscriptExpr
>(VE
->IgnoreParens());
22195 auto *OASE
= dyn_cast
<OMPArraySectionExpr
>(VE
->IgnoreParens());
22196 auto *OAShE
= dyn_cast
<OMPArrayShapingExpr
>(VE
->IgnoreParens());
22198 Type
= ASE
->getType().getNonReferenceType();
22200 QualType BaseType
=
22201 OMPArraySectionExpr::getBaseOriginalType(OASE
->getBase());
22202 if (const auto *ATy
= BaseType
->getAsArrayTypeUnsafe())
22203 Type
= ATy
->getElementType();
22205 Type
= BaseType
->getPointeeType();
22206 Type
= Type
.getNonReferenceType();
22207 } else if (OAShE
) {
22208 Type
= OAShE
->getBase()->getType()->getPointeeType();
22210 Type
= VE
->getType();
22213 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
22214 // A list item in a to or from clause must have a mappable type.
22215 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
22216 // A list item must have a mappable type.
22217 if (!checkTypeMappable(VE
->getExprLoc(), VE
->getSourceRange(), SemaRef
,
22218 DSAS
, Type
, /*FullCheck=*/true))
22221 if (CKind
== OMPC_map
) {
22222 // target enter data
22223 // OpenMP [2.10.2, Restrictions, p. 99]
22224 // A map-type must be specified in all map clauses and must be either
22225 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
22226 // no map type is present.
22227 OpenMPDirectiveKind DKind
= DSAS
->getCurrentDirective();
22228 if (DKind
== OMPD_target_enter_data
&&
22229 !(MapType
== OMPC_MAP_to
|| MapType
== OMPC_MAP_alloc
||
22230 SemaRef
.getLangOpts().OpenMP
>= 52)) {
22231 SemaRef
.Diag(StartLoc
, diag::err_omp_invalid_map_type_for_directive
)
22232 << (IsMapTypeImplicit
? 1 : 0)
22233 << getOpenMPSimpleClauseTypeName(OMPC_map
, MapType
)
22234 << getOpenMPDirectiveName(DKind
);
22238 // target exit_data
22239 // OpenMP [2.10.3, Restrictions, p. 102]
22240 // A map-type must be specified in all map clauses and must be either
22241 // from, release, or delete. Starting with OpenMP 5.2 the default map
22242 // type is `from` if no map type is present.
22243 if (DKind
== OMPD_target_exit_data
&&
22244 !(MapType
== OMPC_MAP_from
|| MapType
== OMPC_MAP_release
||
22245 MapType
== OMPC_MAP_delete
|| SemaRef
.getLangOpts().OpenMP
>= 52)) {
22246 SemaRef
.Diag(StartLoc
, diag::err_omp_invalid_map_type_for_directive
)
22247 << (IsMapTypeImplicit
? 1 : 0)
22248 << getOpenMPSimpleClauseTypeName(OMPC_map
, MapType
)
22249 << getOpenMPDirectiveName(DKind
);
22253 // The 'ompx_hold' modifier is specifically intended to be used on a
22254 // 'target' or 'target data' directive to prevent data from being unmapped
22255 // during the associated statement. It is not permitted on a 'target
22256 // enter data' or 'target exit data' directive, which have no associated
22258 if ((DKind
== OMPD_target_enter_data
|| DKind
== OMPD_target_exit_data
) &&
22260 SemaRef
.Diag(StartLoc
,
22261 diag::err_omp_invalid_map_type_modifier_for_directive
)
22262 << getOpenMPSimpleClauseTypeName(OMPC_map
,
22263 OMPC_MAP_MODIFIER_ompx_hold
)
22264 << getOpenMPDirectiveName(DKind
);
22268 // target, target data
22269 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
22270 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
22271 // A map-type in a map clause must be to, from, tofrom or alloc
22272 if ((DKind
== OMPD_target_data
||
22273 isOpenMPTargetExecutionDirective(DKind
)) &&
22274 !(MapType
== OMPC_MAP_to
|| MapType
== OMPC_MAP_from
||
22275 MapType
== OMPC_MAP_tofrom
|| MapType
== OMPC_MAP_alloc
)) {
22276 SemaRef
.Diag(StartLoc
, diag::err_omp_invalid_map_type_for_directive
)
22277 << (IsMapTypeImplicit
? 1 : 0)
22278 << getOpenMPSimpleClauseTypeName(OMPC_map
, MapType
)
22279 << getOpenMPDirectiveName(DKind
);
22283 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
22284 // A list item cannot appear in both a map clause and a data-sharing
22285 // attribute clause on the same construct
22287 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
22288 // A list item cannot appear in both a map clause and a data-sharing
22289 // attribute clause on the same construct unless the construct is a
22290 // combined construct.
22291 if (VD
&& ((SemaRef
.LangOpts
.OpenMP
<= 45 &&
22292 isOpenMPTargetExecutionDirective(DKind
)) ||
22293 DKind
== OMPD_target
)) {
22294 DSAStackTy::DSAVarData DVar
= DSAS
->getTopDSA(VD
, /*FromParent=*/false);
22295 if (isOpenMPPrivate(DVar
.CKind
)) {
22296 SemaRef
.Diag(ELoc
, diag::err_omp_variable_in_given_clause_and_dsa
)
22297 << getOpenMPClauseName(DVar
.CKind
)
22298 << getOpenMPClauseName(OMPC_map
)
22299 << getOpenMPDirectiveName(DSAS
->getCurrentDirective());
22300 reportOriginalDsa(SemaRef
, DSAS
, CurDeclaration
, DVar
);
22306 // Try to find the associated user-defined mapper.
22307 ExprResult ER
= buildUserDefinedMapperRef(
22308 SemaRef
, DSAS
->getCurScope(), MapperIdScopeSpec
, MapperId
,
22309 Type
.getCanonicalType(), UnresolvedMapper
);
22310 if (ER
.isInvalid())
22312 MVLI
.UDMapperList
.push_back(ER
.get());
22314 // Save the current expression.
22315 MVLI
.ProcessedVarList
.push_back(RE
);
22317 // Store the components in the stack so that they can be used to check
22318 // against other clauses later on.
22319 DSAS
->addMappableExpressionComponents(CurDeclaration
, CurComponents
,
22320 /*WhereFoundClauseKind=*/OMPC_map
);
22322 // Save the components and declaration to create the clause. For purposes of
22323 // the clause creation, any component list that has base 'this' uses
22324 // null as base declaration.
22325 MVLI
.VarComponents
.resize(MVLI
.VarComponents
.size() + 1);
22326 MVLI
.VarComponents
.back().append(CurComponents
.begin(),
22327 CurComponents
.end());
22328 MVLI
.VarBaseDeclarations
.push_back(isa
<MemberExpr
>(BE
) ? nullptr
22333 OMPClause
*Sema::ActOnOpenMPMapClause(
22334 Expr
*IteratorModifier
, ArrayRef
<OpenMPMapModifierKind
> MapTypeModifiers
,
22335 ArrayRef
<SourceLocation
> MapTypeModifiersLoc
,
22336 CXXScopeSpec
&MapperIdScopeSpec
, DeclarationNameInfo
&MapperId
,
22337 OpenMPMapClauseKind MapType
, bool IsMapTypeImplicit
, SourceLocation MapLoc
,
22338 SourceLocation ColonLoc
, ArrayRef
<Expr
*> VarList
,
22339 const OMPVarListLocTy
&Locs
, bool NoDiagnose
,
22340 ArrayRef
<Expr
*> UnresolvedMappers
) {
22341 OpenMPMapModifierKind Modifiers
[] = {
22342 OMPC_MAP_MODIFIER_unknown
, OMPC_MAP_MODIFIER_unknown
,
22343 OMPC_MAP_MODIFIER_unknown
, OMPC_MAP_MODIFIER_unknown
,
22344 OMPC_MAP_MODIFIER_unknown
, OMPC_MAP_MODIFIER_unknown
};
22345 SourceLocation ModifiersLoc
[NumberOfOMPMapClauseModifiers
];
22347 if (IteratorModifier
&& !IteratorModifier
->getType()->isSpecificBuiltinType(
22348 BuiltinType::OMPIterator
))
22349 Diag(IteratorModifier
->getExprLoc(),
22350 diag::err_omp_map_modifier_not_iterator
);
22352 // Process map-type-modifiers, flag errors for duplicate modifiers.
22353 unsigned Count
= 0;
22354 for (unsigned I
= 0, E
= MapTypeModifiers
.size(); I
< E
; ++I
) {
22355 if (MapTypeModifiers
[I
] != OMPC_MAP_MODIFIER_unknown
&&
22356 llvm::is_contained(Modifiers
, MapTypeModifiers
[I
])) {
22357 Diag(MapTypeModifiersLoc
[I
], diag::err_omp_duplicate_map_type_modifier
);
22360 assert(Count
< NumberOfOMPMapClauseModifiers
&&
22361 "Modifiers exceed the allowed number of map type modifiers");
22362 Modifiers
[Count
] = MapTypeModifiers
[I
];
22363 ModifiersLoc
[Count
] = MapTypeModifiersLoc
[I
];
22367 MappableVarListInfo
MVLI(VarList
);
22368 checkMappableExpressionList(*this, DSAStack
, OMPC_map
, MVLI
, Locs
.StartLoc
,
22369 MapperIdScopeSpec
, MapperId
, UnresolvedMappers
,
22370 MapType
, Modifiers
, IsMapTypeImplicit
,
22373 // We need to produce a map clause even if we don't have variables so that
22374 // other diagnostics related with non-existing map clauses are accurate.
22375 return OMPMapClause::Create(
22376 Context
, Locs
, MVLI
.ProcessedVarList
, MVLI
.VarBaseDeclarations
,
22377 MVLI
.VarComponents
, MVLI
.UDMapperList
, IteratorModifier
, Modifiers
,
22378 ModifiersLoc
, MapperIdScopeSpec
.getWithLocInContext(Context
), MapperId
,
22379 MapType
, IsMapTypeImplicit
, MapLoc
);
22382 QualType
Sema::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc
,
22383 TypeResult ParsedType
) {
22384 assert(ParsedType
.isUsable());
22386 QualType ReductionType
= GetTypeFromParser(ParsedType
.get());
22387 if (ReductionType
.isNull())
22390 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
22391 // A type name in a declare reduction directive cannot be a function type, an
22392 // array type, a reference type, or a type qualified with const, volatile or
22394 if (ReductionType
.hasQualifiers()) {
22395 Diag(TyLoc
, diag::err_omp_reduction_wrong_type
) << 0;
22399 if (ReductionType
->isFunctionType()) {
22400 Diag(TyLoc
, diag::err_omp_reduction_wrong_type
) << 1;
22403 if (ReductionType
->isReferenceType()) {
22404 Diag(TyLoc
, diag::err_omp_reduction_wrong_type
) << 2;
22407 if (ReductionType
->isArrayType()) {
22408 Diag(TyLoc
, diag::err_omp_reduction_wrong_type
) << 3;
22411 return ReductionType
;
22414 Sema::DeclGroupPtrTy
Sema::ActOnOpenMPDeclareReductionDirectiveStart(
22415 Scope
*S
, DeclContext
*DC
, DeclarationName Name
,
22416 ArrayRef
<std::pair
<QualType
, SourceLocation
>> ReductionTypes
,
22417 AccessSpecifier AS
, Decl
*PrevDeclInScope
) {
22418 SmallVector
<Decl
*, 8> Decls
;
22419 Decls
.reserve(ReductionTypes
.size());
22421 LookupResult
Lookup(*this, Name
, SourceLocation(), LookupOMPReductionName
,
22422 forRedeclarationInCurContext());
22423 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
22424 // A reduction-identifier may not be re-declared in the current scope for the
22425 // same type or for a type that is compatible according to the base language
22427 llvm::DenseMap
<QualType
, SourceLocation
> PreviousRedeclTypes
;
22428 OMPDeclareReductionDecl
*PrevDRD
= nullptr;
22429 bool InCompoundScope
= true;
22430 if (S
!= nullptr) {
22431 // Find previous declaration with the same name not referenced in other
22433 FunctionScopeInfo
*ParentFn
= getEnclosingFunction();
22435 (ParentFn
!= nullptr) && !ParentFn
->CompoundScopes
.empty();
22436 LookupName(Lookup
, S
);
22437 FilterLookupForScope(Lookup
, DC
, S
, /*ConsiderLinkage=*/false,
22438 /*AllowInlineNamespace=*/false);
22439 llvm::DenseMap
<OMPDeclareReductionDecl
*, bool> UsedAsPrevious
;
22440 LookupResult::Filter Filter
= Lookup
.makeFilter();
22441 while (Filter
.hasNext()) {
22442 auto *PrevDecl
= cast
<OMPDeclareReductionDecl
>(Filter
.next());
22443 if (InCompoundScope
) {
22444 auto I
= UsedAsPrevious
.find(PrevDecl
);
22445 if (I
== UsedAsPrevious
.end())
22446 UsedAsPrevious
[PrevDecl
] = false;
22447 if (OMPDeclareReductionDecl
*D
= PrevDecl
->getPrevDeclInScope())
22448 UsedAsPrevious
[D
] = true;
22450 PreviousRedeclTypes
[PrevDecl
->getType().getCanonicalType()] =
22451 PrevDecl
->getLocation();
22454 if (InCompoundScope
) {
22455 for (const auto &PrevData
: UsedAsPrevious
) {
22456 if (!PrevData
.second
) {
22457 PrevDRD
= PrevData
.first
;
22462 } else if (PrevDeclInScope
!= nullptr) {
22463 auto *PrevDRDInScope
= PrevDRD
=
22464 cast
<OMPDeclareReductionDecl
>(PrevDeclInScope
);
22466 PreviousRedeclTypes
[PrevDRDInScope
->getType().getCanonicalType()] =
22467 PrevDRDInScope
->getLocation();
22468 PrevDRDInScope
= PrevDRDInScope
->getPrevDeclInScope();
22469 } while (PrevDRDInScope
!= nullptr);
22471 for (const auto &TyData
: ReductionTypes
) {
22472 const auto I
= PreviousRedeclTypes
.find(TyData
.first
.getCanonicalType());
22473 bool Invalid
= false;
22474 if (I
!= PreviousRedeclTypes
.end()) {
22475 Diag(TyData
.second
, diag::err_omp_declare_reduction_redefinition
)
22477 Diag(I
->second
, diag::note_previous_definition
);
22480 PreviousRedeclTypes
[TyData
.first
.getCanonicalType()] = TyData
.second
;
22481 auto *DRD
= OMPDeclareReductionDecl::Create(Context
, DC
, TyData
.second
,
22482 Name
, TyData
.first
, PrevDRD
);
22484 DRD
->setAccess(AS
);
22485 Decls
.push_back(DRD
);
22487 DRD
->setInvalidDecl();
22492 return DeclGroupPtrTy::make(
22493 DeclGroupRef::Create(Context
, Decls
.begin(), Decls
.size()));
22496 void Sema::ActOnOpenMPDeclareReductionCombinerStart(Scope
*S
, Decl
*D
) {
22497 auto *DRD
= cast
<OMPDeclareReductionDecl
>(D
);
22499 // Enter new function scope.
22500 PushFunctionScope();
22501 setFunctionHasBranchProtectedScope();
22502 getCurFunction()->setHasOMPDeclareReductionCombiner();
22505 PushDeclContext(S
, DRD
);
22509 PushExpressionEvaluationContext(
22510 ExpressionEvaluationContext::PotentiallyEvaluated
);
22512 QualType ReductionType
= DRD
->getType();
22513 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
22514 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
22515 // uses semantics of argument handles by value, but it should be passed by
22516 // reference. C lang does not support references, so pass all parameters as
22518 // Create 'T omp_in;' variable.
22519 VarDecl
*OmpInParm
=
22520 buildVarDecl(*this, D
->getLocation(), ReductionType
, "omp_in");
22521 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
22522 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
22523 // uses semantics of argument handles by value, but it should be passed by
22524 // reference. C lang does not support references, so pass all parameters as
22526 // Create 'T omp_out;' variable.
22527 VarDecl
*OmpOutParm
=
22528 buildVarDecl(*this, D
->getLocation(), ReductionType
, "omp_out");
22529 if (S
!= nullptr) {
22530 PushOnScopeChains(OmpInParm
, S
);
22531 PushOnScopeChains(OmpOutParm
, S
);
22533 DRD
->addDecl(OmpInParm
);
22534 DRD
->addDecl(OmpOutParm
);
22537 ::buildDeclRefExpr(*this, OmpInParm
, ReductionType
, D
->getLocation());
22539 ::buildDeclRefExpr(*this, OmpOutParm
, ReductionType
, D
->getLocation());
22540 DRD
->setCombinerData(InE
, OutE
);
22543 void Sema::ActOnOpenMPDeclareReductionCombinerEnd(Decl
*D
, Expr
*Combiner
) {
22544 auto *DRD
= cast
<OMPDeclareReductionDecl
>(D
);
22545 DiscardCleanupsInEvaluationContext();
22546 PopExpressionEvaluationContext();
22549 PopFunctionScopeInfo();
22551 if (Combiner
!= nullptr)
22552 DRD
->setCombiner(Combiner
);
22554 DRD
->setInvalidDecl();
22557 VarDecl
*Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope
*S
, Decl
*D
) {
22558 auto *DRD
= cast
<OMPDeclareReductionDecl
>(D
);
22560 // Enter new function scope.
22561 PushFunctionScope();
22562 setFunctionHasBranchProtectedScope();
22565 PushDeclContext(S
, DRD
);
22569 PushExpressionEvaluationContext(
22570 ExpressionEvaluationContext::PotentiallyEvaluated
);
22572 QualType ReductionType
= DRD
->getType();
22573 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
22574 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
22575 // uses semantics of argument handles by value, but it should be passed by
22576 // reference. C lang does not support references, so pass all parameters as
22578 // Create 'T omp_priv;' variable.
22579 VarDecl
*OmpPrivParm
=
22580 buildVarDecl(*this, D
->getLocation(), ReductionType
, "omp_priv");
22581 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
22582 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
22583 // uses semantics of argument handles by value, but it should be passed by
22584 // reference. C lang does not support references, so pass all parameters as
22586 // Create 'T omp_orig;' variable.
22587 VarDecl
*OmpOrigParm
=
22588 buildVarDecl(*this, D
->getLocation(), ReductionType
, "omp_orig");
22589 if (S
!= nullptr) {
22590 PushOnScopeChains(OmpPrivParm
, S
);
22591 PushOnScopeChains(OmpOrigParm
, S
);
22593 DRD
->addDecl(OmpPrivParm
);
22594 DRD
->addDecl(OmpOrigParm
);
22597 ::buildDeclRefExpr(*this, OmpOrigParm
, ReductionType
, D
->getLocation());
22599 ::buildDeclRefExpr(*this, OmpPrivParm
, ReductionType
, D
->getLocation());
22600 DRD
->setInitializerData(OrigE
, PrivE
);
22601 return OmpPrivParm
;
22604 void Sema::ActOnOpenMPDeclareReductionInitializerEnd(Decl
*D
, Expr
*Initializer
,
22605 VarDecl
*OmpPrivParm
) {
22606 auto *DRD
= cast
<OMPDeclareReductionDecl
>(D
);
22607 DiscardCleanupsInEvaluationContext();
22608 PopExpressionEvaluationContext();
22611 PopFunctionScopeInfo();
22613 if (Initializer
!= nullptr) {
22614 DRD
->setInitializer(Initializer
, OMPDeclareReductionInitKind::Call
);
22615 } else if (OmpPrivParm
->hasInit()) {
22616 DRD
->setInitializer(OmpPrivParm
->getInit(),
22617 OmpPrivParm
->isDirectInit()
22618 ? OMPDeclareReductionInitKind::Direct
22619 : OMPDeclareReductionInitKind::Copy
);
22621 DRD
->setInvalidDecl();
22625 Sema::DeclGroupPtrTy
Sema::ActOnOpenMPDeclareReductionDirectiveEnd(
22626 Scope
*S
, DeclGroupPtrTy DeclReductions
, bool IsValid
) {
22627 for (Decl
*D
: DeclReductions
.get()) {
22630 PushOnScopeChains(cast
<OMPDeclareReductionDecl
>(D
), S
,
22631 /*AddToContext=*/false);
22633 D
->setInvalidDecl();
22636 return DeclReductions
;
22639 TypeResult
Sema::ActOnOpenMPDeclareMapperVarDecl(Scope
*S
, Declarator
&D
) {
22640 TypeSourceInfo
*TInfo
= GetTypeForDeclarator(D
, S
);
22641 QualType T
= TInfo
->getType();
22642 if (D
.isInvalidType())
22645 if (getLangOpts().CPlusPlus
) {
22646 // Check that there are no default arguments (C++ only).
22647 CheckExtraCXXDefaultArguments(D
);
22650 return CreateParsedType(T
, TInfo
);
22653 QualType
Sema::ActOnOpenMPDeclareMapperType(SourceLocation TyLoc
,
22654 TypeResult ParsedType
) {
22655 assert(ParsedType
.isUsable() && "Expect usable parsed mapper type");
22657 QualType MapperType
= GetTypeFromParser(ParsedType
.get());
22658 assert(!MapperType
.isNull() && "Expect valid mapper type");
22660 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22661 // The type must be of struct, union or class type in C and C++
22662 if (!MapperType
->isStructureOrClassType() && !MapperType
->isUnionType()) {
22663 Diag(TyLoc
, diag::err_omp_mapper_wrong_type
);
22669 Sema::DeclGroupPtrTy
Sema::ActOnOpenMPDeclareMapperDirective(
22670 Scope
*S
, DeclContext
*DC
, DeclarationName Name
, QualType MapperType
,
22671 SourceLocation StartLoc
, DeclarationName VN
, AccessSpecifier AS
,
22672 Expr
*MapperVarRef
, ArrayRef
<OMPClause
*> Clauses
, Decl
*PrevDeclInScope
) {
22673 LookupResult
Lookup(*this, Name
, SourceLocation(), LookupOMPMapperName
,
22674 forRedeclarationInCurContext());
22675 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22676 // A mapper-identifier may not be redeclared in the current scope for the
22677 // same type or for a type that is compatible according to the base language
22679 llvm::DenseMap
<QualType
, SourceLocation
> PreviousRedeclTypes
;
22680 OMPDeclareMapperDecl
*PrevDMD
= nullptr;
22681 bool InCompoundScope
= true;
22682 if (S
!= nullptr) {
22683 // Find previous declaration with the same name not referenced in other
22685 FunctionScopeInfo
*ParentFn
= getEnclosingFunction();
22687 (ParentFn
!= nullptr) && !ParentFn
->CompoundScopes
.empty();
22688 LookupName(Lookup
, S
);
22689 FilterLookupForScope(Lookup
, DC
, S
, /*ConsiderLinkage=*/false,
22690 /*AllowInlineNamespace=*/false);
22691 llvm::DenseMap
<OMPDeclareMapperDecl
*, bool> UsedAsPrevious
;
22692 LookupResult::Filter Filter
= Lookup
.makeFilter();
22693 while (Filter
.hasNext()) {
22694 auto *PrevDecl
= cast
<OMPDeclareMapperDecl
>(Filter
.next());
22695 if (InCompoundScope
) {
22696 auto I
= UsedAsPrevious
.find(PrevDecl
);
22697 if (I
== UsedAsPrevious
.end())
22698 UsedAsPrevious
[PrevDecl
] = false;
22699 if (OMPDeclareMapperDecl
*D
= PrevDecl
->getPrevDeclInScope())
22700 UsedAsPrevious
[D
] = true;
22702 PreviousRedeclTypes
[PrevDecl
->getType().getCanonicalType()] =
22703 PrevDecl
->getLocation();
22706 if (InCompoundScope
) {
22707 for (const auto &PrevData
: UsedAsPrevious
) {
22708 if (!PrevData
.second
) {
22709 PrevDMD
= PrevData
.first
;
22714 } else if (PrevDeclInScope
) {
22715 auto *PrevDMDInScope
= PrevDMD
=
22716 cast
<OMPDeclareMapperDecl
>(PrevDeclInScope
);
22718 PreviousRedeclTypes
[PrevDMDInScope
->getType().getCanonicalType()] =
22719 PrevDMDInScope
->getLocation();
22720 PrevDMDInScope
= PrevDMDInScope
->getPrevDeclInScope();
22721 } while (PrevDMDInScope
!= nullptr);
22723 const auto I
= PreviousRedeclTypes
.find(MapperType
.getCanonicalType());
22724 bool Invalid
= false;
22725 if (I
!= PreviousRedeclTypes
.end()) {
22726 Diag(StartLoc
, diag::err_omp_declare_mapper_redefinition
)
22727 << MapperType
<< Name
;
22728 Diag(I
->second
, diag::note_previous_definition
);
22731 // Build expressions for implicit maps of data members with 'default'
22733 SmallVector
<OMPClause
*, 4> ClausesWithImplicit(Clauses
.begin(),
22735 if (LangOpts
.OpenMP
>= 50)
22736 processImplicitMapsWithDefaultMappers(*this, DSAStack
, ClausesWithImplicit
);
22738 OMPDeclareMapperDecl::Create(Context
, DC
, StartLoc
, Name
, MapperType
, VN
,
22739 ClausesWithImplicit
, PrevDMD
);
22741 PushOnScopeChains(DMD
, S
);
22744 DMD
->setAccess(AS
);
22746 DMD
->setInvalidDecl();
22748 auto *VD
= cast
<DeclRefExpr
>(MapperVarRef
)->getDecl();
22749 VD
->setDeclContext(DMD
);
22750 VD
->setLexicalDeclContext(DMD
);
22752 DMD
->setMapperVarRef(MapperVarRef
);
22754 return DeclGroupPtrTy::make(DeclGroupRef(DMD
));
22758 Sema::ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope
*S
, QualType MapperType
,
22759 SourceLocation StartLoc
,
22760 DeclarationName VN
) {
22761 TypeSourceInfo
*TInfo
=
22762 Context
.getTrivialTypeSourceInfo(MapperType
, StartLoc
);
22763 auto *VD
= VarDecl::Create(Context
, Context
.getTranslationUnitDecl(),
22764 StartLoc
, StartLoc
, VN
.getAsIdentifierInfo(),
22765 MapperType
, TInfo
, SC_None
);
22767 PushOnScopeChains(VD
, S
, /*AddToContext=*/false);
22768 Expr
*E
= buildDeclRefExpr(*this, VD
, MapperType
, StartLoc
);
22769 DSAStack
->addDeclareMapperVarRef(E
);
22773 void Sema::ActOnOpenMPIteratorVarDecl(VarDecl
*VD
) {
22774 if (DSAStack
->getDeclareMapperVarRef())
22775 DSAStack
->addIteratorVarDecl(VD
);
22778 bool Sema::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl
*VD
) const {
22779 assert(LangOpts
.OpenMP
&& "Expected OpenMP mode.");
22780 const Expr
*Ref
= DSAStack
->getDeclareMapperVarRef();
22781 if (const auto *DRE
= cast_or_null
<DeclRefExpr
>(Ref
)) {
22782 if (VD
->getCanonicalDecl() == DRE
->getDecl()->getCanonicalDecl())
22784 if (VD
->isUsableInConstantExpressions(Context
))
22786 if (LangOpts
.OpenMP
>= 52 && DSAStack
->isIteratorVarDecl(VD
))
22793 const ValueDecl
*Sema::getOpenMPDeclareMapperVarName() const {
22794 assert(LangOpts
.OpenMP
&& "Expected OpenMP mode.");
22795 return cast
<DeclRefExpr
>(DSAStack
->getDeclareMapperVarRef())->getDecl();
22798 OMPClause
*Sema::ActOnOpenMPNumTeamsClause(Expr
*NumTeams
,
22799 SourceLocation StartLoc
,
22800 SourceLocation LParenLoc
,
22801 SourceLocation EndLoc
) {
22802 Expr
*ValExpr
= NumTeams
;
22803 Stmt
*HelperValStmt
= nullptr;
22805 // OpenMP [teams Constrcut, Restrictions]
22806 // The num_teams expression must evaluate to a positive integer value.
22807 if (!isNonNegativeIntegerValue(ValExpr
, *this, OMPC_num_teams
,
22808 /*StrictlyPositive=*/true))
22811 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
22812 OpenMPDirectiveKind CaptureRegion
=
22813 getOpenMPCaptureRegionForClause(DKind
, OMPC_num_teams
, LangOpts
.OpenMP
);
22814 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
22815 ValExpr
= MakeFullExpr(ValExpr
).get();
22816 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
22817 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
22818 HelperValStmt
= buildPreInits(Context
, Captures
);
22821 return new (Context
) OMPNumTeamsClause(ValExpr
, HelperValStmt
, CaptureRegion
,
22822 StartLoc
, LParenLoc
, EndLoc
);
22825 OMPClause
*Sema::ActOnOpenMPThreadLimitClause(Expr
*ThreadLimit
,
22826 SourceLocation StartLoc
,
22827 SourceLocation LParenLoc
,
22828 SourceLocation EndLoc
) {
22829 Expr
*ValExpr
= ThreadLimit
;
22830 Stmt
*HelperValStmt
= nullptr;
22832 // OpenMP [teams Constrcut, Restrictions]
22833 // The thread_limit expression must evaluate to a positive integer value.
22834 if (!isNonNegativeIntegerValue(ValExpr
, *this, OMPC_thread_limit
,
22835 /*StrictlyPositive=*/true))
22838 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
22839 OpenMPDirectiveKind CaptureRegion
= getOpenMPCaptureRegionForClause(
22840 DKind
, OMPC_thread_limit
, LangOpts
.OpenMP
);
22841 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
22842 ValExpr
= MakeFullExpr(ValExpr
).get();
22843 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
22844 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
22845 HelperValStmt
= buildPreInits(Context
, Captures
);
22848 return new (Context
) OMPThreadLimitClause(
22849 ValExpr
, HelperValStmt
, CaptureRegion
, StartLoc
, LParenLoc
, EndLoc
);
22852 OMPClause
*Sema::ActOnOpenMPPriorityClause(Expr
*Priority
,
22853 SourceLocation StartLoc
,
22854 SourceLocation LParenLoc
,
22855 SourceLocation EndLoc
) {
22856 Expr
*ValExpr
= Priority
;
22857 Stmt
*HelperValStmt
= nullptr;
22858 OpenMPDirectiveKind CaptureRegion
= OMPD_unknown
;
22860 // OpenMP [2.9.1, task Constrcut]
22861 // The priority-value is a non-negative numerical scalar expression.
22862 if (!isNonNegativeIntegerValue(
22863 ValExpr
, *this, OMPC_priority
,
22864 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
22865 DSAStack
->getCurrentDirective(), &CaptureRegion
, &HelperValStmt
))
22868 return new (Context
) OMPPriorityClause(ValExpr
, HelperValStmt
, CaptureRegion
,
22869 StartLoc
, LParenLoc
, EndLoc
);
22872 OMPClause
*Sema::ActOnOpenMPGrainsizeClause(
22873 OpenMPGrainsizeClauseModifier Modifier
, Expr
*Grainsize
,
22874 SourceLocation StartLoc
, SourceLocation LParenLoc
,
22875 SourceLocation ModifierLoc
, SourceLocation EndLoc
) {
22876 assert((ModifierLoc
.isInvalid() || LangOpts
.OpenMP
>= 51) &&
22877 "Unexpected grainsize modifier in OpenMP < 51.");
22879 if (ModifierLoc
.isValid() && Modifier
== OMPC_GRAINSIZE_unknown
) {
22880 std::string Values
= getListOfPossibleValues(OMPC_grainsize
, /*First=*/0,
22881 OMPC_GRAINSIZE_unknown
);
22882 Diag(ModifierLoc
, diag::err_omp_unexpected_clause_value
)
22883 << Values
<< getOpenMPClauseName(OMPC_grainsize
);
22887 Expr
*ValExpr
= Grainsize
;
22888 Stmt
*HelperValStmt
= nullptr;
22889 OpenMPDirectiveKind CaptureRegion
= OMPD_unknown
;
22891 // OpenMP [2.9.2, taskloop Constrcut]
22892 // The parameter of the grainsize clause must be a positive integer
22894 if (!isNonNegativeIntegerValue(ValExpr
, *this, OMPC_grainsize
,
22895 /*StrictlyPositive=*/true,
22896 /*BuildCapture=*/true,
22897 DSAStack
->getCurrentDirective(),
22898 &CaptureRegion
, &HelperValStmt
))
22901 return new (Context
)
22902 OMPGrainsizeClause(Modifier
, ValExpr
, HelperValStmt
, CaptureRegion
,
22903 StartLoc
, LParenLoc
, ModifierLoc
, EndLoc
);
22906 OMPClause
*Sema::ActOnOpenMPNumTasksClause(
22907 OpenMPNumTasksClauseModifier Modifier
, Expr
*NumTasks
,
22908 SourceLocation StartLoc
, SourceLocation LParenLoc
,
22909 SourceLocation ModifierLoc
, SourceLocation EndLoc
) {
22910 assert((ModifierLoc
.isInvalid() || LangOpts
.OpenMP
>= 51) &&
22911 "Unexpected num_tasks modifier in OpenMP < 51.");
22913 if (ModifierLoc
.isValid() && Modifier
== OMPC_NUMTASKS_unknown
) {
22914 std::string Values
= getListOfPossibleValues(OMPC_num_tasks
, /*First=*/0,
22915 OMPC_NUMTASKS_unknown
);
22916 Diag(ModifierLoc
, diag::err_omp_unexpected_clause_value
)
22917 << Values
<< getOpenMPClauseName(OMPC_num_tasks
);
22921 Expr
*ValExpr
= NumTasks
;
22922 Stmt
*HelperValStmt
= nullptr;
22923 OpenMPDirectiveKind CaptureRegion
= OMPD_unknown
;
22925 // OpenMP [2.9.2, taskloop Constrcut]
22926 // The parameter of the num_tasks clause must be a positive integer
22928 if (!isNonNegativeIntegerValue(
22929 ValExpr
, *this, OMPC_num_tasks
,
22930 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
22931 DSAStack
->getCurrentDirective(), &CaptureRegion
, &HelperValStmt
))
22934 return new (Context
)
22935 OMPNumTasksClause(Modifier
, ValExpr
, HelperValStmt
, CaptureRegion
,
22936 StartLoc
, LParenLoc
, ModifierLoc
, EndLoc
);
22939 OMPClause
*Sema::ActOnOpenMPHintClause(Expr
*Hint
, SourceLocation StartLoc
,
22940 SourceLocation LParenLoc
,
22941 SourceLocation EndLoc
) {
22942 // OpenMP [2.13.2, critical construct, Description]
22943 // ... where hint-expression is an integer constant expression that evaluates
22944 // to a valid lock hint.
22945 ExprResult HintExpr
=
22946 VerifyPositiveIntegerConstantInClause(Hint
, OMPC_hint
, false);
22947 if (HintExpr
.isInvalid())
22949 return new (Context
)
22950 OMPHintClause(HintExpr
.get(), StartLoc
, LParenLoc
, EndLoc
);
22953 /// Tries to find omp_event_handle_t type.
22954 static bool findOMPEventHandleT(Sema
&S
, SourceLocation Loc
,
22955 DSAStackTy
*Stack
) {
22956 QualType OMPEventHandleT
= Stack
->getOMPEventHandleT();
22957 if (!OMPEventHandleT
.isNull())
22959 IdentifierInfo
*II
= &S
.PP
.getIdentifierTable().get("omp_event_handle_t");
22960 ParsedType PT
= S
.getTypeName(*II
, Loc
, S
.getCurScope());
22961 if (!PT
.getAsOpaquePtr() || PT
.get().isNull()) {
22962 S
.Diag(Loc
, diag::err_omp_implied_type_not_found
) << "omp_event_handle_t";
22965 Stack
->setOMPEventHandleT(PT
.get());
22969 OMPClause
*Sema::ActOnOpenMPDetachClause(Expr
*Evt
, SourceLocation StartLoc
,
22970 SourceLocation LParenLoc
,
22971 SourceLocation EndLoc
) {
22972 if (!Evt
->isValueDependent() && !Evt
->isTypeDependent() &&
22973 !Evt
->isInstantiationDependent() &&
22974 !Evt
->containsUnexpandedParameterPack()) {
22975 if (!findOMPEventHandleT(*this, Evt
->getExprLoc(), DSAStack
))
22977 // OpenMP 5.0, 2.10.1 task Construct.
22978 // event-handle is a variable of the omp_event_handle_t type.
22979 auto *Ref
= dyn_cast
<DeclRefExpr
>(Evt
->IgnoreParenImpCasts());
22981 Diag(Evt
->getExprLoc(), diag::err_omp_var_expected
)
22982 << "omp_event_handle_t" << 0 << Evt
->getSourceRange();
22985 auto *VD
= dyn_cast_or_null
<VarDecl
>(Ref
->getDecl());
22987 Diag(Evt
->getExprLoc(), diag::err_omp_var_expected
)
22988 << "omp_event_handle_t" << 0 << Evt
->getSourceRange();
22991 if (!Context
.hasSameUnqualifiedType(DSAStack
->getOMPEventHandleT(),
22993 VD
->getType().isConstant(Context
)) {
22994 Diag(Evt
->getExprLoc(), diag::err_omp_var_expected
)
22995 << "omp_event_handle_t" << 1 << VD
->getType()
22996 << Evt
->getSourceRange();
22999 // OpenMP 5.0, 2.10.1 task Construct
23000 // [detach clause]... The event-handle will be considered as if it was
23001 // specified on a firstprivate clause.
23002 DSAStackTy::DSAVarData DVar
= DSAStack
->getTopDSA(VD
, /*FromParent=*/false);
23003 if (DVar
.CKind
!= OMPC_unknown
&& DVar
.CKind
!= OMPC_firstprivate
&&
23005 Diag(Evt
->getExprLoc(), diag::err_omp_wrong_dsa
)
23006 << getOpenMPClauseName(DVar
.CKind
)
23007 << getOpenMPClauseName(OMPC_firstprivate
);
23008 reportOriginalDsa(*this, DSAStack
, VD
, DVar
);
23013 return new (Context
) OMPDetachClause(Evt
, StartLoc
, LParenLoc
, EndLoc
);
23016 OMPClause
*Sema::ActOnOpenMPDistScheduleClause(
23017 OpenMPDistScheduleClauseKind Kind
, Expr
*ChunkSize
, SourceLocation StartLoc
,
23018 SourceLocation LParenLoc
, SourceLocation KindLoc
, SourceLocation CommaLoc
,
23019 SourceLocation EndLoc
) {
23020 if (Kind
== OMPC_DIST_SCHEDULE_unknown
) {
23021 std::string Values
;
23023 Values
+= getOpenMPSimpleClauseTypeName(OMPC_dist_schedule
, 0);
23025 Diag(KindLoc
, diag::err_omp_unexpected_clause_value
)
23026 << Values
<< getOpenMPClauseName(OMPC_dist_schedule
);
23029 Expr
*ValExpr
= ChunkSize
;
23030 Stmt
*HelperValStmt
= nullptr;
23032 if (!ChunkSize
->isValueDependent() && !ChunkSize
->isTypeDependent() &&
23033 !ChunkSize
->isInstantiationDependent() &&
23034 !ChunkSize
->containsUnexpandedParameterPack()) {
23035 SourceLocation ChunkSizeLoc
= ChunkSize
->getBeginLoc();
23037 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc
, ChunkSize
);
23038 if (Val
.isInvalid())
23041 ValExpr
= Val
.get();
23043 // OpenMP [2.7.1, Restrictions]
23044 // chunk_size must be a loop invariant integer expression with a positive
23046 if (std::optional
<llvm::APSInt
> Result
=
23047 ValExpr
->getIntegerConstantExpr(Context
)) {
23048 if (Result
->isSigned() && !Result
->isStrictlyPositive()) {
23049 Diag(ChunkSizeLoc
, diag::err_omp_negative_expression_in_clause
)
23050 << "dist_schedule" << ChunkSize
->getSourceRange();
23053 } else if (getOpenMPCaptureRegionForClause(
23054 DSAStack
->getCurrentDirective(), OMPC_dist_schedule
,
23055 LangOpts
.OpenMP
) != OMPD_unknown
&&
23056 !CurContext
->isDependentContext()) {
23057 ValExpr
= MakeFullExpr(ValExpr
).get();
23058 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
23059 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
23060 HelperValStmt
= buildPreInits(Context
, Captures
);
23065 return new (Context
)
23066 OMPDistScheduleClause(StartLoc
, LParenLoc
, KindLoc
, CommaLoc
, EndLoc
,
23067 Kind
, ValExpr
, HelperValStmt
);
23070 OMPClause
*Sema::ActOnOpenMPDefaultmapClause(
23071 OpenMPDefaultmapClauseModifier M
, OpenMPDefaultmapClauseKind Kind
,
23072 SourceLocation StartLoc
, SourceLocation LParenLoc
, SourceLocation MLoc
,
23073 SourceLocation KindLoc
, SourceLocation EndLoc
) {
23074 if (getLangOpts().OpenMP
< 50) {
23075 if (M
!= OMPC_DEFAULTMAP_MODIFIER_tofrom
||
23076 Kind
!= OMPC_DEFAULTMAP_scalar
) {
23078 SourceLocation Loc
;
23080 if (M
!= OMPC_DEFAULTMAP_MODIFIER_tofrom
) {
23081 Value
+= getOpenMPSimpleClauseTypeName(OMPC_defaultmap
,
23082 OMPC_DEFAULTMAP_MODIFIER_tofrom
);
23085 Value
+= getOpenMPSimpleClauseTypeName(OMPC_defaultmap
,
23086 OMPC_DEFAULTMAP_scalar
);
23090 Diag(Loc
, diag::err_omp_unexpected_clause_value
)
23091 << Value
<< getOpenMPClauseName(OMPC_defaultmap
);
23095 bool isDefaultmapModifier
= (M
!= OMPC_DEFAULTMAP_MODIFIER_unknown
);
23096 bool isDefaultmapKind
= (Kind
!= OMPC_DEFAULTMAP_unknown
) ||
23097 (LangOpts
.OpenMP
>= 50 && KindLoc
.isInvalid());
23098 if (!isDefaultmapKind
|| !isDefaultmapModifier
) {
23099 StringRef KindValue
= "'scalar', 'aggregate', 'pointer'";
23100 if (LangOpts
.OpenMP
== 50) {
23101 StringRef ModifierValue
= "'alloc', 'from', 'to', 'tofrom', "
23102 "'firstprivate', 'none', 'default'";
23103 if (!isDefaultmapKind
&& isDefaultmapModifier
) {
23104 Diag(KindLoc
, diag::err_omp_unexpected_clause_value
)
23105 << KindValue
<< getOpenMPClauseName(OMPC_defaultmap
);
23106 } else if (isDefaultmapKind
&& !isDefaultmapModifier
) {
23107 Diag(MLoc
, diag::err_omp_unexpected_clause_value
)
23108 << ModifierValue
<< getOpenMPClauseName(OMPC_defaultmap
);
23110 Diag(MLoc
, diag::err_omp_unexpected_clause_value
)
23111 << ModifierValue
<< getOpenMPClauseName(OMPC_defaultmap
);
23112 Diag(KindLoc
, diag::err_omp_unexpected_clause_value
)
23113 << KindValue
<< getOpenMPClauseName(OMPC_defaultmap
);
23116 StringRef ModifierValue
=
23117 "'alloc', 'from', 'to', 'tofrom', "
23118 "'firstprivate', 'none', 'default', 'present'";
23119 if (!isDefaultmapKind
&& isDefaultmapModifier
) {
23120 Diag(KindLoc
, diag::err_omp_unexpected_clause_value
)
23121 << KindValue
<< getOpenMPClauseName(OMPC_defaultmap
);
23122 } else if (isDefaultmapKind
&& !isDefaultmapModifier
) {
23123 Diag(MLoc
, diag::err_omp_unexpected_clause_value
)
23124 << ModifierValue
<< getOpenMPClauseName(OMPC_defaultmap
);
23126 Diag(MLoc
, diag::err_omp_unexpected_clause_value
)
23127 << ModifierValue
<< getOpenMPClauseName(OMPC_defaultmap
);
23128 Diag(KindLoc
, diag::err_omp_unexpected_clause_value
)
23129 << KindValue
<< getOpenMPClauseName(OMPC_defaultmap
);
23135 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
23136 // At most one defaultmap clause for each category can appear on the
23138 if (DSAStack
->checkDefaultmapCategory(Kind
)) {
23139 Diag(StartLoc
, diag::err_omp_one_defaultmap_each_category
);
23143 if (Kind
== OMPC_DEFAULTMAP_unknown
) {
23144 // Variable category is not specified - mark all categories.
23145 DSAStack
->setDefaultDMAAttr(M
, OMPC_DEFAULTMAP_aggregate
, StartLoc
);
23146 DSAStack
->setDefaultDMAAttr(M
, OMPC_DEFAULTMAP_scalar
, StartLoc
);
23147 DSAStack
->setDefaultDMAAttr(M
, OMPC_DEFAULTMAP_pointer
, StartLoc
);
23149 DSAStack
->setDefaultDMAAttr(M
, Kind
, StartLoc
);
23152 return new (Context
)
23153 OMPDefaultmapClause(StartLoc
, LParenLoc
, MLoc
, KindLoc
, EndLoc
, Kind
, M
);
23156 bool Sema::ActOnStartOpenMPDeclareTargetContext(
23157 DeclareTargetContextInfo
&DTCI
) {
23158 DeclContext
*CurLexicalContext
= getCurLexicalContext();
23159 if (!CurLexicalContext
->isFileContext() &&
23160 !CurLexicalContext
->isExternCContext() &&
23161 !CurLexicalContext
->isExternCXXContext() &&
23162 !isa
<CXXRecordDecl
>(CurLexicalContext
) &&
23163 !isa
<ClassTemplateDecl
>(CurLexicalContext
) &&
23164 !isa
<ClassTemplatePartialSpecializationDecl
>(CurLexicalContext
) &&
23165 !isa
<ClassTemplateSpecializationDecl
>(CurLexicalContext
)) {
23166 Diag(DTCI
.Loc
, diag::err_omp_region_not_file_context
);
23170 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
23171 if (getLangOpts().HIP
)
23172 Diag(DTCI
.Loc
, diag::warn_hip_omp_target_directives
);
23174 DeclareTargetNesting
.push_back(DTCI
);
23178 const Sema::DeclareTargetContextInfo
23179 Sema::ActOnOpenMPEndDeclareTargetDirective() {
23180 assert(!DeclareTargetNesting
.empty() &&
23181 "check isInOpenMPDeclareTargetContext() first!");
23182 return DeclareTargetNesting
.pop_back_val();
23185 void Sema::ActOnFinishedOpenMPDeclareTargetContext(
23186 DeclareTargetContextInfo
&DTCI
) {
23187 for (auto &It
: DTCI
.ExplicitlyMapped
)
23188 ActOnOpenMPDeclareTargetName(It
.first
, It
.second
.Loc
, It
.second
.MT
, DTCI
);
23191 void Sema::DiagnoseUnterminatedOpenMPDeclareTarget() {
23192 if (DeclareTargetNesting
.empty())
23194 DeclareTargetContextInfo
&DTCI
= DeclareTargetNesting
.back();
23195 Diag(DTCI
.Loc
, diag::warn_omp_unterminated_declare_target
)
23196 << getOpenMPDirectiveName(DTCI
.Kind
);
23199 NamedDecl
*Sema::lookupOpenMPDeclareTargetName(Scope
*CurScope
,
23200 CXXScopeSpec
&ScopeSpec
,
23201 const DeclarationNameInfo
&Id
) {
23202 LookupResult
Lookup(*this, Id
, LookupOrdinaryName
);
23203 LookupParsedName(Lookup
, CurScope
, &ScopeSpec
, true);
23205 if (Lookup
.isAmbiguous())
23207 Lookup
.suppressDiagnostics();
23209 if (!Lookup
.isSingleResult()) {
23210 VarOrFuncDeclFilterCCC
CCC(*this);
23211 if (TypoCorrection Corrected
=
23212 CorrectTypo(Id
, LookupOrdinaryName
, CurScope
, nullptr, CCC
,
23213 CTK_ErrorRecovery
)) {
23214 diagnoseTypo(Corrected
, PDiag(diag::err_undeclared_var_use_suggest
)
23216 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected
.getCorrectionDecl());
23220 Diag(Id
.getLoc(), diag::err_undeclared_var_use
) << Id
.getName();
23224 NamedDecl
*ND
= Lookup
.getAsSingle
<NamedDecl
>();
23225 if (!isa
<VarDecl
>(ND
) && !isa
<FunctionDecl
>(ND
) &&
23226 !isa
<FunctionTemplateDecl
>(ND
)) {
23227 Diag(Id
.getLoc(), diag::err_omp_invalid_target_decl
) << Id
.getName();
23233 void Sema::ActOnOpenMPDeclareTargetName(NamedDecl
*ND
, SourceLocation Loc
,
23234 OMPDeclareTargetDeclAttr::MapTypeTy MT
,
23235 DeclareTargetContextInfo
&DTCI
) {
23236 assert((isa
<VarDecl
>(ND
) || isa
<FunctionDecl
>(ND
) ||
23237 isa
<FunctionTemplateDecl
>(ND
)) &&
23238 "Expected variable, function or function template.");
23240 // Diagnose marking after use as it may lead to incorrect diagnosis and
23242 if (LangOpts
.OpenMP
>= 50 &&
23243 (ND
->isUsed(/*CheckUsedAttr=*/false) || ND
->isReferenced()))
23244 Diag(Loc
, diag::warn_omp_declare_target_after_first_use
);
23246 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
23247 if (getLangOpts().HIP
)
23248 Diag(Loc
, diag::warn_hip_omp_target_directives
);
23250 // Explicit declare target lists have precedence.
23251 const unsigned Level
= -1;
23253 auto *VD
= cast
<ValueDecl
>(ND
);
23254 std::optional
<OMPDeclareTargetDeclAttr
*> ActiveAttr
=
23255 OMPDeclareTargetDeclAttr::getActiveAttr(VD
);
23256 if (ActiveAttr
&& (*ActiveAttr
)->getDevType() != DTCI
.DT
&&
23257 (*ActiveAttr
)->getLevel() == Level
) {
23258 Diag(Loc
, diag::err_omp_device_type_mismatch
)
23259 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI
.DT
)
23260 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
23261 (*ActiveAttr
)->getDevType());
23264 if (ActiveAttr
&& (*ActiveAttr
)->getMapType() != MT
&&
23265 (*ActiveAttr
)->getLevel() == Level
) {
23266 Diag(Loc
, diag::err_omp_declare_target_to_and_link
) << ND
;
23270 if (ActiveAttr
&& (*ActiveAttr
)->getLevel() == Level
)
23273 Expr
*IndirectE
= nullptr;
23274 bool IsIndirect
= false;
23275 if (DTCI
.Indirect
) {
23276 IndirectE
= *DTCI
.Indirect
;
23280 auto *A
= OMPDeclareTargetDeclAttr::CreateImplicit(
23281 Context
, MT
, DTCI
.DT
, IndirectE
, IsIndirect
, Level
,
23282 SourceRange(Loc
, Loc
));
23284 if (ASTMutationListener
*ML
= Context
.getASTMutationListener())
23285 ML
->DeclarationMarkedOpenMPDeclareTarget(ND
, A
);
23286 checkDeclIsAllowedInOpenMPTarget(nullptr, ND
, Loc
);
23287 if (auto *VD
= dyn_cast
<VarDecl
>(ND
);
23288 LangOpts
.OpenMP
&& VD
&& VD
->hasAttr
<OMPDeclareTargetDeclAttr
>() &&
23289 VD
->hasGlobalStorage())
23290 ActOnOpenMPDeclareTargetInitializer(ND
);
23293 static void checkDeclInTargetContext(SourceLocation SL
, SourceRange SR
,
23294 Sema
&SemaRef
, Decl
*D
) {
23295 if (!D
|| !isa
<VarDecl
>(D
))
23297 auto *VD
= cast
<VarDecl
>(D
);
23298 std::optional
<OMPDeclareTargetDeclAttr::MapTypeTy
> MapTy
=
23299 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD
);
23300 if (SemaRef
.LangOpts
.OpenMP
>= 50 &&
23301 (SemaRef
.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
23302 SemaRef
.getCurBlock() || SemaRef
.getCurCapturedRegion()) &&
23303 VD
->hasGlobalStorage()) {
23304 if (!MapTy
|| (*MapTy
!= OMPDeclareTargetDeclAttr::MT_To
&&
23305 *MapTy
!= OMPDeclareTargetDeclAttr::MT_Enter
)) {
23306 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
23307 // If a lambda declaration and definition appears between a
23308 // declare target directive and the matching end declare target
23309 // directive, all variables that are captured by the lambda
23310 // expression must also appear in a to clause.
23311 SemaRef
.Diag(VD
->getLocation(),
23312 diag::err_omp_lambda_capture_in_declare_target_not_to
);
23313 SemaRef
.Diag(SL
, diag::note_var_explicitly_captured_here
)
23320 SemaRef
.Diag(VD
->getLocation(), diag::warn_omp_not_in_target_context
);
23321 SemaRef
.Diag(SL
, diag::note_used_here
) << SR
;
23324 static bool checkValueDeclInTarget(SourceLocation SL
, SourceRange SR
,
23325 Sema
&SemaRef
, DSAStackTy
*Stack
,
23327 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD
) ||
23328 checkTypeMappable(SL
, SR
, SemaRef
, Stack
, VD
->getType(),
23329 /*FullCheck=*/false);
23332 void Sema::checkDeclIsAllowedInOpenMPTarget(Expr
*E
, Decl
*D
,
23333 SourceLocation IdLoc
) {
23334 if (!D
|| D
->isInvalidDecl())
23336 SourceRange SR
= E
? E
->getSourceRange() : D
->getSourceRange();
23337 SourceLocation SL
= E
? E
->getBeginLoc() : D
->getLocation();
23338 if (auto *VD
= dyn_cast
<VarDecl
>(D
)) {
23339 // Only global variables can be marked as declare target.
23340 if (!VD
->isFileVarDecl() && !VD
->isStaticLocal() &&
23341 !VD
->isStaticDataMember())
23343 // 2.10.6: threadprivate variable cannot appear in a declare target
23345 if (DSAStack
->isThreadPrivate(VD
)) {
23346 Diag(SL
, diag::err_omp_threadprivate_in_target
);
23347 reportOriginalDsa(*this, DSAStack
, VD
, DSAStack
->getTopDSA(VD
, false));
23351 if (const auto *FTD
= dyn_cast
<FunctionTemplateDecl
>(D
))
23352 D
= FTD
->getTemplatedDecl();
23353 if (auto *FD
= dyn_cast
<FunctionDecl
>(D
)) {
23354 std::optional
<OMPDeclareTargetDeclAttr::MapTypeTy
> Res
=
23355 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD
);
23356 if (IdLoc
.isValid() && Res
&& *Res
== OMPDeclareTargetDeclAttr::MT_Link
) {
23357 Diag(IdLoc
, diag::err_omp_function_in_link_clause
);
23358 Diag(FD
->getLocation(), diag::note_defined_here
) << FD
;
23362 if (auto *VD
= dyn_cast
<ValueDecl
>(D
)) {
23363 // Problem if any with var declared with incomplete type will be reported
23364 // as normal, so no need to check it here.
23365 if ((E
|| !VD
->getType()->isIncompleteType()) &&
23366 !checkValueDeclInTarget(SL
, SR
, *this, DSAStack
, VD
))
23368 if (!E
&& isInOpenMPDeclareTargetContext()) {
23369 // Checking declaration inside declare target region.
23370 if (isa
<VarDecl
>(D
) || isa
<FunctionDecl
>(D
) ||
23371 isa
<FunctionTemplateDecl
>(D
)) {
23372 std::optional
<OMPDeclareTargetDeclAttr
*> ActiveAttr
=
23373 OMPDeclareTargetDeclAttr::getActiveAttr(VD
);
23374 unsigned Level
= DeclareTargetNesting
.size();
23375 if (ActiveAttr
&& (*ActiveAttr
)->getLevel() >= Level
)
23377 DeclareTargetContextInfo
&DTCI
= DeclareTargetNesting
.back();
23378 Expr
*IndirectE
= nullptr;
23379 bool IsIndirect
= false;
23380 if (DTCI
.Indirect
) {
23381 IndirectE
= *DTCI
.Indirect
;
23385 auto *A
= OMPDeclareTargetDeclAttr::CreateImplicit(
23387 getLangOpts().OpenMP
>= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
23388 : OMPDeclareTargetDeclAttr::MT_To
,
23389 DTCI
.DT
, IndirectE
, IsIndirect
, Level
,
23390 SourceRange(DTCI
.Loc
, DTCI
.Loc
));
23392 if (ASTMutationListener
*ML
= Context
.getASTMutationListener())
23393 ML
->DeclarationMarkedOpenMPDeclareTarget(D
, A
);
23400 checkDeclInTargetContext(E
->getExprLoc(), E
->getSourceRange(), *this, D
);
23403 /// This class visits every VarDecl that the initializer references and adds
23404 /// OMPDeclareTargetDeclAttr to each of them.
23405 class GlobalDeclRefChecker final
23406 : public StmtVisitor
<GlobalDeclRefChecker
> {
23407 SmallVector
<VarDecl
*> DeclVector
;
23411 /// A StmtVisitor class function that visits all DeclRefExpr and adds
23412 /// OMPDeclareTargetDeclAttr to them.
23413 void VisitDeclRefExpr(DeclRefExpr
*Node
) {
23414 if (auto *VD
= dyn_cast
<VarDecl
>(Node
->getDecl())) {
23416 DeclVector
.push_back(VD
);
23419 /// A function that iterates across each of the Expr's children.
23420 void VisitExpr(Expr
*Ex
) {
23421 for (auto *Child
: Ex
->children()) {
23425 /// A function that keeps a record of all the Decls that are variables, has
23426 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
23427 /// each Decl one at a time and use the inherited 'visit' functions to look
23428 /// for DeclRefExpr.
23429 void declareTargetInitializer(Decl
*TD
) {
23430 A
= TD
->getAttr
<OMPDeclareTargetDeclAttr
>();
23431 DeclVector
.push_back(cast
<VarDecl
>(TD
));
23432 while (!DeclVector
.empty()) {
23433 VarDecl
*TargetVarDecl
= DeclVector
.pop_back_val();
23434 if (TargetVarDecl
->hasAttr
<OMPDeclareTargetDeclAttr
>() &&
23435 TargetVarDecl
->hasInit() && TargetVarDecl
->hasGlobalStorage()) {
23436 if (Expr
*Ex
= TargetVarDecl
->getInit())
23443 /// Adding OMPDeclareTargetDeclAttr to variables with static storage
23444 /// duration that are referenced in the initializer expression list of
23445 /// variables with static storage duration in declare target directive.
23446 void Sema::ActOnOpenMPDeclareTargetInitializer(Decl
*TargetDecl
) {
23447 GlobalDeclRefChecker Checker
;
23448 if (isa
<VarDecl
>(TargetDecl
))
23449 Checker
.declareTargetInitializer(TargetDecl
);
23452 OMPClause
*Sema::ActOnOpenMPToClause(
23453 ArrayRef
<OpenMPMotionModifierKind
> MotionModifiers
,
23454 ArrayRef
<SourceLocation
> MotionModifiersLoc
,
23455 CXXScopeSpec
&MapperIdScopeSpec
, DeclarationNameInfo
&MapperId
,
23456 SourceLocation ColonLoc
, ArrayRef
<Expr
*> VarList
,
23457 const OMPVarListLocTy
&Locs
, ArrayRef
<Expr
*> UnresolvedMappers
) {
23458 OpenMPMotionModifierKind Modifiers
[] = {OMPC_MOTION_MODIFIER_unknown
,
23459 OMPC_MOTION_MODIFIER_unknown
};
23460 SourceLocation ModifiersLoc
[NumberOfOMPMotionModifiers
];
23462 // Process motion-modifiers, flag errors for duplicate modifiers.
23463 unsigned Count
= 0;
23464 for (unsigned I
= 0, E
= MotionModifiers
.size(); I
< E
; ++I
) {
23465 if (MotionModifiers
[I
] != OMPC_MOTION_MODIFIER_unknown
&&
23466 llvm::is_contained(Modifiers
, MotionModifiers
[I
])) {
23467 Diag(MotionModifiersLoc
[I
], diag::err_omp_duplicate_motion_modifier
);
23470 assert(Count
< NumberOfOMPMotionModifiers
&&
23471 "Modifiers exceed the allowed number of motion modifiers");
23472 Modifiers
[Count
] = MotionModifiers
[I
];
23473 ModifiersLoc
[Count
] = MotionModifiersLoc
[I
];
23477 MappableVarListInfo
MVLI(VarList
);
23478 checkMappableExpressionList(*this, DSAStack
, OMPC_to
, MVLI
, Locs
.StartLoc
,
23479 MapperIdScopeSpec
, MapperId
, UnresolvedMappers
);
23480 if (MVLI
.ProcessedVarList
.empty())
23483 return OMPToClause::Create(
23484 Context
, Locs
, MVLI
.ProcessedVarList
, MVLI
.VarBaseDeclarations
,
23485 MVLI
.VarComponents
, MVLI
.UDMapperList
, Modifiers
, ModifiersLoc
,
23486 MapperIdScopeSpec
.getWithLocInContext(Context
), MapperId
);
23489 OMPClause
*Sema::ActOnOpenMPFromClause(
23490 ArrayRef
<OpenMPMotionModifierKind
> MotionModifiers
,
23491 ArrayRef
<SourceLocation
> MotionModifiersLoc
,
23492 CXXScopeSpec
&MapperIdScopeSpec
, DeclarationNameInfo
&MapperId
,
23493 SourceLocation ColonLoc
, ArrayRef
<Expr
*> VarList
,
23494 const OMPVarListLocTy
&Locs
, ArrayRef
<Expr
*> UnresolvedMappers
) {
23495 OpenMPMotionModifierKind Modifiers
[] = {OMPC_MOTION_MODIFIER_unknown
,
23496 OMPC_MOTION_MODIFIER_unknown
};
23497 SourceLocation ModifiersLoc
[NumberOfOMPMotionModifiers
];
23499 // Process motion-modifiers, flag errors for duplicate modifiers.
23500 unsigned Count
= 0;
23501 for (unsigned I
= 0, E
= MotionModifiers
.size(); I
< E
; ++I
) {
23502 if (MotionModifiers
[I
] != OMPC_MOTION_MODIFIER_unknown
&&
23503 llvm::is_contained(Modifiers
, MotionModifiers
[I
])) {
23504 Diag(MotionModifiersLoc
[I
], diag::err_omp_duplicate_motion_modifier
);
23507 assert(Count
< NumberOfOMPMotionModifiers
&&
23508 "Modifiers exceed the allowed number of motion modifiers");
23509 Modifiers
[Count
] = MotionModifiers
[I
];
23510 ModifiersLoc
[Count
] = MotionModifiersLoc
[I
];
23514 MappableVarListInfo
MVLI(VarList
);
23515 checkMappableExpressionList(*this, DSAStack
, OMPC_from
, MVLI
, Locs
.StartLoc
,
23516 MapperIdScopeSpec
, MapperId
, UnresolvedMappers
);
23517 if (MVLI
.ProcessedVarList
.empty())
23520 return OMPFromClause::Create(
23521 Context
, Locs
, MVLI
.ProcessedVarList
, MVLI
.VarBaseDeclarations
,
23522 MVLI
.VarComponents
, MVLI
.UDMapperList
, Modifiers
, ModifiersLoc
,
23523 MapperIdScopeSpec
.getWithLocInContext(Context
), MapperId
);
23526 OMPClause
*Sema::ActOnOpenMPUseDevicePtrClause(ArrayRef
<Expr
*> VarList
,
23527 const OMPVarListLocTy
&Locs
) {
23528 MappableVarListInfo
MVLI(VarList
);
23529 SmallVector
<Expr
*, 8> PrivateCopies
;
23530 SmallVector
<Expr
*, 8> Inits
;
23532 for (Expr
*RefExpr
: VarList
) {
23533 assert(RefExpr
&& "NULL expr in OpenMP use_device_ptr clause.");
23534 SourceLocation ELoc
;
23535 SourceRange ERange
;
23536 Expr
*SimpleRefExpr
= RefExpr
;
23537 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
23539 // It will be analyzed later.
23540 MVLI
.ProcessedVarList
.push_back(RefExpr
);
23541 PrivateCopies
.push_back(nullptr);
23542 Inits
.push_back(nullptr);
23544 ValueDecl
*D
= Res
.first
;
23548 QualType Type
= D
->getType();
23549 Type
= Type
.getNonReferenceType().getUnqualifiedType();
23551 auto *VD
= dyn_cast
<VarDecl
>(D
);
23553 // Item should be a pointer or reference to pointer.
23554 if (!Type
->isPointerType()) {
23555 Diag(ELoc
, diag::err_omp_usedeviceptr_not_a_pointer
)
23556 << 0 << RefExpr
->getSourceRange();
23560 // Build the private variable and the expression that refers to it.
23562 buildVarDecl(*this, ELoc
, Type
, D
->getName(),
23563 D
->hasAttrs() ? &D
->getAttrs() : nullptr,
23564 VD
? cast
<DeclRefExpr
>(SimpleRefExpr
) : nullptr);
23565 if (VDPrivate
->isInvalidDecl())
23568 CurContext
->addDecl(VDPrivate
);
23569 DeclRefExpr
*VDPrivateRefExpr
= buildDeclRefExpr(
23570 *this, VDPrivate
, RefExpr
->getType().getUnqualifiedType(), ELoc
);
23572 // Add temporary variable to initialize the private copy of the pointer.
23574 buildVarDecl(*this, RefExpr
->getExprLoc(), Type
, ".devptr.temp");
23575 DeclRefExpr
*VDInitRefExpr
= buildDeclRefExpr(
23576 *this, VDInit
, RefExpr
->getType(), RefExpr
->getExprLoc());
23577 AddInitializerToDecl(VDPrivate
,
23578 DefaultLvalueConversion(VDInitRefExpr
).get(),
23579 /*DirectInit=*/false);
23581 // If required, build a capture to implement the privatization initialized
23582 // with the current list item value.
23583 DeclRefExpr
*Ref
= nullptr;
23585 Ref
= buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/true);
23586 MVLI
.ProcessedVarList
.push_back(VD
? RefExpr
->IgnoreParens() : Ref
);
23587 PrivateCopies
.push_back(VDPrivateRefExpr
);
23588 Inits
.push_back(VDInitRefExpr
);
23590 // We need to add a data sharing attribute for this variable to make sure it
23591 // is correctly captured. A variable that shows up in a use_device_ptr has
23592 // similar properties of a first private variable.
23593 DSAStack
->addDSA(D
, RefExpr
->IgnoreParens(), OMPC_firstprivate
, Ref
);
23595 // Create a mappable component for the list item. List items in this clause
23596 // only need a component.
23597 MVLI
.VarBaseDeclarations
.push_back(D
);
23598 MVLI
.VarComponents
.resize(MVLI
.VarComponents
.size() + 1);
23599 MVLI
.VarComponents
.back().emplace_back(SimpleRefExpr
, D
,
23600 /*IsNonContiguous=*/false);
23603 if (MVLI
.ProcessedVarList
.empty())
23606 return OMPUseDevicePtrClause::Create(
23607 Context
, Locs
, MVLI
.ProcessedVarList
, PrivateCopies
, Inits
,
23608 MVLI
.VarBaseDeclarations
, MVLI
.VarComponents
);
23611 OMPClause
*Sema::ActOnOpenMPUseDeviceAddrClause(ArrayRef
<Expr
*> VarList
,
23612 const OMPVarListLocTy
&Locs
) {
23613 MappableVarListInfo
MVLI(VarList
);
23615 for (Expr
*RefExpr
: VarList
) {
23616 assert(RefExpr
&& "NULL expr in OpenMP use_device_addr clause.");
23617 SourceLocation ELoc
;
23618 SourceRange ERange
;
23619 Expr
*SimpleRefExpr
= RefExpr
;
23620 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
,
23621 /*AllowArraySection=*/true);
23623 // It will be analyzed later.
23624 MVLI
.ProcessedVarList
.push_back(RefExpr
);
23626 ValueDecl
*D
= Res
.first
;
23629 auto *VD
= dyn_cast
<VarDecl
>(D
);
23631 // If required, build a capture to implement the privatization initialized
23632 // with the current list item value.
23633 DeclRefExpr
*Ref
= nullptr;
23635 Ref
= buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/true);
23636 MVLI
.ProcessedVarList
.push_back(VD
? RefExpr
->IgnoreParens() : Ref
);
23638 // We need to add a data sharing attribute for this variable to make sure it
23639 // is correctly captured. A variable that shows up in a use_device_addr has
23640 // similar properties of a first private variable.
23641 DSAStack
->addDSA(D
, RefExpr
->IgnoreParens(), OMPC_firstprivate
, Ref
);
23643 // Create a mappable component for the list item. List items in this clause
23644 // only need a component.
23645 MVLI
.VarBaseDeclarations
.push_back(D
);
23646 MVLI
.VarComponents
.emplace_back();
23647 Expr
*Component
= SimpleRefExpr
;
23648 if (VD
&& (isa
<OMPArraySectionExpr
>(RefExpr
->IgnoreParenImpCasts()) ||
23649 isa
<ArraySubscriptExpr
>(RefExpr
->IgnoreParenImpCasts())))
23650 Component
= DefaultFunctionArrayLvalueConversion(SimpleRefExpr
).get();
23651 MVLI
.VarComponents
.back().emplace_back(Component
, D
,
23652 /*IsNonContiguous=*/false);
23655 if (MVLI
.ProcessedVarList
.empty())
23658 return OMPUseDeviceAddrClause::Create(Context
, Locs
, MVLI
.ProcessedVarList
,
23659 MVLI
.VarBaseDeclarations
,
23660 MVLI
.VarComponents
);
23663 OMPClause
*Sema::ActOnOpenMPIsDevicePtrClause(ArrayRef
<Expr
*> VarList
,
23664 const OMPVarListLocTy
&Locs
) {
23665 MappableVarListInfo
MVLI(VarList
);
23666 for (Expr
*RefExpr
: VarList
) {
23667 assert(RefExpr
&& "NULL expr in OpenMP is_device_ptr clause.");
23668 SourceLocation ELoc
;
23669 SourceRange ERange
;
23670 Expr
*SimpleRefExpr
= RefExpr
;
23671 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
23673 // It will be analyzed later.
23674 MVLI
.ProcessedVarList
.push_back(RefExpr
);
23676 ValueDecl
*D
= Res
.first
;
23680 QualType Type
= D
->getType();
23681 // item should be a pointer or array or reference to pointer or array
23682 if (!Type
.getNonReferenceType()->isPointerType() &&
23683 !Type
.getNonReferenceType()->isArrayType()) {
23684 Diag(ELoc
, diag::err_omp_argument_type_isdeviceptr
)
23685 << 0 << RefExpr
->getSourceRange();
23689 // Check if the declaration in the clause does not show up in any data
23690 // sharing attribute.
23691 DSAStackTy::DSAVarData DVar
= DSAStack
->getTopDSA(D
, /*FromParent=*/false);
23692 if (isOpenMPPrivate(DVar
.CKind
)) {
23693 Diag(ELoc
, diag::err_omp_variable_in_given_clause_and_dsa
)
23694 << getOpenMPClauseName(DVar
.CKind
)
23695 << getOpenMPClauseName(OMPC_is_device_ptr
)
23696 << getOpenMPDirectiveName(DSAStack
->getCurrentDirective());
23697 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
23701 const Expr
*ConflictExpr
;
23702 if (DSAStack
->checkMappableExprComponentListsForDecl(
23703 D
, /*CurrentRegionOnly=*/true,
23705 OMPClauseMappableExprCommon::MappableExprComponentListRef R
,
23706 OpenMPClauseKind
) -> bool {
23707 ConflictExpr
= R
.front().getAssociatedExpression();
23710 Diag(ELoc
, diag::err_omp_map_shared_storage
) << RefExpr
->getSourceRange();
23711 Diag(ConflictExpr
->getExprLoc(), diag::note_used_here
)
23712 << ConflictExpr
->getSourceRange();
23716 // Store the components in the stack so that they can be used to check
23717 // against other clauses later on.
23718 OMPClauseMappableExprCommon::MappableComponent
MC(
23719 SimpleRefExpr
, D
, /*IsNonContiguous=*/false);
23720 DSAStack
->addMappableExpressionComponents(
23721 D
, MC
, /*WhereFoundClauseKind=*/OMPC_is_device_ptr
);
23723 // Record the expression we've just processed.
23724 MVLI
.ProcessedVarList
.push_back(SimpleRefExpr
);
23726 // Create a mappable component for the list item. List items in this clause
23727 // only need a component. We use a null declaration to signal fields in
23729 assert((isa
<DeclRefExpr
>(SimpleRefExpr
) ||
23730 isa
<CXXThisExpr
>(cast
<MemberExpr
>(SimpleRefExpr
)->getBase())) &&
23731 "Unexpected device pointer expression!");
23732 MVLI
.VarBaseDeclarations
.push_back(
23733 isa
<DeclRefExpr
>(SimpleRefExpr
) ? D
: nullptr);
23734 MVLI
.VarComponents
.resize(MVLI
.VarComponents
.size() + 1);
23735 MVLI
.VarComponents
.back().push_back(MC
);
23738 if (MVLI
.ProcessedVarList
.empty())
23741 return OMPIsDevicePtrClause::Create(Context
, Locs
, MVLI
.ProcessedVarList
,
23742 MVLI
.VarBaseDeclarations
,
23743 MVLI
.VarComponents
);
23746 OMPClause
*Sema::ActOnOpenMPHasDeviceAddrClause(ArrayRef
<Expr
*> VarList
,
23747 const OMPVarListLocTy
&Locs
) {
23748 MappableVarListInfo
MVLI(VarList
);
23749 for (Expr
*RefExpr
: VarList
) {
23750 assert(RefExpr
&& "NULL expr in OpenMP has_device_addr clause.");
23751 SourceLocation ELoc
;
23752 SourceRange ERange
;
23753 Expr
*SimpleRefExpr
= RefExpr
;
23754 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
,
23755 /*AllowArraySection=*/true);
23757 // It will be analyzed later.
23758 MVLI
.ProcessedVarList
.push_back(RefExpr
);
23760 ValueDecl
*D
= Res
.first
;
23764 // Check if the declaration in the clause does not show up in any data
23765 // sharing attribute.
23766 DSAStackTy::DSAVarData DVar
= DSAStack
->getTopDSA(D
, /*FromParent=*/false);
23767 if (isOpenMPPrivate(DVar
.CKind
)) {
23768 Diag(ELoc
, diag::err_omp_variable_in_given_clause_and_dsa
)
23769 << getOpenMPClauseName(DVar
.CKind
)
23770 << getOpenMPClauseName(OMPC_has_device_addr
)
23771 << getOpenMPDirectiveName(DSAStack
->getCurrentDirective());
23772 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
23776 const Expr
*ConflictExpr
;
23777 if (DSAStack
->checkMappableExprComponentListsForDecl(
23778 D
, /*CurrentRegionOnly=*/true,
23780 OMPClauseMappableExprCommon::MappableExprComponentListRef R
,
23781 OpenMPClauseKind
) -> bool {
23782 ConflictExpr
= R
.front().getAssociatedExpression();
23785 Diag(ELoc
, diag::err_omp_map_shared_storage
) << RefExpr
->getSourceRange();
23786 Diag(ConflictExpr
->getExprLoc(), diag::note_used_here
)
23787 << ConflictExpr
->getSourceRange();
23791 // Store the components in the stack so that they can be used to check
23792 // against other clauses later on.
23793 Expr
*Component
= SimpleRefExpr
;
23794 auto *VD
= dyn_cast
<VarDecl
>(D
);
23795 if (VD
&& (isa
<OMPArraySectionExpr
>(RefExpr
->IgnoreParenImpCasts()) ||
23796 isa
<ArraySubscriptExpr
>(RefExpr
->IgnoreParenImpCasts())))
23797 Component
= DefaultFunctionArrayLvalueConversion(SimpleRefExpr
).get();
23798 OMPClauseMappableExprCommon::MappableComponent
MC(
23799 Component
, D
, /*IsNonContiguous=*/false);
23800 DSAStack
->addMappableExpressionComponents(
23801 D
, MC
, /*WhereFoundClauseKind=*/OMPC_has_device_addr
);
23803 // Record the expression we've just processed.
23804 if (!VD
&& !CurContext
->isDependentContext()) {
23806 buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/true);
23807 assert(Ref
&& "has_device_addr capture failed");
23808 MVLI
.ProcessedVarList
.push_back(Ref
);
23810 MVLI
.ProcessedVarList
.push_back(RefExpr
->IgnoreParens());
23812 // Create a mappable component for the list item. List items in this clause
23813 // only need a component. We use a null declaration to signal fields in
23815 assert((isa
<DeclRefExpr
>(SimpleRefExpr
) ||
23816 isa
<CXXThisExpr
>(cast
<MemberExpr
>(SimpleRefExpr
)->getBase())) &&
23817 "Unexpected device pointer expression!");
23818 MVLI
.VarBaseDeclarations
.push_back(
23819 isa
<DeclRefExpr
>(SimpleRefExpr
) ? D
: nullptr);
23820 MVLI
.VarComponents
.resize(MVLI
.VarComponents
.size() + 1);
23821 MVLI
.VarComponents
.back().push_back(MC
);
23824 if (MVLI
.ProcessedVarList
.empty())
23827 return OMPHasDeviceAddrClause::Create(Context
, Locs
, MVLI
.ProcessedVarList
,
23828 MVLI
.VarBaseDeclarations
,
23829 MVLI
.VarComponents
);
23832 OMPClause
*Sema::ActOnOpenMPAllocateClause(
23833 Expr
*Allocator
, ArrayRef
<Expr
*> VarList
, SourceLocation StartLoc
,
23834 SourceLocation ColonLoc
, SourceLocation LParenLoc
, SourceLocation EndLoc
) {
23836 // OpenMP [2.11.4 allocate Clause, Description]
23837 // allocator is an expression of omp_allocator_handle_t type.
23838 if (!findOMPAllocatorHandleT(*this, Allocator
->getExprLoc(), DSAStack
))
23841 ExprResult AllocatorRes
= DefaultLvalueConversion(Allocator
);
23842 if (AllocatorRes
.isInvalid())
23844 AllocatorRes
= PerformImplicitConversion(AllocatorRes
.get(),
23845 DSAStack
->getOMPAllocatorHandleT(),
23846 Sema::AA_Initializing
,
23847 /*AllowExplicit=*/true);
23848 if (AllocatorRes
.isInvalid())
23850 Allocator
= AllocatorRes
.get();
23852 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
23853 // allocate clauses that appear on a target construct or on constructs in a
23854 // target region must specify an allocator expression unless a requires
23855 // directive with the dynamic_allocators clause is present in the same
23856 // compilation unit.
23857 if (LangOpts
.OpenMPIsTargetDevice
&&
23858 !DSAStack
->hasRequiresDeclWithClause
<OMPDynamicAllocatorsClause
>())
23859 targetDiag(StartLoc
, diag::err_expected_allocator_expression
);
23861 // Analyze and build list of variables.
23862 SmallVector
<Expr
*, 8> Vars
;
23863 for (Expr
*RefExpr
: VarList
) {
23864 assert(RefExpr
&& "NULL expr in OpenMP private clause.");
23865 SourceLocation ELoc
;
23866 SourceRange ERange
;
23867 Expr
*SimpleRefExpr
= RefExpr
;
23868 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
23870 // It will be analyzed later.
23871 Vars
.push_back(RefExpr
);
23873 ValueDecl
*D
= Res
.first
;
23877 auto *VD
= dyn_cast
<VarDecl
>(D
);
23878 DeclRefExpr
*Ref
= nullptr;
23879 if (!VD
&& !CurContext
->isDependentContext())
23880 Ref
= buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/false);
23881 Vars
.push_back((VD
|| CurContext
->isDependentContext())
23882 ? RefExpr
->IgnoreParens()
23890 DSAStack
->addInnerAllocatorExpr(Allocator
);
23891 return OMPAllocateClause::Create(Context
, StartLoc
, LParenLoc
, Allocator
,
23892 ColonLoc
, EndLoc
, Vars
);
23895 OMPClause
*Sema::ActOnOpenMPNontemporalClause(ArrayRef
<Expr
*> VarList
,
23896 SourceLocation StartLoc
,
23897 SourceLocation LParenLoc
,
23898 SourceLocation EndLoc
) {
23899 SmallVector
<Expr
*, 8> Vars
;
23900 for (Expr
*RefExpr
: VarList
) {
23901 assert(RefExpr
&& "NULL expr in OpenMP nontemporal clause.");
23902 SourceLocation ELoc
;
23903 SourceRange ERange
;
23904 Expr
*SimpleRefExpr
= RefExpr
;
23905 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
23907 // It will be analyzed later.
23908 Vars
.push_back(RefExpr
);
23909 ValueDecl
*D
= Res
.first
;
23913 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
23914 // A list-item cannot appear in more than one nontemporal clause.
23915 if (const Expr
*PrevRef
=
23916 DSAStack
->addUniqueNontemporal(D
, SimpleRefExpr
)) {
23917 Diag(ELoc
, diag::err_omp_used_in_clause_twice
)
23918 << 0 << getOpenMPClauseName(OMPC_nontemporal
) << ERange
;
23919 Diag(PrevRef
->getExprLoc(), diag::note_omp_explicit_dsa
)
23920 << getOpenMPClauseName(OMPC_nontemporal
);
23924 Vars
.push_back(RefExpr
);
23930 return OMPNontemporalClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
,
23934 StmtResult
Sema::ActOnOpenMPScopeDirective(ArrayRef
<OMPClause
*> Clauses
,
23935 Stmt
*AStmt
, SourceLocation StartLoc
,
23936 SourceLocation EndLoc
) {
23938 return StmtError();
23940 setFunctionHasBranchProtectedScope();
23942 return OMPScopeDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
);
23945 OMPClause
*Sema::ActOnOpenMPInclusiveClause(ArrayRef
<Expr
*> VarList
,
23946 SourceLocation StartLoc
,
23947 SourceLocation LParenLoc
,
23948 SourceLocation EndLoc
) {
23949 SmallVector
<Expr
*, 8> Vars
;
23950 for (Expr
*RefExpr
: VarList
) {
23951 assert(RefExpr
&& "NULL expr in OpenMP nontemporal clause.");
23952 SourceLocation ELoc
;
23953 SourceRange ERange
;
23954 Expr
*SimpleRefExpr
= RefExpr
;
23955 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
,
23956 /*AllowArraySection=*/true);
23958 // It will be analyzed later.
23959 Vars
.push_back(RefExpr
);
23960 ValueDecl
*D
= Res
.first
;
23964 const DSAStackTy::DSAVarData DVar
=
23965 DSAStack
->getTopDSA(D
, /*FromParent=*/true);
23966 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23967 // A list item that appears in the inclusive or exclusive clause must appear
23968 // in a reduction clause with the inscan modifier on the enclosing
23969 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23970 if (DVar
.CKind
!= OMPC_reduction
|| DVar
.Modifier
!= OMPC_REDUCTION_inscan
)
23971 Diag(ELoc
, diag::err_omp_inclusive_exclusive_not_reduction
)
23972 << RefExpr
->getSourceRange();
23974 if (DSAStack
->getParentDirective() != OMPD_unknown
)
23975 DSAStack
->markDeclAsUsedInScanDirective(D
);
23976 Vars
.push_back(RefExpr
);
23982 return OMPInclusiveClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
, Vars
);
23985 OMPClause
*Sema::ActOnOpenMPExclusiveClause(ArrayRef
<Expr
*> VarList
,
23986 SourceLocation StartLoc
,
23987 SourceLocation LParenLoc
,
23988 SourceLocation EndLoc
) {
23989 SmallVector
<Expr
*, 8> Vars
;
23990 for (Expr
*RefExpr
: VarList
) {
23991 assert(RefExpr
&& "NULL expr in OpenMP nontemporal clause.");
23992 SourceLocation ELoc
;
23993 SourceRange ERange
;
23994 Expr
*SimpleRefExpr
= RefExpr
;
23995 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
,
23996 /*AllowArraySection=*/true);
23998 // It will be analyzed later.
23999 Vars
.push_back(RefExpr
);
24000 ValueDecl
*D
= Res
.first
;
24004 OpenMPDirectiveKind ParentDirective
= DSAStack
->getParentDirective();
24005 DSAStackTy::DSAVarData DVar
;
24006 if (ParentDirective
!= OMPD_unknown
)
24007 DVar
= DSAStack
->getTopDSA(D
, /*FromParent=*/true);
24008 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
24009 // A list item that appears in the inclusive or exclusive clause must appear
24010 // in a reduction clause with the inscan modifier on the enclosing
24011 // worksharing-loop, worksharing-loop SIMD, or simd construct.
24012 if (ParentDirective
== OMPD_unknown
|| DVar
.CKind
!= OMPC_reduction
||
24013 DVar
.Modifier
!= OMPC_REDUCTION_inscan
) {
24014 Diag(ELoc
, diag::err_omp_inclusive_exclusive_not_reduction
)
24015 << RefExpr
->getSourceRange();
24017 DSAStack
->markDeclAsUsedInScanDirective(D
);
24019 Vars
.push_back(RefExpr
);
24025 return OMPExclusiveClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
, Vars
);
24028 /// Tries to find omp_alloctrait_t type.
24029 static bool findOMPAlloctraitT(Sema
&S
, SourceLocation Loc
, DSAStackTy
*Stack
) {
24030 QualType OMPAlloctraitT
= Stack
->getOMPAlloctraitT();
24031 if (!OMPAlloctraitT
.isNull())
24033 IdentifierInfo
&II
= S
.PP
.getIdentifierTable().get("omp_alloctrait_t");
24034 ParsedType PT
= S
.getTypeName(II
, Loc
, S
.getCurScope());
24035 if (!PT
.getAsOpaquePtr() || PT
.get().isNull()) {
24036 S
.Diag(Loc
, diag::err_omp_implied_type_not_found
) << "omp_alloctrait_t";
24039 Stack
->setOMPAlloctraitT(PT
.get());
24043 OMPClause
*Sema::ActOnOpenMPUsesAllocatorClause(
24044 SourceLocation StartLoc
, SourceLocation LParenLoc
, SourceLocation EndLoc
,
24045 ArrayRef
<UsesAllocatorsData
> Data
) {
24046 // OpenMP [2.12.5, target Construct]
24047 // allocator is an identifier of omp_allocator_handle_t type.
24048 if (!findOMPAllocatorHandleT(*this, StartLoc
, DSAStack
))
24050 // OpenMP [2.12.5, target Construct]
24051 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
24054 [](const UsesAllocatorsData
&D
) { return D
.AllocatorTraits
; }) &&
24055 !findOMPAlloctraitT(*this, StartLoc
, DSAStack
))
24057 llvm::SmallPtrSet
<CanonicalDeclPtr
<Decl
>, 4> PredefinedAllocators
;
24058 for (int I
= 0; I
< OMPAllocateDeclAttr::OMPUserDefinedMemAlloc
; ++I
) {
24059 auto AllocatorKind
= static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I
);
24060 StringRef Allocator
=
24061 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind
);
24062 DeclarationName AllocatorName
= &Context
.Idents
.get(Allocator
);
24063 PredefinedAllocators
.insert(LookupSingleName(
24064 TUScope
, AllocatorName
, StartLoc
, Sema::LookupAnyName
));
24067 SmallVector
<OMPUsesAllocatorsClause::Data
, 4> NewData
;
24068 for (const UsesAllocatorsData
&D
: Data
) {
24069 Expr
*AllocatorExpr
= nullptr;
24070 // Check allocator expression.
24071 if (D
.Allocator
->isTypeDependent()) {
24072 AllocatorExpr
= D
.Allocator
;
24074 // Traits were specified - need to assign new allocator to the specified
24075 // allocator, so it must be an lvalue.
24076 AllocatorExpr
= D
.Allocator
->IgnoreParenImpCasts();
24077 auto *DRE
= dyn_cast
<DeclRefExpr
>(AllocatorExpr
);
24078 bool IsPredefinedAllocator
= false;
24080 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy
=
24081 getAllocatorKind(*this, DSAStack
, AllocatorExpr
);
24082 IsPredefinedAllocator
=
24084 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc
;
24086 QualType OMPAllocatorHandleT
= DSAStack
->getOMPAllocatorHandleT();
24087 QualType AllocatorExprType
= AllocatorExpr
->getType();
24088 bool IsTypeCompatible
= IsPredefinedAllocator
;
24089 IsTypeCompatible
= IsTypeCompatible
||
24090 Context
.hasSameUnqualifiedType(AllocatorExprType
,
24091 OMPAllocatorHandleT
);
24093 IsTypeCompatible
||
24094 Context
.typesAreCompatible(AllocatorExprType
, OMPAllocatorHandleT
);
24095 bool IsNonConstantLValue
=
24096 !AllocatorExprType
.isConstant(Context
) && AllocatorExpr
->isLValue();
24097 if (!DRE
|| !IsTypeCompatible
||
24098 (!IsPredefinedAllocator
&& !IsNonConstantLValue
)) {
24099 Diag(D
.Allocator
->getExprLoc(), diag::err_omp_var_expected
)
24100 << "omp_allocator_handle_t" << (DRE
? 1 : 0)
24101 << AllocatorExpr
->getType() << D
.Allocator
->getSourceRange();
24104 // OpenMP [2.12.5, target Construct]
24105 // Predefined allocators appearing in a uses_allocators clause cannot have
24106 // traits specified.
24107 if (IsPredefinedAllocator
&& D
.AllocatorTraits
) {
24108 Diag(D
.AllocatorTraits
->getExprLoc(),
24109 diag::err_omp_predefined_allocator_with_traits
)
24110 << D
.AllocatorTraits
->getSourceRange();
24111 Diag(D
.Allocator
->getExprLoc(), diag::note_omp_predefined_allocator
)
24112 << cast
<NamedDecl
>(DRE
->getDecl())->getName()
24113 << D
.Allocator
->getSourceRange();
24116 // OpenMP [2.12.5, target Construct]
24117 // Non-predefined allocators appearing in a uses_allocators clause must
24118 // have traits specified.
24119 if (!IsPredefinedAllocator
&& !D
.AllocatorTraits
) {
24120 Diag(D
.Allocator
->getExprLoc(),
24121 diag::err_omp_nonpredefined_allocator_without_traits
);
24124 // No allocator traits - just convert it to rvalue.
24125 if (!D
.AllocatorTraits
)
24126 AllocatorExpr
= DefaultLvalueConversion(AllocatorExpr
).get();
24127 DSAStack
->addUsesAllocatorsDecl(
24129 IsPredefinedAllocator
24130 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
24131 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator
);
24133 Expr
*AllocatorTraitsExpr
= nullptr;
24134 if (D
.AllocatorTraits
) {
24135 if (D
.AllocatorTraits
->isTypeDependent()) {
24136 AllocatorTraitsExpr
= D
.AllocatorTraits
;
24138 // OpenMP [2.12.5, target Construct]
24139 // Arrays that contain allocator traits that appear in a uses_allocators
24140 // clause must be constant arrays, have constant values and be defined
24141 // in the same scope as the construct in which the clause appears.
24142 AllocatorTraitsExpr
= D
.AllocatorTraits
->IgnoreParenImpCasts();
24143 // Check that traits expr is a constant array.
24145 if (const ArrayType
*Ty
=
24146 AllocatorTraitsExpr
->getType()->getAsArrayTypeUnsafe())
24147 if (const auto *ConstArrayTy
= dyn_cast
<ConstantArrayType
>(Ty
))
24148 TraitTy
= ConstArrayTy
->getElementType();
24149 if (TraitTy
.isNull() ||
24150 !(Context
.hasSameUnqualifiedType(TraitTy
,
24151 DSAStack
->getOMPAlloctraitT()) ||
24152 Context
.typesAreCompatible(TraitTy
, DSAStack
->getOMPAlloctraitT(),
24153 /*CompareUnqualified=*/true))) {
24154 Diag(D
.AllocatorTraits
->getExprLoc(),
24155 diag::err_omp_expected_array_alloctraits
)
24156 << AllocatorTraitsExpr
->getType();
24159 // Do not map by default allocator traits if it is a standalone
24161 if (auto *DRE
= dyn_cast
<DeclRefExpr
>(AllocatorTraitsExpr
))
24162 DSAStack
->addUsesAllocatorsDecl(
24164 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait
);
24167 OMPUsesAllocatorsClause::Data
&NewD
= NewData
.emplace_back();
24168 NewD
.Allocator
= AllocatorExpr
;
24169 NewD
.AllocatorTraits
= AllocatorTraitsExpr
;
24170 NewD
.LParenLoc
= D
.LParenLoc
;
24171 NewD
.RParenLoc
= D
.RParenLoc
;
24173 return OMPUsesAllocatorsClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
,
24177 OMPClause
*Sema::ActOnOpenMPAffinityClause(
24178 SourceLocation StartLoc
, SourceLocation LParenLoc
, SourceLocation ColonLoc
,
24179 SourceLocation EndLoc
, Expr
*Modifier
, ArrayRef
<Expr
*> Locators
) {
24180 SmallVector
<Expr
*, 8> Vars
;
24181 for (Expr
*RefExpr
: Locators
) {
24182 assert(RefExpr
&& "NULL expr in OpenMP shared clause.");
24183 if (isa
<DependentScopeDeclRefExpr
>(RefExpr
) || RefExpr
->isTypeDependent()) {
24184 // It will be analyzed later.
24185 Vars
.push_back(RefExpr
);
24189 SourceLocation ELoc
= RefExpr
->getExprLoc();
24190 Expr
*SimpleExpr
= RefExpr
->IgnoreParenImpCasts();
24192 if (!SimpleExpr
->isLValue()) {
24193 Diag(ELoc
, diag::err_omp_expected_addressable_lvalue_or_array_item
)
24194 << 1 << 0 << RefExpr
->getSourceRange();
24200 Sema::TentativeAnalysisScope
Trap(*this);
24201 Res
= CreateBuiltinUnaryOp(ELoc
, UO_AddrOf
, SimpleExpr
);
24203 if (!Res
.isUsable() && !isa
<OMPArraySectionExpr
>(SimpleExpr
) &&
24204 !isa
<OMPArrayShapingExpr
>(SimpleExpr
)) {
24205 Diag(ELoc
, diag::err_omp_expected_addressable_lvalue_or_array_item
)
24206 << 1 << 0 << RefExpr
->getSourceRange();
24209 Vars
.push_back(SimpleExpr
);
24212 return OMPAffinityClause::Create(Context
, StartLoc
, LParenLoc
, ColonLoc
,
24213 EndLoc
, Modifier
, Vars
);
24216 OMPClause
*Sema::ActOnOpenMPBindClause(OpenMPBindClauseKind Kind
,
24217 SourceLocation KindLoc
,
24218 SourceLocation StartLoc
,
24219 SourceLocation LParenLoc
,
24220 SourceLocation EndLoc
) {
24221 if (Kind
== OMPC_BIND_unknown
) {
24222 Diag(KindLoc
, diag::err_omp_unexpected_clause_value
)
24223 << getListOfPossibleValues(OMPC_bind
, /*First=*/0,
24224 /*Last=*/unsigned(OMPC_BIND_unknown
))
24225 << getOpenMPClauseName(OMPC_bind
);
24229 return OMPBindClause::Create(Context
, Kind
, KindLoc
, StartLoc
, LParenLoc
,
24233 OMPClause
*Sema::ActOnOpenMPXDynCGroupMemClause(Expr
*Size
,
24234 SourceLocation StartLoc
,
24235 SourceLocation LParenLoc
,
24236 SourceLocation EndLoc
) {
24237 Expr
*ValExpr
= Size
;
24238 Stmt
*HelperValStmt
= nullptr;
24240 // OpenMP [2.5, Restrictions]
24241 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
24243 if (!isNonNegativeIntegerValue(ValExpr
, *this, OMPC_ompx_dyn_cgroup_mem
,
24244 /*StrictlyPositive=*/false))
24247 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
24248 OpenMPDirectiveKind CaptureRegion
= getOpenMPCaptureRegionForClause(
24249 DKind
, OMPC_ompx_dyn_cgroup_mem
, LangOpts
.OpenMP
);
24250 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
24251 ValExpr
= MakeFullExpr(ValExpr
).get();
24252 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
24253 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
24254 HelperValStmt
= buildPreInits(Context
, Captures
);
24257 return new (Context
) OMPXDynCGroupMemClause(
24258 ValExpr
, HelperValStmt
, CaptureRegion
, StartLoc
, LParenLoc
, EndLoc
);
24261 OMPClause
*Sema::ActOnOpenMPDoacrossClause(
24262 OpenMPDoacrossClauseModifier DepType
, SourceLocation DepLoc
,
24263 SourceLocation ColonLoc
, ArrayRef
<Expr
*> VarList
, SourceLocation StartLoc
,
24264 SourceLocation LParenLoc
, SourceLocation EndLoc
) {
24266 if (DSAStack
->getCurrentDirective() == OMPD_ordered
&&
24267 DepType
!= OMPC_DOACROSS_source
&& DepType
!= OMPC_DOACROSS_sink
&&
24268 DepType
!= OMPC_DOACROSS_sink_omp_cur_iteration
&&
24269 DepType
!= OMPC_DOACROSS_source_omp_cur_iteration
&&
24270 DepType
!= OMPC_DOACROSS_source
) {
24271 Diag(DepLoc
, diag::err_omp_unexpected_clause_value
)
24272 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_doacross
);
24276 SmallVector
<Expr
*, 8> Vars
;
24277 DSAStackTy::OperatorOffsetTy OpsOffs
;
24278 llvm::APSInt
TotalDepCount(/*BitWidth=*/32);
24279 DoacrossDataInfoTy VarOffset
= ProcessOpenMPDoacrossClauseCommon(
24281 DepType
== OMPC_DOACROSS_source
||
24282 DepType
== OMPC_DOACROSS_source_omp_cur_iteration
||
24283 DepType
== OMPC_DOACROSS_sink_omp_cur_iteration
,
24284 VarList
, DSAStack
, EndLoc
);
24285 Vars
= VarOffset
.Vars
;
24286 OpsOffs
= VarOffset
.OpsOffs
;
24287 TotalDepCount
= VarOffset
.TotalDepCount
;
24288 auto *C
= OMPDoacrossClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
,
24289 DepType
, DepLoc
, ColonLoc
, Vars
,
24290 TotalDepCount
.getZExtValue());
24291 if (DSAStack
->isParentOrderedRegion())
24292 DSAStack
->addDoacrossDependClause(C
, OpsOffs
);
24296 OMPClause
*Sema::ActOnOpenMPXAttributeClause(ArrayRef
<const Attr
*> Attrs
,
24297 SourceLocation StartLoc
,
24298 SourceLocation LParenLoc
,
24299 SourceLocation EndLoc
) {
24300 return new (Context
) OMPXAttributeClause(Attrs
, StartLoc
, LParenLoc
, EndLoc
);
24303 OMPClause
*Sema::ActOnOpenMPXBareClause(SourceLocation StartLoc
,
24304 SourceLocation EndLoc
) {
24305 return new (Context
) OMPXBareClause(StartLoc
, EndLoc
);