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
+ 1];
165 OpenMPDirectiveKind Directive
= OMPD_unknown
;
166 /// GenericLoopDirective with bind clause is mapped to other directives,
167 /// like for, distribute and simd. Presently, set MappedDirective to
168 /// OMPLoop. This may also be used in a similar way for other constructs.
169 OpenMPDirectiveKind MappedDirective
= OMPD_unknown
;
170 DeclarationNameInfo DirectiveName
;
171 Scope
*CurScope
= nullptr;
172 DeclContext
*Context
= nullptr;
173 SourceLocation ConstructLoc
;
174 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
175 /// get the data (loop counters etc.) about enclosing loop-based construct.
176 /// This data is required during codegen.
177 DoacrossClauseMapTy DoacrossDepends
;
178 /// First argument (Expr *) contains optional argument of the
179 /// 'ordered' clause, the second one is true if the regions has 'ordered'
180 /// clause, false otherwise.
181 std::optional
<std::pair
<const Expr
*, OMPOrderedClause
*>> OrderedRegion
;
182 bool RegionHasOrderConcurrent
= false;
183 unsigned AssociatedLoops
= 1;
184 bool HasMutipleLoops
= false;
185 const Decl
*PossiblyLoopCounter
= nullptr;
186 bool NowaitRegion
= false;
187 bool UntiedRegion
= false;
188 bool CancelRegion
= false;
189 bool LoopStart
= false;
190 bool BodyComplete
= false;
191 SourceLocation PrevScanLocation
;
192 SourceLocation PrevOrderedLocation
;
193 SourceLocation InnerTeamsRegionLoc
;
194 /// Reference to the taskgroup task_reduction reference expression.
195 Expr
*TaskgroupReductionRef
= nullptr;
196 llvm::DenseSet
<QualType
> MappedClassesQualTypes
;
197 SmallVector
<Expr
*, 4> InnerUsedAllocators
;
198 llvm::DenseSet
<CanonicalDeclPtr
<Decl
>> ImplicitTaskFirstprivates
;
199 /// List of globals marked as declare target link in this target region
200 /// (isOpenMPTargetExecutionDirective(Directive) == true).
201 llvm::SmallVector
<DeclRefExpr
*, 4> DeclareTargetLinkVarDecls
;
202 /// List of decls used in inclusive/exclusive clauses of the scan directive.
203 llvm::DenseSet
<CanonicalDeclPtr
<Decl
>> UsedInScanDirective
;
204 llvm::DenseMap
<CanonicalDeclPtr
<const Decl
>, UsesAllocatorsDeclKind
>
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_unknown
+ 1;
3693 llvm::SmallVector
<Expr
*, 4> ImplicitFirstprivate
;
3694 llvm::SmallVector
<Expr
*, 4> ImplicitPrivate
;
3695 llvm::SmallVector
<Expr
*, 4> ImplicitMap
[DefaultmapKindNum
][OMPC_MAP_delete
];
3696 llvm::SmallVector
<OpenMPMapModifierKind
, NumberOfOMPMapClauseModifiers
>
3697 ImplicitMapModifier
[DefaultmapKindNum
];
3698 Sema::VarsWithInheritedDSAType VarsWithInheritedDSA
;
3699 llvm::SmallDenseSet
<const ValueDecl
*, 4> ImplicitDeclarations
;
3701 void VisitSubCaptures(OMPExecutableDirective
*S
) {
3702 // Check implicitly captured variables.
3703 if (!S
->hasAssociatedStmt() || !S
->getAssociatedStmt())
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_unknown
+ 1;
6280 SmallVector
<Expr
*, 4> ImplicitMaps
[DefaultmapKindNum
][OMPC_MAP_delete
];
6281 SmallVector
<OpenMPMapModifierKind
, NumberOfOMPMapClauseModifiers
>
6282 ImplicitMapModifiers
[DefaultmapKindNum
];
6283 SmallVector
<SourceLocation
, NumberOfOMPMapClauseModifiers
>
6284 ImplicitMapModifiersLoc
[DefaultmapKindNum
];
6285 // Get the original location of present modifier from Defaultmap clause.
6286 SourceLocation PresentModifierLocs
[DefaultmapKindNum
];
6287 for (OMPClause
*C
: Clauses
) {
6288 if (auto *DMC
= dyn_cast
<OMPDefaultmapClause
>(C
))
6289 if (DMC
->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present
)
6290 PresentModifierLocs
[DMC
->getDefaultmapKind()] =
6291 DMC
->getDefaultmapModifierLoc();
6293 for (unsigned VC
= 0; VC
< DefaultmapKindNum
; ++VC
) {
6294 auto Kind
= static_cast<OpenMPDefaultmapClauseKind
>(VC
);
6295 for (unsigned I
= 0; I
< OMPC_MAP_delete
; ++I
) {
6296 ArrayRef
<Expr
*> ImplicitMap
= DSAChecker
.getImplicitMap(
6297 Kind
, static_cast<OpenMPMapClauseKind
>(I
));
6298 ImplicitMaps
[VC
][I
].append(ImplicitMap
.begin(), ImplicitMap
.end());
6300 ArrayRef
<OpenMPMapModifierKind
> ImplicitModifier
=
6301 DSAChecker
.getImplicitMapModifier(Kind
);
6302 ImplicitMapModifiers
[VC
].append(ImplicitModifier
.begin(),
6303 ImplicitModifier
.end());
6304 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc
[VC
]),
6305 ImplicitModifier
.size(), PresentModifierLocs
[VC
]);
6307 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6308 for (OMPClause
*C
: Clauses
) {
6309 if (auto *IRC
= dyn_cast
<OMPInReductionClause
>(C
)) {
6310 for (Expr
*E
: IRC
->taskgroup_descriptors())
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 /// An expression contains semantical error not related to
11609 /// 'omp atomic [update]'
11610 NotAValidExpression
,
11611 /// No errors is found.
11614 /// Reference to Sema.
11616 /// A location for note diagnostics (when error is found).
11617 SourceLocation NoteLoc
;
11618 /// 'x' lvalue part of the source atomic expression.
11620 /// 'expr' rvalue part of the source atomic expression.
11622 /// Helper expression of the form
11623 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11624 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11626 /// Is 'x' a LHS in a RHS part of full update expression. It is
11627 /// important for non-associative operations.
11628 bool IsXLHSInRHSPart
;
11629 BinaryOperatorKind Op
;
11630 SourceLocation OpLoc
;
11631 /// true if the source expression is a postfix unary operation, false
11632 /// if it is a prefix unary operation.
11633 bool IsPostfixUpdate
;
11636 OpenMPAtomicUpdateChecker(Sema
&SemaRef
)
11637 : SemaRef(SemaRef
), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11638 IsXLHSInRHSPart(false), Op(BO_PtrMemD
), IsPostfixUpdate(false) {}
11639 /// Check specified statement that it is suitable for 'atomic update'
11640 /// constructs and extract 'x', 'expr' and Operation from the original
11641 /// expression. If DiagId and NoteId == 0, then only check is performed
11642 /// without error notification.
11643 /// \param DiagId Diagnostic which should be emitted if error is found.
11644 /// \param NoteId Diagnostic note for the main error message.
11645 /// \return true if statement is not an update expression, false otherwise.
11646 bool checkStatement(Stmt
*S
, unsigned DiagId
= 0, unsigned NoteId
= 0);
11647 /// Return the 'x' lvalue part of the source atomic expression.
11648 Expr
*getX() const { return X
; }
11649 /// Return the 'expr' rvalue part of the source atomic expression.
11650 Expr
*getExpr() const { return E
; }
11651 /// Return the update expression used in calculation of the updated
11652 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11653 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11654 Expr
*getUpdateExpr() const { return UpdateExpr
; }
11655 /// Return true if 'x' is LHS in RHS part of full update expression,
11656 /// false otherwise.
11657 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart
; }
11659 /// true if the source expression is a postfix unary operation, false
11660 /// if it is a prefix unary operation.
11661 bool isPostfixUpdate() const { return IsPostfixUpdate
; }
11664 bool checkBinaryOperation(BinaryOperator
*AtomicBinOp
, unsigned DiagId
= 0,
11665 unsigned NoteId
= 0);
11668 bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11669 BinaryOperator
*AtomicBinOp
, unsigned DiagId
, unsigned NoteId
) {
11670 ExprAnalysisErrorCode ErrorFound
= NoError
;
11671 SourceLocation ErrorLoc
, NoteLoc
;
11672 SourceRange ErrorRange
, NoteRange
;
11673 // Allowed constructs are:
11674 // x = x binop expr;
11675 // x = expr binop x;
11676 if (AtomicBinOp
->getOpcode() == BO_Assign
) {
11677 X
= AtomicBinOp
->getLHS();
11678 if (const auto *AtomicInnerBinOp
= dyn_cast
<BinaryOperator
>(
11679 AtomicBinOp
->getRHS()->IgnoreParenImpCasts())) {
11680 if (AtomicInnerBinOp
->isMultiplicativeOp() ||
11681 AtomicInnerBinOp
->isAdditiveOp() || AtomicInnerBinOp
->isShiftOp() ||
11682 AtomicInnerBinOp
->isBitwiseOp()) {
11683 Op
= AtomicInnerBinOp
->getOpcode();
11684 OpLoc
= AtomicInnerBinOp
->getOperatorLoc();
11685 Expr
*LHS
= AtomicInnerBinOp
->getLHS();
11686 Expr
*RHS
= AtomicInnerBinOp
->getRHS();
11687 llvm::FoldingSetNodeID XId
, LHSId
, RHSId
;
11688 X
->IgnoreParenImpCasts()->Profile(XId
, SemaRef
.getASTContext(),
11689 /*Canonical=*/true);
11690 LHS
->IgnoreParenImpCasts()->Profile(LHSId
, SemaRef
.getASTContext(),
11691 /*Canonical=*/true);
11692 RHS
->IgnoreParenImpCasts()->Profile(RHSId
, SemaRef
.getASTContext(),
11693 /*Canonical=*/true);
11694 if (XId
== LHSId
) {
11696 IsXLHSInRHSPart
= true;
11697 } else if (XId
== RHSId
) {
11699 IsXLHSInRHSPart
= false;
11701 ErrorLoc
= AtomicInnerBinOp
->getExprLoc();
11702 ErrorRange
= AtomicInnerBinOp
->getSourceRange();
11703 NoteLoc
= X
->getExprLoc();
11704 NoteRange
= X
->getSourceRange();
11705 ErrorFound
= NotAnUpdateExpression
;
11708 ErrorLoc
= AtomicInnerBinOp
->getExprLoc();
11709 ErrorRange
= AtomicInnerBinOp
->getSourceRange();
11710 NoteLoc
= AtomicInnerBinOp
->getOperatorLoc();
11711 NoteRange
= SourceRange(NoteLoc
, NoteLoc
);
11712 ErrorFound
= NotABinaryOperator
;
11715 NoteLoc
= ErrorLoc
= AtomicBinOp
->getRHS()->getExprLoc();
11716 NoteRange
= ErrorRange
= AtomicBinOp
->getRHS()->getSourceRange();
11717 ErrorFound
= NotABinaryExpression
;
11720 ErrorLoc
= AtomicBinOp
->getExprLoc();
11721 ErrorRange
= AtomicBinOp
->getSourceRange();
11722 NoteLoc
= AtomicBinOp
->getOperatorLoc();
11723 NoteRange
= SourceRange(NoteLoc
, NoteLoc
);
11724 ErrorFound
= NotAnAssignmentOp
;
11726 if (ErrorFound
!= NoError
&& DiagId
!= 0 && NoteId
!= 0) {
11727 SemaRef
.Diag(ErrorLoc
, DiagId
) << ErrorRange
;
11728 SemaRef
.Diag(NoteLoc
, NoteId
) << ErrorFound
<< NoteRange
;
11731 if (SemaRef
.CurContext
->isDependentContext())
11732 E
= X
= UpdateExpr
= nullptr;
11733 return ErrorFound
!= NoError
;
11736 bool OpenMPAtomicUpdateChecker::checkStatement(Stmt
*S
, unsigned DiagId
,
11738 ExprAnalysisErrorCode ErrorFound
= NoError
;
11739 SourceLocation ErrorLoc
, NoteLoc
;
11740 SourceRange ErrorRange
, NoteRange
;
11741 // Allowed constructs are:
11747 // x = x binop expr;
11748 // x = expr binop x;
11749 if (auto *AtomicBody
= dyn_cast
<Expr
>(S
)) {
11750 AtomicBody
= AtomicBody
->IgnoreParenImpCasts();
11751 if (AtomicBody
->getType()->isScalarType() ||
11752 AtomicBody
->isInstantiationDependent()) {
11753 if (const auto *AtomicCompAssignOp
= dyn_cast
<CompoundAssignOperator
>(
11754 AtomicBody
->IgnoreParenImpCasts())) {
11755 // Check for Compound Assignment Operation
11756 Op
= BinaryOperator::getOpForCompoundAssignment(
11757 AtomicCompAssignOp
->getOpcode());
11758 OpLoc
= AtomicCompAssignOp
->getOperatorLoc();
11759 E
= AtomicCompAssignOp
->getRHS();
11760 X
= AtomicCompAssignOp
->getLHS()->IgnoreParens();
11761 IsXLHSInRHSPart
= true;
11762 } else if (auto *AtomicBinOp
= dyn_cast
<BinaryOperator
>(
11763 AtomicBody
->IgnoreParenImpCasts())) {
11764 // Check for Binary Operation
11765 if (checkBinaryOperation(AtomicBinOp
, DiagId
, NoteId
))
11767 } else if (const auto *AtomicUnaryOp
= dyn_cast
<UnaryOperator
>(
11768 AtomicBody
->IgnoreParenImpCasts())) {
11769 // Check for Unary Operation
11770 if (AtomicUnaryOp
->isIncrementDecrementOp()) {
11771 IsPostfixUpdate
= AtomicUnaryOp
->isPostfix();
11772 Op
= AtomicUnaryOp
->isIncrementOp() ? BO_Add
: BO_Sub
;
11773 OpLoc
= AtomicUnaryOp
->getOperatorLoc();
11774 X
= AtomicUnaryOp
->getSubExpr()->IgnoreParens();
11775 E
= SemaRef
.ActOnIntegerConstant(OpLoc
, /*uint64_t Val=*/1).get();
11776 IsXLHSInRHSPart
= true;
11778 ErrorFound
= NotAnUnaryIncDecExpression
;
11779 ErrorLoc
= AtomicUnaryOp
->getExprLoc();
11780 ErrorRange
= AtomicUnaryOp
->getSourceRange();
11781 NoteLoc
= AtomicUnaryOp
->getOperatorLoc();
11782 NoteRange
= SourceRange(NoteLoc
, NoteLoc
);
11784 } else if (!AtomicBody
->isInstantiationDependent()) {
11785 ErrorFound
= NotABinaryOrUnaryExpression
;
11786 NoteLoc
= ErrorLoc
= AtomicBody
->getExprLoc();
11787 NoteRange
= ErrorRange
= AtomicBody
->getSourceRange();
11788 } else if (AtomicBody
->containsErrors()) {
11789 ErrorFound
= NotAValidExpression
;
11790 NoteLoc
= ErrorLoc
= AtomicBody
->getExprLoc();
11791 NoteRange
= ErrorRange
= AtomicBody
->getSourceRange();
11794 ErrorFound
= NotAScalarType
;
11795 NoteLoc
= ErrorLoc
= AtomicBody
->getBeginLoc();
11796 NoteRange
= ErrorRange
= SourceRange(NoteLoc
, NoteLoc
);
11799 ErrorFound
= NotAnExpression
;
11800 NoteLoc
= ErrorLoc
= S
->getBeginLoc();
11801 NoteRange
= ErrorRange
= SourceRange(NoteLoc
, NoteLoc
);
11803 if (ErrorFound
!= NoError
&& DiagId
!= 0 && NoteId
!= 0) {
11804 SemaRef
.Diag(ErrorLoc
, DiagId
) << ErrorRange
;
11805 SemaRef
.Diag(NoteLoc
, NoteId
) << ErrorFound
<< NoteRange
;
11808 if (SemaRef
.CurContext
->isDependentContext())
11809 E
= X
= UpdateExpr
= nullptr;
11810 if (ErrorFound
== NoError
&& E
&& X
) {
11811 // Build an update expression of form 'OpaqueValueExpr(x) binop
11812 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11813 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11814 auto *OVEX
= new (SemaRef
.getASTContext())
11815 OpaqueValueExpr(X
->getExprLoc(), X
->getType(), VK_PRValue
);
11816 auto *OVEExpr
= new (SemaRef
.getASTContext())
11817 OpaqueValueExpr(E
->getExprLoc(), E
->getType(), VK_PRValue
);
11818 ExprResult Update
=
11819 SemaRef
.CreateBuiltinBinOp(OpLoc
, Op
, IsXLHSInRHSPart
? OVEX
: OVEExpr
,
11820 IsXLHSInRHSPart
? OVEExpr
: OVEX
);
11821 if (Update
.isInvalid())
11823 Update
= SemaRef
.PerformImplicitConversion(Update
.get(), X
->getType(),
11825 if (Update
.isInvalid())
11827 UpdateExpr
= Update
.get();
11829 return ErrorFound
!= NoError
;
11832 /// Get the node id of the fixed point of an expression \a S.
11833 llvm::FoldingSetNodeID
getNodeId(ASTContext
&Context
, const Expr
*S
) {
11834 llvm::FoldingSetNodeID Id
;
11835 S
->IgnoreParenImpCasts()->Profile(Id
, Context
, true);
11839 /// Check if two expressions are same.
11840 bool checkIfTwoExprsAreSame(ASTContext
&Context
, const Expr
*LHS
,
11842 return getNodeId(Context
, LHS
) == getNodeId(Context
, RHS
);
11845 class OpenMPAtomicCompareChecker
{
11847 /// All kinds of errors that can occur in `atomic compare`
11849 /// Empty compound statement.
11851 /// More than one statement in a compound statement.
11853 /// Not an assignment binary operator.
11855 /// Not a conditional operator.
11857 /// Wrong false expr. According to the spec, 'x' should be at the false
11858 /// expression of a conditional expression.
11860 /// The condition of a conditional expression is not a binary operator.
11862 /// Invalid binary operator (not <, >, or ==).
11864 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11866 /// X is not a lvalue.
11870 /// Not an integer.
11872 /// 'else' statement is not expected.
11874 /// Not an equality operator.
11876 /// Invalid assignment (not v == x).
11878 /// Not if statement
11880 /// More than two statements in a compund statement.
11882 /// Not a compound statement.
11884 /// No else statement.
11892 struct ErrorInfoTy
{
11894 SourceLocation ErrorLoc
;
11895 SourceRange ErrorRange
;
11896 SourceLocation NoteLoc
;
11897 SourceRange NoteRange
;
11900 OpenMPAtomicCompareChecker(Sema
&S
) : ContextRef(S
.getASTContext()) {}
11902 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11903 bool checkStmt(Stmt
*S
, ErrorInfoTy
&ErrorInfo
);
11905 Expr
*getX() const { return X
; }
11906 Expr
*getE() const { return E
; }
11907 Expr
*getD() const { return D
; }
11908 Expr
*getCond() const { return C
; }
11909 bool isXBinopExpr() const { return IsXBinopExpr
; }
11912 /// Reference to ASTContext
11913 ASTContext
&ContextRef
;
11914 /// 'x' lvalue part of the source atomic expression.
11916 /// 'expr' or 'e' rvalue part of the source atomic expression.
11918 /// 'd' rvalue part of the source atomic expression.
11920 /// 'cond' part of the source atomic expression. It is in one of the following
11927 /// True if the cond expr is in the form of 'x ordop expr'.
11928 bool IsXBinopExpr
= true;
11930 /// Check if it is a valid conditional update statement (cond-update-stmt).
11931 bool checkCondUpdateStmt(IfStmt
*S
, ErrorInfoTy
&ErrorInfo
);
11933 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11934 bool checkCondExprStmt(Stmt
*S
, ErrorInfoTy
&ErrorInfo
);
11936 /// Check if all captured values have right type.
11937 bool checkType(ErrorInfoTy
&ErrorInfo
) const;
11939 static bool CheckValue(const Expr
*E
, ErrorInfoTy
&ErrorInfo
,
11940 bool ShouldBeLValue
, bool ShouldBeInteger
= false) {
11941 if (E
->isInstantiationDependent())
11944 if (ShouldBeLValue
&& !E
->isLValue()) {
11945 ErrorInfo
.Error
= ErrorTy::XNotLValue
;
11946 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= E
->getExprLoc();
11947 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= E
->getSourceRange();
11951 QualType QTy
= E
->getType();
11952 if (!QTy
->isScalarType()) {
11953 ErrorInfo
.Error
= ErrorTy::NotScalar
;
11954 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= E
->getExprLoc();
11955 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= E
->getSourceRange();
11958 if (ShouldBeInteger
&& !QTy
->isIntegerType()) {
11959 ErrorInfo
.Error
= ErrorTy::NotInteger
;
11960 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= E
->getExprLoc();
11961 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= E
->getSourceRange();
11969 bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt
*S
,
11970 ErrorInfoTy
&ErrorInfo
) {
11971 auto *Then
= S
->getThen();
11972 if (auto *CS
= dyn_cast
<CompoundStmt
>(Then
)) {
11973 if (CS
->body_empty()) {
11974 ErrorInfo
.Error
= ErrorTy::NoStmt
;
11975 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
11976 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= CS
->getSourceRange();
11979 if (CS
->size() > 1) {
11980 ErrorInfo
.Error
= ErrorTy::MoreThanOneStmt
;
11981 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
11982 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S
->getSourceRange();
11985 Then
= CS
->body_front();
11988 auto *BO
= dyn_cast
<BinaryOperator
>(Then
);
11990 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
11991 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Then
->getBeginLoc();
11992 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Then
->getSourceRange();
11995 if (BO
->getOpcode() != BO_Assign
) {
11996 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
11997 ErrorInfo
.ErrorLoc
= BO
->getExprLoc();
11998 ErrorInfo
.NoteLoc
= BO
->getOperatorLoc();
11999 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= BO
->getSourceRange();
12005 auto *Cond
= dyn_cast
<BinaryOperator
>(S
->getCond());
12007 ErrorInfo
.Error
= ErrorTy::NotABinaryOp
;
12008 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= S
->getCond()->getExprLoc();
12009 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S
->getCond()->getSourceRange();
12013 switch (Cond
->getOpcode()) {
12017 if (checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getLHS())) {
12018 E
= Cond
->getRHS();
12019 } else if (checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getRHS())) {
12020 E
= Cond
->getLHS();
12022 ErrorInfo
.Error
= ErrorTy::InvalidComparison
;
12023 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Cond
->getExprLoc();
12024 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Cond
->getSourceRange();
12032 if (checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getLHS()) &&
12033 checkIfTwoExprsAreSame(ContextRef
, E
, Cond
->getRHS())) {
12035 } else if (checkIfTwoExprsAreSame(ContextRef
, E
, Cond
->getLHS()) &&
12036 checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getRHS())) {
12038 IsXBinopExpr
= false;
12040 ErrorInfo
.Error
= ErrorTy::InvalidComparison
;
12041 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Cond
->getExprLoc();
12042 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Cond
->getSourceRange();
12048 ErrorInfo
.Error
= ErrorTy::InvalidBinaryOp
;
12049 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Cond
->getExprLoc();
12050 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Cond
->getSourceRange();
12054 if (S
->getElse()) {
12055 ErrorInfo
.Error
= ErrorTy::UnexpectedElse
;
12056 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= S
->getElse()->getBeginLoc();
12057 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S
->getElse()->getSourceRange();
12064 bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt
*S
,
12065 ErrorInfoTy
&ErrorInfo
) {
12066 auto *BO
= dyn_cast
<BinaryOperator
>(S
);
12068 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12069 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= S
->getBeginLoc();
12070 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S
->getSourceRange();
12073 if (BO
->getOpcode() != BO_Assign
) {
12074 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12075 ErrorInfo
.ErrorLoc
= BO
->getExprLoc();
12076 ErrorInfo
.NoteLoc
= BO
->getOperatorLoc();
12077 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= BO
->getSourceRange();
12083 auto *CO
= dyn_cast
<ConditionalOperator
>(BO
->getRHS()->IgnoreParenImpCasts());
12085 ErrorInfo
.Error
= ErrorTy::NotCondOp
;
12086 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= BO
->getRHS()->getExprLoc();
12087 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= BO
->getRHS()->getSourceRange();
12091 if (!checkIfTwoExprsAreSame(ContextRef
, X
, CO
->getFalseExpr())) {
12092 ErrorInfo
.Error
= ErrorTy::WrongFalseExpr
;
12093 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CO
->getFalseExpr()->getExprLoc();
12094 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
=
12095 CO
->getFalseExpr()->getSourceRange();
12099 auto *Cond
= dyn_cast
<BinaryOperator
>(CO
->getCond());
12101 ErrorInfo
.Error
= ErrorTy::NotABinaryOp
;
12102 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CO
->getCond()->getExprLoc();
12103 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
=
12104 CO
->getCond()->getSourceRange();
12108 switch (Cond
->getOpcode()) {
12111 D
= CO
->getTrueExpr();
12112 if (checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getLHS())) {
12113 E
= Cond
->getRHS();
12114 } else if (checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getRHS())) {
12115 E
= Cond
->getLHS();
12117 ErrorInfo
.Error
= ErrorTy::InvalidComparison
;
12118 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Cond
->getExprLoc();
12119 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Cond
->getSourceRange();
12126 E
= CO
->getTrueExpr();
12127 if (checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getLHS()) &&
12128 checkIfTwoExprsAreSame(ContextRef
, E
, Cond
->getRHS())) {
12130 } else if (checkIfTwoExprsAreSame(ContextRef
, E
, Cond
->getLHS()) &&
12131 checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getRHS())) {
12133 IsXBinopExpr
= false;
12135 ErrorInfo
.Error
= ErrorTy::InvalidComparison
;
12136 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Cond
->getExprLoc();
12137 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Cond
->getSourceRange();
12143 ErrorInfo
.Error
= ErrorTy::InvalidBinaryOp
;
12144 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Cond
->getExprLoc();
12145 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Cond
->getSourceRange();
12152 bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy
&ErrorInfo
) const {
12153 // 'x' and 'e' cannot be nullptr
12154 assert(X
&& E
&& "X and E cannot be nullptr");
12156 if (!CheckValue(X
, ErrorInfo
, true))
12159 if (!CheckValue(E
, ErrorInfo
, false))
12162 if (D
&& !CheckValue(D
, ErrorInfo
, false))
12168 bool OpenMPAtomicCompareChecker::checkStmt(
12169 Stmt
*S
, OpenMPAtomicCompareChecker::ErrorInfoTy
&ErrorInfo
) {
12170 auto *CS
= dyn_cast
<CompoundStmt
>(S
);
12172 if (CS
->body_empty()) {
12173 ErrorInfo
.Error
= ErrorTy::NoStmt
;
12174 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
12175 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= CS
->getSourceRange();
12179 if (CS
->size() != 1) {
12180 ErrorInfo
.Error
= ErrorTy::MoreThanOneStmt
;
12181 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
12182 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= CS
->getSourceRange();
12185 S
= CS
->body_front();
12190 if (auto *IS
= dyn_cast
<IfStmt
>(S
)) {
12191 // Check if the statement is in one of the following forms
12192 // (cond-update-stmt):
12193 // if (expr ordop x) { x = expr; }
12194 // if (x ordop expr) { x = expr; }
12195 // if (x == e) { x = d; }
12196 Res
= checkCondUpdateStmt(IS
, ErrorInfo
);
12198 // Check if the statement is in one of the following forms (cond-expr-stmt):
12199 // x = expr ordop x ? expr : x;
12200 // x = x ordop expr ? expr : x;
12201 // x = x == e ? d : x;
12202 Res
= checkCondExprStmt(S
, ErrorInfo
);
12208 return checkType(ErrorInfo
);
12211 class OpenMPAtomicCompareCaptureChecker final
12212 : public OpenMPAtomicCompareChecker
{
12214 OpenMPAtomicCompareCaptureChecker(Sema
&S
) : OpenMPAtomicCompareChecker(S
) {}
12216 Expr
*getV() const { return V
; }
12217 Expr
*getR() const { return R
; }
12218 bool isFailOnly() const { return IsFailOnly
; }
12219 bool isPostfixUpdate() const { return IsPostfixUpdate
; }
12221 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
12222 bool checkStmt(Stmt
*S
, ErrorInfoTy
&ErrorInfo
);
12225 bool checkType(ErrorInfoTy
&ErrorInfo
);
12227 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
12228 // form of 'conditional-update-capture-atomic' structured block on the v5.2
12230 // (1) { v = x; cond-update-stmt }
12231 // (2) { cond-update-stmt v = x; }
12232 // (3) if(x == e) { x = d; } else { v = x; }
12233 // (4) { r = x == e; if(r) { x = d; } }
12234 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
12236 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
12237 bool checkForm3(IfStmt
*S
, ErrorInfoTy
&ErrorInfo
);
12239 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
12240 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
12241 bool checkForm45(Stmt
*S
, ErrorInfoTy
&ErrorInfo
);
12243 /// 'v' lvalue part of the source atomic expression.
12245 /// 'r' lvalue part of the source atomic expression.
12247 /// If 'v' is only updated when the comparison fails.
12248 bool IsFailOnly
= false;
12249 /// If original value of 'x' must be stored in 'v', not an updated one.
12250 bool IsPostfixUpdate
= false;
12253 bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy
&ErrorInfo
) {
12254 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo
))
12257 if (V
&& !CheckValue(V
, ErrorInfo
, true))
12260 if (R
&& !CheckValue(R
, ErrorInfo
, true, true))
12266 bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt
*S
,
12267 ErrorInfoTy
&ErrorInfo
) {
12270 auto *Then
= S
->getThen();
12271 if (auto *CS
= dyn_cast
<CompoundStmt
>(Then
)) {
12272 if (CS
->body_empty()) {
12273 ErrorInfo
.Error
= ErrorTy::NoStmt
;
12274 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
12275 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= CS
->getSourceRange();
12278 if (CS
->size() > 1) {
12279 ErrorInfo
.Error
= ErrorTy::MoreThanOneStmt
;
12280 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
12281 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= CS
->getSourceRange();
12284 Then
= CS
->body_front();
12287 auto *BO
= dyn_cast
<BinaryOperator
>(Then
);
12289 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12290 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Then
->getBeginLoc();
12291 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Then
->getSourceRange();
12294 if (BO
->getOpcode() != BO_Assign
) {
12295 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12296 ErrorInfo
.ErrorLoc
= BO
->getExprLoc();
12297 ErrorInfo
.NoteLoc
= BO
->getOperatorLoc();
12298 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= BO
->getSourceRange();
12305 auto *Cond
= dyn_cast
<BinaryOperator
>(S
->getCond());
12307 ErrorInfo
.Error
= ErrorTy::NotABinaryOp
;
12308 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= S
->getCond()->getExprLoc();
12309 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S
->getCond()->getSourceRange();
12312 if (Cond
->getOpcode() != BO_EQ
) {
12313 ErrorInfo
.Error
= ErrorTy::NotEQ
;
12314 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Cond
->getExprLoc();
12315 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Cond
->getSourceRange();
12319 if (checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getLHS())) {
12320 E
= Cond
->getRHS();
12321 } else if (checkIfTwoExprsAreSame(ContextRef
, X
, Cond
->getRHS())) {
12322 E
= Cond
->getLHS();
12324 ErrorInfo
.Error
= ErrorTy::InvalidComparison
;
12325 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Cond
->getExprLoc();
12326 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Cond
->getSourceRange();
12332 if (!S
->getElse()) {
12333 ErrorInfo
.Error
= ErrorTy::NoElse
;
12334 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= S
->getBeginLoc();
12335 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S
->getSourceRange();
12339 auto *Else
= S
->getElse();
12340 if (auto *CS
= dyn_cast
<CompoundStmt
>(Else
)) {
12341 if (CS
->body_empty()) {
12342 ErrorInfo
.Error
= ErrorTy::NoStmt
;
12343 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
12344 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= CS
->getSourceRange();
12347 if (CS
->size() > 1) {
12348 ErrorInfo
.Error
= ErrorTy::MoreThanOneStmt
;
12349 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
12350 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S
->getSourceRange();
12353 Else
= CS
->body_front();
12356 auto *ElseBO
= dyn_cast
<BinaryOperator
>(Else
);
12358 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12359 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Else
->getBeginLoc();
12360 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Else
->getSourceRange();
12363 if (ElseBO
->getOpcode() != BO_Assign
) {
12364 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12365 ErrorInfo
.ErrorLoc
= ElseBO
->getExprLoc();
12366 ErrorInfo
.NoteLoc
= ElseBO
->getOperatorLoc();
12367 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= ElseBO
->getSourceRange();
12371 if (!checkIfTwoExprsAreSame(ContextRef
, X
, ElseBO
->getRHS())) {
12372 ErrorInfo
.Error
= ErrorTy::InvalidAssignment
;
12373 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= ElseBO
->getRHS()->getExprLoc();
12374 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
=
12375 ElseBO
->getRHS()->getSourceRange();
12379 V
= ElseBO
->getLHS();
12381 return checkType(ErrorInfo
);
12384 bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt
*S
,
12385 ErrorInfoTy
&ErrorInfo
) {
12386 // We don't check here as they should be already done before call this
12388 auto *CS
= cast
<CompoundStmt
>(S
);
12389 assert(CS
->size() == 2 && "CompoundStmt size is not expected");
12390 auto *S1
= cast
<BinaryOperator
>(CS
->body_front());
12391 auto *S2
= cast
<IfStmt
>(CS
->body_back());
12392 assert(S1
->getOpcode() == BO_Assign
&& "unexpected binary operator");
12394 if (!checkIfTwoExprsAreSame(ContextRef
, S1
->getLHS(), S2
->getCond())) {
12395 ErrorInfo
.Error
= ErrorTy::InvalidCondition
;
12396 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= S2
->getCond()->getExprLoc();
12397 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S1
->getLHS()->getSourceRange();
12403 auto *Then
= S2
->getThen();
12404 if (auto *ThenCS
= dyn_cast
<CompoundStmt
>(Then
)) {
12405 if (ThenCS
->body_empty()) {
12406 ErrorInfo
.Error
= ErrorTy::NoStmt
;
12407 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= ThenCS
->getBeginLoc();
12408 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= ThenCS
->getSourceRange();
12411 if (ThenCS
->size() > 1) {
12412 ErrorInfo
.Error
= ErrorTy::MoreThanOneStmt
;
12413 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= ThenCS
->getBeginLoc();
12414 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= ThenCS
->getSourceRange();
12417 Then
= ThenCS
->body_front();
12420 auto *ThenBO
= dyn_cast
<BinaryOperator
>(Then
);
12422 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12423 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= S2
->getBeginLoc();
12424 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S2
->getSourceRange();
12427 if (ThenBO
->getOpcode() != BO_Assign
) {
12428 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12429 ErrorInfo
.ErrorLoc
= ThenBO
->getExprLoc();
12430 ErrorInfo
.NoteLoc
= ThenBO
->getOperatorLoc();
12431 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= ThenBO
->getSourceRange();
12435 X
= ThenBO
->getLHS();
12436 D
= ThenBO
->getRHS();
12438 auto *BO
= cast
<BinaryOperator
>(S1
->getRHS()->IgnoreImpCasts());
12439 if (BO
->getOpcode() != BO_EQ
) {
12440 ErrorInfo
.Error
= ErrorTy::NotEQ
;
12441 ErrorInfo
.ErrorLoc
= BO
->getExprLoc();
12442 ErrorInfo
.NoteLoc
= BO
->getOperatorLoc();
12443 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= BO
->getSourceRange();
12449 if (checkIfTwoExprsAreSame(ContextRef
, X
, BO
->getLHS())) {
12451 } else if (checkIfTwoExprsAreSame(ContextRef
, X
, BO
->getRHS())) {
12454 ErrorInfo
.Error
= ErrorTy::InvalidComparison
;
12455 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= BO
->getExprLoc();
12456 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= BO
->getSourceRange();
12460 if (S2
->getElse()) {
12463 auto *Else
= S2
->getElse();
12464 if (auto *ElseCS
= dyn_cast
<CompoundStmt
>(Else
)) {
12465 if (ElseCS
->body_empty()) {
12466 ErrorInfo
.Error
= ErrorTy::NoStmt
;
12467 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= ElseCS
->getBeginLoc();
12468 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= ElseCS
->getSourceRange();
12471 if (ElseCS
->size() > 1) {
12472 ErrorInfo
.Error
= ErrorTy::MoreThanOneStmt
;
12473 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= ElseCS
->getBeginLoc();
12474 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= ElseCS
->getSourceRange();
12477 Else
= ElseCS
->body_front();
12480 auto *ElseBO
= dyn_cast
<BinaryOperator
>(Else
);
12482 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12483 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= Else
->getBeginLoc();
12484 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= Else
->getSourceRange();
12487 if (ElseBO
->getOpcode() != BO_Assign
) {
12488 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12489 ErrorInfo
.ErrorLoc
= ElseBO
->getExprLoc();
12490 ErrorInfo
.NoteLoc
= ElseBO
->getOperatorLoc();
12491 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= ElseBO
->getSourceRange();
12494 if (!checkIfTwoExprsAreSame(ContextRef
, X
, ElseBO
->getRHS())) {
12495 ErrorInfo
.Error
= ErrorTy::InvalidAssignment
;
12496 ErrorInfo
.ErrorLoc
= ElseBO
->getRHS()->getExprLoc();
12497 ErrorInfo
.NoteLoc
= X
->getExprLoc();
12498 ErrorInfo
.ErrorRange
= ElseBO
->getRHS()->getSourceRange();
12499 ErrorInfo
.NoteRange
= X
->getSourceRange();
12503 V
= ElseBO
->getLHS();
12506 return checkType(ErrorInfo
);
12509 bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt
*S
,
12510 ErrorInfoTy
&ErrorInfo
) {
12511 // if(x == e) { x = d; } else { v = x; }
12512 if (auto *IS
= dyn_cast
<IfStmt
>(S
))
12513 return checkForm3(IS
, ErrorInfo
);
12515 auto *CS
= dyn_cast
<CompoundStmt
>(S
);
12517 ErrorInfo
.Error
= ErrorTy::NotCompoundStmt
;
12518 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= S
->getBeginLoc();
12519 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= S
->getSourceRange();
12522 if (CS
->body_empty()) {
12523 ErrorInfo
.Error
= ErrorTy::NoStmt
;
12524 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
12525 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= CS
->getSourceRange();
12529 // { if(x == e) { x = d; } else { v = x; } }
12530 if (CS
->size() == 1) {
12531 auto *IS
= dyn_cast
<IfStmt
>(CS
->body_front());
12533 ErrorInfo
.Error
= ErrorTy::NotIfStmt
;
12534 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->body_front()->getBeginLoc();
12535 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
=
12536 CS
->body_front()->getSourceRange();
12540 return checkForm3(IS
, ErrorInfo
);
12541 } else if (CS
->size() == 2) {
12542 auto *S1
= CS
->body_front();
12543 auto *S2
= CS
->body_back();
12545 Stmt
*UpdateStmt
= nullptr;
12546 Stmt
*CondUpdateStmt
= nullptr;
12547 Stmt
*CondExprStmt
= nullptr;
12549 if (auto *BO
= dyn_cast
<BinaryOperator
>(S1
)) {
12550 // It could be one of the following cases:
12551 // { v = x; cond-update-stmt }
12552 // { v = x; cond-expr-stmt }
12553 // { cond-expr-stmt; v = x; }
12555 if (isa
<BinaryOperator
>(BO
->getRHS()->IgnoreImpCasts()) ||
12556 isa
<ConditionalOperator
>(BO
->getRHS()->IgnoreImpCasts())) {
12557 // check if form 45
12558 if (isa
<IfStmt
>(S2
))
12559 return checkForm45(CS
, ErrorInfo
);
12560 // { cond-expr-stmt; v = x; }
12564 IsPostfixUpdate
= true;
12566 if (isa
<IfStmt
>(S2
)) {
12567 // { v = x; cond-update-stmt }
12568 CondUpdateStmt
= S2
;
12570 // { v = x; cond-expr-stmt }
12575 // { cond-update-stmt v = x; }
12577 CondUpdateStmt
= S1
;
12580 auto CheckCondUpdateStmt
= [this, &ErrorInfo
](Stmt
*CUS
) {
12581 auto *IS
= dyn_cast
<IfStmt
>(CUS
);
12583 ErrorInfo
.Error
= ErrorTy::NotIfStmt
;
12584 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CUS
->getBeginLoc();
12585 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= CUS
->getSourceRange();
12589 return checkCondUpdateStmt(IS
, ErrorInfo
);
12592 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12593 auto CheckUpdateStmt
= [this, &ErrorInfo
](Stmt
*US
) {
12594 auto *BO
= dyn_cast
<BinaryOperator
>(US
);
12596 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12597 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= US
->getBeginLoc();
12598 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= US
->getSourceRange();
12601 if (BO
->getOpcode() != BO_Assign
) {
12602 ErrorInfo
.Error
= ErrorTy::NotAnAssignment
;
12603 ErrorInfo
.ErrorLoc
= BO
->getExprLoc();
12604 ErrorInfo
.NoteLoc
= BO
->getOperatorLoc();
12605 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= BO
->getSourceRange();
12608 if (!checkIfTwoExprsAreSame(ContextRef
, this->X
, BO
->getRHS())) {
12609 ErrorInfo
.Error
= ErrorTy::InvalidAssignment
;
12610 ErrorInfo
.ErrorLoc
= BO
->getRHS()->getExprLoc();
12611 ErrorInfo
.NoteLoc
= this->X
->getExprLoc();
12612 ErrorInfo
.ErrorRange
= BO
->getRHS()->getSourceRange();
12613 ErrorInfo
.NoteRange
= this->X
->getSourceRange();
12617 this->V
= BO
->getLHS();
12622 if (CondUpdateStmt
&& !CheckCondUpdateStmt(CondUpdateStmt
))
12624 if (CondExprStmt
&& !checkCondExprStmt(CondExprStmt
, ErrorInfo
))
12626 if (!CheckUpdateStmt(UpdateStmt
))
12629 ErrorInfo
.Error
= ErrorTy::MoreThanTwoStmts
;
12630 ErrorInfo
.ErrorLoc
= ErrorInfo
.NoteLoc
= CS
->getBeginLoc();
12631 ErrorInfo
.ErrorRange
= ErrorInfo
.NoteRange
= CS
->getSourceRange();
12635 return checkType(ErrorInfo
);
12639 StmtResult
Sema::ActOnOpenMPAtomicDirective(ArrayRef
<OMPClause
*> Clauses
,
12641 SourceLocation StartLoc
,
12642 SourceLocation EndLoc
) {
12643 // Register location of the first atomic directive.
12644 DSAStack
->addAtomicDirectiveLoc(StartLoc
);
12646 return StmtError();
12648 // 1.2.2 OpenMP Language Terminology
12649 // Structured block - An executable statement with a single entry at the
12650 // top and a single exit at the bottom.
12651 // The point of exit cannot be a branch out of the structured block.
12652 // longjmp() and throw() must not violate the entry/exit criteria.
12653 OpenMPClauseKind AtomicKind
= OMPC_unknown
;
12654 SourceLocation AtomicKindLoc
;
12655 OpenMPClauseKind MemOrderKind
= OMPC_unknown
;
12656 SourceLocation MemOrderLoc
;
12657 bool MutexClauseEncountered
= false;
12658 llvm::SmallSet
<OpenMPClauseKind
, 2> EncounteredAtomicKinds
;
12659 for (const OMPClause
*C
: Clauses
) {
12660 switch (C
->getClauseKind()) {
12664 MutexClauseEncountered
= true;
12667 case OMPC_compare
: {
12668 if (AtomicKind
!= OMPC_unknown
&& MutexClauseEncountered
) {
12669 Diag(C
->getBeginLoc(), diag::err_omp_atomic_several_clauses
)
12670 << SourceRange(C
->getBeginLoc(), C
->getEndLoc());
12671 Diag(AtomicKindLoc
, diag::note_omp_previous_mem_order_clause
)
12672 << getOpenMPClauseName(AtomicKind
);
12674 AtomicKind
= C
->getClauseKind();
12675 AtomicKindLoc
= C
->getBeginLoc();
12676 if (!EncounteredAtomicKinds
.insert(C
->getClauseKind()).second
) {
12677 Diag(C
->getBeginLoc(), diag::err_omp_atomic_several_clauses
)
12678 << SourceRange(C
->getBeginLoc(), C
->getEndLoc());
12679 Diag(AtomicKindLoc
, diag::note_omp_previous_mem_order_clause
)
12680 << getOpenMPClauseName(AtomicKind
);
12686 if (AtomicKind
!= OMPC_compare
) {
12687 Diag(C
->getBeginLoc(), diag::err_omp_atomic_fail_no_compare
)
12688 << SourceRange(C
->getBeginLoc(), C
->getEndLoc());
12689 return StmtError();
12697 case OMPC_relaxed
: {
12698 if (MemOrderKind
!= OMPC_unknown
) {
12699 Diag(C
->getBeginLoc(), diag::err_omp_several_mem_order_clauses
)
12700 << getOpenMPDirectiveName(OMPD_atomic
) << 0
12701 << SourceRange(C
->getBeginLoc(), C
->getEndLoc());
12702 Diag(MemOrderLoc
, diag::note_omp_previous_mem_order_clause
)
12703 << getOpenMPClauseName(MemOrderKind
);
12705 MemOrderKind
= C
->getClauseKind();
12706 MemOrderLoc
= C
->getBeginLoc();
12710 // The following clauses are allowed, but we don't need to do anything here.
12714 llvm_unreachable("unknown clause is encountered");
12717 bool IsCompareCapture
= false;
12718 if (EncounteredAtomicKinds
.contains(OMPC_compare
) &&
12719 EncounteredAtomicKinds
.contains(OMPC_capture
)) {
12720 IsCompareCapture
= true;
12721 AtomicKind
= OMPC_compare
;
12723 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12724 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12726 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12728 // If atomic-clause is update or not present then memory-order-clause must not
12729 // be acq_rel or acquire.
12730 if ((AtomicKind
== OMPC_read
&&
12731 (MemOrderKind
== OMPC_acq_rel
|| MemOrderKind
== OMPC_release
)) ||
12732 ((AtomicKind
== OMPC_write
|| AtomicKind
== OMPC_update
||
12733 AtomicKind
== OMPC_unknown
) &&
12734 (MemOrderKind
== OMPC_acq_rel
|| MemOrderKind
== OMPC_acquire
))) {
12735 SourceLocation Loc
= AtomicKindLoc
;
12736 if (AtomicKind
== OMPC_unknown
)
12738 Diag(Loc
, diag::err_omp_atomic_incompatible_mem_order_clause
)
12739 << getOpenMPClauseName(AtomicKind
)
12740 << (AtomicKind
== OMPC_unknown
? 1 : 0)
12741 << getOpenMPClauseName(MemOrderKind
);
12742 Diag(MemOrderLoc
, diag::note_omp_previous_mem_order_clause
)
12743 << getOpenMPClauseName(MemOrderKind
);
12746 Stmt
*Body
= AStmt
;
12747 if (auto *EWC
= dyn_cast
<ExprWithCleanups
>(Body
))
12748 Body
= EWC
->getSubExpr();
12753 Expr
*UE
= nullptr;
12755 Expr
*CE
= nullptr;
12757 bool IsXLHSInRHSPart
= false;
12758 bool IsPostfixUpdate
= false;
12759 bool IsFailOnly
= false;
12760 // OpenMP [2.12.6, atomic Construct]
12761 // In the next expressions:
12762 // * x and v (as applicable) are both l-value expressions with scalar type.
12763 // * During the execution of an atomic region, multiple syntactic
12764 // occurrences of x must designate the same storage location.
12765 // * Neither of v and expr (as applicable) may access the storage location
12766 // designated by x.
12767 // * Neither of x and expr (as applicable) may access the storage location
12768 // designated by v.
12769 // * expr is an expression with scalar type.
12770 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12771 // * binop, binop=, ++, and -- are not overloaded operators.
12772 // * The expression x binop expr must be numerically equivalent to x binop
12773 // (expr). This requirement is satisfied if the operators in expr have
12774 // precedence greater than binop, or by using parentheses around expr or
12775 // subexpressions of expr.
12776 // * The expression expr binop x must be numerically equivalent to (expr)
12777 // binop x. This requirement is satisfied if the operators in expr have
12778 // precedence equal to or greater than binop, or by using parentheses around
12779 // expr or subexpressions of expr.
12780 // * For forms that allow multiple occurrences of x, the number of times
12781 // that x is evaluated is unspecified.
12782 if (AtomicKind
== OMPC_read
) {
12789 } ErrorFound
= NoError
;
12790 SourceLocation ErrorLoc
, NoteLoc
;
12791 SourceRange ErrorRange
, NoteRange
;
12792 // If clause is read:
12794 if (const auto *AtomicBody
= dyn_cast
<Expr
>(Body
)) {
12795 const auto *AtomicBinOp
=
12796 dyn_cast
<BinaryOperator
>(AtomicBody
->IgnoreParenImpCasts());
12797 if (AtomicBinOp
&& AtomicBinOp
->getOpcode() == BO_Assign
) {
12798 X
= AtomicBinOp
->getRHS()->IgnoreParenImpCasts();
12799 V
= AtomicBinOp
->getLHS()->IgnoreParenImpCasts();
12800 if ((X
->isInstantiationDependent() || X
->getType()->isScalarType()) &&
12801 (V
->isInstantiationDependent() || V
->getType()->isScalarType())) {
12802 if (!X
->isLValue() || !V
->isLValue()) {
12803 const Expr
*NotLValueExpr
= X
->isLValue() ? V
: X
;
12804 ErrorFound
= NotAnLValue
;
12805 ErrorLoc
= AtomicBinOp
->getExprLoc();
12806 ErrorRange
= AtomicBinOp
->getSourceRange();
12807 NoteLoc
= NotLValueExpr
->getExprLoc();
12808 NoteRange
= NotLValueExpr
->getSourceRange();
12810 } else if (!X
->isInstantiationDependent() ||
12811 !V
->isInstantiationDependent()) {
12812 const Expr
*NotScalarExpr
=
12813 (X
->isInstantiationDependent() || X
->getType()->isScalarType())
12816 ErrorFound
= NotAScalarType
;
12817 ErrorLoc
= AtomicBinOp
->getExprLoc();
12818 ErrorRange
= AtomicBinOp
->getSourceRange();
12819 NoteLoc
= NotScalarExpr
->getExprLoc();
12820 NoteRange
= NotScalarExpr
->getSourceRange();
12822 } else if (!AtomicBody
->isInstantiationDependent()) {
12823 ErrorFound
= NotAnAssignmentOp
;
12824 ErrorLoc
= AtomicBody
->getExprLoc();
12825 ErrorRange
= AtomicBody
->getSourceRange();
12826 NoteLoc
= AtomicBinOp
? AtomicBinOp
->getOperatorLoc()
12827 : AtomicBody
->getExprLoc();
12828 NoteRange
= AtomicBinOp
? AtomicBinOp
->getSourceRange()
12829 : AtomicBody
->getSourceRange();
12832 ErrorFound
= NotAnExpression
;
12833 NoteLoc
= ErrorLoc
= Body
->getBeginLoc();
12834 NoteRange
= ErrorRange
= SourceRange(NoteLoc
, NoteLoc
);
12836 if (ErrorFound
!= NoError
) {
12837 Diag(ErrorLoc
, diag::err_omp_atomic_read_not_expression_statement
)
12839 Diag(NoteLoc
, diag::note_omp_atomic_read_write
)
12840 << ErrorFound
<< NoteRange
;
12841 return StmtError();
12843 if (CurContext
->isDependentContext())
12845 } else if (AtomicKind
== OMPC_write
) {
12852 } ErrorFound
= NoError
;
12853 SourceLocation ErrorLoc
, NoteLoc
;
12854 SourceRange ErrorRange
, NoteRange
;
12855 // If clause is write:
12857 if (const auto *AtomicBody
= dyn_cast
<Expr
>(Body
)) {
12858 const auto *AtomicBinOp
=
12859 dyn_cast
<BinaryOperator
>(AtomicBody
->IgnoreParenImpCasts());
12860 if (AtomicBinOp
&& AtomicBinOp
->getOpcode() == BO_Assign
) {
12861 X
= AtomicBinOp
->getLHS();
12862 E
= AtomicBinOp
->getRHS();
12863 if ((X
->isInstantiationDependent() || X
->getType()->isScalarType()) &&
12864 (E
->isInstantiationDependent() || E
->getType()->isScalarType())) {
12865 if (!X
->isLValue()) {
12866 ErrorFound
= NotAnLValue
;
12867 ErrorLoc
= AtomicBinOp
->getExprLoc();
12868 ErrorRange
= AtomicBinOp
->getSourceRange();
12869 NoteLoc
= X
->getExprLoc();
12870 NoteRange
= X
->getSourceRange();
12872 } else if (!X
->isInstantiationDependent() ||
12873 !E
->isInstantiationDependent()) {
12874 const Expr
*NotScalarExpr
=
12875 (X
->isInstantiationDependent() || X
->getType()->isScalarType())
12878 ErrorFound
= NotAScalarType
;
12879 ErrorLoc
= AtomicBinOp
->getExprLoc();
12880 ErrorRange
= AtomicBinOp
->getSourceRange();
12881 NoteLoc
= NotScalarExpr
->getExprLoc();
12882 NoteRange
= NotScalarExpr
->getSourceRange();
12884 } else if (!AtomicBody
->isInstantiationDependent()) {
12885 ErrorFound
= NotAnAssignmentOp
;
12886 ErrorLoc
= AtomicBody
->getExprLoc();
12887 ErrorRange
= AtomicBody
->getSourceRange();
12888 NoteLoc
= AtomicBinOp
? AtomicBinOp
->getOperatorLoc()
12889 : AtomicBody
->getExprLoc();
12890 NoteRange
= AtomicBinOp
? AtomicBinOp
->getSourceRange()
12891 : AtomicBody
->getSourceRange();
12894 ErrorFound
= NotAnExpression
;
12895 NoteLoc
= ErrorLoc
= Body
->getBeginLoc();
12896 NoteRange
= ErrorRange
= SourceRange(NoteLoc
, NoteLoc
);
12898 if (ErrorFound
!= NoError
) {
12899 Diag(ErrorLoc
, diag::err_omp_atomic_write_not_expression_statement
)
12901 Diag(NoteLoc
, diag::note_omp_atomic_read_write
)
12902 << ErrorFound
<< NoteRange
;
12903 return StmtError();
12905 if (CurContext
->isDependentContext())
12907 } else if (AtomicKind
== OMPC_update
|| AtomicKind
== OMPC_unknown
) {
12908 // If clause is update:
12914 // x = x binop expr;
12915 // x = expr binop x;
12916 OpenMPAtomicUpdateChecker
Checker(*this);
12917 if (Checker
.checkStatement(
12919 (AtomicKind
== OMPC_update
)
12920 ? diag::err_omp_atomic_update_not_expression_statement
12921 : diag::err_omp_atomic_not_expression_statement
,
12922 diag::note_omp_atomic_update
))
12923 return StmtError();
12924 if (!CurContext
->isDependentContext()) {
12925 E
= Checker
.getExpr();
12926 X
= Checker
.getX();
12927 UE
= Checker
.getUpdateExpr();
12928 IsXLHSInRHSPart
= Checker
.isXLHSInRHSPart();
12930 } else if (AtomicKind
== OMPC_capture
) {
12933 NotACompoundStatement
,
12934 NotTwoSubstatements
,
12935 NotASpecificExpression
,
12937 } ErrorFound
= NoError
;
12938 SourceLocation ErrorLoc
, NoteLoc
;
12939 SourceRange ErrorRange
, NoteRange
;
12940 if (const auto *AtomicBody
= dyn_cast
<Expr
>(Body
)) {
12941 // If clause is a capture:
12946 // v = x binop= expr;
12947 // v = x = x binop expr;
12948 // v = x = expr binop x;
12949 const auto *AtomicBinOp
=
12950 dyn_cast
<BinaryOperator
>(AtomicBody
->IgnoreParenImpCasts());
12951 if (AtomicBinOp
&& AtomicBinOp
->getOpcode() == BO_Assign
) {
12952 V
= AtomicBinOp
->getLHS();
12953 Body
= AtomicBinOp
->getRHS()->IgnoreParenImpCasts();
12954 OpenMPAtomicUpdateChecker
Checker(*this);
12955 if (Checker
.checkStatement(
12956 Body
, diag::err_omp_atomic_capture_not_expression_statement
,
12957 diag::note_omp_atomic_update
))
12958 return StmtError();
12959 E
= Checker
.getExpr();
12960 X
= Checker
.getX();
12961 UE
= Checker
.getUpdateExpr();
12962 IsXLHSInRHSPart
= Checker
.isXLHSInRHSPart();
12963 IsPostfixUpdate
= Checker
.isPostfixUpdate();
12964 } else if (!AtomicBody
->isInstantiationDependent()) {
12965 ErrorLoc
= AtomicBody
->getExprLoc();
12966 ErrorRange
= AtomicBody
->getSourceRange();
12967 NoteLoc
= AtomicBinOp
? AtomicBinOp
->getOperatorLoc()
12968 : AtomicBody
->getExprLoc();
12969 NoteRange
= AtomicBinOp
? AtomicBinOp
->getSourceRange()
12970 : AtomicBody
->getSourceRange();
12971 ErrorFound
= NotAnAssignmentOp
;
12973 if (ErrorFound
!= NoError
) {
12974 Diag(ErrorLoc
, diag::err_omp_atomic_capture_not_expression_statement
)
12976 Diag(NoteLoc
, diag::note_omp_atomic_capture
) << ErrorFound
<< NoteRange
;
12977 return StmtError();
12979 if (CurContext
->isDependentContext())
12980 UE
= V
= E
= X
= nullptr;
12982 // If clause is a capture:
12983 // { v = x; x = expr; }
12988 // { v = x; x binop= expr; }
12989 // { v = x; x = x binop expr; }
12990 // { v = x; x = expr binop x; }
12995 // { x binop= expr; v = x; }
12996 // { x = x binop expr; v = x; }
12997 // { x = expr binop x; v = x; }
12998 if (auto *CS
= dyn_cast
<CompoundStmt
>(Body
)) {
12999 // Check that this is { expr1; expr2; }
13000 if (CS
->size() == 2) {
13001 Stmt
*First
= CS
->body_front();
13002 Stmt
*Second
= CS
->body_back();
13003 if (auto *EWC
= dyn_cast
<ExprWithCleanups
>(First
))
13004 First
= EWC
->getSubExpr()->IgnoreParenImpCasts();
13005 if (auto *EWC
= dyn_cast
<ExprWithCleanups
>(Second
))
13006 Second
= EWC
->getSubExpr()->IgnoreParenImpCasts();
13007 // Need to find what subexpression is 'v' and what is 'x'.
13008 OpenMPAtomicUpdateChecker
Checker(*this);
13009 bool IsUpdateExprFound
= !Checker
.checkStatement(Second
);
13010 BinaryOperator
*BinOp
= nullptr;
13011 if (IsUpdateExprFound
) {
13012 BinOp
= dyn_cast
<BinaryOperator
>(First
);
13013 IsUpdateExprFound
= BinOp
&& BinOp
->getOpcode() == BO_Assign
;
13015 if (IsUpdateExprFound
&& !CurContext
->isDependentContext()) {
13020 // { v = x; x binop= expr; }
13021 // { v = x; x = x binop expr; }
13022 // { v = x; x = expr binop x; }
13023 // Check that the first expression has form v = x.
13024 Expr
*PossibleX
= BinOp
->getRHS()->IgnoreParenImpCasts();
13025 llvm::FoldingSetNodeID XId
, PossibleXId
;
13026 Checker
.getX()->Profile(XId
, Context
, /*Canonical=*/true);
13027 PossibleX
->Profile(PossibleXId
, Context
, /*Canonical=*/true);
13028 IsUpdateExprFound
= XId
== PossibleXId
;
13029 if (IsUpdateExprFound
) {
13030 V
= BinOp
->getLHS();
13031 X
= Checker
.getX();
13032 E
= Checker
.getExpr();
13033 UE
= Checker
.getUpdateExpr();
13034 IsXLHSInRHSPart
= Checker
.isXLHSInRHSPart();
13035 IsPostfixUpdate
= true;
13038 if (!IsUpdateExprFound
) {
13039 IsUpdateExprFound
= !Checker
.checkStatement(First
);
13041 if (IsUpdateExprFound
) {
13042 BinOp
= dyn_cast
<BinaryOperator
>(Second
);
13043 IsUpdateExprFound
= BinOp
&& BinOp
->getOpcode() == BO_Assign
;
13045 if (IsUpdateExprFound
&& !CurContext
->isDependentContext()) {
13050 // { x binop= expr; v = x; }
13051 // { x = x binop expr; v = x; }
13052 // { x = expr binop x; v = x; }
13053 // Check that the second expression has form v = x.
13054 Expr
*PossibleX
= BinOp
->getRHS()->IgnoreParenImpCasts();
13055 llvm::FoldingSetNodeID XId
, PossibleXId
;
13056 Checker
.getX()->Profile(XId
, Context
, /*Canonical=*/true);
13057 PossibleX
->Profile(PossibleXId
, Context
, /*Canonical=*/true);
13058 IsUpdateExprFound
= XId
== PossibleXId
;
13059 if (IsUpdateExprFound
) {
13060 V
= BinOp
->getLHS();
13061 X
= Checker
.getX();
13062 E
= Checker
.getExpr();
13063 UE
= Checker
.getUpdateExpr();
13064 IsXLHSInRHSPart
= Checker
.isXLHSInRHSPart();
13065 IsPostfixUpdate
= false;
13069 if (!IsUpdateExprFound
) {
13070 // { v = x; x = expr; }
13071 auto *FirstExpr
= dyn_cast
<Expr
>(First
);
13072 auto *SecondExpr
= dyn_cast
<Expr
>(Second
);
13073 if (!FirstExpr
|| !SecondExpr
||
13074 !(FirstExpr
->isInstantiationDependent() ||
13075 SecondExpr
->isInstantiationDependent())) {
13076 auto *FirstBinOp
= dyn_cast
<BinaryOperator
>(First
);
13077 if (!FirstBinOp
|| FirstBinOp
->getOpcode() != BO_Assign
) {
13078 ErrorFound
= NotAnAssignmentOp
;
13079 NoteLoc
= ErrorLoc
= FirstBinOp
? FirstBinOp
->getOperatorLoc()
13080 : First
->getBeginLoc();
13081 NoteRange
= ErrorRange
= FirstBinOp
13082 ? FirstBinOp
->getSourceRange()
13083 : SourceRange(ErrorLoc
, ErrorLoc
);
13085 auto *SecondBinOp
= dyn_cast
<BinaryOperator
>(Second
);
13086 if (!SecondBinOp
|| SecondBinOp
->getOpcode() != BO_Assign
) {
13087 ErrorFound
= NotAnAssignmentOp
;
13088 NoteLoc
= ErrorLoc
= SecondBinOp
13089 ? SecondBinOp
->getOperatorLoc()
13090 : Second
->getBeginLoc();
13091 NoteRange
= ErrorRange
=
13092 SecondBinOp
? SecondBinOp
->getSourceRange()
13093 : SourceRange(ErrorLoc
, ErrorLoc
);
13095 Expr
*PossibleXRHSInFirst
=
13096 FirstBinOp
->getRHS()->IgnoreParenImpCasts();
13097 Expr
*PossibleXLHSInSecond
=
13098 SecondBinOp
->getLHS()->IgnoreParenImpCasts();
13099 llvm::FoldingSetNodeID X1Id
, X2Id
;
13100 PossibleXRHSInFirst
->Profile(X1Id
, Context
,
13101 /*Canonical=*/true);
13102 PossibleXLHSInSecond
->Profile(X2Id
, Context
,
13103 /*Canonical=*/true);
13104 IsUpdateExprFound
= X1Id
== X2Id
;
13105 if (IsUpdateExprFound
) {
13106 V
= FirstBinOp
->getLHS();
13107 X
= SecondBinOp
->getLHS();
13108 E
= SecondBinOp
->getRHS();
13110 IsXLHSInRHSPart
= false;
13111 IsPostfixUpdate
= true;
13113 ErrorFound
= NotASpecificExpression
;
13114 ErrorLoc
= FirstBinOp
->getExprLoc();
13115 ErrorRange
= FirstBinOp
->getSourceRange();
13116 NoteLoc
= SecondBinOp
->getLHS()->getExprLoc();
13117 NoteRange
= SecondBinOp
->getRHS()->getSourceRange();
13124 NoteLoc
= ErrorLoc
= Body
->getBeginLoc();
13125 NoteRange
= ErrorRange
=
13126 SourceRange(Body
->getBeginLoc(), Body
->getBeginLoc());
13127 ErrorFound
= NotTwoSubstatements
;
13130 NoteLoc
= ErrorLoc
= Body
->getBeginLoc();
13131 NoteRange
= ErrorRange
=
13132 SourceRange(Body
->getBeginLoc(), Body
->getBeginLoc());
13133 ErrorFound
= NotACompoundStatement
;
13136 if (ErrorFound
!= NoError
) {
13137 Diag(ErrorLoc
, diag::err_omp_atomic_capture_not_compound_statement
)
13139 Diag(NoteLoc
, diag::note_omp_atomic_capture
) << ErrorFound
<< NoteRange
;
13140 return StmtError();
13142 if (CurContext
->isDependentContext())
13143 UE
= V
= E
= X
= nullptr;
13144 } else if (AtomicKind
== OMPC_compare
) {
13145 if (IsCompareCapture
) {
13146 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo
;
13147 OpenMPAtomicCompareCaptureChecker
Checker(*this);
13148 if (!Checker
.checkStmt(Body
, ErrorInfo
)) {
13149 Diag(ErrorInfo
.ErrorLoc
, diag::err_omp_atomic_compare_capture
)
13150 << ErrorInfo
.ErrorRange
;
13151 Diag(ErrorInfo
.NoteLoc
, diag::note_omp_atomic_compare
)
13152 << ErrorInfo
.Error
<< ErrorInfo
.NoteRange
;
13153 return StmtError();
13155 X
= Checker
.getX();
13156 E
= Checker
.getE();
13157 D
= Checker
.getD();
13158 CE
= Checker
.getCond();
13159 V
= Checker
.getV();
13160 R
= Checker
.getR();
13161 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13162 IsXLHSInRHSPart
= Checker
.isXBinopExpr();
13163 IsFailOnly
= Checker
.isFailOnly();
13164 IsPostfixUpdate
= Checker
.isPostfixUpdate();
13166 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo
;
13167 OpenMPAtomicCompareChecker
Checker(*this);
13168 if (!Checker
.checkStmt(Body
, ErrorInfo
)) {
13169 Diag(ErrorInfo
.ErrorLoc
, diag::err_omp_atomic_compare
)
13170 << ErrorInfo
.ErrorRange
;
13171 Diag(ErrorInfo
.NoteLoc
, diag::note_omp_atomic_compare
)
13172 << ErrorInfo
.Error
<< ErrorInfo
.NoteRange
;
13173 return StmtError();
13175 X
= Checker
.getX();
13176 E
= Checker
.getE();
13177 D
= Checker
.getD();
13178 CE
= Checker
.getCond();
13179 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13180 IsXLHSInRHSPart
= Checker
.isXBinopExpr();
13184 setFunctionHasBranchProtectedScope();
13186 return OMPAtomicDirective::Create(
13187 Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
13188 {X
, V
, R
, E
, UE
, D
, CE
, IsXLHSInRHSPart
, IsPostfixUpdate
, IsFailOnly
});
13191 StmtResult
Sema::ActOnOpenMPTargetDirective(ArrayRef
<OMPClause
*> Clauses
,
13193 SourceLocation StartLoc
,
13194 SourceLocation EndLoc
) {
13196 return StmtError();
13198 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13199 // 1.2.2 OpenMP Language Terminology
13200 // Structured block - An executable statement with a single entry at the
13201 // top and a single exit at the bottom.
13202 // The point of exit cannot be a branch out of the structured block.
13203 // longjmp() and throw() must not violate the entry/exit criteria.
13204 CS
->getCapturedDecl()->setNothrow();
13205 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target
);
13206 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
13207 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
13208 // 1.2.2 OpenMP Language Terminology
13209 // Structured block - An executable statement with a single entry at the
13210 // top and a single exit at the bottom.
13211 // The point of exit cannot be a branch out of the structured block.
13212 // longjmp() and throw() must not violate the entry/exit criteria.
13213 CS
->getCapturedDecl()->setNothrow();
13216 // OpenMP [2.16, Nesting of Regions]
13217 // If specified, a teams construct must be contained within a target
13218 // construct. That target construct must contain no statements or directives
13219 // outside of the teams construct.
13220 if (DSAStack
->hasInnerTeamsRegion()) {
13221 const Stmt
*S
= CS
->IgnoreContainers(/*IgnoreCaptured=*/true);
13222 bool OMPTeamsFound
= true;
13223 if (const auto *CS
= dyn_cast
<CompoundStmt
>(S
)) {
13224 auto I
= CS
->body_begin();
13225 while (I
!= CS
->body_end()) {
13226 const auto *OED
= dyn_cast
<OMPExecutableDirective
>(*I
);
13227 if (!OED
|| !isOpenMPTeamsDirective(OED
->getDirectiveKind()) ||
13230 OMPTeamsFound
= false;
13235 assert(I
!= CS
->body_end() && "Not found statement");
13238 const auto *OED
= dyn_cast
<OMPExecutableDirective
>(S
);
13239 OMPTeamsFound
= OED
&& isOpenMPTeamsDirective(OED
->getDirectiveKind());
13241 if (!OMPTeamsFound
) {
13242 Diag(StartLoc
, diag::err_omp_target_contains_not_only_teams
);
13243 Diag(DSAStack
->getInnerTeamsRegionLoc(),
13244 diag::note_omp_nested_teams_construct_here
);
13245 Diag(S
->getBeginLoc(), diag::note_omp_nested_statement_here
)
13246 << isa
<OMPExecutableDirective
>(S
);
13247 return StmtError();
13251 setFunctionHasBranchProtectedScope();
13253 return OMPTargetDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
);
13257 Sema::ActOnOpenMPTargetParallelDirective(ArrayRef
<OMPClause
*> Clauses
,
13258 Stmt
*AStmt
, SourceLocation StartLoc
,
13259 SourceLocation EndLoc
) {
13261 return StmtError();
13263 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13264 // 1.2.2 OpenMP Language Terminology
13265 // Structured block - An executable statement with a single entry at the
13266 // top and a single exit at the bottom.
13267 // The point of exit cannot be a branch out of the structured block.
13268 // longjmp() and throw() must not violate the entry/exit criteria.
13269 CS
->getCapturedDecl()->setNothrow();
13270 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_parallel
);
13271 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
13272 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
13273 // 1.2.2 OpenMP Language Terminology
13274 // Structured block - An executable statement with a single entry at the
13275 // top and a single exit at the bottom.
13276 // The point of exit cannot be a branch out of the structured block.
13277 // longjmp() and throw() must not violate the entry/exit criteria.
13278 CS
->getCapturedDecl()->setNothrow();
13281 setFunctionHasBranchProtectedScope();
13283 return OMPTargetParallelDirective::Create(
13284 Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
13285 DSAStack
->getTaskgroupReductionRef(), DSAStack
->isCancelRegion());
13288 StmtResult
Sema::ActOnOpenMPTargetParallelForDirective(
13289 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13290 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13292 return StmtError();
13294 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13295 // 1.2.2 OpenMP Language Terminology
13296 // Structured block - An executable statement with a single entry at the
13297 // top and a single exit at the bottom.
13298 // The point of exit cannot be a branch out of the structured block.
13299 // longjmp() and throw() must not violate the entry/exit criteria.
13300 CS
->getCapturedDecl()->setNothrow();
13301 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_parallel_for
);
13302 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
13303 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
13304 // 1.2.2 OpenMP Language Terminology
13305 // Structured block - An executable statement with a single entry at the
13306 // top and a single exit at the bottom.
13307 // The point of exit cannot be a branch out of the structured block.
13308 // longjmp() and throw() must not violate the entry/exit criteria.
13309 CS
->getCapturedDecl()->setNothrow();
13312 OMPLoopBasedDirective::HelperExprs B
;
13313 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13314 // define the nested loops number.
13315 unsigned NestedLoopCount
=
13316 checkOpenMPLoop(OMPD_target_parallel_for
, getCollapseNumberExpr(Clauses
),
13317 getOrderedNumberExpr(Clauses
), CS
, *this, *DSAStack
,
13318 VarsWithImplicitDSA
, B
);
13319 if (NestedLoopCount
== 0)
13320 return StmtError();
13322 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13323 "omp target parallel for loop exprs were not built");
13325 if (!CurContext
->isDependentContext()) {
13326 // Finalize the clauses that need pre-built expressions for CodeGen.
13327 for (OMPClause
*C
: Clauses
) {
13328 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
13329 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
13330 B
.NumIterations
, *this, CurScope
,
13332 return StmtError();
13336 setFunctionHasBranchProtectedScope();
13337 return OMPTargetParallelForDirective::Create(
13338 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
,
13339 DSAStack
->getTaskgroupReductionRef(), DSAStack
->isCancelRegion());
13342 /// Check for existence of a map clause in the list of clauses.
13343 static bool hasClauses(ArrayRef
<OMPClause
*> Clauses
,
13344 const OpenMPClauseKind K
) {
13345 return llvm::any_of(
13346 Clauses
, [K
](const OMPClause
*C
) { return C
->getClauseKind() == K
; });
13349 template <typename
... Params
>
13350 static bool hasClauses(ArrayRef
<OMPClause
*> Clauses
, const OpenMPClauseKind K
,
13351 const Params
... ClauseTypes
) {
13352 return hasClauses(Clauses
, K
) || hasClauses(Clauses
, ClauseTypes
...);
13355 /// Check if the variables in the mapping clause are externally visible.
13356 static bool isClauseMappable(ArrayRef
<OMPClause
*> Clauses
) {
13357 for (const OMPClause
*C
: Clauses
) {
13358 if (auto *TC
= dyn_cast
<OMPToClause
>(C
))
13359 return llvm::all_of(TC
->all_decls(), [](ValueDecl
*VD
) {
13360 return !VD
|| !VD
->hasAttr
<OMPDeclareTargetDeclAttr
>() ||
13361 (VD
->isExternallyVisible() &&
13362 VD
->getVisibility() != HiddenVisibility
);
13364 else if (auto *FC
= dyn_cast
<OMPFromClause
>(C
))
13365 return llvm::all_of(FC
->all_decls(), [](ValueDecl
*VD
) {
13366 return !VD
|| !VD
->hasAttr
<OMPDeclareTargetDeclAttr
>() ||
13367 (VD
->isExternallyVisible() &&
13368 VD
->getVisibility() != HiddenVisibility
);
13375 StmtResult
Sema::ActOnOpenMPTargetDataDirective(ArrayRef
<OMPClause
*> Clauses
,
13377 SourceLocation StartLoc
,
13378 SourceLocation EndLoc
) {
13380 return StmtError();
13382 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13384 // OpenMP [2.12.2, target data Construct, Restrictions]
13385 // At least one map, use_device_addr or use_device_ptr clause must appear on
13387 if (!hasClauses(Clauses
, OMPC_map
, OMPC_use_device_ptr
) &&
13388 (LangOpts
.OpenMP
< 50 || !hasClauses(Clauses
, OMPC_use_device_addr
))) {
13389 StringRef Expected
;
13390 if (LangOpts
.OpenMP
< 50)
13391 Expected
= "'map' or 'use_device_ptr'";
13393 Expected
= "'map', 'use_device_ptr', or 'use_device_addr'";
13394 Diag(StartLoc
, diag::err_omp_no_clause_for_directive
)
13395 << Expected
<< getOpenMPDirectiveName(OMPD_target_data
);
13396 return StmtError();
13399 setFunctionHasBranchProtectedScope();
13401 return OMPTargetDataDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
,
13406 Sema::ActOnOpenMPTargetEnterDataDirective(ArrayRef
<OMPClause
*> Clauses
,
13407 SourceLocation StartLoc
,
13408 SourceLocation EndLoc
, Stmt
*AStmt
) {
13410 return StmtError();
13412 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13413 // 1.2.2 OpenMP Language Terminology
13414 // Structured block - An executable statement with a single entry at the
13415 // top and a single exit at the bottom.
13416 // The point of exit cannot be a branch out of the structured block.
13417 // longjmp() and throw() must not violate the entry/exit criteria.
13418 CS
->getCapturedDecl()->setNothrow();
13419 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_enter_data
);
13420 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
13421 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
13422 // 1.2.2 OpenMP Language Terminology
13423 // Structured block - An executable statement with a single entry at the
13424 // top and a single exit at the bottom.
13425 // The point of exit cannot be a branch out of the structured block.
13426 // longjmp() and throw() must not violate the entry/exit criteria.
13427 CS
->getCapturedDecl()->setNothrow();
13430 // OpenMP [2.10.2, Restrictions, p. 99]
13431 // At least one map clause must appear on the directive.
13432 if (!hasClauses(Clauses
, OMPC_map
)) {
13433 Diag(StartLoc
, diag::err_omp_no_clause_for_directive
)
13434 << "'map'" << getOpenMPDirectiveName(OMPD_target_enter_data
);
13435 return StmtError();
13438 return OMPTargetEnterDataDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
,
13443 Sema::ActOnOpenMPTargetExitDataDirective(ArrayRef
<OMPClause
*> Clauses
,
13444 SourceLocation StartLoc
,
13445 SourceLocation EndLoc
, Stmt
*AStmt
) {
13447 return StmtError();
13449 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13450 // 1.2.2 OpenMP Language Terminology
13451 // Structured block - An executable statement with a single entry at the
13452 // top and a single exit at the bottom.
13453 // The point of exit cannot be a branch out of the structured block.
13454 // longjmp() and throw() must not violate the entry/exit criteria.
13455 CS
->getCapturedDecl()->setNothrow();
13456 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_exit_data
);
13457 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
13458 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
13459 // 1.2.2 OpenMP Language Terminology
13460 // Structured block - An executable statement with a single entry at the
13461 // top and a single exit at the bottom.
13462 // The point of exit cannot be a branch out of the structured block.
13463 // longjmp() and throw() must not violate the entry/exit criteria.
13464 CS
->getCapturedDecl()->setNothrow();
13467 // OpenMP [2.10.3, Restrictions, p. 102]
13468 // At least one map clause must appear on the directive.
13469 if (!hasClauses(Clauses
, OMPC_map
)) {
13470 Diag(StartLoc
, diag::err_omp_no_clause_for_directive
)
13471 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data
);
13472 return StmtError();
13475 return OMPTargetExitDataDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
,
13479 StmtResult
Sema::ActOnOpenMPTargetUpdateDirective(ArrayRef
<OMPClause
*> Clauses
,
13480 SourceLocation StartLoc
,
13481 SourceLocation EndLoc
,
13484 return StmtError();
13486 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13487 // 1.2.2 OpenMP Language Terminology
13488 // Structured block - An executable statement with a single entry at the
13489 // top and a single exit at the bottom.
13490 // The point of exit cannot be a branch out of the structured block.
13491 // longjmp() and throw() must not violate the entry/exit criteria.
13492 CS
->getCapturedDecl()->setNothrow();
13493 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_update
);
13494 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
13495 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
13496 // 1.2.2 OpenMP Language Terminology
13497 // Structured block - An executable statement with a single entry at the
13498 // top and a single exit at the bottom.
13499 // The point of exit cannot be a branch out of the structured block.
13500 // longjmp() and throw() must not violate the entry/exit criteria.
13501 CS
->getCapturedDecl()->setNothrow();
13504 if (!hasClauses(Clauses
, OMPC_to
, OMPC_from
)) {
13505 Diag(StartLoc
, diag::err_omp_at_least_one_motion_clause_required
);
13506 return StmtError();
13509 if (!isClauseMappable(Clauses
)) {
13510 Diag(StartLoc
, diag::err_omp_cannot_update_with_internal_linkage
);
13511 return StmtError();
13514 return OMPTargetUpdateDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
,
13518 StmtResult
Sema::ActOnOpenMPTeamsDirective(ArrayRef
<OMPClause
*> Clauses
,
13519 Stmt
*AStmt
, SourceLocation StartLoc
,
13520 SourceLocation EndLoc
) {
13522 return StmtError();
13524 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13525 if (getLangOpts().HIP
&& (DSAStack
->getParentDirective() == OMPD_target
))
13526 Diag(StartLoc
, diag::warn_hip_omp_target_directives
);
13528 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13529 // 1.2.2 OpenMP Language Terminology
13530 // Structured block - An executable statement with a single entry at the
13531 // top and a single exit at the bottom.
13532 // The point of exit cannot be a branch out of the structured block.
13533 // longjmp() and throw() must not violate the entry/exit criteria.
13534 CS
->getCapturedDecl()->setNothrow();
13536 setFunctionHasBranchProtectedScope();
13538 DSAStack
->setParentTeamsRegionLoc(StartLoc
);
13540 return OMPTeamsDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
);
13544 Sema::ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc
,
13545 SourceLocation EndLoc
,
13546 OpenMPDirectiveKind CancelRegion
) {
13547 if (DSAStack
->isParentNowaitRegion()) {
13548 Diag(StartLoc
, diag::err_omp_parent_cancel_region_nowait
) << 0;
13549 return StmtError();
13551 if (DSAStack
->isParentOrderedRegion()) {
13552 Diag(StartLoc
, diag::err_omp_parent_cancel_region_ordered
) << 0;
13553 return StmtError();
13555 return OMPCancellationPointDirective::Create(Context
, StartLoc
, EndLoc
,
13559 StmtResult
Sema::ActOnOpenMPCancelDirective(ArrayRef
<OMPClause
*> Clauses
,
13560 SourceLocation StartLoc
,
13561 SourceLocation EndLoc
,
13562 OpenMPDirectiveKind CancelRegion
) {
13563 if (DSAStack
->isParentNowaitRegion()) {
13564 Diag(StartLoc
, diag::err_omp_parent_cancel_region_nowait
) << 1;
13565 return StmtError();
13567 if (DSAStack
->isParentOrderedRegion()) {
13568 Diag(StartLoc
, diag::err_omp_parent_cancel_region_ordered
) << 1;
13569 return StmtError();
13571 DSAStack
->setParentCancelRegion(/*Cancel=*/true);
13572 return OMPCancelDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
,
13576 static bool checkReductionClauseWithNogroup(Sema
&S
,
13577 ArrayRef
<OMPClause
*> Clauses
) {
13578 const OMPClause
*ReductionClause
= nullptr;
13579 const OMPClause
*NogroupClause
= nullptr;
13580 for (const OMPClause
*C
: Clauses
) {
13581 if (C
->getClauseKind() == OMPC_reduction
) {
13582 ReductionClause
= C
;
13587 if (C
->getClauseKind() == OMPC_nogroup
) {
13589 if (ReductionClause
)
13594 if (ReductionClause
&& NogroupClause
) {
13595 S
.Diag(ReductionClause
->getBeginLoc(), diag::err_omp_reduction_with_nogroup
)
13596 << SourceRange(NogroupClause
->getBeginLoc(),
13597 NogroupClause
->getEndLoc());
13603 StmtResult
Sema::ActOnOpenMPTaskLoopDirective(
13604 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13605 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13607 return StmtError();
13609 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13610 OMPLoopBasedDirective::HelperExprs B
;
13611 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13612 // define the nested loops number.
13613 unsigned NestedLoopCount
=
13614 checkOpenMPLoop(OMPD_taskloop
, getCollapseNumberExpr(Clauses
),
13615 /*OrderedLoopCountExpr=*/nullptr, AStmt
, *this, *DSAStack
,
13616 VarsWithImplicitDSA
, B
);
13617 if (NestedLoopCount
== 0)
13618 return StmtError();
13620 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13621 "omp for loop exprs were not built");
13623 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13624 // The grainsize clause and num_tasks clause are mutually exclusive and may
13625 // not appear on the same taskloop directive.
13626 if (checkMutuallyExclusiveClauses(*this, Clauses
,
13627 {OMPC_grainsize
, OMPC_num_tasks
}))
13628 return StmtError();
13629 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13630 // If a reduction clause is present on the taskloop directive, the nogroup
13631 // clause must not be specified.
13632 if (checkReductionClauseWithNogroup(*this, Clauses
))
13633 return StmtError();
13635 setFunctionHasBranchProtectedScope();
13636 return OMPTaskLoopDirective::Create(Context
, StartLoc
, EndLoc
,
13637 NestedLoopCount
, Clauses
, AStmt
, B
,
13638 DSAStack
->isCancelRegion());
13641 StmtResult
Sema::ActOnOpenMPTaskLoopSimdDirective(
13642 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13643 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13645 return StmtError();
13647 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13648 OMPLoopBasedDirective::HelperExprs B
;
13649 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13650 // define the nested loops number.
13651 unsigned NestedLoopCount
=
13652 checkOpenMPLoop(OMPD_taskloop_simd
, getCollapseNumberExpr(Clauses
),
13653 /*OrderedLoopCountExpr=*/nullptr, AStmt
, *this, *DSAStack
,
13654 VarsWithImplicitDSA
, B
);
13655 if (NestedLoopCount
== 0)
13656 return StmtError();
13658 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13659 "omp for loop exprs were not built");
13661 if (!CurContext
->isDependentContext()) {
13662 // Finalize the clauses that need pre-built expressions for CodeGen.
13663 for (OMPClause
*C
: Clauses
) {
13664 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
13665 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
13666 B
.NumIterations
, *this, CurScope
,
13668 return StmtError();
13672 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13673 // The grainsize clause and num_tasks clause are mutually exclusive and may
13674 // not appear on the same taskloop directive.
13675 if (checkMutuallyExclusiveClauses(*this, Clauses
,
13676 {OMPC_grainsize
, OMPC_num_tasks
}))
13677 return StmtError();
13678 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13679 // If a reduction clause is present on the taskloop directive, the nogroup
13680 // clause must not be specified.
13681 if (checkReductionClauseWithNogroup(*this, Clauses
))
13682 return StmtError();
13683 if (checkSimdlenSafelenSpecified(*this, Clauses
))
13684 return StmtError();
13686 setFunctionHasBranchProtectedScope();
13687 return OMPTaskLoopSimdDirective::Create(Context
, StartLoc
, EndLoc
,
13688 NestedLoopCount
, Clauses
, AStmt
, B
);
13691 StmtResult
Sema::ActOnOpenMPMasterTaskLoopDirective(
13692 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13693 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13695 return StmtError();
13697 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13698 OMPLoopBasedDirective::HelperExprs B
;
13699 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13700 // define the nested loops number.
13701 unsigned NestedLoopCount
=
13702 checkOpenMPLoop(OMPD_master_taskloop
, getCollapseNumberExpr(Clauses
),
13703 /*OrderedLoopCountExpr=*/nullptr, AStmt
, *this, *DSAStack
,
13704 VarsWithImplicitDSA
, B
);
13705 if (NestedLoopCount
== 0)
13706 return StmtError();
13708 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13709 "omp for loop exprs were not built");
13711 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13712 // The grainsize clause and num_tasks clause are mutually exclusive and may
13713 // not appear on the same taskloop directive.
13714 if (checkMutuallyExclusiveClauses(*this, Clauses
,
13715 {OMPC_grainsize
, OMPC_num_tasks
}))
13716 return StmtError();
13717 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13718 // If a reduction clause is present on the taskloop directive, the nogroup
13719 // clause must not be specified.
13720 if (checkReductionClauseWithNogroup(*this, Clauses
))
13721 return StmtError();
13723 setFunctionHasBranchProtectedScope();
13724 return OMPMasterTaskLoopDirective::Create(Context
, StartLoc
, EndLoc
,
13725 NestedLoopCount
, Clauses
, AStmt
, B
,
13726 DSAStack
->isCancelRegion());
13729 StmtResult
Sema::ActOnOpenMPMaskedTaskLoopDirective(
13730 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13731 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13733 return StmtError();
13735 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13736 OMPLoopBasedDirective::HelperExprs B
;
13737 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13738 // define the nested loops number.
13739 unsigned NestedLoopCount
=
13740 checkOpenMPLoop(OMPD_masked_taskloop
, getCollapseNumberExpr(Clauses
),
13741 /*OrderedLoopCountExpr=*/nullptr, AStmt
, *this, *DSAStack
,
13742 VarsWithImplicitDSA
, B
);
13743 if (NestedLoopCount
== 0)
13744 return StmtError();
13746 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13747 "omp for loop exprs were not built");
13749 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13750 // The grainsize clause and num_tasks clause are mutually exclusive and may
13751 // not appear on the same taskloop directive.
13752 if (checkMutuallyExclusiveClauses(*this, Clauses
,
13753 {OMPC_grainsize
, OMPC_num_tasks
}))
13754 return StmtError();
13755 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13756 // If a reduction clause is present on the taskloop directive, the nogroup
13757 // clause must not be specified.
13758 if (checkReductionClauseWithNogroup(*this, Clauses
))
13759 return StmtError();
13761 setFunctionHasBranchProtectedScope();
13762 return OMPMaskedTaskLoopDirective::Create(Context
, StartLoc
, EndLoc
,
13763 NestedLoopCount
, Clauses
, AStmt
, B
,
13764 DSAStack
->isCancelRegion());
13767 StmtResult
Sema::ActOnOpenMPMasterTaskLoopSimdDirective(
13768 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13769 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13771 return StmtError();
13773 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13774 OMPLoopBasedDirective::HelperExprs B
;
13775 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13776 // define the nested loops number.
13777 unsigned NestedLoopCount
=
13778 checkOpenMPLoop(OMPD_master_taskloop_simd
, getCollapseNumberExpr(Clauses
),
13779 /*OrderedLoopCountExpr=*/nullptr, AStmt
, *this, *DSAStack
,
13780 VarsWithImplicitDSA
, B
);
13781 if (NestedLoopCount
== 0)
13782 return StmtError();
13784 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13785 "omp for loop exprs were not built");
13787 if (!CurContext
->isDependentContext()) {
13788 // Finalize the clauses that need pre-built expressions for CodeGen.
13789 for (OMPClause
*C
: Clauses
) {
13790 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
13791 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
13792 B
.NumIterations
, *this, CurScope
,
13794 return StmtError();
13798 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13799 // The grainsize clause and num_tasks clause are mutually exclusive and may
13800 // not appear on the same taskloop directive.
13801 if (checkMutuallyExclusiveClauses(*this, Clauses
,
13802 {OMPC_grainsize
, OMPC_num_tasks
}))
13803 return StmtError();
13804 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13805 // If a reduction clause is present on the taskloop directive, the nogroup
13806 // clause must not be specified.
13807 if (checkReductionClauseWithNogroup(*this, Clauses
))
13808 return StmtError();
13809 if (checkSimdlenSafelenSpecified(*this, Clauses
))
13810 return StmtError();
13812 setFunctionHasBranchProtectedScope();
13813 return OMPMasterTaskLoopSimdDirective::Create(
13814 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
13817 StmtResult
Sema::ActOnOpenMPMaskedTaskLoopSimdDirective(
13818 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13819 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13821 return StmtError();
13823 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13824 OMPLoopBasedDirective::HelperExprs B
;
13825 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13826 // define the nested loops number.
13827 unsigned NestedLoopCount
=
13828 checkOpenMPLoop(OMPD_masked_taskloop_simd
, getCollapseNumberExpr(Clauses
),
13829 /*OrderedLoopCountExpr=*/nullptr, AStmt
, *this, *DSAStack
,
13830 VarsWithImplicitDSA
, B
);
13831 if (NestedLoopCount
== 0)
13832 return StmtError();
13834 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13835 "omp for loop exprs were not built");
13837 if (!CurContext
->isDependentContext()) {
13838 // Finalize the clauses that need pre-built expressions for CodeGen.
13839 for (OMPClause
*C
: Clauses
) {
13840 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
13841 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
13842 B
.NumIterations
, *this, CurScope
,
13844 return StmtError();
13848 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13849 // The grainsize clause and num_tasks clause are mutually exclusive and may
13850 // not appear on the same taskloop directive.
13851 if (checkMutuallyExclusiveClauses(*this, Clauses
,
13852 {OMPC_grainsize
, OMPC_num_tasks
}))
13853 return StmtError();
13854 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13855 // If a reduction clause is present on the taskloop directive, the nogroup
13856 // clause must not be specified.
13857 if (checkReductionClauseWithNogroup(*this, Clauses
))
13858 return StmtError();
13859 if (checkSimdlenSafelenSpecified(*this, Clauses
))
13860 return StmtError();
13862 setFunctionHasBranchProtectedScope();
13863 return OMPMaskedTaskLoopSimdDirective::Create(
13864 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
13867 StmtResult
Sema::ActOnOpenMPParallelMasterTaskLoopDirective(
13868 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13869 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13871 return StmtError();
13873 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13874 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13875 // 1.2.2 OpenMP Language Terminology
13876 // Structured block - An executable statement with a single entry at the
13877 // top and a single exit at the bottom.
13878 // The point of exit cannot be a branch out of the structured block.
13879 // longjmp() and throw() must not violate the entry/exit criteria.
13880 CS
->getCapturedDecl()->setNothrow();
13881 for (int ThisCaptureLevel
=
13882 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop
);
13883 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
13884 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
13885 // 1.2.2 OpenMP Language Terminology
13886 // Structured block - An executable statement with a single entry at the
13887 // top and a single exit at the bottom.
13888 // The point of exit cannot be a branch out of the structured block.
13889 // longjmp() and throw() must not violate the entry/exit criteria.
13890 CS
->getCapturedDecl()->setNothrow();
13893 OMPLoopBasedDirective::HelperExprs B
;
13894 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13895 // define the nested loops number.
13896 unsigned NestedLoopCount
= checkOpenMPLoop(
13897 OMPD_parallel_master_taskloop
, getCollapseNumberExpr(Clauses
),
13898 /*OrderedLoopCountExpr=*/nullptr, CS
, *this, *DSAStack
,
13899 VarsWithImplicitDSA
, B
);
13900 if (NestedLoopCount
== 0)
13901 return StmtError();
13903 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13904 "omp for loop exprs were not built");
13906 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13907 // The grainsize clause and num_tasks clause are mutually exclusive and may
13908 // not appear on the same taskloop directive.
13909 if (checkMutuallyExclusiveClauses(*this, Clauses
,
13910 {OMPC_grainsize
, OMPC_num_tasks
}))
13911 return StmtError();
13912 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13913 // If a reduction clause is present on the taskloop directive, the nogroup
13914 // clause must not be specified.
13915 if (checkReductionClauseWithNogroup(*this, Clauses
))
13916 return StmtError();
13918 setFunctionHasBranchProtectedScope();
13919 return OMPParallelMasterTaskLoopDirective::Create(
13920 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
,
13921 DSAStack
->isCancelRegion());
13924 StmtResult
Sema::ActOnOpenMPParallelMaskedTaskLoopDirective(
13925 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13926 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13928 return StmtError();
13930 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13931 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13932 // 1.2.2 OpenMP Language Terminology
13933 // Structured block - An executable statement with a single entry at the
13934 // top and a single exit at the bottom.
13935 // The point of exit cannot be a branch out of the structured block.
13936 // longjmp() and throw() must not violate the entry/exit criteria.
13937 CS
->getCapturedDecl()->setNothrow();
13938 for (int ThisCaptureLevel
=
13939 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop
);
13940 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
13941 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
13942 // 1.2.2 OpenMP Language Terminology
13943 // Structured block - An executable statement with a single entry at the
13944 // top and a single exit at the bottom.
13945 // The point of exit cannot be a branch out of the structured block.
13946 // longjmp() and throw() must not violate the entry/exit criteria.
13947 CS
->getCapturedDecl()->setNothrow();
13950 OMPLoopBasedDirective::HelperExprs B
;
13951 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13952 // define the nested loops number.
13953 unsigned NestedLoopCount
= checkOpenMPLoop(
13954 OMPD_parallel_masked_taskloop
, getCollapseNumberExpr(Clauses
),
13955 /*OrderedLoopCountExpr=*/nullptr, CS
, *this, *DSAStack
,
13956 VarsWithImplicitDSA
, B
);
13957 if (NestedLoopCount
== 0)
13958 return StmtError();
13960 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
13961 "omp for loop exprs were not built");
13963 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13964 // The grainsize clause and num_tasks clause are mutually exclusive and may
13965 // not appear on the same taskloop directive.
13966 if (checkMutuallyExclusiveClauses(*this, Clauses
,
13967 {OMPC_grainsize
, OMPC_num_tasks
}))
13968 return StmtError();
13969 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13970 // If a reduction clause is present on the taskloop directive, the nogroup
13971 // clause must not be specified.
13972 if (checkReductionClauseWithNogroup(*this, Clauses
))
13973 return StmtError();
13975 setFunctionHasBranchProtectedScope();
13976 return OMPParallelMaskedTaskLoopDirective::Create(
13977 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
,
13978 DSAStack
->isCancelRegion());
13981 StmtResult
Sema::ActOnOpenMPParallelMasterTaskLoopSimdDirective(
13982 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
13983 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
13985 return StmtError();
13987 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
13988 auto *CS
= cast
<CapturedStmt
>(AStmt
);
13989 // 1.2.2 OpenMP Language Terminology
13990 // Structured block - An executable statement with a single entry at the
13991 // top and a single exit at the bottom.
13992 // The point of exit cannot be a branch out of the structured block.
13993 // longjmp() and throw() must not violate the entry/exit criteria.
13994 CS
->getCapturedDecl()->setNothrow();
13995 for (int ThisCaptureLevel
=
13996 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop_simd
);
13997 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
13998 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
13999 // 1.2.2 OpenMP Language Terminology
14000 // Structured block - An executable statement with a single entry at the
14001 // top and a single exit at the bottom.
14002 // The point of exit cannot be a branch out of the structured block.
14003 // longjmp() and throw() must not violate the entry/exit criteria.
14004 CS
->getCapturedDecl()->setNothrow();
14007 OMPLoopBasedDirective::HelperExprs B
;
14008 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14009 // define the nested loops number.
14010 unsigned NestedLoopCount
= checkOpenMPLoop(
14011 OMPD_parallel_master_taskloop_simd
, getCollapseNumberExpr(Clauses
),
14012 /*OrderedLoopCountExpr=*/nullptr, CS
, *this, *DSAStack
,
14013 VarsWithImplicitDSA
, B
);
14014 if (NestedLoopCount
== 0)
14015 return StmtError();
14017 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14018 "omp for loop exprs were not built");
14020 if (!CurContext
->isDependentContext()) {
14021 // Finalize the clauses that need pre-built expressions for CodeGen.
14022 for (OMPClause
*C
: Clauses
) {
14023 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14024 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14025 B
.NumIterations
, *this, CurScope
,
14027 return StmtError();
14031 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14032 // The grainsize clause and num_tasks clause are mutually exclusive and may
14033 // not appear on the same taskloop directive.
14034 if (checkMutuallyExclusiveClauses(*this, Clauses
,
14035 {OMPC_grainsize
, OMPC_num_tasks
}))
14036 return StmtError();
14037 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14038 // If a reduction clause is present on the taskloop directive, the nogroup
14039 // clause must not be specified.
14040 if (checkReductionClauseWithNogroup(*this, Clauses
))
14041 return StmtError();
14042 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14043 return StmtError();
14045 setFunctionHasBranchProtectedScope();
14046 return OMPParallelMasterTaskLoopSimdDirective::Create(
14047 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14050 StmtResult
Sema::ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
14051 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14052 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14054 return StmtError();
14056 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
14057 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14058 // 1.2.2 OpenMP Language Terminology
14059 // Structured block - An executable statement with a single entry at the
14060 // top and a single exit at the bottom.
14061 // The point of exit cannot be a branch out of the structured block.
14062 // longjmp() and throw() must not violate the entry/exit criteria.
14063 CS
->getCapturedDecl()->setNothrow();
14064 for (int ThisCaptureLevel
=
14065 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop_simd
);
14066 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14067 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14068 // 1.2.2 OpenMP Language Terminology
14069 // Structured block - An executable statement with a single entry at the
14070 // top and a single exit at the bottom.
14071 // The point of exit cannot be a branch out of the structured block.
14072 // longjmp() and throw() must not violate the entry/exit criteria.
14073 CS
->getCapturedDecl()->setNothrow();
14076 OMPLoopBasedDirective::HelperExprs B
;
14077 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14078 // define the nested loops number.
14079 unsigned NestedLoopCount
= checkOpenMPLoop(
14080 OMPD_parallel_masked_taskloop_simd
, getCollapseNumberExpr(Clauses
),
14081 /*OrderedLoopCountExpr=*/nullptr, CS
, *this, *DSAStack
,
14082 VarsWithImplicitDSA
, B
);
14083 if (NestedLoopCount
== 0)
14084 return StmtError();
14086 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14087 "omp for loop exprs were not built");
14089 if (!CurContext
->isDependentContext()) {
14090 // Finalize the clauses that need pre-built expressions for CodeGen.
14091 for (OMPClause
*C
: Clauses
) {
14092 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14093 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14094 B
.NumIterations
, *this, CurScope
,
14096 return StmtError();
14100 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14101 // The grainsize clause and num_tasks clause are mutually exclusive and may
14102 // not appear on the same taskloop directive.
14103 if (checkMutuallyExclusiveClauses(*this, Clauses
,
14104 {OMPC_grainsize
, OMPC_num_tasks
}))
14105 return StmtError();
14106 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14107 // If a reduction clause is present on the taskloop directive, the nogroup
14108 // clause must not be specified.
14109 if (checkReductionClauseWithNogroup(*this, Clauses
))
14110 return StmtError();
14111 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14112 return StmtError();
14114 setFunctionHasBranchProtectedScope();
14115 return OMPParallelMaskedTaskLoopSimdDirective::Create(
14116 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14119 StmtResult
Sema::ActOnOpenMPDistributeDirective(
14120 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14121 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14123 return StmtError();
14125 if (!checkLastPrivateForMappedDirectives(Clauses
))
14126 return StmtError();
14128 assert(isa
<CapturedStmt
>(AStmt
) && "Captured statement expected");
14129 OMPLoopBasedDirective::HelperExprs B
;
14130 // In presence of clause 'collapse' with number of loops, it will
14131 // define the nested loops number.
14132 unsigned NestedLoopCount
=
14133 checkOpenMPLoop(OMPD_distribute
, getCollapseNumberExpr(Clauses
),
14134 nullptr /*ordered not a clause on distribute*/, AStmt
,
14135 *this, *DSAStack
, VarsWithImplicitDSA
, B
);
14136 if (NestedLoopCount
== 0)
14137 return StmtError();
14139 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14140 "omp for loop exprs were not built");
14142 setFunctionHasBranchProtectedScope();
14143 auto *DistributeDirective
= OMPDistributeDirective::Create(
14144 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
,
14145 DSAStack
->getMappedDirective());
14146 return DistributeDirective
;
14149 StmtResult
Sema::ActOnOpenMPDistributeParallelForDirective(
14150 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14151 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14153 return StmtError();
14155 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14156 // 1.2.2 OpenMP Language Terminology
14157 // Structured block - An executable statement with a single entry at the
14158 // top and a single exit at the bottom.
14159 // The point of exit cannot be a branch out of the structured block.
14160 // longjmp() and throw() must not violate the entry/exit criteria.
14161 CS
->getCapturedDecl()->setNothrow();
14162 for (int ThisCaptureLevel
=
14163 getOpenMPCaptureLevels(OMPD_distribute_parallel_for
);
14164 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14165 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14166 // 1.2.2 OpenMP Language Terminology
14167 // Structured block - An executable statement with a single entry at the
14168 // top and a single exit at the bottom.
14169 // The point of exit cannot be a branch out of the structured block.
14170 // longjmp() and throw() must not violate the entry/exit criteria.
14171 CS
->getCapturedDecl()->setNothrow();
14174 OMPLoopBasedDirective::HelperExprs B
;
14175 // In presence of clause 'collapse' with number of loops, it will
14176 // define the nested loops number.
14177 unsigned NestedLoopCount
= checkOpenMPLoop(
14178 OMPD_distribute_parallel_for
, getCollapseNumberExpr(Clauses
),
14179 nullptr /*ordered not a clause on distribute*/, CS
, *this, *DSAStack
,
14180 VarsWithImplicitDSA
, B
);
14181 if (NestedLoopCount
== 0)
14182 return StmtError();
14184 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14185 "omp for loop exprs were not built");
14187 setFunctionHasBranchProtectedScope();
14188 return OMPDistributeParallelForDirective::Create(
14189 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
,
14190 DSAStack
->getTaskgroupReductionRef(), DSAStack
->isCancelRegion());
14193 StmtResult
Sema::ActOnOpenMPDistributeParallelForSimdDirective(
14194 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14195 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14197 return StmtError();
14199 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14200 // 1.2.2 OpenMP Language Terminology
14201 // Structured block - An executable statement with a single entry at the
14202 // top and a single exit at the bottom.
14203 // The point of exit cannot be a branch out of the structured block.
14204 // longjmp() and throw() must not violate the entry/exit criteria.
14205 CS
->getCapturedDecl()->setNothrow();
14206 for (int ThisCaptureLevel
=
14207 getOpenMPCaptureLevels(OMPD_distribute_parallel_for_simd
);
14208 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14209 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14210 // 1.2.2 OpenMP Language Terminology
14211 // Structured block - An executable statement with a single entry at the
14212 // top and a single exit at the bottom.
14213 // The point of exit cannot be a branch out of the structured block.
14214 // longjmp() and throw() must not violate the entry/exit criteria.
14215 CS
->getCapturedDecl()->setNothrow();
14218 OMPLoopBasedDirective::HelperExprs B
;
14219 // In presence of clause 'collapse' with number of loops, it will
14220 // define the nested loops number.
14221 unsigned NestedLoopCount
= checkOpenMPLoop(
14222 OMPD_distribute_parallel_for_simd
, getCollapseNumberExpr(Clauses
),
14223 nullptr /*ordered not a clause on distribute*/, CS
, *this, *DSAStack
,
14224 VarsWithImplicitDSA
, B
);
14225 if (NestedLoopCount
== 0)
14226 return StmtError();
14228 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14229 "omp for loop exprs were not built");
14231 if (!CurContext
->isDependentContext()) {
14232 // Finalize the clauses that need pre-built expressions for CodeGen.
14233 for (OMPClause
*C
: Clauses
) {
14234 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14235 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14236 B
.NumIterations
, *this, CurScope
,
14238 return StmtError();
14242 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14243 return StmtError();
14245 setFunctionHasBranchProtectedScope();
14246 return OMPDistributeParallelForSimdDirective::Create(
14247 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14250 StmtResult
Sema::ActOnOpenMPDistributeSimdDirective(
14251 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14252 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14254 return StmtError();
14256 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14257 // 1.2.2 OpenMP Language Terminology
14258 // Structured block - An executable statement with a single entry at the
14259 // top and a single exit at the bottom.
14260 // The point of exit cannot be a branch out of the structured block.
14261 // longjmp() and throw() must not violate the entry/exit criteria.
14262 CS
->getCapturedDecl()->setNothrow();
14263 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_distribute_simd
);
14264 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14265 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14266 // 1.2.2 OpenMP Language Terminology
14267 // Structured block - An executable statement with a single entry at the
14268 // top and a single exit at the bottom.
14269 // The point of exit cannot be a branch out of the structured block.
14270 // longjmp() and throw() must not violate the entry/exit criteria.
14271 CS
->getCapturedDecl()->setNothrow();
14274 OMPLoopBasedDirective::HelperExprs B
;
14275 // In presence of clause 'collapse' with number of loops, it will
14276 // define the nested loops number.
14277 unsigned NestedLoopCount
=
14278 checkOpenMPLoop(OMPD_distribute_simd
, getCollapseNumberExpr(Clauses
),
14279 nullptr /*ordered not a clause on distribute*/, CS
, *this,
14280 *DSAStack
, VarsWithImplicitDSA
, B
);
14281 if (NestedLoopCount
== 0)
14282 return StmtError();
14284 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14285 "omp for loop exprs were not built");
14287 if (!CurContext
->isDependentContext()) {
14288 // Finalize the clauses that need pre-built expressions for CodeGen.
14289 for (OMPClause
*C
: Clauses
) {
14290 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14291 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14292 B
.NumIterations
, *this, CurScope
,
14294 return StmtError();
14298 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14299 return StmtError();
14301 setFunctionHasBranchProtectedScope();
14302 return OMPDistributeSimdDirective::Create(Context
, StartLoc
, EndLoc
,
14303 NestedLoopCount
, Clauses
, AStmt
, B
);
14306 StmtResult
Sema::ActOnOpenMPTargetParallelForSimdDirective(
14307 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14308 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14310 return StmtError();
14312 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14313 // 1.2.2 OpenMP Language Terminology
14314 // Structured block - An executable statement with a single entry at the
14315 // top and a single exit at the bottom.
14316 // The point of exit cannot be a branch out of the structured block.
14317 // longjmp() and throw() must not violate the entry/exit criteria.
14318 CS
->getCapturedDecl()->setNothrow();
14319 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_parallel_for
);
14320 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14321 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14322 // 1.2.2 OpenMP Language Terminology
14323 // Structured block - An executable statement with a single entry at the
14324 // top and a single exit at the bottom.
14325 // The point of exit cannot be a branch out of the structured block.
14326 // longjmp() and throw() must not violate the entry/exit criteria.
14327 CS
->getCapturedDecl()->setNothrow();
14330 OMPLoopBasedDirective::HelperExprs B
;
14331 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14332 // define the nested loops number.
14333 unsigned NestedLoopCount
= checkOpenMPLoop(
14334 OMPD_target_parallel_for_simd
, getCollapseNumberExpr(Clauses
),
14335 getOrderedNumberExpr(Clauses
), CS
, *this, *DSAStack
, VarsWithImplicitDSA
,
14337 if (NestedLoopCount
== 0)
14338 return StmtError();
14340 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14341 "omp target parallel for simd loop exprs were not built");
14343 if (!CurContext
->isDependentContext()) {
14344 // Finalize the clauses that need pre-built expressions for CodeGen.
14345 for (OMPClause
*C
: Clauses
) {
14346 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14347 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14348 B
.NumIterations
, *this, CurScope
,
14350 return StmtError();
14353 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14354 return StmtError();
14356 setFunctionHasBranchProtectedScope();
14357 return OMPTargetParallelForSimdDirective::Create(
14358 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14361 StmtResult
Sema::ActOnOpenMPTargetSimdDirective(
14362 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14363 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14365 return StmtError();
14367 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14368 // 1.2.2 OpenMP Language Terminology
14369 // Structured block - An executable statement with a single entry at the
14370 // top and a single exit at the bottom.
14371 // The point of exit cannot be a branch out of the structured block.
14372 // longjmp() and throw() must not violate the entry/exit criteria.
14373 CS
->getCapturedDecl()->setNothrow();
14374 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_simd
);
14375 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14376 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14377 // 1.2.2 OpenMP Language Terminology
14378 // Structured block - An executable statement with a single entry at the
14379 // top and a single exit at the bottom.
14380 // The point of exit cannot be a branch out of the structured block.
14381 // longjmp() and throw() must not violate the entry/exit criteria.
14382 CS
->getCapturedDecl()->setNothrow();
14385 OMPLoopBasedDirective::HelperExprs B
;
14386 // In presence of clause 'collapse' with number of loops, it will define the
14387 // nested loops number.
14388 unsigned NestedLoopCount
=
14389 checkOpenMPLoop(OMPD_target_simd
, getCollapseNumberExpr(Clauses
),
14390 getOrderedNumberExpr(Clauses
), CS
, *this, *DSAStack
,
14391 VarsWithImplicitDSA
, B
);
14392 if (NestedLoopCount
== 0)
14393 return StmtError();
14395 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14396 "omp target simd loop exprs were not built");
14398 if (!CurContext
->isDependentContext()) {
14399 // Finalize the clauses that need pre-built expressions for CodeGen.
14400 for (OMPClause
*C
: Clauses
) {
14401 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14402 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14403 B
.NumIterations
, *this, CurScope
,
14405 return StmtError();
14409 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14410 return StmtError();
14412 setFunctionHasBranchProtectedScope();
14413 return OMPTargetSimdDirective::Create(Context
, StartLoc
, EndLoc
,
14414 NestedLoopCount
, Clauses
, AStmt
, B
);
14417 StmtResult
Sema::ActOnOpenMPTeamsDistributeDirective(
14418 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14419 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14421 return StmtError();
14423 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14424 // 1.2.2 OpenMP Language Terminology
14425 // Structured block - An executable statement with a single entry at the
14426 // top and a single exit at the bottom.
14427 // The point of exit cannot be a branch out of the structured block.
14428 // longjmp() and throw() must not violate the entry/exit criteria.
14429 CS
->getCapturedDecl()->setNothrow();
14430 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_teams_distribute
);
14431 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14432 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14433 // 1.2.2 OpenMP Language Terminology
14434 // Structured block - An executable statement with a single entry at the
14435 // top and a single exit at the bottom.
14436 // The point of exit cannot be a branch out of the structured block.
14437 // longjmp() and throw() must not violate the entry/exit criteria.
14438 CS
->getCapturedDecl()->setNothrow();
14441 OMPLoopBasedDirective::HelperExprs B
;
14442 // In presence of clause 'collapse' with number of loops, it will
14443 // define the nested loops number.
14444 unsigned NestedLoopCount
=
14445 checkOpenMPLoop(OMPD_teams_distribute
, getCollapseNumberExpr(Clauses
),
14446 nullptr /*ordered not a clause on distribute*/, CS
, *this,
14447 *DSAStack
, VarsWithImplicitDSA
, B
);
14448 if (NestedLoopCount
== 0)
14449 return StmtError();
14451 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14452 "omp teams distribute loop exprs were not built");
14454 setFunctionHasBranchProtectedScope();
14456 DSAStack
->setParentTeamsRegionLoc(StartLoc
);
14458 return OMPTeamsDistributeDirective::Create(
14459 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14462 StmtResult
Sema::ActOnOpenMPTeamsDistributeSimdDirective(
14463 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14464 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14466 return StmtError();
14468 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14469 // 1.2.2 OpenMP Language Terminology
14470 // Structured block - An executable statement with a single entry at the
14471 // top and a single exit at the bottom.
14472 // The point of exit cannot be a branch out of the structured block.
14473 // longjmp() and throw() must not violate the entry/exit criteria.
14474 CS
->getCapturedDecl()->setNothrow();
14475 for (int ThisCaptureLevel
=
14476 getOpenMPCaptureLevels(OMPD_teams_distribute_simd
);
14477 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14478 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14479 // 1.2.2 OpenMP Language Terminology
14480 // Structured block - An executable statement with a single entry at the
14481 // top and a single exit at the bottom.
14482 // The point of exit cannot be a branch out of the structured block.
14483 // longjmp() and throw() must not violate the entry/exit criteria.
14484 CS
->getCapturedDecl()->setNothrow();
14487 OMPLoopBasedDirective::HelperExprs B
;
14488 // In presence of clause 'collapse' with number of loops, it will
14489 // define the nested loops number.
14490 unsigned NestedLoopCount
= checkOpenMPLoop(
14491 OMPD_teams_distribute_simd
, getCollapseNumberExpr(Clauses
),
14492 nullptr /*ordered not a clause on distribute*/, CS
, *this, *DSAStack
,
14493 VarsWithImplicitDSA
, B
);
14495 if (NestedLoopCount
== 0)
14496 return StmtError();
14498 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14499 "omp teams distribute simd loop exprs were not built");
14501 if (!CurContext
->isDependentContext()) {
14502 // Finalize the clauses that need pre-built expressions for CodeGen.
14503 for (OMPClause
*C
: Clauses
) {
14504 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14505 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14506 B
.NumIterations
, *this, CurScope
,
14508 return StmtError();
14512 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14513 return StmtError();
14515 setFunctionHasBranchProtectedScope();
14517 DSAStack
->setParentTeamsRegionLoc(StartLoc
);
14519 return OMPTeamsDistributeSimdDirective::Create(
14520 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14523 StmtResult
Sema::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
14524 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14525 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14527 return StmtError();
14529 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14530 // 1.2.2 OpenMP Language Terminology
14531 // Structured block - An executable statement with a single entry at the
14532 // top and a single exit at the bottom.
14533 // The point of exit cannot be a branch out of the structured block.
14534 // longjmp() and throw() must not violate the entry/exit criteria.
14535 CS
->getCapturedDecl()->setNothrow();
14537 for (int ThisCaptureLevel
=
14538 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for_simd
);
14539 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14540 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14541 // 1.2.2 OpenMP Language Terminology
14542 // Structured block - An executable statement with a single entry at the
14543 // top and a single exit at the bottom.
14544 // The point of exit cannot be a branch out of the structured block.
14545 // longjmp() and throw() must not violate the entry/exit criteria.
14546 CS
->getCapturedDecl()->setNothrow();
14549 OMPLoopBasedDirective::HelperExprs B
;
14550 // In presence of clause 'collapse' with number of loops, it will
14551 // define the nested loops number.
14552 unsigned NestedLoopCount
= checkOpenMPLoop(
14553 OMPD_teams_distribute_parallel_for_simd
, getCollapseNumberExpr(Clauses
),
14554 nullptr /*ordered not a clause on distribute*/, CS
, *this, *DSAStack
,
14555 VarsWithImplicitDSA
, B
);
14557 if (NestedLoopCount
== 0)
14558 return StmtError();
14560 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14561 "omp for loop exprs were not built");
14563 if (!CurContext
->isDependentContext()) {
14564 // Finalize the clauses that need pre-built expressions for CodeGen.
14565 for (OMPClause
*C
: Clauses
) {
14566 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14567 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14568 B
.NumIterations
, *this, CurScope
,
14570 return StmtError();
14574 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14575 return StmtError();
14577 setFunctionHasBranchProtectedScope();
14579 DSAStack
->setParentTeamsRegionLoc(StartLoc
);
14581 return OMPTeamsDistributeParallelForSimdDirective::Create(
14582 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14585 StmtResult
Sema::ActOnOpenMPTeamsDistributeParallelForDirective(
14586 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14587 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14589 return StmtError();
14591 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14592 // 1.2.2 OpenMP Language Terminology
14593 // Structured block - An executable statement with a single entry at the
14594 // top and a single exit at the bottom.
14595 // The point of exit cannot be a branch out of the structured block.
14596 // longjmp() and throw() must not violate the entry/exit criteria.
14597 CS
->getCapturedDecl()->setNothrow();
14599 for (int ThisCaptureLevel
=
14600 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for
);
14601 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14602 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14603 // 1.2.2 OpenMP Language Terminology
14604 // Structured block - An executable statement with a single entry at the
14605 // top and a single exit at the bottom.
14606 // The point of exit cannot be a branch out of the structured block.
14607 // longjmp() and throw() must not violate the entry/exit criteria.
14608 CS
->getCapturedDecl()->setNothrow();
14611 OMPLoopBasedDirective::HelperExprs B
;
14612 // In presence of clause 'collapse' with number of loops, it will
14613 // define the nested loops number.
14614 unsigned NestedLoopCount
= checkOpenMPLoop(
14615 OMPD_teams_distribute_parallel_for
, getCollapseNumberExpr(Clauses
),
14616 nullptr /*ordered not a clause on distribute*/, CS
, *this, *DSAStack
,
14617 VarsWithImplicitDSA
, B
);
14619 if (NestedLoopCount
== 0)
14620 return StmtError();
14622 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14623 "omp for loop exprs were not built");
14625 setFunctionHasBranchProtectedScope();
14627 DSAStack
->setParentTeamsRegionLoc(StartLoc
);
14629 return OMPTeamsDistributeParallelForDirective::Create(
14630 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
,
14631 DSAStack
->getTaskgroupReductionRef(), DSAStack
->isCancelRegion());
14634 StmtResult
Sema::ActOnOpenMPTargetTeamsDirective(ArrayRef
<OMPClause
*> Clauses
,
14636 SourceLocation StartLoc
,
14637 SourceLocation EndLoc
) {
14639 return StmtError();
14641 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14642 // 1.2.2 OpenMP Language Terminology
14643 // Structured block - An executable statement with a single entry at the
14644 // top and a single exit at the bottom.
14645 // The point of exit cannot be a branch out of the structured block.
14646 // longjmp() and throw() must not violate the entry/exit criteria.
14647 CS
->getCapturedDecl()->setNothrow();
14649 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(OMPD_target_teams
);
14650 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14651 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14652 // 1.2.2 OpenMP Language Terminology
14653 // Structured block - An executable statement with a single entry at the
14654 // top and a single exit at the bottom.
14655 // The point of exit cannot be a branch out of the structured block.
14656 // longjmp() and throw() must not violate the entry/exit criteria.
14657 CS
->getCapturedDecl()->setNothrow();
14659 setFunctionHasBranchProtectedScope();
14661 const OMPClause
*BareClause
= nullptr;
14662 bool HasThreadLimitAndNumTeamsClause
= hasClauses(Clauses
, OMPC_num_teams
) &&
14663 hasClauses(Clauses
, OMPC_thread_limit
);
14664 bool HasBareClause
= llvm::any_of(Clauses
, [&](const OMPClause
*C
) {
14666 return C
->getClauseKind() == OMPC_ompx_bare
;
14669 if (HasBareClause
&& !HasThreadLimitAndNumTeamsClause
) {
14670 Diag(BareClause
->getBeginLoc(), diag::err_ompx_bare_no_grid
);
14671 return StmtError();
14674 return OMPTargetTeamsDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
,
14678 StmtResult
Sema::ActOnOpenMPTargetTeamsDistributeDirective(
14679 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14680 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14682 return StmtError();
14684 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14685 // 1.2.2 OpenMP Language Terminology
14686 // Structured block - An executable statement with a single entry at the
14687 // top and a single exit at the bottom.
14688 // The point of exit cannot be a branch out of the structured block.
14689 // longjmp() and throw() must not violate the entry/exit criteria.
14690 CS
->getCapturedDecl()->setNothrow();
14691 for (int ThisCaptureLevel
=
14692 getOpenMPCaptureLevels(OMPD_target_teams_distribute
);
14693 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14694 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14695 // 1.2.2 OpenMP Language Terminology
14696 // Structured block - An executable statement with a single entry at the
14697 // top and a single exit at the bottom.
14698 // The point of exit cannot be a branch out of the structured block.
14699 // longjmp() and throw() must not violate the entry/exit criteria.
14700 CS
->getCapturedDecl()->setNothrow();
14703 OMPLoopBasedDirective::HelperExprs B
;
14704 // In presence of clause 'collapse' with number of loops, it will
14705 // define the nested loops number.
14706 unsigned NestedLoopCount
= checkOpenMPLoop(
14707 OMPD_target_teams_distribute
, getCollapseNumberExpr(Clauses
),
14708 nullptr /*ordered not a clause on distribute*/, CS
, *this, *DSAStack
,
14709 VarsWithImplicitDSA
, B
);
14710 if (NestedLoopCount
== 0)
14711 return StmtError();
14713 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14714 "omp target teams distribute loop exprs were not built");
14716 setFunctionHasBranchProtectedScope();
14717 return OMPTargetTeamsDistributeDirective::Create(
14718 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14721 StmtResult
Sema::ActOnOpenMPTargetTeamsDistributeParallelForDirective(
14722 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14723 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14725 return StmtError();
14727 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14728 // 1.2.2 OpenMP Language Terminology
14729 // Structured block - An executable statement with a single entry at the
14730 // top and a single exit at the bottom.
14731 // The point of exit cannot be a branch out of the structured block.
14732 // longjmp() and throw() must not violate the entry/exit criteria.
14733 CS
->getCapturedDecl()->setNothrow();
14734 for (int ThisCaptureLevel
=
14735 getOpenMPCaptureLevels(OMPD_target_teams_distribute_parallel_for
);
14736 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14737 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14738 // 1.2.2 OpenMP Language Terminology
14739 // Structured block - An executable statement with a single entry at the
14740 // top and a single exit at the bottom.
14741 // The point of exit cannot be a branch out of the structured block.
14742 // longjmp() and throw() must not violate the entry/exit criteria.
14743 CS
->getCapturedDecl()->setNothrow();
14746 OMPLoopBasedDirective::HelperExprs B
;
14747 // In presence of clause 'collapse' with number of loops, it will
14748 // define the nested loops number.
14749 unsigned NestedLoopCount
= checkOpenMPLoop(
14750 OMPD_target_teams_distribute_parallel_for
, getCollapseNumberExpr(Clauses
),
14751 nullptr /*ordered not a clause on distribute*/, CS
, *this, *DSAStack
,
14752 VarsWithImplicitDSA
, B
);
14753 if (NestedLoopCount
== 0)
14754 return StmtError();
14756 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14757 "omp target teams distribute parallel for loop exprs were not built");
14759 if (!CurContext
->isDependentContext()) {
14760 // Finalize the clauses that need pre-built expressions for CodeGen.
14761 for (OMPClause
*C
: Clauses
) {
14762 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14763 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14764 B
.NumIterations
, *this, CurScope
,
14766 return StmtError();
14770 setFunctionHasBranchProtectedScope();
14771 return OMPTargetTeamsDistributeParallelForDirective::Create(
14772 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
,
14773 DSAStack
->getTaskgroupReductionRef(), DSAStack
->isCancelRegion());
14776 StmtResult
Sema::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
14777 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14778 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14780 return StmtError();
14782 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14783 // 1.2.2 OpenMP Language Terminology
14784 // Structured block - An executable statement with a single entry at the
14785 // top and a single exit at the bottom.
14786 // The point of exit cannot be a branch out of the structured block.
14787 // longjmp() and throw() must not violate the entry/exit criteria.
14788 CS
->getCapturedDecl()->setNothrow();
14789 for (int ThisCaptureLevel
= getOpenMPCaptureLevels(
14790 OMPD_target_teams_distribute_parallel_for_simd
);
14791 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14792 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14793 // 1.2.2 OpenMP Language Terminology
14794 // Structured block - An executable statement with a single entry at the
14795 // top and a single exit at the bottom.
14796 // The point of exit cannot be a branch out of the structured block.
14797 // longjmp() and throw() must not violate the entry/exit criteria.
14798 CS
->getCapturedDecl()->setNothrow();
14801 OMPLoopBasedDirective::HelperExprs B
;
14802 // In presence of clause 'collapse' with number of loops, it will
14803 // define the nested loops number.
14804 unsigned NestedLoopCount
=
14805 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd
,
14806 getCollapseNumberExpr(Clauses
),
14807 nullptr /*ordered not a clause on distribute*/, CS
, *this,
14808 *DSAStack
, VarsWithImplicitDSA
, B
);
14809 if (NestedLoopCount
== 0)
14810 return StmtError();
14812 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14813 "omp target teams distribute parallel for simd loop exprs were not "
14816 if (!CurContext
->isDependentContext()) {
14817 // Finalize the clauses that need pre-built expressions for CodeGen.
14818 for (OMPClause
*C
: Clauses
) {
14819 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14820 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14821 B
.NumIterations
, *this, CurScope
,
14823 return StmtError();
14827 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14828 return StmtError();
14830 setFunctionHasBranchProtectedScope();
14831 return OMPTargetTeamsDistributeParallelForSimdDirective::Create(
14832 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14835 StmtResult
Sema::ActOnOpenMPTargetTeamsDistributeSimdDirective(
14836 ArrayRef
<OMPClause
*> Clauses
, Stmt
*AStmt
, SourceLocation StartLoc
,
14837 SourceLocation EndLoc
, VarsWithInheritedDSAType
&VarsWithImplicitDSA
) {
14839 return StmtError();
14841 auto *CS
= cast
<CapturedStmt
>(AStmt
);
14842 // 1.2.2 OpenMP Language Terminology
14843 // Structured block - An executable statement with a single entry at the
14844 // top and a single exit at the bottom.
14845 // The point of exit cannot be a branch out of the structured block.
14846 // longjmp() and throw() must not violate the entry/exit criteria.
14847 CS
->getCapturedDecl()->setNothrow();
14848 for (int ThisCaptureLevel
=
14849 getOpenMPCaptureLevels(OMPD_target_teams_distribute_simd
);
14850 ThisCaptureLevel
> 1; --ThisCaptureLevel
) {
14851 CS
= cast
<CapturedStmt
>(CS
->getCapturedStmt());
14852 // 1.2.2 OpenMP Language Terminology
14853 // Structured block - An executable statement with a single entry at the
14854 // top and a single exit at the bottom.
14855 // The point of exit cannot be a branch out of the structured block.
14856 // longjmp() and throw() must not violate the entry/exit criteria.
14857 CS
->getCapturedDecl()->setNothrow();
14860 OMPLoopBasedDirective::HelperExprs B
;
14861 // In presence of clause 'collapse' with number of loops, it will
14862 // define the nested loops number.
14863 unsigned NestedLoopCount
= checkOpenMPLoop(
14864 OMPD_target_teams_distribute_simd
, getCollapseNumberExpr(Clauses
),
14865 nullptr /*ordered not a clause on distribute*/, CS
, *this, *DSAStack
,
14866 VarsWithImplicitDSA
, B
);
14867 if (NestedLoopCount
== 0)
14868 return StmtError();
14870 assert((CurContext
->isDependentContext() || B
.builtAll()) &&
14871 "omp target teams distribute simd loop exprs were not built");
14873 if (!CurContext
->isDependentContext()) {
14874 // Finalize the clauses that need pre-built expressions for CodeGen.
14875 for (OMPClause
*C
: Clauses
) {
14876 if (auto *LC
= dyn_cast
<OMPLinearClause
>(C
))
14877 if (FinishOpenMPLinearClause(*LC
, cast
<DeclRefExpr
>(B
.IterationVarRef
),
14878 B
.NumIterations
, *this, CurScope
,
14880 return StmtError();
14884 if (checkSimdlenSafelenSpecified(*this, Clauses
))
14885 return StmtError();
14887 setFunctionHasBranchProtectedScope();
14888 return OMPTargetTeamsDistributeSimdDirective::Create(
14889 Context
, StartLoc
, EndLoc
, NestedLoopCount
, Clauses
, AStmt
, B
);
14892 bool Sema::checkTransformableLoopNest(
14893 OpenMPDirectiveKind Kind
, Stmt
*AStmt
, int NumLoops
,
14894 SmallVectorImpl
<OMPLoopBasedDirective::HelperExprs
> &LoopHelpers
,
14896 SmallVectorImpl
<SmallVector
<llvm::PointerUnion
<Stmt
*, Decl
*>, 0>>
14898 OriginalInits
.emplace_back();
14899 bool Result
= OMPLoopBasedDirective::doForAllLoops(
14900 AStmt
->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops
,
14901 [this, &LoopHelpers
, &Body
, &OriginalInits
, Kind
](unsigned Cnt
,
14903 VarsWithInheritedDSAType TmpDSA
;
14904 unsigned SingleNumLoops
=
14905 checkOpenMPLoop(Kind
, nullptr, nullptr, CurStmt
, *this, *DSAStack
,
14906 TmpDSA
, LoopHelpers
[Cnt
]);
14907 if (SingleNumLoops
== 0)
14909 assert(SingleNumLoops
== 1 && "Expect single loop iteration space");
14910 if (auto *For
= dyn_cast
<ForStmt
>(CurStmt
)) {
14911 OriginalInits
.back().push_back(For
->getInit());
14912 Body
= For
->getBody();
14914 assert(isa
<CXXForRangeStmt
>(CurStmt
) &&
14915 "Expected canonical for or range-based for loops.");
14916 auto *CXXFor
= cast
<CXXForRangeStmt
>(CurStmt
);
14917 OriginalInits
.back().push_back(CXXFor
->getBeginStmt());
14918 Body
= CXXFor
->getBody();
14920 OriginalInits
.emplace_back();
14923 [&OriginalInits
](OMPLoopBasedDirective
*Transform
) {
14924 Stmt
*DependentPreInits
;
14925 if (auto *Dir
= dyn_cast
<OMPTileDirective
>(Transform
))
14926 DependentPreInits
= Dir
->getPreInits();
14927 else if (auto *Dir
= dyn_cast
<OMPUnrollDirective
>(Transform
))
14928 DependentPreInits
= Dir
->getPreInits();
14930 llvm_unreachable("Unhandled loop transformation");
14931 if (!DependentPreInits
)
14933 llvm::append_range(OriginalInits
.back(),
14934 cast
<DeclStmt
>(DependentPreInits
)->getDeclGroup());
14936 assert(OriginalInits
.back().empty() && "No preinit after innermost loop");
14937 OriginalInits
.pop_back();
14941 StmtResult
Sema::ActOnOpenMPTileDirective(ArrayRef
<OMPClause
*> Clauses
,
14942 Stmt
*AStmt
, SourceLocation StartLoc
,
14943 SourceLocation EndLoc
) {
14944 auto SizesClauses
=
14945 OMPExecutableDirective::getClausesOfKind
<OMPSizesClause
>(Clauses
);
14946 if (SizesClauses
.empty()) {
14947 // A missing 'sizes' clause is already reported by the parser.
14948 return StmtError();
14950 const OMPSizesClause
*SizesClause
= *SizesClauses
.begin();
14951 unsigned NumLoops
= SizesClause
->getNumSizes();
14953 // Empty statement should only be possible if there already was an error.
14955 return StmtError();
14957 // Verify and diagnose loop nest.
14958 SmallVector
<OMPLoopBasedDirective::HelperExprs
, 4> LoopHelpers(NumLoops
);
14959 Stmt
*Body
= nullptr;
14960 SmallVector
<SmallVector
<llvm::PointerUnion
<Stmt
*, Decl
*>, 0>, 4>
14962 if (!checkTransformableLoopNest(OMPD_tile
, AStmt
, NumLoops
, LoopHelpers
, Body
,
14964 return StmtError();
14966 // Delay tiling to when template is completely instantiated.
14967 if (CurContext
->isDependentContext())
14968 return OMPTileDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
,
14969 NumLoops
, AStmt
, nullptr, nullptr);
14971 SmallVector
<Decl
*, 4> PreInits
;
14973 // Create iteration variables for the generated loops.
14974 SmallVector
<VarDecl
*, 4> FloorIndVars
;
14975 SmallVector
<VarDecl
*, 4> TileIndVars
;
14976 FloorIndVars
.resize(NumLoops
);
14977 TileIndVars
.resize(NumLoops
);
14978 for (unsigned I
= 0; I
< NumLoops
; ++I
) {
14979 OMPLoopBasedDirective::HelperExprs
&LoopHelper
= LoopHelpers
[I
];
14981 assert(LoopHelper
.Counters
.size() == 1 &&
14982 "Expect single-dimensional loop iteration space");
14983 auto *OrigCntVar
= cast
<DeclRefExpr
>(LoopHelper
.Counters
.front());
14984 std::string OrigVarName
= OrigCntVar
->getNameInfo().getAsString();
14985 DeclRefExpr
*IterVarRef
= cast
<DeclRefExpr
>(LoopHelper
.IterationVarRef
);
14986 QualType CntTy
= IterVarRef
->getType();
14988 // Iteration variable for the floor (i.e. outer) loop.
14990 std::string FloorCntName
=
14991 (Twine(".floor_") + llvm::utostr(I
) + ".iv." + OrigVarName
).str();
14992 VarDecl
*FloorCntDecl
=
14993 buildVarDecl(*this, {}, CntTy
, FloorCntName
, nullptr, OrigCntVar
);
14994 FloorIndVars
[I
] = FloorCntDecl
;
14997 // Iteration variable for the tile (i.e. inner) loop.
14999 std::string TileCntName
=
15000 (Twine(".tile_") + llvm::utostr(I
) + ".iv." + OrigVarName
).str();
15002 // Reuse the iteration variable created by checkOpenMPLoop. It is also
15003 // used by the expressions to derive the original iteration variable's
15004 // value from the logical iteration number.
15005 auto *TileCntDecl
= cast
<VarDecl
>(IterVarRef
->getDecl());
15006 TileCntDecl
->setDeclName(&PP
.getIdentifierTable().get(TileCntName
));
15007 TileIndVars
[I
] = TileCntDecl
;
15009 for (auto &P
: OriginalInits
[I
]) {
15010 if (auto *D
= P
.dyn_cast
<Decl
*>())
15011 PreInits
.push_back(D
);
15012 else if (auto *PI
= dyn_cast_or_null
<DeclStmt
>(P
.dyn_cast
<Stmt
*>()))
15013 PreInits
.append(PI
->decl_begin(), PI
->decl_end());
15015 if (auto *PI
= cast_or_null
<DeclStmt
>(LoopHelper
.PreInits
))
15016 PreInits
.append(PI
->decl_begin(), PI
->decl_end());
15017 // Gather declarations for the data members used as counters.
15018 for (Expr
*CounterRef
: LoopHelper
.Counters
) {
15019 auto *CounterDecl
= cast
<DeclRefExpr
>(CounterRef
)->getDecl();
15020 if (isa
<OMPCapturedExprDecl
>(CounterDecl
))
15021 PreInits
.push_back(CounterDecl
);
15025 // Once the original iteration values are set, append the innermost body.
15026 Stmt
*Inner
= Body
;
15028 // Create tile loops from the inside to the outside.
15029 for (int I
= NumLoops
- 1; I
>= 0; --I
) {
15030 OMPLoopBasedDirective::HelperExprs
&LoopHelper
= LoopHelpers
[I
];
15031 Expr
*NumIterations
= LoopHelper
.NumIterations
;
15032 auto *OrigCntVar
= cast
<DeclRefExpr
>(LoopHelper
.Counters
[0]);
15033 QualType CntTy
= OrigCntVar
->getType();
15034 Expr
*DimTileSize
= SizesClause
->getSizesRefs()[I
];
15035 Scope
*CurScope
= getCurScope();
15037 // Commonly used variables.
15038 DeclRefExpr
*TileIV
= buildDeclRefExpr(*this, TileIndVars
[I
], CntTy
,
15039 OrigCntVar
->getExprLoc());
15040 DeclRefExpr
*FloorIV
= buildDeclRefExpr(*this, FloorIndVars
[I
], CntTy
,
15041 OrigCntVar
->getExprLoc());
15043 // For init-statement: auto .tile.iv = .floor.iv
15044 AddInitializerToDecl(TileIndVars
[I
], DefaultLvalueConversion(FloorIV
).get(),
15045 /*DirectInit=*/false);
15046 Decl
*CounterDecl
= TileIndVars
[I
];
15047 StmtResult InitStmt
= new (Context
)
15048 DeclStmt(DeclGroupRef::Create(Context
, &CounterDecl
, 1),
15049 OrigCntVar
->getBeginLoc(), OrigCntVar
->getEndLoc());
15050 if (!InitStmt
.isUsable())
15051 return StmtError();
15053 // For cond-expression: .tile.iv < min(.floor.iv + DimTileSize,
15055 ExprResult EndOfTile
= BuildBinOp(CurScope
, LoopHelper
.Cond
->getExprLoc(),
15056 BO_Add
, FloorIV
, DimTileSize
);
15057 if (!EndOfTile
.isUsable())
15058 return StmtError();
15059 ExprResult IsPartialTile
=
15060 BuildBinOp(CurScope
, LoopHelper
.Cond
->getExprLoc(), BO_LT
,
15061 NumIterations
, EndOfTile
.get());
15062 if (!IsPartialTile
.isUsable())
15063 return StmtError();
15064 ExprResult MinTileAndIterSpace
= ActOnConditionalOp(
15065 LoopHelper
.Cond
->getBeginLoc(), LoopHelper
.Cond
->getEndLoc(),
15066 IsPartialTile
.get(), NumIterations
, EndOfTile
.get());
15067 if (!MinTileAndIterSpace
.isUsable())
15068 return StmtError();
15069 ExprResult CondExpr
= BuildBinOp(CurScope
, LoopHelper
.Cond
->getExprLoc(),
15070 BO_LT
, TileIV
, MinTileAndIterSpace
.get());
15071 if (!CondExpr
.isUsable())
15072 return StmtError();
15074 // For incr-statement: ++.tile.iv
15075 ExprResult IncrStmt
=
15076 BuildUnaryOp(CurScope
, LoopHelper
.Inc
->getExprLoc(), UO_PreInc
, TileIV
);
15077 if (!IncrStmt
.isUsable())
15078 return StmtError();
15080 // Statements to set the original iteration variable's value from the
15081 // logical iteration number.
15082 // Generated for loop is:
15083 // Original_for_init;
15084 // for (auto .tile.iv = .floor.iv; .tile.iv < min(.floor.iv + DimTileSize,
15085 // NumIterations); ++.tile.iv) {
15087 // Original_counter_update;
15089 // FIXME: If the innermost body is an loop itself, inserting these
15090 // statements stops it being recognized as a perfectly nested loop (e.g.
15091 // for applying tiling again). If this is the case, sink the expressions
15092 // further into the inner loop.
15093 SmallVector
<Stmt
*, 4> BodyParts
;
15094 BodyParts
.append(LoopHelper
.Updates
.begin(), LoopHelper
.Updates
.end());
15095 BodyParts
.push_back(Inner
);
15096 Inner
= CompoundStmt::Create(Context
, BodyParts
, FPOptionsOverride(),
15097 Inner
->getBeginLoc(), Inner
->getEndLoc());
15098 Inner
= new (Context
)
15099 ForStmt(Context
, InitStmt
.get(), CondExpr
.get(), nullptr,
15100 IncrStmt
.get(), Inner
, LoopHelper
.Init
->getBeginLoc(),
15101 LoopHelper
.Init
->getBeginLoc(), LoopHelper
.Inc
->getEndLoc());
15104 // Create floor loops from the inside to the outside.
15105 for (int I
= NumLoops
- 1; I
>= 0; --I
) {
15106 auto &LoopHelper
= LoopHelpers
[I
];
15107 Expr
*NumIterations
= LoopHelper
.NumIterations
;
15108 DeclRefExpr
*OrigCntVar
= cast
<DeclRefExpr
>(LoopHelper
.Counters
[0]);
15109 QualType CntTy
= OrigCntVar
->getType();
15110 Expr
*DimTileSize
= SizesClause
->getSizesRefs()[I
];
15111 Scope
*CurScope
= getCurScope();
15113 // Commonly used variables.
15114 DeclRefExpr
*FloorIV
= buildDeclRefExpr(*this, FloorIndVars
[I
], CntTy
,
15115 OrigCntVar
->getExprLoc());
15117 // For init-statement: auto .floor.iv = 0
15118 AddInitializerToDecl(
15120 ActOnIntegerConstant(LoopHelper
.Init
->getExprLoc(), 0).get(),
15121 /*DirectInit=*/false);
15122 Decl
*CounterDecl
= FloorIndVars
[I
];
15123 StmtResult InitStmt
= new (Context
)
15124 DeclStmt(DeclGroupRef::Create(Context
, &CounterDecl
, 1),
15125 OrigCntVar
->getBeginLoc(), OrigCntVar
->getEndLoc());
15126 if (!InitStmt
.isUsable())
15127 return StmtError();
15129 // For cond-expression: .floor.iv < NumIterations
15130 ExprResult CondExpr
= BuildBinOp(CurScope
, LoopHelper
.Cond
->getExprLoc(),
15131 BO_LT
, FloorIV
, NumIterations
);
15132 if (!CondExpr
.isUsable())
15133 return StmtError();
15135 // For incr-statement: .floor.iv += DimTileSize
15136 ExprResult IncrStmt
= BuildBinOp(CurScope
, LoopHelper
.Inc
->getExprLoc(),
15137 BO_AddAssign
, FloorIV
, DimTileSize
);
15138 if (!IncrStmt
.isUsable())
15139 return StmtError();
15141 Inner
= new (Context
)
15142 ForStmt(Context
, InitStmt
.get(), CondExpr
.get(), nullptr,
15143 IncrStmt
.get(), Inner
, LoopHelper
.Init
->getBeginLoc(),
15144 LoopHelper
.Init
->getBeginLoc(), LoopHelper
.Inc
->getEndLoc());
15147 return OMPTileDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, NumLoops
,
15149 buildPreInits(Context
, PreInits
));
15152 StmtResult
Sema::ActOnOpenMPUnrollDirective(ArrayRef
<OMPClause
*> Clauses
,
15154 SourceLocation StartLoc
,
15155 SourceLocation EndLoc
) {
15156 // Empty statement should only be possible if there already was an error.
15158 return StmtError();
15160 if (checkMutuallyExclusiveClauses(*this, Clauses
, {OMPC_partial
, OMPC_full
}))
15161 return StmtError();
15163 const OMPFullClause
*FullClause
=
15164 OMPExecutableDirective::getSingleClause
<OMPFullClause
>(Clauses
);
15165 const OMPPartialClause
*PartialClause
=
15166 OMPExecutableDirective::getSingleClause
<OMPPartialClause
>(Clauses
);
15167 assert(!(FullClause
&& PartialClause
) &&
15168 "mutual exclusivity must have been checked before");
15170 constexpr unsigned NumLoops
= 1;
15171 Stmt
*Body
= nullptr;
15172 SmallVector
<OMPLoopBasedDirective::HelperExprs
, NumLoops
> LoopHelpers(
15174 SmallVector
<SmallVector
<llvm::PointerUnion
<Stmt
*, Decl
*>, 0>, NumLoops
+ 1>
15176 if (!checkTransformableLoopNest(OMPD_unroll
, AStmt
, NumLoops
, LoopHelpers
,
15177 Body
, OriginalInits
))
15178 return StmtError();
15180 unsigned NumGeneratedLoops
= PartialClause
? 1 : 0;
15182 // Delay unrolling to when template is completely instantiated.
15183 if (CurContext
->isDependentContext())
15184 return OMPUnrollDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
15185 NumGeneratedLoops
, nullptr, nullptr);
15187 OMPLoopBasedDirective::HelperExprs
&LoopHelper
= LoopHelpers
.front();
15190 if (!VerifyPositiveIntegerConstantInClause(
15191 LoopHelper
.NumIterations
, OMPC_full
, /*StrictlyPositive=*/false,
15192 /*SuppressExprDiags=*/true)
15194 Diag(AStmt
->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count
);
15195 Diag(FullClause
->getBeginLoc(), diag::note_omp_directive_here
)
15196 << "#pragma omp unroll full";
15197 return StmtError();
15201 // The generated loop may only be passed to other loop-associated directive
15202 // when a partial clause is specified. Without the requirement it is
15203 // sufficient to generate loop unroll metadata at code-generation.
15204 if (NumGeneratedLoops
== 0)
15205 return OMPUnrollDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
15206 NumGeneratedLoops
, nullptr, nullptr);
15208 // Otherwise, we need to provide a de-sugared/transformed AST that can be
15209 // associated with another loop directive.
15211 // The canonical loop analysis return by checkTransformableLoopNest assumes
15212 // the following structure to be the same loop without transformations or
15213 // directives applied: \code OriginalInits; LoopHelper.PreInits;
15214 // LoopHelper.Counters;
15215 // for (; IV < LoopHelper.NumIterations; ++IV) {
15216 // LoopHelper.Updates;
15220 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
15221 // and referenced by LoopHelper.IterationVarRef.
15223 // The unrolling directive transforms this into the following loop:
15225 // OriginalInits; \
15226 // LoopHelper.PreInits; > NewPreInits
15227 // LoopHelper.Counters; /
15228 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
15229 // #pragma clang loop unroll_count(Factor)
15230 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
15232 // LoopHelper.Updates;
15237 // where UIV is a new logical iteration counter. IV must be the same VarDecl
15238 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
15239 // references it. If the partially unrolled loop is associated with another
15240 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
15241 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
15242 // OpenMP canonical loop. The inner loop is not an associable canonical loop
15243 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
15244 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
15245 // property of the OMPLoopBasedDirective instead of statements in
15246 // CompoundStatement. This is to allow the loop to become a non-outermost loop
15247 // of a canonical loop nest where these PreInits are emitted before the
15248 // outermost directive.
15250 // Determine the PreInit declarations.
15251 SmallVector
<Decl
*, 4> PreInits
;
15252 assert(OriginalInits
.size() == 1 &&
15253 "Expecting a single-dimensional loop iteration space");
15254 for (auto &P
: OriginalInits
[0]) {
15255 if (auto *D
= P
.dyn_cast
<Decl
*>())
15256 PreInits
.push_back(D
);
15257 else if (auto *PI
= dyn_cast_or_null
<DeclStmt
>(P
.dyn_cast
<Stmt
*>()))
15258 PreInits
.append(PI
->decl_begin(), PI
->decl_end());
15260 if (auto *PI
= cast_or_null
<DeclStmt
>(LoopHelper
.PreInits
))
15261 PreInits
.append(PI
->decl_begin(), PI
->decl_end());
15262 // Gather declarations for the data members used as counters.
15263 for (Expr
*CounterRef
: LoopHelper
.Counters
) {
15264 auto *CounterDecl
= cast
<DeclRefExpr
>(CounterRef
)->getDecl();
15265 if (isa
<OMPCapturedExprDecl
>(CounterDecl
))
15266 PreInits
.push_back(CounterDecl
);
15269 auto *IterationVarRef
= cast
<DeclRefExpr
>(LoopHelper
.IterationVarRef
);
15270 QualType IVTy
= IterationVarRef
->getType();
15271 assert(LoopHelper
.Counters
.size() == 1 &&
15272 "Expecting a single-dimensional loop iteration space");
15273 auto *OrigVar
= cast
<DeclRefExpr
>(LoopHelper
.Counters
.front());
15275 // Determine the unroll factor.
15277 SourceLocation FactorLoc
;
15278 if (Expr
*FactorVal
= PartialClause
->getFactor()) {
15279 Factor
= FactorVal
->getIntegerConstantExpr(Context
)->getZExtValue();
15280 FactorLoc
= FactorVal
->getExprLoc();
15282 // TODO: Use a better profitability model.
15285 assert(Factor
> 0 && "Expected positive unroll factor");
15286 auto MakeFactorExpr
= [this, Factor
, IVTy
, FactorLoc
]() {
15287 return IntegerLiteral::Create(
15288 Context
, llvm::APInt(Context
.getIntWidth(IVTy
), Factor
), IVTy
,
15292 // Iteration variable SourceLocations.
15293 SourceLocation OrigVarLoc
= OrigVar
->getExprLoc();
15294 SourceLocation OrigVarLocBegin
= OrigVar
->getBeginLoc();
15295 SourceLocation OrigVarLocEnd
= OrigVar
->getEndLoc();
15297 // Internal variable names.
15298 std::string OrigVarName
= OrigVar
->getNameInfo().getAsString();
15299 std::string OuterIVName
= (Twine(".unrolled.iv.") + OrigVarName
).str();
15300 std::string InnerIVName
= (Twine(".unroll_inner.iv.") + OrigVarName
).str();
15301 std::string InnerTripCountName
=
15302 (Twine(".unroll_inner.tripcount.") + OrigVarName
).str();
15304 // Create the iteration variable for the unrolled loop.
15305 VarDecl
*OuterIVDecl
=
15306 buildVarDecl(*this, {}, IVTy
, OuterIVName
, nullptr, OrigVar
);
15307 auto MakeOuterRef
= [this, OuterIVDecl
, IVTy
, OrigVarLoc
]() {
15308 return buildDeclRefExpr(*this, OuterIVDecl
, IVTy
, OrigVarLoc
);
15311 // Iteration variable for the inner loop: Reuse the iteration variable created
15312 // by checkOpenMPLoop.
15313 auto *InnerIVDecl
= cast
<VarDecl
>(IterationVarRef
->getDecl());
15314 InnerIVDecl
->setDeclName(&PP
.getIdentifierTable().get(InnerIVName
));
15315 auto MakeInnerRef
= [this, InnerIVDecl
, IVTy
, OrigVarLoc
]() {
15316 return buildDeclRefExpr(*this, InnerIVDecl
, IVTy
, OrigVarLoc
);
15319 // Make a copy of the NumIterations expression for each use: By the AST
15320 // constraints, every expression object in a DeclContext must be unique.
15321 CaptureVars
CopyTransformer(*this);
15322 auto MakeNumIterations
= [&CopyTransformer
, &LoopHelper
]() -> Expr
* {
15323 return AssertSuccess(
15324 CopyTransformer
.TransformExpr(LoopHelper
.NumIterations
));
15327 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
15328 ExprResult LValueConv
= DefaultLvalueConversion(MakeOuterRef());
15329 AddInitializerToDecl(InnerIVDecl
, LValueConv
.get(), /*DirectInit=*/false);
15330 StmtResult InnerInit
= new (Context
)
15331 DeclStmt(DeclGroupRef(InnerIVDecl
), OrigVarLocBegin
, OrigVarLocEnd
);
15332 if (!InnerInit
.isUsable())
15333 return StmtError();
15335 // Inner For cond-expression:
15337 // .unroll_inner.iv < .unrolled.iv + Factor &&
15338 // .unroll_inner.iv < NumIterations
15340 // This conjunction of two conditions allows ScalarEvolution to derive the
15341 // maximum trip count of the inner loop.
15342 ExprResult EndOfTile
= BuildBinOp(CurScope
, LoopHelper
.Cond
->getExprLoc(),
15343 BO_Add
, MakeOuterRef(), MakeFactorExpr());
15344 if (!EndOfTile
.isUsable())
15345 return StmtError();
15346 ExprResult InnerCond1
= BuildBinOp(CurScope
, LoopHelper
.Cond
->getExprLoc(),
15347 BO_LT
, MakeInnerRef(), EndOfTile
.get());
15348 if (!InnerCond1
.isUsable())
15349 return StmtError();
15350 ExprResult InnerCond2
=
15351 BuildBinOp(CurScope
, LoopHelper
.Cond
->getExprLoc(), BO_LT
, MakeInnerRef(),
15352 MakeNumIterations());
15353 if (!InnerCond2
.isUsable())
15354 return StmtError();
15355 ExprResult InnerCond
=
15356 BuildBinOp(CurScope
, LoopHelper
.Cond
->getExprLoc(), BO_LAnd
,
15357 InnerCond1
.get(), InnerCond2
.get());
15358 if (!InnerCond
.isUsable())
15359 return StmtError();
15361 // Inner For incr-statement: ++.unroll_inner.iv
15362 ExprResult InnerIncr
= BuildUnaryOp(CurScope
, LoopHelper
.Inc
->getExprLoc(),
15363 UO_PreInc
, MakeInnerRef());
15364 if (!InnerIncr
.isUsable())
15365 return StmtError();
15367 // Inner For statement.
15368 SmallVector
<Stmt
*> InnerBodyStmts
;
15369 InnerBodyStmts
.append(LoopHelper
.Updates
.begin(), LoopHelper
.Updates
.end());
15370 InnerBodyStmts
.push_back(Body
);
15371 CompoundStmt
*InnerBody
=
15372 CompoundStmt::Create(Context
, InnerBodyStmts
, FPOptionsOverride(),
15373 Body
->getBeginLoc(), Body
->getEndLoc());
15374 ForStmt
*InnerFor
= new (Context
)
15375 ForStmt(Context
, InnerInit
.get(), InnerCond
.get(), nullptr,
15376 InnerIncr
.get(), InnerBody
, LoopHelper
.Init
->getBeginLoc(),
15377 LoopHelper
.Init
->getBeginLoc(), LoopHelper
.Inc
->getEndLoc());
15379 // Unroll metadata for the inner loop.
15380 // This needs to take into account the remainder portion of the unrolled loop,
15381 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
15382 // supports multiple loop exits. Instead, unroll using a factor equivalent to
15383 // the maximum trip count, which will also generate a remainder loop. Just
15384 // `unroll(enable)` (which could have been useful if the user has not
15385 // specified a concrete factor; even though the outer loop cannot be
15386 // influenced anymore, would avoid more code bloat than necessary) will refuse
15387 // the loop because "Won't unroll; remainder loop could not be generated when
15388 // assuming runtime trip count". Even if it did work, it must not choose a
15389 // larger unroll factor than the maximum loop length, or it would always just
15390 // execute the remainder loop.
15391 LoopHintAttr
*UnrollHintAttr
=
15392 LoopHintAttr::CreateImplicit(Context
, LoopHintAttr::UnrollCount
,
15393 LoopHintAttr::Numeric
, MakeFactorExpr());
15394 AttributedStmt
*InnerUnrolled
=
15395 AttributedStmt::Create(Context
, StartLoc
, {UnrollHintAttr
}, InnerFor
);
15397 // Outer For init-statement: auto .unrolled.iv = 0
15398 AddInitializerToDecl(
15399 OuterIVDecl
, ActOnIntegerConstant(LoopHelper
.Init
->getExprLoc(), 0).get(),
15400 /*DirectInit=*/false);
15401 StmtResult OuterInit
= new (Context
)
15402 DeclStmt(DeclGroupRef(OuterIVDecl
), OrigVarLocBegin
, OrigVarLocEnd
);
15403 if (!OuterInit
.isUsable())
15404 return StmtError();
15406 // Outer For cond-expression: .unrolled.iv < NumIterations
15407 ExprResult OuterConde
=
15408 BuildBinOp(CurScope
, LoopHelper
.Cond
->getExprLoc(), BO_LT
, MakeOuterRef(),
15409 MakeNumIterations());
15410 if (!OuterConde
.isUsable())
15411 return StmtError();
15413 // Outer For incr-statement: .unrolled.iv += Factor
15414 ExprResult OuterIncr
=
15415 BuildBinOp(CurScope
, LoopHelper
.Inc
->getExprLoc(), BO_AddAssign
,
15416 MakeOuterRef(), MakeFactorExpr());
15417 if (!OuterIncr
.isUsable())
15418 return StmtError();
15420 // Outer For statement.
15421 ForStmt
*OuterFor
= new (Context
)
15422 ForStmt(Context
, OuterInit
.get(), OuterConde
.get(), nullptr,
15423 OuterIncr
.get(), InnerUnrolled
, LoopHelper
.Init
->getBeginLoc(),
15424 LoopHelper
.Init
->getBeginLoc(), LoopHelper
.Inc
->getEndLoc());
15426 return OMPUnrollDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
,
15427 NumGeneratedLoops
, OuterFor
,
15428 buildPreInits(Context
, PreInits
));
15431 OMPClause
*Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind
, Expr
*Expr
,
15432 SourceLocation StartLoc
,
15433 SourceLocation LParenLoc
,
15434 SourceLocation EndLoc
) {
15435 OMPClause
*Res
= nullptr;
15438 Res
= ActOnOpenMPFinalClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15440 case OMPC_num_threads
:
15441 Res
= ActOnOpenMPNumThreadsClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15444 Res
= ActOnOpenMPSafelenClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15447 Res
= ActOnOpenMPSimdlenClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15449 case OMPC_allocator
:
15450 Res
= ActOnOpenMPAllocatorClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15452 case OMPC_collapse
:
15453 Res
= ActOnOpenMPCollapseClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15456 Res
= ActOnOpenMPOrderedClause(StartLoc
, EndLoc
, LParenLoc
, Expr
);
15458 case OMPC_num_teams
:
15459 Res
= ActOnOpenMPNumTeamsClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15461 case OMPC_thread_limit
:
15462 Res
= ActOnOpenMPThreadLimitClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15464 case OMPC_priority
:
15465 Res
= ActOnOpenMPPriorityClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15468 Res
= ActOnOpenMPHintClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15471 Res
= ActOnOpenMPDepobjClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15474 Res
= ActOnOpenMPDetachClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15476 case OMPC_novariants
:
15477 Res
= ActOnOpenMPNovariantsClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15479 case OMPC_nocontext
:
15480 Res
= ActOnOpenMPNocontextClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15483 Res
= ActOnOpenMPFilterClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15486 Res
= ActOnOpenMPPartialClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15489 Res
= ActOnOpenMPMessageClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15492 Res
= ActOnOpenMPAlignClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15494 case OMPC_ompx_dyn_cgroup_mem
:
15495 Res
= ActOnOpenMPXDynCGroupMemClause(Expr
, StartLoc
, LParenLoc
, EndLoc
);
15497 case OMPC_grainsize
:
15498 case OMPC_num_tasks
:
15502 case OMPC_proc_bind
:
15503 case OMPC_schedule
:
15505 case OMPC_firstprivate
:
15506 case OMPC_lastprivate
:
15508 case OMPC_reduction
:
15509 case OMPC_task_reduction
:
15510 case OMPC_in_reduction
:
15514 case OMPC_copyprivate
:
15517 case OMPC_mergeable
:
15518 case OMPC_threadprivate
:
15520 case OMPC_allocate
:
15537 case OMPC_dist_schedule
:
15538 case OMPC_defaultmap
:
15543 case OMPC_use_device_ptr
:
15544 case OMPC_use_device_addr
:
15545 case OMPC_is_device_ptr
:
15546 case OMPC_unified_address
:
15547 case OMPC_unified_shared_memory
:
15548 case OMPC_reverse_offload
:
15549 case OMPC_dynamic_allocators
:
15550 case OMPC_atomic_default_mem_order
:
15551 case OMPC_device_type
:
15553 case OMPC_nontemporal
:
15556 case OMPC_severity
:
15558 case OMPC_inclusive
:
15559 case OMPC_exclusive
:
15560 case OMPC_uses_allocators
:
15561 case OMPC_affinity
:
15565 llvm_unreachable("Clause is not allowed.");
15570 // An OpenMP directive such as 'target parallel' has two captured regions:
15571 // for the 'target' and 'parallel' respectively. This function returns
15572 // the region in which to capture expressions associated with a clause.
15573 // A return value of OMPD_unknown signifies that the expression should not
15575 static OpenMPDirectiveKind
getOpenMPCaptureRegionForClause(
15576 OpenMPDirectiveKind DKind
, OpenMPClauseKind CKind
, unsigned OpenMPVersion
,
15577 OpenMPDirectiveKind NameModifier
= OMPD_unknown
) {
15578 OpenMPDirectiveKind CaptureRegion
= OMPD_unknown
;
15582 case OMPD_target_parallel_for_simd
:
15583 if (OpenMPVersion
>= 50 &&
15584 (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
)) {
15585 CaptureRegion
= OMPD_parallel
;
15589 case OMPD_target_parallel
:
15590 case OMPD_target_parallel_for
:
15591 case OMPD_target_parallel_loop
:
15592 // If this clause applies to the nested 'parallel' region, capture within
15593 // the 'target' region, otherwise do not capture.
15594 if (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_parallel
)
15595 CaptureRegion
= OMPD_target
;
15597 case OMPD_target_teams_distribute_parallel_for_simd
:
15598 if (OpenMPVersion
>= 50 &&
15599 (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
)) {
15600 CaptureRegion
= OMPD_parallel
;
15604 case OMPD_target_teams_loop
:
15605 case OMPD_target_teams_distribute_parallel_for
:
15606 // If this clause applies to the nested 'parallel' region, capture within
15607 // the 'teams' region, otherwise do not capture.
15608 if (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_parallel
)
15609 CaptureRegion
= OMPD_teams
;
15611 case OMPD_teams_distribute_parallel_for_simd
:
15612 if (OpenMPVersion
>= 50 &&
15613 (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
)) {
15614 CaptureRegion
= OMPD_parallel
;
15618 case OMPD_teams_distribute_parallel_for
:
15619 CaptureRegion
= OMPD_teams
;
15621 case OMPD_target_update
:
15622 case OMPD_target_enter_data
:
15623 case OMPD_target_exit_data
:
15624 CaptureRegion
= OMPD_task
;
15626 case OMPD_parallel_masked_taskloop
:
15627 if (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_taskloop
)
15628 CaptureRegion
= OMPD_parallel
;
15630 case OMPD_parallel_master_taskloop
:
15631 if (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_taskloop
)
15632 CaptureRegion
= OMPD_parallel
;
15634 case OMPD_parallel_masked_taskloop_simd
:
15635 if ((OpenMPVersion
<= 45 && NameModifier
== OMPD_unknown
) ||
15636 NameModifier
== OMPD_taskloop
) {
15637 CaptureRegion
= OMPD_parallel
;
15640 if (OpenMPVersion
<= 45)
15642 if (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
)
15643 CaptureRegion
= OMPD_taskloop
;
15645 case OMPD_parallel_master_taskloop_simd
:
15646 if ((OpenMPVersion
<= 45 && NameModifier
== OMPD_unknown
) ||
15647 NameModifier
== OMPD_taskloop
) {
15648 CaptureRegion
= OMPD_parallel
;
15651 if (OpenMPVersion
<= 45)
15653 if (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
)
15654 CaptureRegion
= OMPD_taskloop
;
15656 case OMPD_parallel_for_simd
:
15657 if (OpenMPVersion
<= 45)
15659 if (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
)
15660 CaptureRegion
= OMPD_parallel
;
15662 case OMPD_taskloop_simd
:
15663 case OMPD_master_taskloop_simd
:
15664 case OMPD_masked_taskloop_simd
:
15665 if (OpenMPVersion
<= 45)
15667 if (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
)
15668 CaptureRegion
= OMPD_taskloop
;
15670 case OMPD_distribute_parallel_for_simd
:
15671 if (OpenMPVersion
<= 45)
15673 if (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
)
15674 CaptureRegion
= OMPD_parallel
;
15676 case OMPD_target_simd
:
15677 if (OpenMPVersion
>= 50 &&
15678 (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
))
15679 CaptureRegion
= OMPD_target
;
15681 case OMPD_teams_distribute_simd
:
15682 case OMPD_target_teams_distribute_simd
:
15683 if (OpenMPVersion
>= 50 &&
15684 (NameModifier
== OMPD_unknown
|| NameModifier
== OMPD_simd
))
15685 CaptureRegion
= OMPD_teams
;
15688 case OMPD_parallel
:
15689 case OMPD_parallel_master
:
15690 case OMPD_parallel_masked
:
15691 case OMPD_parallel_sections
:
15692 case OMPD_parallel_for
:
15693 case OMPD_parallel_loop
:
15695 case OMPD_target_teams
:
15696 case OMPD_target_teams_distribute
:
15697 case OMPD_distribute_parallel_for
:
15699 case OMPD_taskloop
:
15700 case OMPD_master_taskloop
:
15701 case OMPD_masked_taskloop
:
15702 case OMPD_target_data
:
15704 case OMPD_for_simd
:
15705 case OMPD_distribute_simd
:
15706 // Do not capture if-clause expressions.
15708 case OMPD_threadprivate
:
15709 case OMPD_allocate
:
15710 case OMPD_taskyield
:
15713 case OMPD_taskwait
:
15714 case OMPD_cancellation_point
:
15718 case OMPD_declare_reduction
:
15719 case OMPD_declare_mapper
:
15720 case OMPD_declare_simd
:
15721 case OMPD_declare_variant
:
15722 case OMPD_begin_declare_variant
:
15723 case OMPD_end_declare_variant
:
15724 case OMPD_declare_target
:
15725 case OMPD_end_declare_target
:
15727 case OMPD_teams_loop
:
15732 case OMPD_sections
:
15737 case OMPD_critical
:
15738 case OMPD_taskgroup
:
15739 case OMPD_distribute
:
15742 case OMPD_teams_distribute
:
15743 case OMPD_requires
:
15744 case OMPD_metadirective
:
15745 llvm_unreachable("Unexpected OpenMP directive with if-clause");
15748 llvm_unreachable("Unknown OpenMP directive");
15751 case OMPC_num_threads
:
15753 case OMPD_target_parallel
:
15754 case OMPD_target_parallel_for
:
15755 case OMPD_target_parallel_for_simd
:
15756 case OMPD_target_parallel_loop
:
15757 CaptureRegion
= OMPD_target
;
15759 case OMPD_teams_distribute_parallel_for
:
15760 case OMPD_teams_distribute_parallel_for_simd
:
15761 case OMPD_target_teams_distribute_parallel_for
:
15762 case OMPD_target_teams_distribute_parallel_for_simd
:
15763 CaptureRegion
= OMPD_teams
;
15765 case OMPD_parallel
:
15766 case OMPD_parallel_master
:
15767 case OMPD_parallel_masked
:
15768 case OMPD_parallel_sections
:
15769 case OMPD_parallel_for
:
15770 case OMPD_parallel_for_simd
:
15771 case OMPD_parallel_loop
:
15772 case OMPD_distribute_parallel_for
:
15773 case OMPD_distribute_parallel_for_simd
:
15774 case OMPD_parallel_master_taskloop
:
15775 case OMPD_parallel_masked_taskloop
:
15776 case OMPD_parallel_master_taskloop_simd
:
15777 case OMPD_parallel_masked_taskloop_simd
:
15778 // Do not capture num_threads-clause expressions.
15780 case OMPD_target_data
:
15781 case OMPD_target_enter_data
:
15782 case OMPD_target_exit_data
:
15783 case OMPD_target_update
:
15785 case OMPD_target_simd
:
15786 case OMPD_target_teams
:
15787 case OMPD_target_teams_distribute
:
15788 case OMPD_target_teams_distribute_simd
:
15791 case OMPD_taskloop
:
15792 case OMPD_taskloop_simd
:
15793 case OMPD_master_taskloop
:
15794 case OMPD_masked_taskloop
:
15795 case OMPD_master_taskloop_simd
:
15796 case OMPD_masked_taskloop_simd
:
15797 case OMPD_threadprivate
:
15798 case OMPD_allocate
:
15799 case OMPD_taskyield
:
15802 case OMPD_taskwait
:
15803 case OMPD_cancellation_point
:
15807 case OMPD_declare_reduction
:
15808 case OMPD_declare_mapper
:
15809 case OMPD_declare_simd
:
15810 case OMPD_declare_variant
:
15811 case OMPD_begin_declare_variant
:
15812 case OMPD_end_declare_variant
:
15813 case OMPD_declare_target
:
15814 case OMPD_end_declare_target
:
15816 case OMPD_teams_loop
:
15817 case OMPD_target_teams_loop
:
15823 case OMPD_for_simd
:
15824 case OMPD_sections
:
15829 case OMPD_critical
:
15830 case OMPD_taskgroup
:
15831 case OMPD_distribute
:
15834 case OMPD_distribute_simd
:
15835 case OMPD_teams_distribute
:
15836 case OMPD_teams_distribute_simd
:
15837 case OMPD_requires
:
15838 case OMPD_metadirective
:
15839 llvm_unreachable("Unexpected OpenMP directive with num_threads-clause");
15842 llvm_unreachable("Unknown OpenMP directive");
15845 case OMPC_num_teams
:
15847 case OMPD_target_teams
:
15848 case OMPD_target_teams_distribute
:
15849 case OMPD_target_teams_distribute_simd
:
15850 case OMPD_target_teams_distribute_parallel_for
:
15851 case OMPD_target_teams_distribute_parallel_for_simd
:
15852 case OMPD_target_teams_loop
:
15853 CaptureRegion
= OMPD_target
;
15855 case OMPD_teams_distribute_parallel_for
:
15856 case OMPD_teams_distribute_parallel_for_simd
:
15858 case OMPD_teams_distribute
:
15859 case OMPD_teams_distribute_simd
:
15860 case OMPD_teams_loop
:
15861 // Do not capture num_teams-clause expressions.
15863 case OMPD_distribute_parallel_for
:
15864 case OMPD_distribute_parallel_for_simd
:
15866 case OMPD_taskloop
:
15867 case OMPD_taskloop_simd
:
15868 case OMPD_master_taskloop
:
15869 case OMPD_masked_taskloop
:
15870 case OMPD_master_taskloop_simd
:
15871 case OMPD_masked_taskloop_simd
:
15872 case OMPD_parallel_master_taskloop
:
15873 case OMPD_parallel_masked_taskloop
:
15874 case OMPD_parallel_master_taskloop_simd
:
15875 case OMPD_parallel_masked_taskloop_simd
:
15876 case OMPD_target_data
:
15877 case OMPD_target_enter_data
:
15878 case OMPD_target_exit_data
:
15879 case OMPD_target_update
:
15881 case OMPD_parallel
:
15882 case OMPD_parallel_master
:
15883 case OMPD_parallel_masked
:
15884 case OMPD_parallel_sections
:
15885 case OMPD_parallel_for
:
15886 case OMPD_parallel_for_simd
:
15887 case OMPD_parallel_loop
:
15889 case OMPD_target_simd
:
15890 case OMPD_target_parallel
:
15891 case OMPD_target_parallel_for
:
15892 case OMPD_target_parallel_for_simd
:
15893 case OMPD_target_parallel_loop
:
15894 case OMPD_threadprivate
:
15895 case OMPD_allocate
:
15896 case OMPD_taskyield
:
15899 case OMPD_taskwait
:
15900 case OMPD_cancellation_point
:
15904 case OMPD_declare_reduction
:
15905 case OMPD_declare_mapper
:
15906 case OMPD_declare_simd
:
15907 case OMPD_declare_variant
:
15908 case OMPD_begin_declare_variant
:
15909 case OMPD_end_declare_variant
:
15910 case OMPD_declare_target
:
15911 case OMPD_end_declare_target
:
15917 case OMPD_for_simd
:
15918 case OMPD_sections
:
15923 case OMPD_critical
:
15924 case OMPD_taskgroup
:
15925 case OMPD_distribute
:
15928 case OMPD_distribute_simd
:
15929 case OMPD_requires
:
15930 case OMPD_metadirective
:
15931 llvm_unreachable("Unexpected OpenMP directive with num_teams-clause");
15934 llvm_unreachable("Unknown OpenMP directive");
15937 case OMPC_thread_limit
:
15940 case OMPD_target_teams
:
15941 case OMPD_target_teams_distribute
:
15942 case OMPD_target_teams_distribute_simd
:
15943 case OMPD_target_teams_distribute_parallel_for
:
15944 case OMPD_target_teams_distribute_parallel_for_simd
:
15945 case OMPD_target_teams_loop
:
15946 case OMPD_target_simd
:
15947 case OMPD_target_parallel
:
15948 case OMPD_target_parallel_for
:
15949 case OMPD_target_parallel_for_simd
:
15950 case OMPD_target_parallel_loop
:
15951 CaptureRegion
= OMPD_target
;
15953 case OMPD_teams_distribute_parallel_for
:
15954 case OMPD_teams_distribute_parallel_for_simd
:
15956 case OMPD_teams_distribute
:
15957 case OMPD_teams_distribute_simd
:
15958 case OMPD_teams_loop
:
15959 // Do not capture thread_limit-clause expressions.
15961 case OMPD_distribute_parallel_for
:
15962 case OMPD_distribute_parallel_for_simd
:
15964 case OMPD_taskloop
:
15965 case OMPD_taskloop_simd
:
15966 case OMPD_master_taskloop
:
15967 case OMPD_masked_taskloop
:
15968 case OMPD_master_taskloop_simd
:
15969 case OMPD_masked_taskloop_simd
:
15970 case OMPD_parallel_master_taskloop
:
15971 case OMPD_parallel_masked_taskloop
:
15972 case OMPD_parallel_master_taskloop_simd
:
15973 case OMPD_parallel_masked_taskloop_simd
:
15974 case OMPD_target_data
:
15975 case OMPD_target_enter_data
:
15976 case OMPD_target_exit_data
:
15977 case OMPD_target_update
:
15979 case OMPD_parallel
:
15980 case OMPD_parallel_master
:
15981 case OMPD_parallel_masked
:
15982 case OMPD_parallel_sections
:
15983 case OMPD_parallel_for
:
15984 case OMPD_parallel_for_simd
:
15985 case OMPD_parallel_loop
:
15986 case OMPD_threadprivate
:
15987 case OMPD_allocate
:
15988 case OMPD_taskyield
:
15991 case OMPD_taskwait
:
15992 case OMPD_cancellation_point
:
15996 case OMPD_declare_reduction
:
15997 case OMPD_declare_mapper
:
15998 case OMPD_declare_simd
:
15999 case OMPD_declare_variant
:
16000 case OMPD_begin_declare_variant
:
16001 case OMPD_end_declare_variant
:
16002 case OMPD_declare_target
:
16003 case OMPD_end_declare_target
:
16009 case OMPD_for_simd
:
16010 case OMPD_sections
:
16015 case OMPD_critical
:
16016 case OMPD_taskgroup
:
16017 case OMPD_distribute
:
16020 case OMPD_distribute_simd
:
16021 case OMPD_requires
:
16022 case OMPD_metadirective
:
16023 llvm_unreachable("Unexpected OpenMP directive with thread_limit-clause");
16026 llvm_unreachable("Unknown OpenMP directive");
16029 case OMPC_schedule
:
16031 case OMPD_parallel_for
:
16032 case OMPD_parallel_for_simd
:
16033 case OMPD_distribute_parallel_for
:
16034 case OMPD_distribute_parallel_for_simd
:
16035 case OMPD_teams_distribute_parallel_for
:
16036 case OMPD_teams_distribute_parallel_for_simd
:
16037 case OMPD_target_parallel_for
:
16038 case OMPD_target_parallel_for_simd
:
16039 case OMPD_target_teams_distribute_parallel_for
:
16040 case OMPD_target_teams_distribute_parallel_for_simd
:
16041 CaptureRegion
= OMPD_parallel
;
16044 case OMPD_for_simd
:
16045 // Do not capture schedule-clause expressions.
16048 case OMPD_taskloop
:
16049 case OMPD_taskloop_simd
:
16050 case OMPD_master_taskloop
:
16051 case OMPD_masked_taskloop
:
16052 case OMPD_master_taskloop_simd
:
16053 case OMPD_masked_taskloop_simd
:
16054 case OMPD_parallel_master_taskloop
:
16055 case OMPD_parallel_masked_taskloop
:
16056 case OMPD_parallel_master_taskloop_simd
:
16057 case OMPD_parallel_masked_taskloop_simd
:
16058 case OMPD_target_data
:
16059 case OMPD_target_enter_data
:
16060 case OMPD_target_exit_data
:
16061 case OMPD_target_update
:
16063 case OMPD_teams_distribute
:
16064 case OMPD_teams_distribute_simd
:
16065 case OMPD_target_teams_distribute
:
16066 case OMPD_target_teams_distribute_simd
:
16068 case OMPD_target_simd
:
16069 case OMPD_target_parallel
:
16071 case OMPD_parallel
:
16072 case OMPD_parallel_master
:
16073 case OMPD_parallel_masked
:
16074 case OMPD_parallel_sections
:
16075 case OMPD_threadprivate
:
16076 case OMPD_allocate
:
16077 case OMPD_taskyield
:
16080 case OMPD_taskwait
:
16081 case OMPD_cancellation_point
:
16085 case OMPD_declare_reduction
:
16086 case OMPD_declare_mapper
:
16087 case OMPD_declare_simd
:
16088 case OMPD_declare_variant
:
16089 case OMPD_begin_declare_variant
:
16090 case OMPD_end_declare_variant
:
16091 case OMPD_declare_target
:
16092 case OMPD_end_declare_target
:
16094 case OMPD_teams_loop
:
16095 case OMPD_target_teams_loop
:
16096 case OMPD_parallel_loop
:
16097 case OMPD_target_parallel_loop
:
16101 case OMPD_sections
:
16106 case OMPD_critical
:
16107 case OMPD_taskgroup
:
16108 case OMPD_distribute
:
16111 case OMPD_distribute_simd
:
16112 case OMPD_target_teams
:
16113 case OMPD_requires
:
16114 case OMPD_metadirective
:
16115 llvm_unreachable("Unexpected OpenMP directive with schedule clause");
16118 llvm_unreachable("Unknown OpenMP directive");
16121 case OMPC_dist_schedule
:
16123 case OMPD_teams_distribute_parallel_for
:
16124 case OMPD_teams_distribute_parallel_for_simd
:
16125 case OMPD_teams_distribute
:
16126 case OMPD_teams_distribute_simd
:
16127 case OMPD_target_teams_distribute_parallel_for
:
16128 case OMPD_target_teams_distribute_parallel_for_simd
:
16129 case OMPD_target_teams_distribute
:
16130 case OMPD_target_teams_distribute_simd
:
16131 CaptureRegion
= OMPD_teams
;
16133 case OMPD_distribute_parallel_for
:
16134 case OMPD_distribute_parallel_for_simd
:
16135 case OMPD_distribute
:
16136 case OMPD_distribute_simd
:
16137 // Do not capture dist_schedule-clause expressions.
16139 case OMPD_parallel_for
:
16140 case OMPD_parallel_for_simd
:
16141 case OMPD_target_parallel_for_simd
:
16142 case OMPD_target_parallel_for
:
16144 case OMPD_taskloop
:
16145 case OMPD_taskloop_simd
:
16146 case OMPD_master_taskloop
:
16147 case OMPD_masked_taskloop
:
16148 case OMPD_master_taskloop_simd
:
16149 case OMPD_masked_taskloop_simd
:
16150 case OMPD_parallel_master_taskloop
:
16151 case OMPD_parallel_masked_taskloop
:
16152 case OMPD_parallel_master_taskloop_simd
:
16153 case OMPD_parallel_masked_taskloop_simd
:
16154 case OMPD_target_data
:
16155 case OMPD_target_enter_data
:
16156 case OMPD_target_exit_data
:
16157 case OMPD_target_update
:
16160 case OMPD_target_simd
:
16161 case OMPD_target_parallel
:
16163 case OMPD_parallel
:
16164 case OMPD_parallel_master
:
16165 case OMPD_parallel_masked
:
16166 case OMPD_parallel_sections
:
16167 case OMPD_threadprivate
:
16168 case OMPD_allocate
:
16169 case OMPD_taskyield
:
16172 case OMPD_taskwait
:
16173 case OMPD_cancellation_point
:
16177 case OMPD_declare_reduction
:
16178 case OMPD_declare_mapper
:
16179 case OMPD_declare_simd
:
16180 case OMPD_declare_variant
:
16181 case OMPD_begin_declare_variant
:
16182 case OMPD_end_declare_variant
:
16183 case OMPD_declare_target
:
16184 case OMPD_end_declare_target
:
16186 case OMPD_teams_loop
:
16187 case OMPD_target_teams_loop
:
16188 case OMPD_parallel_loop
:
16189 case OMPD_target_parallel_loop
:
16194 case OMPD_for_simd
:
16195 case OMPD_sections
:
16200 case OMPD_critical
:
16201 case OMPD_taskgroup
:
16204 case OMPD_target_teams
:
16205 case OMPD_requires
:
16206 case OMPD_metadirective
:
16207 llvm_unreachable("Unexpected OpenMP directive with dist_schedule clause");
16210 llvm_unreachable("Unknown OpenMP directive");
16213 case OMPC_ompx_dyn_cgroup_mem
:
16216 case OMPD_target_simd
:
16217 case OMPD_target_teams
:
16218 case OMPD_target_parallel
:
16219 case OMPD_target_teams_distribute
:
16220 case OMPD_target_teams_distribute_simd
:
16221 case OMPD_target_parallel_for
:
16222 case OMPD_target_parallel_for_simd
:
16223 case OMPD_target_parallel_loop
:
16224 case OMPD_target_teams_distribute_parallel_for
:
16225 case OMPD_target_teams_distribute_parallel_for_simd
:
16226 case OMPD_target_teams_loop
:
16227 CaptureRegion
= OMPD_target
;
16230 llvm_unreachable("Unknown OpenMP directive");
16235 case OMPD_target_update
:
16236 case OMPD_target_enter_data
:
16237 case OMPD_target_exit_data
:
16239 case OMPD_target_simd
:
16240 case OMPD_target_teams
:
16241 case OMPD_target_parallel
:
16242 case OMPD_target_teams_distribute
:
16243 case OMPD_target_teams_distribute_simd
:
16244 case OMPD_target_parallel_for
:
16245 case OMPD_target_parallel_for_simd
:
16246 case OMPD_target_parallel_loop
:
16247 case OMPD_target_teams_distribute_parallel_for
:
16248 case OMPD_target_teams_distribute_parallel_for_simd
:
16249 case OMPD_target_teams_loop
:
16250 case OMPD_dispatch
:
16251 CaptureRegion
= OMPD_task
;
16253 case OMPD_target_data
:
16255 // Do not capture device-clause expressions.
16257 case OMPD_teams_distribute_parallel_for
:
16258 case OMPD_teams_distribute_parallel_for_simd
:
16260 case OMPD_teams_distribute
:
16261 case OMPD_teams_distribute_simd
:
16262 case OMPD_distribute_parallel_for
:
16263 case OMPD_distribute_parallel_for_simd
:
16265 case OMPD_taskloop
:
16266 case OMPD_taskloop_simd
:
16267 case OMPD_master_taskloop
:
16268 case OMPD_masked_taskloop
:
16269 case OMPD_master_taskloop_simd
:
16270 case OMPD_masked_taskloop_simd
:
16271 case OMPD_parallel_master_taskloop
:
16272 case OMPD_parallel_masked_taskloop
:
16273 case OMPD_parallel_master_taskloop_simd
:
16274 case OMPD_parallel_masked_taskloop_simd
:
16276 case OMPD_parallel
:
16277 case OMPD_parallel_master
:
16278 case OMPD_parallel_masked
:
16279 case OMPD_parallel_sections
:
16280 case OMPD_parallel_for
:
16281 case OMPD_parallel_for_simd
:
16282 case OMPD_threadprivate
:
16283 case OMPD_allocate
:
16284 case OMPD_taskyield
:
16287 case OMPD_taskwait
:
16288 case OMPD_cancellation_point
:
16292 case OMPD_declare_reduction
:
16293 case OMPD_declare_mapper
:
16294 case OMPD_declare_simd
:
16295 case OMPD_declare_variant
:
16296 case OMPD_begin_declare_variant
:
16297 case OMPD_end_declare_variant
:
16298 case OMPD_declare_target
:
16299 case OMPD_end_declare_target
:
16301 case OMPD_teams_loop
:
16302 case OMPD_parallel_loop
:
16307 case OMPD_for_simd
:
16308 case OMPD_sections
:
16313 case OMPD_critical
:
16314 case OMPD_taskgroup
:
16315 case OMPD_distribute
:
16318 case OMPD_distribute_simd
:
16319 case OMPD_requires
:
16320 case OMPD_metadirective
:
16321 llvm_unreachable("Unexpected OpenMP directive with device-clause");
16324 llvm_unreachable("Unknown OpenMP directive");
16327 case OMPC_grainsize
:
16328 case OMPC_num_tasks
:
16330 case OMPC_priority
:
16333 case OMPD_taskloop
:
16334 case OMPD_taskloop_simd
:
16335 case OMPD_master_taskloop
:
16336 case OMPD_masked_taskloop
:
16337 case OMPD_master_taskloop_simd
:
16338 case OMPD_masked_taskloop_simd
:
16340 case OMPD_parallel_masked_taskloop
:
16341 case OMPD_parallel_masked_taskloop_simd
:
16342 case OMPD_parallel_master_taskloop
:
16343 case OMPD_parallel_master_taskloop_simd
:
16344 CaptureRegion
= OMPD_parallel
;
16346 case OMPD_target_update
:
16347 case OMPD_target_enter_data
:
16348 case OMPD_target_exit_data
:
16350 case OMPD_target_simd
:
16351 case OMPD_target_teams
:
16352 case OMPD_target_parallel
:
16353 case OMPD_target_teams_distribute
:
16354 case OMPD_target_teams_distribute_simd
:
16355 case OMPD_target_parallel_for
:
16356 case OMPD_target_parallel_for_simd
:
16357 case OMPD_target_teams_distribute_parallel_for
:
16358 case OMPD_target_teams_distribute_parallel_for_simd
:
16359 case OMPD_target_data
:
16360 case OMPD_teams_distribute_parallel_for
:
16361 case OMPD_teams_distribute_parallel_for_simd
:
16363 case OMPD_teams_distribute
:
16364 case OMPD_teams_distribute_simd
:
16365 case OMPD_distribute_parallel_for
:
16366 case OMPD_distribute_parallel_for_simd
:
16368 case OMPD_parallel
:
16369 case OMPD_parallel_master
:
16370 case OMPD_parallel_masked
:
16371 case OMPD_parallel_sections
:
16372 case OMPD_parallel_for
:
16373 case OMPD_parallel_for_simd
:
16374 case OMPD_threadprivate
:
16375 case OMPD_allocate
:
16376 case OMPD_taskyield
:
16379 case OMPD_taskwait
:
16380 case OMPD_cancellation_point
:
16384 case OMPD_declare_reduction
:
16385 case OMPD_declare_mapper
:
16386 case OMPD_declare_simd
:
16387 case OMPD_declare_variant
:
16388 case OMPD_begin_declare_variant
:
16389 case OMPD_end_declare_variant
:
16390 case OMPD_declare_target
:
16391 case OMPD_end_declare_target
:
16393 case OMPD_teams_loop
:
16394 case OMPD_target_teams_loop
:
16395 case OMPD_parallel_loop
:
16396 case OMPD_target_parallel_loop
:
16401 case OMPD_for_simd
:
16402 case OMPD_sections
:
16407 case OMPD_critical
:
16408 case OMPD_taskgroup
:
16409 case OMPD_distribute
:
16412 case OMPD_distribute_simd
:
16413 case OMPD_requires
:
16414 case OMPD_metadirective
:
16415 llvm_unreachable("Unexpected OpenMP directive with grainsize-clause");
16418 llvm_unreachable("Unknown OpenMP directive");
16421 case OMPC_novariants
:
16422 case OMPC_nocontext
:
16424 case OMPD_dispatch
:
16425 CaptureRegion
= OMPD_task
;
16428 llvm_unreachable("Unexpected OpenMP directive");
16432 // Do not capture filter-clause expressions.
16435 if (DKind
== OMPD_metadirective
) {
16436 CaptureRegion
= OMPD_metadirective
;
16437 } else if (DKind
== OMPD_unknown
) {
16438 llvm_unreachable("Unknown OpenMP directive");
16440 llvm_unreachable("Unexpected OpenMP directive with when clause");
16443 case OMPC_firstprivate
:
16444 case OMPC_lastprivate
:
16445 case OMPC_reduction
:
16446 case OMPC_task_reduction
:
16447 case OMPC_in_reduction
:
16450 case OMPC_proc_bind
:
16454 case OMPC_allocator
:
16455 case OMPC_collapse
:
16460 case OMPC_copyprivate
:
16464 case OMPC_mergeable
:
16465 case OMPC_threadprivate
:
16466 case OMPC_allocate
:
16485 case OMPC_defaultmap
:
16490 case OMPC_use_device_ptr
:
16491 case OMPC_use_device_addr
:
16492 case OMPC_is_device_ptr
:
16493 case OMPC_unified_address
:
16494 case OMPC_unified_shared_memory
:
16495 case OMPC_reverse_offload
:
16496 case OMPC_dynamic_allocators
:
16497 case OMPC_atomic_default_mem_order
:
16498 case OMPC_device_type
:
16500 case OMPC_nontemporal
:
16503 case OMPC_severity
:
16507 case OMPC_inclusive
:
16508 case OMPC_exclusive
:
16509 case OMPC_uses_allocators
:
16510 case OMPC_affinity
:
16513 llvm_unreachable("Unexpected OpenMP clause.");
16515 return CaptureRegion
;
16518 OMPClause
*Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier
,
16519 Expr
*Condition
, SourceLocation StartLoc
,
16520 SourceLocation LParenLoc
,
16521 SourceLocation NameModifierLoc
,
16522 SourceLocation ColonLoc
,
16523 SourceLocation EndLoc
) {
16524 Expr
*ValExpr
= Condition
;
16525 Stmt
*HelperValStmt
= nullptr;
16526 OpenMPDirectiveKind CaptureRegion
= OMPD_unknown
;
16527 if (!Condition
->isValueDependent() && !Condition
->isTypeDependent() &&
16528 !Condition
->isInstantiationDependent() &&
16529 !Condition
->containsUnexpandedParameterPack()) {
16530 ExprResult Val
= CheckBooleanCondition(StartLoc
, Condition
);
16531 if (Val
.isInvalid())
16534 ValExpr
= Val
.get();
16536 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
16537 CaptureRegion
= getOpenMPCaptureRegionForClause(
16538 DKind
, OMPC_if
, LangOpts
.OpenMP
, NameModifier
);
16539 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
16540 ValExpr
= MakeFullExpr(ValExpr
).get();
16541 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
16542 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
16543 HelperValStmt
= buildPreInits(Context
, Captures
);
16547 return new (Context
)
16548 OMPIfClause(NameModifier
, ValExpr
, HelperValStmt
, CaptureRegion
, StartLoc
,
16549 LParenLoc
, NameModifierLoc
, ColonLoc
, EndLoc
);
16552 OMPClause
*Sema::ActOnOpenMPFinalClause(Expr
*Condition
,
16553 SourceLocation StartLoc
,
16554 SourceLocation LParenLoc
,
16555 SourceLocation EndLoc
) {
16556 Expr
*ValExpr
= Condition
;
16557 Stmt
*HelperValStmt
= nullptr;
16558 OpenMPDirectiveKind CaptureRegion
= OMPD_unknown
;
16559 if (!Condition
->isValueDependent() && !Condition
->isTypeDependent() &&
16560 !Condition
->isInstantiationDependent() &&
16561 !Condition
->containsUnexpandedParameterPack()) {
16562 ExprResult Val
= CheckBooleanCondition(StartLoc
, Condition
);
16563 if (Val
.isInvalid())
16566 ValExpr
= MakeFullExpr(Val
.get()).get();
16568 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
16570 getOpenMPCaptureRegionForClause(DKind
, OMPC_final
, LangOpts
.OpenMP
);
16571 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
16572 ValExpr
= MakeFullExpr(ValExpr
).get();
16573 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
16574 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
16575 HelperValStmt
= buildPreInits(Context
, Captures
);
16579 return new (Context
) OMPFinalClause(ValExpr
, HelperValStmt
, CaptureRegion
,
16580 StartLoc
, LParenLoc
, EndLoc
);
16583 ExprResult
Sema::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc
,
16586 return ExprError();
16588 class IntConvertDiagnoser
: public ICEConvertDiagnoser
{
16590 IntConvertDiagnoser()
16591 : ICEConvertDiagnoser(/*AllowScopedEnumerations*/ false, false, true) {}
16592 SemaDiagnosticBuilder
diagnoseNotInt(Sema
&S
, SourceLocation Loc
,
16593 QualType T
) override
{
16594 return S
.Diag(Loc
, diag::err_omp_not_integral
) << T
;
16596 SemaDiagnosticBuilder
diagnoseIncomplete(Sema
&S
, SourceLocation Loc
,
16597 QualType T
) override
{
16598 return S
.Diag(Loc
, diag::err_omp_incomplete_type
) << T
;
16600 SemaDiagnosticBuilder
diagnoseExplicitConv(Sema
&S
, SourceLocation Loc
,
16602 QualType ConvTy
) override
{
16603 return S
.Diag(Loc
, diag::err_omp_explicit_conversion
) << T
<< ConvTy
;
16605 SemaDiagnosticBuilder
noteExplicitConv(Sema
&S
, CXXConversionDecl
*Conv
,
16606 QualType ConvTy
) override
{
16607 return S
.Diag(Conv
->getLocation(), diag::note_omp_conversion_here
)
16608 << ConvTy
->isEnumeralType() << ConvTy
;
16610 SemaDiagnosticBuilder
diagnoseAmbiguous(Sema
&S
, SourceLocation Loc
,
16611 QualType T
) override
{
16612 return S
.Diag(Loc
, diag::err_omp_ambiguous_conversion
) << T
;
16614 SemaDiagnosticBuilder
noteAmbiguous(Sema
&S
, CXXConversionDecl
*Conv
,
16615 QualType ConvTy
) override
{
16616 return S
.Diag(Conv
->getLocation(), diag::note_omp_conversion_here
)
16617 << ConvTy
->isEnumeralType() << ConvTy
;
16619 SemaDiagnosticBuilder
diagnoseConversion(Sema
&, SourceLocation
, QualType
,
16620 QualType
) override
{
16621 llvm_unreachable("conversion functions are permitted");
16623 } ConvertDiagnoser
;
16624 return PerformContextualImplicitConversion(Loc
, Op
, ConvertDiagnoser
);
16628 isNonNegativeIntegerValue(Expr
*&ValExpr
, Sema
&SemaRef
, OpenMPClauseKind CKind
,
16629 bool StrictlyPositive
, bool BuildCapture
= false,
16630 OpenMPDirectiveKind DKind
= OMPD_unknown
,
16631 OpenMPDirectiveKind
*CaptureRegion
= nullptr,
16632 Stmt
**HelperValStmt
= nullptr) {
16633 if (!ValExpr
->isTypeDependent() && !ValExpr
->isValueDependent() &&
16634 !ValExpr
->isInstantiationDependent()) {
16635 SourceLocation Loc
= ValExpr
->getExprLoc();
16637 SemaRef
.PerformOpenMPImplicitIntegerConversion(Loc
, ValExpr
);
16638 if (Value
.isInvalid())
16641 ValExpr
= Value
.get();
16642 // The expression must evaluate to a non-negative integer value.
16643 if (std::optional
<llvm::APSInt
> Result
=
16644 ValExpr
->getIntegerConstantExpr(SemaRef
.Context
)) {
16645 if (Result
->isSigned() &&
16646 !((!StrictlyPositive
&& Result
->isNonNegative()) ||
16647 (StrictlyPositive
&& Result
->isStrictlyPositive()))) {
16648 SemaRef
.Diag(Loc
, diag::err_omp_negative_expression_in_clause
)
16649 << getOpenMPClauseName(CKind
) << (StrictlyPositive
? 1 : 0)
16650 << ValExpr
->getSourceRange();
16657 getOpenMPCaptureRegionForClause(DKind
, CKind
, SemaRef
.LangOpts
.OpenMP
);
16658 if (*CaptureRegion
!= OMPD_unknown
&&
16659 !SemaRef
.CurContext
->isDependentContext()) {
16660 ValExpr
= SemaRef
.MakeFullExpr(ValExpr
).get();
16661 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
16662 ValExpr
= tryBuildCapture(SemaRef
, ValExpr
, Captures
).get();
16663 *HelperValStmt
= buildPreInits(SemaRef
.Context
, Captures
);
16669 OMPClause
*Sema::ActOnOpenMPNumThreadsClause(Expr
*NumThreads
,
16670 SourceLocation StartLoc
,
16671 SourceLocation LParenLoc
,
16672 SourceLocation EndLoc
) {
16673 Expr
*ValExpr
= NumThreads
;
16674 Stmt
*HelperValStmt
= nullptr;
16676 // OpenMP [2.5, Restrictions]
16677 // The num_threads expression must evaluate to a positive integer value.
16678 if (!isNonNegativeIntegerValue(ValExpr
, *this, OMPC_num_threads
,
16679 /*StrictlyPositive=*/true))
16682 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
16683 OpenMPDirectiveKind CaptureRegion
=
16684 getOpenMPCaptureRegionForClause(DKind
, OMPC_num_threads
, LangOpts
.OpenMP
);
16685 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
16686 ValExpr
= MakeFullExpr(ValExpr
).get();
16687 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
16688 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
16689 HelperValStmt
= buildPreInits(Context
, Captures
);
16692 return new (Context
) OMPNumThreadsClause(
16693 ValExpr
, HelperValStmt
, CaptureRegion
, StartLoc
, LParenLoc
, EndLoc
);
16696 ExprResult
Sema::VerifyPositiveIntegerConstantInClause(Expr
*E
,
16697 OpenMPClauseKind CKind
,
16698 bool StrictlyPositive
,
16699 bool SuppressExprDiags
) {
16701 return ExprError();
16702 if (E
->isValueDependent() || E
->isTypeDependent() ||
16703 E
->isInstantiationDependent() || E
->containsUnexpandedParameterPack())
16706 llvm::APSInt Result
;
16708 if (SuppressExprDiags
) {
16709 // Use a custom diagnoser that suppresses 'note' diagnostics about the
16711 struct SuppressedDiagnoser
: public Sema::VerifyICEDiagnoser
{
16712 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
16713 Sema::SemaDiagnosticBuilder
diagnoseNotICE(Sema
&S
,
16714 SourceLocation Loc
) override
{
16715 llvm_unreachable("Diagnostic suppressed");
16718 ICE
= VerifyIntegerConstantExpression(E
, &Result
, Diagnoser
, AllowFold
);
16720 ICE
= VerifyIntegerConstantExpression(E
, &Result
, /*FIXME*/ AllowFold
);
16722 if (ICE
.isInvalid())
16723 return ExprError();
16725 if ((StrictlyPositive
&& !Result
.isStrictlyPositive()) ||
16726 (!StrictlyPositive
&& !Result
.isNonNegative())) {
16727 Diag(E
->getExprLoc(), diag::err_omp_negative_expression_in_clause
)
16728 << getOpenMPClauseName(CKind
) << (StrictlyPositive
? 1 : 0)
16729 << E
->getSourceRange();
16730 return ExprError();
16732 if ((CKind
== OMPC_aligned
|| CKind
== OMPC_align
) && !Result
.isPowerOf2()) {
16733 Diag(E
->getExprLoc(), diag::warn_omp_alignment_not_power_of_two
)
16734 << E
->getSourceRange();
16735 return ExprError();
16737 if (CKind
== OMPC_collapse
&& DSAStack
->getAssociatedLoops() == 1)
16738 DSAStack
->setAssociatedLoops(Result
.getExtValue());
16739 else if (CKind
== OMPC_ordered
)
16740 DSAStack
->setAssociatedLoops(Result
.getExtValue());
16744 OMPClause
*Sema::ActOnOpenMPSafelenClause(Expr
*Len
, SourceLocation StartLoc
,
16745 SourceLocation LParenLoc
,
16746 SourceLocation EndLoc
) {
16747 // OpenMP [2.8.1, simd construct, Description]
16748 // The parameter of the safelen clause must be a constant
16749 // positive integer expression.
16750 ExprResult Safelen
= VerifyPositiveIntegerConstantInClause(Len
, OMPC_safelen
);
16751 if (Safelen
.isInvalid())
16753 return new (Context
)
16754 OMPSafelenClause(Safelen
.get(), StartLoc
, LParenLoc
, EndLoc
);
16757 OMPClause
*Sema::ActOnOpenMPSimdlenClause(Expr
*Len
, SourceLocation StartLoc
,
16758 SourceLocation LParenLoc
,
16759 SourceLocation EndLoc
) {
16760 // OpenMP [2.8.1, simd construct, Description]
16761 // The parameter of the simdlen clause must be a constant
16762 // positive integer expression.
16763 ExprResult Simdlen
= VerifyPositiveIntegerConstantInClause(Len
, OMPC_simdlen
);
16764 if (Simdlen
.isInvalid())
16766 return new (Context
)
16767 OMPSimdlenClause(Simdlen
.get(), StartLoc
, LParenLoc
, EndLoc
);
16770 /// Tries to find omp_allocator_handle_t type.
16771 static bool findOMPAllocatorHandleT(Sema
&S
, SourceLocation Loc
,
16772 DSAStackTy
*Stack
) {
16773 if (!Stack
->getOMPAllocatorHandleT().isNull())
16776 // Set the allocator handle type.
16777 IdentifierInfo
*II
= &S
.PP
.getIdentifierTable().get("omp_allocator_handle_t");
16778 ParsedType PT
= S
.getTypeName(*II
, Loc
, S
.getCurScope());
16779 if (!PT
.getAsOpaquePtr() || PT
.get().isNull()) {
16780 S
.Diag(Loc
, diag::err_omp_implied_type_not_found
)
16781 << "omp_allocator_handle_t";
16784 QualType AllocatorHandleEnumTy
= PT
.get();
16785 AllocatorHandleEnumTy
.addConst();
16786 Stack
->setOMPAllocatorHandleT(AllocatorHandleEnumTy
);
16788 // Fill the predefined allocator map.
16789 bool ErrorFound
= false;
16790 for (int I
= 0; I
< OMPAllocateDeclAttr::OMPUserDefinedMemAlloc
; ++I
) {
16791 auto AllocatorKind
= static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I
);
16792 StringRef Allocator
=
16793 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind
);
16794 DeclarationName AllocatorName
= &S
.getASTContext().Idents
.get(Allocator
);
16795 auto *VD
= dyn_cast_or_null
<ValueDecl
>(
16796 S
.LookupSingleName(S
.TUScope
, AllocatorName
, Loc
, Sema::LookupAnyName
));
16801 QualType AllocatorType
=
16802 VD
->getType().getNonLValueExprType(S
.getASTContext());
16803 ExprResult Res
= S
.BuildDeclRefExpr(VD
, AllocatorType
, VK_LValue
, Loc
);
16804 if (!Res
.isUsable()) {
16808 Res
= S
.PerformImplicitConversion(Res
.get(), AllocatorHandleEnumTy
,
16809 Sema::AA_Initializing
,
16810 /* AllowExplicit */ true);
16811 if (!Res
.isUsable()) {
16815 Stack
->setAllocator(AllocatorKind
, Res
.get());
16818 S
.Diag(Loc
, diag::err_omp_implied_type_not_found
)
16819 << "omp_allocator_handle_t";
16826 OMPClause
*Sema::ActOnOpenMPAllocatorClause(Expr
*A
, SourceLocation StartLoc
,
16827 SourceLocation LParenLoc
,
16828 SourceLocation EndLoc
) {
16829 // OpenMP [2.11.3, allocate Directive, Description]
16830 // allocator is an expression of omp_allocator_handle_t type.
16831 if (!findOMPAllocatorHandleT(*this, A
->getExprLoc(), DSAStack
))
16834 ExprResult Allocator
= DefaultLvalueConversion(A
);
16835 if (Allocator
.isInvalid())
16837 Allocator
= PerformImplicitConversion(Allocator
.get(),
16838 DSAStack
->getOMPAllocatorHandleT(),
16839 Sema::AA_Initializing
,
16840 /*AllowExplicit=*/true);
16841 if (Allocator
.isInvalid())
16843 return new (Context
)
16844 OMPAllocatorClause(Allocator
.get(), StartLoc
, LParenLoc
, EndLoc
);
16847 OMPClause
*Sema::ActOnOpenMPCollapseClause(Expr
*NumForLoops
,
16848 SourceLocation StartLoc
,
16849 SourceLocation LParenLoc
,
16850 SourceLocation EndLoc
) {
16851 // OpenMP [2.7.1, loop construct, Description]
16852 // OpenMP [2.8.1, simd construct, Description]
16853 // OpenMP [2.9.6, distribute construct, Description]
16854 // The parameter of the collapse clause must be a constant
16855 // positive integer expression.
16856 ExprResult NumForLoopsResult
=
16857 VerifyPositiveIntegerConstantInClause(NumForLoops
, OMPC_collapse
);
16858 if (NumForLoopsResult
.isInvalid())
16860 return new (Context
)
16861 OMPCollapseClause(NumForLoopsResult
.get(), StartLoc
, LParenLoc
, EndLoc
);
16864 OMPClause
*Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc
,
16865 SourceLocation EndLoc
,
16866 SourceLocation LParenLoc
,
16867 Expr
*NumForLoops
) {
16868 // OpenMP [2.7.1, loop construct, Description]
16869 // OpenMP [2.8.1, simd construct, Description]
16870 // OpenMP [2.9.6, distribute construct, Description]
16871 // The parameter of the ordered clause must be a constant
16872 // positive integer expression if any.
16873 if (NumForLoops
&& LParenLoc
.isValid()) {
16874 ExprResult NumForLoopsResult
=
16875 VerifyPositiveIntegerConstantInClause(NumForLoops
, OMPC_ordered
);
16876 if (NumForLoopsResult
.isInvalid())
16878 NumForLoops
= NumForLoopsResult
.get();
16880 NumForLoops
= nullptr;
16882 auto *Clause
= OMPOrderedClause::Create(
16883 Context
, NumForLoops
, NumForLoops
? DSAStack
->getAssociatedLoops() : 0,
16884 StartLoc
, LParenLoc
, EndLoc
);
16885 DSAStack
->setOrderedRegion(/*IsOrdered=*/true, NumForLoops
, Clause
);
16889 OMPClause
*Sema::ActOnOpenMPSimpleClause(
16890 OpenMPClauseKind Kind
, unsigned Argument
, SourceLocation ArgumentLoc
,
16891 SourceLocation StartLoc
, SourceLocation LParenLoc
, SourceLocation EndLoc
) {
16892 OMPClause
*Res
= nullptr;
16895 Res
= ActOnOpenMPDefaultClause(static_cast<DefaultKind
>(Argument
),
16896 ArgumentLoc
, StartLoc
, LParenLoc
, EndLoc
);
16898 case OMPC_proc_bind
:
16899 Res
= ActOnOpenMPProcBindClause(static_cast<ProcBindKind
>(Argument
),
16900 ArgumentLoc
, StartLoc
, LParenLoc
, EndLoc
);
16902 case OMPC_atomic_default_mem_order
:
16903 Res
= ActOnOpenMPAtomicDefaultMemOrderClause(
16904 static_cast<OpenMPAtomicDefaultMemOrderClauseKind
>(Argument
),
16905 ArgumentLoc
, StartLoc
, LParenLoc
, EndLoc
);
16908 Res
= ActOnOpenMPFailClause(
16909 static_cast<OpenMPClauseKind
>(Argument
),
16910 ArgumentLoc
, StartLoc
, LParenLoc
, EndLoc
);
16913 Res
= ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind
>(Argument
),
16914 ArgumentLoc
, StartLoc
, LParenLoc
, EndLoc
);
16917 Res
= ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind
>(Argument
),
16918 ArgumentLoc
, StartLoc
, LParenLoc
, EndLoc
);
16921 Res
= ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind
>(Argument
),
16922 ArgumentLoc
, StartLoc
, LParenLoc
, EndLoc
);
16924 case OMPC_severity
:
16925 Res
= ActOnOpenMPSeverityClause(
16926 static_cast<OpenMPSeverityClauseKind
>(Argument
), ArgumentLoc
, StartLoc
,
16927 LParenLoc
, EndLoc
);
16931 case OMPC_num_threads
:
16935 case OMPC_allocator
:
16936 case OMPC_collapse
:
16937 case OMPC_schedule
:
16939 case OMPC_firstprivate
:
16940 case OMPC_lastprivate
:
16942 case OMPC_reduction
:
16943 case OMPC_task_reduction
:
16944 case OMPC_in_reduction
:
16948 case OMPC_copyprivate
:
16952 case OMPC_mergeable
:
16953 case OMPC_threadprivate
:
16954 case OMPC_allocate
:
16971 case OMPC_num_teams
:
16972 case OMPC_thread_limit
:
16973 case OMPC_priority
:
16974 case OMPC_grainsize
:
16976 case OMPC_num_tasks
:
16978 case OMPC_dist_schedule
:
16979 case OMPC_defaultmap
:
16984 case OMPC_use_device_ptr
:
16985 case OMPC_use_device_addr
:
16986 case OMPC_is_device_ptr
:
16987 case OMPC_has_device_addr
:
16988 case OMPC_unified_address
:
16989 case OMPC_unified_shared_memory
:
16990 case OMPC_reverse_offload
:
16991 case OMPC_dynamic_allocators
:
16992 case OMPC_device_type
:
16994 case OMPC_nontemporal
:
16996 case OMPC_novariants
:
16997 case OMPC_nocontext
:
16999 case OMPC_inclusive
:
17000 case OMPC_exclusive
:
17001 case OMPC_uses_allocators
:
17002 case OMPC_affinity
:
17006 llvm_unreachable("Clause is not allowed.");
17012 getListOfPossibleValues(OpenMPClauseKind K
, unsigned First
, unsigned Last
,
17013 ArrayRef
<unsigned> Exclude
= std::nullopt
) {
17014 SmallString
<256> Buffer
;
17015 llvm::raw_svector_ostream
Out(Buffer
);
17016 unsigned Skipped
= Exclude
.size();
17017 for (unsigned I
= First
; I
< Last
; ++I
) {
17018 if (llvm::is_contained(Exclude
, I
)) {
17022 Out
<< "'" << getOpenMPSimpleClauseTypeName(K
, I
) << "'";
17023 if (I
+ Skipped
+ 2 == Last
)
17025 else if (I
+ Skipped
+ 1 != Last
)
17028 return std::string(Out
.str());
17031 OMPClause
*Sema::ActOnOpenMPDefaultClause(DefaultKind Kind
,
17032 SourceLocation KindKwLoc
,
17033 SourceLocation StartLoc
,
17034 SourceLocation LParenLoc
,
17035 SourceLocation EndLoc
) {
17036 if (Kind
== OMP_DEFAULT_unknown
) {
17037 Diag(KindKwLoc
, diag::err_omp_unexpected_clause_value
)
17038 << getListOfPossibleValues(OMPC_default
, /*First=*/0,
17039 /*Last=*/unsigned(OMP_DEFAULT_unknown
))
17040 << getOpenMPClauseName(OMPC_default
);
17045 case OMP_DEFAULT_none
:
17046 DSAStack
->setDefaultDSANone(KindKwLoc
);
17048 case OMP_DEFAULT_shared
:
17049 DSAStack
->setDefaultDSAShared(KindKwLoc
);
17051 case OMP_DEFAULT_firstprivate
:
17052 DSAStack
->setDefaultDSAFirstPrivate(KindKwLoc
);
17054 case OMP_DEFAULT_private
:
17055 DSAStack
->setDefaultDSAPrivate(KindKwLoc
);
17058 llvm_unreachable("DSA unexpected in OpenMP default clause");
17061 return new (Context
)
17062 OMPDefaultClause(Kind
, KindKwLoc
, StartLoc
, LParenLoc
, EndLoc
);
17065 OMPClause
*Sema::ActOnOpenMPProcBindClause(ProcBindKind Kind
,
17066 SourceLocation KindKwLoc
,
17067 SourceLocation StartLoc
,
17068 SourceLocation LParenLoc
,
17069 SourceLocation EndLoc
) {
17070 if (Kind
== OMP_PROC_BIND_unknown
) {
17071 Diag(KindKwLoc
, diag::err_omp_unexpected_clause_value
)
17072 << getListOfPossibleValues(OMPC_proc_bind
,
17073 /*First=*/unsigned(OMP_PROC_BIND_master
),
17075 unsigned(LangOpts
.OpenMP
> 50
17076 ? OMP_PROC_BIND_primary
17077 : OMP_PROC_BIND_spread
) +
17079 << getOpenMPClauseName(OMPC_proc_bind
);
17082 if (Kind
== OMP_PROC_BIND_primary
&& LangOpts
.OpenMP
< 51)
17083 Diag(KindKwLoc
, diag::err_omp_unexpected_clause_value
)
17084 << getListOfPossibleValues(OMPC_proc_bind
,
17085 /*First=*/unsigned(OMP_PROC_BIND_master
),
17087 unsigned(OMP_PROC_BIND_spread
) + 1)
17088 << getOpenMPClauseName(OMPC_proc_bind
);
17089 return new (Context
)
17090 OMPProcBindClause(Kind
, KindKwLoc
, StartLoc
, LParenLoc
, EndLoc
);
17093 OMPClause
*Sema::ActOnOpenMPAtomicDefaultMemOrderClause(
17094 OpenMPAtomicDefaultMemOrderClauseKind Kind
, SourceLocation KindKwLoc
,
17095 SourceLocation StartLoc
, SourceLocation LParenLoc
, SourceLocation EndLoc
) {
17096 if (Kind
== OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
) {
17097 Diag(KindKwLoc
, diag::err_omp_unexpected_clause_value
)
17098 << getListOfPossibleValues(
17099 OMPC_atomic_default_mem_order
, /*First=*/0,
17100 /*Last=*/OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
)
17101 << getOpenMPClauseName(OMPC_atomic_default_mem_order
);
17104 return new (Context
) OMPAtomicDefaultMemOrderClause(Kind
, KindKwLoc
, StartLoc
,
17105 LParenLoc
, EndLoc
);
17108 OMPClause
*Sema::ActOnOpenMPAtClause(OpenMPAtClauseKind Kind
,
17109 SourceLocation KindKwLoc
,
17110 SourceLocation StartLoc
,
17111 SourceLocation LParenLoc
,
17112 SourceLocation EndLoc
) {
17113 if (Kind
== OMPC_AT_unknown
) {
17114 Diag(KindKwLoc
, diag::err_omp_unexpected_clause_value
)
17115 << getListOfPossibleValues(OMPC_at
, /*First=*/0,
17116 /*Last=*/OMPC_AT_unknown
)
17117 << getOpenMPClauseName(OMPC_at
);
17120 return new (Context
)
17121 OMPAtClause(Kind
, KindKwLoc
, StartLoc
, LParenLoc
, EndLoc
);
17124 OMPClause
*Sema::ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind
,
17125 SourceLocation KindKwLoc
,
17126 SourceLocation StartLoc
,
17127 SourceLocation LParenLoc
,
17128 SourceLocation EndLoc
) {
17129 if (Kind
== OMPC_SEVERITY_unknown
) {
17130 Diag(KindKwLoc
, diag::err_omp_unexpected_clause_value
)
17131 << getListOfPossibleValues(OMPC_severity
, /*First=*/0,
17132 /*Last=*/OMPC_SEVERITY_unknown
)
17133 << getOpenMPClauseName(OMPC_severity
);
17136 return new (Context
)
17137 OMPSeverityClause(Kind
, KindKwLoc
, StartLoc
, LParenLoc
, EndLoc
);
17140 OMPClause
*Sema::ActOnOpenMPMessageClause(Expr
*ME
, SourceLocation StartLoc
,
17141 SourceLocation LParenLoc
,
17142 SourceLocation EndLoc
) {
17143 assert(ME
&& "NULL expr in Message clause");
17144 if (!isa
<StringLiteral
>(ME
)) {
17145 Diag(ME
->getBeginLoc(), diag::warn_clause_expected_string
)
17146 << getOpenMPClauseName(OMPC_message
);
17149 return new (Context
) OMPMessageClause(ME
, StartLoc
, LParenLoc
, EndLoc
);
17152 OMPClause
*Sema::ActOnOpenMPOrderClause(
17153 OpenMPOrderClauseModifier Modifier
, OpenMPOrderClauseKind Kind
,
17154 SourceLocation StartLoc
, SourceLocation LParenLoc
, SourceLocation MLoc
,
17155 SourceLocation KindLoc
, SourceLocation EndLoc
) {
17156 if (Kind
!= OMPC_ORDER_concurrent
||
17157 (LangOpts
.OpenMP
< 51 && MLoc
.isValid())) {
17158 // Kind should be concurrent,
17159 // Modifiers introduced in OpenMP 5.1
17160 static_assert(OMPC_ORDER_unknown
> 0,
17161 "OMPC_ORDER_unknown not greater than 0");
17163 Diag(KindLoc
, diag::err_omp_unexpected_clause_value
)
17164 << getListOfPossibleValues(OMPC_order
,
17166 /*Last=*/OMPC_ORDER_unknown
)
17167 << getOpenMPClauseName(OMPC_order
);
17170 if (LangOpts
.OpenMP
>= 51) {
17171 if (Modifier
== OMPC_ORDER_MODIFIER_unknown
&& MLoc
.isValid()) {
17172 Diag(MLoc
, diag::err_omp_unexpected_clause_value
)
17173 << getListOfPossibleValues(OMPC_order
,
17174 /*First=*/OMPC_ORDER_MODIFIER_unknown
+ 1,
17175 /*Last=*/OMPC_ORDER_MODIFIER_last
)
17176 << getOpenMPClauseName(OMPC_order
);
17178 DSAStack
->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
17179 if (DSAStack
->getCurScope()) {
17180 // mark the current scope with 'order' flag
17181 unsigned existingFlags
= DSAStack
->getCurScope()->getFlags();
17182 DSAStack
->getCurScope()->setFlags(existingFlags
|
17183 Scope::OpenMPOrderClauseScope
);
17187 return new (Context
) OMPOrderClause(Kind
, KindLoc
, StartLoc
, LParenLoc
,
17188 EndLoc
, Modifier
, MLoc
);
17191 OMPClause
*Sema::ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind
,
17192 SourceLocation KindKwLoc
,
17193 SourceLocation StartLoc
,
17194 SourceLocation LParenLoc
,
17195 SourceLocation EndLoc
) {
17196 if (Kind
== OMPC_DEPEND_unknown
|| Kind
== OMPC_DEPEND_source
||
17197 Kind
== OMPC_DEPEND_sink
|| Kind
== OMPC_DEPEND_depobj
) {
17198 SmallVector
<unsigned> Except
= {
17199 OMPC_DEPEND_source
, OMPC_DEPEND_sink
, OMPC_DEPEND_depobj
,
17200 OMPC_DEPEND_outallmemory
, OMPC_DEPEND_inoutallmemory
};
17201 if (LangOpts
.OpenMP
< 51)
17202 Except
.push_back(OMPC_DEPEND_inoutset
);
17203 Diag(KindKwLoc
, diag::err_omp_unexpected_clause_value
)
17204 << getListOfPossibleValues(OMPC_depend
, /*First=*/0,
17205 /*Last=*/OMPC_DEPEND_unknown
, Except
)
17206 << getOpenMPClauseName(OMPC_update
);
17209 return OMPUpdateClause::Create(Context
, StartLoc
, LParenLoc
, KindKwLoc
, Kind
,
17213 OMPClause
*Sema::ActOnOpenMPSizesClause(ArrayRef
<Expr
*> SizeExprs
,
17214 SourceLocation StartLoc
,
17215 SourceLocation LParenLoc
,
17216 SourceLocation EndLoc
) {
17217 for (Expr
*SizeExpr
: SizeExprs
) {
17218 ExprResult NumForLoopsResult
= VerifyPositiveIntegerConstantInClause(
17219 SizeExpr
, OMPC_sizes
, /*StrictlyPositive=*/true);
17220 if (!NumForLoopsResult
.isUsable())
17224 DSAStack
->setAssociatedLoops(SizeExprs
.size());
17225 return OMPSizesClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
,
17229 OMPClause
*Sema::ActOnOpenMPFullClause(SourceLocation StartLoc
,
17230 SourceLocation EndLoc
) {
17231 return OMPFullClause::Create(Context
, StartLoc
, EndLoc
);
17234 OMPClause
*Sema::ActOnOpenMPPartialClause(Expr
*FactorExpr
,
17235 SourceLocation StartLoc
,
17236 SourceLocation LParenLoc
,
17237 SourceLocation EndLoc
) {
17239 // If an argument is specified, it must be a constant (or an unevaluated
17240 // template expression).
17241 ExprResult FactorResult
= VerifyPositiveIntegerConstantInClause(
17242 FactorExpr
, OMPC_partial
, /*StrictlyPositive=*/true);
17243 if (FactorResult
.isInvalid())
17245 FactorExpr
= FactorResult
.get();
17248 return OMPPartialClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
,
17252 OMPClause
*Sema::ActOnOpenMPAlignClause(Expr
*A
, SourceLocation StartLoc
,
17253 SourceLocation LParenLoc
,
17254 SourceLocation EndLoc
) {
17255 ExprResult AlignVal
;
17256 AlignVal
= VerifyPositiveIntegerConstantInClause(A
, OMPC_align
);
17257 if (AlignVal
.isInvalid())
17259 return OMPAlignClause::Create(Context
, AlignVal
.get(), StartLoc
, LParenLoc
,
17263 OMPClause
*Sema::ActOnOpenMPSingleExprWithArgClause(
17264 OpenMPClauseKind Kind
, ArrayRef
<unsigned> Argument
, Expr
*Expr
,
17265 SourceLocation StartLoc
, SourceLocation LParenLoc
,
17266 ArrayRef
<SourceLocation
> ArgumentLoc
, SourceLocation DelimLoc
,
17267 SourceLocation EndLoc
) {
17268 OMPClause
*Res
= nullptr;
17270 case OMPC_schedule
:
17271 enum { Modifier1
, Modifier2
, ScheduleKind
, NumberOfElements
};
17272 assert(Argument
.size() == NumberOfElements
&&
17273 ArgumentLoc
.size() == NumberOfElements
);
17274 Res
= ActOnOpenMPScheduleClause(
17275 static_cast<OpenMPScheduleClauseModifier
>(Argument
[Modifier1
]),
17276 static_cast<OpenMPScheduleClauseModifier
>(Argument
[Modifier2
]),
17277 static_cast<OpenMPScheduleClauseKind
>(Argument
[ScheduleKind
]), Expr
,
17278 StartLoc
, LParenLoc
, ArgumentLoc
[Modifier1
], ArgumentLoc
[Modifier2
],
17279 ArgumentLoc
[ScheduleKind
], DelimLoc
, EndLoc
);
17282 assert(Argument
.size() == 1 && ArgumentLoc
.size() == 1);
17283 Res
= ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind
>(Argument
.back()),
17284 Expr
, StartLoc
, LParenLoc
, ArgumentLoc
.back(),
17287 case OMPC_dist_schedule
:
17288 Res
= ActOnOpenMPDistScheduleClause(
17289 static_cast<OpenMPDistScheduleClauseKind
>(Argument
.back()), Expr
,
17290 StartLoc
, LParenLoc
, ArgumentLoc
.back(), DelimLoc
, EndLoc
);
17292 case OMPC_defaultmap
:
17293 enum { Modifier
, DefaultmapKind
};
17294 Res
= ActOnOpenMPDefaultmapClause(
17295 static_cast<OpenMPDefaultmapClauseModifier
>(Argument
[Modifier
]),
17296 static_cast<OpenMPDefaultmapClauseKind
>(Argument
[DefaultmapKind
]),
17297 StartLoc
, LParenLoc
, ArgumentLoc
[Modifier
], ArgumentLoc
[DefaultmapKind
],
17301 enum { OrderModifier
, OrderKind
};
17302 Res
= ActOnOpenMPOrderClause(
17303 static_cast<OpenMPOrderClauseModifier
>(Argument
[OrderModifier
]),
17304 static_cast<OpenMPOrderClauseKind
>(Argument
[OrderKind
]), StartLoc
,
17305 LParenLoc
, ArgumentLoc
[OrderModifier
], ArgumentLoc
[OrderKind
], EndLoc
);
17308 assert(Argument
.size() == 1 && ArgumentLoc
.size() == 1);
17309 Res
= ActOnOpenMPDeviceClause(
17310 static_cast<OpenMPDeviceClauseModifier
>(Argument
.back()), Expr
,
17311 StartLoc
, LParenLoc
, ArgumentLoc
.back(), EndLoc
);
17313 case OMPC_grainsize
:
17314 assert(Argument
.size() == 1 && ArgumentLoc
.size() == 1 &&
17315 "Modifier for grainsize clause and its location are expected.");
17316 Res
= ActOnOpenMPGrainsizeClause(
17317 static_cast<OpenMPGrainsizeClauseModifier
>(Argument
.back()), Expr
,
17318 StartLoc
, LParenLoc
, ArgumentLoc
.back(), EndLoc
);
17320 case OMPC_num_tasks
:
17321 assert(Argument
.size() == 1 && ArgumentLoc
.size() == 1 &&
17322 "Modifier for num_tasks clause and its location are expected.");
17323 Res
= ActOnOpenMPNumTasksClause(
17324 static_cast<OpenMPNumTasksClauseModifier
>(Argument
.back()), Expr
,
17325 StartLoc
, LParenLoc
, ArgumentLoc
.back(), EndLoc
);
17328 case OMPC_num_threads
:
17332 case OMPC_allocator
:
17333 case OMPC_collapse
:
17335 case OMPC_proc_bind
:
17337 case OMPC_firstprivate
:
17338 case OMPC_lastprivate
:
17340 case OMPC_reduction
:
17341 case OMPC_task_reduction
:
17342 case OMPC_in_reduction
:
17346 case OMPC_copyprivate
:
17350 case OMPC_mergeable
:
17351 case OMPC_threadprivate
:
17352 case OMPC_allocate
:
17369 case OMPC_num_teams
:
17370 case OMPC_thread_limit
:
17371 case OMPC_priority
:
17378 case OMPC_use_device_ptr
:
17379 case OMPC_use_device_addr
:
17380 case OMPC_is_device_ptr
:
17381 case OMPC_has_device_addr
:
17382 case OMPC_unified_address
:
17383 case OMPC_unified_shared_memory
:
17384 case OMPC_reverse_offload
:
17385 case OMPC_dynamic_allocators
:
17386 case OMPC_atomic_default_mem_order
:
17387 case OMPC_device_type
:
17389 case OMPC_nontemporal
:
17391 case OMPC_severity
:
17394 case OMPC_novariants
:
17395 case OMPC_nocontext
:
17397 case OMPC_inclusive
:
17398 case OMPC_exclusive
:
17399 case OMPC_uses_allocators
:
17400 case OMPC_affinity
:
17404 llvm_unreachable("Clause is not allowed.");
17409 static bool checkScheduleModifiers(Sema
&S
, OpenMPScheduleClauseModifier M1
,
17410 OpenMPScheduleClauseModifier M2
,
17411 SourceLocation M1Loc
, SourceLocation M2Loc
) {
17412 if (M1
== OMPC_SCHEDULE_MODIFIER_unknown
&& M1Loc
.isValid()) {
17413 SmallVector
<unsigned, 2> Excluded
;
17414 if (M2
!= OMPC_SCHEDULE_MODIFIER_unknown
)
17415 Excluded
.push_back(M2
);
17416 if (M2
== OMPC_SCHEDULE_MODIFIER_nonmonotonic
)
17417 Excluded
.push_back(OMPC_SCHEDULE_MODIFIER_monotonic
);
17418 if (M2
== OMPC_SCHEDULE_MODIFIER_monotonic
)
17419 Excluded
.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic
);
17420 S
.Diag(M1Loc
, diag::err_omp_unexpected_clause_value
)
17421 << getListOfPossibleValues(OMPC_schedule
,
17422 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown
+ 1,
17423 /*Last=*/OMPC_SCHEDULE_MODIFIER_last
,
17425 << getOpenMPClauseName(OMPC_schedule
);
17431 OMPClause
*Sema::ActOnOpenMPScheduleClause(
17432 OpenMPScheduleClauseModifier M1
, OpenMPScheduleClauseModifier M2
,
17433 OpenMPScheduleClauseKind Kind
, Expr
*ChunkSize
, SourceLocation StartLoc
,
17434 SourceLocation LParenLoc
, SourceLocation M1Loc
, SourceLocation M2Loc
,
17435 SourceLocation KindLoc
, SourceLocation CommaLoc
, SourceLocation EndLoc
) {
17436 if (checkScheduleModifiers(*this, M1
, M2
, M1Loc
, M2Loc
) ||
17437 checkScheduleModifiers(*this, M2
, M1
, M2Loc
, M1Loc
))
17439 // OpenMP, 2.7.1, Loop Construct, Restrictions
17440 // Either the monotonic modifier or the nonmonotonic modifier can be specified
17442 if ((M1
== M2
&& M1
!= OMPC_SCHEDULE_MODIFIER_unknown
) ||
17443 (M1
== OMPC_SCHEDULE_MODIFIER_monotonic
&&
17444 M2
== OMPC_SCHEDULE_MODIFIER_nonmonotonic
) ||
17445 (M1
== OMPC_SCHEDULE_MODIFIER_nonmonotonic
&&
17446 M2
== OMPC_SCHEDULE_MODIFIER_monotonic
)) {
17447 Diag(M2Loc
, diag::err_omp_unexpected_schedule_modifier
)
17448 << getOpenMPSimpleClauseTypeName(OMPC_schedule
, M2
)
17449 << getOpenMPSimpleClauseTypeName(OMPC_schedule
, M1
);
17452 if (Kind
== OMPC_SCHEDULE_unknown
) {
17453 std::string Values
;
17454 if (M1Loc
.isInvalid() && M2Loc
.isInvalid()) {
17455 unsigned Exclude
[] = {OMPC_SCHEDULE_unknown
};
17456 Values
= getListOfPossibleValues(OMPC_schedule
, /*First=*/0,
17457 /*Last=*/OMPC_SCHEDULE_MODIFIER_last
,
17460 Values
= getListOfPossibleValues(OMPC_schedule
, /*First=*/0,
17461 /*Last=*/OMPC_SCHEDULE_unknown
);
17463 Diag(KindLoc
, diag::err_omp_unexpected_clause_value
)
17464 << Values
<< getOpenMPClauseName(OMPC_schedule
);
17467 // OpenMP, 2.7.1, Loop Construct, Restrictions
17468 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
17469 // schedule(guided).
17470 // OpenMP 5.0 does not have this restriction.
17471 if (LangOpts
.OpenMP
< 50 &&
17472 (M1
== OMPC_SCHEDULE_MODIFIER_nonmonotonic
||
17473 M2
== OMPC_SCHEDULE_MODIFIER_nonmonotonic
) &&
17474 Kind
!= OMPC_SCHEDULE_dynamic
&& Kind
!= OMPC_SCHEDULE_guided
) {
17475 Diag(M1
== OMPC_SCHEDULE_MODIFIER_nonmonotonic
? M1Loc
: M2Loc
,
17476 diag::err_omp_schedule_nonmonotonic_static
);
17479 Expr
*ValExpr
= ChunkSize
;
17480 Stmt
*HelperValStmt
= nullptr;
17482 if (!ChunkSize
->isValueDependent() && !ChunkSize
->isTypeDependent() &&
17483 !ChunkSize
->isInstantiationDependent() &&
17484 !ChunkSize
->containsUnexpandedParameterPack()) {
17485 SourceLocation ChunkSizeLoc
= ChunkSize
->getBeginLoc();
17487 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc
, ChunkSize
);
17488 if (Val
.isInvalid())
17491 ValExpr
= Val
.get();
17493 // OpenMP [2.7.1, Restrictions]
17494 // chunk_size must be a loop invariant integer expression with a positive
17496 if (std::optional
<llvm::APSInt
> Result
=
17497 ValExpr
->getIntegerConstantExpr(Context
)) {
17498 if (Result
->isSigned() && !Result
->isStrictlyPositive()) {
17499 Diag(ChunkSizeLoc
, diag::err_omp_negative_expression_in_clause
)
17500 << "schedule" << 1 << ChunkSize
->getSourceRange();
17503 } else if (getOpenMPCaptureRegionForClause(
17504 DSAStack
->getCurrentDirective(), OMPC_schedule
,
17505 LangOpts
.OpenMP
) != OMPD_unknown
&&
17506 !CurContext
->isDependentContext()) {
17507 ValExpr
= MakeFullExpr(ValExpr
).get();
17508 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
17509 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
17510 HelperValStmt
= buildPreInits(Context
, Captures
);
17515 return new (Context
)
17516 OMPScheduleClause(StartLoc
, LParenLoc
, KindLoc
, CommaLoc
, EndLoc
, Kind
,
17517 ValExpr
, HelperValStmt
, M1
, M1Loc
, M2
, M2Loc
);
17520 OMPClause
*Sema::ActOnOpenMPClause(OpenMPClauseKind Kind
,
17521 SourceLocation StartLoc
,
17522 SourceLocation EndLoc
) {
17523 OMPClause
*Res
= nullptr;
17526 Res
= ActOnOpenMPOrderedClause(StartLoc
, EndLoc
);
17529 Res
= ActOnOpenMPNowaitClause(StartLoc
, EndLoc
);
17532 Res
= ActOnOpenMPUntiedClause(StartLoc
, EndLoc
);
17534 case OMPC_mergeable
:
17535 Res
= ActOnOpenMPMergeableClause(StartLoc
, EndLoc
);
17538 Res
= ActOnOpenMPReadClause(StartLoc
, EndLoc
);
17541 Res
= ActOnOpenMPWriteClause(StartLoc
, EndLoc
);
17544 Res
= ActOnOpenMPUpdateClause(StartLoc
, EndLoc
);
17547 Res
= ActOnOpenMPCaptureClause(StartLoc
, EndLoc
);
17550 Res
= ActOnOpenMPCompareClause(StartLoc
, EndLoc
);
17553 Res
= ActOnOpenMPFailClause(StartLoc
, EndLoc
);
17556 Res
= ActOnOpenMPSeqCstClause(StartLoc
, EndLoc
);
17559 Res
= ActOnOpenMPAcqRelClause(StartLoc
, EndLoc
);
17562 Res
= ActOnOpenMPAcquireClause(StartLoc
, EndLoc
);
17565 Res
= ActOnOpenMPReleaseClause(StartLoc
, EndLoc
);
17568 Res
= ActOnOpenMPRelaxedClause(StartLoc
, EndLoc
);
17571 Res
= ActOnOpenMPThreadsClause(StartLoc
, EndLoc
);
17574 Res
= ActOnOpenMPSIMDClause(StartLoc
, EndLoc
);
17577 Res
= ActOnOpenMPNogroupClause(StartLoc
, EndLoc
);
17579 case OMPC_unified_address
:
17580 Res
= ActOnOpenMPUnifiedAddressClause(StartLoc
, EndLoc
);
17582 case OMPC_unified_shared_memory
:
17583 Res
= ActOnOpenMPUnifiedSharedMemoryClause(StartLoc
, EndLoc
);
17585 case OMPC_reverse_offload
:
17586 Res
= ActOnOpenMPReverseOffloadClause(StartLoc
, EndLoc
);
17588 case OMPC_dynamic_allocators
:
17589 Res
= ActOnOpenMPDynamicAllocatorsClause(StartLoc
, EndLoc
);
17592 Res
= ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc
,
17593 /*LParenLoc=*/SourceLocation(),
17594 /*VarLoc=*/SourceLocation(), EndLoc
);
17597 Res
= ActOnOpenMPFullClause(StartLoc
, EndLoc
);
17600 Res
= ActOnOpenMPPartialClause(nullptr, StartLoc
, /*LParenLoc=*/{}, EndLoc
);
17602 case OMPC_ompx_bare
:
17603 Res
= ActOnOpenMPXBareClause(StartLoc
, EndLoc
);
17607 case OMPC_num_threads
:
17611 case OMPC_allocator
:
17612 case OMPC_collapse
:
17613 case OMPC_schedule
:
17615 case OMPC_firstprivate
:
17616 case OMPC_lastprivate
:
17618 case OMPC_reduction
:
17619 case OMPC_task_reduction
:
17620 case OMPC_in_reduction
:
17624 case OMPC_copyprivate
:
17626 case OMPC_proc_bind
:
17627 case OMPC_threadprivate
:
17628 case OMPC_allocate
:
17634 case OMPC_num_teams
:
17635 case OMPC_thread_limit
:
17636 case OMPC_priority
:
17637 case OMPC_grainsize
:
17638 case OMPC_num_tasks
:
17640 case OMPC_dist_schedule
:
17641 case OMPC_defaultmap
:
17646 case OMPC_use_device_ptr
:
17647 case OMPC_use_device_addr
:
17648 case OMPC_is_device_ptr
:
17649 case OMPC_has_device_addr
:
17650 case OMPC_atomic_default_mem_order
:
17651 case OMPC_device_type
:
17653 case OMPC_nontemporal
:
17656 case OMPC_severity
:
17658 case OMPC_novariants
:
17659 case OMPC_nocontext
:
17661 case OMPC_inclusive
:
17662 case OMPC_exclusive
:
17663 case OMPC_uses_allocators
:
17664 case OMPC_affinity
:
17666 case OMPC_ompx_dyn_cgroup_mem
:
17668 llvm_unreachable("Clause is not allowed.");
17673 OMPClause
*Sema::ActOnOpenMPNowaitClause(SourceLocation StartLoc
,
17674 SourceLocation EndLoc
) {
17675 DSAStack
->setNowaitRegion();
17676 return new (Context
) OMPNowaitClause(StartLoc
, EndLoc
);
17679 OMPClause
*Sema::ActOnOpenMPUntiedClause(SourceLocation StartLoc
,
17680 SourceLocation EndLoc
) {
17681 DSAStack
->setUntiedRegion();
17682 return new (Context
) OMPUntiedClause(StartLoc
, EndLoc
);
17685 OMPClause
*Sema::ActOnOpenMPMergeableClause(SourceLocation StartLoc
,
17686 SourceLocation EndLoc
) {
17687 return new (Context
) OMPMergeableClause(StartLoc
, EndLoc
);
17690 OMPClause
*Sema::ActOnOpenMPReadClause(SourceLocation StartLoc
,
17691 SourceLocation EndLoc
) {
17692 return new (Context
) OMPReadClause(StartLoc
, EndLoc
);
17695 OMPClause
*Sema::ActOnOpenMPWriteClause(SourceLocation StartLoc
,
17696 SourceLocation EndLoc
) {
17697 return new (Context
) OMPWriteClause(StartLoc
, EndLoc
);
17700 OMPClause
*Sema::ActOnOpenMPUpdateClause(SourceLocation StartLoc
,
17701 SourceLocation EndLoc
) {
17702 return OMPUpdateClause::Create(Context
, StartLoc
, EndLoc
);
17705 OMPClause
*Sema::ActOnOpenMPCaptureClause(SourceLocation StartLoc
,
17706 SourceLocation EndLoc
) {
17707 return new (Context
) OMPCaptureClause(StartLoc
, EndLoc
);
17710 OMPClause
*Sema::ActOnOpenMPCompareClause(SourceLocation StartLoc
,
17711 SourceLocation EndLoc
) {
17712 return new (Context
) OMPCompareClause(StartLoc
, EndLoc
);
17715 OMPClause
*Sema::ActOnOpenMPFailClause(SourceLocation StartLoc
,
17716 SourceLocation EndLoc
) {
17717 return new (Context
) OMPFailClause(StartLoc
, EndLoc
);
17720 OMPClause
*Sema::ActOnOpenMPFailClause(
17721 OpenMPClauseKind Parameter
, SourceLocation KindLoc
,
17722 SourceLocation StartLoc
, SourceLocation LParenLoc
,
17723 SourceLocation EndLoc
) {
17725 if (!checkFailClauseParameter(Parameter
)) {
17726 Diag(KindLoc
, diag::err_omp_atomic_fail_wrong_or_no_clauses
);
17729 return new (Context
)
17730 OMPFailClause(Parameter
, KindLoc
, StartLoc
, LParenLoc
, EndLoc
);
17733 OMPClause
*Sema::ActOnOpenMPSeqCstClause(SourceLocation StartLoc
,
17734 SourceLocation EndLoc
) {
17735 return new (Context
) OMPSeqCstClause(StartLoc
, EndLoc
);
17738 OMPClause
*Sema::ActOnOpenMPAcqRelClause(SourceLocation StartLoc
,
17739 SourceLocation EndLoc
) {
17740 return new (Context
) OMPAcqRelClause(StartLoc
, EndLoc
);
17743 OMPClause
*Sema::ActOnOpenMPAcquireClause(SourceLocation StartLoc
,
17744 SourceLocation EndLoc
) {
17745 return new (Context
) OMPAcquireClause(StartLoc
, EndLoc
);
17748 OMPClause
*Sema::ActOnOpenMPReleaseClause(SourceLocation StartLoc
,
17749 SourceLocation EndLoc
) {
17750 return new (Context
) OMPReleaseClause(StartLoc
, EndLoc
);
17753 OMPClause
*Sema::ActOnOpenMPRelaxedClause(SourceLocation StartLoc
,
17754 SourceLocation EndLoc
) {
17755 return new (Context
) OMPRelaxedClause(StartLoc
, EndLoc
);
17758 OMPClause
*Sema::ActOnOpenMPThreadsClause(SourceLocation StartLoc
,
17759 SourceLocation EndLoc
) {
17760 return new (Context
) OMPThreadsClause(StartLoc
, EndLoc
);
17763 OMPClause
*Sema::ActOnOpenMPSIMDClause(SourceLocation StartLoc
,
17764 SourceLocation EndLoc
) {
17765 return new (Context
) OMPSIMDClause(StartLoc
, EndLoc
);
17768 OMPClause
*Sema::ActOnOpenMPNogroupClause(SourceLocation StartLoc
,
17769 SourceLocation EndLoc
) {
17770 return new (Context
) OMPNogroupClause(StartLoc
, EndLoc
);
17773 OMPClause
*Sema::ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc
,
17774 SourceLocation EndLoc
) {
17775 return new (Context
) OMPUnifiedAddressClause(StartLoc
, EndLoc
);
17778 OMPClause
*Sema::ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc
,
17779 SourceLocation EndLoc
) {
17780 return new (Context
) OMPUnifiedSharedMemoryClause(StartLoc
, EndLoc
);
17783 OMPClause
*Sema::ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc
,
17784 SourceLocation EndLoc
) {
17785 return new (Context
) OMPReverseOffloadClause(StartLoc
, EndLoc
);
17788 OMPClause
*Sema::ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc
,
17789 SourceLocation EndLoc
) {
17790 return new (Context
) OMPDynamicAllocatorsClause(StartLoc
, EndLoc
);
17793 StmtResult
Sema::ActOnOpenMPInteropDirective(ArrayRef
<OMPClause
*> Clauses
,
17794 SourceLocation StartLoc
,
17795 SourceLocation EndLoc
) {
17797 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17798 // At least one action-clause must appear on a directive.
17799 if (!hasClauses(Clauses
, OMPC_init
, OMPC_use
, OMPC_destroy
, OMPC_nowait
)) {
17800 StringRef Expected
= "'init', 'use', 'destroy', or 'nowait'";
17801 Diag(StartLoc
, diag::err_omp_no_clause_for_directive
)
17802 << Expected
<< getOpenMPDirectiveName(OMPD_interop
);
17803 return StmtError();
17806 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17807 // A depend clause can only appear on the directive if a targetsync
17808 // interop-type is present or the interop-var was initialized with
17809 // the targetsync interop-type.
17811 // If there is any 'init' clause diagnose if there is no 'init' clause with
17812 // interop-type of 'targetsync'. Cases involving other directives cannot be
17814 const OMPDependClause
*DependClause
= nullptr;
17815 bool HasInitClause
= false;
17816 bool IsTargetSync
= false;
17817 for (const OMPClause
*C
: Clauses
) {
17820 if (const auto *InitClause
= dyn_cast
<OMPInitClause
>(C
)) {
17821 HasInitClause
= true;
17822 if (InitClause
->getIsTargetSync())
17823 IsTargetSync
= true;
17824 } else if (const auto *DC
= dyn_cast
<OMPDependClause
>(C
)) {
17828 if (DependClause
&& HasInitClause
&& !IsTargetSync
) {
17829 Diag(DependClause
->getBeginLoc(), diag::err_omp_interop_bad_depend_clause
);
17830 return StmtError();
17833 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17834 // Each interop-var may be specified for at most one action-clause of each
17835 // interop construct.
17836 llvm::SmallPtrSet
<const ValueDecl
*, 4> InteropVars
;
17837 for (OMPClause
*C
: Clauses
) {
17838 OpenMPClauseKind ClauseKind
= C
->getClauseKind();
17839 std::pair
<ValueDecl
*, bool> DeclResult
;
17840 SourceLocation ELoc
;
17841 SourceRange ERange
;
17843 if (ClauseKind
== OMPC_init
) {
17844 auto *E
= cast
<OMPInitClause
>(C
)->getInteropVar();
17845 DeclResult
= getPrivateItem(*this, E
, ELoc
, ERange
);
17846 } else if (ClauseKind
== OMPC_use
) {
17847 auto *E
= cast
<OMPUseClause
>(C
)->getInteropVar();
17848 DeclResult
= getPrivateItem(*this, E
, ELoc
, ERange
);
17849 } else if (ClauseKind
== OMPC_destroy
) {
17850 auto *E
= cast
<OMPDestroyClause
>(C
)->getInteropVar();
17851 DeclResult
= getPrivateItem(*this, E
, ELoc
, ERange
);
17854 if (DeclResult
.first
) {
17855 if (!InteropVars
.insert(DeclResult
.first
).second
) {
17856 Diag(ELoc
, diag::err_omp_interop_var_multiple_actions
)
17857 << DeclResult
.first
;
17858 return StmtError();
17863 return OMPInteropDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
);
17866 static bool isValidInteropVariable(Sema
&SemaRef
, Expr
*InteropVarExpr
,
17867 SourceLocation VarLoc
,
17868 OpenMPClauseKind Kind
) {
17869 SourceLocation ELoc
;
17870 SourceRange ERange
;
17871 Expr
*RefExpr
= InteropVarExpr
;
17873 getPrivateItem(SemaRef
, RefExpr
, ELoc
, ERange
,
17874 /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t");
17877 // It will be analyzed later.
17884 // Interop variable should be of type omp_interop_t.
17885 bool HasError
= false;
17886 QualType InteropType
;
17887 LookupResult
Result(SemaRef
, &SemaRef
.Context
.Idents
.get("omp_interop_t"),
17888 VarLoc
, Sema::LookupOrdinaryName
);
17889 if (SemaRef
.LookupName(Result
, SemaRef
.getCurScope())) {
17890 NamedDecl
*ND
= Result
.getFoundDecl();
17891 if (const auto *TD
= dyn_cast
<TypeDecl
>(ND
)) {
17892 InteropType
= QualType(TD
->getTypeForDecl(), 0);
17901 SemaRef
.Diag(VarLoc
, diag::err_omp_implied_type_not_found
)
17902 << "omp_interop_t";
17906 QualType VarType
= InteropVarExpr
->getType().getUnqualifiedType();
17907 if (!SemaRef
.Context
.hasSameType(InteropType
, VarType
)) {
17908 SemaRef
.Diag(VarLoc
, diag::err_omp_interop_variable_wrong_type
);
17912 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17913 // The interop-var passed to init or destroy must be non-const.
17914 if ((Kind
== OMPC_init
|| Kind
== OMPC_destroy
) &&
17915 isConstNotMutableType(SemaRef
, InteropVarExpr
->getType())) {
17916 SemaRef
.Diag(VarLoc
, diag::err_omp_interop_variable_expected
)
17917 << /*non-const*/ 1;
17924 Sema::ActOnOpenMPInitClause(Expr
*InteropVar
, OMPInteropInfo
&InteropInfo
,
17925 SourceLocation StartLoc
, SourceLocation LParenLoc
,
17926 SourceLocation VarLoc
, SourceLocation EndLoc
) {
17928 if (!isValidInteropVariable(*this, InteropVar
, VarLoc
, OMPC_init
))
17931 // Check prefer_type values. These foreign-runtime-id values are either
17932 // string literals or constant integral expressions.
17933 for (const Expr
*E
: InteropInfo
.PreferTypes
) {
17934 if (E
->isValueDependent() || E
->isTypeDependent() ||
17935 E
->isInstantiationDependent() || E
->containsUnexpandedParameterPack())
17937 if (E
->isIntegerConstantExpr(Context
))
17939 if (isa
<StringLiteral
>(E
))
17941 Diag(E
->getExprLoc(), diag::err_omp_interop_prefer_type
);
17945 return OMPInitClause::Create(Context
, InteropVar
, InteropInfo
, StartLoc
,
17946 LParenLoc
, VarLoc
, EndLoc
);
17949 OMPClause
*Sema::ActOnOpenMPUseClause(Expr
*InteropVar
, SourceLocation StartLoc
,
17950 SourceLocation LParenLoc
,
17951 SourceLocation VarLoc
,
17952 SourceLocation EndLoc
) {
17954 if (!isValidInteropVariable(*this, InteropVar
, VarLoc
, OMPC_use
))
17957 return new (Context
)
17958 OMPUseClause(InteropVar
, StartLoc
, LParenLoc
, VarLoc
, EndLoc
);
17961 OMPClause
*Sema::ActOnOpenMPDestroyClause(Expr
*InteropVar
,
17962 SourceLocation StartLoc
,
17963 SourceLocation LParenLoc
,
17964 SourceLocation VarLoc
,
17965 SourceLocation EndLoc
) {
17966 if (!InteropVar
&& LangOpts
.OpenMP
>= 52 &&
17967 DSAStack
->getCurrentDirective() == OMPD_depobj
) {
17968 Diag(StartLoc
, diag::err_omp_expected_clause_argument
)
17969 << getOpenMPClauseName(OMPC_destroy
)
17970 << getOpenMPDirectiveName(OMPD_depobj
);
17974 !isValidInteropVariable(*this, InteropVar
, VarLoc
, OMPC_destroy
))
17977 return new (Context
)
17978 OMPDestroyClause(InteropVar
, StartLoc
, LParenLoc
, VarLoc
, EndLoc
);
17981 OMPClause
*Sema::ActOnOpenMPNovariantsClause(Expr
*Condition
,
17982 SourceLocation StartLoc
,
17983 SourceLocation LParenLoc
,
17984 SourceLocation EndLoc
) {
17985 Expr
*ValExpr
= Condition
;
17986 Stmt
*HelperValStmt
= nullptr;
17987 OpenMPDirectiveKind CaptureRegion
= OMPD_unknown
;
17988 if (!Condition
->isValueDependent() && !Condition
->isTypeDependent() &&
17989 !Condition
->isInstantiationDependent() &&
17990 !Condition
->containsUnexpandedParameterPack()) {
17991 ExprResult Val
= CheckBooleanCondition(StartLoc
, Condition
);
17992 if (Val
.isInvalid())
17995 ValExpr
= MakeFullExpr(Val
.get()).get();
17997 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
17998 CaptureRegion
= getOpenMPCaptureRegionForClause(DKind
, OMPC_novariants
,
18000 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
18001 ValExpr
= MakeFullExpr(ValExpr
).get();
18002 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
18003 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
18004 HelperValStmt
= buildPreInits(Context
, Captures
);
18008 return new (Context
) OMPNovariantsClause(
18009 ValExpr
, HelperValStmt
, CaptureRegion
, StartLoc
, LParenLoc
, EndLoc
);
18012 OMPClause
*Sema::ActOnOpenMPNocontextClause(Expr
*Condition
,
18013 SourceLocation StartLoc
,
18014 SourceLocation LParenLoc
,
18015 SourceLocation EndLoc
) {
18016 Expr
*ValExpr
= Condition
;
18017 Stmt
*HelperValStmt
= nullptr;
18018 OpenMPDirectiveKind CaptureRegion
= OMPD_unknown
;
18019 if (!Condition
->isValueDependent() && !Condition
->isTypeDependent() &&
18020 !Condition
->isInstantiationDependent() &&
18021 !Condition
->containsUnexpandedParameterPack()) {
18022 ExprResult Val
= CheckBooleanCondition(StartLoc
, Condition
);
18023 if (Val
.isInvalid())
18026 ValExpr
= MakeFullExpr(Val
.get()).get();
18028 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
18030 getOpenMPCaptureRegionForClause(DKind
, OMPC_nocontext
, LangOpts
.OpenMP
);
18031 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
18032 ValExpr
= MakeFullExpr(ValExpr
).get();
18033 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
18034 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
18035 HelperValStmt
= buildPreInits(Context
, Captures
);
18039 return new (Context
) OMPNocontextClause(ValExpr
, HelperValStmt
, CaptureRegion
,
18040 StartLoc
, LParenLoc
, EndLoc
);
18043 OMPClause
*Sema::ActOnOpenMPFilterClause(Expr
*ThreadID
,
18044 SourceLocation StartLoc
,
18045 SourceLocation LParenLoc
,
18046 SourceLocation EndLoc
) {
18047 Expr
*ValExpr
= ThreadID
;
18048 Stmt
*HelperValStmt
= nullptr;
18050 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
18051 OpenMPDirectiveKind CaptureRegion
=
18052 getOpenMPCaptureRegionForClause(DKind
, OMPC_filter
, LangOpts
.OpenMP
);
18053 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
18054 ValExpr
= MakeFullExpr(ValExpr
).get();
18055 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
18056 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
18057 HelperValStmt
= buildPreInits(Context
, Captures
);
18060 return new (Context
) OMPFilterClause(ValExpr
, HelperValStmt
, CaptureRegion
,
18061 StartLoc
, LParenLoc
, EndLoc
);
18064 OMPClause
*Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind
,
18065 ArrayRef
<Expr
*> VarList
,
18066 const OMPVarListLocTy
&Locs
,
18067 OpenMPVarListDataTy
&Data
) {
18068 SourceLocation StartLoc
= Locs
.StartLoc
;
18069 SourceLocation LParenLoc
= Locs
.LParenLoc
;
18070 SourceLocation EndLoc
= Locs
.EndLoc
;
18071 OMPClause
*Res
= nullptr;
18072 int ExtraModifier
= Data
.ExtraModifier
;
18073 SourceLocation ExtraModifierLoc
= Data
.ExtraModifierLoc
;
18074 SourceLocation ColonLoc
= Data
.ColonLoc
;
18077 Res
= ActOnOpenMPPrivateClause(VarList
, StartLoc
, LParenLoc
, EndLoc
);
18079 case OMPC_firstprivate
:
18080 Res
= ActOnOpenMPFirstprivateClause(VarList
, StartLoc
, LParenLoc
, EndLoc
);
18082 case OMPC_lastprivate
:
18083 assert(0 <= ExtraModifier
&& ExtraModifier
<= OMPC_LASTPRIVATE_unknown
&&
18084 "Unexpected lastprivate modifier.");
18085 Res
= ActOnOpenMPLastprivateClause(
18086 VarList
, static_cast<OpenMPLastprivateModifier
>(ExtraModifier
),
18087 ExtraModifierLoc
, ColonLoc
, StartLoc
, LParenLoc
, EndLoc
);
18090 Res
= ActOnOpenMPSharedClause(VarList
, StartLoc
, LParenLoc
, EndLoc
);
18092 case OMPC_reduction
:
18093 assert(0 <= ExtraModifier
&& ExtraModifier
<= OMPC_REDUCTION_unknown
&&
18094 "Unexpected lastprivate modifier.");
18095 Res
= ActOnOpenMPReductionClause(
18096 VarList
, static_cast<OpenMPReductionClauseModifier
>(ExtraModifier
),
18097 StartLoc
, LParenLoc
, ExtraModifierLoc
, ColonLoc
, EndLoc
,
18098 Data
.ReductionOrMapperIdScopeSpec
, Data
.ReductionOrMapperId
);
18100 case OMPC_task_reduction
:
18101 Res
= ActOnOpenMPTaskReductionClause(
18102 VarList
, StartLoc
, LParenLoc
, ColonLoc
, EndLoc
,
18103 Data
.ReductionOrMapperIdScopeSpec
, Data
.ReductionOrMapperId
);
18105 case OMPC_in_reduction
:
18106 Res
= ActOnOpenMPInReductionClause(
18107 VarList
, StartLoc
, LParenLoc
, ColonLoc
, EndLoc
,
18108 Data
.ReductionOrMapperIdScopeSpec
, Data
.ReductionOrMapperId
);
18111 assert(0 <= ExtraModifier
&& ExtraModifier
<= OMPC_LINEAR_unknown
&&
18112 "Unexpected linear modifier.");
18113 Res
= ActOnOpenMPLinearClause(
18114 VarList
, Data
.DepModOrTailExpr
, StartLoc
, LParenLoc
,
18115 static_cast<OpenMPLinearClauseKind
>(ExtraModifier
), ExtraModifierLoc
,
18116 ColonLoc
, Data
.StepModifierLoc
, EndLoc
);
18119 Res
= ActOnOpenMPAlignedClause(VarList
, Data
.DepModOrTailExpr
, StartLoc
,
18120 LParenLoc
, ColonLoc
, EndLoc
);
18123 Res
= ActOnOpenMPCopyinClause(VarList
, StartLoc
, LParenLoc
, EndLoc
);
18125 case OMPC_copyprivate
:
18126 Res
= ActOnOpenMPCopyprivateClause(VarList
, StartLoc
, LParenLoc
, EndLoc
);
18129 Res
= ActOnOpenMPFlushClause(VarList
, StartLoc
, LParenLoc
, EndLoc
);
18132 assert(0 <= ExtraModifier
&& ExtraModifier
<= OMPC_DEPEND_unknown
&&
18133 "Unexpected depend modifier.");
18134 Res
= ActOnOpenMPDependClause(
18135 {static_cast<OpenMPDependClauseKind
>(ExtraModifier
), ExtraModifierLoc
,
18136 ColonLoc
, Data
.OmpAllMemoryLoc
},
18137 Data
.DepModOrTailExpr
, VarList
, StartLoc
, LParenLoc
, EndLoc
);
18140 assert(0 <= ExtraModifier
&& ExtraModifier
<= OMPC_MAP_unknown
&&
18141 "Unexpected map modifier.");
18142 Res
= ActOnOpenMPMapClause(
18143 Data
.IteratorExpr
, Data
.MapTypeModifiers
, Data
.MapTypeModifiersLoc
,
18144 Data
.ReductionOrMapperIdScopeSpec
, Data
.ReductionOrMapperId
,
18145 static_cast<OpenMPMapClauseKind
>(ExtraModifier
), Data
.IsMapTypeImplicit
,
18146 ExtraModifierLoc
, ColonLoc
, VarList
, Locs
);
18150 ActOnOpenMPToClause(Data
.MotionModifiers
, Data
.MotionModifiersLoc
,
18151 Data
.ReductionOrMapperIdScopeSpec
,
18152 Data
.ReductionOrMapperId
, ColonLoc
, VarList
, Locs
);
18155 Res
= ActOnOpenMPFromClause(Data
.MotionModifiers
, Data
.MotionModifiersLoc
,
18156 Data
.ReductionOrMapperIdScopeSpec
,
18157 Data
.ReductionOrMapperId
, ColonLoc
, VarList
,
18160 case OMPC_use_device_ptr
:
18161 Res
= ActOnOpenMPUseDevicePtrClause(VarList
, Locs
);
18163 case OMPC_use_device_addr
:
18164 Res
= ActOnOpenMPUseDeviceAddrClause(VarList
, Locs
);
18166 case OMPC_is_device_ptr
:
18167 Res
= ActOnOpenMPIsDevicePtrClause(VarList
, Locs
);
18169 case OMPC_has_device_addr
:
18170 Res
= ActOnOpenMPHasDeviceAddrClause(VarList
, Locs
);
18172 case OMPC_allocate
:
18173 Res
= ActOnOpenMPAllocateClause(Data
.DepModOrTailExpr
, VarList
, StartLoc
,
18174 LParenLoc
, ColonLoc
, EndLoc
);
18176 case OMPC_nontemporal
:
18177 Res
= ActOnOpenMPNontemporalClause(VarList
, StartLoc
, LParenLoc
, EndLoc
);
18179 case OMPC_inclusive
:
18180 Res
= ActOnOpenMPInclusiveClause(VarList
, StartLoc
, LParenLoc
, EndLoc
);
18182 case OMPC_exclusive
:
18183 Res
= ActOnOpenMPExclusiveClause(VarList
, StartLoc
, LParenLoc
, EndLoc
);
18185 case OMPC_affinity
:
18186 Res
= ActOnOpenMPAffinityClause(StartLoc
, LParenLoc
, ColonLoc
, EndLoc
,
18187 Data
.DepModOrTailExpr
, VarList
);
18189 case OMPC_doacross
:
18190 Res
= ActOnOpenMPDoacrossClause(
18191 static_cast<OpenMPDoacrossClauseModifier
>(ExtraModifier
),
18192 ExtraModifierLoc
, ColonLoc
, VarList
, StartLoc
, LParenLoc
, EndLoc
);
18197 case OMPC_num_threads
:
18201 case OMPC_allocator
:
18202 case OMPC_collapse
:
18204 case OMPC_proc_bind
:
18205 case OMPC_schedule
:
18209 case OMPC_mergeable
:
18210 case OMPC_threadprivate
:
18224 case OMPC_num_teams
:
18225 case OMPC_thread_limit
:
18226 case OMPC_priority
:
18227 case OMPC_grainsize
:
18229 case OMPC_num_tasks
:
18231 case OMPC_dist_schedule
:
18232 case OMPC_defaultmap
:
18235 case OMPC_unified_address
:
18236 case OMPC_unified_shared_memory
:
18237 case OMPC_reverse_offload
:
18238 case OMPC_dynamic_allocators
:
18239 case OMPC_atomic_default_mem_order
:
18240 case OMPC_device_type
:
18244 case OMPC_severity
:
18247 case OMPC_novariants
:
18248 case OMPC_nocontext
:
18250 case OMPC_uses_allocators
:
18254 llvm_unreachable("Clause is not allowed.");
18259 ExprResult
Sema::getOpenMPCapturedExpr(VarDecl
*Capture
, ExprValueKind VK
,
18260 ExprObjectKind OK
, SourceLocation Loc
) {
18261 ExprResult Res
= BuildDeclRefExpr(
18262 Capture
, Capture
->getType().getNonReferenceType(), VK_LValue
, Loc
);
18263 if (!Res
.isUsable())
18264 return ExprError();
18265 if (OK
== OK_Ordinary
&& !getLangOpts().CPlusPlus
) {
18266 Res
= CreateBuiltinUnaryOp(Loc
, UO_Deref
, Res
.get());
18267 if (!Res
.isUsable())
18268 return ExprError();
18270 if (VK
!= VK_LValue
&& Res
.get()->isGLValue()) {
18271 Res
= DefaultLvalueConversion(Res
.get());
18272 if (!Res
.isUsable())
18273 return ExprError();
18278 OMPClause
*Sema::ActOnOpenMPPrivateClause(ArrayRef
<Expr
*> VarList
,
18279 SourceLocation StartLoc
,
18280 SourceLocation LParenLoc
,
18281 SourceLocation EndLoc
) {
18282 SmallVector
<Expr
*, 8> Vars
;
18283 SmallVector
<Expr
*, 8> PrivateCopies
;
18284 bool IsImplicitClause
=
18285 StartLoc
.isInvalid() && LParenLoc
.isInvalid() && EndLoc
.isInvalid();
18286 for (Expr
*RefExpr
: VarList
) {
18287 assert(RefExpr
&& "NULL expr in OpenMP private clause.");
18288 SourceLocation ELoc
;
18289 SourceRange ERange
;
18290 Expr
*SimpleRefExpr
= RefExpr
;
18291 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
18293 // It will be analyzed later.
18294 Vars
.push_back(RefExpr
);
18295 PrivateCopies
.push_back(nullptr);
18297 ValueDecl
*D
= Res
.first
;
18301 QualType Type
= D
->getType();
18302 auto *VD
= dyn_cast
<VarDecl
>(D
);
18304 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18305 // A variable that appears in a private clause must not have an incomplete
18306 // type or a reference type.
18307 if (RequireCompleteType(ELoc
, Type
, diag::err_omp_private_incomplete_type
))
18309 Type
= Type
.getNonReferenceType();
18311 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18312 // A variable that is privatized must not have a const-qualified type
18313 // unless it is of class type with a mutable member. This restriction does
18314 // not apply to the firstprivate clause.
18316 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
18317 // A variable that appears in a private clause must not have a
18318 // const-qualified type unless it is of class type with a mutable member.
18319 if (rejectConstNotMutableType(*this, D
, Type
, OMPC_private
, ELoc
))
18322 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18324 // Variables with the predetermined data-sharing attributes may not be
18325 // listed in data-sharing attributes clauses, except for the cases
18326 // listed below. For these exceptions only, listing a predetermined
18327 // variable in a data-sharing attribute clause is allowed and overrides
18328 // the variable's predetermined data-sharing attributes.
18329 DSAStackTy::DSAVarData DVar
= DSAStack
->getTopDSA(D
, /*FromParent=*/false);
18330 if (DVar
.CKind
!= OMPC_unknown
&& DVar
.CKind
!= OMPC_private
) {
18331 Diag(ELoc
, diag::err_omp_wrong_dsa
) << getOpenMPClauseName(DVar
.CKind
)
18332 << getOpenMPClauseName(OMPC_private
);
18333 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18337 OpenMPDirectiveKind CurrDir
= DSAStack
->getCurrentDirective();
18338 // Variably modified types are not supported for tasks.
18339 if (!Type
->isAnyPointerType() && Type
->isVariablyModifiedType() &&
18340 isOpenMPTaskingDirective(CurrDir
)) {
18341 Diag(ELoc
, diag::err_omp_variably_modified_type_not_supported
)
18342 << getOpenMPClauseName(OMPC_private
) << Type
18343 << getOpenMPDirectiveName(CurrDir
);
18344 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
18345 VarDecl::DeclarationOnly
;
18346 Diag(D
->getLocation(),
18347 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
18352 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18353 // A list item cannot appear in both a map clause and a data-sharing
18354 // attribute clause on the same construct
18356 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18357 // A list item cannot appear in both a map clause and a data-sharing
18358 // attribute clause on the same construct unless the construct is a
18359 // combined construct.
18360 if ((LangOpts
.OpenMP
<= 45 && isOpenMPTargetExecutionDirective(CurrDir
)) ||
18361 CurrDir
== OMPD_target
) {
18362 OpenMPClauseKind ConflictKind
;
18363 if (DSAStack
->checkMappableExprComponentListsForDecl(
18364 VD
, /*CurrentRegionOnly=*/true,
18365 [&](OMPClauseMappableExprCommon::MappableExprComponentListRef
,
18366 OpenMPClauseKind WhereFoundClauseKind
) -> bool {
18367 ConflictKind
= WhereFoundClauseKind
;
18370 Diag(ELoc
, diag::err_omp_variable_in_given_clause_and_dsa
)
18371 << getOpenMPClauseName(OMPC_private
)
18372 << getOpenMPClauseName(ConflictKind
)
18373 << getOpenMPDirectiveName(CurrDir
);
18374 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18379 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
18380 // A variable of class type (or array thereof) that appears in a private
18381 // clause requires an accessible, unambiguous default constructor for the
18383 // Generate helper private variable and initialize it with the default
18384 // value. The address of the original variable is replaced by the address of
18385 // the new private variable in CodeGen. This new variable is not added to
18386 // IdResolver, so the code in the OpenMP region uses original variable for
18387 // proper diagnostics.
18388 Type
= Type
.getUnqualifiedType();
18389 VarDecl
*VDPrivate
=
18390 buildVarDecl(*this, ELoc
, Type
, D
->getName(),
18391 D
->hasAttrs() ? &D
->getAttrs() : nullptr,
18392 VD
? cast
<DeclRefExpr
>(SimpleRefExpr
) : nullptr);
18393 ActOnUninitializedDecl(VDPrivate
);
18394 if (VDPrivate
->isInvalidDecl())
18396 DeclRefExpr
*VDPrivateRefExpr
= buildDeclRefExpr(
18397 *this, VDPrivate
, RefExpr
->getType().getUnqualifiedType(), ELoc
);
18399 DeclRefExpr
*Ref
= nullptr;
18400 if (!VD
&& !CurContext
->isDependentContext()) {
18401 auto *FD
= dyn_cast
<FieldDecl
>(D
);
18402 VarDecl
*VD
= FD
? DSAStack
->getImplicitFDCapExprDecl(FD
) : nullptr;
18404 Ref
= buildDeclRefExpr(*this, VD
, VD
->getType().getNonReferenceType(),
18405 RefExpr
->getExprLoc());
18407 Ref
= buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/false);
18409 if (!IsImplicitClause
)
18410 DSAStack
->addDSA(D
, RefExpr
->IgnoreParens(), OMPC_private
, Ref
);
18411 Vars
.push_back((VD
|| CurContext
->isDependentContext())
18412 ? RefExpr
->IgnoreParens()
18414 PrivateCopies
.push_back(VDPrivateRefExpr
);
18420 return OMPPrivateClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
, Vars
,
18424 OMPClause
*Sema::ActOnOpenMPFirstprivateClause(ArrayRef
<Expr
*> VarList
,
18425 SourceLocation StartLoc
,
18426 SourceLocation LParenLoc
,
18427 SourceLocation EndLoc
) {
18428 SmallVector
<Expr
*, 8> Vars
;
18429 SmallVector
<Expr
*, 8> PrivateCopies
;
18430 SmallVector
<Expr
*, 8> Inits
;
18431 SmallVector
<Decl
*, 4> ExprCaptures
;
18432 bool IsImplicitClause
=
18433 StartLoc
.isInvalid() && LParenLoc
.isInvalid() && EndLoc
.isInvalid();
18434 SourceLocation ImplicitClauseLoc
= DSAStack
->getConstructLoc();
18436 for (Expr
*RefExpr
: VarList
) {
18437 assert(RefExpr
&& "NULL expr in OpenMP firstprivate clause.");
18438 SourceLocation ELoc
;
18439 SourceRange ERange
;
18440 Expr
*SimpleRefExpr
= RefExpr
;
18441 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
18443 // It will be analyzed later.
18444 Vars
.push_back(RefExpr
);
18445 PrivateCopies
.push_back(nullptr);
18446 Inits
.push_back(nullptr);
18448 ValueDecl
*D
= Res
.first
;
18452 ELoc
= IsImplicitClause
? ImplicitClauseLoc
: ELoc
;
18453 QualType Type
= D
->getType();
18454 auto *VD
= dyn_cast
<VarDecl
>(D
);
18456 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18457 // A variable that appears in a private clause must not have an incomplete
18458 // type or a reference type.
18459 if (RequireCompleteType(ELoc
, Type
,
18460 diag::err_omp_firstprivate_incomplete_type
))
18462 Type
= Type
.getNonReferenceType();
18464 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
18465 // A variable of class type (or array thereof) that appears in a private
18466 // clause requires an accessible, unambiguous copy constructor for the
18468 QualType ElemType
= Context
.getBaseElementType(Type
).getNonReferenceType();
18470 // If an implicit firstprivate variable found it was checked already.
18471 DSAStackTy::DSAVarData TopDVar
;
18472 if (!IsImplicitClause
) {
18473 DSAStackTy::DSAVarData DVar
=
18474 DSAStack
->getTopDSA(D
, /*FromParent=*/false);
18476 OpenMPDirectiveKind CurrDir
= DSAStack
->getCurrentDirective();
18477 bool IsConstant
= ElemType
.isConstant(Context
);
18478 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
18479 // A list item that specifies a given variable may not appear in more
18480 // than one clause on the same directive, except that a variable may be
18481 // specified in both firstprivate and lastprivate clauses.
18482 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18483 // A list item may appear in a firstprivate or lastprivate clause but not
18485 if (DVar
.CKind
!= OMPC_unknown
&& DVar
.CKind
!= OMPC_firstprivate
&&
18486 (isOpenMPDistributeDirective(CurrDir
) ||
18487 DVar
.CKind
!= OMPC_lastprivate
) &&
18489 Diag(ELoc
, diag::err_omp_wrong_dsa
)
18490 << getOpenMPClauseName(DVar
.CKind
)
18491 << getOpenMPClauseName(OMPC_firstprivate
);
18492 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18496 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18498 // Variables with the predetermined data-sharing attributes may not be
18499 // listed in data-sharing attributes clauses, except for the cases
18500 // listed below. For these exceptions only, listing a predetermined
18501 // variable in a data-sharing attribute clause is allowed and overrides
18502 // the variable's predetermined data-sharing attributes.
18503 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18504 // in a Construct, C/C++, p.2]
18505 // Variables with const-qualified type having no mutable member may be
18506 // listed in a firstprivate clause, even if they are static data members.
18507 if (!(IsConstant
|| (VD
&& VD
->isStaticDataMember())) && !DVar
.RefExpr
&&
18508 DVar
.CKind
!= OMPC_unknown
&& DVar
.CKind
!= OMPC_shared
) {
18509 Diag(ELoc
, diag::err_omp_wrong_dsa
)
18510 << getOpenMPClauseName(DVar
.CKind
)
18511 << getOpenMPClauseName(OMPC_firstprivate
);
18512 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18516 // OpenMP [2.9.3.4, Restrictions, p.2]
18517 // A list item that is private within a parallel region must not appear
18518 // in a firstprivate clause on a worksharing construct if any of the
18519 // worksharing regions arising from the worksharing construct ever bind
18520 // to any of the parallel regions arising from the parallel construct.
18521 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18522 // A list item that is private within a teams region must not appear in a
18523 // firstprivate clause on a distribute construct if any of the distribute
18524 // regions arising from the distribute construct ever bind to any of the
18525 // teams regions arising from the teams construct.
18526 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18527 // A list item that appears in a reduction clause of a teams construct
18528 // must not appear in a firstprivate clause on a distribute construct if
18529 // any of the distribute regions arising from the distribute construct
18530 // ever bind to any of the teams regions arising from the teams construct.
18531 if ((isOpenMPWorksharingDirective(CurrDir
) ||
18532 isOpenMPDistributeDirective(CurrDir
)) &&
18533 !isOpenMPParallelDirective(CurrDir
) &&
18534 !isOpenMPTeamsDirective(CurrDir
)) {
18535 DVar
= DSAStack
->getImplicitDSA(D
, true);
18536 if (DVar
.CKind
!= OMPC_shared
&&
18537 (isOpenMPParallelDirective(DVar
.DKind
) ||
18538 isOpenMPTeamsDirective(DVar
.DKind
) ||
18539 DVar
.DKind
== OMPD_unknown
)) {
18540 Diag(ELoc
, diag::err_omp_required_access
)
18541 << getOpenMPClauseName(OMPC_firstprivate
)
18542 << getOpenMPClauseName(OMPC_shared
);
18543 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18547 // OpenMP [2.9.3.4, Restrictions, p.3]
18548 // A list item that appears in a reduction clause of a parallel construct
18549 // must not appear in a firstprivate clause on a worksharing or task
18550 // construct if any of the worksharing or task regions arising from the
18551 // worksharing or task construct ever bind to any of the parallel regions
18552 // arising from the parallel construct.
18553 // OpenMP [2.9.3.4, Restrictions, p.4]
18554 // A list item that appears in a reduction clause in worksharing
18555 // construct must not appear in a firstprivate clause in a task construct
18556 // encountered during execution of any of the worksharing regions arising
18557 // from the worksharing construct.
18558 if (isOpenMPTaskingDirective(CurrDir
)) {
18559 DVar
= DSAStack
->hasInnermostDSA(
18561 [](OpenMPClauseKind C
, bool AppliedToPointee
) {
18562 return C
== OMPC_reduction
&& !AppliedToPointee
;
18564 [](OpenMPDirectiveKind K
) {
18565 return isOpenMPParallelDirective(K
) ||
18566 isOpenMPWorksharingDirective(K
) ||
18567 isOpenMPTeamsDirective(K
);
18569 /*FromParent=*/true);
18570 if (DVar
.CKind
== OMPC_reduction
&&
18571 (isOpenMPParallelDirective(DVar
.DKind
) ||
18572 isOpenMPWorksharingDirective(DVar
.DKind
) ||
18573 isOpenMPTeamsDirective(DVar
.DKind
))) {
18574 Diag(ELoc
, diag::err_omp_parallel_reduction_in_task_firstprivate
)
18575 << getOpenMPDirectiveName(DVar
.DKind
);
18576 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18581 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18582 // A list item cannot appear in both a map clause and a data-sharing
18583 // attribute clause on the same construct
18585 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18586 // A list item cannot appear in both a map clause and a data-sharing
18587 // attribute clause on the same construct unless the construct is a
18588 // combined construct.
18589 if ((LangOpts
.OpenMP
<= 45 &&
18590 isOpenMPTargetExecutionDirective(CurrDir
)) ||
18591 CurrDir
== OMPD_target
) {
18592 OpenMPClauseKind ConflictKind
;
18593 if (DSAStack
->checkMappableExprComponentListsForDecl(
18594 VD
, /*CurrentRegionOnly=*/true,
18596 OMPClauseMappableExprCommon::MappableExprComponentListRef
,
18597 OpenMPClauseKind WhereFoundClauseKind
) {
18598 ConflictKind
= WhereFoundClauseKind
;
18601 Diag(ELoc
, diag::err_omp_variable_in_given_clause_and_dsa
)
18602 << getOpenMPClauseName(OMPC_firstprivate
)
18603 << getOpenMPClauseName(ConflictKind
)
18604 << getOpenMPDirectiveName(DSAStack
->getCurrentDirective());
18605 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18611 // Variably modified types are not supported for tasks.
18612 if (!Type
->isAnyPointerType() && Type
->isVariablyModifiedType() &&
18613 isOpenMPTaskingDirective(DSAStack
->getCurrentDirective())) {
18614 Diag(ELoc
, diag::err_omp_variably_modified_type_not_supported
)
18615 << getOpenMPClauseName(OMPC_firstprivate
) << Type
18616 << getOpenMPDirectiveName(DSAStack
->getCurrentDirective());
18617 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
18618 VarDecl::DeclarationOnly
;
18619 Diag(D
->getLocation(),
18620 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
18625 Type
= Type
.getUnqualifiedType();
18626 VarDecl
*VDPrivate
=
18627 buildVarDecl(*this, ELoc
, Type
, D
->getName(),
18628 D
->hasAttrs() ? &D
->getAttrs() : nullptr,
18629 VD
? cast
<DeclRefExpr
>(SimpleRefExpr
) : nullptr);
18630 // Generate helper private variable and initialize it with the value of the
18631 // original variable. The address of the original variable is replaced by
18632 // the address of the new private variable in the CodeGen. This new variable
18633 // is not added to IdResolver, so the code in the OpenMP region uses
18634 // original variable for proper diagnostics and variable capturing.
18635 Expr
*VDInitRefExpr
= nullptr;
18636 // For arrays generate initializer for single element and replace it by the
18637 // original array element in CodeGen.
18638 if (Type
->isArrayType()) {
18640 buildVarDecl(*this, RefExpr
->getExprLoc(), ElemType
, D
->getName());
18641 VDInitRefExpr
= buildDeclRefExpr(*this, VDInit
, ElemType
, ELoc
);
18642 Expr
*Init
= DefaultLvalueConversion(VDInitRefExpr
).get();
18643 ElemType
= ElemType
.getUnqualifiedType();
18644 VarDecl
*VDInitTemp
= buildVarDecl(*this, RefExpr
->getExprLoc(), ElemType
,
18645 ".firstprivate.temp");
18646 InitializedEntity Entity
=
18647 InitializedEntity::InitializeVariable(VDInitTemp
);
18648 InitializationKind Kind
= InitializationKind::CreateCopy(ELoc
, ELoc
);
18650 InitializationSequence
InitSeq(*this, Entity
, Kind
, Init
);
18651 ExprResult Result
= InitSeq
.Perform(*this, Entity
, Kind
, Init
);
18652 if (Result
.isInvalid())
18653 VDPrivate
->setInvalidDecl();
18655 VDPrivate
->setInit(Result
.getAs
<Expr
>());
18656 // Remove temp variable declaration.
18657 Context
.Deallocate(VDInitTemp
);
18659 VarDecl
*VDInit
= buildVarDecl(*this, RefExpr
->getExprLoc(), Type
,
18660 ".firstprivate.temp");
18661 VDInitRefExpr
= buildDeclRefExpr(*this, VDInit
, RefExpr
->getType(),
18662 RefExpr
->getExprLoc());
18663 AddInitializerToDecl(VDPrivate
,
18664 DefaultLvalueConversion(VDInitRefExpr
).get(),
18665 /*DirectInit=*/false);
18667 if (VDPrivate
->isInvalidDecl()) {
18668 if (IsImplicitClause
) {
18669 Diag(RefExpr
->getExprLoc(),
18670 diag::note_omp_task_predetermined_firstprivate_here
);
18674 CurContext
->addDecl(VDPrivate
);
18675 DeclRefExpr
*VDPrivateRefExpr
= buildDeclRefExpr(
18676 *this, VDPrivate
, RefExpr
->getType().getUnqualifiedType(),
18677 RefExpr
->getExprLoc());
18678 DeclRefExpr
*Ref
= nullptr;
18679 if (!VD
&& !CurContext
->isDependentContext()) {
18680 if (TopDVar
.CKind
== OMPC_lastprivate
) {
18681 Ref
= TopDVar
.PrivateCopy
;
18683 auto *FD
= dyn_cast
<FieldDecl
>(D
);
18684 VarDecl
*VD
= FD
? DSAStack
->getImplicitFDCapExprDecl(FD
) : nullptr;
18686 Ref
= buildDeclRefExpr(*this, VD
, VD
->getType().getNonReferenceType(),
18687 RefExpr
->getExprLoc());
18689 Ref
= buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/true);
18690 if (VD
|| !isOpenMPCapturedDecl(D
))
18691 ExprCaptures
.push_back(Ref
->getDecl());
18694 if (!IsImplicitClause
)
18695 DSAStack
->addDSA(D
, RefExpr
->IgnoreParens(), OMPC_firstprivate
, Ref
);
18696 Vars
.push_back((VD
|| CurContext
->isDependentContext())
18697 ? RefExpr
->IgnoreParens()
18699 PrivateCopies
.push_back(VDPrivateRefExpr
);
18700 Inits
.push_back(VDInitRefExpr
);
18706 return OMPFirstprivateClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
,
18707 Vars
, PrivateCopies
, Inits
,
18708 buildPreInits(Context
, ExprCaptures
));
18711 OMPClause
*Sema::ActOnOpenMPLastprivateClause(
18712 ArrayRef
<Expr
*> VarList
, OpenMPLastprivateModifier LPKind
,
18713 SourceLocation LPKindLoc
, SourceLocation ColonLoc
, SourceLocation StartLoc
,
18714 SourceLocation LParenLoc
, SourceLocation EndLoc
) {
18715 if (LPKind
== OMPC_LASTPRIVATE_unknown
&& LPKindLoc
.isValid()) {
18716 assert(ColonLoc
.isValid() && "Colon location must be valid.");
18717 Diag(LPKindLoc
, diag::err_omp_unexpected_clause_value
)
18718 << getListOfPossibleValues(OMPC_lastprivate
, /*First=*/0,
18719 /*Last=*/OMPC_LASTPRIVATE_unknown
)
18720 << getOpenMPClauseName(OMPC_lastprivate
);
18724 SmallVector
<Expr
*, 8> Vars
;
18725 SmallVector
<Expr
*, 8> SrcExprs
;
18726 SmallVector
<Expr
*, 8> DstExprs
;
18727 SmallVector
<Expr
*, 8> AssignmentOps
;
18728 SmallVector
<Decl
*, 4> ExprCaptures
;
18729 SmallVector
<Expr
*, 4> ExprPostUpdates
;
18730 for (Expr
*RefExpr
: VarList
) {
18731 assert(RefExpr
&& "NULL expr in OpenMP lastprivate clause.");
18732 SourceLocation ELoc
;
18733 SourceRange ERange
;
18734 Expr
*SimpleRefExpr
= RefExpr
;
18735 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
18737 // It will be analyzed later.
18738 Vars
.push_back(RefExpr
);
18739 SrcExprs
.push_back(nullptr);
18740 DstExprs
.push_back(nullptr);
18741 AssignmentOps
.push_back(nullptr);
18743 ValueDecl
*D
= Res
.first
;
18747 QualType Type
= D
->getType();
18748 auto *VD
= dyn_cast
<VarDecl
>(D
);
18750 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
18751 // A variable that appears in a lastprivate clause must not have an
18752 // incomplete type or a reference type.
18753 if (RequireCompleteType(ELoc
, Type
,
18754 diag::err_omp_lastprivate_incomplete_type
))
18756 Type
= Type
.getNonReferenceType();
18758 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18759 // A variable that is privatized must not have a const-qualified type
18760 // unless it is of class type with a mutable member. This restriction does
18761 // not apply to the firstprivate clause.
18763 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
18764 // A variable that appears in a lastprivate clause must not have a
18765 // const-qualified type unless it is of class type with a mutable member.
18766 if (rejectConstNotMutableType(*this, D
, Type
, OMPC_lastprivate
, ELoc
))
18769 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
18770 // A list item that appears in a lastprivate clause with the conditional
18771 // modifier must be a scalar variable.
18772 if (LPKind
== OMPC_LASTPRIVATE_conditional
&& !Type
->isScalarType()) {
18773 Diag(ELoc
, diag::err_omp_lastprivate_conditional_non_scalar
);
18774 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
18775 VarDecl::DeclarationOnly
;
18776 Diag(D
->getLocation(),
18777 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
18782 OpenMPDirectiveKind CurrDir
= DSAStack
->getCurrentDirective();
18783 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
18785 // Variables with the predetermined data-sharing attributes may not be
18786 // listed in data-sharing attributes clauses, except for the cases
18788 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18789 // A list item may appear in a firstprivate or lastprivate clause but not
18791 DSAStackTy::DSAVarData DVar
= DSAStack
->getTopDSA(D
, /*FromParent=*/false);
18792 if (DVar
.CKind
!= OMPC_unknown
&& DVar
.CKind
!= OMPC_lastprivate
&&
18793 (isOpenMPDistributeDirective(CurrDir
) ||
18794 DVar
.CKind
!= OMPC_firstprivate
) &&
18795 (DVar
.CKind
!= OMPC_private
|| DVar
.RefExpr
!= nullptr)) {
18796 Diag(ELoc
, diag::err_omp_wrong_dsa
)
18797 << getOpenMPClauseName(DVar
.CKind
)
18798 << getOpenMPClauseName(OMPC_lastprivate
);
18799 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18803 // OpenMP [2.14.3.5, Restrictions, p.2]
18804 // A list item that is private within a parallel region, or that appears in
18805 // the reduction clause of a parallel construct, must not appear in a
18806 // lastprivate clause on a worksharing construct if any of the corresponding
18807 // worksharing regions ever binds to any of the corresponding parallel
18809 DSAStackTy::DSAVarData TopDVar
= DVar
;
18810 if (isOpenMPWorksharingDirective(CurrDir
) &&
18811 !isOpenMPParallelDirective(CurrDir
) &&
18812 !isOpenMPTeamsDirective(CurrDir
)) {
18813 DVar
= DSAStack
->getImplicitDSA(D
, true);
18814 if (DVar
.CKind
!= OMPC_shared
) {
18815 Diag(ELoc
, diag::err_omp_required_access
)
18816 << getOpenMPClauseName(OMPC_lastprivate
)
18817 << getOpenMPClauseName(OMPC_shared
);
18818 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18823 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
18824 // A variable of class type (or array thereof) that appears in a
18825 // lastprivate clause requires an accessible, unambiguous default
18826 // constructor for the class type, unless the list item is also specified
18827 // in a firstprivate clause.
18828 // A variable of class type (or array thereof) that appears in a
18829 // lastprivate clause requires an accessible, unambiguous copy assignment
18830 // operator for the class type.
18831 Type
= Context
.getBaseElementType(Type
).getNonReferenceType();
18832 VarDecl
*SrcVD
= buildVarDecl(*this, ERange
.getBegin(),
18833 Type
.getUnqualifiedType(), ".lastprivate.src",
18834 D
->hasAttrs() ? &D
->getAttrs() : nullptr);
18835 DeclRefExpr
*PseudoSrcExpr
=
18836 buildDeclRefExpr(*this, SrcVD
, Type
.getUnqualifiedType(), ELoc
);
18838 buildVarDecl(*this, ERange
.getBegin(), Type
, ".lastprivate.dst",
18839 D
->hasAttrs() ? &D
->getAttrs() : nullptr);
18840 DeclRefExpr
*PseudoDstExpr
= buildDeclRefExpr(*this, DstVD
, Type
, ELoc
);
18841 // For arrays generate assignment operation for single element and replace
18842 // it by the original array element in CodeGen.
18843 ExprResult AssignmentOp
= BuildBinOp(/*S=*/nullptr, ELoc
, BO_Assign
,
18844 PseudoDstExpr
, PseudoSrcExpr
);
18845 if (AssignmentOp
.isInvalid())
18848 ActOnFinishFullExpr(AssignmentOp
.get(), ELoc
, /*DiscardedValue*/ false);
18849 if (AssignmentOp
.isInvalid())
18852 DeclRefExpr
*Ref
= nullptr;
18853 if (!VD
&& !CurContext
->isDependentContext()) {
18854 if (TopDVar
.CKind
== OMPC_firstprivate
) {
18855 Ref
= TopDVar
.PrivateCopy
;
18857 Ref
= buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/false);
18858 if (!isOpenMPCapturedDecl(D
))
18859 ExprCaptures
.push_back(Ref
->getDecl());
18861 if ((TopDVar
.CKind
== OMPC_firstprivate
&& !TopDVar
.PrivateCopy
) ||
18862 (!isOpenMPCapturedDecl(D
) &&
18863 Ref
->getDecl()->hasAttr
<OMPCaptureNoInitAttr
>())) {
18864 ExprResult RefRes
= DefaultLvalueConversion(Ref
);
18865 if (!RefRes
.isUsable())
18867 ExprResult PostUpdateRes
=
18868 BuildBinOp(DSAStack
->getCurScope(), ELoc
, BO_Assign
, SimpleRefExpr
,
18870 if (!PostUpdateRes
.isUsable())
18872 ExprPostUpdates
.push_back(
18873 IgnoredValueConversions(PostUpdateRes
.get()).get());
18876 DSAStack
->addDSA(D
, RefExpr
->IgnoreParens(), OMPC_lastprivate
, Ref
);
18877 Vars
.push_back((VD
|| CurContext
->isDependentContext())
18878 ? RefExpr
->IgnoreParens()
18880 SrcExprs
.push_back(PseudoSrcExpr
);
18881 DstExprs
.push_back(PseudoDstExpr
);
18882 AssignmentOps
.push_back(AssignmentOp
.get());
18888 return OMPLastprivateClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
,
18889 Vars
, SrcExprs
, DstExprs
, AssignmentOps
,
18890 LPKind
, LPKindLoc
, ColonLoc
,
18891 buildPreInits(Context
, ExprCaptures
),
18892 buildPostUpdate(*this, ExprPostUpdates
));
18895 OMPClause
*Sema::ActOnOpenMPSharedClause(ArrayRef
<Expr
*> VarList
,
18896 SourceLocation StartLoc
,
18897 SourceLocation LParenLoc
,
18898 SourceLocation EndLoc
) {
18899 SmallVector
<Expr
*, 8> Vars
;
18900 for (Expr
*RefExpr
: VarList
) {
18901 assert(RefExpr
&& "NULL expr in OpenMP lastprivate clause.");
18902 SourceLocation ELoc
;
18903 SourceRange ERange
;
18904 Expr
*SimpleRefExpr
= RefExpr
;
18905 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
18907 // It will be analyzed later.
18908 Vars
.push_back(RefExpr
);
18910 ValueDecl
*D
= Res
.first
;
18914 auto *VD
= dyn_cast
<VarDecl
>(D
);
18915 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18917 // Variables with the predetermined data-sharing attributes may not be
18918 // listed in data-sharing attributes clauses, except for the cases
18919 // listed below. For these exceptions only, listing a predetermined
18920 // variable in a data-sharing attribute clause is allowed and overrides
18921 // the variable's predetermined data-sharing attributes.
18922 DSAStackTy::DSAVarData DVar
= DSAStack
->getTopDSA(D
, /*FromParent=*/false);
18923 if (DVar
.CKind
!= OMPC_unknown
&& DVar
.CKind
!= OMPC_shared
&&
18925 Diag(ELoc
, diag::err_omp_wrong_dsa
) << getOpenMPClauseName(DVar
.CKind
)
18926 << getOpenMPClauseName(OMPC_shared
);
18927 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
18931 DeclRefExpr
*Ref
= nullptr;
18932 if (!VD
&& isOpenMPCapturedDecl(D
) && !CurContext
->isDependentContext())
18933 Ref
= buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/true);
18934 DSAStack
->addDSA(D
, RefExpr
->IgnoreParens(), OMPC_shared
, Ref
);
18935 Vars
.push_back((VD
|| !Ref
|| CurContext
->isDependentContext())
18936 ? RefExpr
->IgnoreParens()
18943 return OMPSharedClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
, Vars
);
18947 class DSARefChecker
: public StmtVisitor
<DSARefChecker
, bool> {
18951 bool VisitDeclRefExpr(DeclRefExpr
*E
) {
18952 if (auto *VD
= dyn_cast
<VarDecl
>(E
->getDecl())) {
18953 DSAStackTy::DSAVarData DVar
= Stack
->getTopDSA(VD
, /*FromParent=*/false);
18954 if (DVar
.CKind
== OMPC_shared
&& !DVar
.RefExpr
)
18956 if (DVar
.CKind
!= OMPC_unknown
)
18958 DSAStackTy::DSAVarData DVarPrivate
= Stack
->hasDSA(
18960 [](OpenMPClauseKind C
, bool AppliedToPointee
, bool) {
18961 return isOpenMPPrivate(C
) && !AppliedToPointee
;
18963 [](OpenMPDirectiveKind
) { return true; },
18964 /*FromParent=*/true);
18965 return DVarPrivate
.CKind
!= OMPC_unknown
;
18969 bool VisitStmt(Stmt
*S
) {
18970 for (Stmt
*Child
: S
->children()) {
18971 if (Child
&& Visit(Child
))
18976 explicit DSARefChecker(DSAStackTy
*S
) : Stack(S
) {}
18981 // Transform MemberExpression for specified FieldDecl of current class to
18982 // DeclRefExpr to specified OMPCapturedExprDecl.
18983 class TransformExprToCaptures
: public TreeTransform
<TransformExprToCaptures
> {
18984 typedef TreeTransform
<TransformExprToCaptures
> BaseTransform
;
18985 ValueDecl
*Field
= nullptr;
18986 DeclRefExpr
*CapturedExpr
= nullptr;
18989 TransformExprToCaptures(Sema
&SemaRef
, ValueDecl
*FieldDecl
)
18990 : BaseTransform(SemaRef
), Field(FieldDecl
), CapturedExpr(nullptr) {}
18992 ExprResult
TransformMemberExpr(MemberExpr
*E
) {
18993 if (isa
<CXXThisExpr
>(E
->getBase()->IgnoreParenImpCasts()) &&
18994 E
->getMemberDecl() == Field
) {
18995 CapturedExpr
= buildCapture(SemaRef
, Field
, E
, /*WithInit=*/false);
18996 return CapturedExpr
;
18998 return BaseTransform::TransformMemberExpr(E
);
19000 DeclRefExpr
*getCapturedExpr() { return CapturedExpr
; }
19004 template <typename T
, typename U
>
19005 static T
filterLookupForUDReductionAndMapper(
19006 SmallVectorImpl
<U
> &Lookups
, const llvm::function_ref
<T(ValueDecl
*)> Gen
) {
19007 for (U
&Set
: Lookups
) {
19008 for (auto *D
: Set
) {
19009 if (T Res
= Gen(cast
<ValueDecl
>(D
)))
19016 static NamedDecl
*findAcceptableDecl(Sema
&SemaRef
, NamedDecl
*D
) {
19017 assert(!LookupResult::isVisible(SemaRef
, D
) && "not in slow case");
19019 for (auto *RD
: D
->redecls()) {
19020 // Don't bother with extra checks if we already know this one isn't visible.
19024 auto ND
= cast
<NamedDecl
>(RD
);
19025 if (LookupResult::isVisible(SemaRef
, ND
))
19033 argumentDependentLookup(Sema
&SemaRef
, const DeclarationNameInfo
&Id
,
19034 SourceLocation Loc
, QualType Ty
,
19035 SmallVectorImpl
<UnresolvedSet
<8>> &Lookups
) {
19036 // Find all of the associated namespaces and classes based on the
19037 // arguments we have.
19038 Sema::AssociatedNamespaceSet AssociatedNamespaces
;
19039 Sema::AssociatedClassSet AssociatedClasses
;
19040 OpaqueValueExpr
OVE(Loc
, Ty
, VK_LValue
);
19041 SemaRef
.FindAssociatedClassesAndNamespaces(Loc
, &OVE
, AssociatedNamespaces
,
19042 AssociatedClasses
);
19044 // C++ [basic.lookup.argdep]p3:
19045 // Let X be the lookup set produced by unqualified lookup (3.4.1)
19046 // and let Y be the lookup set produced by argument dependent
19047 // lookup (defined as follows). If X contains [...] then Y is
19048 // empty. Otherwise Y is the set of declarations found in the
19049 // namespaces associated with the argument types as described
19050 // below. The set of declarations found by the lookup of the name
19051 // is the union of X and Y.
19053 // Here, we compute Y and add its members to the overloaded
19055 for (auto *NS
: AssociatedNamespaces
) {
19056 // When considering an associated namespace, the lookup is the
19057 // same as the lookup performed when the associated namespace is
19058 // used as a qualifier (3.4.3.2) except that:
19060 // -- Any using-directives in the associated namespace are
19063 // -- Any namespace-scope friend functions declared in
19064 // associated classes are visible within their respective
19065 // namespaces even if they are not visible during an ordinary
19067 DeclContext::lookup_result R
= NS
->lookup(Id
.getName());
19068 for (auto *D
: R
) {
19069 auto *Underlying
= D
;
19070 if (auto *USD
= dyn_cast
<UsingShadowDecl
>(D
))
19071 Underlying
= USD
->getTargetDecl();
19073 if (!isa
<OMPDeclareReductionDecl
>(Underlying
) &&
19074 !isa
<OMPDeclareMapperDecl
>(Underlying
))
19077 if (!SemaRef
.isVisible(D
)) {
19078 D
= findAcceptableDecl(SemaRef
, D
);
19081 if (auto *USD
= dyn_cast
<UsingShadowDecl
>(D
))
19082 Underlying
= USD
->getTargetDecl();
19084 Lookups
.emplace_back();
19085 Lookups
.back().addDecl(Underlying
);
19091 buildDeclareReductionRef(Sema
&SemaRef
, SourceLocation Loc
, SourceRange Range
,
19092 Scope
*S
, CXXScopeSpec
&ReductionIdScopeSpec
,
19093 const DeclarationNameInfo
&ReductionId
, QualType Ty
,
19094 CXXCastPath
&BasePath
, Expr
*UnresolvedReduction
) {
19095 if (ReductionIdScopeSpec
.isInvalid())
19096 return ExprError();
19097 SmallVector
<UnresolvedSet
<8>, 4> Lookups
;
19099 LookupResult
Lookup(SemaRef
, ReductionId
, Sema::LookupOMPReductionName
);
19100 Lookup
.suppressDiagnostics();
19101 while (S
&& SemaRef
.LookupParsedName(Lookup
, S
, &ReductionIdScopeSpec
)) {
19102 NamedDecl
*D
= Lookup
.getRepresentativeDecl();
19104 S
= S
->getParent();
19105 } while (S
&& !S
->isDeclScope(D
));
19107 S
= S
->getParent();
19108 Lookups
.emplace_back();
19109 Lookups
.back().append(Lookup
.begin(), Lookup
.end());
19112 } else if (auto *ULE
=
19113 cast_or_null
<UnresolvedLookupExpr
>(UnresolvedReduction
)) {
19114 Lookups
.push_back(UnresolvedSet
<8>());
19115 Decl
*PrevD
= nullptr;
19116 for (NamedDecl
*D
: ULE
->decls()) {
19118 Lookups
.push_back(UnresolvedSet
<8>());
19119 else if (auto *DRD
= dyn_cast
<OMPDeclareReductionDecl
>(D
))
19120 Lookups
.back().addDecl(DRD
);
19124 if (SemaRef
.CurContext
->isDependentContext() || Ty
->isDependentType() ||
19125 Ty
->isInstantiationDependentType() ||
19126 Ty
->containsUnexpandedParameterPack() ||
19127 filterLookupForUDReductionAndMapper
<bool>(Lookups
, [](ValueDecl
*D
) {
19128 return !D
->isInvalidDecl() &&
19129 (D
->getType()->isDependentType() ||
19130 D
->getType()->isInstantiationDependentType() ||
19131 D
->getType()->containsUnexpandedParameterPack());
19133 UnresolvedSet
<8> ResSet
;
19134 for (const UnresolvedSet
<8> &Set
: Lookups
) {
19137 ResSet
.append(Set
.begin(), Set
.end());
19138 // The last item marks the end of all declarations at the specified scope.
19139 ResSet
.addDecl(Set
[Set
.size() - 1]);
19141 return UnresolvedLookupExpr::Create(
19142 SemaRef
.Context
, /*NamingClass=*/nullptr,
19143 ReductionIdScopeSpec
.getWithLocInContext(SemaRef
.Context
), ReductionId
,
19144 /*ADL=*/true, /*Overloaded=*/true, ResSet
.begin(), ResSet
.end());
19146 // Lookup inside the classes.
19147 // C++ [over.match.oper]p3:
19148 // For a unary operator @ with an operand of a type whose
19149 // cv-unqualified version is T1, and for a binary operator @ with
19150 // a left operand of a type whose cv-unqualified version is T1 and
19151 // a right operand of a type whose cv-unqualified version is T2,
19152 // three sets of candidate functions, designated member
19153 // candidates, non-member candidates and built-in candidates, are
19154 // constructed as follows:
19155 // -- If T1 is a complete class type or a class currently being
19156 // defined, the set of member candidates is the result of the
19157 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
19158 // the set of member candidates is empty.
19159 LookupResult
Lookup(SemaRef
, ReductionId
, Sema::LookupOMPReductionName
);
19160 Lookup
.suppressDiagnostics();
19161 if (const auto *TyRec
= Ty
->getAs
<RecordType
>()) {
19162 // Complete the type if it can be completed.
19163 // If the type is neither complete nor being defined, bail out now.
19164 if (SemaRef
.isCompleteType(Loc
, Ty
) || TyRec
->isBeingDefined() ||
19165 TyRec
->getDecl()->getDefinition()) {
19167 SemaRef
.LookupQualifiedName(Lookup
, TyRec
->getDecl());
19168 if (Lookup
.empty()) {
19169 Lookups
.emplace_back();
19170 Lookups
.back().append(Lookup
.begin(), Lookup
.end());
19175 if (SemaRef
.getLangOpts().CPlusPlus
)
19176 argumentDependentLookup(SemaRef
, ReductionId
, Loc
, Ty
, Lookups
);
19177 if (auto *VD
= filterLookupForUDReductionAndMapper
<ValueDecl
*>(
19178 Lookups
, [&SemaRef
, Ty
](ValueDecl
*D
) -> ValueDecl
* {
19179 if (!D
->isInvalidDecl() &&
19180 SemaRef
.Context
.hasSameType(D
->getType(), Ty
))
19184 return SemaRef
.BuildDeclRefExpr(VD
, VD
->getType().getNonReferenceType(),
19186 if (SemaRef
.getLangOpts().CPlusPlus
) {
19187 if (auto *VD
= filterLookupForUDReductionAndMapper
<ValueDecl
*>(
19188 Lookups
, [&SemaRef
, Ty
, Loc
](ValueDecl
*D
) -> ValueDecl
* {
19189 if (!D
->isInvalidDecl() &&
19190 SemaRef
.IsDerivedFrom(Loc
, Ty
, D
->getType()) &&
19191 !Ty
.isMoreQualifiedThan(D
->getType()))
19195 CXXBasePaths
Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
19196 /*DetectVirtual=*/false);
19197 if (SemaRef
.IsDerivedFrom(Loc
, Ty
, VD
->getType(), Paths
)) {
19198 if (!Paths
.isAmbiguous(SemaRef
.Context
.getCanonicalType(
19199 VD
->getType().getUnqualifiedType()))) {
19200 if (SemaRef
.CheckBaseClassAccess(
19201 Loc
, VD
->getType(), Ty
, Paths
.front(),
19202 /*DiagID=*/0) != Sema::AR_inaccessible
) {
19203 SemaRef
.BuildBasePathArray(Paths
, BasePath
);
19204 return SemaRef
.BuildDeclRefExpr(
19205 VD
, VD
->getType().getNonReferenceType(), VK_LValue
, Loc
);
19211 if (ReductionIdScopeSpec
.isSet()) {
19212 SemaRef
.Diag(Loc
, diag::err_omp_not_resolved_reduction_identifier
)
19214 return ExprError();
19216 return ExprEmpty();
19220 /// Data for the reduction-based clauses.
19221 struct ReductionData
{
19222 /// List of original reduction items.
19223 SmallVector
<Expr
*, 8> Vars
;
19224 /// List of private copies of the reduction items.
19225 SmallVector
<Expr
*, 8> Privates
;
19226 /// LHS expressions for the reduction_op expressions.
19227 SmallVector
<Expr
*, 8> LHSs
;
19228 /// RHS expressions for the reduction_op expressions.
19229 SmallVector
<Expr
*, 8> RHSs
;
19230 /// Reduction operation expression.
19231 SmallVector
<Expr
*, 8> ReductionOps
;
19232 /// inscan copy operation expressions.
19233 SmallVector
<Expr
*, 8> InscanCopyOps
;
19234 /// inscan copy temp array expressions for prefix sums.
19235 SmallVector
<Expr
*, 8> InscanCopyArrayTemps
;
19236 /// inscan copy temp array element expressions for prefix sums.
19237 SmallVector
<Expr
*, 8> InscanCopyArrayElems
;
19238 /// Taskgroup descriptors for the corresponding reduction items in
19239 /// in_reduction clauses.
19240 SmallVector
<Expr
*, 8> TaskgroupDescriptors
;
19241 /// List of captures for clause.
19242 SmallVector
<Decl
*, 4> ExprCaptures
;
19243 /// List of postupdate expressions.
19244 SmallVector
<Expr
*, 4> ExprPostUpdates
;
19245 /// Reduction modifier.
19246 unsigned RedModifier
= 0;
19247 ReductionData() = delete;
19248 /// Reserves required memory for the reduction data.
19249 ReductionData(unsigned Size
, unsigned Modifier
= 0) : RedModifier(Modifier
) {
19250 Vars
.reserve(Size
);
19251 Privates
.reserve(Size
);
19252 LHSs
.reserve(Size
);
19253 RHSs
.reserve(Size
);
19254 ReductionOps
.reserve(Size
);
19255 if (RedModifier
== OMPC_REDUCTION_inscan
) {
19256 InscanCopyOps
.reserve(Size
);
19257 InscanCopyArrayTemps
.reserve(Size
);
19258 InscanCopyArrayElems
.reserve(Size
);
19260 TaskgroupDescriptors
.reserve(Size
);
19261 ExprCaptures
.reserve(Size
);
19262 ExprPostUpdates
.reserve(Size
);
19264 /// Stores reduction item and reduction operation only (required for dependent
19265 /// reduction item).
19266 void push(Expr
*Item
, Expr
*ReductionOp
) {
19267 Vars
.emplace_back(Item
);
19268 Privates
.emplace_back(nullptr);
19269 LHSs
.emplace_back(nullptr);
19270 RHSs
.emplace_back(nullptr);
19271 ReductionOps
.emplace_back(ReductionOp
);
19272 TaskgroupDescriptors
.emplace_back(nullptr);
19273 if (RedModifier
== OMPC_REDUCTION_inscan
) {
19274 InscanCopyOps
.push_back(nullptr);
19275 InscanCopyArrayTemps
.push_back(nullptr);
19276 InscanCopyArrayElems
.push_back(nullptr);
19279 /// Stores reduction data.
19280 void push(Expr
*Item
, Expr
*Private
, Expr
*LHS
, Expr
*RHS
, Expr
*ReductionOp
,
19281 Expr
*TaskgroupDescriptor
, Expr
*CopyOp
, Expr
*CopyArrayTemp
,
19282 Expr
*CopyArrayElem
) {
19283 Vars
.emplace_back(Item
);
19284 Privates
.emplace_back(Private
);
19285 LHSs
.emplace_back(LHS
);
19286 RHSs
.emplace_back(RHS
);
19287 ReductionOps
.emplace_back(ReductionOp
);
19288 TaskgroupDescriptors
.emplace_back(TaskgroupDescriptor
);
19289 if (RedModifier
== OMPC_REDUCTION_inscan
) {
19290 InscanCopyOps
.push_back(CopyOp
);
19291 InscanCopyArrayTemps
.push_back(CopyArrayTemp
);
19292 InscanCopyArrayElems
.push_back(CopyArrayElem
);
19294 assert(CopyOp
== nullptr && CopyArrayTemp
== nullptr &&
19295 CopyArrayElem
== nullptr &&
19296 "Copy operation must be used for inscan reductions only.");
19302 static bool checkOMPArraySectionConstantForReduction(
19303 ASTContext
&Context
, const OMPArraySectionExpr
*OASE
, bool &SingleElement
,
19304 SmallVectorImpl
<llvm::APSInt
> &ArraySizes
) {
19305 const Expr
*Length
= OASE
->getLength();
19306 if (Length
== nullptr) {
19307 // For array sections of the form [1:] or [:], we would need to analyze
19308 // the lower bound...
19309 if (OASE
->getColonLocFirst().isValid())
19312 // This is an array subscript which has implicit length 1!
19313 SingleElement
= true;
19314 ArraySizes
.push_back(llvm::APSInt::get(1));
19316 Expr::EvalResult Result
;
19317 if (!Length
->EvaluateAsInt(Result
, Context
))
19320 llvm::APSInt ConstantLengthValue
= Result
.Val
.getInt();
19321 SingleElement
= (ConstantLengthValue
.getSExtValue() == 1);
19322 ArraySizes
.push_back(ConstantLengthValue
);
19325 // Get the base of this array section and walk up from there.
19326 const Expr
*Base
= OASE
->getBase()->IgnoreParenImpCasts();
19328 // We require length = 1 for all array sections except the right-most to
19329 // guarantee that the memory region is contiguous and has no holes in it.
19330 while (const auto *TempOASE
= dyn_cast
<OMPArraySectionExpr
>(Base
)) {
19331 Length
= TempOASE
->getLength();
19332 if (Length
== nullptr) {
19333 // For array sections of the form [1:] or [:], we would need to analyze
19334 // the lower bound...
19335 if (OASE
->getColonLocFirst().isValid())
19338 // This is an array subscript which has implicit length 1!
19339 ArraySizes
.push_back(llvm::APSInt::get(1));
19341 Expr::EvalResult Result
;
19342 if (!Length
->EvaluateAsInt(Result
, Context
))
19345 llvm::APSInt ConstantLengthValue
= Result
.Val
.getInt();
19346 if (ConstantLengthValue
.getSExtValue() != 1)
19349 ArraySizes
.push_back(ConstantLengthValue
);
19351 Base
= TempOASE
->getBase()->IgnoreParenImpCasts();
19354 // If we have a single element, we don't need to add the implicit lengths.
19355 if (!SingleElement
) {
19356 while (const auto *TempASE
= dyn_cast
<ArraySubscriptExpr
>(Base
)) {
19357 // Has implicit length 1!
19358 ArraySizes
.push_back(llvm::APSInt::get(1));
19359 Base
= TempASE
->getBase()->IgnoreParenImpCasts();
19363 // This array section can be privatized as a single value or as a constant
19368 static BinaryOperatorKind
19369 getRelatedCompoundReductionOp(BinaryOperatorKind BOK
) {
19371 return BO_AddAssign
;
19373 return BO_MulAssign
;
19375 return BO_AndAssign
;
19377 return BO_OrAssign
;
19379 return BO_XorAssign
;
19383 static bool actOnOMPReductionKindClause(
19384 Sema
&S
, DSAStackTy
*Stack
, OpenMPClauseKind ClauseKind
,
19385 ArrayRef
<Expr
*> VarList
, SourceLocation StartLoc
, SourceLocation LParenLoc
,
19386 SourceLocation ColonLoc
, SourceLocation EndLoc
,
19387 CXXScopeSpec
&ReductionIdScopeSpec
, const DeclarationNameInfo
&ReductionId
,
19388 ArrayRef
<Expr
*> UnresolvedReductions
, ReductionData
&RD
) {
19389 DeclarationName DN
= ReductionId
.getName();
19390 OverloadedOperatorKind OOK
= DN
.getCXXOverloadedOperator();
19391 BinaryOperatorKind BOK
= BO_Comma
;
19393 ASTContext
&Context
= S
.Context
;
19394 // OpenMP [2.14.3.6, reduction clause]
19396 // reduction-identifier is either an identifier or one of the following
19397 // operators: +, -, *, &, |, ^, && and ||
19399 // reduction-identifier is either an id-expression or one of the following
19400 // operators: +, -, *, &, |, ^, && and ||
19406 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
19407 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
19408 // reduction identifier.
19409 if (S
.LangOpts
.OpenMP
> 52)
19435 case OO_Array_Delete
:
19444 case OO_GreaterEqual
:
19446 case OO_MinusEqual
:
19448 case OO_SlashEqual
:
19449 case OO_PercentEqual
:
19450 case OO_CaretEqual
:
19454 case OO_GreaterGreater
:
19455 case OO_LessLessEqual
:
19456 case OO_GreaterGreaterEqual
:
19457 case OO_EqualEqual
:
19458 case OO_ExclaimEqual
:
19461 case OO_MinusMinus
:
19467 case OO_Conditional
:
19469 case NUM_OVERLOADED_OPERATORS
:
19470 llvm_unreachable("Unexpected reduction identifier");
19472 if (IdentifierInfo
*II
= DN
.getAsIdentifierInfo()) {
19473 if (II
->isStr("max"))
19475 else if (II
->isStr("min"))
19481 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
19482 // A reduction clause with the minus (-) operator was deprecated
19483 if (OOK
== OO_Minus
&& S
.LangOpts
.OpenMP
== 52)
19484 S
.Diag(ReductionId
.getLoc(), diag::warn_omp_minus_in_reduction_deprecated
);
19486 SourceRange ReductionIdRange
;
19487 if (ReductionIdScopeSpec
.isValid())
19488 ReductionIdRange
.setBegin(ReductionIdScopeSpec
.getBeginLoc());
19490 ReductionIdRange
.setBegin(ReductionId
.getBeginLoc());
19491 ReductionIdRange
.setEnd(ReductionId
.getEndLoc());
19493 auto IR
= UnresolvedReductions
.begin(), ER
= UnresolvedReductions
.end();
19494 bool FirstIter
= true;
19495 for (Expr
*RefExpr
: VarList
) {
19496 assert(RefExpr
&& "nullptr expr in OpenMP reduction clause.");
19497 // OpenMP [2.1, C/C++]
19498 // A list item is a variable or array section, subject to the restrictions
19499 // specified in Section 2.4 on page 42 and in each of the sections
19500 // describing clauses and directives for which a list appears.
19501 // OpenMP [2.14.3.3, Restrictions, p.1]
19502 // A variable that is part of another variable (as an array or
19503 // structure element) cannot appear in a private clause.
19504 if (!FirstIter
&& IR
!= ER
)
19507 SourceLocation ELoc
;
19508 SourceRange ERange
;
19509 Expr
*SimpleRefExpr
= RefExpr
;
19510 auto Res
= getPrivateItem(S
, SimpleRefExpr
, ELoc
, ERange
,
19511 /*AllowArraySection=*/true);
19513 // Try to find 'declare reduction' corresponding construct before using
19514 // builtin/overloaded operators.
19515 QualType Type
= Context
.DependentTy
;
19516 CXXCastPath BasePath
;
19517 ExprResult DeclareReductionRef
= buildDeclareReductionRef(
19518 S
, ELoc
, ERange
, Stack
->getCurScope(), ReductionIdScopeSpec
,
19519 ReductionId
, Type
, BasePath
, IR
== ER
? nullptr : *IR
);
19520 Expr
*ReductionOp
= nullptr;
19521 if (S
.CurContext
->isDependentContext() &&
19522 (DeclareReductionRef
.isUnset() ||
19523 isa
<UnresolvedLookupExpr
>(DeclareReductionRef
.get())))
19524 ReductionOp
= DeclareReductionRef
.get();
19525 // It will be analyzed later.
19526 RD
.push(RefExpr
, ReductionOp
);
19528 ValueDecl
*D
= Res
.first
;
19532 Expr
*TaskgroupDescriptor
= nullptr;
19534 auto *ASE
= dyn_cast
<ArraySubscriptExpr
>(RefExpr
->IgnoreParens());
19535 auto *OASE
= dyn_cast
<OMPArraySectionExpr
>(RefExpr
->IgnoreParens());
19537 Type
= ASE
->getType().getNonReferenceType();
19539 QualType BaseType
=
19540 OMPArraySectionExpr::getBaseOriginalType(OASE
->getBase());
19541 if (const auto *ATy
= BaseType
->getAsArrayTypeUnsafe())
19542 Type
= ATy
->getElementType();
19544 Type
= BaseType
->getPointeeType();
19545 Type
= Type
.getNonReferenceType();
19547 Type
= Context
.getBaseElementType(D
->getType().getNonReferenceType());
19549 auto *VD
= dyn_cast
<VarDecl
>(D
);
19551 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19552 // A variable that appears in a private clause must not have an incomplete
19553 // type or a reference type.
19554 if (S
.RequireCompleteType(ELoc
, D
->getType(),
19555 diag::err_omp_reduction_incomplete_type
))
19557 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19558 // A list item that appears in a reduction clause must not be
19559 // const-qualified.
19560 if (rejectConstNotMutableType(S
, D
, Type
, ClauseKind
, ELoc
,
19561 /*AcceptIfMutable*/ false, ASE
|| OASE
))
19564 OpenMPDirectiveKind CurrDir
= Stack
->getCurrentDirective();
19565 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
19566 // If a list-item is a reference type then it must bind to the same object
19567 // for all threads of the team.
19568 if (!ASE
&& !OASE
) {
19570 VarDecl
*VDDef
= VD
->getDefinition();
19571 if (VD
->getType()->isReferenceType() && VDDef
&& VDDef
->hasInit()) {
19572 DSARefChecker
Check(Stack
);
19573 if (Check
.Visit(VDDef
->getInit())) {
19574 S
.Diag(ELoc
, diag::err_omp_reduction_ref_type_arg
)
19575 << getOpenMPClauseName(ClauseKind
) << ERange
;
19576 S
.Diag(VDDef
->getLocation(), diag::note_defined_here
) << VDDef
;
19582 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
19584 // Variables with the predetermined data-sharing attributes may not be
19585 // listed in data-sharing attributes clauses, except for the cases
19586 // listed below. For these exceptions only, listing a predetermined
19587 // variable in a data-sharing attribute clause is allowed and overrides
19588 // the variable's predetermined data-sharing attributes.
19589 // OpenMP [2.14.3.6, Restrictions, p.3]
19590 // Any number of reduction clauses can be specified on the directive,
19591 // but a list item can appear only once in the reduction clauses for that
19593 DSAStackTy::DSAVarData DVar
= Stack
->getTopDSA(D
, /*FromParent=*/false);
19594 if (DVar
.CKind
== OMPC_reduction
) {
19595 S
.Diag(ELoc
, diag::err_omp_once_referenced
)
19596 << getOpenMPClauseName(ClauseKind
);
19598 S
.Diag(DVar
.RefExpr
->getExprLoc(), diag::note_omp_referenced
);
19601 if (DVar
.CKind
!= OMPC_unknown
) {
19602 S
.Diag(ELoc
, diag::err_omp_wrong_dsa
)
19603 << getOpenMPClauseName(DVar
.CKind
)
19604 << getOpenMPClauseName(OMPC_reduction
);
19605 reportOriginalDsa(S
, Stack
, D
, DVar
);
19609 // OpenMP [2.14.3.6, Restrictions, p.1]
19610 // A list item that appears in a reduction clause of a worksharing
19611 // construct must be shared in the parallel regions to which any of the
19612 // worksharing regions arising from the worksharing construct bind.
19613 if (isOpenMPWorksharingDirective(CurrDir
) &&
19614 !isOpenMPParallelDirective(CurrDir
) &&
19615 !isOpenMPTeamsDirective(CurrDir
)) {
19616 DVar
= Stack
->getImplicitDSA(D
, true);
19617 if (DVar
.CKind
!= OMPC_shared
) {
19618 S
.Diag(ELoc
, diag::err_omp_required_access
)
19619 << getOpenMPClauseName(OMPC_reduction
)
19620 << getOpenMPClauseName(OMPC_shared
);
19621 reportOriginalDsa(S
, Stack
, D
, DVar
);
19626 // Threadprivates cannot be shared between threads, so dignose if the base
19627 // is a threadprivate variable.
19628 DSAStackTy::DSAVarData DVar
= Stack
->getTopDSA(D
, /*FromParent=*/false);
19629 if (DVar
.CKind
== OMPC_threadprivate
) {
19630 S
.Diag(ELoc
, diag::err_omp_wrong_dsa
)
19631 << getOpenMPClauseName(DVar
.CKind
)
19632 << getOpenMPClauseName(OMPC_reduction
);
19633 reportOriginalDsa(S
, Stack
, D
, DVar
);
19638 // Try to find 'declare reduction' corresponding construct before using
19639 // builtin/overloaded operators.
19640 CXXCastPath BasePath
;
19641 ExprResult DeclareReductionRef
= buildDeclareReductionRef(
19642 S
, ELoc
, ERange
, Stack
->getCurScope(), ReductionIdScopeSpec
,
19643 ReductionId
, Type
, BasePath
, IR
== ER
? nullptr : *IR
);
19644 if (DeclareReductionRef
.isInvalid())
19646 if (S
.CurContext
->isDependentContext() &&
19647 (DeclareReductionRef
.isUnset() ||
19648 isa
<UnresolvedLookupExpr
>(DeclareReductionRef
.get()))) {
19649 RD
.push(RefExpr
, DeclareReductionRef
.get());
19652 if (BOK
== BO_Comma
&& DeclareReductionRef
.isUnset()) {
19653 // Not allowed reduction identifier is found.
19654 if (S
.LangOpts
.OpenMP
> 52)
19655 S
.Diag(ReductionId
.getBeginLoc(),
19656 diag::err_omp_unknown_reduction_identifier_since_omp_6_0
)
19657 << Type
<< ReductionIdRange
;
19659 S
.Diag(ReductionId
.getBeginLoc(),
19660 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0
)
19661 << Type
<< ReductionIdRange
;
19665 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19666 // The type of a list item that appears in a reduction clause must be valid
19667 // for the reduction-identifier. For a max or min reduction in C, the type
19668 // of the list item must be an allowed arithmetic data type: char, int,
19669 // float, double, or _Bool, possibly modified with long, short, signed, or
19670 // unsigned. For a max or min reduction in C++, the type of the list item
19671 // must be an allowed arithmetic data type: char, wchar_t, int, float,
19672 // double, or bool, possibly modified with long, short, signed, or unsigned.
19673 if (DeclareReductionRef
.isUnset()) {
19674 if ((BOK
== BO_GT
|| BOK
== BO_LT
) &&
19675 !(Type
->isScalarType() ||
19676 (S
.getLangOpts().CPlusPlus
&& Type
->isArithmeticType()))) {
19677 S
.Diag(ELoc
, diag::err_omp_clause_not_arithmetic_type_arg
)
19678 << getOpenMPClauseName(ClauseKind
) << S
.getLangOpts().CPlusPlus
;
19679 if (!ASE
&& !OASE
) {
19680 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
19681 VarDecl::DeclarationOnly
;
19682 S
.Diag(D
->getLocation(),
19683 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
19688 if ((BOK
== BO_OrAssign
|| BOK
== BO_AndAssign
|| BOK
== BO_XorAssign
) &&
19689 !S
.getLangOpts().CPlusPlus
&& Type
->isFloatingType()) {
19690 S
.Diag(ELoc
, diag::err_omp_clause_floating_type_arg
)
19691 << getOpenMPClauseName(ClauseKind
);
19692 if (!ASE
&& !OASE
) {
19693 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
19694 VarDecl::DeclarationOnly
;
19695 S
.Diag(D
->getLocation(),
19696 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
19703 Type
= Type
.getNonLValueExprType(Context
).getUnqualifiedType();
19704 VarDecl
*LHSVD
= buildVarDecl(S
, ELoc
, Type
, ".reduction.lhs",
19705 D
->hasAttrs() ? &D
->getAttrs() : nullptr);
19706 VarDecl
*RHSVD
= buildVarDecl(S
, ELoc
, Type
, D
->getName(),
19707 D
->hasAttrs() ? &D
->getAttrs() : nullptr);
19708 QualType PrivateTy
= Type
;
19710 // Try if we can determine constant lengths for all array sections and avoid
19712 bool ConstantLengthOASE
= false;
19714 bool SingleElement
;
19715 llvm::SmallVector
<llvm::APSInt
, 4> ArraySizes
;
19716 ConstantLengthOASE
= checkOMPArraySectionConstantForReduction(
19717 Context
, OASE
, SingleElement
, ArraySizes
);
19719 // If we don't have a single element, we must emit a constant array type.
19720 if (ConstantLengthOASE
&& !SingleElement
) {
19721 for (llvm::APSInt
&Size
: ArraySizes
)
19722 PrivateTy
= Context
.getConstantArrayType(PrivateTy
, Size
, nullptr,
19723 ArraySizeModifier::Normal
,
19724 /*IndexTypeQuals=*/0);
19728 if ((OASE
&& !ConstantLengthOASE
) ||
19730 D
->getType().getNonReferenceType()->isVariablyModifiedType())) {
19731 if (!Context
.getTargetInfo().isVLASupported()) {
19732 if (isOpenMPTargetExecutionDirective(Stack
->getCurrentDirective())) {
19733 S
.Diag(ELoc
, diag::err_omp_reduction_vla_unsupported
) << !!OASE
;
19734 S
.Diag(ELoc
, diag::note_vla_unsupported
);
19737 S
.targetDiag(ELoc
, diag::err_omp_reduction_vla_unsupported
) << !!OASE
;
19738 S
.targetDiag(ELoc
, diag::note_vla_unsupported
);
19741 // For arrays/array sections only:
19742 // Create pseudo array type for private copy. The size for this array will
19743 // be generated during codegen.
19744 // For array subscripts or single variables Private Ty is the same as Type
19745 // (type of the variable or single array element).
19746 PrivateTy
= Context
.getVariableArrayType(
19749 OpaqueValueExpr(ELoc
, Context
.getSizeType(), VK_PRValue
),
19750 ArraySizeModifier::Normal
, /*IndexTypeQuals=*/0, SourceRange());
19751 } else if (!ASE
&& !OASE
&&
19752 Context
.getAsArrayType(D
->getType().getNonReferenceType())) {
19753 PrivateTy
= D
->getType().getNonReferenceType();
19756 VarDecl
*PrivateVD
=
19757 buildVarDecl(S
, ELoc
, PrivateTy
, D
->getName(),
19758 D
->hasAttrs() ? &D
->getAttrs() : nullptr,
19759 VD
? cast
<DeclRefExpr
>(SimpleRefExpr
) : nullptr);
19760 // Add initializer for private variable.
19761 Expr
*Init
= nullptr;
19762 DeclRefExpr
*LHSDRE
= buildDeclRefExpr(S
, LHSVD
, Type
, ELoc
);
19763 DeclRefExpr
*RHSDRE
= buildDeclRefExpr(S
, RHSVD
, Type
, ELoc
);
19764 if (DeclareReductionRef
.isUsable()) {
19765 auto *DRDRef
= DeclareReductionRef
.getAs
<DeclRefExpr
>();
19766 auto *DRD
= cast
<OMPDeclareReductionDecl
>(DRDRef
->getDecl());
19767 if (DRD
->getInitializer()) {
19769 RHSVD
->setInit(DRDRef
);
19770 RHSVD
->setInitStyle(VarDecl::CallInit
);
19778 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
19779 if (Type
->isScalarType() || Type
->isAnyComplexType())
19780 Init
= S
.ActOnIntegerConstant(ELoc
, /*Val=*/0).get();
19784 if (Type
->isScalarType() || Type
->isAnyComplexType()) {
19785 // '*' and '&&' reduction ops - initializer is '1'.
19786 Init
= S
.ActOnIntegerConstant(ELoc
, /*Val=*/1).get();
19790 // '&' reduction op - initializer is '~0'.
19791 QualType OrigType
= Type
;
19792 if (auto *ComplexTy
= OrigType
->getAs
<ComplexType
>())
19793 Type
= ComplexTy
->getElementType();
19794 if (Type
->isRealFloatingType()) {
19795 llvm::APFloat InitValue
= llvm::APFloat::getAllOnesValue(
19796 Context
.getFloatTypeSemantics(Type
));
19797 Init
= FloatingLiteral::Create(Context
, InitValue
, /*isexact=*/true,
19799 } else if (Type
->isScalarType()) {
19800 uint64_t Size
= Context
.getTypeSize(Type
);
19801 QualType IntTy
= Context
.getIntTypeForBitwidth(Size
, /*Signed=*/0);
19802 llvm::APInt InitValue
= llvm::APInt::getAllOnes(Size
);
19803 Init
= IntegerLiteral::Create(Context
, InitValue
, IntTy
, ELoc
);
19805 if (Init
&& OrigType
->isAnyComplexType()) {
19806 // Init = 0xFFFF + 0xFFFFi;
19807 auto *Im
= new (Context
) ImaginaryLiteral(Init
, OrigType
);
19808 Init
= S
.CreateBuiltinBinOp(ELoc
, BO_Add
, Init
, Im
).get();
19815 // 'min' reduction op - initializer is 'Largest representable number in
19816 // the reduction list item type'.
19817 // 'max' reduction op - initializer is 'Least representable number in
19818 // the reduction list item type'.
19819 if (Type
->isIntegerType() || Type
->isPointerType()) {
19820 bool IsSigned
= Type
->hasSignedIntegerRepresentation();
19821 uint64_t Size
= Context
.getTypeSize(Type
);
19823 Context
.getIntTypeForBitwidth(Size
, /*Signed=*/IsSigned
);
19824 llvm::APInt InitValue
=
19825 (BOK
!= BO_LT
) ? IsSigned
? llvm::APInt::getSignedMinValue(Size
)
19826 : llvm::APInt::getMinValue(Size
)
19827 : IsSigned
? llvm::APInt::getSignedMaxValue(Size
)
19828 : llvm::APInt::getMaxValue(Size
);
19829 Init
= IntegerLiteral::Create(Context
, InitValue
, IntTy
, ELoc
);
19830 if (Type
->isPointerType()) {
19831 // Cast to pointer type.
19832 ExprResult CastExpr
= S
.BuildCStyleCastExpr(
19833 ELoc
, Context
.getTrivialTypeSourceInfo(Type
, ELoc
), ELoc
, Init
);
19834 if (CastExpr
.isInvalid())
19836 Init
= CastExpr
.get();
19838 } else if (Type
->isRealFloatingType()) {
19839 llvm::APFloat InitValue
= llvm::APFloat::getLargest(
19840 Context
.getFloatTypeSemantics(Type
), BOK
!= BO_LT
);
19841 Init
= FloatingLiteral::Create(Context
, InitValue
, /*isexact=*/true,
19870 llvm_unreachable("Unexpected reduction operation");
19873 if (Init
&& DeclareReductionRef
.isUnset()) {
19874 S
.AddInitializerToDecl(RHSVD
, Init
, /*DirectInit=*/false);
19875 // Store initializer for single element in private copy. Will be used
19877 PrivateVD
->setInit(RHSVD
->getInit());
19878 PrivateVD
->setInitStyle(RHSVD
->getInitStyle());
19879 } else if (!Init
) {
19880 S
.ActOnUninitializedDecl(RHSVD
);
19881 // Store initializer for single element in private copy. Will be used
19883 PrivateVD
->setInit(RHSVD
->getInit());
19884 PrivateVD
->setInitStyle(RHSVD
->getInitStyle());
19886 if (RHSVD
->isInvalidDecl())
19888 if (!RHSVD
->hasInit() && DeclareReductionRef
.isUnset()) {
19889 S
.Diag(ELoc
, diag::err_omp_reduction_id_not_compatible
)
19890 << Type
<< ReductionIdRange
;
19891 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
19892 VarDecl::DeclarationOnly
;
19893 S
.Diag(D
->getLocation(),
19894 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
19898 DeclRefExpr
*PrivateDRE
= buildDeclRefExpr(S
, PrivateVD
, PrivateTy
, ELoc
);
19899 ExprResult ReductionOp
;
19900 if (DeclareReductionRef
.isUsable()) {
19901 QualType RedTy
= DeclareReductionRef
.get()->getType();
19902 QualType PtrRedTy
= Context
.getPointerType(RedTy
);
19903 ExprResult LHS
= S
.CreateBuiltinUnaryOp(ELoc
, UO_AddrOf
, LHSDRE
);
19904 ExprResult RHS
= S
.CreateBuiltinUnaryOp(ELoc
, UO_AddrOf
, RHSDRE
);
19905 if (!BasePath
.empty()) {
19906 LHS
= S
.DefaultLvalueConversion(LHS
.get());
19907 RHS
= S
.DefaultLvalueConversion(RHS
.get());
19908 LHS
= ImplicitCastExpr::Create(
19909 Context
, PtrRedTy
, CK_UncheckedDerivedToBase
, LHS
.get(), &BasePath
,
19910 LHS
.get()->getValueKind(), FPOptionsOverride());
19911 RHS
= ImplicitCastExpr::Create(
19912 Context
, PtrRedTy
, CK_UncheckedDerivedToBase
, RHS
.get(), &BasePath
,
19913 RHS
.get()->getValueKind(), FPOptionsOverride());
19915 FunctionProtoType::ExtProtoInfo EPI
;
19916 QualType Params
[] = {PtrRedTy
, PtrRedTy
};
19917 QualType FnTy
= Context
.getFunctionType(Context
.VoidTy
, Params
, EPI
);
19918 auto *OVE
= new (Context
) OpaqueValueExpr(
19919 ELoc
, Context
.getPointerType(FnTy
), VK_PRValue
, OK_Ordinary
,
19920 S
.DefaultLvalueConversion(DeclareReductionRef
.get()).get());
19921 Expr
*Args
[] = {LHS
.get(), RHS
.get()};
19923 CallExpr::Create(Context
, OVE
, Args
, Context
.VoidTy
, VK_PRValue
, ELoc
,
19924 S
.CurFPFeatureOverrides());
19926 BinaryOperatorKind CombBOK
= getRelatedCompoundReductionOp(BOK
);
19927 if (Type
->isRecordType() && CombBOK
!= BOK
) {
19928 Sema::TentativeAnalysisScope
Trap(S
);
19930 S
.BuildBinOp(Stack
->getCurScope(), ReductionId
.getBeginLoc(),
19931 CombBOK
, LHSDRE
, RHSDRE
);
19933 if (!ReductionOp
.isUsable()) {
19935 S
.BuildBinOp(Stack
->getCurScope(), ReductionId
.getBeginLoc(), BOK
,
19937 if (ReductionOp
.isUsable()) {
19938 if (BOK
!= BO_LT
&& BOK
!= BO_GT
) {
19940 S
.BuildBinOp(Stack
->getCurScope(), ReductionId
.getBeginLoc(),
19941 BO_Assign
, LHSDRE
, ReductionOp
.get());
19943 auto *ConditionalOp
= new (Context
)
19944 ConditionalOperator(ReductionOp
.get(), ELoc
, LHSDRE
, ELoc
,
19945 RHSDRE
, Type
, VK_LValue
, OK_Ordinary
);
19947 S
.BuildBinOp(Stack
->getCurScope(), ReductionId
.getBeginLoc(),
19948 BO_Assign
, LHSDRE
, ConditionalOp
);
19952 if (ReductionOp
.isUsable())
19953 ReductionOp
= S
.ActOnFinishFullExpr(ReductionOp
.get(),
19954 /*DiscardedValue*/ false);
19955 if (!ReductionOp
.isUsable())
19959 // Add copy operations for inscan reductions.
19961 ExprResult CopyOpRes
, TempArrayRes
, TempArrayElem
;
19962 if (ClauseKind
== OMPC_reduction
&&
19963 RD
.RedModifier
== OMPC_REDUCTION_inscan
) {
19964 ExprResult RHS
= S
.DefaultLvalueConversion(RHSDRE
);
19965 CopyOpRes
= S
.BuildBinOp(Stack
->getCurScope(), ELoc
, BO_Assign
, LHSDRE
,
19967 if (!CopyOpRes
.isUsable())
19970 S
.ActOnFinishFullExpr(CopyOpRes
.get(), /*DiscardedValue=*/true);
19971 if (!CopyOpRes
.isUsable())
19973 // For simd directive and simd-based directives in simd mode no need to
19974 // construct temp array, need just a single temp element.
19975 if (Stack
->getCurrentDirective() == OMPD_simd
||
19976 (S
.getLangOpts().OpenMPSimd
&&
19977 isOpenMPSimdDirective(Stack
->getCurrentDirective()))) {
19978 VarDecl
*TempArrayVD
=
19979 buildVarDecl(S
, ELoc
, PrivateTy
, D
->getName(),
19980 D
->hasAttrs() ? &D
->getAttrs() : nullptr);
19981 // Add a constructor to the temp decl.
19982 S
.ActOnUninitializedDecl(TempArrayVD
);
19983 TempArrayRes
= buildDeclRefExpr(S
, TempArrayVD
, PrivateTy
, ELoc
);
19985 // Build temp array for prefix sum.
19986 auto *Dim
= new (S
.Context
)
19987 OpaqueValueExpr(ELoc
, S
.Context
.getSizeType(), VK_PRValue
);
19988 QualType ArrayTy
= S
.Context
.getVariableArrayType(
19989 PrivateTy
, Dim
, ArraySizeModifier::Normal
,
19990 /*IndexTypeQuals=*/0, {ELoc
, ELoc
});
19991 VarDecl
*TempArrayVD
=
19992 buildVarDecl(S
, ELoc
, ArrayTy
, D
->getName(),
19993 D
->hasAttrs() ? &D
->getAttrs() : nullptr);
19994 // Add a constructor to the temp decl.
19995 S
.ActOnUninitializedDecl(TempArrayVD
);
19996 TempArrayRes
= buildDeclRefExpr(S
, TempArrayVD
, ArrayTy
, ELoc
);
19998 S
.DefaultFunctionArrayLvalueConversion(TempArrayRes
.get());
19999 auto *Idx
= new (S
.Context
)
20000 OpaqueValueExpr(ELoc
, S
.Context
.getSizeType(), VK_PRValue
);
20001 TempArrayElem
= S
.CreateBuiltinArraySubscriptExpr(TempArrayElem
.get(),
20006 // OpenMP [2.15.4.6, Restrictions, p.2]
20007 // A list item that appears in an in_reduction clause of a task construct
20008 // must appear in a task_reduction clause of a construct associated with a
20009 // taskgroup region that includes the participating task in its taskgroup
20010 // set. The construct associated with the innermost region that meets this
20011 // condition must specify the same reduction-identifier as the in_reduction
20013 if (ClauseKind
== OMPC_in_reduction
) {
20014 SourceRange ParentSR
;
20015 BinaryOperatorKind ParentBOK
;
20016 const Expr
*ParentReductionOp
= nullptr;
20017 Expr
*ParentBOKTD
= nullptr, *ParentReductionOpTD
= nullptr;
20018 DSAStackTy::DSAVarData ParentBOKDSA
=
20019 Stack
->getTopMostTaskgroupReductionData(D
, ParentSR
, ParentBOK
,
20021 DSAStackTy::DSAVarData ParentReductionOpDSA
=
20022 Stack
->getTopMostTaskgroupReductionData(
20023 D
, ParentSR
, ParentReductionOp
, ParentReductionOpTD
);
20024 bool IsParentBOK
= ParentBOKDSA
.DKind
!= OMPD_unknown
;
20025 bool IsParentReductionOp
= ParentReductionOpDSA
.DKind
!= OMPD_unknown
;
20026 if ((DeclareReductionRef
.isUnset() && IsParentReductionOp
) ||
20027 (DeclareReductionRef
.isUsable() && IsParentBOK
) ||
20028 (IsParentBOK
&& BOK
!= ParentBOK
) || IsParentReductionOp
) {
20029 bool EmitError
= true;
20030 if (IsParentReductionOp
&& DeclareReductionRef
.isUsable()) {
20031 llvm::FoldingSetNodeID RedId
, ParentRedId
;
20032 ParentReductionOp
->Profile(ParentRedId
, Context
, /*Canonical=*/true);
20033 DeclareReductionRef
.get()->Profile(RedId
, Context
,
20034 /*Canonical=*/true);
20035 EmitError
= RedId
!= ParentRedId
;
20038 S
.Diag(ReductionId
.getBeginLoc(),
20039 diag::err_omp_reduction_identifier_mismatch
)
20040 << ReductionIdRange
<< RefExpr
->getSourceRange();
20041 S
.Diag(ParentSR
.getBegin(),
20042 diag::note_omp_previous_reduction_identifier
)
20044 << (IsParentBOK
? ParentBOKDSA
.RefExpr
20045 : ParentReductionOpDSA
.RefExpr
)
20046 ->getSourceRange();
20050 TaskgroupDescriptor
= IsParentBOK
? ParentBOKTD
: ParentReductionOpTD
;
20053 DeclRefExpr
*Ref
= nullptr;
20054 Expr
*VarsExpr
= RefExpr
->IgnoreParens();
20055 if (!VD
&& !S
.CurContext
->isDependentContext()) {
20057 TransformExprToCaptures
RebuildToCapture(S
, D
);
20059 RebuildToCapture
.TransformExpr(RefExpr
->IgnoreParens()).get();
20060 Ref
= RebuildToCapture
.getCapturedExpr();
20062 VarsExpr
= Ref
= buildCapture(S
, D
, SimpleRefExpr
, /*WithInit=*/false);
20064 if (!S
.isOpenMPCapturedDecl(D
)) {
20065 RD
.ExprCaptures
.emplace_back(Ref
->getDecl());
20066 if (Ref
->getDecl()->hasAttr
<OMPCaptureNoInitAttr
>()) {
20067 ExprResult RefRes
= S
.DefaultLvalueConversion(Ref
);
20068 if (!RefRes
.isUsable())
20070 ExprResult PostUpdateRes
=
20071 S
.BuildBinOp(Stack
->getCurScope(), ELoc
, BO_Assign
, SimpleRefExpr
,
20073 if (!PostUpdateRes
.isUsable())
20075 if (isOpenMPTaskingDirective(Stack
->getCurrentDirective()) ||
20076 Stack
->getCurrentDirective() == OMPD_taskgroup
) {
20077 S
.Diag(RefExpr
->getExprLoc(),
20078 diag::err_omp_reduction_non_addressable_expression
)
20079 << RefExpr
->getSourceRange();
20082 RD
.ExprPostUpdates
.emplace_back(
20083 S
.IgnoredValueConversions(PostUpdateRes
.get()).get());
20087 // All reduction items are still marked as reduction (to do not increase
20088 // code base size).
20089 unsigned Modifier
= RD
.RedModifier
;
20090 // Consider task_reductions as reductions with task modifier. Required for
20091 // correct analysis of in_reduction clauses.
20092 if (CurrDir
== OMPD_taskgroup
&& ClauseKind
== OMPC_task_reduction
)
20093 Modifier
= OMPC_REDUCTION_task
;
20094 Stack
->addDSA(D
, RefExpr
->IgnoreParens(), OMPC_reduction
, Ref
, Modifier
,
20096 if (Modifier
== OMPC_REDUCTION_task
&&
20097 (CurrDir
== OMPD_taskgroup
||
20098 ((isOpenMPParallelDirective(CurrDir
) ||
20099 isOpenMPWorksharingDirective(CurrDir
)) &&
20100 !isOpenMPSimdDirective(CurrDir
)))) {
20101 if (DeclareReductionRef
.isUsable())
20102 Stack
->addTaskgroupReductionData(D
, ReductionIdRange
,
20103 DeclareReductionRef
.get());
20105 Stack
->addTaskgroupReductionData(D
, ReductionIdRange
, BOK
);
20107 RD
.push(VarsExpr
, PrivateDRE
, LHSDRE
, RHSDRE
, ReductionOp
.get(),
20108 TaskgroupDescriptor
, CopyOpRes
.get(), TempArrayRes
.get(),
20109 TempArrayElem
.get());
20111 return RD
.Vars
.empty();
20114 OMPClause
*Sema::ActOnOpenMPReductionClause(
20115 ArrayRef
<Expr
*> VarList
, OpenMPReductionClauseModifier Modifier
,
20116 SourceLocation StartLoc
, SourceLocation LParenLoc
,
20117 SourceLocation ModifierLoc
, SourceLocation ColonLoc
, SourceLocation EndLoc
,
20118 CXXScopeSpec
&ReductionIdScopeSpec
, const DeclarationNameInfo
&ReductionId
,
20119 ArrayRef
<Expr
*> UnresolvedReductions
) {
20120 if (ModifierLoc
.isValid() && Modifier
== OMPC_REDUCTION_unknown
) {
20121 Diag(LParenLoc
, diag::err_omp_unexpected_clause_value
)
20122 << getListOfPossibleValues(OMPC_reduction
, /*First=*/0,
20123 /*Last=*/OMPC_REDUCTION_unknown
)
20124 << getOpenMPClauseName(OMPC_reduction
);
20127 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
20128 // A reduction clause with the inscan reduction-modifier may only appear on a
20129 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
20130 // construct, a parallel worksharing-loop construct or a parallel
20131 // worksharing-loop SIMD construct.
20132 if (Modifier
== OMPC_REDUCTION_inscan
&&
20133 (DSAStack
->getCurrentDirective() != OMPD_for
&&
20134 DSAStack
->getCurrentDirective() != OMPD_for_simd
&&
20135 DSAStack
->getCurrentDirective() != OMPD_simd
&&
20136 DSAStack
->getCurrentDirective() != OMPD_parallel_for
&&
20137 DSAStack
->getCurrentDirective() != OMPD_parallel_for_simd
)) {
20138 Diag(ModifierLoc
, diag::err_omp_wrong_inscan_reduction
);
20142 ReductionData
RD(VarList
.size(), Modifier
);
20143 if (actOnOMPReductionKindClause(*this, DSAStack
, OMPC_reduction
, VarList
,
20144 StartLoc
, LParenLoc
, ColonLoc
, EndLoc
,
20145 ReductionIdScopeSpec
, ReductionId
,
20146 UnresolvedReductions
, RD
))
20149 return OMPReductionClause::Create(
20150 Context
, StartLoc
, LParenLoc
, ModifierLoc
, ColonLoc
, EndLoc
, Modifier
,
20151 RD
.Vars
, ReductionIdScopeSpec
.getWithLocInContext(Context
), ReductionId
,
20152 RD
.Privates
, RD
.LHSs
, RD
.RHSs
, RD
.ReductionOps
, RD
.InscanCopyOps
,
20153 RD
.InscanCopyArrayTemps
, RD
.InscanCopyArrayElems
,
20154 buildPreInits(Context
, RD
.ExprCaptures
),
20155 buildPostUpdate(*this, RD
.ExprPostUpdates
));
20158 OMPClause
*Sema::ActOnOpenMPTaskReductionClause(
20159 ArrayRef
<Expr
*> VarList
, SourceLocation StartLoc
, SourceLocation LParenLoc
,
20160 SourceLocation ColonLoc
, SourceLocation EndLoc
,
20161 CXXScopeSpec
&ReductionIdScopeSpec
, const DeclarationNameInfo
&ReductionId
,
20162 ArrayRef
<Expr
*> UnresolvedReductions
) {
20163 ReductionData
RD(VarList
.size());
20164 if (actOnOMPReductionKindClause(*this, DSAStack
, OMPC_task_reduction
, VarList
,
20165 StartLoc
, LParenLoc
, ColonLoc
, EndLoc
,
20166 ReductionIdScopeSpec
, ReductionId
,
20167 UnresolvedReductions
, RD
))
20170 return OMPTaskReductionClause::Create(
20171 Context
, StartLoc
, LParenLoc
, ColonLoc
, EndLoc
, RD
.Vars
,
20172 ReductionIdScopeSpec
.getWithLocInContext(Context
), ReductionId
,
20173 RD
.Privates
, RD
.LHSs
, RD
.RHSs
, RD
.ReductionOps
,
20174 buildPreInits(Context
, RD
.ExprCaptures
),
20175 buildPostUpdate(*this, RD
.ExprPostUpdates
));
20178 OMPClause
*Sema::ActOnOpenMPInReductionClause(
20179 ArrayRef
<Expr
*> VarList
, SourceLocation StartLoc
, SourceLocation LParenLoc
,
20180 SourceLocation ColonLoc
, SourceLocation EndLoc
,
20181 CXXScopeSpec
&ReductionIdScopeSpec
, const DeclarationNameInfo
&ReductionId
,
20182 ArrayRef
<Expr
*> UnresolvedReductions
) {
20183 ReductionData
RD(VarList
.size());
20184 if (actOnOMPReductionKindClause(*this, DSAStack
, OMPC_in_reduction
, VarList
,
20185 StartLoc
, LParenLoc
, ColonLoc
, EndLoc
,
20186 ReductionIdScopeSpec
, ReductionId
,
20187 UnresolvedReductions
, RD
))
20190 return OMPInReductionClause::Create(
20191 Context
, StartLoc
, LParenLoc
, ColonLoc
, EndLoc
, RD
.Vars
,
20192 ReductionIdScopeSpec
.getWithLocInContext(Context
), ReductionId
,
20193 RD
.Privates
, RD
.LHSs
, RD
.RHSs
, RD
.ReductionOps
, RD
.TaskgroupDescriptors
,
20194 buildPreInits(Context
, RD
.ExprCaptures
),
20195 buildPostUpdate(*this, RD
.ExprPostUpdates
));
20198 bool Sema::CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind
,
20199 SourceLocation LinLoc
) {
20200 if ((!LangOpts
.CPlusPlus
&& LinKind
!= OMPC_LINEAR_val
) ||
20201 LinKind
== OMPC_LINEAR_unknown
|| LinKind
== OMPC_LINEAR_step
) {
20202 Diag(LinLoc
, diag::err_omp_wrong_linear_modifier
) << LangOpts
.CPlusPlus
;
20208 bool Sema::CheckOpenMPLinearDecl(const ValueDecl
*D
, SourceLocation ELoc
,
20209 OpenMPLinearClauseKind LinKind
, QualType Type
,
20210 bool IsDeclareSimd
) {
20211 const auto *VD
= dyn_cast_or_null
<VarDecl
>(D
);
20212 // A variable must not have an incomplete type or a reference type.
20213 if (RequireCompleteType(ELoc
, Type
, diag::err_omp_linear_incomplete_type
))
20215 if ((LinKind
== OMPC_LINEAR_uval
|| LinKind
== OMPC_LINEAR_ref
) &&
20216 !Type
->isReferenceType()) {
20217 Diag(ELoc
, diag::err_omp_wrong_linear_modifier_non_reference
)
20218 << Type
<< getOpenMPSimpleClauseTypeName(OMPC_linear
, LinKind
);
20221 Type
= Type
.getNonReferenceType();
20223 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
20224 // A variable that is privatized must not have a const-qualified type
20225 // unless it is of class type with a mutable member. This restriction does
20226 // not apply to the firstprivate clause, nor to the linear clause on
20227 // declarative directives (like declare simd).
20228 if (!IsDeclareSimd
&&
20229 rejectConstNotMutableType(*this, D
, Type
, OMPC_linear
, ELoc
))
20232 // A list item must be of integral or pointer type.
20233 Type
= Type
.getUnqualifiedType().getCanonicalType();
20234 const auto *Ty
= Type
.getTypePtrOrNull();
20235 if (!Ty
|| (LinKind
!= OMPC_LINEAR_ref
&& !Ty
->isDependentType() &&
20236 !Ty
->isIntegralType(Context
) && !Ty
->isPointerType())) {
20237 Diag(ELoc
, diag::err_omp_linear_expected_int_or_ptr
) << Type
;
20239 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
20240 VarDecl::DeclarationOnly
;
20241 Diag(D
->getLocation(),
20242 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
20250 OMPClause
*Sema::ActOnOpenMPLinearClause(
20251 ArrayRef
<Expr
*> VarList
, Expr
*Step
, SourceLocation StartLoc
,
20252 SourceLocation LParenLoc
, OpenMPLinearClauseKind LinKind
,
20253 SourceLocation LinLoc
, SourceLocation ColonLoc
,
20254 SourceLocation StepModifierLoc
, SourceLocation EndLoc
) {
20255 SmallVector
<Expr
*, 8> Vars
;
20256 SmallVector
<Expr
*, 8> Privates
;
20257 SmallVector
<Expr
*, 8> Inits
;
20258 SmallVector
<Decl
*, 4> ExprCaptures
;
20259 SmallVector
<Expr
*, 4> ExprPostUpdates
;
20260 // OpenMP 5.2 [Section 5.4.6, linear clause]
20261 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
20263 if (LinLoc
.isValid() && StepModifierLoc
.isInvalid() && Step
&&
20264 getLangOpts().OpenMP
>= 52)
20265 Diag(Step
->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive
);
20266 if (CheckOpenMPLinearModifier(LinKind
, LinLoc
))
20267 LinKind
= OMPC_LINEAR_val
;
20268 for (Expr
*RefExpr
: VarList
) {
20269 assert(RefExpr
&& "NULL expr in OpenMP linear clause.");
20270 SourceLocation ELoc
;
20271 SourceRange ERange
;
20272 Expr
*SimpleRefExpr
= RefExpr
;
20273 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
20275 // It will be analyzed later.
20276 Vars
.push_back(RefExpr
);
20277 Privates
.push_back(nullptr);
20278 Inits
.push_back(nullptr);
20280 ValueDecl
*D
= Res
.first
;
20284 QualType Type
= D
->getType();
20285 auto *VD
= dyn_cast
<VarDecl
>(D
);
20287 // OpenMP [2.14.3.7, linear clause]
20288 // A list-item cannot appear in more than one linear clause.
20289 // A list-item that appears in a linear clause cannot appear in any
20290 // other data-sharing attribute clause.
20291 DSAStackTy::DSAVarData DVar
= DSAStack
->getTopDSA(D
, /*FromParent=*/false);
20292 if (DVar
.RefExpr
) {
20293 Diag(ELoc
, diag::err_omp_wrong_dsa
) << getOpenMPClauseName(DVar
.CKind
)
20294 << getOpenMPClauseName(OMPC_linear
);
20295 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
20299 if (CheckOpenMPLinearDecl(D
, ELoc
, LinKind
, Type
))
20301 Type
= Type
.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20303 // Build private copy of original var.
20305 buildVarDecl(*this, ELoc
, Type
, D
->getName(),
20306 D
->hasAttrs() ? &D
->getAttrs() : nullptr,
20307 VD
? cast
<DeclRefExpr
>(SimpleRefExpr
) : nullptr);
20308 DeclRefExpr
*PrivateRef
= buildDeclRefExpr(*this, Private
, Type
, ELoc
);
20309 // Build var to save initial value.
20310 VarDecl
*Init
= buildVarDecl(*this, ELoc
, Type
, ".linear.start");
20312 DeclRefExpr
*Ref
= nullptr;
20313 if (!VD
&& !CurContext
->isDependentContext()) {
20314 Ref
= buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/false);
20315 if (!isOpenMPCapturedDecl(D
)) {
20316 ExprCaptures
.push_back(Ref
->getDecl());
20317 if (Ref
->getDecl()->hasAttr
<OMPCaptureNoInitAttr
>()) {
20318 ExprResult RefRes
= DefaultLvalueConversion(Ref
);
20319 if (!RefRes
.isUsable())
20321 ExprResult PostUpdateRes
=
20322 BuildBinOp(DSAStack
->getCurScope(), ELoc
, BO_Assign
,
20323 SimpleRefExpr
, RefRes
.get());
20324 if (!PostUpdateRes
.isUsable())
20326 ExprPostUpdates
.push_back(
20327 IgnoredValueConversions(PostUpdateRes
.get()).get());
20331 if (LinKind
== OMPC_LINEAR_uval
)
20332 InitExpr
= VD
? VD
->getInit() : SimpleRefExpr
;
20334 InitExpr
= VD
? SimpleRefExpr
: Ref
;
20335 AddInitializerToDecl(Init
, DefaultLvalueConversion(InitExpr
).get(),
20336 /*DirectInit=*/false);
20337 DeclRefExpr
*InitRef
= buildDeclRefExpr(*this, Init
, Type
, ELoc
);
20339 DSAStack
->addDSA(D
, RefExpr
->IgnoreParens(), OMPC_linear
, Ref
);
20340 Vars
.push_back((VD
|| CurContext
->isDependentContext())
20341 ? RefExpr
->IgnoreParens()
20343 Privates
.push_back(PrivateRef
);
20344 Inits
.push_back(InitRef
);
20350 Expr
*StepExpr
= Step
;
20351 Expr
*CalcStepExpr
= nullptr;
20352 if (Step
&& !Step
->isValueDependent() && !Step
->isTypeDependent() &&
20353 !Step
->isInstantiationDependent() &&
20354 !Step
->containsUnexpandedParameterPack()) {
20355 SourceLocation StepLoc
= Step
->getBeginLoc();
20356 ExprResult Val
= PerformOpenMPImplicitIntegerConversion(StepLoc
, Step
);
20357 if (Val
.isInvalid())
20359 StepExpr
= Val
.get();
20361 // Build var to save the step value.
20363 buildVarDecl(*this, StepLoc
, StepExpr
->getType(), ".linear.step");
20364 ExprResult SaveRef
=
20365 buildDeclRefExpr(*this, SaveVar
, StepExpr
->getType(), StepLoc
);
20366 ExprResult CalcStep
=
20367 BuildBinOp(CurScope
, StepLoc
, BO_Assign
, SaveRef
.get(), StepExpr
);
20368 CalcStep
= ActOnFinishFullExpr(CalcStep
.get(), /*DiscardedValue*/ false);
20370 // Warn about zero linear step (it would be probably better specified as
20371 // making corresponding variables 'const').
20372 if (std::optional
<llvm::APSInt
> Result
=
20373 StepExpr
->getIntegerConstantExpr(Context
)) {
20374 if (!Result
->isNegative() && !Result
->isStrictlyPositive())
20375 Diag(StepLoc
, diag::warn_omp_linear_step_zero
)
20376 << Vars
[0] << (Vars
.size() > 1);
20377 } else if (CalcStep
.isUsable()) {
20378 // Calculate the step beforehand instead of doing this on each iteration.
20379 // (This is not used if the number of iterations may be kfold-ed).
20380 CalcStepExpr
= CalcStep
.get();
20384 return OMPLinearClause::Create(Context
, StartLoc
, LParenLoc
, LinKind
, LinLoc
,
20385 ColonLoc
, StepModifierLoc
, EndLoc
, Vars
,
20386 Privates
, Inits
, StepExpr
, CalcStepExpr
,
20387 buildPreInits(Context
, ExprCaptures
),
20388 buildPostUpdate(*this, ExprPostUpdates
));
20391 static bool FinishOpenMPLinearClause(OMPLinearClause
&Clause
, DeclRefExpr
*IV
,
20392 Expr
*NumIterations
, Sema
&SemaRef
,
20393 Scope
*S
, DSAStackTy
*Stack
) {
20394 // Walk the vars and build update/final expressions for the CodeGen.
20395 SmallVector
<Expr
*, 8> Updates
;
20396 SmallVector
<Expr
*, 8> Finals
;
20397 SmallVector
<Expr
*, 8> UsedExprs
;
20398 Expr
*Step
= Clause
.getStep();
20399 Expr
*CalcStep
= Clause
.getCalcStep();
20400 // OpenMP [2.14.3.7, linear clause]
20401 // If linear-step is not specified it is assumed to be 1.
20403 Step
= SemaRef
.ActOnIntegerConstant(SourceLocation(), 1).get();
20405 Step
= cast
<BinaryOperator
>(CalcStep
)->getLHS();
20406 bool HasErrors
= false;
20407 auto CurInit
= Clause
.inits().begin();
20408 auto CurPrivate
= Clause
.privates().begin();
20409 OpenMPLinearClauseKind LinKind
= Clause
.getModifier();
20410 for (Expr
*RefExpr
: Clause
.varlists()) {
20411 SourceLocation ELoc
;
20412 SourceRange ERange
;
20413 Expr
*SimpleRefExpr
= RefExpr
;
20414 auto Res
= getPrivateItem(SemaRef
, SimpleRefExpr
, ELoc
, ERange
);
20415 ValueDecl
*D
= Res
.first
;
20416 if (Res
.second
|| !D
) {
20417 Updates
.push_back(nullptr);
20418 Finals
.push_back(nullptr);
20422 auto &&Info
= Stack
->isLoopControlVariable(D
);
20423 // OpenMP [2.15.11, distribute simd Construct]
20424 // A list item may not appear in a linear clause, unless it is the loop
20425 // iteration variable.
20426 if (isOpenMPDistributeDirective(Stack
->getCurrentDirective()) &&
20427 isOpenMPSimdDirective(Stack
->getCurrentDirective()) && !Info
.first
) {
20429 diag::err_omp_linear_distribute_var_non_loop_iteration
);
20430 Updates
.push_back(nullptr);
20431 Finals
.push_back(nullptr);
20435 Expr
*InitExpr
= *CurInit
;
20437 // Build privatized reference to the current linear var.
20438 auto *DE
= cast
<DeclRefExpr
>(SimpleRefExpr
);
20440 if (LinKind
== OMPC_LINEAR_uval
)
20441 CapturedRef
= cast
<VarDecl
>(DE
->getDecl())->getInit();
20444 buildDeclRefExpr(SemaRef
, cast
<VarDecl
>(DE
->getDecl()),
20445 DE
->getType().getUnqualifiedType(), DE
->getExprLoc(),
20446 /*RefersToCapture=*/true);
20448 // Build update: Var = InitExpr + IV * Step
20451 Update
= buildCounterUpdate(
20452 SemaRef
, S
, RefExpr
->getExprLoc(), *CurPrivate
, InitExpr
, IV
, Step
,
20453 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
20455 Update
= *CurPrivate
;
20456 Update
= SemaRef
.ActOnFinishFullExpr(Update
.get(), DE
->getBeginLoc(),
20457 /*DiscardedValue*/ false);
20459 // Build final: Var = PrivCopy;
20462 Final
= SemaRef
.BuildBinOp(
20463 S
, RefExpr
->getExprLoc(), BO_Assign
, CapturedRef
,
20464 SemaRef
.DefaultLvalueConversion(*CurPrivate
).get());
20466 Final
= *CurPrivate
;
20467 Final
= SemaRef
.ActOnFinishFullExpr(Final
.get(), DE
->getBeginLoc(),
20468 /*DiscardedValue*/ false);
20470 if (!Update
.isUsable() || !Final
.isUsable()) {
20471 Updates
.push_back(nullptr);
20472 Finals
.push_back(nullptr);
20473 UsedExprs
.push_back(nullptr);
20476 Updates
.push_back(Update
.get());
20477 Finals
.push_back(Final
.get());
20479 UsedExprs
.push_back(SimpleRefExpr
);
20484 if (Expr
*S
= Clause
.getStep())
20485 UsedExprs
.push_back(S
);
20486 // Fill the remaining part with the nullptr.
20487 UsedExprs
.append(Clause
.varlist_size() + 1 - UsedExprs
.size(), nullptr);
20488 Clause
.setUpdates(Updates
);
20489 Clause
.setFinals(Finals
);
20490 Clause
.setUsedExprs(UsedExprs
);
20494 OMPClause
*Sema::ActOnOpenMPAlignedClause(
20495 ArrayRef
<Expr
*> VarList
, Expr
*Alignment
, SourceLocation StartLoc
,
20496 SourceLocation LParenLoc
, SourceLocation ColonLoc
, SourceLocation EndLoc
) {
20497 SmallVector
<Expr
*, 8> Vars
;
20498 for (Expr
*RefExpr
: VarList
) {
20499 assert(RefExpr
&& "NULL expr in OpenMP linear clause.");
20500 SourceLocation ELoc
;
20501 SourceRange ERange
;
20502 Expr
*SimpleRefExpr
= RefExpr
;
20503 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
20505 // It will be analyzed later.
20506 Vars
.push_back(RefExpr
);
20508 ValueDecl
*D
= Res
.first
;
20512 QualType QType
= D
->getType();
20513 auto *VD
= dyn_cast
<VarDecl
>(D
);
20515 // OpenMP [2.8.1, simd construct, Restrictions]
20516 // The type of list items appearing in the aligned clause must be
20517 // array, pointer, reference to array, or reference to pointer.
20518 QType
= QType
.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20519 const Type
*Ty
= QType
.getTypePtrOrNull();
20520 if (!Ty
|| (!Ty
->isArrayType() && !Ty
->isPointerType())) {
20521 Diag(ELoc
, diag::err_omp_aligned_expected_array_or_ptr
)
20522 << QType
<< getLangOpts().CPlusPlus
<< ERange
;
20523 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
20524 VarDecl::DeclarationOnly
;
20525 Diag(D
->getLocation(),
20526 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
20531 // OpenMP [2.8.1, simd construct, Restrictions]
20532 // A list-item cannot appear in more than one aligned clause.
20533 if (const Expr
*PrevRef
= DSAStack
->addUniqueAligned(D
, SimpleRefExpr
)) {
20534 Diag(ELoc
, diag::err_omp_used_in_clause_twice
)
20535 << 0 << getOpenMPClauseName(OMPC_aligned
) << ERange
;
20536 Diag(PrevRef
->getExprLoc(), diag::note_omp_explicit_dsa
)
20537 << getOpenMPClauseName(OMPC_aligned
);
20541 DeclRefExpr
*Ref
= nullptr;
20542 if (!VD
&& isOpenMPCapturedDecl(D
))
20543 Ref
= buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/true);
20544 Vars
.push_back(DefaultFunctionArrayConversion(
20545 (VD
|| !Ref
) ? RefExpr
->IgnoreParens() : Ref
)
20549 // OpenMP [2.8.1, simd construct, Description]
20550 // The parameter of the aligned clause, alignment, must be a constant
20551 // positive integer expression.
20552 // If no optional parameter is specified, implementation-defined default
20553 // alignments for SIMD instructions on the target platforms are assumed.
20554 if (Alignment
!= nullptr) {
20555 ExprResult AlignResult
=
20556 VerifyPositiveIntegerConstantInClause(Alignment
, OMPC_aligned
);
20557 if (AlignResult
.isInvalid())
20559 Alignment
= AlignResult
.get();
20564 return OMPAlignedClause::Create(Context
, StartLoc
, LParenLoc
, ColonLoc
,
20565 EndLoc
, Vars
, Alignment
);
20568 OMPClause
*Sema::ActOnOpenMPCopyinClause(ArrayRef
<Expr
*> VarList
,
20569 SourceLocation StartLoc
,
20570 SourceLocation LParenLoc
,
20571 SourceLocation EndLoc
) {
20572 SmallVector
<Expr
*, 8> Vars
;
20573 SmallVector
<Expr
*, 8> SrcExprs
;
20574 SmallVector
<Expr
*, 8> DstExprs
;
20575 SmallVector
<Expr
*, 8> AssignmentOps
;
20576 for (Expr
*RefExpr
: VarList
) {
20577 assert(RefExpr
&& "NULL expr in OpenMP copyin clause.");
20578 if (isa
<DependentScopeDeclRefExpr
>(RefExpr
)) {
20579 // It will be analyzed later.
20580 Vars
.push_back(RefExpr
);
20581 SrcExprs
.push_back(nullptr);
20582 DstExprs
.push_back(nullptr);
20583 AssignmentOps
.push_back(nullptr);
20587 SourceLocation ELoc
= RefExpr
->getExprLoc();
20588 // OpenMP [2.1, C/C++]
20589 // A list item is a variable name.
20590 // OpenMP [2.14.4.1, Restrictions, p.1]
20591 // A list item that appears in a copyin clause must be threadprivate.
20592 auto *DE
= dyn_cast
<DeclRefExpr
>(RefExpr
);
20593 if (!DE
|| !isa
<VarDecl
>(DE
->getDecl())) {
20594 Diag(ELoc
, diag::err_omp_expected_var_name_member_expr
)
20595 << 0 << RefExpr
->getSourceRange();
20599 Decl
*D
= DE
->getDecl();
20600 auto *VD
= cast
<VarDecl
>(D
);
20602 QualType Type
= VD
->getType();
20603 if (Type
->isDependentType() || Type
->isInstantiationDependentType()) {
20604 // It will be analyzed later.
20605 Vars
.push_back(DE
);
20606 SrcExprs
.push_back(nullptr);
20607 DstExprs
.push_back(nullptr);
20608 AssignmentOps
.push_back(nullptr);
20612 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
20613 // A list item that appears in a copyin clause must be threadprivate.
20614 if (!DSAStack
->isThreadPrivate(VD
)) {
20615 Diag(ELoc
, diag::err_omp_required_access
)
20616 << getOpenMPClauseName(OMPC_copyin
)
20617 << getOpenMPDirectiveName(OMPD_threadprivate
);
20621 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20622 // A variable of class type (or array thereof) that appears in a
20623 // copyin clause requires an accessible, unambiguous copy assignment
20624 // operator for the class type.
20625 QualType ElemType
= Context
.getBaseElementType(Type
).getNonReferenceType();
20627 buildVarDecl(*this, DE
->getBeginLoc(), ElemType
.getUnqualifiedType(),
20628 ".copyin.src", VD
->hasAttrs() ? &VD
->getAttrs() : nullptr);
20629 DeclRefExpr
*PseudoSrcExpr
= buildDeclRefExpr(
20630 *this, SrcVD
, ElemType
.getUnqualifiedType(), DE
->getExprLoc());
20632 buildVarDecl(*this, DE
->getBeginLoc(), ElemType
, ".copyin.dst",
20633 VD
->hasAttrs() ? &VD
->getAttrs() : nullptr);
20634 DeclRefExpr
*PseudoDstExpr
=
20635 buildDeclRefExpr(*this, DstVD
, ElemType
, DE
->getExprLoc());
20636 // For arrays generate assignment operation for single element and replace
20637 // it by the original array element in CodeGen.
20638 ExprResult AssignmentOp
=
20639 BuildBinOp(/*S=*/nullptr, DE
->getExprLoc(), BO_Assign
, PseudoDstExpr
,
20641 if (AssignmentOp
.isInvalid())
20643 AssignmentOp
= ActOnFinishFullExpr(AssignmentOp
.get(), DE
->getExprLoc(),
20644 /*DiscardedValue*/ false);
20645 if (AssignmentOp
.isInvalid())
20648 DSAStack
->addDSA(VD
, DE
, OMPC_copyin
);
20649 Vars
.push_back(DE
);
20650 SrcExprs
.push_back(PseudoSrcExpr
);
20651 DstExprs
.push_back(PseudoDstExpr
);
20652 AssignmentOps
.push_back(AssignmentOp
.get());
20658 return OMPCopyinClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
, Vars
,
20659 SrcExprs
, DstExprs
, AssignmentOps
);
20662 OMPClause
*Sema::ActOnOpenMPCopyprivateClause(ArrayRef
<Expr
*> VarList
,
20663 SourceLocation StartLoc
,
20664 SourceLocation LParenLoc
,
20665 SourceLocation EndLoc
) {
20666 SmallVector
<Expr
*, 8> Vars
;
20667 SmallVector
<Expr
*, 8> SrcExprs
;
20668 SmallVector
<Expr
*, 8> DstExprs
;
20669 SmallVector
<Expr
*, 8> AssignmentOps
;
20670 for (Expr
*RefExpr
: VarList
) {
20671 assert(RefExpr
&& "NULL expr in OpenMP linear clause.");
20672 SourceLocation ELoc
;
20673 SourceRange ERange
;
20674 Expr
*SimpleRefExpr
= RefExpr
;
20675 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
20677 // It will be analyzed later.
20678 Vars
.push_back(RefExpr
);
20679 SrcExprs
.push_back(nullptr);
20680 DstExprs
.push_back(nullptr);
20681 AssignmentOps
.push_back(nullptr);
20683 ValueDecl
*D
= Res
.first
;
20687 QualType Type
= D
->getType();
20688 auto *VD
= dyn_cast
<VarDecl
>(D
);
20690 // OpenMP [2.14.4.2, Restrictions, p.2]
20691 // A list item that appears in a copyprivate clause may not appear in a
20692 // private or firstprivate clause on the single construct.
20693 if (!VD
|| !DSAStack
->isThreadPrivate(VD
)) {
20694 DSAStackTy::DSAVarData DVar
=
20695 DSAStack
->getTopDSA(D
, /*FromParent=*/false);
20696 if (DVar
.CKind
!= OMPC_unknown
&& DVar
.CKind
!= OMPC_copyprivate
&&
20698 Diag(ELoc
, diag::err_omp_wrong_dsa
)
20699 << getOpenMPClauseName(DVar
.CKind
)
20700 << getOpenMPClauseName(OMPC_copyprivate
);
20701 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
20705 // OpenMP [2.11.4.2, Restrictions, p.1]
20706 // All list items that appear in a copyprivate clause must be either
20707 // threadprivate or private in the enclosing context.
20708 if (DVar
.CKind
== OMPC_unknown
) {
20709 DVar
= DSAStack
->getImplicitDSA(D
, false);
20710 if (DVar
.CKind
== OMPC_shared
) {
20711 Diag(ELoc
, diag::err_omp_required_access
)
20712 << getOpenMPClauseName(OMPC_copyprivate
)
20713 << "threadprivate or private in the enclosing context";
20714 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
20720 // Variably modified types are not supported.
20721 if (!Type
->isAnyPointerType() && Type
->isVariablyModifiedType()) {
20722 Diag(ELoc
, diag::err_omp_variably_modified_type_not_supported
)
20723 << getOpenMPClauseName(OMPC_copyprivate
) << Type
20724 << getOpenMPDirectiveName(DSAStack
->getCurrentDirective());
20725 bool IsDecl
= !VD
|| VD
->isThisDeclarationADefinition(Context
) ==
20726 VarDecl::DeclarationOnly
;
20727 Diag(D
->getLocation(),
20728 IsDecl
? diag::note_previous_decl
: diag::note_defined_here
)
20733 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20734 // A variable of class type (or array thereof) that appears in a
20735 // copyin clause requires an accessible, unambiguous copy assignment
20736 // operator for the class type.
20737 Type
= Context
.getBaseElementType(Type
.getNonReferenceType())
20738 .getUnqualifiedType();
20740 buildVarDecl(*this, RefExpr
->getBeginLoc(), Type
, ".copyprivate.src",
20741 D
->hasAttrs() ? &D
->getAttrs() : nullptr);
20742 DeclRefExpr
*PseudoSrcExpr
= buildDeclRefExpr(*this, SrcVD
, Type
, ELoc
);
20744 buildVarDecl(*this, RefExpr
->getBeginLoc(), Type
, ".copyprivate.dst",
20745 D
->hasAttrs() ? &D
->getAttrs() : nullptr);
20746 DeclRefExpr
*PseudoDstExpr
= buildDeclRefExpr(*this, DstVD
, Type
, ELoc
);
20747 ExprResult AssignmentOp
= BuildBinOp(
20748 DSAStack
->getCurScope(), ELoc
, BO_Assign
, PseudoDstExpr
, PseudoSrcExpr
);
20749 if (AssignmentOp
.isInvalid())
20752 ActOnFinishFullExpr(AssignmentOp
.get(), ELoc
, /*DiscardedValue*/ false);
20753 if (AssignmentOp
.isInvalid())
20756 // No need to mark vars as copyprivate, they are already threadprivate or
20757 // implicitly private.
20758 assert(VD
|| isOpenMPCapturedDecl(D
));
20760 VD
? RefExpr
->IgnoreParens()
20761 : buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/false));
20762 SrcExprs
.push_back(PseudoSrcExpr
);
20763 DstExprs
.push_back(PseudoDstExpr
);
20764 AssignmentOps
.push_back(AssignmentOp
.get());
20770 return OMPCopyprivateClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
,
20771 Vars
, SrcExprs
, DstExprs
, AssignmentOps
);
20774 OMPClause
*Sema::ActOnOpenMPFlushClause(ArrayRef
<Expr
*> VarList
,
20775 SourceLocation StartLoc
,
20776 SourceLocation LParenLoc
,
20777 SourceLocation EndLoc
) {
20778 if (VarList
.empty())
20781 return OMPFlushClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
, VarList
);
20784 /// Tries to find omp_depend_t. type.
20785 static bool findOMPDependT(Sema
&S
, SourceLocation Loc
, DSAStackTy
*Stack
,
20786 bool Diagnose
= true) {
20787 QualType OMPDependT
= Stack
->getOMPDependT();
20788 if (!OMPDependT
.isNull())
20790 IdentifierInfo
*II
= &S
.PP
.getIdentifierTable().get("omp_depend_t");
20791 ParsedType PT
= S
.getTypeName(*II
, Loc
, S
.getCurScope());
20792 if (!PT
.getAsOpaquePtr() || PT
.get().isNull()) {
20794 S
.Diag(Loc
, diag::err_omp_implied_type_not_found
) << "omp_depend_t";
20797 Stack
->setOMPDependT(PT
.get());
20801 OMPClause
*Sema::ActOnOpenMPDepobjClause(Expr
*Depobj
, SourceLocation StartLoc
,
20802 SourceLocation LParenLoc
,
20803 SourceLocation EndLoc
) {
20807 bool OMPDependTFound
= findOMPDependT(*this, StartLoc
, DSAStack
);
20809 // OpenMP 5.0, 2.17.10.1 depobj Construct
20810 // depobj is an lvalue expression of type omp_depend_t.
20811 if (!Depobj
->isTypeDependent() && !Depobj
->isValueDependent() &&
20812 !Depobj
->isInstantiationDependent() &&
20813 !Depobj
->containsUnexpandedParameterPack() &&
20814 (OMPDependTFound
&&
20815 !Context
.typesAreCompatible(DSAStack
->getOMPDependT(), Depobj
->getType(),
20816 /*CompareUnqualified=*/true))) {
20817 Diag(Depobj
->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue
)
20818 << 0 << Depobj
->getType() << Depobj
->getSourceRange();
20821 if (!Depobj
->isLValue()) {
20822 Diag(Depobj
->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue
)
20823 << 1 << Depobj
->getSourceRange();
20826 return OMPDepobjClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
, Depobj
);
20830 // Utility struct that gathers the related info for doacross clause.
20831 struct DoacrossDataInfoTy
{
20832 // The list of expressions.
20833 SmallVector
<Expr
*, 8> Vars
;
20834 // The OperatorOffset for doacross loop.
20835 DSAStackTy::OperatorOffsetTy OpsOffs
;
20836 // The depended loop count.
20837 llvm::APSInt TotalDepCount
;
20840 static DoacrossDataInfoTy
20841 ProcessOpenMPDoacrossClauseCommon(Sema
&SemaRef
, bool IsSource
,
20842 ArrayRef
<Expr
*> VarList
, DSAStackTy
*Stack
,
20843 SourceLocation EndLoc
) {
20845 SmallVector
<Expr
*, 8> Vars
;
20846 DSAStackTy::OperatorOffsetTy OpsOffs
;
20847 llvm::APSInt
DepCounter(/*BitWidth=*/32);
20848 llvm::APSInt
TotalDepCount(/*BitWidth=*/32);
20850 if (const Expr
*OrderedCountExpr
=
20851 Stack
->getParentOrderedRegionParam().first
) {
20852 TotalDepCount
= OrderedCountExpr
->EvaluateKnownConstInt(SemaRef
.Context
);
20853 TotalDepCount
.setIsUnsigned(/*Val=*/true);
20856 for (Expr
*RefExpr
: VarList
) {
20857 assert(RefExpr
&& "NULL expr in OpenMP doacross clause.");
20858 if (isa
<DependentScopeDeclRefExpr
>(RefExpr
)) {
20859 // It will be analyzed later.
20860 Vars
.push_back(RefExpr
);
20864 SourceLocation ELoc
= RefExpr
->getExprLoc();
20865 Expr
*SimpleExpr
= RefExpr
->IgnoreParenCasts();
20867 if (Stack
->getParentOrderedRegionParam().first
&&
20868 DepCounter
>= TotalDepCount
) {
20869 SemaRef
.Diag(ELoc
, diag::err_omp_depend_sink_unexpected_expr
);
20873 // OpenMP [2.13.9, Summary]
20874 // depend(dependence-type : vec), where dependence-type is:
20875 // 'sink' and where vec is the iteration vector, which has the form:
20876 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
20877 // where n is the value specified by the ordered clause in the loop
20878 // directive, xi denotes the loop iteration variable of the i-th nested
20879 // loop associated with the loop directive, and di is a constant
20880 // non-negative integer.
20881 if (SemaRef
.CurContext
->isDependentContext()) {
20882 // It will be analyzed later.
20883 Vars
.push_back(RefExpr
);
20886 SimpleExpr
= SimpleExpr
->IgnoreImplicit();
20887 OverloadedOperatorKind OOK
= OO_None
;
20888 SourceLocation OOLoc
;
20889 Expr
*LHS
= SimpleExpr
;
20890 Expr
*RHS
= nullptr;
20891 if (auto *BO
= dyn_cast
<BinaryOperator
>(SimpleExpr
)) {
20892 OOK
= BinaryOperator::getOverloadedOperator(BO
->getOpcode());
20893 OOLoc
= BO
->getOperatorLoc();
20894 LHS
= BO
->getLHS()->IgnoreParenImpCasts();
20895 RHS
= BO
->getRHS()->IgnoreParenImpCasts();
20896 } else if (auto *OCE
= dyn_cast
<CXXOperatorCallExpr
>(SimpleExpr
)) {
20897 OOK
= OCE
->getOperator();
20898 OOLoc
= OCE
->getOperatorLoc();
20899 LHS
= OCE
->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20900 RHS
= OCE
->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
20901 } else if (auto *MCE
= dyn_cast
<CXXMemberCallExpr
>(SimpleExpr
)) {
20902 OOK
= MCE
->getMethodDecl()
20905 .getCXXOverloadedOperator();
20906 OOLoc
= MCE
->getCallee()->getExprLoc();
20907 LHS
= MCE
->getImplicitObjectArgument()->IgnoreParenImpCasts();
20908 RHS
= MCE
->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20910 SourceLocation ELoc
;
20911 SourceRange ERange
;
20912 auto Res
= getPrivateItem(SemaRef
, LHS
, ELoc
, ERange
);
20914 // It will be analyzed later.
20915 Vars
.push_back(RefExpr
);
20917 ValueDecl
*D
= Res
.first
;
20921 if (OOK
!= OO_Plus
&& OOK
!= OO_Minus
&& (RHS
|| OOK
!= OO_None
)) {
20922 SemaRef
.Diag(OOLoc
, diag::err_omp_depend_sink_expected_plus_minus
);
20926 ExprResult RHSRes
= SemaRef
.VerifyPositiveIntegerConstantInClause(
20927 RHS
, OMPC_depend
, /*StrictlyPositive=*/false);
20928 if (RHSRes
.isInvalid())
20931 if (!SemaRef
.CurContext
->isDependentContext() &&
20932 Stack
->getParentOrderedRegionParam().first
&&
20933 DepCounter
!= Stack
->isParentLoopControlVariable(D
).first
) {
20934 const ValueDecl
*VD
=
20935 Stack
->getParentLoopControlVariable(DepCounter
.getZExtValue());
20937 SemaRef
.Diag(ELoc
, diag::err_omp_depend_sink_expected_loop_iteration
)
20940 SemaRef
.Diag(ELoc
, diag::err_omp_depend_sink_expected_loop_iteration
)
20944 OpsOffs
.emplace_back(RHS
, OOK
);
20946 Vars
.push_back(RefExpr
->IgnoreParenImpCasts());
20948 if (!SemaRef
.CurContext
->isDependentContext() && !IsSource
&&
20949 TotalDepCount
> VarList
.size() &&
20950 Stack
->getParentOrderedRegionParam().first
&&
20951 Stack
->getParentLoopControlVariable(VarList
.size() + 1)) {
20952 SemaRef
.Diag(EndLoc
, diag::err_omp_depend_sink_expected_loop_iteration
)
20953 << 1 << Stack
->getParentLoopControlVariable(VarList
.size() + 1);
20955 return {Vars
, OpsOffs
, TotalDepCount
};
20959 Sema::ActOnOpenMPDependClause(const OMPDependClause::DependDataTy
&Data
,
20960 Expr
*DepModifier
, ArrayRef
<Expr
*> VarList
,
20961 SourceLocation StartLoc
, SourceLocation LParenLoc
,
20962 SourceLocation EndLoc
) {
20963 OpenMPDependClauseKind DepKind
= Data
.DepKind
;
20964 SourceLocation DepLoc
= Data
.DepLoc
;
20965 if (DSAStack
->getCurrentDirective() == OMPD_ordered
&&
20966 DepKind
!= OMPC_DEPEND_source
&& DepKind
!= OMPC_DEPEND_sink
) {
20967 Diag(DepLoc
, diag::err_omp_unexpected_clause_value
)
20968 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend
);
20971 if (DSAStack
->getCurrentDirective() == OMPD_taskwait
&&
20972 DepKind
== OMPC_DEPEND_mutexinoutset
) {
20973 Diag(DepLoc
, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed
);
20976 if ((DSAStack
->getCurrentDirective() != OMPD_ordered
||
20977 DSAStack
->getCurrentDirective() == OMPD_depobj
) &&
20978 (DepKind
== OMPC_DEPEND_unknown
|| DepKind
== OMPC_DEPEND_source
||
20979 DepKind
== OMPC_DEPEND_sink
||
20980 ((LangOpts
.OpenMP
< 50 ||
20981 DSAStack
->getCurrentDirective() == OMPD_depobj
) &&
20982 DepKind
== OMPC_DEPEND_depobj
))) {
20983 SmallVector
<unsigned, 6> Except
= {OMPC_DEPEND_source
, OMPC_DEPEND_sink
,
20984 OMPC_DEPEND_outallmemory
,
20985 OMPC_DEPEND_inoutallmemory
};
20986 if (LangOpts
.OpenMP
< 50 || DSAStack
->getCurrentDirective() == OMPD_depobj
)
20987 Except
.push_back(OMPC_DEPEND_depobj
);
20988 if (LangOpts
.OpenMP
< 51)
20989 Except
.push_back(OMPC_DEPEND_inoutset
);
20990 std::string Expected
= (LangOpts
.OpenMP
>= 50 && !DepModifier
)
20991 ? "depend modifier(iterator) or "
20993 Diag(DepLoc
, diag::err_omp_unexpected_clause_value
)
20994 << Expected
+ getListOfPossibleValues(OMPC_depend
, /*First=*/0,
20995 /*Last=*/OMPC_DEPEND_unknown
,
20997 << getOpenMPClauseName(OMPC_depend
);
21001 (DepKind
== OMPC_DEPEND_source
|| DepKind
== OMPC_DEPEND_sink
)) {
21002 Diag(DepModifier
->getExprLoc(),
21003 diag::err_omp_depend_sink_source_with_modifier
);
21007 !DepModifier
->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator
))
21008 Diag(DepModifier
->getExprLoc(), diag::err_omp_depend_modifier_not_iterator
);
21010 SmallVector
<Expr
*, 8> Vars
;
21011 DSAStackTy::OperatorOffsetTy OpsOffs
;
21012 llvm::APSInt
TotalDepCount(/*BitWidth=*/32);
21014 if (DepKind
== OMPC_DEPEND_sink
|| DepKind
== OMPC_DEPEND_source
) {
21015 DoacrossDataInfoTy VarOffset
= ProcessOpenMPDoacrossClauseCommon(
21016 *this, DepKind
== OMPC_DEPEND_source
, VarList
, DSAStack
, EndLoc
);
21017 Vars
= VarOffset
.Vars
;
21018 OpsOffs
= VarOffset
.OpsOffs
;
21019 TotalDepCount
= VarOffset
.TotalDepCount
;
21021 for (Expr
*RefExpr
: VarList
) {
21022 assert(RefExpr
&& "NULL expr in OpenMP shared clause.");
21023 if (isa
<DependentScopeDeclRefExpr
>(RefExpr
)) {
21024 // It will be analyzed later.
21025 Vars
.push_back(RefExpr
);
21029 SourceLocation ELoc
= RefExpr
->getExprLoc();
21030 Expr
*SimpleExpr
= RefExpr
->IgnoreParenCasts();
21031 if (DepKind
!= OMPC_DEPEND_sink
&& DepKind
!= OMPC_DEPEND_source
) {
21032 bool OMPDependTFound
= LangOpts
.OpenMP
>= 50;
21033 if (OMPDependTFound
)
21034 OMPDependTFound
= findOMPDependT(*this, StartLoc
, DSAStack
,
21035 DepKind
== OMPC_DEPEND_depobj
);
21036 if (DepKind
== OMPC_DEPEND_depobj
) {
21037 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21038 // List items used in depend clauses with the depobj dependence type
21039 // must be expressions of the omp_depend_t type.
21040 if (!RefExpr
->isValueDependent() && !RefExpr
->isTypeDependent() &&
21041 !RefExpr
->isInstantiationDependent() &&
21042 !RefExpr
->containsUnexpandedParameterPack() &&
21043 (OMPDependTFound
&&
21044 !Context
.hasSameUnqualifiedType(DSAStack
->getOMPDependT(),
21045 RefExpr
->getType()))) {
21046 Diag(ELoc
, diag::err_omp_expected_omp_depend_t_lvalue
)
21047 << 0 << RefExpr
->getType() << RefExpr
->getSourceRange();
21050 if (!RefExpr
->isLValue()) {
21051 Diag(ELoc
, diag::err_omp_expected_omp_depend_t_lvalue
)
21052 << 1 << RefExpr
->getType() << RefExpr
->getSourceRange();
21056 // OpenMP 5.0 [2.17.11, Restrictions]
21057 // List items used in depend clauses cannot be zero-length array
21059 QualType ExprTy
= RefExpr
->getType().getNonReferenceType();
21060 const auto *OASE
= dyn_cast
<OMPArraySectionExpr
>(SimpleExpr
);
21062 QualType BaseType
=
21063 OMPArraySectionExpr::getBaseOriginalType(OASE
->getBase());
21064 if (BaseType
.isNull())
21066 if (const auto *ATy
= BaseType
->getAsArrayTypeUnsafe())
21067 ExprTy
= ATy
->getElementType();
21069 ExprTy
= BaseType
->getPointeeType();
21070 ExprTy
= ExprTy
.getNonReferenceType();
21071 const Expr
*Length
= OASE
->getLength();
21072 Expr::EvalResult Result
;
21073 if (Length
&& !Length
->isValueDependent() &&
21074 Length
->EvaluateAsInt(Result
, Context
) &&
21075 Result
.Val
.getInt().isZero()) {
21077 diag::err_omp_depend_zero_length_array_section_not_allowed
)
21078 << SimpleExpr
->getSourceRange();
21083 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21084 // List items used in depend clauses with the in, out, inout,
21085 // inoutset, or mutexinoutset dependence types cannot be
21086 // expressions of the omp_depend_t type.
21087 if (!RefExpr
->isValueDependent() && !RefExpr
->isTypeDependent() &&
21088 !RefExpr
->isInstantiationDependent() &&
21089 !RefExpr
->containsUnexpandedParameterPack() &&
21090 (!RefExpr
->IgnoreParenImpCasts()->isLValue() ||
21091 (OMPDependTFound
&& DSAStack
->getOMPDependT().getTypePtr() ==
21092 ExprTy
.getTypePtr()))) {
21093 Diag(ELoc
, diag::err_omp_expected_addressable_lvalue_or_array_item
)
21094 << (LangOpts
.OpenMP
>= 50 ? 1 : 0)
21095 << (LangOpts
.OpenMP
>= 50 ? 1 : 0) << RefExpr
->getSourceRange();
21099 auto *ASE
= dyn_cast
<ArraySubscriptExpr
>(SimpleExpr
);
21100 if (ASE
&& !ASE
->getBase()->isTypeDependent() &&
21103 .getNonReferenceType()
21104 ->isPointerType() &&
21105 !ASE
->getBase()->getType().getNonReferenceType()->isArrayType()) {
21106 Diag(ELoc
, diag::err_omp_expected_addressable_lvalue_or_array_item
)
21107 << (LangOpts
.OpenMP
>= 50 ? 1 : 0)
21108 << (LangOpts
.OpenMP
>= 50 ? 1 : 0) << RefExpr
->getSourceRange();
21114 Sema::TentativeAnalysisScope
Trap(*this);
21115 Res
= CreateBuiltinUnaryOp(ELoc
, UO_AddrOf
,
21116 RefExpr
->IgnoreParenImpCasts());
21118 if (!Res
.isUsable() && !isa
<OMPArraySectionExpr
>(SimpleExpr
) &&
21119 !isa
<OMPArrayShapingExpr
>(SimpleExpr
)) {
21120 Diag(ELoc
, diag::err_omp_expected_addressable_lvalue_or_array_item
)
21121 << (LangOpts
.OpenMP
>= 50 ? 1 : 0)
21122 << (LangOpts
.OpenMP
>= 50 ? 1 : 0) << RefExpr
->getSourceRange();
21127 Vars
.push_back(RefExpr
->IgnoreParenImpCasts());
21131 if (DepKind
!= OMPC_DEPEND_source
&& DepKind
!= OMPC_DEPEND_sink
&&
21132 DepKind
!= OMPC_DEPEND_outallmemory
&&
21133 DepKind
!= OMPC_DEPEND_inoutallmemory
&& Vars
.empty())
21136 auto *C
= OMPDependClause::Create(
21137 Context
, StartLoc
, LParenLoc
, EndLoc
,
21138 {DepKind
, DepLoc
, Data
.ColonLoc
, Data
.OmpAllMemoryLoc
}, DepModifier
, Vars
,
21139 TotalDepCount
.getZExtValue());
21140 if ((DepKind
== OMPC_DEPEND_sink
|| DepKind
== OMPC_DEPEND_source
) &&
21141 DSAStack
->isParentOrderedRegion())
21142 DSAStack
->addDoacrossDependClause(C
, OpsOffs
);
21146 OMPClause
*Sema::ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier
,
21147 Expr
*Device
, SourceLocation StartLoc
,
21148 SourceLocation LParenLoc
,
21149 SourceLocation ModifierLoc
,
21150 SourceLocation EndLoc
) {
21151 assert((ModifierLoc
.isInvalid() || LangOpts
.OpenMP
>= 50) &&
21152 "Unexpected device modifier in OpenMP < 50.");
21154 bool ErrorFound
= false;
21155 if (ModifierLoc
.isValid() && Modifier
== OMPC_DEVICE_unknown
) {
21156 std::string Values
=
21157 getListOfPossibleValues(OMPC_device
, /*First=*/0, OMPC_DEVICE_unknown
);
21158 Diag(ModifierLoc
, diag::err_omp_unexpected_clause_value
)
21159 << Values
<< getOpenMPClauseName(OMPC_device
);
21163 Expr
*ValExpr
= Device
;
21164 Stmt
*HelperValStmt
= nullptr;
21166 // OpenMP [2.9.1, Restrictions]
21167 // The device expression must evaluate to a non-negative integer value.
21168 ErrorFound
= !isNonNegativeIntegerValue(ValExpr
, *this, OMPC_device
,
21169 /*StrictlyPositive=*/false) ||
21174 // OpenMP 5.0 [2.12.5, Restrictions]
21175 // In case of ancestor device-modifier, a requires directive with
21176 // the reverse_offload clause must be specified.
21177 if (Modifier
== OMPC_DEVICE_ancestor
) {
21178 if (!DSAStack
->hasRequiresDeclWithClause
<OMPReverseOffloadClause
>()) {
21181 diag::err_omp_device_ancestor_without_requires_reverse_offload
);
21186 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
21187 OpenMPDirectiveKind CaptureRegion
=
21188 getOpenMPCaptureRegionForClause(DKind
, OMPC_device
, LangOpts
.OpenMP
);
21189 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
21190 ValExpr
= MakeFullExpr(ValExpr
).get();
21191 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
21192 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
21193 HelperValStmt
= buildPreInits(Context
, Captures
);
21196 return new (Context
)
21197 OMPDeviceClause(Modifier
, ValExpr
, HelperValStmt
, CaptureRegion
, StartLoc
,
21198 LParenLoc
, ModifierLoc
, EndLoc
);
21201 static bool checkTypeMappable(SourceLocation SL
, SourceRange SR
, Sema
&SemaRef
,
21202 DSAStackTy
*Stack
, QualType QTy
,
21203 bool FullCheck
= true) {
21204 if (SemaRef
.RequireCompleteType(SL
, QTy
, diag::err_incomplete_type
))
21206 if (FullCheck
&& !SemaRef
.CurContext
->isDependentContext() &&
21207 !QTy
.isTriviallyCopyableType(SemaRef
.Context
))
21208 SemaRef
.Diag(SL
, diag::warn_omp_non_trivial_type_mapped
) << QTy
<< SR
;
21212 /// Return true if it can be proven that the provided array expression
21213 /// (array section or array subscript) does NOT specify the whole size of the
21214 /// array whose base type is \a BaseQTy.
21215 static bool checkArrayExpressionDoesNotReferToWholeSize(Sema
&SemaRef
,
21217 QualType BaseQTy
) {
21218 const auto *OASE
= dyn_cast
<OMPArraySectionExpr
>(E
);
21220 // If this is an array subscript, it refers to the whole size if the size of
21221 // the dimension is constant and equals 1. Also, an array section assumes the
21222 // format of an array subscript if no colon is used.
21223 if (isa
<ArraySubscriptExpr
>(E
) ||
21224 (OASE
&& OASE
->getColonLocFirst().isInvalid())) {
21225 if (const auto *ATy
= dyn_cast
<ConstantArrayType
>(BaseQTy
.getTypePtr()))
21226 return ATy
->getSize().getSExtValue() != 1;
21227 // Size can't be evaluated statically.
21231 assert(OASE
&& "Expecting array section if not an array subscript.");
21232 const Expr
*LowerBound
= OASE
->getLowerBound();
21233 const Expr
*Length
= OASE
->getLength();
21235 // If there is a lower bound that does not evaluates to zero, we are not
21236 // covering the whole dimension.
21238 Expr::EvalResult Result
;
21239 if (!LowerBound
->EvaluateAsInt(Result
, SemaRef
.getASTContext()))
21240 return false; // Can't get the integer value as a constant.
21242 llvm::APSInt ConstLowerBound
= Result
.Val
.getInt();
21243 if (ConstLowerBound
.getSExtValue())
21247 // If we don't have a length we covering the whole dimension.
21251 // If the base is a pointer, we don't have a way to get the size of the
21253 if (BaseQTy
->isPointerType())
21256 // We can only check if the length is the same as the size of the dimension
21257 // if we have a constant array.
21258 const auto *CATy
= dyn_cast
<ConstantArrayType
>(BaseQTy
.getTypePtr());
21262 Expr::EvalResult Result
;
21263 if (!Length
->EvaluateAsInt(Result
, SemaRef
.getASTContext()))
21264 return false; // Can't get the integer value as a constant.
21266 llvm::APSInt ConstLength
= Result
.Val
.getInt();
21267 return CATy
->getSize().getSExtValue() != ConstLength
.getSExtValue();
21270 // Return true if it can be proven that the provided array expression (array
21271 // section or array subscript) does NOT specify a single element of the array
21272 // whose base type is \a BaseQTy.
21273 static bool checkArrayExpressionDoesNotReferToUnitySize(Sema
&SemaRef
,
21275 QualType BaseQTy
) {
21276 const auto *OASE
= dyn_cast
<OMPArraySectionExpr
>(E
);
21278 // An array subscript always refer to a single element. Also, an array section
21279 // assumes the format of an array subscript if no colon is used.
21280 if (isa
<ArraySubscriptExpr
>(E
) ||
21281 (OASE
&& OASE
->getColonLocFirst().isInvalid()))
21284 assert(OASE
&& "Expecting array section if not an array subscript.");
21285 const Expr
*Length
= OASE
->getLength();
21287 // If we don't have a length we have to check if the array has unitary size
21288 // for this dimension. Also, we should always expect a length if the base type
21291 if (const auto *ATy
= dyn_cast
<ConstantArrayType
>(BaseQTy
.getTypePtr()))
21292 return ATy
->getSize().getSExtValue() != 1;
21293 // We cannot assume anything.
21297 // Check if the length evaluates to 1.
21298 Expr::EvalResult Result
;
21299 if (!Length
->EvaluateAsInt(Result
, SemaRef
.getASTContext()))
21300 return false; // Can't get the integer value as a constant.
21302 llvm::APSInt ConstLength
= Result
.Val
.getInt();
21303 return ConstLength
.getSExtValue() != 1;
21306 // The base of elements of list in a map clause have to be either:
21307 // - a reference to variable or field.
21308 // - a member expression.
21309 // - an array expression.
21311 // E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
21312 // reference to 'r'.
21319 // #pragma omp target map (S.Arr[:12]);
21323 // We want to retrieve the member expression 'this->S';
21325 // OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
21326 // If a list item is an array section, it must specify contiguous storage.
21328 // For this restriction it is sufficient that we make sure only references
21329 // to variables or fields and array expressions, and that no array sections
21330 // exist except in the rightmost expression (unless they cover the whole
21331 // dimension of the array). E.g. these would be invalid:
21333 // r.ArrS[3:5].Arr[6:7]
21337 // but these would be valid:
21338 // r.ArrS[3].Arr[6:7]
21342 class MapBaseChecker final
: public StmtVisitor
<MapBaseChecker
, bool> {
21344 OpenMPClauseKind CKind
= OMPC_unknown
;
21345 OpenMPDirectiveKind DKind
= OMPD_unknown
;
21346 OMPClauseMappableExprCommon::MappableExprComponentList
&Components
;
21347 bool IsNonContiguous
= false;
21348 bool NoDiagnose
= false;
21349 const Expr
*RelevantExpr
= nullptr;
21350 bool AllowUnitySizeArraySection
= true;
21351 bool AllowWholeSizeArraySection
= true;
21352 bool AllowAnotherPtr
= true;
21353 SourceLocation ELoc
;
21354 SourceRange ERange
;
21356 void emitErrorMsg() {
21357 // If nothing else worked, this is not a valid map clause expression.
21358 if (SemaRef
.getLangOpts().OpenMP
< 50) {
21360 diag::err_omp_expected_named_var_member_or_array_expression
)
21363 SemaRef
.Diag(ELoc
, diag::err_omp_non_lvalue_in_map_or_motion_clauses
)
21364 << getOpenMPClauseName(CKind
) << ERange
;
21369 bool VisitDeclRefExpr(DeclRefExpr
*DRE
) {
21370 if (!isa
<VarDecl
>(DRE
->getDecl())) {
21374 assert(!RelevantExpr
&& "RelevantExpr is expected to be nullptr");
21375 RelevantExpr
= DRE
;
21376 // Record the component.
21377 Components
.emplace_back(DRE
, DRE
->getDecl(), IsNonContiguous
);
21381 bool VisitMemberExpr(MemberExpr
*ME
) {
21383 Expr
*BaseE
= ME
->getBase()->IgnoreParenCasts();
21385 if (isa
<CXXThisExpr
>(BaseE
)) {
21386 assert(!RelevantExpr
&& "RelevantExpr is expected to be nullptr");
21387 // We found a base expression: this->Val.
21393 if (!isa
<FieldDecl
>(ME
->getMemberDecl())) {
21395 SemaRef
.Diag(ELoc
, diag::err_omp_expected_access_to_data_field
)
21396 << ME
->getSourceRange();
21404 auto *FD
= cast
<FieldDecl
>(ME
->getMemberDecl());
21406 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
21407 // A bit-field cannot appear in a map clause.
21409 if (FD
->isBitField()) {
21411 SemaRef
.Diag(ELoc
, diag::err_omp_bit_fields_forbidden_in_clause
)
21412 << ME
->getSourceRange() << getOpenMPClauseName(CKind
);
21420 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21421 // If the type of a list item is a reference to a type T then the type
21422 // will be considered to be T for all purposes of this clause.
21423 QualType CurType
= BaseE
->getType().getNonReferenceType();
21425 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
21426 // A list item cannot be a variable that is a member of a structure with
21429 if (CurType
->isUnionType()) {
21431 SemaRef
.Diag(ELoc
, diag::err_omp_union_type_not_allowed
)
21432 << ME
->getSourceRange();
21435 return RelevantExpr
|| Visit(E
);
21438 // If we got a member expression, we should not expect any array section
21441 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
21442 // If a list item is an element of a structure, only the rightmost symbol
21443 // of the variable reference can be an array section.
21445 AllowUnitySizeArraySection
= false;
21446 AllowWholeSizeArraySection
= false;
21448 // Record the component.
21449 Components
.emplace_back(ME
, FD
, IsNonContiguous
);
21450 return RelevantExpr
|| Visit(E
);
21453 bool VisitArraySubscriptExpr(ArraySubscriptExpr
*AE
) {
21454 Expr
*E
= AE
->getBase()->IgnoreParenImpCasts();
21456 if (!E
->getType()->isAnyPointerType() && !E
->getType()->isArrayType()) {
21458 SemaRef
.Diag(ELoc
, diag::err_omp_expected_base_var_name
)
21459 << 0 << AE
->getSourceRange();
21462 return RelevantExpr
|| Visit(E
);
21465 // If we got an array subscript that express the whole dimension we
21466 // can have any array expressions before. If it only expressing part of
21467 // the dimension, we can only have unitary-size array expressions.
21468 if (checkArrayExpressionDoesNotReferToWholeSize(SemaRef
, AE
, E
->getType()))
21469 AllowWholeSizeArraySection
= false;
21471 if (const auto *TE
= dyn_cast
<CXXThisExpr
>(E
->IgnoreParenCasts())) {
21472 Expr::EvalResult Result
;
21473 if (!AE
->getIdx()->isValueDependent() &&
21474 AE
->getIdx()->EvaluateAsInt(Result
, SemaRef
.getASTContext()) &&
21475 !Result
.Val
.getInt().isZero()) {
21476 SemaRef
.Diag(AE
->getIdx()->getExprLoc(),
21477 diag::err_omp_invalid_map_this_expr
);
21478 SemaRef
.Diag(AE
->getIdx()->getExprLoc(),
21479 diag::note_omp_invalid_subscript_on_this_ptr_map
);
21481 assert(!RelevantExpr
&& "RelevantExpr is expected to be nullptr");
21485 // Record the component - we don't have any declaration associated.
21486 Components
.emplace_back(AE
, nullptr, IsNonContiguous
);
21488 return RelevantExpr
|| Visit(E
);
21491 bool VisitOMPArraySectionExpr(OMPArraySectionExpr
*OASE
) {
21492 // After OMP 5.0 Array section in reduction clause will be implicitly
21494 assert(!(SemaRef
.getLangOpts().OpenMP
< 50 && NoDiagnose
) &&
21495 "Array sections cannot be implicitly mapped.");
21496 Expr
*E
= OASE
->getBase()->IgnoreParenImpCasts();
21498 OMPArraySectionExpr::getBaseOriginalType(E
).getCanonicalType();
21500 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21501 // If the type of a list item is a reference to a type T then the type
21502 // will be considered to be T for all purposes of this clause.
21503 if (CurType
->isReferenceType())
21504 CurType
= CurType
->getPointeeType();
21506 bool IsPointer
= CurType
->isAnyPointerType();
21508 if (!IsPointer
&& !CurType
->isArrayType()) {
21509 SemaRef
.Diag(ELoc
, diag::err_omp_expected_base_var_name
)
21510 << 0 << OASE
->getSourceRange();
21515 checkArrayExpressionDoesNotReferToWholeSize(SemaRef
, OASE
, CurType
);
21517 checkArrayExpressionDoesNotReferToUnitySize(SemaRef
, OASE
, CurType
);
21519 if (AllowWholeSizeArraySection
) {
21520 // Any array section is currently allowed. Allowing a whole size array
21521 // section implies allowing a unity array section as well.
21523 // If this array section refers to the whole dimension we can still
21524 // accept other array sections before this one, except if the base is a
21525 // pointer. Otherwise, only unitary sections are accepted.
21526 if (NotWhole
|| IsPointer
)
21527 AllowWholeSizeArraySection
= false;
21528 } else if (DKind
== OMPD_target_update
&&
21529 SemaRef
.getLangOpts().OpenMP
>= 50) {
21530 if (IsPointer
&& !AllowAnotherPtr
)
21531 SemaRef
.Diag(ELoc
, diag::err_omp_section_length_undefined
)
21532 << /*array of unknown bound */ 1;
21534 IsNonContiguous
= true;
21535 } else if (AllowUnitySizeArraySection
&& NotUnity
) {
21536 // A unity or whole array section is not allowed and that is not
21537 // compatible with the properties of the current array section.
21541 diag::err_array_section_does_not_specify_contiguous_storage
)
21542 << OASE
->getSourceRange();
21547 AllowAnotherPtr
= false;
21549 if (const auto *TE
= dyn_cast
<CXXThisExpr
>(E
)) {
21550 Expr::EvalResult ResultR
;
21551 Expr::EvalResult ResultL
;
21552 if (!OASE
->getLength()->isValueDependent() &&
21553 OASE
->getLength()->EvaluateAsInt(ResultR
, SemaRef
.getASTContext()) &&
21554 !ResultR
.Val
.getInt().isOne()) {
21555 SemaRef
.Diag(OASE
->getLength()->getExprLoc(),
21556 diag::err_omp_invalid_map_this_expr
);
21557 SemaRef
.Diag(OASE
->getLength()->getExprLoc(),
21558 diag::note_omp_invalid_length_on_this_ptr_mapping
);
21560 if (OASE
->getLowerBound() && !OASE
->getLowerBound()->isValueDependent() &&
21561 OASE
->getLowerBound()->EvaluateAsInt(ResultL
,
21562 SemaRef
.getASTContext()) &&
21563 !ResultL
.Val
.getInt().isZero()) {
21564 SemaRef
.Diag(OASE
->getLowerBound()->getExprLoc(),
21565 diag::err_omp_invalid_map_this_expr
);
21566 SemaRef
.Diag(OASE
->getLowerBound()->getExprLoc(),
21567 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping
);
21569 assert(!RelevantExpr
&& "RelevantExpr is expected to be nullptr");
21573 // Record the component - we don't have any declaration associated.
21574 Components
.emplace_back(OASE
, nullptr, /*IsNonContiguous=*/false);
21575 return RelevantExpr
|| Visit(E
);
21577 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr
*E
) {
21578 Expr
*Base
= E
->getBase();
21580 // Record the component - we don't have any declaration associated.
21581 Components
.emplace_back(E
, nullptr, IsNonContiguous
);
21583 return Visit(Base
->IgnoreParenImpCasts());
21586 bool VisitUnaryOperator(UnaryOperator
*UO
) {
21587 if (SemaRef
.getLangOpts().OpenMP
< 50 || !UO
->isLValue() ||
21588 UO
->getOpcode() != UO_Deref
) {
21592 if (!RelevantExpr
) {
21593 // Record the component if haven't found base decl.
21594 Components
.emplace_back(UO
, nullptr, /*IsNonContiguous=*/false);
21596 return RelevantExpr
|| Visit(UO
->getSubExpr()->IgnoreParenImpCasts());
21598 bool VisitBinaryOperator(BinaryOperator
*BO
) {
21599 if (SemaRef
.getLangOpts().OpenMP
< 50 || !BO
->getType()->isPointerType()) {
21604 // Pointer arithmetic is the only thing we expect to happen here so after we
21605 // make sure the binary operator is a pointer type, the only thing we need
21606 // to do is to visit the subtree that has the same type as root (so that we
21607 // know the other subtree is just an offset)
21608 Expr
*LE
= BO
->getLHS()->IgnoreParenImpCasts();
21609 Expr
*RE
= BO
->getRHS()->IgnoreParenImpCasts();
21610 Components
.emplace_back(BO
, nullptr, false);
21611 assert((LE
->getType().getTypePtr() == BO
->getType().getTypePtr() ||
21612 RE
->getType().getTypePtr() == BO
->getType().getTypePtr()) &&
21613 "Either LHS or RHS have base decl inside");
21614 if (BO
->getType().getTypePtr() == LE
->getType().getTypePtr())
21615 return RelevantExpr
|| Visit(LE
);
21616 return RelevantExpr
|| Visit(RE
);
21618 bool VisitCXXThisExpr(CXXThisExpr
*CTE
) {
21619 assert(!RelevantExpr
&& "RelevantExpr is expected to be nullptr");
21620 RelevantExpr
= CTE
;
21621 Components
.emplace_back(CTE
, nullptr, IsNonContiguous
);
21624 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr
*COCE
) {
21625 assert(!RelevantExpr
&& "RelevantExpr is expected to be nullptr");
21626 Components
.emplace_back(COCE
, nullptr, IsNonContiguous
);
21629 bool VisitOpaqueValueExpr(OpaqueValueExpr
*E
) {
21630 Expr
*Source
= E
->getSourceExpr();
21635 return Visit(Source
);
21637 bool VisitStmt(Stmt
*) {
21641 const Expr
*getFoundBase() const { return RelevantExpr
; }
21642 explicit MapBaseChecker(
21643 Sema
&SemaRef
, OpenMPClauseKind CKind
, OpenMPDirectiveKind DKind
,
21644 OMPClauseMappableExprCommon::MappableExprComponentList
&Components
,
21645 bool NoDiagnose
, SourceLocation
&ELoc
, SourceRange
&ERange
)
21646 : SemaRef(SemaRef
), CKind(CKind
), DKind(DKind
), Components(Components
),
21647 NoDiagnose(NoDiagnose
), ELoc(ELoc
), ERange(ERange
) {}
21651 /// Return the expression of the base of the mappable expression or null if it
21652 /// cannot be determined and do all the necessary checks to see if the
21653 /// expression is valid as a standalone mappable expression. In the process,
21654 /// record all the components of the expression.
21655 static const Expr
*checkMapClauseExpressionBase(
21656 Sema
&SemaRef
, Expr
*E
,
21657 OMPClauseMappableExprCommon::MappableExprComponentList
&CurComponents
,
21658 OpenMPClauseKind CKind
, OpenMPDirectiveKind DKind
, bool NoDiagnose
) {
21659 SourceLocation ELoc
= E
->getExprLoc();
21660 SourceRange ERange
= E
->getSourceRange();
21661 MapBaseChecker
Checker(SemaRef
, CKind
, DKind
, CurComponents
, NoDiagnose
, ELoc
,
21663 if (Checker
.Visit(E
->IgnoreParens())) {
21664 // Check if the highest dimension array section has length specified
21665 if (SemaRef
.getLangOpts().OpenMP
>= 50 && !CurComponents
.empty() &&
21666 (CKind
== OMPC_to
|| CKind
== OMPC_from
)) {
21667 auto CI
= CurComponents
.rbegin();
21668 auto CE
= CurComponents
.rend();
21669 for (; CI
!= CE
; ++CI
) {
21671 dyn_cast
<OMPArraySectionExpr
>(CI
->getAssociatedExpression());
21674 if (OASE
&& OASE
->getLength())
21676 SemaRef
.Diag(ELoc
, diag::err_array_section_does_not_specify_length
)
21680 return Checker
.getFoundBase();
21685 // Return true if expression E associated with value VD has conflicts with other
21686 // map information.
21687 static bool checkMapConflicts(
21688 Sema
&SemaRef
, DSAStackTy
*DSAS
, const ValueDecl
*VD
, const Expr
*E
,
21689 bool CurrentRegionOnly
,
21690 OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents
,
21691 OpenMPClauseKind CKind
) {
21693 SourceLocation ELoc
= E
->getExprLoc();
21694 SourceRange ERange
= E
->getSourceRange();
21696 // In order to easily check the conflicts we need to match each component of
21697 // the expression under test with the components of the expressions that are
21698 // already in the stack.
21700 assert(!CurComponents
.empty() && "Map clause expression with no components!");
21701 assert(CurComponents
.back().getAssociatedDeclaration() == VD
&&
21702 "Map clause expression with unexpected base!");
21704 // Variables to help detecting enclosing problems in data environment nests.
21705 bool IsEnclosedByDataEnvironmentExpr
= false;
21706 const Expr
*EnclosingExpr
= nullptr;
21708 bool FoundError
= DSAS
->checkMappableExprComponentListsForDecl(
21709 VD
, CurrentRegionOnly
,
21710 [&IsEnclosedByDataEnvironmentExpr
, &SemaRef
, VD
, CurrentRegionOnly
, ELoc
,
21711 ERange
, CKind
, &EnclosingExpr
,
21712 CurComponents
](OMPClauseMappableExprCommon::MappableExprComponentListRef
21714 OpenMPClauseKind Kind
) {
21715 if (CKind
== Kind
&& SemaRef
.LangOpts
.OpenMP
>= 50)
21717 assert(!StackComponents
.empty() &&
21718 "Map clause expression with no components!");
21719 assert(StackComponents
.back().getAssociatedDeclaration() == VD
&&
21720 "Map clause expression with unexpected base!");
21723 // The whole expression in the stack.
21724 const Expr
*RE
= StackComponents
.front().getAssociatedExpression();
21726 // Expressions must start from the same base. Here we detect at which
21727 // point both expressions diverge from each other and see if we can
21728 // detect if the memory referred to both expressions is contiguous and
21730 auto CI
= CurComponents
.rbegin();
21731 auto CE
= CurComponents
.rend();
21732 auto SI
= StackComponents
.rbegin();
21733 auto SE
= StackComponents
.rend();
21734 for (; CI
!= CE
&& SI
!= SE
; ++CI
, ++SI
) {
21736 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
21737 // At most one list item can be an array item derived from a given
21738 // variable in map clauses of the same construct.
21739 if (CurrentRegionOnly
&&
21740 (isa
<ArraySubscriptExpr
>(CI
->getAssociatedExpression()) ||
21741 isa
<OMPArraySectionExpr
>(CI
->getAssociatedExpression()) ||
21742 isa
<OMPArrayShapingExpr
>(CI
->getAssociatedExpression())) &&
21743 (isa
<ArraySubscriptExpr
>(SI
->getAssociatedExpression()) ||
21744 isa
<OMPArraySectionExpr
>(SI
->getAssociatedExpression()) ||
21745 isa
<OMPArrayShapingExpr
>(SI
->getAssociatedExpression()))) {
21746 SemaRef
.Diag(CI
->getAssociatedExpression()->getExprLoc(),
21747 diag::err_omp_multiple_array_items_in_map_clause
)
21748 << CI
->getAssociatedExpression()->getSourceRange();
21749 SemaRef
.Diag(SI
->getAssociatedExpression()->getExprLoc(),
21750 diag::note_used_here
)
21751 << SI
->getAssociatedExpression()->getSourceRange();
21755 // Do both expressions have the same kind?
21756 if (CI
->getAssociatedExpression()->getStmtClass() !=
21757 SI
->getAssociatedExpression()->getStmtClass())
21760 // Are we dealing with different variables/fields?
21761 if (CI
->getAssociatedDeclaration() != SI
->getAssociatedDeclaration())
21764 // Check if the extra components of the expressions in the enclosing
21765 // data environment are redundant for the current base declaration.
21766 // If they are, the maps completely overlap, which is legal.
21767 for (; SI
!= SE
; ++SI
) {
21769 if (const auto *ASE
=
21770 dyn_cast
<ArraySubscriptExpr
>(SI
->getAssociatedExpression())) {
21771 Type
= ASE
->getBase()->IgnoreParenImpCasts()->getType();
21772 } else if (const auto *OASE
= dyn_cast
<OMPArraySectionExpr
>(
21773 SI
->getAssociatedExpression())) {
21774 const Expr
*E
= OASE
->getBase()->IgnoreParenImpCasts();
21776 OMPArraySectionExpr::getBaseOriginalType(E
).getCanonicalType();
21777 } else if (const auto *OASE
= dyn_cast
<OMPArrayShapingExpr
>(
21778 SI
->getAssociatedExpression())) {
21779 Type
= OASE
->getBase()->getType()->getPointeeType();
21781 if (Type
.isNull() || Type
->isAnyPointerType() ||
21782 checkArrayExpressionDoesNotReferToWholeSize(
21783 SemaRef
, SI
->getAssociatedExpression(), Type
))
21787 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21788 // List items of map clauses in the same construct must not share
21789 // original storage.
21791 // If the expressions are exactly the same or one is a subset of the
21792 // other, it means they are sharing storage.
21793 if (CI
== CE
&& SI
== SE
) {
21794 if (CurrentRegionOnly
) {
21795 if (CKind
== OMPC_map
) {
21796 SemaRef
.Diag(ELoc
, diag::err_omp_map_shared_storage
) << ERange
;
21798 assert(CKind
== OMPC_to
|| CKind
== OMPC_from
);
21799 SemaRef
.Diag(ELoc
, diag::err_omp_once_referenced_in_target_update
)
21802 SemaRef
.Diag(RE
->getExprLoc(), diag::note_used_here
)
21803 << RE
->getSourceRange();
21806 // If we find the same expression in the enclosing data environment,
21808 IsEnclosedByDataEnvironmentExpr
= true;
21812 QualType DerivedType
=
21813 std::prev(CI
)->getAssociatedDeclaration()->getType();
21814 SourceLocation DerivedLoc
=
21815 std::prev(CI
)->getAssociatedExpression()->getExprLoc();
21817 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21818 // If the type of a list item is a reference to a type T then the type
21819 // will be considered to be T for all purposes of this clause.
21820 DerivedType
= DerivedType
.getNonReferenceType();
21822 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
21823 // A variable for which the type is pointer and an array section
21824 // derived from that variable must not appear as list items of map
21825 // clauses of the same construct.
21827 // Also, cover one of the cases in:
21828 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21829 // If any part of the original storage of a list item has corresponding
21830 // storage in the device data environment, all of the original storage
21831 // must have corresponding storage in the device data environment.
21833 if (DerivedType
->isAnyPointerType()) {
21834 if (CI
== CE
|| SI
== SE
) {
21837 diag::err_omp_pointer_mapped_along_with_derived_section
)
21839 SemaRef
.Diag(RE
->getExprLoc(), diag::note_used_here
)
21840 << RE
->getSourceRange();
21843 if (CI
->getAssociatedExpression()->getStmtClass() !=
21844 SI
->getAssociatedExpression()->getStmtClass() ||
21845 CI
->getAssociatedDeclaration()->getCanonicalDecl() ==
21846 SI
->getAssociatedDeclaration()->getCanonicalDecl()) {
21847 assert(CI
!= CE
&& SI
!= SE
);
21848 SemaRef
.Diag(DerivedLoc
, diag::err_omp_same_pointer_dereferenced
)
21850 SemaRef
.Diag(RE
->getExprLoc(), diag::note_used_here
)
21851 << RE
->getSourceRange();
21856 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21857 // List items of map clauses in the same construct must not share
21858 // original storage.
21860 // An expression is a subset of the other.
21861 if (CurrentRegionOnly
&& (CI
== CE
|| SI
== SE
)) {
21862 if (CKind
== OMPC_map
) {
21863 if (CI
!= CE
|| SI
!= SE
) {
21864 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
21867 CI
!= CE
? CurComponents
.begin() : StackComponents
.begin();
21868 auto End
= CI
!= CE
? CurComponents
.end() : StackComponents
.end();
21870 while (It
!= End
&& !It
->getAssociatedDeclaration())
21871 std::advance(It
, 1);
21872 assert(It
!= End
&&
21873 "Expected at least one component with the declaration.");
21874 if (It
!= Begin
&& It
->getAssociatedDeclaration()
21876 .getCanonicalType()
21877 ->isAnyPointerType()) {
21878 IsEnclosedByDataEnvironmentExpr
= false;
21879 EnclosingExpr
= nullptr;
21883 SemaRef
.Diag(ELoc
, diag::err_omp_map_shared_storage
) << ERange
;
21885 assert(CKind
== OMPC_to
|| CKind
== OMPC_from
);
21886 SemaRef
.Diag(ELoc
, diag::err_omp_once_referenced_in_target_update
)
21889 SemaRef
.Diag(RE
->getExprLoc(), diag::note_used_here
)
21890 << RE
->getSourceRange();
21894 // The current expression uses the same base as other expression in the
21895 // data environment but does not contain it completely.
21896 if (!CurrentRegionOnly
&& SI
!= SE
)
21897 EnclosingExpr
= RE
;
21899 // The current expression is a subset of the expression in the data
21901 IsEnclosedByDataEnvironmentExpr
|=
21902 (!CurrentRegionOnly
&& CI
!= CE
&& SI
== SE
);
21907 if (CurrentRegionOnly
)
21910 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21911 // If any part of the original storage of a list item has corresponding
21912 // storage in the device data environment, all of the original storage must
21913 // have corresponding storage in the device data environment.
21914 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
21915 // If a list item is an element of a structure, and a different element of
21916 // the structure has a corresponding list item in the device data environment
21917 // prior to a task encountering the construct associated with the map clause,
21918 // then the list item must also have a corresponding list item in the device
21919 // data environment prior to the task encountering the construct.
21921 if (EnclosingExpr
&& !IsEnclosedByDataEnvironmentExpr
) {
21923 diag::err_omp_original_storage_is_shared_and_does_not_contain
)
21925 SemaRef
.Diag(EnclosingExpr
->getExprLoc(), diag::note_used_here
)
21926 << EnclosingExpr
->getSourceRange();
21933 // Look up the user-defined mapper given the mapper name and mapped type, and
21934 // build a reference to it.
21935 static ExprResult
buildUserDefinedMapperRef(Sema
&SemaRef
, Scope
*S
,
21936 CXXScopeSpec
&MapperIdScopeSpec
,
21937 const DeclarationNameInfo
&MapperId
,
21939 Expr
*UnresolvedMapper
) {
21940 if (MapperIdScopeSpec
.isInvalid())
21941 return ExprError();
21942 // Get the actual type for the array type.
21943 if (Type
->isArrayType()) {
21944 assert(Type
->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
21945 Type
= Type
->getAsArrayTypeUnsafe()->getElementType().getCanonicalType();
21947 // Find all user-defined mappers with the given MapperId.
21948 SmallVector
<UnresolvedSet
<8>, 4> Lookups
;
21949 LookupResult
Lookup(SemaRef
, MapperId
, Sema::LookupOMPMapperName
);
21950 Lookup
.suppressDiagnostics();
21952 while (S
&& SemaRef
.LookupParsedName(Lookup
, S
, &MapperIdScopeSpec
)) {
21953 NamedDecl
*D
= Lookup
.getRepresentativeDecl();
21954 while (S
&& !S
->isDeclScope(D
))
21955 S
= S
->getParent();
21957 S
= S
->getParent();
21958 Lookups
.emplace_back();
21959 Lookups
.back().append(Lookup
.begin(), Lookup
.end());
21962 } else if (auto *ULE
= cast_or_null
<UnresolvedLookupExpr
>(UnresolvedMapper
)) {
21963 // Extract the user-defined mappers with the given MapperId.
21964 Lookups
.push_back(UnresolvedSet
<8>());
21965 for (NamedDecl
*D
: ULE
->decls()) {
21966 auto *DMD
= cast
<OMPDeclareMapperDecl
>(D
);
21967 assert(DMD
&& "Expect valid OMPDeclareMapperDecl during instantiation.");
21968 Lookups
.back().addDecl(DMD
);
21971 // Defer the lookup for dependent types. The results will be passed through
21972 // UnresolvedMapper on instantiation.
21973 if (SemaRef
.CurContext
->isDependentContext() || Type
->isDependentType() ||
21974 Type
->isInstantiationDependentType() ||
21975 Type
->containsUnexpandedParameterPack() ||
21976 filterLookupForUDReductionAndMapper
<bool>(Lookups
, [](ValueDecl
*D
) {
21977 return !D
->isInvalidDecl() &&
21978 (D
->getType()->isDependentType() ||
21979 D
->getType()->isInstantiationDependentType() ||
21980 D
->getType()->containsUnexpandedParameterPack());
21982 UnresolvedSet
<8> URS
;
21983 for (const UnresolvedSet
<8> &Set
: Lookups
) {
21986 URS
.append(Set
.begin(), Set
.end());
21988 return UnresolvedLookupExpr::Create(
21989 SemaRef
.Context
, /*NamingClass=*/nullptr,
21990 MapperIdScopeSpec
.getWithLocInContext(SemaRef
.Context
), MapperId
,
21991 /*ADL=*/false, /*Overloaded=*/true, URS
.begin(), URS
.end());
21993 SourceLocation Loc
= MapperId
.getLoc();
21994 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21995 // The type must be of struct, union or class type in C and C++
21996 if (!Type
->isStructureOrClassType() && !Type
->isUnionType() &&
21997 (MapperIdScopeSpec
.isSet() || MapperId
.getAsString() != "default")) {
21998 SemaRef
.Diag(Loc
, diag::err_omp_mapper_wrong_type
);
21999 return ExprError();
22001 // Perform argument dependent lookup.
22002 if (SemaRef
.getLangOpts().CPlusPlus
&& !MapperIdScopeSpec
.isSet())
22003 argumentDependentLookup(SemaRef
, MapperId
, Loc
, Type
, Lookups
);
22004 // Return the first user-defined mapper with the desired type.
22005 if (auto *VD
= filterLookupForUDReductionAndMapper
<ValueDecl
*>(
22006 Lookups
, [&SemaRef
, Type
](ValueDecl
*D
) -> ValueDecl
* {
22007 if (!D
->isInvalidDecl() &&
22008 SemaRef
.Context
.hasSameType(D
->getType(), Type
))
22012 return SemaRef
.BuildDeclRefExpr(VD
, Type
, VK_LValue
, Loc
);
22013 // Find the first user-defined mapper with a type derived from the desired
22015 if (auto *VD
= filterLookupForUDReductionAndMapper
<ValueDecl
*>(
22016 Lookups
, [&SemaRef
, Type
, Loc
](ValueDecl
*D
) -> ValueDecl
* {
22017 if (!D
->isInvalidDecl() &&
22018 SemaRef
.IsDerivedFrom(Loc
, Type
, D
->getType()) &&
22019 !Type
.isMoreQualifiedThan(D
->getType()))
22023 CXXBasePaths
Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
22024 /*DetectVirtual=*/false);
22025 if (SemaRef
.IsDerivedFrom(Loc
, Type
, VD
->getType(), Paths
)) {
22026 if (!Paths
.isAmbiguous(SemaRef
.Context
.getCanonicalType(
22027 VD
->getType().getUnqualifiedType()))) {
22028 if (SemaRef
.CheckBaseClassAccess(
22029 Loc
, VD
->getType(), Type
, Paths
.front(),
22030 /*DiagID=*/0) != Sema::AR_inaccessible
) {
22031 return SemaRef
.BuildDeclRefExpr(VD
, Type
, VK_LValue
, Loc
);
22036 // Report error if a mapper is specified, but cannot be found.
22037 if (MapperIdScopeSpec
.isSet() || MapperId
.getAsString() != "default") {
22038 SemaRef
.Diag(Loc
, diag::err_omp_invalid_mapper
)
22039 << Type
<< MapperId
.getName();
22040 return ExprError();
22042 return ExprEmpty();
22046 // Utility struct that gathers all the related lists associated with a mappable
22048 struct MappableVarListInfo
{
22049 // The list of expressions.
22050 ArrayRef
<Expr
*> VarList
;
22051 // The list of processed expressions.
22052 SmallVector
<Expr
*, 16> ProcessedVarList
;
22053 // The mappble components for each expression.
22054 OMPClauseMappableExprCommon::MappableExprComponentLists VarComponents
;
22055 // The base declaration of the variable.
22056 SmallVector
<ValueDecl
*, 16> VarBaseDeclarations
;
22057 // The reference to the user-defined mapper associated with every expression.
22058 SmallVector
<Expr
*, 16> UDMapperList
;
22060 MappableVarListInfo(ArrayRef
<Expr
*> VarList
) : VarList(VarList
) {
22061 // We have a list of components and base declarations for each entry in the
22063 VarComponents
.reserve(VarList
.size());
22064 VarBaseDeclarations
.reserve(VarList
.size());
22069 // Check the validity of the provided variable list for the provided clause kind
22070 // \a CKind. In the check process the valid expressions, mappable expression
22071 // components, variables, and user-defined mappers are extracted and used to
22072 // fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
22073 // UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
22074 // and \a MapperId are expected to be valid if the clause kind is 'map'.
22075 static void checkMappableExpressionList(
22076 Sema
&SemaRef
, DSAStackTy
*DSAS
, OpenMPClauseKind CKind
,
22077 MappableVarListInfo
&MVLI
, SourceLocation StartLoc
,
22078 CXXScopeSpec
&MapperIdScopeSpec
, DeclarationNameInfo MapperId
,
22079 ArrayRef
<Expr
*> UnresolvedMappers
,
22080 OpenMPMapClauseKind MapType
= OMPC_MAP_unknown
,
22081 ArrayRef
<OpenMPMapModifierKind
> Modifiers
= std::nullopt
,
22082 bool IsMapTypeImplicit
= false, bool NoDiagnose
= false) {
22083 // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
22084 assert((CKind
== OMPC_map
|| CKind
== OMPC_to
|| CKind
== OMPC_from
) &&
22085 "Unexpected clause kind with mappable expressions!");
22087 // If the identifier of user-defined mapper is not specified, it is "default".
22088 // We do not change the actual name in this clause to distinguish whether a
22089 // mapper is specified explicitly, i.e., it is not explicitly specified when
22090 // MapperId.getName() is empty.
22091 if (!MapperId
.getName() || MapperId
.getName().isEmpty()) {
22092 auto &DeclNames
= SemaRef
.getASTContext().DeclarationNames
;
22093 MapperId
.setName(DeclNames
.getIdentifier(
22094 &SemaRef
.getASTContext().Idents
.get("default")));
22095 MapperId
.setLoc(StartLoc
);
22098 // Iterators to find the current unresolved mapper expression.
22099 auto UMIt
= UnresolvedMappers
.begin(), UMEnd
= UnresolvedMappers
.end();
22100 bool UpdateUMIt
= false;
22101 Expr
*UnresolvedMapper
= nullptr;
22103 bool HasHoldModifier
=
22104 llvm::is_contained(Modifiers
, OMPC_MAP_MODIFIER_ompx_hold
);
22106 // Keep track of the mappable components and base declarations in this clause.
22107 // Each entry in the list is going to have a list of components associated. We
22108 // record each set of the components so that we can build the clause later on.
22109 // In the end we should have the same amount of declarations and component
22112 for (Expr
*RE
: MVLI
.VarList
) {
22113 assert(RE
&& "Null expr in omp to/from/map clause");
22114 SourceLocation ELoc
= RE
->getExprLoc();
22116 // Find the current unresolved mapper expression.
22117 if (UpdateUMIt
&& UMIt
!= UMEnd
) {
22121 "Expect the size of UnresolvedMappers to match with that of VarList");
22125 UnresolvedMapper
= *UMIt
;
22127 const Expr
*VE
= RE
->IgnoreParenLValueCasts();
22129 if (VE
->isValueDependent() || VE
->isTypeDependent() ||
22130 VE
->isInstantiationDependent() ||
22131 VE
->containsUnexpandedParameterPack()) {
22132 // Try to find the associated user-defined mapper.
22133 ExprResult ER
= buildUserDefinedMapperRef(
22134 SemaRef
, DSAS
->getCurScope(), MapperIdScopeSpec
, MapperId
,
22135 VE
->getType().getCanonicalType(), UnresolvedMapper
);
22136 if (ER
.isInvalid())
22138 MVLI
.UDMapperList
.push_back(ER
.get());
22139 // We can only analyze this information once the missing information is
22141 MVLI
.ProcessedVarList
.push_back(RE
);
22145 Expr
*SimpleExpr
= RE
->IgnoreParenCasts();
22147 if (!RE
->isLValue()) {
22148 if (SemaRef
.getLangOpts().OpenMP
< 50) {
22150 ELoc
, diag::err_omp_expected_named_var_member_or_array_expression
)
22151 << RE
->getSourceRange();
22153 SemaRef
.Diag(ELoc
, diag::err_omp_non_lvalue_in_map_or_motion_clauses
)
22154 << getOpenMPClauseName(CKind
) << RE
->getSourceRange();
22159 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents
;
22160 ValueDecl
*CurDeclaration
= nullptr;
22162 // Obtain the array or member expression bases if required. Also, fill the
22163 // components array with all the components identified in the process.
22165 checkMapClauseExpressionBase(SemaRef
, SimpleExpr
, CurComponents
, CKind
,
22166 DSAS
->getCurrentDirective(), NoDiagnose
);
22170 assert(!CurComponents
.empty() &&
22171 "Invalid mappable expression information.");
22173 if (const auto *TE
= dyn_cast
<CXXThisExpr
>(BE
)) {
22174 // Add store "this" pointer to class in DSAStackTy for future checking
22175 DSAS
->addMappedClassesQualTypes(TE
->getType());
22176 // Try to find the associated user-defined mapper.
22177 ExprResult ER
= buildUserDefinedMapperRef(
22178 SemaRef
, DSAS
->getCurScope(), MapperIdScopeSpec
, MapperId
,
22179 VE
->getType().getCanonicalType(), UnresolvedMapper
);
22180 if (ER
.isInvalid())
22182 MVLI
.UDMapperList
.push_back(ER
.get());
22183 // Skip restriction checking for variable or field declarations
22184 MVLI
.ProcessedVarList
.push_back(RE
);
22185 MVLI
.VarComponents
.resize(MVLI
.VarComponents
.size() + 1);
22186 MVLI
.VarComponents
.back().append(CurComponents
.begin(),
22187 CurComponents
.end());
22188 MVLI
.VarBaseDeclarations
.push_back(nullptr);
22192 // For the following checks, we rely on the base declaration which is
22193 // expected to be associated with the last component. The declaration is
22194 // expected to be a variable or a field (if 'this' is being mapped).
22195 CurDeclaration
= CurComponents
.back().getAssociatedDeclaration();
22196 assert(CurDeclaration
&& "Null decl on map clause.");
22198 CurDeclaration
->isCanonicalDecl() &&
22199 "Expecting components to have associated only canonical declarations.");
22201 auto *VD
= dyn_cast
<VarDecl
>(CurDeclaration
);
22202 const auto *FD
= dyn_cast
<FieldDecl
>(CurDeclaration
);
22204 assert((VD
|| FD
) && "Only variables or fields are expected here!");
22207 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
22208 // threadprivate variables cannot appear in a map clause.
22209 // OpenMP 4.5 [2.10.5, target update Construct]
22210 // threadprivate variables cannot appear in a from clause.
22211 if (VD
&& DSAS
->isThreadPrivate(VD
)) {
22214 DSAStackTy::DSAVarData DVar
= DSAS
->getTopDSA(VD
, /*FromParent=*/false);
22215 SemaRef
.Diag(ELoc
, diag::err_omp_threadprivate_in_clause
)
22216 << getOpenMPClauseName(CKind
);
22217 reportOriginalDsa(SemaRef
, DSAS
, VD
, DVar
);
22221 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
22222 // A list item cannot appear in both a map clause and a data-sharing
22223 // attribute clause on the same construct.
22225 // Check conflicts with other map clause expressions. We check the conflicts
22226 // with the current construct separately from the enclosing data
22227 // environment, because the restrictions are different. We only have to
22228 // check conflicts across regions for the map clauses.
22229 if (checkMapConflicts(SemaRef
, DSAS
, CurDeclaration
, SimpleExpr
,
22230 /*CurrentRegionOnly=*/true, CurComponents
, CKind
))
22232 if (CKind
== OMPC_map
&&
22233 (SemaRef
.getLangOpts().OpenMP
<= 45 || StartLoc
.isValid()) &&
22234 checkMapConflicts(SemaRef
, DSAS
, CurDeclaration
, SimpleExpr
,
22235 /*CurrentRegionOnly=*/false, CurComponents
, CKind
))
22238 // OpenMP 4.5 [2.10.5, target update Construct]
22239 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22240 // If the type of a list item is a reference to a type T then the type will
22241 // be considered to be T for all purposes of this clause.
22242 auto I
= llvm::find_if(
22244 [](const OMPClauseMappableExprCommon::MappableComponent
&MC
) {
22245 return MC
.getAssociatedDeclaration();
22247 assert(I
!= CurComponents
.end() && "Null decl on map clause.");
22250 auto *ASE
= dyn_cast
<ArraySubscriptExpr
>(VE
->IgnoreParens());
22251 auto *OASE
= dyn_cast
<OMPArraySectionExpr
>(VE
->IgnoreParens());
22252 auto *OAShE
= dyn_cast
<OMPArrayShapingExpr
>(VE
->IgnoreParens());
22254 Type
= ASE
->getType().getNonReferenceType();
22256 QualType BaseType
=
22257 OMPArraySectionExpr::getBaseOriginalType(OASE
->getBase());
22258 if (const auto *ATy
= BaseType
->getAsArrayTypeUnsafe())
22259 Type
= ATy
->getElementType();
22261 Type
= BaseType
->getPointeeType();
22262 Type
= Type
.getNonReferenceType();
22263 } else if (OAShE
) {
22264 Type
= OAShE
->getBase()->getType()->getPointeeType();
22266 Type
= VE
->getType();
22269 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
22270 // A list item in a to or from clause must have a mappable type.
22271 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
22272 // A list item must have a mappable type.
22273 if (!checkTypeMappable(VE
->getExprLoc(), VE
->getSourceRange(), SemaRef
,
22274 DSAS
, Type
, /*FullCheck=*/true))
22277 if (CKind
== OMPC_map
) {
22278 // target enter data
22279 // OpenMP [2.10.2, Restrictions, p. 99]
22280 // A map-type must be specified in all map clauses and must be either
22281 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
22282 // no map type is present.
22283 OpenMPDirectiveKind DKind
= DSAS
->getCurrentDirective();
22284 if (DKind
== OMPD_target_enter_data
&&
22285 !(MapType
== OMPC_MAP_to
|| MapType
== OMPC_MAP_alloc
||
22286 SemaRef
.getLangOpts().OpenMP
>= 52)) {
22287 SemaRef
.Diag(StartLoc
, diag::err_omp_invalid_map_type_for_directive
)
22288 << (IsMapTypeImplicit
? 1 : 0)
22289 << getOpenMPSimpleClauseTypeName(OMPC_map
, MapType
)
22290 << getOpenMPDirectiveName(DKind
);
22294 // target exit_data
22295 // OpenMP [2.10.3, Restrictions, p. 102]
22296 // A map-type must be specified in all map clauses and must be either
22297 // from, release, or delete. Starting with OpenMP 5.2 the default map
22298 // type is `from` if no map type is present.
22299 if (DKind
== OMPD_target_exit_data
&&
22300 !(MapType
== OMPC_MAP_from
|| MapType
== OMPC_MAP_release
||
22301 MapType
== OMPC_MAP_delete
|| SemaRef
.getLangOpts().OpenMP
>= 52)) {
22302 SemaRef
.Diag(StartLoc
, diag::err_omp_invalid_map_type_for_directive
)
22303 << (IsMapTypeImplicit
? 1 : 0)
22304 << getOpenMPSimpleClauseTypeName(OMPC_map
, MapType
)
22305 << getOpenMPDirectiveName(DKind
);
22309 // The 'ompx_hold' modifier is specifically intended to be used on a
22310 // 'target' or 'target data' directive to prevent data from being unmapped
22311 // during the associated statement. It is not permitted on a 'target
22312 // enter data' or 'target exit data' directive, which have no associated
22314 if ((DKind
== OMPD_target_enter_data
|| DKind
== OMPD_target_exit_data
) &&
22316 SemaRef
.Diag(StartLoc
,
22317 diag::err_omp_invalid_map_type_modifier_for_directive
)
22318 << getOpenMPSimpleClauseTypeName(OMPC_map
,
22319 OMPC_MAP_MODIFIER_ompx_hold
)
22320 << getOpenMPDirectiveName(DKind
);
22324 // target, target data
22325 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
22326 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
22327 // A map-type in a map clause must be to, from, tofrom or alloc
22328 if ((DKind
== OMPD_target_data
||
22329 isOpenMPTargetExecutionDirective(DKind
)) &&
22330 !(MapType
== OMPC_MAP_to
|| MapType
== OMPC_MAP_from
||
22331 MapType
== OMPC_MAP_tofrom
|| MapType
== OMPC_MAP_alloc
)) {
22332 SemaRef
.Diag(StartLoc
, diag::err_omp_invalid_map_type_for_directive
)
22333 << (IsMapTypeImplicit
? 1 : 0)
22334 << getOpenMPSimpleClauseTypeName(OMPC_map
, MapType
)
22335 << getOpenMPDirectiveName(DKind
);
22339 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
22340 // A list item cannot appear in both a map clause and a data-sharing
22341 // attribute clause on the same construct
22343 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
22344 // A list item cannot appear in both a map clause and a data-sharing
22345 // attribute clause on the same construct unless the construct is a
22346 // combined construct.
22347 if (VD
&& ((SemaRef
.LangOpts
.OpenMP
<= 45 &&
22348 isOpenMPTargetExecutionDirective(DKind
)) ||
22349 DKind
== OMPD_target
)) {
22350 DSAStackTy::DSAVarData DVar
= DSAS
->getTopDSA(VD
, /*FromParent=*/false);
22351 if (isOpenMPPrivate(DVar
.CKind
)) {
22352 SemaRef
.Diag(ELoc
, diag::err_omp_variable_in_given_clause_and_dsa
)
22353 << getOpenMPClauseName(DVar
.CKind
)
22354 << getOpenMPClauseName(OMPC_map
)
22355 << getOpenMPDirectiveName(DSAS
->getCurrentDirective());
22356 reportOriginalDsa(SemaRef
, DSAS
, CurDeclaration
, DVar
);
22362 // Try to find the associated user-defined mapper.
22363 ExprResult ER
= buildUserDefinedMapperRef(
22364 SemaRef
, DSAS
->getCurScope(), MapperIdScopeSpec
, MapperId
,
22365 Type
.getCanonicalType(), UnresolvedMapper
);
22366 if (ER
.isInvalid())
22368 MVLI
.UDMapperList
.push_back(ER
.get());
22370 // Save the current expression.
22371 MVLI
.ProcessedVarList
.push_back(RE
);
22373 // Store the components in the stack so that they can be used to check
22374 // against other clauses later on.
22375 DSAS
->addMappableExpressionComponents(CurDeclaration
, CurComponents
,
22376 /*WhereFoundClauseKind=*/OMPC_map
);
22378 // Save the components and declaration to create the clause. For purposes of
22379 // the clause creation, any component list that has base 'this' uses
22380 // null as base declaration.
22381 MVLI
.VarComponents
.resize(MVLI
.VarComponents
.size() + 1);
22382 MVLI
.VarComponents
.back().append(CurComponents
.begin(),
22383 CurComponents
.end());
22384 MVLI
.VarBaseDeclarations
.push_back(isa
<MemberExpr
>(BE
) ? nullptr
22389 OMPClause
*Sema::ActOnOpenMPMapClause(
22390 Expr
*IteratorModifier
, ArrayRef
<OpenMPMapModifierKind
> MapTypeModifiers
,
22391 ArrayRef
<SourceLocation
> MapTypeModifiersLoc
,
22392 CXXScopeSpec
&MapperIdScopeSpec
, DeclarationNameInfo
&MapperId
,
22393 OpenMPMapClauseKind MapType
, bool IsMapTypeImplicit
, SourceLocation MapLoc
,
22394 SourceLocation ColonLoc
, ArrayRef
<Expr
*> VarList
,
22395 const OMPVarListLocTy
&Locs
, bool NoDiagnose
,
22396 ArrayRef
<Expr
*> UnresolvedMappers
) {
22397 OpenMPMapModifierKind Modifiers
[] = {
22398 OMPC_MAP_MODIFIER_unknown
, OMPC_MAP_MODIFIER_unknown
,
22399 OMPC_MAP_MODIFIER_unknown
, OMPC_MAP_MODIFIER_unknown
,
22400 OMPC_MAP_MODIFIER_unknown
, OMPC_MAP_MODIFIER_unknown
};
22401 SourceLocation ModifiersLoc
[NumberOfOMPMapClauseModifiers
];
22403 if (IteratorModifier
&& !IteratorModifier
->getType()->isSpecificBuiltinType(
22404 BuiltinType::OMPIterator
))
22405 Diag(IteratorModifier
->getExprLoc(),
22406 diag::err_omp_map_modifier_not_iterator
);
22408 // Process map-type-modifiers, flag errors for duplicate modifiers.
22409 unsigned Count
= 0;
22410 for (unsigned I
= 0, E
= MapTypeModifiers
.size(); I
< E
; ++I
) {
22411 if (MapTypeModifiers
[I
] != OMPC_MAP_MODIFIER_unknown
&&
22412 llvm::is_contained(Modifiers
, MapTypeModifiers
[I
])) {
22413 Diag(MapTypeModifiersLoc
[I
], diag::err_omp_duplicate_map_type_modifier
);
22416 assert(Count
< NumberOfOMPMapClauseModifiers
&&
22417 "Modifiers exceed the allowed number of map type modifiers");
22418 Modifiers
[Count
] = MapTypeModifiers
[I
];
22419 ModifiersLoc
[Count
] = MapTypeModifiersLoc
[I
];
22423 MappableVarListInfo
MVLI(VarList
);
22424 checkMappableExpressionList(*this, DSAStack
, OMPC_map
, MVLI
, Locs
.StartLoc
,
22425 MapperIdScopeSpec
, MapperId
, UnresolvedMappers
,
22426 MapType
, Modifiers
, IsMapTypeImplicit
,
22429 // We need to produce a map clause even if we don't have variables so that
22430 // other diagnostics related with non-existing map clauses are accurate.
22431 return OMPMapClause::Create(
22432 Context
, Locs
, MVLI
.ProcessedVarList
, MVLI
.VarBaseDeclarations
,
22433 MVLI
.VarComponents
, MVLI
.UDMapperList
, IteratorModifier
, Modifiers
,
22434 ModifiersLoc
, MapperIdScopeSpec
.getWithLocInContext(Context
), MapperId
,
22435 MapType
, IsMapTypeImplicit
, MapLoc
);
22438 QualType
Sema::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc
,
22439 TypeResult ParsedType
) {
22440 assert(ParsedType
.isUsable());
22442 QualType ReductionType
= GetTypeFromParser(ParsedType
.get());
22443 if (ReductionType
.isNull())
22446 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
22447 // A type name in a declare reduction directive cannot be a function type, an
22448 // array type, a reference type, or a type qualified with const, volatile or
22450 if (ReductionType
.hasQualifiers()) {
22451 Diag(TyLoc
, diag::err_omp_reduction_wrong_type
) << 0;
22455 if (ReductionType
->isFunctionType()) {
22456 Diag(TyLoc
, diag::err_omp_reduction_wrong_type
) << 1;
22459 if (ReductionType
->isReferenceType()) {
22460 Diag(TyLoc
, diag::err_omp_reduction_wrong_type
) << 2;
22463 if (ReductionType
->isArrayType()) {
22464 Diag(TyLoc
, diag::err_omp_reduction_wrong_type
) << 3;
22467 return ReductionType
;
22470 Sema::DeclGroupPtrTy
Sema::ActOnOpenMPDeclareReductionDirectiveStart(
22471 Scope
*S
, DeclContext
*DC
, DeclarationName Name
,
22472 ArrayRef
<std::pair
<QualType
, SourceLocation
>> ReductionTypes
,
22473 AccessSpecifier AS
, Decl
*PrevDeclInScope
) {
22474 SmallVector
<Decl
*, 8> Decls
;
22475 Decls
.reserve(ReductionTypes
.size());
22477 LookupResult
Lookup(*this, Name
, SourceLocation(), LookupOMPReductionName
,
22478 forRedeclarationInCurContext());
22479 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
22480 // A reduction-identifier may not be re-declared in the current scope for the
22481 // same type or for a type that is compatible according to the base language
22483 llvm::DenseMap
<QualType
, SourceLocation
> PreviousRedeclTypes
;
22484 OMPDeclareReductionDecl
*PrevDRD
= nullptr;
22485 bool InCompoundScope
= true;
22486 if (S
!= nullptr) {
22487 // Find previous declaration with the same name not referenced in other
22489 FunctionScopeInfo
*ParentFn
= getEnclosingFunction();
22491 (ParentFn
!= nullptr) && !ParentFn
->CompoundScopes
.empty();
22492 LookupName(Lookup
, S
);
22493 FilterLookupForScope(Lookup
, DC
, S
, /*ConsiderLinkage=*/false,
22494 /*AllowInlineNamespace=*/false);
22495 llvm::DenseMap
<OMPDeclareReductionDecl
*, bool> UsedAsPrevious
;
22496 LookupResult::Filter Filter
= Lookup
.makeFilter();
22497 while (Filter
.hasNext()) {
22498 auto *PrevDecl
= cast
<OMPDeclareReductionDecl
>(Filter
.next());
22499 if (InCompoundScope
) {
22500 auto I
= UsedAsPrevious
.find(PrevDecl
);
22501 if (I
== UsedAsPrevious
.end())
22502 UsedAsPrevious
[PrevDecl
] = false;
22503 if (OMPDeclareReductionDecl
*D
= PrevDecl
->getPrevDeclInScope())
22504 UsedAsPrevious
[D
] = true;
22506 PreviousRedeclTypes
[PrevDecl
->getType().getCanonicalType()] =
22507 PrevDecl
->getLocation();
22510 if (InCompoundScope
) {
22511 for (const auto &PrevData
: UsedAsPrevious
) {
22512 if (!PrevData
.second
) {
22513 PrevDRD
= PrevData
.first
;
22518 } else if (PrevDeclInScope
!= nullptr) {
22519 auto *PrevDRDInScope
= PrevDRD
=
22520 cast
<OMPDeclareReductionDecl
>(PrevDeclInScope
);
22522 PreviousRedeclTypes
[PrevDRDInScope
->getType().getCanonicalType()] =
22523 PrevDRDInScope
->getLocation();
22524 PrevDRDInScope
= PrevDRDInScope
->getPrevDeclInScope();
22525 } while (PrevDRDInScope
!= nullptr);
22527 for (const auto &TyData
: ReductionTypes
) {
22528 const auto I
= PreviousRedeclTypes
.find(TyData
.first
.getCanonicalType());
22529 bool Invalid
= false;
22530 if (I
!= PreviousRedeclTypes
.end()) {
22531 Diag(TyData
.second
, diag::err_omp_declare_reduction_redefinition
)
22533 Diag(I
->second
, diag::note_previous_definition
);
22536 PreviousRedeclTypes
[TyData
.first
.getCanonicalType()] = TyData
.second
;
22537 auto *DRD
= OMPDeclareReductionDecl::Create(Context
, DC
, TyData
.second
,
22538 Name
, TyData
.first
, PrevDRD
);
22540 DRD
->setAccess(AS
);
22541 Decls
.push_back(DRD
);
22543 DRD
->setInvalidDecl();
22548 return DeclGroupPtrTy::make(
22549 DeclGroupRef::Create(Context
, Decls
.begin(), Decls
.size()));
22552 void Sema::ActOnOpenMPDeclareReductionCombinerStart(Scope
*S
, Decl
*D
) {
22553 auto *DRD
= cast
<OMPDeclareReductionDecl
>(D
);
22555 // Enter new function scope.
22556 PushFunctionScope();
22557 setFunctionHasBranchProtectedScope();
22558 getCurFunction()->setHasOMPDeclareReductionCombiner();
22561 PushDeclContext(S
, DRD
);
22565 PushExpressionEvaluationContext(
22566 ExpressionEvaluationContext::PotentiallyEvaluated
);
22568 QualType ReductionType
= DRD
->getType();
22569 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
22570 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
22571 // uses semantics of argument handles by value, but it should be passed by
22572 // reference. C lang does not support references, so pass all parameters as
22574 // Create 'T omp_in;' variable.
22575 VarDecl
*OmpInParm
=
22576 buildVarDecl(*this, D
->getLocation(), ReductionType
, "omp_in");
22577 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
22578 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
22579 // uses semantics of argument handles by value, but it should be passed by
22580 // reference. C lang does not support references, so pass all parameters as
22582 // Create 'T omp_out;' variable.
22583 VarDecl
*OmpOutParm
=
22584 buildVarDecl(*this, D
->getLocation(), ReductionType
, "omp_out");
22585 if (S
!= nullptr) {
22586 PushOnScopeChains(OmpInParm
, S
);
22587 PushOnScopeChains(OmpOutParm
, S
);
22589 DRD
->addDecl(OmpInParm
);
22590 DRD
->addDecl(OmpOutParm
);
22593 ::buildDeclRefExpr(*this, OmpInParm
, ReductionType
, D
->getLocation());
22595 ::buildDeclRefExpr(*this, OmpOutParm
, ReductionType
, D
->getLocation());
22596 DRD
->setCombinerData(InE
, OutE
);
22599 void Sema::ActOnOpenMPDeclareReductionCombinerEnd(Decl
*D
, Expr
*Combiner
) {
22600 auto *DRD
= cast
<OMPDeclareReductionDecl
>(D
);
22601 DiscardCleanupsInEvaluationContext();
22602 PopExpressionEvaluationContext();
22605 PopFunctionScopeInfo();
22607 if (Combiner
!= nullptr)
22608 DRD
->setCombiner(Combiner
);
22610 DRD
->setInvalidDecl();
22613 VarDecl
*Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope
*S
, Decl
*D
) {
22614 auto *DRD
= cast
<OMPDeclareReductionDecl
>(D
);
22616 // Enter new function scope.
22617 PushFunctionScope();
22618 setFunctionHasBranchProtectedScope();
22621 PushDeclContext(S
, DRD
);
22625 PushExpressionEvaluationContext(
22626 ExpressionEvaluationContext::PotentiallyEvaluated
);
22628 QualType ReductionType
= DRD
->getType();
22629 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
22630 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
22631 // uses semantics of argument handles by value, but it should be passed by
22632 // reference. C lang does not support references, so pass all parameters as
22634 // Create 'T omp_priv;' variable.
22635 VarDecl
*OmpPrivParm
=
22636 buildVarDecl(*this, D
->getLocation(), ReductionType
, "omp_priv");
22637 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
22638 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
22639 // uses semantics of argument handles by value, but it should be passed by
22640 // reference. C lang does not support references, so pass all parameters as
22642 // Create 'T omp_orig;' variable.
22643 VarDecl
*OmpOrigParm
=
22644 buildVarDecl(*this, D
->getLocation(), ReductionType
, "omp_orig");
22645 if (S
!= nullptr) {
22646 PushOnScopeChains(OmpPrivParm
, S
);
22647 PushOnScopeChains(OmpOrigParm
, S
);
22649 DRD
->addDecl(OmpPrivParm
);
22650 DRD
->addDecl(OmpOrigParm
);
22653 ::buildDeclRefExpr(*this, OmpOrigParm
, ReductionType
, D
->getLocation());
22655 ::buildDeclRefExpr(*this, OmpPrivParm
, ReductionType
, D
->getLocation());
22656 DRD
->setInitializerData(OrigE
, PrivE
);
22657 return OmpPrivParm
;
22660 void Sema::ActOnOpenMPDeclareReductionInitializerEnd(Decl
*D
, Expr
*Initializer
,
22661 VarDecl
*OmpPrivParm
) {
22662 auto *DRD
= cast
<OMPDeclareReductionDecl
>(D
);
22663 DiscardCleanupsInEvaluationContext();
22664 PopExpressionEvaluationContext();
22667 PopFunctionScopeInfo();
22669 if (Initializer
!= nullptr) {
22670 DRD
->setInitializer(Initializer
, OMPDeclareReductionInitKind::Call
);
22671 } else if (OmpPrivParm
->hasInit()) {
22672 DRD
->setInitializer(OmpPrivParm
->getInit(),
22673 OmpPrivParm
->isDirectInit()
22674 ? OMPDeclareReductionInitKind::Direct
22675 : OMPDeclareReductionInitKind::Copy
);
22677 DRD
->setInvalidDecl();
22681 Sema::DeclGroupPtrTy
Sema::ActOnOpenMPDeclareReductionDirectiveEnd(
22682 Scope
*S
, DeclGroupPtrTy DeclReductions
, bool IsValid
) {
22683 for (Decl
*D
: DeclReductions
.get()) {
22686 PushOnScopeChains(cast
<OMPDeclareReductionDecl
>(D
), S
,
22687 /*AddToContext=*/false);
22689 D
->setInvalidDecl();
22692 return DeclReductions
;
22695 TypeResult
Sema::ActOnOpenMPDeclareMapperVarDecl(Scope
*S
, Declarator
&D
) {
22696 TypeSourceInfo
*TInfo
= GetTypeForDeclarator(D
, S
);
22697 QualType T
= TInfo
->getType();
22698 if (D
.isInvalidType())
22701 if (getLangOpts().CPlusPlus
) {
22702 // Check that there are no default arguments (C++ only).
22703 CheckExtraCXXDefaultArguments(D
);
22706 return CreateParsedType(T
, TInfo
);
22709 QualType
Sema::ActOnOpenMPDeclareMapperType(SourceLocation TyLoc
,
22710 TypeResult ParsedType
) {
22711 assert(ParsedType
.isUsable() && "Expect usable parsed mapper type");
22713 QualType MapperType
= GetTypeFromParser(ParsedType
.get());
22714 assert(!MapperType
.isNull() && "Expect valid mapper type");
22716 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22717 // The type must be of struct, union or class type in C and C++
22718 if (!MapperType
->isStructureOrClassType() && !MapperType
->isUnionType()) {
22719 Diag(TyLoc
, diag::err_omp_mapper_wrong_type
);
22725 Sema::DeclGroupPtrTy
Sema::ActOnOpenMPDeclareMapperDirective(
22726 Scope
*S
, DeclContext
*DC
, DeclarationName Name
, QualType MapperType
,
22727 SourceLocation StartLoc
, DeclarationName VN
, AccessSpecifier AS
,
22728 Expr
*MapperVarRef
, ArrayRef
<OMPClause
*> Clauses
, Decl
*PrevDeclInScope
) {
22729 LookupResult
Lookup(*this, Name
, SourceLocation(), LookupOMPMapperName
,
22730 forRedeclarationInCurContext());
22731 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22732 // A mapper-identifier may not be redeclared in the current scope for the
22733 // same type or for a type that is compatible according to the base language
22735 llvm::DenseMap
<QualType
, SourceLocation
> PreviousRedeclTypes
;
22736 OMPDeclareMapperDecl
*PrevDMD
= nullptr;
22737 bool InCompoundScope
= true;
22738 if (S
!= nullptr) {
22739 // Find previous declaration with the same name not referenced in other
22741 FunctionScopeInfo
*ParentFn
= getEnclosingFunction();
22743 (ParentFn
!= nullptr) && !ParentFn
->CompoundScopes
.empty();
22744 LookupName(Lookup
, S
);
22745 FilterLookupForScope(Lookup
, DC
, S
, /*ConsiderLinkage=*/false,
22746 /*AllowInlineNamespace=*/false);
22747 llvm::DenseMap
<OMPDeclareMapperDecl
*, bool> UsedAsPrevious
;
22748 LookupResult::Filter Filter
= Lookup
.makeFilter();
22749 while (Filter
.hasNext()) {
22750 auto *PrevDecl
= cast
<OMPDeclareMapperDecl
>(Filter
.next());
22751 if (InCompoundScope
) {
22752 auto I
= UsedAsPrevious
.find(PrevDecl
);
22753 if (I
== UsedAsPrevious
.end())
22754 UsedAsPrevious
[PrevDecl
] = false;
22755 if (OMPDeclareMapperDecl
*D
= PrevDecl
->getPrevDeclInScope())
22756 UsedAsPrevious
[D
] = true;
22758 PreviousRedeclTypes
[PrevDecl
->getType().getCanonicalType()] =
22759 PrevDecl
->getLocation();
22762 if (InCompoundScope
) {
22763 for (const auto &PrevData
: UsedAsPrevious
) {
22764 if (!PrevData
.second
) {
22765 PrevDMD
= PrevData
.first
;
22770 } else if (PrevDeclInScope
) {
22771 auto *PrevDMDInScope
= PrevDMD
=
22772 cast
<OMPDeclareMapperDecl
>(PrevDeclInScope
);
22774 PreviousRedeclTypes
[PrevDMDInScope
->getType().getCanonicalType()] =
22775 PrevDMDInScope
->getLocation();
22776 PrevDMDInScope
= PrevDMDInScope
->getPrevDeclInScope();
22777 } while (PrevDMDInScope
!= nullptr);
22779 const auto I
= PreviousRedeclTypes
.find(MapperType
.getCanonicalType());
22780 bool Invalid
= false;
22781 if (I
!= PreviousRedeclTypes
.end()) {
22782 Diag(StartLoc
, diag::err_omp_declare_mapper_redefinition
)
22783 << MapperType
<< Name
;
22784 Diag(I
->second
, diag::note_previous_definition
);
22787 // Build expressions for implicit maps of data members with 'default'
22789 SmallVector
<OMPClause
*, 4> ClausesWithImplicit(Clauses
.begin(),
22791 if (LangOpts
.OpenMP
>= 50)
22792 processImplicitMapsWithDefaultMappers(*this, DSAStack
, ClausesWithImplicit
);
22794 OMPDeclareMapperDecl::Create(Context
, DC
, StartLoc
, Name
, MapperType
, VN
,
22795 ClausesWithImplicit
, PrevDMD
);
22797 PushOnScopeChains(DMD
, S
);
22800 DMD
->setAccess(AS
);
22802 DMD
->setInvalidDecl();
22804 auto *VD
= cast
<DeclRefExpr
>(MapperVarRef
)->getDecl();
22805 VD
->setDeclContext(DMD
);
22806 VD
->setLexicalDeclContext(DMD
);
22808 DMD
->setMapperVarRef(MapperVarRef
);
22810 return DeclGroupPtrTy::make(DeclGroupRef(DMD
));
22814 Sema::ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope
*S
, QualType MapperType
,
22815 SourceLocation StartLoc
,
22816 DeclarationName VN
) {
22817 TypeSourceInfo
*TInfo
=
22818 Context
.getTrivialTypeSourceInfo(MapperType
, StartLoc
);
22819 auto *VD
= VarDecl::Create(Context
, Context
.getTranslationUnitDecl(),
22820 StartLoc
, StartLoc
, VN
.getAsIdentifierInfo(),
22821 MapperType
, TInfo
, SC_None
);
22823 PushOnScopeChains(VD
, S
, /*AddToContext=*/false);
22824 Expr
*E
= buildDeclRefExpr(*this, VD
, MapperType
, StartLoc
);
22825 DSAStack
->addDeclareMapperVarRef(E
);
22829 void Sema::ActOnOpenMPIteratorVarDecl(VarDecl
*VD
) {
22830 if (DSAStack
->getDeclareMapperVarRef())
22831 DSAStack
->addIteratorVarDecl(VD
);
22834 bool Sema::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl
*VD
) const {
22835 assert(LangOpts
.OpenMP
&& "Expected OpenMP mode.");
22836 const Expr
*Ref
= DSAStack
->getDeclareMapperVarRef();
22837 if (const auto *DRE
= cast_or_null
<DeclRefExpr
>(Ref
)) {
22838 if (VD
->getCanonicalDecl() == DRE
->getDecl()->getCanonicalDecl())
22840 if (VD
->isUsableInConstantExpressions(Context
))
22842 if (LangOpts
.OpenMP
>= 52 && DSAStack
->isIteratorVarDecl(VD
))
22849 const ValueDecl
*Sema::getOpenMPDeclareMapperVarName() const {
22850 assert(LangOpts
.OpenMP
&& "Expected OpenMP mode.");
22851 return cast
<DeclRefExpr
>(DSAStack
->getDeclareMapperVarRef())->getDecl();
22854 OMPClause
*Sema::ActOnOpenMPNumTeamsClause(Expr
*NumTeams
,
22855 SourceLocation StartLoc
,
22856 SourceLocation LParenLoc
,
22857 SourceLocation EndLoc
) {
22858 Expr
*ValExpr
= NumTeams
;
22859 Stmt
*HelperValStmt
= nullptr;
22861 // OpenMP [teams Constrcut, Restrictions]
22862 // The num_teams expression must evaluate to a positive integer value.
22863 if (!isNonNegativeIntegerValue(ValExpr
, *this, OMPC_num_teams
,
22864 /*StrictlyPositive=*/true))
22867 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
22868 OpenMPDirectiveKind CaptureRegion
=
22869 getOpenMPCaptureRegionForClause(DKind
, OMPC_num_teams
, LangOpts
.OpenMP
);
22870 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
22871 ValExpr
= MakeFullExpr(ValExpr
).get();
22872 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
22873 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
22874 HelperValStmt
= buildPreInits(Context
, Captures
);
22877 return new (Context
) OMPNumTeamsClause(ValExpr
, HelperValStmt
, CaptureRegion
,
22878 StartLoc
, LParenLoc
, EndLoc
);
22881 OMPClause
*Sema::ActOnOpenMPThreadLimitClause(Expr
*ThreadLimit
,
22882 SourceLocation StartLoc
,
22883 SourceLocation LParenLoc
,
22884 SourceLocation EndLoc
) {
22885 Expr
*ValExpr
= ThreadLimit
;
22886 Stmt
*HelperValStmt
= nullptr;
22888 // OpenMP [teams Constrcut, Restrictions]
22889 // The thread_limit expression must evaluate to a positive integer value.
22890 if (!isNonNegativeIntegerValue(ValExpr
, *this, OMPC_thread_limit
,
22891 /*StrictlyPositive=*/true))
22894 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
22895 OpenMPDirectiveKind CaptureRegion
= getOpenMPCaptureRegionForClause(
22896 DKind
, OMPC_thread_limit
, LangOpts
.OpenMP
);
22897 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
22898 ValExpr
= MakeFullExpr(ValExpr
).get();
22899 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
22900 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
22901 HelperValStmt
= buildPreInits(Context
, Captures
);
22904 return new (Context
) OMPThreadLimitClause(
22905 ValExpr
, HelperValStmt
, CaptureRegion
, StartLoc
, LParenLoc
, EndLoc
);
22908 OMPClause
*Sema::ActOnOpenMPPriorityClause(Expr
*Priority
,
22909 SourceLocation StartLoc
,
22910 SourceLocation LParenLoc
,
22911 SourceLocation EndLoc
) {
22912 Expr
*ValExpr
= Priority
;
22913 Stmt
*HelperValStmt
= nullptr;
22914 OpenMPDirectiveKind CaptureRegion
= OMPD_unknown
;
22916 // OpenMP [2.9.1, task Constrcut]
22917 // The priority-value is a non-negative numerical scalar expression.
22918 if (!isNonNegativeIntegerValue(
22919 ValExpr
, *this, OMPC_priority
,
22920 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
22921 DSAStack
->getCurrentDirective(), &CaptureRegion
, &HelperValStmt
))
22924 return new (Context
) OMPPriorityClause(ValExpr
, HelperValStmt
, CaptureRegion
,
22925 StartLoc
, LParenLoc
, EndLoc
);
22928 OMPClause
*Sema::ActOnOpenMPGrainsizeClause(
22929 OpenMPGrainsizeClauseModifier Modifier
, Expr
*Grainsize
,
22930 SourceLocation StartLoc
, SourceLocation LParenLoc
,
22931 SourceLocation ModifierLoc
, SourceLocation EndLoc
) {
22932 assert((ModifierLoc
.isInvalid() || LangOpts
.OpenMP
>= 51) &&
22933 "Unexpected grainsize modifier in OpenMP < 51.");
22935 if (ModifierLoc
.isValid() && Modifier
== OMPC_GRAINSIZE_unknown
) {
22936 std::string Values
= getListOfPossibleValues(OMPC_grainsize
, /*First=*/0,
22937 OMPC_GRAINSIZE_unknown
);
22938 Diag(ModifierLoc
, diag::err_omp_unexpected_clause_value
)
22939 << Values
<< getOpenMPClauseName(OMPC_grainsize
);
22943 Expr
*ValExpr
= Grainsize
;
22944 Stmt
*HelperValStmt
= nullptr;
22945 OpenMPDirectiveKind CaptureRegion
= OMPD_unknown
;
22947 // OpenMP [2.9.2, taskloop Constrcut]
22948 // The parameter of the grainsize clause must be a positive integer
22950 if (!isNonNegativeIntegerValue(ValExpr
, *this, OMPC_grainsize
,
22951 /*StrictlyPositive=*/true,
22952 /*BuildCapture=*/true,
22953 DSAStack
->getCurrentDirective(),
22954 &CaptureRegion
, &HelperValStmt
))
22957 return new (Context
)
22958 OMPGrainsizeClause(Modifier
, ValExpr
, HelperValStmt
, CaptureRegion
,
22959 StartLoc
, LParenLoc
, ModifierLoc
, EndLoc
);
22962 OMPClause
*Sema::ActOnOpenMPNumTasksClause(
22963 OpenMPNumTasksClauseModifier Modifier
, Expr
*NumTasks
,
22964 SourceLocation StartLoc
, SourceLocation LParenLoc
,
22965 SourceLocation ModifierLoc
, SourceLocation EndLoc
) {
22966 assert((ModifierLoc
.isInvalid() || LangOpts
.OpenMP
>= 51) &&
22967 "Unexpected num_tasks modifier in OpenMP < 51.");
22969 if (ModifierLoc
.isValid() && Modifier
== OMPC_NUMTASKS_unknown
) {
22970 std::string Values
= getListOfPossibleValues(OMPC_num_tasks
, /*First=*/0,
22971 OMPC_NUMTASKS_unknown
);
22972 Diag(ModifierLoc
, diag::err_omp_unexpected_clause_value
)
22973 << Values
<< getOpenMPClauseName(OMPC_num_tasks
);
22977 Expr
*ValExpr
= NumTasks
;
22978 Stmt
*HelperValStmt
= nullptr;
22979 OpenMPDirectiveKind CaptureRegion
= OMPD_unknown
;
22981 // OpenMP [2.9.2, taskloop Constrcut]
22982 // The parameter of the num_tasks clause must be a positive integer
22984 if (!isNonNegativeIntegerValue(
22985 ValExpr
, *this, OMPC_num_tasks
,
22986 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
22987 DSAStack
->getCurrentDirective(), &CaptureRegion
, &HelperValStmt
))
22990 return new (Context
)
22991 OMPNumTasksClause(Modifier
, ValExpr
, HelperValStmt
, CaptureRegion
,
22992 StartLoc
, LParenLoc
, ModifierLoc
, EndLoc
);
22995 OMPClause
*Sema::ActOnOpenMPHintClause(Expr
*Hint
, SourceLocation StartLoc
,
22996 SourceLocation LParenLoc
,
22997 SourceLocation EndLoc
) {
22998 // OpenMP [2.13.2, critical construct, Description]
22999 // ... where hint-expression is an integer constant expression that evaluates
23000 // to a valid lock hint.
23001 ExprResult HintExpr
=
23002 VerifyPositiveIntegerConstantInClause(Hint
, OMPC_hint
, false);
23003 if (HintExpr
.isInvalid())
23005 return new (Context
)
23006 OMPHintClause(HintExpr
.get(), StartLoc
, LParenLoc
, EndLoc
);
23009 /// Tries to find omp_event_handle_t type.
23010 static bool findOMPEventHandleT(Sema
&S
, SourceLocation Loc
,
23011 DSAStackTy
*Stack
) {
23012 QualType OMPEventHandleT
= Stack
->getOMPEventHandleT();
23013 if (!OMPEventHandleT
.isNull())
23015 IdentifierInfo
*II
= &S
.PP
.getIdentifierTable().get("omp_event_handle_t");
23016 ParsedType PT
= S
.getTypeName(*II
, Loc
, S
.getCurScope());
23017 if (!PT
.getAsOpaquePtr() || PT
.get().isNull()) {
23018 S
.Diag(Loc
, diag::err_omp_implied_type_not_found
) << "omp_event_handle_t";
23021 Stack
->setOMPEventHandleT(PT
.get());
23025 OMPClause
*Sema::ActOnOpenMPDetachClause(Expr
*Evt
, SourceLocation StartLoc
,
23026 SourceLocation LParenLoc
,
23027 SourceLocation EndLoc
) {
23028 if (!Evt
->isValueDependent() && !Evt
->isTypeDependent() &&
23029 !Evt
->isInstantiationDependent() &&
23030 !Evt
->containsUnexpandedParameterPack()) {
23031 if (!findOMPEventHandleT(*this, Evt
->getExprLoc(), DSAStack
))
23033 // OpenMP 5.0, 2.10.1 task Construct.
23034 // event-handle is a variable of the omp_event_handle_t type.
23035 auto *Ref
= dyn_cast
<DeclRefExpr
>(Evt
->IgnoreParenImpCasts());
23037 Diag(Evt
->getExprLoc(), diag::err_omp_var_expected
)
23038 << "omp_event_handle_t" << 0 << Evt
->getSourceRange();
23041 auto *VD
= dyn_cast_or_null
<VarDecl
>(Ref
->getDecl());
23043 Diag(Evt
->getExprLoc(), diag::err_omp_var_expected
)
23044 << "omp_event_handle_t" << 0 << Evt
->getSourceRange();
23047 if (!Context
.hasSameUnqualifiedType(DSAStack
->getOMPEventHandleT(),
23049 VD
->getType().isConstant(Context
)) {
23050 Diag(Evt
->getExprLoc(), diag::err_omp_var_expected
)
23051 << "omp_event_handle_t" << 1 << VD
->getType()
23052 << Evt
->getSourceRange();
23055 // OpenMP 5.0, 2.10.1 task Construct
23056 // [detach clause]... The event-handle will be considered as if it was
23057 // specified on a firstprivate clause.
23058 DSAStackTy::DSAVarData DVar
= DSAStack
->getTopDSA(VD
, /*FromParent=*/false);
23059 if (DVar
.CKind
!= OMPC_unknown
&& DVar
.CKind
!= OMPC_firstprivate
&&
23061 Diag(Evt
->getExprLoc(), diag::err_omp_wrong_dsa
)
23062 << getOpenMPClauseName(DVar
.CKind
)
23063 << getOpenMPClauseName(OMPC_firstprivate
);
23064 reportOriginalDsa(*this, DSAStack
, VD
, DVar
);
23069 return new (Context
) OMPDetachClause(Evt
, StartLoc
, LParenLoc
, EndLoc
);
23072 OMPClause
*Sema::ActOnOpenMPDistScheduleClause(
23073 OpenMPDistScheduleClauseKind Kind
, Expr
*ChunkSize
, SourceLocation StartLoc
,
23074 SourceLocation LParenLoc
, SourceLocation KindLoc
, SourceLocation CommaLoc
,
23075 SourceLocation EndLoc
) {
23076 if (Kind
== OMPC_DIST_SCHEDULE_unknown
) {
23077 std::string Values
;
23079 Values
+= getOpenMPSimpleClauseTypeName(OMPC_dist_schedule
, 0);
23081 Diag(KindLoc
, diag::err_omp_unexpected_clause_value
)
23082 << Values
<< getOpenMPClauseName(OMPC_dist_schedule
);
23085 Expr
*ValExpr
= ChunkSize
;
23086 Stmt
*HelperValStmt
= nullptr;
23088 if (!ChunkSize
->isValueDependent() && !ChunkSize
->isTypeDependent() &&
23089 !ChunkSize
->isInstantiationDependent() &&
23090 !ChunkSize
->containsUnexpandedParameterPack()) {
23091 SourceLocation ChunkSizeLoc
= ChunkSize
->getBeginLoc();
23093 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc
, ChunkSize
);
23094 if (Val
.isInvalid())
23097 ValExpr
= Val
.get();
23099 // OpenMP [2.7.1, Restrictions]
23100 // chunk_size must be a loop invariant integer expression with a positive
23102 if (std::optional
<llvm::APSInt
> Result
=
23103 ValExpr
->getIntegerConstantExpr(Context
)) {
23104 if (Result
->isSigned() && !Result
->isStrictlyPositive()) {
23105 Diag(ChunkSizeLoc
, diag::err_omp_negative_expression_in_clause
)
23106 << "dist_schedule" << ChunkSize
->getSourceRange();
23109 } else if (getOpenMPCaptureRegionForClause(
23110 DSAStack
->getCurrentDirective(), OMPC_dist_schedule
,
23111 LangOpts
.OpenMP
) != OMPD_unknown
&&
23112 !CurContext
->isDependentContext()) {
23113 ValExpr
= MakeFullExpr(ValExpr
).get();
23114 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
23115 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
23116 HelperValStmt
= buildPreInits(Context
, Captures
);
23121 return new (Context
)
23122 OMPDistScheduleClause(StartLoc
, LParenLoc
, KindLoc
, CommaLoc
, EndLoc
,
23123 Kind
, ValExpr
, HelperValStmt
);
23126 OMPClause
*Sema::ActOnOpenMPDefaultmapClause(
23127 OpenMPDefaultmapClauseModifier M
, OpenMPDefaultmapClauseKind Kind
,
23128 SourceLocation StartLoc
, SourceLocation LParenLoc
, SourceLocation MLoc
,
23129 SourceLocation KindLoc
, SourceLocation EndLoc
) {
23130 if (getLangOpts().OpenMP
< 50) {
23131 if (M
!= OMPC_DEFAULTMAP_MODIFIER_tofrom
||
23132 Kind
!= OMPC_DEFAULTMAP_scalar
) {
23134 SourceLocation Loc
;
23136 if (M
!= OMPC_DEFAULTMAP_MODIFIER_tofrom
) {
23137 Value
+= getOpenMPSimpleClauseTypeName(OMPC_defaultmap
,
23138 OMPC_DEFAULTMAP_MODIFIER_tofrom
);
23141 Value
+= getOpenMPSimpleClauseTypeName(OMPC_defaultmap
,
23142 OMPC_DEFAULTMAP_scalar
);
23146 Diag(Loc
, diag::err_omp_unexpected_clause_value
)
23147 << Value
<< getOpenMPClauseName(OMPC_defaultmap
);
23151 bool isDefaultmapModifier
= (M
!= OMPC_DEFAULTMAP_MODIFIER_unknown
);
23152 bool isDefaultmapKind
= (Kind
!= OMPC_DEFAULTMAP_unknown
) ||
23153 (LangOpts
.OpenMP
>= 50 && KindLoc
.isInvalid());
23154 if (!isDefaultmapKind
|| !isDefaultmapModifier
) {
23155 StringRef KindValue
= "'scalar', 'aggregate', 'pointer'";
23156 if (LangOpts
.OpenMP
== 50) {
23157 StringRef ModifierValue
= "'alloc', 'from', 'to', 'tofrom', "
23158 "'firstprivate', 'none', 'default'";
23159 if (!isDefaultmapKind
&& isDefaultmapModifier
) {
23160 Diag(KindLoc
, diag::err_omp_unexpected_clause_value
)
23161 << KindValue
<< getOpenMPClauseName(OMPC_defaultmap
);
23162 } else if (isDefaultmapKind
&& !isDefaultmapModifier
) {
23163 Diag(MLoc
, diag::err_omp_unexpected_clause_value
)
23164 << ModifierValue
<< getOpenMPClauseName(OMPC_defaultmap
);
23166 Diag(MLoc
, diag::err_omp_unexpected_clause_value
)
23167 << ModifierValue
<< getOpenMPClauseName(OMPC_defaultmap
);
23168 Diag(KindLoc
, diag::err_omp_unexpected_clause_value
)
23169 << KindValue
<< getOpenMPClauseName(OMPC_defaultmap
);
23172 StringRef ModifierValue
=
23173 "'alloc', 'from', 'to', 'tofrom', "
23174 "'firstprivate', 'none', 'default', 'present'";
23175 if (!isDefaultmapKind
&& isDefaultmapModifier
) {
23176 Diag(KindLoc
, diag::err_omp_unexpected_clause_value
)
23177 << KindValue
<< getOpenMPClauseName(OMPC_defaultmap
);
23178 } else if (isDefaultmapKind
&& !isDefaultmapModifier
) {
23179 Diag(MLoc
, diag::err_omp_unexpected_clause_value
)
23180 << ModifierValue
<< getOpenMPClauseName(OMPC_defaultmap
);
23182 Diag(MLoc
, diag::err_omp_unexpected_clause_value
)
23183 << ModifierValue
<< getOpenMPClauseName(OMPC_defaultmap
);
23184 Diag(KindLoc
, diag::err_omp_unexpected_clause_value
)
23185 << KindValue
<< getOpenMPClauseName(OMPC_defaultmap
);
23191 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
23192 // At most one defaultmap clause for each category can appear on the
23194 if (DSAStack
->checkDefaultmapCategory(Kind
)) {
23195 Diag(StartLoc
, diag::err_omp_one_defaultmap_each_category
);
23199 if (Kind
== OMPC_DEFAULTMAP_unknown
) {
23200 // Variable category is not specified - mark all categories.
23201 DSAStack
->setDefaultDMAAttr(M
, OMPC_DEFAULTMAP_aggregate
, StartLoc
);
23202 DSAStack
->setDefaultDMAAttr(M
, OMPC_DEFAULTMAP_scalar
, StartLoc
);
23203 DSAStack
->setDefaultDMAAttr(M
, OMPC_DEFAULTMAP_pointer
, StartLoc
);
23205 DSAStack
->setDefaultDMAAttr(M
, Kind
, StartLoc
);
23208 return new (Context
)
23209 OMPDefaultmapClause(StartLoc
, LParenLoc
, MLoc
, KindLoc
, EndLoc
, Kind
, M
);
23212 bool Sema::ActOnStartOpenMPDeclareTargetContext(
23213 DeclareTargetContextInfo
&DTCI
) {
23214 DeclContext
*CurLexicalContext
= getCurLexicalContext();
23215 if (!CurLexicalContext
->isFileContext() &&
23216 !CurLexicalContext
->isExternCContext() &&
23217 !CurLexicalContext
->isExternCXXContext() &&
23218 !isa
<CXXRecordDecl
>(CurLexicalContext
) &&
23219 !isa
<ClassTemplateDecl
>(CurLexicalContext
) &&
23220 !isa
<ClassTemplatePartialSpecializationDecl
>(CurLexicalContext
) &&
23221 !isa
<ClassTemplateSpecializationDecl
>(CurLexicalContext
)) {
23222 Diag(DTCI
.Loc
, diag::err_omp_region_not_file_context
);
23226 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
23227 if (getLangOpts().HIP
)
23228 Diag(DTCI
.Loc
, diag::warn_hip_omp_target_directives
);
23230 DeclareTargetNesting
.push_back(DTCI
);
23234 const Sema::DeclareTargetContextInfo
23235 Sema::ActOnOpenMPEndDeclareTargetDirective() {
23236 assert(!DeclareTargetNesting
.empty() &&
23237 "check isInOpenMPDeclareTargetContext() first!");
23238 return DeclareTargetNesting
.pop_back_val();
23241 void Sema::ActOnFinishedOpenMPDeclareTargetContext(
23242 DeclareTargetContextInfo
&DTCI
) {
23243 for (auto &It
: DTCI
.ExplicitlyMapped
)
23244 ActOnOpenMPDeclareTargetName(It
.first
, It
.second
.Loc
, It
.second
.MT
, DTCI
);
23247 void Sema::DiagnoseUnterminatedOpenMPDeclareTarget() {
23248 if (DeclareTargetNesting
.empty())
23250 DeclareTargetContextInfo
&DTCI
= DeclareTargetNesting
.back();
23251 Diag(DTCI
.Loc
, diag::warn_omp_unterminated_declare_target
)
23252 << getOpenMPDirectiveName(DTCI
.Kind
);
23255 NamedDecl
*Sema::lookupOpenMPDeclareTargetName(Scope
*CurScope
,
23256 CXXScopeSpec
&ScopeSpec
,
23257 const DeclarationNameInfo
&Id
) {
23258 LookupResult
Lookup(*this, Id
, LookupOrdinaryName
);
23259 LookupParsedName(Lookup
, CurScope
, &ScopeSpec
, true);
23261 if (Lookup
.isAmbiguous())
23263 Lookup
.suppressDiagnostics();
23265 if (!Lookup
.isSingleResult()) {
23266 VarOrFuncDeclFilterCCC
CCC(*this);
23267 if (TypoCorrection Corrected
=
23268 CorrectTypo(Id
, LookupOrdinaryName
, CurScope
, nullptr, CCC
,
23269 CTK_ErrorRecovery
)) {
23270 diagnoseTypo(Corrected
, PDiag(diag::err_undeclared_var_use_suggest
)
23272 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected
.getCorrectionDecl());
23276 Diag(Id
.getLoc(), diag::err_undeclared_var_use
) << Id
.getName();
23280 NamedDecl
*ND
= Lookup
.getAsSingle
<NamedDecl
>();
23281 if (!isa
<VarDecl
>(ND
) && !isa
<FunctionDecl
>(ND
) &&
23282 !isa
<FunctionTemplateDecl
>(ND
)) {
23283 Diag(Id
.getLoc(), diag::err_omp_invalid_target_decl
) << Id
.getName();
23289 void Sema::ActOnOpenMPDeclareTargetName(NamedDecl
*ND
, SourceLocation Loc
,
23290 OMPDeclareTargetDeclAttr::MapTypeTy MT
,
23291 DeclareTargetContextInfo
&DTCI
) {
23292 assert((isa
<VarDecl
>(ND
) || isa
<FunctionDecl
>(ND
) ||
23293 isa
<FunctionTemplateDecl
>(ND
)) &&
23294 "Expected variable, function or function template.");
23296 // Diagnose marking after use as it may lead to incorrect diagnosis and
23298 if (LangOpts
.OpenMP
>= 50 &&
23299 (ND
->isUsed(/*CheckUsedAttr=*/false) || ND
->isReferenced()))
23300 Diag(Loc
, diag::warn_omp_declare_target_after_first_use
);
23302 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
23303 if (getLangOpts().HIP
)
23304 Diag(Loc
, diag::warn_hip_omp_target_directives
);
23306 // Explicit declare target lists have precedence.
23307 const unsigned Level
= -1;
23309 auto *VD
= cast
<ValueDecl
>(ND
);
23310 std::optional
<OMPDeclareTargetDeclAttr
*> ActiveAttr
=
23311 OMPDeclareTargetDeclAttr::getActiveAttr(VD
);
23312 if (ActiveAttr
&& (*ActiveAttr
)->getDevType() != DTCI
.DT
&&
23313 (*ActiveAttr
)->getLevel() == Level
) {
23314 Diag(Loc
, diag::err_omp_device_type_mismatch
)
23315 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI
.DT
)
23316 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
23317 (*ActiveAttr
)->getDevType());
23320 if (ActiveAttr
&& (*ActiveAttr
)->getMapType() != MT
&&
23321 (*ActiveAttr
)->getLevel() == Level
) {
23322 Diag(Loc
, diag::err_omp_declare_target_to_and_link
) << ND
;
23326 if (ActiveAttr
&& (*ActiveAttr
)->getLevel() == Level
)
23329 Expr
*IndirectE
= nullptr;
23330 bool IsIndirect
= false;
23331 if (DTCI
.Indirect
) {
23332 IndirectE
= *DTCI
.Indirect
;
23336 auto *A
= OMPDeclareTargetDeclAttr::CreateImplicit(
23337 Context
, MT
, DTCI
.DT
, IndirectE
, IsIndirect
, Level
,
23338 SourceRange(Loc
, Loc
));
23340 if (ASTMutationListener
*ML
= Context
.getASTMutationListener())
23341 ML
->DeclarationMarkedOpenMPDeclareTarget(ND
, A
);
23342 checkDeclIsAllowedInOpenMPTarget(nullptr, ND
, Loc
);
23343 if (auto *VD
= dyn_cast
<VarDecl
>(ND
);
23344 LangOpts
.OpenMP
&& VD
&& VD
->hasAttr
<OMPDeclareTargetDeclAttr
>() &&
23345 VD
->hasGlobalStorage())
23346 ActOnOpenMPDeclareTargetInitializer(ND
);
23349 static void checkDeclInTargetContext(SourceLocation SL
, SourceRange SR
,
23350 Sema
&SemaRef
, Decl
*D
) {
23351 if (!D
|| !isa
<VarDecl
>(D
))
23353 auto *VD
= cast
<VarDecl
>(D
);
23354 std::optional
<OMPDeclareTargetDeclAttr::MapTypeTy
> MapTy
=
23355 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD
);
23356 if (SemaRef
.LangOpts
.OpenMP
>= 50 &&
23357 (SemaRef
.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
23358 SemaRef
.getCurBlock() || SemaRef
.getCurCapturedRegion()) &&
23359 VD
->hasGlobalStorage()) {
23360 if (!MapTy
|| (*MapTy
!= OMPDeclareTargetDeclAttr::MT_To
&&
23361 *MapTy
!= OMPDeclareTargetDeclAttr::MT_Enter
)) {
23362 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
23363 // If a lambda declaration and definition appears between a
23364 // declare target directive and the matching end declare target
23365 // directive, all variables that are captured by the lambda
23366 // expression must also appear in a to clause.
23367 SemaRef
.Diag(VD
->getLocation(),
23368 diag::err_omp_lambda_capture_in_declare_target_not_to
);
23369 SemaRef
.Diag(SL
, diag::note_var_explicitly_captured_here
)
23376 SemaRef
.Diag(VD
->getLocation(), diag::warn_omp_not_in_target_context
);
23377 SemaRef
.Diag(SL
, diag::note_used_here
) << SR
;
23380 static bool checkValueDeclInTarget(SourceLocation SL
, SourceRange SR
,
23381 Sema
&SemaRef
, DSAStackTy
*Stack
,
23383 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD
) ||
23384 checkTypeMappable(SL
, SR
, SemaRef
, Stack
, VD
->getType(),
23385 /*FullCheck=*/false);
23388 void Sema::checkDeclIsAllowedInOpenMPTarget(Expr
*E
, Decl
*D
,
23389 SourceLocation IdLoc
) {
23390 if (!D
|| D
->isInvalidDecl())
23392 SourceRange SR
= E
? E
->getSourceRange() : D
->getSourceRange();
23393 SourceLocation SL
= E
? E
->getBeginLoc() : D
->getLocation();
23394 if (auto *VD
= dyn_cast
<VarDecl
>(D
)) {
23395 // Only global variables can be marked as declare target.
23396 if (!VD
->isFileVarDecl() && !VD
->isStaticLocal() &&
23397 !VD
->isStaticDataMember())
23399 // 2.10.6: threadprivate variable cannot appear in a declare target
23401 if (DSAStack
->isThreadPrivate(VD
)) {
23402 Diag(SL
, diag::err_omp_threadprivate_in_target
);
23403 reportOriginalDsa(*this, DSAStack
, VD
, DSAStack
->getTopDSA(VD
, false));
23407 if (const auto *FTD
= dyn_cast
<FunctionTemplateDecl
>(D
))
23408 D
= FTD
->getTemplatedDecl();
23409 if (auto *FD
= dyn_cast
<FunctionDecl
>(D
)) {
23410 std::optional
<OMPDeclareTargetDeclAttr::MapTypeTy
> Res
=
23411 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD
);
23412 if (IdLoc
.isValid() && Res
&& *Res
== OMPDeclareTargetDeclAttr::MT_Link
) {
23413 Diag(IdLoc
, diag::err_omp_function_in_link_clause
);
23414 Diag(FD
->getLocation(), diag::note_defined_here
) << FD
;
23418 if (auto *VD
= dyn_cast
<ValueDecl
>(D
)) {
23419 // Problem if any with var declared with incomplete type will be reported
23420 // as normal, so no need to check it here.
23421 if ((E
|| !VD
->getType()->isIncompleteType()) &&
23422 !checkValueDeclInTarget(SL
, SR
, *this, DSAStack
, VD
))
23424 if (!E
&& isInOpenMPDeclareTargetContext()) {
23425 // Checking declaration inside declare target region.
23426 if (isa
<VarDecl
>(D
) || isa
<FunctionDecl
>(D
) ||
23427 isa
<FunctionTemplateDecl
>(D
)) {
23428 std::optional
<OMPDeclareTargetDeclAttr
*> ActiveAttr
=
23429 OMPDeclareTargetDeclAttr::getActiveAttr(VD
);
23430 unsigned Level
= DeclareTargetNesting
.size();
23431 if (ActiveAttr
&& (*ActiveAttr
)->getLevel() >= Level
)
23433 DeclareTargetContextInfo
&DTCI
= DeclareTargetNesting
.back();
23434 Expr
*IndirectE
= nullptr;
23435 bool IsIndirect
= false;
23436 if (DTCI
.Indirect
) {
23437 IndirectE
= *DTCI
.Indirect
;
23441 auto *A
= OMPDeclareTargetDeclAttr::CreateImplicit(
23443 getLangOpts().OpenMP
>= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
23444 : OMPDeclareTargetDeclAttr::MT_To
,
23445 DTCI
.DT
, IndirectE
, IsIndirect
, Level
,
23446 SourceRange(DTCI
.Loc
, DTCI
.Loc
));
23448 if (ASTMutationListener
*ML
= Context
.getASTMutationListener())
23449 ML
->DeclarationMarkedOpenMPDeclareTarget(D
, A
);
23456 checkDeclInTargetContext(E
->getExprLoc(), E
->getSourceRange(), *this, D
);
23459 /// This class visits every VarDecl that the initializer references and adds
23460 /// OMPDeclareTargetDeclAttr to each of them.
23461 class GlobalDeclRefChecker final
23462 : public StmtVisitor
<GlobalDeclRefChecker
> {
23463 SmallVector
<VarDecl
*> DeclVector
;
23467 /// A StmtVisitor class function that visits all DeclRefExpr and adds
23468 /// OMPDeclareTargetDeclAttr to them.
23469 void VisitDeclRefExpr(DeclRefExpr
*Node
) {
23470 if (auto *VD
= dyn_cast
<VarDecl
>(Node
->getDecl())) {
23472 DeclVector
.push_back(VD
);
23475 /// A function that iterates across each of the Expr's children.
23476 void VisitExpr(Expr
*Ex
) {
23477 for (auto *Child
: Ex
->children()) {
23481 /// A function that keeps a record of all the Decls that are variables, has
23482 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
23483 /// each Decl one at a time and use the inherited 'visit' functions to look
23484 /// for DeclRefExpr.
23485 void declareTargetInitializer(Decl
*TD
) {
23486 A
= TD
->getAttr
<OMPDeclareTargetDeclAttr
>();
23487 DeclVector
.push_back(cast
<VarDecl
>(TD
));
23488 while (!DeclVector
.empty()) {
23489 VarDecl
*TargetVarDecl
= DeclVector
.pop_back_val();
23490 if (TargetVarDecl
->hasAttr
<OMPDeclareTargetDeclAttr
>() &&
23491 TargetVarDecl
->hasInit() && TargetVarDecl
->hasGlobalStorage()) {
23492 if (Expr
*Ex
= TargetVarDecl
->getInit())
23499 /// Adding OMPDeclareTargetDeclAttr to variables with static storage
23500 /// duration that are referenced in the initializer expression list of
23501 /// variables with static storage duration in declare target directive.
23502 void Sema::ActOnOpenMPDeclareTargetInitializer(Decl
*TargetDecl
) {
23503 GlobalDeclRefChecker Checker
;
23504 if (isa
<VarDecl
>(TargetDecl
))
23505 Checker
.declareTargetInitializer(TargetDecl
);
23508 OMPClause
*Sema::ActOnOpenMPToClause(
23509 ArrayRef
<OpenMPMotionModifierKind
> MotionModifiers
,
23510 ArrayRef
<SourceLocation
> MotionModifiersLoc
,
23511 CXXScopeSpec
&MapperIdScopeSpec
, DeclarationNameInfo
&MapperId
,
23512 SourceLocation ColonLoc
, ArrayRef
<Expr
*> VarList
,
23513 const OMPVarListLocTy
&Locs
, ArrayRef
<Expr
*> UnresolvedMappers
) {
23514 OpenMPMotionModifierKind Modifiers
[] = {OMPC_MOTION_MODIFIER_unknown
,
23515 OMPC_MOTION_MODIFIER_unknown
};
23516 SourceLocation ModifiersLoc
[NumberOfOMPMotionModifiers
];
23518 // Process motion-modifiers, flag errors for duplicate modifiers.
23519 unsigned Count
= 0;
23520 for (unsigned I
= 0, E
= MotionModifiers
.size(); I
< E
; ++I
) {
23521 if (MotionModifiers
[I
] != OMPC_MOTION_MODIFIER_unknown
&&
23522 llvm::is_contained(Modifiers
, MotionModifiers
[I
])) {
23523 Diag(MotionModifiersLoc
[I
], diag::err_omp_duplicate_motion_modifier
);
23526 assert(Count
< NumberOfOMPMotionModifiers
&&
23527 "Modifiers exceed the allowed number of motion modifiers");
23528 Modifiers
[Count
] = MotionModifiers
[I
];
23529 ModifiersLoc
[Count
] = MotionModifiersLoc
[I
];
23533 MappableVarListInfo
MVLI(VarList
);
23534 checkMappableExpressionList(*this, DSAStack
, OMPC_to
, MVLI
, Locs
.StartLoc
,
23535 MapperIdScopeSpec
, MapperId
, UnresolvedMappers
);
23536 if (MVLI
.ProcessedVarList
.empty())
23539 return OMPToClause::Create(
23540 Context
, Locs
, MVLI
.ProcessedVarList
, MVLI
.VarBaseDeclarations
,
23541 MVLI
.VarComponents
, MVLI
.UDMapperList
, Modifiers
, ModifiersLoc
,
23542 MapperIdScopeSpec
.getWithLocInContext(Context
), MapperId
);
23545 OMPClause
*Sema::ActOnOpenMPFromClause(
23546 ArrayRef
<OpenMPMotionModifierKind
> MotionModifiers
,
23547 ArrayRef
<SourceLocation
> MotionModifiersLoc
,
23548 CXXScopeSpec
&MapperIdScopeSpec
, DeclarationNameInfo
&MapperId
,
23549 SourceLocation ColonLoc
, ArrayRef
<Expr
*> VarList
,
23550 const OMPVarListLocTy
&Locs
, ArrayRef
<Expr
*> UnresolvedMappers
) {
23551 OpenMPMotionModifierKind Modifiers
[] = {OMPC_MOTION_MODIFIER_unknown
,
23552 OMPC_MOTION_MODIFIER_unknown
};
23553 SourceLocation ModifiersLoc
[NumberOfOMPMotionModifiers
];
23555 // Process motion-modifiers, flag errors for duplicate modifiers.
23556 unsigned Count
= 0;
23557 for (unsigned I
= 0, E
= MotionModifiers
.size(); I
< E
; ++I
) {
23558 if (MotionModifiers
[I
] != OMPC_MOTION_MODIFIER_unknown
&&
23559 llvm::is_contained(Modifiers
, MotionModifiers
[I
])) {
23560 Diag(MotionModifiersLoc
[I
], diag::err_omp_duplicate_motion_modifier
);
23563 assert(Count
< NumberOfOMPMotionModifiers
&&
23564 "Modifiers exceed the allowed number of motion modifiers");
23565 Modifiers
[Count
] = MotionModifiers
[I
];
23566 ModifiersLoc
[Count
] = MotionModifiersLoc
[I
];
23570 MappableVarListInfo
MVLI(VarList
);
23571 checkMappableExpressionList(*this, DSAStack
, OMPC_from
, MVLI
, Locs
.StartLoc
,
23572 MapperIdScopeSpec
, MapperId
, UnresolvedMappers
);
23573 if (MVLI
.ProcessedVarList
.empty())
23576 return OMPFromClause::Create(
23577 Context
, Locs
, MVLI
.ProcessedVarList
, MVLI
.VarBaseDeclarations
,
23578 MVLI
.VarComponents
, MVLI
.UDMapperList
, Modifiers
, ModifiersLoc
,
23579 MapperIdScopeSpec
.getWithLocInContext(Context
), MapperId
);
23582 OMPClause
*Sema::ActOnOpenMPUseDevicePtrClause(ArrayRef
<Expr
*> VarList
,
23583 const OMPVarListLocTy
&Locs
) {
23584 MappableVarListInfo
MVLI(VarList
);
23585 SmallVector
<Expr
*, 8> PrivateCopies
;
23586 SmallVector
<Expr
*, 8> Inits
;
23588 for (Expr
*RefExpr
: VarList
) {
23589 assert(RefExpr
&& "NULL expr in OpenMP use_device_ptr clause.");
23590 SourceLocation ELoc
;
23591 SourceRange ERange
;
23592 Expr
*SimpleRefExpr
= RefExpr
;
23593 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
23595 // It will be analyzed later.
23596 MVLI
.ProcessedVarList
.push_back(RefExpr
);
23597 PrivateCopies
.push_back(nullptr);
23598 Inits
.push_back(nullptr);
23600 ValueDecl
*D
= Res
.first
;
23604 QualType Type
= D
->getType();
23605 Type
= Type
.getNonReferenceType().getUnqualifiedType();
23607 auto *VD
= dyn_cast
<VarDecl
>(D
);
23609 // Item should be a pointer or reference to pointer.
23610 if (!Type
->isPointerType()) {
23611 Diag(ELoc
, diag::err_omp_usedeviceptr_not_a_pointer
)
23612 << 0 << RefExpr
->getSourceRange();
23616 // Build the private variable and the expression that refers to it.
23618 buildVarDecl(*this, ELoc
, Type
, D
->getName(),
23619 D
->hasAttrs() ? &D
->getAttrs() : nullptr,
23620 VD
? cast
<DeclRefExpr
>(SimpleRefExpr
) : nullptr);
23621 if (VDPrivate
->isInvalidDecl())
23624 CurContext
->addDecl(VDPrivate
);
23625 DeclRefExpr
*VDPrivateRefExpr
= buildDeclRefExpr(
23626 *this, VDPrivate
, RefExpr
->getType().getUnqualifiedType(), ELoc
);
23628 // Add temporary variable to initialize the private copy of the pointer.
23630 buildVarDecl(*this, RefExpr
->getExprLoc(), Type
, ".devptr.temp");
23631 DeclRefExpr
*VDInitRefExpr
= buildDeclRefExpr(
23632 *this, VDInit
, RefExpr
->getType(), RefExpr
->getExprLoc());
23633 AddInitializerToDecl(VDPrivate
,
23634 DefaultLvalueConversion(VDInitRefExpr
).get(),
23635 /*DirectInit=*/false);
23637 // If required, build a capture to implement the privatization initialized
23638 // with the current list item value.
23639 DeclRefExpr
*Ref
= nullptr;
23641 Ref
= buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/true);
23642 MVLI
.ProcessedVarList
.push_back(VD
? RefExpr
->IgnoreParens() : Ref
);
23643 PrivateCopies
.push_back(VDPrivateRefExpr
);
23644 Inits
.push_back(VDInitRefExpr
);
23646 // We need to add a data sharing attribute for this variable to make sure it
23647 // is correctly captured. A variable that shows up in a use_device_ptr has
23648 // similar properties of a first private variable.
23649 DSAStack
->addDSA(D
, RefExpr
->IgnoreParens(), OMPC_firstprivate
, Ref
);
23651 // Create a mappable component for the list item. List items in this clause
23652 // only need a component.
23653 MVLI
.VarBaseDeclarations
.push_back(D
);
23654 MVLI
.VarComponents
.resize(MVLI
.VarComponents
.size() + 1);
23655 MVLI
.VarComponents
.back().emplace_back(SimpleRefExpr
, D
,
23656 /*IsNonContiguous=*/false);
23659 if (MVLI
.ProcessedVarList
.empty())
23662 return OMPUseDevicePtrClause::Create(
23663 Context
, Locs
, MVLI
.ProcessedVarList
, PrivateCopies
, Inits
,
23664 MVLI
.VarBaseDeclarations
, MVLI
.VarComponents
);
23667 OMPClause
*Sema::ActOnOpenMPUseDeviceAddrClause(ArrayRef
<Expr
*> VarList
,
23668 const OMPVarListLocTy
&Locs
) {
23669 MappableVarListInfo
MVLI(VarList
);
23671 for (Expr
*RefExpr
: VarList
) {
23672 assert(RefExpr
&& "NULL expr in OpenMP use_device_addr clause.");
23673 SourceLocation ELoc
;
23674 SourceRange ERange
;
23675 Expr
*SimpleRefExpr
= RefExpr
;
23676 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
,
23677 /*AllowArraySection=*/true);
23679 // It will be analyzed later.
23680 MVLI
.ProcessedVarList
.push_back(RefExpr
);
23682 ValueDecl
*D
= Res
.first
;
23685 auto *VD
= dyn_cast
<VarDecl
>(D
);
23687 // If required, build a capture to implement the privatization initialized
23688 // with the current list item value.
23689 DeclRefExpr
*Ref
= nullptr;
23691 Ref
= buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/true);
23692 MVLI
.ProcessedVarList
.push_back(VD
? RefExpr
->IgnoreParens() : Ref
);
23694 // We need to add a data sharing attribute for this variable to make sure it
23695 // is correctly captured. A variable that shows up in a use_device_addr has
23696 // similar properties of a first private variable.
23697 DSAStack
->addDSA(D
, RefExpr
->IgnoreParens(), OMPC_firstprivate
, Ref
);
23699 // Create a mappable component for the list item. List items in this clause
23700 // only need a component.
23701 MVLI
.VarBaseDeclarations
.push_back(D
);
23702 MVLI
.VarComponents
.emplace_back();
23703 Expr
*Component
= SimpleRefExpr
;
23704 if (VD
&& (isa
<OMPArraySectionExpr
>(RefExpr
->IgnoreParenImpCasts()) ||
23705 isa
<ArraySubscriptExpr
>(RefExpr
->IgnoreParenImpCasts())))
23706 Component
= DefaultFunctionArrayLvalueConversion(SimpleRefExpr
).get();
23707 MVLI
.VarComponents
.back().emplace_back(Component
, D
,
23708 /*IsNonContiguous=*/false);
23711 if (MVLI
.ProcessedVarList
.empty())
23714 return OMPUseDeviceAddrClause::Create(Context
, Locs
, MVLI
.ProcessedVarList
,
23715 MVLI
.VarBaseDeclarations
,
23716 MVLI
.VarComponents
);
23719 OMPClause
*Sema::ActOnOpenMPIsDevicePtrClause(ArrayRef
<Expr
*> VarList
,
23720 const OMPVarListLocTy
&Locs
) {
23721 MappableVarListInfo
MVLI(VarList
);
23722 for (Expr
*RefExpr
: VarList
) {
23723 assert(RefExpr
&& "NULL expr in OpenMP is_device_ptr clause.");
23724 SourceLocation ELoc
;
23725 SourceRange ERange
;
23726 Expr
*SimpleRefExpr
= RefExpr
;
23727 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
23729 // It will be analyzed later.
23730 MVLI
.ProcessedVarList
.push_back(RefExpr
);
23732 ValueDecl
*D
= Res
.first
;
23736 QualType Type
= D
->getType();
23737 // item should be a pointer or array or reference to pointer or array
23738 if (!Type
.getNonReferenceType()->isPointerType() &&
23739 !Type
.getNonReferenceType()->isArrayType()) {
23740 Diag(ELoc
, diag::err_omp_argument_type_isdeviceptr
)
23741 << 0 << RefExpr
->getSourceRange();
23745 // Check if the declaration in the clause does not show up in any data
23746 // sharing attribute.
23747 DSAStackTy::DSAVarData DVar
= DSAStack
->getTopDSA(D
, /*FromParent=*/false);
23748 if (isOpenMPPrivate(DVar
.CKind
)) {
23749 Diag(ELoc
, diag::err_omp_variable_in_given_clause_and_dsa
)
23750 << getOpenMPClauseName(DVar
.CKind
)
23751 << getOpenMPClauseName(OMPC_is_device_ptr
)
23752 << getOpenMPDirectiveName(DSAStack
->getCurrentDirective());
23753 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
23757 const Expr
*ConflictExpr
;
23758 if (DSAStack
->checkMappableExprComponentListsForDecl(
23759 D
, /*CurrentRegionOnly=*/true,
23761 OMPClauseMappableExprCommon::MappableExprComponentListRef R
,
23762 OpenMPClauseKind
) -> bool {
23763 ConflictExpr
= R
.front().getAssociatedExpression();
23766 Diag(ELoc
, diag::err_omp_map_shared_storage
) << RefExpr
->getSourceRange();
23767 Diag(ConflictExpr
->getExprLoc(), diag::note_used_here
)
23768 << ConflictExpr
->getSourceRange();
23772 // Store the components in the stack so that they can be used to check
23773 // against other clauses later on.
23774 OMPClauseMappableExprCommon::MappableComponent
MC(
23775 SimpleRefExpr
, D
, /*IsNonContiguous=*/false);
23776 DSAStack
->addMappableExpressionComponents(
23777 D
, MC
, /*WhereFoundClauseKind=*/OMPC_is_device_ptr
);
23779 // Record the expression we've just processed.
23780 MVLI
.ProcessedVarList
.push_back(SimpleRefExpr
);
23782 // Create a mappable component for the list item. List items in this clause
23783 // only need a component. We use a null declaration to signal fields in
23785 assert((isa
<DeclRefExpr
>(SimpleRefExpr
) ||
23786 isa
<CXXThisExpr
>(cast
<MemberExpr
>(SimpleRefExpr
)->getBase())) &&
23787 "Unexpected device pointer expression!");
23788 MVLI
.VarBaseDeclarations
.push_back(
23789 isa
<DeclRefExpr
>(SimpleRefExpr
) ? D
: nullptr);
23790 MVLI
.VarComponents
.resize(MVLI
.VarComponents
.size() + 1);
23791 MVLI
.VarComponents
.back().push_back(MC
);
23794 if (MVLI
.ProcessedVarList
.empty())
23797 return OMPIsDevicePtrClause::Create(Context
, Locs
, MVLI
.ProcessedVarList
,
23798 MVLI
.VarBaseDeclarations
,
23799 MVLI
.VarComponents
);
23802 OMPClause
*Sema::ActOnOpenMPHasDeviceAddrClause(ArrayRef
<Expr
*> VarList
,
23803 const OMPVarListLocTy
&Locs
) {
23804 MappableVarListInfo
MVLI(VarList
);
23805 for (Expr
*RefExpr
: VarList
) {
23806 assert(RefExpr
&& "NULL expr in OpenMP has_device_addr clause.");
23807 SourceLocation ELoc
;
23808 SourceRange ERange
;
23809 Expr
*SimpleRefExpr
= RefExpr
;
23810 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
,
23811 /*AllowArraySection=*/true);
23813 // It will be analyzed later.
23814 MVLI
.ProcessedVarList
.push_back(RefExpr
);
23816 ValueDecl
*D
= Res
.first
;
23820 // Check if the declaration in the clause does not show up in any data
23821 // sharing attribute.
23822 DSAStackTy::DSAVarData DVar
= DSAStack
->getTopDSA(D
, /*FromParent=*/false);
23823 if (isOpenMPPrivate(DVar
.CKind
)) {
23824 Diag(ELoc
, diag::err_omp_variable_in_given_clause_and_dsa
)
23825 << getOpenMPClauseName(DVar
.CKind
)
23826 << getOpenMPClauseName(OMPC_has_device_addr
)
23827 << getOpenMPDirectiveName(DSAStack
->getCurrentDirective());
23828 reportOriginalDsa(*this, DSAStack
, D
, DVar
);
23832 const Expr
*ConflictExpr
;
23833 if (DSAStack
->checkMappableExprComponentListsForDecl(
23834 D
, /*CurrentRegionOnly=*/true,
23836 OMPClauseMappableExprCommon::MappableExprComponentListRef R
,
23837 OpenMPClauseKind
) -> bool {
23838 ConflictExpr
= R
.front().getAssociatedExpression();
23841 Diag(ELoc
, diag::err_omp_map_shared_storage
) << RefExpr
->getSourceRange();
23842 Diag(ConflictExpr
->getExprLoc(), diag::note_used_here
)
23843 << ConflictExpr
->getSourceRange();
23847 // Store the components in the stack so that they can be used to check
23848 // against other clauses later on.
23849 Expr
*Component
= SimpleRefExpr
;
23850 auto *VD
= dyn_cast
<VarDecl
>(D
);
23851 if (VD
&& (isa
<OMPArraySectionExpr
>(RefExpr
->IgnoreParenImpCasts()) ||
23852 isa
<ArraySubscriptExpr
>(RefExpr
->IgnoreParenImpCasts())))
23853 Component
= DefaultFunctionArrayLvalueConversion(SimpleRefExpr
).get();
23854 OMPClauseMappableExprCommon::MappableComponent
MC(
23855 Component
, D
, /*IsNonContiguous=*/false);
23856 DSAStack
->addMappableExpressionComponents(
23857 D
, MC
, /*WhereFoundClauseKind=*/OMPC_has_device_addr
);
23859 // Record the expression we've just processed.
23860 if (!VD
&& !CurContext
->isDependentContext()) {
23862 buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/true);
23863 assert(Ref
&& "has_device_addr capture failed");
23864 MVLI
.ProcessedVarList
.push_back(Ref
);
23866 MVLI
.ProcessedVarList
.push_back(RefExpr
->IgnoreParens());
23868 // Create a mappable component for the list item. List items in this clause
23869 // only need a component. We use a null declaration to signal fields in
23871 assert((isa
<DeclRefExpr
>(SimpleRefExpr
) ||
23872 isa
<CXXThisExpr
>(cast
<MemberExpr
>(SimpleRefExpr
)->getBase())) &&
23873 "Unexpected device pointer expression!");
23874 MVLI
.VarBaseDeclarations
.push_back(
23875 isa
<DeclRefExpr
>(SimpleRefExpr
) ? D
: nullptr);
23876 MVLI
.VarComponents
.resize(MVLI
.VarComponents
.size() + 1);
23877 MVLI
.VarComponents
.back().push_back(MC
);
23880 if (MVLI
.ProcessedVarList
.empty())
23883 return OMPHasDeviceAddrClause::Create(Context
, Locs
, MVLI
.ProcessedVarList
,
23884 MVLI
.VarBaseDeclarations
,
23885 MVLI
.VarComponents
);
23888 OMPClause
*Sema::ActOnOpenMPAllocateClause(
23889 Expr
*Allocator
, ArrayRef
<Expr
*> VarList
, SourceLocation StartLoc
,
23890 SourceLocation ColonLoc
, SourceLocation LParenLoc
, SourceLocation EndLoc
) {
23892 // OpenMP [2.11.4 allocate Clause, Description]
23893 // allocator is an expression of omp_allocator_handle_t type.
23894 if (!findOMPAllocatorHandleT(*this, Allocator
->getExprLoc(), DSAStack
))
23897 ExprResult AllocatorRes
= DefaultLvalueConversion(Allocator
);
23898 if (AllocatorRes
.isInvalid())
23900 AllocatorRes
= PerformImplicitConversion(AllocatorRes
.get(),
23901 DSAStack
->getOMPAllocatorHandleT(),
23902 Sema::AA_Initializing
,
23903 /*AllowExplicit=*/true);
23904 if (AllocatorRes
.isInvalid())
23906 Allocator
= AllocatorRes
.get();
23908 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
23909 // allocate clauses that appear on a target construct or on constructs in a
23910 // target region must specify an allocator expression unless a requires
23911 // directive with the dynamic_allocators clause is present in the same
23912 // compilation unit.
23913 if (LangOpts
.OpenMPIsTargetDevice
&&
23914 !DSAStack
->hasRequiresDeclWithClause
<OMPDynamicAllocatorsClause
>())
23915 targetDiag(StartLoc
, diag::err_expected_allocator_expression
);
23917 // Analyze and build list of variables.
23918 SmallVector
<Expr
*, 8> Vars
;
23919 for (Expr
*RefExpr
: VarList
) {
23920 assert(RefExpr
&& "NULL expr in OpenMP private clause.");
23921 SourceLocation ELoc
;
23922 SourceRange ERange
;
23923 Expr
*SimpleRefExpr
= RefExpr
;
23924 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
23926 // It will be analyzed later.
23927 Vars
.push_back(RefExpr
);
23929 ValueDecl
*D
= Res
.first
;
23933 auto *VD
= dyn_cast
<VarDecl
>(D
);
23934 DeclRefExpr
*Ref
= nullptr;
23935 if (!VD
&& !CurContext
->isDependentContext())
23936 Ref
= buildCapture(*this, D
, SimpleRefExpr
, /*WithInit=*/false);
23937 Vars
.push_back((VD
|| CurContext
->isDependentContext())
23938 ? RefExpr
->IgnoreParens()
23946 DSAStack
->addInnerAllocatorExpr(Allocator
);
23947 return OMPAllocateClause::Create(Context
, StartLoc
, LParenLoc
, Allocator
,
23948 ColonLoc
, EndLoc
, Vars
);
23951 OMPClause
*Sema::ActOnOpenMPNontemporalClause(ArrayRef
<Expr
*> VarList
,
23952 SourceLocation StartLoc
,
23953 SourceLocation LParenLoc
,
23954 SourceLocation EndLoc
) {
23955 SmallVector
<Expr
*, 8> Vars
;
23956 for (Expr
*RefExpr
: VarList
) {
23957 assert(RefExpr
&& "NULL expr in OpenMP nontemporal clause.");
23958 SourceLocation ELoc
;
23959 SourceRange ERange
;
23960 Expr
*SimpleRefExpr
= RefExpr
;
23961 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
);
23963 // It will be analyzed later.
23964 Vars
.push_back(RefExpr
);
23965 ValueDecl
*D
= Res
.first
;
23969 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
23970 // A list-item cannot appear in more than one nontemporal clause.
23971 if (const Expr
*PrevRef
=
23972 DSAStack
->addUniqueNontemporal(D
, SimpleRefExpr
)) {
23973 Diag(ELoc
, diag::err_omp_used_in_clause_twice
)
23974 << 0 << getOpenMPClauseName(OMPC_nontemporal
) << ERange
;
23975 Diag(PrevRef
->getExprLoc(), diag::note_omp_explicit_dsa
)
23976 << getOpenMPClauseName(OMPC_nontemporal
);
23980 Vars
.push_back(RefExpr
);
23986 return OMPNontemporalClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
,
23990 StmtResult
Sema::ActOnOpenMPScopeDirective(ArrayRef
<OMPClause
*> Clauses
,
23991 Stmt
*AStmt
, SourceLocation StartLoc
,
23992 SourceLocation EndLoc
) {
23994 return StmtError();
23996 setFunctionHasBranchProtectedScope();
23998 return OMPScopeDirective::Create(Context
, StartLoc
, EndLoc
, Clauses
, AStmt
);
24001 OMPClause
*Sema::ActOnOpenMPInclusiveClause(ArrayRef
<Expr
*> VarList
,
24002 SourceLocation StartLoc
,
24003 SourceLocation LParenLoc
,
24004 SourceLocation EndLoc
) {
24005 SmallVector
<Expr
*, 8> Vars
;
24006 for (Expr
*RefExpr
: VarList
) {
24007 assert(RefExpr
&& "NULL expr in OpenMP nontemporal clause.");
24008 SourceLocation ELoc
;
24009 SourceRange ERange
;
24010 Expr
*SimpleRefExpr
= RefExpr
;
24011 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
,
24012 /*AllowArraySection=*/true);
24014 // It will be analyzed later.
24015 Vars
.push_back(RefExpr
);
24016 ValueDecl
*D
= Res
.first
;
24020 const DSAStackTy::DSAVarData DVar
=
24021 DSAStack
->getTopDSA(D
, /*FromParent=*/true);
24022 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
24023 // A list item that appears in the inclusive or exclusive clause must appear
24024 // in a reduction clause with the inscan modifier on the enclosing
24025 // worksharing-loop, worksharing-loop SIMD, or simd construct.
24026 if (DVar
.CKind
!= OMPC_reduction
|| DVar
.Modifier
!= OMPC_REDUCTION_inscan
)
24027 Diag(ELoc
, diag::err_omp_inclusive_exclusive_not_reduction
)
24028 << RefExpr
->getSourceRange();
24030 if (DSAStack
->getParentDirective() != OMPD_unknown
)
24031 DSAStack
->markDeclAsUsedInScanDirective(D
);
24032 Vars
.push_back(RefExpr
);
24038 return OMPInclusiveClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
, Vars
);
24041 OMPClause
*Sema::ActOnOpenMPExclusiveClause(ArrayRef
<Expr
*> VarList
,
24042 SourceLocation StartLoc
,
24043 SourceLocation LParenLoc
,
24044 SourceLocation EndLoc
) {
24045 SmallVector
<Expr
*, 8> Vars
;
24046 for (Expr
*RefExpr
: VarList
) {
24047 assert(RefExpr
&& "NULL expr in OpenMP nontemporal clause.");
24048 SourceLocation ELoc
;
24049 SourceRange ERange
;
24050 Expr
*SimpleRefExpr
= RefExpr
;
24051 auto Res
= getPrivateItem(*this, SimpleRefExpr
, ELoc
, ERange
,
24052 /*AllowArraySection=*/true);
24054 // It will be analyzed later.
24055 Vars
.push_back(RefExpr
);
24056 ValueDecl
*D
= Res
.first
;
24060 OpenMPDirectiveKind ParentDirective
= DSAStack
->getParentDirective();
24061 DSAStackTy::DSAVarData DVar
;
24062 if (ParentDirective
!= OMPD_unknown
)
24063 DVar
= DSAStack
->getTopDSA(D
, /*FromParent=*/true);
24064 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
24065 // A list item that appears in the inclusive or exclusive clause must appear
24066 // in a reduction clause with the inscan modifier on the enclosing
24067 // worksharing-loop, worksharing-loop SIMD, or simd construct.
24068 if (ParentDirective
== OMPD_unknown
|| DVar
.CKind
!= OMPC_reduction
||
24069 DVar
.Modifier
!= OMPC_REDUCTION_inscan
) {
24070 Diag(ELoc
, diag::err_omp_inclusive_exclusive_not_reduction
)
24071 << RefExpr
->getSourceRange();
24073 DSAStack
->markDeclAsUsedInScanDirective(D
);
24075 Vars
.push_back(RefExpr
);
24081 return OMPExclusiveClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
, Vars
);
24084 /// Tries to find omp_alloctrait_t type.
24085 static bool findOMPAlloctraitT(Sema
&S
, SourceLocation Loc
, DSAStackTy
*Stack
) {
24086 QualType OMPAlloctraitT
= Stack
->getOMPAlloctraitT();
24087 if (!OMPAlloctraitT
.isNull())
24089 IdentifierInfo
&II
= S
.PP
.getIdentifierTable().get("omp_alloctrait_t");
24090 ParsedType PT
= S
.getTypeName(II
, Loc
, S
.getCurScope());
24091 if (!PT
.getAsOpaquePtr() || PT
.get().isNull()) {
24092 S
.Diag(Loc
, diag::err_omp_implied_type_not_found
) << "omp_alloctrait_t";
24095 Stack
->setOMPAlloctraitT(PT
.get());
24099 OMPClause
*Sema::ActOnOpenMPUsesAllocatorClause(
24100 SourceLocation StartLoc
, SourceLocation LParenLoc
, SourceLocation EndLoc
,
24101 ArrayRef
<UsesAllocatorsData
> Data
) {
24102 // OpenMP [2.12.5, target Construct]
24103 // allocator is an identifier of omp_allocator_handle_t type.
24104 if (!findOMPAllocatorHandleT(*this, StartLoc
, DSAStack
))
24106 // OpenMP [2.12.5, target Construct]
24107 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
24110 [](const UsesAllocatorsData
&D
) { return D
.AllocatorTraits
; }) &&
24111 !findOMPAlloctraitT(*this, StartLoc
, DSAStack
))
24113 llvm::SmallPtrSet
<CanonicalDeclPtr
<Decl
>, 4> PredefinedAllocators
;
24114 for (int I
= 0; I
< OMPAllocateDeclAttr::OMPUserDefinedMemAlloc
; ++I
) {
24115 auto AllocatorKind
= static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I
);
24116 StringRef Allocator
=
24117 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind
);
24118 DeclarationName AllocatorName
= &Context
.Idents
.get(Allocator
);
24119 PredefinedAllocators
.insert(LookupSingleName(
24120 TUScope
, AllocatorName
, StartLoc
, Sema::LookupAnyName
));
24123 SmallVector
<OMPUsesAllocatorsClause::Data
, 4> NewData
;
24124 for (const UsesAllocatorsData
&D
: Data
) {
24125 Expr
*AllocatorExpr
= nullptr;
24126 // Check allocator expression.
24127 if (D
.Allocator
->isTypeDependent()) {
24128 AllocatorExpr
= D
.Allocator
;
24130 // Traits were specified - need to assign new allocator to the specified
24131 // allocator, so it must be an lvalue.
24132 AllocatorExpr
= D
.Allocator
->IgnoreParenImpCasts();
24133 auto *DRE
= dyn_cast
<DeclRefExpr
>(AllocatorExpr
);
24134 bool IsPredefinedAllocator
= false;
24136 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy
=
24137 getAllocatorKind(*this, DSAStack
, AllocatorExpr
);
24138 IsPredefinedAllocator
=
24140 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc
;
24142 QualType OMPAllocatorHandleT
= DSAStack
->getOMPAllocatorHandleT();
24143 QualType AllocatorExprType
= AllocatorExpr
->getType();
24144 bool IsTypeCompatible
= IsPredefinedAllocator
;
24145 IsTypeCompatible
= IsTypeCompatible
||
24146 Context
.hasSameUnqualifiedType(AllocatorExprType
,
24147 OMPAllocatorHandleT
);
24149 IsTypeCompatible
||
24150 Context
.typesAreCompatible(AllocatorExprType
, OMPAllocatorHandleT
);
24151 bool IsNonConstantLValue
=
24152 !AllocatorExprType
.isConstant(Context
) && AllocatorExpr
->isLValue();
24153 if (!DRE
|| !IsTypeCompatible
||
24154 (!IsPredefinedAllocator
&& !IsNonConstantLValue
)) {
24155 Diag(D
.Allocator
->getExprLoc(), diag::err_omp_var_expected
)
24156 << "omp_allocator_handle_t" << (DRE
? 1 : 0)
24157 << AllocatorExpr
->getType() << D
.Allocator
->getSourceRange();
24160 // OpenMP [2.12.5, target Construct]
24161 // Predefined allocators appearing in a uses_allocators clause cannot have
24162 // traits specified.
24163 if (IsPredefinedAllocator
&& D
.AllocatorTraits
) {
24164 Diag(D
.AllocatorTraits
->getExprLoc(),
24165 diag::err_omp_predefined_allocator_with_traits
)
24166 << D
.AllocatorTraits
->getSourceRange();
24167 Diag(D
.Allocator
->getExprLoc(), diag::note_omp_predefined_allocator
)
24168 << cast
<NamedDecl
>(DRE
->getDecl())->getName()
24169 << D
.Allocator
->getSourceRange();
24172 // OpenMP [2.12.5, target Construct]
24173 // Non-predefined allocators appearing in a uses_allocators clause must
24174 // have traits specified.
24175 if (!IsPredefinedAllocator
&& !D
.AllocatorTraits
) {
24176 Diag(D
.Allocator
->getExprLoc(),
24177 diag::err_omp_nonpredefined_allocator_without_traits
);
24180 // No allocator traits - just convert it to rvalue.
24181 if (!D
.AllocatorTraits
)
24182 AllocatorExpr
= DefaultLvalueConversion(AllocatorExpr
).get();
24183 DSAStack
->addUsesAllocatorsDecl(
24185 IsPredefinedAllocator
24186 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
24187 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator
);
24189 Expr
*AllocatorTraitsExpr
= nullptr;
24190 if (D
.AllocatorTraits
) {
24191 if (D
.AllocatorTraits
->isTypeDependent()) {
24192 AllocatorTraitsExpr
= D
.AllocatorTraits
;
24194 // OpenMP [2.12.5, target Construct]
24195 // Arrays that contain allocator traits that appear in a uses_allocators
24196 // clause must be constant arrays, have constant values and be defined
24197 // in the same scope as the construct in which the clause appears.
24198 AllocatorTraitsExpr
= D
.AllocatorTraits
->IgnoreParenImpCasts();
24199 // Check that traits expr is a constant array.
24201 if (const ArrayType
*Ty
=
24202 AllocatorTraitsExpr
->getType()->getAsArrayTypeUnsafe())
24203 if (const auto *ConstArrayTy
= dyn_cast
<ConstantArrayType
>(Ty
))
24204 TraitTy
= ConstArrayTy
->getElementType();
24205 if (TraitTy
.isNull() ||
24206 !(Context
.hasSameUnqualifiedType(TraitTy
,
24207 DSAStack
->getOMPAlloctraitT()) ||
24208 Context
.typesAreCompatible(TraitTy
, DSAStack
->getOMPAlloctraitT(),
24209 /*CompareUnqualified=*/true))) {
24210 Diag(D
.AllocatorTraits
->getExprLoc(),
24211 diag::err_omp_expected_array_alloctraits
)
24212 << AllocatorTraitsExpr
->getType();
24215 // Do not map by default allocator traits if it is a standalone
24217 if (auto *DRE
= dyn_cast
<DeclRefExpr
>(AllocatorTraitsExpr
))
24218 DSAStack
->addUsesAllocatorsDecl(
24220 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait
);
24223 OMPUsesAllocatorsClause::Data
&NewD
= NewData
.emplace_back();
24224 NewD
.Allocator
= AllocatorExpr
;
24225 NewD
.AllocatorTraits
= AllocatorTraitsExpr
;
24226 NewD
.LParenLoc
= D
.LParenLoc
;
24227 NewD
.RParenLoc
= D
.RParenLoc
;
24229 return OMPUsesAllocatorsClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
,
24233 OMPClause
*Sema::ActOnOpenMPAffinityClause(
24234 SourceLocation StartLoc
, SourceLocation LParenLoc
, SourceLocation ColonLoc
,
24235 SourceLocation EndLoc
, Expr
*Modifier
, ArrayRef
<Expr
*> Locators
) {
24236 SmallVector
<Expr
*, 8> Vars
;
24237 for (Expr
*RefExpr
: Locators
) {
24238 assert(RefExpr
&& "NULL expr in OpenMP shared clause.");
24239 if (isa
<DependentScopeDeclRefExpr
>(RefExpr
) || RefExpr
->isTypeDependent()) {
24240 // It will be analyzed later.
24241 Vars
.push_back(RefExpr
);
24245 SourceLocation ELoc
= RefExpr
->getExprLoc();
24246 Expr
*SimpleExpr
= RefExpr
->IgnoreParenImpCasts();
24248 if (!SimpleExpr
->isLValue()) {
24249 Diag(ELoc
, diag::err_omp_expected_addressable_lvalue_or_array_item
)
24250 << 1 << 0 << RefExpr
->getSourceRange();
24256 Sema::TentativeAnalysisScope
Trap(*this);
24257 Res
= CreateBuiltinUnaryOp(ELoc
, UO_AddrOf
, SimpleExpr
);
24259 if (!Res
.isUsable() && !isa
<OMPArraySectionExpr
>(SimpleExpr
) &&
24260 !isa
<OMPArrayShapingExpr
>(SimpleExpr
)) {
24261 Diag(ELoc
, diag::err_omp_expected_addressable_lvalue_or_array_item
)
24262 << 1 << 0 << RefExpr
->getSourceRange();
24265 Vars
.push_back(SimpleExpr
);
24268 return OMPAffinityClause::Create(Context
, StartLoc
, LParenLoc
, ColonLoc
,
24269 EndLoc
, Modifier
, Vars
);
24272 OMPClause
*Sema::ActOnOpenMPBindClause(OpenMPBindClauseKind Kind
,
24273 SourceLocation KindLoc
,
24274 SourceLocation StartLoc
,
24275 SourceLocation LParenLoc
,
24276 SourceLocation EndLoc
) {
24277 if (Kind
== OMPC_BIND_unknown
) {
24278 Diag(KindLoc
, diag::err_omp_unexpected_clause_value
)
24279 << getListOfPossibleValues(OMPC_bind
, /*First=*/0,
24280 /*Last=*/unsigned(OMPC_BIND_unknown
))
24281 << getOpenMPClauseName(OMPC_bind
);
24285 return OMPBindClause::Create(Context
, Kind
, KindLoc
, StartLoc
, LParenLoc
,
24289 OMPClause
*Sema::ActOnOpenMPXDynCGroupMemClause(Expr
*Size
,
24290 SourceLocation StartLoc
,
24291 SourceLocation LParenLoc
,
24292 SourceLocation EndLoc
) {
24293 Expr
*ValExpr
= Size
;
24294 Stmt
*HelperValStmt
= nullptr;
24296 // OpenMP [2.5, Restrictions]
24297 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
24299 if (!isNonNegativeIntegerValue(ValExpr
, *this, OMPC_ompx_dyn_cgroup_mem
,
24300 /*StrictlyPositive=*/false))
24303 OpenMPDirectiveKind DKind
= DSAStack
->getCurrentDirective();
24304 OpenMPDirectiveKind CaptureRegion
= getOpenMPCaptureRegionForClause(
24305 DKind
, OMPC_ompx_dyn_cgroup_mem
, LangOpts
.OpenMP
);
24306 if (CaptureRegion
!= OMPD_unknown
&& !CurContext
->isDependentContext()) {
24307 ValExpr
= MakeFullExpr(ValExpr
).get();
24308 llvm::MapVector
<const Expr
*, DeclRefExpr
*> Captures
;
24309 ValExpr
= tryBuildCapture(*this, ValExpr
, Captures
).get();
24310 HelperValStmt
= buildPreInits(Context
, Captures
);
24313 return new (Context
) OMPXDynCGroupMemClause(
24314 ValExpr
, HelperValStmt
, CaptureRegion
, StartLoc
, LParenLoc
, EndLoc
);
24317 OMPClause
*Sema::ActOnOpenMPDoacrossClause(
24318 OpenMPDoacrossClauseModifier DepType
, SourceLocation DepLoc
,
24319 SourceLocation ColonLoc
, ArrayRef
<Expr
*> VarList
, SourceLocation StartLoc
,
24320 SourceLocation LParenLoc
, SourceLocation EndLoc
) {
24322 if (DSAStack
->getCurrentDirective() == OMPD_ordered
&&
24323 DepType
!= OMPC_DOACROSS_source
&& DepType
!= OMPC_DOACROSS_sink
&&
24324 DepType
!= OMPC_DOACROSS_sink_omp_cur_iteration
&&
24325 DepType
!= OMPC_DOACROSS_source_omp_cur_iteration
&&
24326 DepType
!= OMPC_DOACROSS_source
) {
24327 Diag(DepLoc
, diag::err_omp_unexpected_clause_value
)
24328 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_doacross
);
24332 SmallVector
<Expr
*, 8> Vars
;
24333 DSAStackTy::OperatorOffsetTy OpsOffs
;
24334 llvm::APSInt
TotalDepCount(/*BitWidth=*/32);
24335 DoacrossDataInfoTy VarOffset
= ProcessOpenMPDoacrossClauseCommon(
24337 DepType
== OMPC_DOACROSS_source
||
24338 DepType
== OMPC_DOACROSS_source_omp_cur_iteration
||
24339 DepType
== OMPC_DOACROSS_sink_omp_cur_iteration
,
24340 VarList
, DSAStack
, EndLoc
);
24341 Vars
= VarOffset
.Vars
;
24342 OpsOffs
= VarOffset
.OpsOffs
;
24343 TotalDepCount
= VarOffset
.TotalDepCount
;
24344 auto *C
= OMPDoacrossClause::Create(Context
, StartLoc
, LParenLoc
, EndLoc
,
24345 DepType
, DepLoc
, ColonLoc
, Vars
,
24346 TotalDepCount
.getZExtValue());
24347 if (DSAStack
->isParentOrderedRegion())
24348 DSAStack
->addDoacrossDependClause(C
, OpsOffs
);
24352 OMPClause
*Sema::ActOnOpenMPXAttributeClause(ArrayRef
<const Attr
*> Attrs
,
24353 SourceLocation StartLoc
,
24354 SourceLocation LParenLoc
,
24355 SourceLocation EndLoc
) {
24356 return new (Context
) OMPXAttributeClause(Attrs
, StartLoc
, LParenLoc
, EndLoc
);
24359 OMPClause
*Sema::ActOnOpenMPXBareClause(SourceLocation StartLoc
,
24360 SourceLocation EndLoc
) {
24361 return new (Context
) OMPXBareClause(StartLoc
, EndLoc
);