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);
7366 if (!CalleeFnDecl) {
7371 if ((DRE = dyn_cast<DeclRefExpr>(E)))
7373 if (
auto *ME = dyn_cast<MemberExpr>(E))
7375 else if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
7381 if (VD && !VD->
hasAttr<OMPTargetIndirectCallAttr>()) {
7384 ML->DeclarationMarkedOpenMPIndirectCall(VD);
7393 CalleeFnDecl->
getName().starts_with_insensitive(
"omp_")) {
7396 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7399 if (!CalleeFnDecl->
hasAttr<OMPDeclareVariantAttr>())
7404 CE](StringRef ISATrait) {
7418 while (CalleeFnDecl) {
7419 for (OMPDeclareVariantAttr *A :
7421 Expr *VariantRef = A->getVariantFuncRef();
7423 VariantMatchInfo VMI;
7426 if (!isVariantApplicableInContext(VMI, OMPCtx,
7430 VMIs.push_back(VMI);
7431 Exprs.push_back(VariantRef);
7439 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7459 if (
auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7460 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7462 Context, MemberCall->getImplicitObjectArgument(),
7463 false, SpecializedMethod, Context.BoundMemberTy,
7464 MemberCall->getValueKind(), MemberCall->getObjectKind());
7466 NewCall =
SemaRef.BuildCallExpr(
Scope, BestExpr, LParenLoc, ArgExprs,
7467 RParenLoc, ExecConfig);
7469 if (
CallExpr *NCE = dyn_cast<CallExpr>(NewCall.
get())) {
7470 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7472 CalleeFnType, NewCalleeFnDecl->
getType(),
7483 VMIs.erase(VMIs.begin() + BestIdx);
7484 Exprs.erase(Exprs.begin() + BestIdx);
7485 }
while (!VMIs.empty());
7492std::optional<std::pair<FunctionDecl *, Expr *>>
7496 unsigned NumAppendArgs,
7500 return std::nullopt;
7502 const int VariantId = 1;
7505 Diag(SR.
getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7507 return std::nullopt;
7510 if (
auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7511 ADecl = FTD->getTemplatedDecl();
7514 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7518 return std::nullopt;
7521 auto &&HasMultiVersionAttributes = [](
const FunctionDecl *FD) {
7524 return FD->isMultiVersion() || FD->
hasAttr<TargetAttr>();
7527 if (HasMultiVersionAttributes(FD)) {
7528 Diag(FD->
getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7530 return std::nullopt;
7535 Diag(SR.
getBegin(), diag::warn_omp_declare_variant_after_used)
7540 if (!FD->isThisDeclarationADefinition() && FD->isDefined(
Definition) &&
7542 Diag(SR.
getBegin(), diag::warn_omp_declare_variant_after_emitted)
7547 Diag(SR.
getBegin(), diag::err_omp_function_expected) << VariantId;
7548 return std::nullopt;
7551 auto ShouldDelayChecks = [](
Expr *&E, bool) {
7557 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef,
false) ||
7559 return std::make_pair(FD, VariantRef);
7562 auto HandleNonConstantScoresAndConditions = [
this](
Expr *&E,
7563 bool IsScore) ->
bool {
7569 Diag(E->
getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7577 diag::err_omp_declare_variant_user_condition_not_constant)
7583 return std::nullopt;
7586 if (NumAppendArgs) {
7589 Diag(FD->
getLocation(), diag::err_omp_declare_variant_prototype_required)
7591 return std::nullopt;
7600 TD = dyn_cast_or_null<TypeDecl>(ND);
7603 Diag(SR.
getBegin(), diag::err_omp_interop_type_not_found) << SR;
7604 return std::nullopt;
7609 if (PTy->isVariadic()) {
7610 Diag(FD->
getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7611 return std::nullopt;
7614 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7615 Params.insert(Params.end(), NumAppendArgs, InteropType);
7616 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7617 PTy->getExtProtoInfo());
7625 auto *
Method = dyn_cast<CXXMethodDecl>(FD);
7627 FnPtrType = Context.getMemberPointerType(
7628 AdjustedFnType, std::nullopt,
Method->getParent());
7640 return std::nullopt;
7642 VariantRef = ER.
get();
7644 FnPtrType = Context.getPointerType(AdjustedFnType);
7646 QualType VarianPtrType = Context.getPointerType(VariantRef->
getType());
7650 false, Sema::AllowedExplicit::None,
7656 diag::err_omp_declare_variant_incompat_types)
7660 return std::nullopt;
7662 VariantRefCast =
SemaRef.PerformImplicitConversion(
7666 return std::nullopt;
7670 Expr *PossibleAddrOfVariantRef = VariantRefCast.
get();
7671 if (
auto *UO = dyn_cast<UnaryOperator>(
7673 VariantRefCast = UO->getSubExpr();
7682 return std::nullopt;
7690 return std::nullopt;
7692 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7696 return std::nullopt;
7701 diag::err_omp_declare_variant_same_base_function)
7703 return std::nullopt;
7709 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7712 diag::err_omp_declare_variant_incompat_types)
7713 << NewFD->getType() << FD->
getType() << (NumAppendArgs ? 1 : 0)
7715 return std::nullopt;
7720 else if (NewFD->getType()->isFunctionNoProtoType())
7726 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7728 diag::warn_omp_declare_variant_marked_as_declare_variant)
7731 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->
getRange();
7732 Diag(SR.
getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7733 return std::nullopt;
7736 enum DoesntSupport {
7745 if (
const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7746 if (CXXFD->isVirtual()) {
7749 return std::nullopt;
7755 return std::nullopt;
7761 return std::nullopt;
7765 if (FD->isDeleted()) {
7768 return std::nullopt;
7771 if (FD->isDefaulted()) {
7774 return std::nullopt;
7777 if (FD->isConstexpr()) {
7779 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7780 return std::nullopt;
7784 if (
SemaRef.areMultiversionVariantFunctionsCompatible(
7790 SemaRef.PDiag(diag::err_omp_declare_variant_doesnt_support)),
7792 SemaRef.PDiag(diag::err_omp_declare_variant_diff)
7796 return std::nullopt;
7814 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7815 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7816 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDeviceAddr);
7818 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7819 VariantMatchInfo VMI;
7821 if (!llvm::is_contained(
7822 VMI.ConstructTraits,
7823 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7824 if (!AllAdjustArgs.empty())
7825 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7827 if (!AppendArgs.empty())
7828 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7839 for (
Expr *E : AllAdjustArgs) {
7841 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7842 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7844 if (FD->
getNumParams() > PVD->getFunctionScopeIndex() &&
7848 if (!AdjustVars.insert(CanonPVD).second) {
7849 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7858 Diag(E->
getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7867 for (
Expr *E : AdjustArgsNeedDeviceAddr) {
7869 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7870 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
7873 diag::err_omp_non_by_ref_need_device_addr_modifier_argument);
7879 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7881 const_cast<Expr **
>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7882 const_cast<Expr **
>(AdjustArgsNeedDevicePtr.data()),
7883 AdjustArgsNeedDevicePtr.size(),
7884 const_cast<Expr **
>(AdjustArgsNeedDeviceAddr.data()),
7885 AdjustArgsNeedDeviceAddr.size(),
7886 const_cast<OMPInteropInfo *
>(AppendArgs.data()), AppendArgs.size(), SR);
7892 auto *CS = dyn_cast<CapturedStmt>(AStmt);
7893 assert(CS &&
"Captured statement expected");
7902 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7924 return OMPParallelDirective::Create(
7931struct LoopIterationSpace final {
7934 bool IsStrictCompare =
false;
7936 Expr *PreCond =
nullptr;
7939 Expr *NumIterations =
nullptr;
7941 Expr *CounterVar =
nullptr;
7943 Expr *PrivateCounterVar =
nullptr;
7945 Expr *CounterInit =
nullptr;
7948 Expr *CounterStep =
nullptr;
7950 bool Subtract =
false;
7960 Expr *MinValue =
nullptr;
7964 Expr *MaxValue =
nullptr;
7966 bool IsNonRectangularLB =
false;
7968 bool IsNonRectangularUB =
false;
7971 unsigned LoopDependentIdx = 0;
7975 Expr *FinalCondition =
nullptr;
7982 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7983 VarDecl *ForbiddenVar =
nullptr;
7987 explicit ForSubExprChecker(
7988 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
7989 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
7992 ShouldVisitImplicitCode =
true;
7995 bool VisitDeclRefExpr(DeclRefExpr *E)
override {
8000 if (
V->getType()->isReferenceType()) {
8001 VarDecl *VD =
V->getDefinition();
8004 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(I);
8010 Decl *Canon =
V->getCanonicalDecl();
8011 if (CollapsedLoopVarDecls.contains(Canon)) {
8020 VarDecl *getForbiddenVar()
const {
return ForbiddenVar; }
8021 SourceRange getErrRange()
const {
return ErrLoc; }
8027class OpenMPIterationSpaceChecker {
8031 bool SupportsNonRectangular;
8035 SourceLocation DefaultLoc;
8037 SourceLocation ConditionLoc;
8039 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
8041 SourceRange InitSrcRange;
8043 SourceRange ConditionSrcRange;
8045 SourceRange IncrementSrcRange;
8047 ValueDecl *LCDecl =
nullptr;
8049 Expr *LCRef =
nullptr;
8055 Expr *Step =
nullptr;
8062 std::optional<bool> TestIsLessOp;
8064 bool TestIsStrictOp =
false;
8066 bool SubtractStep =
false;
8068 const ValueDecl *DepDecl =
nullptr;
8071 std::optional<unsigned> InitDependOnLC;
8074 std::optional<unsigned> CondDependOnLC;
8076 std::optional<unsigned> doesDependOnLoopCounter(
const Stmt *S,
8077 bool IsInitializer);
8083 OpenMPIterationSpaceChecker(
8084 Sema &SemaRef,
bool SupportsNonRectangular, DSAStackTy &Stack,
8085 SourceLocation DefaultLoc,
8086 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls)
8087 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
8088 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
8089 CollapsedLoopVarDecls(CollapsedLoopDecls) {}
8092 bool checkAndSetInit(Stmt *S,
bool EmitDiags =
true);
8095 bool checkAndSetCond(Expr *S);
8098 bool checkAndSetInc(Expr *S);
8100 ValueDecl *getLoopDecl()
const {
return LCDecl; }
8102 Expr *getLoopDeclRefExpr()
const {
return LCRef; }
8104 SourceRange getInitSrcRange()
const {
return InitSrcRange; }
8106 SourceRange getConditionSrcRange()
const {
return ConditionSrcRange; }
8108 SourceRange getIncrementSrcRange()
const {
return IncrementSrcRange; }
8110 bool shouldSubtractStep()
const {
return SubtractStep; }
8112 bool isStrictTestOp()
const {
return TestIsStrictOp; }
8114 Expr *buildNumIterations(
8115 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces,
bool LimitedType,
8116 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
8119 buildPreCond(Scope *S, Expr *
Cond,
8120 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
8123 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8124 DSAStackTy &DSA)
const;
8127 Expr *buildPrivateCounterVar()
const;
8131 Expr *buildCounterStep()
const;
8135 buildOrderedLoopData(Scope *S, Expr *Counter,
8136 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8137 SourceLocation Loc, Expr *Inc =
nullptr,
8140 std::pair<Expr *, Expr *> buildMinMaxValues(
8141 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
8143 Expr *buildFinalCondition(Scope *S)
const;
8145 bool dependent()
const;
8147 bool doesInitDependOnLC()
const {
return InitDependOnLC.has_value(); }
8149 bool doesCondDependOnLC()
const {
return CondDependOnLC.has_value(); }
8151 unsigned getLoopDependentIdx()
const {
8152 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
8158 bool checkAndSetIncRHS(Expr *RHS);
8160 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
8163 bool setUB(Expr *NewUB, std::optional<bool> LessOp,
bool StrictOp,
8164 SourceRange SR, SourceLocation SL);
8166 bool setStep(Expr *NewStep,
bool Subtract);
8169bool OpenMPIterationSpaceChecker::dependent()
const {
8171 assert(!LB && !UB && !Step);
8179bool OpenMPIterationSpaceChecker::setLCDeclAndLB(
ValueDecl *NewLCDecl,
8181 Expr *NewLB,
bool EmitDiags) {
8183 assert(LCDecl ==
nullptr && LB ==
nullptr && LCRef ==
nullptr &&
8184 UB ==
nullptr && Step ==
nullptr && !TestIsLessOp && !TestIsStrictOp);
8188 LCRef = NewLCRefExpr;
8189 if (
auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
8191 if ((Ctor->isCopyOrMoveConstructor() ||
8192 Ctor->isConvertingConstructor(
false)) &&
8193 CE->getNumArgs() > 0 && CE->getArg(0) !=
nullptr)
8197 InitDependOnLC = doesDependOnLoopCounter(LB,
true);
8201bool OpenMPIterationSpaceChecker::setUB(
Expr *NewUB, std::optional<bool> LessOp,
8205 assert(LCDecl !=
nullptr && LB !=
nullptr && UB ==
nullptr &&
8206 Step ==
nullptr && !TestIsLessOp && !TestIsStrictOp);
8211 TestIsLessOp = LessOp;
8212 TestIsStrictOp = StrictOp;
8213 ConditionSrcRange = SR;
8215 CondDependOnLC = doesDependOnLoopCounter(UB,
false);
8219bool OpenMPIterationSpaceChecker::setStep(
Expr *NewStep,
bool Subtract) {
8221 assert(LCDecl !=
nullptr && LB !=
nullptr && Step ==
nullptr);
8231 NewStep = Val.
get();
8244 std::optional<llvm::APSInt>
Result =
8255 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8256 if (UB && (IsConstZero ||
8257 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8258 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8260 diag::err_omp_loop_incr_not_compatible)
8262 SemaRef.
Diag(ConditionLoc,
8263 diag::note_omp_loop_cond_requires_compatible_incr)
8264 << *TestIsLessOp << ConditionSrcRange;
8267 if (*TestIsLessOp == Subtract) {
8271 Subtract = !Subtract;
8276 SubtractStep = Subtract;
8283class LoopCounterRefChecker final
8287 const ValueDecl *CurLCDecl =
nullptr;
8288 const ValueDecl *DepDecl =
nullptr;
8289 const ValueDecl *PrevDepDecl =
nullptr;
8290 bool IsInitializer =
true;
8291 bool SupportsNonRectangular;
8292 unsigned BaseLoopId = 0;
8293 bool checkDecl(
const Expr *E,
const ValueDecl *VD) {
8295 SemaRef.Diag(E->
getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8296 << (IsInitializer ? 0 : 1);
8299 const auto &&
Data = Stack.isLoopControlVariable(VD);
8304 SmallString<128> Name;
8305 llvm::raw_svector_ostream
OS(Name);
8309 diag::err_omp_wrong_dependency_iterator_type)
8311 SemaRef.Diag(VD->
getLocation(), diag::note_previous_decl) << VD;
8314 if (
Data.first && !SupportsNonRectangular) {
8315 SemaRef.Diag(E->
getExprLoc(), diag::err_omp_invariant_dependency);
8319 (DepDecl || (PrevDepDecl &&
8321 if (!DepDecl && PrevDepDecl)
8322 DepDecl = PrevDepDecl;
8323 SmallString<128> Name;
8324 llvm::raw_svector_ostream
OS(Name);
8328 diag::err_omp_invariant_or_linear_dependency)
8334 BaseLoopId =
Data.first;
8340 bool VisitDeclRefExpr(
const DeclRefExpr *E) {
8341 const ValueDecl *VD = E->
getDecl();
8343 return checkDecl(E, VD);
8346 bool VisitMemberExpr(
const MemberExpr *E) {
8350 return checkDecl(E, VD);
8354 bool VisitStmt(
const Stmt *S) {
8356 for (
const Stmt *Child : S->
children())
8357 Res = (Child && Visit(Child)) || Res;
8360 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8361 const ValueDecl *CurLCDecl,
bool IsInitializer,
8362 const ValueDecl *PrevDepDecl =
nullptr,
8363 bool SupportsNonRectangular =
true)
8364 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8365 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8366 SupportsNonRectangular(SupportsNonRectangular) {}
8367 unsigned getBaseLoopId()
const {
8368 assert(CurLCDecl &&
"Expected loop dependency.");
8371 const ValueDecl *getDepDecl()
const {
8372 assert(CurLCDecl &&
"Expected loop dependency.");
8378std::optional<unsigned>
8379OpenMPIterationSpaceChecker::doesDependOnLoopCounter(
const Stmt *S,
8380 bool IsInitializer) {
8382 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8383 DepDecl, SupportsNonRectangular);
8384 if (LoopStmtChecker.Visit(S)) {
8385 DepDecl = LoopStmtChecker.getDepDecl();
8386 return LoopStmtChecker.getBaseLoopId();
8388 return std::nullopt;
8391bool OpenMPIterationSpaceChecker::checkAndSetInit(
Stmt *S,
bool EmitDiags) {
8402 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8406 if (
auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8407 if (!ExprTemp->cleanupsHaveSideEffects())
8408 S = ExprTemp->getSubExpr();
8410 if (!CollapsedLoopVarDecls.empty()) {
8411 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8412 if (!FSEC.TraverseStmt(S)) {
8414 SemaRef.Diag(
Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8415 <<
Range.getEnd() << 0 << FSEC.getForbiddenVar();
8421 if (
Expr *E = dyn_cast<Expr>(S))
8423 if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8424 if (BO->getOpcode() == BO_Assign) {
8426 if (
auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8427 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->
getDecl()))
8429 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8431 return setLCDeclAndLB(DRE->
getDecl(), DRE, BO->getRHS(), EmitDiags);
8433 if (
auto *ME = dyn_cast<MemberExpr>(LHS)) {
8434 if (ME->isArrow() &&
8436 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8440 }
else if (
auto *DS = dyn_cast<DeclStmt>(S)) {
8441 if (DS->isSingleDecl()) {
8442 if (
auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8443 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8447 diag::ext_omp_loop_not_canonical_init)
8449 return setLCDeclAndLB(
8452 Var->getType().getNonReferenceType(),
8454 Var->getInit(), EmitDiags);
8458 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8459 if (CE->getOperator() == OO_Equal) {
8460 Expr *LHS = CE->getArg(0);
8461 if (
auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8462 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->
getDecl()))
8464 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8466 return setLCDeclAndLB(DRE->
getDecl(), DRE, CE->getArg(1), EmitDiags);
8468 if (
auto *ME = dyn_cast<MemberExpr>(LHS)) {
8469 if (ME->isArrow() &&
8471 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8477 if (dependent() || SemaRef.CurContext->isDependentContext())
8480 SemaRef.Diag(S->
getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8492 if (
const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8494 if ((Ctor->isCopyOrMoveConstructor() ||
8495 Ctor->isConvertingConstructor(
false)) &&
8496 CE->getNumArgs() > 0 && CE->getArg(0) !=
nullptr)
8498 if (
const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8499 if (
const auto *VD = dyn_cast<VarDecl>(DRE->
getDecl()))
8502 if (
const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8503 if (ME->isArrow() &&
isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8508bool OpenMPIterationSpaceChecker::checkAndSetCond(
Expr *S) {
8515 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8517 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8518 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8524 if (!CollapsedLoopVarDecls.empty()) {
8525 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8526 if (!FSEC.TraverseStmt(S)) {
8528 SemaRef.Diag(
Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8529 <<
Range.getEnd() << 1 << FSEC.getForbiddenVar();
8535 auto &&CheckAndSetCond =
8540 if (getInitLCDecl(LHS) == LCDecl)
8541 return setUB(
const_cast<Expr *
>(RHS),
8542 (Opcode == BO_LT || Opcode == BO_LE),
8543 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8544 if (getInitLCDecl(RHS) == LCDecl)
8545 return setUB(
const_cast<Expr *
>(LHS),
8546 (Opcode == BO_GT || Opcode == BO_GE),
8547 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8548 }
else if (IneqCondIsCanonical && Opcode == BO_NE) {
8549 return setUB(
const_cast<Expr *
>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8553 return std::nullopt;
8555 std::optional<bool> Res;
8556 if (
auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8559 RBO->getOperatorLoc());
8560 }
else if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8561 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8562 BO->getSourceRange(), BO->getOperatorLoc());
8563 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8564 if (CE->getNumArgs() == 2) {
8565 Res = CheckAndSetCond(
8567 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8572 if (dependent() || SemaRef.CurContext->isDependentContext())
8574 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8575 << (IneqCondIsCanonical ? 1 : 0) << S->
getSourceRange() << LCDecl;
8579bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(
Expr *RHS) {
8586 if (
auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8587 if (BO->isAdditiveOp()) {
8588 bool IsAdd = BO->getOpcode() == BO_Add;
8589 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8590 return setStep(BO->getRHS(), !IsAdd);
8591 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8592 return setStep(BO->getLHS(),
false);
8594 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8595 bool IsAdd = CE->getOperator() == OO_Plus;
8596 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8597 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8598 return setStep(CE->getArg(1), !IsAdd);
8599 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8600 return setStep(CE->getArg(0),
false);
8603 if (dependent() || SemaRef.CurContext->isDependentContext())
8605 SemaRef.Diag(RHS->
getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8610bool OpenMPIterationSpaceChecker::checkAndSetInc(
Expr *S) {
8625 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8628 if (
auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8629 if (!ExprTemp->cleanupsHaveSideEffects())
8630 S = ExprTemp->getSubExpr();
8632 if (!CollapsedLoopVarDecls.empty()) {
8633 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8634 if (!FSEC.TraverseStmt(S)) {
8636 SemaRef.Diag(
Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8637 <<
Range.getEnd() << 2 << FSEC.getForbiddenVar();
8644 if (
auto *UO = dyn_cast<UnaryOperator>(S)) {
8645 if (UO->isIncrementDecrementOp() &&
8646 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8647 return setStep(SemaRef
8648 .ActOnIntegerConstant(UO->getBeginLoc(),
8649 (UO->isDecrementOp() ? -1 : 1))
8652 }
else if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8653 switch (BO->getOpcode()) {
8656 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8657 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8660 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8661 return checkAndSetIncRHS(BO->getRHS());
8666 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8667 switch (CE->getOperator()) {
8670 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8671 return setStep(SemaRef
8672 .ActOnIntegerConstant(
8674 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8680 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8681 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8684 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8685 return checkAndSetIncRHS(CE->getArg(1));
8691 if (dependent() || SemaRef.CurContext->isDependentContext())
8693 SemaRef.Diag(S->
getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8700 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8701 StringRef Name =
".capture_expr.") {
8709 auto I = Captures.find(
Capture);
8710 if (I != Captures.end())
8723 bool TestIsStrictOp,
bool RoundToStep,
8724 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8725 std::optional<unsigned> InitDependOnLC,
8726 std::optional<unsigned> CondDependOnLC) {
8727 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures,
".new_step");
8730 llvm::APSInt LRes, SRes;
8731 bool IsLowerConst =
false, IsStepConst =
false;
8732 if (std::optional<llvm::APSInt> Res =
8735 IsLowerConst =
true;
8737 if (std::optional<llvm::APSInt> Res =
8742 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8743 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8744 (TestIsStrictOp && LRes.isStrictlyPositive()));
8745 bool NeedToReorganize =
false;
8747 if (!NoNeedToConvert && IsLowerConst &&
8748 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8749 NoNeedToConvert =
true;
8751 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8752 ? LRes.getBitWidth()
8753 : SRes.getBitWidth();
8754 LRes = LRes.extend(BW + 1);
8755 LRes.setIsSigned(
true);
8756 SRes = SRes.extend(BW + 1);
8757 SRes.setIsSigned(
true);
8759 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8760 LRes = LRes.trunc(BW);
8762 if (TestIsStrictOp) {
8763 unsigned BW = LRes.getBitWidth();
8764 LRes = LRes.extend(BW + 1);
8765 LRes.setIsSigned(
true);
8768 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8770 LRes = LRes.trunc(BW);
8772 NeedToReorganize = NoNeedToConvert;
8775 bool IsUpperConst =
false;
8776 if (std::optional<llvm::APSInt> Res =
8779 IsUpperConst =
true;
8781 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8782 (!RoundToStep || IsStepConst)) {
8783 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8784 : URes.getBitWidth();
8785 LRes = LRes.extend(BW + 1);
8786 LRes.setIsSigned(
true);
8787 URes = URes.extend(BW + 1);
8788 URes.setIsSigned(
true);
8790 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8791 NeedToReorganize = NoNeedToConvert;
8796 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8802 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8805 LowerSize > UpperSize ? LowerSize : UpperSize, 0);
8816 if (!Lower || !Upper || NewStep.
isInvalid())
8823 if (TestIsStrictOp && InitDependOnLC.has_value() &&
8824 !CondDependOnLC.has_value()) {
8825 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8838 if (NeedToReorganize) {
8852 S, DefaultLoc, BO_Add, Diff.
get(),
8862 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.
get());
8866 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8882 S, DefaultLoc, BO_Sub, Diff.
get(),
8902 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Div, Diff.
get(), NewStep.
get());
8910Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8912 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
8921 if (InitDependOnLC) {
8922 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8923 if (!IS.MinValue || !IS.MaxValue)
8932 IS.CounterVar, MinValue.
get());
8937 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.
get(), LBVal);
8952 IS.CounterVar, MaxValue.
get());
8957 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.
get(), LBVal);
8966 tryBuildCapture(SemaRef, LBMinVal.
get(), Captures,
".lb_min").get();
8968 tryBuildCapture(SemaRef, LBMaxVal.
get(), Captures,
".lb_max").get();
8969 if (!LBMin || !LBMax)
8973 SemaRef.
BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8977 tryBuildCapture(SemaRef, MinLessMaxRes.
get(), Captures,
".min_less_max")
8981 if (*TestIsLessOp) {
8985 MinLessMax, LBMin, LBMax);
8988 LBVal = MinLB.
get();
8993 MinLessMax, LBMax, LBMin);
8996 LBVal = MaxLB.
get();
9000 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
9003 LBVal = LBMinVal.
get();
9007 if (CondDependOnLC) {
9008 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
9009 if (!IS.MinValue || !IS.MaxValue)
9018 IS.CounterVar, MinValue.
get());
9023 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.
get(), UBVal);
9038 IS.CounterVar, MaxValue.
get());
9043 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.
get(), UBVal);
9052 tryBuildCapture(SemaRef, UBMinVal.
get(), Captures,
".ub_min").get();
9054 tryBuildCapture(SemaRef, UBMaxVal.
get(), Captures,
".ub_max").get();
9055 if (!UBMin || !UBMax)
9059 SemaRef.
BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
9062 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.
get(),
9063 Captures,
".min_greater_max")
9067 if (*TestIsLessOp) {
9071 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
9074 UBVal = MaxUB.
get();
9079 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
9082 UBVal = MinUB.
get();
9085 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
9086 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
9087 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures,
".upper").get();
9088 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures,
".lower").get();
9089 if (!Upper || !Lower)
9093 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType, TestIsStrictOp,
9094 true, Captures, InitDependOnLC, CondDependOnLC);
9102 C.getTypeSize(
Type) >
C.getTypeSize(VarType);
9105 UseVarType ?
C.getTypeSize(VarType) :
C.getTypeSize(
Type);
9108 Type =
C.getIntTypeForBitwidth(NewSize, IsSigned);
9118 unsigned NewSize = (
C.getTypeSize(
Type) > 32) ? 64 : 32;
9119 if (NewSize !=
C.getTypeSize(
Type)) {
9120 if (NewSize <
C.getTypeSize(
Type)) {
9121 assert(NewSize == 64 &&
"incorrect loop var size");
9122 SemaRef.
Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
9123 << InitSrcRange << ConditionSrcRange;
9125 QualType NewType =
C.getIntTypeForBitwidth(
9127 C.getTypeSize(
Type) < NewSize);
9141std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
9142 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
9146 return std::make_pair(
nullptr,
nullptr);
9149 Expr *MinExpr =
nullptr;
9150 Expr *MaxExpr =
nullptr;
9151 Expr *LBExpr = *TestIsLessOp ? LB : UB;
9152 Expr *UBExpr = *TestIsLessOp ? UB : LB;
9154 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
9156 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
9158 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
9160 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
9161 if (!Upper || !Lower)
9162 return std::make_pair(
nullptr,
nullptr);
9173 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType, TestIsStrictOp,
9174 false, Captures, InitDependOnLC, CondDependOnLC);
9177 return std::make_pair(
nullptr,
nullptr);
9183 return std::make_pair(
nullptr,
nullptr);
9185 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures,
".new_step");
9187 return std::make_pair(
nullptr,
nullptr);
9188 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Mul, Diff.
get(), NewStep.
get());
9190 return std::make_pair(
nullptr,
nullptr);
9195 return std::make_pair(
nullptr,
nullptr);
9207 return std::make_pair(
nullptr,
nullptr);
9209 if (*TestIsLessOp) {
9213 S, DefaultLoc, BO_Add,
9217 return std::make_pair(
nullptr,
nullptr);
9222 S, DefaultLoc, BO_Sub,
9226 return std::make_pair(
nullptr,
nullptr);
9235 return std::make_pair(
nullptr,
nullptr);
9240 return std::make_pair(
nullptr,
nullptr);
9243 MaxExpr = Diff.
get();
9245 MinExpr = Diff.
get();
9247 return std::make_pair(MinExpr, MaxExpr);
9250Expr *OpenMPIterationSpaceChecker::buildFinalCondition(
Scope *S)
const {
9251 if (InitDependOnLC || CondDependOnLC)
9256Expr *OpenMPIterationSpaceChecker::buildPreCond(
9258 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
9263 if (CondDependOnLC || InitDependOnLC)
9274 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
9275 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
9281 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
9282 : (TestIsStrictOp ? BO_GT : BO_GE),
9283 NewLB.
get(), NewUB.
get());
9298DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9299 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9300 DSAStackTy &DSA)
const {
9301 auto *VD = dyn_cast<VarDecl>(LCDecl);
9306 const DSAStackTy::DSAVarData
Data =
9307 DSA.getTopDSA(LCDecl,
false);
9311 Captures.insert(std::make_pair(LCRef, Ref));
9317Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar()
const {
9334Expr *OpenMPIterationSpaceChecker::buildCounterInit()
const {
return LB; }
9337Expr *OpenMPIterationSpaceChecker::buildCounterStep()
const {
return Step; }
9339Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9341 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
SourceLocation Loc,
9347 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9348 "Expected only + or - operations for depend clauses.");
9360 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9362 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9363 if (!Upper || !Lower)
9367 calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9369 Captures, InitDependOnLC, CondDependOnLC);
9379 assert(
getLangOpts().OpenMP &&
"OpenMP is not active.");
9380 assert(
Init &&
"Expected loop in canonical form.");
9381 unsigned AssociatedLoops =
DSAStack->getAssociatedLoops();
9388 OpenMPIterationSpaceChecker ISC(
SemaRef,
true,
9390 if (!ISC.checkAndSetInit(
Init,
false)) {
9392 auto *VD = dyn_cast<VarDecl>(D);
9403 DSAStack->addLoopControlVariable(D, VD);
9405 if (LD != D->getCanonicalDecl()) {
9406 DSAStack->resetPossibleLoopCounter();
9407 if (
auto *Var = dyn_cast_or_null<VarDecl>(LD))
9420 DSAStackTy::DSAVarData DVar =
9424 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9427 ? (
DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9430 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9433 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9435 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9437 IsOpenMPTaskloopDirective(DKind) ||
9440 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9441 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9443 Diag(
Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9445 << getOpenMPDirectiveName(DKind, OMPVersion)
9447 if (DVar.RefExpr ==
nullptr)
9448 DVar.CKind = PredeterminedCKind;
9450 }
else if (LoopDeclRefExpr) {
9455 if (DVar.CKind == OMPC_unknown)
9456 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9460 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9465class OMPDoacrossKind {
9468 return C->getDependenceType() == OMPC_DOACROSS_source ||
9469 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9472 return C->getDependenceType() == OMPC_DOACROSS_sink;
9474 bool isSinkIter(
const OMPDoacrossClause *
C) {
9475 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9483 unsigned CurrentNestedLoopCount,
unsigned NestedLoopCount,
9484 unsigned TotalNestedLoopCount,
Expr *CollapseLoopCountExpr,
9485 Expr *OrderedLoopCountExpr,
9488 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9489 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls) {
9494 if (
auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9495 S = CanonLoop->getLoopStmt();
9496 auto *For = dyn_cast_or_null<ForStmt>(S);
9497 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9499 if (!For && (SemaRef.
LangOpts.OpenMP <= 45 || !CXXFor)) {
9500 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
9502 << (CollapseLoopCountExpr !=
nullptr || OrderedLoopCountExpr !=
nullptr)
9503 << getOpenMPDirectiveName(DKind, OMPVersion) << TotalNestedLoopCount
9504 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9505 if (TotalNestedLoopCount > 1) {
9506 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9507 SemaRef.
Diag(DSA.getConstructLoc(),
9508 diag::note_omp_collapse_ordered_expr)
9511 else if (CollapseLoopCountExpr)
9513 diag::note_omp_collapse_ordered_expr)
9515 else if (OrderedLoopCountExpr)
9517 diag::note_omp_collapse_ordered_expr)
9522 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9528 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9529 For ? For->getForLoc() : CXXFor->getForLoc(),
9530 CollapsedLoopVarDecls);
9533 Stmt *
Init = For ? For->getInit() : CXXFor->getBeginStmt();
9534 if (ISC.checkAndSetInit(
Init))
9537 bool HasErrors =
false;
9540 if (
ValueDecl *LCDecl = ISC.getLoopDecl()) {
9550 SemaRef.
Diag(
Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9564 VarsWithImplicitDSA.erase(LCDecl);
9568 "DSA for non-loop vars");
9571 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9574 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9581 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9582 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9583 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9584 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9591 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9592 ISC.buildCounterVar(Captures, DSA);
9593 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9594 ISC.buildPrivateCounterVar();
9595 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9596 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9597 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9598 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9599 ISC.getConditionSrcRange();
9600 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9601 ISC.getIncrementSrcRange();
9602 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9603 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9604 ISC.isStrictTestOp();
9605 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9606 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9607 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9608 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9609 ISC.buildFinalCondition(DSA.getCurScope());
9610 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9611 ISC.doesInitDependOnLC();
9612 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9613 ISC.doesCondDependOnLC();
9614 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9615 ISC.getLoopDependentIdx();
9618 (ResultIterSpaces[CurrentNestedLoopCount].PreCond ==
nullptr ||
9619 ResultIterSpaces[CurrentNestedLoopCount].NumIterations ==
nullptr ||
9620 ResultIterSpaces[CurrentNestedLoopCount].CounterVar ==
nullptr ||
9621 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar ==
nullptr ||
9622 ResultIterSpaces[CurrentNestedLoopCount].CounterInit ==
nullptr ||
9623 ResultIterSpaces[CurrentNestedLoopCount].CounterStep ==
nullptr);
9624 if (!HasErrors && DSA.isOrderedRegion()) {
9625 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9626 if (CurrentNestedLoopCount <
9627 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9628 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9629 CurrentNestedLoopCount,
9630 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9631 DSA.getOrderedRegionParam().second->setLoopCounter(
9632 CurrentNestedLoopCount,
9633 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9636 for (
auto &Pair : DSA.getDoacrossDependClauses()) {
9637 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9638 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9640 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9641 if (CurrentNestedLoopCount >= NumLoops) {
9645 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9646 Pair.second.size() <= CurrentNestedLoopCount) {
9648 DependC->setLoopData(CurrentNestedLoopCount,
nullptr);
9651 OMPDoacrossKind ODK;
9652 if (DoacrossC && ODK.isSink(DoacrossC) &&
9653 Pair.second.size() <= CurrentNestedLoopCount) {
9655 DoacrossC->setLoopData(CurrentNestedLoopCount,
nullptr);
9660 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9661 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9662 (DoacrossC && ODK.isSource(DoacrossC)))
9663 CntValue = ISC.buildOrderedLoopData(
9665 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9667 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9670 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9678 CntValue = ISC.buildOrderedLoopData(
9680 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9681 DepLoc, Inc, clang::OO_Minus);
9683 CntValue = ISC.buildOrderedLoopData(
9685 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9686 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9687 Pair.second[CurrentNestedLoopCount].second);
9689 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9691 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9702 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9706 : tryBuildCapture(SemaRef, Start.
get(), Captures);
9727 bool IsNonRectangularLB,
9728 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures =
nullptr) {
9737 NewStep = tryBuildCapture(SemaRef, Step.
get(), *Captures);
9752 if (Captures && !IsNonRectangularLB)
9753 NewStart = tryBuildCapture(SemaRef, Start.
get(), *Captures);
9762 Update.get()->getType()->isOverloadableType()) {
9769 SemaRef.
BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9770 VarRef.
get(), SavedUpdate.
get());
9781 NewStart.
get(), SavedUpdate.
get());
9806 unsigned HasBits =
C.getTypeSize(OldType);
9807 if (HasBits >= Bits)
9810 QualType NewType =
C.getIntTypeForBitwidth(Bits,
true);
9820 if (std::optional<llvm::APSInt> Result =
9822 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9829 if (!PreInits.empty()) {
9850 if (
auto *CS = dyn_cast<CompoundStmt>(Item))
9859 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9860 if (!Captures.empty()) {
9862 for (
const auto &Pair : Captures)
9863 PreInits.push_back(Pair.second->getDecl());
9871 if (PreInits.empty())
9875 for (
Stmt *S : PreInits)
9882 Expr *PostUpdate =
nullptr;
9883 if (!PostUpdates.empty()) {
9884 for (
Expr *E : PostUpdates) {
9890 PostUpdate = PostUpdate
9904 int NestingDepth = 0;
9905 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
9927 if (NestingDepth > 0)
9938 Expr *OrderedLoopCountExpr,
Stmt *AStmt,
Sema &SemaRef,
9941 OMPLoopBasedDirective::HelperExprs &Built) {
9945 if ((CollapseLoopCountExpr && CollapseLoopCountExpr->
containsErrors()) ||
9946 (OrderedLoopCountExpr && OrderedLoopCountExpr->
containsErrors()))
9949 unsigned NestedLoopCount = 1;
9950 bool SupportsNonPerfectlyNested = (SemaRef.
LangOpts.OpenMP >= 50) &&
9954 if (CollapseLoopCountExpr) {
9959 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9968 unsigned OrderedLoopCount = 1;
9969 if (OrderedLoopCountExpr) {
9975 llvm::APSInt Result = EVResult.
Val.
getInt();
9976 if (Result.getLimitedValue() < NestedLoopCount) {
9978 diag::err_omp_wrong_ordered_loop_count)
9981 diag::note_collapse_loop_count)
9984 OrderedLoopCount = Result.getLimitedValue();
9992 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9993 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9995 if (!OMPLoopBasedDirective::doForAllLoops(
9998 SupportsNonPerfectlyNested, NumLoops,
9999 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
10000 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
10001 &IterSpaces, &Captures,
10002 &CollapsedLoopVarDecls](
unsigned Cnt,
Stmt *CurStmt) {
10004 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
10005 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
10006 VarsWithImplicitDSA, IterSpaces, Captures,
10007 CollapsedLoopVarDecls))
10009 if (Cnt > 0 && Cnt >= NestedLoopCount &&
10010 IterSpaces[Cnt].CounterVar) {
10014 Captures[DRE] = DRE;
10020 Stmt *DependentPreInits = Transform->getPreInits();
10021 if (!DependentPreInits)
10028 for (
Stmt *S : Constituents) {
10029 if (
auto *DC = dyn_cast<DeclStmt>(S)) {
10030 for (
Decl *
C : DC->decls()) {
10033 SemaRef, D, D->getType().getNonReferenceType(),
10036 Captures[Ref] = Ref;
10043 Built.clear(NestedLoopCount);
10046 return NestedLoopCount;
10079 auto PreCond =
ExprResult(IterSpaces[0].PreCond);
10080 Expr *N0 = IterSpaces[0].NumIterations;
10099 return NestedLoopCount;
10102 bool AllCountsNeedLessThan32Bits =
C.getTypeSize(N0->
getType()) < 32;
10104 Scope *CurScope = DSA.getCurScope();
10105 for (
unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
10106 if (PreCond.isUsable()) {
10108 SemaRef.
BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
10109 PreCond.get(), IterSpaces[Cnt].PreCond);
10111 Expr *N = IterSpaces[Cnt].NumIterations;
10113 AllCountsNeedLessThan32Bits &=
C.getTypeSize(N->
getType()) < 32;
10116 CurScope, Loc, BO_Mul, LastIteration32.
get(),
10124 CurScope, Loc, BO_Mul, LastIteration64.
get(),
10134 if (SemaRef.
getLangOpts().OpenMPOptimisticCollapse ||
10136 C.getTypeSize(LastIteration32.
get()->
getType()) == 32 &&
10137 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
10141 LastIteration64.
get(), SemaRef))))
10142 LastIteration = LastIteration32;
10161 LastIteration.
get(),
10173 tryBuildCapture(SemaRef, LastIteration.
get(), Captures);
10174 LastIteration = SaveRef;
10187 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
10216 buildVarDecl(SemaRef, InitLoc, StrideVType,
".omp.stride");
10225 UB.
get(), LastIteration.
get());
10228 LastIteration.
get(), UB.
get());
10229 EUB = SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, UB.
get(),
10240 buildVarDecl(SemaRef, InitLoc, VType,
".omp.comb.lb");
10248 buildVarDecl(SemaRef, InitLoc, VType,
".omp.comb.ub");
10254 CurScope, InitLoc, BO_GT, CombUB.
get(), LastIteration.
get());
10257 LastIteration.
get(), CombUB.
get());
10258 CombEUB = SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.
get(),
10267 "Unexpected number of parameters in loop combined directive");
10308 SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, IV.
get(), CombRHS);
10314 bool UseStrictCompare =
10316 llvm::all_of(IterSpaces, [](
const LoopIterationSpace &LIS) {
10317 return LIS.IsStrictCompare;
10323 if (UseStrictCompare) {
10326 .
BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
10338 UseStrictCompare ? BO_LT : BO_LE, IV.
get(),
10341 NumIterations.
get());
10344 CombDistCond = SemaRef.
BuildBinOp(CurScope, CondLoc, BO_LT, IV.
get(),
10345 NumIterations.
get());
10350 Expr *BoundCombUB = CombUB.
get();
10351 if (UseStrictCompare) {
10355 CurScope, CondLoc, BO_Add, BoundCombUB,
10363 SemaRef.
BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10364 IV.
get(), BoundCombUB);
10371 if (!Inc.isUsable())
10373 Inc = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, IV.
get(), Inc.get());
10375 if (!Inc.isUsable())
10382 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10388 NextLB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Add, LB.
get(), ST.
get());
10399 NextUB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Add, UB.
get(), ST.
get());
10415 CombNextLB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.
get(),
10427 CombNextUB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.
get(),
10441 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10444 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.
get(), BoundUB);
10445 assert(DistCond.
isUsable() &&
"distribute cond expr was not built");
10449 assert(DistInc.
isUsable() &&
"distribute inc expr was not built");
10450 DistInc = SemaRef.
BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.
get(),
10454 assert(DistInc.
isUsable() &&
"distribute inc expr was not built");
10465 DistEUBLoc, NewPrevUB.
get());
10470 UB.
get(), NewPrevUB.
get());
10472 DistEUBLoc, DistEUBLoc, IsUBGreater.
get(), NewPrevUB.
get(), UB.
get());
10473 PrevEUB = SemaRef.
BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.
get(),
10481 Expr *BoundPrevUB = PrevUB.
get();
10482 if (UseStrictCompare) {
10486 CurScope, CondLoc, BO_Add, BoundPrevUB,
10494 SemaRef.
BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10495 IV.
get(), BoundPrevUB);
10499 bool HasErrors =
false;
10500 Built.Counters.resize(NestedLoopCount);
10501 Built.Inits.resize(NestedLoopCount);
10502 Built.Updates.resize(NestedLoopCount);
10503 Built.Finals.resize(NestedLoopCount);
10504 Built.DependentCounters.resize(NestedLoopCount);
10505 Built.DependentInits.resize(NestedLoopCount);
10506 Built.FinalsConditions.resize(NestedLoopCount);
10524 for (
unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10525 LoopIterationSpace &IS = IterSpaces[Cnt];
10531 for (
unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10532 Prod = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.
get(),
10533 IterSpaces[K].NumIterations);
10538 if (Cnt + 1 < NestedLoopCount)
10552 if (Cnt + 1 < NestedLoopCount)
10553 Prod = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.
get(),
10557 Acc = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.
get(), Prod.
get());
10566 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10567 if (!
Init.isUsable()) {
10572 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10573 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10574 if (!
Update.isUsable()) {
10582 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10583 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10584 if (!Final.isUsable()) {
10589 if (!
Update.isUsable() || !Final.isUsable()) {
10594 Built.Counters[Cnt] = IS.CounterVar;
10595 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10596 Built.Inits[Cnt] =
Init.get();
10597 Built.Updates[Cnt] =
Update.get();
10598 Built.Finals[Cnt] = Final.get();
10599 Built.DependentCounters[Cnt] =
nullptr;
10600 Built.DependentInits[Cnt] =
nullptr;
10601 Built.FinalsConditions[Cnt] =
nullptr;
10602 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10603 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10604 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10605 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10614 Built.IterationVarRef = IV.
get();
10615 Built.LastIteration = LastIteration.
get();
10616 Built.NumIterations = NumIterations.
get();
10617 Built.CalcLastIteration = SemaRef
10621 Built.PreCond = PreCond.get();
10623 Built.Cond =
Cond.get();
10624 Built.Init =
Init.get();
10625 Built.Inc = Inc.get();
10626 Built.LB = LB.
get();
10627 Built.UB = UB.
get();
10628 Built.IL = IL.
get();
10629 Built.ST = ST.
get();
10630 Built.EUB = EUB.
get();
10631 Built.NLB = NextLB.
get();
10632 Built.NUB = NextUB.
get();
10633 Built.PrevLB = PrevLB.
get();
10634 Built.PrevUB = PrevUB.
get();
10635 Built.DistInc = DistInc.
get();
10636 Built.PrevEUB = PrevEUB.
get();
10637 Built.DistCombinedFields.LB = CombLB.
get();
10638 Built.DistCombinedFields.UB = CombUB.
get();
10639 Built.DistCombinedFields.EUB = CombEUB.
get();
10640 Built.DistCombinedFields.Init = CombInit.
get();
10641 Built.DistCombinedFields.Cond = CombCond.
get();
10642 Built.DistCombinedFields.NLB = CombNextLB.
get();
10643 Built.DistCombinedFields.NUB = CombNextUB.
get();
10644 Built.DistCombinedFields.DistCond = CombDistCond.
get();
10645 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.
get();
10647 return NestedLoopCount;
10651 auto CollapseClauses =
10652 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10653 if (CollapseClauses.begin() != CollapseClauses.end())
10654 return (*CollapseClauses.begin())->getNumForLoops();
10659 auto OrderedClauses =
10660 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10661 if (OrderedClauses.begin() != OrderedClauses.end())
10662 return (*OrderedClauses.begin())->getNumForLoops();
10671 for (
const OMPClause *Clause : Clauses) {
10672 if (Clause->getClauseKind() == OMPC_safelen)
10674 else if (Clause->getClauseKind() == OMPC_simdlen)
10676 if (Safelen && Simdlen)
10680 if (Simdlen && Safelen) {
10694 llvm::APSInt SimdlenRes = SimdlenResult.
Val.
getInt();
10695 llvm::APSInt SafelenRes = SafelenResult.
Val.
getInt();
10700 if (SimdlenRes > SafelenRes) {
10702 diag::err_omp_wrong_simdlen_safelen_values)
10719 OMPLoopBasedDirective::HelperExprs B;
10725 if (NestedLoopCount == 0)
10734 auto *SimdDirective = OMPSimdDirective::Create(
10735 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10736 return SimdDirective;
10746 OMPLoopBasedDirective::HelperExprs B;
10752 if (NestedLoopCount == 0)
10758 auto *ForDirective = OMPForDirective::Create(
10759 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10761 return ForDirective;
10773 OMPLoopBasedDirective::HelperExprs B;
10776 unsigned NestedLoopCount =
10779 VarsWithImplicitDSA, B);
10780 if (NestedLoopCount == 0)
10789 return OMPForSimdDirective::Create(
getASTContext(), StartLoc, EndLoc,
10790 NestedLoopCount, Clauses, AStmt, B);
10794 Stmt *AStmt, DSAStackTy *Stack) {
10799 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
10800 auto BaseStmt = AStmt;
10801 while (
auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10803 if (
auto *
C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10804 auto S =
C->children();
10805 if (S.begin() == S.end())
10809 for (
Stmt *SectionStmt : llvm::drop_begin(S)) {
10812 SemaRef.
Diag(SectionStmt->getBeginLoc(),
10813 diag::err_omp_sections_substmt_not_section)
10814 << getOpenMPDirectiveName(DKind, OMPVersion);
10818 ->setHasCancel(Stack->isCancelRegion());
10821 SemaRef.
Diag(AStmt->
getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10822 << getOpenMPDirectiveName(DKind, OMPVersion);
10835 SemaRef.setFunctionHasBranchProtectedScope();
10837 return OMPSectionsDirective::Create(
10848 SemaRef.setFunctionHasBranchProtectedScope();
10851 return OMPSectionDirective::Create(
getASTContext(), StartLoc, EndLoc, AStmt,
10857 if (
auto *CE = dyn_cast<CallExpr>(E))
10858 if (CE->getDirectCallee())
10879 if (!
SemaRef.CurContext->isDependentContext()) {
10880 Expr *TargetCall =
nullptr;
10882 auto *E = dyn_cast<Expr>(S);
10890 if (
auto *BO = dyn_cast<BinaryOperator>(E)) {
10891 if (BO->getOpcode() == BO_Assign)
10894 if (
auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10895 if (COCE->getOperator() == OO_Equal)
10907 SemaRef.setFunctionHasBranchProtectedScope();
10910 Clauses, AStmt, TargetCallLoc);
10915 DSAStackTy *Stack) {
10916 bool ErrorFound =
false;
10918 if (
auto *LPC = dyn_cast<OMPLastprivateClause>(
C)) {
10919 for (
Expr *RefExpr : LPC->varlist()) {
10922 Expr *SimpleRefExpr = RefExpr;
10925 auto &&Info = Stack->isLoopControlVariable(D);
10928 S.
Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10929 << getOpenMPDirectiveName(K, OMPVersion);
10953 OMPLoopDirective::HelperExprs B;
10958 if (NestedLoopCount == 0)
10961 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10962 "omp loop exprs were not built");
10965 NestedLoopCount, Clauses, AStmt, B);
10982 OMPLoopDirective::HelperExprs B;
10984 unsigned NestedLoopCount =
10987 VarsWithImplicitDSA, B);
10988 if (NestedLoopCount == 0)
10991 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10992 "omp loop exprs were not built");
10994 DSAStack->setParentTeamsRegionLoc(StartLoc);
10997 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11016 OMPLoopDirective::HelperExprs B;
11018 unsigned NestedLoopCount =
11021 VarsWithImplicitDSA, B);
11022 if (NestedLoopCount == 0)
11025 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11026 "omp loop exprs were not built");
11029 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11049 OMPLoopDirective::HelperExprs B;
11051 unsigned NestedLoopCount =
11054 VarsWithImplicitDSA, B);
11055 if (NestedLoopCount == 0)
11058 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11059 "omp loop exprs were not built");
11062 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11081 OMPLoopDirective::HelperExprs B;
11083 unsigned NestedLoopCount =
11086 VarsWithImplicitDSA, B);
11087 if (NestedLoopCount == 0)
11090 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11091 "omp loop exprs were not built");
11094 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11106 SemaRef.setFunctionHasBranchProtectedScope();
11111 const OMPClause *Copyprivate =
nullptr;
11112 for (
const OMPClause *Clause : Clauses) {
11113 if (Clause->getClauseKind() == OMPC_nowait)
11115 else if (Clause->getClauseKind() == OMPC_copyprivate)
11116 Copyprivate = Clause;
11117 if (Copyprivate && Nowait) {
11119 diag::err_omp_single_copyprivate_with_nowait);
11125 return OMPSingleDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses,
11135 SemaRef.setFunctionHasBranchProtectedScope();
11137 return OMPMasterDirective::Create(
getASTContext(), StartLoc, EndLoc, AStmt);
11147 SemaRef.setFunctionHasBranchProtectedScope();
11159 bool ErrorFound =
false;
11162 bool DependentHint =
false;
11164 if (
C->getClauseKind() == OMPC_hint) {
11166 Diag(
C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
11172 DependentHint =
true;
11175 HintLoc =
C->getBeginLoc();
11181 const auto Pair =
DSAStack->getCriticalWithHint(DirName);
11182 if (Pair.first && DirName.
getName() && !DependentHint) {
11183 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
11184 Diag(StartLoc, diag::err_omp_critical_with_hint);
11186 Diag(HintLoc, diag::note_omp_critical_hint_here)
11187 << 0 <<
toString(Hint, 10,
false);
11189 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
11190 if (
const auto *
C = Pair.first->getSingleClause<
OMPHintClause>()) {
11191 Diag(
C->getBeginLoc(), diag::note_omp_critical_hint_here)
11196 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
11201 SemaRef.setFunctionHasBranchProtectedScope();
11203 auto *Dir = OMPCriticalDirective::Create(
getASTContext(), DirName, StartLoc,
11204 EndLoc, Clauses, AStmt);
11205 if (!Pair.first && DirName.
getName() && !DependentHint)
11206 DSAStack->addCriticalWithHint(Dir, Hint);
11218 OMPLoopBasedDirective::HelperExprs B;
11221 unsigned NestedLoopCount =
11224 VarsWithImplicitDSA, B);
11225 if (NestedLoopCount == 0)
11231 return OMPParallelForDirective::Create(
11232 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11245 OMPLoopBasedDirective::HelperExprs B;
11248 unsigned NestedLoopCount =
11251 VarsWithImplicitDSA, B);
11252 if (NestedLoopCount == 0)
11261 return OMPParallelForSimdDirective::Create(
11262 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11273 return OMPParallelMasterDirective::Create(
11275 DSAStack->getTaskgroupReductionRef());
11286 return OMPParallelMaskedDirective::Create(
11288 DSAStack->getTaskgroupReductionRef());
11297 SemaRef.setFunctionHasBranchProtectedScope();
11299 return OMPParallelSectionsDirective::Create(
11309 bool ErrorFound =
false;
11311 if (llvm::is_contained(MutuallyExclusiveClauses,
C->getClauseKind())) {
11315 S.
Diag(
C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
11338 {OMPC_detach, OMPC_mergeable}))
11343 return OMPTaskDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses,
11344 AStmt,
DSAStack->isCancelRegion());
11349 return OMPTaskyieldDirective::Create(
getASTContext(), StartLoc, EndLoc);
11354 return OMPBarrierDirective::Create(
getASTContext(), StartLoc, EndLoc);
11360 bool InExContext) {
11361 const OMPAtClause *AtC =
11362 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11364 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11365 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
11369 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11370 const OMPSeverityClause *SeverityC =
11371 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11372 const OMPMessageClause *MessageC =
11373 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11374 std::optional<std::string> SL =
11375 MessageC ? MessageC->tryEvaluateString(
getASTContext()) : std::nullopt;
11377 if (MessageC && !SL)
11378 Diag(MessageC->getMessageString()->getBeginLoc(),
11379 diag::warn_clause_expected_string)
11381 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11382 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
11383 << SL.value_or(
"WARNING");
11385 Diag(StartLoc, diag::err_diagnose_if_succeeded) << SL.value_or(
"ERROR");
11386 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11397 const OMPNowaitClause *NowaitC =
11398 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11400 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11402 if (NowaitC && !HasDependC) {
11403 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11407 return OMPTaskwaitDirective::Create(
getASTContext(), StartLoc, EndLoc,
11420 SemaRef.setFunctionHasBranchProtectedScope();
11422 return OMPTaskgroupDirective::Create(
getASTContext(), StartLoc, EndLoc,
11424 DSAStack->getTaskgroupReductionRef());
11433 if (
C->getClauseKind() == OMPC_flush)
11442 if (
C->getClauseKind() == OMPC_acq_rel ||
11443 C->getClauseKind() == OMPC_acquire ||
11444 C->getClauseKind() == OMPC_release ||
11445 C->getClauseKind() == OMPC_seq_cst ) {
11446 if (MemOrderKind != OMPC_unknown) {
11447 Diag(
C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11448 << getOpenMPDirectiveName(OMPD_flush, OMPVersion) << 1
11450 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11453 MemOrderKind =
C->getClauseKind();
11454 MemOrderLoc =
C->getBeginLoc();
11458 if (FC && OrderClause) {
11459 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11461 Diag(OrderClause->
getBeginLoc(), diag::note_omp_flush_order_clause_here)
11465 return OMPFlushDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses);
11471 if (Clauses.empty()) {
11472 Diag(StartLoc, diag::err_omp_depobj_expected);
11474 }
else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11475 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11479 if (Clauses.size() > 2) {
11480 Diag(Clauses[2]->getBeginLoc(),
11481 diag::err_omp_depobj_single_clause_expected);
11483 }
else if (Clauses.size() < 1) {
11484 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11487 return OMPDepobjDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses);
11494 if (Clauses.size() != 1) {
11495 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11496 diag::err_omp_scan_single_clause_expected);
11505 return StmtError(
Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11506 << getOpenMPDirectiveName(OMPD_scan, OMPVersion) << 5);
11511 if (
DSAStack->doesParentHasScanDirective()) {
11512 Diag(StartLoc, diag::err_omp_several_directives_in_region) <<
"scan";
11514 diag::note_omp_previous_directive)
11518 DSAStack->setParentHasScanDirective(StartLoc);
11526 const OMPClause *DependFound =
nullptr;
11527 const OMPClause *DependSourceClause =
nullptr;
11528 const OMPClause *DependSinkClause =
nullptr;
11529 const OMPClause *DoacrossFound =
nullptr;
11530 const OMPClause *DoacrossSourceClause =
nullptr;
11531 const OMPClause *DoacrossSinkClause =
nullptr;
11532 bool ErrorFound =
false;
11536 auto DOC = dyn_cast<OMPDoacrossClause>(
C);
11537 auto DC = dyn_cast<OMPDependClause>(
C);
11539 DependFound = DC ?
C :
nullptr;
11540 DoacrossFound = DOC ?
C :
nullptr;
11541 OMPDoacrossKind ODK;
11542 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11543 (DOC && (ODK.isSource(DOC)))) {
11544 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11546 Diag(
C->getBeginLoc(), diag::err_omp_more_one_clause)
11547 << getOpenMPDirectiveName(OMPD_ordered, OMPVersion)
11553 DependSourceClause =
C;
11555 DoacrossSourceClause =
C;
11557 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11558 Diag(
C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11559 << (DC ?
"depend" :
"doacross") << 0;
11562 }
else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11563 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11564 if (DependSourceClause || DoacrossSourceClause) {
11565 Diag(
C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11566 << (DC ?
"depend" :
"doacross") << 1;
11570 DependSinkClause =
C;
11572 DoacrossSinkClause =
C;
11574 }
else if (
C->getClauseKind() == OMPC_threads) {
11576 }
else if (
C->getClauseKind() == OMPC_simd) {
11580 if (!ErrorFound && !SC &&
11585 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11588 }
else if ((DependFound || DoacrossFound) && (TC || SC)) {
11591 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11594 : SC->getClauseKind());
11596 }
else if ((DependFound || DoacrossFound) &&
11597 !
DSAStack->getParentOrderedRegionParam().first) {
11600 Diag(Loc, diag::err_omp_ordered_directive_without_param)
11604 }
else if (TC || Clauses.empty()) {
11605 if (
const Expr *Param =
DSAStack->getParentOrderedRegionParam().first) {
11607 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11608 << (TC !=
nullptr);
11609 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11613 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11621 if (!DependFound && !DoacrossFound) {
11622 if (
DSAStack->doesParentHasOrderedDirective()) {
11623 Diag(StartLoc, diag::err_omp_several_directives_in_region) <<
"ordered";
11625 diag::note_omp_previous_directive)
11629 DSAStack->setParentHasOrderedDirective(StartLoc);
11635 SemaRef.setFunctionHasBranchProtectedScope();
11638 return OMPOrderedDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses,
11645class OpenMPAtomicUpdateChecker {
11647 enum ExprAnalysisErrorCode {
11651 NotABinaryOrUnaryExpression,
11653 NotAnUnaryIncDecExpression,
11659 NotABinaryExpression,
11662 NotABinaryOperator,
11665 NotAnUpdateExpression,
11668 NotAValidExpression,
11694 OpenMPAtomicUpdateChecker(
Sema &SemaRef)
11704 bool checkStatement(Stmt *S,
unsigned DiagId = 0,
unsigned NoteId = 0);
11706 Expr *
getX()
const {
return X; }
11708 Expr *
getExpr()
const {
return E; }
11722 bool checkBinaryOperation(BinaryOperator *AtomicBinOp,
unsigned DiagId = 0,
11723 unsigned NoteId = 0);
11726bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11727 BinaryOperator *AtomicBinOp,
unsigned DiagId,
unsigned NoteId) {
11728 ExprAnalysisErrorCode ErrorFound = NoError;
11734 if (AtomicBinOp->
getOpcode() == BO_Assign) {
11736 if (
const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11738 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11739 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11740 AtomicInnerBinOp->isBitwiseOp()) {
11741 Op = AtomicInnerBinOp->getOpcode();
11742 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11743 Expr *LHS = AtomicInnerBinOp->getLHS();
11744 Expr *RHS = AtomicInnerBinOp->getRHS();
11745 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11752 if (XId == LHSId) {
11755 }
else if (XId == RHSId) {
11759 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11760 ErrorRange = AtomicInnerBinOp->getSourceRange();
11761 NoteLoc =
X->getExprLoc();
11762 NoteRange =
X->getSourceRange();
11763 ErrorFound = NotAnUpdateExpression;
11766 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11767 ErrorRange = AtomicInnerBinOp->getSourceRange();
11768 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11770 ErrorFound = NotABinaryOperator;
11775 ErrorFound = NotABinaryExpression;
11782 ErrorFound = NotAnAssignmentOp;
11784 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11785 SemaRef.
Diag(ErrorLoc, DiagId) << ErrorRange;
11786 SemaRef.
Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11790 E =
X = UpdateExpr =
nullptr;
11791 return ErrorFound != NoError;
11794bool OpenMPAtomicUpdateChecker::checkStatement(
Stmt *S,
unsigned DiagId,
11796 ExprAnalysisErrorCode ErrorFound = NoError;
11807 if (
auto *AtomicBody = dyn_cast<Expr>(S)) {
11808 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11809 if (AtomicBody->getType()->isScalarType() ||
11810 AtomicBody->isInstantiationDependent()) {
11811 if (
const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11812 AtomicBody->IgnoreParenImpCasts())) {
11815 AtomicCompAssignOp->getOpcode());
11816 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11817 E = AtomicCompAssignOp->getRHS();
11820 }
else if (
auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11821 AtomicBody->IgnoreParenImpCasts())) {
11823 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11825 }
else if (
const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11826 AtomicBody->IgnoreParenImpCasts())) {
11828 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11830 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11831 OpLoc = AtomicUnaryOp->getOperatorLoc();
11832 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11836 ErrorFound = NotAnUnaryIncDecExpression;
11837 ErrorLoc = AtomicUnaryOp->getExprLoc();
11838 ErrorRange = AtomicUnaryOp->getSourceRange();
11839 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11842 }
else if (!AtomicBody->isInstantiationDependent()) {
11843 ErrorFound = NotABinaryOrUnaryExpression;
11844 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11845 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11846 }
else if (AtomicBody->containsErrors()) {
11847 ErrorFound = NotAValidExpression;
11848 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11849 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11852 ErrorFound = NotAScalarType;
11853 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11854 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
11857 ErrorFound = NotAnExpression;
11859 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
11861 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11862 SemaRef.
Diag(ErrorLoc, DiagId) << ErrorRange;
11863 SemaRef.
Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11867 E =
X = UpdateExpr =
nullptr;
11868 if (ErrorFound == NoError && E &&
X) {
11885 UpdateExpr =
Update.get();
11887 return ErrorFound != NoError;
11891llvm::FoldingSetNodeID getNodeId(
ASTContext &Context,
const Expr *S) {
11892 llvm::FoldingSetNodeID Id;
11898bool checkIfTwoExprsAreSame(
ASTContext &Context,
const Expr *LHS,
11900 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11903class OpenMPAtomicCompareChecker {
11950 struct ErrorInfoTy {
11952 SourceLocation ErrorLoc;
11953 SourceRange ErrorRange;
11954 SourceLocation NoteLoc;
11955 SourceRange NoteRange;
11958 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11961 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11963 Expr *
getX()
const {
return X; }
11964 Expr *getE()
const {
return E; }
11965 Expr *
getD()
const {
return D; }
11966 Expr *getCond()
const {
return C; }
11967 bool isXBinopExpr()
const {
return IsXBinopExpr; }
11971 ASTContext &ContextRef;
11986 bool IsXBinopExpr =
true;
11989 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11992 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11995 bool checkType(ErrorInfoTy &ErrorInfo)
const;
11997 static bool CheckValue(
const Expr *E, ErrorInfoTy &ErrorInfo,
11998 bool ShouldBeLValue,
bool ShouldBeInteger =
false) {
12002 if (ShouldBeLValue && !E->
isLValue()) {
12003 ErrorInfo.Error = ErrorTy::XNotLValue;
12004 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->
getExprLoc();
12005 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->
getSourceRange();
12011 ErrorInfo.Error = ErrorTy::NotScalar;
12012 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->
getExprLoc();
12013 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->
getSourceRange();
12017 ErrorInfo.Error = ErrorTy::NotInteger;
12018 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->
getExprLoc();
12019 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->
getSourceRange();
12027bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(
IfStmt *S,
12028 ErrorInfoTy &ErrorInfo) {
12030 if (
auto *CS = dyn_cast<CompoundStmt>(Then)) {
12031 if (CS->body_empty()) {
12032 ErrorInfo.Error = ErrorTy::NoStmt;
12033 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12034 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12037 if (CS->size() > 1) {
12038 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12039 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12040 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
12043 Then = CS->body_front();
12046 auto *BO = dyn_cast<BinaryOperator>(Then);
12048 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12049 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12050 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12053 if (BO->getOpcode() != BO_Assign) {
12054 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12055 ErrorInfo.ErrorLoc = BO->getExprLoc();
12056 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12057 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12063 auto *
Cond = dyn_cast<BinaryOperator>(S->
getCond());
12064 auto *
Call = dyn_cast<CXXOperatorCallExpr>(S->
getCond());
12065 Expr *LHS =
nullptr;
12066 Expr *RHS =
nullptr;
12068 LHS =
Cond->getLHS();
12069 RHS =
Cond->getRHS();
12071 LHS =
Call->getArg(0);
12072 RHS =
Call->getArg(1);
12074 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12080 if ((
Cond &&
Cond->getOpcode() == BO_EQ) ||
12081 (
Call &&
Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12084 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS)) {
12086 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12089 ErrorInfo.Error = ErrorTy::InvalidComparison;
12091 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12095 }
else if ((
Cond &&
12096 (
Cond->getOpcode() == BO_LT ||
Cond->getOpcode() == BO_GT)) ||
12098 (
Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12099 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12101 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS) &&
12102 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12104 }
else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12105 checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12107 IsXBinopExpr =
false;
12109 ErrorInfo.Error = ErrorTy::InvalidComparison;
12111 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12116 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12123 ErrorInfo.Error = ErrorTy::UnexpectedElse;
12132bool OpenMPAtomicCompareChecker::checkCondExprStmt(
Stmt *S,
12133 ErrorInfoTy &ErrorInfo) {
12134 auto *BO = dyn_cast<BinaryOperator>(S);
12136 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12137 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->
getBeginLoc();
12138 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
12141 if (BO->getOpcode() != BO_Assign) {
12142 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12143 ErrorInfo.ErrorLoc = BO->getExprLoc();
12144 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12145 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12151 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
12153 ErrorInfo.Error = ErrorTy::NotCondOp;
12154 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
12155 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
12159 if (!checkIfTwoExprsAreSame(ContextRef,
X, CO->getFalseExpr())) {
12160 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
12161 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
12162 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12163 CO->getFalseExpr()->getSourceRange();
12167 auto *
Cond = dyn_cast<BinaryOperator>(CO->getCond());
12168 auto *
Call = dyn_cast<CXXOperatorCallExpr>(CO->getCond());
12169 Expr *LHS =
nullptr;
12170 Expr *RHS =
nullptr;
12172 LHS =
Cond->getLHS();
12173 RHS =
Cond->getRHS();
12175 LHS =
Call->getArg(0);
12176 RHS =
Call->getArg(1);
12178 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12179 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12180 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12181 CO->getCond()->getSourceRange();
12185 if ((
Cond &&
Cond->getOpcode() == BO_EQ) ||
12186 (
Call &&
Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12188 D = CO->getTrueExpr();
12189 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS)) {
12191 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12194 ErrorInfo.Error = ErrorTy::InvalidComparison;
12195 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12196 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12197 CO->getCond()->getSourceRange();
12200 }
else if ((
Cond &&
12201 (
Cond->getOpcode() == BO_LT ||
Cond->getOpcode() == BO_GT)) ||
12203 (
Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12204 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12206 E = CO->getTrueExpr();
12207 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS) &&
12208 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12210 }
else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12211 checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12213 IsXBinopExpr =
false;
12215 ErrorInfo.Error = ErrorTy::InvalidComparison;
12216 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12217 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12218 CO->getCond()->getSourceRange();
12222 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12223 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12224 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12225 CO->getCond()->getSourceRange();
12232bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo)
const {
12234 assert(
X && E &&
"X and E cannot be nullptr");
12236 if (!CheckValue(
X, ErrorInfo,
true))
12239 if (!CheckValue(E, ErrorInfo,
false))
12242 if (D && !CheckValue(D, ErrorInfo,
false))
12248bool OpenMPAtomicCompareChecker::checkStmt(
12249 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
12250 auto *CS = dyn_cast<CompoundStmt>(S);
12252 if (CS->body_empty()) {
12253 ErrorInfo.Error = ErrorTy::NoStmt;
12254 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12255 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12259 if (CS->size() != 1) {
12260 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12261 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12262 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12265 S = CS->body_front();
12270 if (
auto *IS = dyn_cast<IfStmt>(S)) {
12276 Res = checkCondUpdateStmt(IS, ErrorInfo);
12282 Res = checkCondExprStmt(S, ErrorInfo);
12288 return checkType(ErrorInfo);
12291class OpenMPAtomicCompareCaptureChecker final
12292 :
public OpenMPAtomicCompareChecker {
12294 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
12296 Expr *
getV()
const {
return V; }
12297 Expr *
getR()
const {
return R; }
12302 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12305 bool checkType(ErrorInfoTy &ErrorInfo);
12317 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12321 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12333bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12334 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12337 if (
V && !CheckValue(
V, ErrorInfo,
true))
12340 if (R && !CheckValue(R, ErrorInfo,
true,
true))
12346bool OpenMPAtomicCompareCaptureChecker::checkForm3(
IfStmt *S,
12347 ErrorInfoTy &ErrorInfo) {
12351 if (
auto *CS = dyn_cast<CompoundStmt>(Then)) {
12352 if (CS->body_empty()) {
12353 ErrorInfo.Error = ErrorTy::NoStmt;
12354 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12355 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12358 if (CS->size() > 1) {
12359 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12360 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12361 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12364 Then = CS->body_front();
12367 auto *BO = dyn_cast<BinaryOperator>(Then);
12369 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12370 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12371 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12374 if (BO->getOpcode() != BO_Assign) {
12375 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12376 ErrorInfo.ErrorLoc = BO->getExprLoc();
12377 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12378 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12385 auto *
Cond = dyn_cast<BinaryOperator>(S->
getCond());
12386 auto *
Call = dyn_cast<CXXOperatorCallExpr>(S->
getCond());
12387 Expr *LHS =
nullptr;
12388 Expr *RHS =
nullptr;
12390 LHS =
Cond->getLHS();
12391 RHS =
Cond->getRHS();
12393 LHS =
Call->getArg(0);
12394 RHS =
Call->getArg(1);
12396 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12401 if ((
Cond &&
Cond->getOpcode() != BO_EQ) ||
12402 (
Call &&
Call->getOperator() != OverloadedOperatorKind::OO_EqualEqual)) {
12403 ErrorInfo.Error = ErrorTy::NotEQ;
12409 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS)) {
12411 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12414 ErrorInfo.Error = ErrorTy::InvalidComparison;
12423 ErrorInfo.Error = ErrorTy::NoElse;
12424 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->
getBeginLoc();
12425 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
12430 if (
auto *CS = dyn_cast<CompoundStmt>(Else)) {
12431 if (CS->body_empty()) {
12432 ErrorInfo.Error = ErrorTy::NoStmt;
12433 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12434 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12437 if (CS->size() > 1) {
12438 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12439 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12440 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
12443 Else = CS->body_front();
12446 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12448 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12449 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12450 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12453 if (ElseBO->getOpcode() != BO_Assign) {
12454 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12455 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12456 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12457 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12461 if (!checkIfTwoExprsAreSame(ContextRef,
X, ElseBO->getRHS())) {
12462 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12463 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12464 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12465 ElseBO->getRHS()->getSourceRange();
12469 V = ElseBO->getLHS();
12471 return checkType(ErrorInfo);
12474bool OpenMPAtomicCompareCaptureChecker::checkForm45(
Stmt *S,
12475 ErrorInfoTy &ErrorInfo) {
12479 assert(CS->size() == 2 &&
"CompoundStmt size is not expected");
12482 assert(S1->getOpcode() == BO_Assign &&
"unexpected binary operator");
12484 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12485 ErrorInfo.Error = ErrorTy::InvalidCondition;
12486 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12487 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12493 auto *Then = S2->getThen();
12494 if (
auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12495 if (ThenCS->body_empty()) {
12496 ErrorInfo.Error = ErrorTy::NoStmt;
12497 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12498 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12501 if (ThenCS->size() > 1) {
12502 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12503 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12504 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12507 Then = ThenCS->body_front();
12510 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12512 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12513 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12514 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12517 if (ThenBO->getOpcode() != BO_Assign) {
12518 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12519 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12520 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12521 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12525 X = ThenBO->getLHS();
12526 D = ThenBO->getRHS();
12529 if (BO->getOpcode() != BO_EQ) {
12530 ErrorInfo.Error = ErrorTy::NotEQ;
12531 ErrorInfo.ErrorLoc = BO->getExprLoc();
12532 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12533 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12539 if (checkIfTwoExprsAreSame(ContextRef,
X, BO->getLHS())) {
12541 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, BO->getRHS())) {
12544 ErrorInfo.Error = ErrorTy::InvalidComparison;
12545 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12546 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12550 if (S2->getElse()) {
12553 auto *Else = S2->getElse();
12554 if (
auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12555 if (ElseCS->body_empty()) {
12556 ErrorInfo.Error = ErrorTy::NoStmt;
12557 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12558 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12561 if (ElseCS->size() > 1) {
12562 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12563 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12564 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12567 Else = ElseCS->body_front();
12570 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12572 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12573 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12574 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12577 if (ElseBO->getOpcode() != BO_Assign) {
12578 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12579 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12580 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12581 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12584 if (!checkIfTwoExprsAreSame(ContextRef,
X, ElseBO->getRHS())) {
12585 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12586 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12587 ErrorInfo.NoteLoc =
X->getExprLoc();
12588 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12589 ErrorInfo.NoteRange =
X->getSourceRange();
12593 V = ElseBO->getLHS();
12596 return checkType(ErrorInfo);
12599bool OpenMPAtomicCompareCaptureChecker::checkStmt(
Stmt *S,
12600 ErrorInfoTy &ErrorInfo) {
12602 if (
auto *IS = dyn_cast<IfStmt>(S))
12603 return checkForm3(IS, ErrorInfo);
12605 auto *CS = dyn_cast<CompoundStmt>(S);
12607 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12608 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->
getBeginLoc();
12609 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
12612 if (CS->body_empty()) {
12613 ErrorInfo.Error = ErrorTy::NoStmt;
12614 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12615 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12620 if (CS->size() == 1) {
12621 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12623 ErrorInfo.Error = ErrorTy::NotIfStmt;
12624 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->
getBeginLoc();
12625 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12630 return checkForm3(IS, ErrorInfo);
12631 }
else if (CS->size() == 2) {
12632 auto *S1 = CS->body_front();
12633 auto *S2 = CS->body_back();
12635 Stmt *UpdateStmt =
nullptr;
12636 Stmt *CondUpdateStmt =
nullptr;
12637 Stmt *CondExprStmt =
nullptr;
12639 if (
auto *BO = dyn_cast<BinaryOperator>(S1)) {
12649 return checkForm45(CS, ErrorInfo);
12658 CondUpdateStmt = S2;
12667 CondUpdateStmt = S1;
12670 auto CheckCondUpdateStmt = [
this, &ErrorInfo](
Stmt *CUS) {
12671 auto *IS = dyn_cast<IfStmt>(CUS);
12673 ErrorInfo.Error = ErrorTy::NotIfStmt;
12674 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12675 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12679 return checkCondUpdateStmt(IS, ErrorInfo);
12683 auto CheckUpdateStmt = [
this, &ErrorInfo](
Stmt *US) {
12684 auto *BO = dyn_cast<BinaryOperator>(US);
12686 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12687 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12688 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12691 if (BO->getOpcode() != BO_Assign) {
12692 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12693 ErrorInfo.ErrorLoc = BO->getExprLoc();
12694 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12695 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12698 if (!checkIfTwoExprsAreSame(ContextRef, this->
X, BO->getRHS())) {
12699 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12700 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12701 ErrorInfo.NoteLoc = this->
X->getExprLoc();
12702 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12703 ErrorInfo.NoteRange = this->
X->getSourceRange();
12707 this->
V = BO->getLHS();
12712 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12714 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12716 if (!CheckUpdateStmt(UpdateStmt))
12719 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12720 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12721 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12725 return checkType(ErrorInfo);
12736 DSAStack->addAtomicDirectiveLoc(StartLoc);
12749 bool MutexClauseEncountered =
false;
12750 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12752 switch (
C->getClauseKind()) {
12756 MutexClauseEncountered =
true;
12759 case OMPC_compare: {
12760 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12761 Diag(
C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12763 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12766 AtomicKind =
C->getClauseKind();
12767 AtomicKindLoc =
C->getBeginLoc();
12768 if (!EncounteredAtomicKinds.insert(
C->getClauseKind()).second) {
12769 Diag(
C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12771 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12779 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12780 Diag(
C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12791 case OMPC_relaxed: {
12792 if (MemOrderKind != OMPC_unknown) {
12793 Diag(
C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12794 << getOpenMPDirectiveName(OMPD_atomic, OMPVersion) << 0
12796 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12799 MemOrderKind =
C->getClauseKind();
12800 MemOrderLoc =
C->getBeginLoc();
12808 llvm_unreachable(
"unknown clause is encountered");
12811 bool IsCompareCapture =
false;
12812 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12813 EncounteredAtomicKinds.contains(OMPC_capture)) {
12814 IsCompareCapture =
true;
12815 AtomicKind = OMPC_compare;
12824 if ((AtomicKind == OMPC_read &&
12825 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12826 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12827 AtomicKind == OMPC_unknown) &&
12828 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12830 if (AtomicKind == OMPC_unknown)
12832 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12834 << (AtomicKind == OMPC_unknown ? 1 : 0)
12836 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12840 Stmt *Body = AStmt;
12841 if (
auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12842 Body = EWC->getSubExpr();
12847 Expr *UE =
nullptr;
12849 Expr *CE =
nullptr;
12876 if (AtomicKind == OMPC_read) {
12883 } ErrorFound = NoError;
12888 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12889 const auto *AtomicBinOp =
12890 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12891 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12894 if ((
X->isInstantiationDependent() ||
X->getType()->isScalarType()) &&
12895 (
V->isInstantiationDependent() ||
V->getType()->isScalarType())) {
12896 if (!
X->isLValue() || !
V->isLValue()) {
12897 const Expr *NotLValueExpr =
X->isLValue() ?
V :
X;
12898 ErrorFound = NotAnLValue;
12904 }
else if (!
X->isInstantiationDependent() ||
12905 !
V->isInstantiationDependent()) {
12906 const Expr *NotScalarExpr =
12907 (
X->isInstantiationDependent() ||
X->getType()->isScalarType())
12910 ErrorFound = NotAScalarType;
12916 }
else if (!AtomicBody->isInstantiationDependent()) {
12917 ErrorFound = NotAnAssignmentOp;
12918 ErrorLoc = AtomicBody->getExprLoc();
12919 ErrorRange = AtomicBody->getSourceRange();
12921 : AtomicBody->getExprLoc();
12923 : AtomicBody->getSourceRange();
12926 ErrorFound = NotAnExpression;
12928 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
12930 if (ErrorFound != NoError) {
12931 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12933 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12934 << ErrorFound << NoteRange;
12937 if (
SemaRef.CurContext->isDependentContext())
12939 }
else if (AtomicKind == OMPC_write) {
12946 } ErrorFound = NoError;
12951 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12952 const auto *AtomicBinOp =
12953 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12954 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12956 E = AtomicBinOp->
getRHS();
12957 if ((
X->isInstantiationDependent() ||
X->getType()->isScalarType()) &&
12959 if (!
X->isLValue()) {
12960 ErrorFound = NotAnLValue;
12963 NoteLoc =
X->getExprLoc();
12964 NoteRange =
X->getSourceRange();
12966 }
else if (!
X->isInstantiationDependent() ||
12968 const Expr *NotScalarExpr =
12969 (
X->isInstantiationDependent() ||
X->getType()->isScalarType())
12972 ErrorFound = NotAScalarType;
12978 }
else if (!AtomicBody->isInstantiationDependent()) {
12979 ErrorFound = NotAnAssignmentOp;
12980 ErrorLoc = AtomicBody->getExprLoc();
12981 ErrorRange = AtomicBody->getSourceRange();
12983 : AtomicBody->getExprLoc();
12985 : AtomicBody->getSourceRange();
12988 ErrorFound = NotAnExpression;
12990 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
12992 if (ErrorFound != NoError) {
12993 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12995 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12996 << ErrorFound << NoteRange;
12999 if (
SemaRef.CurContext->isDependentContext())
13001 }
else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
13010 OpenMPAtomicUpdateChecker Checker(
SemaRef);
13011 if (Checker.checkStatement(
13013 (AtomicKind == OMPC_update)
13014 ? diag::err_omp_atomic_update_not_expression_statement
13015 : diag::err_omp_atomic_not_expression_statement,
13016 diag::note_omp_atomic_update))
13018 if (!
SemaRef.CurContext->isDependentContext()) {
13019 E = Checker.getExpr();
13020 X = Checker.getX();
13021 UE = Checker.getUpdateExpr();
13024 }
else if (AtomicKind == OMPC_capture) {
13027 NotACompoundStatement,
13028 NotTwoSubstatements,
13029 NotASpecificExpression,
13031 } ErrorFound = NoError;
13034 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
13043 const auto *AtomicBinOp =
13044 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
13045 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
13048 OpenMPAtomicUpdateChecker Checker(
SemaRef);
13049 if (Checker.checkStatement(
13050 Body, diag::err_omp_atomic_capture_not_expression_statement,
13051 diag::note_omp_atomic_update))
13053 E = Checker.getExpr();
13054 X = Checker.getX();
13055 UE = Checker.getUpdateExpr();
13058 }
else if (!AtomicBody->isInstantiationDependent()) {
13059 ErrorLoc = AtomicBody->getExprLoc();
13060 ErrorRange = AtomicBody->getSourceRange();
13062 : AtomicBody->getExprLoc();
13064 : AtomicBody->getSourceRange();
13065 ErrorFound = NotAnAssignmentOp;
13067 if (ErrorFound != NoError) {
13068 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
13070 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13073 if (
SemaRef.CurContext->isDependentContext())
13074 UE =
V = E =
X =
nullptr;
13092 if (
auto *CS = dyn_cast<CompoundStmt>(Body)) {
13094 if (CS->size() == 2) {
13096 Stmt *Second = CS->body_back();
13097 if (
auto *EWC = dyn_cast<ExprWithCleanups>(
First))
13098 First = EWC->getSubExpr()->IgnoreParenImpCasts();
13099 if (
auto *EWC = dyn_cast<ExprWithCleanups>(Second))
13100 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
13102 OpenMPAtomicUpdateChecker Checker(
SemaRef);
13103 bool IsUpdateExprFound = !Checker.checkStatement(Second);
13105 if (IsUpdateExprFound) {
13106 BinOp = dyn_cast<BinaryOperator>(
First);
13107 IsUpdateExprFound = BinOp && BinOp->
getOpcode() == BO_Assign;
13109 if (IsUpdateExprFound && !
SemaRef.CurContext->isDependentContext()) {
13119 llvm::FoldingSetNodeID XId, PossibleXId;
13120 Checker.getX()->Profile(XId, Context,
true);
13121 PossibleX->
Profile(PossibleXId, Context,
true);
13122 IsUpdateExprFound = XId == PossibleXId;
13123 if (IsUpdateExprFound) {
13125 X = Checker.getX();
13126 E = Checker.getExpr();
13127 UE = Checker.getUpdateExpr();
13132 if (!IsUpdateExprFound) {
13133 IsUpdateExprFound = !Checker.checkStatement(
First);
13135 if (IsUpdateExprFound) {
13136 BinOp = dyn_cast<BinaryOperator>(Second);
13137 IsUpdateExprFound = BinOp && BinOp->
getOpcode() == BO_Assign;
13139 if (IsUpdateExprFound &&
13140 !
SemaRef.CurContext->isDependentContext()) {
13150 llvm::FoldingSetNodeID XId, PossibleXId;
13151 Checker.getX()->Profile(XId, Context,
true);
13152 PossibleX->
Profile(PossibleXId, Context,
true);
13153 IsUpdateExprFound = XId == PossibleXId;
13154 if (IsUpdateExprFound) {
13156 X = Checker.getX();
13157 E = Checker.getExpr();
13158 UE = Checker.getUpdateExpr();
13164 if (!IsUpdateExprFound) {
13166 auto *FirstExpr = dyn_cast<Expr>(
First);
13167 auto *SecondExpr = dyn_cast<Expr>(Second);
13168 if (!FirstExpr || !SecondExpr ||
13169 !(FirstExpr->isInstantiationDependent() ||
13170 SecondExpr->isInstantiationDependent())) {
13171 auto *FirstBinOp = dyn_cast<BinaryOperator>(
First);
13172 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
13173 ErrorFound = NotAnAssignmentOp;
13174 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
13175 :
First->getBeginLoc();
13176 NoteRange = ErrorRange = FirstBinOp
13177 ? FirstBinOp->getSourceRange()
13180 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
13181 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
13182 ErrorFound = NotAnAssignmentOp;
13183 NoteLoc = ErrorLoc = SecondBinOp
13184 ? SecondBinOp->getOperatorLoc()
13186 NoteRange = ErrorRange =
13187 SecondBinOp ? SecondBinOp->getSourceRange()
13190 Expr *PossibleXRHSInFirst =
13192 Expr *PossibleXLHSInSecond =
13194 llvm::FoldingSetNodeID X1Id, X2Id;
13195 PossibleXRHSInFirst->
Profile(X1Id, Context,
13197 PossibleXLHSInSecond->
Profile(X2Id, Context,
13199 IsUpdateExprFound = X1Id == X2Id;
13200 if (IsUpdateExprFound) {
13201 V = FirstBinOp->getLHS();
13202 X = SecondBinOp->getLHS();
13203 E = SecondBinOp->getRHS();
13208 ErrorFound = NotASpecificExpression;
13209 ErrorLoc = FirstBinOp->getExprLoc();
13210 ErrorRange = FirstBinOp->getSourceRange();
13211 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
13212 NoteRange = SecondBinOp->getRHS()->getSourceRange();
13220 NoteRange = ErrorRange =
13222 ErrorFound = NotTwoSubstatements;
13226 NoteRange = ErrorRange =
13228 ErrorFound = NotACompoundStatement;
13231 if (ErrorFound != NoError) {
13232 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
13234 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13237 if (
SemaRef.CurContext->isDependentContext())
13238 UE =
V = E =
X =
nullptr;
13239 }
else if (AtomicKind == OMPC_compare) {
13240 if (IsCompareCapture) {
13241 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
13242 OpenMPAtomicCompareCaptureChecker Checker(
SemaRef);
13243 if (!Checker.checkStmt(Body, ErrorInfo)) {
13244 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
13245 << ErrorInfo.ErrorRange;
13246 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13247 << ErrorInfo.Error << ErrorInfo.NoteRange;
13250 X = Checker.getX();
13251 E = Checker.getE();
13252 D = Checker.getD();
13253 CE = Checker.getCond();
13254 V = Checker.getV();
13255 R = Checker.getR();
13261 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
13262 OpenMPAtomicCompareChecker Checker(
SemaRef);
13263 if (!Checker.checkStmt(Body, ErrorInfo)) {
13264 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
13265 << ErrorInfo.ErrorRange;
13266 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13267 << ErrorInfo.Error << ErrorInfo.NoteRange;
13270 X = Checker.getX();
13271 E = Checker.getE();
13272 D = Checker.getD();
13273 CE = Checker.getCond();
13279 auto *It = find_if(Clauses, [](
OMPClause *
C) {
13280 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
13282 if (It != Clauses.end()) {
13283 auto *
Cond = dyn_cast<BinaryOperator>(CE);
13284 if (
Cond->getOpcode() != BO_EQ) {
13285 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
13286 ErrorInfo.ErrorLoc =
Cond->getExprLoc();
13287 ErrorInfo.NoteLoc =
Cond->getOperatorLoc();
13288 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
Cond->getSourceRange();
13290 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
13291 << ErrorInfo.ErrorRange;
13300 SemaRef.setFunctionHasBranchProtectedScope();
13302 return OMPAtomicDirective::Create(
13303 Context, StartLoc, EndLoc, Clauses, AStmt,
13320 if (
DSAStack->hasInnerTeamsRegion()) {
13322 bool OMPTeamsFound =
true;
13323 if (
const auto *CS = dyn_cast<CompoundStmt>(S)) {
13324 auto I = CS->body_begin();
13325 while (I != CS->body_end()) {
13326 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
13328 if (!IsTeams || I != CS->body_begin()) {
13329 OMPTeamsFound =
false;
13330 if (IsTeams && I != CS->body_begin()) {
13339 assert(I != CS->body_end() &&
"Not found statement");
13342 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
13345 if (!OMPTeamsFound) {
13346 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
13348 diag::note_omp_nested_teams_construct_here);
13381 OMPLoopBasedDirective::HelperExprs B;
13384 unsigned NestedLoopCount =
13387 VarsWithImplicitDSA, B);
13388 if (NestedLoopCount == 0)
13395 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13402 return llvm::any_of(
13403 Clauses, [K](
const OMPClause *
C) {
return C->getClauseKind() == K; });
13406template <
typename... Params>
13408 const Params... ClauseTypes) {
13415 if (
auto *TC = dyn_cast<OMPToClause>(
C))
13416 return llvm::all_of(TC->all_decls(), [](
ValueDecl *VD) {
13417 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13418 (VD->isExternallyVisible() &&
13419 VD->getVisibility() != HiddenVisibility);
13421 else if (
auto *FC = dyn_cast<OMPFromClause>(
C))
13422 return llvm::all_of(FC->all_decls(), [](
ValueDecl *VD) {
13423 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13424 (VD->isExternallyVisible() &&
13425 VD->getVisibility() != HiddenVisibility);
13444 if (!
hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13446 !
hasClauses(Clauses, OMPC_use_device_addr))) {
13449 Expected =
"'map' or 'use_device_ptr'";
13451 Expected =
"'map', 'use_device_ptr', or 'use_device_addr'";
13453 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13454 <<
Expected << getOpenMPDirectiveName(OMPD_target_data, OMPVersion);
13458 SemaRef.setFunctionHasBranchProtectedScope();
13476 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13478 << getOpenMPDirectiveName(OMPD_target_enter_data, OMPVersion);
13498 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13499 <<
"'map'" << getOpenMPDirectiveName(OMPD_target_exit_data, OMPVersion);
13515 if (!
hasClauses(Clauses, OMPC_to, OMPC_from)) {
13516 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13521 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13531template <
typename ClauseType>
13534 unsigned MaxNum,
unsigned Diag) {
13535 auto ClauseItr = llvm::find_if(Clauses, llvm::IsaPred<ClauseType>);
13536 if (ClauseItr == Clauses.end())
13539 auto VarList =
C->getVarRefs();
13540 if (VarList.size() > MaxNum) {
13541 SemaRef.
Diag(VarList[MaxNum]->getBeginLoc(),
Diag)
13557 diag::err_omp_num_teams_multi_expr_not_allowed) ||
13559 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
13564 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13568 DSAStack->setParentTeamsRegionLoc(StartLoc);
13577 if (
DSAStack->isParentNowaitRegion()) {
13578 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13581 if (
DSAStack->isParentOrderedRegion()) {
13582 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13586 EndLoc, CancelRegion);
13592 if (
DSAStack->isParentNowaitRegion()) {
13593 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13596 if (
DSAStack->isParentOrderedRegion()) {
13597 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13600 DSAStack->setParentCancelRegion(
true);
13607 const OMPClause *ReductionClause =
nullptr;
13608 const OMPClause *NogroupClause =
nullptr;
13610 if (
C->getClauseKind() == OMPC_reduction) {
13611 ReductionClause =
C;
13616 if (
C->getClauseKind() == OMPC_nogroup) {
13618 if (ReductionClause)
13623 if (ReductionClause && NogroupClause) {
13624 S.
Diag(ReductionClause->
getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13639 OMPLoopBasedDirective::HelperExprs B;
13642 unsigned NestedLoopCount =
13645 *
DSAStack, VarsWithImplicitDSA, B);
13646 if (NestedLoopCount == 0)
13649 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13650 "omp for loop exprs were not built");
13656 {OMPC_grainsize, OMPC_num_tasks}))
13664 SemaRef.setFunctionHasBranchProtectedScope();
13666 NestedLoopCount, Clauses, AStmt, B,
13680 OMPLoopBasedDirective::HelperExprs B;
13683 unsigned NestedLoopCount =
13686 VarsWithImplicitDSA, B);
13687 if (NestedLoopCount == 0)
13697 {OMPC_grainsize, OMPC_num_tasks}))
13708 NestedLoopCount, Clauses, AStmt, B);
13718 OMPLoopBasedDirective::HelperExprs B;
13721 unsigned NestedLoopCount =
13724 *
DSAStack, VarsWithImplicitDSA, B);
13725 if (NestedLoopCount == 0)
13728 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13729 "omp for loop exprs were not built");
13735 {OMPC_grainsize, OMPC_num_tasks}))
13743 SemaRef.setFunctionHasBranchProtectedScope();
13745 NestedLoopCount, Clauses, AStmt, B,
13756 OMPLoopBasedDirective::HelperExprs B;
13759 unsigned NestedLoopCount =
13762 *
DSAStack, VarsWithImplicitDSA, B);
13763 if (NestedLoopCount == 0)
13766 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13767 "omp for loop exprs were not built");
13773 {OMPC_grainsize, OMPC_num_tasks}))
13781 SemaRef.setFunctionHasBranchProtectedScope();
13783 NestedLoopCount, Clauses, AStmt, B,
13797 OMPLoopBasedDirective::HelperExprs B;
13800 unsigned NestedLoopCount =
13803 VarsWithImplicitDSA, B);
13804 if (NestedLoopCount == 0)
13814 {OMPC_grainsize, OMPC_num_tasks}))
13825 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13838 OMPLoopBasedDirective::HelperExprs B;
13841 unsigned NestedLoopCount =
13844 VarsWithImplicitDSA, B);
13845 if (NestedLoopCount == 0)
13855 {OMPC_grainsize, OMPC_num_tasks}))
13866 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13878 OMPLoopBasedDirective::HelperExprs B;
13884 VarsWithImplicitDSA, B);
13885 if (NestedLoopCount == 0)
13888 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13889 "omp for loop exprs were not built");
13895 {OMPC_grainsize, OMPC_num_tasks}))
13904 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13917 OMPLoopBasedDirective::HelperExprs B;
13923 VarsWithImplicitDSA, B);
13924 if (NestedLoopCount == 0)
13927 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13928 "omp for loop exprs were not built");
13934 {OMPC_grainsize, OMPC_num_tasks}))
13943 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13954 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
13956 OMPLoopBasedDirective::HelperExprs B;
13962 VarsWithImplicitDSA, B);
13963 if (NestedLoopCount == 0)
13973 {OMPC_grainsize, OMPC_num_tasks}))
13984 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13994 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
13996 OMPLoopBasedDirective::HelperExprs B;
14002 VarsWithImplicitDSA, B);
14003 if (NestedLoopCount == 0)
14013 {OMPC_grainsize, OMPC_num_tasks}))
14024 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14034 OMPLoopBasedDirective::HelperExprs B;
14037 unsigned NestedLoopCount =
14041 if (NestedLoopCount == 0)
14044 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14045 "omp for loop exprs were not built");
14047 SemaRef.setFunctionHasBranchProtectedScope();
14049 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14050 return DistributeDirective;
14062 OMPLoopBasedDirective::HelperExprs B;
14068 VarsWithImplicitDSA, B);
14069 if (NestedLoopCount == 0)
14072 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14073 "omp for loop exprs were not built");
14076 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14087 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
14089 OMPLoopBasedDirective::HelperExprs B;
14095 VarsWithImplicitDSA, B);
14096 if (NestedLoopCount == 0)
14106 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14118 OMPLoopBasedDirective::HelperExprs B;
14121 unsigned NestedLoopCount =
14125 if (NestedLoopCount == 0)
14135 NestedLoopCount, Clauses, AStmt, B);
14147 OMPLoopBasedDirective::HelperExprs B;
14153 VarsWithImplicitDSA, B);
14154 if (NestedLoopCount == 0)
14164 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14175 OMPLoopBasedDirective::HelperExprs B;
14178 unsigned NestedLoopCount =
14181 VarsWithImplicitDSA, B);
14182 if (NestedLoopCount == 0)
14192 NestedLoopCount, Clauses, AStmt, B);
14204 OMPLoopBasedDirective::HelperExprs B;
14207 unsigned NestedLoopCount =
14211 if (NestedLoopCount == 0)
14214 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14215 "omp teams distribute loop exprs were not built");
14217 DSAStack->setParentTeamsRegionLoc(StartLoc);
14220 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14232 OMPLoopBasedDirective::HelperExprs B;
14238 VarsWithImplicitDSA, B);
14239 if (NestedLoopCount == 0)
14248 DSAStack->setParentTeamsRegionLoc(StartLoc);
14251 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14261 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
14263 OMPLoopBasedDirective::HelperExprs B;
14269 VarsWithImplicitDSA, B);
14270 if (NestedLoopCount == 0)
14279 DSAStack->setParentTeamsRegionLoc(StartLoc);
14282 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14292 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
14294 OMPLoopBasedDirective::HelperExprs B;
14300 VarsWithImplicitDSA, B);
14302 if (NestedLoopCount == 0)
14305 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14306 "omp for loop exprs were not built");
14308 DSAStack->setParentTeamsRegionLoc(StartLoc);
14311 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14324 bool HasThreadLimitAndNumTeamsClause =
hasClauses(Clauses, OMPC_num_teams) &&
14326 bool HasBareClause = llvm::any_of(Clauses, [&](
const OMPClause *
C) {
14328 return C->getClauseKind() == OMPC_ompx_bare;
14331 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
14336 unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 2;
14337 unsigned NumTeamsDiag = HasBareClause
14338 ? diag::err_ompx_more_than_three_expr_not_allowed
14339 : diag::err_omp_num_teams_multi_expr_not_allowed;
14340 unsigned ThreadLimitDiag =
14341 HasBareClause ? diag::err_ompx_more_than_three_expr_not_allowed
14342 : diag::err_omp_multi_expr_not_allowed;
14345 *
this, Clauses, ClauseMaxNumExprs, NumTeamsDiag) ||
14347 *
this, Clauses, ClauseMaxNumExprs, ThreadLimitDiag)) {
14362 diag::err_omp_num_teams_multi_expr_not_allowed) ||
14364 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14370 OMPLoopBasedDirective::HelperExprs B;
14376 VarsWithImplicitDSA, B);
14377 if (NestedLoopCount == 0)
14380 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14381 "omp target teams distribute loop exprs were not built");
14384 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14395 diag::err_omp_num_teams_multi_expr_not_allowed) ||
14397 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14401 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
14403 OMPLoopBasedDirective::HelperExprs B;
14409 VarsWithImplicitDSA, B);
14410 if (NestedLoopCount == 0)
14417 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14429 diag::err_omp_num_teams_multi_expr_not_allowed) ||
14431 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14435 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
14437 OMPLoopBasedDirective::HelperExprs B;
14440 unsigned NestedLoopCount =
14445 if (NestedLoopCount == 0)
14455 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14466 diag::err_omp_num_teams_multi_expr_not_allowed) ||
14468 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14472 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
14474 OMPLoopBasedDirective::HelperExprs B;
14480 VarsWithImplicitDSA, B);
14481 if (NestedLoopCount == 0)
14491 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14498 Stmt *Dir = Transform->getDirective();
14500#define STMT(CLASS, PARENT)
14501#define ABSTRACT_STMT(CLASS)
14502#define COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT) \
14503 case Stmt::CLASS##Class: \
14504 appendFlattenedStmtList(PreInits, \
14505 static_cast<const CLASS *>(Dir)->getPreInits()); \
14507#define OMPCANONICALLOOPNESTTRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14508 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14509#define OMPCANONICALLOOPSEQUENCETRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14510 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14511#include "clang/AST/StmtNodes.inc"
14512#undef COMMON_OMP_LOOP_TRANSFORMATION
14514 llvm_unreachable(
"Not a loop transformation");
14518bool SemaOpenMP::checkTransformableLoopNest(
14522 OriginalInits.emplace_back();
14523 bool Result = OMPLoopBasedDirective::doForAllLoops(
14525 [
this, &LoopHelpers, &Body, &OriginalInits, Kind](
unsigned Cnt,
14527 VarsWithInheritedDSAType TmpDSA;
14528 unsigned SingleNumLoops =
14529 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
14530 TmpDSA, LoopHelpers[Cnt]);
14531 if (SingleNumLoops == 0)
14533 assert(SingleNumLoops == 1 &&
"Expect single loop iteration space");
14534 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14535 OriginalInits.back().push_back(For->getInit());
14536 Body = For->getBody();
14538 assert(isa<CXXForRangeStmt>(CurStmt) &&
14539 "Expected canonical for or range-based for loops.");
14540 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14541 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14542 Body = CXXFor->getBody();
14544 OriginalInits.emplace_back();
14547 [&OriginalInits](OMPLoopTransformationDirective *Transform) {
14550 assert(OriginalInits.back().empty() &&
"No preinit after innermost loop");
14551 OriginalInits.pop_back();
14589 unsigned NestedLoopCount = 0;
14636bool SemaOpenMP::analyzeLoopSequence(
Stmt *LoopSeqStmt,
14637 LoopSequenceAnalysis &SeqAnalysis,
14643 auto StoreLoopStatements = [](LoopAnalysis &Analysis, Stmt *LoopStmt) {
14644 if (
auto *For = dyn_cast<ForStmt>(LoopStmt)) {
14645 Analysis.OriginalInits.push_back(For->getInit());
14646 Analysis.TheForStmt = For;
14649 Analysis.OriginalInits.push_back(CXXFor->getBeginStmt());
14650 Analysis.TheForStmt = CXXFor;
14657 auto AnalyzeLoopGeneration = [&](Stmt *Child) {
14659 Stmt *TransformedStmt = LoopTransform->getTransformedStmt();
14660 unsigned NumGeneratedTopLevelLoops =
14661 LoopTransform->getNumGeneratedTopLevelLoops();
14664 if (!TransformedStmt) {
14665 if (NumGeneratedTopLevelLoops > 0) {
14666 SeqAnalysis.LoopSeqSize += NumGeneratedTopLevelLoops;
14670 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14671 << 0 << getOpenMPDirectiveName(Kind);
14676 if (!NumGeneratedTopLevelLoops) {
14677 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14678 << 0 << getOpenMPDirectiveName(Kind);
14682 if (NumGeneratedTopLevelLoops > 1) {
14689 updatePreInits(LoopTransform, SeqAnalysis.LoopSequencePreInits);
14690 return analyzeLoopSequence(TransformedStmt, SeqAnalysis, Context, Kind);
14694 LoopAnalysis &NewTransformedSingleLoop =
14695 SeqAnalysis.Loops.emplace_back(Child);
14698 NewTransformedSingleLoop.HelperExprs);
14703 StoreLoopStatements(NewTransformedSingleLoop, TransformedStmt);
14704 updatePreInits(LoopTransform, NewTransformedSingleLoop.TransformsPreInits);
14706 SeqAnalysis.LoopSeqSize++;
14711 auto AnalyzeRegularLoop = [&](Stmt *Child) {
14712 LoopAnalysis &NewRegularLoop = SeqAnalysis.Loops.emplace_back(Child);
14713 unsigned IsCanonical =
14715 TmpDSA, NewRegularLoop.HelperExprs);
14720 StoreLoopStatements(NewRegularLoop, Child);
14721 NestedLoopCounterVisitor NLCV;
14727 for (Stmt *Child : LoopSeqStmt->
children()) {
14731 if (!LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
14732 Child = Child->IgnoreContainers();
14739 if (!analyzeLoopSequence(Child, SeqAnalysis, Context, Kind))
14746 if (LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
14747 if (LoopAnalysis::isLoopTransformation(Child)) {
14748 if (!AnalyzeLoopGeneration(Child))
14752 if (!AnalyzeRegularLoop(Child))
14754 SeqAnalysis.LoopSeqSize++;
14758 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14759 << 0 << getOpenMPDirectiveName(Kind);
14766bool SemaOpenMP::checkTransformableLoopSequence(
14791 << getOpenMPDirectiveName(Kind);
14796 if (!analyzeLoopSequence(AStmt, SeqAnalysis, Context, Kind))
14800 if (!SeqAnalysis.LoopSeqSize) {
14802 << getOpenMPDirectiveName(Kind);
14810 OMPLoopBasedDirective::HelperExprs &LoopHelper,
14816 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
14817 Stmt *RangeInit = CXXRangeFor->getInit();
14819 PreInits.push_back(RangeInit);
14821 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14826 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14832 llvm::append_range(PreInits, OriginalInit);
14835 if (
auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits)) {
14836 PreInits.push_back(
new (Context)
DeclStmt(
14837 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14841 for (
Expr *CounterRef : LoopHelper.Counters) {
14844 PreInits.push_back(
new (Context)
DeclStmt(
14852 size_t NumLoops = LoopStmts.size();
14853 OMPLoopBasedDirective::doForAllLoops(
14854 AStmt,
false, NumLoops,
14855 [LoopStmts](
unsigned Cnt,
Stmt *CurStmt) {
14856 assert(!LoopStmts[Cnt] &&
"Loop statement must not yet be assigned");
14857 LoopStmts[Cnt] = CurStmt;
14860 assert(!is_contained(LoopStmts,
nullptr) &&
14861 "Expecting a loop statement for each affected loop");
14879 const auto *SizesClause =
14880 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14881 if (!SizesClause ||
14882 llvm::any_of(SizesClause->getSizesRefs(), [](
Expr *E) { return !E; }))
14884 unsigned NumLoops = SizesClause->getNumSizes();
14892 Stmt *Body =
nullptr;
14894 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14899 if (
SemaRef.CurContext->isDependentContext())
14901 NumLoops, AStmt,
nullptr,
nullptr);
14903 assert(LoopHelpers.size() == NumLoops &&
14904 "Expecting loop iteration space dimensionality to match number of "
14906 assert(OriginalInits.size() == NumLoops &&
14907 "Expecting loop iteration space dimensionality to match number of "
14915 CaptureVars CopyTransformer(
SemaRef);
14920 FloorIndVars.resize(NumLoops);
14921 TileIndVars.resize(NumLoops);
14922 for (
unsigned I = 0; I < NumLoops; ++I) {
14923 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14925 assert(LoopHelper.Counters.size() == 1 &&
14926 "Expect single-dimensional loop iteration space");
14928 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14934 std::string FloorCntName =
14935 (Twine(
".floor_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
14938 FloorIndVars[I] = FloorCntDecl;
14943 std::string TileCntName =
14944 (Twine(
".tile_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
14950 TileCntDecl->setDeclName(
14951 &
SemaRef.PP.getIdentifierTable().get(TileCntName));
14952 TileIndVars[I] = TileCntDecl;
14960 Stmt *Inner = Body;
14962 auto MakeDimTileSize = [&
SemaRef = this->SemaRef, &CopyTransformer, &Context,
14963 SizesClause, CurScope](
int I) ->
Expr * {
14964 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
14970 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
14989 uint64_t DimWidth = Context.getTypeSize(DimTy);
14991 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14995 CurScope, {}, BO_LE,
14999 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
15005 for (
int I = NumLoops - 1; I >= 0; --I) {
15006 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15007 Expr *NumIterations = LoopHelper.NumIterations;
15010 Stmt *LoopStmt = LoopStmts[I];
15015 auto MakeTileIVRef = [&
SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
15018 OrigCntVar->getExprLoc());
15022 SemaRef.AddInitializerToDecl(
15025 .DefaultLvalueConversion(
15029 Decl *CounterDecl = TileIndVars[I];
15032 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15038 Expr *DimTileSize = MakeDimTileSize(I);
15042 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15048 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15049 NumIterations, EndOfTile.
get());
15053 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
15054 IsPartialTile.
get(), NumIterations, EndOfTile.
get());
15055 if (!MinTileAndIterSpace.
isUsable())
15058 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15059 MakeTileIVRef(), MinTileAndIterSpace.
get());
15065 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef());
15086 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15087 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15088 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15089 BodyParts.push_back(Inner);
15092 Inner =
new (Context)
15095 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15099 for (
int I = NumLoops - 1; I >= 0; --I) {
15100 auto &LoopHelper = LoopHelpers[I];
15101 Expr *NumIterations = LoopHelper.NumIterations;
15106 SemaRef.AddInitializerToDecl(
15108 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15110 Decl *CounterDecl = FloorIndVars[I];
15119 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15126 Expr *DimTileSize = MakeDimTileSize(I);
15130 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15136 Inner =
new (Context)
15139 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15154 const auto *SizesClause =
15155 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
15156 if (!SizesClause ||
15157 llvm::any_of(SizesClause->getSizesRefs(), [](
const Expr *SizeExpr) {
15158 return !SizeExpr || SizeExpr->containsErrors();
15161 unsigned NumLoops = SizesClause->getNumSizes();
15169 Stmt *Body =
nullptr;
15171 if (!checkTransformableLoopNest(OMPD_stripe, AStmt, NumLoops, LoopHelpers,
15172 Body, OriginalInits))
15176 if (
SemaRef.CurContext->isDependentContext())
15178 NumLoops, AStmt,
nullptr,
nullptr);
15180 assert(LoopHelpers.size() == NumLoops &&
15181 "Expecting loop iteration space dimensionality to match number of "
15183 assert(OriginalInits.size() == NumLoops &&
15184 "Expecting loop iteration space dimensionality to match number of "
15192 CaptureVars CopyTransformer(
SemaRef);
15197 FloorIndVars.resize(NumLoops);
15198 StripeIndVars.resize(NumLoops);
15199 for (
unsigned I : llvm::seq<unsigned>(NumLoops)) {
15200 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15202 assert(LoopHelper.Counters.size() == 1 &&
15203 "Expect single-dimensional loop iteration space");
15205 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15211 std::string FloorCntName =
15212 (Twine(
".floor_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
15215 FloorIndVars[I] = FloorCntDecl;
15220 std::string StripeCntName =
15221 (Twine(
".stripe_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
15227 StripeCntDecl->setDeclName(
15228 &
SemaRef.PP.getIdentifierTable().get(StripeCntName));
15229 StripeIndVars[I] = StripeCntDecl;
15237 Stmt *Inner = Body;
15239 auto MakeDimStripeSize = [&](
int I) ->
Expr * {
15240 Expr *DimStripeSizeExpr = SizesClause->getSizesRefs()[I];
15242 return AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr));
15261 uint64_t DimWidth = Context.getTypeSize(DimTy);
15263 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
15267 CurScope, {}, BO_LE,
15271 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), DimTy,
15277 for (
int I = NumLoops - 1; I >= 0; --I) {
15278 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15279 Expr *NumIterations = LoopHelper.NumIterations;
15282 Stmt *LoopStmt = LoopStmts[I];
15285 SemaRef.AddInitializerToDecl(
15288 .DefaultLvalueConversion(
15292 Decl *CounterDecl = StripeIndVars[I];
15295 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15302 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15304 MakeDimStripeSize(I));
15308 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15309 NumIterations, EndOfStripe.
get());
15313 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
15314 IsPartialStripe.
get(), NumIterations, EndOfStripe.
get());
15315 if (!MinStripeAndIterSpace.
isUsable())
15318 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15320 MinStripeAndIterSpace.
get());
15326 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc,
15348 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15349 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15350 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15351 BodyParts.push_back(Inner);
15354 Inner =
new (Context)
15357 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15361 for (
int I = NumLoops - 1; I >= 0; --I) {
15362 auto &LoopHelper = LoopHelpers[I];
15363 Expr *NumIterations = LoopHelper.NumIterations;
15368 SemaRef.AddInitializerToDecl(
15370 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15372 Decl *CounterDecl = FloorIndVars[I];
15381 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15389 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15391 MakeDimStripeSize(I));
15395 Inner =
new (Context)
15398 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15402 NumLoops, AStmt, Inner,
15417 {OMPC_partial, OMPC_full}))
15421 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
15423 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
15424 assert(!(FullClause && PartialClause) &&
15425 "mutual exclusivity must have been checked before");
15427 constexpr unsigned NumLoops = 1;
15428 Stmt *Body =
nullptr;
15432 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
15433 Body, OriginalInits))
15436 unsigned NumGeneratedTopLevelLoops = PartialClause ? 1 : 0;
15439 if (
SemaRef.CurContext->isDependentContext())
15441 NumGeneratedTopLevelLoops,
nullptr,
15444 assert(LoopHelpers.size() == NumLoops &&
15445 "Expecting a single-dimensional loop iteration space");
15446 assert(OriginalInits.size() == NumLoops &&
15447 "Expecting a single-dimensional loop iteration space");
15448 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15452 LoopHelper.NumIterations, OMPC_full,
false,
15455 Diag(AStmt->
getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
15457 <<
"#pragma omp unroll full";
15465 if (NumGeneratedTopLevelLoops == 0)
15467 NumGeneratedTopLevelLoops,
nullptr,
15513 Stmt *LoopStmt =
nullptr;
15518 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15521 QualType IVTy = IterationVarRef->getType();
15522 assert(LoopHelper.Counters.size() == 1 &&
15523 "Expecting a single-dimensional loop iteration space");
15531 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
15532 FactorLoc = FactorVal->getExprLoc();
15537 assert(Factor > 0 &&
"Expected positive unroll factor");
15538 auto MakeFactorExpr = [
this, Factor, IVTy, FactorLoc]() {
15550 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15551 std::string OuterIVName = (Twine(
".unrolled.iv.") + OrigVarName).str();
15552 std::string InnerIVName = (Twine(
".unroll_inner.iv.") + OrigVarName).str();
15557 auto MakeOuterRef = [
this, OuterIVDecl, IVTy, OrigVarLoc]() {
15563 auto *InnerIVDecl =
cast<VarDecl>(IterationVarRef->getDecl());
15564 InnerIVDecl->setDeclName(&
SemaRef.PP.getIdentifierTable().get(InnerIVName));
15565 auto MakeInnerRef = [
this, InnerIVDecl, IVTy, OrigVarLoc]() {
15571 CaptureVars CopyTransformer(
SemaRef);
15572 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() ->
Expr * {
15574 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15579 SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.
get(),
15594 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15595 MakeOuterRef(), MakeFactorExpr());
15599 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15600 MakeInnerRef(), EndOfTile.
get());
15604 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15605 MakeInnerRef(), MakeNumIterations());
15609 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
15610 InnerCond1.
get(), InnerCond2.
get());
15616 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef());
15622 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15623 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15624 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15625 InnerBodyStmts.push_back(Body);
15629 ForStmt *InnerFor =
new (Context)
15630 ForStmt(Context, InnerInit.
get(), InnerCond.
get(),
nullptr,
15632 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15646 LoopHintAttr *UnrollHintAttr =
15647 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
15648 LoopHintAttr::Numeric, MakeFactorExpr());
15653 SemaRef.AddInitializerToDecl(
15655 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15664 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15665 MakeOuterRef(), MakeNumIterations());
15671 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15672 MakeOuterRef(), MakeFactorExpr());
15677 ForStmt *OuterFor =
new (Context)
15678 ForStmt(Context, OuterInit.
get(), OuterConde.
get(),
nullptr,
15680 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15683 NumGeneratedTopLevelLoops, OuterFor,
15697 constexpr unsigned NumLoops = 1;
15698 Stmt *Body =
nullptr;
15702 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
15703 Body, OriginalInits))
15708 if (
SemaRef.CurContext->isDependentContext())
15710 NumLoops,
nullptr,
nullptr);
15712 assert(LoopHelpers.size() == NumLoops &&
15713 "Expecting a single-dimensional loop iteration space");
15714 assert(OriginalInits.size() == NumLoops &&
15715 "Expecting a single-dimensional loop iteration space");
15716 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15719 Stmt *LoopStmt =
nullptr;
15724 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15727 QualType IVTy = IterationVarRef->getType();
15728 uint64_t IVWidth = Context.getTypeSize(IVTy);
15742 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15744 ForwardIVName += OrigVarName;
15746 ReversedIVName += OrigVarName;
15779 CaptureVars CopyTransformer(
SemaRef);
15780 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() ->
Expr * {
15782 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15788 auto MakeForwardRef = [&
SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
15795 auto *ReversedIVDecl =
cast<VarDecl>(IterationVarRef->getDecl());
15796 ReversedIVDecl->setDeclName(
15797 &
SemaRef.PP.getIdentifierTable().get(ReversedIVName));
15804 ForwardIVDecl->
getType(), OrigVarLoc);
15805 SemaRef.AddInitializerToDecl(ForwardIVDecl,
Zero,
false);
15808 if (!
Init.isUsable())
15816 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15817 MakeForwardRef(), MakeNumIterations());
15818 if (!
Cond.isUsable())
15826 UO_PreInc, MakeForwardRef());
15837 MakeNumIterations(), One);
15840 Minus =
SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, Minus.
get(),
15845 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
15848 SemaRef.AddInitializerToDecl(ReversedIVDecl, Minus.
get(),
15853 BodyStmts.reserve(LoopHelper.Updates.size() + 2 +
15855 BodyStmts.push_back(InitReversed.
get());
15856 llvm::append_range(BodyStmts, LoopHelper.Updates);
15857 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15858 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15859 BodyStmts.push_back(Body);
15860 auto *ReversedBody =
15865 auto *ReversedFor =
new (Context)
15868 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15887 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
15888 size_t NumLoops = PermutationClause ? PermutationClause->
getNumLoops() : 2;
15892 Stmt *Body =
nullptr;
15894 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
15895 LoopHelpers, Body, OriginalInits))
15901 NumLoops, AStmt,
nullptr,
nullptr);
15905 if (PermutationClause &&
15906 llvm::is_contained(PermutationClause->
getArgsRefs(),
nullptr))
15909 assert(LoopHelpers.size() == NumLoops &&
15910 "Expecting loop iteration space dimensionaly to match number of "
15912 assert(OriginalInits.size() == NumLoops &&
15913 "Expecting loop iteration space dimensionaly to match number of "
15918 if (!PermutationClause) {
15919 Permutation = {1, 0};
15922 llvm::BitVector Flags(PermArgs.size());
15923 for (
Expr *PermArg : PermArgs) {
15924 std::optional<llvm::APSInt> PermCstExpr =
15925 PermArg->getIntegerConstantExpr(Context);
15928 uint64_t PermInt = PermCstExpr->getZExtValue();
15929 assert(1 <= PermInt && PermInt <= NumLoops &&
15930 "Must be a permutation; diagnostic emitted in "
15931 "ActOnOpenMPPermutationClause");
15932 if (Flags[PermInt - 1]) {
15933 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
15934 Diag(PermArg->getExprLoc(),
15935 diag::err_omp_interchange_permutation_value_repeated)
15936 << PermInt << ExprRange;
15939 Flags[PermInt - 1] =
true;
15941 Permutation.push_back(PermInt - 1);
15944 if (Permutation.size() != NumLoops)
15949 if (NumLoops <= 1 || llvm::all_of(llvm::enumerate(Permutation), [](
auto P) {
15950 auto [Idx, Arg] = P;
15954 NumLoops, AStmt, AStmt,
nullptr);
15962 for (
auto I : llvm::seq<int>(NumLoops)) {
15963 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15965 assert(LoopHelper.Counters.size() == 1 &&
15966 "Single-dimensional loop iteration space expected");
15973 CaptureVars CopyTransformer(
SemaRef);
15978 Stmt *Inner = Body;
15979 for (
auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
15981 uint64_t SourceIdx = Permutation[TargetIdx];
15982 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
15983 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
15984 assert(SourceHelper.Counters.size() == 1 &&
15985 "Single-dimensional loop iteration space expected");
15992 "Expected the logical iteration counter to be an integer");
15994 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15999 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() ->
Expr * {
16001 CopyTransformer.TransformExpr(SourceHelper.NumIterations));
16008 PermutedCntName.append({llvm::utostr(TargetIdx),
".iv.", OrigVarName});
16010 PermutedCntDecl->setDeclName(
16011 &
SemaRef.PP.getIdentifierTable().get(PermutedCntName));
16012 PermutedIndVars[TargetIdx] = PermutedCntDecl;
16013 auto MakePermutedRef = [
this, PermutedCntDecl, IVTy, OrigVarLoc]() {
16022 if (!
Zero.isUsable())
16024 SemaRef.AddInitializerToDecl(PermutedCntDecl,
Zero.get(),
16028 OrigCntVar->getEndLoc());
16037 SemaRef.BuildBinOp(CurScope, SourceHelper.Cond->getExprLoc(), BO_LT,
16038 MakePermutedRef(), MakeNumIterations());
16047 CurScope, SourceHelper.Inc->getExprLoc(), UO_PreInc, MakePermutedRef());
16052 SourceHelper.Updates.end());
16053 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
16054 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
16055 BodyParts.push_back(Inner);
16058 Inner =
new (Context)
ForStmt(
16059 Context, InitStmt.
get(), CondExpr.
get(),
nullptr, IncrStmt.
get(), Inner,
16060 SourceHelper.Init->
getBeginLoc(), SourceHelper.Init->getBeginLoc(),
16061 SourceHelper.Inc->getEndLoc());
16065 NumLoops, AStmt, Inner,
16077 CaptureVars CopyTransformer(
SemaRef);
16089 1, AStmt,
nullptr,
nullptr);
16093 LoopSequenceAnalysis SeqAnalysis;
16094 if (!checkTransformableLoopSequence(OMPD_fuse, AStmt, SeqAnalysis, Context))
16099 assert(SeqAnalysis.LoopSeqSize == SeqAnalysis.Loops.size() &&
16100 "Inconsistent size of the loop sequence and the number of loops "
16101 "found in the sequence");
16105 OMPExecutableDirective::getSingleClause<OMPLoopRangeClause>(Clauses);
16109 if (LRC && (!LRC->getFirst() || !LRC->getCount()))
16114 auto EvaluateLoopRangeArguments = [&Context](
Expr *
First,
Expr *Count,
16115 uint64_t &FirstVal,
16116 uint64_t &CountVal) {
16117 llvm::APSInt FirstInt =
First->EvaluateKnownConstInt(Context);
16118 llvm::APSInt CountInt = Count->EvaluateKnownConstInt(Context);
16119 FirstVal = FirstInt.getZExtValue();
16120 CountVal = CountInt.getZExtValue();
16126 auto ValidLoopRange = [](uint64_t FirstVal, uint64_t CountVal,
16127 unsigned NumLoops) ->
bool {
16128 return FirstVal + CountVal - 1 <= NumLoops;
16130 uint64_t FirstVal = 1, CountVal = 0, LastVal = SeqAnalysis.LoopSeqSize;
16136 EvaluateLoopRangeArguments(LRC->getFirst(), LRC->getCount(), FirstVal,
16139 SemaRef.Diag(LRC->getCountLoc(), diag::warn_omp_redundant_fusion)
16140 << getOpenMPDirectiveName(OMPD_fuse);
16142 if (!ValidLoopRange(FirstVal, CountVal, SeqAnalysis.LoopSeqSize)) {
16143 SemaRef.Diag(LRC->getFirstLoc(), diag::err_omp_invalid_looprange)
16144 << getOpenMPDirectiveName(OMPD_fuse) << FirstVal
16145 << (FirstVal + CountVal - 1) << SeqAnalysis.LoopSeqSize;
16149 LastVal = FirstVal + CountVal - 1;
16154 unsigned NumGeneratedTopLevelLoops =
16155 LRC ? SeqAnalysis.LoopSeqSize - CountVal + 1 : 1;
16159 if (SeqAnalysis.LoopSeqSize == 1)
16161 << getOpenMPDirectiveName(OMPD_fuse);
16165 SeqAnalysis.Loops[FirstVal - 1].HelperExprs.IterationVarRef->getType();
16166 for (
unsigned I : llvm::seq<unsigned>(FirstVal, LastVal)) {
16168 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef->getType();
16169 if (Context.getTypeSize(CurrentIVType) > Context.getTypeSize(IVType)) {
16170 IVType = CurrentIVType;
16173 uint64_t IVBitWidth = Context.getIntWidth(IVType);
16186 auto CreateHelperVarAndStmt =
16188 unsigned I,
bool NeedsNewVD =
false) {
16189 Expr *TransformedExpr =
16191 if (!TransformedExpr)
16192 return std::pair<VarDecl *, StmtResult>(
nullptr,
StmtError());
16194 auto Name = (Twine(
".omp.") + BaseName + std::to_string(I)).str();
16199 SemaRef.AddInitializerToDecl(VD, TransformedExpr,
false);
16209 return std::make_pair(VD,
DeclStmt);
16227 llvm::append_range(PreInits, SeqAnalysis.LoopSequencePreInits);
16240 unsigned int TransformIndex = 0;
16241 for (
unsigned I : llvm::seq<unsigned>(FirstVal - 1)) {
16242 if (SeqAnalysis.Loops[I].isLoopTransformation())
16246 for (
unsigned int I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16247 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16249 SeqAnalysis.Loops[I].TheForStmt,
16250 SeqAnalysis.Loops[I].OriginalInits, PreInits);
16251 }
else if (SeqAnalysis.Loops[I].isLoopTransformation()) {
16256 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16257 llvm::append_range(PreInits, TransformPreInit);
16260 SeqAnalysis.Loops[I].TheForStmt,
16261 SeqAnalysis.Loops[I].OriginalInits, PreInits);
16263 auto [UBVD, UBDStmt] =
16264 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.UB,
"ub", J);
16265 auto [LBVD, LBDStmt] =
16266 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.LB,
"lb", J);
16267 auto [STVD, STDStmt] =
16268 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.ST,
"st", J);
16269 auto [NIVD, NIDStmt] = CreateHelperVarAndStmt(
16270 SeqAnalysis.Loops[I].HelperExprs.NumIterations,
"ni", J,
true);
16271 auto [IVVD, IVDStmt] = CreateHelperVarAndStmt(
16272 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef,
"iv", J);
16274 assert(LBVD && STVD && NIVD && IVVD &&
16275 "OpenMP Fuse Helper variables creation failed");
16277 UBVarDecls.push_back(UBVD);
16278 LBVarDecls.push_back(LBVD);
16279 STVarDecls.push_back(STVD);
16280 NIVarDecls.push_back(NIVD);
16281 IVVarDecls.push_back(IVVD);
16283 PreInits.push_back(LBDStmt.get());
16284 PreInits.push_back(STDStmt.get());
16285 PreInits.push_back(NIDStmt.get());
16286 PreInits.push_back(IVDStmt.get());
16319 StringRef IndexName =
".omp.fuse.index";
16324 SemaRef.AddInitializerToDecl(IndexDecl, InitVal,
false);
16331 auto MakeIVRef = [&
SemaRef = this->SemaRef, IndexDecl, IVType,
16349 for (
unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16350 DeclRefExpr *NIRef = MakeVarDeclRef(NIVarDecls[J]);
16358 std::string TempName = (Twine(
".omp.temp.") + Twine(J)).str();
16372 PreInits.push_back(TempStmt.
get());
16381 DeclRefExpr *NIRef2 = MakeVarDeclRef(NIVarDecls[J]);
16395 const std::string MaxName = Twine(
".omp.fuse.max").str();
16403 if (MaxStmt.isInvalid())
16405 PreInits.push_back(MaxStmt.get());
16409 MakeIVRef(), MaxRef);
16435 for (
unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16440 MakeVarDeclRef(STVarDecls[J]), MakeIVRef());
16444 MakeVarDeclRef(LBVarDecls[J]), IdxExpr.
get());
16449 MakeVarDeclRef(IVVarDecls[J]), IdxExpr.
get());
16455 BodyStmts.push_back(IdxExpr.
get());
16456 llvm::append_range(BodyStmts, SeqAnalysis.Loops[I].HelperExprs.Updates);
16459 if (
auto *SourceCXXFor =
16460 dyn_cast<CXXForRangeStmt>(SeqAnalysis.Loops[I].TheForStmt))
16461 BodyStmts.push_back(SourceCXXFor->getLoopVarStmt());
16465 ?
cast<ForStmt>(SeqAnalysis.Loops[I].TheForStmt)->getBody()
16467 BodyStmts.push_back(Body);
16474 MakeVarDeclRef(NIVarDecls[J]));
16484 FusedBodyStmts.push_back(IfStatement);
16490 ForStmt *FusedForStmt =
new (Context)
16504 Stmt *FusionStmt = FusedForStmt;
16505 if (LRC && CountVal != SeqAnalysis.LoopSeqSize) {
16509 TransformIndex = 0;
16515 for (
unsigned I : llvm::seq<unsigned>(SeqAnalysis.LoopSeqSize)) {
16516 if (I >= FirstVal - 1 && I < FirstVal + CountVal - 1) {
16519 if (!SeqAnalysis.Loops[I].isLoopTransformation())
16528 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16529 const auto &TransformPreInit =
16530 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16531 if (!TransformPreInit.empty())
16532 llvm::append_range(PreInits, TransformPreInit);
16535 FinalLoops.push_back(SeqAnalysis.Loops[I].TheForStmt);
16538 FinalLoops.insert(FinalLoops.begin() + (FirstVal - 1), FusedForStmt);
16543 NumGeneratedTopLevelLoops, AStmt, FusionStmt,
16563 case OMPC_allocator:
16566 case OMPC_collapse:
16575 case OMPC_priority:
16587 case OMPC_novariants:
16590 case OMPC_nocontext:
16605 case OMPC_ompx_dyn_cgroup_mem:
16611 case OMPC_transparent:
16614 case OMPC_dyn_groupprivate:
16615 case OMPC_grainsize:
16616 case OMPC_num_tasks:
16617 case OMPC_num_threads:
16621 case OMPC_proc_bind:
16622 case OMPC_schedule:
16624 case OMPC_firstprivate:
16625 case OMPC_lastprivate:
16627 case OMPC_reduction:
16628 case OMPC_task_reduction:
16629 case OMPC_in_reduction:
16633 case OMPC_copyprivate:
16635 case OMPC_mergeable:
16636 case OMPC_threadprivate:
16637 case OMPC_groupprivate:
16639 case OMPC_allocate:
16656 case OMPC_dist_schedule:
16657 case OMPC_defaultmap:
16662 case OMPC_use_device_ptr:
16663 case OMPC_use_device_addr:
16664 case OMPC_is_device_ptr:
16665 case OMPC_unified_address:
16666 case OMPC_unified_shared_memory:
16667 case OMPC_reverse_offload:
16668 case OMPC_dynamic_allocators:
16669 case OMPC_atomic_default_mem_order:
16670 case OMPC_self_maps:
16671 case OMPC_device_type:
16673 case OMPC_nontemporal:
16676 case OMPC_severity:
16678 case OMPC_inclusive:
16679 case OMPC_exclusive:
16680 case OMPC_uses_allocators:
16681 case OMPC_affinity:
16684 case OMPC_num_teams:
16685 case OMPC_thread_limit:
16687 llvm_unreachable(
"Clause is not allowed.");
16700 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
16701 "Invalid directive with CKind-clause");
16704 if (NameModifier != OMPD_unknown &&
16705 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
16706 return OMPD_unknown;
16725 case OMPD_teams_loop:
16726 case OMPD_target_teams_loop:
16730 case OMPD_target_update:
16731 case OMPD_target_enter_data:
16732 case OMPD_target_exit_data:
16738 case OMPC_num_teams:
16739 case OMPC_thread_limit:
16740 case OMPC_ompx_dyn_cgroup_mem:
16741 case OMPC_dyn_groupprivate:
16743 if (Leafs[0] == OMPD_target)
16744 return OMPD_target;
16747 if (Leafs[0] == OMPD_target ||
16748 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
16749 OMPD_target_enter_data, OMPD_target_exit_data},
16753 case OMPC_novariants:
16754 case OMPC_nocontext:
16755 if (DKind == OMPD_dispatch)
16759 if (DKind == OMPD_metadirective)
16760 return OMPD_metadirective;
16763 return OMPD_unknown;
16776 int InnermostIdx = [&]() {
16777 for (
int I = EndIdx - 1; I >= 0; --I) {
16778 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
16786 for (
int I = InnermostIdx - 1; I >= 0; --I) {
16791 if (Regions[0] != OMPD_unknown)
16792 return Regions.back();
16794 return OMPD_unknown;
16799 for (
int I = 0, E = Leafs.size(); I != E; ++I) {
16800 if (Leafs[I] == Dir)
16806 int End = NameModifier == OMPD_unknown ? Leafs.size()
16807 : GetLeafIndex(NameModifier);
16808 return GetEnclosingRegion(End, CKind);
16811 return OMPD_unknown;
16819 Stmt *HelperValStmt =
nullptr;
16822 !
Condition->isInstantiationDependent() &&
16823 !
Condition->containsUnexpandedParameterPack()) {
16828 ValExpr = Val.
get();
16832 DKind, OMPC_if,
getLangOpts().OpenMP, NameModifier);
16833 if (CaptureRegion != OMPD_unknown &&
16834 !
SemaRef.CurContext->isDependentContext()) {
16835 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
16836 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16837 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16843 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
16844 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
16852 Stmt *HelperValStmt =
nullptr;
16855 !
Condition->isInstantiationDependent() &&
16856 !
Condition->containsUnexpandedParameterPack()) {
16861 ValExpr =
SemaRef.MakeFullExpr(Val.
get()).get();
16866 if (CaptureRegion != OMPD_unknown &&
16867 !
SemaRef.CurContext->isDependentContext()) {
16868 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
16869 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16870 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16876 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16887 IntConvertDiagnoser()
16888 : ICEConvertDiagnoser(
false,
false,
true) {}
16891 return S.
Diag(Loc, diag::err_omp_not_integral) << T;
16895 return S.
Diag(Loc, diag::err_omp_incomplete_type) << T;
16900 return S.
Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
16909 return S.
Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
16918 llvm_unreachable(
"conversion functions are permitted");
16920 } ConvertDiagnoser;
16921 return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
16926 bool StrictlyPositive,
bool BuildCapture =
false,
16929 Stmt **HelperValStmt =
nullptr) {
16935 if (
Value.isInvalid())
16938 ValExpr =
Value.get();
16940 if (std::optional<llvm::APSInt> Result =
16942 if (Result->isSigned() &&
16943 !((!StrictlyPositive && Result->isNonNegative()) ||
16944 (StrictlyPositive && Result->isStrictlyPositive()))) {
16945 SemaRef.
Diag(Loc, diag::err_omp_negative_expression_in_clause)
16955 if (*CaptureRegion != OMPD_unknown &&
16958 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16959 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16970 llvm::raw_svector_ostream
Out(Buffer);
16971 unsigned Skipped = Exclude.size();
16972 for (
unsigned I =
First; I <
Last; ++I) {
16973 if (llvm::is_contained(Exclude, I)) {
16978 if (I + Skipped + 2 ==
Last)
16980 else if (I + Skipped + 1 !=
Last)
16983 return std::string(
Out.str());
16991 "Unexpected num_threads modifier in OpenMP < 60.");
16996 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
17001 Expr *ValExpr = NumThreads;
17002 Stmt *HelperValStmt =
nullptr;
17013 if (CaptureRegion != OMPD_unknown &&
17014 !
SemaRef.CurContext->isDependentContext()) {
17015 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
17016 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17017 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
17023 StartLoc, LParenLoc, ModifierLoc, EndLoc);
17028 bool SuppressExprDiags) {
17037 if (SuppressExprDiags) {
17041 SuppressedDiagnoser() : VerifyICEDiagnoser(
true) {}
17044 llvm_unreachable(
"Diagnostic suppressed");
17047 ICE =
SemaRef.VerifyIntegerConstantExpression(E, &
Result, Diagnoser,
17057 if ((StrictlyPositive && !
Result.isStrictlyPositive()) ||
17058 (!StrictlyPositive && !
Result.isNonNegative())) {
17059 Diag(E->
getExprLoc(), diag::err_omp_negative_expression_in_clause)
17064 if ((CKind == OMPC_aligned || CKind == OMPC_align ||
17065 CKind == OMPC_allocate) &&
17067 Diag(E->
getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
17072 if (!
Result.isRepresentableByInt64()) {
17078 if (CKind == OMPC_collapse &&
DSAStack->getAssociatedLoops() == 1)
17080 else if (CKind == OMPC_ordered)
17099 if (
Result.isNonNegative()) {
17103 diag::err_omp_negative_expression_in_clause)
17106 }
else if (
auto *DeclRef = dyn_cast<DeclRefExpr>(DeviceNumExpr)) {
17113 Diag(DeviceNumExpr->
getExprLoc(), diag::err_expected_expression);
17147 DSAStackTy *Stack) {
17148 if (!Stack->getOMPAllocatorHandleT().isNull())
17155 S.
Diag(Loc, diag::err_omp_implied_type_not_found)
17156 <<
"omp_allocator_handle_t";
17161 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
17164 bool ErrorFound =
false;
17165 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
17166 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
17167 StringRef Allocator =
17168 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
17170 auto *VD = dyn_cast_or_null<ValueDecl>(
17190 Stack->setAllocator(AllocatorKind, Res.
get());
17193 S.
Diag(Loc, diag::err_omp_implied_type_not_found)
17194 <<
"omp_allocator_handle_t";
17213 Allocator =
SemaRef.PerformImplicitConversion(
17214 Allocator.
get(),
DSAStack->getOMPAllocatorHandleT(),
17243 Expr *NumForLoops) {
17249 if (NumForLoops && LParenLoc.
isValid()) {
17254 NumForLoops = NumForLoopsResult.
get();
17256 NumForLoops =
nullptr;
17260 NumForLoops ?
DSAStack->getAssociatedLoops() : 0,
17261 StartLoc, LParenLoc, EndLoc);
17262 DSAStack->setOrderedRegion(
true, NumForLoops, Clause);
17271 case OMPC_proc_bind:
17273 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17275 case OMPC_atomic_default_mem_order:
17278 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17282 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17286 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17290 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17294 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17296 case OMPC_severity:
17299 LParenLoc, EndLoc);
17301 case OMPC_threadset:
17303 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17307 case OMPC_num_threads:
17311 case OMPC_allocator:
17312 case OMPC_collapse:
17313 case OMPC_schedule:
17315 case OMPC_firstprivate:
17316 case OMPC_lastprivate:
17318 case OMPC_reduction:
17319 case OMPC_task_reduction:
17320 case OMPC_in_reduction:
17324 case OMPC_copyprivate:
17328 case OMPC_mergeable:
17329 case OMPC_threadprivate:
17330 case OMPC_groupprivate:
17331 case OMPC_allocate:
17348 case OMPC_num_teams:
17349 case OMPC_thread_limit:
17350 case OMPC_priority:
17351 case OMPC_grainsize:
17353 case OMPC_num_tasks:
17355 case OMPC_dist_schedule:
17357 case OMPC_defaultmap:
17362 case OMPC_use_device_ptr:
17363 case OMPC_use_device_addr:
17364 case OMPC_is_device_ptr:
17365 case OMPC_has_device_addr:
17366 case OMPC_unified_address:
17367 case OMPC_unified_shared_memory:
17368 case OMPC_reverse_offload:
17369 case OMPC_dynamic_allocators:
17370 case OMPC_self_maps:
17371 case OMPC_device_type:
17373 case OMPC_nontemporal:
17375 case OMPC_novariants:
17376 case OMPC_nocontext:
17378 case OMPC_inclusive:
17379 case OMPC_exclusive:
17380 case OMPC_uses_allocators:
17381 case OMPC_affinity:
17385 llvm_unreachable(
"Clause is not allowed.");
17394 if (M == OMP_DEFAULT_unknown) {
17395 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17397 unsigned(OMP_DEFAULT_unknown))
17402 Diag(VCKindLoc, diag::err_omp_default_vc)
17407 bool IsTargetDefault =
17414 if (IsTargetDefault && M == OMP_DEFAULT_shared)
17417 auto SetDefaultClauseAttrs = [&](llvm::omp::DefaultKind M,
17423 case OMP_DEFAULT_none:
17424 if (IsTargetDefault)
17425 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_none;
17427 DSAStack->setDefaultDSANone(MLoc);
17429 case OMP_DEFAULT_firstprivate:
17430 if (IsTargetDefault)
17431 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_firstprivate;
17433 DSAStack->setDefaultDSAFirstPrivate(MLoc);
17435 case OMP_DEFAULT_private:
17436 if (IsTargetDefault)
17437 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_private;
17439 DSAStack->setDefaultDSAPrivate(MLoc);
17441 case OMP_DEFAULT_shared:
17442 assert(!IsTargetDefault &&
"DSA shared invalid with target directive");
17443 DSAStack->setDefaultDSAShared(MLoc);
17446 llvm_unreachable(
"unexpected DSA in OpenMP default clause");
17450 case OMPC_DEFAULT_VC_aggregate:
17451 if (IsTargetDefault)
17452 DefMapKind = OMPC_DEFAULTMAP_aggregate;
17454 DSAStack->setDefaultDSAVCAggregate(VCKindLoc);
17456 case OMPC_DEFAULT_VC_pointer:
17457 if (IsTargetDefault)
17458 DefMapKind = OMPC_DEFAULTMAP_pointer;
17460 DSAStack->setDefaultDSAVCPointer(VCKindLoc);
17462 case OMPC_DEFAULT_VC_scalar:
17463 if (IsTargetDefault)
17464 DefMapKind = OMPC_DEFAULTMAP_scalar;
17466 DSAStack->setDefaultDSAVCScalar(VCKindLoc);
17468 case OMPC_DEFAULT_VC_all:
17469 if (IsTargetDefault)
17470 DefMapKind = OMPC_DEFAULTMAP_all;
17472 DSAStack->setDefaultDSAVCAll(VCKindLoc);
17475 llvm_unreachable(
"unexpected variable category in OpenMP default clause");
17484 if (IsTargetDefault) {
17485 if (DefMapKind == OMPC_DEFAULTMAP_all) {
17486 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_aggregate, MLoc);
17487 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_scalar, MLoc);
17488 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_pointer, MLoc);
17490 DSAStack->setDefaultDMAAttr(DefMapMod, DefMapKind, MLoc);
17495 SetDefaultClauseAttrs(M, VCKind);
17497 OMPDefaultClause(M, MLoc, VCKind, VCKindLoc, StartLoc, LParenLoc, EndLoc);
17506 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17509 << getOpenMPClauseName(OMPC_threadset);
17518 Expr *ImpexTypeArg,
17526 return new (Ctx) OMPTransparentClause(ER.
get(), StartLoc, LParenLoc, EndLoc);
17533 if (!ImpexTypeArg) {
17535 OMPTransparentClause(ImpexTypeArg, StartLoc, LParenLoc, EndLoc);
17546 SemaRef.Diag(StartLoc, diag::err_omp_implied_type_not_found)
17551 StartLoc, LParenLoc, EndLoc);
17556 StartLoc, LParenLoc, EndLoc);
17562 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(StartLoc,
17564 if (std::optional<llvm::APSInt>
Result =
17565 Value.get()->getIntegerConstantExpr(
SemaRef.Context)) {
17566 if (
Result->isNegative() ||
17569 SemaRef.Diag(StartLoc, diag::err_omp_transparent_invalid_value);
17572 StartLoc, LParenLoc, EndLoc);
17575 SemaRef.Diag(StartLoc, diag::err_omp_transparent_invalid_type) << Ty;
17584 if (Kind == OMP_PROC_BIND_unknown) {
17585 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17587 unsigned(OMP_PROC_BIND_master),
17590 ? OMP_PROC_BIND_primary
17591 : OMP_PROC_BIND_spread) +
17596 if (Kind == OMP_PROC_BIND_primary &&
getLangOpts().OpenMP < 51)
17597 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17599 unsigned(OMP_PROC_BIND_master),
17601 unsigned(OMP_PROC_BIND_spread) + 1)
17604 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17611 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17613 OMPC_atomic_default_mem_order, 0,
17618 return new (
getASTContext()) OMPAtomicDefaultMemOrderClause(
17619 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17628 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17635 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17644 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17651 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17658 assert(ME &&
"NULL expr in Message clause");
17667 Stmt *HelperValStmt =
nullptr;
17673 DKind == OMPD_unknown ? OMPD_unknown
17676 if (CaptureRegion != OMPD_unknown &&
17677 !
SemaRef.CurContext->isDependentContext()) {
17678 ME =
SemaRef.MakeFullExpr(ME).get();
17679 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17680 ME = tryBuildCapture(
SemaRef, ME, Captures).get();
17685 ME =
SemaRef.DefaultFunctionArrayLvalueConversion(ME).get();
17688 ME, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17695 if (Kind != OMPC_ORDER_concurrent ||
17700 "OMPC_ORDER_unknown not greater than 0");
17702 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17711 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17717 DSAStack->setRegionHasOrderConcurrent(
true);
17720 unsigned existingFlags =
DSAStack->getCurScope()->getFlags();
17721 DSAStack->getCurScope()->setFlags(existingFlags |
17726 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
17735 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
17737 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
17738 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
17740 Except.push_back(OMPC_DEPEND_inoutset);
17741 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17747 return OMPUpdateClause::Create(
getASTContext(), StartLoc, LParenLoc,
17748 KindKwLoc, Kind, EndLoc);
17757 for (
Expr *&SizeExpr : SanitizedSizeExprs) {
17767 QualType SizeTy = SizeExpr->getType();
17796 if (!SizeExpr->isInstantiationDependent() && !IsValid)
17797 SizeExpr =
nullptr;
17801 SanitizedSizeExprs);
17808 size_t NumLoops = PermExprs.size();
17810 llvm::append_range(SanitizedPermExprs, PermExprs);
17812 for (
Expr *&PermExpr : SanitizedPermExprs) {
17815 if (!PermExpr || PermExpr->isInstantiationDependent())
17818 llvm::APSInt PermVal;
17821 bool IsValid = PermEvalExpr.
isUsable();
17823 PermExpr = PermEvalExpr.
get();
17825 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
17829 diag::err_omp_interchange_permutation_value_range)
17830 << NumLoops << ExprRange;
17834 if (!PermExpr->isInstantiationDependent() && !IsValid)
17835 PermExpr =
nullptr;
17839 EndLoc, SanitizedPermExprs);
17855 FactorExpr, OMPC_partial,
true);
17858 FactorExpr = FactorResult.
get();
17887 FirstLoc, CountLoc, EndLoc,
First, Count);
17898 LParenLoc, EndLoc);
17908 case OMPC_schedule: {
17909 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
17910 assert(Argument.size() == NumberOfElements &&
17911 ArgumentLoc.size() == NumberOfElements);
17916 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
17917 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
17921 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17923 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
17926 case OMPC_dist_schedule:
17929 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
17932 enum { DefaultModifier, DefaultVarCategory };
17934 static_cast<llvm::omp::DefaultKind
>(Argument[DefaultModifier]),
17935 ArgumentLoc[DefaultModifier],
17937 Argument[DefaultVarCategory]),
17938 ArgumentLoc[DefaultVarCategory], StartLoc, LParenLoc, EndLoc);
17940 case OMPC_defaultmap:
17941 enum { Modifier, DefaultmapKind };
17945 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
17949 enum { OrderModifier, OrderKind };
17953 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
17956 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17959 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17961 case OMPC_grainsize:
17962 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17963 "Modifier for grainsize clause and its location are expected.");
17966 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17968 case OMPC_num_tasks:
17969 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17970 "Modifier for num_tasks clause and its location are expected.");
17973 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17975 case OMPC_dyn_groupprivate: {
17976 enum { Modifier1, Modifier2, NumberOfElements };
17977 assert(Argument.size() == NumberOfElements &&
17978 ArgumentLoc.size() == NumberOfElements &&
17979 "Modifiers for dyn_groupprivate clause and their locations are "
17984 Argument[Modifier2]),
17985 Expr, StartLoc, LParenLoc, ArgumentLoc[Modifier1],
17986 ArgumentLoc[Modifier2], EndLoc);
17989 case OMPC_num_threads:
17990 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17991 "Modifier for num_threads clause and its location are expected.");
17994 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
18000 case OMPC_allocator:
18001 case OMPC_collapse:
18002 case OMPC_proc_bind:
18004 case OMPC_firstprivate:
18005 case OMPC_lastprivate:
18007 case OMPC_reduction:
18008 case OMPC_task_reduction:
18009 case OMPC_in_reduction:
18013 case OMPC_copyprivate:
18017 case OMPC_mergeable:
18018 case OMPC_threadprivate:
18019 case OMPC_groupprivate:
18020 case OMPC_allocate:
18037 case OMPC_num_teams:
18038 case OMPC_thread_limit:
18039 case OMPC_priority:
18046 case OMPC_use_device_ptr:
18047 case OMPC_use_device_addr:
18048 case OMPC_is_device_ptr:
18049 case OMPC_has_device_addr:
18050 case OMPC_unified_address:
18051 case OMPC_unified_shared_memory:
18052 case OMPC_reverse_offload:
18053 case OMPC_dynamic_allocators:
18054 case OMPC_atomic_default_mem_order:
18055 case OMPC_self_maps:
18056 case OMPC_device_type:
18058 case OMPC_nontemporal:
18060 case OMPC_severity:
18063 case OMPC_novariants:
18064 case OMPC_nocontext:
18066 case OMPC_inclusive:
18067 case OMPC_exclusive:
18068 case OMPC_uses_allocators:
18069 case OMPC_affinity:
18073 llvm_unreachable(
"Clause is not allowed.");
18084 Excluded.push_back(M2);
18085 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
18086 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
18087 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
18088 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
18089 S.
Diag(M1Loc, diag::err_omp_unexpected_clause_value)
18112 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
18113 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
18114 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
18115 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
18116 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
18122 std::string Values;
18132 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
18141 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
18142 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
18143 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
18144 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
18145 diag::err_omp_schedule_nonmonotonic_static);
18148 Expr *ValExpr = ChunkSize;
18149 Stmt *HelperValStmt =
nullptr;
18160 ValExpr = Val.
get();
18165 if (std::optional<llvm::APSInt>
Result =
18167 if (
Result->isSigned() && !
Result->isStrictlyPositive()) {
18168 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
18173 DSAStack->getCurrentDirective(), OMPC_schedule,
18175 !
SemaRef.CurContext->isDependentContext()) {
18176 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
18177 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18178 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
18185 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
18186 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
18205 case OMPC_mergeable:
18253 case OMPC_unified_address:
18256 case OMPC_unified_shared_memory:
18259 case OMPC_reverse_offload:
18262 case OMPC_dynamic_allocators:
18265 case OMPC_self_maps:
18279 case OMPC_ompx_bare:
18284 case OMPC_num_threads:
18288 case OMPC_allocator:
18289 case OMPC_collapse:
18290 case OMPC_schedule:
18292 case OMPC_firstprivate:
18293 case OMPC_lastprivate:
18295 case OMPC_reduction:
18296 case OMPC_task_reduction:
18297 case OMPC_in_reduction:
18301 case OMPC_copyprivate:
18303 case OMPC_proc_bind:
18304 case OMPC_threadprivate:
18305 case OMPC_groupprivate:
18306 case OMPC_allocate:
18312 case OMPC_num_teams:
18313 case OMPC_thread_limit:
18314 case OMPC_priority:
18315 case OMPC_grainsize:
18316 case OMPC_num_tasks:
18318 case OMPC_dist_schedule:
18319 case OMPC_defaultmap:
18324 case OMPC_use_device_ptr:
18325 case OMPC_use_device_addr:
18326 case OMPC_is_device_ptr:
18327 case OMPC_has_device_addr:
18328 case OMPC_atomic_default_mem_order:
18329 case OMPC_device_type:
18331 case OMPC_nontemporal:
18334 case OMPC_severity:
18336 case OMPC_novariants:
18337 case OMPC_nocontext:
18339 case OMPC_inclusive:
18340 case OMPC_exclusive:
18341 case OMPC_uses_allocators:
18342 case OMPC_affinity:
18344 case OMPC_ompx_dyn_cgroup_mem:
18345 case OMPC_dyn_groupprivate:
18347 llvm_unreachable(
"Clause is not allowed.");
18359 !
Condition->isInstantiationDependent() &&
18360 !
Condition->containsUnexpandedParameterPack()) {
18365 ValExpr = Val.
get();
18370 OMPNowaitClause(ValExpr, StartLoc, LParenLoc, EndLoc);
18376 return new (
getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
18381 return new (
getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
18386 return new (
getASTContext()) OMPReadClause(StartLoc, EndLoc);
18391 return new (
getASTContext()) OMPWriteClause(StartLoc, EndLoc);
18396 return OMPUpdateClause::Create(
getASTContext(), StartLoc, EndLoc);
18401 return new (
getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
18406 return new (
getASTContext()) OMPCompareClause(StartLoc, EndLoc);
18411 return new (
getASTContext()) OMPFailClause(StartLoc, EndLoc);
18421 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
18425 OMPFailClause(
Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
18430 return new (
getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
18435 return new (
getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
18440 return new (
getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
18445 return new (
getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
18450 return new (
getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
18455 return new (
getASTContext()) OMPWeakClause(StartLoc, EndLoc);
18475 return new (
getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
18481 return new (
getASTContext()) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
18486 return new (
getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
18492 return new (
getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
18497 return new (
getASTContext()) OMPSelfMapsClause(StartLoc, EndLoc);
18507 if (!
hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
18509 StringRef
Expected =
"'init', 'use', 'destroy', or 'nowait'";
18510 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
18511 <<
Expected << getOpenMPDirectiveName(OMPD_interop, OMPVersion);
18524 bool HasInitClause =
false;
18525 bool IsTargetSync =
false;
18529 if (
const auto *InitClause = dyn_cast<OMPInitClause>(
C)) {
18530 HasInitClause =
true;
18531 if (InitClause->getIsTargetSync())
18532 IsTargetSync =
true;
18533 }
else if (
const auto *DC = dyn_cast<OMPDependClause>(
C)) {
18537 if (DependClause && HasInitClause && !IsTargetSync) {
18538 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
18552 if (ClauseKind == OMPC_init) {
18555 }
else if (ClauseKind == OMPC_use) {
18558 }
else if (ClauseKind == OMPC_destroy) {
18564 if (!InteropVars.insert(
DeclResult.first).second) {
18565 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
18581 Expr *RefExpr = InteropVarExpr;
18596 bool HasError =
false;
18602 if (
const auto *TD = dyn_cast<TypeDecl>(ND)) {
18603 InteropType =
QualType(TD->getTypeForDecl(), 0);
18612 SemaRef.
Diag(VarLoc, diag::err_omp_implied_type_not_found)
18613 <<
"omp_interop_t";
18619 SemaRef.
Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
18625 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
18627 SemaRef.
Diag(VarLoc, diag::err_omp_interop_variable_expected)
18656 StartLoc, LParenLoc, VarLoc, EndLoc);
18669 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
18678 DSAStack->getCurrentDirective() == OMPD_depobj) {
18680 Diag(StartLoc, diag::err_omp_expected_clause_argument)
18682 << getOpenMPDirectiveName(OMPD_depobj, OMPVersion);
18698 Stmt *HelperValStmt =
nullptr;
18701 !
Condition->isInstantiationDependent() &&
18702 !
Condition->containsUnexpandedParameterPack()) {
18707 ValExpr =
SemaRef.MakeFullExpr(Val.
get()).get();
18712 if (CaptureRegion != OMPD_unknown &&
18713 !
SemaRef.CurContext->isDependentContext()) {
18714 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
18715 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18716 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
18722 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18730 Stmt *HelperValStmt =
nullptr;
18733 !
Condition->isInstantiationDependent() &&
18734 !
Condition->containsUnexpandedParameterPack()) {
18739 ValExpr =
SemaRef.MakeFullExpr(Val.
get()).get();
18744 if (CaptureRegion != OMPD_unknown &&
18745 !
SemaRef.CurContext->isDependentContext()) {
18746 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
18747 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18748 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
18754 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18761 Expr *ValExpr = ThreadID;
18762 Stmt *HelperValStmt =
nullptr;
18767 if (CaptureRegion != OMPD_unknown &&
18768 !
SemaRef.CurContext->isDependentContext()) {
18769 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
18770 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18771 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
18776 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18787 int ExtraModifier =
Data.ExtraModifier;
18788 int OriginalSharingModifier =
Data.OriginalSharingModifier;
18795 case OMPC_firstprivate:
18798 case OMPC_lastprivate:
18800 "Unexpected lastprivate modifier.");
18803 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
18808 case OMPC_reduction:
18810 "Unexpected lastprivate modifier.");
18814 ExtraModifier, OriginalSharingModifier),
18815 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
18816 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
18818 case OMPC_task_reduction:
18820 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18821 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
18823 case OMPC_in_reduction:
18825 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18826 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
18830 "Unexpected linear modifier.");
18832 VarList,
Data.DepModOrTailExpr, StartLoc, LParenLoc,
18834 ColonLoc,
Data.StepModifierLoc, EndLoc);
18838 LParenLoc, ColonLoc, EndLoc);
18843 case OMPC_copyprivate:
18851 "Unexpected depend modifier.");
18854 ColonLoc,
Data.OmpAllMemoryLoc},
18855 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
18859 "Unexpected map modifier.");
18861 Data.IteratorExpr,
Data.MapTypeModifiers,
Data.MapTypeModifiersLoc,
18862 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId,
18864 ExtraModifierLoc, ColonLoc, VarList, Locs);
18868 Data.MotionModifiers,
Data.MotionModifiersLoc,
Data.IteratorExpr,
18869 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId, ColonLoc,
18874 Data.MotionModifiers,
Data.MotionModifiersLoc,
Data.IteratorExpr,
18875 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId, ColonLoc,
18878 case OMPC_use_device_ptr:
18879 assert(0 <=
Data.ExtraModifier &&
18881 "Unexpected use_device_ptr fallback modifier.");
18885 Data.ExtraModifierLoc);
18887 case OMPC_use_device_addr:
18890 case OMPC_is_device_ptr:
18893 case OMPC_has_device_addr:
18896 case OMPC_allocate: {
18900 if (!
Data.AllocClauseModifiers.empty()) {
18901 assert(
Data.AllocClauseModifiers.size() <= 2 &&
18902 "More allocate modifiers than expected");
18903 Modifier1 =
Data.AllocClauseModifiers[0];
18904 Modifier1Loc =
Data.AllocClauseModifiersLoc[0];
18905 if (
Data.AllocClauseModifiers.size() == 2) {
18906 Modifier2 =
Data.AllocClauseModifiers[1];
18907 Modifier2Loc =
Data.AllocClauseModifiersLoc[1];
18911 Data.DepModOrTailExpr,
Data.AllocateAlignment, Modifier1, Modifier1Loc,
18912 Modifier2, Modifier2Loc, VarList, StartLoc, LParenLoc, ColonLoc,
18916 case OMPC_nontemporal:
18919 case OMPC_inclusive:
18922 case OMPC_exclusive:
18925 case OMPC_affinity:
18927 Data.DepModOrTailExpr, VarList);
18929 case OMPC_doacross:
18932 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
18934 case OMPC_num_teams:
18937 case OMPC_thread_limit:
18943 case OMPC_num_threads:
18947 case OMPC_allocator:
18948 case OMPC_collapse:
18950 case OMPC_proc_bind:
18951 case OMPC_schedule:
18955 case OMPC_mergeable:
18956 case OMPC_threadprivate:
18957 case OMPC_groupprivate:
18971 case OMPC_priority:
18972 case OMPC_grainsize:
18974 case OMPC_num_tasks:
18976 case OMPC_dist_schedule:
18977 case OMPC_defaultmap:
18980 case OMPC_unified_address:
18981 case OMPC_unified_shared_memory:
18982 case OMPC_reverse_offload:
18983 case OMPC_dynamic_allocators:
18984 case OMPC_atomic_default_mem_order:
18985 case OMPC_self_maps:
18986 case OMPC_device_type:
18990 case OMPC_severity:
18993 case OMPC_novariants:
18994 case OMPC_nocontext:
18996 case OMPC_uses_allocators:
19000 llvm_unreachable(
"Clause is not allowed.");
19013 Res =
SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.
get());
19018 Res =
SemaRef.DefaultLvalueConversion(Res.
get());
19032 bool IsImplicitClause =
19034 for (
Expr *RefExpr : VarList) {
19035 assert(RefExpr &&
"NULL expr in OpenMP private clause.");
19038 Expr *SimpleRefExpr = RefExpr;
19042 Vars.push_back(RefExpr);
19043 PrivateCopies.push_back(
nullptr);
19050 auto *VD = dyn_cast<VarDecl>(D);
19056 diag::err_omp_private_incomplete_type))
19058 Type =
Type.getNonReferenceType();
19078 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
19079 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
19080 Diag(ELoc, diag::err_omp_wrong_dsa)
19091 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19093 << getOpenMPDirectiveName(CurrDir, OMPVersion);
19094 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19097 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19112 CurrDir == OMPD_target) {
19114 if (
DSAStack->checkMappableExprComponentListsForDecl(
19118 ConflictKind = WhereFoundClauseKind;
19121 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
19124 << getOpenMPDirectiveName(CurrDir, OMPVersion);
19144 SemaRef.ActOnUninitializedDecl(VDPrivate);
19151 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
19152 auto *FD = dyn_cast<FieldDecl>(D);
19156 RefExpr->getExprLoc());
19160 if (!IsImplicitClause)
19161 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
19162 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
19163 ? RefExpr->IgnoreParens()
19165 PrivateCopies.push_back(VDPrivateRefExpr);
19171 return OMPPrivateClause::Create(
getASTContext(), StartLoc, LParenLoc, EndLoc,
19172 Vars, PrivateCopies);
19183 bool IsImplicitClause =
19188 for (
Expr *RefExpr : VarList) {
19189 assert(RefExpr &&
"NULL expr in OpenMP firstprivate clause.");
19192 Expr *SimpleRefExpr = RefExpr;
19196 Vars.push_back(RefExpr);
19197 PrivateCopies.push_back(
nullptr);
19198 Inits.push_back(
nullptr);
19204 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
19206 auto *VD = dyn_cast<VarDecl>(D);
19212 diag::err_omp_firstprivate_incomplete_type))
19214 Type =
Type.getNonReferenceType();
19224 DSAStackTy::DSAVarData TopDVar;
19225 if (!IsImplicitClause) {
19226 DSAStackTy::DSAVarData DVar =
19238 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
19240 DVar.CKind != OMPC_lastprivate) &&
19242 Diag(ELoc, diag::err_omp_wrong_dsa)
19260 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
19261 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
19262 Diag(ELoc, diag::err_omp_wrong_dsa)
19288 DVar =
DSAStack->getImplicitDSA(D,
true);
19289 if (DVar.CKind != OMPC_shared &&
19292 DVar.DKind == OMPD_unknown)) {
19293 Diag(ELoc, diag::err_omp_required_access)
19315 return C == OMPC_reduction && !AppliedToPointee;
19323 if (DVar.CKind == OMPC_reduction &&
19327 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
19328 << getOpenMPDirectiveName(DVar.DKind, OMPVersion);
19344 CurrDir == OMPD_target) {
19346 if (
DSAStack->checkMappableExprComponentListsForDecl(
19351 ConflictKind = WhereFoundClauseKind;
19354 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
19357 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
19368 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19370 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
19372 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19375 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19390 Expr *VDInitRefExpr =
nullptr;
19400 ElemType,
".firstprivate.temp");
19415 ".firstprivate.temp");
19417 RefExpr->getExprLoc());
19418 SemaRef.AddInitializerToDecl(
19419 VDPrivate,
SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
19423 if (IsImplicitClause) {
19424 Diag(RefExpr->getExprLoc(),
19425 diag::note_omp_task_predetermined_firstprivate_here);
19429 SemaRef.CurContext->addDecl(VDPrivate);
19432 RefExpr->getExprLoc());
19434 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
19435 if (TopDVar.CKind == OMPC_lastprivate) {
19436 Ref = TopDVar.PrivateCopy;
19438 auto *FD = dyn_cast<FieldDecl>(D);
19443 RefExpr->getExprLoc());
19447 ExprCaptures.push_back(Ref->
getDecl());
19450 if (!IsImplicitClause)
19451 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
19452 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
19453 ? RefExpr->IgnoreParens()
19455 PrivateCopies.push_back(VDPrivateRefExpr);
19456 Inits.push_back(VDInitRefExpr);
19462 return OMPFirstprivateClause::Create(
19472 assert(ColonLoc.
isValid() &&
"Colon location must be valid.");
19473 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
19486 for (
Expr *RefExpr : VarList) {
19487 assert(RefExpr &&
"NULL expr in OpenMP lastprivate clause.");
19490 Expr *SimpleRefExpr = RefExpr;
19494 Vars.push_back(RefExpr);
19495 SrcExprs.push_back(
nullptr);
19496 DstExprs.push_back(
nullptr);
19497 AssignmentOps.push_back(
nullptr);
19504 auto *VD = dyn_cast<VarDecl>(D);
19510 diag::err_omp_lastprivate_incomplete_type))
19512 Type =
Type.getNonReferenceType();
19529 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
19530 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19533 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19547 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
19548 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
19550 DVar.CKind != OMPC_firstprivate) &&
19551 (DVar.CKind != OMPC_private || DVar.RefExpr !=
nullptr)) {
19552 Diag(ELoc, diag::err_omp_wrong_dsa)
19565 DSAStackTy::DSAVarData TopDVar = DVar;
19569 DVar =
DSAStack->getImplicitDSA(D,
true);
19570 if (DVar.CKind != OMPC_shared) {
19571 Diag(ELoc, diag::err_omp_required_access)
19589 Type.getUnqualifiedType(),
".lastprivate.src",
19600 PseudoDstExpr, PseudoSrcExpr);
19603 AssignmentOp =
SemaRef.ActOnFinishFullExpr(AssignmentOp.
get(), ELoc,
19609 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
19610 if (TopDVar.CKind == OMPC_firstprivate) {
19611 Ref = TopDVar.PrivateCopy;
19615 ExprCaptures.push_back(Ref->
getDecl());
19617 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
19625 SimpleRefExpr, RefRes.
get());
19628 ExprPostUpdates.push_back(
19629 SemaRef.IgnoredValueConversions(PostUpdateRes.
get()).get());
19632 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
19633 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
19634 ? RefExpr->IgnoreParens()
19636 SrcExprs.push_back(PseudoSrcExpr);
19637 DstExprs.push_back(PseudoDstExpr);
19638 AssignmentOps.push_back(AssignmentOp.
get());
19644 return OMPLastprivateClause::Create(
19645 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
19646 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
19656 for (
Expr *RefExpr : VarList) {
19657 assert(RefExpr &&
"NULL expr in OpenMP shared clause.");
19660 Expr *SimpleRefExpr = RefExpr;
19664 Vars.push_back(RefExpr);
19670 auto *VD = dyn_cast<VarDecl>(D);
19678 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
19679 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
19681 Diag(ELoc, diag::err_omp_wrong_dsa)
19690 !
SemaRef.CurContext->isDependentContext())
19692 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
19693 Vars.push_back((VD || !Ref ||
SemaRef.CurContext->isDependentContext())
19694 ? RefExpr->IgnoreParens()
19701 return OMPSharedClause::Create(
getASTContext(), StartLoc, LParenLoc, EndLoc,
19706class DSARefChecker :
public StmtVisitor<DSARefChecker, bool> {
19711 if (
auto *VD = dyn_cast<VarDecl>(E->
getDecl())) {
19712 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD,
false);
19713 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
19715 if (DVar.CKind != OMPC_unknown)
19717 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
19724 return DVarPrivate.CKind != OMPC_unknown;
19728 bool VisitStmt(Stmt *S) {
19729 for (Stmt *Child : S->
children()) {
19730 if (Child && Visit(Child))
19735 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
19742class TransformExprToCaptures :
public TreeTransform<TransformExprToCaptures> {
19743 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
19744 ValueDecl *
Field =
nullptr;
19745 DeclRefExpr *CapturedExpr =
nullptr;
19748 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
19749 : BaseTransform(SemaRef),
Field(FieldDecl), CapturedExpr(
nullptr) {}
19751 ExprResult TransformMemberExpr(MemberExpr *E) {
19754 CapturedExpr =
buildCapture(SemaRef, Field, E,
false);
19755 return CapturedExpr;
19757 return BaseTransform::TransformMemberExpr(E);
19759 DeclRefExpr *getCapturedExpr() {
return CapturedExpr; }
19763template <
typename T,
typename U>
19766 for (
U &
Set : Lookups) {
19767 for (
auto *D :
Set) {
19778 for (
auto *RD : D->
redecls()) {
19801 AssociatedClasses);
19814 for (
auto *NS : AssociatedNamespaces) {
19827 for (
auto *D : R) {
19828 auto *Underlying = D;
19829 if (
auto *USD = dyn_cast<UsingShadowDecl>(D))
19830 Underlying = USD->getTargetDecl();
19840 if (
auto *USD = dyn_cast<UsingShadowDecl>(D))
19841 Underlying = USD->getTargetDecl();
19843 Lookups.emplace_back();
19844 Lookups.back().addDecl(Underlying);
19868 Lookups.emplace_back();
19869 Lookups.back().append(Lookup.
begin(), Lookup.
end());
19872 }
else if (
auto *ULE =
19873 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
19875 Decl *PrevD =
nullptr;
19879 else if (
auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
19880 Lookups.back().addDecl(DRD);
19888 return !D->isInvalidDecl() &&
19889 (D->getType()->isDependentType() ||
19890 D->getType()->isInstantiationDependentType() ||
19891 D->getType()->containsUnexpandedParameterPack());
19904 true, ResSet.
begin(), ResSet.
end(),
false,
19927 if (IsComplete || RD->isBeingDefined()) {
19930 if (Lookup.
empty()) {
19931 Lookups.emplace_back();
19932 Lookups.back().append(Lookup.
begin(), Lookup.
end());
19974 if (ReductionIdScopeSpec.
isSet()) {
19975 SemaRef.
Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
19984struct ReductionData {
19986 SmallVector<Expr *, 8> Vars;
19990 SmallVector<Expr *, 8> LHSs;
19992 SmallVector<Expr *, 8> RHSs;
19994 SmallVector<Expr *, 8> ReductionOps;
19996 SmallVector<Expr *, 8> InscanCopyOps;
19998 SmallVector<Expr *, 8> InscanCopyArrayTemps;
20000 SmallVector<Expr *, 8> InscanCopyArrayElems;
20003 SmallVector<Expr *, 8> TaskgroupDescriptors;
20005 SmallVector<Decl *, 4> ExprCaptures;
20007 SmallVector<Expr *, 4> ExprPostUpdates;
20009 unsigned RedModifier = 0;
20011 unsigned OrigSharingModifier = 0;
20013 SmallVector<bool, 8> IsPrivateVarReduction;
20014 ReductionData() =
delete;
20016 ReductionData(
unsigned Size,
unsigned Modifier = 0,
unsigned OrgModifier = 0)
20017 : RedModifier(Modifier), OrigSharingModifier(OrgModifier) {
20018 Vars.reserve(Size);
20020 LHSs.reserve(Size);
20021 RHSs.reserve(Size);
20022 ReductionOps.reserve(Size);
20023 IsPrivateVarReduction.reserve(Size);
20024 if (RedModifier == OMPC_REDUCTION_inscan) {
20025 InscanCopyOps.reserve(Size);
20026 InscanCopyArrayTemps.reserve(Size);
20027 InscanCopyArrayElems.reserve(Size);
20029 TaskgroupDescriptors.reserve(Size);
20030 ExprCaptures.reserve(Size);
20031 ExprPostUpdates.reserve(Size);
20035 void push(Expr *Item, Expr *ReductionOp) {
20036 Vars.emplace_back(Item);
20038 LHSs.emplace_back(
nullptr);
20039 RHSs.emplace_back(
nullptr);
20040 ReductionOps.emplace_back(ReductionOp);
20041 IsPrivateVarReduction.emplace_back(
false);
20042 TaskgroupDescriptors.emplace_back(
nullptr);
20043 if (RedModifier == OMPC_REDUCTION_inscan) {
20044 InscanCopyOps.push_back(
nullptr);
20045 InscanCopyArrayTemps.push_back(
nullptr);
20046 InscanCopyArrayElems.push_back(
nullptr);
20050 void push(Expr *Item, Expr *
Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
20051 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
20052 Expr *CopyArrayElem,
bool IsPrivate) {
20053 Vars.emplace_back(Item);
20055 LHSs.emplace_back(LHS);
20056 RHSs.emplace_back(RHS);
20057 ReductionOps.emplace_back(ReductionOp);
20058 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
20059 if (RedModifier == OMPC_REDUCTION_inscan) {
20060 InscanCopyOps.push_back(CopyOp);
20061 InscanCopyArrayTemps.push_back(CopyArrayTemp);
20062 InscanCopyArrayElems.push_back(CopyArrayElem);
20064 assert(CopyOp ==
nullptr && CopyArrayTemp ==
nullptr &&
20065 CopyArrayElem ==
nullptr &&
20066 "Copy operation must be used for inscan reductions only.");
20068 IsPrivateVarReduction.emplace_back(IsPrivate);
20077 if (Length ==
nullptr) {
20084 SingleElement =
true;
20085 ArraySizes.push_back(llvm::APSInt::get(1));
20088 if (!Length->EvaluateAsInt(Result, Context))
20091 llvm::APSInt ConstantLengthValue = Result.
Val.
getInt();
20092 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
20093 ArraySizes.push_back(ConstantLengthValue);
20101 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base)) {
20102 Length = TempOASE->getLength();
20103 if (Length ==
nullptr) {
20110 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
20111 ArraySizes.push_back(ConstantOne);
20114 if (!Length->EvaluateAsInt(Result, Context))
20117 llvm::APSInt ConstantLengthValue = Result.
Val.
getInt();
20118 if (ConstantLengthValue.getSExtValue() != 1)
20121 ArraySizes.push_back(ConstantLengthValue);
20123 Base = TempOASE->getBase()->IgnoreParenImpCasts();
20127 if (!SingleElement) {
20128 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base)) {
20130 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
20131 ArraySizes.push_back(ConstantOne);
20132 Base = TempASE->getBase()->IgnoreParenImpCasts();
20144 return BO_AddAssign;
20146 return BO_MulAssign;
20148 return BO_AndAssign;
20150 return BO_OrAssign;
20152 return BO_XorAssign;
20208 case OO_Array_Delete:
20217 case OO_GreaterEqual:
20219 case OO_MinusEqual:
20221 case OO_SlashEqual:
20222 case OO_PercentEqual:
20223 case OO_CaretEqual:
20227 case OO_GreaterGreater:
20228 case OO_LessLessEqual:
20229 case OO_GreaterGreaterEqual:
20230 case OO_EqualEqual:
20231 case OO_ExclaimEqual:
20234 case OO_MinusMinus:
20240 case OO_Conditional:
20243 llvm_unreachable(
"Unexpected reduction identifier");
20246 if (II->isStr(
"max"))
20248 else if (II->isStr(
"min"))
20256 if (OOK == OO_Minus && S.
LangOpts.OpenMP == 52)
20257 S.
Diag(ReductionId.
getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
20260 if (ReductionIdScopeSpec.
isValid())
20266 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
20267 bool FirstIter =
true;
20268 for (
Expr *RefExpr : VarList) {
20269 assert(RefExpr &&
"nullptr expr in OpenMP reduction clause.");
20277 if (!FirstIter && IR != ER)
20282 bool IsPrivate =
false;
20283 Expr *SimpleRefExpr = RefExpr;
20292 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
20293 ReductionId,
Type, BasePath, IR == ER ?
nullptr : *IR);
20294 Expr *ReductionOp =
nullptr;
20296 (DeclareReductionRef.
isUnset() ||
20298 ReductionOp = DeclareReductionRef.
get();
20300 RD.push(RefExpr, ReductionOp);
20306 Expr *TaskgroupDescriptor =
nullptr;
20308 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
20309 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
20311 Type = ASE->getType().getNonReferenceType();
20315 if (
const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20316 Type = ATy->getElementType();
20319 Type =
Type.getNonReferenceType();
20323 auto *VD = dyn_cast<VarDecl>(D);
20329 diag::err_omp_reduction_incomplete_type))
20335 false, ASE || OASE))
20342 if (!ASE && !OASE) {
20344 VarDecl *VDDef = VD->getDefinition();
20346 DSARefChecker Check(Stack);
20347 if (Check.Visit(VDDef->
getInit())) {
20348 S.
Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
20367 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D,
false);
20368 if (DVar.CKind == OMPC_reduction) {
20369 S.
Diag(ELoc, diag::err_omp_once_referenced)
20375 if (DVar.CKind != OMPC_unknown) {
20376 S.
Diag(ELoc, diag::err_omp_wrong_dsa)
20392 DVar = Stack->getImplicitDSA(D,
true);
20393 if (DVar.CKind != OMPC_shared) {
20394 S.
Diag(ELoc, diag::err_omp_required_access)
20408 DVar = Stack->getImplicitDSA(D,
true);
20410 IsPrivate = DVar.CKind != OMPC_shared;
20411 bool IsOrphaned =
false;
20413 IsOrphaned = ParentDir == OMPD_unknown;
20415 RD.OrigSharingModifier == OMPC_ORIGINAL_SHARING_private))
20421 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D,
false);
20422 if (DVar.CKind == OMPC_threadprivate) {
20423 S.
Diag(ELoc, diag::err_omp_wrong_dsa)
20435 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
20436 ReductionId,
Type, BasePath, IR == ER ?
nullptr : *IR);
20440 (DeclareReductionRef.
isUnset() ||
20442 RD.push(RefExpr, DeclareReductionRef.
get());
20445 if (BOK == BO_Comma && DeclareReductionRef.
isUnset()) {
20449 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
20450 <<
Type << ReductionIdRange;
20453 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
20454 <<
Type << ReductionIdRange;
20466 if (DeclareReductionRef.
isUnset()) {
20467 if ((BOK == BO_GT || BOK == BO_LT) &&
20470 S.
Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
20473 if (!ASE && !OASE) {
20474 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20477 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20482 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
20484 S.
Diag(ELoc, diag::err_omp_clause_floating_type_arg)
20486 if (!ASE && !OASE) {
20487 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20490 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20497 Type =
Type.getNonLValueExprType(Context).getUnqualifiedType();
20506 bool ConstantLengthOASE =
false;
20508 bool SingleElement;
20511 Context, OASE, SingleElement, ArraySizes);
20514 if (ConstantLengthOASE && !SingleElement) {
20515 for (llvm::APSInt &Size : ArraySizes)
20516 PrivateTy = Context.getConstantArrayType(PrivateTy, Size,
nullptr,
20522 if ((OASE && !ConstantLengthOASE) ||
20525 if (!Context.getTargetInfo().isVLASupported()) {
20527 S.
Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
20528 S.
Diag(ELoc, diag::note_vla_unsupported);
20531 S.
targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
20532 S.
targetDiag(ELoc, diag::note_vla_unsupported);
20540 PrivateTy = Context.getVariableArrayType(
20545 }
else if (!ASE && !OASE &&
20558 if (DeclareReductionRef.
isUsable()) {
20561 if (DRD->getInitializer()) {
20587 Type = ComplexTy->getElementType();
20589 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
20590 Context.getFloatTypeSemantics(
Type));
20594 uint64_t Size = Context.getTypeSize(
Type);
20595 QualType IntTy = Context.getIntTypeForBitwidth(Size, 0);
20596 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
20615 uint64_t Size = Context.getTypeSize(
Type);
20617 Context.getIntTypeForBitwidth(Size, IsSigned);
20618 llvm::APInt InitValue =
20619 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
20620 : llvm::APInt::getMinValue(Size)
20621 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
20622 : llvm::APInt::getMaxValue(Size);
20627 ELoc, Context.getTrivialTypeSourceInfo(
Type, ELoc), ELoc,
Init);
20633 llvm::APFloat InitValue = llvm::APFloat::getLargest(
20634 Context.getFloatTypeSemantics(
Type), BOK != BO_LT);
20664 llvm_unreachable(
"Unexpected reduction operation");
20673 }
else if (!
Init) {
20683 S.
Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
20684 <<
Type << ReductionIdRange;
20685 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20688 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20694 if (DeclareReductionRef.
isUsable()) {
20696 QualType PtrRedTy = Context.getPointerType(RedTy);
20699 if (!BasePath.empty()) {
20703 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.
get(), &BasePath,
20706 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.
get(), &BasePath,
20710 QualType Params[] = {PtrRedTy, PtrRedTy};
20711 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
20725 CombBOK, LHSDRE, RHSDRE);
20732 if (BOK != BO_LT && BOK != BO_GT) {
20735 BO_Assign, LHSDRE, ReductionOp.
get());
20737 auto *ConditionalOp =
new (Context)
20742 BO_Assign, LHSDRE, ConditionalOp);
20755 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
20756 if (ClauseKind == OMPC_reduction &&
20757 RD.RedModifier == OMPC_REDUCTION_inscan) {
20759 CopyOpRes = S.
BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
20769 if (Stack->getCurrentDirective() == OMPD_simd ||
20807 if (ClauseKind == OMPC_in_reduction) {
20810 const Expr *ParentReductionOp =
nullptr;
20811 Expr *ParentBOKTD =
nullptr, *ParentReductionOpTD =
nullptr;
20812 DSAStackTy::DSAVarData ParentBOKDSA =
20813 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
20815 DSAStackTy::DSAVarData ParentReductionOpDSA =
20816 Stack->getTopMostTaskgroupReductionData(
20817 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
20818 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
20819 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
20820 if ((DeclareReductionRef.
isUnset() && IsParentReductionOp) ||
20821 (DeclareReductionRef.
isUsable() && IsParentBOK) ||
20822 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
20823 bool EmitError =
true;
20824 if (IsParentReductionOp && DeclareReductionRef.
isUsable()) {
20825 llvm::FoldingSetNodeID RedId, ParentRedId;
20826 ParentReductionOp->
Profile(ParentRedId, Context,
true);
20827 DeclareReductionRef.
get()->
Profile(RedId, Context,
20829 EmitError = RedId != ParentRedId;
20833 diag::err_omp_reduction_identifier_mismatch)
20834 << ReductionIdRange << RefExpr->getSourceRange();
20836 diag::note_omp_previous_reduction_identifier)
20838 << (IsParentBOK ? ParentBOKDSA.RefExpr
20839 : ParentReductionOpDSA.RefExpr)
20840 ->getSourceRange();
20844 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
20851 TransformExprToCaptures RebuildToCapture(S, D);
20853 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
20854 Ref = RebuildToCapture.getCapturedExpr();
20856 VarsExpr = Ref =
buildCapture(S, D, SimpleRefExpr,
false);
20859 RD.ExprCaptures.emplace_back(Ref->
getDecl());
20865 S.
BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
20870 Stack->getCurrentDirective() == OMPD_taskgroup) {
20871 S.
Diag(RefExpr->getExprLoc(),
20872 diag::err_omp_reduction_non_addressable_expression)
20873 << RefExpr->getSourceRange();
20876 RD.ExprPostUpdates.emplace_back(
20883 unsigned Modifier = RD.RedModifier;
20886 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
20887 Modifier = OMPC_REDUCTION_task;
20888 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
20890 if (Modifier == OMPC_REDUCTION_task &&
20891 (CurrDir == OMPD_taskgroup ||
20895 if (DeclareReductionRef.
isUsable())
20896 Stack->addTaskgroupReductionData(D, ReductionIdRange,
20897 DeclareReductionRef.
get());
20899 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
20901 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.
get(),
20902 TaskgroupDescriptor, CopyOpRes.
get(), TempArrayRes.
get(),
20903 TempArrayElem.
get(), IsPrivate);
20905 return RD.Vars.empty();
20921 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
20932 if (Modifier == OMPC_REDUCTION_inscan &&
20933 (
DSAStack->getCurrentDirective() != OMPD_for &&
20934 DSAStack->getCurrentDirective() != OMPD_for_simd &&
20935 DSAStack->getCurrentDirective() != OMPD_simd &&
20936 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
20937 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
20938 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
20941 ReductionData RD(VarList.size(), Modifier, OriginalSharingModifier);
20943 StartLoc, LParenLoc, ColonLoc, EndLoc,
20944 ReductionIdScopeSpec, ReductionId,
20945 UnresolvedReductions, RD))
20948 return OMPReductionClause::Create(
20949 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
20952 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
20953 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
20956 OriginalSharingModifier);
20964 ReductionData RD(VarList.size());
20966 VarList, StartLoc, LParenLoc, ColonLoc,
20967 EndLoc, ReductionIdScopeSpec, ReductionId,
20968 UnresolvedReductions, RD))
20971 return OMPTaskReductionClause::Create(
20972 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20974 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
20984 ReductionData RD(VarList.size());
20986 StartLoc, LParenLoc, ColonLoc, EndLoc,
20987 ReductionIdScopeSpec, ReductionId,
20988 UnresolvedReductions, RD))
20991 return OMPInReductionClause::Create(
20992 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20994 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
21003 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
21013 const auto *VD = dyn_cast_or_null<VarDecl>(D);
21016 diag::err_omp_linear_incomplete_type))
21018 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
21020 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
21024 Type =
Type.getNonReferenceType();
21031 if (!IsDeclareSimd &&
21036 Type =
Type.getUnqualifiedType().getCanonicalType();
21037 const auto *Ty =
Type.getTypePtrOrNull();
21038 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
21039 !Ty->isIntegralType(
getASTContext()) && !Ty->isPointerType())) {
21040 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) <<
Type;
21042 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
21045 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21068 Diag(Step->
getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
21070 LinKind = OMPC_LINEAR_val;
21071 for (
Expr *RefExpr : VarList) {
21072 assert(RefExpr &&
"NULL expr in OpenMP linear clause.");
21075 Expr *SimpleRefExpr = RefExpr;
21079 Vars.push_back(RefExpr);
21081 Inits.push_back(
nullptr);
21088 auto *VD = dyn_cast<VarDecl>(D);
21094 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
21095 if (DVar.RefExpr) {
21096 Diag(ELoc, diag::err_omp_wrong_dsa)
21105 Type =
Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
21117 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
21120 ExprCaptures.push_back(Ref->
getDecl());
21127 SimpleRefExpr, RefRes.
get());
21130 ExprPostUpdates.push_back(
21131 SemaRef.IgnoredValueConversions(PostUpdateRes.
get()).get());
21135 if (LinKind == OMPC_LINEAR_uval)
21136 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
21138 InitExpr = VD ? SimpleRefExpr : Ref;
21139 SemaRef.AddInitializerToDecl(
21140 Init,
SemaRef.DefaultLvalueConversion(InitExpr).get(),
21144 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
21145 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
21146 ? RefExpr->IgnoreParens()
21149 Inits.push_back(InitRef);
21155 Expr *StepExpr = Step;
21156 Expr *CalcStepExpr =
nullptr;
21164 StepExpr = Val.
get();
21172 SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.
get(), StepExpr);
21174 SemaRef.ActOnFinishFullExpr(CalcStep.
get(),
false);
21178 if (std::optional<llvm::APSInt>
Result =
21180 if (!
Result->isNegative() && !
Result->isStrictlyPositive())
21181 Diag(StepLoc, diag::warn_omp_linear_step_zero)
21182 << Vars[0] << (Vars.size() > 1);
21186 CalcStepExpr = CalcStep.
get();
21190 return OMPLinearClause::Create(
getASTContext(), StartLoc, LParenLoc, LinKind,
21191 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
21198 Expr *NumIterations,
Sema &SemaRef,
21199 Scope *S, DSAStackTy *Stack) {
21204 Expr *Step = Clause.getStep();
21205 Expr *CalcStep = Clause.getCalcStep();
21212 bool HasErrors =
false;
21213 auto CurInit = Clause.inits().begin();
21214 auto CurPrivate = Clause.privates().begin();
21216 for (
Expr *RefExpr : Clause.varlist()) {
21219 Expr *SimpleRefExpr = RefExpr;
21220 auto Res =
getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21222 if (Res.second || !D) {
21224 Finals.push_back(
nullptr);
21228 auto &&Info = Stack->isLoopControlVariable(D);
21235 diag::err_omp_linear_distribute_var_non_loop_iteration);
21237 Finals.push_back(
nullptr);
21241 Expr *InitExpr = *CurInit;
21246 if (LinKind == OMPC_LINEAR_uval)
21251 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
21258 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
21269 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
21272 Final = *CurPrivate;
21276 if (!
Update.isUsable() || !Final.isUsable()) {
21278 Finals.push_back(
nullptr);
21279 UsedExprs.push_back(
nullptr);
21283 Finals.push_back(Final.get());
21285 UsedExprs.push_back(SimpleRefExpr);
21290 if (
Expr *S = Clause.getStep())
21291 UsedExprs.push_back(S);
21293 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(),
nullptr);
21295 Clause.setFinals(Finals);
21296 Clause.setUsedExprs(UsedExprs);
21304 for (
Expr *RefExpr : VarList) {
21305 assert(RefExpr &&
"NULL expr in OpenMP aligned clause.");
21308 Expr *SimpleRefExpr = RefExpr;
21312 Vars.push_back(RefExpr);
21319 auto *VD = dyn_cast<VarDecl>(D);
21327 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
21329 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
21332 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21339 if (
const Expr *PrevRef =
DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
21340 Diag(ELoc, diag::err_omp_used_in_clause_twice)
21342 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
21351 .DefaultFunctionArrayConversion(
21352 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
21361 if (Alignment !=
nullptr) {
21366 Alignment = AlignResult.
get();
21372 ColonLoc, EndLoc, Vars, Alignment);
21383 for (
Expr *RefExpr : VarList) {
21384 assert(RefExpr &&
"NULL expr in OpenMP copyin clause.");
21387 Vars.push_back(RefExpr);
21388 SrcExprs.push_back(
nullptr);
21389 DstExprs.push_back(
nullptr);
21390 AssignmentOps.push_back(
nullptr);
21399 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
21401 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
21402 << 0 << RefExpr->getSourceRange();
21406 Decl *D = DE->getDecl();
21412 Vars.push_back(DE);
21413 SrcExprs.push_back(
nullptr);
21414 DstExprs.push_back(
nullptr);
21415 AssignmentOps.push_back(
nullptr);
21421 if (!
DSAStack->isThreadPrivate(VD)) {
21423 Diag(ELoc, diag::err_omp_required_access)
21425 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion);
21448 SemaRef.BuildBinOp(
nullptr, DE->getExprLoc(), BO_Assign,
21449 PseudoDstExpr, PseudoSrcExpr);
21458 DSAStack->addDSA(VD, DE, OMPC_copyin);
21459 Vars.push_back(DE);
21460 SrcExprs.push_back(PseudoSrcExpr);
21461 DstExprs.push_back(PseudoDstExpr);
21462 AssignmentOps.push_back(AssignmentOp.
get());
21469 Vars, SrcExprs, DstExprs, AssignmentOps);
21480 for (
Expr *RefExpr : VarList) {
21481 assert(RefExpr &&
"NULL expr in OpenMP copyprivate clause.");
21484 Expr *SimpleRefExpr = RefExpr;
21488 Vars.push_back(RefExpr);
21489 SrcExprs.push_back(
nullptr);
21490 DstExprs.push_back(
nullptr);
21491 AssignmentOps.push_back(
nullptr);
21498 auto *VD = dyn_cast<VarDecl>(D);
21503 if (!VD || !
DSAStack->isThreadPrivate(VD)) {
21504 DSAStackTy::DSAVarData DVar =
21506 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
21508 Diag(ELoc, diag::err_omp_wrong_dsa)
21518 if (DVar.CKind == OMPC_unknown) {
21519 DVar =
DSAStack->getImplicitDSA(D,
false);
21520 if (DVar.CKind == OMPC_shared) {
21521 Diag(ELoc, diag::err_omp_required_access)
21523 <<
"threadprivate or private in the enclosing context";
21533 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
21535 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
21537 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
21540 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21561 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
21564 AssignmentOp =
SemaRef.ActOnFinishFullExpr(AssignmentOp.
get(), ELoc,
21573 VD ? RefExpr->IgnoreParens()
21575 SrcExprs.push_back(PseudoSrcExpr);
21576 DstExprs.push_back(PseudoDstExpr);
21577 AssignmentOps.push_back(AssignmentOp.
get());
21584 EndLoc, Vars, SrcExprs, DstExprs,
21592 if (VarList.empty())
21601 bool Diagnose =
true) {
21602 QualType OMPDependT = Stack->getOMPDependT();
21603 if (!OMPDependT.
isNull())
21609 S.
Diag(Loc, diag::err_omp_implied_type_not_found) <<
"omp_depend_t";
21612 Stack->setOMPDependT(PT.
get());
21633 Diag(Depobj->
getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
21638 Diag(Depobj->
getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
21648struct DoacrossDataInfoTy {
21652 DSAStackTy::OperatorOffsetTy OpsOffs;
21654 llvm::APSInt TotalDepCount;
21657static DoacrossDataInfoTy
21663 DSAStackTy::OperatorOffsetTy OpsOffs;
21664 llvm::APSInt DepCounter(32);
21665 llvm::APSInt TotalDepCount(32);
21667 if (
const Expr *OrderedCountExpr =
21668 Stack->getParentOrderedRegionParam().first) {
21669 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.
Context);
21670 TotalDepCount.setIsUnsigned(
true);
21673 for (
Expr *RefExpr : VarList) {
21674 assert(RefExpr &&
"NULL expr in OpenMP doacross clause.");
21677 Vars.push_back(RefExpr);
21684 if (Stack->getParentOrderedRegionParam().first &&
21685 DepCounter >= TotalDepCount) {
21686 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
21700 Vars.push_back(RefExpr);
21707 Expr *RHS =
nullptr;
21708 if (
auto *BO = dyn_cast<BinaryOperator>(
SimpleExpr)) {
21710 OOLoc = BO->getOperatorLoc();
21713 }
else if (
auto *OCE = dyn_cast<CXXOperatorCallExpr>(
SimpleExpr)) {
21714 OOK = OCE->getOperator();
21715 OOLoc = OCE->getOperatorLoc();
21718 }
else if (
auto *MCE = dyn_cast<CXXMemberCallExpr>(
SimpleExpr)) {
21719 OOK = MCE->getMethodDecl()
21722 .getCXXOverloadedOperator();
21723 OOLoc = MCE->getCallee()->getExprLoc();
21732 Vars.push_back(RefExpr);
21738 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK !=
OO_None)) {
21739 SemaRef.
Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
21745 RHS, OMPC_depend,
false);
21750 Stack->getParentOrderedRegionParam().first &&
21751 DepCounter != Stack->isParentLoopControlVariable(D).first) {
21753 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
21755 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
21758 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
21762 OpsOffs.emplace_back(RHS, OOK);
21764 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21767 TotalDepCount > VarList.size() &&
21768 Stack->getParentOrderedRegionParam().first &&
21769 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
21770 SemaRef.
Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
21771 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
21773 return {Vars, OpsOffs, TotalDepCount};
21782 if (
DSAStack->getCurrentDirective() == OMPD_ordered &&
21783 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
21784 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21788 if (
DSAStack->getCurrentDirective() == OMPD_taskwait &&
21789 DepKind == OMPC_DEPEND_mutexinoutset) {
21790 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
21793 if ((
DSAStack->getCurrentDirective() != OMPD_ordered ||
21794 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21796 DepKind == OMPC_DEPEND_sink ||
21798 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21799 DepKind == OMPC_DEPEND_depobj))) {
21801 OMPC_DEPEND_outallmemory,
21802 OMPC_DEPEND_inoutallmemory};
21804 DSAStack->getCurrentDirective() == OMPD_depobj)
21805 Except.push_back(OMPC_DEPEND_depobj);
21807 Except.push_back(OMPC_DEPEND_inoutset);
21809 ?
"depend modifier(iterator) or "
21811 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21819 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
21821 diag::err_omp_depend_sink_source_with_modifier);
21826 Diag(DepModifier->
getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
21829 DSAStackTy::OperatorOffsetTy OpsOffs;
21830 llvm::APSInt TotalDepCount(32);
21832 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
21835 Vars = VarOffset.Vars;
21836 OpsOffs = VarOffset.OpsOffs;
21837 TotalDepCount = VarOffset.TotalDepCount;
21839 for (
Expr *RefExpr : VarList) {
21840 assert(RefExpr &&
"NULL expr in OpenMP depend clause.");
21843 Vars.push_back(RefExpr);
21849 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
21850 bool OMPDependTFound =
getLangOpts().OpenMP >= 50;
21851 if (OMPDependTFound)
21853 DepKind == OMPC_DEPEND_depobj);
21854 if (DepKind == OMPC_DEPEND_depobj) {
21858 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21859 !RefExpr->isInstantiationDependent() &&
21860 !RefExpr->containsUnexpandedParameterPack() &&
21861 (OMPDependTFound &&
21863 DSAStack->getOMPDependT(), RefExpr->getType()))) {
21864 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21865 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
21868 if (!RefExpr->isLValue()) {
21869 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21870 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
21877 QualType ExprTy = RefExpr->getType().getNonReferenceType();
21878 const auto *OASE = dyn_cast<ArraySectionExpr>(
SimpleExpr);
21882 if (BaseType.isNull())
21884 if (
const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21885 ExprTy = ATy->getElementType();
21888 if (BaseType.isNull() || ExprTy.
isNull())
21891 const Expr *Length = OASE->getLength();
21893 if (Length && !Length->isValueDependent() &&
21895 Result.Val.getInt().isZero()) {
21897 diag::err_omp_depend_zero_length_array_section_not_allowed)
21907 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21908 !RefExpr->isInstantiationDependent() &&
21909 !RefExpr->containsUnexpandedParameterPack() &&
21910 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
21911 (OMPDependTFound &&
DSAStack->getOMPDependT().getTypePtr() ==
21913 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21916 << RefExpr->getSourceRange();
21920 auto *ASE = dyn_cast<ArraySubscriptExpr>(
SimpleExpr);
21921 if (ASE && !ASE->getBase()->isTypeDependent() &&
21924 .getNonReferenceType()
21925 ->isPointerType() &&
21926 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
21927 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21930 << RefExpr->getSourceRange();
21937 Res =
SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
21938 RefExpr->IgnoreParenImpCasts());
21942 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21945 << RefExpr->getSourceRange();
21950 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21954 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
21955 DepKind != OMPC_DEPEND_outallmemory &&
21956 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
21961 {DepKind, DepLoc,
Data.ColonLoc,
Data.OmpAllMemoryLoc}, DepModifier, Vars,
21962 TotalDepCount.getZExtValue());
21963 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
21964 DSAStack->isParentOrderedRegion())
21965 DSAStack->addDoacrossDependClause(
C, OpsOffs);
21974 "Unexpected device modifier in OpenMP < 50.");
21976 bool ErrorFound =
false;
21978 std::string Values =
21980 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
21986 Stmt *HelperValStmt =
nullptr;
21999 if (Modifier == OMPC_DEVICE_ancestor) {
22000 if (!
DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
22003 diag::err_omp_device_ancestor_without_requires_reverse_offload);
22011 if (CaptureRegion != OMPD_unknown &&
22012 !
SemaRef.CurContext->isDependentContext()) {
22013 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
22014 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22015 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
22020 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
22021 LParenLoc, ModifierLoc, EndLoc);
22026 bool FullCheck =
true) {
22031 SemaRef.
Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
22041 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
22047 (OASE && OASE->getColonLocFirst().isInvalid())) {
22048 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
22049 return ATy->getSExtSize() != 1;
22054 assert(OASE &&
"Expecting array section if not an array subscript.");
22055 const Expr *LowerBound = OASE->getLowerBound();
22056 const Expr *Length = OASE->getLength();
22065 llvm::APSInt ConstLowerBound = Result.
Val.
getInt();
22066 if (ConstLowerBound.getSExtValue())
22081 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr());
22086 if (!Length->EvaluateAsInt(Result, SemaRef.
getASTContext()))
22089 llvm::APSInt ConstLength = Result.
Val.
getInt();
22090 return CATy->getSExtSize() != ConstLength.getSExtValue();
22099 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
22104 (OASE && OASE->getColonLocFirst().isInvalid()))
22107 assert(OASE &&
"Expecting array section if not an array subscript.");
22108 const Expr *Length = OASE->getLength();
22114 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
22115 return ATy->getSExtSize() != 1;
22122 if (!Length->EvaluateAsInt(Result, SemaRef.
getASTContext()))
22125 llvm::APSInt ConstLength = Result.
Val.
getInt();
22126 return ConstLength.getSExtValue() != 1;
22165class MapBaseChecker final :
public StmtVisitor<MapBaseChecker, bool> {
22170 bool IsNonContiguous =
false;
22171 bool NoDiagnose =
false;
22172 const Expr *RelevantExpr =
nullptr;
22173 bool AllowUnitySizeArraySection =
true;
22174 bool AllowWholeSizeArraySection =
true;
22175 bool AllowAnotherPtr =
true;
22176 SourceLocation ELoc;
22177 SourceRange ERange;
22179 void emitErrorMsg() {
22181 if (SemaRef.getLangOpts().OpenMP < 50) {
22183 diag::err_omp_expected_named_var_member_or_array_expression)
22186 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
22192 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
22197 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22198 RelevantExpr = DRE;
22200 Components.emplace_back(DRE, DRE->
getDecl(), IsNonContiguous);
22204 bool VisitMemberExpr(MemberExpr *ME) {
22209 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22218 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
22234 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
22254 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
22258 return RelevantExpr || Visit(E);
22268 AllowUnitySizeArraySection =
false;
22269 AllowWholeSizeArraySection =
false;
22272 Components.emplace_back(ME, FD, IsNonContiguous);
22273 return RelevantExpr || Visit(E);
22276 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
22281 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
22285 return RelevantExpr || Visit(E);
22292 AllowWholeSizeArraySection =
false;
22295 Expr::EvalResult
Result;
22298 !
Result.Val.getInt().isZero()) {
22300 diag::err_omp_invalid_map_this_expr);
22302 diag::note_omp_invalid_subscript_on_this_ptr_map);
22304 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22309 Components.emplace_back(AE,
nullptr, IsNonContiguous);
22311 return RelevantExpr || Visit(E);
22314 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
22317 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
22318 "Array sections cannot be implicitly mapped.");
22332 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
22342 if (AllowWholeSizeArraySection) {
22349 if (NotWhole || IsPointer)
22350 AllowWholeSizeArraySection =
false;
22351 }
else if (DKind == OMPD_target_update &&
22352 SemaRef.getLangOpts().OpenMP >= 50) {
22353 if (IsPointer && !AllowAnotherPtr)
22354 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
22357 IsNonContiguous =
true;
22358 }
else if (AllowUnitySizeArraySection && NotUnity) {
22364 diag::err_array_section_does_not_specify_contiguous_storage)
22370 AllowAnotherPtr =
false;
22372 if (
const auto *TE = dyn_cast<CXXThisExpr>(E)) {
22373 Expr::EvalResult ResultR;
22374 Expr::EvalResult ResultL;
22379 diag::err_omp_invalid_map_this_expr);
22381 diag::note_omp_invalid_length_on_this_ptr_mapping);
22385 SemaRef.getASTContext()) &&
22388 diag::err_omp_invalid_map_this_expr);
22390 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
22392 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22397 Components.emplace_back(OASE,
nullptr,
false);
22398 return RelevantExpr || Visit(E);
22400 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
22404 Components.emplace_back(E,
nullptr, IsNonContiguous);
22406 return Visit(
Base->IgnoreParenImpCasts());
22409 bool VisitUnaryOperator(UnaryOperator *UO) {
22410 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->
isLValue() ||
22415 if (!RelevantExpr) {
22417 Components.emplace_back(UO,
nullptr,
false);
22421 bool VisitBinaryOperator(BinaryOperator *BO) {
22433 Components.emplace_back(BO,
nullptr,
false);
22436 "Either LHS or RHS have base decl inside");
22438 return RelevantExpr || Visit(LE);
22439 return RelevantExpr || Visit(RE);
22441 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
22442 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22443 RelevantExpr = CTE;
22444 Components.emplace_back(CTE,
nullptr, IsNonContiguous);
22447 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
22448 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22449 Components.emplace_back(COCE,
nullptr, IsNonContiguous);
22452 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
22458 return Visit(Source);
22460 bool VisitStmt(Stmt *) {
22464 const Expr *getFoundBase()
const {
return RelevantExpr; }
22465 explicit MapBaseChecker(
22468 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
22469 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
22470 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
22484 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
22488 if (SemaRef.
getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
22489 (CKind == OMPC_to || CKind == OMPC_from)) {
22490 auto CI = CurComponents.rbegin();
22491 auto CE = CurComponents.rend();
22492 for (; CI != CE; ++CI) {
22494 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
22499 SemaRef.
Diag(ELoc, diag::err_array_section_does_not_specify_length)
22503 return Checker.getFoundBase();
22512 bool CurrentRegionOnly,
22523 assert(!CurComponents.empty() &&
"Map clause expression with no components!");
22524 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
22525 "Map clause expression with unexpected base!");
22528 bool IsEnclosedByDataEnvironmentExpr =
false;
22529 const Expr *EnclosingExpr =
nullptr;
22531 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
22532 VD, CurrentRegionOnly,
22533 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
22534 ERange, CKind, &EnclosingExpr,
22538 if (CKind == Kind && SemaRef.
LangOpts.OpenMP >= 50)
22540 assert(!StackComponents.empty() &&
22541 "Map clause expression with no components!");
22542 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
22543 "Map clause expression with unexpected base!");
22547 const Expr *RE = StackComponents.front().getAssociatedExpression();
22553 auto CI = CurComponents.rbegin();
22554 auto CE = CurComponents.rend();
22555 auto SI = StackComponents.rbegin();
22556 auto SE = StackComponents.rend();
22557 for (; CI != CE && SI != SE; ++CI, ++SI) {
22562 if (CurrentRegionOnly &&
22569 SemaRef.
Diag(CI->getAssociatedExpression()->getExprLoc(),
22570 diag::err_omp_multiple_array_items_in_map_clause)
22571 << CI->getAssociatedExpression()->getSourceRange();
22572 SemaRef.
Diag(SI->getAssociatedExpression()->getExprLoc(),
22573 diag::note_used_here)
22574 << SI->getAssociatedExpression()->getSourceRange();
22579 if (CI->getAssociatedExpression()->getStmtClass() !=
22580 SI->getAssociatedExpression()->getStmtClass())
22584 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
22590 for (; SI != SE; ++SI) {
22592 if (
const auto *ASE =
22593 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
22594 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
22595 }
else if (
const auto *OASE = dyn_cast<ArraySectionExpr>(
22596 SI->getAssociatedExpression())) {
22599 }
else if (
const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
22600 SI->getAssociatedExpression())) {
22605 SemaRef, SI->getAssociatedExpression(),
Type))
22615 if (CI == CE && SI == SE) {
22616 if (CurrentRegionOnly) {
22617 if (CKind == OMPC_map) {
22618 SemaRef.
Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
22620 assert(CKind == OMPC_to || CKind == OMPC_from);
22621 SemaRef.
Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
22630 IsEnclosedByDataEnvironmentExpr =
true;
22635 std::prev(CI)->getAssociatedDeclaration()->getType();
22637 std::prev(CI)->getAssociatedExpression()->getExprLoc();
22656 if (CI == CE || SI == SE) {
22659 diag::err_omp_pointer_mapped_along_with_derived_section)
22665 if (CI->getAssociatedExpression()->getStmtClass() !=
22666 SI->getAssociatedExpression()->getStmtClass() ||
22667 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
22668 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
22669 assert(CI != CE && SI != SE);
22670 SemaRef.
Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
22683 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
22684 if (CKind == OMPC_map) {
22685 if (CI != CE || SI != SE) {
22689 CI != CE ? CurComponents.begin() : StackComponents.begin();
22690 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
22692 while (It != End && !It->getAssociatedDeclaration())
22693 std::advance(It, 1);
22694 assert(It != End &&
22695 "Expected at least one component with the declaration.");
22696 if (It != Begin && It->getAssociatedDeclaration()
22698 .getCanonicalType()
22699 ->isAnyPointerType()) {
22700 IsEnclosedByDataEnvironmentExpr =
false;
22701 EnclosingExpr =
nullptr;
22705 SemaRef.
Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
22707 assert(CKind == OMPC_to || CKind == OMPC_from);
22708 SemaRef.
Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
22718 if (!CurrentRegionOnly && SI != SE)
22719 EnclosingExpr = RE;
22723 IsEnclosedByDataEnvironmentExpr |=
22724 (!CurrentRegionOnly && CI != CE && SI == SE);
22729 if (CurrentRegionOnly)
22743 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
22745 diag::err_omp_original_storage_is_shared_and_does_not_contain)
22761 Expr *UnresolvedMapper) {
22781 Lookups.emplace_back();
22782 Lookups.back().append(Lookup.
begin(), Lookup.
end());
22785 }
else if (
auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
22790 assert(DMD &&
"Expect valid OMPDeclareMapperDecl during instantiation.");
22791 Lookups.back().addDecl(DMD);
22800 return !D->isInvalidDecl() &&
22801 (D->getType()->isDependentType() ||
22802 D->getType()->isInstantiationDependentType() ||
22803 D->getType()->containsUnexpandedParameterPack());
22814 false, URS.
begin(), URS.
end(),
false,
22822 SemaRef.
Diag(Loc, diag::err_omp_mapper_wrong_type);
22863 SemaRef.
Diag(Loc, diag::err_omp_invalid_mapper)
22873struct MappableVarListInfo {
22875 ArrayRef<Expr *> VarList;
22877 SmallVector<Expr *, 16> ProcessedVarList;
22881 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
22883 SmallVector<Expr *, 16> UDMapperList;
22885 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
22888 VarComponents.reserve(VarList.size());
22889 VarBaseDeclarations.reserve(VarList.size());
22898 const RecordDecl *RD = BaseType->getAsRecordDecl();
22908 for (
auto *FD : RD->
fields()) {
22910 MapperVarRef,
false, Range.getBegin(),
22916 SExprs.push_back(BE);
22924 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
22927 Maps.push_back(MapClause);
22928 return MapperVarRef;
22932 DSAStackTy *Stack) {
22938 const RecordDecl *RD = BaseType->getAsRecordDecl();
22947 MapperId = DeclNames.getIdentifier(&Ctx.
Idents.
get(
"default"));
22949 BaseType, MapperId, Maps,
nullptr);
22959 DMD->setMapperVarRef(MapperVarRef);
22983 Lookups.emplace_back();
22984 Lookups.back().append(Lookup.
begin(), Lookup.
end());
22991 return !D->isInvalidDecl() &&
22992 (D->getType()->isDependentType() ||
22993 D->getType()->isInstantiationDependentType() ||
22994 D->getType()->containsUnexpandedParameterPack());
23040 {CanonType,
nullptr});
23041 llvm::DenseMap<const Type *, bool> Visited;
23043 while (!Types.empty()) {
23044 auto [BaseType, CurFD] = Types.pop_back_val();
23045 while (ParentChain.back().second == 0)
23046 ParentChain.pop_back();
23047 --ParentChain.back().second;
23048 if (BaseType.isNull())
23051 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
23054 auto It = Visited.find(BaseType.getTypePtr());
23055 if (It == Visited.end()) {
23064 DefaultMapperId, BaseType);
23065 It = Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
23071 bool FirstIter =
true;
23081 ParentChain.emplace_back(CurFD, 1);
23083 ++ParentChain.back().second;
23085 Types.emplace_back(FieldTy, FD);
23104 bool IsMapTypeImplicit =
false,
bool NoDiagnose =
false) {
23107 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from ||
23108 CKind == OMPC_use_device_addr) &&
23109 "Unexpected clause kind with mappable expressions!");
23110 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
23118 MapperId.
setName(DeclNames.getIdentifier(
23120 MapperId.
setLoc(StartLoc);
23124 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
23125 bool UpdateUMIt =
false;
23126 Expr *UnresolvedMapper =
nullptr;
23128 bool HasHoldModifier =
23129 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
23137 for (
Expr *RE : MVLI.VarList) {
23138 assert(RE &&
"Null expr in omp to/from/map clause");
23142 if (UpdateUMIt && UMIt != UMEnd) {
23146 "Expect the size of UnresolvedMappers to match with that of VarList");
23150 UnresolvedMapper = *UMIt;
23154 if (
VE->isValueDependent() ||
VE->isTypeDependent() ||
23155 VE->isInstantiationDependent() ||
23156 VE->containsUnexpandedParameterPack()) {
23159 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23160 VE->getType().getCanonicalType(), UnresolvedMapper);
23163 MVLI.UDMapperList.push_back(ER.
get());
23166 MVLI.ProcessedVarList.push_back(RE);
23175 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
23178 SemaRef.
Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
23191 DSAS->getCurrentDirective(), NoDiagnose);
23195 assert(!CurComponents.empty() &&
23196 "Invalid mappable expression information.");
23198 if (
const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
23200 DSAS->addMappedClassesQualTypes(TE->getType());
23203 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23204 VE->getType().getCanonicalType(), UnresolvedMapper);
23207 MVLI.UDMapperList.push_back(ER.
get());
23209 MVLI.ProcessedVarList.push_back(RE);
23210 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23211 MVLI.VarComponents.back().append(CurComponents.begin(),
23212 CurComponents.end());
23213 MVLI.VarBaseDeclarations.push_back(
nullptr);
23220 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
23221 assert(CurDeclaration &&
"Null decl on map clause.");
23224 "Expecting components to have associated only canonical declarations.");
23226 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
23227 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
23229 assert((VD || FD) &&
"Only variables or fields are expected here!");
23236 if (VD && DSAS->isThreadPrivate(VD)) {
23239 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD,
false);
23240 SemaRef.
Diag(ELoc, diag::err_omp_threadprivate_in_clause)
23255 true, CurComponents, CKind))
23257 if (CKind == OMPC_map &&
23260 false, CurComponents, CKind))
23267 auto I = llvm::find_if(
23269 [](
const OMPClauseMappableExprCommon::MappableComponent &MC) {
23272 assert(I != CurComponents.end() &&
"Null decl on map clause.");
23275 auto *ASE = dyn_cast<ArraySubscriptExpr>(
VE->IgnoreParens());
23276 auto *OASE = dyn_cast<ArraySectionExpr>(
VE->IgnoreParens());
23277 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(
VE->IgnoreParens());
23279 Type = ASE->getType().getNonReferenceType();
23284 Type = ATy->getElementType();
23287 Type =
Type.getNonReferenceType();
23288 }
else if (OAShE) {
23302 if (CKind == OMPC_map) {
23309 if (DKind == OMPD_target_enter_data &&
23310 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
23312 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23313 << (IsMapTypeImplicit ? 1 : 0)
23315 << getOpenMPDirectiveName(DKind, OMPVersion);
23324 if (DKind == OMPD_target_exit_data &&
23325 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
23326 MapType == OMPC_MAP_delete || SemaRef.
getLangOpts().OpenMP >= 52)) {
23327 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23328 << (IsMapTypeImplicit ? 1 : 0)
23330 << getOpenMPDirectiveName(DKind, OMPVersion);
23339 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
23341 SemaRef.
Diag(StartLoc,
23342 diag::err_omp_invalid_map_type_modifier_for_directive)
23344 OMPC_MAP_MODIFIER_ompx_hold)
23345 << getOpenMPDirectiveName(DKind, OMPVersion);
23353 if ((DKind == OMPD_target_data ||
23355 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
23356 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
23357 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23358 << (IsMapTypeImplicit ? 1 : 0)
23360 << getOpenMPDirectiveName(DKind, OMPVersion);
23372 if (VD && ((SemaRef.
LangOpts.OpenMP <= 45 &&
23374 DKind == OMPD_target)) {
23375 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD,
false);
23377 SemaRef.
Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23380 << getOpenMPDirectiveName(DSAS->getCurrentDirective(),
23390 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23391 Type.getCanonicalType(), UnresolvedMapper);
23403 BaseType =
VE->getType().getCanonicalType();
23410 ElemType = ATy->getElementType();
23415 }
else if (
VE->getType()->isArrayType()) {
23416 const ArrayType *AT =
VE->getType()->getAsArrayTypeUnsafe();
23426 MVLI.UDMapperList.push_back(ER.
get());
23429 MVLI.ProcessedVarList.push_back(RE);
23433 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
23439 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23440 MVLI.VarComponents.back().append(CurComponents.begin(),
23441 CurComponents.end());
23463 BuiltinType::OMPIterator))
23465 diag::err_omp_map_modifier_not_iterator);
23468 unsigned Count = 0;
23469 for (
unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
23471 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
23472 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
23476 "Modifiers exceed the allowed number of map type modifiers");
23477 Modifiers[Count] = MapTypeModifiers[I];
23478 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
23482 MappableVarListInfo MVLI(VarList);
23484 MapperIdScopeSpec, MapperId, UnresolvedMappers,
23485 MapType, Modifiers, IsMapTypeImplicit,
23491 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23492 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
23494 MapperId, MapType, IsMapTypeImplicit, MapLoc);
23502 if (ReductionType.
isNull())
23510 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
23515 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
23519 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
23523 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
23526 return ReductionType;
23532 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
23535 Decls.reserve(ReductionTypes.size());
23539 SemaRef.forRedeclarationInCurContext());
23544 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
23546 bool InCompoundScope =
true;
23547 if (S !=
nullptr) {
23553 SemaRef.LookupName(Lookup, S);
23554 SemaRef.FilterLookupForScope(Lookup, DC, S,
false,
23556 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
23558 while (Filter.hasNext()) {
23560 if (InCompoundScope) {
23561 UsedAsPrevious.try_emplace(PrevDecl,
false);
23563 UsedAsPrevious[D] =
true;
23565 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
23566 PrevDecl->getLocation();
23569 if (InCompoundScope) {
23570 for (
const auto &PrevData : UsedAsPrevious) {
23571 if (!PrevData.second) {
23572 PrevDRD = PrevData.first;
23577 }
else if (PrevDeclInScope !=
nullptr) {
23578 auto *PrevDRDInScope = PrevDRD =
23581 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
23582 PrevDRDInScope->getLocation();
23583 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
23584 }
while (PrevDRDInScope !=
nullptr);
23586 for (
const auto &TyData : ReductionTypes) {
23587 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
23589 if (I != PreviousRedeclTypes.end()) {
23590 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
23592 Diag(I->second, diag::note_previous_definition);
23595 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
23597 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
23599 DRD->setAccess(AS);
23600 Decls.push_back(DRD);
23602 DRD->setInvalidDecl();
23616 SemaRef.setFunctionHasBranchProtectedScope();
23617 SemaRef.getCurFunction()->setHasOMPDeclareReductionCombiner();
23620 SemaRef.PushDeclContext(S, DRD);
23624 SemaRef.PushExpressionEvaluationContext(
23627 QualType ReductionType = DRD->getType();
23644 if (S !=
nullptr) {
23645 SemaRef.PushOnScopeChains(OmpInParm, S);
23646 SemaRef.PushOnScopeChains(OmpOutParm, S);
23648 DRD->addDecl(OmpInParm);
23649 DRD->addDecl(OmpOutParm);
23655 DRD->setCombinerData(InE, OutE);
23661 SemaRef.DiscardCleanupsInEvaluationContext();
23662 SemaRef.PopExpressionEvaluationContext();
23665 SemaRef.PopFunctionScopeInfo();
23667 if (Combiner !=
nullptr)
23668 DRD->setCombiner(Combiner);
23670 DRD->setInvalidDecl();
23679 SemaRef.setFunctionHasBranchProtectedScope();
23682 SemaRef.PushDeclContext(S, DRD);
23686 SemaRef.PushExpressionEvaluationContext(
23689 QualType ReductionType = DRD->getType();
23706 if (S !=
nullptr) {
23707 SemaRef.PushOnScopeChains(OmpPrivParm, S);
23708 SemaRef.PushOnScopeChains(OmpOrigParm, S);
23710 DRD->addDecl(OmpPrivParm);
23711 DRD->addDecl(OmpOrigParm);
23717 DRD->setInitializerData(OrigE, PrivE);
23718 return OmpPrivParm;
23724 SemaRef.DiscardCleanupsInEvaluationContext();
23725 SemaRef.PopExpressionEvaluationContext();
23728 SemaRef.PopFunctionScopeInfo();
23732 }
else if (OmpPrivParm->
hasInit()) {
23733 DRD->setInitializer(OmpPrivParm->
getInit(),
23738 DRD->setInvalidDecl();
23744 for (
Decl *D : DeclReductions.
get()) {
23750 D->setInvalidDecl();
23753 return DeclReductions;
23765 SemaRef.CheckExtraCXXDefaultArguments(D);
23768 return SemaRef.CreateParsedType(T, TInfo);
23773 assert(
ParsedType.isUsable() &&
"Expect usable parsed mapper type");
23776 assert(!MapperType.
isNull() &&
"Expect valid mapper type");
23781 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
23793 SemaRef.forRedeclarationInCurContext());
23798 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
23800 bool InCompoundScope =
true;
23801 if (S !=
nullptr) {
23807 SemaRef.LookupName(Lookup, S);
23808 SemaRef.FilterLookupForScope(Lookup, DC, S,
false,
23810 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
23812 while (Filter.hasNext()) {
23814 if (InCompoundScope) {
23815 UsedAsPrevious.try_emplace(PrevDecl,
false);
23817 UsedAsPrevious[D] =
true;
23819 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
23820 PrevDecl->getLocation();
23823 if (InCompoundScope) {
23824 for (
const auto &PrevData : UsedAsPrevious) {
23825 if (!PrevData.second) {
23826 PrevDMD = PrevData.first;
23831 }
else if (PrevDeclInScope) {
23832 auto *PrevDMDInScope = PrevDMD =
23835 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
23836 PrevDMDInScope->getLocation();
23837 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
23838 }
while (PrevDMDInScope !=
nullptr);
23842 if (I != PreviousRedeclTypes.end()) {
23843 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
23844 << MapperType << Name;
23845 Diag(I->second, diag::note_previous_definition);
23853 ClausesWithImplicit);
23855 MapperType, VN, ClausesWithImplicit,
23858 SemaRef.PushOnScopeChains(DMD, S);
23861 DMD->setAccess(AS);
23863 DMD->setInvalidDecl();
23869 DMD->setMapperVarRef(MapperVarRef);
23883 SemaRef.PushOnScopeChains(VD, S,
false);
23885 DSAStack->addDeclareMapperVarRef(E);
23892 if (
DSAStack->getDeclareMapperVarRef()) {
23898 assert(!IsGlobalVar &&
"Only declare mapper handles TU-scope iterators.");
23903 assert(
getLangOpts().OpenMP &&
"Expected OpenMP mode.");
23905 if (
const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
23918 assert(
getLangOpts().OpenMP &&
"Expected OpenMP mode.");
23926 if (VarList.empty())
23929 for (
Expr *ValExpr : VarList) {
23938 if (VarList.size() == 2) {
23939 Expr *LowerBound = VarList[0];
23940 Expr *UpperBound = VarList[1];
23948 llvm::APSInt LowerVal =
23950 llvm::APSInt UpperVal =
23953 if (LowerVal > UpperVal) {
23955 diag::err_omp_num_teams_lower_bound_larger)
23965 if (CaptureRegion == OMPD_unknown ||
SemaRef.CurContext->isDependentContext())
23967 LParenLoc, EndLoc, VarList,
23970 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23972 for (
Expr *ValExpr : VarList) {
23973 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
23974 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
23975 Vars.push_back(ValExpr);
23980 LParenLoc, EndLoc, Vars, PreInit);
23987 if (VarList.empty())
23990 for (
Expr *ValExpr : VarList) {
24001 if (CaptureRegion == OMPD_unknown ||
SemaRef.CurContext->isDependentContext())
24003 StartLoc, LParenLoc, EndLoc, VarList,
24006 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24008 for (
Expr *ValExpr : VarList) {
24009 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
24010 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
24011 Vars.push_back(ValExpr);
24016 LParenLoc, EndLoc, Vars, PreInit);
24023 Expr *ValExpr = Priority;
24024 Stmt *HelperValStmt =
nullptr;
24030 ValExpr,
SemaRef, OMPC_priority,
24032 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
24036 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
24044 "Unexpected grainsize modifier in OpenMP < 51.");
24049 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
24054 Expr *ValExpr = Grainsize;
24055 Stmt *HelperValStmt =
nullptr;
24065 &CaptureRegion, &HelperValStmt))
24070 StartLoc, LParenLoc, ModifierLoc, EndLoc);
24078 "Unexpected num_tasks modifier in OpenMP < 51.");
24083 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
24088 Expr *ValExpr = NumTasks;
24089 Stmt *HelperValStmt =
nullptr;
24096 ValExpr,
SemaRef, OMPC_num_tasks,
24098 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
24103 StartLoc, LParenLoc, ModifierLoc, EndLoc);
24123 DSAStackTy *Stack) {
24124 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
24125 if (!OMPEventHandleT.
isNull())
24130 S.
Diag(Loc, diag::err_omp_implied_type_not_found) <<
"omp_event_handle_t";
24133 Stack->setOMPEventHandleT(PT.
get());
24154 auto *VD = dyn_cast_or_null<VarDecl>(Ref->
getDecl());
24164 <<
"omp_event_handle_t" << 1 << VD->
getType()
24171 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(VD,
false);
24172 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
24191 std::string Values;
24195 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24199 Expr *ValExpr = ChunkSize;
24200 Stmt *HelperValStmt =
nullptr;
24211 ValExpr = Val.
get();
24216 if (std::optional<llvm::APSInt>
Result =
24218 if (
Result->isSigned() && !
Result->isStrictlyPositive()) {
24219 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
24220 <<
"dist_schedule" << 1
24225 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
24227 !
SemaRef.CurContext->isDependentContext()) {
24228 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
24229 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24230 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
24238 Kind, ValExpr, HelperValStmt);
24246 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
24247 Kind != OMPC_DEFAULTMAP_scalar) {
24251 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
24253 OMPC_DEFAULTMAP_MODIFIER_tofrom);
24257 OMPC_DEFAULTMAP_scalar);
24261 Diag(Loc, diag::err_omp_unexpected_clause_value)
24269 if (!isDefaultmapKind || !isDefaultmapModifier) {
24271 ?
"'scalar', 'aggregate', 'pointer'"
24272 :
"'scalar', 'aggregate', 'pointer', 'all'";
24274 StringRef ModifierValue =
"'alloc', 'from', 'to', 'tofrom', "
24275 "'firstprivate', 'none', 'default'";
24276 if (!isDefaultmapKind && isDefaultmapModifier) {
24277 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24279 }
else if (isDefaultmapKind && !isDefaultmapModifier) {
24280 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24283 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24285 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24289 StringRef ModifierValue =
24291 ?
"'alloc', 'from', 'to', 'tofrom', "
24292 "'firstprivate', 'none', 'default', 'present'"
24293 :
"'storage', 'from', 'to', 'tofrom', "
24294 "'firstprivate', 'private', 'none', 'default', 'present'";
24295 if (!isDefaultmapKind && isDefaultmapModifier) {
24296 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24298 }
else if (isDefaultmapKind && !isDefaultmapModifier) {
24299 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24302 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24304 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24314 if (
DSAStack->checkDefaultmapCategory(Kind)) {
24315 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
24321 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
24322 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
24323 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
24325 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
24342 Diag(DTCI.
Loc, diag::err_omp_region_not_file_context);
24348 Diag(DTCI.
Loc, diag::warn_hip_omp_target_directives);
24350 DeclareTargetNesting.push_back(DTCI);
24356 assert(!DeclareTargetNesting.empty() &&
24357 "check isInOpenMPDeclareTargetContext() first!");
24358 return DeclareTargetNesting.pop_back_val();
24368 if (DeclareTargetNesting.empty())
24372 Diag(DTCI.
Loc, diag::warn_omp_unterminated_declare_target)
24373 << getOpenMPDirectiveName(DTCI.
Kind, OMPVersion);
24379 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
24388 VarOrFuncDeclFilterCCC CCC(
SemaRef);
24392 SemaRef.diagnoseTypo(Corrected,
24393 SemaRef.PDiag(diag::err_undeclared_var_use_suggest)
24417 "Expected variable, function or function template.");
24419 if (
auto *VD = dyn_cast<VarDecl>(ND)) {
24421 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
24422 !VD->isStaticDataMember()) {
24423 Diag(Loc, diag::err_omp_declare_target_has_local_vars)
24432 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
24436 Diag(Loc, diag::warn_hip_omp_target_directives);
24439 const unsigned Level = -1;
24442 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
24443 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
24444 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.
DT &&
24445 (*ActiveAttr)->getLevel() == Level) {
24446 Diag(Loc, diag::err_omp_device_type_mismatch)
24447 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.
DT)
24448 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
24449 (*ActiveAttr)->getDevType());
24452 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
24453 (*ActiveAttr)->getLevel() == Level) {
24454 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
24458 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
24461 Expr *IndirectE =
nullptr;
24462 bool IsIndirect =
false;
24468 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
24473 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
24475 if (
auto *VD = dyn_cast<VarDecl>(ND);
24477 VD->hasGlobalStorage())
24486 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy>
MapTy =
24487 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
24488 if (SemaRef.
LangOpts.OpenMP >= 50 &&
24491 VD->hasGlobalStorage()) {
24492 if (!
MapTy || (*
MapTy != OMPDeclareTargetDeclAttr::MT_To &&
24493 *
MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
24500 diag::err_omp_lambda_capture_in_declare_target_not_to);
24501 SemaRef.
Diag(SL, diag::note_var_explicitly_captured_here)
24508 SemaRef.
Diag(VD->
getLocation(), diag::warn_omp_not_in_target_context);
24509 SemaRef.
Diag(SL, diag::note_used_here) << SR;
24513 Sema &SemaRef, DSAStackTy *Stack,
24515 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
24526 if (
auto *VD = dyn_cast<VarDecl>(D)) {
24528 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
24529 !VD->isStaticDataMember())
24533 if (
DSAStack->isThreadPrivate(VD)) {
24534 Diag(SL, diag::err_omp_threadprivate_in_target);
24539 if (
const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
24540 D = FTD->getTemplatedDecl();
24541 if (
auto *FD = dyn_cast<FunctionDecl>(D)) {
24542 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
24543 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
24544 if (IdLoc.
isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
24545 Diag(IdLoc, diag::err_omp_function_in_link_clause);
24550 if (
auto *VD = dyn_cast<ValueDecl>(D)) {
24560 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
24561 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
24562 unsigned Level = DeclareTargetNesting.size();
24563 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
24566 Expr *IndirectE =
nullptr;
24567 bool IsIndirect =
false;
24573 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
24575 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
24576 : OMPDeclareTargetDeclAttr::MT_To,
24577 DTCI.
DT, IndirectE, IsIndirect, Level,
24581 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
24601 if (
auto *VD = dyn_cast<VarDecl>(Node->
getDecl())) {
24603 DeclVector.push_back(VD);
24608 for (
auto *Child : Ex->
children()) {
24617 A = TD->
getAttr<OMPDeclareTargetDeclAttr>();
24619 llvm::SmallDenseSet<Decl *> Visited;
24620 while (!DeclVector.empty()) {
24621 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
24622 if (!Visited.insert(TargetVarDecl).second)
24625 if (TargetVarDecl->
hasAttr<OMPDeclareTargetDeclAttr>() &&
24655 unsigned Count = 0;
24656 for (
unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
24658 llvm::is_contained(Modifiers, MotionModifiers[I])) {
24659 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
24663 "Modifiers exceed the allowed number of motion modifiers");
24664 Modifiers[Count] = MotionModifiers[I];
24665 ModifiersLoc[Count] = MotionModifiersLoc[I];
24669 MappableVarListInfo MVLI(VarList);
24671 MapperIdScopeSpec, MapperId, UnresolvedMappers);
24672 if (MVLI.ProcessedVarList.empty())
24675 if (
auto *DRE = dyn_cast<DeclRefExpr>(IteratorExpr))
24676 if (
auto *VD = dyn_cast<VarDecl>(DRE->
getDecl()))
24679 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24680 MVLI.VarComponents, MVLI.UDMapperList, IteratorExpr, Modifiers,
24697 unsigned Count = 0;
24698 for (
unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
24700 llvm::is_contained(Modifiers, MotionModifiers[I])) {
24701 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
24705 "Modifiers exceed the allowed number of motion modifiers");
24706 Modifiers[Count] = MotionModifiers[I];
24707 ModifiersLoc[Count] = MotionModifiersLoc[I];
24711 MappableVarListInfo MVLI(VarList);
24713 MapperIdScopeSpec, MapperId, UnresolvedMappers);
24714 if (MVLI.ProcessedVarList.empty())
24717 if (
auto *DRE = dyn_cast<DeclRefExpr>(IteratorExpr))
24718 if (
auto *VD = dyn_cast<VarDecl>(DRE->
getDecl()))
24721 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24722 MVLI.VarComponents, MVLI.UDMapperList, IteratorExpr, Modifiers,
24731 MappableVarListInfo MVLI(VarList);
24735 for (
Expr *RefExpr : VarList) {
24736 assert(RefExpr &&
"NULL expr in OpenMP use_device_ptr clause.");
24739 Expr *SimpleRefExpr = RefExpr;
24743 MVLI.ProcessedVarList.push_back(RefExpr);
24744 PrivateCopies.push_back(
nullptr);
24745 Inits.push_back(
nullptr);
24752 Type =
Type.getNonReferenceType().getUnqualifiedType();
24754 auto *VD = dyn_cast<VarDecl>(D);
24758 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
24759 << 0 << RefExpr->getSourceRange();
24768 if (VDPrivate->isInvalidDecl())
24771 SemaRef.CurContext->addDecl(VDPrivate);
24773 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
24780 SemaRef.AddInitializerToDecl(
24781 VDPrivate,
SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
24789 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
24790 PrivateCopies.push_back(VDPrivateRefExpr);
24791 Inits.push_back(VDInitRefExpr);
24796 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
24800 MVLI.VarBaseDeclarations.push_back(D);
24801 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24802 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
24806 if (MVLI.ProcessedVarList.empty())
24811 MVLI.VarBaseDeclarations, MVLI.VarComponents, FallbackModifier,
24812 FallbackModifierLoc);
24818 MappableVarListInfo MVLI(VarList);
24820 for (
Expr *RefExpr : VarList) {
24821 assert(RefExpr &&
"NULL expr in OpenMP use_device_addr clause.");
24824 Expr *SimpleRefExpr = RefExpr;
24830 MVLI.ProcessedVarList.push_back(RefExpr);
24835 auto *VD = dyn_cast<VarDecl>(D);
24842 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
24847 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
24853 SemaRef, RefExpr, CurComponents, OMPC_use_device_addr,
24860 assert(!CurComponents.empty() &&
24861 "use_device_addr clause expression with no components!");
24878 CurComponents,
DSAStack->getCurrentDirective());
24879 const Expr *AttachPtrExpr = AttachPtrResult.first;
24881 if (AttachPtrExpr) {
24883 bool IsValidBase =
false;
24886 IsValidBase =
true;
24887 else if (
const auto *ME = dyn_cast<MemberExpr>(BaseExpr);
24889 IsValidBase =
true;
24891 if (!IsValidBase) {
24893 diag::err_omp_expected_base_pointer_var_name_member_expr)
24894 << (
SemaRef.getCurrentThisType().isNull() ? 0 : 1)
24901 ValueDecl *CurDeclaration = CurComponents.back().getAssociatedDeclaration();
24903 "Unexpected null decl for use_device_addr clause.");
24905 MVLI.VarBaseDeclarations.push_back(CurDeclaration);
24906 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24907 MVLI.VarComponents.back().append(CurComponents.begin(),
24908 CurComponents.end());
24911 if (MVLI.ProcessedVarList.empty())
24915 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24916 MVLI.VarComponents);
24922 MappableVarListInfo MVLI(VarList);
24923 for (
Expr *RefExpr : VarList) {
24924 assert(RefExpr &&
"NULL expr in OpenMP is_device_ptr clause.");
24927 Expr *SimpleRefExpr = RefExpr;
24931 MVLI.ProcessedVarList.push_back(RefExpr);
24941 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
24942 << 0 << RefExpr->getSourceRange();
24948 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
24951 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
24954 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
24960 const Expr *ConflictExpr;
24961 if (
DSAStack->checkMappableExprComponentListsForDecl(
24966 ConflictExpr = R.front().getAssociatedExpression();
24969 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
24978 SimpleRefExpr, D,
false);
24979 DSAStack->addMappableExpressionComponents(
24980 D, MC, OMPC_is_device_ptr);
24983 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
24990 "Unexpected device pointer expression!");
24991 MVLI.VarBaseDeclarations.push_back(
24993 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24994 MVLI.VarComponents.back().push_back(MC);
24997 if (MVLI.ProcessedVarList.empty())
25001 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
25002 MVLI.VarComponents);
25008 MappableVarListInfo MVLI(VarList);
25009 for (
Expr *RefExpr : VarList) {
25010 assert(RefExpr &&
"NULL expr in OpenMP has_device_addr clause.");
25013 Expr *SimpleRefExpr = RefExpr;
25018 MVLI.ProcessedVarList.push_back(RefExpr);
25026 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
25029 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
25032 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
25038 const Expr *ConflictExpr;
25039 if (
DSAStack->checkMappableExprComponentListsForDecl(
25044 ConflictExpr = R.front().getAssociatedExpression();
25047 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
25055 Expr *Component = SimpleRefExpr;
25056 auto *VD = dyn_cast<VarDecl>(D);
25060 SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
25062 Component, D,
false);
25063 DSAStack->addMappableExpressionComponents(
25064 D, MC, OMPC_has_device_addr);
25067 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
25070 assert(Ref &&
"has_device_addr capture failed");
25071 MVLI.ProcessedVarList.push_back(Ref);
25073 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
25080 "Unexpected device pointer expression!");
25081 MVLI.VarBaseDeclarations.push_back(
25083 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
25084 MVLI.VarComponents.back().push_back(MC);
25087 if (MVLI.ProcessedVarList.empty())
25091 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
25092 MVLI.VarComponents);
25106 bool AllocDependent =
25110 if (!AllocDependent) {
25119 AllocatorRes =
SemaRef.PerformImplicitConversion(
25120 AllocatorRes.
get(),
DSAStack->getOMPAllocatorHandleT(),
25125 Allocator = AllocatorRes.
isUsable() ? AllocatorRes.
get() :
nullptr;
25134 !
DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
25135 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
25142 if (!AlignmentDependent) {
25145 Alignment = AlignResult.
isUsable() ? AlignResult.
get() :
nullptr;
25150 for (
Expr *RefExpr : VarList) {
25151 assert(RefExpr &&
"NULL expr in OpenMP allocate clause.");
25154 Expr *SimpleRefExpr = RefExpr;
25158 Vars.push_back(RefExpr);
25164 auto *VD = dyn_cast<VarDecl>(D);
25166 if (!VD && !
SemaRef.CurContext->isDependentContext())
25168 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
25169 ? RefExpr->IgnoreParens()
25177 DSAStack->addInnerAllocatorExpr(Allocator);
25180 getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
25181 FirstAllocateModifier, FirstAllocateModifierLoc, SecondAllocateModifier,
25182 SecondAllocateModifierLoc, EndLoc, Vars);
25190 for (
Expr *RefExpr : VarList) {
25191 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
25194 Expr *SimpleRefExpr = RefExpr;
25198 Vars.push_back(RefExpr);
25205 if (
const Expr *PrevRef =
25206 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
25207 Diag(ELoc, diag::err_omp_used_in_clause_twice)
25209 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
25214 Vars.push_back(RefExpr);
25231 SemaRef.setFunctionHasBranchProtectedScope();
25233 return OMPScopeDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses,
25242 for (
Expr *RefExpr : VarList) {
25243 assert(RefExpr &&
"NULL expr in OpenMP inclusive clause.");
25246 Expr *SimpleRefExpr = RefExpr;
25251 Vars.push_back(RefExpr);
25256 const DSAStackTy::DSAVarData DVar =
25262 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
25263 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
25264 << RefExpr->getSourceRange();
25266 if (
DSAStack->getParentDirective() != OMPD_unknown)
25267 DSAStack->markDeclAsUsedInScanDirective(D);
25268 Vars.push_back(RefExpr);
25283 for (
Expr *RefExpr : VarList) {
25284 assert(RefExpr &&
"NULL expr in OpenMP exclusive clause.");
25287 Expr *SimpleRefExpr = RefExpr;
25292 Vars.push_back(RefExpr);
25298 DSAStackTy::DSAVarData DVar;
25299 if (ParentDirective != OMPD_unknown)
25300 DVar =
DSAStack->getTopDSA(D,
true);
25305 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
25306 DVar.Modifier != OMPC_REDUCTION_inscan) {
25307 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
25308 << RefExpr->getSourceRange();
25310 DSAStack->markDeclAsUsedInScanDirective(D);
25312 Vars.push_back(RefExpr);
25324 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
25325 if (!OMPAlloctraitT.
isNull())
25330 S.
Diag(Loc, diag::err_omp_implied_type_not_found) <<
"omp_alloctrait_t";
25333 Stack->setOMPAlloctraitT(PT.
get());
25353 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
25354 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
25355 StringRef Allocator =
25356 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
25358 PredefinedAllocators.insert(
SemaRef.LookupSingleName(
25364 Expr *AllocatorExpr =
nullptr;
25372 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
25373 bool IsPredefinedAllocator =
false;
25375 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
25377 IsPredefinedAllocator =
25379 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
25383 bool IsTypeCompatible = IsPredefinedAllocator;
25384 IsTypeCompatible = IsTypeCompatible ||
25385 Context.hasSameUnqualifiedType(AllocatorExprType,
25386 OMPAllocatorHandleT);
25388 IsTypeCompatible ||
25389 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
25390 bool IsNonConstantLValue =
25392 if (!DRE || !IsTypeCompatible ||
25393 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
25395 <<
"omp_allocator_handle_t" << (DRE ? 1 : 0)
25404 diag::err_omp_predefined_allocator_with_traits)
25417 diag::err_omp_nonpredefined_allocator_without_traits);
25423 AllocatorExpr =
SemaRef.DefaultLvalueConversion(AllocatorExpr).get();
25426 IsPredefinedAllocator
25427 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
25428 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
25430 Expr *AllocatorTraitsExpr =
nullptr;
25444 if (
const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
25445 TraitTy = ConstArrayTy->getElementType();
25447 !(Context.hasSameUnqualifiedType(TraitTy,
25449 Context.typesAreCompatible(TraitTy,
DSAStack->getOMPAlloctraitT(),
25452 diag::err_omp_expected_array_alloctraits)
25453 << AllocatorTraitsExpr->
getType();
25458 if (
auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
25461 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
25478 for (
Expr *RefExpr : Locators) {
25479 assert(RefExpr &&
"NULL expr in OpenMP affinity clause.");
25482 Vars.push_back(RefExpr);
25490 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
25491 << 1 << 0 << RefExpr->getSourceRange();
25502 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
25503 << 1 << 0 << RefExpr->getSourceRange();
25510 ColonLoc, EndLoc, Modifier, Vars);
25519 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
25527 LParenLoc, EndLoc);
25534 Expr *ValExpr = Size;
25535 Stmt *HelperValStmt =
nullptr;
25546 DKind, OMPC_ompx_dyn_cgroup_mem,
getLangOpts().OpenMP);
25547 if (CaptureRegion != OMPD_unknown &&
25548 !
SemaRef.CurContext->isDependentContext()) {
25549 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
25550 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
25551 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
25556 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
25571 diag::err_omp_unexpected_clause_value)
25572 << Values << getOpenMPClauseName(OMPC_dyn_groupprivate);
25576 Expr *ValExpr = Size;
25577 Stmt *HelperValStmt =
nullptr;
25588 DKind, OMPC_dyn_groupprivate,
getLangOpts().OpenMP);
25589 if (CaptureRegion != OMPD_unknown &&
25590 !
SemaRef.CurContext->isDependentContext()) {
25591 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
25592 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
25593 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
25598 StartLoc, LParenLoc, EndLoc, ValExpr, HelperValStmt, CaptureRegion, M1,
25607 if (
DSAStack->getCurrentDirective() == OMPD_ordered &&
25608 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
25609 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
25610 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
25611 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
25617 DSAStackTy::OperatorOffsetTy OpsOffs;
25618 llvm::APSInt TotalDepCount(32);
25621 DepType == OMPC_DOACROSS_source ||
25622 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
25623 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
25625 Vars = VarOffset.Vars;
25626 OpsOffs = VarOffset.OpsOffs;
25627 TotalDepCount = VarOffset.TotalDepCount;
25629 EndLoc, DepType, DepLoc, ColonLoc, Vars,
25630 TotalDepCount.getZExtValue());
25631 if (
DSAStack->isParentOrderedRegion())
25632 DSAStack->addDoacrossDependClause(
C, OpsOffs);
25652 return new (
getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
25660 return OMPAbsentClause::Create(
getASTContext(), DKVec, Loc, LLoc, RLoc);
25661 case OMPC_contains:
25662 return OMPContainsClause::Create(
getASTContext(), DKVec, Loc, LLoc, RLoc);
25664 llvm_unreachable(
"Unexpected OpenMP clause");
25672 case OMPC_no_openmp:
25674 case OMPC_no_openmp_routines:
25675 return new (
getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
25676 case OMPC_no_parallelism:
25677 return new (
getASTContext()) OMPNoParallelismClause(Loc, RLoc);
25678 case OMPC_no_openmp_constructs:
25679 return new (
getASTContext()) OMPNoOpenMPConstructsClause(Loc, RLoc);
25681 llvm_unreachable(
"Unexpected OpenMP clause");
25690 if (
Base->hasPlaceholderType() &&
25691 !
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
25704 LowerBound =
Result.get();
25706 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
25726 if (
Base->isTypeDependent() ||
25729 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
25732 Base, LowerBound, Length, Stride, Context.DependentTy,
VK_LValue,
25733 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
25745 Diag(
Base->getExprLoc(), diag::err_omp_typecheck_section_value)
25746 <<
Base->getSourceRange());
25752 if (Res.isInvalid())
25754 diag::err_omp_typecheck_section_not_integer)
25756 LowerBound = Res.get();
25766 if (Res.isInvalid())
25768 diag::err_omp_typecheck_section_not_integer)
25769 << 1 << Length->getSourceRange());
25770 Length = Res.get();
25772 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
25773 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
25774 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
25775 << 1 << Length->getSourceRange();
25782 diag::err_omp_typecheck_section_not_integer)
25784 Stride = Res.
get();
25797 Diag(
Base->getExprLoc(), diag::err_omp_section_function_type)
25798 << ResultTy <<
Base->getSourceRange();
25802 if (
SemaRef.RequireCompleteType(
Base->getExprLoc(), ResultTy,
25803 diag::err_omp_section_incomplete_type,
Base))
25811 llvm::APSInt LowerBoundValue =
Result.Val.getInt();
25812 if (LowerBoundValue.isNegative()) {
25814 diag::err_omp_section_not_subset_of_array)
25823 if (Length->EvaluateAsInt(
Result, Context)) {
25826 llvm::APSInt LengthValue =
Result.Val.getInt();
25827 if (LengthValue.isNegative()) {
25828 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
25829 <<
toString(LengthValue, 10,
true)
25830 << Length->getSourceRange();
25834 }
else if (
SemaRef.getLangOpts().OpenMP < 60 && ColonLocFirst.
isValid() &&
25840 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
25850 llvm::APSInt StrideValue =
Result.Val.getInt();
25851 if (!StrideValue.isStrictlyPositive()) {
25852 Diag(Stride->
getExprLoc(), diag::err_omp_section_stride_non_positive)
25853 <<
toString(StrideValue, 10,
true)
25860 if (!
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
25867 Base, LowerBound, Length, Stride, Context.ArraySectionTy,
VK_LValue,
25868 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
25875 if (
Base->hasPlaceholderType()) {
25889 LParenLoc, RParenLoc, Dims, Brackets);
25891 (!
Base->isTypeDependent() &&
25894 diag::err_omp_non_pointer_type_array_shaping_base)
25895 <<
Base->getSourceRange());
25898 bool ErrorFound =
false;
25900 if (
Dim->hasPlaceholderType()) {
25902 if (
Result.isInvalid()) {
25907 if (
Result.isInvalid()) {
25913 if (!
Dim->isTypeDependent()) {
25916 if (
Result.isInvalid()) {
25918 Diag(
Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
25919 <<
Dim->getSourceRange();
25924 if (!
Dim->isValueDependent() &&
Dim->EvaluateAsInt(EvResult, Context)) {
25929 if (!
Value.isStrictlyPositive()) {
25930 Diag(
Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
25932 <<
Dim->getSourceRange();
25938 NewDims.push_back(
Dim);
25943 LParenLoc, RParenLoc, NewDims, Brackets);
25953 bool IsCorrect =
true;
25958 if (!D.Type.getAsOpaquePtr()) {
25962 DeclTy = Context.IntTy;
25963 StartLoc = D.DeclIdentLoc;
25969 bool IsDeclTyDependent = DeclTy->isDependentType() ||
25970 DeclTy->containsUnexpandedParameterPack() ||
25971 DeclTy->isInstantiationDependentType();
25972 if (!IsDeclTyDependent) {
25973 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
25976 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
25981 if (DeclTy.isConstant(Context)) {
25984 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
25992 assert(D.DeclIdent &&
"Identifier expected.");
25997 D.DeclIdent, DeclTy, TInfo,
SC_None);
26015 SemaRef.PushOnScopeChains(VD, S);
26018 SemaRef.CurContext->addDecl(VD);
26024 Expr *Begin = D.Range.Begin;
26028 Begin = BeginRes.
get();
26030 Expr *End = D.Range.End;
26034 End = EndRes.
get();
26036 Expr *Step = D.Range.Step;
26039 Diag(Step->
getExprLoc(), diag::err_omp_iterator_step_not_integral)
26044 std::optional<llvm::APSInt>
Result =
26050 Diag(Step->
getExprLoc(), diag::err_omp_iterator_step_constant_zero)
26056 if (!Begin || !End || !IsCorrect) {
26072 if (
Decl *ID = D.IteratorDecl)
26073 ID->setInvalidDecl();
26078 if (!
SemaRef.CurContext->isDependentContext()) {
26085 D.Range.End, D.Range.Begin);
26091 if (D.Range.Step) {
26094 Res =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.
get(),
26101 Res =
SemaRef.CreateBuiltinBinOp(
26102 D.AssignmentLoc, BO_Sub, Res.
get(),
26103 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
26109 Res =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.
get(),
26115 St1 =
SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus,
26119 D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End);
26125 Res1 =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.
get(),
26132 Res1 =
SemaRef.CreateBuiltinBinOp(
26133 D.AssignmentLoc, BO_Sub, Res1.
get(),
26134 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
26140 Res1 =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.
get(),
26148 D.AssignmentLoc, BO_GT, D.Range.Step,
26149 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get());
26154 Res =
SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc,
26161 Res =
SemaRef.ActOnFinishFullExpr(Res.
get(),
false);
26173 CounterVD->setImplicit();
26180 if (D.Range.Step) {
26181 UpdateRes =
SemaRef.CreateBuiltinBinOp(
26182 D.AssignmentLoc, BO_Mul,
26183 SemaRef.DefaultLvalueConversion(RefRes.
get()).get(), St.
get());
26185 UpdateRes =
SemaRef.DefaultLvalueConversion(RefRes.
get());
26191 UpdateRes =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add,
26192 D.Range.Begin, UpdateRes.
get());
26201 UpdateRes =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign,
26202 VDRes.
get(), UpdateRes.
get());
26208 SemaRef.ActOnFinishFullExpr(UpdateRes.
get(),
true);
26214 D.AssignmentLoc, UO_PreInc, RefRes.
get());
26215 if (!CounterUpdateRes.
isUsable()) {
26219 CounterUpdateRes =
SemaRef.ActOnFinishFullExpr(CounterUpdateRes.
get(),
26221 if (!CounterUpdateRes.
isUsable()) {
26232 Helpers.assign(ID.size(), {});
26237 if (
Decl *ID = D.IteratorDecl)
26238 ID->setInvalidDecl();
26243 LLoc, RLoc, ID, Helpers);
26248 StringRef AssumptionStr) {
26249 if (llvm::getKnownAssumptionStrings().count(AssumptionStr))
26252 unsigned BestEditDistance = 3;
26253 StringRef Suggestion;
26254 for (
const auto &KnownAssumptionIt : llvm::getKnownAssumptionStrings()) {
26255 unsigned EditDistance =
26256 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
26257 if (EditDistance < BestEditDistance) {
26258 Suggestion = KnownAssumptionIt.getKey();
26259 BestEditDistance = EditDistance;
26263 if (!Suggestion.empty())
26264 S.
Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
26265 << AssumptionStr << Suggestion;
26267 S.
Diag(Loc, diag::warn_omp_assume_attribute_string_unknown)
26275 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.
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.