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);
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()) {
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 {
3914 llvm::SetVector<Expr *> Privates;
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);
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)
4789 bool ErrorFound =
false;
4790 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
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);
4854 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4859 diag::err_omp_simple_clause_incompatible_with_ordered)
4862 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4873 Diag(
C->getBeginLoc(), diag::err_omp_linear_ordered)
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,
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() &&
6909 DSAStack->addTargetDirLocation(StartLoc);
6920 assert(Aligneds.size() == Alignments.size());
6921 assert(Linears.size() == LinModifiers.size());
6922 assert(Linears.size() == Steps.size());
6926 const int SimdId = 0;
6928 Diag(SR.
getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6933 if (
auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6934 ADecl = FTD->getTemplatedDecl();
6936 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6938 Diag(ADecl->
getLocation(), diag::err_omp_function_expected) << SimdId;
6954 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6955 const Expr *UniformedLinearThis =
nullptr;
6956 for (
const Expr *E : Uniforms) {
6958 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E))
6959 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
6960 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6961 FD->getParamDecl(PVD->getFunctionScopeIndex())
6963 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
6967 UniformedLinearThis = E;
6981 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6982 const Expr *AlignedThis =
nullptr;
6983 for (
const Expr *E : Aligneds) {
6985 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E))
6986 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6988 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6989 FD->getParamDecl(PVD->getFunctionScopeIndex())
6993 auto [It, Inserted] = AlignedArgs.try_emplace(CanonPVD, E);
6998 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7003 .getNonReferenceType()
7004 .getUnqualifiedType()
7005 .getCanonicalType();
7008 Diag(E->
getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
7010 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
7034 for (
Expr *E : Alignments) {
7038 NewAligns.push_back(Align.
get());
7049 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
7050 const bool IsUniformedThis = UniformedLinearThis !=
nullptr;
7051 auto MI = LinModifiers.begin();
7052 for (
const Expr *E : Linears) {
7056 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E))
7057 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7059 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7060 FD->getParamDecl(PVD->getFunctionScopeIndex())
7064 if (
auto It = LinearArgs.find(CanonPVD); It != LinearArgs.end()) {
7069 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7074 if (
auto It = UniformedArgs.find(CanonPVD);
7075 It != UniformedArgs.end()) {
7080 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7084 LinearArgs[CanonPVD] = E;
7090 PVD->getOriginalType(),
7096 if (UniformedLinearThis) {
7102 Diag(UniformedLinearThis->
getExprLoc(), diag::note_omp_explicit_dsa)
7107 UniformedLinearThis = E;
7118 Expr *Step =
nullptr;
7119 Expr *NewStep =
nullptr;
7121 for (
Expr *E : Steps) {
7123 if (Step == E || !E) {
7124 NewSteps.push_back(E ? NewStep :
nullptr);
7128 if (
const auto *DRE = dyn_cast<DeclRefExpr>(Step))
7129 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7131 if (UniformedArgs.count(CanonPVD) == 0) {
7138 NewSteps.push_back(Step);
7153 .VerifyIntegerConstantExpression(
7157 NewSteps.push_back(NewStep);
7159 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7161 Uniforms.size(),
const_cast<Expr **
>(Aligneds.data()), Aligneds.size(),
7162 const_cast<Expr **
>(NewAligns.data()), NewAligns.size(),
7163 const_cast<Expr **
>(Linears.data()), Linears.size(),
7164 const_cast<unsigned *
>(LinModifiers.data()), LinModifiers.size(),
7165 NewSteps.data(), NewSteps.size(), SR);
7175 "Unexpected directive category");
7184 llvm_unreachable(
"Unknown OpenMP directive");
7193 "Expected function type with prototype.");
7195 "Expected function with type with no prototype.");
7197 "Expected function with prototype.");
7205 Param->setScopeInfo(0, Params.size());
7206 Param->setImplicit();
7207 Params.push_back(Param);
7210 FD->setParams(Params);
7217 if (
auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7218 FD = UTemplDecl->getTemplatedDecl();
7221 assert(FD &&
"Expected a function declaration!");
7226 if (!
SemaRef.inTemplateInstantiation()) {
7227 for (OMPAssumeAttr *AA : OMPAssumeScoped)
7230 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7234SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(
OMPTraitInfo &TI)
7235 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7243 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7246 bool IsTemplated = !TemplateParamLists.empty();
7249 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7266 for (
auto *Candidate : Lookup) {
7267 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7272 if (
SemaRef.Context.isSameTemplateParameterList(
7273 FTD->getTemplateParameters(), TemplateParamLists.back()))
7274 UDecl = FTD->getTemplatedDecl();
7275 }
else if (!IsTemplated)
7276 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7290 FType, UDeclTy,
false,
7297 Bases.push_back(UDecl);
7301 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7303 if (Bases.empty() && UseImplicitBase) {
7305 Decl *BaseD =
SemaRef.HandleDeclarator(S, D, TemplateParamLists);
7307 if (
auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7308 Bases.push_back(BaseTemplD->getTemplatedDecl());
7313 std::string MangledName;
7316 MangledName += DVScope.NameSuffix;
7331 if (
auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7332 FD = UTemplDecl->getTemplatedDecl();
7340 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7341 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7348 BaseFD->addAttr(OMPDeclareVariantA);
7368 CalleeFnDecl->
getName().starts_with_insensitive(
"omp_")) {
7371 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7374 if (!CalleeFnDecl->
hasAttr<OMPDeclareVariantAttr>())
7379 CE](StringRef ISATrait) {
7393 while (CalleeFnDecl) {
7394 for (OMPDeclareVariantAttr *A :
7396 Expr *VariantRef = A->getVariantFuncRef();
7398 VariantMatchInfo VMI;
7401 if (!isVariantApplicableInContext(VMI, OMPCtx,
7405 VMIs.push_back(VMI);
7406 Exprs.push_back(VariantRef);
7414 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7434 if (
auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7435 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7437 Context, MemberCall->getImplicitObjectArgument(),
7438 false, SpecializedMethod, Context.BoundMemberTy,
7439 MemberCall->getValueKind(), MemberCall->getObjectKind());
7441 NewCall =
SemaRef.BuildCallExpr(
Scope, BestExpr, LParenLoc, ArgExprs,
7442 RParenLoc, ExecConfig);
7444 if (
CallExpr *NCE = dyn_cast<CallExpr>(NewCall.
get())) {
7445 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7447 CalleeFnType, NewCalleeFnDecl->
getType(),
7458 VMIs.erase(VMIs.begin() + BestIdx);
7459 Exprs.erase(Exprs.begin() + BestIdx);
7460 }
while (!VMIs.empty());
7467std::optional<std::pair<FunctionDecl *, Expr *>>
7471 unsigned NumAppendArgs,
7475 return std::nullopt;
7477 const int VariantId = 1;
7480 Diag(SR.
getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7482 return std::nullopt;
7485 if (
auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7486 ADecl = FTD->getTemplatedDecl();
7489 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7493 return std::nullopt;
7496 auto &&HasMultiVersionAttributes = [](
const FunctionDecl *FD) {
7499 return FD->isMultiVersion() || FD->
hasAttr<TargetAttr>();
7502 if (HasMultiVersionAttributes(FD)) {
7503 Diag(FD->
getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7505 return std::nullopt;
7510 Diag(SR.
getBegin(), diag::warn_omp_declare_variant_after_used)
7515 if (!FD->isThisDeclarationADefinition() && FD->isDefined(
Definition) &&
7517 Diag(SR.
getBegin(), diag::warn_omp_declare_variant_after_emitted)
7522 Diag(SR.
getBegin(), diag::err_omp_function_expected) << VariantId;
7523 return std::nullopt;
7526 auto ShouldDelayChecks = [](
Expr *&E, bool) {
7532 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef,
false) ||
7534 return std::make_pair(FD, VariantRef);
7537 auto HandleNonConstantScoresAndConditions = [
this](
Expr *&E,
7538 bool IsScore) ->
bool {
7544 Diag(E->
getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7552 diag::err_omp_declare_variant_user_condition_not_constant)
7558 return std::nullopt;
7561 if (NumAppendArgs) {
7564 Diag(FD->
getLocation(), diag::err_omp_declare_variant_prototype_required)
7566 return std::nullopt;
7575 TD = dyn_cast_or_null<TypeDecl>(ND);
7578 Diag(SR.
getBegin(), diag::err_omp_interop_type_not_found) << SR;
7579 return std::nullopt;
7584 if (PTy->isVariadic()) {
7585 Diag(FD->
getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7586 return std::nullopt;
7589 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7590 Params.insert(Params.end(), NumAppendArgs, InteropType);
7591 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7592 PTy->getExtProtoInfo());
7600 auto *
Method = dyn_cast<CXXMethodDecl>(FD);
7602 FnPtrType = Context.getMemberPointerType(
7603 AdjustedFnType, std::nullopt,
Method->getParent());
7615 return std::nullopt;
7617 VariantRef = ER.
get();
7619 FnPtrType = Context.getPointerType(AdjustedFnType);
7621 QualType VarianPtrType = Context.getPointerType(VariantRef->
getType());
7625 false, Sema::AllowedExplicit::None,
7631 diag::err_omp_declare_variant_incompat_types)
7635 return std::nullopt;
7637 VariantRefCast =
SemaRef.PerformImplicitConversion(
7641 return std::nullopt;
7645 Expr *PossibleAddrOfVariantRef = VariantRefCast.
get();
7646 if (
auto *UO = dyn_cast<UnaryOperator>(
7648 VariantRefCast = UO->getSubExpr();
7657 return std::nullopt;
7665 return std::nullopt;
7667 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7671 return std::nullopt;
7676 diag::err_omp_declare_variant_same_base_function)
7678 return std::nullopt;
7684 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7687 diag::err_omp_declare_variant_incompat_types)
7688 << NewFD->getType() << FD->
getType() << (NumAppendArgs ? 1 : 0)
7690 return std::nullopt;
7695 else if (NewFD->getType()->isFunctionNoProtoType())
7701 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7703 diag::warn_omp_declare_variant_marked_as_declare_variant)
7706 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->
getRange();
7707 Diag(SR.
getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7708 return std::nullopt;
7711 enum DoesntSupport {
7720 if (
const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7721 if (CXXFD->isVirtual()) {
7724 return std::nullopt;
7730 return std::nullopt;
7736 return std::nullopt;
7740 if (FD->isDeleted()) {
7743 return std::nullopt;
7746 if (FD->isDefaulted()) {
7749 return std::nullopt;
7752 if (FD->isConstexpr()) {
7754 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7755 return std::nullopt;
7759 if (
SemaRef.areMultiversionVariantFunctionsCompatible(
7765 SemaRef.PDiag(diag::err_omp_declare_variant_doesnt_support)),
7767 SemaRef.PDiag(diag::err_omp_declare_variant_diff)
7771 return std::nullopt;
7789 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7790 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7791 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDeviceAddr);
7793 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7794 VariantMatchInfo VMI;
7796 if (!llvm::is_contained(
7797 VMI.ConstructTraits,
7798 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7799 if (!AllAdjustArgs.empty())
7800 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7802 if (!AppendArgs.empty())
7803 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7814 for (
Expr *E : AllAdjustArgs) {
7816 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7817 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7819 if (FD->
getNumParams() > PVD->getFunctionScopeIndex() &&
7823 if (!AdjustVars.insert(CanonPVD).second) {
7824 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7833 Diag(E->
getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7842 for (
Expr *E : AdjustArgsNeedDeviceAddr) {
7844 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7845 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
7848 diag::err_omp_non_by_ref_need_device_addr_modifier_argument);
7854 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7856 const_cast<Expr **
>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7857 const_cast<Expr **
>(AdjustArgsNeedDevicePtr.data()),
7858 AdjustArgsNeedDevicePtr.size(),
7859 const_cast<Expr **
>(AdjustArgsNeedDeviceAddr.data()),
7860 AdjustArgsNeedDeviceAddr.size(),
7861 const_cast<OMPInteropInfo *
>(AppendArgs.data()), AppendArgs.size(), SR);
7867 auto *CS = dyn_cast<CapturedStmt>(AStmt);
7868 assert(CS &&
"Captured statement expected");
7877 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7899 return OMPParallelDirective::Create(
7906struct LoopIterationSpace final {
7909 bool IsStrictCompare =
false;
7911 Expr *PreCond =
nullptr;
7914 Expr *NumIterations =
nullptr;
7916 Expr *CounterVar =
nullptr;
7918 Expr *PrivateCounterVar =
nullptr;
7920 Expr *CounterInit =
nullptr;
7923 Expr *CounterStep =
nullptr;
7925 bool Subtract =
false;
7935 Expr *MinValue =
nullptr;
7939 Expr *MaxValue =
nullptr;
7941 bool IsNonRectangularLB =
false;
7943 bool IsNonRectangularUB =
false;
7946 unsigned LoopDependentIdx = 0;
7950 Expr *FinalCondition =
nullptr;
7957 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7958 VarDecl *ForbiddenVar =
nullptr;
7962 explicit ForSubExprChecker(
7963 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
7964 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
7967 ShouldVisitImplicitCode =
true;
7970 bool VisitDeclRefExpr(DeclRefExpr *E)
override {
7975 if (
V->getType()->isReferenceType()) {
7976 VarDecl *VD =
V->getDefinition();
7979 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(I);
7985 Decl *Canon =
V->getCanonicalDecl();
7986 if (CollapsedLoopVarDecls.contains(Canon)) {
7995 VarDecl *getForbiddenVar()
const {
return ForbiddenVar; }
7996 SourceRange getErrRange()
const {
return ErrLoc; }
8002class OpenMPIterationSpaceChecker {
8006 bool SupportsNonRectangular;
8010 SourceLocation DefaultLoc;
8012 SourceLocation ConditionLoc;
8014 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
8016 SourceRange InitSrcRange;
8018 SourceRange ConditionSrcRange;
8020 SourceRange IncrementSrcRange;
8022 ValueDecl *LCDecl =
nullptr;
8024 Expr *LCRef =
nullptr;
8030 Expr *Step =
nullptr;
8037 std::optional<bool> TestIsLessOp;
8039 bool TestIsStrictOp =
false;
8041 bool SubtractStep =
false;
8043 const ValueDecl *DepDecl =
nullptr;
8046 std::optional<unsigned> InitDependOnLC;
8049 std::optional<unsigned> CondDependOnLC;
8051 std::optional<unsigned> doesDependOnLoopCounter(
const Stmt *S,
8052 bool IsInitializer);
8058 OpenMPIterationSpaceChecker(
8059 Sema &SemaRef,
bool SupportsNonRectangular, DSAStackTy &Stack,
8060 SourceLocation DefaultLoc,
8061 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls)
8062 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
8063 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
8064 CollapsedLoopVarDecls(CollapsedLoopDecls) {}
8067 bool checkAndSetInit(Stmt *S,
bool EmitDiags =
true);
8070 bool checkAndSetCond(Expr *S);
8073 bool checkAndSetInc(Expr *S);
8075 ValueDecl *getLoopDecl()
const {
return LCDecl; }
8077 Expr *getLoopDeclRefExpr()
const {
return LCRef; }
8079 SourceRange getInitSrcRange()
const {
return InitSrcRange; }
8081 SourceRange getConditionSrcRange()
const {
return ConditionSrcRange; }
8083 SourceRange getIncrementSrcRange()
const {
return IncrementSrcRange; }
8085 bool shouldSubtractStep()
const {
return SubtractStep; }
8087 bool isStrictTestOp()
const {
return TestIsStrictOp; }
8089 Expr *buildNumIterations(
8090 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces,
bool LimitedType,
8091 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
8094 buildPreCond(Scope *S, Expr *
Cond,
8095 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
8098 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8099 DSAStackTy &DSA)
const;
8102 Expr *buildPrivateCounterVar()
const;
8106 Expr *buildCounterStep()
const;
8110 buildOrderedLoopData(Scope *S, Expr *Counter,
8111 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8112 SourceLocation Loc, Expr *Inc =
nullptr,
8115 std::pair<Expr *, Expr *> buildMinMaxValues(
8116 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
8118 Expr *buildFinalCondition(Scope *S)
const;
8120 bool dependent()
const;
8122 bool doesInitDependOnLC()
const {
return InitDependOnLC.has_value(); }
8124 bool doesCondDependOnLC()
const {
return CondDependOnLC.has_value(); }
8126 unsigned getLoopDependentIdx()
const {
8127 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
8133 bool checkAndSetIncRHS(Expr *RHS);
8135 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
8138 bool setUB(Expr *NewUB, std::optional<bool> LessOp,
bool StrictOp,
8139 SourceRange SR, SourceLocation SL);
8141 bool setStep(Expr *NewStep,
bool Subtract);
8144bool OpenMPIterationSpaceChecker::dependent()
const {
8146 assert(!LB && !UB && !Step);
8154bool OpenMPIterationSpaceChecker::setLCDeclAndLB(
ValueDecl *NewLCDecl,
8156 Expr *NewLB,
bool EmitDiags) {
8158 assert(LCDecl ==
nullptr && LB ==
nullptr && LCRef ==
nullptr &&
8159 UB ==
nullptr && Step ==
nullptr && !TestIsLessOp && !TestIsStrictOp);
8163 LCRef = NewLCRefExpr;
8164 if (
auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
8166 if ((Ctor->isCopyOrMoveConstructor() ||
8167 Ctor->isConvertingConstructor(
false)) &&
8168 CE->getNumArgs() > 0 && CE->getArg(0) !=
nullptr)
8172 InitDependOnLC = doesDependOnLoopCounter(LB,
true);
8176bool OpenMPIterationSpaceChecker::setUB(
Expr *NewUB, std::optional<bool> LessOp,
8180 assert(LCDecl !=
nullptr && LB !=
nullptr && UB ==
nullptr &&
8181 Step ==
nullptr && !TestIsLessOp && !TestIsStrictOp);
8186 TestIsLessOp = LessOp;
8187 TestIsStrictOp = StrictOp;
8188 ConditionSrcRange = SR;
8190 CondDependOnLC = doesDependOnLoopCounter(UB,
false);
8194bool OpenMPIterationSpaceChecker::setStep(
Expr *NewStep,
bool Subtract) {
8196 assert(LCDecl !=
nullptr && LB !=
nullptr && Step ==
nullptr);
8206 NewStep = Val.
get();
8219 std::optional<llvm::APSInt>
Result =
8230 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8231 if (UB && (IsConstZero ||
8232 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8233 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8235 diag::err_omp_loop_incr_not_compatible)
8237 SemaRef.
Diag(ConditionLoc,
8238 diag::note_omp_loop_cond_requires_compatible_incr)
8239 << *TestIsLessOp << ConditionSrcRange;
8242 if (*TestIsLessOp == Subtract) {
8246 Subtract = !Subtract;
8251 SubtractStep = Subtract;
8258class LoopCounterRefChecker final
8262 const ValueDecl *CurLCDecl =
nullptr;
8263 const ValueDecl *DepDecl =
nullptr;
8264 const ValueDecl *PrevDepDecl =
nullptr;
8265 bool IsInitializer =
true;
8266 bool SupportsNonRectangular;
8267 unsigned BaseLoopId = 0;
8268 bool checkDecl(
const Expr *E,
const ValueDecl *VD) {
8270 SemaRef.Diag(E->
getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8271 << (IsInitializer ? 0 : 1);
8274 const auto &&
Data = Stack.isLoopControlVariable(VD);
8279 SmallString<128> Name;
8280 llvm::raw_svector_ostream
OS(Name);
8284 diag::err_omp_wrong_dependency_iterator_type)
8286 SemaRef.Diag(VD->
getLocation(), diag::note_previous_decl) << VD;
8289 if (
Data.first && !SupportsNonRectangular) {
8290 SemaRef.Diag(E->
getExprLoc(), diag::err_omp_invariant_dependency);
8294 (DepDecl || (PrevDepDecl &&
8296 if (!DepDecl && PrevDepDecl)
8297 DepDecl = PrevDepDecl;
8298 SmallString<128> Name;
8299 llvm::raw_svector_ostream
OS(Name);
8303 diag::err_omp_invariant_or_linear_dependency)
8309 BaseLoopId =
Data.first;
8315 bool VisitDeclRefExpr(
const DeclRefExpr *E) {
8316 const ValueDecl *VD = E->
getDecl();
8318 return checkDecl(E, VD);
8321 bool VisitMemberExpr(
const MemberExpr *E) {
8325 return checkDecl(E, VD);
8329 bool VisitStmt(
const Stmt *S) {
8331 for (
const Stmt *Child : S->
children())
8332 Res = (Child && Visit(Child)) || Res;
8335 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8336 const ValueDecl *CurLCDecl,
bool IsInitializer,
8337 const ValueDecl *PrevDepDecl =
nullptr,
8338 bool SupportsNonRectangular =
true)
8339 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8340 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8341 SupportsNonRectangular(SupportsNonRectangular) {}
8342 unsigned getBaseLoopId()
const {
8343 assert(CurLCDecl &&
"Expected loop dependency.");
8346 const ValueDecl *getDepDecl()
const {
8347 assert(CurLCDecl &&
"Expected loop dependency.");
8353std::optional<unsigned>
8354OpenMPIterationSpaceChecker::doesDependOnLoopCounter(
const Stmt *S,
8355 bool IsInitializer) {
8357 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8358 DepDecl, SupportsNonRectangular);
8359 if (LoopStmtChecker.Visit(S)) {
8360 DepDecl = LoopStmtChecker.getDepDecl();
8361 return LoopStmtChecker.getBaseLoopId();
8363 return std::nullopt;
8366bool OpenMPIterationSpaceChecker::checkAndSetInit(
Stmt *S,
bool EmitDiags) {
8377 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8381 if (
auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8382 if (!ExprTemp->cleanupsHaveSideEffects())
8383 S = ExprTemp->getSubExpr();
8385 if (!CollapsedLoopVarDecls.empty()) {
8386 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8387 if (!FSEC.TraverseStmt(S)) {
8389 SemaRef.Diag(
Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8390 <<
Range.getEnd() << 0 << FSEC.getForbiddenVar();
8396 if (
Expr *E = dyn_cast<Expr>(S))
8398 if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8399 if (BO->getOpcode() == BO_Assign) {
8401 if (
auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8402 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->
getDecl()))
8404 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8406 return setLCDeclAndLB(DRE->
getDecl(), DRE, BO->getRHS(), EmitDiags);
8408 if (
auto *ME = dyn_cast<MemberExpr>(LHS)) {
8409 if (ME->isArrow() &&
8411 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8415 }
else if (
auto *DS = dyn_cast<DeclStmt>(S)) {
8416 if (DS->isSingleDecl()) {
8417 if (
auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8418 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8422 diag::ext_omp_loop_not_canonical_init)
8424 return setLCDeclAndLB(
8427 Var->getType().getNonReferenceType(),
8429 Var->getInit(), EmitDiags);
8433 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8434 if (CE->getOperator() == OO_Equal) {
8435 Expr *LHS = CE->getArg(0);
8436 if (
auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8437 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->
getDecl()))
8439 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8441 return setLCDeclAndLB(DRE->
getDecl(), DRE, CE->getArg(1), EmitDiags);
8443 if (
auto *ME = dyn_cast<MemberExpr>(LHS)) {
8444 if (ME->isArrow() &&
8446 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8452 if (dependent() || SemaRef.CurContext->isDependentContext())
8455 SemaRef.Diag(S->
getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8467 if (
const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8469 if ((Ctor->isCopyOrMoveConstructor() ||
8470 Ctor->isConvertingConstructor(
false)) &&
8471 CE->getNumArgs() > 0 && CE->getArg(0) !=
nullptr)
8473 if (
const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8474 if (
const auto *VD = dyn_cast<VarDecl>(DRE->
getDecl()))
8477 if (
const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8478 if (ME->isArrow() &&
isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8483bool OpenMPIterationSpaceChecker::checkAndSetCond(
Expr *S) {
8490 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8492 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8493 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8499 if (!CollapsedLoopVarDecls.empty()) {
8500 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8501 if (!FSEC.TraverseStmt(S)) {
8503 SemaRef.Diag(
Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8504 <<
Range.getEnd() << 1 << FSEC.getForbiddenVar();
8510 auto &&CheckAndSetCond =
8515 if (getInitLCDecl(LHS) == LCDecl)
8516 return setUB(
const_cast<Expr *
>(RHS),
8517 (Opcode == BO_LT || Opcode == BO_LE),
8518 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8519 if (getInitLCDecl(RHS) == LCDecl)
8520 return setUB(
const_cast<Expr *
>(LHS),
8521 (Opcode == BO_GT || Opcode == BO_GE),
8522 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8523 }
else if (IneqCondIsCanonical && Opcode == BO_NE) {
8524 return setUB(
const_cast<Expr *
>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8528 return std::nullopt;
8530 std::optional<bool> Res;
8531 if (
auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8534 RBO->getOperatorLoc());
8535 }
else if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8536 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8537 BO->getSourceRange(), BO->getOperatorLoc());
8538 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8539 if (CE->getNumArgs() == 2) {
8540 Res = CheckAndSetCond(
8542 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8547 if (dependent() || SemaRef.CurContext->isDependentContext())
8549 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8550 << (IneqCondIsCanonical ? 1 : 0) << S->
getSourceRange() << LCDecl;
8554bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(
Expr *RHS) {
8561 if (
auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8562 if (BO->isAdditiveOp()) {
8563 bool IsAdd = BO->getOpcode() == BO_Add;
8564 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8565 return setStep(BO->getRHS(), !IsAdd);
8566 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8567 return setStep(BO->getLHS(),
false);
8569 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8570 bool IsAdd = CE->getOperator() == OO_Plus;
8571 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8572 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8573 return setStep(CE->getArg(1), !IsAdd);
8574 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8575 return setStep(CE->getArg(0),
false);
8578 if (dependent() || SemaRef.CurContext->isDependentContext())
8580 SemaRef.Diag(RHS->
getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8585bool OpenMPIterationSpaceChecker::checkAndSetInc(
Expr *S) {
8600 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8603 if (
auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8604 if (!ExprTemp->cleanupsHaveSideEffects())
8605 S = ExprTemp->getSubExpr();
8607 if (!CollapsedLoopVarDecls.empty()) {
8608 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8609 if (!FSEC.TraverseStmt(S)) {
8611 SemaRef.Diag(
Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8612 <<
Range.getEnd() << 2 << FSEC.getForbiddenVar();
8619 if (
auto *UO = dyn_cast<UnaryOperator>(S)) {
8620 if (UO->isIncrementDecrementOp() &&
8621 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8622 return setStep(SemaRef
8623 .ActOnIntegerConstant(UO->getBeginLoc(),
8624 (UO->isDecrementOp() ? -1 : 1))
8627 }
else if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8628 switch (BO->getOpcode()) {
8631 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8632 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8635 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8636 return checkAndSetIncRHS(BO->getRHS());
8641 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8642 switch (CE->getOperator()) {
8645 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8646 return setStep(SemaRef
8647 .ActOnIntegerConstant(
8649 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8655 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8656 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8659 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8660 return checkAndSetIncRHS(CE->getArg(1));
8666 if (dependent() || SemaRef.CurContext->isDependentContext())
8668 SemaRef.Diag(S->
getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8675 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8676 StringRef Name =
".capture_expr.") {
8684 auto I = Captures.find(
Capture);
8685 if (I != Captures.end())
8698 bool TestIsStrictOp,
bool RoundToStep,
8699 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8700 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures,
".new_step");
8703 llvm::APSInt LRes, SRes;
8704 bool IsLowerConst =
false, IsStepConst =
false;
8705 if (std::optional<llvm::APSInt> Res =
8708 IsLowerConst =
true;
8710 if (std::optional<llvm::APSInt> Res =
8715 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8716 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8717 (TestIsStrictOp && LRes.isStrictlyPositive()));
8718 bool NeedToReorganize =
false;
8720 if (!NoNeedToConvert && IsLowerConst &&
8721 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8722 NoNeedToConvert =
true;
8724 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8725 ? LRes.getBitWidth()
8726 : SRes.getBitWidth();
8727 LRes = LRes.extend(BW + 1);
8728 LRes.setIsSigned(
true);
8729 SRes = SRes.extend(BW + 1);
8730 SRes.setIsSigned(
true);
8732 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8733 LRes = LRes.trunc(BW);
8735 if (TestIsStrictOp) {
8736 unsigned BW = LRes.getBitWidth();
8737 LRes = LRes.extend(BW + 1);
8738 LRes.setIsSigned(
true);
8741 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8743 LRes = LRes.trunc(BW);
8745 NeedToReorganize = NoNeedToConvert;
8748 bool IsUpperConst =
false;
8749 if (std::optional<llvm::APSInt> Res =
8752 IsUpperConst =
true;
8754 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8755 (!RoundToStep || IsStepConst)) {
8756 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8757 : URes.getBitWidth();
8758 LRes = LRes.extend(BW + 1);
8759 LRes.setIsSigned(
true);
8760 URes = URes.extend(BW + 1);
8761 URes.setIsSigned(
true);
8763 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8764 NeedToReorganize = NoNeedToConvert;
8769 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8775 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8778 LowerSize > UpperSize ? LowerSize : UpperSize, 0);
8789 if (!Lower || !Upper || NewStep.
isInvalid())
8795 if (NeedToReorganize) {
8809 S, DefaultLoc, BO_Add, Diff.
get(),
8819 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.
get());
8823 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8839 S, DefaultLoc, BO_Sub, Diff.
get(),
8859 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Div, Diff.
get(), NewStep.
get());
8867Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8869 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
8878 if (InitDependOnLC) {
8879 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8880 if (!IS.MinValue || !IS.MaxValue)
8889 IS.CounterVar, MinValue.
get());
8894 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.
get(), LBVal);
8909 IS.CounterVar, MaxValue.
get());
8914 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.
get(), LBVal);
8923 tryBuildCapture(SemaRef, LBMinVal.
get(), Captures,
".lb_min").get();
8925 tryBuildCapture(SemaRef, LBMaxVal.
get(), Captures,
".lb_max").get();
8926 if (!LBMin || !LBMax)
8930 SemaRef.
BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8934 tryBuildCapture(SemaRef, MinLessMaxRes.
get(), Captures,
".min_less_max")
8938 if (*TestIsLessOp) {
8942 MinLessMax, LBMin, LBMax);
8945 LBVal = MinLB.
get();
8950 MinLessMax, LBMax, LBMin);
8953 LBVal = MaxLB.
get();
8957 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8960 LBVal = LBMinVal.
get();
8964 if (CondDependOnLC) {
8965 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8966 if (!IS.MinValue || !IS.MaxValue)
8975 IS.CounterVar, MinValue.
get());
8980 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.
get(), UBVal);
8995 IS.CounterVar, MaxValue.
get());
9000 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.
get(), UBVal);
9009 tryBuildCapture(SemaRef, UBMinVal.
get(), Captures,
".ub_min").get();
9011 tryBuildCapture(SemaRef, UBMaxVal.
get(), Captures,
".ub_max").get();
9012 if (!UBMin || !UBMax)
9016 SemaRef.
BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
9019 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.
get(),
9020 Captures,
".min_greater_max")
9024 if (*TestIsLessOp) {
9028 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
9031 UBVal = MaxUB.
get();
9036 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
9039 UBVal = MinUB.
get();
9042 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
9043 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
9044 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures,
".upper").get();
9045 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures,
".lower").get();
9046 if (!Upper || !Lower)
9049 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9050 Step, VarType, TestIsStrictOp,
9059 C.getTypeSize(
Type) >
C.getTypeSize(VarType);
9062 UseVarType ?
C.getTypeSize(VarType) :
C.getTypeSize(
Type);
9065 Type =
C.getIntTypeForBitwidth(NewSize, IsSigned);
9075 unsigned NewSize = (
C.getTypeSize(
Type) > 32) ? 64 : 32;
9076 if (NewSize !=
C.getTypeSize(
Type)) {
9077 if (NewSize <
C.getTypeSize(
Type)) {
9078 assert(NewSize == 64 &&
"incorrect loop var size");
9079 SemaRef.
Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
9080 << InitSrcRange << ConditionSrcRange;
9082 QualType NewType =
C.getIntTypeForBitwidth(
9084 C.getTypeSize(
Type) < NewSize);
9098std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
9099 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
9103 return std::make_pair(
nullptr,
nullptr);
9106 Expr *MinExpr =
nullptr;
9107 Expr *MaxExpr =
nullptr;
9108 Expr *LBExpr = *TestIsLessOp ? LB : UB;
9109 Expr *UBExpr = *TestIsLessOp ? UB : LB;
9111 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
9113 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
9115 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
9117 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
9118 if (!Upper || !Lower)
9119 return std::make_pair(
nullptr,
nullptr);
9129 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9130 Step, VarType, TestIsStrictOp,
9133 return std::make_pair(
nullptr,
nullptr);
9139 return std::make_pair(
nullptr,
nullptr);
9141 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures,
".new_step");
9143 return std::make_pair(
nullptr,
nullptr);
9144 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Mul, Diff.
get(), NewStep.
get());
9146 return std::make_pair(
nullptr,
nullptr);
9151 return std::make_pair(
nullptr,
nullptr);
9163 return std::make_pair(
nullptr,
nullptr);
9165 if (*TestIsLessOp) {
9169 S, DefaultLoc, BO_Add,
9173 return std::make_pair(
nullptr,
nullptr);
9178 S, DefaultLoc, BO_Sub,
9182 return std::make_pair(
nullptr,
nullptr);
9191 return std::make_pair(
nullptr,
nullptr);
9196 return std::make_pair(
nullptr,
nullptr);
9199 MaxExpr = Diff.
get();
9201 MinExpr = Diff.
get();
9203 return std::make_pair(MinExpr, MaxExpr);
9206Expr *OpenMPIterationSpaceChecker::buildFinalCondition(
Scope *S)
const {
9207 if (InitDependOnLC || CondDependOnLC)
9212Expr *OpenMPIterationSpaceChecker::buildPreCond(
9214 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
9219 if (CondDependOnLC || InitDependOnLC)
9230 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
9231 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
9237 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
9238 : (TestIsStrictOp ? BO_GT : BO_GE),
9239 NewLB.
get(), NewUB.
get());
9254DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9255 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9256 DSAStackTy &DSA)
const {
9257 auto *VD = dyn_cast<VarDecl>(LCDecl);
9262 const DSAStackTy::DSAVarData
Data =
9263 DSA.getTopDSA(LCDecl,
false);
9267 Captures.insert(std::make_pair(LCRef, Ref));
9273Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar()
const {
9290Expr *OpenMPIterationSpaceChecker::buildCounterInit()
const {
return LB; }
9293Expr *OpenMPIterationSpaceChecker::buildCounterStep()
const {
return Step; }
9295Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9297 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
SourceLocation Loc,
9303 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9304 "Expected only + or - operations for depend clauses.");
9316 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9318 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9319 if (!Upper || !Lower)
9323 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9324 false,
false, Captures);
9334 assert(
getLangOpts().OpenMP &&
"OpenMP is not active.");
9335 assert(
Init &&
"Expected loop in canonical form.");
9336 unsigned AssociatedLoops =
DSAStack->getAssociatedLoops();
9343 OpenMPIterationSpaceChecker ISC(
SemaRef,
true,
9345 if (!ISC.checkAndSetInit(
Init,
false)) {
9347 auto *VD = dyn_cast<VarDecl>(D);
9358 DSAStack->addLoopControlVariable(D, VD);
9360 if (LD != D->getCanonicalDecl()) {
9361 DSAStack->resetPossibleLoopCounter();
9362 if (
auto *Var = dyn_cast_or_null<VarDecl>(LD))
9375 DSAStackTy::DSAVarData DVar =
9379 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9382 ? (
DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9385 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9388 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9390 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9392 IsOpenMPTaskloopDirective(DKind) ||
9395 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9396 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9398 Diag(
Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9400 << getOpenMPDirectiveName(DKind, OMPVersion)
9402 if (DVar.RefExpr ==
nullptr)
9403 DVar.CKind = PredeterminedCKind;
9405 }
else if (LoopDeclRefExpr) {
9410 if (DVar.CKind == OMPC_unknown)
9411 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9415 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9420class OMPDoacrossKind {
9423 return C->getDependenceType() == OMPC_DOACROSS_source ||
9424 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9427 return C->getDependenceType() == OMPC_DOACROSS_sink;
9429 bool isSinkIter(
const OMPDoacrossClause *
C) {
9430 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9438 unsigned CurrentNestedLoopCount,
unsigned NestedLoopCount,
9439 unsigned TotalNestedLoopCount,
Expr *CollapseLoopCountExpr,
9440 Expr *OrderedLoopCountExpr,
9443 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9444 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls) {
9449 if (
auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9450 S = CanonLoop->getLoopStmt();
9451 auto *For = dyn_cast_or_null<ForStmt>(S);
9452 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9454 if (!For && (SemaRef.
LangOpts.OpenMP <= 45 || !CXXFor)) {
9455 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
9457 << (CollapseLoopCountExpr !=
nullptr || OrderedLoopCountExpr !=
nullptr)
9458 << getOpenMPDirectiveName(DKind, OMPVersion) << TotalNestedLoopCount
9459 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9460 if (TotalNestedLoopCount > 1) {
9461 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9462 SemaRef.
Diag(DSA.getConstructLoc(),
9463 diag::note_omp_collapse_ordered_expr)
9466 else if (CollapseLoopCountExpr)
9468 diag::note_omp_collapse_ordered_expr)
9470 else if (OrderedLoopCountExpr)
9472 diag::note_omp_collapse_ordered_expr)
9477 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9483 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9484 For ? For->getForLoc() : CXXFor->getForLoc(),
9485 CollapsedLoopVarDecls);
9488 Stmt *
Init = For ? For->getInit() : CXXFor->getBeginStmt();
9489 if (ISC.checkAndSetInit(
Init))
9492 bool HasErrors =
false;
9495 if (
ValueDecl *LCDecl = ISC.getLoopDecl()) {
9505 SemaRef.
Diag(
Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9519 VarsWithImplicitDSA.erase(LCDecl);
9523 "DSA for non-loop vars");
9526 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9529 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9536 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9537 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9538 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9539 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9546 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9547 ISC.buildCounterVar(Captures, DSA);
9548 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9549 ISC.buildPrivateCounterVar();
9550 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9551 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9552 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9553 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9554 ISC.getConditionSrcRange();
9555 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9556 ISC.getIncrementSrcRange();
9557 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9558 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9559 ISC.isStrictTestOp();
9560 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9561 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9562 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9563 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9564 ISC.buildFinalCondition(DSA.getCurScope());
9565 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9566 ISC.doesInitDependOnLC();
9567 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9568 ISC.doesCondDependOnLC();
9569 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9570 ISC.getLoopDependentIdx();
9573 (ResultIterSpaces[CurrentNestedLoopCount].PreCond ==
nullptr ||
9574 ResultIterSpaces[CurrentNestedLoopCount].NumIterations ==
nullptr ||
9575 ResultIterSpaces[CurrentNestedLoopCount].CounterVar ==
nullptr ||
9576 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar ==
nullptr ||
9577 ResultIterSpaces[CurrentNestedLoopCount].CounterInit ==
nullptr ||
9578 ResultIterSpaces[CurrentNestedLoopCount].CounterStep ==
nullptr);
9579 if (!HasErrors && DSA.isOrderedRegion()) {
9580 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9581 if (CurrentNestedLoopCount <
9582 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9583 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9584 CurrentNestedLoopCount,
9585 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9586 DSA.getOrderedRegionParam().second->setLoopCounter(
9587 CurrentNestedLoopCount,
9588 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9591 for (
auto &Pair : DSA.getDoacrossDependClauses()) {
9592 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9593 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9595 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9596 if (CurrentNestedLoopCount >= NumLoops) {
9600 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9601 Pair.second.size() <= CurrentNestedLoopCount) {
9603 DependC->setLoopData(CurrentNestedLoopCount,
nullptr);
9606 OMPDoacrossKind ODK;
9607 if (DoacrossC && ODK.isSink(DoacrossC) &&
9608 Pair.second.size() <= CurrentNestedLoopCount) {
9610 DoacrossC->setLoopData(CurrentNestedLoopCount,
nullptr);
9615 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9616 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9617 (DoacrossC && ODK.isSource(DoacrossC)))
9618 CntValue = ISC.buildOrderedLoopData(
9620 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9622 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9625 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9633 CntValue = ISC.buildOrderedLoopData(
9635 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9636 DepLoc, Inc, clang::OO_Minus);
9638 CntValue = ISC.buildOrderedLoopData(
9640 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9641 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9642 Pair.second[CurrentNestedLoopCount].second);
9644 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9646 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9657 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9661 : tryBuildCapture(SemaRef, Start.
get(), Captures);
9682 bool IsNonRectangularLB,
9683 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures =
nullptr) {
9692 NewStep = tryBuildCapture(SemaRef, Step.
get(), *Captures);
9707 if (Captures && !IsNonRectangularLB)
9708 NewStart = tryBuildCapture(SemaRef, Start.
get(), *Captures);
9717 Update.get()->getType()->isOverloadableType()) {
9724 SemaRef.
BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9725 VarRef.
get(), SavedUpdate.
get());
9736 NewStart.
get(), SavedUpdate.
get());
9761 unsigned HasBits =
C.getTypeSize(OldType);
9762 if (HasBits >= Bits)
9765 QualType NewType =
C.getIntTypeForBitwidth(Bits,
true);
9775 if (std::optional<llvm::APSInt> Result =
9777 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9784 if (!PreInits.empty()) {
9805 if (
auto *CS = dyn_cast<CompoundStmt>(Item))
9814 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9815 if (!Captures.empty()) {
9817 for (
const auto &Pair : Captures)
9818 PreInits.push_back(Pair.second->getDecl());
9826 if (PreInits.empty())
9830 for (
Stmt *S : PreInits)
9837 Expr *PostUpdate =
nullptr;
9838 if (!PostUpdates.empty()) {
9839 for (
Expr *E : PostUpdates) {
9845 PostUpdate = PostUpdate
9859 int NestingDepth = 0;
9860 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
9882 if (NestingDepth > 0)
9893 Expr *OrderedLoopCountExpr,
Stmt *AStmt,
Sema &SemaRef,
9896 OMPLoopBasedDirective::HelperExprs &Built) {
9900 if ((CollapseLoopCountExpr && CollapseLoopCountExpr->
containsErrors()) ||
9901 (OrderedLoopCountExpr && OrderedLoopCountExpr->
containsErrors()))
9904 unsigned NestedLoopCount = 1;
9905 bool SupportsNonPerfectlyNested = (SemaRef.
LangOpts.OpenMP >= 50) &&
9909 if (CollapseLoopCountExpr) {
9914 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9923 unsigned OrderedLoopCount = 1;
9924 if (OrderedLoopCountExpr) {
9930 llvm::APSInt Result = EVResult.
Val.
getInt();
9931 if (Result.getLimitedValue() < NestedLoopCount) {
9933 diag::err_omp_wrong_ordered_loop_count)
9936 diag::note_collapse_loop_count)
9939 OrderedLoopCount = Result.getLimitedValue();
9947 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9948 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9950 if (!OMPLoopBasedDirective::doForAllLoops(
9953 SupportsNonPerfectlyNested, NumLoops,
9954 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9955 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9956 &IterSpaces, &Captures,
9957 &CollapsedLoopVarDecls](
unsigned Cnt,
Stmt *CurStmt) {
9959 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9960 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9961 VarsWithImplicitDSA, IterSpaces, Captures,
9962 CollapsedLoopVarDecls))
9964 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9965 IterSpaces[Cnt].CounterVar) {
9969 Captures[DRE] = DRE;
9975 Stmt *DependentPreInits = Transform->getPreInits();
9976 if (!DependentPreInits)
9983 for (
Stmt *S : Constituents) {
9984 if (
auto *DC = dyn_cast<DeclStmt>(S)) {
9985 for (
Decl *
C : DC->decls()) {
9988 SemaRef, D, D->getType().getNonReferenceType(),
9991 Captures[Ref] = Ref;
9998 Built.clear(NestedLoopCount);
10001 return NestedLoopCount;
10034 auto PreCond =
ExprResult(IterSpaces[0].PreCond);
10035 Expr *N0 = IterSpaces[0].NumIterations;
10054 return NestedLoopCount;
10057 bool AllCountsNeedLessThan32Bits =
C.getTypeSize(N0->
getType()) < 32;
10059 Scope *CurScope = DSA.getCurScope();
10060 for (
unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
10061 if (PreCond.isUsable()) {
10063 SemaRef.
BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
10064 PreCond.get(), IterSpaces[Cnt].PreCond);
10066 Expr *N = IterSpaces[Cnt].NumIterations;
10068 AllCountsNeedLessThan32Bits &=
C.getTypeSize(N->
getType()) < 32;
10071 CurScope, Loc, BO_Mul, LastIteration32.
get(),
10079 CurScope, Loc, BO_Mul, LastIteration64.
get(),
10089 if (SemaRef.
getLangOpts().OpenMPOptimisticCollapse ||
10091 C.getTypeSize(LastIteration32.
get()->
getType()) == 32 &&
10092 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
10096 LastIteration64.
get(), SemaRef))))
10097 LastIteration = LastIteration32;
10116 LastIteration.
get(),
10128 tryBuildCapture(SemaRef, LastIteration.
get(), Captures);
10129 LastIteration = SaveRef;
10142 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
10171 buildVarDecl(SemaRef, InitLoc, StrideVType,
".omp.stride");
10180 UB.
get(), LastIteration.
get());
10183 LastIteration.
get(), UB.
get());
10184 EUB = SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, UB.
get(),
10195 buildVarDecl(SemaRef, InitLoc, VType,
".omp.comb.lb");
10203 buildVarDecl(SemaRef, InitLoc, VType,
".omp.comb.ub");
10209 CurScope, InitLoc, BO_GT, CombUB.
get(), LastIteration.
get());
10212 LastIteration.
get(), CombUB.
get());
10213 CombEUB = SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.
get(),
10222 "Unexpected number of parameters in loop combined directive");
10263 SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, IV.
get(), CombRHS);
10269 bool UseStrictCompare =
10271 llvm::all_of(IterSpaces, [](
const LoopIterationSpace &LIS) {
10272 return LIS.IsStrictCompare;
10278 if (UseStrictCompare) {
10281 .
BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
10293 UseStrictCompare ? BO_LT : BO_LE, IV.
get(),
10296 NumIterations.
get());
10299 CombDistCond = SemaRef.
BuildBinOp(CurScope, CondLoc, BO_LT, IV.
get(),
10300 NumIterations.
get());
10305 Expr *BoundCombUB = CombUB.
get();
10306 if (UseStrictCompare) {
10310 CurScope, CondLoc, BO_Add, BoundCombUB,
10318 SemaRef.
BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10319 IV.
get(), BoundCombUB);
10326 if (!Inc.isUsable())
10328 Inc = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, IV.
get(), Inc.get());
10330 if (!Inc.isUsable())
10337 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10343 NextLB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Add, LB.
get(), ST.
get());
10354 NextUB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Add, UB.
get(), ST.
get());
10370 CombNextLB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.
get(),
10382 CombNextUB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.
get(),
10396 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10399 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.
get(), BoundUB);
10400 assert(DistCond.
isUsable() &&
"distribute cond expr was not built");
10404 assert(DistInc.
isUsable() &&
"distribute inc expr was not built");
10405 DistInc = SemaRef.
BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.
get(),
10409 assert(DistInc.
isUsable() &&
"distribute inc expr was not built");
10420 DistEUBLoc, NewPrevUB.
get());
10425 UB.
get(), NewPrevUB.
get());
10427 DistEUBLoc, DistEUBLoc, IsUBGreater.
get(), NewPrevUB.
get(), UB.
get());
10428 PrevEUB = SemaRef.
BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.
get(),
10436 Expr *BoundPrevUB = PrevUB.
get();
10437 if (UseStrictCompare) {
10441 CurScope, CondLoc, BO_Add, BoundPrevUB,
10449 SemaRef.
BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10450 IV.
get(), BoundPrevUB);
10454 bool HasErrors =
false;
10455 Built.Counters.resize(NestedLoopCount);
10456 Built.Inits.resize(NestedLoopCount);
10457 Built.Updates.resize(NestedLoopCount);
10458 Built.Finals.resize(NestedLoopCount);
10459 Built.DependentCounters.resize(NestedLoopCount);
10460 Built.DependentInits.resize(NestedLoopCount);
10461 Built.FinalsConditions.resize(NestedLoopCount);
10479 for (
unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10480 LoopIterationSpace &IS = IterSpaces[Cnt];
10486 for (
unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10487 Prod = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.
get(),
10488 IterSpaces[K].NumIterations);
10493 if (Cnt + 1 < NestedLoopCount)
10507 if (Cnt + 1 < NestedLoopCount)
10508 Prod = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.
get(),
10512 Acc = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.
get(), Prod.
get());
10521 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10522 if (!
Init.isUsable()) {
10527 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10528 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10529 if (!
Update.isUsable()) {
10537 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10538 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10539 if (!Final.isUsable()) {
10544 if (!
Update.isUsable() || !Final.isUsable()) {
10549 Built.Counters[Cnt] = IS.CounterVar;
10550 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10551 Built.Inits[Cnt] =
Init.get();
10552 Built.Updates[Cnt] =
Update.get();
10553 Built.Finals[Cnt] = Final.get();
10554 Built.DependentCounters[Cnt] =
nullptr;
10555 Built.DependentInits[Cnt] =
nullptr;
10556 Built.FinalsConditions[Cnt] =
nullptr;
10557 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10558 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10559 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10560 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10569 Built.IterationVarRef = IV.
get();
10570 Built.LastIteration = LastIteration.
get();
10571 Built.NumIterations = NumIterations.
get();
10572 Built.CalcLastIteration = SemaRef
10576 Built.PreCond = PreCond.get();
10578 Built.Cond =
Cond.get();
10579 Built.Init =
Init.get();
10580 Built.Inc = Inc.get();
10581 Built.LB = LB.
get();
10582 Built.UB = UB.
get();
10583 Built.IL = IL.
get();
10584 Built.ST = ST.
get();
10585 Built.EUB = EUB.
get();
10586 Built.NLB = NextLB.
get();
10587 Built.NUB = NextUB.
get();
10588 Built.PrevLB = PrevLB.
get();
10589 Built.PrevUB = PrevUB.
get();
10590 Built.DistInc = DistInc.
get();
10591 Built.PrevEUB = PrevEUB.
get();
10592 Built.DistCombinedFields.LB = CombLB.
get();
10593 Built.DistCombinedFields.UB = CombUB.
get();
10594 Built.DistCombinedFields.EUB = CombEUB.
get();
10595 Built.DistCombinedFields.Init = CombInit.
get();
10596 Built.DistCombinedFields.Cond = CombCond.
get();
10597 Built.DistCombinedFields.NLB = CombNextLB.
get();
10598 Built.DistCombinedFields.NUB = CombNextUB.
get();
10599 Built.DistCombinedFields.DistCond = CombDistCond.
get();
10600 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.
get();
10602 return NestedLoopCount;
10606 auto CollapseClauses =
10607 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10608 if (CollapseClauses.begin() != CollapseClauses.end())
10609 return (*CollapseClauses.begin())->getNumForLoops();
10614 auto OrderedClauses =
10615 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10616 if (OrderedClauses.begin() != OrderedClauses.end())
10617 return (*OrderedClauses.begin())->getNumForLoops();
10626 for (
const OMPClause *Clause : Clauses) {
10627 if (Clause->getClauseKind() == OMPC_safelen)
10629 else if (Clause->getClauseKind() == OMPC_simdlen)
10631 if (Safelen && Simdlen)
10635 if (Simdlen && Safelen) {
10649 llvm::APSInt SimdlenRes = SimdlenResult.
Val.
getInt();
10650 llvm::APSInt SafelenRes = SafelenResult.
Val.
getInt();
10655 if (SimdlenRes > SafelenRes) {
10657 diag::err_omp_wrong_simdlen_safelen_values)
10674 OMPLoopBasedDirective::HelperExprs B;
10680 if (NestedLoopCount == 0)
10689 auto *SimdDirective = OMPSimdDirective::Create(
10690 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10691 return SimdDirective;
10701 OMPLoopBasedDirective::HelperExprs B;
10707 if (NestedLoopCount == 0)
10713 auto *ForDirective = OMPForDirective::Create(
10714 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10716 return ForDirective;
10728 OMPLoopBasedDirective::HelperExprs B;
10731 unsigned NestedLoopCount =
10734 VarsWithImplicitDSA, B);
10735 if (NestedLoopCount == 0)
10744 return OMPForSimdDirective::Create(
getASTContext(), StartLoc, EndLoc,
10745 NestedLoopCount, Clauses, AStmt, B);
10749 Stmt *AStmt, DSAStackTy *Stack) {
10754 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
10755 auto BaseStmt = AStmt;
10756 while (
auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10758 if (
auto *
C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10759 auto S =
C->children();
10760 if (S.begin() == S.end())
10764 for (
Stmt *SectionStmt : llvm::drop_begin(S)) {
10767 SemaRef.
Diag(SectionStmt->getBeginLoc(),
10768 diag::err_omp_sections_substmt_not_section)
10769 << getOpenMPDirectiveName(DKind, OMPVersion);
10773 ->setHasCancel(Stack->isCancelRegion());
10776 SemaRef.
Diag(AStmt->
getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10777 << getOpenMPDirectiveName(DKind, OMPVersion);
10790 SemaRef.setFunctionHasBranchProtectedScope();
10792 return OMPSectionsDirective::Create(
10803 SemaRef.setFunctionHasBranchProtectedScope();
10806 return OMPSectionDirective::Create(
getASTContext(), StartLoc, EndLoc, AStmt,
10812 if (
auto *CE = dyn_cast<CallExpr>(E))
10813 if (CE->getDirectCallee())
10834 if (!
SemaRef.CurContext->isDependentContext()) {
10835 Expr *TargetCall =
nullptr;
10837 auto *E = dyn_cast<Expr>(S);
10845 if (
auto *BO = dyn_cast<BinaryOperator>(E)) {
10846 if (BO->getOpcode() == BO_Assign)
10849 if (
auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10850 if (COCE->getOperator() == OO_Equal)
10862 SemaRef.setFunctionHasBranchProtectedScope();
10865 Clauses, AStmt, TargetCallLoc);
10870 DSAStackTy *Stack) {
10871 bool ErrorFound =
false;
10873 if (
auto *LPC = dyn_cast<OMPLastprivateClause>(
C)) {
10874 for (
Expr *RefExpr : LPC->varlist()) {
10877 Expr *SimpleRefExpr = RefExpr;
10880 auto &&Info = Stack->isLoopControlVariable(D);
10883 S.
Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10884 << getOpenMPDirectiveName(K, OMPVersion);
10908 OMPLoopDirective::HelperExprs B;
10913 if (NestedLoopCount == 0)
10916 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10917 "omp loop exprs were not built");
10920 NestedLoopCount, Clauses, AStmt, B);
10937 OMPLoopDirective::HelperExprs B;
10939 unsigned NestedLoopCount =
10942 VarsWithImplicitDSA, B);
10943 if (NestedLoopCount == 0)
10946 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10947 "omp loop exprs were not built");
10949 DSAStack->setParentTeamsRegionLoc(StartLoc);
10952 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10971 OMPLoopDirective::HelperExprs B;
10973 unsigned NestedLoopCount =
10976 VarsWithImplicitDSA, B);
10977 if (NestedLoopCount == 0)
10980 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10981 "omp loop exprs were not built");
10984 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11004 OMPLoopDirective::HelperExprs B;
11006 unsigned NestedLoopCount =
11009 VarsWithImplicitDSA, B);
11010 if (NestedLoopCount == 0)
11013 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11014 "omp loop exprs were not built");
11017 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11036 OMPLoopDirective::HelperExprs B;
11038 unsigned NestedLoopCount =
11041 VarsWithImplicitDSA, B);
11042 if (NestedLoopCount == 0)
11045 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11046 "omp loop exprs were not built");
11049 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11061 SemaRef.setFunctionHasBranchProtectedScope();
11066 const OMPClause *Copyprivate =
nullptr;
11067 for (
const OMPClause *Clause : Clauses) {
11068 if (Clause->getClauseKind() == OMPC_nowait)
11070 else if (Clause->getClauseKind() == OMPC_copyprivate)
11071 Copyprivate = Clause;
11072 if (Copyprivate && Nowait) {
11074 diag::err_omp_single_copyprivate_with_nowait);
11080 return OMPSingleDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses,
11090 SemaRef.setFunctionHasBranchProtectedScope();
11092 return OMPMasterDirective::Create(
getASTContext(), StartLoc, EndLoc, AStmt);
11102 SemaRef.setFunctionHasBranchProtectedScope();
11114 bool ErrorFound =
false;
11117 bool DependentHint =
false;
11119 if (
C->getClauseKind() == OMPC_hint) {
11121 Diag(
C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
11127 DependentHint =
true;
11130 HintLoc =
C->getBeginLoc();
11136 const auto Pair =
DSAStack->getCriticalWithHint(DirName);
11137 if (Pair.first && DirName.
getName() && !DependentHint) {
11138 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
11139 Diag(StartLoc, diag::err_omp_critical_with_hint);
11141 Diag(HintLoc, diag::note_omp_critical_hint_here)
11142 << 0 <<
toString(Hint, 10,
false);
11144 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
11145 if (
const auto *
C = Pair.first->getSingleClause<
OMPHintClause>()) {
11146 Diag(
C->getBeginLoc(), diag::note_omp_critical_hint_here)
11151 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
11156 SemaRef.setFunctionHasBranchProtectedScope();
11158 auto *Dir = OMPCriticalDirective::Create(
getASTContext(), DirName, StartLoc,
11159 EndLoc, Clauses, AStmt);
11160 if (!Pair.first && DirName.
getName() && !DependentHint)
11161 DSAStack->addCriticalWithHint(Dir, Hint);
11173 OMPLoopBasedDirective::HelperExprs B;
11176 unsigned NestedLoopCount =
11179 VarsWithImplicitDSA, B);
11180 if (NestedLoopCount == 0)
11186 return OMPParallelForDirective::Create(
11187 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11200 OMPLoopBasedDirective::HelperExprs B;
11203 unsigned NestedLoopCount =
11206 VarsWithImplicitDSA, B);
11207 if (NestedLoopCount == 0)
11216 return OMPParallelForSimdDirective::Create(
11217 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11228 return OMPParallelMasterDirective::Create(
11230 DSAStack->getTaskgroupReductionRef());
11241 return OMPParallelMaskedDirective::Create(
11243 DSAStack->getTaskgroupReductionRef());
11252 SemaRef.setFunctionHasBranchProtectedScope();
11254 return OMPParallelSectionsDirective::Create(
11264 bool ErrorFound =
false;
11266 if (llvm::is_contained(MutuallyExclusiveClauses,
C->getClauseKind())) {
11270 S.
Diag(
C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
11293 {OMPC_detach, OMPC_mergeable}))
11298 return OMPTaskDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses,
11299 AStmt,
DSAStack->isCancelRegion());
11304 return OMPTaskyieldDirective::Create(
getASTContext(), StartLoc, EndLoc);
11309 return OMPBarrierDirective::Create(
getASTContext(), StartLoc, EndLoc);
11315 bool InExContext) {
11317 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11319 if (AtC && !InExContext && AtC->
getAtKind() == OMPC_AT_execution) {
11324 if (!AtC || AtC->
getAtKind() == OMPC_AT_compilation) {
11326 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11328 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11329 std::optional<std::string> SL =
11332 if (MessageC && !SL)
11334 diag::warn_clause_expected_string)
11336 if (SeverityC && SeverityC->
getSeverityKind() == OMPC_SEVERITY_warning)
11338 << SL.value_or(
"WARNING");
11340 Diag(StartLoc, diag::err_diagnose_if_succeeded) << SL.value_or(
"ERROR");
11341 if (!SeverityC || SeverityC->
getSeverityKind() != OMPC_SEVERITY_warning)
11353 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11355 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11357 if (NowaitC && !HasDependC) {
11358 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11362 return OMPTaskwaitDirective::Create(
getASTContext(), StartLoc, EndLoc,
11375 SemaRef.setFunctionHasBranchProtectedScope();
11377 return OMPTaskgroupDirective::Create(
getASTContext(), StartLoc, EndLoc,
11379 DSAStack->getTaskgroupReductionRef());
11388 if (
C->getClauseKind() == OMPC_flush)
11397 if (
C->getClauseKind() == OMPC_acq_rel ||
11398 C->getClauseKind() == OMPC_acquire ||
11399 C->getClauseKind() == OMPC_release ||
11400 C->getClauseKind() == OMPC_seq_cst ) {
11401 if (MemOrderKind != OMPC_unknown) {
11402 Diag(
C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11403 << getOpenMPDirectiveName(OMPD_flush, OMPVersion) << 1
11405 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11408 MemOrderKind =
C->getClauseKind();
11409 MemOrderLoc =
C->getBeginLoc();
11413 if (FC && OrderClause) {
11416 Diag(OrderClause->
getBeginLoc(), diag::note_omp_flush_order_clause_here)
11420 return OMPFlushDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses);
11426 if (Clauses.empty()) {
11427 Diag(StartLoc, diag::err_omp_depobj_expected);
11429 }
else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11430 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11434 if (Clauses.size() > 2) {
11435 Diag(Clauses[2]->getBeginLoc(),
11436 diag::err_omp_depobj_single_clause_expected);
11438 }
else if (Clauses.size() < 1) {
11439 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11442 return OMPDepobjDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses);
11449 if (Clauses.size() != 1) {
11450 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11451 diag::err_omp_scan_single_clause_expected);
11460 return StmtError(
Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11461 << getOpenMPDirectiveName(OMPD_scan, OMPVersion) << 5);
11466 if (
DSAStack->doesParentHasScanDirective()) {
11467 Diag(StartLoc, diag::err_omp_several_directives_in_region) <<
"scan";
11469 diag::note_omp_previous_directive)
11473 DSAStack->setParentHasScanDirective(StartLoc);
11481 const OMPClause *DependFound =
nullptr;
11482 const OMPClause *DependSourceClause =
nullptr;
11483 const OMPClause *DependSinkClause =
nullptr;
11484 const OMPClause *DoacrossFound =
nullptr;
11485 const OMPClause *DoacrossSourceClause =
nullptr;
11486 const OMPClause *DoacrossSinkClause =
nullptr;
11487 bool ErrorFound =
false;
11491 auto DOC = dyn_cast<OMPDoacrossClause>(
C);
11492 auto DC = dyn_cast<OMPDependClause>(
C);
11494 DependFound = DC ?
C :
nullptr;
11495 DoacrossFound = DOC ?
C :
nullptr;
11496 OMPDoacrossKind ODK;
11497 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11498 (DOC && (ODK.isSource(DOC)))) {
11499 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11501 Diag(
C->getBeginLoc(), diag::err_omp_more_one_clause)
11502 << getOpenMPDirectiveName(OMPD_ordered, OMPVersion)
11508 DependSourceClause =
C;
11510 DoacrossSourceClause =
C;
11512 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11513 Diag(
C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11514 << (DC ?
"depend" :
"doacross") << 0;
11517 }
else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11518 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11519 if (DependSourceClause || DoacrossSourceClause) {
11520 Diag(
C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11521 << (DC ?
"depend" :
"doacross") << 1;
11525 DependSinkClause =
C;
11527 DoacrossSinkClause =
C;
11529 }
else if (
C->getClauseKind() == OMPC_threads) {
11531 }
else if (
C->getClauseKind() == OMPC_simd) {
11535 if (!ErrorFound && !SC &&
11540 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11543 }
else if ((DependFound || DoacrossFound) && (TC || SC)) {
11546 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11551 }
else if ((DependFound || DoacrossFound) &&
11552 !
DSAStack->getParentOrderedRegionParam().first) {
11555 Diag(Loc, diag::err_omp_ordered_directive_without_param)
11559 }
else if (TC || Clauses.empty()) {
11560 if (
const Expr *Param =
DSAStack->getParentOrderedRegionParam().first) {
11562 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11563 << (TC !=
nullptr);
11564 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11568 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11576 if (!DependFound && !DoacrossFound) {
11577 if (
DSAStack->doesParentHasOrderedDirective()) {
11578 Diag(StartLoc, diag::err_omp_several_directives_in_region) <<
"ordered";
11580 diag::note_omp_previous_directive)
11584 DSAStack->setParentHasOrderedDirective(StartLoc);
11590 SemaRef.setFunctionHasBranchProtectedScope();
11593 return OMPOrderedDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses,
11600class OpenMPAtomicUpdateChecker {
11602 enum ExprAnalysisErrorCode {
11606 NotABinaryOrUnaryExpression,
11608 NotAnUnaryIncDecExpression,
11614 NotABinaryExpression,
11617 NotABinaryOperator,
11620 NotAnUpdateExpression,
11623 NotAValidExpression,
11649 OpenMPAtomicUpdateChecker(
Sema &SemaRef)
11659 bool checkStatement(Stmt *S,
unsigned DiagId = 0,
unsigned NoteId = 0);
11661 Expr *
getX()
const {
return X; }
11663 Expr *
getExpr()
const {
return E; }
11677 bool checkBinaryOperation(BinaryOperator *AtomicBinOp,
unsigned DiagId = 0,
11678 unsigned NoteId = 0);
11681bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11682 BinaryOperator *AtomicBinOp,
unsigned DiagId,
unsigned NoteId) {
11683 ExprAnalysisErrorCode ErrorFound = NoError;
11689 if (AtomicBinOp->
getOpcode() == BO_Assign) {
11691 if (
const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11693 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11694 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11695 AtomicInnerBinOp->isBitwiseOp()) {
11696 Op = AtomicInnerBinOp->getOpcode();
11697 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11698 Expr *LHS = AtomicInnerBinOp->getLHS();
11699 Expr *RHS = AtomicInnerBinOp->getRHS();
11700 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11707 if (XId == LHSId) {
11710 }
else if (XId == RHSId) {
11714 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11715 ErrorRange = AtomicInnerBinOp->getSourceRange();
11716 NoteLoc =
X->getExprLoc();
11717 NoteRange =
X->getSourceRange();
11718 ErrorFound = NotAnUpdateExpression;
11721 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11722 ErrorRange = AtomicInnerBinOp->getSourceRange();
11723 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11725 ErrorFound = NotABinaryOperator;
11730 ErrorFound = NotABinaryExpression;
11737 ErrorFound = NotAnAssignmentOp;
11739 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11740 SemaRef.
Diag(ErrorLoc, DiagId) << ErrorRange;
11741 SemaRef.
Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11745 E =
X = UpdateExpr =
nullptr;
11746 return ErrorFound != NoError;
11749bool OpenMPAtomicUpdateChecker::checkStatement(
Stmt *S,
unsigned DiagId,
11751 ExprAnalysisErrorCode ErrorFound = NoError;
11762 if (
auto *AtomicBody = dyn_cast<Expr>(S)) {
11763 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11764 if (AtomicBody->getType()->isScalarType() ||
11765 AtomicBody->isInstantiationDependent()) {
11766 if (
const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11767 AtomicBody->IgnoreParenImpCasts())) {
11770 AtomicCompAssignOp->getOpcode());
11771 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11772 E = AtomicCompAssignOp->getRHS();
11775 }
else if (
auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11776 AtomicBody->IgnoreParenImpCasts())) {
11778 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11780 }
else if (
const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11781 AtomicBody->IgnoreParenImpCasts())) {
11783 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11785 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11786 OpLoc = AtomicUnaryOp->getOperatorLoc();
11787 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11791 ErrorFound = NotAnUnaryIncDecExpression;
11792 ErrorLoc = AtomicUnaryOp->getExprLoc();
11793 ErrorRange = AtomicUnaryOp->getSourceRange();
11794 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11797 }
else if (!AtomicBody->isInstantiationDependent()) {
11798 ErrorFound = NotABinaryOrUnaryExpression;
11799 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11800 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11801 }
else if (AtomicBody->containsErrors()) {
11802 ErrorFound = NotAValidExpression;
11803 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11804 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11807 ErrorFound = NotAScalarType;
11808 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11809 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
11812 ErrorFound = NotAnExpression;
11814 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
11816 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11817 SemaRef.
Diag(ErrorLoc, DiagId) << ErrorRange;
11818 SemaRef.
Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11822 E =
X = UpdateExpr =
nullptr;
11823 if (ErrorFound == NoError && E &&
X) {
11840 UpdateExpr =
Update.get();
11842 return ErrorFound != NoError;
11846llvm::FoldingSetNodeID getNodeId(
ASTContext &Context,
const Expr *S) {
11847 llvm::FoldingSetNodeID Id;
11853bool checkIfTwoExprsAreSame(
ASTContext &Context,
const Expr *LHS,
11855 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11858class OpenMPAtomicCompareChecker {
11905 struct ErrorInfoTy {
11907 SourceLocation ErrorLoc;
11908 SourceRange ErrorRange;
11909 SourceLocation NoteLoc;
11910 SourceRange NoteRange;
11913 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11916 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11918 Expr *
getX()
const {
return X; }
11919 Expr *getE()
const {
return E; }
11920 Expr *
getD()
const {
return D; }
11921 Expr *getCond()
const {
return C; }
11922 bool isXBinopExpr()
const {
return IsXBinopExpr; }
11926 ASTContext &ContextRef;
11941 bool IsXBinopExpr =
true;
11944 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11947 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11950 bool checkType(ErrorInfoTy &ErrorInfo)
const;
11952 static bool CheckValue(
const Expr *E, ErrorInfoTy &ErrorInfo,
11953 bool ShouldBeLValue,
bool ShouldBeInteger =
false) {
11957 if (ShouldBeLValue && !E->
isLValue()) {
11958 ErrorInfo.Error = ErrorTy::XNotLValue;
11959 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->
getExprLoc();
11960 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->
getSourceRange();
11966 ErrorInfo.Error = ErrorTy::NotScalar;
11967 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->
getExprLoc();
11968 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->
getSourceRange();
11972 ErrorInfo.Error = ErrorTy::NotInteger;
11973 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->
getExprLoc();
11974 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->
getSourceRange();
11982bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(
IfStmt *S,
11983 ErrorInfoTy &ErrorInfo) {
11985 if (
auto *CS = dyn_cast<CompoundStmt>(Then)) {
11986 if (CS->body_empty()) {
11987 ErrorInfo.Error = ErrorTy::NoStmt;
11988 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11989 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11992 if (CS->size() > 1) {
11993 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11994 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11995 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
11998 Then = CS->body_front();
12001 auto *BO = dyn_cast<BinaryOperator>(Then);
12003 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12004 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12005 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12008 if (BO->getOpcode() != BO_Assign) {
12009 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12010 ErrorInfo.ErrorLoc = BO->getExprLoc();
12011 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12012 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12018 auto *
Cond = dyn_cast<BinaryOperator>(S->
getCond());
12019 auto *
Call = dyn_cast<CXXOperatorCallExpr>(S->
getCond());
12020 Expr *LHS =
nullptr;
12021 Expr *RHS =
nullptr;
12023 LHS =
Cond->getLHS();
12024 RHS =
Cond->getRHS();
12026 LHS =
Call->getArg(0);
12027 RHS =
Call->getArg(1);
12029 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12035 if ((
Cond &&
Cond->getOpcode() == BO_EQ) ||
12036 (
Call &&
Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12039 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS)) {
12041 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12044 ErrorInfo.Error = ErrorTy::InvalidComparison;
12046 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12050 }
else if ((
Cond &&
12051 (
Cond->getOpcode() == BO_LT ||
Cond->getOpcode() == BO_GT)) ||
12053 (
Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12054 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12056 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS) &&
12057 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12059 }
else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12060 checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12062 IsXBinopExpr =
false;
12064 ErrorInfo.Error = ErrorTy::InvalidComparison;
12066 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12071 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12078 ErrorInfo.Error = ErrorTy::UnexpectedElse;
12087bool OpenMPAtomicCompareChecker::checkCondExprStmt(
Stmt *S,
12088 ErrorInfoTy &ErrorInfo) {
12089 auto *BO = dyn_cast<BinaryOperator>(S);
12091 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12092 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->
getBeginLoc();
12093 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
12096 if (BO->getOpcode() != BO_Assign) {
12097 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12098 ErrorInfo.ErrorLoc = BO->getExprLoc();
12099 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12100 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12106 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
12108 ErrorInfo.Error = ErrorTy::NotCondOp;
12109 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
12110 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
12114 if (!checkIfTwoExprsAreSame(ContextRef,
X, CO->getFalseExpr())) {
12115 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
12116 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
12117 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12118 CO->getFalseExpr()->getSourceRange();
12122 auto *
Cond = dyn_cast<BinaryOperator>(CO->getCond());
12123 auto *
Call = dyn_cast<CXXOperatorCallExpr>(CO->getCond());
12124 Expr *LHS =
nullptr;
12125 Expr *RHS =
nullptr;
12127 LHS =
Cond->getLHS();
12128 RHS =
Cond->getRHS();
12130 LHS =
Call->getArg(0);
12131 RHS =
Call->getArg(1);
12133 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12134 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12135 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12136 CO->getCond()->getSourceRange();
12140 if ((
Cond &&
Cond->getOpcode() == BO_EQ) ||
12141 (
Call &&
Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12143 D = CO->getTrueExpr();
12144 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS)) {
12146 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12149 ErrorInfo.Error = ErrorTy::InvalidComparison;
12150 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12151 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12152 CO->getCond()->getSourceRange();
12155 }
else if ((
Cond &&
12156 (
Cond->getOpcode() == BO_LT ||
Cond->getOpcode() == BO_GT)) ||
12158 (
Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12159 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12161 E = CO->getTrueExpr();
12162 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS) &&
12163 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12165 }
else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12166 checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12168 IsXBinopExpr =
false;
12170 ErrorInfo.Error = ErrorTy::InvalidComparison;
12171 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12172 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12173 CO->getCond()->getSourceRange();
12177 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12178 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12179 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12180 CO->getCond()->getSourceRange();
12187bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo)
const {
12189 assert(
X && E &&
"X and E cannot be nullptr");
12191 if (!CheckValue(
X, ErrorInfo,
true))
12194 if (!CheckValue(E, ErrorInfo,
false))
12197 if (D && !CheckValue(D, ErrorInfo,
false))
12203bool OpenMPAtomicCompareChecker::checkStmt(
12204 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
12205 auto *CS = dyn_cast<CompoundStmt>(S);
12207 if (CS->body_empty()) {
12208 ErrorInfo.Error = ErrorTy::NoStmt;
12209 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12210 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12214 if (CS->size() != 1) {
12215 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12216 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12217 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12220 S = CS->body_front();
12225 if (
auto *IS = dyn_cast<IfStmt>(S)) {
12231 Res = checkCondUpdateStmt(IS, ErrorInfo);
12237 Res = checkCondExprStmt(S, ErrorInfo);
12243 return checkType(ErrorInfo);
12246class OpenMPAtomicCompareCaptureChecker final
12247 :
public OpenMPAtomicCompareChecker {
12249 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
12251 Expr *
getV()
const {
return V; }
12252 Expr *
getR()
const {
return R; }
12257 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12260 bool checkType(ErrorInfoTy &ErrorInfo);
12272 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12276 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12288bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12289 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12292 if (
V && !CheckValue(
V, ErrorInfo,
true))
12295 if (R && !CheckValue(R, ErrorInfo,
true,
true))
12301bool OpenMPAtomicCompareCaptureChecker::checkForm3(
IfStmt *S,
12302 ErrorInfoTy &ErrorInfo) {
12306 if (
auto *CS = dyn_cast<CompoundStmt>(Then)) {
12307 if (CS->body_empty()) {
12308 ErrorInfo.Error = ErrorTy::NoStmt;
12309 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12310 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12313 if (CS->size() > 1) {
12314 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12315 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12316 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12319 Then = CS->body_front();
12322 auto *BO = dyn_cast<BinaryOperator>(Then);
12324 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12325 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12326 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12329 if (BO->getOpcode() != BO_Assign) {
12330 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12331 ErrorInfo.ErrorLoc = BO->getExprLoc();
12332 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12333 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12340 auto *
Cond = dyn_cast<BinaryOperator>(S->
getCond());
12341 auto *
Call = dyn_cast<CXXOperatorCallExpr>(S->
getCond());
12342 Expr *LHS =
nullptr;
12343 Expr *RHS =
nullptr;
12345 LHS =
Cond->getLHS();
12346 RHS =
Cond->getRHS();
12348 LHS =
Call->getArg(0);
12349 RHS =
Call->getArg(1);
12351 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12356 if ((
Cond &&
Cond->getOpcode() != BO_EQ) ||
12357 (
Call &&
Call->getOperator() != OverloadedOperatorKind::OO_EqualEqual)) {
12358 ErrorInfo.Error = ErrorTy::NotEQ;
12364 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS)) {
12366 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12369 ErrorInfo.Error = ErrorTy::InvalidComparison;
12378 ErrorInfo.Error = ErrorTy::NoElse;
12379 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->
getBeginLoc();
12380 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
12385 if (
auto *CS = dyn_cast<CompoundStmt>(Else)) {
12386 if (CS->body_empty()) {
12387 ErrorInfo.Error = ErrorTy::NoStmt;
12388 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12389 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12392 if (CS->size() > 1) {
12393 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12394 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12395 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
12398 Else = CS->body_front();
12401 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12403 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12404 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12405 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12408 if (ElseBO->getOpcode() != BO_Assign) {
12409 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12410 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12411 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12412 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12416 if (!checkIfTwoExprsAreSame(ContextRef,
X, ElseBO->getRHS())) {
12417 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12418 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12419 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12420 ElseBO->getRHS()->getSourceRange();
12424 V = ElseBO->getLHS();
12426 return checkType(ErrorInfo);
12429bool OpenMPAtomicCompareCaptureChecker::checkForm45(
Stmt *S,
12430 ErrorInfoTy &ErrorInfo) {
12434 assert(CS->size() == 2 &&
"CompoundStmt size is not expected");
12437 assert(S1->getOpcode() == BO_Assign &&
"unexpected binary operator");
12439 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12440 ErrorInfo.Error = ErrorTy::InvalidCondition;
12441 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12442 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12448 auto *Then = S2->getThen();
12449 if (
auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12450 if (ThenCS->body_empty()) {
12451 ErrorInfo.Error = ErrorTy::NoStmt;
12452 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12453 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12456 if (ThenCS->size() > 1) {
12457 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12458 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12459 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12462 Then = ThenCS->body_front();
12465 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12467 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12468 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12469 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12472 if (ThenBO->getOpcode() != BO_Assign) {
12473 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12474 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12475 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12476 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12480 X = ThenBO->getLHS();
12481 D = ThenBO->getRHS();
12484 if (BO->getOpcode() != BO_EQ) {
12485 ErrorInfo.Error = ErrorTy::NotEQ;
12486 ErrorInfo.ErrorLoc = BO->getExprLoc();
12487 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12488 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12494 if (checkIfTwoExprsAreSame(ContextRef,
X, BO->getLHS())) {
12496 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, BO->getRHS())) {
12499 ErrorInfo.Error = ErrorTy::InvalidComparison;
12500 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12501 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12505 if (S2->getElse()) {
12508 auto *Else = S2->getElse();
12509 if (
auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12510 if (ElseCS->body_empty()) {
12511 ErrorInfo.Error = ErrorTy::NoStmt;
12512 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12513 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12516 if (ElseCS->size() > 1) {
12517 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12518 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12519 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12522 Else = ElseCS->body_front();
12525 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12527 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12528 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12529 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12532 if (ElseBO->getOpcode() != BO_Assign) {
12533 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12534 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12535 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12536 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12539 if (!checkIfTwoExprsAreSame(ContextRef,
X, ElseBO->getRHS())) {
12540 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12541 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12542 ErrorInfo.NoteLoc =
X->getExprLoc();
12543 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12544 ErrorInfo.NoteRange =
X->getSourceRange();
12548 V = ElseBO->getLHS();
12551 return checkType(ErrorInfo);
12554bool OpenMPAtomicCompareCaptureChecker::checkStmt(
Stmt *S,
12555 ErrorInfoTy &ErrorInfo) {
12557 if (
auto *IS = dyn_cast<IfStmt>(S))
12558 return checkForm3(IS, ErrorInfo);
12560 auto *CS = dyn_cast<CompoundStmt>(S);
12562 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12563 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->
getBeginLoc();
12564 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
12567 if (CS->body_empty()) {
12568 ErrorInfo.Error = ErrorTy::NoStmt;
12569 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12570 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12575 if (CS->size() == 1) {
12576 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12578 ErrorInfo.Error = ErrorTy::NotIfStmt;
12579 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->
getBeginLoc();
12580 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12585 return checkForm3(IS, ErrorInfo);
12586 }
else if (CS->size() == 2) {
12587 auto *S1 = CS->body_front();
12588 auto *S2 = CS->body_back();
12590 Stmt *UpdateStmt =
nullptr;
12591 Stmt *CondUpdateStmt =
nullptr;
12592 Stmt *CondExprStmt =
nullptr;
12594 if (
auto *BO = dyn_cast<BinaryOperator>(S1)) {
12604 return checkForm45(CS, ErrorInfo);
12613 CondUpdateStmt = S2;
12622 CondUpdateStmt = S1;
12625 auto CheckCondUpdateStmt = [
this, &ErrorInfo](
Stmt *CUS) {
12626 auto *IS = dyn_cast<IfStmt>(CUS);
12628 ErrorInfo.Error = ErrorTy::NotIfStmt;
12629 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12630 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12634 return checkCondUpdateStmt(IS, ErrorInfo);
12638 auto CheckUpdateStmt = [
this, &ErrorInfo](
Stmt *US) {
12639 auto *BO = dyn_cast<BinaryOperator>(US);
12641 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12642 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12643 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12646 if (BO->getOpcode() != BO_Assign) {
12647 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12648 ErrorInfo.ErrorLoc = BO->getExprLoc();
12649 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12650 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12653 if (!checkIfTwoExprsAreSame(ContextRef, this->
X, BO->getRHS())) {
12654 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12655 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12656 ErrorInfo.NoteLoc = this->
X->getExprLoc();
12657 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12658 ErrorInfo.NoteRange = this->
X->getSourceRange();
12662 this->
V = BO->getLHS();
12667 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12669 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12671 if (!CheckUpdateStmt(UpdateStmt))
12674 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12675 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12676 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12680 return checkType(ErrorInfo);
12691 DSAStack->addAtomicDirectiveLoc(StartLoc);
12704 bool MutexClauseEncountered =
false;
12705 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12707 switch (
C->getClauseKind()) {
12711 MutexClauseEncountered =
true;
12714 case OMPC_compare: {
12715 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12716 Diag(
C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12718 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12721 AtomicKind =
C->getClauseKind();
12722 AtomicKindLoc =
C->getBeginLoc();
12723 if (!EncounteredAtomicKinds.insert(
C->getClauseKind()).second) {
12724 Diag(
C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12726 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12734 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12735 Diag(
C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12746 case OMPC_relaxed: {
12747 if (MemOrderKind != OMPC_unknown) {
12748 Diag(
C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12749 << getOpenMPDirectiveName(OMPD_atomic, OMPVersion) << 0
12751 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12754 MemOrderKind =
C->getClauseKind();
12755 MemOrderLoc =
C->getBeginLoc();
12763 llvm_unreachable(
"unknown clause is encountered");
12766 bool IsCompareCapture =
false;
12767 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12768 EncounteredAtomicKinds.contains(OMPC_capture)) {
12769 IsCompareCapture =
true;
12770 AtomicKind = OMPC_compare;
12779 if ((AtomicKind == OMPC_read &&
12780 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12781 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12782 AtomicKind == OMPC_unknown) &&
12783 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12785 if (AtomicKind == OMPC_unknown)
12787 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12789 << (AtomicKind == OMPC_unknown ? 1 : 0)
12791 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12795 Stmt *Body = AStmt;
12796 if (
auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12797 Body = EWC->getSubExpr();
12802 Expr *UE =
nullptr;
12804 Expr *CE =
nullptr;
12831 if (AtomicKind == OMPC_read) {
12838 } ErrorFound = NoError;
12843 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12844 const auto *AtomicBinOp =
12845 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12846 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12849 if ((
X->isInstantiationDependent() ||
X->getType()->isScalarType()) &&
12850 (
V->isInstantiationDependent() ||
V->getType()->isScalarType())) {
12851 if (!
X->isLValue() || !
V->isLValue()) {
12852 const Expr *NotLValueExpr =
X->isLValue() ?
V :
X;
12853 ErrorFound = NotAnLValue;
12859 }
else if (!
X->isInstantiationDependent() ||
12860 !
V->isInstantiationDependent()) {
12861 const Expr *NotScalarExpr =
12862 (
X->isInstantiationDependent() ||
X->getType()->isScalarType())
12865 ErrorFound = NotAScalarType;
12871 }
else if (!AtomicBody->isInstantiationDependent()) {
12872 ErrorFound = NotAnAssignmentOp;
12873 ErrorLoc = AtomicBody->getExprLoc();
12874 ErrorRange = AtomicBody->getSourceRange();
12876 : AtomicBody->getExprLoc();
12878 : AtomicBody->getSourceRange();
12881 ErrorFound = NotAnExpression;
12883 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
12885 if (ErrorFound != NoError) {
12886 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12888 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12889 << ErrorFound << NoteRange;
12892 if (
SemaRef.CurContext->isDependentContext())
12894 }
else if (AtomicKind == OMPC_write) {
12901 } ErrorFound = NoError;
12906 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12907 const auto *AtomicBinOp =
12908 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12909 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12911 E = AtomicBinOp->
getRHS();
12912 if ((
X->isInstantiationDependent() ||
X->getType()->isScalarType()) &&
12914 if (!
X->isLValue()) {
12915 ErrorFound = NotAnLValue;
12918 NoteLoc =
X->getExprLoc();
12919 NoteRange =
X->getSourceRange();
12921 }
else if (!
X->isInstantiationDependent() ||
12923 const Expr *NotScalarExpr =
12924 (
X->isInstantiationDependent() ||
X->getType()->isScalarType())
12927 ErrorFound = NotAScalarType;
12933 }
else if (!AtomicBody->isInstantiationDependent()) {
12934 ErrorFound = NotAnAssignmentOp;
12935 ErrorLoc = AtomicBody->getExprLoc();
12936 ErrorRange = AtomicBody->getSourceRange();
12938 : AtomicBody->getExprLoc();
12940 : AtomicBody->getSourceRange();
12943 ErrorFound = NotAnExpression;
12945 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
12947 if (ErrorFound != NoError) {
12948 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12950 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12951 << ErrorFound << NoteRange;
12954 if (
SemaRef.CurContext->isDependentContext())
12956 }
else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12965 OpenMPAtomicUpdateChecker Checker(
SemaRef);
12966 if (Checker.checkStatement(
12968 (AtomicKind == OMPC_update)
12969 ? diag::err_omp_atomic_update_not_expression_statement
12970 : diag::err_omp_atomic_not_expression_statement,
12971 diag::note_omp_atomic_update))
12973 if (!
SemaRef.CurContext->isDependentContext()) {
12974 E = Checker.getExpr();
12975 X = Checker.getX();
12976 UE = Checker.getUpdateExpr();
12979 }
else if (AtomicKind == OMPC_capture) {
12982 NotACompoundStatement,
12983 NotTwoSubstatements,
12984 NotASpecificExpression,
12986 } ErrorFound = NoError;
12989 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12998 const auto *AtomicBinOp =
12999 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
13000 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
13003 OpenMPAtomicUpdateChecker Checker(
SemaRef);
13004 if (Checker.checkStatement(
13005 Body, diag::err_omp_atomic_capture_not_expression_statement,
13006 diag::note_omp_atomic_update))
13008 E = Checker.getExpr();
13009 X = Checker.getX();
13010 UE = Checker.getUpdateExpr();
13013 }
else if (!AtomicBody->isInstantiationDependent()) {
13014 ErrorLoc = AtomicBody->getExprLoc();
13015 ErrorRange = AtomicBody->getSourceRange();
13017 : AtomicBody->getExprLoc();
13019 : AtomicBody->getSourceRange();
13020 ErrorFound = NotAnAssignmentOp;
13022 if (ErrorFound != NoError) {
13023 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
13025 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13028 if (
SemaRef.CurContext->isDependentContext())
13029 UE =
V = E =
X =
nullptr;
13047 if (
auto *CS = dyn_cast<CompoundStmt>(Body)) {
13049 if (CS->size() == 2) {
13051 Stmt *Second = CS->body_back();
13052 if (
auto *EWC = dyn_cast<ExprWithCleanups>(
First))
13053 First = EWC->getSubExpr()->IgnoreParenImpCasts();
13054 if (
auto *EWC = dyn_cast<ExprWithCleanups>(Second))
13055 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
13057 OpenMPAtomicUpdateChecker Checker(
SemaRef);
13058 bool IsUpdateExprFound = !Checker.checkStatement(Second);
13060 if (IsUpdateExprFound) {
13061 BinOp = dyn_cast<BinaryOperator>(
First);
13062 IsUpdateExprFound = BinOp && BinOp->
getOpcode() == BO_Assign;
13064 if (IsUpdateExprFound && !
SemaRef.CurContext->isDependentContext()) {
13074 llvm::FoldingSetNodeID XId, PossibleXId;
13075 Checker.getX()->Profile(XId, Context,
true);
13076 PossibleX->
Profile(PossibleXId, Context,
true);
13077 IsUpdateExprFound = XId == PossibleXId;
13078 if (IsUpdateExprFound) {
13080 X = Checker.getX();
13081 E = Checker.getExpr();
13082 UE = Checker.getUpdateExpr();
13087 if (!IsUpdateExprFound) {
13088 IsUpdateExprFound = !Checker.checkStatement(
First);
13090 if (IsUpdateExprFound) {
13091 BinOp = dyn_cast<BinaryOperator>(Second);
13092 IsUpdateExprFound = BinOp && BinOp->
getOpcode() == BO_Assign;
13094 if (IsUpdateExprFound &&
13095 !
SemaRef.CurContext->isDependentContext()) {
13105 llvm::FoldingSetNodeID XId, PossibleXId;
13106 Checker.getX()->Profile(XId, Context,
true);
13107 PossibleX->
Profile(PossibleXId, Context,
true);
13108 IsUpdateExprFound = XId == PossibleXId;
13109 if (IsUpdateExprFound) {
13111 X = Checker.getX();
13112 E = Checker.getExpr();
13113 UE = Checker.getUpdateExpr();
13119 if (!IsUpdateExprFound) {
13121 auto *FirstExpr = dyn_cast<Expr>(
First);
13122 auto *SecondExpr = dyn_cast<Expr>(Second);
13123 if (!FirstExpr || !SecondExpr ||
13124 !(FirstExpr->isInstantiationDependent() ||
13125 SecondExpr->isInstantiationDependent())) {
13126 auto *FirstBinOp = dyn_cast<BinaryOperator>(
First);
13127 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
13128 ErrorFound = NotAnAssignmentOp;
13129 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
13130 :
First->getBeginLoc();
13131 NoteRange = ErrorRange = FirstBinOp
13132 ? FirstBinOp->getSourceRange()
13135 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
13136 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
13137 ErrorFound = NotAnAssignmentOp;
13138 NoteLoc = ErrorLoc = SecondBinOp
13139 ? SecondBinOp->getOperatorLoc()
13141 NoteRange = ErrorRange =
13142 SecondBinOp ? SecondBinOp->getSourceRange()
13145 Expr *PossibleXRHSInFirst =
13147 Expr *PossibleXLHSInSecond =
13149 llvm::FoldingSetNodeID X1Id, X2Id;
13150 PossibleXRHSInFirst->
Profile(X1Id, Context,
13152 PossibleXLHSInSecond->
Profile(X2Id, Context,
13154 IsUpdateExprFound = X1Id == X2Id;
13155 if (IsUpdateExprFound) {
13156 V = FirstBinOp->getLHS();
13157 X = SecondBinOp->getLHS();
13158 E = SecondBinOp->getRHS();
13163 ErrorFound = NotASpecificExpression;
13164 ErrorLoc = FirstBinOp->getExprLoc();
13165 ErrorRange = FirstBinOp->getSourceRange();
13166 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
13167 NoteRange = SecondBinOp->getRHS()->getSourceRange();
13175 NoteRange = ErrorRange =
13177 ErrorFound = NotTwoSubstatements;
13181 NoteRange = ErrorRange =
13183 ErrorFound = NotACompoundStatement;
13186 if (ErrorFound != NoError) {
13187 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
13189 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13192 if (
SemaRef.CurContext->isDependentContext())
13193 UE =
V = E =
X =
nullptr;
13194 }
else if (AtomicKind == OMPC_compare) {
13195 if (IsCompareCapture) {
13196 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
13197 OpenMPAtomicCompareCaptureChecker Checker(
SemaRef);
13198 if (!Checker.checkStmt(Body, ErrorInfo)) {
13199 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
13200 << ErrorInfo.ErrorRange;
13201 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13202 << ErrorInfo.Error << ErrorInfo.NoteRange;
13205 X = Checker.getX();
13206 E = Checker.getE();
13207 D = Checker.getD();
13208 CE = Checker.getCond();
13209 V = Checker.getV();
13210 R = Checker.getR();
13216 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
13217 OpenMPAtomicCompareChecker Checker(
SemaRef);
13218 if (!Checker.checkStmt(Body, ErrorInfo)) {
13219 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
13220 << ErrorInfo.ErrorRange;
13221 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13222 << ErrorInfo.Error << ErrorInfo.NoteRange;
13225 X = Checker.getX();
13226 E = Checker.getE();
13227 D = Checker.getD();
13228 CE = Checker.getCond();
13234 auto *It = find_if(Clauses, [](
OMPClause *
C) {
13235 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
13237 if (It != Clauses.end()) {
13238 auto *
Cond = dyn_cast<BinaryOperator>(CE);
13239 if (
Cond->getOpcode() != BO_EQ) {
13240 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
13241 ErrorInfo.ErrorLoc =
Cond->getExprLoc();
13242 ErrorInfo.NoteLoc =
Cond->getOperatorLoc();
13243 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
Cond->getSourceRange();
13245 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
13246 << ErrorInfo.ErrorRange;
13255 SemaRef.setFunctionHasBranchProtectedScope();
13257 return OMPAtomicDirective::Create(
13258 Context, StartLoc, EndLoc, Clauses, AStmt,
13275 if (
DSAStack->hasInnerTeamsRegion()) {
13277 bool OMPTeamsFound =
true;
13278 if (
const auto *CS = dyn_cast<CompoundStmt>(S)) {
13279 auto I = CS->body_begin();
13280 while (I != CS->body_end()) {
13281 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
13283 if (!IsTeams || I != CS->body_begin()) {
13284 OMPTeamsFound =
false;
13285 if (IsTeams && I != CS->body_begin()) {
13294 assert(I != CS->body_end() &&
"Not found statement");
13297 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
13300 if (!OMPTeamsFound) {
13301 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
13303 diag::note_omp_nested_teams_construct_here);
13336 OMPLoopBasedDirective::HelperExprs B;
13339 unsigned NestedLoopCount =
13342 VarsWithImplicitDSA, B);
13343 if (NestedLoopCount == 0)
13350 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13357 return llvm::any_of(
13358 Clauses, [K](
const OMPClause *
C) {
return C->getClauseKind() == K; });
13361template <
typename... Params>
13363 const Params... ClauseTypes) {
13370 if (
auto *TC = dyn_cast<OMPToClause>(
C))
13371 return llvm::all_of(TC->all_decls(), [](
ValueDecl *VD) {
13372 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13373 (VD->isExternallyVisible() &&
13374 VD->getVisibility() != HiddenVisibility);
13376 else if (
auto *FC = dyn_cast<OMPFromClause>(
C))
13377 return llvm::all_of(FC->all_decls(), [](
ValueDecl *VD) {
13378 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13379 (VD->isExternallyVisible() &&
13380 VD->getVisibility() != HiddenVisibility);
13399 if (!
hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13401 !
hasClauses(Clauses, OMPC_use_device_addr))) {
13404 Expected =
"'map' or 'use_device_ptr'";
13406 Expected =
"'map', 'use_device_ptr', or 'use_device_addr'";
13408 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13409 <<
Expected << getOpenMPDirectiveName(OMPD_target_data, OMPVersion);
13413 SemaRef.setFunctionHasBranchProtectedScope();
13431 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13433 << getOpenMPDirectiveName(OMPD_target_enter_data, OMPVersion);
13453 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13454 <<
"'map'" << getOpenMPDirectiveName(OMPD_target_exit_data, OMPVersion);
13470 if (!
hasClauses(Clauses, OMPC_to, OMPC_from)) {
13471 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13476 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13486template <
typename ClauseType>
13489 unsigned MaxNum,
unsigned Diag) {
13490 auto ClauseItr = llvm::find_if(Clauses, llvm::IsaPred<ClauseType>);
13491 if (ClauseItr == Clauses.end())
13494 auto VarList =
C->getVarRefs();
13495 if (VarList.size() > MaxNum) {
13496 SemaRef.
Diag(VarList[MaxNum]->getBeginLoc(),
Diag)
13511 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
13513 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
13518 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13522 DSAStack->setParentTeamsRegionLoc(StartLoc);
13531 if (
DSAStack->isParentNowaitRegion()) {
13532 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13535 if (
DSAStack->isParentOrderedRegion()) {
13536 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13540 EndLoc, CancelRegion);
13546 if (
DSAStack->isParentNowaitRegion()) {
13547 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13550 if (
DSAStack->isParentOrderedRegion()) {
13551 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13554 DSAStack->setParentCancelRegion(
true);
13561 const OMPClause *ReductionClause =
nullptr;
13562 const OMPClause *NogroupClause =
nullptr;
13564 if (
C->getClauseKind() == OMPC_reduction) {
13565 ReductionClause =
C;
13570 if (
C->getClauseKind() == OMPC_nogroup) {
13572 if (ReductionClause)
13577 if (ReductionClause && NogroupClause) {
13578 S.
Diag(ReductionClause->
getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13593 OMPLoopBasedDirective::HelperExprs B;
13596 unsigned NestedLoopCount =
13599 *
DSAStack, VarsWithImplicitDSA, B);
13600 if (NestedLoopCount == 0)
13603 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13604 "omp for loop exprs were not built");
13610 {OMPC_grainsize, OMPC_num_tasks}))
13618 SemaRef.setFunctionHasBranchProtectedScope();
13620 NestedLoopCount, Clauses, AStmt, B,
13634 OMPLoopBasedDirective::HelperExprs B;
13637 unsigned NestedLoopCount =
13640 VarsWithImplicitDSA, B);
13641 if (NestedLoopCount == 0)
13651 {OMPC_grainsize, OMPC_num_tasks}))
13662 NestedLoopCount, Clauses, AStmt, B);
13672 OMPLoopBasedDirective::HelperExprs B;
13675 unsigned NestedLoopCount =
13678 *
DSAStack, VarsWithImplicitDSA, B);
13679 if (NestedLoopCount == 0)
13682 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13683 "omp for loop exprs were not built");
13689 {OMPC_grainsize, OMPC_num_tasks}))
13697 SemaRef.setFunctionHasBranchProtectedScope();
13699 NestedLoopCount, Clauses, AStmt, B,
13710 OMPLoopBasedDirective::HelperExprs B;
13713 unsigned NestedLoopCount =
13716 *
DSAStack, VarsWithImplicitDSA, B);
13717 if (NestedLoopCount == 0)
13720 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13721 "omp for loop exprs were not built");
13727 {OMPC_grainsize, OMPC_num_tasks}))
13735 SemaRef.setFunctionHasBranchProtectedScope();
13737 NestedLoopCount, Clauses, AStmt, B,
13751 OMPLoopBasedDirective::HelperExprs B;
13754 unsigned NestedLoopCount =
13757 VarsWithImplicitDSA, B);
13758 if (NestedLoopCount == 0)
13768 {OMPC_grainsize, OMPC_num_tasks}))
13779 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13792 OMPLoopBasedDirective::HelperExprs B;
13795 unsigned NestedLoopCount =
13798 VarsWithImplicitDSA, B);
13799 if (NestedLoopCount == 0)
13809 {OMPC_grainsize, OMPC_num_tasks}))
13820 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13832 OMPLoopBasedDirective::HelperExprs B;
13838 VarsWithImplicitDSA, B);
13839 if (NestedLoopCount == 0)
13842 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13843 "omp for loop exprs were not built");
13849 {OMPC_grainsize, OMPC_num_tasks}))
13858 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13871 OMPLoopBasedDirective::HelperExprs B;
13877 VarsWithImplicitDSA, B);
13878 if (NestedLoopCount == 0)
13881 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13882 "omp for loop exprs were not built");
13888 {OMPC_grainsize, OMPC_num_tasks}))
13897 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13908 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
13910 OMPLoopBasedDirective::HelperExprs B;
13916 VarsWithImplicitDSA, B);
13917 if (NestedLoopCount == 0)
13927 {OMPC_grainsize, OMPC_num_tasks}))
13938 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13948 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
13950 OMPLoopBasedDirective::HelperExprs B;
13956 VarsWithImplicitDSA, B);
13957 if (NestedLoopCount == 0)
13967 {OMPC_grainsize, OMPC_num_tasks}))
13978 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13988 OMPLoopBasedDirective::HelperExprs B;
13991 unsigned NestedLoopCount =
13995 if (NestedLoopCount == 0)
13998 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13999 "omp for loop exprs were not built");
14001 SemaRef.setFunctionHasBranchProtectedScope();
14003 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14004 return DistributeDirective;
14016 OMPLoopBasedDirective::HelperExprs B;
14022 VarsWithImplicitDSA, B);
14023 if (NestedLoopCount == 0)
14026 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14027 "omp for loop exprs were not built");
14030 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14041 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
14043 OMPLoopBasedDirective::HelperExprs B;
14049 VarsWithImplicitDSA, B);
14050 if (NestedLoopCount == 0)
14060 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14072 OMPLoopBasedDirective::HelperExprs B;
14075 unsigned NestedLoopCount =
14079 if (NestedLoopCount == 0)
14089 NestedLoopCount, Clauses, AStmt, B);
14101 OMPLoopBasedDirective::HelperExprs B;
14107 VarsWithImplicitDSA, B);
14108 if (NestedLoopCount == 0)
14118 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14129 OMPLoopBasedDirective::HelperExprs B;
14132 unsigned NestedLoopCount =
14135 VarsWithImplicitDSA, B);
14136 if (NestedLoopCount == 0)
14146 NestedLoopCount, Clauses, AStmt, B);
14158 OMPLoopBasedDirective::HelperExprs B;
14161 unsigned NestedLoopCount =
14165 if (NestedLoopCount == 0)
14168 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14169 "omp teams distribute loop exprs were not built");
14171 DSAStack->setParentTeamsRegionLoc(StartLoc);
14174 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14186 OMPLoopBasedDirective::HelperExprs B;
14192 VarsWithImplicitDSA, B);
14193 if (NestedLoopCount == 0)
14202 DSAStack->setParentTeamsRegionLoc(StartLoc);
14205 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14215 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
14217 OMPLoopBasedDirective::HelperExprs B;
14223 VarsWithImplicitDSA, B);
14224 if (NestedLoopCount == 0)
14233 DSAStack->setParentTeamsRegionLoc(StartLoc);
14236 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14246 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
14248 OMPLoopBasedDirective::HelperExprs B;
14254 VarsWithImplicitDSA, B);
14256 if (NestedLoopCount == 0)
14259 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14260 "omp for loop exprs were not built");
14262 DSAStack->setParentTeamsRegionLoc(StartLoc);
14265 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14278 bool HasThreadLimitAndNumTeamsClause =
hasClauses(Clauses, OMPC_num_teams) &&
14280 bool HasBareClause = llvm::any_of(Clauses, [&](
const OMPClause *
C) {
14282 return C->getClauseKind() == OMPC_ompx_bare;
14285 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
14290 unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 1;
14291 unsigned DiagNo = HasBareClause
14292 ? diag::err_ompx_more_than_three_expr_not_allowed
14293 : diag::err_omp_multi_expr_not_allowed;
14295 ClauseMaxNumExprs, DiagNo) ||
14297 ClauseMaxNumExprs, DiagNo))
14311 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
14313 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14319 OMPLoopBasedDirective::HelperExprs B;
14325 VarsWithImplicitDSA, B);
14326 if (NestedLoopCount == 0)
14329 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14330 "omp target teams distribute loop exprs were not built");
14333 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14343 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
14345 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14349 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
14351 OMPLoopBasedDirective::HelperExprs B;
14357 VarsWithImplicitDSA, B);
14358 if (NestedLoopCount == 0)
14365 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14376 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
14378 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14382 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
14384 OMPLoopBasedDirective::HelperExprs B;
14387 unsigned NestedLoopCount =
14392 if (NestedLoopCount == 0)
14402 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14412 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
14414 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14418 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
14420 OMPLoopBasedDirective::HelperExprs B;
14426 VarsWithImplicitDSA, B);
14427 if (NestedLoopCount == 0)
14437 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14444 Stmt *Dir = Transform->getDirective();
14446#define STMT(CLASS, PARENT)
14447#define ABSTRACT_STMT(CLASS)
14448#define COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT) \
14449 case Stmt::CLASS##Class: \
14450 appendFlattenedStmtList(PreInits, \
14451 static_cast<const CLASS *>(Dir)->getPreInits()); \
14453#define OMPCANONICALLOOPNESTTRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14454 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14455#define OMPCANONICALLOOPSEQUENCETRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14456 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14457#include "clang/AST/StmtNodes.inc"
14458#undef COMMON_OMP_LOOP_TRANSFORMATION
14460 llvm_unreachable(
"Not a loop transformation");
14464bool SemaOpenMP::checkTransformableLoopNest(
14468 OriginalInits.emplace_back();
14469 bool Result = OMPLoopBasedDirective::doForAllLoops(
14471 [
this, &LoopHelpers, &Body, &OriginalInits, Kind](
unsigned Cnt,
14473 VarsWithInheritedDSAType TmpDSA;
14474 unsigned SingleNumLoops =
14475 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
14476 TmpDSA, LoopHelpers[Cnt]);
14477 if (SingleNumLoops == 0)
14479 assert(SingleNumLoops == 1 &&
"Expect single loop iteration space");
14480 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14481 OriginalInits.back().push_back(For->getInit());
14482 Body = For->getBody();
14484 assert(isa<CXXForRangeStmt>(CurStmt) &&
14485 "Expected canonical for or range-based for loops.");
14486 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14487 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14488 Body = CXXFor->getBody();
14490 OriginalInits.emplace_back();
14493 [&OriginalInits](OMPLoopTransformationDirective *Transform) {
14496 assert(OriginalInits.back().empty() &&
"No preinit after innermost loop");
14497 OriginalInits.pop_back();
14535 unsigned NestedLoopCount = 0;
14582bool SemaOpenMP::analyzeLoopSequence(
Stmt *LoopSeqStmt,
14583 LoopSequenceAnalysis &SeqAnalysis,
14589 auto StoreLoopStatements = [](LoopAnalysis &Analysis, Stmt *LoopStmt) {
14590 if (
auto *For = dyn_cast<ForStmt>(LoopStmt)) {
14591 Analysis.OriginalInits.push_back(For->getInit());
14592 Analysis.TheForStmt = For;
14595 Analysis.OriginalInits.push_back(CXXFor->getBeginStmt());
14596 Analysis.TheForStmt = CXXFor;
14603 auto AnalyzeLoopGeneration = [&](Stmt *Child) {
14605 Stmt *TransformedStmt = LoopTransform->getTransformedStmt();
14606 unsigned NumGeneratedTopLevelLoops =
14607 LoopTransform->getNumGeneratedTopLevelLoops();
14610 if (!TransformedStmt) {
14611 if (NumGeneratedTopLevelLoops > 0) {
14612 SeqAnalysis.LoopSeqSize += NumGeneratedTopLevelLoops;
14616 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14617 << 0 << getOpenMPDirectiveName(Kind);
14622 if (!NumGeneratedTopLevelLoops) {
14623 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14624 << 0 << getOpenMPDirectiveName(Kind);
14628 if (NumGeneratedTopLevelLoops > 1) {
14635 updatePreInits(LoopTransform, SeqAnalysis.LoopSequencePreInits);
14636 return analyzeLoopSequence(TransformedStmt, SeqAnalysis, Context, Kind);
14640 LoopAnalysis &NewTransformedSingleLoop =
14641 SeqAnalysis.Loops.emplace_back(Child);
14644 NewTransformedSingleLoop.HelperExprs);
14649 StoreLoopStatements(NewTransformedSingleLoop, TransformedStmt);
14650 updatePreInits(LoopTransform, NewTransformedSingleLoop.TransformsPreInits);
14652 SeqAnalysis.LoopSeqSize++;
14657 auto AnalyzeRegularLoop = [&](Stmt *Child) {
14658 LoopAnalysis &NewRegularLoop = SeqAnalysis.Loops.emplace_back(Child);
14659 unsigned IsCanonical =
14661 TmpDSA, NewRegularLoop.HelperExprs);
14666 StoreLoopStatements(NewRegularLoop, Child);
14667 NestedLoopCounterVisitor NLCV;
14673 for (Stmt *Child : LoopSeqStmt->
children()) {
14677 if (!LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
14678 Child = Child->IgnoreContainers();
14685 if (!analyzeLoopSequence(Child, SeqAnalysis, Context, Kind))
14692 if (LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
14693 if (LoopAnalysis::isLoopTransformation(Child)) {
14694 if (!AnalyzeLoopGeneration(Child))
14698 if (!AnalyzeRegularLoop(Child))
14700 SeqAnalysis.LoopSeqSize++;
14704 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14705 << 0 << getOpenMPDirectiveName(Kind);
14712bool SemaOpenMP::checkTransformableLoopSequence(
14737 << getOpenMPDirectiveName(Kind);
14742 if (!analyzeLoopSequence(AStmt, SeqAnalysis, Context, Kind))
14746 if (!SeqAnalysis.LoopSeqSize) {
14748 << getOpenMPDirectiveName(Kind);
14756 OMPLoopBasedDirective::HelperExprs &LoopHelper,
14762 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
14763 Stmt *RangeInit = CXXRangeFor->getInit();
14765 PreInits.push_back(RangeInit);
14767 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14772 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14778 llvm::append_range(PreInits, OriginalInit);
14781 if (
auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits)) {
14782 PreInits.push_back(
new (Context)
DeclStmt(
14783 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14787 for (
Expr *CounterRef : LoopHelper.Counters) {
14790 PreInits.push_back(
new (Context)
DeclStmt(
14798 size_t NumLoops = LoopStmts.size();
14799 OMPLoopBasedDirective::doForAllLoops(
14800 AStmt,
false, NumLoops,
14801 [LoopStmts](
unsigned Cnt,
Stmt *CurStmt) {
14802 assert(!LoopStmts[Cnt] &&
"Loop statement must not yet be assigned");
14803 LoopStmts[Cnt] = CurStmt;
14806 assert(!is_contained(LoopStmts,
nullptr) &&
14807 "Expecting a loop statement for each affected loop");
14825 const auto *SizesClause =
14826 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14827 if (!SizesClause ||
14828 llvm::any_of(SizesClause->getSizesRefs(), [](
Expr *E) { return !E; }))
14830 unsigned NumLoops = SizesClause->getNumSizes();
14838 Stmt *Body =
nullptr;
14840 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14845 if (
SemaRef.CurContext->isDependentContext())
14847 NumLoops, AStmt,
nullptr,
nullptr);
14849 assert(LoopHelpers.size() == NumLoops &&
14850 "Expecting loop iteration space dimensionality to match number of "
14852 assert(OriginalInits.size() == NumLoops &&
14853 "Expecting loop iteration space dimensionality to match number of "
14861 CaptureVars CopyTransformer(
SemaRef);
14866 FloorIndVars.resize(NumLoops);
14867 TileIndVars.resize(NumLoops);
14868 for (
unsigned I = 0; I < NumLoops; ++I) {
14869 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14871 assert(LoopHelper.Counters.size() == 1 &&
14872 "Expect single-dimensional loop iteration space");
14874 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14880 std::string FloorCntName =
14881 (Twine(
".floor_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
14884 FloorIndVars[I] = FloorCntDecl;
14889 std::string TileCntName =
14890 (Twine(
".tile_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
14896 TileCntDecl->setDeclName(
14897 &
SemaRef.PP.getIdentifierTable().get(TileCntName));
14898 TileIndVars[I] = TileCntDecl;
14906 Stmt *Inner = Body;
14908 auto MakeDimTileSize = [&
SemaRef = this->SemaRef, &CopyTransformer, &Context,
14909 SizesClause, CurScope](
int I) ->
Expr * {
14910 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
14916 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
14935 uint64_t DimWidth = Context.getTypeSize(DimTy);
14937 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14941 CurScope, {}, BO_LE,
14945 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
14951 for (
int I = NumLoops - 1; I >= 0; --I) {
14952 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14953 Expr *NumIterations = LoopHelper.NumIterations;
14956 Stmt *LoopStmt = LoopStmts[I];
14961 auto MakeTileIVRef = [&
SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
14964 OrigCntVar->getExprLoc());
14968 SemaRef.AddInitializerToDecl(
14971 .DefaultLvalueConversion(
14975 Decl *CounterDecl = TileIndVars[I];
14978 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14984 Expr *DimTileSize = MakeDimTileSize(I);
14988 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14994 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14995 NumIterations, EndOfTile.
get());
14999 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
15000 IsPartialTile.
get(), NumIterations, EndOfTile.
get());
15001 if (!MinTileAndIterSpace.
isUsable())
15004 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15005 MakeTileIVRef(), MinTileAndIterSpace.
get());
15011 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef());
15032 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15033 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15034 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15035 BodyParts.push_back(Inner);
15038 Inner =
new (Context)
15041 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15045 for (
int I = NumLoops - 1; I >= 0; --I) {
15046 auto &LoopHelper = LoopHelpers[I];
15047 Expr *NumIterations = LoopHelper.NumIterations;
15052 SemaRef.AddInitializerToDecl(
15054 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15056 Decl *CounterDecl = FloorIndVars[I];
15065 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15072 Expr *DimTileSize = MakeDimTileSize(I);
15076 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15082 Inner =
new (Context)
15085 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15100 const auto *SizesClause =
15101 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
15102 if (!SizesClause ||
15103 llvm::any_of(SizesClause->getSizesRefs(), [](
const Expr *SizeExpr) {
15104 return !SizeExpr || SizeExpr->containsErrors();
15107 unsigned NumLoops = SizesClause->getNumSizes();
15115 Stmt *Body =
nullptr;
15117 if (!checkTransformableLoopNest(OMPD_stripe, AStmt, NumLoops, LoopHelpers,
15118 Body, OriginalInits))
15122 if (
SemaRef.CurContext->isDependentContext())
15124 NumLoops, AStmt,
nullptr,
nullptr);
15126 assert(LoopHelpers.size() == NumLoops &&
15127 "Expecting loop iteration space dimensionality to match number of "
15129 assert(OriginalInits.size() == NumLoops &&
15130 "Expecting loop iteration space dimensionality to match number of "
15138 CaptureVars CopyTransformer(
SemaRef);
15143 FloorIndVars.resize(NumLoops);
15144 StripeIndVars.resize(NumLoops);
15145 for (
unsigned I : llvm::seq<unsigned>(NumLoops)) {
15146 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15148 assert(LoopHelper.Counters.size() == 1 &&
15149 "Expect single-dimensional loop iteration space");
15151 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15157 std::string FloorCntName =
15158 (Twine(
".floor_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
15161 FloorIndVars[I] = FloorCntDecl;
15166 std::string StripeCntName =
15167 (Twine(
".stripe_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
15173 StripeCntDecl->setDeclName(
15174 &
SemaRef.PP.getIdentifierTable().get(StripeCntName));
15175 StripeIndVars[I] = StripeCntDecl;
15183 Stmt *Inner = Body;
15185 auto MakeDimStripeSize = [&](
int I) ->
Expr * {
15186 Expr *DimStripeSizeExpr = SizesClause->getSizesRefs()[I];
15188 return AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr));
15207 uint64_t DimWidth = Context.getTypeSize(DimTy);
15209 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
15213 CurScope, {}, BO_LE,
15217 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), DimTy,
15223 for (
int I = NumLoops - 1; I >= 0; --I) {
15224 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15225 Expr *NumIterations = LoopHelper.NumIterations;
15228 Stmt *LoopStmt = LoopStmts[I];
15231 SemaRef.AddInitializerToDecl(
15234 .DefaultLvalueConversion(
15238 Decl *CounterDecl = StripeIndVars[I];
15241 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15248 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15250 MakeDimStripeSize(I));
15254 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15255 NumIterations, EndOfStripe.
get());
15259 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
15260 IsPartialStripe.
get(), NumIterations, EndOfStripe.
get());
15261 if (!MinStripeAndIterSpace.
isUsable())
15264 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15266 MinStripeAndIterSpace.
get());
15272 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc,
15294 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15295 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15296 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15297 BodyParts.push_back(Inner);
15300 Inner =
new (Context)
15303 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15307 for (
int I = NumLoops - 1; I >= 0; --I) {
15308 auto &LoopHelper = LoopHelpers[I];
15309 Expr *NumIterations = LoopHelper.NumIterations;
15314 SemaRef.AddInitializerToDecl(
15316 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15318 Decl *CounterDecl = FloorIndVars[I];
15327 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15335 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15337 MakeDimStripeSize(I));
15341 Inner =
new (Context)
15344 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15348 NumLoops, AStmt, Inner,
15363 {OMPC_partial, OMPC_full}))
15367 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
15369 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
15370 assert(!(FullClause && PartialClause) &&
15371 "mutual exclusivity must have been checked before");
15373 constexpr unsigned NumLoops = 1;
15374 Stmt *Body =
nullptr;
15378 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
15379 Body, OriginalInits))
15382 unsigned NumGeneratedTopLevelLoops = PartialClause ? 1 : 0;
15385 if (
SemaRef.CurContext->isDependentContext())
15387 NumGeneratedTopLevelLoops,
nullptr,
15390 assert(LoopHelpers.size() == NumLoops &&
15391 "Expecting a single-dimensional loop iteration space");
15392 assert(OriginalInits.size() == NumLoops &&
15393 "Expecting a single-dimensional loop iteration space");
15394 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15398 LoopHelper.NumIterations, OMPC_full,
false,
15401 Diag(AStmt->
getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
15403 <<
"#pragma omp unroll full";
15411 if (NumGeneratedTopLevelLoops == 0)
15413 NumGeneratedTopLevelLoops,
nullptr,
15459 Stmt *LoopStmt =
nullptr;
15464 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15467 QualType IVTy = IterationVarRef->getType();
15468 assert(LoopHelper.Counters.size() == 1 &&
15469 "Expecting a single-dimensional loop iteration space");
15477 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
15478 FactorLoc = FactorVal->getExprLoc();
15483 assert(Factor > 0 &&
"Expected positive unroll factor");
15484 auto MakeFactorExpr = [
this, Factor, IVTy, FactorLoc]() {
15496 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15497 std::string OuterIVName = (Twine(
".unrolled.iv.") + OrigVarName).str();
15498 std::string InnerIVName = (Twine(
".unroll_inner.iv.") + OrigVarName).str();
15503 auto MakeOuterRef = [
this, OuterIVDecl, IVTy, OrigVarLoc]() {
15509 auto *InnerIVDecl =
cast<VarDecl>(IterationVarRef->getDecl());
15510 InnerIVDecl->setDeclName(&
SemaRef.PP.getIdentifierTable().get(InnerIVName));
15511 auto MakeInnerRef = [
this, InnerIVDecl, IVTy, OrigVarLoc]() {
15517 CaptureVars CopyTransformer(
SemaRef);
15518 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() ->
Expr * {
15520 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15525 SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.
get(),
15540 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15541 MakeOuterRef(), MakeFactorExpr());
15545 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15546 MakeInnerRef(), EndOfTile.
get());
15550 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15551 MakeInnerRef(), MakeNumIterations());
15555 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
15556 InnerCond1.
get(), InnerCond2.
get());
15562 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef());
15568 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15569 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15570 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15571 InnerBodyStmts.push_back(Body);
15575 ForStmt *InnerFor =
new (Context)
15576 ForStmt(Context, InnerInit.
get(), InnerCond.
get(),
nullptr,
15578 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15592 LoopHintAttr *UnrollHintAttr =
15593 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
15594 LoopHintAttr::Numeric, MakeFactorExpr());
15599 SemaRef.AddInitializerToDecl(
15601 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15610 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15611 MakeOuterRef(), MakeNumIterations());
15617 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15618 MakeOuterRef(), MakeFactorExpr());
15623 ForStmt *OuterFor =
new (Context)
15624 ForStmt(Context, OuterInit.
get(), OuterConde.
get(),
nullptr,
15626 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15629 NumGeneratedTopLevelLoops, OuterFor,
15643 constexpr unsigned NumLoops = 1;
15644 Stmt *Body =
nullptr;
15648 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
15649 Body, OriginalInits))
15654 if (
SemaRef.CurContext->isDependentContext())
15656 NumLoops,
nullptr,
nullptr);
15658 assert(LoopHelpers.size() == NumLoops &&
15659 "Expecting a single-dimensional loop iteration space");
15660 assert(OriginalInits.size() == NumLoops &&
15661 "Expecting a single-dimensional loop iteration space");
15662 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15665 Stmt *LoopStmt =
nullptr;
15670 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15673 QualType IVTy = IterationVarRef->getType();
15674 uint64_t IVWidth = Context.getTypeSize(IVTy);
15688 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15690 ForwardIVName += OrigVarName;
15692 ReversedIVName += OrigVarName;
15725 CaptureVars CopyTransformer(
SemaRef);
15726 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() ->
Expr * {
15728 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15734 auto MakeForwardRef = [&
SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
15741 auto *ReversedIVDecl =
cast<VarDecl>(IterationVarRef->getDecl());
15742 ReversedIVDecl->setDeclName(
15743 &
SemaRef.PP.getIdentifierTable().get(ReversedIVName));
15750 ForwardIVDecl->
getType(), OrigVarLoc);
15751 SemaRef.AddInitializerToDecl(ForwardIVDecl,
Zero,
false);
15754 if (!
Init.isUsable())
15762 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15763 MakeForwardRef(), MakeNumIterations());
15764 if (!
Cond.isUsable())
15772 UO_PreInc, MakeForwardRef());
15783 MakeNumIterations(), One);
15786 Minus =
SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, Minus.
get(),
15791 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
15794 SemaRef.AddInitializerToDecl(ReversedIVDecl, Minus.
get(),
15799 BodyStmts.reserve(LoopHelper.Updates.size() + 2 +
15801 BodyStmts.push_back(InitReversed.
get());
15802 llvm::append_range(BodyStmts, LoopHelper.Updates);
15803 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15804 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15805 BodyStmts.push_back(Body);
15806 auto *ReversedBody =
15811 auto *ReversedFor =
new (Context)
15814 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15833 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
15834 size_t NumLoops = PermutationClause ? PermutationClause->
getNumLoops() : 2;
15838 Stmt *Body =
nullptr;
15840 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
15841 LoopHelpers, Body, OriginalInits))
15847 NumLoops, AStmt,
nullptr,
nullptr);
15851 if (PermutationClause &&
15852 llvm::is_contained(PermutationClause->
getArgsRefs(),
nullptr))
15855 assert(LoopHelpers.size() == NumLoops &&
15856 "Expecting loop iteration space dimensionaly to match number of "
15858 assert(OriginalInits.size() == NumLoops &&
15859 "Expecting loop iteration space dimensionaly to match number of "
15864 if (!PermutationClause) {
15865 Permutation = {1, 0};
15868 llvm::BitVector Flags(PermArgs.size());
15869 for (
Expr *PermArg : PermArgs) {
15870 std::optional<llvm::APSInt> PermCstExpr =
15871 PermArg->getIntegerConstantExpr(Context);
15874 uint64_t PermInt = PermCstExpr->getZExtValue();
15875 assert(1 <= PermInt && PermInt <= NumLoops &&
15876 "Must be a permutation; diagnostic emitted in "
15877 "ActOnOpenMPPermutationClause");
15878 if (Flags[PermInt - 1]) {
15879 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
15880 Diag(PermArg->getExprLoc(),
15881 diag::err_omp_interchange_permutation_value_repeated)
15882 << PermInt << ExprRange;
15885 Flags[PermInt - 1] =
true;
15887 Permutation.push_back(PermInt - 1);
15890 if (Permutation.size() != NumLoops)
15895 if (NumLoops <= 1 || llvm::all_of(llvm::enumerate(Permutation), [](
auto P) {
15896 auto [Idx, Arg] = P;
15900 NumLoops, AStmt, AStmt,
nullptr);
15908 for (
auto I : llvm::seq<int>(NumLoops)) {
15909 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15911 assert(LoopHelper.Counters.size() == 1 &&
15912 "Single-dimensional loop iteration space expected");
15919 CaptureVars CopyTransformer(
SemaRef);
15924 Stmt *Inner = Body;
15925 for (
auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
15927 uint64_t SourceIdx = Permutation[TargetIdx];
15928 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
15929 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
15930 assert(SourceHelper.Counters.size() == 1 &&
15931 "Single-dimensional loop iteration space expected");
15938 "Expected the logical iteration counter to be an integer");
15940 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15945 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() ->
Expr * {
15947 CopyTransformer.TransformExpr(SourceHelper.NumIterations));
15954 PermutedCntName.append({llvm::utostr(TargetIdx),
".iv.", OrigVarName});
15956 PermutedCntDecl->setDeclName(
15957 &
SemaRef.PP.getIdentifierTable().get(PermutedCntName));
15958 PermutedIndVars[TargetIdx] = PermutedCntDecl;
15959 auto MakePermutedRef = [
this, PermutedCntDecl, IVTy, OrigVarLoc]() {
15968 if (!
Zero.isUsable())
15970 SemaRef.AddInitializerToDecl(PermutedCntDecl,
Zero.get(),
15974 OrigCntVar->getEndLoc());
15983 SemaRef.BuildBinOp(CurScope, SourceHelper.Cond->getExprLoc(), BO_LT,
15984 MakePermutedRef(), MakeNumIterations());
15993 CurScope, SourceHelper.Inc->getExprLoc(), UO_PreInc, MakePermutedRef());
15998 SourceHelper.Updates.end());
15999 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
16000 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
16001 BodyParts.push_back(Inner);
16004 Inner =
new (Context)
ForStmt(
16005 Context, InitStmt.
get(), CondExpr.
get(),
nullptr, IncrStmt.
get(), Inner,
16006 SourceHelper.Init->
getBeginLoc(), SourceHelper.Init->getBeginLoc(),
16007 SourceHelper.Inc->getEndLoc());
16011 NumLoops, AStmt, Inner,
16023 CaptureVars CopyTransformer(
SemaRef);
16035 1, AStmt,
nullptr,
nullptr);
16039 LoopSequenceAnalysis SeqAnalysis;
16040 if (!checkTransformableLoopSequence(OMPD_fuse, AStmt, SeqAnalysis, Context))
16045 assert(SeqAnalysis.LoopSeqSize == SeqAnalysis.Loops.size() &&
16046 "Inconsistent size of the loop sequence and the number of loops "
16047 "found in the sequence");
16051 OMPExecutableDirective::getSingleClause<OMPLoopRangeClause>(Clauses);
16055 if (LRC && (!LRC->getFirst() || !LRC->getCount()))
16060 auto EvaluateLoopRangeArguments = [&Context](
Expr *
First,
Expr *Count,
16061 uint64_t &FirstVal,
16062 uint64_t &CountVal) {
16063 llvm::APSInt FirstInt =
First->EvaluateKnownConstInt(Context);
16064 llvm::APSInt CountInt = Count->EvaluateKnownConstInt(Context);
16065 FirstVal = FirstInt.getZExtValue();
16066 CountVal = CountInt.getZExtValue();
16072 auto ValidLoopRange = [](uint64_t FirstVal, uint64_t CountVal,
16073 unsigned NumLoops) ->
bool {
16074 return FirstVal + CountVal - 1 <= NumLoops;
16076 uint64_t FirstVal = 1, CountVal = 0, LastVal = SeqAnalysis.LoopSeqSize;
16082 EvaluateLoopRangeArguments(LRC->getFirst(), LRC->getCount(), FirstVal,
16085 SemaRef.Diag(LRC->getCountLoc(), diag::warn_omp_redundant_fusion)
16086 << getOpenMPDirectiveName(OMPD_fuse);
16088 if (!ValidLoopRange(FirstVal, CountVal, SeqAnalysis.LoopSeqSize)) {
16089 SemaRef.Diag(LRC->getFirstLoc(), diag::err_omp_invalid_looprange)
16090 << getOpenMPDirectiveName(OMPD_fuse) << FirstVal
16091 << (FirstVal + CountVal - 1) << SeqAnalysis.LoopSeqSize;
16095 LastVal = FirstVal + CountVal - 1;
16100 unsigned NumGeneratedTopLevelLoops =
16101 LRC ? SeqAnalysis.LoopSeqSize - CountVal + 1 : 1;
16105 if (SeqAnalysis.LoopSeqSize == 1)
16107 << getOpenMPDirectiveName(OMPD_fuse);
16111 SeqAnalysis.Loops[FirstVal - 1].HelperExprs.IterationVarRef->getType();
16112 for (
unsigned I : llvm::seq<unsigned>(FirstVal, LastVal)) {
16114 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef->getType();
16115 if (Context.getTypeSize(CurrentIVType) > Context.getTypeSize(IVType)) {
16116 IVType = CurrentIVType;
16119 uint64_t IVBitWidth = Context.getIntWidth(IVType);
16132 auto CreateHelperVarAndStmt =
16134 unsigned I,
bool NeedsNewVD =
false) {
16135 Expr *TransformedExpr =
16137 if (!TransformedExpr)
16138 return std::pair<VarDecl *, StmtResult>(
nullptr,
StmtError());
16140 auto Name = (Twine(
".omp.") + BaseName + std::to_string(I)).str();
16145 SemaRef.AddInitializerToDecl(VD, TransformedExpr,
false);
16155 return std::make_pair(VD,
DeclStmt);
16173 llvm::append_range(PreInits, SeqAnalysis.LoopSequencePreInits);
16186 unsigned int TransformIndex = 0;
16187 for (
unsigned I : llvm::seq<unsigned>(FirstVal - 1)) {
16188 if (SeqAnalysis.Loops[I].isLoopTransformation())
16192 for (
unsigned int I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16193 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16195 SeqAnalysis.Loops[I].TheForStmt,
16196 SeqAnalysis.Loops[I].OriginalInits, PreInits);
16197 }
else if (SeqAnalysis.Loops[I].isLoopTransformation()) {
16202 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16203 llvm::append_range(PreInits, TransformPreInit);
16206 SeqAnalysis.Loops[I].TheForStmt,
16207 SeqAnalysis.Loops[I].OriginalInits, PreInits);
16209 auto [UBVD, UBDStmt] =
16210 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.UB,
"ub", J);
16211 auto [LBVD, LBDStmt] =
16212 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.LB,
"lb", J);
16213 auto [STVD, STDStmt] =
16214 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.ST,
"st", J);
16215 auto [NIVD, NIDStmt] = CreateHelperVarAndStmt(
16216 SeqAnalysis.Loops[I].HelperExprs.NumIterations,
"ni", J,
true);
16217 auto [IVVD, IVDStmt] = CreateHelperVarAndStmt(
16218 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef,
"iv", J);
16220 assert(LBVD && STVD && NIVD && IVVD &&
16221 "OpenMP Fuse Helper variables creation failed");
16223 UBVarDecls.push_back(UBVD);
16224 LBVarDecls.push_back(LBVD);
16225 STVarDecls.push_back(STVD);
16226 NIVarDecls.push_back(NIVD);
16227 IVVarDecls.push_back(IVVD);
16229 PreInits.push_back(LBDStmt.get());
16230 PreInits.push_back(STDStmt.get());
16231 PreInits.push_back(NIDStmt.get());
16232 PreInits.push_back(IVDStmt.get());
16265 StringRef IndexName =
".omp.fuse.index";
16270 SemaRef.AddInitializerToDecl(IndexDecl, InitVal,
false);
16277 auto MakeIVRef = [&
SemaRef = this->SemaRef, IndexDecl, IVType,
16295 for (
unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16296 DeclRefExpr *NIRef = MakeVarDeclRef(NIVarDecls[J]);
16304 std::string TempName = (Twine(
".omp.temp.") + Twine(J)).str();
16318 PreInits.push_back(TempStmt.
get());
16327 DeclRefExpr *NIRef2 = MakeVarDeclRef(NIVarDecls[J]);
16341 const std::string MaxName = Twine(
".omp.fuse.max").str();
16349 if (MaxStmt.isInvalid())
16351 PreInits.push_back(MaxStmt.get());
16355 MakeIVRef(), MaxRef);
16381 for (
unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16386 MakeVarDeclRef(STVarDecls[J]), MakeIVRef());
16390 MakeVarDeclRef(LBVarDecls[J]), IdxExpr.
get());
16395 MakeVarDeclRef(IVVarDecls[J]), IdxExpr.
get());
16401 BodyStmts.push_back(IdxExpr.
get());
16402 llvm::append_range(BodyStmts, SeqAnalysis.Loops[I].HelperExprs.Updates);
16405 if (
auto *SourceCXXFor =
16406 dyn_cast<CXXForRangeStmt>(SeqAnalysis.Loops[I].TheForStmt))
16407 BodyStmts.push_back(SourceCXXFor->getLoopVarStmt());
16411 ?
cast<ForStmt>(SeqAnalysis.Loops[I].TheForStmt)->getBody()
16413 BodyStmts.push_back(Body);
16420 MakeVarDeclRef(NIVarDecls[J]));
16430 FusedBodyStmts.push_back(IfStatement);
16436 ForStmt *FusedForStmt =
new (Context)
16450 Stmt *FusionStmt = FusedForStmt;
16451 if (LRC && CountVal != SeqAnalysis.LoopSeqSize) {
16455 TransformIndex = 0;
16461 for (
unsigned I : llvm::seq<unsigned>(SeqAnalysis.LoopSeqSize)) {
16462 if (I >= FirstVal - 1 && I < FirstVal + CountVal - 1) {
16465 if (!SeqAnalysis.Loops[I].isLoopTransformation())
16474 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16475 const auto &TransformPreInit =
16476 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16477 if (!TransformPreInit.empty())
16478 llvm::append_range(PreInits, TransformPreInit);
16481 FinalLoops.push_back(SeqAnalysis.Loops[I].TheForStmt);
16484 FinalLoops.insert(FinalLoops.begin() + (FirstVal - 1), FusedForStmt);
16489 NumGeneratedTopLevelLoops, AStmt, FusionStmt,
16509 case OMPC_allocator:
16512 case OMPC_collapse:
16521 case OMPC_priority:
16533 case OMPC_novariants:
16536 case OMPC_nocontext:
16551 case OMPC_ompx_dyn_cgroup_mem:
16557 case OMPC_dyn_groupprivate:
16558 case OMPC_grainsize:
16559 case OMPC_num_tasks:
16560 case OMPC_num_threads:
16564 case OMPC_proc_bind:
16565 case OMPC_schedule:
16567 case OMPC_firstprivate:
16568 case OMPC_lastprivate:
16570 case OMPC_reduction:
16571 case OMPC_task_reduction:
16572 case OMPC_in_reduction:
16576 case OMPC_copyprivate:
16578 case OMPC_mergeable:
16579 case OMPC_threadprivate:
16580 case OMPC_groupprivate:
16582 case OMPC_allocate:
16599 case OMPC_dist_schedule:
16600 case OMPC_defaultmap:
16605 case OMPC_use_device_ptr:
16606 case OMPC_use_device_addr:
16607 case OMPC_is_device_ptr:
16608 case OMPC_unified_address:
16609 case OMPC_unified_shared_memory:
16610 case OMPC_reverse_offload:
16611 case OMPC_dynamic_allocators:
16612 case OMPC_atomic_default_mem_order:
16613 case OMPC_self_maps:
16614 case OMPC_device_type:
16616 case OMPC_nontemporal:
16619 case OMPC_severity:
16621 case OMPC_inclusive:
16622 case OMPC_exclusive:
16623 case OMPC_uses_allocators:
16624 case OMPC_affinity:
16627 case OMPC_num_teams:
16628 case OMPC_thread_limit:
16630 llvm_unreachable(
"Clause is not allowed.");
16643 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
16644 "Invalid directive with CKind-clause");
16647 if (NameModifier != OMPD_unknown &&
16648 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
16649 return OMPD_unknown;
16668 case OMPD_teams_loop:
16669 case OMPD_target_teams_loop:
16673 case OMPD_target_update:
16674 case OMPD_target_enter_data:
16675 case OMPD_target_exit_data:
16681 case OMPC_num_teams:
16682 case OMPC_thread_limit:
16683 case OMPC_ompx_dyn_cgroup_mem:
16684 case OMPC_dyn_groupprivate:
16686 if (Leafs[0] == OMPD_target)
16687 return OMPD_target;
16690 if (Leafs[0] == OMPD_target ||
16691 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
16692 OMPD_target_enter_data, OMPD_target_exit_data},
16696 case OMPC_novariants:
16697 case OMPC_nocontext:
16698 if (DKind == OMPD_dispatch)
16702 if (DKind == OMPD_metadirective)
16703 return OMPD_metadirective;
16706 return OMPD_unknown;
16719 int InnermostIdx = [&]() {
16720 for (
int I = EndIdx - 1; I >= 0; --I) {
16721 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
16729 for (
int I = InnermostIdx - 1; I >= 0; --I) {
16734 if (Regions[0] != OMPD_unknown)
16735 return Regions.back();
16737 return OMPD_unknown;
16742 for (
int I = 0, E = Leafs.size(); I != E; ++I) {
16743 if (Leafs[I] == Dir)
16749 int End = NameModifier == OMPD_unknown ? Leafs.size()
16750 : GetLeafIndex(NameModifier);
16751 return GetEnclosingRegion(End, CKind);
16754 return OMPD_unknown;
16762 Stmt *HelperValStmt =
nullptr;
16765 !
Condition->isInstantiationDependent() &&
16766 !
Condition->containsUnexpandedParameterPack()) {
16771 ValExpr = Val.
get();
16775 DKind, OMPC_if,
getLangOpts().OpenMP, NameModifier);
16776 if (CaptureRegion != OMPD_unknown &&
16777 !
SemaRef.CurContext->isDependentContext()) {
16778 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
16779 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16780 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16786 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
16787 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
16795 Stmt *HelperValStmt =
nullptr;
16798 !
Condition->isInstantiationDependent() &&
16799 !
Condition->containsUnexpandedParameterPack()) {
16804 ValExpr =
SemaRef.MakeFullExpr(Val.
get()).get();
16809 if (CaptureRegion != OMPD_unknown &&
16810 !
SemaRef.CurContext->isDependentContext()) {
16811 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
16812 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16813 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16819 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16830 IntConvertDiagnoser()
16831 : ICEConvertDiagnoser(
false,
false,
true) {}
16834 return S.
Diag(Loc, diag::err_omp_not_integral) <<
T;
16838 return S.
Diag(Loc, diag::err_omp_incomplete_type) <<
T;
16843 return S.
Diag(Loc, diag::err_omp_explicit_conversion) <<
T << ConvTy;
16852 return S.
Diag(Loc, diag::err_omp_ambiguous_conversion) <<
T;
16861 llvm_unreachable(
"conversion functions are permitted");
16863 } ConvertDiagnoser;
16864 return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
16869 bool StrictlyPositive,
bool BuildCapture =
false,
16872 Stmt **HelperValStmt =
nullptr) {
16878 if (
Value.isInvalid())
16881 ValExpr =
Value.get();
16883 if (std::optional<llvm::APSInt> Result =
16885 if (Result->isSigned() &&
16886 !((!StrictlyPositive && Result->isNonNegative()) ||
16887 (StrictlyPositive && Result->isStrictlyPositive()))) {
16888 SemaRef.
Diag(Loc, diag::err_omp_negative_expression_in_clause)
16898 if (*CaptureRegion != OMPD_unknown &&
16901 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16902 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16913 llvm::raw_svector_ostream
Out(Buffer);
16914 unsigned Skipped = Exclude.size();
16915 for (
unsigned I =
First; I <
Last; ++I) {
16916 if (llvm::is_contained(Exclude, I)) {
16921 if (I + Skipped + 2 ==
Last)
16923 else if (I + Skipped + 1 !=
Last)
16926 return std::string(
Out.str());
16934 "Unexpected num_threads modifier in OpenMP < 60.");
16939 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
16944 Expr *ValExpr = NumThreads;
16945 Stmt *HelperValStmt =
nullptr;
16956 if (CaptureRegion != OMPD_unknown &&
16957 !
SemaRef.CurContext->isDependentContext()) {
16958 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
16959 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16960 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16966 StartLoc, LParenLoc, ModifierLoc, EndLoc);
16971 bool SuppressExprDiags) {
16980 if (SuppressExprDiags) {
16984 SuppressedDiagnoser() : VerifyICEDiagnoser(
true) {}
16987 llvm_unreachable(
"Diagnostic suppressed");
16990 ICE =
SemaRef.VerifyIntegerConstantExpression(E, &
Result, Diagnoser,
17000 if ((StrictlyPositive && !
Result.isStrictlyPositive()) ||
17001 (!StrictlyPositive && !
Result.isNonNegative())) {
17002 Diag(E->
getExprLoc(), diag::err_omp_negative_expression_in_clause)
17007 if ((CKind == OMPC_aligned || CKind == OMPC_align ||
17008 CKind == OMPC_allocate) &&
17010 Diag(E->
getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
17015 if (!
Result.isRepresentableByInt64()) {
17021 if (CKind == OMPC_collapse &&
DSAStack->getAssociatedLoops() == 1)
17023 else if (CKind == OMPC_ordered)
17042 if (
Result.isNonNegative()) {
17046 diag::err_omp_negative_expression_in_clause)
17049 }
else if (
auto *DeclRef = dyn_cast<DeclRefExpr>(DeviceNumExpr)) {
17056 Diag(DeviceNumExpr->
getExprLoc(), diag::err_expected_expression);
17090 DSAStackTy *Stack) {
17091 if (!Stack->getOMPAllocatorHandleT().isNull())
17098 S.
Diag(Loc, diag::err_omp_implied_type_not_found)
17099 <<
"omp_allocator_handle_t";
17104 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
17107 bool ErrorFound =
false;
17108 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
17109 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
17110 StringRef Allocator =
17111 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
17113 auto *VD = dyn_cast_or_null<ValueDecl>(
17133 Stack->setAllocator(AllocatorKind, Res.
get());
17136 S.
Diag(Loc, diag::err_omp_implied_type_not_found)
17137 <<
"omp_allocator_handle_t";
17156 Allocator =
SemaRef.PerformImplicitConversion(
17157 Allocator.
get(),
DSAStack->getOMPAllocatorHandleT(),
17186 Expr *NumForLoops) {
17192 if (NumForLoops && LParenLoc.
isValid()) {
17197 NumForLoops = NumForLoopsResult.
get();
17199 NumForLoops =
nullptr;
17203 NumForLoops ?
DSAStack->getAssociatedLoops() : 0,
17204 StartLoc, LParenLoc, EndLoc);
17205 DSAStack->setOrderedRegion(
true, NumForLoops, Clause);
17214 case OMPC_proc_bind:
17216 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17218 case OMPC_atomic_default_mem_order:
17221 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17225 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17229 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17233 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17237 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17239 case OMPC_severity:
17242 LParenLoc, EndLoc);
17244 case OMPC_threadset:
17246 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17250 case OMPC_num_threads:
17254 case OMPC_allocator:
17255 case OMPC_collapse:
17256 case OMPC_schedule:
17258 case OMPC_firstprivate:
17259 case OMPC_lastprivate:
17261 case OMPC_reduction:
17262 case OMPC_task_reduction:
17263 case OMPC_in_reduction:
17267 case OMPC_copyprivate:
17271 case OMPC_mergeable:
17272 case OMPC_threadprivate:
17273 case OMPC_groupprivate:
17274 case OMPC_allocate:
17291 case OMPC_num_teams:
17292 case OMPC_thread_limit:
17293 case OMPC_priority:
17294 case OMPC_grainsize:
17296 case OMPC_num_tasks:
17298 case OMPC_dist_schedule:
17300 case OMPC_defaultmap:
17305 case OMPC_use_device_ptr:
17306 case OMPC_use_device_addr:
17307 case OMPC_is_device_ptr:
17308 case OMPC_has_device_addr:
17309 case OMPC_unified_address:
17310 case OMPC_unified_shared_memory:
17311 case OMPC_reverse_offload:
17312 case OMPC_dynamic_allocators:
17313 case OMPC_self_maps:
17314 case OMPC_device_type:
17316 case OMPC_nontemporal:
17318 case OMPC_novariants:
17319 case OMPC_nocontext:
17321 case OMPC_inclusive:
17322 case OMPC_exclusive:
17323 case OMPC_uses_allocators:
17324 case OMPC_affinity:
17328 llvm_unreachable(
"Clause is not allowed.");
17337 if (M == OMP_DEFAULT_unknown) {
17338 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17340 unsigned(OMP_DEFAULT_unknown))
17345 Diag(VCKindLoc, diag::err_omp_default_vc)
17350 bool IsTargetDefault =
17357 if (IsTargetDefault && M == OMP_DEFAULT_shared)
17360 auto SetDefaultClauseAttrs = [&](llvm::omp::DefaultKind M,
17366 case OMP_DEFAULT_none:
17367 if (IsTargetDefault)
17368 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_none;
17370 DSAStack->setDefaultDSANone(MLoc);
17372 case OMP_DEFAULT_firstprivate:
17373 if (IsTargetDefault)
17374 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_firstprivate;
17376 DSAStack->setDefaultDSAFirstPrivate(MLoc);
17378 case OMP_DEFAULT_private:
17379 if (IsTargetDefault)
17380 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_private;
17382 DSAStack->setDefaultDSAPrivate(MLoc);
17384 case OMP_DEFAULT_shared:
17385 assert(!IsTargetDefault &&
"DSA shared invalid with target directive");
17386 DSAStack->setDefaultDSAShared(MLoc);
17389 llvm_unreachable(
"unexpected DSA in OpenMP default clause");
17393 case OMPC_DEFAULT_VC_aggregate:
17394 if (IsTargetDefault)
17395 DefMapKind = OMPC_DEFAULTMAP_aggregate;
17397 DSAStack->setDefaultDSAVCAggregate(VCKindLoc);
17399 case OMPC_DEFAULT_VC_pointer:
17400 if (IsTargetDefault)
17401 DefMapKind = OMPC_DEFAULTMAP_pointer;
17403 DSAStack->setDefaultDSAVCPointer(VCKindLoc);
17405 case OMPC_DEFAULT_VC_scalar:
17406 if (IsTargetDefault)
17407 DefMapKind = OMPC_DEFAULTMAP_scalar;
17409 DSAStack->setDefaultDSAVCScalar(VCKindLoc);
17411 case OMPC_DEFAULT_VC_all:
17412 if (IsTargetDefault)
17413 DefMapKind = OMPC_DEFAULTMAP_all;
17415 DSAStack->setDefaultDSAVCAll(VCKindLoc);
17418 llvm_unreachable(
"unexpected variable category in OpenMP default clause");
17427 if (IsTargetDefault) {
17428 if (DefMapKind == OMPC_DEFAULTMAP_all) {
17429 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_aggregate, MLoc);
17430 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_scalar, MLoc);
17431 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_pointer, MLoc);
17433 DSAStack->setDefaultDMAAttr(DefMapMod, DefMapKind, MLoc);
17438 SetDefaultClauseAttrs(M, VCKind);
17440 OMPDefaultClause(M, MLoc, VCKind, VCKindLoc, StartLoc, LParenLoc, EndLoc);
17449 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17452 << getOpenMPClauseName(OMPC_threadset);
17465 if (Kind == OMP_PROC_BIND_unknown) {
17466 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17468 unsigned(OMP_PROC_BIND_master),
17471 ? OMP_PROC_BIND_primary
17472 : OMP_PROC_BIND_spread) +
17477 if (Kind == OMP_PROC_BIND_primary &&
getLangOpts().OpenMP < 51)
17478 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17480 unsigned(OMP_PROC_BIND_master),
17482 unsigned(OMP_PROC_BIND_spread) + 1)
17492 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17494 OMPC_atomic_default_mem_order, 0,
17500 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17509 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17516 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17525 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17539 assert(ME &&
"NULL expr in Message clause");
17548 Stmt *HelperValStmt =
nullptr;
17554 DKind == OMPD_unknown ? OMPD_unknown
17557 if (CaptureRegion != OMPD_unknown &&
17558 !
SemaRef.CurContext->isDependentContext()) {
17559 ME =
SemaRef.MakeFullExpr(ME).get();
17560 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17561 ME = tryBuildCapture(
SemaRef, ME, Captures).get();
17566 ME =
SemaRef.DefaultFunctionArrayLvalueConversion(ME).get();
17569 ME, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17576 if (Kind != OMPC_ORDER_concurrent ||
17581 "OMPC_ORDER_unknown not greater than 0");
17583 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17592 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17598 DSAStack->setRegionHasOrderConcurrent(
true);
17601 unsigned existingFlags =
DSAStack->getCurScope()->getFlags();
17602 DSAStack->getCurScope()->setFlags(existingFlags |
17607 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
17616 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
17618 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
17619 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
17621 Except.push_back(OMPC_DEPEND_inoutset);
17622 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17629 KindKwLoc, Kind, EndLoc);
17638 for (
Expr *&SizeExpr : SanitizedSizeExprs) {
17648 QualType SizeTy = SizeExpr->getType();
17677 if (!SizeExpr->isInstantiationDependent() && !IsValid)
17678 SizeExpr =
nullptr;
17682 SanitizedSizeExprs);
17689 size_t NumLoops = PermExprs.size();
17691 llvm::append_range(SanitizedPermExprs, PermExprs);
17693 for (
Expr *&PermExpr : SanitizedPermExprs) {
17696 if (!PermExpr || PermExpr->isInstantiationDependent())
17699 llvm::APSInt PermVal;
17702 bool IsValid = PermEvalExpr.
isUsable();
17704 PermExpr = PermEvalExpr.
get();
17706 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
17710 diag::err_omp_interchange_permutation_value_range)
17711 << NumLoops << ExprRange;
17715 if (!PermExpr->isInstantiationDependent() && !IsValid)
17716 PermExpr =
nullptr;
17720 EndLoc, SanitizedPermExprs);
17736 FactorExpr, OMPC_partial,
true);
17739 FactorExpr = FactorResult.
get();
17768 FirstLoc, CountLoc, EndLoc,
First, Count);
17779 LParenLoc, EndLoc);
17789 case OMPC_schedule: {
17790 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
17791 assert(Argument.size() == NumberOfElements &&
17792 ArgumentLoc.size() == NumberOfElements);
17797 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
17798 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
17802 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17804 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
17807 case OMPC_dist_schedule:
17810 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
17813 enum { DefaultModifier, DefaultVarCategory };
17815 static_cast<llvm::omp::DefaultKind
>(Argument[DefaultModifier]),
17816 ArgumentLoc[DefaultModifier],
17818 Argument[DefaultVarCategory]),
17819 ArgumentLoc[DefaultVarCategory], StartLoc, LParenLoc, EndLoc);
17821 case OMPC_defaultmap:
17822 enum { Modifier, DefaultmapKind };
17826 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
17830 enum { OrderModifier, OrderKind };
17834 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
17837 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17840 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17842 case OMPC_grainsize:
17843 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17844 "Modifier for grainsize clause and its location are expected.");
17847 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17849 case OMPC_num_tasks:
17850 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17851 "Modifier for num_tasks clause and its location are expected.");
17854 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17856 case OMPC_dyn_groupprivate: {
17857 enum { Modifier1, Modifier2, NumberOfElements };
17858 assert(Argument.size() == NumberOfElements &&
17859 ArgumentLoc.size() == NumberOfElements &&
17860 "Modifiers for dyn_groupprivate clause and their locations are "
17865 Argument[Modifier2]),
17866 Expr, StartLoc, LParenLoc, ArgumentLoc[Modifier1],
17867 ArgumentLoc[Modifier2], EndLoc);
17870 case OMPC_num_threads:
17871 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17872 "Modifier for num_threads clause and its location are expected.");
17875 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17881 case OMPC_allocator:
17882 case OMPC_collapse:
17883 case OMPC_proc_bind:
17885 case OMPC_firstprivate:
17886 case OMPC_lastprivate:
17888 case OMPC_reduction:
17889 case OMPC_task_reduction:
17890 case OMPC_in_reduction:
17894 case OMPC_copyprivate:
17898 case OMPC_mergeable:
17899 case OMPC_threadprivate:
17900 case OMPC_groupprivate:
17901 case OMPC_allocate:
17918 case OMPC_num_teams:
17919 case OMPC_thread_limit:
17920 case OMPC_priority:
17927 case OMPC_use_device_ptr:
17928 case OMPC_use_device_addr:
17929 case OMPC_is_device_ptr:
17930 case OMPC_has_device_addr:
17931 case OMPC_unified_address:
17932 case OMPC_unified_shared_memory:
17933 case OMPC_reverse_offload:
17934 case OMPC_dynamic_allocators:
17935 case OMPC_atomic_default_mem_order:
17936 case OMPC_self_maps:
17937 case OMPC_device_type:
17939 case OMPC_nontemporal:
17941 case OMPC_severity:
17944 case OMPC_novariants:
17945 case OMPC_nocontext:
17947 case OMPC_inclusive:
17948 case OMPC_exclusive:
17949 case OMPC_uses_allocators:
17950 case OMPC_affinity:
17954 llvm_unreachable(
"Clause is not allowed.");
17965 Excluded.push_back(M2);
17966 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
17967 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
17968 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
17969 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
17970 S.
Diag(M1Loc, diag::err_omp_unexpected_clause_value)
17993 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
17994 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
17995 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
17996 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
17997 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
18003 std::string Values;
18013 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
18022 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
18023 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
18024 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
18025 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
18026 diag::err_omp_schedule_nonmonotonic_static);
18029 Expr *ValExpr = ChunkSize;
18030 Stmt *HelperValStmt =
nullptr;
18041 ValExpr = Val.
get();
18046 if (std::optional<llvm::APSInt>
Result =
18048 if (
Result->isSigned() && !
Result->isStrictlyPositive()) {
18049 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
18054 DSAStack->getCurrentDirective(), OMPC_schedule,
18056 !
SemaRef.CurContext->isDependentContext()) {
18057 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
18058 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18059 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
18067 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
18086 case OMPC_mergeable:
18134 case OMPC_unified_address:
18137 case OMPC_unified_shared_memory:
18140 case OMPC_reverse_offload:
18143 case OMPC_dynamic_allocators:
18146 case OMPC_self_maps:
18160 case OMPC_ompx_bare:
18165 case OMPC_num_threads:
18169 case OMPC_allocator:
18170 case OMPC_collapse:
18171 case OMPC_schedule:
18173 case OMPC_firstprivate:
18174 case OMPC_lastprivate:
18176 case OMPC_reduction:
18177 case OMPC_task_reduction:
18178 case OMPC_in_reduction:
18182 case OMPC_copyprivate:
18184 case OMPC_proc_bind:
18185 case OMPC_threadprivate:
18186 case OMPC_groupprivate:
18187 case OMPC_allocate:
18193 case OMPC_num_teams:
18194 case OMPC_thread_limit:
18195 case OMPC_priority:
18196 case OMPC_grainsize:
18197 case OMPC_num_tasks:
18199 case OMPC_dist_schedule:
18200 case OMPC_defaultmap:
18205 case OMPC_use_device_ptr:
18206 case OMPC_use_device_addr:
18207 case OMPC_is_device_ptr:
18208 case OMPC_has_device_addr:
18209 case OMPC_atomic_default_mem_order:
18210 case OMPC_device_type:
18212 case OMPC_nontemporal:
18215 case OMPC_severity:
18217 case OMPC_novariants:
18218 case OMPC_nocontext:
18220 case OMPC_inclusive:
18221 case OMPC_exclusive:
18222 case OMPC_uses_allocators:
18223 case OMPC_affinity:
18225 case OMPC_ompx_dyn_cgroup_mem:
18226 case OMPC_dyn_groupprivate:
18228 llvm_unreachable(
"Clause is not allowed.");
18240 !
Condition->isInstantiationDependent() &&
18241 !
Condition->containsUnexpandedParameterPack()) {
18246 ValExpr = Val.
get();
18302 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
18388 if (!
hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
18390 StringRef
Expected =
"'init', 'use', 'destroy', or 'nowait'";
18391 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
18392 <<
Expected << getOpenMPDirectiveName(OMPD_interop, OMPVersion);
18405 bool HasInitClause =
false;
18406 bool IsTargetSync =
false;
18410 if (
const auto *InitClause = dyn_cast<OMPInitClause>(
C)) {
18411 HasInitClause =
true;
18412 if (InitClause->getIsTargetSync())
18413 IsTargetSync =
true;
18414 }
else if (
const auto *DC = dyn_cast<OMPDependClause>(
C)) {
18418 if (DependClause && HasInitClause && !IsTargetSync) {
18419 Diag(DependClause->
getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
18433 if (ClauseKind == OMPC_init) {
18436 }
else if (ClauseKind == OMPC_use) {
18439 }
else if (ClauseKind == OMPC_destroy) {
18445 if (!InteropVars.insert(
DeclResult.first).second) {
18446 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
18462 Expr *RefExpr = InteropVarExpr;
18477 bool HasError =
false;
18483 if (
const auto *TD = dyn_cast<TypeDecl>(ND)) {
18484 InteropType =
QualType(TD->getTypeForDecl(), 0);
18493 SemaRef.
Diag(VarLoc, diag::err_omp_implied_type_not_found)
18494 <<
"omp_interop_t";
18500 SemaRef.
Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
18506 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
18508 SemaRef.
Diag(VarLoc, diag::err_omp_interop_variable_expected)
18537 StartLoc, LParenLoc, VarLoc, EndLoc);
18550 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
18559 DSAStack->getCurrentDirective() == OMPD_depobj) {
18561 Diag(StartLoc, diag::err_omp_expected_clause_argument)
18563 << getOpenMPDirectiveName(OMPD_depobj, OMPVersion);
18579 Stmt *HelperValStmt =
nullptr;
18582 !
Condition->isInstantiationDependent() &&
18583 !
Condition->containsUnexpandedParameterPack()) {
18588 ValExpr =
SemaRef.MakeFullExpr(Val.
get()).get();
18593 if (CaptureRegion != OMPD_unknown &&
18594 !
SemaRef.CurContext->isDependentContext()) {
18595 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
18596 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18597 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
18603 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18611 Stmt *HelperValStmt =
nullptr;
18614 !
Condition->isInstantiationDependent() &&
18615 !
Condition->containsUnexpandedParameterPack()) {
18620 ValExpr =
SemaRef.MakeFullExpr(Val.
get()).get();
18625 if (CaptureRegion != OMPD_unknown &&
18626 !
SemaRef.CurContext->isDependentContext()) {
18627 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
18628 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18629 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
18635 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18642 Expr *ValExpr = ThreadID;
18643 Stmt *HelperValStmt =
nullptr;
18648 if (CaptureRegion != OMPD_unknown &&
18649 !
SemaRef.CurContext->isDependentContext()) {
18650 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
18651 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18652 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
18657 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18668 int ExtraModifier =
Data.ExtraModifier;
18669 int OriginalSharingModifier =
Data.OriginalSharingModifier;
18676 case OMPC_firstprivate:
18679 case OMPC_lastprivate:
18681 "Unexpected lastprivate modifier.");
18684 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
18689 case OMPC_reduction:
18691 "Unexpected lastprivate modifier.");
18695 ExtraModifier, OriginalSharingModifier),
18696 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
18697 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
18699 case OMPC_task_reduction:
18701 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18702 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
18704 case OMPC_in_reduction:
18706 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18707 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
18711 "Unexpected linear modifier.");
18713 VarList,
Data.DepModOrTailExpr, StartLoc, LParenLoc,
18715 ColonLoc,
Data.StepModifierLoc, EndLoc);
18719 LParenLoc, ColonLoc, EndLoc);
18724 case OMPC_copyprivate:
18732 "Unexpected depend modifier.");
18735 ColonLoc,
Data.OmpAllMemoryLoc},
18736 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
18740 "Unexpected map modifier.");
18742 Data.IteratorExpr,
Data.MapTypeModifiers,
Data.MapTypeModifiersLoc,
18743 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId,
18745 ExtraModifierLoc, ColonLoc, VarList, Locs);
18749 Data.MotionModifiers,
Data.MotionModifiersLoc,
Data.IteratorExpr,
18750 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId, ColonLoc,
18755 Data.MotionModifiers,
Data.MotionModifiersLoc,
Data.IteratorExpr,
18756 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId, ColonLoc,
18759 case OMPC_use_device_ptr:
18762 case OMPC_use_device_addr:
18765 case OMPC_is_device_ptr:
18768 case OMPC_has_device_addr:
18771 case OMPC_allocate: {
18775 if (!
Data.AllocClauseModifiers.empty()) {
18776 assert(
Data.AllocClauseModifiers.size() <= 2 &&
18777 "More allocate modifiers than expected");
18778 Modifier1 =
Data.AllocClauseModifiers[0];
18779 Modifier1Loc =
Data.AllocClauseModifiersLoc[0];
18780 if (
Data.AllocClauseModifiers.size() == 2) {
18781 Modifier2 =
Data.AllocClauseModifiers[1];
18782 Modifier2Loc =
Data.AllocClauseModifiersLoc[1];
18786 Data.DepModOrTailExpr,
Data.AllocateAlignment, Modifier1, Modifier1Loc,
18787 Modifier2, Modifier2Loc, VarList, StartLoc, LParenLoc, ColonLoc,
18791 case OMPC_nontemporal:
18794 case OMPC_inclusive:
18797 case OMPC_exclusive:
18800 case OMPC_affinity:
18802 Data.DepModOrTailExpr, VarList);
18804 case OMPC_doacross:
18807 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
18809 case OMPC_num_teams:
18812 case OMPC_thread_limit:
18818 case OMPC_num_threads:
18822 case OMPC_allocator:
18823 case OMPC_collapse:
18825 case OMPC_proc_bind:
18826 case OMPC_schedule:
18830 case OMPC_mergeable:
18831 case OMPC_threadprivate:
18832 case OMPC_groupprivate:
18846 case OMPC_priority:
18847 case OMPC_grainsize:
18849 case OMPC_num_tasks:
18851 case OMPC_dist_schedule:
18852 case OMPC_defaultmap:
18855 case OMPC_unified_address:
18856 case OMPC_unified_shared_memory:
18857 case OMPC_reverse_offload:
18858 case OMPC_dynamic_allocators:
18859 case OMPC_atomic_default_mem_order:
18860 case OMPC_self_maps:
18861 case OMPC_device_type:
18865 case OMPC_severity:
18868 case OMPC_novariants:
18869 case OMPC_nocontext:
18871 case OMPC_uses_allocators:
18875 llvm_unreachable(
"Clause is not allowed.");
18888 Res =
SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.
get());
18893 Res =
SemaRef.DefaultLvalueConversion(Res.
get());
18907 bool IsImplicitClause =
18909 for (
Expr *RefExpr : VarList) {
18910 assert(RefExpr &&
"NULL expr in OpenMP private clause.");
18913 Expr *SimpleRefExpr = RefExpr;
18917 Vars.push_back(RefExpr);
18918 PrivateCopies.push_back(
nullptr);
18925 auto *VD = dyn_cast<VarDecl>(D);
18931 diag::err_omp_private_incomplete_type))
18933 Type =
Type.getNonReferenceType();
18953 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
18954 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
18955 Diag(ELoc, diag::err_omp_wrong_dsa)
18966 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18968 << getOpenMPDirectiveName(CurrDir, OMPVersion);
18969 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
18972 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18987 CurrDir == OMPD_target) {
18989 if (
DSAStack->checkMappableExprComponentListsForDecl(
18993 ConflictKind = WhereFoundClauseKind;
18996 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18999 << getOpenMPDirectiveName(CurrDir, OMPVersion);
19019 SemaRef.ActOnUninitializedDecl(VDPrivate);
19026 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
19027 auto *FD = dyn_cast<FieldDecl>(D);
19031 RefExpr->getExprLoc());
19035 if (!IsImplicitClause)
19036 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
19037 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
19038 ? RefExpr->IgnoreParens()
19040 PrivateCopies.push_back(VDPrivateRefExpr);
19047 Vars, PrivateCopies);
19058 bool IsImplicitClause =
19063 for (
Expr *RefExpr : VarList) {
19064 assert(RefExpr &&
"NULL expr in OpenMP firstprivate clause.");
19067 Expr *SimpleRefExpr = RefExpr;
19071 Vars.push_back(RefExpr);
19072 PrivateCopies.push_back(
nullptr);
19073 Inits.push_back(
nullptr);
19079 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
19081 auto *VD = dyn_cast<VarDecl>(D);
19087 diag::err_omp_firstprivate_incomplete_type))
19089 Type =
Type.getNonReferenceType();
19099 DSAStackTy::DSAVarData TopDVar;
19100 if (!IsImplicitClause) {
19101 DSAStackTy::DSAVarData DVar =
19113 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
19115 DVar.CKind != OMPC_lastprivate) &&
19117 Diag(ELoc, diag::err_omp_wrong_dsa)
19135 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
19136 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
19137 Diag(ELoc, diag::err_omp_wrong_dsa)
19163 DVar =
DSAStack->getImplicitDSA(D,
true);
19164 if (DVar.CKind != OMPC_shared &&
19167 DVar.DKind == OMPD_unknown)) {
19168 Diag(ELoc, diag::err_omp_required_access)
19190 return C == OMPC_reduction && !AppliedToPointee;
19198 if (DVar.CKind == OMPC_reduction &&
19202 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
19203 << getOpenMPDirectiveName(DVar.DKind, OMPVersion);
19219 CurrDir == OMPD_target) {
19221 if (
DSAStack->checkMappableExprComponentListsForDecl(
19226 ConflictKind = WhereFoundClauseKind;
19229 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
19232 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
19243 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19245 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
19247 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19250 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19265 Expr *VDInitRefExpr =
nullptr;
19275 ElemType,
".firstprivate.temp");
19290 ".firstprivate.temp");
19292 RefExpr->getExprLoc());
19293 SemaRef.AddInitializerToDecl(
19294 VDPrivate,
SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
19298 if (IsImplicitClause) {
19299 Diag(RefExpr->getExprLoc(),
19300 diag::note_omp_task_predetermined_firstprivate_here);
19304 SemaRef.CurContext->addDecl(VDPrivate);
19307 RefExpr->getExprLoc());
19309 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
19310 if (TopDVar.CKind == OMPC_lastprivate) {
19311 Ref = TopDVar.PrivateCopy;
19313 auto *FD = dyn_cast<FieldDecl>(D);
19318 RefExpr->getExprLoc());
19322 ExprCaptures.push_back(Ref->
getDecl());
19325 if (!IsImplicitClause)
19326 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
19327 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
19328 ? RefExpr->IgnoreParens()
19330 PrivateCopies.push_back(VDPrivateRefExpr);
19331 Inits.push_back(VDInitRefExpr);
19338 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
19347 assert(ColonLoc.
isValid() &&
"Colon location must be valid.");
19348 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
19361 for (
Expr *RefExpr : VarList) {
19362 assert(RefExpr &&
"NULL expr in OpenMP lastprivate clause.");
19365 Expr *SimpleRefExpr = RefExpr;
19369 Vars.push_back(RefExpr);
19370 SrcExprs.push_back(
nullptr);
19371 DstExprs.push_back(
nullptr);
19372 AssignmentOps.push_back(
nullptr);
19379 auto *VD = dyn_cast<VarDecl>(D);
19385 diag::err_omp_lastprivate_incomplete_type))
19387 Type =
Type.getNonReferenceType();
19404 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
19405 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19408 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19422 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
19423 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
19425 DVar.CKind != OMPC_firstprivate) &&
19426 (DVar.CKind != OMPC_private || DVar.RefExpr !=
nullptr)) {
19427 Diag(ELoc, diag::err_omp_wrong_dsa)
19440 DSAStackTy::DSAVarData TopDVar = DVar;
19444 DVar =
DSAStack->getImplicitDSA(D,
true);
19445 if (DVar.CKind != OMPC_shared) {
19446 Diag(ELoc, diag::err_omp_required_access)
19464 Type.getUnqualifiedType(),
".lastprivate.src",
19475 PseudoDstExpr, PseudoSrcExpr);
19478 AssignmentOp =
SemaRef.ActOnFinishFullExpr(AssignmentOp.
get(), ELoc,
19484 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
19485 if (TopDVar.CKind == OMPC_firstprivate) {
19486 Ref = TopDVar.PrivateCopy;
19490 ExprCaptures.push_back(Ref->
getDecl());
19492 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
19500 SimpleRefExpr, RefRes.
get());
19503 ExprPostUpdates.push_back(
19504 SemaRef.IgnoredValueConversions(PostUpdateRes.
get()).get());
19507 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
19508 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
19509 ? RefExpr->IgnoreParens()
19511 SrcExprs.push_back(PseudoSrcExpr);
19512 DstExprs.push_back(PseudoDstExpr);
19513 AssignmentOps.push_back(AssignmentOp.
get());
19520 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
19521 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
19531 for (
Expr *RefExpr : VarList) {
19532 assert(RefExpr &&
"NULL expr in OpenMP shared clause.");
19535 Expr *SimpleRefExpr = RefExpr;
19539 Vars.push_back(RefExpr);
19545 auto *VD = dyn_cast<VarDecl>(D);
19553 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
19554 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
19556 Diag(ELoc, diag::err_omp_wrong_dsa)
19565 !
SemaRef.CurContext->isDependentContext())
19567 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
19568 Vars.push_back((VD || !Ref ||
SemaRef.CurContext->isDependentContext())
19569 ? RefExpr->IgnoreParens()
19581class DSARefChecker :
public StmtVisitor<DSARefChecker, bool> {
19586 if (
auto *VD = dyn_cast<VarDecl>(E->
getDecl())) {
19587 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD,
false);
19588 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
19590 if (DVar.CKind != OMPC_unknown)
19592 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
19599 return DVarPrivate.CKind != OMPC_unknown;
19603 bool VisitStmt(Stmt *S) {
19604 for (Stmt *Child : S->
children()) {
19605 if (Child && Visit(Child))
19610 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
19617class TransformExprToCaptures :
public TreeTransform<TransformExprToCaptures> {
19618 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
19619 ValueDecl *
Field =
nullptr;
19620 DeclRefExpr *CapturedExpr =
nullptr;
19623 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
19624 : BaseTransform(SemaRef),
Field(FieldDecl), CapturedExpr(
nullptr) {}
19626 ExprResult TransformMemberExpr(MemberExpr *E) {
19629 CapturedExpr =
buildCapture(SemaRef, Field, E,
false);
19630 return CapturedExpr;
19632 return BaseTransform::TransformMemberExpr(E);
19634 DeclRefExpr *getCapturedExpr() {
return CapturedExpr; }
19638template <
typename T,
typename U>
19641 for (
U &
Set : Lookups) {
19642 for (
auto *D :
Set) {
19653 for (
auto *RD : D->
redecls()) {
19676 AssociatedClasses);
19689 for (
auto *NS : AssociatedNamespaces) {
19702 for (
auto *D : R) {
19703 auto *Underlying = D;
19704 if (
auto *USD = dyn_cast<UsingShadowDecl>(D))
19705 Underlying = USD->getTargetDecl();
19715 if (
auto *USD = dyn_cast<UsingShadowDecl>(D))
19716 Underlying = USD->getTargetDecl();
19718 Lookups.emplace_back();
19719 Lookups.back().addDecl(Underlying);
19743 Lookups.emplace_back();
19744 Lookups.back().append(Lookup.
begin(), Lookup.
end());
19747 }
else if (
auto *ULE =
19748 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
19750 Decl *PrevD =
nullptr;
19754 else if (
auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
19755 Lookups.back().addDecl(DRD);
19763 return !D->isInvalidDecl() &&
19764 (D->getType()->isDependentType() ||
19765 D->getType()->isInstantiationDependentType() ||
19766 D->getType()->containsUnexpandedParameterPack());
19779 true, ResSet.
begin(), ResSet.
end(),
false,
19802 if (IsComplete || RD->isBeingDefined()) {
19805 if (Lookup.
empty()) {
19806 Lookups.emplace_back();
19807 Lookups.back().append(Lookup.
begin(), Lookup.
end());
19849 if (ReductionIdScopeSpec.
isSet()) {
19850 SemaRef.
Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
19859struct ReductionData {
19861 SmallVector<Expr *, 8> Vars;
19863 SmallVector<Expr *, 8> Privates;
19865 SmallVector<Expr *, 8> LHSs;
19867 SmallVector<Expr *, 8> RHSs;
19869 SmallVector<Expr *, 8> ReductionOps;
19871 SmallVector<Expr *, 8> InscanCopyOps;
19873 SmallVector<Expr *, 8> InscanCopyArrayTemps;
19875 SmallVector<Expr *, 8> InscanCopyArrayElems;
19878 SmallVector<Expr *, 8> TaskgroupDescriptors;
19880 SmallVector<Decl *, 4> ExprCaptures;
19882 SmallVector<Expr *, 4> ExprPostUpdates;
19884 unsigned RedModifier = 0;
19886 unsigned OrigSharingModifier = 0;
19888 SmallVector<bool, 8> IsPrivateVarReduction;
19889 ReductionData() =
delete;
19891 ReductionData(
unsigned Size,
unsigned Modifier = 0,
unsigned OrgModifier = 0)
19892 : RedModifier(Modifier), OrigSharingModifier(OrgModifier) {
19893 Vars.reserve(Size);
19894 Privates.reserve(Size);
19895 LHSs.reserve(Size);
19896 RHSs.reserve(Size);
19897 ReductionOps.reserve(Size);
19898 IsPrivateVarReduction.reserve(Size);
19899 if (RedModifier == OMPC_REDUCTION_inscan) {
19900 InscanCopyOps.reserve(Size);
19901 InscanCopyArrayTemps.reserve(Size);
19902 InscanCopyArrayElems.reserve(Size);
19904 TaskgroupDescriptors.reserve(Size);
19905 ExprCaptures.reserve(Size);
19906 ExprPostUpdates.reserve(Size);
19910 void push(Expr *Item, Expr *ReductionOp) {
19911 Vars.emplace_back(Item);
19912 Privates.emplace_back(
nullptr);
19913 LHSs.emplace_back(
nullptr);
19914 RHSs.emplace_back(
nullptr);
19915 ReductionOps.emplace_back(ReductionOp);
19916 IsPrivateVarReduction.emplace_back(
false);
19917 TaskgroupDescriptors.emplace_back(
nullptr);
19918 if (RedModifier == OMPC_REDUCTION_inscan) {
19919 InscanCopyOps.push_back(
nullptr);
19920 InscanCopyArrayTemps.push_back(
nullptr);
19921 InscanCopyArrayElems.push_back(
nullptr);
19925 void push(Expr *Item, Expr *
Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
19926 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
19927 Expr *CopyArrayElem,
bool IsPrivate) {
19928 Vars.emplace_back(Item);
19929 Privates.emplace_back(
Private);
19930 LHSs.emplace_back(LHS);
19931 RHSs.emplace_back(RHS);
19932 ReductionOps.emplace_back(ReductionOp);
19933 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
19934 if (RedModifier == OMPC_REDUCTION_inscan) {
19935 InscanCopyOps.push_back(CopyOp);
19936 InscanCopyArrayTemps.push_back(CopyArrayTemp);
19937 InscanCopyArrayElems.push_back(CopyArrayElem);
19939 assert(CopyOp ==
nullptr && CopyArrayTemp ==
nullptr &&
19940 CopyArrayElem ==
nullptr &&
19941 "Copy operation must be used for inscan reductions only.");
19943 IsPrivateVarReduction.emplace_back(IsPrivate);
19952 if (Length ==
nullptr) {
19959 SingleElement =
true;
19960 ArraySizes.push_back(llvm::APSInt::get(1));
19963 if (!Length->EvaluateAsInt(Result, Context))
19966 llvm::APSInt ConstantLengthValue = Result.
Val.
getInt();
19967 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
19968 ArraySizes.push_back(ConstantLengthValue);
19976 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base)) {
19977 Length = TempOASE->getLength();
19978 if (Length ==
nullptr) {
19985 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
19986 ArraySizes.push_back(ConstantOne);
19989 if (!Length->EvaluateAsInt(Result, Context))
19992 llvm::APSInt ConstantLengthValue = Result.
Val.
getInt();
19993 if (ConstantLengthValue.getSExtValue() != 1)
19996 ArraySizes.push_back(ConstantLengthValue);
19998 Base = TempOASE->getBase()->IgnoreParenImpCasts();
20002 if (!SingleElement) {
20003 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base)) {
20005 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
20006 ArraySizes.push_back(ConstantOne);
20007 Base = TempASE->getBase()->IgnoreParenImpCasts();
20019 return BO_AddAssign;
20021 return BO_MulAssign;
20023 return BO_AndAssign;
20025 return BO_OrAssign;
20027 return BO_XorAssign;
20083 case OO_Array_Delete:
20092 case OO_GreaterEqual:
20094 case OO_MinusEqual:
20096 case OO_SlashEqual:
20097 case OO_PercentEqual:
20098 case OO_CaretEqual:
20102 case OO_GreaterGreater:
20103 case OO_LessLessEqual:
20104 case OO_GreaterGreaterEqual:
20105 case OO_EqualEqual:
20106 case OO_ExclaimEqual:
20109 case OO_MinusMinus:
20115 case OO_Conditional:
20118 llvm_unreachable(
"Unexpected reduction identifier");
20121 if (II->isStr(
"max"))
20123 else if (II->isStr(
"min"))
20131 if (OOK == OO_Minus && S.
LangOpts.OpenMP == 52)
20132 S.
Diag(ReductionId.
getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
20135 if (ReductionIdScopeSpec.
isValid())
20141 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
20142 bool FirstIter =
true;
20143 for (
Expr *RefExpr : VarList) {
20144 assert(RefExpr &&
"nullptr expr in OpenMP reduction clause.");
20152 if (!FirstIter && IR != ER)
20157 bool IsPrivate =
false;
20158 Expr *SimpleRefExpr = RefExpr;
20167 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
20168 ReductionId,
Type, BasePath, IR == ER ?
nullptr : *IR);
20169 Expr *ReductionOp =
nullptr;
20171 (DeclareReductionRef.
isUnset() ||
20173 ReductionOp = DeclareReductionRef.
get();
20175 RD.push(RefExpr, ReductionOp);
20181 Expr *TaskgroupDescriptor =
nullptr;
20183 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
20184 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
20186 Type = ASE->getType().getNonReferenceType();
20190 if (
const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20191 Type = ATy->getElementType();
20194 Type =
Type.getNonReferenceType();
20198 auto *VD = dyn_cast<VarDecl>(D);
20204 diag::err_omp_reduction_incomplete_type))
20210 false, ASE || OASE))
20217 if (!ASE && !OASE) {
20219 VarDecl *VDDef = VD->getDefinition();
20221 DSARefChecker Check(Stack);
20222 if (Check.Visit(VDDef->
getInit())) {
20223 S.
Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
20242 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D,
false);
20243 if (DVar.CKind == OMPC_reduction) {
20244 S.
Diag(ELoc, diag::err_omp_once_referenced)
20250 if (DVar.CKind != OMPC_unknown) {
20251 S.
Diag(ELoc, diag::err_omp_wrong_dsa)
20267 DVar = Stack->getImplicitDSA(D,
true);
20268 if (DVar.CKind != OMPC_shared) {
20269 S.
Diag(ELoc, diag::err_omp_required_access)
20283 DVar = Stack->getImplicitDSA(D,
true);
20285 IsPrivate = DVar.CKind != OMPC_shared;
20286 bool IsOrphaned =
false;
20288 IsOrphaned = ParentDir == OMPD_unknown;
20290 RD.OrigSharingModifier == OMPC_ORIGINAL_SHARING_private))
20296 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D,
false);
20297 if (DVar.CKind == OMPC_threadprivate) {
20298 S.
Diag(ELoc, diag::err_omp_wrong_dsa)
20310 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
20311 ReductionId,
Type, BasePath, IR == ER ?
nullptr : *IR);
20315 (DeclareReductionRef.
isUnset() ||
20317 RD.push(RefExpr, DeclareReductionRef.
get());
20320 if (BOK == BO_Comma && DeclareReductionRef.
isUnset()) {
20324 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
20325 <<
Type << ReductionIdRange;
20328 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
20329 <<
Type << ReductionIdRange;
20341 if (DeclareReductionRef.
isUnset()) {
20342 if ((BOK == BO_GT || BOK == BO_LT) &&
20345 S.
Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
20348 if (!ASE && !OASE) {
20349 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20352 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20357 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
20359 S.
Diag(ELoc, diag::err_omp_clause_floating_type_arg)
20361 if (!ASE && !OASE) {
20362 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20365 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20372 Type =
Type.getNonLValueExprType(Context).getUnqualifiedType();
20381 bool ConstantLengthOASE =
false;
20383 bool SingleElement;
20386 Context, OASE, SingleElement, ArraySizes);
20389 if (ConstantLengthOASE && !SingleElement) {
20390 for (llvm::APSInt &Size : ArraySizes)
20391 PrivateTy = Context.getConstantArrayType(PrivateTy, Size,
nullptr,
20397 if ((OASE && !ConstantLengthOASE) ||
20400 if (!Context.getTargetInfo().isVLASupported()) {
20402 S.
Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
20403 S.
Diag(ELoc, diag::note_vla_unsupported);
20406 S.
targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
20407 S.
targetDiag(ELoc, diag::note_vla_unsupported);
20415 PrivateTy = Context.getVariableArrayType(
20420 }
else if (!ASE && !OASE &&
20433 if (DeclareReductionRef.
isUsable()) {
20436 if (DRD->getInitializer()) {
20462 Type = ComplexTy->getElementType();
20464 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
20465 Context.getFloatTypeSemantics(
Type));
20469 uint64_t Size = Context.getTypeSize(
Type);
20470 QualType IntTy = Context.getIntTypeForBitwidth(Size, 0);
20471 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
20490 uint64_t Size = Context.getTypeSize(
Type);
20492 Context.getIntTypeForBitwidth(Size, IsSigned);
20493 llvm::APInt InitValue =
20494 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
20495 : llvm::APInt::getMinValue(Size)
20496 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
20497 : llvm::APInt::getMaxValue(Size);
20502 ELoc, Context.getTrivialTypeSourceInfo(
Type, ELoc), ELoc,
Init);
20508 llvm::APFloat InitValue = llvm::APFloat::getLargest(
20509 Context.getFloatTypeSemantics(
Type), BOK != BO_LT);
20539 llvm_unreachable(
"Unexpected reduction operation");
20548 }
else if (!
Init) {
20558 S.
Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
20559 <<
Type << ReductionIdRange;
20560 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20563 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20569 if (DeclareReductionRef.
isUsable()) {
20571 QualType PtrRedTy = Context.getPointerType(RedTy);
20574 if (!BasePath.empty()) {
20578 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.
get(), &BasePath,
20581 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.
get(), &BasePath,
20585 QualType Params[] = {PtrRedTy, PtrRedTy};
20586 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
20600 CombBOK, LHSDRE, RHSDRE);
20607 if (BOK != BO_LT && BOK != BO_GT) {
20610 BO_Assign, LHSDRE, ReductionOp.
get());
20612 auto *ConditionalOp =
new (Context)
20617 BO_Assign, LHSDRE, ConditionalOp);
20630 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
20631 if (ClauseKind == OMPC_reduction &&
20632 RD.RedModifier == OMPC_REDUCTION_inscan) {
20634 CopyOpRes = S.
BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
20644 if (Stack->getCurrentDirective() == OMPD_simd ||
20682 if (ClauseKind == OMPC_in_reduction) {
20685 const Expr *ParentReductionOp =
nullptr;
20686 Expr *ParentBOKTD =
nullptr, *ParentReductionOpTD =
nullptr;
20687 DSAStackTy::DSAVarData ParentBOKDSA =
20688 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
20690 DSAStackTy::DSAVarData ParentReductionOpDSA =
20691 Stack->getTopMostTaskgroupReductionData(
20692 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
20693 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
20694 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
20695 if ((DeclareReductionRef.
isUnset() && IsParentReductionOp) ||
20696 (DeclareReductionRef.
isUsable() && IsParentBOK) ||
20697 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
20698 bool EmitError =
true;
20699 if (IsParentReductionOp && DeclareReductionRef.
isUsable()) {
20700 llvm::FoldingSetNodeID RedId, ParentRedId;
20701 ParentReductionOp->
Profile(ParentRedId, Context,
true);
20702 DeclareReductionRef.
get()->
Profile(RedId, Context,
20704 EmitError = RedId != ParentRedId;
20708 diag::err_omp_reduction_identifier_mismatch)
20709 << ReductionIdRange << RefExpr->getSourceRange();
20711 diag::note_omp_previous_reduction_identifier)
20713 << (IsParentBOK ? ParentBOKDSA.RefExpr
20714 : ParentReductionOpDSA.RefExpr)
20715 ->getSourceRange();
20719 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
20726 TransformExprToCaptures RebuildToCapture(S, D);
20728 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
20729 Ref = RebuildToCapture.getCapturedExpr();
20731 VarsExpr = Ref =
buildCapture(S, D, SimpleRefExpr,
false);
20734 RD.ExprCaptures.emplace_back(Ref->
getDecl());
20740 S.
BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
20745 Stack->getCurrentDirective() == OMPD_taskgroup) {
20746 S.
Diag(RefExpr->getExprLoc(),
20747 diag::err_omp_reduction_non_addressable_expression)
20748 << RefExpr->getSourceRange();
20751 RD.ExprPostUpdates.emplace_back(
20758 unsigned Modifier = RD.RedModifier;
20761 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
20762 Modifier = OMPC_REDUCTION_task;
20763 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
20765 if (Modifier == OMPC_REDUCTION_task &&
20766 (CurrDir == OMPD_taskgroup ||
20770 if (DeclareReductionRef.
isUsable())
20771 Stack->addTaskgroupReductionData(D, ReductionIdRange,
20772 DeclareReductionRef.
get());
20774 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
20776 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.
get(),
20777 TaskgroupDescriptor, CopyOpRes.
get(), TempArrayRes.
get(),
20778 TempArrayElem.
get(), IsPrivate);
20780 return RD.Vars.empty();
20796 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
20807 if (Modifier == OMPC_REDUCTION_inscan &&
20808 (
DSAStack->getCurrentDirective() != OMPD_for &&
20809 DSAStack->getCurrentDirective() != OMPD_for_simd &&
20810 DSAStack->getCurrentDirective() != OMPD_simd &&
20811 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
20812 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
20813 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
20816 ReductionData RD(VarList.size(), Modifier, OriginalSharingModifier);
20818 StartLoc, LParenLoc, ColonLoc, EndLoc,
20819 ReductionIdScopeSpec, ReductionId,
20820 UnresolvedReductions, RD))
20824 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
20827 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
20828 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
20831 OriginalSharingModifier);
20839 ReductionData RD(VarList.size());
20841 VarList, StartLoc, LParenLoc, ColonLoc,
20842 EndLoc, ReductionIdScopeSpec, ReductionId,
20843 UnresolvedReductions, RD))
20847 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20849 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
20859 ReductionData RD(VarList.size());
20861 StartLoc, LParenLoc, ColonLoc, EndLoc,
20862 ReductionIdScopeSpec, ReductionId,
20863 UnresolvedReductions, RD))
20867 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20869 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
20878 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
20888 const auto *VD = dyn_cast_or_null<VarDecl>(D);
20891 diag::err_omp_linear_incomplete_type))
20893 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
20895 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
20899 Type =
Type.getNonReferenceType();
20906 if (!IsDeclareSimd &&
20911 Type =
Type.getUnqualifiedType().getCanonicalType();
20912 const auto *Ty =
Type.getTypePtrOrNull();
20913 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
20914 !Ty->isIntegralType(
getASTContext()) && !Ty->isPointerType())) {
20915 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) <<
Type;
20917 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
20920 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20943 Diag(Step->
getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
20945 LinKind = OMPC_LINEAR_val;
20946 for (
Expr *RefExpr : VarList) {
20947 assert(RefExpr &&
"NULL expr in OpenMP linear clause.");
20950 Expr *SimpleRefExpr = RefExpr;
20954 Vars.push_back(RefExpr);
20955 Privates.push_back(
nullptr);
20956 Inits.push_back(
nullptr);
20963 auto *VD = dyn_cast<VarDecl>(D);
20969 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
20970 if (DVar.RefExpr) {
20971 Diag(ELoc, diag::err_omp_wrong_dsa)
20980 Type =
Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20992 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
20995 ExprCaptures.push_back(Ref->
getDecl());
21002 SimpleRefExpr, RefRes.
get());
21005 ExprPostUpdates.push_back(
21006 SemaRef.IgnoredValueConversions(PostUpdateRes.
get()).get());
21010 if (LinKind == OMPC_LINEAR_uval)
21011 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
21013 InitExpr = VD ? SimpleRefExpr : Ref;
21014 SemaRef.AddInitializerToDecl(
21015 Init,
SemaRef.DefaultLvalueConversion(InitExpr).get(),
21019 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
21020 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
21021 ? RefExpr->IgnoreParens()
21023 Privates.push_back(PrivateRef);
21024 Inits.push_back(InitRef);
21030 Expr *StepExpr = Step;
21031 Expr *CalcStepExpr =
nullptr;
21039 StepExpr = Val.
get();
21047 SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.
get(), StepExpr);
21049 SemaRef.ActOnFinishFullExpr(CalcStep.
get(),
false);
21053 if (std::optional<llvm::APSInt>
Result =
21055 if (!
Result->isNegative() && !
Result->isStrictlyPositive())
21056 Diag(StepLoc, diag::warn_omp_linear_step_zero)
21057 << Vars[0] << (Vars.size() > 1);
21061 CalcStepExpr = CalcStep.
get();
21066 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
21067 Vars, Privates, Inits, StepExpr, CalcStepExpr,
21073 Expr *NumIterations,
Sema &SemaRef,
21074 Scope *S, DSAStackTy *Stack) {
21079 Expr *Step = Clause.getStep();
21080 Expr *CalcStep = Clause.getCalcStep();
21087 bool HasErrors =
false;
21088 auto CurInit = Clause.inits().begin();
21089 auto CurPrivate = Clause.privates().begin();
21091 for (
Expr *RefExpr : Clause.varlist()) {
21094 Expr *SimpleRefExpr = RefExpr;
21095 auto Res =
getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21097 if (Res.second || !D) {
21098 Updates.push_back(
nullptr);
21099 Finals.push_back(
nullptr);
21103 auto &&Info = Stack->isLoopControlVariable(D);
21110 diag::err_omp_linear_distribute_var_non_loop_iteration);
21111 Updates.push_back(
nullptr);
21112 Finals.push_back(
nullptr);
21116 Expr *InitExpr = *CurInit;
21121 if (LinKind == OMPC_LINEAR_uval)
21126 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
21133 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
21144 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
21147 Final = *CurPrivate;
21151 if (!
Update.isUsable() || !Final.isUsable()) {
21152 Updates.push_back(
nullptr);
21153 Finals.push_back(
nullptr);
21154 UsedExprs.push_back(
nullptr);
21157 Updates.push_back(
Update.get());
21158 Finals.push_back(Final.get());
21160 UsedExprs.push_back(SimpleRefExpr);
21165 if (
Expr *S = Clause.getStep())
21166 UsedExprs.push_back(S);
21168 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(),
nullptr);
21169 Clause.setUpdates(Updates);
21170 Clause.setFinals(Finals);
21171 Clause.setUsedExprs(UsedExprs);
21179 for (
Expr *RefExpr : VarList) {
21180 assert(RefExpr &&
"NULL expr in OpenMP aligned clause.");
21183 Expr *SimpleRefExpr = RefExpr;
21187 Vars.push_back(RefExpr);
21194 auto *VD = dyn_cast<VarDecl>(D);
21202 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
21204 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
21207 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21214 if (
const Expr *PrevRef =
DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
21215 Diag(ELoc, diag::err_omp_used_in_clause_twice)
21217 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
21226 .DefaultFunctionArrayConversion(
21227 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
21236 if (Alignment !=
nullptr) {
21241 Alignment = AlignResult.
get();
21247 ColonLoc, EndLoc, Vars, Alignment);
21258 for (
Expr *RefExpr : VarList) {
21259 assert(RefExpr &&
"NULL expr in OpenMP copyin clause.");
21262 Vars.push_back(RefExpr);
21263 SrcExprs.push_back(
nullptr);
21264 DstExprs.push_back(
nullptr);
21265 AssignmentOps.push_back(
nullptr);
21274 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
21276 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
21277 << 0 << RefExpr->getSourceRange();
21281 Decl *D = DE->getDecl();
21287 Vars.push_back(DE);
21288 SrcExprs.push_back(
nullptr);
21289 DstExprs.push_back(
nullptr);
21290 AssignmentOps.push_back(
nullptr);
21296 if (!
DSAStack->isThreadPrivate(VD)) {
21298 Diag(ELoc, diag::err_omp_required_access)
21300 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion);
21323 SemaRef.BuildBinOp(
nullptr, DE->getExprLoc(), BO_Assign,
21324 PseudoDstExpr, PseudoSrcExpr);
21333 DSAStack->addDSA(VD, DE, OMPC_copyin);
21334 Vars.push_back(DE);
21335 SrcExprs.push_back(PseudoSrcExpr);
21336 DstExprs.push_back(PseudoDstExpr);
21337 AssignmentOps.push_back(AssignmentOp.
get());
21344 Vars, SrcExprs, DstExprs, AssignmentOps);
21355 for (
Expr *RefExpr : VarList) {
21356 assert(RefExpr &&
"NULL expr in OpenMP copyprivate clause.");
21359 Expr *SimpleRefExpr = RefExpr;
21363 Vars.push_back(RefExpr);
21364 SrcExprs.push_back(
nullptr);
21365 DstExprs.push_back(
nullptr);
21366 AssignmentOps.push_back(
nullptr);
21373 auto *VD = dyn_cast<VarDecl>(D);
21378 if (!VD || !
DSAStack->isThreadPrivate(VD)) {
21379 DSAStackTy::DSAVarData DVar =
21381 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
21383 Diag(ELoc, diag::err_omp_wrong_dsa)
21393 if (DVar.CKind == OMPC_unknown) {
21394 DVar =
DSAStack->getImplicitDSA(D,
false);
21395 if (DVar.CKind == OMPC_shared) {
21396 Diag(ELoc, diag::err_omp_required_access)
21398 <<
"threadprivate or private in the enclosing context";
21408 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
21410 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
21412 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
21415 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21436 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
21439 AssignmentOp =
SemaRef.ActOnFinishFullExpr(AssignmentOp.
get(), ELoc,
21448 VD ? RefExpr->IgnoreParens()
21450 SrcExprs.push_back(PseudoSrcExpr);
21451 DstExprs.push_back(PseudoDstExpr);
21452 AssignmentOps.push_back(AssignmentOp.
get());
21459 EndLoc, Vars, SrcExprs, DstExprs,
21467 if (VarList.empty())
21476 bool Diagnose =
true) {
21477 QualType OMPDependT = Stack->getOMPDependT();
21478 if (!OMPDependT.
isNull())
21484 S.
Diag(Loc, diag::err_omp_implied_type_not_found) <<
"omp_depend_t";
21487 Stack->setOMPDependT(PT.
get());
21508 Diag(Depobj->
getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
21513 Diag(Depobj->
getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
21523struct DoacrossDataInfoTy {
21527 DSAStackTy::OperatorOffsetTy OpsOffs;
21529 llvm::APSInt TotalDepCount;
21532static DoacrossDataInfoTy
21538 DSAStackTy::OperatorOffsetTy OpsOffs;
21539 llvm::APSInt DepCounter(32);
21540 llvm::APSInt TotalDepCount(32);
21542 if (
const Expr *OrderedCountExpr =
21543 Stack->getParentOrderedRegionParam().first) {
21544 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.
Context);
21545 TotalDepCount.setIsUnsigned(
true);
21548 for (
Expr *RefExpr : VarList) {
21549 assert(RefExpr &&
"NULL expr in OpenMP doacross clause.");
21552 Vars.push_back(RefExpr);
21559 if (Stack->getParentOrderedRegionParam().first &&
21560 DepCounter >= TotalDepCount) {
21561 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
21575 Vars.push_back(RefExpr);
21582 Expr *RHS =
nullptr;
21583 if (
auto *BO = dyn_cast<BinaryOperator>(
SimpleExpr)) {
21585 OOLoc = BO->getOperatorLoc();
21588 }
else if (
auto *OCE = dyn_cast<CXXOperatorCallExpr>(
SimpleExpr)) {
21589 OOK = OCE->getOperator();
21590 OOLoc = OCE->getOperatorLoc();
21593 }
else if (
auto *MCE = dyn_cast<CXXMemberCallExpr>(
SimpleExpr)) {
21594 OOK = MCE->getMethodDecl()
21597 .getCXXOverloadedOperator();
21598 OOLoc = MCE->getCallee()->getExprLoc();
21607 Vars.push_back(RefExpr);
21613 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK !=
OO_None)) {
21614 SemaRef.
Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
21620 RHS, OMPC_depend,
false);
21625 Stack->getParentOrderedRegionParam().first &&
21626 DepCounter != Stack->isParentLoopControlVariable(D).first) {
21628 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
21630 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
21633 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
21637 OpsOffs.emplace_back(RHS, OOK);
21639 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21642 TotalDepCount > VarList.size() &&
21643 Stack->getParentOrderedRegionParam().first &&
21644 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
21645 SemaRef.
Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
21646 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
21648 return {Vars, OpsOffs, TotalDepCount};
21657 if (
DSAStack->getCurrentDirective() == OMPD_ordered &&
21658 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
21659 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21663 if (
DSAStack->getCurrentDirective() == OMPD_taskwait &&
21664 DepKind == OMPC_DEPEND_mutexinoutset) {
21665 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
21668 if ((
DSAStack->getCurrentDirective() != OMPD_ordered ||
21669 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21671 DepKind == OMPC_DEPEND_sink ||
21673 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21674 DepKind == OMPC_DEPEND_depobj))) {
21676 OMPC_DEPEND_outallmemory,
21677 OMPC_DEPEND_inoutallmemory};
21679 DSAStack->getCurrentDirective() == OMPD_depobj)
21680 Except.push_back(OMPC_DEPEND_depobj);
21682 Except.push_back(OMPC_DEPEND_inoutset);
21684 ?
"depend modifier(iterator) or "
21686 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21694 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
21696 diag::err_omp_depend_sink_source_with_modifier);
21701 Diag(DepModifier->
getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
21704 DSAStackTy::OperatorOffsetTy OpsOffs;
21705 llvm::APSInt TotalDepCount(32);
21707 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
21710 Vars = VarOffset.Vars;
21711 OpsOffs = VarOffset.OpsOffs;
21712 TotalDepCount = VarOffset.TotalDepCount;
21714 for (
Expr *RefExpr : VarList) {
21715 assert(RefExpr &&
"NULL expr in OpenMP depend clause.");
21718 Vars.push_back(RefExpr);
21724 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
21725 bool OMPDependTFound =
getLangOpts().OpenMP >= 50;
21726 if (OMPDependTFound)
21728 DepKind == OMPC_DEPEND_depobj);
21729 if (DepKind == OMPC_DEPEND_depobj) {
21733 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21734 !RefExpr->isInstantiationDependent() &&
21735 !RefExpr->containsUnexpandedParameterPack() &&
21736 (OMPDependTFound &&
21738 DSAStack->getOMPDependT(), RefExpr->getType()))) {
21739 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21740 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
21743 if (!RefExpr->isLValue()) {
21744 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21745 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
21752 QualType ExprTy = RefExpr->getType().getNonReferenceType();
21753 const auto *OASE = dyn_cast<ArraySectionExpr>(
SimpleExpr);
21757 if (BaseType.isNull())
21759 if (
const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21760 ExprTy = ATy->getElementType();
21763 if (BaseType.isNull() || ExprTy.
isNull())
21766 const Expr *Length = OASE->getLength();
21768 if (Length && !Length->isValueDependent() &&
21770 Result.Val.getInt().isZero()) {
21772 diag::err_omp_depend_zero_length_array_section_not_allowed)
21782 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21783 !RefExpr->isInstantiationDependent() &&
21784 !RefExpr->containsUnexpandedParameterPack() &&
21785 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
21786 (OMPDependTFound &&
DSAStack->getOMPDependT().getTypePtr() ==
21788 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21791 << RefExpr->getSourceRange();
21795 auto *ASE = dyn_cast<ArraySubscriptExpr>(
SimpleExpr);
21796 if (ASE && !ASE->getBase()->isTypeDependent() &&
21799 .getNonReferenceType()
21800 ->isPointerType() &&
21801 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
21802 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21805 << RefExpr->getSourceRange();
21812 Res =
SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
21813 RefExpr->IgnoreParenImpCasts());
21817 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21820 << RefExpr->getSourceRange();
21825 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21829 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
21830 DepKind != OMPC_DEPEND_outallmemory &&
21831 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
21836 {DepKind, DepLoc,
Data.ColonLoc,
Data.OmpAllMemoryLoc}, DepModifier, Vars,
21837 TotalDepCount.getZExtValue());
21838 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
21839 DSAStack->isParentOrderedRegion())
21840 DSAStack->addDoacrossDependClause(
C, OpsOffs);
21849 "Unexpected device modifier in OpenMP < 50.");
21851 bool ErrorFound =
false;
21853 std::string Values =
21855 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
21861 Stmt *HelperValStmt =
nullptr;
21874 if (Modifier == OMPC_DEVICE_ancestor) {
21878 diag::err_omp_device_ancestor_without_requires_reverse_offload);
21886 if (CaptureRegion != OMPD_unknown &&
21887 !
SemaRef.CurContext->isDependentContext()) {
21888 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
21889 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21890 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
21895 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
21896 LParenLoc, ModifierLoc, EndLoc);
21901 bool FullCheck =
true) {
21906 SemaRef.
Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
21916 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
21922 (OASE && OASE->getColonLocFirst().isInvalid())) {
21923 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
21924 return ATy->getSExtSize() != 1;
21929 assert(OASE &&
"Expecting array section if not an array subscript.");
21930 const Expr *LowerBound = OASE->getLowerBound();
21931 const Expr *Length = OASE->getLength();
21940 llvm::APSInt ConstLowerBound = Result.
Val.
getInt();
21941 if (ConstLowerBound.getSExtValue())
21956 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr());
21961 if (!Length->EvaluateAsInt(Result, SemaRef.
getASTContext()))
21964 llvm::APSInt ConstLength = Result.
Val.
getInt();
21965 return CATy->getSExtSize() != ConstLength.getSExtValue();
21974 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
21979 (OASE && OASE->getColonLocFirst().isInvalid()))
21982 assert(OASE &&
"Expecting array section if not an array subscript.");
21983 const Expr *Length = OASE->getLength();
21989 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
21990 return ATy->getSExtSize() != 1;
21997 if (!Length->EvaluateAsInt(Result, SemaRef.
getASTContext()))
22000 llvm::APSInt ConstLength = Result.
Val.
getInt();
22001 return ConstLength.getSExtValue() != 1;
22040class MapBaseChecker final :
public StmtVisitor<MapBaseChecker, bool> {
22045 bool IsNonContiguous =
false;
22046 bool NoDiagnose =
false;
22047 const Expr *RelevantExpr =
nullptr;
22048 bool AllowUnitySizeArraySection =
true;
22049 bool AllowWholeSizeArraySection =
true;
22050 bool AllowAnotherPtr =
true;
22051 SourceLocation ELoc;
22052 SourceRange ERange;
22054 void emitErrorMsg() {
22056 if (SemaRef.getLangOpts().OpenMP < 50) {
22058 diag::err_omp_expected_named_var_member_or_array_expression)
22061 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
22067 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
22072 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22073 RelevantExpr = DRE;
22075 Components.emplace_back(DRE, DRE->
getDecl(), IsNonContiguous);
22079 bool VisitMemberExpr(MemberExpr *ME) {
22084 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22093 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
22109 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
22129 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
22133 return RelevantExpr || Visit(E);
22143 AllowUnitySizeArraySection =
false;
22144 AllowWholeSizeArraySection =
false;
22147 Components.emplace_back(ME, FD, IsNonContiguous);
22148 return RelevantExpr || Visit(E);
22151 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
22156 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
22160 return RelevantExpr || Visit(E);
22167 AllowWholeSizeArraySection =
false;
22170 Expr::EvalResult
Result;
22173 !
Result.Val.getInt().isZero()) {
22175 diag::err_omp_invalid_map_this_expr);
22177 diag::note_omp_invalid_subscript_on_this_ptr_map);
22179 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22184 Components.emplace_back(AE,
nullptr, IsNonContiguous);
22186 return RelevantExpr || Visit(E);
22189 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
22192 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
22193 "Array sections cannot be implicitly mapped.");
22207 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
22217 if (AllowWholeSizeArraySection) {
22224 if (NotWhole || IsPointer)
22225 AllowWholeSizeArraySection =
false;
22226 }
else if (DKind == OMPD_target_update &&
22227 SemaRef.getLangOpts().OpenMP >= 50) {
22228 if (IsPointer && !AllowAnotherPtr)
22229 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
22232 IsNonContiguous =
true;
22233 }
else if (AllowUnitySizeArraySection && NotUnity) {
22239 diag::err_array_section_does_not_specify_contiguous_storage)
22245 AllowAnotherPtr =
false;
22247 if (
const auto *TE = dyn_cast<CXXThisExpr>(E)) {
22248 Expr::EvalResult ResultR;
22249 Expr::EvalResult ResultL;
22254 diag::err_omp_invalid_map_this_expr);
22256 diag::note_omp_invalid_length_on_this_ptr_mapping);
22260 SemaRef.getASTContext()) &&
22263 diag::err_omp_invalid_map_this_expr);
22265 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
22267 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22272 Components.emplace_back(OASE,
nullptr,
false);
22273 return RelevantExpr || Visit(E);
22275 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
22279 Components.emplace_back(E,
nullptr, IsNonContiguous);
22281 return Visit(
Base->IgnoreParenImpCasts());
22284 bool VisitUnaryOperator(UnaryOperator *UO) {
22285 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->
isLValue() ||
22290 if (!RelevantExpr) {
22292 Components.emplace_back(UO,
nullptr,
false);
22296 bool VisitBinaryOperator(BinaryOperator *BO) {
22308 Components.emplace_back(BO,
nullptr,
false);
22311 "Either LHS or RHS have base decl inside");
22313 return RelevantExpr || Visit(LE);
22314 return RelevantExpr || Visit(RE);
22316 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
22317 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22318 RelevantExpr = CTE;
22319 Components.emplace_back(CTE,
nullptr, IsNonContiguous);
22322 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
22323 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22324 Components.emplace_back(COCE,
nullptr, IsNonContiguous);
22327 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
22333 return Visit(Source);
22335 bool VisitStmt(Stmt *) {
22339 const Expr *getFoundBase()
const {
return RelevantExpr; }
22340 explicit MapBaseChecker(
22343 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
22344 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
22345 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
22359 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
22363 if (SemaRef.
getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
22364 (CKind == OMPC_to || CKind == OMPC_from)) {
22365 auto CI = CurComponents.rbegin();
22366 auto CE = CurComponents.rend();
22367 for (; CI != CE; ++CI) {
22369 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
22374 SemaRef.
Diag(ELoc, diag::err_array_section_does_not_specify_length)
22378 return Checker.getFoundBase();
22387 bool CurrentRegionOnly,
22398 assert(!CurComponents.empty() &&
"Map clause expression with no components!");
22399 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
22400 "Map clause expression with unexpected base!");
22403 bool IsEnclosedByDataEnvironmentExpr =
false;
22404 const Expr *EnclosingExpr =
nullptr;
22406 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
22407 VD, CurrentRegionOnly,
22408 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
22409 ERange, CKind, &EnclosingExpr,
22413 if (CKind == Kind && SemaRef.
LangOpts.OpenMP >= 50)
22415 assert(!StackComponents.empty() &&
22416 "Map clause expression with no components!");
22417 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
22418 "Map clause expression with unexpected base!");
22422 const Expr *RE = StackComponents.front().getAssociatedExpression();
22428 auto CI = CurComponents.rbegin();
22429 auto CE = CurComponents.rend();
22430 auto SI = StackComponents.rbegin();
22431 auto SE = StackComponents.rend();
22432 for (; CI != CE && SI != SE; ++CI, ++SI) {
22437 if (CurrentRegionOnly &&
22444 SemaRef.
Diag(CI->getAssociatedExpression()->getExprLoc(),
22445 diag::err_omp_multiple_array_items_in_map_clause)
22446 << CI->getAssociatedExpression()->getSourceRange();
22447 SemaRef.
Diag(SI->getAssociatedExpression()->getExprLoc(),
22448 diag::note_used_here)
22449 << SI->getAssociatedExpression()->getSourceRange();
22454 if (CI->getAssociatedExpression()->getStmtClass() !=
22455 SI->getAssociatedExpression()->getStmtClass())
22459 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
22465 for (; SI != SE; ++SI) {
22467 if (
const auto *ASE =
22468 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
22469 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
22470 }
else if (
const auto *OASE = dyn_cast<ArraySectionExpr>(
22471 SI->getAssociatedExpression())) {
22474 }
else if (
const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
22475 SI->getAssociatedExpression())) {
22480 SemaRef, SI->getAssociatedExpression(),
Type))
22490 if (CI == CE && SI == SE) {
22491 if (CurrentRegionOnly) {
22492 if (CKind == OMPC_map) {
22493 SemaRef.
Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
22495 assert(CKind == OMPC_to || CKind == OMPC_from);
22496 SemaRef.
Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
22505 IsEnclosedByDataEnvironmentExpr =
true;
22510 std::prev(CI)->getAssociatedDeclaration()->getType();
22512 std::prev(CI)->getAssociatedExpression()->getExprLoc();
22531 if (CI == CE || SI == SE) {
22534 diag::err_omp_pointer_mapped_along_with_derived_section)
22540 if (CI->getAssociatedExpression()->getStmtClass() !=
22541 SI->getAssociatedExpression()->getStmtClass() ||
22542 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
22543 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
22544 assert(CI != CE && SI != SE);
22545 SemaRef.
Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
22558 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
22559 if (CKind == OMPC_map) {
22560 if (CI != CE || SI != SE) {
22564 CI != CE ? CurComponents.begin() : StackComponents.begin();
22565 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
22567 while (It != End && !It->getAssociatedDeclaration())
22568 std::advance(It, 1);
22569 assert(It != End &&
22570 "Expected at least one component with the declaration.");
22571 if (It != Begin && It->getAssociatedDeclaration()
22573 .getCanonicalType()
22574 ->isAnyPointerType()) {
22575 IsEnclosedByDataEnvironmentExpr =
false;
22576 EnclosingExpr =
nullptr;
22580 SemaRef.
Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
22582 assert(CKind == OMPC_to || CKind == OMPC_from);
22583 SemaRef.
Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
22593 if (!CurrentRegionOnly && SI != SE)
22594 EnclosingExpr = RE;
22598 IsEnclosedByDataEnvironmentExpr |=
22599 (!CurrentRegionOnly && CI != CE && SI == SE);
22604 if (CurrentRegionOnly)
22618 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
22620 diag::err_omp_original_storage_is_shared_and_does_not_contain)
22636 Expr *UnresolvedMapper) {
22656 Lookups.emplace_back();
22657 Lookups.back().append(Lookup.
begin(), Lookup.
end());
22660 }
else if (
auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
22665 assert(DMD &&
"Expect valid OMPDeclareMapperDecl during instantiation.");
22666 Lookups.back().addDecl(DMD);
22675 return !D->isInvalidDecl() &&
22676 (D->getType()->isDependentType() ||
22677 D->getType()->isInstantiationDependentType() ||
22678 D->getType()->containsUnexpandedParameterPack());
22689 false, URS.
begin(), URS.
end(),
false,
22697 SemaRef.
Diag(Loc, diag::err_omp_mapper_wrong_type);
22738 SemaRef.
Diag(Loc, diag::err_omp_invalid_mapper)
22748struct MappableVarListInfo {
22750 ArrayRef<Expr *> VarList;
22752 SmallVector<Expr *, 16> ProcessedVarList;
22756 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
22758 SmallVector<Expr *, 16> UDMapperList;
22760 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
22763 VarComponents.reserve(VarList.size());
22764 VarBaseDeclarations.reserve(VarList.size());
22773 const RecordDecl *RD = BaseType->getAsRecordDecl();
22783 for (
auto *FD : RD->
fields()) {
22785 MapperVarRef,
false, Range.getBegin(),
22791 SExprs.push_back(BE);
22799 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
22802 Maps.push_back(MapClause);
22803 return MapperVarRef;
22807 DSAStackTy *Stack) {
22813 const RecordDecl *RD = BaseType->getAsRecordDecl();
22822 MapperId = DeclNames.getIdentifier(&Ctx.
Idents.
get(
"default"));
22824 BaseType, MapperId, Maps,
nullptr);
22834 DMD->setMapperVarRef(MapperVarRef);
22858 Lookups.emplace_back();
22859 Lookups.back().append(Lookup.
begin(), Lookup.
end());
22866 return !D->isInvalidDecl() &&
22867 (D->getType()->isDependentType() ||
22868 D->getType()->isInstantiationDependentType() ||
22869 D->getType()->containsUnexpandedParameterPack());
22915 {CanonType,
nullptr});
22916 llvm::DenseMap<const Type *, bool> Visited;
22918 while (!Types.empty()) {
22919 auto [BaseType, CurFD] = Types.pop_back_val();
22920 while (ParentChain.back().second == 0)
22921 ParentChain.pop_back();
22922 --ParentChain.back().second;
22923 if (BaseType.isNull())
22926 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
22929 auto It = Visited.find(BaseType.getTypePtr());
22930 if (It == Visited.end()) {
22939 DefaultMapperId, BaseType);
22940 It = Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
22946 bool FirstIter =
true;
22956 ParentChain.emplace_back(CurFD, 1);
22958 ++ParentChain.back().second;
22960 Types.emplace_back(FieldTy, FD);
22979 bool IsMapTypeImplicit =
false,
bool NoDiagnose =
false) {
22982 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from ||
22983 CKind == OMPC_use_device_addr) &&
22984 "Unexpected clause kind with mappable expressions!");
22985 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
22993 MapperId.
setName(DeclNames.getIdentifier(
22995 MapperId.
setLoc(StartLoc);
22999 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
23000 bool UpdateUMIt =
false;
23001 Expr *UnresolvedMapper =
nullptr;
23003 bool HasHoldModifier =
23004 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
23012 for (
Expr *RE : MVLI.VarList) {
23013 assert(RE &&
"Null expr in omp to/from/map clause");
23017 if (UpdateUMIt && UMIt != UMEnd) {
23021 "Expect the size of UnresolvedMappers to match with that of VarList");
23025 UnresolvedMapper = *UMIt;
23029 if (
VE->isValueDependent() ||
VE->isTypeDependent() ||
23030 VE->isInstantiationDependent() ||
23031 VE->containsUnexpandedParameterPack()) {
23034 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23035 VE->getType().getCanonicalType(), UnresolvedMapper);
23038 MVLI.UDMapperList.push_back(ER.
get());
23041 MVLI.ProcessedVarList.push_back(RE);
23050 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
23053 SemaRef.
Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
23066 DSAS->getCurrentDirective(), NoDiagnose);
23070 assert(!CurComponents.empty() &&
23071 "Invalid mappable expression information.");
23073 if (
const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
23075 DSAS->addMappedClassesQualTypes(TE->getType());
23078 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23079 VE->getType().getCanonicalType(), UnresolvedMapper);
23082 MVLI.UDMapperList.push_back(ER.
get());
23084 MVLI.ProcessedVarList.push_back(RE);
23085 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23086 MVLI.VarComponents.back().append(CurComponents.begin(),
23087 CurComponents.end());
23088 MVLI.VarBaseDeclarations.push_back(
nullptr);
23095 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
23096 assert(CurDeclaration &&
"Null decl on map clause.");
23099 "Expecting components to have associated only canonical declarations.");
23101 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
23102 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
23104 assert((VD || FD) &&
"Only variables or fields are expected here!");
23111 if (VD && DSAS->isThreadPrivate(VD)) {
23114 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD,
false);
23115 SemaRef.
Diag(ELoc, diag::err_omp_threadprivate_in_clause)
23130 true, CurComponents, CKind))
23132 if (CKind == OMPC_map &&
23135 false, CurComponents, CKind))
23142 auto I = llvm::find_if(
23147 assert(I != CurComponents.end() &&
"Null decl on map clause.");
23150 auto *ASE = dyn_cast<ArraySubscriptExpr>(
VE->IgnoreParens());
23151 auto *OASE = dyn_cast<ArraySectionExpr>(
VE->IgnoreParens());
23152 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(
VE->IgnoreParens());
23154 Type = ASE->getType().getNonReferenceType();
23159 Type = ATy->getElementType();
23162 Type =
Type.getNonReferenceType();
23163 }
else if (OAShE) {
23177 if (CKind == OMPC_map) {
23184 if (DKind == OMPD_target_enter_data &&
23185 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
23187 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23188 << (IsMapTypeImplicit ? 1 : 0)
23190 << getOpenMPDirectiveName(DKind, OMPVersion);
23199 if (DKind == OMPD_target_exit_data &&
23200 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
23201 MapType == OMPC_MAP_delete || SemaRef.
getLangOpts().OpenMP >= 52)) {
23202 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23203 << (IsMapTypeImplicit ? 1 : 0)
23205 << getOpenMPDirectiveName(DKind, OMPVersion);
23214 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
23216 SemaRef.
Diag(StartLoc,
23217 diag::err_omp_invalid_map_type_modifier_for_directive)
23219 OMPC_MAP_MODIFIER_ompx_hold)
23220 << getOpenMPDirectiveName(DKind, OMPVersion);
23228 if ((DKind == OMPD_target_data ||
23230 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
23231 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
23232 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23233 << (IsMapTypeImplicit ? 1 : 0)
23235 << getOpenMPDirectiveName(DKind, OMPVersion);
23247 if (VD && ((SemaRef.
LangOpts.OpenMP <= 45 &&
23249 DKind == OMPD_target)) {
23250 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD,
false);
23252 SemaRef.
Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23255 << getOpenMPDirectiveName(DSAS->getCurrentDirective(),
23265 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23266 Type.getCanonicalType(), UnresolvedMapper);
23278 BaseType =
VE->getType().getCanonicalType();
23285 ElemType = ATy->getElementType();
23290 }
else if (
VE->getType()->isArrayType()) {
23291 const ArrayType *AT =
VE->getType()->getAsArrayTypeUnsafe();
23301 MVLI.UDMapperList.push_back(ER.
get());
23304 MVLI.ProcessedVarList.push_back(RE);
23308 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
23314 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23315 MVLI.VarComponents.back().append(CurComponents.begin(),
23316 CurComponents.end());
23338 BuiltinType::OMPIterator))
23340 diag::err_omp_map_modifier_not_iterator);
23343 unsigned Count = 0;
23344 for (
unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
23346 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
23347 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
23351 "Modifiers exceed the allowed number of map type modifiers");
23352 Modifiers[Count] = MapTypeModifiers[I];
23353 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
23357 MappableVarListInfo MVLI(VarList);
23359 MapperIdScopeSpec, MapperId, UnresolvedMappers,
23360 MapType, Modifiers, IsMapTypeImplicit,
23366 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23367 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
23369 MapperId, MapType, IsMapTypeImplicit, MapLoc);
23377 if (ReductionType.
isNull())
23385 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
23390 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
23394 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
23398 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
23401 return ReductionType;
23407 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
23410 Decls.reserve(ReductionTypes.size());
23414 SemaRef.forRedeclarationInCurContext());
23419 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
23421 bool InCompoundScope =
true;
23422 if (S !=
nullptr) {
23428 SemaRef.LookupName(Lookup, S);
23429 SemaRef.FilterLookupForScope(Lookup, DC, S,
false,
23431 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
23433 while (Filter.hasNext()) {
23435 if (InCompoundScope) {
23436 UsedAsPrevious.try_emplace(PrevDecl,
false);
23438 UsedAsPrevious[D] =
true;
23440 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
23441 PrevDecl->getLocation();
23444 if (InCompoundScope) {
23445 for (
const auto &PrevData : UsedAsPrevious) {
23446 if (!PrevData.second) {
23447 PrevDRD = PrevData.first;
23452 }
else if (PrevDeclInScope !=
nullptr) {
23453 auto *PrevDRDInScope = PrevDRD =
23456 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
23457 PrevDRDInScope->getLocation();
23458 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
23459 }
while (PrevDRDInScope !=
nullptr);
23461 for (
const auto &TyData : ReductionTypes) {
23462 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
23464 if (I != PreviousRedeclTypes.end()) {
23465 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
23467 Diag(I->second, diag::note_previous_definition);
23470 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
23472 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
23474 DRD->setAccess(AS);
23475 Decls.push_back(DRD);
23477 DRD->setInvalidDecl();
23491 SemaRef.setFunctionHasBranchProtectedScope();
23492 SemaRef.getCurFunction()->setHasOMPDeclareReductionCombiner();
23495 SemaRef.PushDeclContext(S, DRD);
23499 SemaRef.PushExpressionEvaluationContext(
23502 QualType ReductionType = DRD->getType();
23519 if (S !=
nullptr) {
23520 SemaRef.PushOnScopeChains(OmpInParm, S);
23521 SemaRef.PushOnScopeChains(OmpOutParm, S);
23523 DRD->addDecl(OmpInParm);
23524 DRD->addDecl(OmpOutParm);
23530 DRD->setCombinerData(InE, OutE);
23536 SemaRef.DiscardCleanupsInEvaluationContext();
23537 SemaRef.PopExpressionEvaluationContext();
23540 SemaRef.PopFunctionScopeInfo();
23542 if (Combiner !=
nullptr)
23543 DRD->setCombiner(Combiner);
23545 DRD->setInvalidDecl();
23554 SemaRef.setFunctionHasBranchProtectedScope();
23557 SemaRef.PushDeclContext(S, DRD);
23561 SemaRef.PushExpressionEvaluationContext(
23564 QualType ReductionType = DRD->getType();
23581 if (S !=
nullptr) {
23582 SemaRef.PushOnScopeChains(OmpPrivParm, S);
23583 SemaRef.PushOnScopeChains(OmpOrigParm, S);
23585 DRD->addDecl(OmpPrivParm);
23586 DRD->addDecl(OmpOrigParm);
23592 DRD->setInitializerData(OrigE, PrivE);
23593 return OmpPrivParm;
23599 SemaRef.DiscardCleanupsInEvaluationContext();
23600 SemaRef.PopExpressionEvaluationContext();
23603 SemaRef.PopFunctionScopeInfo();
23607 }
else if (OmpPrivParm->
hasInit()) {
23608 DRD->setInitializer(OmpPrivParm->
getInit(),
23613 DRD->setInvalidDecl();
23619 for (
Decl *D : DeclReductions.
get()) {
23625 D->setInvalidDecl();
23628 return DeclReductions;
23640 SemaRef.CheckExtraCXXDefaultArguments(D);
23643 return SemaRef.CreateParsedType(
T, TInfo);
23648 assert(
ParsedType.isUsable() &&
"Expect usable parsed mapper type");
23651 assert(!MapperType.
isNull() &&
"Expect valid mapper type");
23656 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
23668 SemaRef.forRedeclarationInCurContext());
23673 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
23675 bool InCompoundScope =
true;
23676 if (S !=
nullptr) {
23682 SemaRef.LookupName(Lookup, S);
23683 SemaRef.FilterLookupForScope(Lookup, DC, S,
false,
23685 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
23687 while (Filter.hasNext()) {
23689 if (InCompoundScope) {
23690 UsedAsPrevious.try_emplace(PrevDecl,
false);
23692 UsedAsPrevious[D] =
true;
23694 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
23695 PrevDecl->getLocation();
23698 if (InCompoundScope) {
23699 for (
const auto &PrevData : UsedAsPrevious) {
23700 if (!PrevData.second) {
23701 PrevDMD = PrevData.first;
23706 }
else if (PrevDeclInScope) {
23707 auto *PrevDMDInScope = PrevDMD =
23710 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
23711 PrevDMDInScope->getLocation();
23712 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
23713 }
while (PrevDMDInScope !=
nullptr);
23717 if (I != PreviousRedeclTypes.end()) {
23718 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
23719 << MapperType << Name;
23720 Diag(I->second, diag::note_previous_definition);
23728 ClausesWithImplicit);
23730 MapperType, VN, ClausesWithImplicit,
23733 SemaRef.PushOnScopeChains(DMD, S);
23736 DMD->setAccess(AS);
23738 DMD->setInvalidDecl();
23744 DMD->setMapperVarRef(MapperVarRef);
23758 SemaRef.PushOnScopeChains(VD, S,
false);
23760 DSAStack->addDeclareMapperVarRef(E);
23767 if (
DSAStack->getDeclareMapperVarRef()) {
23773 assert(!IsGlobalVar &&
"Only declare mapper handles TU-scope iterators.");
23778 assert(
getLangOpts().OpenMP &&
"Expected OpenMP mode.");
23780 if (
const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
23793 assert(
getLangOpts().OpenMP &&
"Expected OpenMP mode.");
23801 if (VarList.empty())
23804 for (
Expr *ValExpr : VarList) {
23815 if (CaptureRegion == OMPD_unknown ||
SemaRef.CurContext->isDependentContext())
23817 LParenLoc, EndLoc, VarList,
23820 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23822 for (
Expr *ValExpr : VarList) {
23823 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
23824 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
23825 Vars.push_back(ValExpr);
23830 LParenLoc, EndLoc, Vars, PreInit);
23837 if (VarList.empty())
23840 for (
Expr *ValExpr : VarList) {
23851 if (CaptureRegion == OMPD_unknown ||
SemaRef.CurContext->isDependentContext())
23853 StartLoc, LParenLoc, EndLoc, VarList,
23856 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23858 for (
Expr *ValExpr : VarList) {
23859 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
23860 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
23861 Vars.push_back(ValExpr);
23866 LParenLoc, EndLoc, Vars, PreInit);
23873 Expr *ValExpr = Priority;
23874 Stmt *HelperValStmt =
nullptr;
23880 ValExpr,
SemaRef, OMPC_priority,
23882 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
23886 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23894 "Unexpected grainsize modifier in OpenMP < 51.");
23899 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
23904 Expr *ValExpr = Grainsize;
23905 Stmt *HelperValStmt =
nullptr;
23915 &CaptureRegion, &HelperValStmt))
23920 StartLoc, LParenLoc, ModifierLoc, EndLoc);
23928 "Unexpected num_tasks modifier in OpenMP < 51.");
23933 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
23938 Expr *ValExpr = NumTasks;
23939 Stmt *HelperValStmt =
nullptr;
23946 ValExpr,
SemaRef, OMPC_num_tasks,
23948 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
23953 StartLoc, LParenLoc, ModifierLoc, EndLoc);
23973 DSAStackTy *Stack) {
23974 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
23975 if (!OMPEventHandleT.
isNull())
23980 S.
Diag(Loc, diag::err_omp_implied_type_not_found) <<
"omp_event_handle_t";
23983 Stack->setOMPEventHandleT(PT.
get());
24004 auto *VD = dyn_cast_or_null<VarDecl>(Ref->
getDecl());
24014 <<
"omp_event_handle_t" << 1 << VD->
getType()
24021 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(VD,
false);
24022 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
24041 std::string Values;
24045 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24049 Expr *ValExpr = ChunkSize;
24050 Stmt *HelperValStmt =
nullptr;
24061 ValExpr = Val.
get();
24066 if (std::optional<llvm::APSInt>
Result =
24068 if (
Result->isSigned() && !
Result->isStrictlyPositive()) {
24069 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
24070 <<
"dist_schedule" << 1
24075 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
24077 !
SemaRef.CurContext->isDependentContext()) {
24078 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
24079 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24080 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
24088 Kind, ValExpr, HelperValStmt);
24096 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
24097 Kind != OMPC_DEFAULTMAP_scalar) {
24101 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
24103 OMPC_DEFAULTMAP_MODIFIER_tofrom);
24107 OMPC_DEFAULTMAP_scalar);
24111 Diag(Loc, diag::err_omp_unexpected_clause_value)
24119 if (!isDefaultmapKind || !isDefaultmapModifier) {
24121 ?
"'scalar', 'aggregate', 'pointer'"
24122 :
"'scalar', 'aggregate', 'pointer', 'all'";
24124 StringRef ModifierValue =
"'alloc', 'from', 'to', 'tofrom', "
24125 "'firstprivate', 'none', 'default'";
24126 if (!isDefaultmapKind && isDefaultmapModifier) {
24127 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24129 }
else if (isDefaultmapKind && !isDefaultmapModifier) {
24130 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24133 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24135 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24139 StringRef ModifierValue =
24141 ?
"'alloc', 'from', 'to', 'tofrom', "
24142 "'firstprivate', 'none', 'default', 'present'"
24143 :
"'storage', 'from', 'to', 'tofrom', "
24144 "'firstprivate', 'private', 'none', 'default', 'present'";
24145 if (!isDefaultmapKind && isDefaultmapModifier) {
24146 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24148 }
else if (isDefaultmapKind && !isDefaultmapModifier) {
24149 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24152 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24154 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24164 if (
DSAStack->checkDefaultmapCategory(Kind)) {
24165 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
24171 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
24172 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
24173 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
24175 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
24192 Diag(DTCI.
Loc, diag::err_omp_region_not_file_context);
24198 Diag(DTCI.
Loc, diag::warn_hip_omp_target_directives);
24200 DeclareTargetNesting.push_back(DTCI);
24206 assert(!DeclareTargetNesting.empty() &&
24207 "check isInOpenMPDeclareTargetContext() first!");
24208 return DeclareTargetNesting.pop_back_val();
24218 if (DeclareTargetNesting.empty())
24222 Diag(DTCI.
Loc, diag::warn_omp_unterminated_declare_target)
24223 << getOpenMPDirectiveName(DTCI.
Kind, OMPVersion);
24229 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
24238 VarOrFuncDeclFilterCCC CCC(
SemaRef);
24242 SemaRef.diagnoseTypo(Corrected,
24243 SemaRef.PDiag(diag::err_undeclared_var_use_suggest)
24267 "Expected variable, function or function template.");
24269 if (
auto *VD = dyn_cast<VarDecl>(ND)) {
24271 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
24272 !VD->isStaticDataMember()) {
24273 Diag(Loc, diag::err_omp_declare_target_has_local_vars)
24282 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
24286 Diag(Loc, diag::warn_hip_omp_target_directives);
24289 const unsigned Level = -1;
24292 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
24293 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
24294 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.
DT &&
24295 (*ActiveAttr)->getLevel() == Level) {
24296 Diag(Loc, diag::err_omp_device_type_mismatch)
24297 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.
DT)
24298 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
24299 (*ActiveAttr)->getDevType());
24302 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
24303 (*ActiveAttr)->getLevel() == Level) {
24304 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
24308 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
24311 Expr *IndirectE =
nullptr;
24312 bool IsIndirect =
false;
24318 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
24323 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
24325 if (
auto *VD = dyn_cast<VarDecl>(ND);
24327 VD->hasGlobalStorage())
24336 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy>
MapTy =
24337 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
24338 if (SemaRef.
LangOpts.OpenMP >= 50 &&
24341 VD->hasGlobalStorage()) {
24342 if (!
MapTy || (*
MapTy != OMPDeclareTargetDeclAttr::MT_To &&
24343 *
MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
24350 diag::err_omp_lambda_capture_in_declare_target_not_to);
24351 SemaRef.
Diag(SL, diag::note_var_explicitly_captured_here)
24358 SemaRef.
Diag(VD->
getLocation(), diag::warn_omp_not_in_target_context);
24359 SemaRef.
Diag(SL, diag::note_used_here) << SR;
24363 Sema &SemaRef, DSAStackTy *Stack,
24365 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
24376 if (
auto *VD = dyn_cast<VarDecl>(D)) {
24378 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
24379 !VD->isStaticDataMember())
24383 if (
DSAStack->isThreadPrivate(VD)) {
24384 Diag(SL, diag::err_omp_threadprivate_in_target);
24389 if (
const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
24390 D = FTD->getTemplatedDecl();
24391 if (
auto *FD = dyn_cast<FunctionDecl>(D)) {
24392 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
24393 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
24394 if (IdLoc.
isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
24395 Diag(IdLoc, diag::err_omp_function_in_link_clause);
24400 if (
auto *VD = dyn_cast<ValueDecl>(D)) {
24410 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
24411 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
24412 unsigned Level = DeclareTargetNesting.size();
24413 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
24416 Expr *IndirectE =
nullptr;
24417 bool IsIndirect =
false;
24423 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
24425 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
24426 : OMPDeclareTargetDeclAttr::MT_To,
24427 DTCI.
DT, IndirectE, IsIndirect, Level,
24431 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
24451 if (
auto *VD = dyn_cast<VarDecl>(Node->
getDecl())) {
24453 DeclVector.push_back(VD);
24458 for (
auto *Child : Ex->
children()) {
24467 A = TD->
getAttr<OMPDeclareTargetDeclAttr>();
24469 llvm::SmallDenseSet<Decl *> Visited;
24470 while (!DeclVector.empty()) {
24471 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
24472 if (!Visited.insert(TargetVarDecl).second)
24475 if (TargetVarDecl->
hasAttr<OMPDeclareTargetDeclAttr>() &&
24505 unsigned Count = 0;
24506 for (
unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
24508 llvm::is_contained(Modifiers, MotionModifiers[I])) {
24509 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
24513 "Modifiers exceed the allowed number of motion modifiers");
24514 Modifiers[Count] = MotionModifiers[I];
24515 ModifiersLoc[Count] = MotionModifiersLoc[I];
24519 MappableVarListInfo MVLI(VarList);
24521 MapperIdScopeSpec, MapperId, UnresolvedMappers);
24522 if (MVLI.ProcessedVarList.empty())
24525 if (
auto *DRE = dyn_cast<DeclRefExpr>(IteratorExpr))
24526 if (
auto *VD = dyn_cast<VarDecl>(DRE->
getDecl()))
24529 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24530 MVLI.VarComponents, MVLI.UDMapperList, IteratorExpr, Modifiers,
24547 unsigned Count = 0;
24548 for (
unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
24550 llvm::is_contained(Modifiers, MotionModifiers[I])) {
24551 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
24555 "Modifiers exceed the allowed number of motion modifiers");
24556 Modifiers[Count] = MotionModifiers[I];
24557 ModifiersLoc[Count] = MotionModifiersLoc[I];
24561 MappableVarListInfo MVLI(VarList);
24563 MapperIdScopeSpec, MapperId, UnresolvedMappers);
24564 if (MVLI.ProcessedVarList.empty())
24567 if (
auto *DRE = dyn_cast<DeclRefExpr>(IteratorExpr))
24568 if (
auto *VD = dyn_cast<VarDecl>(DRE->
getDecl()))
24571 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24572 MVLI.VarComponents, MVLI.UDMapperList, IteratorExpr, Modifiers,
24580 MappableVarListInfo MVLI(VarList);
24584 for (
Expr *RefExpr : VarList) {
24585 assert(RefExpr &&
"NULL expr in OpenMP use_device_ptr clause.");
24588 Expr *SimpleRefExpr = RefExpr;
24592 MVLI.ProcessedVarList.push_back(RefExpr);
24593 PrivateCopies.push_back(
nullptr);
24594 Inits.push_back(
nullptr);
24601 Type =
Type.getNonReferenceType().getUnqualifiedType();
24603 auto *VD = dyn_cast<VarDecl>(D);
24607 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
24608 << 0 << RefExpr->getSourceRange();
24617 if (VDPrivate->isInvalidDecl())
24620 SemaRef.CurContext->addDecl(VDPrivate);
24622 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
24629 SemaRef.AddInitializerToDecl(
24630 VDPrivate,
SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
24638 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
24639 PrivateCopies.push_back(VDPrivateRefExpr);
24640 Inits.push_back(VDInitRefExpr);
24645 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
24649 MVLI.VarBaseDeclarations.push_back(D);
24650 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24651 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
24655 if (MVLI.ProcessedVarList.empty())
24659 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
24660 MVLI.VarBaseDeclarations, MVLI.VarComponents);
24666 MappableVarListInfo MVLI(VarList);
24668 for (
Expr *RefExpr : VarList) {
24669 assert(RefExpr &&
"NULL expr in OpenMP use_device_addr clause.");
24672 Expr *SimpleRefExpr = RefExpr;
24678 MVLI.ProcessedVarList.push_back(RefExpr);
24683 auto *VD = dyn_cast<VarDecl>(D);
24690 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
24695 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
24701 SemaRef, RefExpr, CurComponents, OMPC_use_device_addr,
24708 assert(!CurComponents.empty() &&
24709 "use_device_addr clause expression with no components!");
24726 CurComponents,
DSAStack->getCurrentDirective());
24727 const Expr *AttachPtrExpr = AttachPtrResult.first;
24729 if (AttachPtrExpr) {
24731 bool IsValidBase =
false;
24734 IsValidBase =
true;
24735 else if (
const auto *ME = dyn_cast<MemberExpr>(BaseExpr);
24737 IsValidBase =
true;
24739 if (!IsValidBase) {
24741 diag::err_omp_expected_base_pointer_var_name_member_expr)
24742 << (
SemaRef.getCurrentThisType().isNull() ? 0 : 1)
24749 ValueDecl *CurDeclaration = CurComponents.back().getAssociatedDeclaration();
24752 "Unexpected null decl for use_device_addr clause.");
24754 MVLI.VarBaseDeclarations.push_back(CurDeclaration);
24755 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24756 MVLI.VarComponents.back().append(CurComponents.begin(),
24757 CurComponents.end());
24760 if (MVLI.ProcessedVarList.empty())
24764 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24765 MVLI.VarComponents);
24771 MappableVarListInfo MVLI(VarList);
24772 for (
Expr *RefExpr : VarList) {
24773 assert(RefExpr &&
"NULL expr in OpenMP is_device_ptr clause.");
24776 Expr *SimpleRefExpr = RefExpr;
24780 MVLI.ProcessedVarList.push_back(RefExpr);
24790 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
24791 << 0 << RefExpr->getSourceRange();
24797 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
24800 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
24803 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
24809 const Expr *ConflictExpr;
24810 if (
DSAStack->checkMappableExprComponentListsForDecl(
24815 ConflictExpr = R.front().getAssociatedExpression();
24818 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
24827 SimpleRefExpr, D,
false);
24828 DSAStack->addMappableExpressionComponents(
24829 D, MC, OMPC_is_device_ptr);
24832 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
24839 "Unexpected device pointer expression!");
24840 MVLI.VarBaseDeclarations.push_back(
24842 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24843 MVLI.VarComponents.back().push_back(MC);
24846 if (MVLI.ProcessedVarList.empty())
24850 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24851 MVLI.VarComponents);
24857 MappableVarListInfo MVLI(VarList);
24858 for (
Expr *RefExpr : VarList) {
24859 assert(RefExpr &&
"NULL expr in OpenMP has_device_addr clause.");
24862 Expr *SimpleRefExpr = RefExpr;
24867 MVLI.ProcessedVarList.push_back(RefExpr);
24875 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
24878 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
24881 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
24887 const Expr *ConflictExpr;
24888 if (
DSAStack->checkMappableExprComponentListsForDecl(
24893 ConflictExpr = R.front().getAssociatedExpression();
24896 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
24904 Expr *Component = SimpleRefExpr;
24905 auto *VD = dyn_cast<VarDecl>(D);
24909 SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
24911 Component, D,
false);
24912 DSAStack->addMappableExpressionComponents(
24913 D, MC, OMPC_has_device_addr);
24916 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
24919 assert(Ref &&
"has_device_addr capture failed");
24920 MVLI.ProcessedVarList.push_back(Ref);
24922 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
24929 "Unexpected device pointer expression!");
24930 MVLI.VarBaseDeclarations.push_back(
24932 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24933 MVLI.VarComponents.back().push_back(MC);
24936 if (MVLI.ProcessedVarList.empty())
24940 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24941 MVLI.VarComponents);
24955 bool AllocDependent =
24959 if (!AllocDependent) {
24968 AllocatorRes =
SemaRef.PerformImplicitConversion(
24969 AllocatorRes.
get(),
DSAStack->getOMPAllocatorHandleT(),
24974 Allocator = AllocatorRes.
isUsable() ? AllocatorRes.
get() :
nullptr;
24984 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
24991 if (!AlignmentDependent) {
24994 Alignment = AlignResult.
isUsable() ? AlignResult.
get() :
nullptr;
24999 for (
Expr *RefExpr : VarList) {
25000 assert(RefExpr &&
"NULL expr in OpenMP allocate clause.");
25003 Expr *SimpleRefExpr = RefExpr;
25007 Vars.push_back(RefExpr);
25013 auto *VD = dyn_cast<VarDecl>(D);
25015 if (!VD && !
SemaRef.CurContext->isDependentContext())
25017 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
25018 ? RefExpr->IgnoreParens()
25026 DSAStack->addInnerAllocatorExpr(Allocator);
25029 getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
25030 FirstAllocateModifier, FirstAllocateModifierLoc, SecondAllocateModifier,
25031 SecondAllocateModifierLoc, EndLoc, Vars);
25039 for (
Expr *RefExpr : VarList) {
25040 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
25043 Expr *SimpleRefExpr = RefExpr;
25047 Vars.push_back(RefExpr);
25054 if (
const Expr *PrevRef =
25055 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
25056 Diag(ELoc, diag::err_omp_used_in_clause_twice)
25058 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
25063 Vars.push_back(RefExpr);
25080 SemaRef.setFunctionHasBranchProtectedScope();
25082 return OMPScopeDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses,
25091 for (
Expr *RefExpr : VarList) {
25092 assert(RefExpr &&
"NULL expr in OpenMP inclusive clause.");
25095 Expr *SimpleRefExpr = RefExpr;
25100 Vars.push_back(RefExpr);
25105 const DSAStackTy::DSAVarData DVar =
25111 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
25112 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
25113 << RefExpr->getSourceRange();
25115 if (
DSAStack->getParentDirective() != OMPD_unknown)
25116 DSAStack->markDeclAsUsedInScanDirective(D);
25117 Vars.push_back(RefExpr);
25132 for (
Expr *RefExpr : VarList) {
25133 assert(RefExpr &&
"NULL expr in OpenMP exclusive clause.");
25136 Expr *SimpleRefExpr = RefExpr;
25141 Vars.push_back(RefExpr);
25147 DSAStackTy::DSAVarData DVar;
25148 if (ParentDirective != OMPD_unknown)
25149 DVar =
DSAStack->getTopDSA(D,
true);
25154 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
25155 DVar.Modifier != OMPC_REDUCTION_inscan) {
25156 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
25157 << RefExpr->getSourceRange();
25159 DSAStack->markDeclAsUsedInScanDirective(D);
25161 Vars.push_back(RefExpr);
25173 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
25174 if (!OMPAlloctraitT.
isNull())
25179 S.
Diag(Loc, diag::err_omp_implied_type_not_found) <<
"omp_alloctrait_t";
25182 Stack->setOMPAlloctraitT(PT.
get());
25202 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
25203 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
25204 StringRef Allocator =
25205 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
25207 PredefinedAllocators.insert(
SemaRef.LookupSingleName(
25213 Expr *AllocatorExpr =
nullptr;
25221 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
25222 bool IsPredefinedAllocator =
false;
25224 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
25226 IsPredefinedAllocator =
25228 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
25232 bool IsTypeCompatible = IsPredefinedAllocator;
25233 IsTypeCompatible = IsTypeCompatible ||
25234 Context.hasSameUnqualifiedType(AllocatorExprType,
25235 OMPAllocatorHandleT);
25237 IsTypeCompatible ||
25238 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
25239 bool IsNonConstantLValue =
25241 if (!DRE || !IsTypeCompatible ||
25242 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
25244 <<
"omp_allocator_handle_t" << (DRE ? 1 : 0)
25253 diag::err_omp_predefined_allocator_with_traits)
25266 diag::err_omp_nonpredefined_allocator_without_traits);
25272 AllocatorExpr =
SemaRef.DefaultLvalueConversion(AllocatorExpr).get();
25275 IsPredefinedAllocator
25276 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
25277 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
25279 Expr *AllocatorTraitsExpr =
nullptr;
25293 if (
const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
25294 TraitTy = ConstArrayTy->getElementType();
25296 !(Context.hasSameUnqualifiedType(TraitTy,
25298 Context.typesAreCompatible(TraitTy,
DSAStack->getOMPAlloctraitT(),
25301 diag::err_omp_expected_array_alloctraits)
25302 << AllocatorTraitsExpr->
getType();
25307 if (
auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
25310 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
25327 for (
Expr *RefExpr : Locators) {
25328 assert(RefExpr &&
"NULL expr in OpenMP affinity clause.");
25331 Vars.push_back(RefExpr);
25339 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
25340 << 1 << 0 << RefExpr->getSourceRange();
25351 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
25352 << 1 << 0 << RefExpr->getSourceRange();
25359 ColonLoc, EndLoc, Modifier, Vars);
25368 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
25376 LParenLoc, EndLoc);
25383 Expr *ValExpr = Size;
25384 Stmt *HelperValStmt =
nullptr;
25395 DKind, OMPC_ompx_dyn_cgroup_mem,
getLangOpts().OpenMP);
25396 if (CaptureRegion != OMPD_unknown &&
25397 !
SemaRef.CurContext->isDependentContext()) {
25398 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
25399 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
25400 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
25405 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
25420 diag::err_omp_unexpected_clause_value)
25421 << Values << getOpenMPClauseName(OMPC_dyn_groupprivate);
25425 Expr *ValExpr = Size;
25426 Stmt *HelperValStmt =
nullptr;
25437 DKind, OMPC_dyn_groupprivate,
getLangOpts().OpenMP);
25438 if (CaptureRegion != OMPD_unknown &&
25439 !
SemaRef.CurContext->isDependentContext()) {
25440 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
25441 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
25442 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
25447 StartLoc, LParenLoc, EndLoc, ValExpr, HelperValStmt, CaptureRegion, M1,
25456 if (
DSAStack->getCurrentDirective() == OMPD_ordered &&
25457 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
25458 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
25459 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
25460 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
25466 DSAStackTy::OperatorOffsetTy OpsOffs;
25467 llvm::APSInt TotalDepCount(32);
25470 DepType == OMPC_DOACROSS_source ||
25471 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
25472 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
25474 Vars = VarOffset.Vars;
25475 OpsOffs = VarOffset.OpsOffs;
25476 TotalDepCount = VarOffset.TotalDepCount;
25478 EndLoc, DepType, DepLoc, ColonLoc, Vars,
25479 TotalDepCount.getZExtValue());
25480 if (
DSAStack->isParentOrderedRegion())
25481 DSAStack->addDoacrossDependClause(
C, OpsOffs);
25510 case OMPC_contains:
25513 llvm_unreachable(
"Unexpected OpenMP clause");
25521 case OMPC_no_openmp:
25523 case OMPC_no_openmp_routines:
25525 case OMPC_no_parallelism:
25527 case OMPC_no_openmp_constructs:
25530 llvm_unreachable(
"Unexpected OpenMP clause");
25539 if (
Base->hasPlaceholderType() &&
25540 !
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
25553 LowerBound =
Result.get();
25555 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
25575 if (
Base->isTypeDependent() ||
25578 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
25581 Base, LowerBound, Length, Stride, Context.DependentTy,
VK_LValue,
25582 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
25594 Diag(
Base->getExprLoc(), diag::err_omp_typecheck_section_value)
25595 <<
Base->getSourceRange());
25601 if (Res.isInvalid())
25603 diag::err_omp_typecheck_section_not_integer)
25605 LowerBound = Res.get();
25615 if (Res.isInvalid())
25617 diag::err_omp_typecheck_section_not_integer)
25618 << 1 << Length->getSourceRange());
25619 Length = Res.get();
25621 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
25622 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
25623 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
25624 << 1 << Length->getSourceRange();
25631 diag::err_omp_typecheck_section_not_integer)
25633 Stride = Res.
get();
25646 Diag(
Base->getExprLoc(), diag::err_omp_section_function_type)
25647 << ResultTy <<
Base->getSourceRange();
25651 if (
SemaRef.RequireCompleteType(
Base->getExprLoc(), ResultTy,
25652 diag::err_omp_section_incomplete_type,
Base))
25660 llvm::APSInt LowerBoundValue =
Result.Val.getInt();
25661 if (LowerBoundValue.isNegative()) {
25663 diag::err_omp_section_not_subset_of_array)
25672 if (Length->EvaluateAsInt(
Result, Context)) {
25675 llvm::APSInt LengthValue =
Result.Val.getInt();
25676 if (LengthValue.isNegative()) {
25677 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
25678 <<
toString(LengthValue, 10,
true)
25679 << Length->getSourceRange();
25683 }
else if (
SemaRef.getLangOpts().OpenMP < 60 && ColonLocFirst.
isValid() &&
25689 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
25699 llvm::APSInt StrideValue =
Result.Val.getInt();
25700 if (!StrideValue.isStrictlyPositive()) {
25701 Diag(Stride->
getExprLoc(), diag::err_omp_section_stride_non_positive)
25702 <<
toString(StrideValue, 10,
true)
25709 if (!
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
25716 Base, LowerBound, Length, Stride, Context.ArraySectionTy,
VK_LValue,
25717 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
25724 if (
Base->hasPlaceholderType()) {
25738 LParenLoc, RParenLoc, Dims, Brackets);
25740 (!
Base->isTypeDependent() &&
25743 diag::err_omp_non_pointer_type_array_shaping_base)
25744 <<
Base->getSourceRange());
25747 bool ErrorFound =
false;
25749 if (
Dim->hasPlaceholderType()) {
25751 if (
Result.isInvalid()) {
25756 if (
Result.isInvalid()) {
25762 if (!
Dim->isTypeDependent()) {
25765 if (
Result.isInvalid()) {
25767 Diag(
Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
25768 <<
Dim->getSourceRange();
25773 if (!
Dim->isValueDependent() &&
Dim->EvaluateAsInt(EvResult, Context)) {
25778 if (!
Value.isStrictlyPositive()) {
25779 Diag(
Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
25781 <<
Dim->getSourceRange();
25787 NewDims.push_back(
Dim);
25792 LParenLoc, RParenLoc, NewDims, Brackets);
25802 bool IsCorrect =
true;
25807 if (!D.Type.getAsOpaquePtr()) {
25811 DeclTy = Context.IntTy;
25812 StartLoc = D.DeclIdentLoc;
25818 bool IsDeclTyDependent = DeclTy->isDependentType() ||
25819 DeclTy->containsUnexpandedParameterPack() ||
25820 DeclTy->isInstantiationDependentType();
25821 if (!IsDeclTyDependent) {
25822 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
25825 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
25830 if (DeclTy.isConstant(Context)) {
25833 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
25841 assert(D.DeclIdent &&
"Identifier expected.");
25846 D.DeclIdent, DeclTy, TInfo,
SC_None);
25864 SemaRef.PushOnScopeChains(VD, S);
25867 SemaRef.CurContext->addDecl(VD);
25873 Expr *Begin = D.Range.Begin;
25877 Begin = BeginRes.
get();
25879 Expr *End = D.Range.End;
25883 End = EndRes.
get();
25885 Expr *Step = D.Range.Step;
25888 Diag(Step->
getExprLoc(), diag::err_omp_iterator_step_not_integral)
25893 std::optional<llvm::APSInt>
Result =
25899 Diag(Step->
getExprLoc(), diag::err_omp_iterator_step_constant_zero)
25905 if (!Begin || !End || !IsCorrect) {
25921 if (
Decl *ID = D.IteratorDecl)
25922 ID->setInvalidDecl();
25927 if (!
SemaRef.CurContext->isDependentContext()) {
25934 D.Range.End, D.Range.Begin);
25940 if (D.Range.Step) {
25943 Res =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.
get(),
25950 Res =
SemaRef.CreateBuiltinBinOp(
25951 D.AssignmentLoc, BO_Sub, Res.
get(),
25952 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
25958 Res =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.
get(),
25964 St1 =
SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus,
25968 D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End);
25974 Res1 =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.
get(),
25981 Res1 =
SemaRef.CreateBuiltinBinOp(
25982 D.AssignmentLoc, BO_Sub, Res1.
get(),
25983 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
25989 Res1 =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.
get(),
25997 D.AssignmentLoc, BO_GT, D.Range.Step,
25998 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get());
26003 Res =
SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc,
26010 Res =
SemaRef.ActOnFinishFullExpr(Res.
get(),
false);
26022 CounterVD->setImplicit();
26029 if (D.Range.Step) {
26030 UpdateRes =
SemaRef.CreateBuiltinBinOp(
26031 D.AssignmentLoc, BO_Mul,
26032 SemaRef.DefaultLvalueConversion(RefRes.
get()).get(), St.
get());
26034 UpdateRes =
SemaRef.DefaultLvalueConversion(RefRes.
get());
26040 UpdateRes =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add,
26041 D.Range.Begin, UpdateRes.
get());
26050 UpdateRes =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign,
26051 VDRes.
get(), UpdateRes.
get());
26057 SemaRef.ActOnFinishFullExpr(UpdateRes.
get(),
true);
26063 D.AssignmentLoc, UO_PreInc, RefRes.
get());
26064 if (!CounterUpdateRes.
isUsable()) {
26068 CounterUpdateRes =
SemaRef.ActOnFinishFullExpr(CounterUpdateRes.
get(),
26070 if (!CounterUpdateRes.
isUsable()) {
26081 Helpers.assign(ID.size(), {});
26086 if (
Decl *ID = D.IteratorDecl)
26087 ID->setInvalidDecl();
26092 LLoc, RLoc, ID, Helpers);
26097 StringRef AssumptionStr) {
26098 if (llvm::getKnownAssumptionStrings().count(AssumptionStr))
26101 unsigned BestEditDistance = 3;
26102 StringRef Suggestion;
26103 for (
const auto &KnownAssumptionIt : llvm::getKnownAssumptionStrings()) {
26104 unsigned EditDistance =
26105 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
26106 if (EditDistance < BestEditDistance) {
26107 Suggestion = KnownAssumptionIt.getKey();
26108 BestEditDistance = EditDistance;
26112 if (!Suggestion.empty())
26113 S.
Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
26114 << AssumptionStr << Suggestion;
26116 S.
Diag(Loc, diag::warn_omp_assume_attribute_string_unknown)
26124 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 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 OMPAssumeDirective * Create(const ASTContext &Ctx, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AStmt)
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.
static OMPDispatchDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, SourceLocation TargetCallLoc)
Creates directive with a list of Clauses.
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.
static OMPErrorDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
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.
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 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.
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.
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'.
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 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 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'.
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 OMPAbsentClause * Create(const ASTContext &C, ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
This represents 'acq_rel' clause in the 'pragma omp atomic|flush' directives.
This represents 'acquire' clause in the 'pragma omp atomic|flush' directives.
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 OMPAlignClause * Create(const ASTContext &C, Expr *A, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'align' clause with the given alignment.
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 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)
This represents 'at' clause in the 'pragma omp error' directive.
SourceLocation getAtKindKwLoc() const
Returns location of clause kind.
OpenMPAtClauseKind getAtKind() const
Returns kind of the clause.
This represents 'atomic_default_mem_order' clause in the 'pragma omp requires' directive.
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').
This represents 'capture' clause in the 'pragma omp atomic' directive.
Pseudo declaration for capturing expressions.
static OMPCapturedExprDecl * Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, QualType T, SourceLocation StartLoc)
Class that represents a component of a mappable expression.
ValueDecl * getAssociatedDeclaration() const
ArrayRef< MappableComponent > MappableExprComponentListRef
SmallVector< MappableComponent, 8 > MappableExprComponentList
SmallVector< MappableExprComponentList, 8 > MappableExprComponentLists
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.
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 'compare' clause in the 'pragma omp atomic' directive.
static OMPContainsClause * Create(const ASTContext &C, ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
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 '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 '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.
This represents 'dist_schedule' clause in the 'pragma omp ...' directive.
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 ....
This represents 'dynamic_allocators' clause in the 'pragma omp requires' directive.
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 'fail' clause in the 'pragma omp atomic' directive.
This represents 'filter' clause in the 'pragma omp ...' directive.
This represents 'final' clause in the 'pragma omp ...' directive.
static OMPFirstprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PrivateVL, ArrayRef< Expr * > InitVL, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents implicit clause 'flush' for the 'pragma omp flush' directive.
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.
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 'grainsize' clause in the 'pragma omp ...' directive.
This represents 'pragma omp groupprivate ...' directive.
static OMPGroupPrivateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL)
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.
This represents the 'holds' clause in the 'pragma omp assume' directive.
This represents 'if' clause in the 'pragma omp ...' directive.
static OMPInReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, ArrayRef< Expr * > TaskgroupDescriptors, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
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 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 OMPIteratorExpr * Create(const ASTContext &Context, QualType T, SourceLocation IteratorKwLoc, SourceLocation L, SourceLocation R, ArrayRef< IteratorDefinition > Data, ArrayRef< OMPIteratorHelperData > Helpers)
This represents clause 'lastprivate' in the 'pragma omp ...' directives.
static OMPLastprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps, OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, SourceLocation ColonLoc, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
This represents clause 'linear' in the 'pragma omp ...' directives.
static OMPLinearClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation StepModifierLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PL, ArrayRef< Expr * > IL, Expr *Step, Expr *CalcStep, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL and a linear step Step.
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.
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.
This represents 'mergeable' clause in the 'pragma omp ...' directive.
This represents the 'message' clause in the 'pragma omp error' and the 'pragma omp parallel' directiv...
Expr * getMessageString() const
Returns message string of the clause.
std::optional< std::string > tryEvaluateString(ASTContext &Ctx) const
Try to evaluate the message string at compile time.
This represents the 'no_openmp' clause in the 'pragma omp assume' directive.
This represents the 'no_openmp_constructs' clause in the.
This represents the 'no_openmp_routines' clause in the 'pragma omp assume' directive.
This represents the 'no_parallelism' clause in the 'pragma omp assume' directive.
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 'nowait' 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 'num_threads' clause in the 'pragma omp ...' directive.
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.
This represents 'ordered' clause in the 'pragma omp ...' directive.
Expr * getNumForLoops() const
Return the number of associated for-loops.
static OMPOrderedClause * Create(const ASTContext &C, Expr *Num, unsigned NumLoops, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'ordered' clause.
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 'priority' clause in the 'pragma omp ...' directive.
static OMPPrivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PrivateVL)
Creates clause with a list of variables VL.
This represents 'proc_bind' clause in the 'pragma omp ...' directive.
This represents 'read' clause in the 'pragma omp atomic' directive.
static OMPReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, OpenMPReductionClauseModifier Modifier, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, ArrayRef< Expr * > CopyOps, ArrayRef< Expr * > CopyArrayTemps, ArrayRef< Expr * > CopyArrayElems, Stmt *PreInit, Expr *PostUpdate, ArrayRef< bool > IsPrivateVarReduction, OpenMPOriginalSharingModifier OriginalSharingModifier)
Creates clause with a list of variables VL.
This represents 'relaxed' clause in the 'pragma omp atomic' directives.
This represents 'release' clause in the 'pragma omp atomic|flush' directives.
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 'reverse_offload' clause in the 'pragma omp requires' directive.
This represents 'simd' clause in the 'pragma omp ...' directive.
This represents 'safelen' clause in the 'pragma omp ...' directive.
Expr * getSafelen() const
Return safe iteration space distance.
This represents 'schedule' clause in the 'pragma omp ...' directive.
SourceLocation getFirstScheduleModifierLoc() const
Get the first modifier location.
OpenMPScheduleClauseModifier getSecondScheduleModifier() const
Get the second modifier of the clause.
OpenMPScheduleClauseModifier getFirstScheduleModifier() const
Get the first modifier of the clause.
SourceLocation getSecondScheduleModifierLoc() const
Get the second modifier location.
This represents 'self_maps' clause in the 'pragma omp requires' directive.
This represents 'seq_cst' clause in the 'pragma omp atomic|flush' directives.
This represents the 'severity' clause in the 'pragma omp error' and the 'pragma omp parallel' directi...
OpenMPSeverityClauseKind getSeverityKind() const
Returns kind of the clause.
SourceLocation getSeverityKindKwLoc() const
Returns location of clause kind.
static OMPSharedClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
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.
static OMPTaskReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
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 'pragma omp threadprivate ...' directive.
static OMPThreadPrivateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL)
This represents 'threads' clause in the 'pragma omp ...' directive.
This represents 'threadset' clause in the 'pragma omp task ...' directive.
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.
Helper data structure representing the traits in a match clause of an declare variant or metadirectiv...
bool isExtensionActive(llvm::omp::TraitProperty TP)
Check the extension trait TP is active.
bool anyScoreOrCondition(llvm::function_ref< bool(Expr *&, bool)> Cond)
void getAsVariantMatchInfo(ASTContext &ASTCtx, llvm::omp::VariantMatchInfo &VMI) const
Create a variant match info object from this trait info object.
This represents 'unified_address' clause in the 'pragma omp requires' directive.
This represents 'unified_shared_memory' clause in the 'pragma omp requires' directive.
This represents 'untied' clause in the 'pragma omp ...' directive.
static OMPUpdateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates clause for 'atomic' directive.
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)
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.
SourceLocation getLParenLoc() const
Returns the location of '('.
This represents 'weak' clause in the 'pragma omp atomic' directives.
This represents 'write' clause in the 'pragma omp atomic' directive.
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.
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,...
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...
OMPClause * ActOnOpenMPUseDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'use_device_ptr' clause.
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 * 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
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
bool isOpenMPNestingTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a teams directive in the outermost n...
bool isa(CodeGen::Address addr)
bool checkFailClauseParameter(OpenMPClauseKind FailClauseParameter)
Checks if the parameter to the fail clause in "#pragma atomic compare fail" is restricted only to mem...
MutableArrayRef< TemplateParameterList * > MultiTemplateParamsArg
bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target data offload directive.
OpenMPDefaultClauseVariableCategory
OpenMP variable-category for 'default' clause.
@ OMPC_DEFAULT_VC_unknown
bool isOpenMPLoopTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive.
OpenMPDefaultmapClauseModifier
OpenMP modifiers for 'defaultmap' clause.
@ OMPC_DEFAULTMAP_MODIFIER_last
@ OMPC_DEFAULTMAP_MODIFIER_unknown
OpenMPOrderClauseModifier
OpenMP modifiers for 'order' clause.
@ OMPC_ORDER_MODIFIER_unknown
@ OMPC_ORDER_MODIFIER_last
@ Comparison
A comparison.
ExprObjectKind
A further classification of the kind of object referenced by an l-value or x-value.
@ OK_Ordinary
An ordinary object is located at an address in memory.
OpenMPAtClauseKind
OpenMP attributes for 'at' clause.
Expr * AssertSuccess(ExprResult R)
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
@ LCK_This
Capturing the *this object by reference.
OpenMPReductionClauseModifier
OpenMP modifiers for 'reduction' clause.
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
@ OMPC_SCHEDULE_MODIFIER_last
@ OMPC_SCHEDULE_MODIFIER_unknown
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
SmallVector< Attr *, 4 > AttrVec
AttrVec - A vector of Attr, which is how they are stored on the AST.
ActionResult< Decl * > DeclResult
const char * getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
bool isOpenMPPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of private clauses like 'private', 'firstprivate',...
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
@ OMPC_DIST_SCHEDULE_unknown
static constexpr StringRef getOpenMPVariantManglingSeparatorStr()
OpenMP variants are mangled early based on their OpenMP context selector.
OpenMPDoacrossClauseModifier
OpenMP dependence types for 'doacross' clause.
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
static constexpr unsigned NumberOfOMPMapClauseModifiers
Number of allowed map-type-modifiers.
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
OpenMPDynGroupprivateClauseFallbackModifier
@ OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown
MutableArrayRef< Expr * > MultiExprArg
@ SD_Static
Static storage duration.
@ Parameter
The parameter type of a method or function.
@ Result
The result type of a method or function.
ActionResult< ParsedType > TypeResult
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
bool isOpenMPGenericLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive constitutes a 'loop' directive in the outermost nest.
OpenMPBindClauseKind
OpenMP bindings for the 'bind' clause.
const FunctionProtoType * T
OpenMPLastprivateModifier
OpenMP 'lastprivate' clause modifier.
@ OMPC_LASTPRIVATE_unknown
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
bool isOpenMPCanonicalLoopSequenceTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive that applies to a canonical loop...
OpenMPGrainsizeClauseModifier
bool IsXLHSInRHSPart
True if UE has the first form and false if the second.
bool IsPostfixUpdate
True if original value of 'x' must be stored in 'v', not an updated one.
bool isOpenMPCanonicalLoopNestTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive that applies to a canonical loop...
OpenMPNumTasksClauseModifier
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
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.
Data for list of allocators.
SourceLocation LParenLoc
Locations of '(' and ')' symbols.
Expr * AllocatorTraits
Allocator traits.
Expr * Allocator
Allocator.
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.
Clang specific specialization of the OMPContext to lookup target features.