40#include "llvm/ADT/IndexedMap.h"
41#include "llvm/ADT/PointerEmbeddedInt.h"
42#include "llvm/ADT/STLExtras.h"
43#include "llvm/ADT/Sequence.h"
44#include "llvm/ADT/SetVector.h"
45#include "llvm/ADT/SmallSet.h"
46#include "llvm/ADT/StringExtras.h"
47#include "llvm/Frontend/OpenMP/OMPAssume.h"
48#include "llvm/Frontend/OpenMP/OMPConstants.h"
49#include "llvm/IR/Assumptions.h"
53using namespace llvm::omp;
68enum DefaultDataSharingAttributes {
73 DSA_firstprivate = 1 << 3,
80enum DefaultDataSharingVCAttributes {
94 unsigned Modifier = 0;
95 const Expr *RefExpr =
nullptr;
96 DeclRefExpr *PrivateCopy =
nullptr;
97 SourceLocation ImplicitDSALoc;
98 bool AppliedToPointee =
false;
99 DSAVarData() =
default;
101 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
102 SourceLocation ImplicitDSALoc,
unsigned Modifier,
103 bool AppliedToPointee)
104 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
105 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
106 AppliedToPointee(AppliedToPointee) {}
108 using OperatorOffsetTy =
109 llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
110 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
112 enum class UsesAllocatorsDeclKind {
116 UserDefinedAllocator,
124 unsigned Modifier = 0;
127 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
128 DeclRefExpr *PrivateCopy =
nullptr;
131 bool AppliedToPointee =
false;
133 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
134 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
135 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
136 using LoopControlVariablesMapTy =
137 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
140 struct MappedExprComponentTy {
144 using MappedExprComponentsTy =
145 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
146 using CriticalsWithHintsTy =
147 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
148 struct ReductionData {
149 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
150 SourceRange ReductionRange;
151 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
152 ReductionData() =
default;
157 void set(
const Expr *RefExpr, SourceRange RR) {
159 ReductionOp = RefExpr;
162 using DeclReductionMapTy =
163 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
164 struct DefaultmapInfo {
168 DefaultmapInfo() =
default;
170 : ImplicitBehavior(M), SLoc(Loc) {}
173 struct SharingMapTy {
174 DeclSAMapTy SharingMap;
175 DeclReductionMapTy ReductionMap;
176 UsedRefMapTy AlignedMap;
177 UsedRefMapTy NontemporalMap;
178 MappedExprComponentsTy MappedExprComponents;
179 LoopControlVariablesMapTy LCVMap;
180 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
181 SourceLocation DefaultAttrLoc;
182 DefaultDataSharingVCAttributes DefaultVCAttr = DSA_VC_all;
183 SourceLocation DefaultAttrVCLoc;
186 DeclarationNameInfo DirectiveName;
187 Scope *CurScope =
nullptr;
188 DeclContext *Context =
nullptr;
189 SourceLocation ConstructLoc;
193 DoacrossClauseMapTy DoacrossDepends;
197 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
198 bool RegionHasOrderConcurrent =
false;
199 unsigned AssociatedLoops = 1;
200 bool HasMutipleLoops =
false;
201 const Decl *PossiblyLoopCounter =
nullptr;
202 bool NowaitRegion =
false;
203 bool UntiedRegion =
false;
204 bool CancelRegion =
false;
205 bool LoopStart =
false;
206 bool BodyComplete =
false;
207 SourceLocation PrevScanLocation;
208 SourceLocation PrevOrderedLocation;
209 SourceLocation InnerTeamsRegionLoc;
211 Expr *TaskgroupReductionRef =
nullptr;
212 llvm::DenseSet<QualType> MappedClassesQualTypes;
213 SmallVector<Expr *, 4> InnerUsedAllocators;
214 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
217 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
219 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
220 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
224 struct ImplicitDefaultFDInfoTy {
226 const FieldDecl *FD =
nullptr;
228 size_t StackLevel = 0;
230 VarDecl *VD =
nullptr;
231 ImplicitDefaultFDInfoTy(
const FieldDecl *FD,
size_t StackLevel,
233 : FD(FD), StackLevel(StackLevel), VD(VD) {}
236 llvm::SmallVector<ImplicitDefaultFDInfoTy, 8>
237 ImplicitDefaultFirstprivateFDs;
238 Expr *DeclareMapperVar =
nullptr;
239 SmallVector<VarDecl *, 16> IteratorVarDecls;
241 Scope *CurScope, SourceLocation Loc)
242 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
244 SharingMapTy() =
default;
247 using StackTy = SmallVector<SharingMapTy, 4>;
250 DeclSAMapTy Threadprivates;
251 DeclSAMapTy Groupprivates;
252 const FunctionScopeInfo *CurrentNonCapturingFunctionScope =
nullptr;
253 SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack;
258 bool ForceCapturing =
false;
261 bool ForceCaptureByReferenceInTargetExecutable =
false;
262 CriticalsWithHintsTy Criticals;
263 unsigned IgnoredStackElements = 0;
267 using const_iterator = StackTy::const_reverse_iterator;
268 const_iterator begin()
const {
269 return Stack.empty() ? const_iterator()
270 : Stack.back().first.rbegin() + IgnoredStackElements;
272 const_iterator end()
const {
273 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
275 using iterator = StackTy::reverse_iterator;
277 return Stack.empty() ? iterator()
278 : Stack.back().first.rbegin() + IgnoredStackElements;
281 return Stack.empty() ? iterator() : Stack.back().first.rend();
286 bool isStackEmpty()
const {
287 return Stack.empty() ||
288 Stack.back().second != CurrentNonCapturingFunctionScope ||
289 Stack.back().first.size() <= IgnoredStackElements;
291 size_t getStackSize()
const {
292 return isStackEmpty() ? 0
293 : Stack.back().first.size() - IgnoredStackElements;
296 SharingMapTy *getTopOfStackOrNull() {
297 size_t Size = getStackSize();
300 return &Stack.back().first[
Size - 1];
302 const SharingMapTy *getTopOfStackOrNull()
const {
303 return const_cast<DSAStackTy &
>(*this).getTopOfStackOrNull();
305 SharingMapTy &getTopOfStack() {
306 assert(!isStackEmpty() &&
"no current directive");
307 return *getTopOfStackOrNull();
309 const SharingMapTy &getTopOfStack()
const {
310 return const_cast<DSAStackTy &
>(*this).getTopOfStack();
313 SharingMapTy *getSecondOnStackOrNull() {
314 size_t Size = getStackSize();
317 return &Stack.back().first[
Size - 2];
319 const SharingMapTy *getSecondOnStackOrNull()
const {
320 return const_cast<DSAStackTy &
>(*this).getSecondOnStackOrNull();
329 SharingMapTy &getStackElemAtLevel(
unsigned Level) {
330 assert(Level < getStackSize() &&
"no such stack element");
331 return Stack.back().first[
Level];
333 const SharingMapTy &getStackElemAtLevel(
unsigned Level)
const {
334 return const_cast<DSAStackTy &
>(*this).getStackElemAtLevel(Level);
337 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D)
const;
340 bool isOpenMPLocal(VarDecl *D, const_iterator Iter)
const;
343 SmallVector<const OMPRequiresDecl *, 2> RequiresDecls;
345 QualType OMPAllocatorHandleT;
349 QualType OMPEventHandleT;
351 QualType OMPAlloctraitT;
353 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
356 SmallVector<SourceLocation, 2> TargetLocations;
357 SourceLocation AtomicLocation;
359 SmallVector<llvm::omp::TraitProperty, 8> ConstructTraits;
362 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
365 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
367 QualType getOMPAllocatorHandleT()
const {
return OMPAllocatorHandleT; }
369 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
371 QualType getOMPAlloctraitT()
const {
return OMPAlloctraitT; }
373 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
375 OMPPredefinedAllocators[AllocatorKind] = Allocator;
378 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind)
const {
379 return OMPPredefinedAllocators[AllocatorKind];
382 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
384 QualType getOMPDependT()
const {
return OMPDependT; }
387 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
389 QualType getOMPEventHandleT()
const {
return OMPEventHandleT; }
391 bool isClauseParsingMode()
const {
return ClauseKindMode != OMPC_unknown; }
393 assert(isClauseParsingMode() &&
"Must be in clause parsing mode.");
394 return ClauseKindMode;
398 bool isBodyComplete()
const {
399 const SharingMapTy *Top = getTopOfStackOrNull();
400 return Top && Top->BodyComplete;
402 void setBodyComplete() { getTopOfStack().BodyComplete =
true; }
404 bool isForceVarCapturing()
const {
return ForceCapturing; }
405 void setForceVarCapturing(
bool V) { ForceCapturing =
V; }
407 void setForceCaptureByReferenceInTargetExecutable(
bool V) {
408 ForceCaptureByReferenceInTargetExecutable =
V;
410 bool isForceCaptureByReferenceInTargetExecutable()
const {
411 return ForceCaptureByReferenceInTargetExecutable;
415 Scope *CurScope, SourceLocation Loc) {
416 assert(!IgnoredStackElements &&
417 "cannot change stack while ignoring elements");
419 Stack.back().second != CurrentNonCapturingFunctionScope)
420 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
421 Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc);
422 Stack.back().first.back().DefaultAttrLoc = Loc;
426 assert(!IgnoredStackElements &&
427 "cannot change stack while ignoring elements");
428 assert(!Stack.back().first.empty() &&
429 "Data-sharing attributes stack is empty!");
430 Stack.back().first.pop_back();
435 class ParentDirectiveScope {
440 ParentDirectiveScope(DSAStackTy &Self,
bool Activate)
441 : Self(Self), Active(
false) {
445 ~ParentDirectiveScope() { disable(); }
448 --Self.IgnoredStackElements;
454 ++Self.IgnoredStackElements;
463 "Expected loop-based directive.");
464 getTopOfStack().LoopStart =
true;
469 "Expected loop-based directive.");
470 getTopOfStack().LoopStart =
false;
473 bool isLoopStarted()
const {
475 "Expected loop-based directive.");
476 return !getTopOfStack().LoopStart;
479 void resetPossibleLoopCounter(
const Decl *D =
nullptr) {
480 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
483 const Decl *getPossiblyLoopCounter()
const {
484 return getTopOfStack().PossiblyLoopCounter;
487 void pushFunction() {
488 assert(!IgnoredStackElements &&
489 "cannot change stack while ignoring elements");
490 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
492 CurrentNonCapturingFunctionScope = CurFnScope;
495 void popFunction(
const FunctionScopeInfo *OldFSI) {
496 assert(!IgnoredStackElements &&
497 "cannot change stack while ignoring elements");
498 if (!Stack.empty() && Stack.back().second == OldFSI) {
499 assert(Stack.back().first.empty());
502 CurrentNonCapturingFunctionScope =
nullptr;
503 for (
const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) {
505 CurrentNonCapturingFunctionScope = FSI;
511 void addCriticalWithHint(
const OMPCriticalDirective *D, llvm::APSInt Hint) {
512 Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint);
514 std::pair<const OMPCriticalDirective *, llvm::APSInt>
515 getCriticalWithHint(
const DeclarationNameInfo &Name)
const {
517 if (I != Criticals.end())
519 return std::make_pair(
nullptr, llvm::APSInt());
524 const Expr *addUniqueAligned(
const ValueDecl *D,
const Expr *NewDE);
528 const Expr *addUniqueNontemporal(
const ValueDecl *D,
const Expr *NewDE);
531 void addLoopControlVariable(
const ValueDecl *D, VarDecl *
Capture);
536 const LCDeclInfo isLoopControlVariable(
const ValueDecl *D)
const;
541 const LCDeclInfo isParentLoopControlVariable(
const ValueDecl *D)
const;
546 const LCDeclInfo isLoopControlVariable(
const ValueDecl *D,
547 unsigned Level)
const;
550 const ValueDecl *getParentLoopControlVariable(
unsigned I)
const;
553 void markDeclAsUsedInScanDirective(ValueDecl *D) {
554 if (SharingMapTy *Stack = getSecondOnStackOrNull())
555 Stack->UsedInScanDirective.insert(D);
559 bool isUsedInScanDirective(ValueDecl *D)
const {
560 if (
const SharingMapTy *Stack = getTopOfStackOrNull())
561 return Stack->UsedInScanDirective.contains(D);
567 DeclRefExpr *PrivateCopy =
nullptr,
unsigned Modifier = 0,
568 bool AppliedToPointee =
false);
572 void addTaskgroupReductionData(
const ValueDecl *D, SourceRange SR,
576 void addTaskgroupReductionData(
const ValueDecl *D, SourceRange SR,
577 const Expr *ReductionRef);
581 getTopMostTaskgroupReductionData(
const ValueDecl *D, SourceRange &SR,
583 Expr *&TaskgroupDescriptor)
const;
587 getTopMostTaskgroupReductionData(
const ValueDecl *D, SourceRange &SR,
588 const Expr *&ReductionRef,
589 Expr *&TaskgroupDescriptor)
const;
592 Expr *getTaskgroupReductionRef()
const {
593 assert((getTopOfStack().
Directive == OMPD_taskgroup ||
597 "taskgroup reference expression requested for non taskgroup or "
598 "parallel/worksharing directive.");
599 return getTopOfStack().TaskgroupReductionRef;
603 bool isTaskgroupReductionRef(
const ValueDecl *VD,
unsigned Level)
const {
604 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
611 const DSAVarData getTopDSA(ValueDecl *D,
bool FromParent);
613 const DSAVarData getImplicitDSA(ValueDecl *D,
bool FromParent)
const;
615 const DSAVarData getImplicitDSA(ValueDecl *D,
unsigned Level)
const;
622 DefaultDataSharingAttributes)>
625 bool FromParent)
const;
630 hasInnermostDSA(ValueDecl *D,
633 bool FromParent)
const;
638 hasExplicitDSA(
const ValueDecl *D,
640 unsigned Level,
bool NotLastprivate =
false)
const;
644 bool hasExplicitDirective(
646 unsigned Level)
const;
650 const llvm::function_ref<
bool(
653 bool FromParent)
const;
657 const SharingMapTy *Top = getTopOfStackOrNull();
658 return Top ? Top->Directive : OMPD_unknown;
662 assert(!isStackEmpty() &&
"No directive at specified level.");
663 return getStackElemAtLevel(Level).Directive;
667 unsigned OpenMPCaptureLevel)
const {
668 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
670 return CaptureRegions[OpenMPCaptureLevel];
674 const SharingMapTy *Parent = getSecondOnStackOrNull();
675 return Parent ? Parent->Directive : OMPD_unknown;
679 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
682 template <
typename ClauseType>
bool hasRequiresDeclWithClause()
const {
683 return llvm::any_of(RequiresDecls, [](
const OMPRequiresDecl *D) {
684 return llvm::any_of(D->
clauselists(), [](
const OMPClause *
C) {
685 return isa<ClauseType>(C);
692 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList)
const {
693 bool IsDuplicate =
false;
694 for (OMPClause *CNew : ClauseList) {
695 for (
const OMPRequiresDecl *D : RequiresDecls) {
696 for (
const OMPClause *CPrev : D->clauselists()) {
697 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
698 SemaRef.Diag(CNew->getBeginLoc(),
699 diag::err_omp_requires_clause_redeclaration)
701 SemaRef.Diag(CPrev->getBeginLoc(),
702 diag::note_omp_requires_previous_clause)
713 void addTargetDirLocation(SourceLocation LocStart) {
714 TargetLocations.push_back(LocStart);
718 void addAtomicDirectiveLoc(SourceLocation Loc) {
719 if (AtomicLocation.isInvalid())
720 AtomicLocation = Loc;
725 SourceLocation getAtomicDirectiveLoc()
const {
return AtomicLocation; }
728 ArrayRef<SourceLocation> getEncounteredTargetLocs()
const {
729 return TargetLocations;
733 void setDefaultDSANone(SourceLocation Loc) {
734 getTopOfStack().DefaultAttr = DSA_none;
735 getTopOfStack().DefaultAttrLoc = Loc;
738 void setDefaultDSAShared(SourceLocation Loc) {
739 getTopOfStack().DefaultAttr = DSA_shared;
740 getTopOfStack().DefaultAttrLoc = Loc;
743 void setDefaultDSAPrivate(SourceLocation Loc) {
744 getTopOfStack().DefaultAttr = DSA_private;
745 getTopOfStack().DefaultAttrLoc = Loc;
748 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
749 getTopOfStack().DefaultAttr = DSA_firstprivate;
750 getTopOfStack().DefaultAttrLoc = Loc;
753 void setDefaultDSAVCAggregate(SourceLocation VCLoc) {
754 getTopOfStack().DefaultVCAttr = DSA_VC_aggregate;
755 getTopOfStack().DefaultAttrVCLoc = VCLoc;
758 void setDefaultDSAVCAll(SourceLocation VCLoc) {
759 getTopOfStack().DefaultVCAttr = DSA_VC_all;
760 getTopOfStack().DefaultAttrVCLoc = VCLoc;
763 void setDefaultDSAVCPointer(SourceLocation VCLoc) {
764 getTopOfStack().DefaultVCAttr = DSA_VC_pointer;
765 getTopOfStack().DefaultAttrVCLoc = VCLoc;
768 void setDefaultDSAVCScalar(SourceLocation VCLoc) {
769 getTopOfStack().DefaultVCAttr = DSA_VC_scalar;
770 getTopOfStack().DefaultAttrVCLoc = VCLoc;
775 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[
Kind];
776 DMI.ImplicitBehavior = M;
782 return getTopOfStack()
783 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
786 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
789 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
791 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
795 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
796 return ConstructTraits;
798 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
801 ConstructTraits.append(Traits.begin(), Traits.end());
803 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
804 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
805 assert(Top == Trait &&
"Something left a trait on the stack!");
811 DefaultDataSharingAttributes getDefaultDSA(
unsigned Level)
const {
812 return getStackSize() <=
Level ? DSA_unspecified
813 : getStackElemAtLevel(Level).DefaultAttr;
815 DefaultDataSharingAttributes getDefaultDSA()
const {
816 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
818 SourceLocation getDefaultDSALocation()
const {
819 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
823 return isStackEmpty()
825 : getTopOfStack().DefaultmapMap[
Kind].ImplicitBehavior;
828 getDefaultmapModifierAtLevel(
unsigned Level,
830 return getStackElemAtLevel(Level).DefaultmapMap[
Kind].ImplicitBehavior;
832 bool isDefaultmapCapturedByRef(
unsigned Level,
835 getDefaultmapModifierAtLevel(Level, Kind);
836 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
837 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
838 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
839 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
840 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom) ||
841 (M == OMPC_DEFAULTMAP_MODIFIER_present) ||
842 (M == OMPC_DEFAULTMAP_MODIFIER_storage);
849 case OMPC_DEFAULTMAP_scalar:
850 case OMPC_DEFAULTMAP_pointer:
852 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
853 (M == OMPC_DEFAULTMAP_MODIFIER_default);
854 case OMPC_DEFAULTMAP_aggregate:
855 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
859 llvm_unreachable(
"Unexpected OpenMPDefaultmapClauseKind enum");
861 bool mustBeFirstprivateAtLevel(
unsigned Level,
864 getDefaultmapModifierAtLevel(Level, Kind);
865 return mustBeFirstprivateBase(M, Kind);
869 return mustBeFirstprivateBase(M, Kind);
873 bool isThreadPrivate(VarDecl *D) {
874 const DSAVarData DVar = getTopDSA(D,
false);
879 void setOrderedRegion(
bool IsOrdered,
const Expr *Param,
880 OMPOrderedClause *Clause) {
882 getTopOfStack().OrderedRegion.emplace(Param, Clause);
884 getTopOfStack().OrderedRegion.reset();
888 bool isOrderedRegion()
const {
889 if (
const SharingMapTy *Top = getTopOfStackOrNull())
890 return Top->OrderedRegion.has_value();
894 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam()
const {
895 if (
const SharingMapTy *Top = getTopOfStackOrNull())
896 if (Top->OrderedRegion)
897 return *Top->OrderedRegion;
898 return std::make_pair(
nullptr,
nullptr);
902 bool isParentOrderedRegion()
const {
903 if (
const SharingMapTy *Parent = getSecondOnStackOrNull())
904 return Parent->OrderedRegion.has_value();
908 std::pair<const Expr *, OMPOrderedClause *>
909 getParentOrderedRegionParam()
const {
910 if (
const SharingMapTy *Parent = getSecondOnStackOrNull())
911 if (Parent->OrderedRegion)
912 return *Parent->OrderedRegion;
913 return std::make_pair(
nullptr,
nullptr);
916 void setRegionHasOrderConcurrent(
bool HasOrderConcurrent) {
917 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
921 bool isParentOrderConcurrent()
const {
922 if (
const SharingMapTy *Parent = getSecondOnStackOrNull())
923 return Parent->RegionHasOrderConcurrent;
927 void setNowaitRegion(
bool IsNowait =
true) {
928 getTopOfStack().NowaitRegion = IsNowait;
932 bool isParentNowaitRegion()
const {
933 if (
const SharingMapTy *Parent = getSecondOnStackOrNull())
934 return Parent->NowaitRegion;
938 void setUntiedRegion(
bool IsUntied =
true) {
939 getTopOfStack().UntiedRegion = IsUntied;
942 bool isUntiedRegion()
const {
943 const SharingMapTy *Top = getTopOfStackOrNull();
944 return Top ? Top->UntiedRegion :
false;
947 void setParentCancelRegion(
bool Cancel =
true) {
948 if (SharingMapTy *Parent = getSecondOnStackOrNull())
949 Parent->CancelRegion |= Cancel;
952 bool isCancelRegion()
const {
953 const SharingMapTy *Top = getTopOfStackOrNull();
954 return Top ? Top->CancelRegion :
false;
958 void setParentHasScanDirective(SourceLocation Loc) {
959 if (SharingMapTy *Parent = getSecondOnStackOrNull())
960 Parent->PrevScanLocation = Loc;
963 bool doesParentHasScanDirective()
const {
964 const SharingMapTy *Top = getSecondOnStackOrNull();
965 return Top ? Top->PrevScanLocation.isValid() :
false;
968 SourceLocation getParentScanDirectiveLoc()
const {
969 const SharingMapTy *Top = getSecondOnStackOrNull();
970 return Top ? Top->PrevScanLocation : SourceLocation();
973 void setParentHasOrderedDirective(SourceLocation Loc) {
974 if (SharingMapTy *Parent = getSecondOnStackOrNull())
975 Parent->PrevOrderedLocation = Loc;
978 bool doesParentHasOrderedDirective()
const {
979 const SharingMapTy *Top = getSecondOnStackOrNull();
980 return Top ? Top->PrevOrderedLocation.isValid() :
false;
983 SourceLocation getParentOrderedDirectiveLoc()
const {
984 const SharingMapTy *Top = getSecondOnStackOrNull();
985 return Top ? Top->PrevOrderedLocation : SourceLocation();
989 void setAssociatedLoops(
unsigned Val) {
990 getTopOfStack().AssociatedLoops = Val;
992 getTopOfStack().HasMutipleLoops =
true;
995 unsigned getAssociatedLoops()
const {
996 const SharingMapTy *Top = getTopOfStackOrNull();
997 return Top ? Top->AssociatedLoops : 0;
1000 bool hasMutipleLoops()
const {
1001 const SharingMapTy *Top = getTopOfStackOrNull();
1002 return Top ? Top->HasMutipleLoops :
false;
1007 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
1008 if (SharingMapTy *Parent = getSecondOnStackOrNull())
1009 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
1012 bool hasInnerTeamsRegion()
const {
1013 return getInnerTeamsRegionLoc().
isValid();
1016 SourceLocation getInnerTeamsRegionLoc()
const {
1017 const SharingMapTy *Top = getTopOfStackOrNull();
1018 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
1021 Scope *getCurScope()
const {
1022 const SharingMapTy *Top = getTopOfStackOrNull();
1023 return Top ? Top->CurScope :
nullptr;
1025 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
1026 SourceLocation getConstructLoc()
const {
1027 const SharingMapTy *Top = getTopOfStackOrNull();
1028 return Top ? Top->ConstructLoc : SourceLocation();
1033 bool checkMappableExprComponentListsForDecl(
1034 const ValueDecl *VD,
bool CurrentRegionOnly,
1035 const llvm::function_ref<
1047 if (CurrentRegionOnly)
1050 std::advance(SI, 1);
1052 for (; SI != SE; ++SI) {
1053 auto MI = SI->MappedExprComponents.find(VD);
1054 if (MI != SI->MappedExprComponents.end())
1056 MI->second.Components)
1057 if (Check(L, MI->second.Kind))
1065 bool checkMappableExprComponentListsForDeclAtLevel(
1066 const ValueDecl *VD,
unsigned Level,
1067 const llvm::function_ref<
1071 if (getStackSize() <= Level)
1074 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1075 auto MI = StackElem.MappedExprComponents.find(VD);
1076 if (MI != StackElem.MappedExprComponents.end())
1078 MI->second.Components)
1079 if (Check(L, MI->second.Kind))
1086 void addMappableExpressionComponents(
1087 const ValueDecl *VD,
1090 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1092 MEC.Components.resize(MEC.Components.size() + 1);
1093 MEC.Components.back().append(Components.begin(), Components.end());
1094 MEC.Kind = WhereFoundClauseKind;
1097 unsigned getNestingLevel()
const {
1098 assert(!isStackEmpty());
1099 return getStackSize() - 1;
1101 void addDoacrossDependClause(OMPClause *
C,
const OperatorOffsetTy &OpsOffs) {
1102 SharingMapTy *Parent = getSecondOnStackOrNull();
1104 Parent->DoacrossDepends.try_emplace(
C, OpsOffs);
1106 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1107 getDoacrossDependClauses()
const {
1108 const SharingMapTy &StackElem = getTopOfStack();
1110 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1111 return llvm::make_range(Ref.begin(), Ref.end());
1113 return llvm::make_range(StackElem.DoacrossDepends.end(),
1114 StackElem.DoacrossDepends.end());
1118 void addMappedClassesQualTypes(QualType QT) {
1119 SharingMapTy &StackElem = getTopOfStack();
1120 StackElem.MappedClassesQualTypes.insert(QT);
1124 bool isClassPreviouslyMapped(QualType QT)
const {
1125 const SharingMapTy &StackElem = getTopOfStack();
1126 return StackElem.MappedClassesQualTypes.contains(QT);
1130 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1131 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1132 E->
getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1133 "Expected declare target link global.");
1134 for (
auto &Elem : *
this) {
1136 Elem.DeclareTargetLinkVarDecls.push_back(E);
1144 ArrayRef<DeclRefExpr *> getLinkGlobals()
const {
1146 "Expected target executable directive.");
1147 return getTopOfStack().DeclareTargetLinkVarDecls;
1151 void addInnerAllocatorExpr(Expr *E) {
1152 getTopOfStack().InnerUsedAllocators.push_back(E);
1155 ArrayRef<Expr *> getInnerAllocators()
const {
1156 return getTopOfStack().InnerUsedAllocators;
1160 void addImplicitTaskFirstprivate(
unsigned Level, Decl *D) {
1161 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(D);
1164 bool isImplicitTaskFirstprivate(Decl *D)
const {
1165 return getTopOfStack().ImplicitTaskFirstprivates.contains(D);
1169 void addUsesAllocatorsDecl(
const Decl *D, UsesAllocatorsDeclKind Kind) {
1170 getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind);
1174 std::optional<UsesAllocatorsDeclKind>
1175 isUsesAllocatorsDecl(
unsigned Level,
const Decl *D)
const {
1176 const SharingMapTy &StackElem = getTopOfStack();
1177 auto I = StackElem.UsesAllocatorsDecls.find(D);
1178 if (I == StackElem.UsesAllocatorsDecls.end())
1179 return std::nullopt;
1180 return I->getSecond();
1182 std::optional<UsesAllocatorsDeclKind>
1183 isUsesAllocatorsDecl(
const Decl *D)
const {
1184 const SharingMapTy &StackElem = getTopOfStack();
1185 auto I = StackElem.UsesAllocatorsDecls.find(D);
1186 if (I == StackElem.UsesAllocatorsDecls.end())
1187 return std::nullopt;
1188 return I->getSecond();
1191 void addDeclareMapperVarRef(Expr *Ref) {
1192 SharingMapTy &StackElem = getTopOfStack();
1193 StackElem.DeclareMapperVar = Ref;
1195 const Expr *getDeclareMapperVarRef()
const {
1196 const SharingMapTy *Top = getTopOfStackOrNull();
1197 return Top ? Top->DeclareMapperVar :
nullptr;
1201 void addIteratorVarDecl(VarDecl *VD) {
1202 SharingMapTy &StackElem = getTopOfStack();
1206 bool isIteratorVarDecl(
const VarDecl *VD)
const {
1207 const SharingMapTy *Top = getTopOfStackOrNull();
1214 VarDecl *getImplicitFDCapExprDecl(
const FieldDecl *FD)
const {
1215 const_iterator I = begin();
1216 const_iterator EndI = end();
1217 size_t StackLevel = getStackSize();
1218 for (; I != EndI; ++I) {
1219 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1223 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1226 for (
const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1227 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1232 bool isImplicitDefaultFirstprivateFD(VarDecl *VD)
const {
1233 const_iterator I = begin();
1234 const_iterator EndI = end();
1235 for (; I != EndI; ++I)
1236 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1240 for (
const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1246 void addImplicitDefaultFirstprivateFD(
const FieldDecl *FD, VarDecl *VD) {
1247 iterator I = begin();
1248 const_iterator EndI = end();
1249 size_t StackLevel = getStackSize();
1250 for (; I != EndI; ++I) {
1251 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1252 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1257 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1267 DKind == OMPD_unknown;
1273 if (
const auto *FE = dyn_cast<FullExpr>(E))
1274 E = FE->getSubExpr();
1276 if (
const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
1277 E = MTE->getSubExpr();
1279 while (
const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
1280 E = Binder->getSubExpr();
1282 if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
1283 E = ICE->getSubExprAsWritten();
1292 if (
const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
1293 if (
const auto *ME = dyn_cast<MemberExpr>(
getExprAsWritten(CED->getInit())))
1294 D = ME->getMemberDecl();
1306 if (
C == OMPC_threadprivate)
1307 return getOpenMPClauseName(
C).str() +
" or thread local";
1308 return getOpenMPClauseName(
C).str();
1314 auto *VD = dyn_cast<VarDecl>(D);
1315 const auto *FD = dyn_cast<FieldDecl>(D);
1317 if (Iter == end()) {
1324 DVar.CKind = OMPC_shared;
1331 DVar.CKind = OMPC_shared;
1335 DVar.CKind = OMPC_shared;
1346 DVar.CKind = OMPC_private;
1350 DVar.DKind = Iter->Directive;
1353 if (Iter->SharingMap.count(D)) {
1354 const DSAInfo &
Data = Iter->SharingMap.lookup(D);
1355 DVar.RefExpr =
Data.RefExpr.getPointer();
1356 DVar.PrivateCopy =
Data.PrivateCopy;
1357 DVar.CKind =
Data.Attributes;
1358 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1359 DVar.Modifier =
Data.Modifier;
1360 DVar.AppliedToPointee =
Data.AppliedToPointee;
1364 DefaultDataSharingAttributes IterDA = Iter->DefaultAttr;
1365 switch (Iter->DefaultVCAttr) {
1366 case DSA_VC_aggregate:
1370 case DSA_VC_pointer:
1388 DVar.CKind = OMPC_shared;
1389 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1393 case DSA_firstprivate:
1396 DVar.CKind = OMPC_unknown;
1398 DVar.CKind = OMPC_firstprivate;
1400 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1408 DVar.CKind = OMPC_unknown;
1410 DVar.CKind = OMPC_private;
1412 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1414 case DSA_unspecified:
1419 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1423 DVar.CKind = OMPC_shared;
1433 DSAVarData DVarTemp;
1434 const_iterator I = Iter, E = end();
1442 DVarTemp = getDSA(I, D);
1443 if (DVarTemp.CKind != OMPC_shared) {
1444 DVar.RefExpr =
nullptr;
1445 DVar.CKind = OMPC_firstprivate;
1448 }
while (I != E && !isImplicitTaskingRegion(I->Directive));
1450 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1459 return getDSA(++Iter, D);
1462const Expr *DSAStackTy::addUniqueAligned(
const ValueDecl *D,
1463 const Expr *NewDE) {
1464 assert(!isStackEmpty() &&
"Data sharing attributes stack is empty");
1466 SharingMapTy &StackElem = getTopOfStack();
1467 auto [It, Inserted] = StackElem.AlignedMap.try_emplace(D, NewDE);
1469 assert(NewDE &&
"Unexpected nullptr expr to be added into aligned map");
1472 assert(It->second &&
"Unexpected nullptr expr in the aligned map");
1476const Expr *DSAStackTy::addUniqueNontemporal(
const ValueDecl *D,
1477 const Expr *NewDE) {
1478 assert(!isStackEmpty() &&
"Data sharing attributes stack is empty");
1480 SharingMapTy &StackElem = getTopOfStack();
1481 auto [It, Inserted] = StackElem.NontemporalMap.try_emplace(D, NewDE);
1483 assert(NewDE &&
"Unexpected nullptr expr to be added into aligned map");
1486 assert(It->second &&
"Unexpected nullptr expr in the aligned map");
1490void DSAStackTy::addLoopControlVariable(
const ValueDecl *D, VarDecl *
Capture) {
1491 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1493 SharingMapTy &StackElem = getTopOfStack();
1494 StackElem.LCVMap.try_emplace(
1495 D, LCDeclInfo(StackElem.LCVMap.size() + 1,
Capture));
1498const DSAStackTy::LCDeclInfo
1499DSAStackTy::isLoopControlVariable(
const ValueDecl *D)
const {
1500 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1502 const SharingMapTy &StackElem = getTopOfStack();
1503 auto It = StackElem.LCVMap.find(D);
1504 if (It != StackElem.LCVMap.end())
1506 return {0,
nullptr};
1509const DSAStackTy::LCDeclInfo
1510DSAStackTy::isLoopControlVariable(
const ValueDecl *D,
unsigned Level)
const {
1511 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1513 for (
unsigned I = Level + 1; I > 0; --I) {
1514 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1515 auto It = StackElem.LCVMap.find(D);
1516 if (It != StackElem.LCVMap.end())
1519 return {0,
nullptr};
1522const DSAStackTy::LCDeclInfo
1523DSAStackTy::isParentLoopControlVariable(
const ValueDecl *D)
const {
1524 const SharingMapTy *Parent = getSecondOnStackOrNull();
1525 assert(Parent &&
"Data-sharing attributes stack is empty");
1527 auto It = Parent->LCVMap.find(D);
1528 if (It != Parent->LCVMap.end())
1530 return {0,
nullptr};
1533const ValueDecl *DSAStackTy::getParentLoopControlVariable(
unsigned I)
const {
1534 const SharingMapTy *Parent = getSecondOnStackOrNull();
1535 assert(Parent &&
"Data-sharing attributes stack is empty");
1536 if (Parent->LCVMap.size() < I)
1538 for (
const auto &Pair : Parent->LCVMap)
1539 if (Pair.second.first == I)
1544void DSAStackTy::addDSA(
const ValueDecl *D,
const Expr *E,
OpenMPClauseKind A,
1545 DeclRefExpr *PrivateCopy,
unsigned Modifier,
1546 bool AppliedToPointee) {
1548 if (A == OMPC_threadprivate) {
1549 DSAInfo &
Data = Threadprivates[D];
1550 Data.Attributes = A;
1551 Data.RefExpr.setPointer(E);
1552 Data.PrivateCopy =
nullptr;
1553 Data.Modifier = Modifier;
1554 }
else if (A == OMPC_groupprivate) {
1555 DSAInfo &
Data = Groupprivates[D];
1556 Data.Attributes = A;
1557 Data.RefExpr.setPointer(E);
1558 Data.PrivateCopy =
nullptr;
1559 Data.Modifier = Modifier;
1561 DSAInfo &
Data = getTopOfStack().SharingMap[D];
1562 assert(
Data.Attributes == OMPC_unknown || (A ==
Data.Attributes) ||
1563 (A == OMPC_firstprivate &&
Data.Attributes == OMPC_lastprivate) ||
1564 (A == OMPC_lastprivate &&
Data.Attributes == OMPC_firstprivate) ||
1565 (isLoopControlVariable(D).first && A == OMPC_private));
1566 Data.Modifier = Modifier;
1567 if (A == OMPC_lastprivate &&
Data.Attributes == OMPC_firstprivate) {
1568 Data.RefExpr.setInt(
true);
1571 const bool IsLastprivate =
1572 A == OMPC_lastprivate ||
Data.Attributes == OMPC_lastprivate;
1573 Data.Attributes = A;
1574 Data.RefExpr.setPointerAndInt(E, IsLastprivate);
1575 Data.PrivateCopy = PrivateCopy;
1576 Data.AppliedToPointee = AppliedToPointee;
1578 DSAInfo &
Data = getTopOfStack().SharingMap[PrivateCopy->
getDecl()];
1579 Data.Modifier = Modifier;
1580 Data.Attributes = A;
1581 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1582 Data.PrivateCopy =
nullptr;
1583 Data.AppliedToPointee = AppliedToPointee;
1590 StringRef Name,
const AttrVec *Attrs =
nullptr,
1605 OMPReferencedVarAttr::CreateImplicit(SemaRef.
Context, OrigRef));
1612 bool RefersToCapture =
false) {
1620void DSAStackTy::addTaskgroupReductionData(
const ValueDecl *D, SourceRange SR,
1623 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1625 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1626 "Additional reduction info may be specified only for reduction items.");
1627 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1628 assert(ReductionData.ReductionRange.isInvalid() &&
1629 (getTopOfStack().
Directive == OMPD_taskgroup ||
1633 "Additional reduction info may be specified only once for reduction "
1635 ReductionData.set(BOK, SR);
1636 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1637 if (!TaskgroupReductionRef) {
1640 TaskgroupReductionRef =
1645void DSAStackTy::addTaskgroupReductionData(
const ValueDecl *D, SourceRange SR,
1646 const Expr *ReductionRef) {
1648 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1650 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1651 "Additional reduction info may be specified only for reduction items.");
1652 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1653 assert(ReductionData.ReductionRange.isInvalid() &&
1654 (getTopOfStack().
Directive == OMPD_taskgroup ||
1658 "Additional reduction info may be specified only once for reduction "
1660 ReductionData.set(ReductionRef, SR);
1661 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1662 if (!TaskgroupReductionRef) {
1665 TaskgroupReductionRef =
1670const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1672 Expr *&TaskgroupDescriptor)
const {
1674 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty.");
1675 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1676 const DSAInfo &
Data = I->SharingMap.lookup(D);
1677 if (
Data.Attributes != OMPC_reduction ||
1678 Data.Modifier != OMPC_REDUCTION_task)
1680 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1681 if (!ReductionData.ReductionOp ||
1683 return DSAVarData();
1684 SR = ReductionData.ReductionRange;
1686 assert(I->TaskgroupReductionRef &&
"taskgroup reduction reference "
1687 "expression for the descriptor is not "
1689 TaskgroupDescriptor = I->TaskgroupReductionRef;
1690 return DSAVarData(I->Directive, OMPC_reduction,
Data.RefExpr.getPointer(),
1691 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1694 return DSAVarData();
1697const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1698 const ValueDecl *D, SourceRange &SR,
const Expr *&ReductionRef,
1699 Expr *&TaskgroupDescriptor)
const {
1701 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty.");
1702 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1703 const DSAInfo &
Data = I->SharingMap.lookup(D);
1704 if (
Data.Attributes != OMPC_reduction ||
1705 Data.Modifier != OMPC_REDUCTION_task)
1707 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1708 if (!ReductionData.ReductionOp ||
1710 return DSAVarData();
1711 SR = ReductionData.ReductionRange;
1713 assert(I->TaskgroupReductionRef &&
"taskgroup reduction reference "
1714 "expression for the descriptor is not "
1716 TaskgroupDescriptor = I->TaskgroupReductionRef;
1717 return DSAVarData(I->Directive, OMPC_reduction,
Data.RefExpr.getPointer(),
1718 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1721 return DSAVarData();
1724bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I)
const {
1726 for (const_iterator E = end(); I != E; ++I) {
1727 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1730 Scope *TopScope = I->CurScope->getParent();
1731 Scope *CurScope = getCurScope();
1732 while (CurScope && CurScope != TopScope && !CurScope->
isDeclScope(D))
1734 return CurScope != TopScope;
1737 if (I->Context == DC)
1746 bool AcceptIfMutable =
true,
1747 bool *IsClassType =
nullptr) {
1749 Type =
Type.getNonReferenceType().getCanonicalType();
1750 bool IsConstant =
Type.isConstant(Context);
1751 Type = Context.getBaseElementType(
Type);
1755 if (
const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1757 RD = CTD->getTemplatedDecl();
1767 bool AcceptIfMutable =
true,
1768 bool ListItemNotVar =
false) {
1772 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1773 : IsClassType ? diag::err_omp_const_not_mutable_variable
1774 : diag::err_omp_const_variable;
1776 if (!ListItemNotVar && D) {
1777 const VarDecl *VD = dyn_cast<VarDecl>(D);
1781 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1789const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1794 auto *VD = dyn_cast<VarDecl>(D);
1795 auto TI = Threadprivates.find(D);
1796 if (TI != Threadprivates.end()) {
1797 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1798 DVar.CKind = OMPC_threadprivate;
1799 DVar.Modifier = TI->getSecond().Modifier;
1802 if (VD && VD->
hasAttr<OMPThreadPrivateDeclAttr>()) {
1805 VD->
getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1806 DVar.CKind = OMPC_threadprivate;
1807 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1814 !(VD->
hasAttr<OMPThreadPrivateDeclAttr>() &&
1821 DVar.CKind = OMPC_threadprivate;
1822 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1827 !isLoopControlVariable(D).first) {
1828 const_iterator IterTarget =
1829 std::find_if(begin(), end(), [](
const SharingMapTy &
Data) {
1832 if (IterTarget != end()) {
1833 const_iterator ParentIterTarget = IterTarget + 1;
1834 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1835 if (isOpenMPLocal(VD, Iter)) {
1839 DVar.CKind = OMPC_threadprivate;
1843 if (!isClauseParsingMode() || IterTarget != begin()) {
1844 auto DSAIter = IterTarget->SharingMap.find(D);
1845 if (DSAIter != IterTarget->SharingMap.end() &&
1847 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1848 DVar.CKind = OMPC_threadprivate;
1851 const_iterator End = end();
1853 D, std::distance(ParentIterTarget, End),
1857 IterTarget->ConstructLoc);
1858 DVar.CKind = OMPC_threadprivate;
1878 const_iterator I = begin();
1879 const_iterator EndI = end();
1880 if (FromParent && I != EndI)
1883 auto It = I->SharingMap.find(D);
1884 if (It != I->SharingMap.end()) {
1885 const DSAInfo &
Data = It->getSecond();
1886 DVar.RefExpr =
Data.RefExpr.getPointer();
1887 DVar.PrivateCopy =
Data.PrivateCopy;
1888 DVar.CKind =
Data.Attributes;
1889 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1890 DVar.DKind = I->Directive;
1891 DVar.Modifier =
Data.Modifier;
1892 DVar.AppliedToPointee =
Data.AppliedToPointee;
1897 DVar.CKind = OMPC_shared;
1904 if (SemaRef.
LangOpts.OpenMP <= 31) {
1912 DSAVarData DVarTemp = hasInnermostDSA(
1915 return C == OMPC_firstprivate ||
C == OMPC_shared;
1917 MatchesAlways, FromParent);
1918 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1921 DVar.CKind = OMPC_shared;
1928 const_iterator I = begin();
1929 const_iterator EndI = end();
1930 if (FromParent && I != EndI)
1934 auto It = I->SharingMap.find(D);
1935 if (It != I->SharingMap.end()) {
1936 const DSAInfo &
Data = It->getSecond();
1937 DVar.RefExpr =
Data.RefExpr.getPointer();
1938 DVar.PrivateCopy =
Data.PrivateCopy;
1939 DVar.CKind =
Data.Attributes;
1940 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1941 DVar.DKind = I->Directive;
1942 DVar.Modifier =
Data.Modifier;
1943 DVar.AppliedToPointee =
Data.AppliedToPointee;
1949const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1950 bool FromParent)
const {
1951 if (isStackEmpty()) {
1953 return getDSA(I, D);
1956 const_iterator StartI = begin();
1957 const_iterator EndI = end();
1958 if (FromParent && StartI != EndI)
1960 return getDSA(StartI, D);
1963const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1964 unsigned Level)
const {
1965 if (getStackSize() <= Level)
1966 return DSAVarData();
1968 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
1969 return getDSA(StartI, D);
1972const DSAStackTy::DSAVarData
1973DSAStackTy::hasDSA(ValueDecl *D,
1975 DefaultDataSharingAttributes)>
1978 bool FromParent)
const {
1982 const_iterator I = begin();
1983 const_iterator EndI = end();
1984 if (FromParent && I != EndI)
1986 for (; I != EndI; ++I) {
1987 if (!DPred(I->Directive) &&
1988 !isImplicitOrExplicitTaskingRegion(I->Directive))
1990 const_iterator NewI = I;
1991 DSAVarData DVar = getDSA(NewI, D);
1992 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1998const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1999 ValueDecl *D,
const llvm::function_ref<
bool(
OpenMPClauseKind,
bool)> CPred,
2001 bool FromParent)
const {
2005 const_iterator StartI = begin();
2006 const_iterator EndI = end();
2007 if (FromParent && StartI != EndI)
2009 if (StartI == EndI || !DPred(StartI->Directive))
2011 const_iterator NewI = StartI;
2012 DSAVarData DVar = getDSA(NewI, D);
2013 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
2018bool DSAStackTy::hasExplicitDSA(
2021 unsigned Level,
bool NotLastprivate)
const {
2022 if (getStackSize() <= Level)
2025 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2026 auto I = StackElem.SharingMap.find(D);
2027 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
2028 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
2029 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
2032 auto LI = StackElem.LCVMap.find(D);
2033 if (LI != StackElem.LCVMap.end())
2034 return CPred(OMPC_private,
false);
2038bool DSAStackTy::hasExplicitDirective(
2040 unsigned Level)
const {
2041 if (getStackSize() <= Level)
2043 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2044 return DPred(StackElem.Directive);
2047bool DSAStackTy::hasDirective(
2049 const DeclarationNameInfo &, SourceLocation)>
2051 bool FromParent)
const {
2053 size_t Skip = FromParent ? 2 : 1;
2054 for (const_iterator I = begin() + std::min(
Skip, getStackSize()), E = end();
2056 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
2062void SemaOpenMP::InitDataSharingAttributesStack() {
2063 VarDataSharingAttributesStack =
new DSAStackTy(SemaRef);
2066#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2068void SemaOpenMP::pushOpenMPFunctionRegion() {
DSAStack->pushFunction(); }
2070void SemaOpenMP::popOpenMPFunctionRegion(
const FunctionScopeInfo *OldFSI) {
2076 "Expected OpenMP device compilation.");
2082enum class FunctionEmissionStatus {
2089SemaBase::SemaDiagnosticBuilder
2093 "Expected OpenMP device compilation.");
2095 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2100 Kind = SemaDiagnosticBuilder::K_Immediate;
2111 ? SemaDiagnosticBuilder::K_Deferred
2112 : SemaDiagnosticBuilder::K_Immediate;
2116 Kind = SemaDiagnosticBuilder::K_Nop;
2119 llvm_unreachable(
"CUDADiscarded unexpected in OpenMP device compilation");
2131 "Expected OpenMP host compilation.");
2133 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2138 Kind = SemaDiagnosticBuilder::K_Immediate;
2141 Kind = SemaDiagnosticBuilder::K_Deferred;
2146 Kind = SemaDiagnosticBuilder::K_Nop;
2156 if (LO.OpenMP <= 45) {
2158 return OMPC_DEFAULTMAP_scalar;
2159 return OMPC_DEFAULTMAP_aggregate;
2162 return OMPC_DEFAULTMAP_pointer;
2164 return OMPC_DEFAULTMAP_scalar;
2165 return OMPC_DEFAULTMAP_aggregate;
2169 unsigned OpenMPCaptureLevel)
const {
2170 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2173 bool IsByRef =
true;
2179 bool IsVariableUsedInMapClause =
false;
2244 bool IsVariableAssociatedWithSection =
false;
2245 bool IsVariableItselfMapped =
false;
2247 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2249 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2250 &IsVariableItselfMapped,
2257 if (WhereFoundClauseKind != OMPC_map &&
2258 WhereFoundClauseKind != OMPC_has_device_addr)
2261 auto EI = MapExprComponents.rbegin();
2262 auto EE = MapExprComponents.rend();
2264 assert(EI != EE &&
"Invalid map expression!");
2267 EI->getAssociatedDeclaration() == D) {
2268 IsVariableUsedInMapClause =
true;
2274 if (MapExprComponents.size() == 1) {
2275 IsVariableItselfMapped =
true;
2283 auto Last = std::prev(EE);
2285 dyn_cast<UnaryOperator>(
Last->getAssociatedExpression());
2286 if ((UO && UO->getOpcode() == UO_Deref) ||
2291 IsVariableAssociatedWithSection =
true;
2302 if (IsVariableUsedInMapClause) {
2319 IsByRef = IsVariableItselfMapped ||
2325 IsByRef = (
DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2328 DSAStack->isDefaultmapCapturedByRef(
2333 return K == OMPC_reduction && !AppliedToPointee;
2341 ((IsVariableUsedInMapClause &&
2342 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2347 return K == OMPC_firstprivate ||
2348 (K == OMPC_reduction && AppliedToPointee);
2351 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2358 !((
DSAStack->getDefaultDSA() == DSA_firstprivate ||
2359 DSAStack->getDefaultDSA() == DSA_private) &&
2363 !
DSAStack->isLoopControlVariable(D, Level).first);
2380unsigned SemaOpenMP::getOpenMPNestingLevel()
const {
2381 assert(getLangOpts().OpenMP);
2382 return DSAStack->getNestingLevel();
2392 !
DSAStack->isClauseParsingMode()) ||
2405 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2408 DefaultDataSharingAttributes DefaultAttr) {
2410 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2414 if (DVarPrivate.CKind != OMPC_unknown)
2420 Expr *CaptureExpr,
bool WithInit,
2426 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2429 auto *VD = dyn_cast<VarDecl>(D);
2438 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2448 DSAStackTy::DSAVarData DVarTop =
2450 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2455 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2459 llvm::reverse(
SemaRef.FunctionScopes),
2460 CheckScopeInfo ? (
SemaRef.FunctionScopes.size() - (StopAt + 1))
2464 if (
auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2470 assert(CSI &&
"Failed to find CapturedRegionScopeInfo");
2481 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2487 if (CheckScopeInfo) {
2488 bool OpenMPFound =
false;
2489 for (
unsigned I = StopAt + 1; I > 0; --I) {
2493 if (
auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2503 if (
DSAStack->getCurrentDirective() != OMPD_unknown &&
2504 (!
DSAStack->isClauseParsingMode() ||
2505 DSAStack->getParentDirective() != OMPD_unknown)) {
2506 auto &&Info =
DSAStack->isLoopControlVariable(D);
2509 isImplicitOrExplicitTaskingRegion(
DSAStack->getCurrentDirective())) ||
2510 (VD &&
DSAStack->isForceVarCapturing()))
2511 return VD ? VD : Info.second;
2512 DSAStackTy::DSAVarData DVarTop =
2514 if (DVarTop.CKind != OMPC_unknown &&
isOpenMPPrivate(DVarTop.CKind) &&
2516 !(DVarTop.AppliedToPointee && DVarTop.CKind != OMPC_reduction)))
2523 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2531 if (VD && !VD->
hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2532 ((
DSAStack->getDefaultDSA() != DSA_none &&
2533 DSAStack->getDefaultDSA() != DSA_private &&
2534 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2535 DVarTop.CKind == OMPC_shared))
2537 auto *FD = dyn_cast<FieldDecl>(D);
2538 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2539 !DVarPrivate.PrivateCopy) {
2540 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2543 DefaultDataSharingAttributes DefaultAttr) {
2545 (DefaultAttr == DSA_firstprivate ||
2546 DefaultAttr == DSA_private);
2550 if (DVarPrivate.CKind == OMPC_unknown)
2556 if (
SemaRef.getCurrentThisType().isNull())
2570 SemaRef.CurContext->getParent(),
false);
2574 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2577 if (DVarPrivate.CKind != OMPC_unknown ||
2578 (VD && (
DSAStack->getDefaultDSA() == DSA_none ||
2579 DSAStack->getDefaultDSA() == DSA_private ||
2580 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2586void SemaOpenMP::adjustOpenMPTargetScopeIndex(
unsigned &FunctionScopesIndex,
2587 unsigned Level)
const {
2588 FunctionScopesIndex -= getOpenMPCaptureLevels(
DSAStack->getDirective(Level));
2592 assert(
getLangOpts().OpenMP &&
"OpenMP must be enabled.");
2598 assert(
getLangOpts().OpenMP &&
"OpenMP must be enabled.");
2600 DSAStack->resetPossibleLoopCounter();
2606 unsigned CapLevel)
const {
2607 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2608 if (
DSAStack->getCurrentDirective() != OMPD_unknown &&
2609 (!
DSAStack->isClauseParsingMode() ||
2610 DSAStack->getParentDirective() != OMPD_unknown)) {
2611 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2614 DefaultDataSharingAttributes DefaultAttr) {
2616 DefaultAttr == DSA_private;
2622 !
DSAStack->isLoopControlVariable(D).first)
2623 return OMPC_private;
2626 bool IsTriviallyCopyable =
2637 (IsTriviallyCopyable ||
2643 return OMPC_firstprivate;
2644 DSAStackTy::DSAVarData DVar =
DSAStack->getImplicitDSA(D, Level);
2645 if (DVar.CKind != OMPC_shared &&
2646 !
DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2647 DSAStack->addImplicitTaskFirstprivate(Level, D);
2648 return OMPC_firstprivate;
2655 DSAStack->resetPossibleLoopCounter(D);
2657 return OMPC_private;
2660 DSAStack->isLoopControlVariable(D).first) &&
2665 return OMPC_private;
2667 if (
const auto *VD = dyn_cast<VarDecl>(D)) {
2673 return OMPC_private;
2678 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2679 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2680 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2681 return OMPC_private;
2685 (
DSAStack->isClauseParsingMode() &&
2686 DSAStack->getClauseParsingMode() == OMPC_private) ||
2691 return K == OMPD_taskgroup ||
2692 ((isOpenMPParallelDirective(K) ||
2693 isOpenMPWorksharingDirective(K)) &&
2694 !isOpenMPSimdDirective(K));
2697 DSAStack->isTaskgroupReductionRef(D, Level)))
2704 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2707 for (
unsigned I =
DSAStack->getNestingLevel() + 1; I > Level; --I) {
2708 const unsigned NewLevel = I - 1;
2712 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2720 if (
DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2730 if (
DSAStack->mustBeFirstprivateAtLevel(
2732 OMPC = OMPC_firstprivate;
2736 if (OMPC != OMPC_unknown)
2738 OMPCaptureKindAttr::CreateImplicit(getASTContext(),
unsigned(OMPC)));
2742 unsigned CaptureLevel)
const {
2743 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2748 const auto *VD = dyn_cast<VarDecl>(D);
2752 Regions[CaptureLevel] != OMPD_task;
2756 unsigned CaptureLevel)
const {
2757 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2760 if (
const auto *VD = dyn_cast<VarDecl>(D)) {
2764 DSAStackTy::DSAVarData TopDVar =
2766 unsigned NumLevels =
2771 return (NumLevels == CaptureLevel + 1 &&
2772 (TopDVar.CKind != OMPC_shared ||
2773 DSAStack->getDefaultDSA() == DSA_firstprivate));
2776 DSAStackTy::DSAVarData DVar =
DSAStack->getImplicitDSA(D, Level);
2777 if (DVar.CKind != OMPC_shared)
2779 }
while (Level > 0);
2785void SemaOpenMP::DestroyDataSharingAttributesStack() {
delete DSAStack; }
2789 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2794 "Not in OpenMP declare variant scope!");
2796 OMPDeclareVariantScopes.pop_back();
2802 assert(
getLangOpts().OpenMP &&
"Expected OpenMP compilation mode.");
2803 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2807 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2810 if (!
getLangOpts().OpenMPIsTargetDevice && DevTy &&
2811 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2814 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2815 if (
getLangOpts().OpenMPIsTargetDevice && DevTy &&
2816 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2818 StringRef HostDevTy =
2820 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2821 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2822 diag::note_omp_marked_device_type_here)
2828 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2832 for (OMPDeclareVariantAttr *A :
2833 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2836 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2837 OMPDeclareTargetDeclAttr::getDeviceType(
2838 VariantFD->getMostRecentDecl());
2839 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2845 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2849 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2850 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2851 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2852 diag::note_omp_marked_device_type_here)
2860 DSAStack->push(DKind, DirName, CurScope, Loc);
2861 SemaRef.PushExpressionEvaluationContext(
2870 DSAStack->setClauseParsingMode(OMPC_unknown);
2871 SemaRef.CleanupVarDeclMarking();
2874static std::pair<ValueDecl *, bool>
2876 SourceRange &ERange,
bool AllowArraySection =
false,
2877 bool AllowAssumedSizeArray =
false, StringRef DiagType =
"");
2882 bool InscanFound =
false;
2889 if (
C->getClauseKind() != OMPC_reduction)
2892 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2894 InscanLoc = RC->getModifierLoc();
2897 if (RC->getModifier() == OMPC_REDUCTION_task) {
2907 S.
Diag(RC->getModifierLoc(),
2908 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2914 if (
C->getClauseKind() != OMPC_reduction)
2917 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2920 : RC->getModifierLoc(),
2921 diag::err_omp_inscan_reduction_expected);
2922 S.
Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2925 for (
Expr *Ref : RC->varlist()) {
2926 assert(Ref &&
"NULL expr in OpenMP reduction clause.");
2929 Expr *SimpleRefExpr = Ref;
2936 S.
Diag(Ref->getExprLoc(),
2937 diag::err_omp_reduction_not_inclusive_exclusive)
2938 << Ref->getSourceRange();
2946 ArrayRef<OMPClause *> Clauses);
2947static DeclRefExpr *
buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2952 const DSAStackTy::DSAVarData &DVar,
2953 bool IsLoopIterVar =
false);
2962 auto FinalizeLastprivate = [&](OMPLastprivateClause *Clause) {
2964 for (
Expr *DE : Clause->varlist()) {
2965 if (DE->isValueDependent() || DE->isTypeDependent()) {
2966 PrivateCopies.push_back(
nullptr);
2972 const DSAStackTy::DSAVarData DVar =
2974 if (DVar.CKind != OMPC_lastprivate) {
2977 PrivateCopies.push_back(
nullptr);
2988 SemaRef.ActOnUninitializedDecl(VDPrivate);
2990 PrivateCopies.push_back(
nullptr);
2996 Clause->setPrivateCopies(PrivateCopies);
3002 for (
Expr *RefExpr : Clause->varlist()) {
3003 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
3006 Expr *SimpleRefExpr = RefExpr;
3010 PrivateRefs.push_back(RefExpr);
3015 const DSAStackTy::DSAVarData DVar =
3017 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
3020 Clause->setPrivateRefs(PrivateRefs);
3024 for (
unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
3032 DSAStackTy::DSAVarData DVar =
3038 Expr *MapExpr =
nullptr;
3040 DSAStack->checkMappableExprComponentListsForDecl(
3046 auto MI = MapExprComponents.rbegin();
3047 auto ME = MapExprComponents.rend();
3049 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
3050 VD->getCanonicalDecl()) {
3051 MapExpr = MI->getAssociatedExpression();
3056 Diag(D.Allocator->getExprLoc(), diag::err_omp_allocator_used_in_clauses)
3061 Diag(MapExpr->getExprLoc(), diag::note_used_here)
3062 << MapExpr->getSourceRange();
3067 if (
const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
3069 if (
auto *Clause = dyn_cast<OMPLastprivateClause>(
C)) {
3070 FinalizeLastprivate(Clause);
3071 }
else if (
auto *Clause = dyn_cast<OMPNontemporalClause>(
C)) {
3072 FinalizeNontemporal(Clause);
3073 }
else if (
auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(
C)) {
3074 FinalizeAllocators(Clause);
3089 Expr *NumIterations, Sema &SemaRef,
3090 Scope *S, DSAStackTy *Stack);
3093 OMPLoopBasedDirective::HelperExprs &B,
3094 DSAStackTy *Stack) {
3096 "loop exprs were not built");
3103 auto *LC = dyn_cast<OMPLinearClause>(
C);
3107 B.NumIterations, SemaRef,
3117class VarDeclFilterCCC final :
public CorrectionCandidateCallback {
3122 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3123 bool ValidateCandidate(
const TypoCorrection &Candidate)
override {
3125 if (
const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3133 std::unique_ptr<CorrectionCandidateCallback> clone()
override {
3134 return std::make_unique<VarDeclFilterCCC>(*
this);
3138class VarOrFuncDeclFilterCCC final :
public CorrectionCandidateCallback {
3143 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3144 bool ValidateCandidate(
const TypoCorrection &Candidate)
override {
3154 std::unique_ptr<CorrectionCandidateCallback> clone()
override {
3155 return std::make_unique<VarOrFuncDeclFilterCCC>(*
this);
3168 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
3177 VarDeclFilterCCC CCC(
SemaRef);
3183 SemaRef.PDiag(Lookup.
empty() ? diag::err_undeclared_var_use_suggest
3184 : diag::err_omp_expected_var_arg_suggest)
3186 VD = Corrected.getCorrectionDeclAs<
VarDecl>();
3189 : diag::err_omp_expected_var_arg)
3202 if ((Kind == OMPD_threadprivate || Kind == OMPD_groupprivate) &&
3204 Diag(Id.
getLoc(), diag::err_omp_global_var_arg)
3205 << getOpenMPDirectiveName(Kind, OMPVersion) << !VD->
isStaticLocal();
3209 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3220 !
SemaRef.getCurLexicalContext()->isTranslationUnit()) {
3222 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3226 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3237 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3241 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3250 (!
SemaRef.getCurLexicalContext()->isFileContext() ||
3251 !
SemaRef.getCurLexicalContext()->Encloses(
3254 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3258 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3267 !
SemaRef.isDeclInScope(ND,
SemaRef.getCurLexicalContext(), CurScope)) {
3269 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3273 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3281 if ((Kind == OMPD_threadprivate && VD->
isUsed() &&
3283 (Kind == OMPD_groupprivate && VD->
isUsed())) {
3285 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3300 SemaRef.CurContext->addDecl(D);
3310 Diag(Loc, diag::err_omp_unexpected_directive)
3311 << getOpenMPDirectiveName(OMPD_groupprivate,
getLangOpts().OpenMP);
3315 SemaRef.CurContext->addDecl(D);
3322class LocalVarRefChecker final
3328 if (
const auto *VD = dyn_cast<VarDecl>(E->
getDecl())) {
3331 diag::err_omp_local_var_in_threadprivate_init)
3333 SemaRef.Diag(VD->
getLocation(), diag::note_defined_here)
3340 bool VisitStmt(
const Stmt *S) {
3341 for (
const Stmt *Child : S->
children()) {
3342 if (Child && Visit(Child))
3347 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3351OMPThreadPrivateDecl *
3356 for (
Expr *RefExpr : VarList) {
3374 if (
SemaRef.RequireCompleteType(
3375 ILoc, VD->
getType(), diag::err_omp_threadprivate_incomplete_type)) {
3383 Diag(ILoc, diag::err_omp_ref_type_arg)
3384 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion)
3389 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3397 !(VD->
hasAttr<OMPThreadPrivateDeclAttr>() &&
3402 Diag(ILoc, diag::err_omp_var_thread_local)
3407 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3415 LocalVarRefChecker Checker(
SemaRef);
3416 if (Checker.Visit(
Init))
3420 Vars.push_back(RefExpr);
3421 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3422 VD->
addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3425 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3428 if (!Vars.empty()) {
3441 for (
Expr *RefExpr : VarList) {
3459 if (
SemaRef.RequireCompleteType(
3460 ILoc, VD->
getType(), diag::err_omp_groupprivate_incomplete_type)) {
3466 Diag(ILoc, diag::err_omp_ref_type_arg)
3467 << getOpenMPDirectiveName(OMPD_groupprivate) << VD->
getType();
3471 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3479 Diag(ILoc, diag::err_omp_groupprivate_with_initializer)
3484 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3489 Vars.push_back(RefExpr);
3490 DSAStack->addDSA(VD, DE, OMPC_groupprivate);
3491 VD->
addAttr(OMPGroupPrivateDeclAttr::CreateImplicit(Context,
3494 ML->DeclarationMarkedOpenMPGroupPrivate(VD);
3497 if (!Vars.empty()) {
3505static OMPAllocateDeclAttr::AllocatorTypeTy
3508 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3512 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3513 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3514 llvm::FoldingSetNodeID AEId;
3517 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3518 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
3519 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3520 llvm::FoldingSetNodeID DAEId;
3523 if (AEId == DAEId) {
3524 AllocatorKindRes = AllocatorKind;
3528 return AllocatorKindRes;
3533 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
Expr *Allocator) {
3534 if (!VD->
hasAttr<OMPAllocateDeclAttr>())
3536 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
3537 Expr *PrevAllocator = A->getAllocator();
3538 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3540 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3541 if (AllocatorsMatch &&
3542 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3543 Allocator && PrevAllocator) {
3546 llvm::FoldingSetNodeID AEId, PAEId;
3549 AllocatorsMatch = AEId == PAEId;
3551 if (!AllocatorsMatch) {
3553 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3557 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3559 PrevAllocator->printPretty(PrevAllocatorStream,
nullptr,
3567 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3569 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3570 S.
Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3571 << (Allocator ? 1 : 0) << AllocatorStream.str()
3572 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3574 S.
Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3575 << PrevAllocatorRange;
3583 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3585 if (VD->
hasAttr<OMPAllocateDeclAttr>())
3598 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.
Context, AllocatorKind,
3599 Allocator, Alignment, SR);
3602 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3608 assert(Clauses.size() <= 2 &&
"Expected at most two clauses.");
3609 Expr *Alignment =
nullptr;
3610 Expr *Allocator =
nullptr;
3611 if (Clauses.empty()) {
3617 !
DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3618 SemaRef.targetDiag(Loc, diag::err_expected_allocator_clause);
3621 if (
const auto *AC = dyn_cast<OMPAllocatorClause>(
C))
3622 Allocator = AC->getAllocator();
3623 else if (
const auto *AC = dyn_cast<OMPAlignClause>(
C))
3624 Alignment = AC->getAlignment();
3626 llvm_unreachable(
"Unexpected clause on allocate directive");
3628 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3631 for (
Expr *RefExpr : VarList) {
3637 VD->
hasAttr<OMPThreadPrivateDeclAttr>() ||
3645 AllocatorKind, Allocator))
3653 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3655 diag::err_omp_expected_predefined_allocator)
3660 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3666 Vars.push_back(RefExpr);
3673 Owner =
SemaRef.getCurLexicalContext();
3684 if (!
SemaRef.CurContext->isFileContext()) {
3685 Diag(Loc, diag::err_omp_invalid_scope) <<
"requires";
3689 SemaRef.CurContext->addDecl(D);
3699 bool SkippedClauses) {
3700 if (!SkippedClauses && Assumptions.empty()) {
3702 Diag(Loc, diag::err_omp_no_clause_for_directive)
3703 << llvm::omp::getAllAssumeClauseOptions()
3704 << llvm::omp::getOpenMPDirectiveName(DKind, OMPVersion);
3708 OMPAssumeAttr::Create(
getASTContext(), llvm::join(Assumptions,
","), Loc);
3709 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3710 OMPAssumeScoped.push_back(AA);
3715 if (Assumptions.empty())
3718 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3719 "Unexpected omp assumption directive!");
3720 OMPAssumeGlobal.push_back(AA);
3727 auto *Ctx =
SemaRef.CurContext;
3728 while (Ctx->getLexicalParent())
3729 Ctx = Ctx->getLexicalParent();
3730 DeclContexts.push_back(Ctx);
3731 while (!DeclContexts.empty()) {
3733 for (
auto *SubDC : DC->
decls()) {
3734 if (SubDC->isInvalidDecl())
3736 if (
auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3737 DeclContexts.push_back(CTD->getTemplatedDecl());
3738 llvm::append_range(DeclContexts, CTD->specializations());
3741 if (
auto *DC = dyn_cast<DeclContext>(SubDC))
3742 DeclContexts.push_back(DC);
3743 if (
auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3753 OMPAssumeScoped.pop_back();
3774 DSAStack->getEncounteredTargetLocs();
3776 if (!TargetLocations.empty() || !AtomicLoc.
isInvalid()) {
3777 for (
const OMPClause *CNew : ClauseList) {
3783 Diag(Loc, diag::err_omp_directive_before_requires)
3786 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3791 Diag(Loc, diag::err_omp_directive_before_requires)
3793 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3799 if (!
DSAStack->hasDuplicateRequiresClause(ClauseList))
3807 const DSAStackTy::DSAVarData &DVar,
3808 bool IsLoopIterVar) {
3810 SemaRef.
Diag(DVar.RefExpr->
getExprLoc(), diag::note_omp_explicit_dsa)
3815 PDSA_StaticMemberShared,
3816 PDSA_StaticLocalVarShared,
3817 PDSA_LoopIterVarPrivate,
3818 PDSA_LoopIterVarLinear,
3819 PDSA_LoopIterVarLastprivate,
3820 PDSA_ConstVarShared,
3821 PDSA_GlobalVarShared,
3822 PDSA_TaskVarFirstprivate,
3823 PDSA_LocalVarPrivate,
3825 } Reason = PDSA_Implicit;
3826 bool ReportHint =
false;
3828 auto *VD = dyn_cast<VarDecl>(D);
3829 if (IsLoopIterVar) {
3830 if (DVar.CKind == OMPC_private)
3831 Reason = PDSA_LoopIterVarPrivate;
3832 else if (DVar.CKind == OMPC_lastprivate)
3833 Reason = PDSA_LoopIterVarLastprivate;
3835 Reason = PDSA_LoopIterVarLinear;
3837 DVar.CKind == OMPC_firstprivate) {
3838 Reason = PDSA_TaskVarFirstprivate;
3839 ReportLoc = DVar.ImplicitDSALoc;
3841 Reason = PDSA_StaticLocalVarShared;
3843 Reason = PDSA_StaticMemberShared;
3845 Reason = PDSA_GlobalVarShared;
3847 Reason = PDSA_ConstVarShared;
3848 else if (VD && VD->
isLocalVarDecl() && DVar.CKind == OMPC_private) {
3850 Reason = PDSA_LocalVarPrivate;
3852 if (Reason != PDSA_Implicit) {
3853 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
3854 SemaRef.
Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3855 << Reason << ReportHint
3856 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
3857 }
else if (DVar.ImplicitDSALoc.
isValid()) {
3858 SemaRef.
Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3865 bool IsAggregateOrDeclareTarget) {
3868 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3869 case OMPC_DEFAULTMAP_MODIFIER_storage:
3870 Kind = OMPC_MAP_alloc;
3872 case OMPC_DEFAULTMAP_MODIFIER_to:
3875 case OMPC_DEFAULTMAP_MODIFIER_from:
3876 Kind = OMPC_MAP_from;
3878 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3879 Kind = OMPC_MAP_tofrom;
3881 case OMPC_DEFAULTMAP_MODIFIER_present:
3887 Kind = OMPC_MAP_alloc;
3889 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3890 case OMPC_DEFAULTMAP_MODIFIER_private:
3892 llvm_unreachable(
"Unexpected defaultmap implicit behavior");
3893 case OMPC_DEFAULTMAP_MODIFIER_none:
3894 case OMPC_DEFAULTMAP_MODIFIER_default:
3899 if (IsAggregateOrDeclareTarget) {
3900 Kind = OMPC_MAP_tofrom;
3903 llvm_unreachable(
"Unexpected defaultmap implicit behavior");
3910struct VariableImplicitInfo {
3915 llvm::SetVector<Expr *> Firstprivates;
3916 llvm::SetVector<Expr *> Mappings[DefaultmapKindNum][MapKindNum];
3917 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
3918 MapModifiers[DefaultmapKindNum];
3921class DSAAttrChecker final :
public StmtVisitor<DSAAttrChecker, void> {
3925 bool ErrorFound =
false;
3926 bool TryCaptureCXXThisMembers =
false;
3927 CapturedStmt *CS =
nullptr;
3929 VariableImplicitInfo ImpInfo;
3931 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3933 void VisitSubCaptures(OMPExecutableDirective *S) {
3935 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3937 if (S->getDirectiveKind() == OMPD_atomic ||
3938 S->getDirectiveKind() == OMPD_critical ||
3939 S->getDirectiveKind() == OMPD_section ||
3940 S->getDirectiveKind() == OMPD_master ||
3941 S->getDirectiveKind() == OMPD_masked ||
3942 S->getDirectiveKind() == OMPD_scope ||
3943 S->getDirectiveKind() == OMPD_assume ||
3945 Visit(S->getAssociatedStmt());
3948 visitSubCaptures(S->getInnermostCapturedStmt());
3951 if (TryCaptureCXXThisMembers ||
3953 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3954 [](
const CapturedStmt::Capture &
C) {
3955 return C.capturesThis();
3957 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3958 TryCaptureCXXThisMembers =
true;
3959 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3960 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3966 for (OMPClause *
C : S->clauses())
3967 if (
auto *FC = dyn_cast<OMPFirstprivateClause>(
C)) {
3968 for (Expr *Ref : FC->varlist())
3975 void VisitDeclRefExpr(DeclRefExpr *E) {
3981 if (
auto *VD = dyn_cast<VarDecl>(E->
getDecl())) {
3984 !Stack->getTopDSA(VD,
false).RefExpr &&
3985 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3986 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3987 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3988 Visit(CED->getInit());
3994 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3999 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
4000 !Stack->isImplicitTaskFirstprivate(VD))
4003 if (Stack->isUsesAllocatorsDecl(VD))
4006 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD,
false);
4008 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
4012 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
4013 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
4015 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
4016 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
4017 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
4018 !Stack->isImplicitTaskFirstprivate(VD))
4026 if (DVar.CKind == OMPC_unknown &&
4027 (Stack->getDefaultDSA() == DSA_none ||
4028 Stack->getDefaultDSA() == DSA_private ||
4029 Stack->getDefaultDSA() == DSA_firstprivate) &&
4030 isImplicitOrExplicitTaskingRegion(DKind) &&
4031 VarsWithInheritedDSA.count(VD) == 0) {
4032 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
4033 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
4034 Stack->getDefaultDSA() == DSA_private)) {
4035 DSAStackTy::DSAVarData DVar =
4036 Stack->getImplicitDSA(VD,
false);
4037 InheritedDSA = DVar.CKind == OMPC_unknown;
4040 VarsWithInheritedDSA[VD] = E;
4041 if (Stack->getDefaultDSA() == DSA_none)
4056 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
4057 OMPC_DEFAULTMAP_MODIFIER_none;
4058 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
4059 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
4063 if (!Stack->checkMappableExprComponentListsForDecl(
4068 auto MI = MapExprComponents.rbegin();
4069 auto ME = MapExprComponents.rend();
4070 return MI != ME && MI->getAssociatedDeclaration() == VD;
4072 VarsWithInheritedDSA[VD] = E;
4078 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
4079 OMPC_DEFAULTMAP_MODIFIER_present;
4080 if (IsModifierPresent) {
4081 if (!llvm::is_contained(ImpInfo.MapModifiers[ClauseKind],
4082 OMPC_MAP_MODIFIER_present)) {
4083 ImpInfo.MapModifiers[ClauseKind].push_back(
4084 OMPC_MAP_MODIFIER_present);
4090 !Stack->isLoopControlVariable(VD).first) {
4091 if (!Stack->checkMappableExprComponentListsForDecl(
4096 if (SemaRef.LangOpts.OpenMP >= 50)
4097 return !StackComponents.empty();
4100 return StackComponents.size() == 1 ||
4102 llvm::drop_begin(llvm::reverse(StackComponents)),
4103 [](const OMPClauseMappableExprCommon::
4104 MappableComponent &MC) {
4105 return MC.getAssociatedDeclaration() ==
4107 (isa<ArraySectionExpr>(
4108 MC.getAssociatedExpression()) ||
4109 isa<OMPArrayShapingExpr>(
4110 MC.getAssociatedExpression()) ||
4111 isa<ArraySubscriptExpr>(
4112 MC.getAssociatedExpression()));
4115 bool IsFirstprivate =
false;
4117 if (
const auto *RD =
4119 IsFirstprivate = RD->isLambda();
4121 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
4122 if (IsFirstprivate) {
4123 ImpInfo.Firstprivates.insert(E);
4126 Stack->getDefaultmapModifier(ClauseKind);
4127 if (M == OMPC_DEFAULTMAP_MODIFIER_private) {
4128 ImpInfo.Privates.insert(E);
4131 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
4132 ImpInfo.Mappings[ClauseKind][
Kind].insert(E);
4143 DVar = Stack->hasInnermostDSA(
4146 return C == OMPC_reduction && !AppliedToPointee;
4155 SemaRef.
Diag(ELoc, diag::err_omp_reduction_in_task);
4161 DVar = Stack->getImplicitDSA(VD,
false);
4163 (((Stack->getDefaultDSA() == DSA_firstprivate &&
4164 DVar.CKind == OMPC_firstprivate) ||
4165 (Stack->getDefaultDSA() == DSA_private &&
4166 DVar.CKind == OMPC_private)) &&
4168 !Stack->isLoopControlVariable(VD).first) {
4169 if (Stack->getDefaultDSA() == DSA_private)
4170 ImpInfo.Privates.insert(E);
4172 ImpInfo.Firstprivates.insert(E);
4179 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
4180 Stack->addToParentTargetRegionLinkGlobals(E);
4185 void VisitMemberExpr(MemberExpr *E) {
4193 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD,
false);
4196 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
4200 !Stack->isLoopControlVariable(FD).first &&
4201 !Stack->checkMappableExprComponentListsForDecl(
4206 return isa<CXXThisExpr>(
4208 StackComponents.back().getAssociatedExpression())
4220 if (Stack->isClassPreviouslyMapped(TE->getType()))
4224 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4229 ImpInfo.Mappings[ClauseKind][
Kind].insert(E);
4238 DVar = Stack->hasInnermostDSA(
4241 return C == OMPC_reduction && !AppliedToPointee;
4250 SemaRef.
Diag(ELoc, diag::err_omp_reduction_in_task);
4256 DVar = Stack->getImplicitDSA(FD,
false);
4258 !Stack->isLoopControlVariable(FD).first) {
4263 if (DVar.CKind != OMPC_unknown)
4264 ImpInfo.Firstprivates.insert(E);
4274 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4275 if (!Stack->checkMappableExprComponentListsForDecl(
4281 auto CCI = CurComponents.rbegin();
4282 auto CCE = CurComponents.rend();
4283 for (const auto &SC : llvm::reverse(StackComponents)) {
4285 if (CCI->getAssociatedExpression()->getStmtClass() !=
4286 SC.getAssociatedExpression()->getStmtClass())
4287 if (!((isa<ArraySectionExpr>(
4288 SC.getAssociatedExpression()) ||
4289 isa<OMPArrayShapingExpr>(
4290 SC.getAssociatedExpression())) &&
4291 isa<ArraySubscriptExpr>(
4292 CCI->getAssociatedExpression())))
4295 const Decl *CCD = CCI->getAssociatedDeclaration();
4296 const Decl *SCD = SC.getAssociatedDeclaration();
4297 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4298 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4301 std::advance(CCI, 1);
4309 }
else if (!TryCaptureCXXThisMembers) {
4313 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4314 for (OMPClause *
C : S->clauses()) {
4317 if (isa_and_nonnull<OMPPrivateClause>(
C))
4325 for (Stmt *CC :
C->children()) {
4332 VisitSubCaptures(S);
4335 void VisitOMPCanonicalLoopNestTransformationDirective(
4336 OMPCanonicalLoopNestTransformationDirective *S) {
4341 void VisitCallExpr(CallExpr *S) {
4350 auto *CI =
Callee->IgnoreParenImpCasts();
4351 if (
auto *CE = dyn_cast<MemberExpr>(CI))
4352 Visit(CE->getBase());
4353 else if (
auto *CE = dyn_cast<DeclRefExpr>(CI))
4357 void VisitStmt(Stmt *S) {
4367 void visitSubCaptures(CapturedStmt *S) {
4368 for (
const CapturedStmt::Capture &Cap : S->
captures()) {
4369 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4371 VarDecl *VD = Cap.getCapturedVar();
4375 Stack->checkMappableExprComponentListsForDecl(
4382 Cap.getLocation(),
true);
4386 bool isErrorFound()
const {
return ErrorFound; }
4387 const VariableImplicitInfo &getImplicitInfo()
const {
return ImpInfo; }
4389 return VarsWithInheritedDSA;
4392 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4393 : Stack(S), SemaRef(SemaRef), ErrorFound(
false), CS(CS) {
4394 DKind = S->getCurrentDirective();
4397 for (DeclRefExpr *E : Stack->getLinkGlobals())
4409 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4411 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4413 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4415 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4417 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4418 Stack->handleConstructTrait(Traits, ScopeEntry);
4421static SmallVector<SemaOpenMP::CapturedParamNameType>
4425 Context.getIntTypeForBitwidth(32, 1).
withConst();
4429 std::make_pair(
".global_tid.", KmpInt32PtrTy),
4430 std::make_pair(
".bound_tid.", KmpInt32PtrTy),
4432 if (LoopBoundSharing) {
4434 Params.push_back(std::make_pair(
".previous.lb.", KmpSizeTy));
4435 Params.push_back(std::make_pair(
".previous.ub.", KmpSizeTy));
4439 Params.push_back(std::make_pair(StringRef(),
QualType()));
4443static SmallVector<SemaOpenMP::CapturedParamNameType>
4448static SmallVector<SemaOpenMP::CapturedParamNameType>
4458 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4460 std::make_pair(
".global_tid.", KmpInt32Ty),
4461 std::make_pair(
".part_id.", KmpInt32PtrTy),
4462 std::make_pair(
".privates.", VoidPtrTy),
4465 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4466 std::make_pair(
".task_t.", Context.VoidPtrTy.withConst()),
4467 std::make_pair(StringRef(),
QualType())
4472static SmallVector<SemaOpenMP::CapturedParamNameType>
4478 Params.push_back(std::make_pair(StringRef(
"dyn_ptr"), VoidPtrTy));
4481 Params.push_back(std::make_pair(StringRef(),
QualType()));
4485static SmallVector<SemaOpenMP::CapturedParamNameType>
4488 std::make_pair(StringRef(),
QualType())
4493static SmallVector<SemaOpenMP::CapturedParamNameType>
4497 Context.getIntTypeForBitwidth(32, 1).
withConst();
4499 Context.getIntTypeForBitwidth(64, 0).
withConst();
4501 Context.getIntTypeForBitwidth(64, 1).
withConst();
4508 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4510 std::make_pair(
".global_tid.", KmpInt32Ty),
4511 std::make_pair(
".part_id.", KmpInt32PtrTy),
4512 std::make_pair(
".privates.", VoidPtrTy),
4515 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4516 std::make_pair(
".task_t.", Context.VoidPtrTy.withConst()),
4517 std::make_pair(
".lb.", KmpUInt64Ty),
4518 std::make_pair(
".ub.", KmpUInt64Ty),
4519 std::make_pair(
".st.", KmpInt64Ty),
4520 std::make_pair(
".liter.", KmpInt32Ty),
4521 std::make_pair(
".reductions.", VoidPtrTy),
4522 std::make_pair(StringRef(),
QualType())
4535 CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
4536 SemaRef.
getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
4539 for (
auto [Level, RKind] : llvm::enumerate(Regions)) {
4574 case OMPD_metadirective:
4577 llvm_unreachable(
"Unexpected capture region");
4594 case OMPD_interchange:
4608int SemaOpenMP::getNumberOfConstructScopes(
unsigned Level)
const {
4609 return getOpenMPCaptureLevels(
DSAStack->getDirective(Level));
4615 return CaptureRegions.size();
4619 Expr *CaptureExpr,
bool WithInit,
4621 bool AsExpression) {
4622 assert(CaptureExpr);
4628 Ty =
C.getLValueReferenceType(Ty);
4630 Ty =
C.getPointerType(Ty);
4642 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(
C));
4692class CaptureRegionUnwinderRAII {
4699 CaptureRegionUnwinderRAII(Sema &S,
bool &ErrorFound,
4701 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4702 ~CaptureRegionUnwinderRAII() {
4705 while (--ThisCaptureLevel >= 0)
4715 if (!
SemaRef.CurContext->isDependentContext() &&
4718 DSAStack->getCurrentDirective()))) {
4720 if (
const auto *RD =
Type.getCanonicalType()
4721 .getNonReferenceType()
4723 bool SavedForceCaptureByReferenceInTargetExecutable =
4724 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4725 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4727 if (RD->isLambda()) {
4728 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4730 RD->getCaptureFields(Captures, ThisCapture);
4737 SemaRef.MarkVariableReferenced(LC.getLocation(), VD);
4738 }
else if (LC.getCaptureKind() ==
LCK_This) {
4741 ThisTy, ThisCapture->
getType()))
4742 SemaRef.CheckCXXThisCapture(LC.getLocation());
4746 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4747 SavedForceCaptureByReferenceInTargetExecutable);
4754 const OMPOrderedClause *Ordered =
nullptr;
4757 for (
const OMPClause *Clause : Clauses) {
4758 if (Clause->getClauseKind() == OMPC_ordered)
4760 else if (Clause->getClauseKind() == OMPC_order) {
4762 if (Order->
getKind() != OMPC_ORDER_concurrent)
4765 if (Ordered && Order)
4769 if (Ordered && Order) {
4771 diag::err_omp_simple_clause_incompatible_with_ordered)
4774 <<
SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4775 S.
Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4776 << 0 <<
SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4789 bool ErrorFound =
false;
4790 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4799 OMPOrderedClause *OC =
nullptr;
4800 OMPScheduleClause *SC =
nullptr;
4807 DSAStack->getCurrentDirective() == OMPD_target) &&
4808 Clause->getClauseKind() == OMPC_in_reduction) {
4812 for (
Expr *E : IRC->taskgroup_descriptors())
4814 SemaRef.MarkDeclarationsReferencedInExpr(E);
4817 Clause->getClauseKind() == OMPC_copyprivate ||
4820 Clause->getClauseKind() == OMPC_copyin)) {
4821 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4824 if (
auto *E = cast_or_null<Expr>(VarRef)) {
4825 SemaRef.MarkDeclarationsReferencedInExpr(E);
4828 DSAStack->setForceVarCapturing(
false);
4829 }
else if (CaptureRegions.size() > 1 ||
4830 CaptureRegions.back() != OMPD_unknown) {
4834 if (
Expr *E =
C->getPostUpdateExpr())
4835 SemaRef.MarkDeclarationsReferencedInExpr(E);
4838 if (Clause->getClauseKind() == OMPC_schedule)
4840 else if (Clause->getClauseKind() == OMPC_ordered)
4842 else if (Clause->getClauseKind() == OMPC_linear)
4847 SemaRef.MarkDeclarationsReferencedInExpr(E);
4852 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4853 SC->getSecondScheduleModifier() ==
4854 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4856 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4857 ? SC->getFirstScheduleModifierLoc()
4858 : SC->getSecondScheduleModifierLoc(),
4859 diag::err_omp_simple_clause_incompatible_with_ordered)
4862 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4863 <<
SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4871 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4872 for (
const OMPLinearClause *
C : LCs) {
4873 Diag(
C->getBeginLoc(), diag::err_omp_linear_ordered)
4874 <<
SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4880 OC->getNumForLoops()) {
4882 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4883 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(), OMPVersion);
4890 unsigned CompletedRegions = 0;
4895 if (ThisCaptureRegion != OMPD_unknown) {
4903 if (CaptureRegion == ThisCaptureRegion ||
4904 CaptureRegion == OMPD_unknown) {
4905 if (
auto *DS = cast_or_null<DeclStmt>(
C->getPreInitStmt())) {
4906 for (
Decl *D : DS->decls())
4913 if (ThisCaptureRegion == OMPD_target) {
4917 if (
const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(
C)) {
4918 for (
unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4922 SemaRef.MarkDeclarationsReferencedInExpr(E);
4928 if (ThisCaptureRegion == OMPD_parallel) {
4932 if (
auto *RC = dyn_cast<OMPReductionClause>(
C)) {
4933 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4935 for (
Expr *E : RC->copy_array_temps())
4937 SemaRef.MarkDeclarationsReferencedInExpr(E);
4939 if (
auto *AC = dyn_cast<OMPAlignedClause>(
C)) {
4940 for (
Expr *E : AC->varlist())
4941 SemaRef.MarkDeclarationsReferencedInExpr(E);
4945 if (++CompletedRegions == CaptureRegions.size())
4947 SR =
SemaRef.ActOnCapturedRegionEnd(SR.
get());
4956 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4959 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4960 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4963 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
4964 SemaRef.
Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4965 << getOpenMPDirectiveName(CancelRegion, OMPVersion);
4975 if (!Stack->getCurScope())
4980 bool NestingProhibited =
false;
4981 bool CloseNesting =
true;
4982 bool OrphanSeen =
false;
4985 ShouldBeInParallelRegion,
4986 ShouldBeInOrderedRegion,
4987 ShouldBeInTargetRegion,
4988 ShouldBeInTeamsRegion,
4989 ShouldBeInLoopSimdRegion,
4990 } Recommend = NoRecommend;
4994 getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
4996 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
4998 if (OMPVersion >= 50 && Stack->isParentOrderConcurrent() &&
5001 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_order)
5002 << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5006 ((OMPVersion <= 45 && CurrentRegion != OMPD_ordered) ||
5007 (OMPVersion >= 50 && CurrentRegion != OMPD_ordered &&
5008 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
5009 CurrentRegion != OMPD_scan))) {
5022 SemaRef.
Diag(StartLoc, (CurrentRegion != OMPD_simd)
5023 ? diag::err_omp_prohibited_region_simd
5024 : diag::warn_omp_nesting_simd)
5025 << (OMPVersion >= 50 ? 1 : 0);
5026 return CurrentRegion != OMPD_simd;
5028 if (EnclosingConstruct == OMPD_atomic) {
5031 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
5034 if (CurrentRegion == OMPD_section) {
5039 if (EnclosingConstruct != OMPD_sections) {
5040 SemaRef.
Diag(StartLoc, diag::err_omp_orphaned_section_directive)
5041 << (ParentRegion != OMPD_unknown)
5042 << getOpenMPDirectiveName(ParentRegion, OMPVersion);
5050 if (ParentRegion == OMPD_unknown &&
5052 CurrentRegion != OMPD_cancellation_point &&
5053 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
5057 if (OMPVersion >= 50 && CurrentRegion == OMPD_loop &&
5058 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
5060 EnclosingConstruct == OMPD_loop)) {
5061 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
5062 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region)
5063 <<
true << getOpenMPDirectiveName(ParentRegion, OMPVersion)
5064 << ErrorMsgNumber << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5067 if (CurrentRegion == OMPD_cancellation_point ||
5068 CurrentRegion == OMPD_cancel) {
5081 if (CancelRegion == OMPD_taskgroup) {
5083 EnclosingConstruct != OMPD_task &&
5084 (OMPVersion < 50 || EnclosingConstruct != OMPD_taskloop);
5085 }
else if (CancelRegion == OMPD_sections) {
5086 NestingProhibited = EnclosingConstruct != OMPD_section &&
5087 EnclosingConstruct != OMPD_sections;
5089 NestingProhibited = CancelRegion != Leafs.back();
5091 OrphanSeen = ParentRegion == OMPD_unknown;
5092 }
else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5099 }
else if (CurrentRegion == OMPD_critical && CurrentName.
getName()) {
5105 bool DeadLock = Stack->hasDirective(
5109 if (K == OMPD_critical && DNI.
getName() == CurrentName.
getName()) {
5110 PreviousCriticalLoc = Loc;
5117 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name)
5119 if (PreviousCriticalLoc.
isValid())
5120 SemaRef.
Diag(PreviousCriticalLoc,
5121 diag::note_omp_previous_critical_region);
5124 }
else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
5134 llvm::is_contained({OMPD_masked, OMPD_master,
5135 OMPD_critical, OMPD_ordered},
5136 EnclosingConstruct);
5147 llvm::is_contained({OMPD_masked, OMPD_master,
5148 OMPD_critical, OMPD_ordered},
5149 EnclosingConstruct);
5150 Recommend = ShouldBeInParallelRegion;
5151 }
else if (CurrentRegion == OMPD_ordered) {
5160 NestingProhibited = EnclosingConstruct == OMPD_critical ||
5163 Stack->isParentOrderedRegion());
5164 Recommend = ShouldBeInOrderedRegion;
5170 (OMPVersion <= 45 && EnclosingConstruct != OMPD_target) ||
5171 (OMPVersion >= 50 && EnclosingConstruct != OMPD_unknown &&
5172 EnclosingConstruct != OMPD_target);
5173 OrphanSeen = ParentRegion == OMPD_unknown;
5174 Recommend = ShouldBeInTargetRegion;
5175 }
else if (CurrentRegion == OMPD_scan) {
5176 if (OMPVersion >= 50) {
5181 NestingProhibited = !llvm::is_contained(
5182 {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
5184 NestingProhibited =
true;
5186 OrphanSeen = ParentRegion == OMPD_unknown;
5187 Recommend = ShouldBeInLoopSimdRegion;
5191 EnclosingConstruct == OMPD_teams) {
5203 CurrentRegion != OMPD_loop &&
5205 CurrentRegion == OMPD_atomic);
5206 Recommend = ShouldBeInParallelRegion;
5208 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5214 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5215 Recommend = ShouldBeInTeamsRegion;
5221 NestingProhibited = EnclosingConstruct != OMPD_teams;
5222 Recommend = ShouldBeInTeamsRegion;
5224 if (!NestingProhibited &&
5231 NestingProhibited = Stack->hasDirective(
5235 OffendingRegion = K;
5241 CloseNesting =
false;
5243 if (NestingProhibited) {
5245 SemaRef.
Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5246 << getOpenMPDirectiveName(CurrentRegion, OMPVersion) << Recommend;
5248 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region)
5249 << CloseNesting << getOpenMPDirectiveName(OffendingRegion, OMPVersion)
5250 << Recommend << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5264 bool ErrorFound =
false;
5265 unsigned NamedModifiersNumber = 0;
5266 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5267 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5271 if (
const auto *IC = dyn_cast_or_null<OMPIfClause>(
C)) {
5275 auto &FNM = FoundNameModifiers[CurNM];
5277 S.
Diag(
C->getBeginLoc(), diag::err_omp_more_one_clause)
5278 << getOpenMPDirectiveName(Kind, OMPVersion)
5280 << getOpenMPDirectiveName(CurNM, OMPVersion);
5282 }
else if (CurNM != OMPD_unknown) {
5283 NameModifierLoc.push_back(IC->getNameModifierLoc());
5284 ++NamedModifiersNumber;
5287 if (CurNM == OMPD_unknown)
5293 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5294 S.
Diag(IC->getNameModifierLoc(),
5295 diag::err_omp_wrong_if_directive_name_modifier)
5296 << getOpenMPDirectiveName(CurNM, OMPVersion)
5297 << getOpenMPDirectiveName(Kind, OMPVersion);
5304 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5305 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5306 S.
Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5307 diag::err_omp_no_more_if_clause);
5310 std::string Sep(
", ");
5311 unsigned AllowedCnt = 0;
5312 unsigned TotalAllowedNum =
5313 AllowedNameModifiers.size() - NamedModifiersNumber;
5314 for (
unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5317 if (!FoundNameModifiers[NM]) {
5319 Values += getOpenMPDirectiveName(NM, OMPVersion);
5321 if (AllowedCnt + 2 == TotalAllowedNum)
5323 else if (AllowedCnt + 1 != TotalAllowedNum)
5328 S.
Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5329 diag::err_omp_unnamed_if_clause)
5330 << (TotalAllowedNum > 1) << Values;
5333 S.
Diag(Loc, diag::note_omp_previous_named_if_clause);
5340static std::pair<ValueDecl *, bool>
5343 bool AllowAssumedSizeArray, StringRef DiagType) {
5346 return std::make_pair(
nullptr,
true);
5372 } IsArrayExpr = NoArrayExpr;
5373 if (AllowArraySection) {
5374 if (
auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5375 Expr *
Base = ASE->getBase()->IgnoreParenImpCasts();
5376 while (
auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
5377 Base = TempASE->getBase()->IgnoreParenImpCasts();
5380 }
else if (
auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5381 Expr *
Base = OASE->getBase()->IgnoreParenImpCasts();
5382 if (S.
getLangOpts().OpenMP >= 60 && !AllowAssumedSizeArray &&
5383 OASE->getColonLocFirst().isValid() && !OASE->getLength()) {
5385 if (BaseType.isNull() || (!BaseType->isConstantArrayType() &&
5386 !BaseType->isVariableArrayType())) {
5387 S.
Diag(OASE->getColonLocFirst(),
5388 diag::err_omp_section_length_undefined)
5389 << (!BaseType.isNull() && BaseType->isArrayType());
5390 return std::make_pair(
nullptr,
false);
5393 while (
auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base))
5394 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5395 while (
auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
5396 Base = TempASE->getBase()->IgnoreParenImpCasts();
5398 IsArrayExpr = OMPArraySection;
5404 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5405 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5410 if (IsArrayExpr != NoArrayExpr) {
5411 S.
Diag(ELoc, diag::err_omp_expected_base_var_name)
5412 << IsArrayExpr << ERange;
5413 }
else if (!DiagType.empty()) {
5417 S.
Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5418 << DiagSelect << DiagType << ERange;
5422 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5423 : diag::err_omp_expected_var_name_member_expr)
5426 return std::make_pair(
nullptr,
false);
5428 return std::make_pair(
5435class AllocatorChecker final :
public ConstStmtVisitor<AllocatorChecker, bool> {
5436 DSAStackTy *S =
nullptr;
5439 bool VisitDeclRefExpr(
const DeclRefExpr *E) {
5440 return S->isUsesAllocatorsDecl(E->
getDecl())
5441 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5442 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5444 bool VisitStmt(
const Stmt *S) {
5445 for (
const Stmt *Child : S->
children()) {
5446 if (Child && Visit(Child))
5451 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5458 "Expected non-dependent context.");
5459 auto AllocateRange =
5462 auto PrivateRange = llvm::make_filter_range(Clauses, [](
const OMPClause *
C) {
5467 if (
Cl->getClauseKind() == OMPC_private) {
5469 I = PC->private_copies().begin();
5470 It = PC->varlist_begin();
5471 Et = PC->varlist_end();
5472 }
else if (
Cl->getClauseKind() == OMPC_firstprivate) {
5474 I = PC->private_copies().begin();
5475 It = PC->varlist_begin();
5476 Et = PC->varlist_end();
5477 }
else if (
Cl->getClauseKind() == OMPC_lastprivate) {
5479 I = PC->private_copies().begin();
5480 It = PC->varlist_begin();
5481 Et = PC->varlist_end();
5482 }
else if (
Cl->getClauseKind() == OMPC_linear) {
5484 I = PC->privates().begin();
5485 It = PC->varlist_begin();
5486 Et = PC->varlist_end();
5487 }
else if (
Cl->getClauseKind() == OMPC_reduction) {
5489 I = PC->privates().begin();
5490 It = PC->varlist_begin();
5491 Et = PC->varlist_end();
5492 }
else if (
Cl->getClauseKind() == OMPC_task_reduction) {
5494 I = PC->privates().begin();
5495 It = PC->varlist_begin();
5496 Et = PC->varlist_end();
5497 }
else if (
Cl->getClauseKind() == OMPC_in_reduction) {
5499 I = PC->privates().begin();
5500 It = PC->varlist_begin();
5501 Et = PC->varlist_end();
5503 llvm_unreachable(
"Expected private clause.");
5505 for (
Expr *E : llvm::make_range(It, Et)) {
5512 Expr *SimpleRefExpr = E;
5515 DeclToCopy.try_emplace(Res.first,
5523 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5525 AC->getAllocator()) {
5526 Expr *Allocator = AC->getAllocator();
5532 AllocatorChecker Checker(Stack);
5533 if (Checker.Visit(Allocator))
5535 diag::err_omp_allocator_not_in_uses_allocators)
5538 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5544 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5548 S.
Diag(AC->getAllocator()->getExprLoc(),
5549 diag::warn_omp_allocate_thread_on_task_target_directive)
5550 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
5552 for (
Expr *E : AC->varlist()) {
5555 Expr *SimpleRefExpr = E;
5560 DSAStackTy::DSAVarData
Data = Stack->getTopDSA(VD,
false);
5563 diag::err_omp_expected_private_copy_for_allocate);
5566 VarDecl *PrivateVD = DeclToCopy[VD];
5568 AllocatorKind, AC->getAllocator()))
5582class CaptureVars :
public TreeTransform<CaptureVars> {
5583 using BaseTransform = TreeTransform<CaptureVars>;
5586 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5588 bool AlwaysRebuild() {
return true; }
5601 BodyStmts.push_back(NewDeclStmt);
5639 DistParam, LogicalTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
5650 auto BuildVarRef = [&](
VarDecl *VD) {
5655 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 0), LogicalTy, {});
5657 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 1), LogicalTy, {});
5663 Actions.
BuildBinOp(
nullptr, {}, BO_LT, BuildVarRef(NewStep),
Zero));
5667 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5671 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5675 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5679 Actions.
BuildUnaryOp(
nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5681 Actions.
BuildBinOp(
nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5685 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5687 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5688 "Expected one of these relational operators");
5695 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5699 if (Rel == BO_GE || Rel == BO_GT)
5701 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5704 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5710 if (Rel == BO_LE || Rel == BO_GE) {
5722 Expr *Divisor = BuildVarRef(NewStep);
5723 if (Rel == BO_GE || Rel == BO_GT)
5726 Expr *DivisorMinusOne =
5729 Actions.
BuildBinOp(
nullptr, {}, BO_Add, Range, DivisorMinusOne));
5731 Actions.
BuildBinOp(
nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5741 Actions.
getCurScope(), {}, BO_Assign, DistRef, Dist));
5742 BodyStmts.push_back(ResultAssign);
5774 {
"Logical", LogicalTy},
5785 assert(!
Invalid &&
"Expecting capture-by-value to work.");
5794 TargetParam, LoopVarTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
5797 IndvarParam, LogicalTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
5800 CaptureVars Recap(Actions);
5805 Actions.
BuildBinOp(
nullptr, {}, BO_Mul, NewStep, LogicalRef));
5820 BO_Assign, TargetRef, Advanced));
5833 if (
auto *For = dyn_cast<ForStmt>(AStmt)) {
5835 if (
auto *LCVarDeclStmt = dyn_cast<DeclStmt>(
Init)) {
5838 }
else if (
auto *LCAssign = dyn_cast<BinaryOperator>(
Init)) {
5840 assert(LCAssign->getOpcode() == BO_Assign &&
5841 "init part must be a loop variable assignment");
5845 llvm_unreachable(
"Cannot determine loop variable");
5848 Cond = For->getCond();
5849 Inc = For->getInc();
5850 }
else if (
auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5851 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5853 LUVDecl = RangeFor->getLoopVariable();
5855 Cond = RangeFor->getCond();
5856 Inc = RangeFor->getInc();
5858 llvm_unreachable(
"unhandled kind of loop");
5867 if (
auto *CondBinExpr = dyn_cast<BinaryOperator>(
Cond)) {
5868 LHS = CondBinExpr->getLHS();
5869 RHS = CondBinExpr->getRHS();
5870 CondRel = CondBinExpr->getOpcode();
5871 }
else if (
auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(
Cond)) {
5872 assert(CondCXXOp->getNumArgs() == 2 &&
"Comparison should have 2 operands");
5873 LHS = CondCXXOp->getArg(0);
5874 RHS = CondCXXOp->getArg(1);
5875 switch (CondCXXOp->getOperator()) {
5876 case OO_ExclaimEqual:
5888 case OO_GreaterEqual:
5892 llvm_unreachable(
"unexpected iterator operator");
5895 llvm_unreachable(
"unexpected loop condition");
5900 std::swap(LHS, RHS);
5917 if (
auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5919 switch (IncUn->getOpcode()) {
5929 llvm_unreachable(
"unhandled unary increment operator");
5933 llvm::APInt(Ctx.
getIntWidth(LogicalTy), Direction,
true),
5935 }
else if (
auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5936 if (IncBin->getOpcode() == BO_AddAssign) {
5937 Step = IncBin->getRHS();
5938 }
else if (IncBin->getOpcode() == BO_SubAssign) {
5940 SemaRef.BuildUnaryOp(
nullptr, {}, UO_Minus, IncBin->getRHS()));
5942 llvm_unreachable(
"unhandled binary increment operator");
5943 }
else if (
auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5944 switch (CondCXXOp->getOperator()) {
5947 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 1), LogicalTy, {});
5951 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), -1), LogicalTy, {});
5954 Step = CondCXXOp->getArg(1);
5958 SemaRef.BuildUnaryOp(
nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5961 llvm_unreachable(
"unhandled overloaded increment operator");
5964 llvm_unreachable(
"unknown increment expression");
5972 nullptr,
nullptr, {},
nullptr);
5973 return OMPCanonicalLoop::create(
getASTContext(), AStmt, DistanceFunc,
5974 LoopVarFunc, LVRef);
5986 "Loop transformation directive expected");
5987 return LoopTransform;
5994 Expr *UnresolvedMapper);
6005 for (
int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
6006 auto *
C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
6010 auto *MI =
C->mapperlist_begin();
6011 for (
auto I =
C->varlist_begin(), End =
C->varlist_end(); I != End;
6030 if (
const auto *ATy = BaseType->getAsArrayTypeUnsafe())
6031 ElemType = ATy->getElementType();
6034 CanonType = ElemType;
6039 1, {CanonType,
nullptr});
6040 llvm::DenseMap<const Type *, Expr *> Visited;
6043 while (!Types.empty()) {
6046 std::tie(BaseType, CurFD) = Types.pop_back_val();
6047 while (ParentChain.back().second == 0)
6048 ParentChain.pop_back();
6049 --ParentChain.back().second;
6050 if (BaseType.isNull())
6053 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
6056 auto It = Visited.find(BaseType.getTypePtr());
6057 if (It == Visited.end()) {
6065 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
6069 It = Visited.try_emplace(BaseType.getTypePtr(), ER.
get()).first;
6076 Expr *BaseExpr = OE;
6077 for (
const auto &P : ParentChain) {
6095 SubExprs.push_back(BaseExpr);
6099 bool FirstIter =
true;
6109 ParentChain.emplace_back(CurFD, 1);
6111 ++ParentChain.back().second;
6113 Types.emplace_back(FieldTy, FD);
6117 if (SubExprs.empty())
6122 nullptr,
C->getMapTypeModifiers(),
C->getMapTypeModifiersLoc(),
6123 MapperIdScopeSpec, MapperId,
C->getMapType(),
6126 Clauses.push_back(NewClause);
6133class TeamsLoopChecker final :
public ConstStmtVisitor<TeamsLoopChecker> {
6140 void VisitOMPExecutableDirective(
const OMPExecutableDirective *D) {
6141 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
6142 if (
const auto *
C = D->getSingleClause<OMPBindClause>())
6143 if (
C->getBindKind() == OMPC_BIND_parallel) {
6144 TeamsLoopCanBeParallelFor =
false;
6149 for (
const Stmt *Child : D->children())
6154 void VisitCallExpr(
const CallExpr *
C) {
6159 bool IsOpenMPAPI =
false;
6160 auto *FD = dyn_cast_or_null<FunctionDecl>(
C->getCalleeDecl());
6162 std::string Name = FD->getNameInfo().getAsString();
6163 IsOpenMPAPI = Name.find(
"omp_") == 0;
6165 TeamsLoopCanBeParallelFor =
6166 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
6167 if (!TeamsLoopCanBeParallelFor)
6170 for (
const Stmt *Child :
C->children())
6175 void VisitCapturedStmt(
const CapturedStmt *S) {
6181 void VisitStmt(
const Stmt *S) {
6184 for (
const Stmt *Child : S->
children())
6188 explicit TeamsLoopChecker(Sema &SemaRef)
6189 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(
true) {}
6192 bool TeamsLoopCanBeParallelFor;
6197 TeamsLoopChecker Checker(SemaRef);
6198 Checker.Visit(AStmt);
6199 return Checker.teamsLoopCanBeParallelFor();
6213 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6214 BindKind = BC->getBindKind();
6226 BindKind = OMPC_BIND_thread;
6228 getLeafConstructsOrSelf(ParentDirective);
6230 if (ParentDirective == OMPD_unknown) {
6232 diag::err_omp_bind_required_on_loop);
6233 }
else if (ParentLeafs.back() == OMPD_parallel) {
6234 BindKind = OMPC_BIND_parallel;
6235 }
else if (ParentLeafs.back() == OMPD_teams) {
6236 BindKind = OMPC_BIND_teams;
6244 ClausesWithImplicit.push_back(
C);
6248 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6250 if (
C->getClauseKind() == OMPC_reduction)
6252 diag::err_omp_loop_reduction_clause);
6259 BindKind, StartLoc)) {
6266 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6269 bool ErrorFound =
false;
6270 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6272 if (AStmt && !
SemaRef.CurContext->isDependentContext() &&
6280 while (--ThisCaptureLevel >= 0)
6282 DSAChecker.Visit(S);
6290 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6292 DSAChecker.visitSubCaptures(CS);
6294 if (DSAChecker.isErrorFound())
6297 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6298 VariableImplicitInfo ImpInfo = DSAChecker.getImplicitInfo();
6301 ImplicitMapModifiersLoc[VariableImplicitInfo::DefaultmapKindNum];
6303 SourceLocation PresentModifierLocs[VariableImplicitInfo::DefaultmapKindNum];
6305 if (
auto *DMC = dyn_cast<OMPDefaultmapClause>(
C))
6306 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6307 PresentModifierLocs[DMC->getDefaultmapKind()] =
6308 DMC->getDefaultmapModifierLoc();
6312 llvm::enum_seq_inclusive<OpenMPDefaultmapClauseKind>(
6314 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[K]),
6315 ImpInfo.MapModifiers[K].size(), PresentModifierLocs[K]);
6319 if (
auto *IRC = dyn_cast<OMPInReductionClause>(
C)) {
6320 for (
Expr *E : IRC->taskgroup_descriptors())
6322 ImpInfo.Firstprivates.insert(E);
6327 if (
auto *DC = dyn_cast<OMPDetachClause>(
C))
6328 ImpInfo.Firstprivates.insert(DC->getEventHandler());
6330 if (!ImpInfo.Firstprivates.empty()) {
6334 ClausesWithImplicit.push_back(
Implicit);
6336 ImpInfo.Firstprivates.size();
6341 if (!ImpInfo.Privates.empty()) {
6345 ClausesWithImplicit.push_back(
Implicit);
6347 ImpInfo.Privates.size();
6356 if (
getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6360 if (
auto *RC = dyn_cast<OMPReductionClause>(
C))
6361 for (
Expr *E : RC->varlist())
6363 ImplicitExprs.emplace_back(E);
6365 if (!ImplicitExprs.empty()) {
6371 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6374 ClausesWithImplicit.emplace_back(
Implicit);
6377 for (
unsigned I = 0; I < VariableImplicitInfo::DefaultmapKindNum; ++I) {
6378 int ClauseKindCnt = -1;
6379 for (
unsigned J = 0; J < VariableImplicitInfo::MapKindNum; ++J) {
6382 if (ImplicitMap.empty())
6388 nullptr, ImpInfo.MapModifiers[I], ImplicitMapModifiersLoc[I],
6389 MapperIdScopeSpec, MapperId, K,
true,
6392 ClausesWithImplicit.emplace_back(
Implicit);
6404 ClausesWithImplicit);
6414 VarsWithInheritedDSA);
6429 assert(ClausesWithImplicit.empty() &&
6430 "reverse directive does not support any clauses");
6433 case OMPD_interchange:
6443 VarsWithInheritedDSA);
6447 EndLoc, VarsWithInheritedDSA);
6454 assert(ClausesWithImplicit.empty() &&
6455 "No clauses are allowed for 'omp section' directive");
6463 assert(ClausesWithImplicit.empty() &&
6464 "No clauses are allowed for 'omp master' directive");
6475 case OMPD_parallel_for:
6477 EndLoc, VarsWithInheritedDSA);
6479 case OMPD_parallel_for_simd:
6481 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6487 case OMPD_parallel_master:
6491 case OMPD_parallel_masked:
6495 case OMPD_parallel_sections:
6503 case OMPD_taskyield:
6504 assert(ClausesWithImplicit.empty() &&
6505 "No clauses are allowed for 'omp taskyield' directive");
6506 assert(AStmt ==
nullptr &&
6507 "No associated statement allowed for 'omp taskyield' directive");
6511 assert(AStmt ==
nullptr &&
6512 "No associated statement allowed for 'omp error' directive");
6516 assert(ClausesWithImplicit.empty() &&
6517 "No clauses are allowed for 'omp barrier' directive");
6518 assert(AStmt ==
nullptr &&
6519 "No associated statement allowed for 'omp barrier' directive");
6523 assert(AStmt ==
nullptr &&
6524 "No associated statement allowed for 'omp taskwait' directive");
6527 case OMPD_taskgroup:
6532 assert(AStmt ==
nullptr &&
6533 "No associated statement allowed for 'omp flush' directive");
6537 assert(AStmt ==
nullptr &&
6538 "No associated statement allowed for 'omp depobj' directive");
6542 assert(AStmt ==
nullptr &&
6543 "No associated statement allowed for 'omp scan' directive");
6562 case OMPD_target_parallel:
6566 case OMPD_target_parallel_for:
6568 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6570 case OMPD_cancellation_point:
6571 assert(ClausesWithImplicit.empty() &&
6572 "No clauses are allowed for 'omp cancellation point' directive");
6573 assert(AStmt ==
nullptr &&
"No associated statement allowed for 'omp "
6574 "cancellation point' directive");
6578 assert(AStmt ==
nullptr &&
6579 "No associated statement allowed for 'omp cancel' directive");
6583 case OMPD_target_data:
6587 case OMPD_target_enter_data:
6591 case OMPD_target_exit_data:
6597 EndLoc, VarsWithInheritedDSA);
6599 case OMPD_taskloop_simd:
6601 EndLoc, VarsWithInheritedDSA);
6603 case OMPD_master_taskloop:
6605 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6607 case OMPD_masked_taskloop:
6609 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6611 case OMPD_master_taskloop_simd:
6613 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6615 case OMPD_masked_taskloop_simd:
6617 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6619 case OMPD_parallel_master_taskloop:
6621 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6623 case OMPD_parallel_masked_taskloop:
6625 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6627 case OMPD_parallel_master_taskloop_simd:
6629 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6631 case OMPD_parallel_masked_taskloop_simd:
6633 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6635 case OMPD_distribute:
6637 EndLoc, VarsWithInheritedDSA);
6639 case OMPD_target_update:
6643 case OMPD_distribute_parallel_for:
6645 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6647 case OMPD_distribute_parallel_for_simd:
6649 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6651 case OMPD_distribute_simd:
6653 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6655 case OMPD_target_parallel_for_simd:
6657 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6659 case OMPD_target_simd:
6661 EndLoc, VarsWithInheritedDSA);
6663 case OMPD_teams_distribute:
6665 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6667 case OMPD_teams_distribute_simd:
6669 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6671 case OMPD_teams_distribute_parallel_for_simd:
6673 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6675 case OMPD_teams_distribute_parallel_for:
6677 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6679 case OMPD_target_teams:
6683 case OMPD_target_teams_distribute:
6685 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6687 case OMPD_target_teams_distribute_parallel_for:
6689 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6691 case OMPD_target_teams_distribute_parallel_for_simd:
6693 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6695 case OMPD_target_teams_distribute_simd:
6697 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6700 assert(AStmt ==
nullptr &&
6701 "No associated statement allowed for 'omp interop' directive");
6710 EndLoc, VarsWithInheritedDSA);
6712 case OMPD_teams_loop:
6714 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6716 case OMPD_target_teams_loop:
6718 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6720 case OMPD_parallel_loop:
6722 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6724 case OMPD_target_parallel_loop:
6726 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6728 case OMPD_declare_target:
6729 case OMPD_end_declare_target:
6730 case OMPD_threadprivate:
6732 case OMPD_declare_reduction:
6733 case OMPD_declare_mapper:
6734 case OMPD_declare_simd:
6736 case OMPD_declare_variant:
6737 case OMPD_begin_declare_variant:
6738 case OMPD_end_declare_variant:
6739 llvm_unreachable(
"OpenMP Directive is not allowed");
6742 llvm_unreachable(
"Unknown OpenMP directive");
6745 ErrorFound = Res.
isInvalid() || ErrorFound;
6749 if (
DSAStack->getDefaultDSA() == DSA_none ||
6750 DSAStack->getDefaultDSA() == DSA_private ||
6751 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6754 switch (
C->getClauseKind()) {
6755 case OMPC_num_threads:
6756 case OMPC_dist_schedule:
6773 case OMPC_grainsize:
6774 case OMPC_num_tasks:
6777 case OMPC_novariants:
6778 case OMPC_nocontext:
6785 case OMPC_num_teams:
6786 case OMPC_thread_limit:
6793 case OMPC_proc_bind:
6795 case OMPC_firstprivate:
6796 case OMPC_lastprivate:
6798 case OMPC_reduction:
6799 case OMPC_task_reduction:
6800 case OMPC_in_reduction:
6804 case OMPC_copyprivate:
6807 case OMPC_mergeable:
6824 case OMPC_defaultmap:
6827 case OMPC_use_device_ptr:
6828 case OMPC_use_device_addr:
6829 case OMPC_is_device_ptr:
6830 case OMPC_has_device_addr:
6831 case OMPC_nontemporal:
6834 case OMPC_inclusive:
6835 case OMPC_exclusive:
6836 case OMPC_uses_allocators:
6843 case OMPC_allocator:
6846 case OMPC_threadprivate:
6847 case OMPC_groupprivate:
6850 case OMPC_unified_address:
6851 case OMPC_unified_shared_memory:
6852 case OMPC_reverse_offload:
6853 case OMPC_dynamic_allocators:
6854 case OMPC_atomic_default_mem_order:
6855 case OMPC_self_maps:
6856 case OMPC_device_type:
6861 llvm_unreachable(
"Unexpected clause");
6863 for (
Stmt *CC :
C->children()) {
6865 DSAChecker.Visit(CC);
6868 for (
const auto &P : DSAChecker.getVarsWithInheritedDSA())
6869 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6871 for (
const auto &P : VarsWithInheritedDSA) {
6875 if (
DSAStack->getDefaultDSA() == DSA_none ||
6876 DSAStack->getDefaultDSA() == DSA_private ||
6877 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6878 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6879 << P.first << P.second->getSourceRange();
6880 Diag(
DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6882 Diag(P.second->getExprLoc(),
6883 diag::err_omp_defaultmap_no_attr_for_variable)
6884 << P.first << P.second->getSourceRange();
6886 diag::note_omp_defaultmap_attr_none);
6892 if (isAllowedClauseForDirective(D, OMPC_if,
getLangOpts().OpenMP))
6893 AllowedNameModifiers.push_back(D);
6895 if (!AllowedNameModifiers.empty())
6902 if (!
SemaRef.CurContext->isDependentContext() &&
6904 !(
DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6905 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6906 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6907 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6909 DSAStack->addTargetDirLocation(StartLoc);
6920 assert(Aligneds.size() == Alignments.size());
6921 assert(Linears.size() == LinModifiers.size());
6922 assert(Linears.size() == Steps.size());
6926 const int SimdId = 0;
6928 Diag(SR.
getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6933 if (
auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6934 ADecl = FTD->getTemplatedDecl();
6936 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6938 Diag(ADecl->
getLocation(), diag::err_omp_function_expected) << SimdId;
6954 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6955 const Expr *UniformedLinearThis =
nullptr;
6956 for (
const Expr *E : Uniforms) {
6958 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E))
6959 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
6960 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6961 FD->getParamDecl(PVD->getFunctionScopeIndex())
6963 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
6967 UniformedLinearThis = E;
6981 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6982 const Expr *AlignedThis =
nullptr;
6983 for (
const Expr *E : Aligneds) {
6985 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E))
6986 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6988 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6989 FD->getParamDecl(PVD->getFunctionScopeIndex())
6993 auto [It, Inserted] = AlignedArgs.try_emplace(CanonPVD, E);
6998 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7003 .getNonReferenceType()
7004 .getUnqualifiedType()
7005 .getCanonicalType();
7008 Diag(E->
getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
7010 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
7034 for (
Expr *E : Alignments) {
7038 NewAligns.push_back(Align.
get());
7049 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
7050 const bool IsUniformedThis = UniformedLinearThis !=
nullptr;
7051 auto MI = LinModifiers.begin();
7052 for (
const Expr *E : Linears) {
7056 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E))
7057 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7059 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7060 FD->getParamDecl(PVD->getFunctionScopeIndex())
7064 if (
auto It = LinearArgs.find(CanonPVD); It != LinearArgs.end()) {
7069 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7074 if (
auto It = UniformedArgs.find(CanonPVD);
7075 It != UniformedArgs.end()) {
7080 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7084 LinearArgs[CanonPVD] = E;
7090 PVD->getOriginalType(),
7096 if (UniformedLinearThis) {
7102 Diag(UniformedLinearThis->
getExprLoc(), diag::note_omp_explicit_dsa)
7107 UniformedLinearThis = E;
7118 Expr *Step =
nullptr;
7119 Expr *NewStep =
nullptr;
7121 for (
Expr *E : Steps) {
7123 if (Step == E || !E) {
7124 NewSteps.push_back(E ? NewStep :
nullptr);
7128 if (
const auto *DRE = dyn_cast<DeclRefExpr>(Step))
7129 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7131 if (UniformedArgs.count(CanonPVD) == 0) {
7138 NewSteps.push_back(Step);
7153 .VerifyIntegerConstantExpression(
7157 NewSteps.push_back(NewStep);
7159 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7161 Uniforms.size(),
const_cast<Expr **
>(Aligneds.data()), Aligneds.size(),
7162 const_cast<Expr **
>(NewAligns.data()), NewAligns.size(),
7163 const_cast<Expr **
>(Linears.data()), Linears.size(),
7164 const_cast<unsigned *
>(LinModifiers.data()), LinModifiers.size(),
7165 NewSteps.data(), NewSteps.size(), SR);
7175 "Unexpected directive category");
7184 llvm_unreachable(
"Unknown OpenMP directive");
7193 "Expected function type with prototype.");
7195 "Expected function with type with no prototype.");
7197 "Expected function with prototype.");
7205 Param->setScopeInfo(0, Params.size());
7206 Param->setImplicit();
7207 Params.push_back(Param);
7210 FD->setParams(Params);
7217 if (
auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7218 FD = UTemplDecl->getTemplatedDecl();
7221 assert(FD &&
"Expected a function declaration!");
7226 if (!
SemaRef.inTemplateInstantiation()) {
7227 for (OMPAssumeAttr *AA : OMPAssumeScoped)
7230 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7234SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(
OMPTraitInfo &TI)
7235 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7243 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7246 bool IsTemplated = !TemplateParamLists.empty();
7249 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7266 for (
auto *Candidate : Lookup) {
7267 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7272 if (
SemaRef.Context.isSameTemplateParameterList(
7273 FTD->getTemplateParameters(), TemplateParamLists.back()))
7274 UDecl = FTD->getTemplatedDecl();
7275 }
else if (!IsTemplated)
7276 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7290 FType, UDeclTy,
false,
7297 Bases.push_back(UDecl);
7301 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7303 if (Bases.empty() && UseImplicitBase) {
7305 Decl *BaseD =
SemaRef.HandleDeclarator(S, D, TemplateParamLists);
7307 if (
auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7308 Bases.push_back(BaseTemplD->getTemplatedDecl());
7313 std::string MangledName;
7316 MangledName += DVScope.NameSuffix;
7331 if (
auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7332 FD = UTemplDecl->getTemplatedDecl();
7340 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7341 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7348 BaseFD->addAttr(OMPDeclareVariantA);
7368 CalleeFnDecl->
getName().starts_with_insensitive(
"omp_")) {
7371 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7374 if (!CalleeFnDecl->
hasAttr<OMPDeclareVariantAttr>())
7379 CE](StringRef ISATrait) {
7393 while (CalleeFnDecl) {
7394 for (OMPDeclareVariantAttr *A :
7396 Expr *VariantRef = A->getVariantFuncRef();
7398 VariantMatchInfo VMI;
7401 if (!isVariantApplicableInContext(VMI, OMPCtx,
7405 VMIs.push_back(VMI);
7406 Exprs.push_back(VariantRef);
7414 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7434 if (
auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7435 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7437 Context, MemberCall->getImplicitObjectArgument(),
7438 false, SpecializedMethod, Context.BoundMemberTy,
7439 MemberCall->getValueKind(), MemberCall->getObjectKind());
7441 NewCall =
SemaRef.BuildCallExpr(
Scope, BestExpr, LParenLoc, ArgExprs,
7442 RParenLoc, ExecConfig);
7444 if (
CallExpr *NCE = dyn_cast<CallExpr>(NewCall.
get())) {
7445 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7447 CalleeFnType, NewCalleeFnDecl->
getType(),
7458 VMIs.erase(VMIs.begin() + BestIdx);
7459 Exprs.erase(Exprs.begin() + BestIdx);
7460 }
while (!VMIs.empty());
7467std::optional<std::pair<FunctionDecl *, Expr *>>
7471 unsigned NumAppendArgs,
7475 return std::nullopt;
7477 const int VariantId = 1;
7480 Diag(SR.
getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7482 return std::nullopt;
7485 if (
auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7486 ADecl = FTD->getTemplatedDecl();
7489 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7493 return std::nullopt;
7496 auto &&HasMultiVersionAttributes = [](
const FunctionDecl *FD) {
7499 return FD->isMultiVersion() || FD->
hasAttr<TargetAttr>();
7502 if (HasMultiVersionAttributes(FD)) {
7503 Diag(FD->
getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7505 return std::nullopt;
7510 Diag(SR.
getBegin(), diag::warn_omp_declare_variant_after_used)
7515 if (!FD->isThisDeclarationADefinition() && FD->isDefined(
Definition) &&
7517 Diag(SR.
getBegin(), diag::warn_omp_declare_variant_after_emitted)
7522 Diag(SR.
getBegin(), diag::err_omp_function_expected) << VariantId;
7523 return std::nullopt;
7526 auto ShouldDelayChecks = [](
Expr *&E, bool) {
7532 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef,
false) ||
7534 return std::make_pair(FD, VariantRef);
7537 auto HandleNonConstantScoresAndConditions = [
this](
Expr *&E,
7538 bool IsScore) ->
bool {
7544 Diag(E->
getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7552 diag::err_omp_declare_variant_user_condition_not_constant)
7558 return std::nullopt;
7561 if (NumAppendArgs) {
7564 Diag(FD->
getLocation(), diag::err_omp_declare_variant_prototype_required)
7566 return std::nullopt;
7575 TD = dyn_cast_or_null<TypeDecl>(ND);
7578 Diag(SR.
getBegin(), diag::err_omp_interop_type_not_found) << SR;
7579 return std::nullopt;
7584 if (PTy->isVariadic()) {
7585 Diag(FD->
getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7586 return std::nullopt;
7589 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7590 Params.insert(Params.end(), NumAppendArgs, InteropType);
7591 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7592 PTy->getExtProtoInfo());
7600 auto *
Method = dyn_cast<CXXMethodDecl>(FD);
7602 FnPtrType = Context.getMemberPointerType(
7603 AdjustedFnType, std::nullopt,
Method->getParent());
7615 return std::nullopt;
7617 VariantRef = ER.
get();
7619 FnPtrType = Context.getPointerType(AdjustedFnType);
7621 QualType VarianPtrType = Context.getPointerType(VariantRef->
getType());
7625 false, Sema::AllowedExplicit::None,
7631 diag::err_omp_declare_variant_incompat_types)
7635 return std::nullopt;
7637 VariantRefCast =
SemaRef.PerformImplicitConversion(
7641 return std::nullopt;
7645 Expr *PossibleAddrOfVariantRef = VariantRefCast.
get();
7646 if (
auto *UO = dyn_cast<UnaryOperator>(
7648 VariantRefCast = UO->getSubExpr();
7657 return std::nullopt;
7665 return std::nullopt;
7667 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7671 return std::nullopt;
7676 diag::err_omp_declare_variant_same_base_function)
7678 return std::nullopt;
7684 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7687 diag::err_omp_declare_variant_incompat_types)
7688 << NewFD->getType() << FD->
getType() << (NumAppendArgs ? 1 : 0)
7690 return std::nullopt;
7695 else if (NewFD->getType()->isFunctionNoProtoType())
7701 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7703 diag::warn_omp_declare_variant_marked_as_declare_variant)
7706 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->
getRange();
7707 Diag(SR.
getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7708 return std::nullopt;
7711 enum DoesntSupport {
7720 if (
const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7721 if (CXXFD->isVirtual()) {
7724 return std::nullopt;
7730 return std::nullopt;
7736 return std::nullopt;
7740 if (FD->isDeleted()) {
7743 return std::nullopt;
7746 if (FD->isDefaulted()) {
7749 return std::nullopt;
7752 if (FD->isConstexpr()) {
7754 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7755 return std::nullopt;
7759 if (
SemaRef.areMultiversionVariantFunctionsCompatible(
7765 SemaRef.PDiag(diag::err_omp_declare_variant_doesnt_support)),
7767 SemaRef.PDiag(diag::err_omp_declare_variant_diff)
7771 return std::nullopt;
7789 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7790 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7791 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDeviceAddr);
7793 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7794 VariantMatchInfo VMI;
7796 if (!llvm::is_contained(
7797 VMI.ConstructTraits,
7798 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7799 if (!AllAdjustArgs.empty())
7800 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7802 if (!AppendArgs.empty())
7803 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7814 for (
Expr *E : AllAdjustArgs) {
7816 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7817 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7819 if (FD->
getNumParams() > PVD->getFunctionScopeIndex() &&
7823 if (!AdjustVars.insert(CanonPVD).second) {
7824 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7833 Diag(E->
getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7842 for (
Expr *E : AdjustArgsNeedDeviceAddr) {
7844 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7845 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
7848 diag::err_omp_non_by_ref_need_device_addr_modifier_argument);
7854 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7856 const_cast<Expr **
>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7857 const_cast<Expr **
>(AdjustArgsNeedDevicePtr.data()),
7858 AdjustArgsNeedDevicePtr.size(),
7859 const_cast<Expr **
>(AdjustArgsNeedDeviceAddr.data()),
7860 AdjustArgsNeedDeviceAddr.size(),
7861 const_cast<OMPInteropInfo *
>(AppendArgs.data()), AppendArgs.size(), SR);
7867 auto *CS = dyn_cast<CapturedStmt>(AStmt);
7868 assert(CS &&
"Captured statement expected");
7877 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7899 return OMPParallelDirective::Create(
7906struct LoopIterationSpace final {
7909 bool IsStrictCompare =
false;
7911 Expr *PreCond =
nullptr;
7914 Expr *NumIterations =
nullptr;
7916 Expr *CounterVar =
nullptr;
7918 Expr *PrivateCounterVar =
nullptr;
7920 Expr *CounterInit =
nullptr;
7923 Expr *CounterStep =
nullptr;
7925 bool Subtract =
false;
7935 Expr *MinValue =
nullptr;
7939 Expr *MaxValue =
nullptr;
7941 bool IsNonRectangularLB =
false;
7943 bool IsNonRectangularUB =
false;
7946 unsigned LoopDependentIdx = 0;
7950 Expr *FinalCondition =
nullptr;
7957 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7958 VarDecl *ForbiddenVar =
nullptr;
7962 explicit ForSubExprChecker(
7963 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
7964 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
7967 ShouldVisitImplicitCode =
true;
7970 bool VisitDeclRefExpr(DeclRefExpr *E)
override {
7975 if (
V->getType()->isReferenceType()) {
7976 VarDecl *VD =
V->getDefinition();
7979 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(I);
7985 Decl *Canon =
V->getCanonicalDecl();
7986 if (CollapsedLoopVarDecls.contains(Canon)) {
7995 VarDecl *getForbiddenVar()
const {
return ForbiddenVar; }
7996 SourceRange getErrRange()
const {
return ErrLoc; }
8002class OpenMPIterationSpaceChecker {
8006 bool SupportsNonRectangular;
8010 SourceLocation DefaultLoc;
8012 SourceLocation ConditionLoc;
8014 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
8016 SourceRange InitSrcRange;
8018 SourceRange ConditionSrcRange;
8020 SourceRange IncrementSrcRange;
8022 ValueDecl *LCDecl =
nullptr;
8024 Expr *LCRef =
nullptr;
8030 Expr *Step =
nullptr;
8037 std::optional<bool> TestIsLessOp;
8039 bool TestIsStrictOp =
false;
8041 bool SubtractStep =
false;
8043 const ValueDecl *DepDecl =
nullptr;
8046 std::optional<unsigned> InitDependOnLC;
8049 std::optional<unsigned> CondDependOnLC;
8051 std::optional<unsigned> doesDependOnLoopCounter(
const Stmt *S,
8052 bool IsInitializer);
8058 OpenMPIterationSpaceChecker(
8059 Sema &SemaRef,
bool SupportsNonRectangular, DSAStackTy &Stack,
8060 SourceLocation DefaultLoc,
8061 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls)
8062 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
8063 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
8064 CollapsedLoopVarDecls(CollapsedLoopDecls) {}
8067 bool checkAndSetInit(Stmt *S,
bool EmitDiags =
true);
8070 bool checkAndSetCond(Expr *S);
8073 bool checkAndSetInc(Expr *S);
8075 ValueDecl *getLoopDecl()
const {
return LCDecl; }
8077 Expr *getLoopDeclRefExpr()
const {
return LCRef; }
8079 SourceRange getInitSrcRange()
const {
return InitSrcRange; }
8081 SourceRange getConditionSrcRange()
const {
return ConditionSrcRange; }
8083 SourceRange getIncrementSrcRange()
const {
return IncrementSrcRange; }
8085 bool shouldSubtractStep()
const {
return SubtractStep; }
8087 bool isStrictTestOp()
const {
return TestIsStrictOp; }
8089 Expr *buildNumIterations(
8090 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces,
bool LimitedType,
8091 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
8094 buildPreCond(Scope *S, Expr *
Cond,
8095 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
8098 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8099 DSAStackTy &DSA)
const;
8102 Expr *buildPrivateCounterVar()
const;
8106 Expr *buildCounterStep()
const;
8110 buildOrderedLoopData(Scope *S, Expr *Counter,
8111 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8112 SourceLocation Loc, Expr *Inc =
nullptr,
8115 std::pair<Expr *, Expr *> buildMinMaxValues(
8116 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
8118 Expr *buildFinalCondition(Scope *S)
const;
8120 bool dependent()
const;
8122 bool doesInitDependOnLC()
const {
return InitDependOnLC.has_value(); }
8124 bool doesCondDependOnLC()
const {
return CondDependOnLC.has_value(); }
8126 unsigned getLoopDependentIdx()
const {
8127 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
8133 bool checkAndSetIncRHS(Expr *RHS);
8135 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
8138 bool setUB(Expr *NewUB, std::optional<bool> LessOp,
bool StrictOp,
8139 SourceRange SR, SourceLocation SL);
8141 bool setStep(Expr *NewStep,
bool Subtract);
8144bool OpenMPIterationSpaceChecker::dependent()
const {
8146 assert(!LB && !UB && !Step);
8154bool OpenMPIterationSpaceChecker::setLCDeclAndLB(
ValueDecl *NewLCDecl,
8156 Expr *NewLB,
bool EmitDiags) {
8158 assert(LCDecl ==
nullptr && LB ==
nullptr && LCRef ==
nullptr &&
8159 UB ==
nullptr && Step ==
nullptr && !TestIsLessOp && !TestIsStrictOp);
8163 LCRef = NewLCRefExpr;
8164 if (
auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
8166 if ((Ctor->isCopyOrMoveConstructor() ||
8167 Ctor->isConvertingConstructor(
false)) &&
8168 CE->getNumArgs() > 0 && CE->getArg(0) !=
nullptr)
8172 InitDependOnLC = doesDependOnLoopCounter(LB,
true);
8176bool OpenMPIterationSpaceChecker::setUB(
Expr *NewUB, std::optional<bool> LessOp,
8180 assert(LCDecl !=
nullptr && LB !=
nullptr && UB ==
nullptr &&
8181 Step ==
nullptr && !TestIsLessOp && !TestIsStrictOp);
8186 TestIsLessOp = LessOp;
8187 TestIsStrictOp = StrictOp;
8188 ConditionSrcRange = SR;
8190 CondDependOnLC = doesDependOnLoopCounter(UB,
false);
8194bool OpenMPIterationSpaceChecker::setStep(
Expr *NewStep,
bool Subtract) {
8196 assert(LCDecl !=
nullptr && LB !=
nullptr && Step ==
nullptr);
8206 NewStep = Val.
get();
8219 std::optional<llvm::APSInt>
Result =
8230 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8231 if (UB && (IsConstZero ||
8232 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8233 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8235 diag::err_omp_loop_incr_not_compatible)
8237 SemaRef.
Diag(ConditionLoc,
8238 diag::note_omp_loop_cond_requires_compatible_incr)
8239 << *TestIsLessOp << ConditionSrcRange;
8242 if (*TestIsLessOp == Subtract) {
8246 Subtract = !Subtract;
8251 SubtractStep = Subtract;
8258class LoopCounterRefChecker final
8262 const ValueDecl *CurLCDecl =
nullptr;
8263 const ValueDecl *DepDecl =
nullptr;
8264 const ValueDecl *PrevDepDecl =
nullptr;
8265 bool IsInitializer =
true;
8266 bool SupportsNonRectangular;
8267 unsigned BaseLoopId = 0;
8268 bool checkDecl(
const Expr *E,
const ValueDecl *VD) {
8270 SemaRef.Diag(E->
getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8271 << (IsInitializer ? 0 : 1);
8274 const auto &&
Data = Stack.isLoopControlVariable(VD);
8279 SmallString<128> Name;
8280 llvm::raw_svector_ostream
OS(Name);
8284 diag::err_omp_wrong_dependency_iterator_type)
8286 SemaRef.Diag(VD->
getLocation(), diag::note_previous_decl) << VD;
8289 if (
Data.first && !SupportsNonRectangular) {
8290 SemaRef.Diag(E->
getExprLoc(), diag::err_omp_invariant_dependency);
8294 (DepDecl || (PrevDepDecl &&
8296 if (!DepDecl && PrevDepDecl)
8297 DepDecl = PrevDepDecl;
8298 SmallString<128> Name;
8299 llvm::raw_svector_ostream
OS(Name);
8303 diag::err_omp_invariant_or_linear_dependency)
8309 BaseLoopId =
Data.first;
8315 bool VisitDeclRefExpr(
const DeclRefExpr *E) {
8316 const ValueDecl *VD = E->
getDecl();
8318 return checkDecl(E, VD);
8321 bool VisitMemberExpr(
const MemberExpr *E) {
8325 return checkDecl(E, VD);
8329 bool VisitStmt(
const Stmt *S) {
8331 for (
const Stmt *Child : S->
children())
8332 Res = (Child && Visit(Child)) || Res;
8335 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8336 const ValueDecl *CurLCDecl,
bool IsInitializer,
8337 const ValueDecl *PrevDepDecl =
nullptr,
8338 bool SupportsNonRectangular =
true)
8339 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8340 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8341 SupportsNonRectangular(SupportsNonRectangular) {}
8342 unsigned getBaseLoopId()
const {
8343 assert(CurLCDecl &&
"Expected loop dependency.");
8346 const ValueDecl *getDepDecl()
const {
8347 assert(CurLCDecl &&
"Expected loop dependency.");
8353std::optional<unsigned>
8354OpenMPIterationSpaceChecker::doesDependOnLoopCounter(
const Stmt *S,
8355 bool IsInitializer) {
8357 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8358 DepDecl, SupportsNonRectangular);
8359 if (LoopStmtChecker.Visit(S)) {
8360 DepDecl = LoopStmtChecker.getDepDecl();
8361 return LoopStmtChecker.getBaseLoopId();
8363 return std::nullopt;
8366bool OpenMPIterationSpaceChecker::checkAndSetInit(
Stmt *S,
bool EmitDiags) {
8377 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8381 if (
auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8382 if (!ExprTemp->cleanupsHaveSideEffects())
8383 S = ExprTemp->getSubExpr();
8385 if (!CollapsedLoopVarDecls.empty()) {
8386 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8387 if (!FSEC.TraverseStmt(S)) {
8389 SemaRef.Diag(
Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8390 <<
Range.getEnd() << 0 << FSEC.getForbiddenVar();
8396 if (
Expr *E = dyn_cast<Expr>(S))
8398 if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8399 if (BO->getOpcode() == BO_Assign) {
8401 if (
auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8402 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->
getDecl()))
8404 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8406 return setLCDeclAndLB(DRE->
getDecl(), DRE, BO->getRHS(), EmitDiags);
8408 if (
auto *ME = dyn_cast<MemberExpr>(LHS)) {
8409 if (ME->isArrow() &&
8411 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8415 }
else if (
auto *DS = dyn_cast<DeclStmt>(S)) {
8416 if (DS->isSingleDecl()) {
8417 if (
auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8418 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8422 diag::ext_omp_loop_not_canonical_init)
8424 return setLCDeclAndLB(
8427 Var->getType().getNonReferenceType(),
8429 Var->getInit(), EmitDiags);
8433 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8434 if (CE->getOperator() == OO_Equal) {
8435 Expr *LHS = CE->getArg(0);
8436 if (
auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8437 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->
getDecl()))
8439 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8441 return setLCDeclAndLB(DRE->
getDecl(), DRE, CE->getArg(1), EmitDiags);
8443 if (
auto *ME = dyn_cast<MemberExpr>(LHS)) {
8444 if (ME->isArrow() &&
8446 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8452 if (dependent() || SemaRef.CurContext->isDependentContext())
8455 SemaRef.Diag(S->
getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8467 if (
const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8469 if ((Ctor->isCopyOrMoveConstructor() ||
8470 Ctor->isConvertingConstructor(
false)) &&
8471 CE->getNumArgs() > 0 && CE->getArg(0) !=
nullptr)
8473 if (
const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8474 if (
const auto *VD = dyn_cast<VarDecl>(DRE->
getDecl()))
8477 if (
const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8478 if (ME->isArrow() &&
isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8483bool OpenMPIterationSpaceChecker::checkAndSetCond(
Expr *S) {
8490 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8492 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8493 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8499 if (!CollapsedLoopVarDecls.empty()) {
8500 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8501 if (!FSEC.TraverseStmt(S)) {
8503 SemaRef.Diag(
Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8504 <<
Range.getEnd() << 1 << FSEC.getForbiddenVar();
8510 auto &&CheckAndSetCond =
8515 if (getInitLCDecl(LHS) == LCDecl)
8516 return setUB(
const_cast<Expr *
>(RHS),
8517 (Opcode == BO_LT || Opcode == BO_LE),
8518 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8519 if (getInitLCDecl(RHS) == LCDecl)
8520 return setUB(
const_cast<Expr *
>(LHS),
8521 (Opcode == BO_GT || Opcode == BO_GE),
8522 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8523 }
else if (IneqCondIsCanonical && Opcode == BO_NE) {
8524 return setUB(
const_cast<Expr *
>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8528 return std::nullopt;
8530 std::optional<bool> Res;
8531 if (
auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8534 RBO->getOperatorLoc());
8535 }
else if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8536 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8537 BO->getSourceRange(), BO->getOperatorLoc());
8538 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8539 if (CE->getNumArgs() == 2) {
8540 Res = CheckAndSetCond(
8542 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8547 if (dependent() || SemaRef.CurContext->isDependentContext())
8549 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8550 << (IneqCondIsCanonical ? 1 : 0) << S->
getSourceRange() << LCDecl;
8554bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(
Expr *RHS) {
8561 if (
auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8562 if (BO->isAdditiveOp()) {
8563 bool IsAdd = BO->getOpcode() == BO_Add;
8564 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8565 return setStep(BO->getRHS(), !IsAdd);
8566 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8567 return setStep(BO->getLHS(),
false);
8569 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8570 bool IsAdd = CE->getOperator() == OO_Plus;
8571 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8572 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8573 return setStep(CE->getArg(1), !IsAdd);
8574 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8575 return setStep(CE->getArg(0),
false);
8578 if (dependent() || SemaRef.CurContext->isDependentContext())
8580 SemaRef.Diag(RHS->
getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8585bool OpenMPIterationSpaceChecker::checkAndSetInc(
Expr *S) {
8600 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8603 if (
auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8604 if (!ExprTemp->cleanupsHaveSideEffects())
8605 S = ExprTemp->getSubExpr();
8607 if (!CollapsedLoopVarDecls.empty()) {
8608 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8609 if (!FSEC.TraverseStmt(S)) {
8611 SemaRef.Diag(
Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8612 <<
Range.getEnd() << 2 << FSEC.getForbiddenVar();
8619 if (
auto *UO = dyn_cast<UnaryOperator>(S)) {
8620 if (UO->isIncrementDecrementOp() &&
8621 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8622 return setStep(SemaRef
8623 .ActOnIntegerConstant(UO->getBeginLoc(),
8624 (UO->isDecrementOp() ? -1 : 1))
8627 }
else if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8628 switch (BO->getOpcode()) {
8631 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8632 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8635 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8636 return checkAndSetIncRHS(BO->getRHS());
8641 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8642 switch (CE->getOperator()) {
8645 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8646 return setStep(SemaRef
8647 .ActOnIntegerConstant(
8649 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8655 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8656 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8659 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8660 return checkAndSetIncRHS(CE->getArg(1));
8666 if (dependent() || SemaRef.CurContext->isDependentContext())
8668 SemaRef.Diag(S->
getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8675 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8676 StringRef Name =
".capture_expr.") {
8684 auto I = Captures.find(
Capture);
8685 if (I != Captures.end())
8698 bool TestIsStrictOp,
bool RoundToStep,
8699 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8700 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures,
".new_step");
8703 llvm::APSInt LRes, SRes;
8704 bool IsLowerConst =
false, IsStepConst =
false;
8705 if (std::optional<llvm::APSInt> Res =
8708 IsLowerConst =
true;
8710 if (std::optional<llvm::APSInt> Res =
8715 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8716 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8717 (TestIsStrictOp && LRes.isStrictlyPositive()));
8718 bool NeedToReorganize =
false;
8720 if (!NoNeedToConvert && IsLowerConst &&
8721 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8722 NoNeedToConvert =
true;
8724 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8725 ? LRes.getBitWidth()
8726 : SRes.getBitWidth();
8727 LRes = LRes.extend(BW + 1);
8728 LRes.setIsSigned(
true);
8729 SRes = SRes.extend(BW + 1);
8730 SRes.setIsSigned(
true);
8732 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8733 LRes = LRes.trunc(BW);
8735 if (TestIsStrictOp) {
8736 unsigned BW = LRes.getBitWidth();
8737 LRes = LRes.extend(BW + 1);
8738 LRes.setIsSigned(
true);
8741 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8743 LRes = LRes.trunc(BW);
8745 NeedToReorganize = NoNeedToConvert;
8748 bool IsUpperConst =
false;
8749 if (std::optional<llvm::APSInt> Res =
8752 IsUpperConst =
true;
8754 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8755 (!RoundToStep || IsStepConst)) {
8756 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8757 : URes.getBitWidth();
8758 LRes = LRes.extend(BW + 1);
8759 LRes.setIsSigned(
true);
8760 URes = URes.extend(BW + 1);
8761 URes.setIsSigned(
true);
8763 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8764 NeedToReorganize = NoNeedToConvert;
8769 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8775 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8778 LowerSize > UpperSize ? LowerSize : UpperSize, 0);
8789 if (!Lower || !Upper || NewStep.
isInvalid())
8795 if (NeedToReorganize) {
8809 S, DefaultLoc, BO_Add, Diff.
get(),
8819 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.
get());
8823 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8839 S, DefaultLoc, BO_Sub, Diff.
get(),
8859 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Div, Diff.
get(), NewStep.
get());
8867Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8869 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
8878 if (InitDependOnLC) {
8879 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8880 if (!IS.MinValue || !IS.MaxValue)
8889 IS.CounterVar, MinValue.
get());
8894 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.
get(), LBVal);
8909 IS.CounterVar, MaxValue.
get());
8914 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.
get(), LBVal);
8923 tryBuildCapture(SemaRef, LBMinVal.
get(), Captures,
".lb_min").get();
8925 tryBuildCapture(SemaRef, LBMaxVal.
get(), Captures,
".lb_max").get();
8926 if (!LBMin || !LBMax)
8930 SemaRef.
BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8934 tryBuildCapture(SemaRef, MinLessMaxRes.
get(), Captures,
".min_less_max")
8938 if (*TestIsLessOp) {
8942 MinLessMax, LBMin, LBMax);
8945 LBVal = MinLB.
get();
8950 MinLessMax, LBMax, LBMin);
8953 LBVal = MaxLB.
get();
8957 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8960 LBVal = LBMinVal.
get();
8964 if (CondDependOnLC) {
8965 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8966 if (!IS.MinValue || !IS.MaxValue)
8975 IS.CounterVar, MinValue.
get());
8980 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.
get(), UBVal);
8995 IS.CounterVar, MaxValue.
get());
9000 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.
get(), UBVal);
9009 tryBuildCapture(SemaRef, UBMinVal.
get(), Captures,
".ub_min").get();
9011 tryBuildCapture(SemaRef, UBMaxVal.
get(), Captures,
".ub_max").get();
9012 if (!UBMin || !UBMax)
9016 SemaRef.
BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
9019 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.
get(),
9020 Captures,
".min_greater_max")
9024 if (*TestIsLessOp) {
9028 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
9031 UBVal = MaxUB.
get();
9036 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
9039 UBVal = MinUB.
get();
9042 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
9043 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
9044 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures,
".upper").get();
9045 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures,
".lower").get();
9046 if (!Upper || !Lower)
9049 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9050 Step, VarType, TestIsStrictOp,
9059 C.getTypeSize(
Type) >
C.getTypeSize(VarType);
9062 UseVarType ?
C.getTypeSize(VarType) :
C.getTypeSize(
Type);
9065 Type =
C.getIntTypeForBitwidth(NewSize, IsSigned);
9075 unsigned NewSize = (
C.getTypeSize(
Type) > 32) ? 64 : 32;
9076 if (NewSize !=
C.getTypeSize(
Type)) {
9077 if (NewSize <
C.getTypeSize(
Type)) {
9078 assert(NewSize == 64 &&
"incorrect loop var size");
9079 SemaRef.
Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
9080 << InitSrcRange << ConditionSrcRange;
9082 QualType NewType =
C.getIntTypeForBitwidth(
9084 C.getTypeSize(
Type) < NewSize);
9098std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
9099 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
9103 return std::make_pair(
nullptr,
nullptr);
9106 Expr *MinExpr =
nullptr;
9107 Expr *MaxExpr =
nullptr;
9108 Expr *LBExpr = *TestIsLessOp ? LB : UB;
9109 Expr *UBExpr = *TestIsLessOp ? UB : LB;
9111 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
9113 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
9115 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
9117 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
9118 if (!Upper || !Lower)
9119 return std::make_pair(
nullptr,
nullptr);
9129 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9130 Step, VarType, TestIsStrictOp,
9133 return std::make_pair(
nullptr,
nullptr);
9139 return std::make_pair(
nullptr,
nullptr);
9141 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures,
".new_step");
9143 return std::make_pair(
nullptr,
nullptr);
9144 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Mul, Diff.
get(), NewStep.
get());
9146 return std::make_pair(
nullptr,
nullptr);
9151 return std::make_pair(
nullptr,
nullptr);
9163 return std::make_pair(
nullptr,
nullptr);
9165 if (*TestIsLessOp) {
9169 S, DefaultLoc, BO_Add,
9173 return std::make_pair(
nullptr,
nullptr);
9178 S, DefaultLoc, BO_Sub,
9182 return std::make_pair(
nullptr,
nullptr);
9191 return std::make_pair(
nullptr,
nullptr);
9196 return std::make_pair(
nullptr,
nullptr);
9199 MaxExpr = Diff.
get();
9201 MinExpr = Diff.
get();
9203 return std::make_pair(MinExpr, MaxExpr);
9206Expr *OpenMPIterationSpaceChecker::buildFinalCondition(
Scope *S)
const {
9207 if (InitDependOnLC || CondDependOnLC)
9212Expr *OpenMPIterationSpaceChecker::buildPreCond(
9214 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
9219 if (CondDependOnLC || InitDependOnLC)
9230 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
9231 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
9237 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
9238 : (TestIsStrictOp ? BO_GT : BO_GE),
9239 NewLB.
get(), NewUB.
get());
9254DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9255 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9256 DSAStackTy &DSA)
const {
9257 auto *VD = dyn_cast<VarDecl>(LCDecl);
9262 const DSAStackTy::DSAVarData
Data =
9263 DSA.getTopDSA(LCDecl,
false);
9267 Captures.insert(std::make_pair(LCRef, Ref));
9273Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar()
const {
9290Expr *OpenMPIterationSpaceChecker::buildCounterInit()
const {
return LB; }
9293Expr *OpenMPIterationSpaceChecker::buildCounterStep()
const {
return Step; }
9295Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9297 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
SourceLocation Loc,
9303 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9304 "Expected only + or - operations for depend clauses.");
9316 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9318 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9319 if (!Upper || !Lower)
9323 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9324 false,
false, Captures);
9334 assert(
getLangOpts().OpenMP &&
"OpenMP is not active.");
9335 assert(
Init &&
"Expected loop in canonical form.");
9336 unsigned AssociatedLoops =
DSAStack->getAssociatedLoops();
9343 OpenMPIterationSpaceChecker ISC(
SemaRef,
true,
9345 if (!ISC.checkAndSetInit(
Init,
false)) {
9347 auto *VD = dyn_cast<VarDecl>(D);
9358 DSAStack->addLoopControlVariable(D, VD);
9360 if (LD != D->getCanonicalDecl()) {
9361 DSAStack->resetPossibleLoopCounter();
9362 if (
auto *Var = dyn_cast_or_null<VarDecl>(LD))
9375 DSAStackTy::DSAVarData DVar =
9379 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9382 ? (
DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9385 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9388 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9390 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9392 IsOpenMPTaskloopDirective(DKind) ||
9395 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9396 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9398 Diag(
Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9400 << getOpenMPDirectiveName(DKind, OMPVersion)
9402 if (DVar.RefExpr ==
nullptr)
9403 DVar.CKind = PredeterminedCKind;
9405 }
else if (LoopDeclRefExpr) {
9410 if (DVar.CKind == OMPC_unknown)
9411 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9415 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9420class OMPDoacrossKind {
9423 return C->getDependenceType() == OMPC_DOACROSS_source ||
9424 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9427 return C->getDependenceType() == OMPC_DOACROSS_sink;
9429 bool isSinkIter(
const OMPDoacrossClause *
C) {
9430 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9438 unsigned CurrentNestedLoopCount,
unsigned NestedLoopCount,
9439 unsigned TotalNestedLoopCount,
Expr *CollapseLoopCountExpr,
9440 Expr *OrderedLoopCountExpr,
9443 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9444 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls) {
9449 if (
auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9450 S = CanonLoop->getLoopStmt();
9451 auto *For = dyn_cast_or_null<ForStmt>(S);
9452 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9454 if (!For && (SemaRef.
LangOpts.OpenMP <= 45 || !CXXFor)) {
9455 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
9457 << (CollapseLoopCountExpr !=
nullptr || OrderedLoopCountExpr !=
nullptr)
9458 << getOpenMPDirectiveName(DKind, OMPVersion) << TotalNestedLoopCount
9459 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9460 if (TotalNestedLoopCount > 1) {
9461 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9462 SemaRef.
Diag(DSA.getConstructLoc(),
9463 diag::note_omp_collapse_ordered_expr)
9466 else if (CollapseLoopCountExpr)
9468 diag::note_omp_collapse_ordered_expr)
9470 else if (OrderedLoopCountExpr)
9472 diag::note_omp_collapse_ordered_expr)
9477 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9483 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9484 For ? For->getForLoc() : CXXFor->getForLoc(),
9485 CollapsedLoopVarDecls);
9488 Stmt *
Init = For ? For->getInit() : CXXFor->getBeginStmt();
9489 if (ISC.checkAndSetInit(
Init))
9492 bool HasErrors =
false;
9495 if (
ValueDecl *LCDecl = ISC.getLoopDecl()) {
9505 SemaRef.
Diag(
Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9519 VarsWithImplicitDSA.erase(LCDecl);
9523 "DSA for non-loop vars");
9526 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9529 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9536 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9537 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9538 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9539 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9546 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9547 ISC.buildCounterVar(Captures, DSA);
9548 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9549 ISC.buildPrivateCounterVar();
9550 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9551 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9552 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9553 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9554 ISC.getConditionSrcRange();
9555 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9556 ISC.getIncrementSrcRange();
9557 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9558 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9559 ISC.isStrictTestOp();
9560 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9561 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9562 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9563 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9564 ISC.buildFinalCondition(DSA.getCurScope());
9565 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9566 ISC.doesInitDependOnLC();
9567 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9568 ISC.doesCondDependOnLC();
9569 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9570 ISC.getLoopDependentIdx();
9573 (ResultIterSpaces[CurrentNestedLoopCount].PreCond ==
nullptr ||
9574 ResultIterSpaces[CurrentNestedLoopCount].NumIterations ==
nullptr ||
9575 ResultIterSpaces[CurrentNestedLoopCount].CounterVar ==
nullptr ||
9576 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar ==
nullptr ||
9577 ResultIterSpaces[CurrentNestedLoopCount].CounterInit ==
nullptr ||
9578 ResultIterSpaces[CurrentNestedLoopCount].CounterStep ==
nullptr);
9579 if (!HasErrors && DSA.isOrderedRegion()) {
9580 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9581 if (CurrentNestedLoopCount <
9582 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9583 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9584 CurrentNestedLoopCount,
9585 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9586 DSA.getOrderedRegionParam().second->setLoopCounter(
9587 CurrentNestedLoopCount,
9588 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9591 for (
auto &Pair : DSA.getDoacrossDependClauses()) {
9592 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9593 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9595 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9596 if (CurrentNestedLoopCount >= NumLoops) {
9600 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9601 Pair.second.size() <= CurrentNestedLoopCount) {
9603 DependC->setLoopData(CurrentNestedLoopCount,
nullptr);
9606 OMPDoacrossKind ODK;
9607 if (DoacrossC && ODK.isSink(DoacrossC) &&
9608 Pair.second.size() <= CurrentNestedLoopCount) {
9610 DoacrossC->setLoopData(CurrentNestedLoopCount,
nullptr);
9615 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9616 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9617 (DoacrossC && ODK.isSource(DoacrossC)))
9618 CntValue = ISC.buildOrderedLoopData(
9620 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9622 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9625 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9633 CntValue = ISC.buildOrderedLoopData(
9635 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9636 DepLoc, Inc, clang::OO_Minus);
9638 CntValue = ISC.buildOrderedLoopData(
9640 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9641 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9642 Pair.second[CurrentNestedLoopCount].second);
9644 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9646 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9657 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9661 : tryBuildCapture(SemaRef, Start.
get(), Captures);
9682 bool IsNonRectangularLB,
9683 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures =
nullptr) {
9692 NewStep = tryBuildCapture(SemaRef, Step.
get(), *Captures);
9707 if (Captures && !IsNonRectangularLB)
9708 NewStart = tryBuildCapture(SemaRef, Start.
get(), *Captures);
9717 Update.get()->getType()->isOverloadableType()) {
9724 SemaRef.
BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9725 VarRef.
get(), SavedUpdate.
get());
9736 NewStart.
get(), SavedUpdate.
get());
9761 unsigned HasBits =
C.getTypeSize(OldType);
9762 if (HasBits >= Bits)
9765 QualType NewType =
C.getIntTypeForBitwidth(Bits,
true);
9775 if (std::optional<llvm::APSInt> Result =
9777 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9784 if (!PreInits.empty()) {
9805 if (
auto *CS = dyn_cast<CompoundStmt>(Item))
9814 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9815 if (!Captures.empty()) {
9817 for (
const auto &Pair : Captures)
9818 PreInits.push_back(Pair.second->getDecl());
9826 if (PreInits.empty())
9830 for (
Stmt *S : PreInits)
9837 Expr *PostUpdate =
nullptr;
9838 if (!PostUpdates.empty()) {
9839 for (
Expr *E : PostUpdates) {
9845 PostUpdate = PostUpdate
9859 int NestingDepth = 0;
9860 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
9882 if (NestingDepth > 0)
9893 Expr *OrderedLoopCountExpr,
Stmt *AStmt,
Sema &SemaRef,
9896 OMPLoopBasedDirective::HelperExprs &Built) {
9900 if ((CollapseLoopCountExpr && CollapseLoopCountExpr->
containsErrors()) ||
9901 (OrderedLoopCountExpr && OrderedLoopCountExpr->
containsErrors()))
9904 unsigned NestedLoopCount = 1;
9905 bool SupportsNonPerfectlyNested = (SemaRef.
LangOpts.OpenMP >= 50) &&
9909 if (CollapseLoopCountExpr) {
9914 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9923 unsigned OrderedLoopCount = 1;
9924 if (OrderedLoopCountExpr) {
9930 llvm::APSInt Result = EVResult.
Val.
getInt();
9931 if (Result.getLimitedValue() < NestedLoopCount) {
9933 diag::err_omp_wrong_ordered_loop_count)
9936 diag::note_collapse_loop_count)
9939 OrderedLoopCount = Result.getLimitedValue();
9947 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9948 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9950 if (!OMPLoopBasedDirective::doForAllLoops(
9953 SupportsNonPerfectlyNested, NumLoops,
9954 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9955 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9956 &IterSpaces, &Captures,
9957 &CollapsedLoopVarDecls](
unsigned Cnt,
Stmt *CurStmt) {
9959 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9960 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9961 VarsWithImplicitDSA, IterSpaces, Captures,
9962 CollapsedLoopVarDecls))
9964 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9965 IterSpaces[Cnt].CounterVar) {
9969 Captures[DRE] = DRE;
9975 Stmt *DependentPreInits = Transform->getPreInits();
9976 if (!DependentPreInits)
9983 for (
Stmt *S : Constituents) {
9984 if (
auto *DC = dyn_cast<DeclStmt>(S)) {
9985 for (
Decl *
C : DC->decls()) {
9988 SemaRef, D, D->getType().getNonReferenceType(),
9991 Captures[Ref] = Ref;
9998 Built.clear(NestedLoopCount);
10001 return NestedLoopCount;
10034 auto PreCond =
ExprResult(IterSpaces[0].PreCond);
10035 Expr *N0 = IterSpaces[0].NumIterations;
10054 return NestedLoopCount;
10057 bool AllCountsNeedLessThan32Bits =
C.getTypeSize(N0->
getType()) < 32;
10059 Scope *CurScope = DSA.getCurScope();
10060 for (
unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
10061 if (PreCond.isUsable()) {
10063 SemaRef.
BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
10064 PreCond.get(), IterSpaces[Cnt].PreCond);
10066 Expr *N = IterSpaces[Cnt].NumIterations;
10068 AllCountsNeedLessThan32Bits &=
C.getTypeSize(N->
getType()) < 32;
10071 CurScope, Loc, BO_Mul, LastIteration32.
get(),
10079 CurScope, Loc, BO_Mul, LastIteration64.
get(),
10089 if (SemaRef.
getLangOpts().OpenMPOptimisticCollapse ||
10091 C.getTypeSize(LastIteration32.
get()->
getType()) == 32 &&
10092 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
10096 LastIteration64.
get(), SemaRef))))
10097 LastIteration = LastIteration32;
10116 LastIteration.
get(),
10128 tryBuildCapture(SemaRef, LastIteration.
get(), Captures);
10129 LastIteration = SaveRef;
10142 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
10171 buildVarDecl(SemaRef, InitLoc, StrideVType,
".omp.stride");
10180 UB.
get(), LastIteration.
get());
10183 LastIteration.
get(), UB.
get());
10184 EUB = SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, UB.
get(),
10195 buildVarDecl(SemaRef, InitLoc, VType,
".omp.comb.lb");
10203 buildVarDecl(SemaRef, InitLoc, VType,
".omp.comb.ub");
10209 CurScope, InitLoc, BO_GT, CombUB.
get(), LastIteration.
get());
10212 LastIteration.
get(), CombUB.
get());
10213 CombEUB = SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.
get(),
10222 "Unexpected number of parameters in loop combined directive");
10263 SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, IV.
get(), CombRHS);
10269 bool UseStrictCompare =
10271 llvm::all_of(IterSpaces, [](
const LoopIterationSpace &LIS) {
10272 return LIS.IsStrictCompare;
10278 if (UseStrictCompare) {
10281 .
BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
10293 UseStrictCompare ? BO_LT : BO_LE, IV.
get(),
10296 NumIterations.
get());
10299 CombDistCond = SemaRef.
BuildBinOp(CurScope, CondLoc, BO_LT, IV.
get(),
10300 NumIterations.
get());
10305 Expr *BoundCombUB = CombUB.
get();
10306 if (UseStrictCompare) {
10310 CurScope, CondLoc, BO_Add, BoundCombUB,
10318 SemaRef.
BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10319 IV.
get(), BoundCombUB);
10326 if (!Inc.isUsable())
10328 Inc = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, IV.
get(), Inc.get());
10330 if (!Inc.isUsable())
10337 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10343 NextLB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Add, LB.
get(), ST.
get());
10354 NextUB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Add, UB.
get(), ST.
get());
10370 CombNextLB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.
get(),
10382 CombNextUB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.
get(),
10396 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10399 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.
get(), BoundUB);
10400 assert(DistCond.
isUsable() &&
"distribute cond expr was not built");
10404 assert(DistInc.
isUsable() &&
"distribute inc expr was not built");
10405 DistInc = SemaRef.
BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.
get(),
10409 assert(DistInc.
isUsable() &&
"distribute inc expr was not built");
10420 DistEUBLoc, NewPrevUB.
get());
10425 UB.
get(), NewPrevUB.
get());
10427 DistEUBLoc, DistEUBLoc, IsUBGreater.
get(), NewPrevUB.
get(), UB.
get());
10428 PrevEUB = SemaRef.
BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.
get(),
10436 Expr *BoundPrevUB = PrevUB.
get();
10437 if (UseStrictCompare) {
10441 CurScope, CondLoc, BO_Add, BoundPrevUB,
10449 SemaRef.
BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10450 IV.
get(), BoundPrevUB);
10454 bool HasErrors =
false;
10455 Built.Counters.resize(NestedLoopCount);
10456 Built.Inits.resize(NestedLoopCount);
10457 Built.Updates.resize(NestedLoopCount);
10458 Built.Finals.resize(NestedLoopCount);
10459 Built.DependentCounters.resize(NestedLoopCount);
10460 Built.DependentInits.resize(NestedLoopCount);
10461 Built.FinalsConditions.resize(NestedLoopCount);
10479 for (
unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10480 LoopIterationSpace &IS = IterSpaces[Cnt];
10486 for (
unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10487 Prod = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.
get(),
10488 IterSpaces[K].NumIterations);
10493 if (Cnt + 1 < NestedLoopCount)
10507 if (Cnt + 1 < NestedLoopCount)
10508 Prod = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.
get(),
10512 Acc = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.
get(), Prod.
get());
10521 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10522 if (!
Init.isUsable()) {
10527 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10528 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10529 if (!
Update.isUsable()) {
10537 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10538 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10539 if (!Final.isUsable()) {
10544 if (!
Update.isUsable() || !Final.isUsable()) {
10549 Built.Counters[Cnt] = IS.CounterVar;
10550 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10551 Built.Inits[Cnt] =
Init.get();
10552 Built.Updates[Cnt] =
Update.get();
10553 Built.Finals[Cnt] = Final.get();
10554 Built.DependentCounters[Cnt] =
nullptr;
10555 Built.DependentInits[Cnt] =
nullptr;
10556 Built.FinalsConditions[Cnt] =
nullptr;
10557 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10558 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10559 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10560 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10569 Built.IterationVarRef = IV.
get();
10570 Built.LastIteration = LastIteration.
get();
10571 Built.NumIterations = NumIterations.
get();
10572 Built.CalcLastIteration = SemaRef
10576 Built.PreCond = PreCond.get();
10578 Built.Cond =
Cond.get();
10579 Built.Init =
Init.get();
10580 Built.Inc = Inc.get();
10581 Built.LB = LB.
get();
10582 Built.UB = UB.
get();
10583 Built.IL = IL.
get();
10584 Built.ST = ST.
get();
10585 Built.EUB = EUB.
get();
10586 Built.NLB = NextLB.
get();
10587 Built.NUB = NextUB.
get();
10588 Built.PrevLB = PrevLB.
get();
10589 Built.PrevUB = PrevUB.
get();
10590 Built.DistInc = DistInc.
get();
10591 Built.PrevEUB = PrevEUB.
get();
10592 Built.DistCombinedFields.LB = CombLB.
get();
10593 Built.DistCombinedFields.UB = CombUB.
get();
10594 Built.DistCombinedFields.EUB = CombEUB.
get();
10595 Built.DistCombinedFields.Init = CombInit.
get();
10596 Built.DistCombinedFields.Cond = CombCond.
get();
10597 Built.DistCombinedFields.NLB = CombNextLB.
get();
10598 Built.DistCombinedFields.NUB = CombNextUB.
get();
10599 Built.DistCombinedFields.DistCond = CombDistCond.
get();
10600 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.
get();
10602 return NestedLoopCount;
10606 auto CollapseClauses =
10607 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10608 if (CollapseClauses.begin() != CollapseClauses.end())
10609 return (*CollapseClauses.begin())->getNumForLoops();
10614 auto OrderedClauses =
10615 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10616 if (OrderedClauses.begin() != OrderedClauses.end())
10617 return (*OrderedClauses.begin())->getNumForLoops();
10626 for (
const OMPClause *Clause : Clauses) {
10627 if (Clause->getClauseKind() == OMPC_safelen)
10629 else if (Clause->getClauseKind() == OMPC_simdlen)
10631 if (Safelen && Simdlen)
10635 if (Simdlen && Safelen) {
10649 llvm::APSInt SimdlenRes = SimdlenResult.
Val.
getInt();
10650 llvm::APSInt SafelenRes = SafelenResult.
Val.
getInt();
10655 if (SimdlenRes > SafelenRes) {
10657 diag::err_omp_wrong_simdlen_safelen_values)
10674 OMPLoopBasedDirective::HelperExprs B;
10680 if (NestedLoopCount == 0)
10689 auto *SimdDirective = OMPSimdDirective::Create(
10690 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10691 return SimdDirective;
10701 OMPLoopBasedDirective::HelperExprs B;
10707 if (NestedLoopCount == 0)
10713 auto *ForDirective = OMPForDirective::Create(
10714 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10716 return ForDirective;
10728 OMPLoopBasedDirective::HelperExprs B;
10731 unsigned NestedLoopCount =
10734 VarsWithImplicitDSA, B);
10735 if (NestedLoopCount == 0)
10744 return OMPForSimdDirective::Create(
getASTContext(), StartLoc, EndLoc,
10745 NestedLoopCount, Clauses, AStmt, B);
10749 Stmt *AStmt, DSAStackTy *Stack) {
10754 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
10755 auto BaseStmt = AStmt;
10756 while (
auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10758 if (
auto *
C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10759 auto S =
C->children();
10760 if (S.begin() == S.end())
10764 for (
Stmt *SectionStmt : llvm::drop_begin(S)) {
10767 SemaRef.
Diag(SectionStmt->getBeginLoc(),
10768 diag::err_omp_sections_substmt_not_section)
10769 << getOpenMPDirectiveName(DKind, OMPVersion);
10773 ->setHasCancel(Stack->isCancelRegion());
10776 SemaRef.
Diag(AStmt->
getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10777 << getOpenMPDirectiveName(DKind, OMPVersion);
10790 SemaRef.setFunctionHasBranchProtectedScope();
10792 return OMPSectionsDirective::Create(
10803 SemaRef.setFunctionHasBranchProtectedScope();
10806 return OMPSectionDirective::Create(
getASTContext(), StartLoc, EndLoc, AStmt,
10812 if (
auto *CE = dyn_cast<CallExpr>(E))
10813 if (CE->getDirectCallee())
10834 if (!
SemaRef.CurContext->isDependentContext()) {
10835 Expr *TargetCall =
nullptr;
10837 auto *E = dyn_cast<Expr>(S);
10845 if (
auto *BO = dyn_cast<BinaryOperator>(E)) {
10846 if (BO->getOpcode() == BO_Assign)
10849 if (
auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10850 if (COCE->getOperator() == OO_Equal)
10862 SemaRef.setFunctionHasBranchProtectedScope();
10865 Clauses, AStmt, TargetCallLoc);
10870 DSAStackTy *Stack) {
10871 bool ErrorFound =
false;
10873 if (
auto *LPC = dyn_cast<OMPLastprivateClause>(
C)) {
10874 for (
Expr *RefExpr : LPC->varlist()) {
10877 Expr *SimpleRefExpr = RefExpr;
10880 auto &&Info = Stack->isLoopControlVariable(D);
10883 S.
Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10884 << getOpenMPDirectiveName(K, OMPVersion);
10908 OMPLoopDirective::HelperExprs B;
10913 if (NestedLoopCount == 0)
10916 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10917 "omp loop exprs were not built");
10920 NestedLoopCount, Clauses, AStmt, B);
10937 OMPLoopDirective::HelperExprs B;
10939 unsigned NestedLoopCount =
10942 VarsWithImplicitDSA, B);
10943 if (NestedLoopCount == 0)
10946 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10947 "omp loop exprs were not built");
10949 DSAStack->setParentTeamsRegionLoc(StartLoc);
10952 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10971 OMPLoopDirective::HelperExprs B;
10973 unsigned NestedLoopCount =
10976 VarsWithImplicitDSA, B);
10977 if (NestedLoopCount == 0)
10980 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10981 "omp loop exprs were not built");
10984 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11004 OMPLoopDirective::HelperExprs B;
11006 unsigned NestedLoopCount =
11009 VarsWithImplicitDSA, B);
11010 if (NestedLoopCount == 0)
11013 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11014 "omp loop exprs were not built");
11017 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11036 OMPLoopDirective::HelperExprs B;
11038 unsigned NestedLoopCount =
11041 VarsWithImplicitDSA, B);
11042 if (NestedLoopCount == 0)
11045 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11046 "omp loop exprs were not built");
11049 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11061 SemaRef.setFunctionHasBranchProtectedScope();
11066 const OMPClause *Copyprivate =
nullptr;
11067 for (
const OMPClause *Clause : Clauses) {
11068 if (Clause->getClauseKind() == OMPC_nowait)
11070 else if (Clause->getClauseKind() == OMPC_copyprivate)
11071 Copyprivate = Clause;
11072 if (Copyprivate && Nowait) {
11074 diag::err_omp_single_copyprivate_with_nowait);
11080 return OMPSingleDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses,
11090 SemaRef.setFunctionHasBranchProtectedScope();
11092 return OMPMasterDirective::Create(
getASTContext(), StartLoc, EndLoc, AStmt);
11102 SemaRef.setFunctionHasBranchProtectedScope();
11114 bool ErrorFound =
false;
11117 bool DependentHint =
false;
11119 if (
C->getClauseKind() == OMPC_hint) {
11121 Diag(
C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
11127 DependentHint =
true;
11130 HintLoc =
C->getBeginLoc();
11136 const auto Pair =
DSAStack->getCriticalWithHint(DirName);
11137 if (Pair.first && DirName.
getName() && !DependentHint) {
11138 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
11139 Diag(StartLoc, diag::err_omp_critical_with_hint);
11141 Diag(HintLoc, diag::note_omp_critical_hint_here)
11142 << 0 <<
toString(Hint, 10,
false);
11144 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
11145 if (
const auto *
C = Pair.first->getSingleClause<
OMPHintClause>()) {
11146 Diag(
C->getBeginLoc(), diag::note_omp_critical_hint_here)
11151 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
11156 SemaRef.setFunctionHasBranchProtectedScope();
11158 auto *Dir = OMPCriticalDirective::Create(
getASTContext(), DirName, StartLoc,
11159 EndLoc, Clauses, AStmt);
11160 if (!Pair.first && DirName.
getName() && !DependentHint)
11161 DSAStack->addCriticalWithHint(Dir, Hint);
11173 OMPLoopBasedDirective::HelperExprs B;
11176 unsigned NestedLoopCount =
11179 VarsWithImplicitDSA, B);
11180 if (NestedLoopCount == 0)
11186 return OMPParallelForDirective::Create(
11187 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11200 OMPLoopBasedDirective::HelperExprs B;
11203 unsigned NestedLoopCount =
11206 VarsWithImplicitDSA, B);
11207 if (NestedLoopCount == 0)
11216 return OMPParallelForSimdDirective::Create(
11217 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11228 return OMPParallelMasterDirective::Create(
11230 DSAStack->getTaskgroupReductionRef());
11241 return OMPParallelMaskedDirective::Create(
11243 DSAStack->getTaskgroupReductionRef());
11252 SemaRef.setFunctionHasBranchProtectedScope();
11254 return OMPParallelSectionsDirective::Create(
11264 bool ErrorFound =
false;
11266 if (llvm::is_contained(MutuallyExclusiveClauses,
C->getClauseKind())) {
11270 S.
Diag(
C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
11293 {OMPC_detach, OMPC_mergeable}))
11298 return OMPTaskDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses,
11299 AStmt,
DSAStack->isCancelRegion());
11304 return OMPTaskyieldDirective::Create(
getASTContext(), StartLoc, EndLoc);
11309 return OMPBarrierDirective::Create(
getASTContext(), StartLoc, EndLoc);
11315 bool InExContext) {
11316 const OMPAtClause *AtC =
11317 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11319 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11320 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
11324 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11325 const OMPSeverityClause *SeverityC =
11326 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11327 const OMPMessageClause *MessageC =
11328 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11329 std::optional<std::string> SL =
11330 MessageC ? MessageC->tryEvaluateString(
getASTContext()) : std::nullopt;
11332 if (MessageC && !SL)
11333 Diag(MessageC->getMessageString()->getBeginLoc(),
11334 diag::warn_clause_expected_string)
11336 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11337 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
11338 << SL.value_or(
"WARNING");
11340 Diag(StartLoc, diag::err_diagnose_if_succeeded) << SL.value_or(
"ERROR");
11341 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11352 const OMPNowaitClause *NowaitC =
11353 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11355 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11357 if (NowaitC && !HasDependC) {
11358 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11362 return OMPTaskwaitDirective::Create(
getASTContext(), StartLoc, EndLoc,
11375 SemaRef.setFunctionHasBranchProtectedScope();
11377 return OMPTaskgroupDirective::Create(
getASTContext(), StartLoc, EndLoc,
11379 DSAStack->getTaskgroupReductionRef());
11388 if (
C->getClauseKind() == OMPC_flush)
11397 if (
C->getClauseKind() == OMPC_acq_rel ||
11398 C->getClauseKind() == OMPC_acquire ||
11399 C->getClauseKind() == OMPC_release ||
11400 C->getClauseKind() == OMPC_seq_cst ) {
11401 if (MemOrderKind != OMPC_unknown) {
11402 Diag(
C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11403 << getOpenMPDirectiveName(OMPD_flush, OMPVersion) << 1
11405 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11408 MemOrderKind =
C->getClauseKind();
11409 MemOrderLoc =
C->getBeginLoc();
11413 if (FC && OrderClause) {
11414 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11416 Diag(OrderClause->
getBeginLoc(), diag::note_omp_flush_order_clause_here)
11420 return OMPFlushDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses);
11426 if (Clauses.empty()) {
11427 Diag(StartLoc, diag::err_omp_depobj_expected);
11429 }
else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11430 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11434 if (Clauses.size() > 2) {
11435 Diag(Clauses[2]->getBeginLoc(),
11436 diag::err_omp_depobj_single_clause_expected);
11438 }
else if (Clauses.size() < 1) {
11439 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11442 return OMPDepobjDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses);
11449 if (Clauses.size() != 1) {
11450 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11451 diag::err_omp_scan_single_clause_expected);
11460 return StmtError(
Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11461 << getOpenMPDirectiveName(OMPD_scan, OMPVersion) << 5);
11466 if (
DSAStack->doesParentHasScanDirective()) {
11467 Diag(StartLoc, diag::err_omp_several_directives_in_region) <<
"scan";
11469 diag::note_omp_previous_directive)
11473 DSAStack->setParentHasScanDirective(StartLoc);
11481 const OMPClause *DependFound =
nullptr;
11482 const OMPClause *DependSourceClause =
nullptr;
11483 const OMPClause *DependSinkClause =
nullptr;
11484 const OMPClause *DoacrossFound =
nullptr;
11485 const OMPClause *DoacrossSourceClause =
nullptr;
11486 const OMPClause *DoacrossSinkClause =
nullptr;
11487 bool ErrorFound =
false;
11491 auto DOC = dyn_cast<OMPDoacrossClause>(
C);
11492 auto DC = dyn_cast<OMPDependClause>(
C);
11494 DependFound = DC ?
C :
nullptr;
11495 DoacrossFound = DOC ?
C :
nullptr;
11496 OMPDoacrossKind ODK;
11497 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11498 (DOC && (ODK.isSource(DOC)))) {
11499 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11501 Diag(
C->getBeginLoc(), diag::err_omp_more_one_clause)
11502 << getOpenMPDirectiveName(OMPD_ordered, OMPVersion)
11508 DependSourceClause =
C;
11510 DoacrossSourceClause =
C;
11512 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11513 Diag(
C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11514 << (DC ?
"depend" :
"doacross") << 0;
11517 }
else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11518 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11519 if (DependSourceClause || DoacrossSourceClause) {
11520 Diag(
C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11521 << (DC ?
"depend" :
"doacross") << 1;
11525 DependSinkClause =
C;
11527 DoacrossSinkClause =
C;
11529 }
else if (
C->getClauseKind() == OMPC_threads) {
11531 }
else if (
C->getClauseKind() == OMPC_simd) {
11535 if (!ErrorFound && !SC &&
11540 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11543 }
else if ((DependFound || DoacrossFound) && (TC || SC)) {
11546 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11549 : SC->getClauseKind());
11551 }
else if ((DependFound || DoacrossFound) &&
11552 !
DSAStack->getParentOrderedRegionParam().first) {
11555 Diag(Loc, diag::err_omp_ordered_directive_without_param)
11559 }
else if (TC || Clauses.empty()) {
11560 if (
const Expr *Param =
DSAStack->getParentOrderedRegionParam().first) {
11562 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11563 << (TC !=
nullptr);
11564 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11568 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11576 if (!DependFound && !DoacrossFound) {
11577 if (
DSAStack->doesParentHasOrderedDirective()) {
11578 Diag(StartLoc, diag::err_omp_several_directives_in_region) <<
"ordered";
11580 diag::note_omp_previous_directive)
11584 DSAStack->setParentHasOrderedDirective(StartLoc);
11590 SemaRef.setFunctionHasBranchProtectedScope();
11593 return OMPOrderedDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses,
11600class OpenMPAtomicUpdateChecker {
11602 enum ExprAnalysisErrorCode {
11606 NotABinaryOrUnaryExpression,
11608 NotAnUnaryIncDecExpression,
11614 NotABinaryExpression,
11617 NotABinaryOperator,
11620 NotAnUpdateExpression,
11623 NotAValidExpression,
11649 OpenMPAtomicUpdateChecker(
Sema &SemaRef)
11659 bool checkStatement(Stmt *S,
unsigned DiagId = 0,
unsigned NoteId = 0);
11661 Expr *
getX()
const {
return X; }
11663 Expr *
getExpr()
const {
return E; }
11677 bool checkBinaryOperation(BinaryOperator *AtomicBinOp,
unsigned DiagId = 0,
11678 unsigned NoteId = 0);
11681bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11682 BinaryOperator *AtomicBinOp,
unsigned DiagId,
unsigned NoteId) {
11683 ExprAnalysisErrorCode ErrorFound = NoError;
11689 if (AtomicBinOp->
getOpcode() == BO_Assign) {
11691 if (
const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11693 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11694 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11695 AtomicInnerBinOp->isBitwiseOp()) {
11696 Op = AtomicInnerBinOp->getOpcode();
11697 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11698 Expr *LHS = AtomicInnerBinOp->getLHS();
11699 Expr *RHS = AtomicInnerBinOp->getRHS();
11700 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11707 if (XId == LHSId) {
11710 }
else if (XId == RHSId) {
11714 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11715 ErrorRange = AtomicInnerBinOp->getSourceRange();
11716 NoteLoc =
X->getExprLoc();
11717 NoteRange =
X->getSourceRange();
11718 ErrorFound = NotAnUpdateExpression;
11721 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11722 ErrorRange = AtomicInnerBinOp->getSourceRange();
11723 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11725 ErrorFound = NotABinaryOperator;
11730 ErrorFound = NotABinaryExpression;
11737 ErrorFound = NotAnAssignmentOp;
11739 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11740 SemaRef.
Diag(ErrorLoc, DiagId) << ErrorRange;
11741 SemaRef.
Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11745 E =
X = UpdateExpr =
nullptr;
11746 return ErrorFound != NoError;
11749bool OpenMPAtomicUpdateChecker::checkStatement(
Stmt *S,
unsigned DiagId,
11751 ExprAnalysisErrorCode ErrorFound = NoError;
11762 if (
auto *AtomicBody = dyn_cast<Expr>(S)) {
11763 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11764 if (AtomicBody->getType()->isScalarType() ||
11765 AtomicBody->isInstantiationDependent()) {
11766 if (
const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11767 AtomicBody->IgnoreParenImpCasts())) {
11770 AtomicCompAssignOp->getOpcode());
11771 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11772 E = AtomicCompAssignOp->getRHS();
11775 }
else if (
auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11776 AtomicBody->IgnoreParenImpCasts())) {
11778 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11780 }
else if (
const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11781 AtomicBody->IgnoreParenImpCasts())) {
11783 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11785 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11786 OpLoc = AtomicUnaryOp->getOperatorLoc();
11787 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11791 ErrorFound = NotAnUnaryIncDecExpression;
11792 ErrorLoc = AtomicUnaryOp->getExprLoc();
11793 ErrorRange = AtomicUnaryOp->getSourceRange();
11794 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11797 }
else if (!AtomicBody->isInstantiationDependent()) {
11798 ErrorFound = NotABinaryOrUnaryExpression;
11799 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11800 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11801 }
else if (AtomicBody->containsErrors()) {
11802 ErrorFound = NotAValidExpression;
11803 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11804 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11807 ErrorFound = NotAScalarType;
11808 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11809 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
11812 ErrorFound = NotAnExpression;
11814 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
11816 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11817 SemaRef.
Diag(ErrorLoc, DiagId) << ErrorRange;
11818 SemaRef.
Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11822 E =
X = UpdateExpr =
nullptr;
11823 if (ErrorFound == NoError && E &&
X) {
11840 UpdateExpr =
Update.get();
11842 return ErrorFound != NoError;
11846llvm::FoldingSetNodeID getNodeId(
ASTContext &Context,
const Expr *S) {
11847 llvm::FoldingSetNodeID Id;
11853bool checkIfTwoExprsAreSame(
ASTContext &Context,
const Expr *LHS,
11855 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11858class OpenMPAtomicCompareChecker {
11905 struct ErrorInfoTy {
11907 SourceLocation ErrorLoc;
11908 SourceRange ErrorRange;
11909 SourceLocation NoteLoc;
11910 SourceRange NoteRange;
11913 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11916 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11918 Expr *
getX()
const {
return X; }
11919 Expr *getE()
const {
return E; }
11920 Expr *
getD()
const {
return D; }
11921 Expr *getCond()
const {
return C; }
11922 bool isXBinopExpr()
const {
return IsXBinopExpr; }
11926 ASTContext &ContextRef;
11941 bool IsXBinopExpr =
true;
11944 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11947 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11950 bool checkType(ErrorInfoTy &ErrorInfo)
const;
11952 static bool CheckValue(
const Expr *E, ErrorInfoTy &ErrorInfo,
11953 bool ShouldBeLValue,
bool ShouldBeInteger =
false) {
11957 if (ShouldBeLValue && !E->
isLValue()) {
11958 ErrorInfo.Error = ErrorTy::XNotLValue;
11959 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->
getExprLoc();
11960 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->
getSourceRange();
11966 ErrorInfo.Error = ErrorTy::NotScalar;
11967 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->
getExprLoc();
11968 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->
getSourceRange();
11972 ErrorInfo.Error = ErrorTy::NotInteger;
11973 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->
getExprLoc();
11974 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->
getSourceRange();
11982bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(
IfStmt *S,
11983 ErrorInfoTy &ErrorInfo) {
11985 if (
auto *CS = dyn_cast<CompoundStmt>(Then)) {
11986 if (CS->body_empty()) {
11987 ErrorInfo.Error = ErrorTy::NoStmt;
11988 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11989 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11992 if (CS->size() > 1) {
11993 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11994 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11995 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
11998 Then = CS->body_front();
12001 auto *BO = dyn_cast<BinaryOperator>(Then);
12003 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12004 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12005 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12008 if (BO->getOpcode() != BO_Assign) {
12009 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12010 ErrorInfo.ErrorLoc = BO->getExprLoc();
12011 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12012 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12018 auto *
Cond = dyn_cast<BinaryOperator>(S->
getCond());
12019 auto *
Call = dyn_cast<CXXOperatorCallExpr>(S->
getCond());
12020 Expr *LHS =
nullptr;
12021 Expr *RHS =
nullptr;
12023 LHS =
Cond->getLHS();
12024 RHS =
Cond->getRHS();
12026 LHS =
Call->getArg(0);
12027 RHS =
Call->getArg(1);
12029 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12035 if ((
Cond &&
Cond->getOpcode() == BO_EQ) ||
12036 (
Call &&
Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12039 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS)) {
12041 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12044 ErrorInfo.Error = ErrorTy::InvalidComparison;
12046 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12050 }
else if ((
Cond &&
12051 (
Cond->getOpcode() == BO_LT ||
Cond->getOpcode() == BO_GT)) ||
12053 (
Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12054 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12056 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS) &&
12057 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12059 }
else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12060 checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12062 IsXBinopExpr =
false;
12064 ErrorInfo.Error = ErrorTy::InvalidComparison;
12066 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12071 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12078 ErrorInfo.Error = ErrorTy::UnexpectedElse;
12087bool OpenMPAtomicCompareChecker::checkCondExprStmt(
Stmt *S,
12088 ErrorInfoTy &ErrorInfo) {
12089 auto *BO = dyn_cast<BinaryOperator>(S);
12091 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12092 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->
getBeginLoc();
12093 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
12096 if (BO->getOpcode() != BO_Assign) {
12097 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12098 ErrorInfo.ErrorLoc = BO->getExprLoc();
12099 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12100 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12106 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
12108 ErrorInfo.Error = ErrorTy::NotCondOp;
12109 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
12110 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
12114 if (!checkIfTwoExprsAreSame(ContextRef,
X, CO->getFalseExpr())) {
12115 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
12116 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
12117 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12118 CO->getFalseExpr()->getSourceRange();
12122 auto *
Cond = dyn_cast<BinaryOperator>(CO->getCond());
12123 auto *
Call = dyn_cast<CXXOperatorCallExpr>(CO->getCond());
12124 Expr *LHS =
nullptr;
12125 Expr *RHS =
nullptr;
12127 LHS =
Cond->getLHS();
12128 RHS =
Cond->getRHS();
12130 LHS =
Call->getArg(0);
12131 RHS =
Call->getArg(1);
12133 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12134 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12135 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12136 CO->getCond()->getSourceRange();
12140 if ((
Cond &&
Cond->getOpcode() == BO_EQ) ||
12141 (
Call &&
Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12143 D = CO->getTrueExpr();
12144 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS)) {
12146 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12149 ErrorInfo.Error = ErrorTy::InvalidComparison;
12150 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12151 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12152 CO->getCond()->getSourceRange();
12155 }
else if ((
Cond &&
12156 (
Cond->getOpcode() == BO_LT ||
Cond->getOpcode() == BO_GT)) ||
12158 (
Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12159 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12161 E = CO->getTrueExpr();
12162 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS) &&
12163 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12165 }
else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12166 checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12168 IsXBinopExpr =
false;
12170 ErrorInfo.Error = ErrorTy::InvalidComparison;
12171 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12172 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12173 CO->getCond()->getSourceRange();
12177 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12178 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12179 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12180 CO->getCond()->getSourceRange();
12187bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo)
const {
12189 assert(
X && E &&
"X and E cannot be nullptr");
12191 if (!CheckValue(
X, ErrorInfo,
true))
12194 if (!CheckValue(E, ErrorInfo,
false))
12197 if (D && !CheckValue(D, ErrorInfo,
false))
12203bool OpenMPAtomicCompareChecker::checkStmt(
12204 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
12205 auto *CS = dyn_cast<CompoundStmt>(S);
12207 if (CS->body_empty()) {
12208 ErrorInfo.Error = ErrorTy::NoStmt;
12209 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12210 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12214 if (CS->size() != 1) {
12215 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12216 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12217 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12220 S = CS->body_front();
12225 if (
auto *IS = dyn_cast<IfStmt>(S)) {
12231 Res = checkCondUpdateStmt(IS, ErrorInfo);
12237 Res = checkCondExprStmt(S, ErrorInfo);
12243 return checkType(ErrorInfo);
12246class OpenMPAtomicCompareCaptureChecker final
12247 :
public OpenMPAtomicCompareChecker {
12249 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
12251 Expr *
getV()
const {
return V; }
12252 Expr *
getR()
const {
return R; }
12257 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12260 bool checkType(ErrorInfoTy &ErrorInfo);
12272 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12276 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12288bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12289 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12292 if (
V && !CheckValue(
V, ErrorInfo,
true))
12295 if (R && !CheckValue(R, ErrorInfo,
true,
true))
12301bool OpenMPAtomicCompareCaptureChecker::checkForm3(
IfStmt *S,
12302 ErrorInfoTy &ErrorInfo) {
12306 if (
auto *CS = dyn_cast<CompoundStmt>(Then)) {
12307 if (CS->body_empty()) {
12308 ErrorInfo.Error = ErrorTy::NoStmt;
12309 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12310 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12313 if (CS->size() > 1) {
12314 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12315 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12316 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12319 Then = CS->body_front();
12322 auto *BO = dyn_cast<BinaryOperator>(Then);
12324 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12325 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12326 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12329 if (BO->getOpcode() != BO_Assign) {
12330 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12331 ErrorInfo.ErrorLoc = BO->getExprLoc();
12332 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12333 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12340 auto *
Cond = dyn_cast<BinaryOperator>(S->
getCond());
12341 auto *
Call = dyn_cast<CXXOperatorCallExpr>(S->
getCond());
12342 Expr *LHS =
nullptr;
12343 Expr *RHS =
nullptr;
12345 LHS =
Cond->getLHS();
12346 RHS =
Cond->getRHS();
12348 LHS =
Call->getArg(0);
12349 RHS =
Call->getArg(1);
12351 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12356 if ((
Cond &&
Cond->getOpcode() != BO_EQ) ||
12357 (
Call &&
Call->getOperator() != OverloadedOperatorKind::OO_EqualEqual)) {
12358 ErrorInfo.Error = ErrorTy::NotEQ;
12364 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS)) {
12366 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12369 ErrorInfo.Error = ErrorTy::InvalidComparison;
12378 ErrorInfo.Error = ErrorTy::NoElse;
12379 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->
getBeginLoc();
12380 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
12385 if (
auto *CS = dyn_cast<CompoundStmt>(Else)) {
12386 if (CS->body_empty()) {
12387 ErrorInfo.Error = ErrorTy::NoStmt;
12388 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12389 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12392 if (CS->size() > 1) {
12393 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12394 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12395 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
12398 Else = CS->body_front();
12401 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12403 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12404 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12405 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12408 if (ElseBO->getOpcode() != BO_Assign) {
12409 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12410 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12411 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12412 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12416 if (!checkIfTwoExprsAreSame(ContextRef,
X, ElseBO->getRHS())) {
12417 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12418 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12419 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12420 ElseBO->getRHS()->getSourceRange();
12424 V = ElseBO->getLHS();
12426 return checkType(ErrorInfo);
12429bool OpenMPAtomicCompareCaptureChecker::checkForm45(
Stmt *S,
12430 ErrorInfoTy &ErrorInfo) {
12434 assert(CS->size() == 2 &&
"CompoundStmt size is not expected");
12437 assert(S1->getOpcode() == BO_Assign &&
"unexpected binary operator");
12439 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12440 ErrorInfo.Error = ErrorTy::InvalidCondition;
12441 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12442 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12448 auto *Then = S2->getThen();
12449 if (
auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12450 if (ThenCS->body_empty()) {
12451 ErrorInfo.Error = ErrorTy::NoStmt;
12452 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12453 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12456 if (ThenCS->size() > 1) {
12457 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12458 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12459 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12462 Then = ThenCS->body_front();
12465 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12467 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12468 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12469 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12472 if (ThenBO->getOpcode() != BO_Assign) {
12473 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12474 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12475 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12476 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12480 X = ThenBO->getLHS();
12481 D = ThenBO->getRHS();
12484 if (BO->getOpcode() != BO_EQ) {
12485 ErrorInfo.Error = ErrorTy::NotEQ;
12486 ErrorInfo.ErrorLoc = BO->getExprLoc();
12487 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12488 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12494 if (checkIfTwoExprsAreSame(ContextRef,
X, BO->getLHS())) {
12496 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, BO->getRHS())) {
12499 ErrorInfo.Error = ErrorTy::InvalidComparison;
12500 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12501 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12505 if (S2->getElse()) {
12508 auto *Else = S2->getElse();
12509 if (
auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12510 if (ElseCS->body_empty()) {
12511 ErrorInfo.Error = ErrorTy::NoStmt;
12512 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12513 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12516 if (ElseCS->size() > 1) {
12517 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12518 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12519 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12522 Else = ElseCS->body_front();
12525 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12527 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12528 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12529 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12532 if (ElseBO->getOpcode() != BO_Assign) {
12533 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12534 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12535 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12536 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12539 if (!checkIfTwoExprsAreSame(ContextRef,
X, ElseBO->getRHS())) {
12540 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12541 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12542 ErrorInfo.NoteLoc =
X->getExprLoc();
12543 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12544 ErrorInfo.NoteRange =
X->getSourceRange();
12548 V = ElseBO->getLHS();
12551 return checkType(ErrorInfo);
12554bool OpenMPAtomicCompareCaptureChecker::checkStmt(
Stmt *S,
12555 ErrorInfoTy &ErrorInfo) {
12557 if (
auto *IS = dyn_cast<IfStmt>(S))
12558 return checkForm3(IS, ErrorInfo);
12560 auto *CS = dyn_cast<CompoundStmt>(S);
12562 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12563 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->
getBeginLoc();
12564 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
12567 if (CS->body_empty()) {
12568 ErrorInfo.Error = ErrorTy::NoStmt;
12569 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12570 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12575 if (CS->size() == 1) {
12576 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12578 ErrorInfo.Error = ErrorTy::NotIfStmt;
12579 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->
getBeginLoc();
12580 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12585 return checkForm3(IS, ErrorInfo);
12586 }
else if (CS->size() == 2) {
12587 auto *S1 = CS->body_front();
12588 auto *S2 = CS->body_back();
12590 Stmt *UpdateStmt =
nullptr;
12591 Stmt *CondUpdateStmt =
nullptr;
12592 Stmt *CondExprStmt =
nullptr;
12594 if (
auto *BO = dyn_cast<BinaryOperator>(S1)) {
12604 return checkForm45(CS, ErrorInfo);
12613 CondUpdateStmt = S2;
12622 CondUpdateStmt = S1;
12625 auto CheckCondUpdateStmt = [
this, &ErrorInfo](
Stmt *CUS) {
12626 auto *IS = dyn_cast<IfStmt>(CUS);
12628 ErrorInfo.Error = ErrorTy::NotIfStmt;
12629 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12630 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12634 return checkCondUpdateStmt(IS, ErrorInfo);
12638 auto CheckUpdateStmt = [
this, &ErrorInfo](
Stmt *US) {
12639 auto *BO = dyn_cast<BinaryOperator>(US);
12641 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12642 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12643 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12646 if (BO->getOpcode() != BO_Assign) {
12647 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12648 ErrorInfo.ErrorLoc = BO->getExprLoc();
12649 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12650 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12653 if (!checkIfTwoExprsAreSame(ContextRef, this->
X, BO->getRHS())) {
12654 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12655 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12656 ErrorInfo.NoteLoc = this->
X->getExprLoc();
12657 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12658 ErrorInfo.NoteRange = this->
X->getSourceRange();
12662 this->
V = BO->getLHS();
12667 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12669 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12671 if (!CheckUpdateStmt(UpdateStmt))
12674 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12675 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12676 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12680 return checkType(ErrorInfo);
12691 DSAStack->addAtomicDirectiveLoc(StartLoc);
12704 bool MutexClauseEncountered =
false;
12705 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12707 switch (
C->getClauseKind()) {
12711 MutexClauseEncountered =
true;
12714 case OMPC_compare: {
12715 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12716 Diag(
C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12718 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12721 AtomicKind =
C->getClauseKind();
12722 AtomicKindLoc =
C->getBeginLoc();
12723 if (!EncounteredAtomicKinds.insert(
C->getClauseKind()).second) {
12724 Diag(
C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12726 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12734 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12735 Diag(
C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12746 case OMPC_relaxed: {
12747 if (MemOrderKind != OMPC_unknown) {
12748 Diag(
C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12749 << getOpenMPDirectiveName(OMPD_atomic, OMPVersion) << 0
12751 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12754 MemOrderKind =
C->getClauseKind();
12755 MemOrderLoc =
C->getBeginLoc();
12763 llvm_unreachable(
"unknown clause is encountered");
12766 bool IsCompareCapture =
false;
12767 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12768 EncounteredAtomicKinds.contains(OMPC_capture)) {
12769 IsCompareCapture =
true;
12770 AtomicKind = OMPC_compare;
12779 if ((AtomicKind == OMPC_read &&
12780 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12781 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12782 AtomicKind == OMPC_unknown) &&
12783 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12785 if (AtomicKind == OMPC_unknown)
12787 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12789 << (AtomicKind == OMPC_unknown ? 1 : 0)
12791 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12795 Stmt *Body = AStmt;
12796 if (
auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12797 Body = EWC->getSubExpr();
12802 Expr *UE =
nullptr;
12804 Expr *CE =
nullptr;
12831 if (AtomicKind == OMPC_read) {
12838 } ErrorFound = NoError;
12843 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12844 const auto *AtomicBinOp =
12845 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12846 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12849 if ((
X->isInstantiationDependent() ||
X->getType()->isScalarType()) &&
12850 (
V->isInstantiationDependent() ||
V->getType()->isScalarType())) {
12851 if (!
X->isLValue() || !
V->isLValue()) {
12852 const Expr *NotLValueExpr =
X->isLValue() ?
V :
X;
12853 ErrorFound = NotAnLValue;
12859 }
else if (!
X->isInstantiationDependent() ||
12860 !
V->isInstantiationDependent()) {
12861 const Expr *NotScalarExpr =
12862 (
X->isInstantiationDependent() ||
X->getType()->isScalarType())
12865 ErrorFound = NotAScalarType;
12871 }
else if (!AtomicBody->isInstantiationDependent()) {
12872 ErrorFound = NotAnAssignmentOp;
12873 ErrorLoc = AtomicBody->getExprLoc();
12874 ErrorRange = AtomicBody->getSourceRange();
12876 : AtomicBody->getExprLoc();
12878 : AtomicBody->getSourceRange();
12881 ErrorFound = NotAnExpression;
12883 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
12885 if (ErrorFound != NoError) {
12886 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12888 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12889 << ErrorFound << NoteRange;
12892 if (
SemaRef.CurContext->isDependentContext())
12894 }
else if (AtomicKind == OMPC_write) {
12901 } ErrorFound = NoError;
12906 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12907 const auto *AtomicBinOp =
12908 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12909 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12911 E = AtomicBinOp->
getRHS();
12912 if ((
X->isInstantiationDependent() ||
X->getType()->isScalarType()) &&
12914 if (!
X->isLValue()) {
12915 ErrorFound = NotAnLValue;
12918 NoteLoc =
X->getExprLoc();
12919 NoteRange =
X->getSourceRange();
12921 }
else if (!
X->isInstantiationDependent() ||
12923 const Expr *NotScalarExpr =
12924 (
X->isInstantiationDependent() ||
X->getType()->isScalarType())
12927 ErrorFound = NotAScalarType;
12933 }
else if (!AtomicBody->isInstantiationDependent()) {
12934 ErrorFound = NotAnAssignmentOp;
12935 ErrorLoc = AtomicBody->getExprLoc();
12936 ErrorRange = AtomicBody->getSourceRange();
12938 : AtomicBody->getExprLoc();
12940 : AtomicBody->getSourceRange();
12943 ErrorFound = NotAnExpression;
12945 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
12947 if (ErrorFound != NoError) {
12948 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12950 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12951 << ErrorFound << NoteRange;
12954 if (
SemaRef.CurContext->isDependentContext())
12956 }
else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12965 OpenMPAtomicUpdateChecker Checker(
SemaRef);
12966 if (Checker.checkStatement(
12968 (AtomicKind == OMPC_update)
12969 ? diag::err_omp_atomic_update_not_expression_statement
12970 : diag::err_omp_atomic_not_expression_statement,
12971 diag::note_omp_atomic_update))
12973 if (!
SemaRef.CurContext->isDependentContext()) {
12974 E = Checker.getExpr();
12975 X = Checker.getX();
12976 UE = Checker.getUpdateExpr();
12979 }
else if (AtomicKind == OMPC_capture) {
12982 NotACompoundStatement,
12983 NotTwoSubstatements,
12984 NotASpecificExpression,
12986 } ErrorFound = NoError;
12989 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12998 const auto *AtomicBinOp =
12999 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
13000 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
13003 OpenMPAtomicUpdateChecker Checker(
SemaRef);
13004 if (Checker.checkStatement(
13005 Body, diag::err_omp_atomic_capture_not_expression_statement,
13006 diag::note_omp_atomic_update))
13008 E = Checker.getExpr();
13009 X = Checker.getX();
13010 UE = Checker.getUpdateExpr();
13013 }
else if (!AtomicBody->isInstantiationDependent()) {
13014 ErrorLoc = AtomicBody->getExprLoc();
13015 ErrorRange = AtomicBody->getSourceRange();
13017 : AtomicBody->getExprLoc();
13019 : AtomicBody->getSourceRange();
13020 ErrorFound = NotAnAssignmentOp;
13022 if (ErrorFound != NoError) {
13023 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
13025 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13028 if (
SemaRef.CurContext->isDependentContext())
13029 UE =
V = E =
X =
nullptr;
13047 if (
auto *CS = dyn_cast<CompoundStmt>(Body)) {
13049 if (CS->size() == 2) {
13051 Stmt *Second = CS->body_back();
13052 if (
auto *EWC = dyn_cast<ExprWithCleanups>(
First))
13053 First = EWC->getSubExpr()->IgnoreParenImpCasts();
13054 if (
auto *EWC = dyn_cast<ExprWithCleanups>(Second))
13055 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
13057 OpenMPAtomicUpdateChecker Checker(
SemaRef);
13058 bool IsUpdateExprFound = !Checker.checkStatement(Second);
13060 if (IsUpdateExprFound) {
13061 BinOp = dyn_cast<BinaryOperator>(
First);
13062 IsUpdateExprFound = BinOp && BinOp->
getOpcode() == BO_Assign;
13064 if (IsUpdateExprFound && !
SemaRef.CurContext->isDependentContext()) {
13074 llvm::FoldingSetNodeID XId, PossibleXId;
13075 Checker.getX()->Profile(XId, Context,
true);
13076 PossibleX->
Profile(PossibleXId, Context,
true);
13077 IsUpdateExprFound = XId == PossibleXId;
13078 if (IsUpdateExprFound) {
13080 X = Checker.getX();
13081 E = Checker.getExpr();
13082 UE = Checker.getUpdateExpr();
13087 if (!IsUpdateExprFound) {
13088 IsUpdateExprFound = !Checker.checkStatement(
First);
13090 if (IsUpdateExprFound) {
13091 BinOp = dyn_cast<BinaryOperator>(Second);
13092 IsUpdateExprFound = BinOp && BinOp->
getOpcode() == BO_Assign;
13094 if (IsUpdateExprFound &&
13095 !
SemaRef.CurContext->isDependentContext()) {
13105 llvm::FoldingSetNodeID XId, PossibleXId;
13106 Checker.getX()->Profile(XId, Context,
true);
13107 PossibleX->
Profile(PossibleXId, Context,
true);
13108 IsUpdateExprFound = XId == PossibleXId;
13109 if (IsUpdateExprFound) {
13111 X = Checker.getX();
13112 E = Checker.getExpr();
13113 UE = Checker.getUpdateExpr();
13119 if (!IsUpdateExprFound) {
13121 auto *FirstExpr = dyn_cast<Expr>(
First);
13122 auto *SecondExpr = dyn_cast<Expr>(Second);
13123 if (!FirstExpr || !SecondExpr ||
13124 !(FirstExpr->isInstantiationDependent() ||
13125 SecondExpr->isInstantiationDependent())) {
13126 auto *FirstBinOp = dyn_cast<BinaryOperator>(
First);
13127 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
13128 ErrorFound = NotAnAssignmentOp;
13129 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
13130 :
First->getBeginLoc();
13131 NoteRange = ErrorRange = FirstBinOp
13132 ? FirstBinOp->getSourceRange()
13135 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
13136 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
13137 ErrorFound = NotAnAssignmentOp;
13138 NoteLoc = ErrorLoc = SecondBinOp
13139 ? SecondBinOp->getOperatorLoc()
13141 NoteRange = ErrorRange =
13142 SecondBinOp ? SecondBinOp->getSourceRange()
13145 Expr *PossibleXRHSInFirst =
13147 Expr *PossibleXLHSInSecond =
13149 llvm::FoldingSetNodeID X1Id, X2Id;
13150 PossibleXRHSInFirst->
Profile(X1Id, Context,
13152 PossibleXLHSInSecond->
Profile(X2Id, Context,
13154 IsUpdateExprFound = X1Id == X2Id;
13155 if (IsUpdateExprFound) {
13156 V = FirstBinOp->getLHS();
13157 X = SecondBinOp->getLHS();
13158 E = SecondBinOp->getRHS();
13163 ErrorFound = NotASpecificExpression;
13164 ErrorLoc = FirstBinOp->getExprLoc();
13165 ErrorRange = FirstBinOp->getSourceRange();
13166 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
13167 NoteRange = SecondBinOp->getRHS()->getSourceRange();
13175 NoteRange = ErrorRange =
13177 ErrorFound = NotTwoSubstatements;
13181 NoteRange = ErrorRange =
13183 ErrorFound = NotACompoundStatement;
13186 if (ErrorFound != NoError) {
13187 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
13189 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13192 if (
SemaRef.CurContext->isDependentContext())
13193 UE =
V = E =
X =
nullptr;
13194 }
else if (AtomicKind == OMPC_compare) {
13195 if (IsCompareCapture) {
13196 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
13197 OpenMPAtomicCompareCaptureChecker Checker(
SemaRef);
13198 if (!Checker.checkStmt(Body, ErrorInfo)) {
13199 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
13200 << ErrorInfo.ErrorRange;
13201 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13202 << ErrorInfo.Error << ErrorInfo.NoteRange;
13205 X = Checker.getX();
13206 E = Checker.getE();
13207 D = Checker.getD();
13208 CE = Checker.getCond();
13209 V = Checker.getV();
13210 R = Checker.getR();
13216 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
13217 OpenMPAtomicCompareChecker Checker(
SemaRef);
13218 if (!Checker.checkStmt(Body, ErrorInfo)) {
13219 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
13220 << ErrorInfo.ErrorRange;
13221 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13222 << ErrorInfo.Error << ErrorInfo.NoteRange;
13225 X = Checker.getX();
13226 E = Checker.getE();
13227 D = Checker.getD();
13228 CE = Checker.getCond();
13234 auto *It = find_if(Clauses, [](
OMPClause *
C) {
13235 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
13237 if (It != Clauses.end()) {
13238 auto *
Cond = dyn_cast<BinaryOperator>(CE);
13239 if (
Cond->getOpcode() != BO_EQ) {
13240 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
13241 ErrorInfo.ErrorLoc =
Cond->getExprLoc();
13242 ErrorInfo.NoteLoc =
Cond->getOperatorLoc();
13243 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
Cond->getSourceRange();
13245 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
13246 << ErrorInfo.ErrorRange;
13255 SemaRef.setFunctionHasBranchProtectedScope();
13257 return OMPAtomicDirective::Create(
13258 Context, StartLoc, EndLoc, Clauses, AStmt,
13275 if (
DSAStack->hasInnerTeamsRegion()) {
13277 bool OMPTeamsFound =
true;
13278 if (
const auto *CS = dyn_cast<CompoundStmt>(S)) {
13279 auto I = CS->body_begin();
13280 while (I != CS->body_end()) {
13281 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
13283 if (!IsTeams || I != CS->body_begin()) {
13284 OMPTeamsFound =
false;
13285 if (IsTeams && I != CS->body_begin()) {
13294 assert(I != CS->body_end() &&
"Not found statement");
13297 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
13300 if (!OMPTeamsFound) {
13301 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
13303 diag::note_omp_nested_teams_construct_here);
13336 OMPLoopBasedDirective::HelperExprs B;
13339 unsigned NestedLoopCount =
13342 VarsWithImplicitDSA, B);
13343 if (NestedLoopCount == 0)
13350 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13357 return llvm::any_of(
13358 Clauses, [K](
const OMPClause *
C) {
return C->getClauseKind() == K; });
13361template <
typename... Params>
13363 const Params... ClauseTypes) {
13370 if (
auto *TC = dyn_cast<OMPToClause>(
C))
13371 return llvm::all_of(TC->all_decls(), [](
ValueDecl *VD) {
13372 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13373 (VD->isExternallyVisible() &&
13374 VD->getVisibility() != HiddenVisibility);
13376 else if (
auto *FC = dyn_cast<OMPFromClause>(
C))
13377 return llvm::all_of(FC->all_decls(), [](
ValueDecl *VD) {
13378 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13379 (VD->isExternallyVisible() &&
13380 VD->getVisibility() != HiddenVisibility);
13399 if (!
hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13401 !
hasClauses(Clauses, OMPC_use_device_addr))) {
13404 Expected =
"'map' or 'use_device_ptr'";
13406 Expected =
"'map', 'use_device_ptr', or 'use_device_addr'";
13408 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13409 <<
Expected << getOpenMPDirectiveName(OMPD_target_data, OMPVersion);
13413 SemaRef.setFunctionHasBranchProtectedScope();
13431 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13433 << getOpenMPDirectiveName(OMPD_target_enter_data, OMPVersion);
13453 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13454 <<
"'map'" << getOpenMPDirectiveName(OMPD_target_exit_data, OMPVersion);
13470 if (!
hasClauses(Clauses, OMPC_to, OMPC_from)) {
13471 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13476 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13486template <
typename ClauseType>
13489 unsigned MaxNum,
unsigned Diag) {
13490 auto ClauseItr = llvm::find_if(Clauses, llvm::IsaPred<ClauseType>);
13491 if (ClauseItr == Clauses.end())
13494 auto VarList =
C->getVarRefs();
13495 if (VarList.size() > MaxNum) {
13496 SemaRef.
Diag(VarList[MaxNum]->getBeginLoc(),
Diag)
13511 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
13513 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
13518 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13522 DSAStack->setParentTeamsRegionLoc(StartLoc);
13531 if (
DSAStack->isParentNowaitRegion()) {
13532 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13535 if (
DSAStack->isParentOrderedRegion()) {
13536 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13540 EndLoc, CancelRegion);
13546 if (
DSAStack->isParentNowaitRegion()) {
13547 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13550 if (
DSAStack->isParentOrderedRegion()) {
13551 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13554 DSAStack->setParentCancelRegion(
true);
13561 const OMPClause *ReductionClause =
nullptr;
13562 const OMPClause *NogroupClause =
nullptr;
13564 if (
C->getClauseKind() == OMPC_reduction) {
13565 ReductionClause =
C;
13570 if (
C->getClauseKind() == OMPC_nogroup) {
13572 if (ReductionClause)
13577 if (ReductionClause && NogroupClause) {
13578 S.
Diag(ReductionClause->
getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13593 OMPLoopBasedDirective::HelperExprs B;
13596 unsigned NestedLoopCount =
13599 *
DSAStack, VarsWithImplicitDSA, B);
13600 if (NestedLoopCount == 0)
13603 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13604 "omp for loop exprs were not built");
13610 {OMPC_grainsize, OMPC_num_tasks}))
13618 SemaRef.setFunctionHasBranchProtectedScope();
13620 NestedLoopCount, Clauses, AStmt, B,
13634 OMPLoopBasedDirective::HelperExprs B;
13637 unsigned NestedLoopCount =
13640 VarsWithImplicitDSA, B);
13641 if (NestedLoopCount == 0)
13651 {OMPC_grainsize, OMPC_num_tasks}))
13662 NestedLoopCount, Clauses, AStmt, B);
13672 OMPLoopBasedDirective::HelperExprs B;
13675 unsigned NestedLoopCount =
13678 *
DSAStack, VarsWithImplicitDSA, B);
13679 if (NestedLoopCount == 0)
13682 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13683 "omp for loop exprs were not built");
13689 {OMPC_grainsize, OMPC_num_tasks}))
13697 SemaRef.setFunctionHasBranchProtectedScope();
13699 NestedLoopCount, Clauses, AStmt, B,
13710 OMPLoopBasedDirective::HelperExprs B;
13713 unsigned NestedLoopCount =
13716 *
DSAStack, VarsWithImplicitDSA, B);
13717 if (NestedLoopCount == 0)
13720 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13721 "omp for loop exprs were not built");
13727 {OMPC_grainsize, OMPC_num_tasks}))
13735 SemaRef.setFunctionHasBranchProtectedScope();
13737 NestedLoopCount, Clauses, AStmt, B,
13751 OMPLoopBasedDirective::HelperExprs B;
13754 unsigned NestedLoopCount =
13757 VarsWithImplicitDSA, B);
13758 if (NestedLoopCount == 0)
13768 {OMPC_grainsize, OMPC_num_tasks}))
13779 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13792 OMPLoopBasedDirective::HelperExprs B;
13795 unsigned NestedLoopCount =
13798 VarsWithImplicitDSA, B);
13799 if (NestedLoopCount == 0)
13809 {OMPC_grainsize, OMPC_num_tasks}))
13820 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13832 OMPLoopBasedDirective::HelperExprs B;
13838 VarsWithImplicitDSA, B);
13839 if (NestedLoopCount == 0)
13842 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13843 "omp for loop exprs were not built");
13849 {OMPC_grainsize, OMPC_num_tasks}))
13858 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13871 OMPLoopBasedDirective::HelperExprs B;
13877 VarsWithImplicitDSA, B);
13878 if (NestedLoopCount == 0)
13881 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13882 "omp for loop exprs were not built");
13888 {OMPC_grainsize, OMPC_num_tasks}))
13897 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13908 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
13910 OMPLoopBasedDirective::HelperExprs B;
13916 VarsWithImplicitDSA, B);
13917 if (NestedLoopCount == 0)
13927 {OMPC_grainsize, OMPC_num_tasks}))
13938 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13948 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
13950 OMPLoopBasedDirective::HelperExprs B;
13956 VarsWithImplicitDSA, B);
13957 if (NestedLoopCount == 0)
13967 {OMPC_grainsize, OMPC_num_tasks}))
13978 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13988 OMPLoopBasedDirective::HelperExprs B;
13991 unsigned NestedLoopCount =
13995 if (NestedLoopCount == 0)
13998 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13999 "omp for loop exprs were not built");
14001 SemaRef.setFunctionHasBranchProtectedScope();
14003 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14004 return DistributeDirective;
14016 OMPLoopBasedDirective::HelperExprs B;
14022 VarsWithImplicitDSA, B);
14023 if (NestedLoopCount == 0)
14026 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14027 "omp for loop exprs were not built");
14030 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14041 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
14043 OMPLoopBasedDirective::HelperExprs B;
14049 VarsWithImplicitDSA, B);
14050 if (NestedLoopCount == 0)
14060 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14072 OMPLoopBasedDirective::HelperExprs B;
14075 unsigned NestedLoopCount =
14079 if (NestedLoopCount == 0)
14089 NestedLoopCount, Clauses, AStmt, B);
14101 OMPLoopBasedDirective::HelperExprs B;
14107 VarsWithImplicitDSA, B);
14108 if (NestedLoopCount == 0)
14118 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14129 OMPLoopBasedDirective::HelperExprs B;
14132 unsigned NestedLoopCount =
14135 VarsWithImplicitDSA, B);
14136 if (NestedLoopCount == 0)
14146 NestedLoopCount, Clauses, AStmt, B);
14158 OMPLoopBasedDirective::HelperExprs B;
14161 unsigned NestedLoopCount =
14165 if (NestedLoopCount == 0)
14168 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14169 "omp teams distribute loop exprs were not built");
14171 DSAStack->setParentTeamsRegionLoc(StartLoc);
14174 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14186 OMPLoopBasedDirective::HelperExprs B;
14192 VarsWithImplicitDSA, B);
14193 if (NestedLoopCount == 0)
14202 DSAStack->setParentTeamsRegionLoc(StartLoc);
14205 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14215 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
14217 OMPLoopBasedDirective::HelperExprs B;
14223 VarsWithImplicitDSA, B);
14224 if (NestedLoopCount == 0)
14233 DSAStack->setParentTeamsRegionLoc(StartLoc);
14236 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14246 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
14248 OMPLoopBasedDirective::HelperExprs B;
14254 VarsWithImplicitDSA, B);
14256 if (NestedLoopCount == 0)
14259 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14260 "omp for loop exprs were not built");
14262 DSAStack->setParentTeamsRegionLoc(StartLoc);
14265 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14278 bool HasThreadLimitAndNumTeamsClause =
hasClauses(Clauses, OMPC_num_teams) &&
14280 bool HasBareClause = llvm::any_of(Clauses, [&](
const OMPClause *
C) {
14282 return C->getClauseKind() == OMPC_ompx_bare;
14285 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
14290 unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 1;
14291 unsigned DiagNo = HasBareClause
14292 ? diag::err_ompx_more_than_three_expr_not_allowed
14293 : diag::err_omp_multi_expr_not_allowed;
14295 ClauseMaxNumExprs, DiagNo) ||
14297 ClauseMaxNumExprs, DiagNo))
14311 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
14313 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14319 OMPLoopBasedDirective::HelperExprs B;
14325 VarsWithImplicitDSA, B);
14326 if (NestedLoopCount == 0)
14329 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14330 "omp target teams distribute loop exprs were not built");
14333 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14343 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
14345 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14349 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
14351 OMPLoopBasedDirective::HelperExprs B;
14357 VarsWithImplicitDSA, B);
14358 if (NestedLoopCount == 0)
14365 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14376 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
14378 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14382 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
14384 OMPLoopBasedDirective::HelperExprs B;
14387 unsigned NestedLoopCount =
14392 if (NestedLoopCount == 0)
14402 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14412 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
14414 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14418 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
14420 OMPLoopBasedDirective::HelperExprs B;
14426 VarsWithImplicitDSA, B);
14427 if (NestedLoopCount == 0)
14437 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14444 Stmt *Dir = Transform->getDirective();
14446#define STMT(CLASS, PARENT)
14447#define ABSTRACT_STMT(CLASS)
14448#define COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT) \
14449 case Stmt::CLASS##Class: \
14450 appendFlattenedStmtList(PreInits, \
14451 static_cast<const CLASS *>(Dir)->getPreInits()); \
14453#define OMPCANONICALLOOPNESTTRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14454 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14455#define OMPCANONICALLOOPSEQUENCETRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14456 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14457#include "clang/AST/StmtNodes.inc"
14458#undef COMMON_OMP_LOOP_TRANSFORMATION
14460 llvm_unreachable(
"Not a loop transformation");
14464bool SemaOpenMP::checkTransformableLoopNest(
14468 OriginalInits.emplace_back();
14469 bool Result = OMPLoopBasedDirective::doForAllLoops(
14471 [
this, &LoopHelpers, &Body, &OriginalInits, Kind](
unsigned Cnt,
14473 VarsWithInheritedDSAType TmpDSA;
14474 unsigned SingleNumLoops =
14475 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
14476 TmpDSA, LoopHelpers[Cnt]);
14477 if (SingleNumLoops == 0)
14479 assert(SingleNumLoops == 1 &&
"Expect single loop iteration space");
14480 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14481 OriginalInits.back().push_back(For->getInit());
14482 Body = For->getBody();
14484 assert(isa<CXXForRangeStmt>(CurStmt) &&
14485 "Expected canonical for or range-based for loops.");
14486 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14487 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14488 Body = CXXFor->getBody();
14490 OriginalInits.emplace_back();
14493 [&OriginalInits](OMPLoopTransformationDirective *Transform) {
14496 assert(OriginalInits.back().empty() &&
"No preinit after innermost loop");
14497 OriginalInits.pop_back();
14535 unsigned NestedLoopCount = 0;
14582bool SemaOpenMP::analyzeLoopSequence(
Stmt *LoopSeqStmt,
14583 LoopSequenceAnalysis &SeqAnalysis,
14589 auto StoreLoopStatements = [](LoopAnalysis &Analysis, Stmt *LoopStmt) {
14590 if (
auto *For = dyn_cast<ForStmt>(LoopStmt)) {
14591 Analysis.OriginalInits.push_back(For->getInit());
14592 Analysis.TheForStmt = For;
14595 Analysis.OriginalInits.push_back(CXXFor->getBeginStmt());
14596 Analysis.TheForStmt = CXXFor;
14603 auto AnalyzeLoopGeneration = [&](Stmt *Child) {
14605 Stmt *TransformedStmt = LoopTransform->getTransformedStmt();
14606 unsigned NumGeneratedTopLevelLoops =
14607 LoopTransform->getNumGeneratedTopLevelLoops();
14610 if (!TransformedStmt) {
14611 if (NumGeneratedTopLevelLoops > 0) {
14612 SeqAnalysis.LoopSeqSize += NumGeneratedTopLevelLoops;
14616 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14617 << 0 << getOpenMPDirectiveName(Kind);
14622 if (!NumGeneratedTopLevelLoops) {
14623 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14624 << 0 << getOpenMPDirectiveName(Kind);
14628 if (NumGeneratedTopLevelLoops > 1) {
14635 updatePreInits(LoopTransform, SeqAnalysis.LoopSequencePreInits);
14636 return analyzeLoopSequence(TransformedStmt, SeqAnalysis, Context, Kind);
14640 LoopAnalysis &NewTransformedSingleLoop =
14641 SeqAnalysis.Loops.emplace_back(Child);
14644 NewTransformedSingleLoop.HelperExprs);
14649 StoreLoopStatements(NewTransformedSingleLoop, TransformedStmt);
14650 updatePreInits(LoopTransform, NewTransformedSingleLoop.TransformsPreInits);
14652 SeqAnalysis.LoopSeqSize++;
14657 auto AnalyzeRegularLoop = [&](Stmt *Child) {
14658 LoopAnalysis &NewRegularLoop = SeqAnalysis.Loops.emplace_back(Child);
14659 unsigned IsCanonical =
14661 TmpDSA, NewRegularLoop.HelperExprs);
14666 StoreLoopStatements(NewRegularLoop, Child);
14667 NestedLoopCounterVisitor NLCV;
14673 for (Stmt *Child : LoopSeqStmt->
children()) {
14677 if (!LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
14678 Child = Child->IgnoreContainers();
14685 if (!analyzeLoopSequence(Child, SeqAnalysis, Context, Kind))
14692 if (LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
14693 if (LoopAnalysis::isLoopTransformation(Child)) {
14694 if (!AnalyzeLoopGeneration(Child))
14698 if (!AnalyzeRegularLoop(Child))
14700 SeqAnalysis.LoopSeqSize++;
14704 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14705 << 0 << getOpenMPDirectiveName(Kind);
14712bool SemaOpenMP::checkTransformableLoopSequence(
14737 << getOpenMPDirectiveName(Kind);
14742 if (!analyzeLoopSequence(AStmt, SeqAnalysis, Context, Kind))
14746 if (!SeqAnalysis.LoopSeqSize) {
14748 << getOpenMPDirectiveName(Kind);
14756 OMPLoopBasedDirective::HelperExprs &LoopHelper,
14762 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
14763 Stmt *RangeInit = CXXRangeFor->getInit();
14765 PreInits.push_back(RangeInit);
14767 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14772 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14778 llvm::append_range(PreInits, OriginalInit);
14781 if (
auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits)) {
14782 PreInits.push_back(
new (Context)
DeclStmt(
14783 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14787 for (
Expr *CounterRef : LoopHelper.Counters) {
14790 PreInits.push_back(
new (Context)
DeclStmt(
14798 size_t NumLoops = LoopStmts.size();
14799 OMPLoopBasedDirective::doForAllLoops(
14800 AStmt,
false, NumLoops,
14801 [LoopStmts](
unsigned Cnt,
Stmt *CurStmt) {
14802 assert(!LoopStmts[Cnt] &&
"Loop statement must not yet be assigned");
14803 LoopStmts[Cnt] = CurStmt;
14806 assert(!is_contained(LoopStmts,
nullptr) &&
14807 "Expecting a loop statement for each affected loop");
14825 const auto *SizesClause =
14826 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14827 if (!SizesClause ||
14828 llvm::any_of(SizesClause->getSizesRefs(), [](
Expr *E) { return !E; }))
14830 unsigned NumLoops = SizesClause->getNumSizes();
14838 Stmt *Body =
nullptr;
14840 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14845 if (
SemaRef.CurContext->isDependentContext())
14847 NumLoops, AStmt,
nullptr,
nullptr);
14849 assert(LoopHelpers.size() == NumLoops &&
14850 "Expecting loop iteration space dimensionality to match number of "
14852 assert(OriginalInits.size() == NumLoops &&
14853 "Expecting loop iteration space dimensionality to match number of "
14861 CaptureVars CopyTransformer(
SemaRef);
14866 FloorIndVars.resize(NumLoops);
14867 TileIndVars.resize(NumLoops);
14868 for (
unsigned I = 0; I < NumLoops; ++I) {
14869 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14871 assert(LoopHelper.Counters.size() == 1 &&
14872 "Expect single-dimensional loop iteration space");
14874 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14880 std::string FloorCntName =
14881 (Twine(
".floor_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
14884 FloorIndVars[I] = FloorCntDecl;
14889 std::string TileCntName =
14890 (Twine(
".tile_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
14896 TileCntDecl->setDeclName(
14897 &
SemaRef.PP.getIdentifierTable().get(TileCntName));
14898 TileIndVars[I] = TileCntDecl;
14906 Stmt *Inner = Body;
14908 auto MakeDimTileSize = [&
SemaRef = this->SemaRef, &CopyTransformer, &Context,
14909 SizesClause, CurScope](
int I) ->
Expr * {
14910 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
14916 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
14935 uint64_t DimWidth = Context.getTypeSize(DimTy);
14937 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14941 CurScope, {}, BO_LE,
14945 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
14951 for (
int I = NumLoops - 1; I >= 0; --I) {
14952 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14953 Expr *NumIterations = LoopHelper.NumIterations;
14956 Stmt *LoopStmt = LoopStmts[I];
14961 auto MakeTileIVRef = [&
SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
14964 OrigCntVar->getExprLoc());
14968 SemaRef.AddInitializerToDecl(
14971 .DefaultLvalueConversion(
14975 Decl *CounterDecl = TileIndVars[I];
14978 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14984 Expr *DimTileSize = MakeDimTileSize(I);
14988 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14994 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14995 NumIterations, EndOfTile.
get());
14999 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
15000 IsPartialTile.
get(), NumIterations, EndOfTile.
get());
15001 if (!MinTileAndIterSpace.
isUsable())
15004 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15005 MakeTileIVRef(), MinTileAndIterSpace.
get());
15011 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef());
15032 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15033 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15034 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15035 BodyParts.push_back(Inner);
15038 Inner =
new (Context)
15041 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15045 for (
int I = NumLoops - 1; I >= 0; --I) {
15046 auto &LoopHelper = LoopHelpers[I];
15047 Expr *NumIterations = LoopHelper.NumIterations;
15052 SemaRef.AddInitializerToDecl(
15054 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15056 Decl *CounterDecl = FloorIndVars[I];
15065 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15072 Expr *DimTileSize = MakeDimTileSize(I);
15076 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15082 Inner =
new (Context)
15085 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15100 const auto *SizesClause =
15101 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
15102 if (!SizesClause ||
15103 llvm::any_of(SizesClause->getSizesRefs(), [](
const Expr *SizeExpr) {
15104 return !SizeExpr || SizeExpr->containsErrors();
15107 unsigned NumLoops = SizesClause->getNumSizes();
15115 Stmt *Body =
nullptr;
15117 if (!checkTransformableLoopNest(OMPD_stripe, AStmt, NumLoops, LoopHelpers,
15118 Body, OriginalInits))
15122 if (
SemaRef.CurContext->isDependentContext())
15124 NumLoops, AStmt,
nullptr,
nullptr);
15126 assert(LoopHelpers.size() == NumLoops &&
15127 "Expecting loop iteration space dimensionality to match number of "
15129 assert(OriginalInits.size() == NumLoops &&
15130 "Expecting loop iteration space dimensionality to match number of "
15138 CaptureVars CopyTransformer(
SemaRef);
15143 FloorIndVars.resize(NumLoops);
15144 StripeIndVars.resize(NumLoops);
15145 for (
unsigned I : llvm::seq<unsigned>(NumLoops)) {
15146 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15148 assert(LoopHelper.Counters.size() == 1 &&
15149 "Expect single-dimensional loop iteration space");
15151 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15157 std::string FloorCntName =
15158 (Twine(
".floor_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
15161 FloorIndVars[I] = FloorCntDecl;
15166 std::string StripeCntName =
15167 (Twine(
".stripe_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
15173 StripeCntDecl->setDeclName(
15174 &
SemaRef.PP.getIdentifierTable().get(StripeCntName));
15175 StripeIndVars[I] = StripeCntDecl;
15183 Stmt *Inner = Body;
15185 auto MakeDimStripeSize = [&](
int I) ->
Expr * {
15186 Expr *DimStripeSizeExpr = SizesClause->getSizesRefs()[I];
15188 return AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr));
15207 uint64_t DimWidth = Context.getTypeSize(DimTy);
15209 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
15213 CurScope, {}, BO_LE,
15217 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), DimTy,
15223 for (
int I = NumLoops - 1; I >= 0; --I) {
15224 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15225 Expr *NumIterations = LoopHelper.NumIterations;
15228 Stmt *LoopStmt = LoopStmts[I];
15231 SemaRef.AddInitializerToDecl(
15234 .DefaultLvalueConversion(
15238 Decl *CounterDecl = StripeIndVars[I];
15241 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15248 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15250 MakeDimStripeSize(I));
15254 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15255 NumIterations, EndOfStripe.
get());
15259 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
15260 IsPartialStripe.
get(), NumIterations, EndOfStripe.
get());
15261 if (!MinStripeAndIterSpace.
isUsable())
15264 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15266 MinStripeAndIterSpace.
get());
15272 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc,
15294 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15295 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15296 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15297 BodyParts.push_back(Inner);
15300 Inner =
new (Context)
15303 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15307 for (
int I = NumLoops - 1; I >= 0; --I) {
15308 auto &LoopHelper = LoopHelpers[I];
15309 Expr *NumIterations = LoopHelper.NumIterations;
15314 SemaRef.AddInitializerToDecl(
15316 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15318 Decl *CounterDecl = FloorIndVars[I];
15327 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15335 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15337 MakeDimStripeSize(I));
15341 Inner =
new (Context)
15344 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15348 NumLoops, AStmt, Inner,
15363 {OMPC_partial, OMPC_full}))
15367 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
15369 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
15370 assert(!(FullClause && PartialClause) &&
15371 "mutual exclusivity must have been checked before");
15373 constexpr unsigned NumLoops = 1;
15374 Stmt *Body =
nullptr;
15378 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
15379 Body, OriginalInits))
15382 unsigned NumGeneratedTopLevelLoops = PartialClause ? 1 : 0;
15385 if (
SemaRef.CurContext->isDependentContext())
15387 NumGeneratedTopLevelLoops,
nullptr,
15390 assert(LoopHelpers.size() == NumLoops &&
15391 "Expecting a single-dimensional loop iteration space");
15392 assert(OriginalInits.size() == NumLoops &&
15393 "Expecting a single-dimensional loop iteration space");
15394 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15398 LoopHelper.NumIterations, OMPC_full,
false,
15401 Diag(AStmt->
getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
15403 <<
"#pragma omp unroll full";
15411 if (NumGeneratedTopLevelLoops == 0)
15413 NumGeneratedTopLevelLoops,
nullptr,
15459 Stmt *LoopStmt =
nullptr;
15464 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15467 QualType IVTy = IterationVarRef->getType();
15468 assert(LoopHelper.Counters.size() == 1 &&
15469 "Expecting a single-dimensional loop iteration space");
15477 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
15478 FactorLoc = FactorVal->getExprLoc();
15483 assert(Factor > 0 &&
"Expected positive unroll factor");
15484 auto MakeFactorExpr = [
this, Factor, IVTy, FactorLoc]() {
15496 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15497 std::string OuterIVName = (Twine(
".unrolled.iv.") + OrigVarName).str();
15498 std::string InnerIVName = (Twine(
".unroll_inner.iv.") + OrigVarName).str();
15503 auto MakeOuterRef = [
this, OuterIVDecl, IVTy, OrigVarLoc]() {
15509 auto *InnerIVDecl =
cast<VarDecl>(IterationVarRef->getDecl());
15510 InnerIVDecl->setDeclName(&
SemaRef.PP.getIdentifierTable().get(InnerIVName));
15511 auto MakeInnerRef = [
this, InnerIVDecl, IVTy, OrigVarLoc]() {
15517 CaptureVars CopyTransformer(
SemaRef);
15518 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() ->
Expr * {
15520 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15525 SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.
get(),
15540 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15541 MakeOuterRef(), MakeFactorExpr());
15545 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15546 MakeInnerRef(), EndOfTile.
get());
15550 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15551 MakeInnerRef(), MakeNumIterations());
15555 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
15556 InnerCond1.
get(), InnerCond2.
get());
15562 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef());
15568 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15569 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15570 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15571 InnerBodyStmts.push_back(Body);
15575 ForStmt *InnerFor =
new (Context)
15576 ForStmt(Context, InnerInit.
get(), InnerCond.
get(),
nullptr,
15578 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15592 LoopHintAttr *UnrollHintAttr =
15593 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
15594 LoopHintAttr::Numeric, MakeFactorExpr());
15599 SemaRef.AddInitializerToDecl(
15601 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15610 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15611 MakeOuterRef(), MakeNumIterations());
15617 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15618 MakeOuterRef(), MakeFactorExpr());
15623 ForStmt *OuterFor =
new (Context)
15624 ForStmt(Context, OuterInit.
get(), OuterConde.
get(),
nullptr,
15626 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15629 NumGeneratedTopLevelLoops, OuterFor,
15643 constexpr unsigned NumLoops = 1;
15644 Stmt *Body =
nullptr;
15648 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
15649 Body, OriginalInits))
15654 if (
SemaRef.CurContext->isDependentContext())
15656 NumLoops,
nullptr,
nullptr);
15658 assert(LoopHelpers.size() == NumLoops &&
15659 "Expecting a single-dimensional loop iteration space");
15660 assert(OriginalInits.size() == NumLoops &&
15661 "Expecting a single-dimensional loop iteration space");
15662 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15665 Stmt *LoopStmt =
nullptr;
15670 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15673 QualType IVTy = IterationVarRef->getType();
15674 uint64_t IVWidth = Context.getTypeSize(IVTy);
15688 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15690 ForwardIVName += OrigVarName;
15692 ReversedIVName += OrigVarName;
15725 CaptureVars CopyTransformer(
SemaRef);
15726 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() ->
Expr * {
15728 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15734 auto MakeForwardRef = [&
SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
15741 auto *ReversedIVDecl =
cast<VarDecl>(IterationVarRef->getDecl());
15742 ReversedIVDecl->setDeclName(
15743 &
SemaRef.PP.getIdentifierTable().get(ReversedIVName));
15750 ForwardIVDecl->
getType(), OrigVarLoc);
15751 SemaRef.AddInitializerToDecl(ForwardIVDecl,
Zero,
false);
15754 if (!
Init.isUsable())
15762 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15763 MakeForwardRef(), MakeNumIterations());
15764 if (!
Cond.isUsable())
15772 UO_PreInc, MakeForwardRef());
15783 MakeNumIterations(), One);
15786 Minus =
SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, Minus.
get(),
15791 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
15794 SemaRef.AddInitializerToDecl(ReversedIVDecl, Minus.
get(),
15799 BodyStmts.reserve(LoopHelper.Updates.size() + 2 +
15801 BodyStmts.push_back(InitReversed.
get());
15802 llvm::append_range(BodyStmts, LoopHelper.Updates);
15803 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15804 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15805 BodyStmts.push_back(Body);
15806 auto *ReversedBody =
15811 auto *ReversedFor =
new (Context)
15814 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15833 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
15834 size_t NumLoops = PermutationClause ? PermutationClause->
getNumLoops() : 2;
15838 Stmt *Body =
nullptr;
15840 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
15841 LoopHelpers, Body, OriginalInits))
15847 NumLoops, AStmt,
nullptr,
nullptr);
15851 if (PermutationClause &&
15852 llvm::is_contained(PermutationClause->
getArgsRefs(),
nullptr))
15855 assert(LoopHelpers.size() == NumLoops &&
15856 "Expecting loop iteration space dimensionaly to match number of "
15858 assert(OriginalInits.size() == NumLoops &&
15859 "Expecting loop iteration space dimensionaly to match number of "
15864 if (!PermutationClause) {
15865 Permutation = {1, 0};
15868 llvm::BitVector Flags(PermArgs.size());
15869 for (
Expr *PermArg : PermArgs) {
15870 std::optional<llvm::APSInt> PermCstExpr =
15871 PermArg->getIntegerConstantExpr(Context);
15874 uint64_t PermInt = PermCstExpr->getZExtValue();
15875 assert(1 <= PermInt && PermInt <= NumLoops &&
15876 "Must be a permutation; diagnostic emitted in "
15877 "ActOnOpenMPPermutationClause");
15878 if (Flags[PermInt - 1]) {
15879 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
15880 Diag(PermArg->getExprLoc(),
15881 diag::err_omp_interchange_permutation_value_repeated)
15882 << PermInt << ExprRange;
15885 Flags[PermInt - 1] =
true;
15887 Permutation.push_back(PermInt - 1);
15890 if (Permutation.size() != NumLoops)
15895 if (NumLoops <= 1 || llvm::all_of(llvm::enumerate(Permutation), [](
auto P) {
15896 auto [Idx, Arg] = P;
15900 NumLoops, AStmt, AStmt,
nullptr);
15908 for (
auto I : llvm::seq<int>(NumLoops)) {
15909 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15911 assert(LoopHelper.Counters.size() == 1 &&
15912 "Single-dimensional loop iteration space expected");
15919 CaptureVars CopyTransformer(
SemaRef);
15924 Stmt *Inner = Body;
15925 for (
auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
15927 uint64_t SourceIdx = Permutation[TargetIdx];
15928 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
15929 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
15930 assert(SourceHelper.Counters.size() == 1 &&
15931 "Single-dimensional loop iteration space expected");
15938 "Expected the logical iteration counter to be an integer");
15940 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15945 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() ->
Expr * {
15947 CopyTransformer.TransformExpr(SourceHelper.NumIterations));
15954 PermutedCntName.append({llvm::utostr(TargetIdx),
".iv.", OrigVarName});
15956 PermutedCntDecl->setDeclName(
15957 &
SemaRef.PP.getIdentifierTable().get(PermutedCntName));
15958 PermutedIndVars[TargetIdx] = PermutedCntDecl;
15959 auto MakePermutedRef = [
this, PermutedCntDecl, IVTy, OrigVarLoc]() {
15968 if (!
Zero.isUsable())
15970 SemaRef.AddInitializerToDecl(PermutedCntDecl,
Zero.get(),
15974 OrigCntVar->getEndLoc());
15983 SemaRef.BuildBinOp(CurScope, SourceHelper.Cond->getExprLoc(), BO_LT,
15984 MakePermutedRef(), MakeNumIterations());
15993 CurScope, SourceHelper.Inc->getExprLoc(), UO_PreInc, MakePermutedRef());
15998 SourceHelper.Updates.end());
15999 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
16000 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
16001 BodyParts.push_back(Inner);
16004 Inner =
new (Context)
ForStmt(
16005 Context, InitStmt.
get(), CondExpr.
get(),
nullptr, IncrStmt.
get(), Inner,
16006 SourceHelper.Init->
getBeginLoc(), SourceHelper.Init->getBeginLoc(),
16007 SourceHelper.Inc->getEndLoc());
16011 NumLoops, AStmt, Inner,
16023 CaptureVars CopyTransformer(
SemaRef);
16035 1, AStmt,
nullptr,
nullptr);
16039 LoopSequenceAnalysis SeqAnalysis;
16040 if (!checkTransformableLoopSequence(OMPD_fuse, AStmt, SeqAnalysis, Context))
16045 assert(SeqAnalysis.LoopSeqSize == SeqAnalysis.Loops.size() &&
16046 "Inconsistent size of the loop sequence and the number of loops "
16047 "found in the sequence");
16051 OMPExecutableDirective::getSingleClause<OMPLoopRangeClause>(Clauses);
16055 if (LRC && (!LRC->getFirst() || !LRC->getCount()))
16060 auto EvaluateLoopRangeArguments = [&Context](
Expr *
First,
Expr *Count,
16061 uint64_t &FirstVal,
16062 uint64_t &CountVal) {
16063 llvm::APSInt FirstInt =
First->EvaluateKnownConstInt(Context);
16064 llvm::APSInt CountInt = Count->EvaluateKnownConstInt(Context);
16065 FirstVal = FirstInt.getZExtValue();
16066 CountVal = CountInt.getZExtValue();
16072 auto ValidLoopRange = [](uint64_t FirstVal, uint64_t CountVal,
16073 unsigned NumLoops) ->
bool {
16074 return FirstVal + CountVal - 1 <= NumLoops;
16076 uint64_t FirstVal = 1, CountVal = 0, LastVal = SeqAnalysis.LoopSeqSize;
16082 EvaluateLoopRangeArguments(LRC->getFirst(), LRC->getCount(), FirstVal,
16085 SemaRef.Diag(LRC->getCountLoc(), diag::warn_omp_redundant_fusion)
16086 << getOpenMPDirectiveName(OMPD_fuse);
16088 if (!ValidLoopRange(FirstVal, CountVal, SeqAnalysis.LoopSeqSize)) {
16089 SemaRef.Diag(LRC->getFirstLoc(), diag::err_omp_invalid_looprange)
16090 << getOpenMPDirectiveName(OMPD_fuse) << FirstVal
16091 << (FirstVal + CountVal - 1) << SeqAnalysis.LoopSeqSize;
16095 LastVal = FirstVal + CountVal - 1;
16100 unsigned NumGeneratedTopLevelLoops =
16101 LRC ? SeqAnalysis.LoopSeqSize - CountVal + 1 : 1;
16105 if (SeqAnalysis.LoopSeqSize == 1)
16107 << getOpenMPDirectiveName(OMPD_fuse);
16111 SeqAnalysis.Loops[FirstVal - 1].HelperExprs.IterationVarRef->getType();
16112 for (
unsigned I : llvm::seq<unsigned>(FirstVal, LastVal)) {
16114 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef->getType();
16115 if (Context.getTypeSize(CurrentIVType) > Context.getTypeSize(IVType)) {
16116 IVType = CurrentIVType;
16119 uint64_t IVBitWidth = Context.getIntWidth(IVType);
16132 auto CreateHelperVarAndStmt =
16134 unsigned I,
bool NeedsNewVD =
false) {
16135 Expr *TransformedExpr =
16137 if (!TransformedExpr)
16138 return std::pair<VarDecl *, StmtResult>(
nullptr,
StmtError());
16140 auto Name = (Twine(
".omp.") + BaseName + std::to_string(I)).str();
16145 SemaRef.AddInitializerToDecl(VD, TransformedExpr,
false);
16155 return std::make_pair(VD,
DeclStmt);
16173 llvm::append_range(PreInits, SeqAnalysis.LoopSequencePreInits);
16186 unsigned int TransformIndex = 0;
16187 for (
unsigned I : llvm::seq<unsigned>(FirstVal - 1)) {
16188 if (SeqAnalysis.Loops[I].isLoopTransformation())
16192 for (
unsigned int I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16193 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16195 SeqAnalysis.Loops[I].TheForStmt,
16196 SeqAnalysis.Loops[I].OriginalInits, PreInits);
16197 }
else if (SeqAnalysis.Loops[I].isLoopTransformation()) {
16202 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16203 llvm::append_range(PreInits, TransformPreInit);
16206 SeqAnalysis.Loops[I].TheForStmt,
16207 SeqAnalysis.Loops[I].OriginalInits, PreInits);
16209 auto [UBVD, UBDStmt] =
16210 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.UB,
"ub", J);
16211 auto [LBVD, LBDStmt] =
16212 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.LB,
"lb", J);
16213 auto [STVD, STDStmt] =
16214 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.ST,
"st", J);
16215 auto [NIVD, NIDStmt] = CreateHelperVarAndStmt(
16216 SeqAnalysis.Loops[I].HelperExprs.NumIterations,
"ni", J,
true);
16217 auto [IVVD, IVDStmt] = CreateHelperVarAndStmt(
16218 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef,
"iv", J);
16220 assert(LBVD && STVD && NIVD && IVVD &&
16221 "OpenMP Fuse Helper variables creation failed");
16223 UBVarDecls.push_back(UBVD);
16224 LBVarDecls.push_back(LBVD);
16225 STVarDecls.push_back(STVD);
16226 NIVarDecls.push_back(NIVD);
16227 IVVarDecls.push_back(IVVD);
16229 PreInits.push_back(LBDStmt.get());
16230 PreInits.push_back(STDStmt.get());
16231 PreInits.push_back(NIDStmt.get());
16232 PreInits.push_back(IVDStmt.get());
16265 StringRef IndexName =
".omp.fuse.index";
16270 SemaRef.AddInitializerToDecl(IndexDecl, InitVal,
false);
16277 auto MakeIVRef = [&
SemaRef = this->SemaRef, IndexDecl, IVType,
16295 for (
unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16296 DeclRefExpr *NIRef = MakeVarDeclRef(NIVarDecls[J]);
16304 std::string TempName = (Twine(
".omp.temp.") + Twine(J)).str();
16318 PreInits.push_back(TempStmt.
get());
16327 DeclRefExpr *NIRef2 = MakeVarDeclRef(NIVarDecls[J]);
16341 const std::string MaxName = Twine(
".omp.fuse.max").str();
16349 if (MaxStmt.isInvalid())
16351 PreInits.push_back(MaxStmt.get());
16355 MakeIVRef(), MaxRef);
16381 for (
unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16386 MakeVarDeclRef(STVarDecls[J]), MakeIVRef());
16390 MakeVarDeclRef(LBVarDecls[J]), IdxExpr.
get());
16395 MakeVarDeclRef(IVVarDecls[J]), IdxExpr.
get());
16401 BodyStmts.push_back(IdxExpr.
get());
16402 llvm::append_range(BodyStmts, SeqAnalysis.Loops[I].HelperExprs.Updates);
16405 if (
auto *SourceCXXFor =
16406 dyn_cast<CXXForRangeStmt>(SeqAnalysis.Loops[I].TheForStmt))
16407 BodyStmts.push_back(SourceCXXFor->getLoopVarStmt());
16411 ?
cast<ForStmt>(SeqAnalysis.Loops[I].TheForStmt)->getBody()
16413 BodyStmts.push_back(Body);
16420 MakeVarDeclRef(NIVarDecls[J]));
16430 FusedBodyStmts.push_back(IfStatement);
16436 ForStmt *FusedForStmt =
new (Context)
16450 Stmt *FusionStmt = FusedForStmt;
16451 if (LRC && CountVal != SeqAnalysis.LoopSeqSize) {
16455 TransformIndex = 0;
16461 for (
unsigned I : llvm::seq<unsigned>(SeqAnalysis.LoopSeqSize)) {
16462 if (I >= FirstVal - 1 && I < FirstVal + CountVal - 1) {
16465 if (!SeqAnalysis.Loops[I].isLoopTransformation())
16474 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16475 const auto &TransformPreInit =
16476 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16477 if (!TransformPreInit.empty())
16478 llvm::append_range(PreInits, TransformPreInit);
16481 FinalLoops.push_back(SeqAnalysis.Loops[I].TheForStmt);
16484 FinalLoops.insert(FinalLoops.begin() + (FirstVal - 1), FusedForStmt);
16489 NumGeneratedTopLevelLoops, AStmt, FusionStmt,
16509 case OMPC_allocator:
16512 case OMPC_collapse:
16521 case OMPC_priority:
16533 case OMPC_novariants:
16536 case OMPC_nocontext:
16551 case OMPC_ompx_dyn_cgroup_mem:
16557 case OMPC_transparent:
16560 case OMPC_dyn_groupprivate:
16561 case OMPC_grainsize:
16562 case OMPC_num_tasks:
16563 case OMPC_num_threads:
16567 case OMPC_proc_bind:
16568 case OMPC_schedule:
16570 case OMPC_firstprivate:
16571 case OMPC_lastprivate:
16573 case OMPC_reduction:
16574 case OMPC_task_reduction:
16575 case OMPC_in_reduction:
16579 case OMPC_copyprivate:
16581 case OMPC_mergeable:
16582 case OMPC_threadprivate:
16583 case OMPC_groupprivate:
16585 case OMPC_allocate:
16602 case OMPC_dist_schedule:
16603 case OMPC_defaultmap:
16608 case OMPC_use_device_ptr:
16609 case OMPC_use_device_addr:
16610 case OMPC_is_device_ptr:
16611 case OMPC_unified_address:
16612 case OMPC_unified_shared_memory:
16613 case OMPC_reverse_offload:
16614 case OMPC_dynamic_allocators:
16615 case OMPC_atomic_default_mem_order:
16616 case OMPC_self_maps:
16617 case OMPC_device_type:
16619 case OMPC_nontemporal:
16622 case OMPC_severity:
16624 case OMPC_inclusive:
16625 case OMPC_exclusive:
16626 case OMPC_uses_allocators:
16627 case OMPC_affinity:
16630 case OMPC_num_teams:
16631 case OMPC_thread_limit:
16633 llvm_unreachable(
"Clause is not allowed.");
16646 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
16647 "Invalid directive with CKind-clause");
16650 if (NameModifier != OMPD_unknown &&
16651 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
16652 return OMPD_unknown;
16671 case OMPD_teams_loop:
16672 case OMPD_target_teams_loop:
16676 case OMPD_target_update:
16677 case OMPD_target_enter_data:
16678 case OMPD_target_exit_data:
16684 case OMPC_num_teams:
16685 case OMPC_thread_limit:
16686 case OMPC_ompx_dyn_cgroup_mem:
16687 case OMPC_dyn_groupprivate:
16689 if (Leafs[0] == OMPD_target)
16690 return OMPD_target;
16693 if (Leafs[0] == OMPD_target ||
16694 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
16695 OMPD_target_enter_data, OMPD_target_exit_data},
16699 case OMPC_novariants:
16700 case OMPC_nocontext:
16701 if (DKind == OMPD_dispatch)
16705 if (DKind == OMPD_metadirective)
16706 return OMPD_metadirective;
16709 return OMPD_unknown;
16722 int InnermostIdx = [&]() {
16723 for (
int I = EndIdx - 1; I >= 0; --I) {
16724 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
16732 for (
int I = InnermostIdx - 1; I >= 0; --I) {
16737 if (Regions[0] != OMPD_unknown)
16738 return Regions.back();
16740 return OMPD_unknown;
16745 for (
int I = 0, E = Leafs.size(); I != E; ++I) {
16746 if (Leafs[I] == Dir)
16752 int End = NameModifier == OMPD_unknown ? Leafs.size()
16753 : GetLeafIndex(NameModifier);
16754 return GetEnclosingRegion(End, CKind);
16757 return OMPD_unknown;
16765 Stmt *HelperValStmt =
nullptr;
16768 !
Condition->isInstantiationDependent() &&
16769 !
Condition->containsUnexpandedParameterPack()) {
16774 ValExpr = Val.
get();
16778 DKind, OMPC_if,
getLangOpts().OpenMP, NameModifier);
16779 if (CaptureRegion != OMPD_unknown &&
16780 !
SemaRef.CurContext->isDependentContext()) {
16781 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
16782 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16783 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16789 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
16790 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
16798 Stmt *HelperValStmt =
nullptr;
16801 !
Condition->isInstantiationDependent() &&
16802 !
Condition->containsUnexpandedParameterPack()) {
16807 ValExpr =
SemaRef.MakeFullExpr(Val.
get()).get();
16812 if (CaptureRegion != OMPD_unknown &&
16813 !
SemaRef.CurContext->isDependentContext()) {
16814 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
16815 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16816 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16822 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16833 IntConvertDiagnoser()
16834 : ICEConvertDiagnoser(
false,
false,
true) {}
16837 return S.
Diag(Loc, diag::err_omp_not_integral) <<
T;
16841 return S.
Diag(Loc, diag::err_omp_incomplete_type) <<
T;
16846 return S.
Diag(Loc, diag::err_omp_explicit_conversion) <<
T << ConvTy;
16855 return S.
Diag(Loc, diag::err_omp_ambiguous_conversion) <<
T;
16864 llvm_unreachable(
"conversion functions are permitted");
16866 } ConvertDiagnoser;
16867 return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
16872 bool StrictlyPositive,
bool BuildCapture =
false,
16875 Stmt **HelperValStmt =
nullptr) {
16881 if (
Value.isInvalid())
16884 ValExpr =
Value.get();
16886 if (std::optional<llvm::APSInt> Result =
16888 if (Result->isSigned() &&
16889 !((!StrictlyPositive && Result->isNonNegative()) ||
16890 (StrictlyPositive && Result->isStrictlyPositive()))) {
16891 SemaRef.
Diag(Loc, diag::err_omp_negative_expression_in_clause)
16901 if (*CaptureRegion != OMPD_unknown &&
16904 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16905 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16916 llvm::raw_svector_ostream
Out(Buffer);
16917 unsigned Skipped = Exclude.size();
16918 for (
unsigned I =
First; I <
Last; ++I) {
16919 if (llvm::is_contained(Exclude, I)) {
16924 if (I + Skipped + 2 ==
Last)
16926 else if (I + Skipped + 1 !=
Last)
16929 return std::string(
Out.str());
16937 "Unexpected num_threads modifier in OpenMP < 60.");
16942 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
16947 Expr *ValExpr = NumThreads;
16948 Stmt *HelperValStmt =
nullptr;
16959 if (CaptureRegion != OMPD_unknown &&
16960 !
SemaRef.CurContext->isDependentContext()) {
16961 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
16962 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16963 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16969 StartLoc, LParenLoc, ModifierLoc, EndLoc);
16974 bool SuppressExprDiags) {
16983 if (SuppressExprDiags) {
16987 SuppressedDiagnoser() : VerifyICEDiagnoser(
true) {}
16990 llvm_unreachable(
"Diagnostic suppressed");
16993 ICE =
SemaRef.VerifyIntegerConstantExpression(E, &
Result, Diagnoser,
17003 if ((StrictlyPositive && !
Result.isStrictlyPositive()) ||
17004 (!StrictlyPositive && !
Result.isNonNegative())) {
17005 Diag(E->
getExprLoc(), diag::err_omp_negative_expression_in_clause)
17010 if ((CKind == OMPC_aligned || CKind == OMPC_align ||
17011 CKind == OMPC_allocate) &&
17013 Diag(E->
getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
17018 if (!
Result.isRepresentableByInt64()) {
17024 if (CKind == OMPC_collapse &&
DSAStack->getAssociatedLoops() == 1)
17026 else if (CKind == OMPC_ordered)
17045 if (
Result.isNonNegative()) {
17049 diag::err_omp_negative_expression_in_clause)
17052 }
else if (
auto *DeclRef = dyn_cast<DeclRefExpr>(DeviceNumExpr)) {
17059 Diag(DeviceNumExpr->
getExprLoc(), diag::err_expected_expression);
17093 DSAStackTy *Stack) {
17094 if (!Stack->getOMPAllocatorHandleT().isNull())
17101 S.
Diag(Loc, diag::err_omp_implied_type_not_found)
17102 <<
"omp_allocator_handle_t";
17107 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
17110 bool ErrorFound =
false;
17111 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
17112 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
17113 StringRef Allocator =
17114 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
17116 auto *VD = dyn_cast_or_null<ValueDecl>(
17136 Stack->setAllocator(AllocatorKind, Res.
get());
17139 S.
Diag(Loc, diag::err_omp_implied_type_not_found)
17140 <<
"omp_allocator_handle_t";
17159 Allocator =
SemaRef.PerformImplicitConversion(
17160 Allocator.
get(),
DSAStack->getOMPAllocatorHandleT(),
17189 Expr *NumForLoops) {
17195 if (NumForLoops && LParenLoc.
isValid()) {
17200 NumForLoops = NumForLoopsResult.
get();
17202 NumForLoops =
nullptr;
17206 NumForLoops ?
DSAStack->getAssociatedLoops() : 0,
17207 StartLoc, LParenLoc, EndLoc);
17208 DSAStack->setOrderedRegion(
true, NumForLoops, Clause);
17217 case OMPC_proc_bind:
17219 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17221 case OMPC_atomic_default_mem_order:
17224 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17228 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17232 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17236 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17240 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17242 case OMPC_severity:
17245 LParenLoc, EndLoc);
17247 case OMPC_threadset:
17249 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17253 case OMPC_num_threads:
17257 case OMPC_allocator:
17258 case OMPC_collapse:
17259 case OMPC_schedule:
17261 case OMPC_firstprivate:
17262 case OMPC_lastprivate:
17264 case OMPC_reduction:
17265 case OMPC_task_reduction:
17266 case OMPC_in_reduction:
17270 case OMPC_copyprivate:
17274 case OMPC_mergeable:
17275 case OMPC_threadprivate:
17276 case OMPC_groupprivate:
17277 case OMPC_allocate:
17294 case OMPC_num_teams:
17295 case OMPC_thread_limit:
17296 case OMPC_priority:
17297 case OMPC_grainsize:
17299 case OMPC_num_tasks:
17301 case OMPC_dist_schedule:
17303 case OMPC_defaultmap:
17308 case OMPC_use_device_ptr:
17309 case OMPC_use_device_addr:
17310 case OMPC_is_device_ptr:
17311 case OMPC_has_device_addr:
17312 case OMPC_unified_address:
17313 case OMPC_unified_shared_memory:
17314 case OMPC_reverse_offload:
17315 case OMPC_dynamic_allocators:
17316 case OMPC_self_maps:
17317 case OMPC_device_type:
17319 case OMPC_nontemporal:
17321 case OMPC_novariants:
17322 case OMPC_nocontext:
17324 case OMPC_inclusive:
17325 case OMPC_exclusive:
17326 case OMPC_uses_allocators:
17327 case OMPC_affinity:
17331 llvm_unreachable(
"Clause is not allowed.");
17340 if (M == OMP_DEFAULT_unknown) {
17341 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17343 unsigned(OMP_DEFAULT_unknown))
17348 Diag(VCKindLoc, diag::err_omp_default_vc)
17353 bool IsTargetDefault =
17360 if (IsTargetDefault && M == OMP_DEFAULT_shared)
17363 auto SetDefaultClauseAttrs = [&](llvm::omp::DefaultKind M,
17369 case OMP_DEFAULT_none:
17370 if (IsTargetDefault)
17371 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_none;
17373 DSAStack->setDefaultDSANone(MLoc);
17375 case OMP_DEFAULT_firstprivate:
17376 if (IsTargetDefault)
17377 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_firstprivate;
17379 DSAStack->setDefaultDSAFirstPrivate(MLoc);
17381 case OMP_DEFAULT_private:
17382 if (IsTargetDefault)
17383 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_private;
17385 DSAStack->setDefaultDSAPrivate(MLoc);
17387 case OMP_DEFAULT_shared:
17388 assert(!IsTargetDefault &&
"DSA shared invalid with target directive");
17389 DSAStack->setDefaultDSAShared(MLoc);
17392 llvm_unreachable(
"unexpected DSA in OpenMP default clause");
17396 case OMPC_DEFAULT_VC_aggregate:
17397 if (IsTargetDefault)
17398 DefMapKind = OMPC_DEFAULTMAP_aggregate;
17400 DSAStack->setDefaultDSAVCAggregate(VCKindLoc);
17402 case OMPC_DEFAULT_VC_pointer:
17403 if (IsTargetDefault)
17404 DefMapKind = OMPC_DEFAULTMAP_pointer;
17406 DSAStack->setDefaultDSAVCPointer(VCKindLoc);
17408 case OMPC_DEFAULT_VC_scalar:
17409 if (IsTargetDefault)
17410 DefMapKind = OMPC_DEFAULTMAP_scalar;
17412 DSAStack->setDefaultDSAVCScalar(VCKindLoc);
17414 case OMPC_DEFAULT_VC_all:
17415 if (IsTargetDefault)
17416 DefMapKind = OMPC_DEFAULTMAP_all;
17418 DSAStack->setDefaultDSAVCAll(VCKindLoc);
17421 llvm_unreachable(
"unexpected variable category in OpenMP default clause");
17430 if (IsTargetDefault) {
17431 if (DefMapKind == OMPC_DEFAULTMAP_all) {
17432 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_aggregate, MLoc);
17433 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_scalar, MLoc);
17434 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_pointer, MLoc);
17436 DSAStack->setDefaultDMAAttr(DefMapMod, DefMapKind, MLoc);
17441 SetDefaultClauseAttrs(M, VCKind);
17443 OMPDefaultClause(M, MLoc, VCKind, VCKindLoc, StartLoc, LParenLoc, EndLoc);
17452 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17455 << getOpenMPClauseName(OMPC_threadset);
17464 Expr *ImpexTypeArg,
17472 return new (Ctx) OMPTransparentClause(ER.
get(), StartLoc, LParenLoc, EndLoc);
17488 SemaRef.Diag(StartLoc, diag::err_omp_implied_type_not_found)
17493 StartLoc, LParenLoc, EndLoc);
17498 StartLoc, LParenLoc, EndLoc);
17504 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(StartLoc,
17506 if (std::optional<llvm::APSInt>
Result =
17507 Value.get()->getIntegerConstantExpr(
SemaRef.Context)) {
17508 if (
Result->isNegative() ||
17511 SemaRef.Diag(StartLoc, diag::err_omp_transparent_invalid_value);
17514 StartLoc, LParenLoc, EndLoc);
17517 SemaRef.Diag(StartLoc, diag::err_omp_transparent_invalid_type) << Ty;
17526 if (Kind == OMP_PROC_BIND_unknown) {
17527 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17529 unsigned(OMP_PROC_BIND_master),
17532 ? OMP_PROC_BIND_primary
17533 : OMP_PROC_BIND_spread) +
17538 if (Kind == OMP_PROC_BIND_primary &&
getLangOpts().OpenMP < 51)
17539 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17541 unsigned(OMP_PROC_BIND_master),
17543 unsigned(OMP_PROC_BIND_spread) + 1)
17546 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17553 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17555 OMPC_atomic_default_mem_order, 0,
17560 return new (
getASTContext()) OMPAtomicDefaultMemOrderClause(
17561 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17570 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17577 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17586 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17593 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17600 assert(ME &&
"NULL expr in Message clause");
17609 Stmt *HelperValStmt =
nullptr;
17615 DKind == OMPD_unknown ? OMPD_unknown
17618 if (CaptureRegion != OMPD_unknown &&
17619 !
SemaRef.CurContext->isDependentContext()) {
17620 ME =
SemaRef.MakeFullExpr(ME).get();
17621 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17622 ME = tryBuildCapture(
SemaRef, ME, Captures).get();
17627 ME =
SemaRef.DefaultFunctionArrayLvalueConversion(ME).get();
17630 ME, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17637 if (Kind != OMPC_ORDER_concurrent ||
17642 "OMPC_ORDER_unknown not greater than 0");
17644 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17653 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17659 DSAStack->setRegionHasOrderConcurrent(
true);
17662 unsigned existingFlags =
DSAStack->getCurScope()->getFlags();
17663 DSAStack->getCurScope()->setFlags(existingFlags |
17668 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
17677 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
17679 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
17680 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
17682 Except.push_back(OMPC_DEPEND_inoutset);
17683 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17689 return OMPUpdateClause::Create(
getASTContext(), StartLoc, LParenLoc,
17690 KindKwLoc, Kind, EndLoc);
17699 for (
Expr *&SizeExpr : SanitizedSizeExprs) {
17709 QualType SizeTy = SizeExpr->getType();
17738 if (!SizeExpr->isInstantiationDependent() && !IsValid)
17739 SizeExpr =
nullptr;
17743 SanitizedSizeExprs);
17750 size_t NumLoops = PermExprs.size();
17752 llvm::append_range(SanitizedPermExprs, PermExprs);
17754 for (
Expr *&PermExpr : SanitizedPermExprs) {
17757 if (!PermExpr || PermExpr->isInstantiationDependent())
17760 llvm::APSInt PermVal;
17763 bool IsValid = PermEvalExpr.
isUsable();
17765 PermExpr = PermEvalExpr.
get();
17767 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
17771 diag::err_omp_interchange_permutation_value_range)
17772 << NumLoops << ExprRange;
17776 if (!PermExpr->isInstantiationDependent() && !IsValid)
17777 PermExpr =
nullptr;
17781 EndLoc, SanitizedPermExprs);
17797 FactorExpr, OMPC_partial,
true);
17800 FactorExpr = FactorResult.
get();
17829 FirstLoc, CountLoc, EndLoc,
First, Count);
17840 LParenLoc, EndLoc);
17850 case OMPC_schedule: {
17851 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
17852 assert(Argument.size() == NumberOfElements &&
17853 ArgumentLoc.size() == NumberOfElements);
17858 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
17859 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
17863 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17865 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
17868 case OMPC_dist_schedule:
17871 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
17874 enum { DefaultModifier, DefaultVarCategory };
17876 static_cast<llvm::omp::DefaultKind
>(Argument[DefaultModifier]),
17877 ArgumentLoc[DefaultModifier],
17879 Argument[DefaultVarCategory]),
17880 ArgumentLoc[DefaultVarCategory], StartLoc, LParenLoc, EndLoc);
17882 case OMPC_defaultmap:
17883 enum { Modifier, DefaultmapKind };
17887 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
17891 enum { OrderModifier, OrderKind };
17895 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
17898 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17901 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17903 case OMPC_grainsize:
17904 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17905 "Modifier for grainsize clause and its location are expected.");
17908 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17910 case OMPC_num_tasks:
17911 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17912 "Modifier for num_tasks clause and its location are expected.");
17915 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17917 case OMPC_dyn_groupprivate: {
17918 enum { Modifier1, Modifier2, NumberOfElements };
17919 assert(Argument.size() == NumberOfElements &&
17920 ArgumentLoc.size() == NumberOfElements &&
17921 "Modifiers for dyn_groupprivate clause and their locations are "
17926 Argument[Modifier2]),
17927 Expr, StartLoc, LParenLoc, ArgumentLoc[Modifier1],
17928 ArgumentLoc[Modifier2], EndLoc);
17931 case OMPC_num_threads:
17932 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17933 "Modifier for num_threads clause and its location are expected.");
17936 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17942 case OMPC_allocator:
17943 case OMPC_collapse:
17944 case OMPC_proc_bind:
17946 case OMPC_firstprivate:
17947 case OMPC_lastprivate:
17949 case OMPC_reduction:
17950 case OMPC_task_reduction:
17951 case OMPC_in_reduction:
17955 case OMPC_copyprivate:
17959 case OMPC_mergeable:
17960 case OMPC_threadprivate:
17961 case OMPC_groupprivate:
17962 case OMPC_allocate:
17979 case OMPC_num_teams:
17980 case OMPC_thread_limit:
17981 case OMPC_priority:
17988 case OMPC_use_device_ptr:
17989 case OMPC_use_device_addr:
17990 case OMPC_is_device_ptr:
17991 case OMPC_has_device_addr:
17992 case OMPC_unified_address:
17993 case OMPC_unified_shared_memory:
17994 case OMPC_reverse_offload:
17995 case OMPC_dynamic_allocators:
17996 case OMPC_atomic_default_mem_order:
17997 case OMPC_self_maps:
17998 case OMPC_device_type:
18000 case OMPC_nontemporal:
18002 case OMPC_severity:
18005 case OMPC_novariants:
18006 case OMPC_nocontext:
18008 case OMPC_inclusive:
18009 case OMPC_exclusive:
18010 case OMPC_uses_allocators:
18011 case OMPC_affinity:
18015 llvm_unreachable(
"Clause is not allowed.");
18026 Excluded.push_back(M2);
18027 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
18028 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
18029 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
18030 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
18031 S.
Diag(M1Loc, diag::err_omp_unexpected_clause_value)
18054 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
18055 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
18056 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
18057 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
18058 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
18064 std::string Values;
18074 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
18083 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
18084 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
18085 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
18086 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
18087 diag::err_omp_schedule_nonmonotonic_static);
18090 Expr *ValExpr = ChunkSize;
18091 Stmt *HelperValStmt =
nullptr;
18102 ValExpr = Val.
get();
18107 if (std::optional<llvm::APSInt>
Result =
18109 if (
Result->isSigned() && !
Result->isStrictlyPositive()) {
18110 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
18115 DSAStack->getCurrentDirective(), OMPC_schedule,
18117 !
SemaRef.CurContext->isDependentContext()) {
18118 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
18119 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18120 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
18127 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
18128 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
18147 case OMPC_mergeable:
18195 case OMPC_unified_address:
18198 case OMPC_unified_shared_memory:
18201 case OMPC_reverse_offload:
18204 case OMPC_dynamic_allocators:
18207 case OMPC_self_maps:
18221 case OMPC_ompx_bare:
18226 case OMPC_num_threads:
18230 case OMPC_allocator:
18231 case OMPC_collapse:
18232 case OMPC_schedule:
18234 case OMPC_firstprivate:
18235 case OMPC_lastprivate:
18237 case OMPC_reduction:
18238 case OMPC_task_reduction:
18239 case OMPC_in_reduction:
18243 case OMPC_copyprivate:
18245 case OMPC_proc_bind:
18246 case OMPC_threadprivate:
18247 case OMPC_groupprivate:
18248 case OMPC_allocate:
18254 case OMPC_num_teams:
18255 case OMPC_thread_limit:
18256 case OMPC_priority:
18257 case OMPC_grainsize:
18258 case OMPC_num_tasks:
18260 case OMPC_dist_schedule:
18261 case OMPC_defaultmap:
18266 case OMPC_use_device_ptr:
18267 case OMPC_use_device_addr:
18268 case OMPC_is_device_ptr:
18269 case OMPC_has_device_addr:
18270 case OMPC_atomic_default_mem_order:
18271 case OMPC_device_type:
18273 case OMPC_nontemporal:
18276 case OMPC_severity:
18278 case OMPC_novariants:
18279 case OMPC_nocontext:
18281 case OMPC_inclusive:
18282 case OMPC_exclusive:
18283 case OMPC_uses_allocators:
18284 case OMPC_affinity:
18286 case OMPC_ompx_dyn_cgroup_mem:
18287 case OMPC_dyn_groupprivate:
18289 llvm_unreachable(
"Clause is not allowed.");
18301 !
Condition->isInstantiationDependent() &&
18302 !
Condition->containsUnexpandedParameterPack()) {
18307 ValExpr = Val.
get();
18312 OMPNowaitClause(ValExpr, StartLoc, LParenLoc, EndLoc);
18318 return new (
getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
18323 return new (
getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
18328 return new (
getASTContext()) OMPReadClause(StartLoc, EndLoc);
18333 return new (
getASTContext()) OMPWriteClause(StartLoc, EndLoc);
18338 return OMPUpdateClause::Create(
getASTContext(), StartLoc, EndLoc);
18343 return new (
getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
18348 return new (
getASTContext()) OMPCompareClause(StartLoc, EndLoc);
18353 return new (
getASTContext()) OMPFailClause(StartLoc, EndLoc);
18363 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
18367 OMPFailClause(
Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
18372 return new (
getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
18377 return new (
getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
18382 return new (
getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
18387 return new (
getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
18392 return new (
getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
18397 return new (
getASTContext()) OMPWeakClause(StartLoc, EndLoc);
18417 return new (
getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
18423 return new (
getASTContext()) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
18428 return new (
getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
18434 return new (
getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
18439 return new (
getASTContext()) OMPSelfMapsClause(StartLoc, EndLoc);
18449 if (!
hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
18451 StringRef
Expected =
"'init', 'use', 'destroy', or 'nowait'";
18452 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
18453 <<
Expected << getOpenMPDirectiveName(OMPD_interop, OMPVersion);
18466 bool HasInitClause =
false;
18467 bool IsTargetSync =
false;
18471 if (
const auto *InitClause = dyn_cast<OMPInitClause>(
C)) {
18472 HasInitClause =
true;
18473 if (InitClause->getIsTargetSync())
18474 IsTargetSync =
true;
18475 }
else if (
const auto *DC = dyn_cast<OMPDependClause>(
C)) {
18479 if (DependClause && HasInitClause && !IsTargetSync) {
18480 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
18494 if (ClauseKind == OMPC_init) {
18497 }
else if (ClauseKind == OMPC_use) {
18500 }
else if (ClauseKind == OMPC_destroy) {
18506 if (!InteropVars.insert(
DeclResult.first).second) {
18507 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
18523 Expr *RefExpr = InteropVarExpr;
18538 bool HasError =
false;
18544 if (
const auto *TD = dyn_cast<TypeDecl>(ND)) {
18545 InteropType =
QualType(TD->getTypeForDecl(), 0);
18554 SemaRef.
Diag(VarLoc, diag::err_omp_implied_type_not_found)
18555 <<
"omp_interop_t";
18561 SemaRef.
Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
18567 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
18569 SemaRef.
Diag(VarLoc, diag::err_omp_interop_variable_expected)
18598 StartLoc, LParenLoc, VarLoc, EndLoc);
18611 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
18620 DSAStack->getCurrentDirective() == OMPD_depobj) {
18622 Diag(StartLoc, diag::err_omp_expected_clause_argument)
18624 << getOpenMPDirectiveName(OMPD_depobj, OMPVersion);
18640 Stmt *HelperValStmt =
nullptr;
18643 !
Condition->isInstantiationDependent() &&
18644 !
Condition->containsUnexpandedParameterPack()) {
18649 ValExpr =
SemaRef.MakeFullExpr(Val.
get()).get();
18654 if (CaptureRegion != OMPD_unknown &&
18655 !
SemaRef.CurContext->isDependentContext()) {
18656 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
18657 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18658 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
18664 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18672 Stmt *HelperValStmt =
nullptr;
18675 !
Condition->isInstantiationDependent() &&
18676 !
Condition->containsUnexpandedParameterPack()) {
18681 ValExpr =
SemaRef.MakeFullExpr(Val.
get()).get();
18686 if (CaptureRegion != OMPD_unknown &&
18687 !
SemaRef.CurContext->isDependentContext()) {
18688 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
18689 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18690 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
18696 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18703 Expr *ValExpr = ThreadID;
18704 Stmt *HelperValStmt =
nullptr;
18709 if (CaptureRegion != OMPD_unknown &&
18710 !
SemaRef.CurContext->isDependentContext()) {
18711 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
18712 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18713 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
18718 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18729 int ExtraModifier =
Data.ExtraModifier;
18730 int OriginalSharingModifier =
Data.OriginalSharingModifier;
18737 case OMPC_firstprivate:
18740 case OMPC_lastprivate:
18742 "Unexpected lastprivate modifier.");
18745 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
18750 case OMPC_reduction:
18752 "Unexpected lastprivate modifier.");
18756 ExtraModifier, OriginalSharingModifier),
18757 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
18758 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
18760 case OMPC_task_reduction:
18762 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18763 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
18765 case OMPC_in_reduction:
18767 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18768 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
18772 "Unexpected linear modifier.");
18774 VarList,
Data.DepModOrTailExpr, StartLoc, LParenLoc,
18776 ColonLoc,
Data.StepModifierLoc, EndLoc);
18780 LParenLoc, ColonLoc, EndLoc);
18785 case OMPC_copyprivate:
18793 "Unexpected depend modifier.");
18796 ColonLoc,
Data.OmpAllMemoryLoc},
18797 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
18801 "Unexpected map modifier.");
18803 Data.IteratorExpr,
Data.MapTypeModifiers,
Data.MapTypeModifiersLoc,
18804 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId,
18806 ExtraModifierLoc, ColonLoc, VarList, Locs);
18810 Data.MotionModifiers,
Data.MotionModifiersLoc,
Data.IteratorExpr,
18811 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId, ColonLoc,
18816 Data.MotionModifiers,
Data.MotionModifiersLoc,
Data.IteratorExpr,
18817 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId, ColonLoc,
18820 case OMPC_use_device_ptr:
18821 assert(0 <=
Data.ExtraModifier &&
18823 "Unexpected use_device_ptr fallback modifier.");
18827 Data.ExtraModifierLoc);
18829 case OMPC_use_device_addr:
18832 case OMPC_is_device_ptr:
18835 case OMPC_has_device_addr:
18838 case OMPC_allocate: {
18842 if (!
Data.AllocClauseModifiers.empty()) {
18843 assert(
Data.AllocClauseModifiers.size() <= 2 &&
18844 "More allocate modifiers than expected");
18845 Modifier1 =
Data.AllocClauseModifiers[0];
18846 Modifier1Loc =
Data.AllocClauseModifiersLoc[0];
18847 if (
Data.AllocClauseModifiers.size() == 2) {
18848 Modifier2 =
Data.AllocClauseModifiers[1];
18849 Modifier2Loc =
Data.AllocClauseModifiersLoc[1];
18853 Data.DepModOrTailExpr,
Data.AllocateAlignment, Modifier1, Modifier1Loc,
18854 Modifier2, Modifier2Loc, VarList, StartLoc, LParenLoc, ColonLoc,
18858 case OMPC_nontemporal:
18861 case OMPC_inclusive:
18864 case OMPC_exclusive:
18867 case OMPC_affinity:
18869 Data.DepModOrTailExpr, VarList);
18871 case OMPC_doacross:
18874 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
18876 case OMPC_num_teams:
18879 case OMPC_thread_limit:
18885 case OMPC_num_threads:
18889 case OMPC_allocator:
18890 case OMPC_collapse:
18892 case OMPC_proc_bind:
18893 case OMPC_schedule:
18897 case OMPC_mergeable:
18898 case OMPC_threadprivate:
18899 case OMPC_groupprivate:
18913 case OMPC_priority:
18914 case OMPC_grainsize:
18916 case OMPC_num_tasks:
18918 case OMPC_dist_schedule:
18919 case OMPC_defaultmap:
18922 case OMPC_unified_address:
18923 case OMPC_unified_shared_memory:
18924 case OMPC_reverse_offload:
18925 case OMPC_dynamic_allocators:
18926 case OMPC_atomic_default_mem_order:
18927 case OMPC_self_maps:
18928 case OMPC_device_type:
18932 case OMPC_severity:
18935 case OMPC_novariants:
18936 case OMPC_nocontext:
18938 case OMPC_uses_allocators:
18942 llvm_unreachable(
"Clause is not allowed.");
18955 Res =
SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.
get());
18960 Res =
SemaRef.DefaultLvalueConversion(Res.
get());
18974 bool IsImplicitClause =
18976 for (
Expr *RefExpr : VarList) {
18977 assert(RefExpr &&
"NULL expr in OpenMP private clause.");
18980 Expr *SimpleRefExpr = RefExpr;
18984 Vars.push_back(RefExpr);
18985 PrivateCopies.push_back(
nullptr);
18992 auto *VD = dyn_cast<VarDecl>(D);
18998 diag::err_omp_private_incomplete_type))
19000 Type =
Type.getNonReferenceType();
19020 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
19021 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
19022 Diag(ELoc, diag::err_omp_wrong_dsa)
19033 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19035 << getOpenMPDirectiveName(CurrDir, OMPVersion);
19036 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19039 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19054 CurrDir == OMPD_target) {
19056 if (
DSAStack->checkMappableExprComponentListsForDecl(
19060 ConflictKind = WhereFoundClauseKind;
19063 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
19066 << getOpenMPDirectiveName(CurrDir, OMPVersion);
19086 SemaRef.ActOnUninitializedDecl(VDPrivate);
19093 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
19094 auto *FD = dyn_cast<FieldDecl>(D);
19098 RefExpr->getExprLoc());
19102 if (!IsImplicitClause)
19103 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
19104 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
19105 ? RefExpr->IgnoreParens()
19107 PrivateCopies.push_back(VDPrivateRefExpr);
19113 return OMPPrivateClause::Create(
getASTContext(), StartLoc, LParenLoc, EndLoc,
19114 Vars, PrivateCopies);
19125 bool IsImplicitClause =
19130 for (
Expr *RefExpr : VarList) {
19131 assert(RefExpr &&
"NULL expr in OpenMP firstprivate clause.");
19134 Expr *SimpleRefExpr = RefExpr;
19138 Vars.push_back(RefExpr);
19139 PrivateCopies.push_back(
nullptr);
19140 Inits.push_back(
nullptr);
19146 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
19148 auto *VD = dyn_cast<VarDecl>(D);
19154 diag::err_omp_firstprivate_incomplete_type))
19156 Type =
Type.getNonReferenceType();
19166 DSAStackTy::DSAVarData TopDVar;
19167 if (!IsImplicitClause) {
19168 DSAStackTy::DSAVarData DVar =
19180 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
19182 DVar.CKind != OMPC_lastprivate) &&
19184 Diag(ELoc, diag::err_omp_wrong_dsa)
19202 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
19203 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
19204 Diag(ELoc, diag::err_omp_wrong_dsa)
19230 DVar =
DSAStack->getImplicitDSA(D,
true);
19231 if (DVar.CKind != OMPC_shared &&
19234 DVar.DKind == OMPD_unknown)) {
19235 Diag(ELoc, diag::err_omp_required_access)
19257 return C == OMPC_reduction && !AppliedToPointee;
19265 if (DVar.CKind == OMPC_reduction &&
19269 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
19270 << getOpenMPDirectiveName(DVar.DKind, OMPVersion);
19286 CurrDir == OMPD_target) {
19288 if (
DSAStack->checkMappableExprComponentListsForDecl(
19293 ConflictKind = WhereFoundClauseKind;
19296 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
19299 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
19310 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19312 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
19314 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19317 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19332 Expr *VDInitRefExpr =
nullptr;
19342 ElemType,
".firstprivate.temp");
19357 ".firstprivate.temp");
19359 RefExpr->getExprLoc());
19360 SemaRef.AddInitializerToDecl(
19361 VDPrivate,
SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
19365 if (IsImplicitClause) {
19366 Diag(RefExpr->getExprLoc(),
19367 diag::note_omp_task_predetermined_firstprivate_here);
19371 SemaRef.CurContext->addDecl(VDPrivate);
19374 RefExpr->getExprLoc());
19376 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
19377 if (TopDVar.CKind == OMPC_lastprivate) {
19378 Ref = TopDVar.PrivateCopy;
19380 auto *FD = dyn_cast<FieldDecl>(D);
19385 RefExpr->getExprLoc());
19389 ExprCaptures.push_back(Ref->
getDecl());
19392 if (!IsImplicitClause)
19393 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
19394 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
19395 ? RefExpr->IgnoreParens()
19397 PrivateCopies.push_back(VDPrivateRefExpr);
19398 Inits.push_back(VDInitRefExpr);
19404 return OMPFirstprivateClause::Create(
19414 assert(ColonLoc.
isValid() &&
"Colon location must be valid.");
19415 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
19428 for (
Expr *RefExpr : VarList) {
19429 assert(RefExpr &&
"NULL expr in OpenMP lastprivate clause.");
19432 Expr *SimpleRefExpr = RefExpr;
19436 Vars.push_back(RefExpr);
19437 SrcExprs.push_back(
nullptr);
19438 DstExprs.push_back(
nullptr);
19439 AssignmentOps.push_back(
nullptr);
19446 auto *VD = dyn_cast<VarDecl>(D);
19452 diag::err_omp_lastprivate_incomplete_type))
19454 Type =
Type.getNonReferenceType();
19471 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
19472 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19475 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19489 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
19490 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
19492 DVar.CKind != OMPC_firstprivate) &&
19493 (DVar.CKind != OMPC_private || DVar.RefExpr !=
nullptr)) {
19494 Diag(ELoc, diag::err_omp_wrong_dsa)
19507 DSAStackTy::DSAVarData TopDVar = DVar;
19511 DVar =
DSAStack->getImplicitDSA(D,
true);
19512 if (DVar.CKind != OMPC_shared) {
19513 Diag(ELoc, diag::err_omp_required_access)
19531 Type.getUnqualifiedType(),
".lastprivate.src",
19542 PseudoDstExpr, PseudoSrcExpr);
19545 AssignmentOp =
SemaRef.ActOnFinishFullExpr(AssignmentOp.
get(), ELoc,
19551 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
19552 if (TopDVar.CKind == OMPC_firstprivate) {
19553 Ref = TopDVar.PrivateCopy;
19557 ExprCaptures.push_back(Ref->
getDecl());
19559 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
19567 SimpleRefExpr, RefRes.
get());
19570 ExprPostUpdates.push_back(
19571 SemaRef.IgnoredValueConversions(PostUpdateRes.
get()).get());
19574 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
19575 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
19576 ? RefExpr->IgnoreParens()
19578 SrcExprs.push_back(PseudoSrcExpr);
19579 DstExprs.push_back(PseudoDstExpr);
19580 AssignmentOps.push_back(AssignmentOp.
get());
19586 return OMPLastprivateClause::Create(
19587 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
19588 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
19598 for (
Expr *RefExpr : VarList) {
19599 assert(RefExpr &&
"NULL expr in OpenMP shared clause.");
19602 Expr *SimpleRefExpr = RefExpr;
19606 Vars.push_back(RefExpr);
19612 auto *VD = dyn_cast<VarDecl>(D);
19620 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
19621 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
19623 Diag(ELoc, diag::err_omp_wrong_dsa)
19632 !
SemaRef.CurContext->isDependentContext())
19634 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
19635 Vars.push_back((VD || !Ref ||
SemaRef.CurContext->isDependentContext())
19636 ? RefExpr->IgnoreParens()
19643 return OMPSharedClause::Create(
getASTContext(), StartLoc, LParenLoc, EndLoc,
19648class DSARefChecker :
public StmtVisitor<DSARefChecker, bool> {
19653 if (
auto *VD = dyn_cast<VarDecl>(E->
getDecl())) {
19654 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD,
false);
19655 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
19657 if (DVar.CKind != OMPC_unknown)
19659 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
19666 return DVarPrivate.CKind != OMPC_unknown;
19670 bool VisitStmt(Stmt *S) {
19671 for (Stmt *Child : S->
children()) {
19672 if (Child && Visit(Child))
19677 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
19684class TransformExprToCaptures :
public TreeTransform<TransformExprToCaptures> {
19685 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
19686 ValueDecl *
Field =
nullptr;
19687 DeclRefExpr *CapturedExpr =
nullptr;
19690 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
19691 : BaseTransform(SemaRef),
Field(FieldDecl), CapturedExpr(
nullptr) {}
19693 ExprResult TransformMemberExpr(MemberExpr *E) {
19696 CapturedExpr =
buildCapture(SemaRef, Field, E,
false);
19697 return CapturedExpr;
19699 return BaseTransform::TransformMemberExpr(E);
19701 DeclRefExpr *getCapturedExpr() {
return CapturedExpr; }
19705template <
typename T,
typename U>
19708 for (
U &
Set : Lookups) {
19709 for (
auto *D :
Set) {
19720 for (
auto *RD : D->
redecls()) {
19743 AssociatedClasses);
19756 for (
auto *NS : AssociatedNamespaces) {
19769 for (
auto *D : R) {
19770 auto *Underlying = D;
19771 if (
auto *USD = dyn_cast<UsingShadowDecl>(D))
19772 Underlying = USD->getTargetDecl();
19782 if (
auto *USD = dyn_cast<UsingShadowDecl>(D))
19783 Underlying = USD->getTargetDecl();
19785 Lookups.emplace_back();
19786 Lookups.back().addDecl(Underlying);
19810 Lookups.emplace_back();
19811 Lookups.back().append(Lookup.
begin(), Lookup.
end());
19814 }
else if (
auto *ULE =
19815 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
19817 Decl *PrevD =
nullptr;
19821 else if (
auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
19822 Lookups.back().addDecl(DRD);
19830 return !D->isInvalidDecl() &&
19831 (D->getType()->isDependentType() ||
19832 D->getType()->isInstantiationDependentType() ||
19833 D->getType()->containsUnexpandedParameterPack());
19846 true, ResSet.
begin(), ResSet.
end(),
false,
19869 if (IsComplete || RD->isBeingDefined()) {
19872 if (Lookup.
empty()) {
19873 Lookups.emplace_back();
19874 Lookups.back().append(Lookup.
begin(), Lookup.
end());
19916 if (ReductionIdScopeSpec.
isSet()) {
19917 SemaRef.
Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
19926struct ReductionData {
19928 SmallVector<Expr *, 8> Vars;
19932 SmallVector<Expr *, 8> LHSs;
19934 SmallVector<Expr *, 8> RHSs;
19936 SmallVector<Expr *, 8> ReductionOps;
19938 SmallVector<Expr *, 8> InscanCopyOps;
19940 SmallVector<Expr *, 8> InscanCopyArrayTemps;
19942 SmallVector<Expr *, 8> InscanCopyArrayElems;
19945 SmallVector<Expr *, 8> TaskgroupDescriptors;
19947 SmallVector<Decl *, 4> ExprCaptures;
19949 SmallVector<Expr *, 4> ExprPostUpdates;
19951 unsigned RedModifier = 0;
19953 unsigned OrigSharingModifier = 0;
19955 SmallVector<bool, 8> IsPrivateVarReduction;
19956 ReductionData() =
delete;
19958 ReductionData(
unsigned Size,
unsigned Modifier = 0,
unsigned OrgModifier = 0)
19959 : RedModifier(Modifier), OrigSharingModifier(OrgModifier) {
19960 Vars.reserve(Size);
19962 LHSs.reserve(Size);
19963 RHSs.reserve(Size);
19964 ReductionOps.reserve(Size);
19965 IsPrivateVarReduction.reserve(Size);
19966 if (RedModifier == OMPC_REDUCTION_inscan) {
19967 InscanCopyOps.reserve(Size);
19968 InscanCopyArrayTemps.reserve(Size);
19969 InscanCopyArrayElems.reserve(Size);
19971 TaskgroupDescriptors.reserve(Size);
19972 ExprCaptures.reserve(Size);
19973 ExprPostUpdates.reserve(Size);
19977 void push(Expr *Item, Expr *ReductionOp) {
19978 Vars.emplace_back(Item);
19980 LHSs.emplace_back(
nullptr);
19981 RHSs.emplace_back(
nullptr);
19982 ReductionOps.emplace_back(ReductionOp);
19983 IsPrivateVarReduction.emplace_back(
false);
19984 TaskgroupDescriptors.emplace_back(
nullptr);
19985 if (RedModifier == OMPC_REDUCTION_inscan) {
19986 InscanCopyOps.push_back(
nullptr);
19987 InscanCopyArrayTemps.push_back(
nullptr);
19988 InscanCopyArrayElems.push_back(
nullptr);
19992 void push(Expr *Item, Expr *
Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
19993 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
19994 Expr *CopyArrayElem,
bool IsPrivate) {
19995 Vars.emplace_back(Item);
19997 LHSs.emplace_back(LHS);
19998 RHSs.emplace_back(RHS);
19999 ReductionOps.emplace_back(ReductionOp);
20000 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
20001 if (RedModifier == OMPC_REDUCTION_inscan) {
20002 InscanCopyOps.push_back(CopyOp);
20003 InscanCopyArrayTemps.push_back(CopyArrayTemp);
20004 InscanCopyArrayElems.push_back(CopyArrayElem);
20006 assert(CopyOp ==
nullptr && CopyArrayTemp ==
nullptr &&
20007 CopyArrayElem ==
nullptr &&
20008 "Copy operation must be used for inscan reductions only.");
20010 IsPrivateVarReduction.emplace_back(IsPrivate);
20019 if (Length ==
nullptr) {
20026 SingleElement =
true;
20027 ArraySizes.push_back(llvm::APSInt::get(1));
20030 if (!Length->EvaluateAsInt(Result, Context))
20033 llvm::APSInt ConstantLengthValue = Result.
Val.
getInt();
20034 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
20035 ArraySizes.push_back(ConstantLengthValue);
20043 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base)) {
20044 Length = TempOASE->getLength();
20045 if (Length ==
nullptr) {
20052 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
20053 ArraySizes.push_back(ConstantOne);
20056 if (!Length->EvaluateAsInt(Result, Context))
20059 llvm::APSInt ConstantLengthValue = Result.
Val.
getInt();
20060 if (ConstantLengthValue.getSExtValue() != 1)
20063 ArraySizes.push_back(ConstantLengthValue);
20065 Base = TempOASE->getBase()->IgnoreParenImpCasts();
20069 if (!SingleElement) {
20070 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base)) {
20072 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
20073 ArraySizes.push_back(ConstantOne);
20074 Base = TempASE->getBase()->IgnoreParenImpCasts();
20086 return BO_AddAssign;
20088 return BO_MulAssign;
20090 return BO_AndAssign;
20092 return BO_OrAssign;
20094 return BO_XorAssign;
20150 case OO_Array_Delete:
20159 case OO_GreaterEqual:
20161 case OO_MinusEqual:
20163 case OO_SlashEqual:
20164 case OO_PercentEqual:
20165 case OO_CaretEqual:
20169 case OO_GreaterGreater:
20170 case OO_LessLessEqual:
20171 case OO_GreaterGreaterEqual:
20172 case OO_EqualEqual:
20173 case OO_ExclaimEqual:
20176 case OO_MinusMinus:
20182 case OO_Conditional:
20185 llvm_unreachable(
"Unexpected reduction identifier");
20188 if (II->isStr(
"max"))
20190 else if (II->isStr(
"min"))
20198 if (OOK == OO_Minus && S.
LangOpts.OpenMP == 52)
20199 S.
Diag(ReductionId.
getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
20202 if (ReductionIdScopeSpec.
isValid())
20208 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
20209 bool FirstIter =
true;
20210 for (
Expr *RefExpr : VarList) {
20211 assert(RefExpr &&
"nullptr expr in OpenMP reduction clause.");
20219 if (!FirstIter && IR != ER)
20224 bool IsPrivate =
false;
20225 Expr *SimpleRefExpr = RefExpr;
20234 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
20235 ReductionId,
Type, BasePath, IR == ER ?
nullptr : *IR);
20236 Expr *ReductionOp =
nullptr;
20238 (DeclareReductionRef.
isUnset() ||
20240 ReductionOp = DeclareReductionRef.
get();
20242 RD.push(RefExpr, ReductionOp);
20248 Expr *TaskgroupDescriptor =
nullptr;
20250 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
20251 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
20253 Type = ASE->getType().getNonReferenceType();
20257 if (
const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20258 Type = ATy->getElementType();
20261 Type =
Type.getNonReferenceType();
20265 auto *VD = dyn_cast<VarDecl>(D);
20271 diag::err_omp_reduction_incomplete_type))
20277 false, ASE || OASE))
20284 if (!ASE && !OASE) {
20286 VarDecl *VDDef = VD->getDefinition();
20288 DSARefChecker Check(Stack);
20289 if (Check.Visit(VDDef->
getInit())) {
20290 S.
Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
20309 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D,
false);
20310 if (DVar.CKind == OMPC_reduction) {
20311 S.
Diag(ELoc, diag::err_omp_once_referenced)
20317 if (DVar.CKind != OMPC_unknown) {
20318 S.
Diag(ELoc, diag::err_omp_wrong_dsa)
20334 DVar = Stack->getImplicitDSA(D,
true);
20335 if (DVar.CKind != OMPC_shared) {
20336 S.
Diag(ELoc, diag::err_omp_required_access)
20350 DVar = Stack->getImplicitDSA(D,
true);
20352 IsPrivate = DVar.CKind != OMPC_shared;
20353 bool IsOrphaned =
false;
20355 IsOrphaned = ParentDir == OMPD_unknown;
20357 RD.OrigSharingModifier == OMPC_ORIGINAL_SHARING_private))
20363 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D,
false);
20364 if (DVar.CKind == OMPC_threadprivate) {
20365 S.
Diag(ELoc, diag::err_omp_wrong_dsa)
20377 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
20378 ReductionId,
Type, BasePath, IR == ER ?
nullptr : *IR);
20382 (DeclareReductionRef.
isUnset() ||
20384 RD.push(RefExpr, DeclareReductionRef.
get());
20387 if (BOK == BO_Comma && DeclareReductionRef.
isUnset()) {
20391 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
20392 <<
Type << ReductionIdRange;
20395 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
20396 <<
Type << ReductionIdRange;
20408 if (DeclareReductionRef.
isUnset()) {
20409 if ((BOK == BO_GT || BOK == BO_LT) &&
20412 S.
Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
20415 if (!ASE && !OASE) {
20416 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20419 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20424 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
20426 S.
Diag(ELoc, diag::err_omp_clause_floating_type_arg)
20428 if (!ASE && !OASE) {
20429 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20432 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20439 Type =
Type.getNonLValueExprType(Context).getUnqualifiedType();
20448 bool ConstantLengthOASE =
false;
20450 bool SingleElement;
20453 Context, OASE, SingleElement, ArraySizes);
20456 if (ConstantLengthOASE && !SingleElement) {
20457 for (llvm::APSInt &Size : ArraySizes)
20458 PrivateTy = Context.getConstantArrayType(PrivateTy, Size,
nullptr,
20464 if ((OASE && !ConstantLengthOASE) ||
20467 if (!Context.getTargetInfo().isVLASupported()) {
20469 S.
Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
20470 S.
Diag(ELoc, diag::note_vla_unsupported);
20473 S.
targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
20474 S.
targetDiag(ELoc, diag::note_vla_unsupported);
20482 PrivateTy = Context.getVariableArrayType(
20487 }
else if (!ASE && !OASE &&
20500 if (DeclareReductionRef.
isUsable()) {
20503 if (DRD->getInitializer()) {
20529 Type = ComplexTy->getElementType();
20531 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
20532 Context.getFloatTypeSemantics(
Type));
20536 uint64_t Size = Context.getTypeSize(
Type);
20537 QualType IntTy = Context.getIntTypeForBitwidth(Size, 0);
20538 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
20557 uint64_t Size = Context.getTypeSize(
Type);
20559 Context.getIntTypeForBitwidth(Size, IsSigned);
20560 llvm::APInt InitValue =
20561 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
20562 : llvm::APInt::getMinValue(Size)
20563 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
20564 : llvm::APInt::getMaxValue(Size);
20569 ELoc, Context.getTrivialTypeSourceInfo(
Type, ELoc), ELoc,
Init);
20575 llvm::APFloat InitValue = llvm::APFloat::getLargest(
20576 Context.getFloatTypeSemantics(
Type), BOK != BO_LT);
20606 llvm_unreachable(
"Unexpected reduction operation");
20615 }
else if (!
Init) {
20625 S.
Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
20626 <<
Type << ReductionIdRange;
20627 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20630 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20636 if (DeclareReductionRef.
isUsable()) {
20638 QualType PtrRedTy = Context.getPointerType(RedTy);
20641 if (!BasePath.empty()) {
20645 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.
get(), &BasePath,
20648 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.
get(), &BasePath,
20652 QualType Params[] = {PtrRedTy, PtrRedTy};
20653 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
20667 CombBOK, LHSDRE, RHSDRE);
20674 if (BOK != BO_LT && BOK != BO_GT) {
20677 BO_Assign, LHSDRE, ReductionOp.
get());
20679 auto *ConditionalOp =
new (Context)
20684 BO_Assign, LHSDRE, ConditionalOp);
20697 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
20698 if (ClauseKind == OMPC_reduction &&
20699 RD.RedModifier == OMPC_REDUCTION_inscan) {
20701 CopyOpRes = S.
BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
20711 if (Stack->getCurrentDirective() == OMPD_simd ||
20749 if (ClauseKind == OMPC_in_reduction) {
20752 const Expr *ParentReductionOp =
nullptr;
20753 Expr *ParentBOKTD =
nullptr, *ParentReductionOpTD =
nullptr;
20754 DSAStackTy::DSAVarData ParentBOKDSA =
20755 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
20757 DSAStackTy::DSAVarData ParentReductionOpDSA =
20758 Stack->getTopMostTaskgroupReductionData(
20759 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
20760 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
20761 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
20762 if ((DeclareReductionRef.
isUnset() && IsParentReductionOp) ||
20763 (DeclareReductionRef.
isUsable() && IsParentBOK) ||
20764 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
20765 bool EmitError =
true;
20766 if (IsParentReductionOp && DeclareReductionRef.
isUsable()) {
20767 llvm::FoldingSetNodeID RedId, ParentRedId;
20768 ParentReductionOp->
Profile(ParentRedId, Context,
true);
20769 DeclareReductionRef.
get()->
Profile(RedId, Context,
20771 EmitError = RedId != ParentRedId;
20775 diag::err_omp_reduction_identifier_mismatch)
20776 << ReductionIdRange << RefExpr->getSourceRange();
20778 diag::note_omp_previous_reduction_identifier)
20780 << (IsParentBOK ? ParentBOKDSA.RefExpr
20781 : ParentReductionOpDSA.RefExpr)
20782 ->getSourceRange();
20786 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
20793 TransformExprToCaptures RebuildToCapture(S, D);
20795 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
20796 Ref = RebuildToCapture.getCapturedExpr();
20798 VarsExpr = Ref =
buildCapture(S, D, SimpleRefExpr,
false);
20801 RD.ExprCaptures.emplace_back(Ref->
getDecl());
20807 S.
BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
20812 Stack->getCurrentDirective() == OMPD_taskgroup) {
20813 S.
Diag(RefExpr->getExprLoc(),
20814 diag::err_omp_reduction_non_addressable_expression)
20815 << RefExpr->getSourceRange();
20818 RD.ExprPostUpdates.emplace_back(
20825 unsigned Modifier = RD.RedModifier;
20828 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
20829 Modifier = OMPC_REDUCTION_task;
20830 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
20832 if (Modifier == OMPC_REDUCTION_task &&
20833 (CurrDir == OMPD_taskgroup ||
20837 if (DeclareReductionRef.
isUsable())
20838 Stack->addTaskgroupReductionData(D, ReductionIdRange,
20839 DeclareReductionRef.
get());
20841 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
20843 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.
get(),
20844 TaskgroupDescriptor, CopyOpRes.
get(), TempArrayRes.
get(),
20845 TempArrayElem.
get(), IsPrivate);
20847 return RD.Vars.empty();
20863 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
20874 if (Modifier == OMPC_REDUCTION_inscan &&
20875 (
DSAStack->getCurrentDirective() != OMPD_for &&
20876 DSAStack->getCurrentDirective() != OMPD_for_simd &&
20877 DSAStack->getCurrentDirective() != OMPD_simd &&
20878 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
20879 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
20880 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
20883 ReductionData RD(VarList.size(), Modifier, OriginalSharingModifier);
20885 StartLoc, LParenLoc, ColonLoc, EndLoc,
20886 ReductionIdScopeSpec, ReductionId,
20887 UnresolvedReductions, RD))
20890 return OMPReductionClause::Create(
20891 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
20894 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
20895 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
20898 OriginalSharingModifier);
20906 ReductionData RD(VarList.size());
20908 VarList, StartLoc, LParenLoc, ColonLoc,
20909 EndLoc, ReductionIdScopeSpec, ReductionId,
20910 UnresolvedReductions, RD))
20913 return OMPTaskReductionClause::Create(
20914 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20916 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
20926 ReductionData RD(VarList.size());
20928 StartLoc, LParenLoc, ColonLoc, EndLoc,
20929 ReductionIdScopeSpec, ReductionId,
20930 UnresolvedReductions, RD))
20933 return OMPInReductionClause::Create(
20934 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20936 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
20945 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
20955 const auto *VD = dyn_cast_or_null<VarDecl>(D);
20958 diag::err_omp_linear_incomplete_type))
20960 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
20962 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
20966 Type =
Type.getNonReferenceType();
20973 if (!IsDeclareSimd &&
20978 Type =
Type.getUnqualifiedType().getCanonicalType();
20979 const auto *Ty =
Type.getTypePtrOrNull();
20980 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
20981 !Ty->isIntegralType(
getASTContext()) && !Ty->isPointerType())) {
20982 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) <<
Type;
20984 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
20987 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21010 Diag(Step->
getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
21012 LinKind = OMPC_LINEAR_val;
21013 for (
Expr *RefExpr : VarList) {
21014 assert(RefExpr &&
"NULL expr in OpenMP linear clause.");
21017 Expr *SimpleRefExpr = RefExpr;
21021 Vars.push_back(RefExpr);
21023 Inits.push_back(
nullptr);
21030 auto *VD = dyn_cast<VarDecl>(D);
21036 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
21037 if (DVar.RefExpr) {
21038 Diag(ELoc, diag::err_omp_wrong_dsa)
21047 Type =
Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
21059 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
21062 ExprCaptures.push_back(Ref->
getDecl());
21069 SimpleRefExpr, RefRes.
get());
21072 ExprPostUpdates.push_back(
21073 SemaRef.IgnoredValueConversions(PostUpdateRes.
get()).get());
21077 if (LinKind == OMPC_LINEAR_uval)
21078 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
21080 InitExpr = VD ? SimpleRefExpr : Ref;
21081 SemaRef.AddInitializerToDecl(
21082 Init,
SemaRef.DefaultLvalueConversion(InitExpr).get(),
21086 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
21087 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
21088 ? RefExpr->IgnoreParens()
21091 Inits.push_back(InitRef);
21097 Expr *StepExpr = Step;
21098 Expr *CalcStepExpr =
nullptr;
21106 StepExpr = Val.
get();
21114 SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.
get(), StepExpr);
21116 SemaRef.ActOnFinishFullExpr(CalcStep.
get(),
false);
21120 if (std::optional<llvm::APSInt>
Result =
21122 if (!
Result->isNegative() && !
Result->isStrictlyPositive())
21123 Diag(StepLoc, diag::warn_omp_linear_step_zero)
21124 << Vars[0] << (Vars.size() > 1);
21128 CalcStepExpr = CalcStep.
get();
21132 return OMPLinearClause::Create(
getASTContext(), StartLoc, LParenLoc, LinKind,
21133 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
21140 Expr *NumIterations,
Sema &SemaRef,
21141 Scope *S, DSAStackTy *Stack) {
21146 Expr *Step = Clause.getStep();
21147 Expr *CalcStep = Clause.getCalcStep();
21154 bool HasErrors =
false;
21155 auto CurInit = Clause.inits().begin();
21156 auto CurPrivate = Clause.privates().begin();
21158 for (
Expr *RefExpr : Clause.varlist()) {
21161 Expr *SimpleRefExpr = RefExpr;
21162 auto Res =
getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21164 if (Res.second || !D) {
21166 Finals.push_back(
nullptr);
21170 auto &&Info = Stack->isLoopControlVariable(D);
21177 diag::err_omp_linear_distribute_var_non_loop_iteration);
21179 Finals.push_back(
nullptr);
21183 Expr *InitExpr = *CurInit;
21188 if (LinKind == OMPC_LINEAR_uval)
21193 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
21200 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
21211 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
21214 Final = *CurPrivate;
21218 if (!
Update.isUsable() || !Final.isUsable()) {
21220 Finals.push_back(
nullptr);
21221 UsedExprs.push_back(
nullptr);
21225 Finals.push_back(Final.get());
21227 UsedExprs.push_back(SimpleRefExpr);
21232 if (
Expr *S = Clause.getStep())
21233 UsedExprs.push_back(S);
21235 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(),
nullptr);
21237 Clause.setFinals(Finals);
21238 Clause.setUsedExprs(UsedExprs);
21246 for (
Expr *RefExpr : VarList) {
21247 assert(RefExpr &&
"NULL expr in OpenMP aligned clause.");
21250 Expr *SimpleRefExpr = RefExpr;
21254 Vars.push_back(RefExpr);
21261 auto *VD = dyn_cast<VarDecl>(D);
21269 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
21271 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
21274 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21281 if (
const Expr *PrevRef =
DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
21282 Diag(ELoc, diag::err_omp_used_in_clause_twice)
21284 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
21293 .DefaultFunctionArrayConversion(
21294 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
21303 if (Alignment !=
nullptr) {
21308 Alignment = AlignResult.
get();
21314 ColonLoc, EndLoc, Vars, Alignment);
21325 for (
Expr *RefExpr : VarList) {
21326 assert(RefExpr &&
"NULL expr in OpenMP copyin clause.");
21329 Vars.push_back(RefExpr);
21330 SrcExprs.push_back(
nullptr);
21331 DstExprs.push_back(
nullptr);
21332 AssignmentOps.push_back(
nullptr);
21341 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
21343 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
21344 << 0 << RefExpr->getSourceRange();
21348 Decl *D = DE->getDecl();
21354 Vars.push_back(DE);
21355 SrcExprs.push_back(
nullptr);
21356 DstExprs.push_back(
nullptr);
21357 AssignmentOps.push_back(
nullptr);
21363 if (!
DSAStack->isThreadPrivate(VD)) {
21365 Diag(ELoc, diag::err_omp_required_access)
21367 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion);
21390 SemaRef.BuildBinOp(
nullptr, DE->getExprLoc(), BO_Assign,
21391 PseudoDstExpr, PseudoSrcExpr);
21400 DSAStack->addDSA(VD, DE, OMPC_copyin);
21401 Vars.push_back(DE);
21402 SrcExprs.push_back(PseudoSrcExpr);
21403 DstExprs.push_back(PseudoDstExpr);
21404 AssignmentOps.push_back(AssignmentOp.
get());
21411 Vars, SrcExprs, DstExprs, AssignmentOps);
21422 for (
Expr *RefExpr : VarList) {
21423 assert(RefExpr &&
"NULL expr in OpenMP copyprivate clause.");
21426 Expr *SimpleRefExpr = RefExpr;
21430 Vars.push_back(RefExpr);
21431 SrcExprs.push_back(
nullptr);
21432 DstExprs.push_back(
nullptr);
21433 AssignmentOps.push_back(
nullptr);
21440 auto *VD = dyn_cast<VarDecl>(D);
21445 if (!VD || !
DSAStack->isThreadPrivate(VD)) {
21446 DSAStackTy::DSAVarData DVar =
21448 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
21450 Diag(ELoc, diag::err_omp_wrong_dsa)
21460 if (DVar.CKind == OMPC_unknown) {
21461 DVar =
DSAStack->getImplicitDSA(D,
false);
21462 if (DVar.CKind == OMPC_shared) {
21463 Diag(ELoc, diag::err_omp_required_access)
21465 <<
"threadprivate or private in the enclosing context";
21475 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
21477 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
21479 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
21482 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21503 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
21506 AssignmentOp =
SemaRef.ActOnFinishFullExpr(AssignmentOp.
get(), ELoc,
21515 VD ? RefExpr->IgnoreParens()
21517 SrcExprs.push_back(PseudoSrcExpr);
21518 DstExprs.push_back(PseudoDstExpr);
21519 AssignmentOps.push_back(AssignmentOp.
get());
21526 EndLoc, Vars, SrcExprs, DstExprs,
21534 if (VarList.empty())
21543 bool Diagnose =
true) {
21544 QualType OMPDependT = Stack->getOMPDependT();
21545 if (!OMPDependT.
isNull())
21551 S.
Diag(Loc, diag::err_omp_implied_type_not_found) <<
"omp_depend_t";
21554 Stack->setOMPDependT(PT.
get());
21575 Diag(Depobj->
getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
21580 Diag(Depobj->
getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
21590struct DoacrossDataInfoTy {
21594 DSAStackTy::OperatorOffsetTy OpsOffs;
21596 llvm::APSInt TotalDepCount;
21599static DoacrossDataInfoTy
21605 DSAStackTy::OperatorOffsetTy OpsOffs;
21606 llvm::APSInt DepCounter(32);
21607 llvm::APSInt TotalDepCount(32);
21609 if (
const Expr *OrderedCountExpr =
21610 Stack->getParentOrderedRegionParam().first) {
21611 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.
Context);
21612 TotalDepCount.setIsUnsigned(
true);
21615 for (
Expr *RefExpr : VarList) {
21616 assert(RefExpr &&
"NULL expr in OpenMP doacross clause.");
21619 Vars.push_back(RefExpr);
21626 if (Stack->getParentOrderedRegionParam().first &&
21627 DepCounter >= TotalDepCount) {
21628 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
21642 Vars.push_back(RefExpr);
21649 Expr *RHS =
nullptr;
21650 if (
auto *BO = dyn_cast<BinaryOperator>(
SimpleExpr)) {
21652 OOLoc = BO->getOperatorLoc();
21655 }
else if (
auto *OCE = dyn_cast<CXXOperatorCallExpr>(
SimpleExpr)) {
21656 OOK = OCE->getOperator();
21657 OOLoc = OCE->getOperatorLoc();
21660 }
else if (
auto *MCE = dyn_cast<CXXMemberCallExpr>(
SimpleExpr)) {
21661 OOK = MCE->getMethodDecl()
21664 .getCXXOverloadedOperator();
21665 OOLoc = MCE->getCallee()->getExprLoc();
21674 Vars.push_back(RefExpr);
21680 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK !=
OO_None)) {
21681 SemaRef.
Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
21687 RHS, OMPC_depend,
false);
21692 Stack->getParentOrderedRegionParam().first &&
21693 DepCounter != Stack->isParentLoopControlVariable(D).first) {
21695 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
21697 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
21700 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
21704 OpsOffs.emplace_back(RHS, OOK);
21706 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21709 TotalDepCount > VarList.size() &&
21710 Stack->getParentOrderedRegionParam().first &&
21711 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
21712 SemaRef.
Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
21713 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
21715 return {Vars, OpsOffs, TotalDepCount};
21724 if (
DSAStack->getCurrentDirective() == OMPD_ordered &&
21725 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
21726 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21730 if (
DSAStack->getCurrentDirective() == OMPD_taskwait &&
21731 DepKind == OMPC_DEPEND_mutexinoutset) {
21732 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
21735 if ((
DSAStack->getCurrentDirective() != OMPD_ordered ||
21736 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21738 DepKind == OMPC_DEPEND_sink ||
21740 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21741 DepKind == OMPC_DEPEND_depobj))) {
21743 OMPC_DEPEND_outallmemory,
21744 OMPC_DEPEND_inoutallmemory};
21746 DSAStack->getCurrentDirective() == OMPD_depobj)
21747 Except.push_back(OMPC_DEPEND_depobj);
21749 Except.push_back(OMPC_DEPEND_inoutset);
21751 ?
"depend modifier(iterator) or "
21753 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21761 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
21763 diag::err_omp_depend_sink_source_with_modifier);
21768 Diag(DepModifier->
getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
21771 DSAStackTy::OperatorOffsetTy OpsOffs;
21772 llvm::APSInt TotalDepCount(32);
21774 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
21777 Vars = VarOffset.Vars;
21778 OpsOffs = VarOffset.OpsOffs;
21779 TotalDepCount = VarOffset.TotalDepCount;
21781 for (
Expr *RefExpr : VarList) {
21782 assert(RefExpr &&
"NULL expr in OpenMP depend clause.");
21785 Vars.push_back(RefExpr);
21791 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
21792 bool OMPDependTFound =
getLangOpts().OpenMP >= 50;
21793 if (OMPDependTFound)
21795 DepKind == OMPC_DEPEND_depobj);
21796 if (DepKind == OMPC_DEPEND_depobj) {
21800 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21801 !RefExpr->isInstantiationDependent() &&
21802 !RefExpr->containsUnexpandedParameterPack() &&
21803 (OMPDependTFound &&
21805 DSAStack->getOMPDependT(), RefExpr->getType()))) {
21806 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21807 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
21810 if (!RefExpr->isLValue()) {
21811 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21812 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
21819 QualType ExprTy = RefExpr->getType().getNonReferenceType();
21820 const auto *OASE = dyn_cast<ArraySectionExpr>(
SimpleExpr);
21824 if (BaseType.isNull())
21826 if (
const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21827 ExprTy = ATy->getElementType();
21830 if (BaseType.isNull() || ExprTy.
isNull())
21833 const Expr *Length = OASE->getLength();
21835 if (Length && !Length->isValueDependent() &&
21837 Result.Val.getInt().isZero()) {
21839 diag::err_omp_depend_zero_length_array_section_not_allowed)
21849 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21850 !RefExpr->isInstantiationDependent() &&
21851 !RefExpr->containsUnexpandedParameterPack() &&
21852 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
21853 (OMPDependTFound &&
DSAStack->getOMPDependT().getTypePtr() ==
21855 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21858 << RefExpr->getSourceRange();
21862 auto *ASE = dyn_cast<ArraySubscriptExpr>(
SimpleExpr);
21863 if (ASE && !ASE->getBase()->isTypeDependent() &&
21866 .getNonReferenceType()
21867 ->isPointerType() &&
21868 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
21869 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21872 << RefExpr->getSourceRange();
21879 Res =
SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
21880 RefExpr->IgnoreParenImpCasts());
21884 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21887 << RefExpr->getSourceRange();
21892 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21896 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
21897 DepKind != OMPC_DEPEND_outallmemory &&
21898 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
21903 {DepKind, DepLoc,
Data.ColonLoc,
Data.OmpAllMemoryLoc}, DepModifier, Vars,
21904 TotalDepCount.getZExtValue());
21905 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
21906 DSAStack->isParentOrderedRegion())
21907 DSAStack->addDoacrossDependClause(
C, OpsOffs);
21916 "Unexpected device modifier in OpenMP < 50.");
21918 bool ErrorFound =
false;
21920 std::string Values =
21922 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
21928 Stmt *HelperValStmt =
nullptr;
21941 if (Modifier == OMPC_DEVICE_ancestor) {
21942 if (!
DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
21945 diag::err_omp_device_ancestor_without_requires_reverse_offload);
21953 if (CaptureRegion != OMPD_unknown &&
21954 !
SemaRef.CurContext->isDependentContext()) {
21955 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
21956 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21957 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
21962 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
21963 LParenLoc, ModifierLoc, EndLoc);
21968 bool FullCheck =
true) {
21973 SemaRef.
Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
21983 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
21989 (OASE && OASE->getColonLocFirst().isInvalid())) {
21990 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
21991 return ATy->getSExtSize() != 1;
21996 assert(OASE &&
"Expecting array section if not an array subscript.");
21997 const Expr *LowerBound = OASE->getLowerBound();
21998 const Expr *Length = OASE->getLength();
22007 llvm::APSInt ConstLowerBound = Result.
Val.
getInt();
22008 if (ConstLowerBound.getSExtValue())
22023 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr());
22028 if (!Length->EvaluateAsInt(Result, SemaRef.
getASTContext()))
22031 llvm::APSInt ConstLength = Result.
Val.
getInt();
22032 return CATy->getSExtSize() != ConstLength.getSExtValue();
22041 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
22046 (OASE && OASE->getColonLocFirst().isInvalid()))
22049 assert(OASE &&
"Expecting array section if not an array subscript.");
22050 const Expr *Length = OASE->getLength();
22056 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
22057 return ATy->getSExtSize() != 1;
22064 if (!Length->EvaluateAsInt(Result, SemaRef.
getASTContext()))
22067 llvm::APSInt ConstLength = Result.
Val.
getInt();
22068 return ConstLength.getSExtValue() != 1;
22107class MapBaseChecker final :
public StmtVisitor<MapBaseChecker, bool> {
22112 bool IsNonContiguous =
false;
22113 bool NoDiagnose =
false;
22114 const Expr *RelevantExpr =
nullptr;
22115 bool AllowUnitySizeArraySection =
true;
22116 bool AllowWholeSizeArraySection =
true;
22117 bool AllowAnotherPtr =
true;
22118 SourceLocation ELoc;
22119 SourceRange ERange;
22121 void emitErrorMsg() {
22123 if (SemaRef.getLangOpts().OpenMP < 50) {
22125 diag::err_omp_expected_named_var_member_or_array_expression)
22128 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
22134 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
22139 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22140 RelevantExpr = DRE;
22142 Components.emplace_back(DRE, DRE->
getDecl(), IsNonContiguous);
22146 bool VisitMemberExpr(MemberExpr *ME) {
22151 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22160 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
22176 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
22196 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
22200 return RelevantExpr || Visit(E);
22210 AllowUnitySizeArraySection =
false;
22211 AllowWholeSizeArraySection =
false;
22214 Components.emplace_back(ME, FD, IsNonContiguous);
22215 return RelevantExpr || Visit(E);
22218 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
22223 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
22227 return RelevantExpr || Visit(E);
22234 AllowWholeSizeArraySection =
false;
22237 Expr::EvalResult
Result;
22240 !
Result.Val.getInt().isZero()) {
22242 diag::err_omp_invalid_map_this_expr);
22244 diag::note_omp_invalid_subscript_on_this_ptr_map);
22246 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22251 Components.emplace_back(AE,
nullptr, IsNonContiguous);
22253 return RelevantExpr || Visit(E);
22256 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
22259 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
22260 "Array sections cannot be implicitly mapped.");
22274 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
22284 if (AllowWholeSizeArraySection) {
22291 if (NotWhole || IsPointer)
22292 AllowWholeSizeArraySection =
false;
22293 }
else if (DKind == OMPD_target_update &&
22294 SemaRef.getLangOpts().OpenMP >= 50) {
22295 if (IsPointer && !AllowAnotherPtr)
22296 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
22299 IsNonContiguous =
true;
22300 }
else if (AllowUnitySizeArraySection && NotUnity) {
22306 diag::err_array_section_does_not_specify_contiguous_storage)
22312 AllowAnotherPtr =
false;
22314 if (
const auto *TE = dyn_cast<CXXThisExpr>(E)) {
22315 Expr::EvalResult ResultR;
22316 Expr::EvalResult ResultL;
22321 diag::err_omp_invalid_map_this_expr);
22323 diag::note_omp_invalid_length_on_this_ptr_mapping);
22327 SemaRef.getASTContext()) &&
22330 diag::err_omp_invalid_map_this_expr);
22332 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
22334 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22339 Components.emplace_back(OASE,
nullptr,
false);
22340 return RelevantExpr || Visit(E);
22342 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
22346 Components.emplace_back(E,
nullptr, IsNonContiguous);
22348 return Visit(
Base->IgnoreParenImpCasts());
22351 bool VisitUnaryOperator(UnaryOperator *UO) {
22352 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->
isLValue() ||
22357 if (!RelevantExpr) {
22359 Components.emplace_back(UO,
nullptr,
false);
22363 bool VisitBinaryOperator(BinaryOperator *BO) {
22375 Components.emplace_back(BO,
nullptr,
false);
22378 "Either LHS or RHS have base decl inside");
22380 return RelevantExpr || Visit(LE);
22381 return RelevantExpr || Visit(RE);
22383 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
22384 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22385 RelevantExpr = CTE;
22386 Components.emplace_back(CTE,
nullptr, IsNonContiguous);
22389 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
22390 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22391 Components.emplace_back(COCE,
nullptr, IsNonContiguous);
22394 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
22400 return Visit(Source);
22402 bool VisitStmt(Stmt *) {
22406 const Expr *getFoundBase()
const {
return RelevantExpr; }
22407 explicit MapBaseChecker(
22410 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
22411 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
22412 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
22426 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
22430 if (SemaRef.
getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
22431 (CKind == OMPC_to || CKind == OMPC_from)) {
22432 auto CI = CurComponents.rbegin();
22433 auto CE = CurComponents.rend();
22434 for (; CI != CE; ++CI) {
22436 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
22441 SemaRef.
Diag(ELoc, diag::err_array_section_does_not_specify_length)
22445 return Checker.getFoundBase();
22454 bool CurrentRegionOnly,
22465 assert(!CurComponents.empty() &&
"Map clause expression with no components!");
22466 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
22467 "Map clause expression with unexpected base!");
22470 bool IsEnclosedByDataEnvironmentExpr =
false;
22471 const Expr *EnclosingExpr =
nullptr;
22473 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
22474 VD, CurrentRegionOnly,
22475 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
22476 ERange, CKind, &EnclosingExpr,
22480 if (CKind == Kind && SemaRef.
LangOpts.OpenMP >= 50)
22482 assert(!StackComponents.empty() &&
22483 "Map clause expression with no components!");
22484 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
22485 "Map clause expression with unexpected base!");
22489 const Expr *RE = StackComponents.front().getAssociatedExpression();
22495 auto CI = CurComponents.rbegin();
22496 auto CE = CurComponents.rend();
22497 auto SI = StackComponents.rbegin();
22498 auto SE = StackComponents.rend();
22499 for (; CI != CE && SI != SE; ++CI, ++SI) {
22504 if (CurrentRegionOnly &&
22511 SemaRef.
Diag(CI->getAssociatedExpression()->getExprLoc(),
22512 diag::err_omp_multiple_array_items_in_map_clause)
22513 << CI->getAssociatedExpression()->getSourceRange();
22514 SemaRef.
Diag(SI->getAssociatedExpression()->getExprLoc(),
22515 diag::note_used_here)
22516 << SI->getAssociatedExpression()->getSourceRange();
22521 if (CI->getAssociatedExpression()->getStmtClass() !=
22522 SI->getAssociatedExpression()->getStmtClass())
22526 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
22532 for (; SI != SE; ++SI) {
22534 if (
const auto *ASE =
22535 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
22536 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
22537 }
else if (
const auto *OASE = dyn_cast<ArraySectionExpr>(
22538 SI->getAssociatedExpression())) {
22541 }
else if (
const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
22542 SI->getAssociatedExpression())) {
22547 SemaRef, SI->getAssociatedExpression(),
Type))
22557 if (CI == CE && SI == SE) {
22558 if (CurrentRegionOnly) {
22559 if (CKind == OMPC_map) {
22560 SemaRef.
Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
22562 assert(CKind == OMPC_to || CKind == OMPC_from);
22563 SemaRef.
Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
22572 IsEnclosedByDataEnvironmentExpr =
true;
22577 std::prev(CI)->getAssociatedDeclaration()->getType();
22579 std::prev(CI)->getAssociatedExpression()->getExprLoc();
22598 if (CI == CE || SI == SE) {
22601 diag::err_omp_pointer_mapped_along_with_derived_section)
22607 if (CI->getAssociatedExpression()->getStmtClass() !=
22608 SI->getAssociatedExpression()->getStmtClass() ||
22609 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
22610 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
22611 assert(CI != CE && SI != SE);
22612 SemaRef.
Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
22625 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
22626 if (CKind == OMPC_map) {
22627 if (CI != CE || SI != SE) {
22631 CI != CE ? CurComponents.begin() : StackComponents.begin();
22632 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
22634 while (It != End && !It->getAssociatedDeclaration())
22635 std::advance(It, 1);
22636 assert(It != End &&
22637 "Expected at least one component with the declaration.");
22638 if (It != Begin && It->getAssociatedDeclaration()
22640 .getCanonicalType()
22641 ->isAnyPointerType()) {
22642 IsEnclosedByDataEnvironmentExpr =
false;
22643 EnclosingExpr =
nullptr;
22647 SemaRef.
Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
22649 assert(CKind == OMPC_to || CKind == OMPC_from);
22650 SemaRef.
Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
22660 if (!CurrentRegionOnly && SI != SE)
22661 EnclosingExpr = RE;
22665 IsEnclosedByDataEnvironmentExpr |=
22666 (!CurrentRegionOnly && CI != CE && SI == SE);
22671 if (CurrentRegionOnly)
22685 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
22687 diag::err_omp_original_storage_is_shared_and_does_not_contain)
22703 Expr *UnresolvedMapper) {
22723 Lookups.emplace_back();
22724 Lookups.back().append(Lookup.
begin(), Lookup.
end());
22727 }
else if (
auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
22732 assert(DMD &&
"Expect valid OMPDeclareMapperDecl during instantiation.");
22733 Lookups.back().addDecl(DMD);
22742 return !D->isInvalidDecl() &&
22743 (D->getType()->isDependentType() ||
22744 D->getType()->isInstantiationDependentType() ||
22745 D->getType()->containsUnexpandedParameterPack());
22756 false, URS.
begin(), URS.
end(),
false,
22764 SemaRef.
Diag(Loc, diag::err_omp_mapper_wrong_type);
22805 SemaRef.
Diag(Loc, diag::err_omp_invalid_mapper)
22815struct MappableVarListInfo {
22817 ArrayRef<Expr *> VarList;
22819 SmallVector<Expr *, 16> ProcessedVarList;
22823 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
22825 SmallVector<Expr *, 16> UDMapperList;
22827 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
22830 VarComponents.reserve(VarList.size());
22831 VarBaseDeclarations.reserve(VarList.size());
22840 const RecordDecl *RD = BaseType->getAsRecordDecl();
22850 for (
auto *FD : RD->
fields()) {
22852 MapperVarRef,
false, Range.getBegin(),
22858 SExprs.push_back(BE);
22866 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
22869 Maps.push_back(MapClause);
22870 return MapperVarRef;
22874 DSAStackTy *Stack) {
22880 const RecordDecl *RD = BaseType->getAsRecordDecl();
22889 MapperId = DeclNames.getIdentifier(&Ctx.
Idents.
get(
"default"));
22891 BaseType, MapperId, Maps,
nullptr);
22901 DMD->setMapperVarRef(MapperVarRef);
22925 Lookups.emplace_back();
22926 Lookups.back().append(Lookup.
begin(), Lookup.
end());
22933 return !D->isInvalidDecl() &&
22934 (D->getType()->isDependentType() ||
22935 D->getType()->isInstantiationDependentType() ||
22936 D->getType()->containsUnexpandedParameterPack());
22982 {CanonType,
nullptr});
22983 llvm::DenseMap<const Type *, bool> Visited;
22985 while (!Types.empty()) {
22986 auto [BaseType, CurFD] = Types.pop_back_val();
22987 while (ParentChain.back().second == 0)
22988 ParentChain.pop_back();
22989 --ParentChain.back().second;
22990 if (BaseType.isNull())
22993 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
22996 auto It = Visited.find(BaseType.getTypePtr());
22997 if (It == Visited.end()) {
23006 DefaultMapperId, BaseType);
23007 It = Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
23013 bool FirstIter =
true;
23023 ParentChain.emplace_back(CurFD, 1);
23025 ++ParentChain.back().second;
23027 Types.emplace_back(FieldTy, FD);
23046 bool IsMapTypeImplicit =
false,
bool NoDiagnose =
false) {
23049 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from ||
23050 CKind == OMPC_use_device_addr) &&
23051 "Unexpected clause kind with mappable expressions!");
23052 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
23060 MapperId.
setName(DeclNames.getIdentifier(
23062 MapperId.
setLoc(StartLoc);
23066 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
23067 bool UpdateUMIt =
false;
23068 Expr *UnresolvedMapper =
nullptr;
23070 bool HasHoldModifier =
23071 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
23079 for (
Expr *RE : MVLI.VarList) {
23080 assert(RE &&
"Null expr in omp to/from/map clause");
23084 if (UpdateUMIt && UMIt != UMEnd) {
23088 "Expect the size of UnresolvedMappers to match with that of VarList");
23092 UnresolvedMapper = *UMIt;
23096 if (
VE->isValueDependent() ||
VE->isTypeDependent() ||
23097 VE->isInstantiationDependent() ||
23098 VE->containsUnexpandedParameterPack()) {
23101 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23102 VE->getType().getCanonicalType(), UnresolvedMapper);
23105 MVLI.UDMapperList.push_back(ER.
get());
23108 MVLI.ProcessedVarList.push_back(RE);
23117 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
23120 SemaRef.
Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
23133 DSAS->getCurrentDirective(), NoDiagnose);
23137 assert(!CurComponents.empty() &&
23138 "Invalid mappable expression information.");
23140 if (
const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
23142 DSAS->addMappedClassesQualTypes(TE->getType());
23145 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23146 VE->getType().getCanonicalType(), UnresolvedMapper);
23149 MVLI.UDMapperList.push_back(ER.
get());
23151 MVLI.ProcessedVarList.push_back(RE);
23152 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23153 MVLI.VarComponents.back().append(CurComponents.begin(),
23154 CurComponents.end());
23155 MVLI.VarBaseDeclarations.push_back(
nullptr);
23162 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
23163 assert(CurDeclaration &&
"Null decl on map clause.");
23166 "Expecting components to have associated only canonical declarations.");
23168 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
23169 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
23171 assert((VD || FD) &&
"Only variables or fields are expected here!");
23178 if (VD && DSAS->isThreadPrivate(VD)) {
23181 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD,
false);
23182 SemaRef.
Diag(ELoc, diag::err_omp_threadprivate_in_clause)
23197 true, CurComponents, CKind))
23199 if (CKind == OMPC_map &&
23202 false, CurComponents, CKind))
23209 auto I = llvm::find_if(
23211 [](
const OMPClauseMappableExprCommon::MappableComponent &MC) {
23214 assert(I != CurComponents.end() &&
"Null decl on map clause.");
23217 auto *ASE = dyn_cast<ArraySubscriptExpr>(
VE->IgnoreParens());
23218 auto *OASE = dyn_cast<ArraySectionExpr>(
VE->IgnoreParens());
23219 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(
VE->IgnoreParens());
23221 Type = ASE->getType().getNonReferenceType();
23226 Type = ATy->getElementType();
23229 Type =
Type.getNonReferenceType();
23230 }
else if (OAShE) {
23244 if (CKind == OMPC_map) {
23251 if (DKind == OMPD_target_enter_data &&
23252 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
23254 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23255 << (IsMapTypeImplicit ? 1 : 0)
23257 << getOpenMPDirectiveName(DKind, OMPVersion);
23266 if (DKind == OMPD_target_exit_data &&
23267 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
23268 MapType == OMPC_MAP_delete || SemaRef.
getLangOpts().OpenMP >= 52)) {
23269 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23270 << (IsMapTypeImplicit ? 1 : 0)
23272 << getOpenMPDirectiveName(DKind, OMPVersion);
23281 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
23283 SemaRef.
Diag(StartLoc,
23284 diag::err_omp_invalid_map_type_modifier_for_directive)
23286 OMPC_MAP_MODIFIER_ompx_hold)
23287 << getOpenMPDirectiveName(DKind, OMPVersion);
23295 if ((DKind == OMPD_target_data ||
23297 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
23298 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
23299 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23300 << (IsMapTypeImplicit ? 1 : 0)
23302 << getOpenMPDirectiveName(DKind, OMPVersion);
23314 if (VD && ((SemaRef.
LangOpts.OpenMP <= 45 &&
23316 DKind == OMPD_target)) {
23317 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD,
false);
23319 SemaRef.
Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23322 << getOpenMPDirectiveName(DSAS->getCurrentDirective(),
23332 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23333 Type.getCanonicalType(), UnresolvedMapper);
23345 BaseType =
VE->getType().getCanonicalType();
23352 ElemType = ATy->getElementType();
23357 }
else if (
VE->getType()->isArrayType()) {
23358 const ArrayType *AT =
VE->getType()->getAsArrayTypeUnsafe();
23368 MVLI.UDMapperList.push_back(ER.
get());
23371 MVLI.ProcessedVarList.push_back(RE);
23375 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
23381 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23382 MVLI.VarComponents.back().append(CurComponents.begin(),
23383 CurComponents.end());
23405 BuiltinType::OMPIterator))
23407 diag::err_omp_map_modifier_not_iterator);
23410 unsigned Count = 0;
23411 for (
unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
23413 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
23414 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
23418 "Modifiers exceed the allowed number of map type modifiers");
23419 Modifiers[Count] = MapTypeModifiers[I];
23420 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
23424 MappableVarListInfo MVLI(VarList);
23426 MapperIdScopeSpec, MapperId, UnresolvedMappers,
23427 MapType, Modifiers, IsMapTypeImplicit,
23433 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23434 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
23436 MapperId, MapType, IsMapTypeImplicit, MapLoc);
23444 if (ReductionType.
isNull())
23452 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
23457 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
23461 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
23465 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
23468 return ReductionType;
23474 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
23477 Decls.reserve(ReductionTypes.size());
23481 SemaRef.forRedeclarationInCurContext());
23486 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
23488 bool InCompoundScope =
true;
23489 if (S !=
nullptr) {
23495 SemaRef.LookupName(Lookup, S);
23496 SemaRef.FilterLookupForScope(Lookup, DC, S,
false,
23498 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
23500 while (Filter.hasNext()) {
23502 if (InCompoundScope) {
23503 UsedAsPrevious.try_emplace(PrevDecl,
false);
23505 UsedAsPrevious[D] =
true;
23507 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
23508 PrevDecl->getLocation();
23511 if (InCompoundScope) {
23512 for (
const auto &PrevData : UsedAsPrevious) {
23513 if (!PrevData.second) {
23514 PrevDRD = PrevData.first;
23519 }
else if (PrevDeclInScope !=
nullptr) {
23520 auto *PrevDRDInScope = PrevDRD =
23523 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
23524 PrevDRDInScope->getLocation();
23525 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
23526 }
while (PrevDRDInScope !=
nullptr);
23528 for (
const auto &TyData : ReductionTypes) {
23529 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
23531 if (I != PreviousRedeclTypes.end()) {
23532 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
23534 Diag(I->second, diag::note_previous_definition);
23537 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
23539 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
23541 DRD->setAccess(AS);
23542 Decls.push_back(DRD);
23544 DRD->setInvalidDecl();
23558 SemaRef.setFunctionHasBranchProtectedScope();
23559 SemaRef.getCurFunction()->setHasOMPDeclareReductionCombiner();
23562 SemaRef.PushDeclContext(S, DRD);
23566 SemaRef.PushExpressionEvaluationContext(
23569 QualType ReductionType = DRD->getType();
23586 if (S !=
nullptr) {
23587 SemaRef.PushOnScopeChains(OmpInParm, S);
23588 SemaRef.PushOnScopeChains(OmpOutParm, S);
23590 DRD->addDecl(OmpInParm);
23591 DRD->addDecl(OmpOutParm);
23597 DRD->setCombinerData(InE, OutE);
23603 SemaRef.DiscardCleanupsInEvaluationContext();
23604 SemaRef.PopExpressionEvaluationContext();
23607 SemaRef.PopFunctionScopeInfo();
23609 if (Combiner !=
nullptr)
23610 DRD->setCombiner(Combiner);
23612 DRD->setInvalidDecl();
23621 SemaRef.setFunctionHasBranchProtectedScope();
23624 SemaRef.PushDeclContext(S, DRD);
23628 SemaRef.PushExpressionEvaluationContext(
23631 QualType ReductionType = DRD->getType();
23648 if (S !=
nullptr) {
23649 SemaRef.PushOnScopeChains(OmpPrivParm, S);
23650 SemaRef.PushOnScopeChains(OmpOrigParm, S);
23652 DRD->addDecl(OmpPrivParm);
23653 DRD->addDecl(OmpOrigParm);
23659 DRD->setInitializerData(OrigE, PrivE);
23660 return OmpPrivParm;
23666 SemaRef.DiscardCleanupsInEvaluationContext();
23667 SemaRef.PopExpressionEvaluationContext();
23670 SemaRef.PopFunctionScopeInfo();
23674 }
else if (OmpPrivParm->
hasInit()) {
23675 DRD->setInitializer(OmpPrivParm->
getInit(),
23680 DRD->setInvalidDecl();
23686 for (
Decl *D : DeclReductions.
get()) {
23692 D->setInvalidDecl();
23695 return DeclReductions;
23707 SemaRef.CheckExtraCXXDefaultArguments(D);
23710 return SemaRef.CreateParsedType(
T, TInfo);
23715 assert(
ParsedType.isUsable() &&
"Expect usable parsed mapper type");
23718 assert(!MapperType.
isNull() &&
"Expect valid mapper type");
23723 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
23735 SemaRef.forRedeclarationInCurContext());
23740 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
23742 bool InCompoundScope =
true;
23743 if (S !=
nullptr) {
23749 SemaRef.LookupName(Lookup, S);
23750 SemaRef.FilterLookupForScope(Lookup, DC, S,
false,
23752 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
23754 while (Filter.hasNext()) {
23756 if (InCompoundScope) {
23757 UsedAsPrevious.try_emplace(PrevDecl,
false);
23759 UsedAsPrevious[D] =
true;
23761 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
23762 PrevDecl->getLocation();
23765 if (InCompoundScope) {
23766 for (
const auto &PrevData : UsedAsPrevious) {
23767 if (!PrevData.second) {
23768 PrevDMD = PrevData.first;
23773 }
else if (PrevDeclInScope) {
23774 auto *PrevDMDInScope = PrevDMD =
23777 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
23778 PrevDMDInScope->getLocation();
23779 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
23780 }
while (PrevDMDInScope !=
nullptr);
23784 if (I != PreviousRedeclTypes.end()) {
23785 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
23786 << MapperType << Name;
23787 Diag(I->second, diag::note_previous_definition);
23795 ClausesWithImplicit);
23797 MapperType, VN, ClausesWithImplicit,
23800 SemaRef.PushOnScopeChains(DMD, S);
23803 DMD->setAccess(AS);
23805 DMD->setInvalidDecl();
23811 DMD->setMapperVarRef(MapperVarRef);
23825 SemaRef.PushOnScopeChains(VD, S,
false);
23827 DSAStack->addDeclareMapperVarRef(E);
23834 if (
DSAStack->getDeclareMapperVarRef()) {
23840 assert(!IsGlobalVar &&
"Only declare mapper handles TU-scope iterators.");
23845 assert(
getLangOpts().OpenMP &&
"Expected OpenMP mode.");
23847 if (
const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
23860 assert(
getLangOpts().OpenMP &&
"Expected OpenMP mode.");
23868 if (VarList.empty())
23871 for (
Expr *ValExpr : VarList) {
23882 if (CaptureRegion == OMPD_unknown ||
SemaRef.CurContext->isDependentContext())
23884 LParenLoc, EndLoc, VarList,
23887 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23889 for (
Expr *ValExpr : VarList) {
23890 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
23891 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
23892 Vars.push_back(ValExpr);
23897 LParenLoc, EndLoc, Vars, PreInit);
23904 if (VarList.empty())
23907 for (
Expr *ValExpr : VarList) {
23918 if (CaptureRegion == OMPD_unknown ||
SemaRef.CurContext->isDependentContext())
23920 StartLoc, LParenLoc, EndLoc, VarList,
23923 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23925 for (
Expr *ValExpr : VarList) {
23926 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
23927 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
23928 Vars.push_back(ValExpr);
23933 LParenLoc, EndLoc, Vars, PreInit);
23940 Expr *ValExpr = Priority;
23941 Stmt *HelperValStmt =
nullptr;
23947 ValExpr,
SemaRef, OMPC_priority,
23949 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
23953 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23961 "Unexpected grainsize modifier in OpenMP < 51.");
23966 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
23971 Expr *ValExpr = Grainsize;
23972 Stmt *HelperValStmt =
nullptr;
23982 &CaptureRegion, &HelperValStmt))
23987 StartLoc, LParenLoc, ModifierLoc, EndLoc);
23995 "Unexpected num_tasks modifier in OpenMP < 51.");
24000 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
24005 Expr *ValExpr = NumTasks;
24006 Stmt *HelperValStmt =
nullptr;
24013 ValExpr,
SemaRef, OMPC_num_tasks,
24015 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
24020 StartLoc, LParenLoc, ModifierLoc, EndLoc);
24040 DSAStackTy *Stack) {
24041 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
24042 if (!OMPEventHandleT.
isNull())
24047 S.
Diag(Loc, diag::err_omp_implied_type_not_found) <<
"omp_event_handle_t";
24050 Stack->setOMPEventHandleT(PT.
get());
24071 auto *VD = dyn_cast_or_null<VarDecl>(Ref->
getDecl());
24081 <<
"omp_event_handle_t" << 1 << VD->
getType()
24088 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(VD,
false);
24089 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
24108 std::string Values;
24112 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24116 Expr *ValExpr = ChunkSize;
24117 Stmt *HelperValStmt =
nullptr;
24128 ValExpr = Val.
get();
24133 if (std::optional<llvm::APSInt>
Result =
24135 if (
Result->isSigned() && !
Result->isStrictlyPositive()) {
24136 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
24137 <<
"dist_schedule" << 1
24142 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
24144 !
SemaRef.CurContext->isDependentContext()) {
24145 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
24146 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24147 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
24155 Kind, ValExpr, HelperValStmt);
24163 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
24164 Kind != OMPC_DEFAULTMAP_scalar) {
24168 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
24170 OMPC_DEFAULTMAP_MODIFIER_tofrom);
24174 OMPC_DEFAULTMAP_scalar);
24178 Diag(Loc, diag::err_omp_unexpected_clause_value)
24186 if (!isDefaultmapKind || !isDefaultmapModifier) {
24188 ?
"'scalar', 'aggregate', 'pointer'"
24189 :
"'scalar', 'aggregate', 'pointer', 'all'";
24191 StringRef ModifierValue =
"'alloc', 'from', 'to', 'tofrom', "
24192 "'firstprivate', 'none', 'default'";
24193 if (!isDefaultmapKind && isDefaultmapModifier) {
24194 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24196 }
else if (isDefaultmapKind && !isDefaultmapModifier) {
24197 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24200 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24202 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24206 StringRef ModifierValue =
24208 ?
"'alloc', 'from', 'to', 'tofrom', "
24209 "'firstprivate', 'none', 'default', 'present'"
24210 :
"'storage', 'from', 'to', 'tofrom', "
24211 "'firstprivate', 'private', 'none', 'default', 'present'";
24212 if (!isDefaultmapKind && isDefaultmapModifier) {
24213 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24215 }
else if (isDefaultmapKind && !isDefaultmapModifier) {
24216 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24219 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24221 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24231 if (
DSAStack->checkDefaultmapCategory(Kind)) {
24232 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
24238 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
24239 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
24240 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
24242 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
24259 Diag(DTCI.
Loc, diag::err_omp_region_not_file_context);
24265 Diag(DTCI.
Loc, diag::warn_hip_omp_target_directives);
24267 DeclareTargetNesting.push_back(DTCI);
24273 assert(!DeclareTargetNesting.empty() &&
24274 "check isInOpenMPDeclareTargetContext() first!");
24275 return DeclareTargetNesting.pop_back_val();
24285 if (DeclareTargetNesting.empty())
24289 Diag(DTCI.
Loc, diag::warn_omp_unterminated_declare_target)
24290 << getOpenMPDirectiveName(DTCI.
Kind, OMPVersion);
24296 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
24305 VarOrFuncDeclFilterCCC CCC(
SemaRef);
24309 SemaRef.diagnoseTypo(Corrected,
24310 SemaRef.PDiag(diag::err_undeclared_var_use_suggest)
24334 "Expected variable, function or function template.");
24336 if (
auto *VD = dyn_cast<VarDecl>(ND)) {
24338 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
24339 !VD->isStaticDataMember()) {
24340 Diag(Loc, diag::err_omp_declare_target_has_local_vars)
24349 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
24353 Diag(Loc, diag::warn_hip_omp_target_directives);
24356 const unsigned Level = -1;
24359 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
24360 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
24361 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.
DT &&
24362 (*ActiveAttr)->getLevel() == Level) {
24363 Diag(Loc, diag::err_omp_device_type_mismatch)
24364 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.
DT)
24365 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
24366 (*ActiveAttr)->getDevType());
24369 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
24370 (*ActiveAttr)->getLevel() == Level) {
24371 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
24375 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
24378 Expr *IndirectE =
nullptr;
24379 bool IsIndirect =
false;
24385 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
24390 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
24392 if (
auto *VD = dyn_cast<VarDecl>(ND);
24394 VD->hasGlobalStorage())
24403 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy>
MapTy =
24404 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
24405 if (SemaRef.
LangOpts.OpenMP >= 50 &&
24408 VD->hasGlobalStorage()) {
24409 if (!
MapTy || (*
MapTy != OMPDeclareTargetDeclAttr::MT_To &&
24410 *
MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
24417 diag::err_omp_lambda_capture_in_declare_target_not_to);
24418 SemaRef.
Diag(SL, diag::note_var_explicitly_captured_here)
24425 SemaRef.
Diag(VD->
getLocation(), diag::warn_omp_not_in_target_context);
24426 SemaRef.
Diag(SL, diag::note_used_here) << SR;
24430 Sema &SemaRef, DSAStackTy *Stack,
24432 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
24443 if (
auto *VD = dyn_cast<VarDecl>(D)) {
24445 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
24446 !VD->isStaticDataMember())
24450 if (
DSAStack->isThreadPrivate(VD)) {
24451 Diag(SL, diag::err_omp_threadprivate_in_target);
24456 if (
const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
24457 D = FTD->getTemplatedDecl();
24458 if (
auto *FD = dyn_cast<FunctionDecl>(D)) {
24459 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
24460 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
24461 if (IdLoc.
isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
24462 Diag(IdLoc, diag::err_omp_function_in_link_clause);
24467 if (
auto *VD = dyn_cast<ValueDecl>(D)) {
24477 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
24478 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
24479 unsigned Level = DeclareTargetNesting.size();
24480 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
24483 Expr *IndirectE =
nullptr;
24484 bool IsIndirect =
false;
24490 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
24492 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
24493 : OMPDeclareTargetDeclAttr::MT_To,
24494 DTCI.
DT, IndirectE, IsIndirect, Level,
24498 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
24518 if (
auto *VD = dyn_cast<VarDecl>(Node->
getDecl())) {
24520 DeclVector.push_back(VD);
24525 for (
auto *Child : Ex->
children()) {
24534 A = TD->
getAttr<OMPDeclareTargetDeclAttr>();
24536 llvm::SmallDenseSet<Decl *> Visited;
24537 while (!DeclVector.empty()) {
24538 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
24539 if (!Visited.insert(TargetVarDecl).second)
24542 if (TargetVarDecl->
hasAttr<OMPDeclareTargetDeclAttr>() &&
24572 unsigned Count = 0;
24573 for (
unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
24575 llvm::is_contained(Modifiers, MotionModifiers[I])) {
24576 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
24580 "Modifiers exceed the allowed number of motion modifiers");
24581 Modifiers[Count] = MotionModifiers[I];
24582 ModifiersLoc[Count] = MotionModifiersLoc[I];
24586 MappableVarListInfo MVLI(VarList);
24588 MapperIdScopeSpec, MapperId, UnresolvedMappers);
24589 if (MVLI.ProcessedVarList.empty())
24592 if (
auto *DRE = dyn_cast<DeclRefExpr>(IteratorExpr))
24593 if (
auto *VD = dyn_cast<VarDecl>(DRE->
getDecl()))
24596 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24597 MVLI.VarComponents, MVLI.UDMapperList, IteratorExpr, Modifiers,
24614 unsigned Count = 0;
24615 for (
unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
24617 llvm::is_contained(Modifiers, MotionModifiers[I])) {
24618 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
24622 "Modifiers exceed the allowed number of motion modifiers");
24623 Modifiers[Count] = MotionModifiers[I];
24624 ModifiersLoc[Count] = MotionModifiersLoc[I];
24628 MappableVarListInfo MVLI(VarList);
24630 MapperIdScopeSpec, MapperId, UnresolvedMappers);
24631 if (MVLI.ProcessedVarList.empty())
24634 if (
auto *DRE = dyn_cast<DeclRefExpr>(IteratorExpr))
24635 if (
auto *VD = dyn_cast<VarDecl>(DRE->
getDecl()))
24638 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24639 MVLI.VarComponents, MVLI.UDMapperList, IteratorExpr, Modifiers,
24648 MappableVarListInfo MVLI(VarList);
24652 for (
Expr *RefExpr : VarList) {
24653 assert(RefExpr &&
"NULL expr in OpenMP use_device_ptr clause.");
24656 Expr *SimpleRefExpr = RefExpr;
24660 MVLI.ProcessedVarList.push_back(RefExpr);
24661 PrivateCopies.push_back(
nullptr);
24662 Inits.push_back(
nullptr);
24669 Type =
Type.getNonReferenceType().getUnqualifiedType();
24671 auto *VD = dyn_cast<VarDecl>(D);
24675 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
24676 << 0 << RefExpr->getSourceRange();
24685 if (VDPrivate->isInvalidDecl())
24688 SemaRef.CurContext->addDecl(VDPrivate);
24690 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
24697 SemaRef.AddInitializerToDecl(
24698 VDPrivate,
SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
24706 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
24707 PrivateCopies.push_back(VDPrivateRefExpr);
24708 Inits.push_back(VDInitRefExpr);
24713 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
24717 MVLI.VarBaseDeclarations.push_back(D);
24718 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24719 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
24723 if (MVLI.ProcessedVarList.empty())
24728 MVLI.VarBaseDeclarations, MVLI.VarComponents, FallbackModifier,
24729 FallbackModifierLoc);
24735 MappableVarListInfo MVLI(VarList);
24737 for (
Expr *RefExpr : VarList) {
24738 assert(RefExpr &&
"NULL expr in OpenMP use_device_addr clause.");
24741 Expr *SimpleRefExpr = RefExpr;
24747 MVLI.ProcessedVarList.push_back(RefExpr);
24752 auto *VD = dyn_cast<VarDecl>(D);
24759 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
24764 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
24770 SemaRef, RefExpr, CurComponents, OMPC_use_device_addr,
24777 assert(!CurComponents.empty() &&
24778 "use_device_addr clause expression with no components!");
24795 CurComponents,
DSAStack->getCurrentDirective());
24796 const Expr *AttachPtrExpr = AttachPtrResult.first;
24798 if (AttachPtrExpr) {
24800 bool IsValidBase =
false;
24803 IsValidBase =
true;
24804 else if (
const auto *ME = dyn_cast<MemberExpr>(BaseExpr);
24806 IsValidBase =
true;
24808 if (!IsValidBase) {
24810 diag::err_omp_expected_base_pointer_var_name_member_expr)
24811 << (
SemaRef.getCurrentThisType().isNull() ? 0 : 1)
24818 ValueDecl *CurDeclaration = CurComponents.back().getAssociatedDeclaration();
24820 "Unexpected null decl for use_device_addr clause.");
24822 MVLI.VarBaseDeclarations.push_back(CurDeclaration);
24823 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24824 MVLI.VarComponents.back().append(CurComponents.begin(),
24825 CurComponents.end());
24828 if (MVLI.ProcessedVarList.empty())
24832 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24833 MVLI.VarComponents);
24839 MappableVarListInfo MVLI(VarList);
24840 for (
Expr *RefExpr : VarList) {
24841 assert(RefExpr &&
"NULL expr in OpenMP is_device_ptr clause.");
24844 Expr *SimpleRefExpr = RefExpr;
24848 MVLI.ProcessedVarList.push_back(RefExpr);
24858 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
24859 << 0 << RefExpr->getSourceRange();
24865 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
24868 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
24871 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
24877 const Expr *ConflictExpr;
24878 if (
DSAStack->checkMappableExprComponentListsForDecl(
24883 ConflictExpr = R.front().getAssociatedExpression();
24886 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
24895 SimpleRefExpr, D,
false);
24896 DSAStack->addMappableExpressionComponents(
24897 D, MC, OMPC_is_device_ptr);
24900 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
24907 "Unexpected device pointer expression!");
24908 MVLI.VarBaseDeclarations.push_back(
24910 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24911 MVLI.VarComponents.back().push_back(MC);
24914 if (MVLI.ProcessedVarList.empty())
24918 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24919 MVLI.VarComponents);
24925 MappableVarListInfo MVLI(VarList);
24926 for (
Expr *RefExpr : VarList) {
24927 assert(RefExpr &&
"NULL expr in OpenMP has_device_addr clause.");
24930 Expr *SimpleRefExpr = RefExpr;
24935 MVLI.ProcessedVarList.push_back(RefExpr);
24943 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
24946 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
24949 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
24955 const Expr *ConflictExpr;
24956 if (
DSAStack->checkMappableExprComponentListsForDecl(
24961 ConflictExpr = R.front().getAssociatedExpression();
24964 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
24972 Expr *Component = SimpleRefExpr;
24973 auto *VD = dyn_cast<VarDecl>(D);
24977 SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
24979 Component, D,
false);
24980 DSAStack->addMappableExpressionComponents(
24981 D, MC, OMPC_has_device_addr);
24984 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
24987 assert(Ref &&
"has_device_addr capture failed");
24988 MVLI.ProcessedVarList.push_back(Ref);
24990 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
24997 "Unexpected device pointer expression!");
24998 MVLI.VarBaseDeclarations.push_back(
25000 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
25001 MVLI.VarComponents.back().push_back(MC);
25004 if (MVLI.ProcessedVarList.empty())
25008 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
25009 MVLI.VarComponents);
25023 bool AllocDependent =
25027 if (!AllocDependent) {
25036 AllocatorRes =
SemaRef.PerformImplicitConversion(
25037 AllocatorRes.
get(),
DSAStack->getOMPAllocatorHandleT(),
25042 Allocator = AllocatorRes.
isUsable() ? AllocatorRes.
get() :
nullptr;
25051 !
DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
25052 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
25059 if (!AlignmentDependent) {
25062 Alignment = AlignResult.
isUsable() ? AlignResult.
get() :
nullptr;
25067 for (
Expr *RefExpr : VarList) {
25068 assert(RefExpr &&
"NULL expr in OpenMP allocate clause.");
25071 Expr *SimpleRefExpr = RefExpr;
25075 Vars.push_back(RefExpr);
25081 auto *VD = dyn_cast<VarDecl>(D);
25083 if (!VD && !
SemaRef.CurContext->isDependentContext())
25085 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
25086 ? RefExpr->IgnoreParens()
25094 DSAStack->addInnerAllocatorExpr(Allocator);
25097 getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
25098 FirstAllocateModifier, FirstAllocateModifierLoc, SecondAllocateModifier,
25099 SecondAllocateModifierLoc, EndLoc, Vars);
25107 for (
Expr *RefExpr : VarList) {
25108 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
25111 Expr *SimpleRefExpr = RefExpr;
25115 Vars.push_back(RefExpr);
25122 if (
const Expr *PrevRef =
25123 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
25124 Diag(ELoc, diag::err_omp_used_in_clause_twice)
25126 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
25131 Vars.push_back(RefExpr);
25148 SemaRef.setFunctionHasBranchProtectedScope();
25150 return OMPScopeDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses,
25159 for (
Expr *RefExpr : VarList) {
25160 assert(RefExpr &&
"NULL expr in OpenMP inclusive clause.");
25163 Expr *SimpleRefExpr = RefExpr;
25168 Vars.push_back(RefExpr);
25173 const DSAStackTy::DSAVarData DVar =
25179 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
25180 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
25181 << RefExpr->getSourceRange();
25183 if (
DSAStack->getParentDirective() != OMPD_unknown)
25184 DSAStack->markDeclAsUsedInScanDirective(D);
25185 Vars.push_back(RefExpr);
25200 for (
Expr *RefExpr : VarList) {
25201 assert(RefExpr &&
"NULL expr in OpenMP exclusive clause.");
25204 Expr *SimpleRefExpr = RefExpr;
25209 Vars.push_back(RefExpr);
25215 DSAStackTy::DSAVarData DVar;
25216 if (ParentDirective != OMPD_unknown)
25217 DVar =
DSAStack->getTopDSA(D,
true);
25222 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
25223 DVar.Modifier != OMPC_REDUCTION_inscan) {
25224 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
25225 << RefExpr->getSourceRange();
25227 DSAStack->markDeclAsUsedInScanDirective(D);
25229 Vars.push_back(RefExpr);
25241 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
25242 if (!OMPAlloctraitT.
isNull())
25247 S.
Diag(Loc, diag::err_omp_implied_type_not_found) <<
"omp_alloctrait_t";
25250 Stack->setOMPAlloctraitT(PT.
get());
25270 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
25271 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
25272 StringRef Allocator =
25273 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
25275 PredefinedAllocators.insert(
SemaRef.LookupSingleName(
25281 Expr *AllocatorExpr =
nullptr;
25289 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
25290 bool IsPredefinedAllocator =
false;
25292 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
25294 IsPredefinedAllocator =
25296 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
25300 bool IsTypeCompatible = IsPredefinedAllocator;
25301 IsTypeCompatible = IsTypeCompatible ||
25302 Context.hasSameUnqualifiedType(AllocatorExprType,
25303 OMPAllocatorHandleT);
25305 IsTypeCompatible ||
25306 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
25307 bool IsNonConstantLValue =
25309 if (!DRE || !IsTypeCompatible ||
25310 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
25312 <<
"omp_allocator_handle_t" << (DRE ? 1 : 0)
25321 diag::err_omp_predefined_allocator_with_traits)
25334 diag::err_omp_nonpredefined_allocator_without_traits);
25340 AllocatorExpr =
SemaRef.DefaultLvalueConversion(AllocatorExpr).get();
25343 IsPredefinedAllocator
25344 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
25345 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
25347 Expr *AllocatorTraitsExpr =
nullptr;
25361 if (
const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
25362 TraitTy = ConstArrayTy->getElementType();
25364 !(Context.hasSameUnqualifiedType(TraitTy,
25366 Context.typesAreCompatible(TraitTy,
DSAStack->getOMPAlloctraitT(),
25369 diag::err_omp_expected_array_alloctraits)
25370 << AllocatorTraitsExpr->
getType();
25375 if (
auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
25378 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
25395 for (
Expr *RefExpr : Locators) {
25396 assert(RefExpr &&
"NULL expr in OpenMP affinity clause.");
25399 Vars.push_back(RefExpr);
25407 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
25408 << 1 << 0 << RefExpr->getSourceRange();
25419 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
25420 << 1 << 0 << RefExpr->getSourceRange();
25427 ColonLoc, EndLoc, Modifier, Vars);
25436 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
25444 LParenLoc, EndLoc);
25451 Expr *ValExpr = Size;
25452 Stmt *HelperValStmt =
nullptr;
25463 DKind, OMPC_ompx_dyn_cgroup_mem,
getLangOpts().OpenMP);
25464 if (CaptureRegion != OMPD_unknown &&
25465 !
SemaRef.CurContext->isDependentContext()) {
25466 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
25467 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
25468 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
25473 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
25488 diag::err_omp_unexpected_clause_value)
25489 << Values << getOpenMPClauseName(OMPC_dyn_groupprivate);
25493 Expr *ValExpr = Size;
25494 Stmt *HelperValStmt =
nullptr;
25505 DKind, OMPC_dyn_groupprivate,
getLangOpts().OpenMP);
25506 if (CaptureRegion != OMPD_unknown &&
25507 !
SemaRef.CurContext->isDependentContext()) {
25508 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
25509 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
25510 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
25515 StartLoc, LParenLoc, EndLoc, ValExpr, HelperValStmt, CaptureRegion, M1,
25524 if (
DSAStack->getCurrentDirective() == OMPD_ordered &&
25525 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
25526 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
25527 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
25528 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
25534 DSAStackTy::OperatorOffsetTy OpsOffs;
25535 llvm::APSInt TotalDepCount(32);
25538 DepType == OMPC_DOACROSS_source ||
25539 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
25540 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
25542 Vars = VarOffset.Vars;
25543 OpsOffs = VarOffset.OpsOffs;
25544 TotalDepCount = VarOffset.TotalDepCount;
25546 EndLoc, DepType, DepLoc, ColonLoc, Vars,
25547 TotalDepCount.getZExtValue());
25548 if (
DSAStack->isParentOrderedRegion())
25549 DSAStack->addDoacrossDependClause(
C, OpsOffs);
25569 return new (
getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
25577 return OMPAbsentClause::Create(
getASTContext(), DKVec, Loc, LLoc, RLoc);
25578 case OMPC_contains:
25579 return OMPContainsClause::Create(
getASTContext(), DKVec, Loc, LLoc, RLoc);
25581 llvm_unreachable(
"Unexpected OpenMP clause");
25589 case OMPC_no_openmp:
25591 case OMPC_no_openmp_routines:
25592 return new (
getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
25593 case OMPC_no_parallelism:
25594 return new (
getASTContext()) OMPNoParallelismClause(Loc, RLoc);
25595 case OMPC_no_openmp_constructs:
25596 return new (
getASTContext()) OMPNoOpenMPConstructsClause(Loc, RLoc);
25598 llvm_unreachable(
"Unexpected OpenMP clause");
25607 if (
Base->hasPlaceholderType() &&
25608 !
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
25621 LowerBound =
Result.get();
25623 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
25643 if (
Base->isTypeDependent() ||
25646 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
25649 Base, LowerBound, Length, Stride, Context.DependentTy,
VK_LValue,
25650 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
25662 Diag(
Base->getExprLoc(), diag::err_omp_typecheck_section_value)
25663 <<
Base->getSourceRange());
25669 if (Res.isInvalid())
25671 diag::err_omp_typecheck_section_not_integer)
25673 LowerBound = Res.get();
25683 if (Res.isInvalid())
25685 diag::err_omp_typecheck_section_not_integer)
25686 << 1 << Length->getSourceRange());
25687 Length = Res.get();
25689 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
25690 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
25691 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
25692 << 1 << Length->getSourceRange();
25699 diag::err_omp_typecheck_section_not_integer)
25701 Stride = Res.
get();
25714 Diag(
Base->getExprLoc(), diag::err_omp_section_function_type)
25715 << ResultTy <<
Base->getSourceRange();
25719 if (
SemaRef.RequireCompleteType(
Base->getExprLoc(), ResultTy,
25720 diag::err_omp_section_incomplete_type,
Base))
25728 llvm::APSInt LowerBoundValue =
Result.Val.getInt();
25729 if (LowerBoundValue.isNegative()) {
25731 diag::err_omp_section_not_subset_of_array)
25740 if (Length->EvaluateAsInt(
Result, Context)) {
25743 llvm::APSInt LengthValue =
Result.Val.getInt();
25744 if (LengthValue.isNegative()) {
25745 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
25746 <<
toString(LengthValue, 10,
true)
25747 << Length->getSourceRange();
25751 }
else if (
SemaRef.getLangOpts().OpenMP < 60 && ColonLocFirst.
isValid() &&
25757 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
25767 llvm::APSInt StrideValue =
Result.Val.getInt();
25768 if (!StrideValue.isStrictlyPositive()) {
25769 Diag(Stride->
getExprLoc(), diag::err_omp_section_stride_non_positive)
25770 <<
toString(StrideValue, 10,
true)
25777 if (!
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
25784 Base, LowerBound, Length, Stride, Context.ArraySectionTy,
VK_LValue,
25785 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
25792 if (
Base->hasPlaceholderType()) {
25806 LParenLoc, RParenLoc, Dims, Brackets);
25808 (!
Base->isTypeDependent() &&
25811 diag::err_omp_non_pointer_type_array_shaping_base)
25812 <<
Base->getSourceRange());
25815 bool ErrorFound =
false;
25817 if (
Dim->hasPlaceholderType()) {
25819 if (
Result.isInvalid()) {
25824 if (
Result.isInvalid()) {
25830 if (!
Dim->isTypeDependent()) {
25833 if (
Result.isInvalid()) {
25835 Diag(
Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
25836 <<
Dim->getSourceRange();
25841 if (!
Dim->isValueDependent() &&
Dim->EvaluateAsInt(EvResult, Context)) {
25846 if (!
Value.isStrictlyPositive()) {
25847 Diag(
Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
25849 <<
Dim->getSourceRange();
25855 NewDims.push_back(
Dim);
25860 LParenLoc, RParenLoc, NewDims, Brackets);
25870 bool IsCorrect =
true;
25875 if (!D.Type.getAsOpaquePtr()) {
25879 DeclTy = Context.IntTy;
25880 StartLoc = D.DeclIdentLoc;
25886 bool IsDeclTyDependent = DeclTy->isDependentType() ||
25887 DeclTy->containsUnexpandedParameterPack() ||
25888 DeclTy->isInstantiationDependentType();
25889 if (!IsDeclTyDependent) {
25890 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
25893 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
25898 if (DeclTy.isConstant(Context)) {
25901 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
25909 assert(D.DeclIdent &&
"Identifier expected.");
25914 D.DeclIdent, DeclTy, TInfo,
SC_None);
25932 SemaRef.PushOnScopeChains(VD, S);
25935 SemaRef.CurContext->addDecl(VD);
25941 Expr *Begin = D.Range.Begin;
25945 Begin = BeginRes.
get();
25947 Expr *End = D.Range.End;
25951 End = EndRes.
get();
25953 Expr *Step = D.Range.Step;
25956 Diag(Step->
getExprLoc(), diag::err_omp_iterator_step_not_integral)
25961 std::optional<llvm::APSInt>
Result =
25967 Diag(Step->
getExprLoc(), diag::err_omp_iterator_step_constant_zero)
25973 if (!Begin || !End || !IsCorrect) {
25989 if (
Decl *ID = D.IteratorDecl)
25990 ID->setInvalidDecl();
25995 if (!
SemaRef.CurContext->isDependentContext()) {
26002 D.Range.End, D.Range.Begin);
26008 if (D.Range.Step) {
26011 Res =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.
get(),
26018 Res =
SemaRef.CreateBuiltinBinOp(
26019 D.AssignmentLoc, BO_Sub, Res.
get(),
26020 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
26026 Res =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.
get(),
26032 St1 =
SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus,
26036 D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End);
26042 Res1 =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.
get(),
26049 Res1 =
SemaRef.CreateBuiltinBinOp(
26050 D.AssignmentLoc, BO_Sub, Res1.
get(),
26051 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
26057 Res1 =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.
get(),
26065 D.AssignmentLoc, BO_GT, D.Range.Step,
26066 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get());
26071 Res =
SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc,
26078 Res =
SemaRef.ActOnFinishFullExpr(Res.
get(),
false);
26090 CounterVD->setImplicit();
26097 if (D.Range.Step) {
26098 UpdateRes =
SemaRef.CreateBuiltinBinOp(
26099 D.AssignmentLoc, BO_Mul,
26100 SemaRef.DefaultLvalueConversion(RefRes.
get()).get(), St.
get());
26102 UpdateRes =
SemaRef.DefaultLvalueConversion(RefRes.
get());
26108 UpdateRes =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add,
26109 D.Range.Begin, UpdateRes.
get());
26118 UpdateRes =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign,
26119 VDRes.
get(), UpdateRes.
get());
26125 SemaRef.ActOnFinishFullExpr(UpdateRes.
get(),
true);
26131 D.AssignmentLoc, UO_PreInc, RefRes.
get());
26132 if (!CounterUpdateRes.
isUsable()) {
26136 CounterUpdateRes =
SemaRef.ActOnFinishFullExpr(CounterUpdateRes.
get(),
26138 if (!CounterUpdateRes.
isUsable()) {
26149 Helpers.assign(ID.size(), {});
26154 if (
Decl *ID = D.IteratorDecl)
26155 ID->setInvalidDecl();
26160 LLoc, RLoc, ID, Helpers);
26165 StringRef AssumptionStr) {
26166 if (llvm::getKnownAssumptionStrings().count(AssumptionStr))
26169 unsigned BestEditDistance = 3;
26170 StringRef Suggestion;
26171 for (
const auto &KnownAssumptionIt : llvm::getKnownAssumptionStrings()) {
26172 unsigned EditDistance =
26173 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
26174 if (EditDistance < BestEditDistance) {
26175 Suggestion = KnownAssumptionIt.getKey();
26176 BestEditDistance = EditDistance;
26180 if (!Suggestion.empty())
26181 S.
Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
26182 << AssumptionStr << Suggestion;
26184 S.
Diag(Loc, diag::warn_omp_assume_attribute_string_unknown)
26192 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc))
Defines the clang::ASTContext interface.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
This file defines OpenMP nodes for declarative directives.
static const Decl * getCanonicalDecl(const Decl *D)
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
llvm::MachO::TargetList TargetList
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
llvm::DenseMap< Stmt *, Stmt * > MapTy
Implements a partial diagnostic that can be emitted anwyhere in a DiagnosticBuilder stream.
@ ForVisibleRedeclaration
The lookup results will be used for redeclaration of a name, if an entity by that name already exists...
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
static VarDecl * buildVarDecl(Sema &S, SourceLocation Loc, QualType Type, IdentifierInfo *II)
Build a variable declaration for move parameter.
static NamedDecl * findAcceptableDecl(Sema &SemaRef, NamedDecl *D, unsigned IDNS)
Retrieve the visible declaration corresponding to D, if any.
static Expr * getOrderedNumberExpr(ArrayRef< OMPClause * > Clauses)
static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack, bool Diagnose=true)
Tries to find omp_depend_t. type.
static Stmt * buildPreInits(ASTContext &Context, MutableArrayRef< Decl * > PreInits)
Build preinits statement for the given declarations.
static void argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id, SourceLocation Loc, QualType Ty, SmallVectorImpl< UnresolvedSet< 8 > > &Lookups)
static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR, Sema &SemaRef, Decl *D)
static void updatePreInits(OMPLoopTransformationDirective *Transform, SmallVectorImpl< Stmt * > &PreInits)
Updates OriginalInits by checking Transform against loop transformation directives and appending thei...
static bool checkGenericLoopLastprivate(Sema &S, ArrayRef< OMPClause * > Clauses, OpenMPDirectiveKind K, DSAStackTy *Stack)
static bool checkSimdlenSafelenSpecified(Sema &S, const ArrayRef< OMPClause * > Clauses)
static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto, QualType NewType)
static bool checkOMPArraySectionConstantForReduction(ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement, SmallVectorImpl< llvm::APSInt > &ArraySizes)
static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind, ArrayRef< OMPClause * > Clauses, ArrayRef< OpenMPDirectiveKind > AllowedNameModifiers)
static void handleDeclareVariantConstructTrait(DSAStackTy *Stack, OpenMPDirectiveKind DKind, bool ScopeEntry)
static VarDecl * precomputeExpr(Sema &Actions, SmallVectorImpl< Stmt * > &BodyStmts, Expr *E, StringRef Name)
static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S, CXXScopeSpec &MapperIdScopeSpec, const DeclarationNameInfo &MapperId, QualType Type)
static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, CXXScopeSpec &MapperIdScopeSpec, const DeclarationNameInfo &MapperId, QualType Type, Expr *UnresolvedMapper)
static bool checkReductionClauseWithNogroup(Sema &S, ArrayRef< OMPClause * > Clauses)
static bool checkSectionsDirective(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt, DSAStackTy *Stack)
static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, SourceLocation M1Loc, SourceLocation M2Loc)
static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef)
static Expr * makeFloorIVRef(Sema &SemaRef, ArrayRef< VarDecl * > FloorIndVars, int I, QualType IVTy, DeclRefExpr *OrigCntVar)
Build and return a DeclRefExpr for the floor induction variable using the SemaRef and the provided pa...
static OMPAllocateDeclAttr::AllocatorTypeTy getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator)
static bool isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind, bool StrictlyPositive, bool BuildCapture=false, OpenMPDirectiveKind DKind=OMPD_unknown, OpenMPDirectiveKind *CaptureRegion=nullptr, Stmt **HelperValStmt=nullptr)
static Expr * buildPostUpdate(Sema &S, ArrayRef< Expr * > PostUpdates)
Build postupdate expression for the given list of postupdates expressions.
static CapturedStmt * buildLoopVarFunc(Sema &Actions, QualType LoopVarTy, QualType LogicalTy, DeclRefExpr *StartExpr, Expr *Step, bool Deref)
Create a closure that computes the loop variable from the logical iteration number.
static ExprResult buildCounterUpdate(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef, ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract, bool IsNonRectangularLB, llvm::MapVector< const Expr *, DeclRefExpr * > *Captures=nullptr)
Build 'VarRef = Start + Iter * Step'.
static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion, OpenMPDirectiveKind NameModifier=OMPD_unknown)
static bool finishLinearClauses(Sema &SemaRef, ArrayRef< OMPClause * > Clauses, OMPLoopBasedDirective::HelperExprs &B, DSAStackTy *Stack)
static Expr * getCollapseNumberExpr(ArrayRef< OMPClause * > Clauses)
static Expr * getDirectCallExpr(Expr *E)
static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef, const Expr *E, QualType BaseQTy)
static OMPCapturedExprDecl * buildCaptureDecl(Sema &S, IdentifierInfo *Id, Expr *CaptureExpr, bool WithInit, DeclContext *CurContext, bool AsExpression)
static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_allocator_handle_t type.
static bool isClauseMappable(ArrayRef< OMPClause * > Clauses)
Check if the variables in the mapping clause are externally visible.
static BinaryOperatorKind getRelatedCompoundReductionOp(BinaryOperatorKind BOK)
static SmallVector< SemaOpenMP::CapturedParamNameType > getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing)
static void collectLoopStmts(Stmt *AStmt, MutableArrayRef< Stmt * > LoopStmts)
Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected loop of a construct.
static bool checkMutuallyExclusiveClauses(Sema &S, ArrayRef< OMPClause * > Clauses, ArrayRef< OpenMPClauseKind > MutuallyExclusiveClauses)
Find and diagnose mutually exclusive clause kinds.
static std::pair< ValueDecl *, bool > getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc, SourceRange &ERange, bool AllowArraySection=false, bool AllowAssumedSizeArray=false, StringRef DiagType="")
static DeclRefExpr * buildImplicitMap(Sema &S, QualType BaseType, DSAStackTy *Stack, SmallVectorImpl< OMPClause * > &Maps)
static bool checkOrderedOrderSpecified(Sema &S, const ArrayRef< OMPClause * > Clauses)
static OpenMPMapClauseKind getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M, bool IsAggregateOrDeclareTarget)
static void processCapturedRegions(Sema &SemaRef, OpenMPDirectiveKind DKind, Scope *CurScope, SourceLocation Loc)
static const Expr * getExprAsWritten(const Expr *E)
static bool checkMapConflicts(Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E, bool CurrentRegionOnly, OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents, OpenMPClauseKind CKind)
static bool isOpenMPDeviceDelayedContext(Sema &S)
static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef)
Convert integer expression E to make it have at least Bits bits.
static SmallVector< SemaOpenMP::CapturedParamNameType > getUnknownRegionParams(Sema &SemaRef)
static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack, QualType CanonType, const Expr *E)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTeamsRegionParams(Sema &SemaRef)
static void checkOMPAssumeAttr(Sema &S, SourceLocation Loc, StringRef AssumptionStr)
Check if AssumptionStr is a known assumption and warn if not.
static void applyOMPAllocateAttribute(Sema &S, VarDecl *VD, OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator, Expr *Alignment, SourceRange SR)
static ExprResult buildImplicitMapper(Sema &S, QualType BaseType, DSAStackTy *Stack)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTargetRegionParams(Sema &SemaRef)
static CapturedStmt * buildDistanceFunc(Sema &Actions, QualType LogicalTy, BinaryOperator::Opcode Rel, Expr *StartExpr, Expr *StopExpr, Expr *StepExpr)
Create a closure that computes the number of iterations of a loop.
static bool checkPreviousOMPAllocateAttribute(Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD, OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator)
static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, Expr *NumIterations, Sema &SemaRef, Scope *S, DSAStackTy *Stack)
static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D, QualType Type, OpenMPClauseKind CKind, SourceLocation ELoc, bool AcceptIfMutable=true, bool ListItemNotVar=false)
static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr, SourceLocation VarLoc, OpenMPClauseKind Kind)
static const ValueDecl * getCanonicalDecl(const ValueDecl *D)
static std::string getOpenMPClauseNameForDiag(OpenMPClauseKind C)
static const Expr * checkMapClauseExpressionBase(Sema &SemaRef, Expr *E, OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose)
Return the expression of the base of the mappable expression or null if it cannot be determined and d...
static void checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind, MappableVarListInfo &MVLI, SourceLocation StartLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId, ArrayRef< Expr * > UnresolvedMappers, OpenMPMapClauseKind MapType=OMPC_MAP_unknown, ArrayRef< OpenMPMapModifierKind > Modifiers={}, bool IsMapTypeImplicit=false, bool NoDiagnose=false)
static bool hasClauses(ArrayRef< OMPClause * > Clauses, const OpenMPClauseKind K)
Check for existence of a map clause in the list of clauses.
static bool checkOpenMPIterationSpace(OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA, unsigned CurrentNestedLoopCount, unsigned NestedLoopCount, unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA, llvm::MutableArrayRef< LoopIterationSpace > ResultIterSpaces, llvm::MapVector< const Expr *, DeclRefExpr * > &Captures, const llvm::SmallPtrSetImpl< const Decl * > &CollapsedLoopVarDecls)
Called on a for stmt to check and extract its iteration space for further processing (such as collaps...
static CapturedStmt * setBranchProtectedScope(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt)
static void processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack, SmallVectorImpl< OMPClause * > &Clauses)
Perform DFS through the structure/class data members trying to find member(s) with user-defined 'defa...
static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion, OpenMPDirectiveKind CancelRegion, SourceLocation StartLoc)
static DeclRefExpr * buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty, SourceLocation Loc, bool RefersToCapture=false)
static ExprResult buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef, ExprResult Start, bool IsNonRectangularLB, llvm::MapVector< const Expr *, DeclRefExpr * > &Captures)
Build 'VarRef = Start.
static DoacrossDataInfoTy ProcessOpenMPDoacrossClauseCommon(Sema &SemaRef, bool IsSource, ArrayRef< Expr * > VarList, DSAStackTy *Stack, SourceLocation EndLoc)
static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR, Sema &SemaRef, DSAStackTy *Stack, ValueDecl *VD)
static bool findOMPEventHandleT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_event_handle_t type.
static ExprResult buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, Scope *S, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, QualType Ty, CXXCastPath &BasePath, Expr *UnresolvedReduction)
static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef)
Check if the given expression E is a constant integer that fits into Bits bits.
static void checkAllocateClauses(Sema &S, DSAStackTy *Stack, ArrayRef< OMPClause * > Clauses)
static bool actOnOMPReductionKindClause(Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions, ReductionData &RD)
static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack, const ValueDecl *D, const DSAStackTy::DSAVarData &DVar, bool IsLoopIterVar=false)
static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last, ArrayRef< unsigned > Exclude={})
static DeclRefExpr * buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr, bool WithInit)
static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_alloctrait_t type.
static void appendFlattenedStmtList(SmallVectorImpl< Stmt * > &TargetList, Stmt *Item)
Append the Item or the content of a CompoundStmt to the list TargetList.
static bool isConstNotMutableType(Sema &SemaRef, QualType Type, bool AcceptIfMutable=true, bool *IsClassType=nullptr)
static void addLoopPreInits(ASTContext &Context, OMPLoopBasedDirective::HelperExprs &LoopHelper, Stmt *LoopStmt, ArrayRef< Stmt * > OriginalInit, SmallVectorImpl< Stmt * > &PreInits)
Add preinit statements that need to be propagated from the selected loop.
static void checkReductionClauses(Sema &S, DSAStackTy *Stack, ArrayRef< OMPClause * > Clauses)
Check consistency of the reduction clauses.
static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef, DSAStackTy *Stack, QualType QTy, bool FullCheck=true)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTaskRegionParams(Sema &SemaRef)
static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack, OpenMPDirectiveKind CurrentRegion, const DeclarationNameInfo &CurrentName, OpenMPDirectiveKind CancelRegion, OpenMPBindClauseKind BindKind, SourceLocation StartLoc)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTaskloopRegionParams(Sema &SemaRef)
static unsigned checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef, DSAStackTy &DSA, SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA, OMPLoopBasedDirective::HelperExprs &Built)
Called on a for stmt to check itself and nested loops (if any).
static OpenMPDefaultmapClauseKind getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD)
static bool checkNumExprsInClause(SemaBase &SemaRef, ArrayRef< OMPClause * > Clauses, unsigned MaxNum, unsigned Diag)
This checks whether a ClauseType clause C has at most Max expression.
static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef, const Expr *E, QualType BaseQTy)
Return true if it can be proven that the provided array expression (array section or array subscript)...
static OMPClause * createTransparentClause(Sema &SemaRef, ASTContext &Ctx, Expr *ImpexTypeArg, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
static T filterLookupForUDReductionAndMapper(SmallVectorImpl< U > &Lookups, const llvm::function_ref< T(ValueDecl *)> Gen)
This file declares semantic analysis for OpenMP constructs and clauses.
static CharSourceRange getRange(const CharSourceRange &EditRange, const SourceManager &SM, const LangOptions &LangOpts, bool IncludeMacroExpansion)
This file defines OpenMP AST classes for executable directives and clauses.
Expr * getUpdateExpr()
Get helper expression of the form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or 'OpaqueValueExp...
Expr * getV()
Get 'v' part of the associated expression/statement.
Expr * getR()
Get 'r' part of the associated expression/statement.
Expr * getD()
Get 'd' part of the associated expression/statement.
Expr * getX()
Get 'x' part of the associated expression/statement.
bool isFailOnly() const
Return true if 'v' is updated only when the condition is evaluated false (compare capture only).
bool isPostfixUpdate() const
Return true if 'v' expression must be updated to original value of 'x', false if 'v' must be updated ...
Expr * getExpr()
Get 'expr' part of the associated expression/statement.
bool isXLHSInRHSPart() const
Return true if helper update expression has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' and...
static QualType getPointeeType(const MemRegion *R)
VerifyDiagnosticConsumer::Directive Directive
Look for variables declared in the body parts of a for-loop nest.
bool VisitCXXForRangeStmt(CXXForRangeStmt *RF) override
bool VisitVarDecl(VarDecl *D) override
ForVarDeclFinder(llvm::SmallPtrSetImpl< const Decl * > &VD)
bool VisitForStmt(ForStmt *F) override
This class visits every VarDecl that the initializer references and adds OMPDeclareTargetDeclAttr to ...
void declareTargetInitializer(Decl *TD)
A function that keeps a record of all the Decls that are variables, has OMPDeclareTargetDeclAttr,...
void VisitDeclRefExpr(DeclRefExpr *Node)
A StmtVisitor class function that visits all DeclRefExpr and adds OMPDeclareTargetDeclAttr to them.
void VisitExpr(Expr *Ex)
A function that iterates across each of the Expr's children.
bool VisitCXXForRangeStmt(CXXForRangeStmt *FRS) override
NestedLoopCounterVisitor()=default
bool VisitForStmt(ForStmt *FS) override
bool TraverseStmt(Stmt *S) override
bool TraverseDecl(Decl *D) override
unsigned getNestedLoopCount() const
static OMPAffinityClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Creates clause with a modifier a list of locator items.
static OMPAlignedClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Expr *A)
Creates clause with a list of variables VL and alignment A.
static OMPAssumeDirective * Create(const ASTContext &Ctx, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AStmt)
This represents 'bind' clause in the 'pragma omp ...' directives.
static OMPBindClause * Create(const ASTContext &C, OpenMPBindClauseKind K, SourceLocation KLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'bind' clause with kind K ('teams', 'parallel', or 'thread').
static OMPCancelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, OpenMPDirectiveKind CancelRegion)
Creates directive.
static OMPCancellationPointDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Creates directive.
Class that represents a component of a mappable expression. E.g. for an expression S....
ValueDecl * getAssociatedDeclaration() const
SmallVector< MappableComponent, 8 > MappableExprComponentList
static std::pair< const Expr *, std::optional< size_t > > findAttachPtrExpr(MappableExprComponentListRef Components, OpenMPDirectiveKind CurDirKind)
Find the attach pointer expression from a list of mappable expression components.
ArrayRef< MappableComponent > MappableExprComponentListRef
SmallVector< MappableExprComponentList, 8 > MappableExprComponentLists
static OMPCopyinClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps)
Creates clause with a list of variables VL.
static OMPCopyprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps)
Creates clause with a list of variables VL.
This represents 'defaultmap' clause in the 'pragma omp ...' directive.
This represents implicit clause 'depend' for the 'pragma omp task' directive.
static OMPDependClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, DependDataTy Data, Expr *DepModifier, ArrayRef< Expr * > VL, unsigned NumLoops)
Creates clause with a list of variables VL.
static OMPDepobjClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, Expr *Depobj)
Creates clause.
This represents 'destroy' clause in the 'pragma omp depobj' directive or the 'pragma omp interop' dir...
This represents 'detach' clause in the 'pragma omp task' directive.
This represents 'device' clause in the 'pragma omp ...' directive.
static OMPDispatchDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, SourceLocation TargetCallLoc)
Creates directive with a list of Clauses.
This represents 'dist_schedule' clause in the 'pragma omp ...' directive.
static OMPDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents the 'doacross' clause for the 'pragma omp ordered' directive.
static OMPDoacrossClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VL, unsigned NumLoops)
Creates clause with a list of expressions VL.
This represents 'dyn_groupprivate' clause in 'pragma omp target ...' and 'pragma omp teams ....
static OMPErrorDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
static OMPExclusiveClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This represents 'filter' clause in the 'pragma omp ...' directive.
This represents implicit clause 'flush' for the 'pragma omp flush' directive. This clause does not ex...
static OMPFlushClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPFromClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, Expr *IteratorExpr, ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId)
Creates clause with a list of variables Vars.
static OMPFuseDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumGeneratedTopLevelLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for pragma omp fuse'.
static OMPGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents 'grainsize' clause in the 'pragma omp ...' directive.
static OMPHasDeviceAddrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
This represents 'hint' clause in the 'pragma omp ...' directive.
static OMPInclusiveClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPInitClause * Create(const ASTContext &C, Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Creates a fully specified clause.
static OMPInterchangeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp interchange'.
static OMPInteropDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive.
static OMPIsDevicePtrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPMapClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, Expr *IteratorModifier, ArrayRef< OpenMPMapModifierKind > MapModifiers, ArrayRef< SourceLocation > MapModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId, OpenMPMapClauseKind Type, bool TypeIsImplicit, SourceLocation TypeLoc)
Creates clause with a list of variables VL.
static OMPMaskedDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
static OMPMaskedTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPMaskedTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPMasterTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPMasterTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents 'nocontext' clause in the 'pragma omp ...' directive.
This represents 'nogroup' clause in the 'pragma omp ...' directive.
This represents clause 'nontemporal' in the 'pragma omp ...' directives.
static OMPNontemporalClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This represents 'novariants' clause in the 'pragma omp ...' directive.
This represents 'num_tasks' clause in the 'pragma omp ...' directive.
static OMPNumTeamsClause * Create(const ASTContext &C, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents 'order' clause in the 'pragma omp ...' directive.
SourceLocation getKindKwLoc() const
Returns location of clause kind.
OpenMPOrderClauseKind getKind() const
Returns kind of the clause.
static OMPParallelGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelMaskedTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPParallelMaskedTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelMasterTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPParallelMasterTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents 'priority' clause in the 'pragma omp ...' directive.
static OMPReverseDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt, unsigned NumLoops, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp reverse'.
This represents 'simd' clause in the 'pragma omp ...' directive.
static OMPScanDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
static OMPStripeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp stripe'.
static OMPTargetDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetEnterDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetExitDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetParallelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetParallelGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool CanBeParallelFor)
Creates directive with a list of Clauses.
static OMPTargetUpdateDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTeamsDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTeamsDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPThreadLimitClause * Create(const ASTContext &C, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents 'threads' clause in the 'pragma omp ...' directive.
static OMPTileDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp tile'.
static OMPToClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, Expr *IteratorModifier, ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId)
Creates clause with a list of variables Vars.
bool isExtensionActive(llvm::omp::TraitProperty TP)
Check the extension trait TP is active.
void getAsVariantMatchInfo(ASTContext &ASTCtx, llvm::omp::VariantMatchInfo &VMI) const
Create a variant match info object from this trait info object.
bool anyScoreOrCondition(llvm::function_ref< bool(Expr *&, bool)> Cond)
static OMPUnrollDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, unsigned NumGeneratedTopLevelLoops, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp unroll'.
This represents the 'use' clause in 'pragma omp ...' directives.
static OMPUseDeviceAddrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPUseDevicePtrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< Expr * > PrivateVars, ArrayRef< Expr * > Inits, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, OpenMPUseDevicePtrFallbackModifier FallbackModifier, SourceLocation FallbackModifierLoc)
Creates clause with a list of variables Vars.
This represents clause 'uses_allocators' in the 'pragma omp target'-based directives.
static OMPUsesAllocatorsClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< OMPUsesAllocatorsClause::Data > Data)
Creates clause with a list of allocators Data.
This represents 'ompx_attribute' clause in a directive that might generate an outlined function.
This represents 'ompx_bare' clause in the 'pragma omp target teams ...' directive.
This represents 'ompx_dyn_cgroup_mem' clause in the 'pragma omp target ...' directive.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
unsigned getIntWidth(QualType T) const
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false, bool Unqualified=false, bool AllowCXX=false, bool IsConditionalOperator=false)
DeclarationNameTable DeclarationNames
QualType getUnsignedPointerDiffType() const
Return the unique unsigned counterpart of "ptrdiff_t" integer type.
ASTMutationListener * getASTMutationListener() const
Retrieve a pointer to the AST mutation listener associated with this AST context, if any.
void Deallocate(void *Ptr) const
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
QualType getUIntPtrType() const
Return a type compatible with "uintptr_t" (C99 7.18.1.4), as defined by the target.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
CharUnits getAlignOfGlobalVarInChars(QualType T, const VarDecl *VD) const
Return the alignment in characters that should be given to a global variable with type T.
QualType getVariableArrayType(QualType EltTy, Expr *NumElts, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return a non-unique reference to the type for a variable array of the specified element type.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
static bool hasSameType(QualType T1, QualType T2)
Determine whether the given types T1 and T2 are equivalent.
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
const TargetInfo & getTargetInfo() const
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
An abstract interface that should be implemented by listeners that want to be notified when an AST en...
This class represents BOTH the OpenMP Array Section and OpenACC 'subarray', with a boolean differenti...
Expr * getBase()
Get base of the array section.
Expr * getLength()
Get length of array section.
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Expr * getLowerBound()
Get lower bound of array section.
SourceLocation getColonLocFirst() const
Represents an array type, per C99 6.7.5.2 - Array Declarators.
QualType getElementType() const
Attr - This represents one attribute.
Represents an attribute applied to a statement.
static AttributedStmt * Create(const ASTContext &C, SourceLocation Loc, ArrayRef< const Attr * > Attrs, Stmt *SubStmt)
SourceLocation getBeginLoc() const
A builtin binary operation expression such as "x + y" or "x <= y".
static bool isRelationalOp(Opcode Opc)
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
static Opcode getOpForCompoundAssignment(Opcode Opc)
SourceLocation getOperatorLoc() const
SourceLocation getExprLoc() const
static Opcode reverseComparisonOp(Opcode Opc)
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
BinaryOperatorKind Opcode
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
bool isAmbiguous(CanQualType BaseType) const
Determine whether the path from the most-derived type to the given base type is ambiguous (i....
Represents a C++ constructor within a class.
Represents a C++ conversion function within a class.
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
Represents a C++ struct/union/class.
bool hasMutableFields() const
Determine whether this class, or any of its class subobjects, contains a mutable field.
bool hasDefinition() const
Represents a C++ nested-name-specifier or a global scope specifier.
bool isValid() const
A scope specifier is present, and it refers to a real scope.
SourceLocation getBeginLoc() const
bool isSet() const
Deprecated.
NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const
Retrieve a nested-name-specifier with location information, copied into the given AST context.
bool isInvalid() const
An error occurred during parsing of the scope specifier.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
SourceLocation getBeginLoc() const
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
A wrapper class around a pointer that always points to its canonical declaration.
Represents the body of a CapturedStmt, and serves as its DeclContext.
unsigned getNumParams() const
void setNothrow(bool Nothrow=true)
Stmt * getBody() const override
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
ImplicitParamDecl * getParam(unsigned i) const
This captures a statement into a function.
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
SourceRange getSourceRange() const LLVM_READONLY
Stmt * getCapturedStmt()
Retrieve the statement being captured.
bool capturesVariable(const VarDecl *Var) const
True if this variable has been captured.
SourceLocation getBeginLoc() const LLVM_READONLY
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Declaration of a class template.
Complex values, per C99 6.2.5p11.
CompoundStmt - This represents a group of statements like { stmt stmt }.
SourceLocation getBeginLoc() const
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
ConditionalOperator - The ?
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
bool Equals(const DeclContext *DC) const
Determine whether this declaration context is equivalent to the declaration context DC.
bool isFileContext() const
DeclContextLookupResult lookup_result
ASTContext & getParentASTContext() const
bool isExternCXXContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
bool isTranslationUnit() const
void addDecl(Decl *D)
Add the declaration D into this context.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
bool isExternCContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
bool Encloses(const DeclContext *DC) const
Determine whether this declaration context semantically encloses the declaration context DC.
void addHiddenDecl(Decl *D)
Add the declaration D to this context without modifying any lookup tables.
static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls)
bool isSingleDecl() const
A reference to a declared variable, function, enum, etc.
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
NonOdrUseReason isNonOdrUse() const
Is this expression a non-odr-use reference, and if so, why?
SourceLocation getEndLoc() const LLVM_READONLY
SourceLocation getBeginLoc() const
ConstexprSpecKind getConstexprSpecifier() const
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
SourceLocation getEndLoc() const
const DeclGroupRef getDeclGroup() const
const Decl * getSingleDecl() const
SourceLocation getBeginLoc() const LLVM_READONLY
Decl - This represents one declaration (or definition), e.g.
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
void markUsed(ASTContext &C)
Mark the declaration used, in the sense of odr-use.
bool isReferenced() const
Whether any declaration of this entity was referenced.
bool isCanonicalDecl() const
Whether this particular Decl is a canonical one.
bool isInvalidDecl() const
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
void setAccess(AccessSpecifier AS)
SourceLocation getLocation() const
void setImplicit(bool I=true)
void setReferenced(bool R=true)
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
bool isUsed(bool CheckUsedAttr=true) const
Whether any (re-)declaration of the entity was used, meaning that a definition is required.
DeclContext * getDeclContext()
AccessSpecifier getAccess() const
void setDeclContext(DeclContext *DC)
setDeclContext - Set both the semantic and lexical DeclContext to DC.
void setLexicalDeclContext(DeclContext *DC)
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
The name of a declaration.
IdentifierInfo * getAsIdentifierInfo() const
Retrieve the IdentifierInfo * stored in this declaration name, or null if this declaration name isn't...
OverloadedOperatorKind getCXXOverloadedOperator() const
If this name is the name of an overloadable operator in C++ (e.g., operator+), retrieve the kind of o...
bool isEmpty() const
Evaluates true when this declaration name is empty.
Information about one declarator, including the parsed type information and the identifier.
const DeclSpec & getDeclSpec() const
getDeclSpec - Return the declaration-specifier that this declarator was declared with.
SourceLocation getIdentifierLoc() const
void SetIdentifier(const IdentifierInfo *Id, SourceLocation IdLoc)
Set the name of this declarator to be the given identifier.
SourceLocation getBeginLoc() const LLVM_READONLY
void setFunctionDefinitionKind(FunctionDefinitionKind Val)
const CXXScopeSpec & getCXXScopeSpec() const
getCXXScopeSpec - Return the C++ scope specifier (global scope or nested-name-specifier) that is part...
bool isInvalidType() const
const IdentifierInfo * getIdentifier() const
virtual bool TraverseStmt(MaybeConst< Stmt > *S)
RAII object that enters a new expression evaluation context.
This represents one expression.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
bool isIntegerConstantExpr(const ASTContext &Ctx) const
@ SE_AllowSideEffects
Allow any unmodeled side effect.
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
bool isValueDependent() const
Determines whether the value of this expression depends on.
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
bool isTypeDependent() const
Determines whether the type of this expression depends on.
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
bool containsUnexpandedParameterPack() const
Whether this expression contains an unexpanded parameter pack (for C++11 variadic templates).
Expr * IgnoreParenLValueCasts() LLVM_READONLY
Skip past any parentheses and lvalue casts which might surround this expression until reaching a fixe...
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
bool containsErrors() const
Whether this expression contains subexpressions which had errors.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents difference between two FPOptions values.
Represents a member of a struct/union/class.
bool isBitField() const
Determines whether this field is a bitfield.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
static FloatingLiteral * Create(const ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L)
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
ArrayRef< ParmVarDecl * > parameters() const
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
FunctionDecl * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
FunctionDecl * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
Represents a prototype with parameter type info, e.g.
One of these records is kept for each identifier that is lexed.
void setMangledOpenMPVariantName(bool I)
Set whether this is the mangled name of an OpenMP variant.
StringRef getName() const
Return the actual identifier string.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
IfStmt - This represents an if/then/else.
static IfStmt * Create(const ASTContext &Ctx, SourceLocation IL, IfStatementKind Kind, Stmt *Init, VarDecl *Var, Expr *Cond, SourceLocation LPL, SourceLocation RPL, Stmt *Then, SourceLocation EL=SourceLocation(), Stmt *Else=nullptr)
Create an IfStmt.
SourceLocation getBeginLoc() const
ImaginaryLiteral - We support imaginary integer and floating point literals, like "1....
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
ImplicitConversionSequence - Represents an implicit conversion sequence, which may be a standard conv...
Describes the kind of initialization being performed, along with location information for tokens rela...
static InitializationKind CreateCopy(SourceLocation InitLoc, SourceLocation EqualLoc, bool AllowExplicitConvs=false)
Create a copy initialization.
Describes the sequence of initializations required to initialize a given object or reference with a s...
ExprResult Perform(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType *ResultType=nullptr)
Perform the actual initialization of the given entity based on the computed initialization sequence.
Describes an entity that is being initialized.
static InitializedEntity InitializeVariable(VarDecl *Var)
Create the initialization entity for a variable.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Describes the capture of a variable or of this, or of a C++1y init-capture.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
A class for iterating through a result set and possibly filtering out results.
Represents the results of name lookup.
LLVM_ATTRIBUTE_REINITIALIZES void clear()
Clears out any current state.
DeclClass * getAsSingle() const
bool empty() const
Return true if no decls were found.
Filter makeFilter()
Create a filter for this result set.
NamedDecl * getFoundDecl() const
Fetch the unique decl found by this lookup.
bool isSingleResult() const
Determines if this names a single result which is not an unresolved value using decl.
NamedDecl * getRepresentativeDecl() const
Fetches a representative decl. Useful for lazy diagnostics.
void suppressDiagnostics()
Suppress the diagnostics that would normally fire because of this lookup.
static bool isVisible(Sema &SemaRef, NamedDecl *D)
Determine whether the given declaration is visible to the program.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
static MemberExpr * CreateImplicit(const ASTContext &C, Expr *Base, bool IsArrow, ValueDecl *MemberDecl, QualType T, ExprValueKind VK, ExprObjectKind OK)
Create an implicit MemberExpr, with no location, qualifier, template arguments, and so on.
SourceLocation getExprLoc() const LLVM_READONLY
This represents a decl that may have a name.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
virtual void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const
Appends a human-readable name for this declaration into the given stream.
void setDeclName(DeclarationName N)
Set the name of this declaration.
A C++ nested-name-specifier augmented with source location information.
static OMPAlignClause * Create(const ASTContext &C, Expr *A, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'align' clause with the given alignment.
static OMPAllocateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, Expr *Allocator, Expr *Alignment, SourceLocation ColonLoc, OpenMPAllocateClauseModifier Modifier1, SourceLocation Modifier1Loc, OpenMPAllocateClauseModifier Modifier2, SourceLocation Modifier2Loc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static bool classof(const OMPClause *T)
static OMPAllocateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL, ArrayRef< OMPClause * > CL)
This represents 'allocator' clause in the 'pragma omp ...' directive.
Expr * getBase()
Fetches base expression of array shaping expression.
static OMPArrayShapingExpr * Create(const ASTContext &Context, QualType T, Expr *Op, SourceLocation L, SourceLocation R, ArrayRef< Expr * > Dims, ArrayRef< SourceRange > BracketRanges)
Pseudo declaration for capturing expressions.
static OMPCapturedExprDecl * Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, QualType T, SourceLocation StartLoc)
static OMPClauseWithPostUpdate * get(OMPClause *C)
Class that handles pre-initialization statement for some clauses, like 'schedule',...
static OMPClauseWithPreInit * get(OMPClause *C)
This is a basic class for representing single OpenMP clause.
SourceLocation getBeginLoc() const
Returns the starting location of the clause.
SourceLocation getEndLoc() const
Returns the ending location of the clause.
OpenMPClauseKind getClauseKind() const
Returns kind of OpenMP clause (private, shared, reduction, etc.).
This represents 'collapse' clause in the 'pragma omp ...' directive.
This represents 'pragma omp declare mapper ...' directive.
static OMPDeclareMapperDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, QualType T, DeclarationName VarName, ArrayRef< OMPClause * > Clauses, OMPDeclareMapperDecl *PrevDeclInScope)
Creates declare mapper node.
This represents 'pragma omp declare reduction ...' directive.
static OMPDeclareReductionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, QualType T, OMPDeclareReductionDecl *PrevDeclInScope)
Create declare reduction node.
This represents 'default' clause in the 'pragma omp ...' directive.
This represents 'final' clause in the 'pragma omp ...' directive.
Representation of the 'full' clause of the 'pragma omp unroll' directive.
static OMPFullClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Build an AST node for a 'full' clause.
This represents 'pragma omp groupprivate ...' directive.
static OMPGroupPrivateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL)
This represents 'if' clause in the 'pragma omp ...' directive.
static OMPIteratorExpr * Create(const ASTContext &Context, QualType T, SourceLocation IteratorKwLoc, SourceLocation L, SourceLocation R, ArrayRef< IteratorDefinition > Data, ArrayRef< OMPIteratorHelperData > Helpers)
static OMPLoopRangeClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation FirstLoc, SourceLocation CountLoc, SourceLocation EndLoc, Expr *First, Expr *Count)
Build a 'looprange' clause AST node.
This represents 'num_threads' clause in the 'pragma omp ...' directive.
Representation of the 'partial' clause of the 'pragma omp unroll' directive.
static OMPPartialClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, Expr *Factor)
Build an AST node for a 'partial' clause.
Expr * getFactor() const
Returns the argument of the clause or nullptr if not set.
This class represents the 'permutation' clause in the 'pragma omp interchange' directive.
unsigned getNumLoops() const
Returns the number of list items.
MutableArrayRef< Expr * > getArgsRefs()
Returns the permutation index expressions.
static OMPPermutationClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Args)
Build a 'permutation' clause AST node.
This represents 'pragma omp requires...' directive.
clauselist_range clauselists()
static OMPRequiresDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< OMPClause * > CL)
Create requires node.
This represents 'safelen' clause in the 'pragma omp ...' directive.
Expr * getSafelen() const
Return safe iteration space distance.
This represents 'simdlen' clause in the 'pragma omp ...' directive.
Expr * getSimdlen() const
Return safe iteration space distance.
static OMPSizesClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Sizes)
Build a 'sizes' AST node.
This represents 'pragma omp threadprivate ...' directive.
static OMPThreadPrivateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL)
This represents 'threadset' clause in the 'pragma omp task ...' directive.
void * getAsOpaquePtr() const
static OpaquePtr make(DeclGroupRef P)
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Represents a parameter to a function.
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
ParsedAttr - Represents a syntactic attribute.
IdentifierTable & getIdentifierTable()
static PseudoObjectExpr * Create(const ASTContext &Context, Expr *syntactic, ArrayRef< Expr * > semantic, unsigned resultIndex)
A (possibly-)qualified type.
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
bool hasQualifiers() const
Determine whether this type has any qualifiers.
QualType withRestrict() const
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
QualType withConst() const
void addConst()
Add the const type qualifier to this QualType.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
bool isConstant(const ASTContext &Ctx) const
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getCanonicalType() const
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
bool isMoreQualifiedThan(QualType Other, const ASTContext &Ctx) const
Determine whether this type is more qualified than the other given type, requiring exact equality for...
const Type * getTypePtrOrNull() const
Represents a struct/union/class.
field_range fields() const
field_iterator field_begin() const
Base for LValueReferenceType and RValueReferenceType.
Scope - A scope is a transient data structure that is used while parsing the program.
bool isDeclScope(const Decl *D) const
isDeclScope - Return true if this is the scope that the specified decl is declared in.
Scope * getBreakParent()
getBreakParent - Return the closest scope that a break statement would be affected by.
bool isOpenMPOrderClauseScope() const
Determine whether this scope is some OpenMP directive with order clause which specifies concurrent sc...
const Scope * getParent() const
getParent - Return the scope that this is nested in.
bool isOpenMPLoopScope() const
Determine whether this scope is a loop having OpenMP loop directive attached.
@ OpenMPOrderClauseScope
This is a scope of some OpenMP directive with order clause which specifies concurrent.
A generic diagnostic builder for errors which may or may not be deferred.
ASTContext & getASTContext() const
const LangOptions & getLangOpts() const
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
StmtResult ActOnOpenMPTargetParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel for' after parsing of the associated statement.
OMPClause * ActOnOpenMPNocontextClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nocontext' clause.
OMPClause * ActOnOpenMPXDynCGroupMemClause(Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_dyn_cgroup_mem' clause.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd(Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid)
Called at the end of 'pragma omp declare reduction'.
bool isInOpenMPTaskUntiedContext() const
Return true if currently in OpenMP task with untied clause context.
OMPClause * ActOnOpenMPUntiedClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'untied' clause.
OMPClause * ActOnOpenMPSafelenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'safelen' clause.
OMPClause * ActOnOpenMPThreadsetClause(OpenMPThreadsetKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'threadset' clause.
OMPClause * ActOnOpenMPHoldsClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'holds' clause.
StmtResult ActOnOpenMPParallelMasterTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel master taskloop simd' after parsing of the associated sta...
StmtResult ActOnOpenMPParallelMasterDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel master' after parsing of the associated statement.
StmtResult ActOnOpenMPDispatchDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp dispatch' after parsing of the.
OMPClause * ActOnOpenMPReadClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'read' clause.
OMPClause * ActOnOpenMPFilterClause(Expr *ThreadID, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'filter' clause.
void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner)
Finish current declare reduction construct initializer.
ExprResult ActOnOpenMPCall(ExprResult Call, Scope *Scope, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig)
Given the potential call expression Call, determine if there is a specialization via the OpenMP decla...
void setOpenMPDeviceNum(int Num)
Setter and getter functions for device_num.
OMPClause * ActOnOpenMPFullClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-form 'full' clauses.
StmtResult ActOnOpenMPTargetEnterDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target enter data' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'detach' clause.
OMPClause * ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'use' clause.
OMPClause * ActOnOpenMPFailClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'fail' clause.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute parallel for simd' after parsing of the as...
StmtResult ActOnOpenMPAssumeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Process an OpenMP assume directive.
void ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called once a target context is completed, that can be when a 'pragma omp end declare target' was enc...
OMPClause * ActOnOpenMPDirectivePresenceClause(OpenMPClauseKind CK, llvm::ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
Called on well-formed 'absent' or 'contains' clauses.
void tryCaptureOpenMPLambdas(ValueDecl *V)
Function tries to capture lambda's captured variables in the OpenMP region before the original lambda...
StmtResult ActOnOpenMPParallelMaskedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel masked' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute parallel for' after parsing of the associa...
OMPClause * ActOnOpenMPPrivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'private' clause.
void StartOpenMPClause(OpenMPClauseKind K)
Start analysis of clauses.
bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, SourceLocation LinLoc)
Checks correctness of linear modifiers.
ExprResult ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType, SourceLocation StartLoc, DeclarationName VN)
Build the mapper variable of 'pragma omp declare mapper'.
OMPClause * ActOnOpenMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc, SourceLocation LParenLoc=SourceLocation(), Expr *NumForLoops=nullptr)
Called on well-formed 'ordered' clause.
OMPClause * ActOnOpenMPSelfMapsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'self_maps' clause.
bool CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc, OpenMPLinearClauseKind LinKind, QualType Type, bool IsDeclareSimd=false)
Checks that the specified declaration matches requirements for the linear decls.
OMPClause * ActOnOpenMPIsDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'is_device_ptr' clause.
OMPClause * ActOnOpenMPHasDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'has_device_addr' clause.
StmtResult ActOnOpenMPErrorDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, bool InExContext=true)
Called on well-formed '#pragma omp error'.
OMPClause * ActOnOpenMPPartialClause(Expr *FactorExpr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'partial' clauses.
StmtResult ActOnOpenMPSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPLastprivateClause(ArrayRef< Expr * > VarList, OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'lastprivate' clause.
void ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT, DeclareTargetContextInfo &DTCI)
Called on correct id-expression from the 'pragma omp declare target'.
DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc, ArrayRef< OMPClause * > ClauseList)
Called on well-formed 'pragma omp requires'.
OMPGroupPrivateDecl * CheckOMPGroupPrivateDecl(SourceLocation Loc, ArrayRef< Expr * > VarList)
Builds a new OpenMPGroupPrivateDecl and checks its correctness.
StmtResult ActOnOpenMPDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPFirstprivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'firstprivate' clause.
StmtResult ActOnOpenMPDepobjDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp depobj'.
ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK, ExprObjectKind OK, SourceLocation Loc)
OMPClause * ActOnOpenMPPriorityClause(Expr *Priority, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'priority' clause.
OMPClause * ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, ArrayRef< unsigned > Arguments, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, ArrayRef< SourceLocation > ArgumentsLoc, SourceLocation DelimLoc, SourceLocation EndLoc)
void ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, ArrayRef< Expr * > AdjustArgsNothing, ArrayRef< Expr * > AdjustArgsNeedDevicePtr, ArrayRef< Expr * > AdjustArgsNeedDeviceAddr, ArrayRef< OMPInteropInfo > AppendArgs, SourceLocation AdjustArgsLoc, SourceLocation AppendArgsLoc, SourceRange SR)
Called on well-formed '#pragma omp declare variant' after parsing of the associated method/function.
StmtResult ActOnOpenMPTargetParallelDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target parallel' after parsing of the associated statement.
OMPClause * ActOnOpenMPDistScheduleClause(OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'dist_schedule' clause.
OpenMPClauseKind isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, unsigned CapLevel) const
Check if the specified variable is used in 'private' clause.
OMPClause * ActOnOpenMPLoopRangeClause(Expr *First, Expr *Count, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation FirstLoc, SourceLocation CountLoc, SourceLocation EndLoc)
Called on well-form 'looprange' clause after parsing its arguments.
OMPClause * ActOnOpenMPPermutationClause(ArrayRef< Expr * > PermExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'permutation' clause after parsing its arguments.
OMPClause * ActOnOpenMPNontemporalClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nontemporal' clause.
OMPClause * ActOnOpenMPBindClause(OpenMPBindClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'bind' clause.
OMPClause * ActOnOpenMPThreadsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'threads' clause.
OMPClause * ActOnOpenMPThreadLimitClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'thread_limit' clause.
OMPClause * ActOnOpenMPSharedClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'shared' clause.
StmtResult ActOnOpenMPTargetExitDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target exit data' after parsing of the associated statement.
StmtResult ActOnOpenMPTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp teams' after parsing of the associated statement.
OMPClause * ActOnOpenMPCopyinClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'copyin' clause.
OMPClause * ActOnOpenMPMergeableClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'mergeable' clause.
void startOpenMPCXXRangeFor()
If the current region is a range loop-based region, mark the start of the loop construct.
OMPClause * ActOnOpenMPDestroyClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'destroy' clause.
StmtResult ActOnOpenMPParallelMaskedTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop' after parsing of the associated statemen...
OMPClause * ActOnOpenMPAffinityClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Called on well-formed 'affinity' clause.
OMPClause * ActOnOpenMPCompareClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'compare' clause.
StmtResult ActOnOpenMPFuseDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp fuse' after parsing of its clauses and the associated statement.
OMPClause * ActOnOpenMPNumTeamsClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_teams' clause.
StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel sections' after parsing of the associated statement.
OMPClause * ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'update' clause.
OMPClause * ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data, Expr *DepModifier, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depend' clause.
OMPClause * ActOnOpenMPDoacrossClause(OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'doacross' clause.
VarDecl * ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
StmtResult ActOnOpenMPTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute parallel for' after parsing of the associated sta...
StmtResult ActOnOpenMPMasterDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp master' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskgroupDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskgroup'.
VarDecl * isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo=false, unsigned StopAt=0)
Check if the specified variable is used in one of the private clauses (private, firstprivate,...
OMPClause * ActOnOpenMPUseDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, OpenMPUseDevicePtrFallbackModifier FallbackModifier, SourceLocation FallbackModifierLoc)
Called on well-formed 'use_device_ptr' clause.
StmtResult ActOnOpenMPMasterTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp master taskloop simd' after parsing of the associated statement.
ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id, OpenMPDirectiveKind Kind)
Called on correct id-expression from the 'pragma omp threadprivate'.
void ActOnOpenMPEndAssumesDirective()
Called on well-formed 'pragma omp end assumes'.
OMPClause * ActOnOpenMPNogroupClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nogroup' clause.
OMPClause * ActOnOpenMPGrainsizeClause(OpenMPGrainsizeClauseModifier Modifier, Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'grainsize' clause.
ExprResult ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc, Expr *LowerBound, SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length, Expr *Stride, SourceLocation RBLoc)
bool isOpenMPRebuildMemberExpr(ValueDecl *D)
The member expression(this->fd) needs to be rebuilt in the template instantiation to generate private...
void ActOnOpenMPDeviceNum(Expr *DeviceNumExpr)
Called on device_num selector in context selectors.
QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare reduction' construct.
StmtResult ActOnOpenMPMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp masked taskloop simd' after parsing of the associated statement.
bool isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, unsigned OpenMPCaptureLevel) const
Return true if the provided declaration VD should be captured by reference.
StmtResult ActOnOpenMPParallelGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel loop' after parsing of the associated statement.
DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList, ArrayRef< OMPClause * > Clauses, DeclContext *Owner=nullptr)
Called on well-formed 'pragma omp allocate'.
OMPClause * ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind)
Return the number of captured regions created for an OpenMP directive.
bool isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified variable is captured by 'target' directive.
StmtResult ActOnOpenMPParallelMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop simd' after parsing of the associated sta...
OMPClause * ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'dynamic_allocators' clause.
StmtResult ActOnOpenMPScopeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scope' after parsing of the associated statement.
void ActOnOpenMPIteratorVarDecl(VarDecl *VD)
bool isInOpenMPDeclareVariantScope() const
Can we exit an OpenMP declare variant scope at the moment.
StmtResult ActOnOpenMPDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute parallel for simd' after parsing of the associated stat...
StmtResult ActOnOpenMPBarrierDirective(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp barrier'.
TypeResult ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D)
Check variable declaration in 'omp declare mapper' construct.
ExprResult ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc, SourceLocation LLoc, SourceLocation RLoc, ArrayRef< OMPIteratorData > Data)
OMPClause * ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< UsesAllocatorsData > Data)
Called on well-formed 'uses_allocators' clause.
StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef< OMPClause * > Clauses)
End of OpenMP region.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveStart(Scope *S, DeclContext *DC, DeclarationName Name, ArrayRef< std::pair< QualType, SourceLocation > > ReductionTypes, AccessSpecifier AS, Decl *PrevDeclInScope=nullptr)
Called on start of 'pragma omp declare reduction'.
OMPClause * ActOnOpenMPAcqRelClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'acq_rel' clause.
OMPClause * ActOnOpenMPAllocatorClause(Expr *Allocator, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocator' clause.
ExprResult VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind, bool StrictlyPositive=true, bool SuppressExprDiags=false)
DeclGroupPtrTy ActOnOpenMPGroupPrivateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList)
Called on well-formed 'pragma omp groupprivate'.
bool isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const
OMPClause * ActOnOpenMPInclusiveClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'inclusive' clause.
SemaDiagnosticBuilder diagIfOpenMPHostCode(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as host cod...
SemaDiagnosticBuilder diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as device c...
StmtResult ActOnOpenMPSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp sections' after parsing of the associated statement.
void ActOnOpenMPEndDeclareVariant()
Handle a omp end declare variant.
OMPClause * ActOnOpenMPTaskReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions={})
Called on well-formed 'task_reduction' clause.
OMPClause * ActOnOpenMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc, SourceLocation LParenLoc, Expr *Condition)
Called on well-formed 'nowait' clause.
StmtResult ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp critical' after parsing of the associated statement.
StmtResult ActOnOpenMPMaskedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp masked' after parsing of the.
StmtResult ActOnOpenMPStripeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
void ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D)
Act on D, a function definition inside of an omp [begin/end] assumes.
void EndOpenMPDSABlock(Stmt *CurDirective)
Called on end of data sharing attribute block.
OMPClause * ActOnOpenMPOrderClause(OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KindLoc, SourceLocation EndLoc)
Called on well-formed 'order' clause.
llvm::SmallDenseMap< const ValueDecl *, const Expr *, 4 > VarsWithInheritedDSAType
OMPClause * ActOnOpenMPSizesClause(ArrayRef< Expr * > SizeExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'sizes' clause.
bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called on the start of target region i.e. 'pragma omp declare target'.
StmtResult ActOnOpenMPTeamsDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute parallel for simd' after parsing of the associate...
OMPClause * ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier, Expr *Device, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'device' clause.
StmtResult ActOnOpenMPDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute' after parsing of the associated statement.
StmtResult ActOnOpenMPSectionDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp section' after parsing of the associated statement.
StmtResult ActOnOpenMPInterchangeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp interchange' after parsing of its clauses and the associated statem...
bool isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified global variable must be captured by outer capture regions.
OMPClause * ActOnOpenMPInReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions={})
Called on well-formed 'in_reduction' clause.
StmtResult ActOnOpenMPGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPFlushClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'flush' pseudo clause.
OMPRequiresDecl * CheckOMPRequiresDecl(SourceLocation Loc, ArrayRef< OMPClause * > Clauses)
Check restrictions on Requires directive.
void ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(Decl *D, SmallVectorImpl< FunctionDecl * > &Bases)
Register D as specialization of all base functions in Bases in the current omp begin/end declare vari...
StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, OpenMPDirectiveKind CancelRegion, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
void EndOpenMPClause()
End analysis of clauses.
bool isInOpenMPAssumeScope() const
Check if there is an active global omp begin assumes directive.
void setOpenMPDeviceNumID(StringRef ID)
StmtResult ActOnOpenMPDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute parallel for' after parsing of the associated statement...
QualType ActOnOpenMPDeclareMapperType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare mapper' construct.
StmtResult ActOnOpenMPTeamsDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target teams' after parsing of the associated statement.
OMPClause * ActOnOpenMPMessageClause(Expr *MS, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'message' clause.
int getOpenMPDeviceNum() const
StmtResult ActOnOpenMPScanDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scan'.
OMPClause * ActOnOpenMPScheduleClause(OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'schedule' clause.
void ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init)
Check if the current region is an OpenMP loop region and if it is, mark loop control variable,...
OMPClause * ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
void DiagnoseUnterminatedOpenMPDeclareTarget()
Report unterminated 'omp declare target' or 'omp begin declare target' at the end of a compilation un...
void finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, const FunctionDecl *Callee, SourceLocation Loc)
Finishes analysis of the deferred functions calls that may be declared as host/nohost during device/h...
OMPClause * ActOnOpenMPSimdlenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'simdlen' clause.
std::optional< std::pair< FunctionDecl *, Expr * > > checkOpenMPDeclareVariantFunction(DeclGroupPtrTy DG, Expr *VariantRef, OMPTraitInfo &TI, unsigned NumAppendArgs, SourceRange SR)
Checks '#pragma omp declare variant' variant function and original functions after parsing of the ass...
StmtResult ActOnOpenMPParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel for simd' after parsing of the associated statement.
OpaquePtr< DeclGroupRef > DeclGroupPtrTy
OMPClause * ActOnOpenMPReleaseClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'release' clause.
OMPClause * ActOnOpenMPAcquireClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'acquire' clause.
OMPClause * ActOnOpenMPProcBindClause(llvm::omp::ProcBindKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'proc_bind' clause.
OMPClause * ActOnOpenMPSIMDClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'simd' clause.
OMPClause * ActOnOpenMPXBareClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_bare' clause.
StmtResult ActOnOpenMPInformationalDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Process an OpenMP informational directive.
StmtResult ActOnOpenMPCanonicalLoop(Stmt *AStmt)
Called for syntactical loops (ForStmt or CXXForRangeStmt) associated to an OpenMP loop directive.
OMPClause * ActOnOpenMPTransparentClause(Expr *Transparent, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'transparent' clause.
OMPClause * ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'hint' clause.
OMPClause * ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK, SourceLocation Loc, SourceLocation RLoc)
StmtResult ActOnOpenMPTargetTeamsDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute' after parsing of the associated statement...
StmtResult ActOnOpenMPParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel for' after parsing of the associated statement.
OMPClause * ActOnOpenMPCaptureClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'capture' clause.
StmtResult ActOnOpenMPForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp for' after parsing of the associated statement.
StmtResult ActOnOpenMPAtomicDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp atomic' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetUpdateDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target update'.
StmtResult ActOnOpenMPOrderedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp ordered' after parsing of the associated statement.
StmtResult ActOnOpenMPReverseDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp reverse'.
ExprResult ActOnOMPArrayShapingExpr(Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc, ArrayRef< Expr * > Dims, ArrayRef< SourceRange > Brackets)
OMPClause * ActOnOpenMPNumThreadsClause(OpenMPNumThreadsClauseModifier Modifier, Expr *NumThreads, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'num_threads' clause.
OMPClause * ActOnOpenMPAtClause(OpenMPAtClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'at' clause.
StmtResult ActOnOpenMPTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp taskloop' after parsing of the associated statement.
OMPClause * ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'init' clause.
OMPClause * ActOnOpenMPUseDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'use_device_addr' clause.
void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
OMPClause * ActOnOpenMPAllocateClause(Expr *Allocator, Expr *Alignment, OpenMPAllocateClauseModifier FirstModifier, SourceLocation FirstModifierLoc, OpenMPAllocateClauseModifier SecondModifier, SourceLocation SecondModifierLoc, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocate' clause.
std::pair< StringRef, QualType > CapturedParamNameType
OMPClause * ActOnOpenMPFinalClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'final' clause.
bool isInOpenMPTargetExecutionDirective() const
Return true inside OpenMP target region.
StmtResult ActOnOpenMPTargetDataDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target data' after parsing of the associated statement.
StmtResult ActOnOpenMPMasterTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp master taskloop' after parsing of the associated statement.
void ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, SmallVectorImpl< FunctionDecl * > &Bases)
The declarator D defines a function in the scope S which is nested in an omp begin/end declare varian...
StmtResult ActOnOpenMPFlushDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp flush'.
StmtResult ActOnOpenMPUnrollDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp unroll' after parsing of its clauses and the associated statement.
OMPClause * ActOnOpenMPMapClause(Expr *IteratorModifier, ArrayRef< OpenMPMapModifierKind > MapTypeModifiers, ArrayRef< SourceLocation > MapTypeModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, bool NoDiagnose=false, ArrayRef< Expr * > UnresolvedMappers={})
Called on well-formed 'map' clause.
OMPClause * ActOnOpenMPNumTasksClause(OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'num_tasks' clause.
void ActOnOpenMPDeclareTargetInitializer(Decl *D)
Adds OMPDeclareTargetDeclAttr to referenced variables in declare target directive.
bool isInOpenMPDeclareTargetContext() const
Return true inside OpenMP declare target region.
OMPClause * ActOnOpenMPFromClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, Expr *IteratorModifier, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers={})
Called on well-formed 'from' clause.
StmtResult ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Called on well-formed '#pragma omp cancellation point'.
OMPClause * ActOnOpenMPDynGroupprivateClause(OpenMPDynGroupprivateClauseModifier M1, OpenMPDynGroupprivateClauseFallbackModifier M2, Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc, SourceLocation EndLoc)
Called on a well-formed 'dyn_groupprivate' clause.
OMPClause * ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef< Expr * > Vars, const OMPVarListLocTy &Locs, OpenMPVarListDataTy &Data)
void startOpenMPLoop()
If the current region is a loop-based region, mark the start of the loop construct.
StmtResult ActOnOpenMPTargetDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target' after parsing of the associated statement.
void StartOpenMPDSABlock(OpenMPDirectiveKind K, const DeclarationNameInfo &DirName, Scope *CurScope, SourceLocation Loc)
Called on start of new data sharing attribute block.
OMPThreadPrivateDecl * CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef< Expr * > VarList)
Builds a new OpenMPThreadPrivateDecl and checks its correctness.
void handleOMPAssumeAttr(Decl *D, const ParsedAttr &AL)
OMPClause * ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'severity' clause.
OMPClause * ActOnOpenMPToClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, Expr *IteratorModifier, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers={})
Called on well-formed 'to' clause.
void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer, VarDecl *OmpPrivParm)
Finish current declare reduction construct initializer.
OMPClause * ActOnOpenMPLinearClause(ArrayRef< Expr * > VarList, Expr *Step, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind, SourceLocation LinLoc, SourceLocation ColonLoc, SourceLocation StepModifierLoc, SourceLocation EndLoc)
Called on well-formed 'linear' clause.
OMPClause * ActOnOpenMPDefaultmapClause(OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KindLoc, SourceLocation EndLoc)
Called on well-formed 'defaultmap' clause.
StmtResult ActOnOpenMPMaskedTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp masked taskloop' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskwaitDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskwait'.
StmtResult ActOnOpenMPForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp for simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPReductionClause(ArrayRef< Expr * > VarList, OpenMPVarListDataTy::OpenMPReductionClauseModifiers Modifiers, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions={})
Called on well-formed 'reduction' clause.
OMPClause * ActOnOpenMPRelaxedClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'relaxed' clause.
OMPClause * ActOnOpenMPAlignedClause(ArrayRef< Expr * > VarList, Expr *Alignment, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc)
Called on well-formed 'aligned' clause.
StmtResult ActOnOpenMPInteropDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp interop'.
OMPClause * ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depobj' pseudo clause.
OMPClause * ActOnOpenMPSeqCstClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'seq_cst' clause.
void checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, SourceLocation IdLoc=SourceLocation())
Check declaration inside target region.
OMPClause * ActOnOpenMPNovariantsClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'novariants' clause.
OMPClause * ActOnOpenMPCopyprivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'copyprivate' clause.
OMPClause * ActOnOpenMPCollapseClause(Expr *NumForLoops, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'collapse' clause.
DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen, ArrayRef< Expr * > Uniforms, ArrayRef< Expr * > Aligneds, ArrayRef< Expr * > Alignments, ArrayRef< Expr * > Linears, ArrayRef< unsigned > LinModifiers, ArrayRef< Expr * > Steps, SourceRange SR)
Called on well-formed '#pragma omp declare simd' after parsing of the associated method/function.
ExprResult PerformOpenMPImplicitIntegerConversion(SourceLocation OpLoc, Expr *Op)
StmtResult ActOnOpenMPTargetSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPDefaultClause(llvm::omp::DefaultKind M, SourceLocation MLoc, OpenMPDefaultClauseVariableCategory VCKind, SourceLocation VCKindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'default' clause.
OMPClause * ActOnOpenMPAlignClause(Expr *Alignment, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'align' clause.
OMPClause * ActOnOpenMPAtomicDefaultMemOrderClause(OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'atomic_default_mem_order' clause.
StmtResult ActOnOpenMPTeamsGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPWeakClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'weak' clause.
OMPClause * ActOnOpenMPXAttributeClause(ArrayRef< const Attr * > Attrs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_attribute' clause.
StmtResult ActOnOpenMPTileDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp tile' after parsing of its clauses and the associated statement.
StmtResult ActOnOpenMPParallelDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel' after parsing of the associated statement.
StmtResult ActOnOpenMPSingleDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp single' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp taskloop simd' after parsing of the associated statement.
const ValueDecl * getOpenMPDeclareMapperVarName() const
StmtResult ActOnOpenMPParallelMasterTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel master taskloop' after parsing of the associated statemen...
DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList)
Called on well-formed 'pragma omp threadprivate'.
void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope)
Initialization of captured region for OpenMP region.
NamedDecl * lookupOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id)
Searches for the provided declaration name for OpenMP declare target directive.
OMPClause * ActOnOpenMPExclusiveClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'exclusive' clause.
OMPClause * ActOnOpenMPWriteClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'write' clause.
StmtResult ActOnOpenMPTargetParallelGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel loop' after parsing of the associated statement.
void ActOnOpenMPAssumesDirective(SourceLocation Loc, OpenMPDirectiveKind DKind, ArrayRef< std::string > Assumptions, bool SkippedClauses)
Called on well-formed 'pragma omp [begin] assume[s]'.
StmtResult ActOnOpenMPTargetParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel for simd' after parsing of the associated statemen...
void ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI)
Handle a omp begin declare variant.
StmtResult ActOnOpenMPLoopnest(Stmt *AStmt)
Process a canonical OpenMP loop nest that can either be a canonical literal loop (ForStmt or CXXForRa...
OMPClause * ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'reverse_offload' clause.
StmtResult ActOnOpenMPTaskDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp task' after parsing of the associated statement.
OMPClause * ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation NameModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc)
Called on well-formed 'if' clause.
StmtResult ActOnOpenMPTargetTeamsDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute simd' after parsing of the associated stat...
const DeclareTargetContextInfo ActOnOpenMPEndDeclareTargetDirective()
Called at the end of target region i.e. 'pragma omp end declare target'.
void setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D, unsigned Level)
Sets OpenMP capture kind (OMPC_private, OMPC_firstprivate, OMPC_map etc.) for FD based on DSA for the...
OMPClause * ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc, SourceLocation EndLoc)
StmtResult ActOnOpenMPCancelDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Called on well-formed '#pragma omp cancel'.
StmtResult ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskyield'.
StmtResult ActOnOpenMPTeamsDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute simd' after parsing of the associated statement.
DeclGroupPtrTy ActOnOpenMPDeclareMapperDirective(Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType, SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS, Expr *MapperVarRef, ArrayRef< OMPClause * > Clauses, Decl *PrevDeclInScope=nullptr)
Called for 'pragma omp declare mapper'.
A RAII object to enter scope of a compound statement.
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Abstract base class used for diagnosing integer constant expression violations.
Sema - This implements semantic analysis and AST building for C.
QualType getCurrentThisType()
Try to retrieve the type of the 'this' pointer.
Scope * getCurScope() const
Retrieve the parser's current scope.
bool isDeclInScope(NamedDecl *D, DeclContext *Ctx, Scope *S=nullptr, bool AllowInlineNamespace=false) const
isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true if 'D' is in Scope 'S',...
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr, bool IsAfterAmp=false)
void BuildBasePathArray(const CXXBasePaths &Paths, CXXCastPath &BasePath)
ExprResult IgnoredValueConversions(Expr *E)
IgnoredValueConversions - Given that an expression's result is syntactically ignored,...
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
@ LookupOMPReductionName
Look up the name of an OpenMP user-defined reduction operation.
@ LookupOMPMapperName
Look up the name of an OpenMP user-defined mapper.
@ LookupAnyName
Look up any declaration with any name.
ExprResult CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, bool ForFoldExpression=false)
CreateBuiltinBinOp - Creates a new built-in binary operation with operator Opc at location TokLoc.
FunctionEmissionStatus
Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
Scope * getScopeForContext(DeclContext *Ctx)
Determines the active Scope associated with the given declaration context.
FPOptionsOverride CurFPFeatureOverrides()
NamedDecl * LookupSingleName(Scope *S, DeclarationName Name, SourceLocation Loc, LookupNameKind NameKind, RedeclarationKind Redecl=RedeclarationKind::NotForRedeclaration)
Look up a name, looking for a single declaration.
void ActOnCapturedRegionError()
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)
void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext=true)
Add this decl to the scope shadowed decl chains.
ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)
ASTContext & getASTContext() const
ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *Input, bool IsAfterAmp=false)
bool tryCaptureVariable(ValueDecl *Var, SourceLocation Loc, TryCaptureKind Kind, SourceLocation EllipsisLoc, bool BuildAndDiagnose, QualType &CaptureType, QualType &DeclRefType, const unsigned *const FunctionScopeIndexToStopAt)
Try to capture the given variable.
void PopExpressionEvaluationContext()
llvm::SmallSetVector< CXXRecordDecl *, 16 > AssociatedClassSet
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
DeclRefExpr * BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, const CXXScopeSpec *SS=nullptr)
void FindAssociatedClassesAndNamespaces(SourceLocation InstantiationLoc, ArrayRef< Expr * > Args, AssociatedNamespaceSet &AssociatedNamespaces, AssociatedClassSet &AssociatedClasses)
Find the associated classes and namespaces for argument-dependent lookup for a call with the given se...
const LangOptions & getLangOpts() const
bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, QualType ObjectType, bool AllowBuiltinCreation=false, bool EnteringContext=false)
Performs name lookup for a name that was parsed in the source code, and may contain a C++ scope speci...
AccessResult CheckBaseClassAccess(SourceLocation AccessLoc, QualType Base, QualType Derived, const CXXBasePath &Path, unsigned DiagID, bool ForceCheck=false, bool ForceUnprivileged=false)
Checks access for a hierarchy conversion.
const LangOptions & LangOpts
sema::LambdaScopeInfo * getCurLambda(bool IgnoreNonLambdaCapturingScope=false)
Retrieve the current lambda scope info, if any.
llvm::SmallSetVector< DeclContext *, 16 > AssociatedNamespaceSet
DeclContext * getCurLexicalContext() const
ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, SourceLocation RParenLoc, Expr *Op)
void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, CapturedRegionKind Kind, unsigned NumParams)
ExprResult DefaultLvalueConversion(Expr *E)
bool isVisible(const NamedDecl *D)
Determine whether a declaration is visible to name lookup.
sema::BlockScopeInfo * getCurBlock()
Retrieve the current block, if any.
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
bool IsDerivedFrom(SourceLocation Loc, CXXRecordDecl *Derived, CXXRecordDecl *Base, CXXBasePaths &Paths)
Determine whether the type Derived is a C++ class that is derived from the type Base.
StmtResult ActOnCapturedRegionEnd(Stmt *S)
ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E)
ExprResult ActOnConditionalOp(SourceLocation QuestionLoc, SourceLocation ColonLoc, Expr *CondExpr, Expr *LHSExpr, Expr *RHSExpr)
ActOnConditionalOp - Parse a ?
ExprResult PerformImplicitConversion(Expr *From, QualType ToType, const ImplicitConversionSequence &ICS, AssignmentAction Action, CheckedConversionKind CCK=CheckedConversionKind::Implicit)
PerformImplicitConversion - Perform an implicit conversion of the expression From to the type ToType ...
bool isCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind=CompleteTypeKind::Default)
void setFunctionHasBranchProtectedScope()
std::pair< StringRef, QualType > CapturedParamNameType
ParsedType getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec *SS=nullptr, bool isClassName=false, bool HasTrailingDot=false, ParsedType ObjectType=nullptr, bool IsCtorOrDtorName=false, bool WantNontrivialTypeSourceInfo=false, bool IsClassTemplateDeductionContext=true, ImplicitTypenameContext AllowImplicitTypename=ImplicitTypenameContext::No, IdentifierInfo **CorrectedII=nullptr)
If the identifier refers to a type name within this scope, return the declaration of that type.
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
@ PotentiallyEvaluated
The current expression is potentially evaluated at run time, which means that code may be generated t...
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
Scope * TUScope
Translation Unit Scope - useful to Objective-C actions that need to lookup file scope declarations in...
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
void DiscardCleanupsInEvaluationContext()
ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, bool ForFoldExpression=false)
ExprResult ActOnIntegerConstant(SourceLocation Loc, int64_t Val)
MemberExpr * BuildMemberExpr(Expr *Base, bool IsArrow, SourceLocation OpLoc, NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl, bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo, QualType Ty, ExprValueKind VK, ExprObjectKind OK, const TemplateArgumentListInfo *TemplateArgs=nullptr)
void ActOnUninitializedDecl(Decl *dcl)
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)
AddInitializerToDecl - Adds the initializer Init to the declaration dcl.
SemaDiagnosticBuilder targetDiag(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD=nullptr)
sema::CapturedRegionScopeInfo * getCurCapturedRegion()
Retrieve the current captured region, if any.
bool LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation=false, bool ForceNoCPlusPlus=false)
Perform unqualified name lookup starting from a given scope.
static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo=nullptr)
StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef< Stmt * > Elts, bool isStmtExpr)
FullExprArg MakeFullExpr(Expr *Arg)
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
void setBegin(SourceLocation b)
SourceLocation getBegin() const
void setEnd(SourceLocation e)
void Visit(PTR(Stmt) S, ParamTys... P)
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Stmt - This represents one statement.
SourceLocation getEndLoc() const LLVM_READONLY
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) const
StmtClass getStmtClass() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical, bool ProfileLambdaExpr=false) const
Produce a unique representation of the given statement.
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
SourceLocation getBeginLoc() const LLVM_READONLY
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
bool isTLSSupported() const
Whether the target supports thread-local storage.
Represents a declaration of a type.
SourceLocation getBeginLoc() const
Get the begin source location.
A container of type source information.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
QualType getType() const
Return the type wrapped by this type source info.
The base class of the type hierarchy.
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantArrayType() const
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool hasIntegerRepresentation() const
Determine whether this type has an integer representation of some sort, e.g., it is an integer type o...
bool isArithmeticType() const
bool isPointerType() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isEnumeralType() const
bool isScalarType() const
bool isVariableArrayType() const
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
bool isAnyCharacterType() const
Determine whether this type is any of the built-in character types.
bool isNonOverloadPlaceholderType() const
Test for a placeholder type other than Overload; see BuiltinType::isNonOverloadPlaceholderType.
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
RecordDecl * castAsRecordDecl() const
bool isAnyComplexType() const
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
bool isFunctionProtoType() const
bool isOverloadableType() const
Determines whether this is a type for which one can define an overloaded operator.
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
const T * getAsAdjusted() const
Member-template getAsAdjusted<specific type>.
bool isFunctionType() const
bool isStructureOrClassType() const
bool isRealFloatingType() const
Floating point categories.
bool isFloatingType() const
bool isAnyPointerType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
bool isFunctionNoProtoType() const
Represents the declaration of a typedef-name via the 'typedef' type specifier.
Base class for declarations which introduce a typedef-name.
Simple class containing the result of Sema::CorrectTypo.
NamedDecl * getCorrectionDecl() const
Gets the pointer to the declaration of the typo correction.
Expr * getSubExpr() const
static UnresolvedLookupExpr * Create(const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End, bool KnownDependent, bool KnownInstantiationDependent)
void append(iterator I, iterator E)
void addDecl(NamedDecl *D)
A set of unresolved declarations.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
void setType(QualType newType)
VarDecl * getPotentiallyDecomposedVarDecl()
const Expr * getExprStmt() const
Represents a variable declaration or definition.
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
bool isFunctionOrMethodVarDecl() const
Similar to isLocalVarDecl, but excludes variables declared in blocks.
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
TLSKind getTLSKind() const
void setInitStyle(InitializationStyle Style)
InitializationStyle getInitStyle() const
The style of initialization for this declaration.
DefinitionKind isThisDeclarationADefinition(ASTContext &) const
Check whether this declaration is a definition.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
@ CInit
C-style initialization with assignment.
@ CallInit
Call-style initialization (C++98)
bool isStaticDataMember() const
Determines whether this is a static data member.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
bool isFileVarDecl() const
Returns true for file scoped variable declaration.
const Expr * getInit() const
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
@ TLS_None
Not a TLS variable.
@ DeclarationOnly
This declaration is only a declaration.
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
bool isDirectInit() const
Whether the initializer is a direct-initializer (list or call).
StorageDuration getStorageDuration() const
Get the storage duration of this variable, per C++ [basic.stc].
StorageClass getStorageClass() const
Returns the storage class as written in the source.
bool isUsableInConstantExpressions(const ASTContext &C) const
Determine whether this variable's value can be used in a constant expression, according to the releva...
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Retains information about a captured region.
unsigned short OpenMPLevel
unsigned short OpenMPCaptureLevel
Retains information about a function, method, or block that is currently being parsed.
SmallVector< CompoundScopeInfo, 4 > CompoundScopes
The stack of currently active compound statement scopes in the function.
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
Defines the clang::TargetInfo interface.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
bool LE(InterpState &S, CodePtr OpPC)
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
The JSON file list parser is used to communicate input to InstallAPI.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
OpenMPOriginalSharingModifier
OpenMP 6.0 original sharing modifiers.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ OO_None
Not an overloaded operator.
@ NUM_OVERLOADED_OPERATORS
Privates[]
This class represents the 'transparent' clause in the 'pragma omp task' directive.
bool isOpenMPNestingTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a teams directive in the outermost n...
bool isa(CodeGen::Address addr)
bool checkFailClauseParameter(OpenMPClauseKind FailClauseParameter)
Checks if the parameter to the fail clause in "#pragma atomic compare fail" is restricted only to mem...
MutableArrayRef< TemplateParameterList * > MultiTemplateParamsArg
bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target data offload directive.
OpenMPDefaultClauseVariableCategory
OpenMP variable-category for 'default' clause.
@ OMPC_DEFAULT_VC_unknown
bool isOpenMPLoopTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive.
OpenMPDefaultmapClauseModifier
OpenMP modifiers for 'defaultmap' clause.
@ OMPC_DEFAULTMAP_MODIFIER_last
@ OMPC_DEFAULTMAP_MODIFIER_unknown
OpenMPOrderClauseModifier
OpenMP modifiers for 'order' clause.
@ OMPC_ORDER_MODIFIER_unknown
@ OMPC_ORDER_MODIFIER_last
@ Comparison
A comparison.
ExprObjectKind
A further classification of the kind of object referenced by an l-value or x-value.
@ OK_Ordinary
An ordinary object is located at an address in memory.
OpenMPAtClauseKind
OpenMP attributes for 'at' clause.
Expr * AssertSuccess(ExprResult R)
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
@ LCK_This
Capturing the *this object by reference.
OpenMPReductionClauseModifier
OpenMP modifiers for 'reduction' clause.
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
@ OMPC_SCHEDULE_MODIFIER_last
@ OMPC_SCHEDULE_MODIFIER_unknown
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
SmallVector< Attr *, 4 > AttrVec
AttrVec - A vector of Attr, which is how they are stored on the AST.
ActionResult< Decl * > DeclResult
const char * getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
bool isOpenMPPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of private clauses like 'private', 'firstprivate',...
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
@ OMPC_DIST_SCHEDULE_unknown
static constexpr StringRef getOpenMPVariantManglingSeparatorStr()
OpenMP variants are mangled early based on their OpenMP context selector.
OpenMPDoacrossClauseModifier
OpenMP dependence types for 'doacross' clause.
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
static constexpr unsigned NumberOfOMPMapClauseModifiers
Number of allowed map-type-modifiers.
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
OpenMPDynGroupprivateClauseFallbackModifier
@ OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown
MutableArrayRef< Expr * > MultiExprArg
@ SD_Static
Static storage duration.
@ Parameter
The parameter type of a method or function.
@ Result
The result type of a method or function.
ActionResult< ParsedType > TypeResult
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
bool isOpenMPGenericLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive constitutes a 'loop' directive in the outermost nest.
OpenMPBindClauseKind
OpenMP bindings for the 'bind' clause.
const FunctionProtoType * T
OpenMPLastprivateModifier
OpenMP 'lastprivate' clause modifier.
@ OMPC_LASTPRIVATE_unknown
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
bool isOpenMPCanonicalLoopSequenceTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive that applies to a canonical loop...
OpenMPGrainsizeClauseModifier
bool IsXLHSInRHSPart
True if UE has the first form and false if the second.
bool IsPostfixUpdate
True if original value of 'x' must be stored in 'v', not an updated one.
bool isOpenMPCanonicalLoopNestTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive that applies to a canonical loop...
OpenMPNumTasksClauseModifier
OpenMPUseDevicePtrFallbackModifier
OpenMP 6.1 use_device_ptr fallback modifier.
@ OMPC_USE_DEVICE_PTR_FALLBACK_unknown
bool isOpenMPOrderConcurrentNestableDirective(OpenMPDirectiveKind DKind, const LangOptions &LangOpts)
Checks if the specified directive is an order concurrent nestable directive that can be nested within...
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
bool isOpenMPCapturingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive can capture variables.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
bool isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of the composite or combined directives that need loop ...
static constexpr unsigned NumberOfOMPMotionModifiers
Number of allowed motion-modifiers.
OpenMPMotionModifierKind
OpenMP modifier kind for 'to' or 'from' clause.
@ OMPC_MOTION_MODIFIER_unknown
OpenMPDefaultmapClauseKind
OpenMP attributes for 'defaultmap' clause.
@ OMPC_DEFAULTMAP_unknown
OpenMPAllocateClauseModifier
OpenMP modifiers for 'allocate' clause.
bool isOpenMPThreadPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of threadprivate clauses like 'threadprivate',...
OpenMPLinearClauseKind
OpenMP attributes for 'linear' clause.
bool isOpenMPExecutableDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "executable".
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
OpenMPDynGroupprivateClauseModifier
@ OMPC_DYN_GROUPPRIVATE_unknown
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
bool isOpenMPInformationalDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "informational".
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
SmallVector< CXXBaseSpecifier *, 4 > CXXCastPath
A simple array of base specifiers.
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPNumThreadsClauseModifier
@ OMPC_NUMTHREADS_unknown
OpenMPAtomicDefaultMemOrderClauseKind
OpenMP attributes for 'atomic_default_mem_order' clause.
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor
bool IsFailOnly
True if 'v' is updated only when the condition is false (compare capture only).
U cast(CodeGen::Address addr)
OpenMPDeviceClauseModifier
OpenMP modifiers for 'device' clause.
OpaquePtr< QualType > ParsedType
An opaque type for threading parsed type information through the parser.
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
@ OMPC_MAP_MODIFIER_unknown
@ None
No keyword precedes the qualified type name.
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
bool isOpenMPNestingDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a distribute directive in the outerm...
ActionResult< Expr * > ExprResult
OpenMPOrderClauseKind
OpenMP attributes for 'order' clause.
@ Implicit
An implicit conversion.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
ActionResult< Stmt * > StmtResult
OpenMPThreadsetKind
OpenMP modifiers for 'threadset' clause.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
@ NOUR_Unevaluated
This name appears in an unevaluated operand.
int const char * function
unsigned operator()(argument_type DK)
OpenMPDirectiveKind argument_type
Data for list of allocators.
Expr * AllocatorTraits
Allocator traits.
Expr * Allocator
Allocator.
SourceLocation LParenLoc
Locations of '(' and ')' symbols.
Clang specific specialization of the OMPContext to lookup target features.
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
SourceLocation getLoc() const
getLoc - Returns the main location of the declaration name.
DeclarationName getName() const
getName - Returns the embedded declaration name.
void setLoc(SourceLocation L)
setLoc - Sets the main location of the declaration name.
void setName(DeclarationName N)
setName - Sets the embedded declaration name.
SourceLocation getBeginLoc() const
getBeginLoc - Retrieve the location of the first token.
std::string getAsString() const
getAsString - Retrieve the human-readable string for this name.
SourceLocation getEndLoc() const LLVM_READONLY
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.
Extra information about a function prototype.
llvm::SmallVector< Expr *, 4 > PreferTypes
Iterator definition representation.
SourceLocation AssignmentLoc
SourceLocation SecondColonLoc
Helper expressions and declaration for OMPIteratorExpr class for each iteration space.
Expr * CounterUpdate
Updater for the internal counter: ++CounterVD;.
Expr * Upper
Normalized upper bound.
Expr * Update
Update expression for the originally specified iteration variable, calculated as VD = Begin + Counter...
VarDecl * CounterVD
Internal normalized counter.
This structure contains most locations needed for by an OMPVarListClause.
SourceLocation StartLoc
Starting location of the clause (the clause keyword).
SourceLocation LParenLoc
Location of '('.
SourceLocation EndLoc
Ending location of the clause.
std::optional< Expr * > Indirect
The directive with indirect clause.
OpenMPDirectiveKind Kind
The directive kind, begin declare target or declare target.
OMPDeclareTargetDeclAttr::DevTypeTy DT
The 'device_type' as parsed from the clause.
SourceLocation Loc
The directive location.
llvm::DenseMap< NamedDecl *, MapInfo > ExplicitlyMapped
Explicitly listed variables and functions in a 'to' or 'link' clause.
Data structure for iterator expression.
int OriginalSharingModifier
Data used for processing a list of variables in OpenMP clauses.
Data for list of allocators.
Expr * AllocatorTraits
Allocator traits.
SourceLocation LParenLoc
Locations of '(' and ')' symbols.
Expr * Allocator
Allocator.