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 {
95 unsigned Modifier = 0;
96 const Expr *RefExpr =
nullptr;
97 DeclRefExpr *PrivateCopy =
nullptr;
98 SourceLocation ImplicitDSALoc;
99 bool AppliedToPointee =
false;
100 DSAVarData() =
default;
102 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
103 SourceLocation ImplicitDSALoc,
unsigned Modifier,
104 bool AppliedToPointee)
105 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
106 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
107 AppliedToPointee(AppliedToPointee) {}
109 using OperatorOffsetTy =
110 llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
111 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
113 enum class UsesAllocatorsDeclKind {
117 UserDefinedAllocator,
125 unsigned Modifier = 0;
128 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
129 DeclRefExpr *PrivateCopy =
nullptr;
132 bool AppliedToPointee =
false;
134 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
135 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
136 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
137 using LoopControlVariablesMapTy =
138 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
141 struct MappedExprComponentTy {
145 using MappedExprComponentsTy =
146 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
147 using CriticalsWithHintsTy =
148 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
149 struct ReductionData {
150 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
151 SourceRange ReductionRange;
152 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
153 ReductionData() =
default;
158 void set(
const Expr *RefExpr, SourceRange RR) {
160 ReductionOp = RefExpr;
163 using DeclReductionMapTy =
164 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
165 struct DefaultmapInfo {
169 DefaultmapInfo() =
default;
171 : ImplicitBehavior(M), SLoc(Loc) {}
174 struct SharingMapTy {
175 DeclSAMapTy SharingMap;
176 DeclReductionMapTy ReductionMap;
177 UsedRefMapTy AlignedMap;
178 UsedRefMapTy NontemporalMap;
179 MappedExprComponentsTy MappedExprComponents;
180 LoopControlVariablesMapTy LCVMap;
181 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
182 SourceLocation DefaultAttrLoc;
183 DefaultDataSharingVCAttributes DefaultVCAttr = DSA_VC_all;
184 SourceLocation DefaultAttrVCLoc;
187 DeclarationNameInfo DirectiveName;
188 Scope *CurScope =
nullptr;
189 DeclContext *Context =
nullptr;
190 SourceLocation ConstructLoc;
194 DoacrossClauseMapTy DoacrossDepends;
198 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
199 bool RegionHasOrderConcurrent =
false;
200 unsigned AssociatedLoops = 1;
201 bool HasMutipleLoops =
false;
202 const Decl *PossiblyLoopCounter =
nullptr;
203 bool NowaitRegion =
false;
204 bool UntiedRegion =
false;
205 bool CancelRegion =
false;
206 bool LoopStart =
false;
207 bool BodyComplete =
false;
208 SourceLocation PrevScanLocation;
209 SourceLocation PrevOrderedLocation;
210 SourceLocation InnerTeamsRegionLoc;
212 Expr *TaskgroupReductionRef =
nullptr;
213 llvm::DenseSet<QualType> MappedClassesQualTypes;
214 SmallVector<Expr *, 4> InnerUsedAllocators;
215 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
218 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
220 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
221 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
225 struct ImplicitDefaultFDInfoTy {
227 const FieldDecl *FD =
nullptr;
229 size_t StackLevel = 0;
231 VarDecl *VD =
nullptr;
232 ImplicitDefaultFDInfoTy(
const FieldDecl *FD,
size_t StackLevel,
234 : FD(FD), StackLevel(StackLevel), VD(VD) {}
237 llvm::SmallVector<ImplicitDefaultFDInfoTy, 8>
238 ImplicitDefaultFirstprivateFDs;
239 Expr *DeclareMapperVar =
nullptr;
240 SmallVector<VarDecl *, 16> IteratorVarDecls;
242 Scope *CurScope, SourceLocation Loc)
243 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
245 SharingMapTy() =
default;
248 using StackTy = SmallVector<SharingMapTy, 4>;
251 DeclSAMapTy Threadprivates;
252 DeclSAMapTy Groupprivates;
253 const FunctionScopeInfo *CurrentNonCapturingFunctionScope =
nullptr;
254 SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack;
259 bool ForceCapturing =
false;
262 bool ForceCaptureByReferenceInTargetExecutable =
false;
263 CriticalsWithHintsTy Criticals;
264 unsigned IgnoredStackElements = 0;
268 using const_iterator = StackTy::const_reverse_iterator;
269 const_iterator begin()
const {
270 return Stack.empty() ? const_iterator()
271 : Stack.back().first.rbegin() + IgnoredStackElements;
273 const_iterator end()
const {
274 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
276 using iterator = StackTy::reverse_iterator;
278 return Stack.empty() ? iterator()
279 : Stack.back().first.rbegin() + IgnoredStackElements;
282 return Stack.empty() ? iterator() : Stack.back().first.rend();
287 bool isStackEmpty()
const {
288 return Stack.empty() ||
289 Stack.back().second != CurrentNonCapturingFunctionScope ||
290 Stack.back().first.size() <= IgnoredStackElements;
292 size_t getStackSize()
const {
293 return isStackEmpty() ? 0
294 : Stack.back().first.size() - IgnoredStackElements;
297 SharingMapTy *getTopOfStackOrNull() {
298 size_t Size = getStackSize();
301 return &Stack.back().first[
Size - 1];
303 const SharingMapTy *getTopOfStackOrNull()
const {
304 return const_cast<DSAStackTy &
>(*this).getTopOfStackOrNull();
306 SharingMapTy &getTopOfStack() {
307 assert(!isStackEmpty() &&
"no current directive");
308 return *getTopOfStackOrNull();
310 const SharingMapTy &getTopOfStack()
const {
311 return const_cast<DSAStackTy &
>(*this).getTopOfStack();
314 SharingMapTy *getSecondOnStackOrNull() {
315 size_t Size = getStackSize();
318 return &Stack.back().first[
Size - 2];
320 const SharingMapTy *getSecondOnStackOrNull()
const {
321 return const_cast<DSAStackTy &
>(*this).getSecondOnStackOrNull();
330 SharingMapTy &getStackElemAtLevel(
unsigned Level) {
331 assert(Level < getStackSize() &&
"no such stack element");
332 return Stack.back().first[
Level];
334 const SharingMapTy &getStackElemAtLevel(
unsigned Level)
const {
335 return const_cast<DSAStackTy &
>(*this).getStackElemAtLevel(Level);
338 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D)
const;
341 bool isOpenMPLocal(VarDecl *D, const_iterator Iter)
const;
344 SmallVector<const OMPRequiresDecl *, 2> RequiresDecls;
346 QualType OMPAllocatorHandleT;
350 QualType OMPEventHandleT;
352 QualType OMPAlloctraitT;
354 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
357 SmallVector<SourceLocation, 2> TargetLocations;
358 SourceLocation AtomicLocation;
360 SmallVector<llvm::omp::TraitProperty, 8> ConstructTraits;
363 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
366 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
368 QualType getOMPAllocatorHandleT()
const {
return OMPAllocatorHandleT; }
370 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
372 QualType getOMPAlloctraitT()
const {
return OMPAlloctraitT; }
374 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
376 OMPPredefinedAllocators[AllocatorKind] = Allocator;
379 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind)
const {
380 return OMPPredefinedAllocators[AllocatorKind];
383 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
385 QualType getOMPDependT()
const {
return OMPDependT; }
388 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
390 QualType getOMPEventHandleT()
const {
return OMPEventHandleT; }
392 bool isClauseParsingMode()
const {
return ClauseKindMode != OMPC_unknown; }
394 assert(isClauseParsingMode() &&
"Must be in clause parsing mode.");
395 return ClauseKindMode;
399 bool isBodyComplete()
const {
400 const SharingMapTy *Top = getTopOfStackOrNull();
401 return Top && Top->BodyComplete;
403 void setBodyComplete() { getTopOfStack().BodyComplete =
true; }
405 bool isForceVarCapturing()
const {
return ForceCapturing; }
406 void setForceVarCapturing(
bool V) { ForceCapturing =
V; }
408 void setForceCaptureByReferenceInTargetExecutable(
bool V) {
409 ForceCaptureByReferenceInTargetExecutable =
V;
411 bool isForceCaptureByReferenceInTargetExecutable()
const {
412 return ForceCaptureByReferenceInTargetExecutable;
416 Scope *CurScope, SourceLocation Loc) {
417 assert(!IgnoredStackElements &&
418 "cannot change stack while ignoring elements");
420 Stack.back().second != CurrentNonCapturingFunctionScope)
421 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
422 Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc);
423 Stack.back().first.back().DefaultAttrLoc = Loc;
427 assert(!IgnoredStackElements &&
428 "cannot change stack while ignoring elements");
429 assert(!Stack.back().first.empty() &&
430 "Data-sharing attributes stack is empty!");
431 Stack.back().first.pop_back();
436 class ParentDirectiveScope {
441 ParentDirectiveScope(DSAStackTy &Self,
bool Activate)
442 : Self(Self), Active(
false) {
446 ~ParentDirectiveScope() { disable(); }
449 --Self.IgnoredStackElements;
455 ++Self.IgnoredStackElements;
464 "Expected loop-based directive.");
465 getTopOfStack().LoopStart =
true;
470 "Expected loop-based directive.");
471 getTopOfStack().LoopStart =
false;
474 bool isLoopStarted()
const {
476 "Expected loop-based directive.");
477 return !getTopOfStack().LoopStart;
480 void resetPossibleLoopCounter(
const Decl *D =
nullptr) {
481 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
484 const Decl *getPossiblyLoopCounter()
const {
485 return getTopOfStack().PossiblyLoopCounter;
488 void pushFunction() {
489 assert(!IgnoredStackElements &&
490 "cannot change stack while ignoring elements");
491 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
493 CurrentNonCapturingFunctionScope = CurFnScope;
496 void popFunction(
const FunctionScopeInfo *OldFSI) {
497 assert(!IgnoredStackElements &&
498 "cannot change stack while ignoring elements");
499 if (!Stack.empty() && Stack.back().second == OldFSI) {
500 assert(Stack.back().first.empty());
503 CurrentNonCapturingFunctionScope =
nullptr;
504 for (
const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) {
506 CurrentNonCapturingFunctionScope = FSI;
512 void addCriticalWithHint(
const OMPCriticalDirective *D, llvm::APSInt Hint) {
513 Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint);
515 std::pair<const OMPCriticalDirective *, llvm::APSInt>
516 getCriticalWithHint(
const DeclarationNameInfo &Name)
const {
518 if (I != Criticals.end())
520 return std::make_pair(
nullptr, llvm::APSInt());
525 const Expr *addUniqueAligned(
const ValueDecl *D,
const Expr *NewDE);
529 const Expr *addUniqueNontemporal(
const ValueDecl *D,
const Expr *NewDE);
532 void addLoopControlVariable(
const ValueDecl *D, VarDecl *
Capture);
537 const LCDeclInfo isLoopControlVariable(
const ValueDecl *D)
const;
542 const LCDeclInfo isParentLoopControlVariable(
const ValueDecl *D)
const;
547 const LCDeclInfo isLoopControlVariable(
const ValueDecl *D,
548 unsigned Level)
const;
551 const ValueDecl *getParentLoopControlVariable(
unsigned I)
const;
554 void markDeclAsUsedInScanDirective(ValueDecl *D) {
555 if (SharingMapTy *Stack = getSecondOnStackOrNull())
556 Stack->UsedInScanDirective.insert(D);
560 bool isUsedInScanDirective(ValueDecl *D)
const {
561 if (
const SharingMapTy *Stack = getTopOfStackOrNull())
562 return Stack->UsedInScanDirective.contains(D);
568 DeclRefExpr *PrivateCopy =
nullptr,
unsigned Modifier = 0,
569 bool AppliedToPointee =
false);
573 void addTaskgroupReductionData(
const ValueDecl *D, SourceRange SR,
577 void addTaskgroupReductionData(
const ValueDecl *D, SourceRange SR,
578 const Expr *ReductionRef);
582 getTopMostTaskgroupReductionData(
const ValueDecl *D, SourceRange &SR,
584 Expr *&TaskgroupDescriptor)
const;
588 getTopMostTaskgroupReductionData(
const ValueDecl *D, SourceRange &SR,
589 const Expr *&ReductionRef,
590 Expr *&TaskgroupDescriptor)
const;
593 Expr *getTaskgroupReductionRef()
const {
594 assert((getTopOfStack().
Directive == OMPD_taskgroup ||
598 "taskgroup reference expression requested for non taskgroup or "
599 "parallel/worksharing directive.");
600 return getTopOfStack().TaskgroupReductionRef;
604 bool isTaskgroupReductionRef(
const ValueDecl *VD,
unsigned Level)
const {
605 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
612 const DSAVarData getTopDSA(ValueDecl *D,
bool FromParent);
614 const DSAVarData getImplicitDSA(ValueDecl *D,
bool FromParent)
const;
616 const DSAVarData getImplicitDSA(ValueDecl *D,
unsigned Level)
const;
623 DefaultDataSharingAttributes)>
626 bool FromParent)
const;
631 hasInnermostDSA(ValueDecl *D,
634 bool FromParent)
const;
639 hasExplicitDSA(
const ValueDecl *D,
641 unsigned Level,
bool NotLastprivate =
false)
const;
645 bool hasExplicitDirective(
647 unsigned Level)
const;
651 const llvm::function_ref<
bool(
654 bool FromParent)
const;
658 const SharingMapTy *Top = getTopOfStackOrNull();
659 return Top ? Top->Directive : OMPD_unknown;
663 assert(!isStackEmpty() &&
"No directive at specified level.");
664 return getStackElemAtLevel(Level).Directive;
668 unsigned OpenMPCaptureLevel)
const {
669 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
671 return CaptureRegions[OpenMPCaptureLevel];
675 const SharingMapTy *Parent = getSecondOnStackOrNull();
676 return Parent ? Parent->Directive : OMPD_unknown;
680 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
683 template <
typename ClauseType>
bool hasRequiresDeclWithClause()
const {
684 return llvm::any_of(RequiresDecls, [](
const OMPRequiresDecl *D) {
685 return llvm::any_of(D->
clauselists(), [](
const OMPClause *
C) {
686 return isa<ClauseType>(C);
693 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList)
const {
694 bool IsDuplicate =
false;
695 for (OMPClause *CNew : ClauseList) {
696 for (
const OMPRequiresDecl *D : RequiresDecls) {
697 for (
const OMPClause *CPrev : D->clauselists()) {
698 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
699 SemaRef.Diag(CNew->getBeginLoc(),
700 diag::err_omp_requires_clause_redeclaration)
702 SemaRef.Diag(CPrev->getBeginLoc(),
703 diag::note_omp_requires_previous_clause)
714 void addTargetDirLocation(SourceLocation LocStart) {
715 TargetLocations.push_back(LocStart);
719 void addAtomicDirectiveLoc(SourceLocation Loc) {
720 if (AtomicLocation.isInvalid())
721 AtomicLocation = Loc;
726 SourceLocation getAtomicDirectiveLoc()
const {
return AtomicLocation; }
729 ArrayRef<SourceLocation> getEncounteredTargetLocs()
const {
730 return TargetLocations;
734 void setDefaultDSANone(SourceLocation Loc) {
735 getTopOfStack().DefaultAttr = DSA_none;
736 getTopOfStack().DefaultAttrLoc = Loc;
739 void setDefaultDSAShared(SourceLocation Loc) {
740 getTopOfStack().DefaultAttr = DSA_shared;
741 getTopOfStack().DefaultAttrLoc = Loc;
744 void setDefaultDSAPrivate(SourceLocation Loc) {
745 getTopOfStack().DefaultAttr = DSA_private;
746 getTopOfStack().DefaultAttrLoc = Loc;
749 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
750 getTopOfStack().DefaultAttr = DSA_firstprivate;
751 getTopOfStack().DefaultAttrLoc = Loc;
754 void setDefaultDSAVCAggregate(SourceLocation VCLoc) {
755 getTopOfStack().DefaultVCAttr = DSA_VC_aggregate;
756 getTopOfStack().DefaultAttrVCLoc = VCLoc;
759 void setDefaultDSAVCAll(SourceLocation VCLoc) {
760 getTopOfStack().DefaultVCAttr = DSA_VC_all;
761 getTopOfStack().DefaultAttrVCLoc = VCLoc;
764 void setDefaultDSAVCAllocatable(SourceLocation VCLoc) {
765 getTopOfStack().DefaultVCAttr = DSA_VC_allocatable;
766 getTopOfStack().DefaultAttrVCLoc = VCLoc;
769 void setDefaultDSAVCPointer(SourceLocation VCLoc) {
770 getTopOfStack().DefaultVCAttr = DSA_VC_pointer;
771 getTopOfStack().DefaultAttrVCLoc = VCLoc;
774 void setDefaultDSAVCScalar(SourceLocation VCLoc) {
775 getTopOfStack().DefaultVCAttr = DSA_VC_scalar;
776 getTopOfStack().DefaultAttrVCLoc = VCLoc;
781 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[
Kind];
782 DMI.ImplicitBehavior = M;
788 return getTopOfStack()
789 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
792 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
795 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
797 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
801 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
802 return ConstructTraits;
804 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
807 ConstructTraits.append(Traits.begin(), Traits.end());
809 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
810 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
811 assert(Top == Trait &&
"Something left a trait on the stack!");
817 DefaultDataSharingAttributes getDefaultDSA(
unsigned Level)
const {
818 return getStackSize() <=
Level ? DSA_unspecified
819 : getStackElemAtLevel(Level).DefaultAttr;
821 DefaultDataSharingAttributes getDefaultDSA()
const {
822 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
824 SourceLocation getDefaultDSALocation()
const {
825 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
829 return isStackEmpty()
831 : getTopOfStack().DefaultmapMap[
Kind].ImplicitBehavior;
834 getDefaultmapModifierAtLevel(
unsigned Level,
836 return getStackElemAtLevel(Level).DefaultmapMap[
Kind].ImplicitBehavior;
838 bool isDefaultmapCapturedByRef(
unsigned Level,
841 getDefaultmapModifierAtLevel(Level, Kind);
842 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
843 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
844 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
845 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
846 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom) ||
847 (M == OMPC_DEFAULTMAP_MODIFIER_present) ||
848 (M == OMPC_DEFAULTMAP_MODIFIER_storage);
855 case OMPC_DEFAULTMAP_scalar:
856 case OMPC_DEFAULTMAP_pointer:
858 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
859 (M == OMPC_DEFAULTMAP_MODIFIER_default);
860 case OMPC_DEFAULTMAP_aggregate:
861 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
865 llvm_unreachable(
"Unexpected OpenMPDefaultmapClauseKind enum");
867 bool mustBeFirstprivateAtLevel(
unsigned Level,
870 getDefaultmapModifierAtLevel(Level, Kind);
871 return mustBeFirstprivateBase(M, Kind);
875 return mustBeFirstprivateBase(M, Kind);
879 bool isThreadPrivate(VarDecl *D) {
880 const DSAVarData DVar = getTopDSA(D,
false);
885 void setOrderedRegion(
bool IsOrdered,
const Expr *Param,
886 OMPOrderedClause *Clause) {
888 getTopOfStack().OrderedRegion.emplace(Param, Clause);
890 getTopOfStack().OrderedRegion.reset();
894 bool isOrderedRegion()
const {
895 if (
const SharingMapTy *Top = getTopOfStackOrNull())
896 return Top->OrderedRegion.has_value();
900 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam()
const {
901 if (
const SharingMapTy *Top = getTopOfStackOrNull())
902 if (Top->OrderedRegion)
903 return *Top->OrderedRegion;
904 return std::make_pair(
nullptr,
nullptr);
908 bool isParentOrderedRegion()
const {
909 if (
const SharingMapTy *Parent = getSecondOnStackOrNull())
910 return Parent->OrderedRegion.has_value();
914 std::pair<const Expr *, OMPOrderedClause *>
915 getParentOrderedRegionParam()
const {
916 if (
const SharingMapTy *Parent = getSecondOnStackOrNull())
917 if (Parent->OrderedRegion)
918 return *Parent->OrderedRegion;
919 return std::make_pair(
nullptr,
nullptr);
922 void setRegionHasOrderConcurrent(
bool HasOrderConcurrent) {
923 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
927 bool isParentOrderConcurrent()
const {
928 if (
const SharingMapTy *Parent = getSecondOnStackOrNull())
929 return Parent->RegionHasOrderConcurrent;
933 void setNowaitRegion(
bool IsNowait =
true) {
934 getTopOfStack().NowaitRegion = IsNowait;
938 bool isParentNowaitRegion()
const {
939 if (
const SharingMapTy *Parent = getSecondOnStackOrNull())
940 return Parent->NowaitRegion;
944 void setUntiedRegion(
bool IsUntied =
true) {
945 getTopOfStack().UntiedRegion = IsUntied;
948 bool isUntiedRegion()
const {
949 const SharingMapTy *Top = getTopOfStackOrNull();
950 return Top ? Top->UntiedRegion :
false;
953 void setParentCancelRegion(
bool Cancel =
true) {
954 if (SharingMapTy *Parent = getSecondOnStackOrNull())
955 Parent->CancelRegion |= Cancel;
958 bool isCancelRegion()
const {
959 const SharingMapTy *Top = getTopOfStackOrNull();
960 return Top ? Top->CancelRegion :
false;
964 void setParentHasScanDirective(SourceLocation Loc) {
965 if (SharingMapTy *Parent = getSecondOnStackOrNull())
966 Parent->PrevScanLocation = Loc;
969 bool doesParentHasScanDirective()
const {
970 const SharingMapTy *Top = getSecondOnStackOrNull();
971 return Top ? Top->PrevScanLocation.isValid() :
false;
974 SourceLocation getParentScanDirectiveLoc()
const {
975 const SharingMapTy *Top = getSecondOnStackOrNull();
976 return Top ? Top->PrevScanLocation : SourceLocation();
979 void setParentHasOrderedDirective(SourceLocation Loc) {
980 if (SharingMapTy *Parent = getSecondOnStackOrNull())
981 Parent->PrevOrderedLocation = Loc;
984 bool doesParentHasOrderedDirective()
const {
985 const SharingMapTy *Top = getSecondOnStackOrNull();
986 return Top ? Top->PrevOrderedLocation.isValid() :
false;
989 SourceLocation getParentOrderedDirectiveLoc()
const {
990 const SharingMapTy *Top = getSecondOnStackOrNull();
991 return Top ? Top->PrevOrderedLocation : SourceLocation();
995 void setAssociatedLoops(
unsigned Val) {
996 getTopOfStack().AssociatedLoops = Val;
998 getTopOfStack().HasMutipleLoops =
true;
1001 unsigned getAssociatedLoops()
const {
1002 const SharingMapTy *Top = getTopOfStackOrNull();
1003 return Top ? Top->AssociatedLoops : 0;
1006 bool hasMutipleLoops()
const {
1007 const SharingMapTy *Top = getTopOfStackOrNull();
1008 return Top ? Top->HasMutipleLoops :
false;
1013 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
1014 if (SharingMapTy *Parent = getSecondOnStackOrNull())
1015 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
1018 bool hasInnerTeamsRegion()
const {
1019 return getInnerTeamsRegionLoc().
isValid();
1022 SourceLocation getInnerTeamsRegionLoc()
const {
1023 const SharingMapTy *Top = getTopOfStackOrNull();
1024 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
1027 Scope *getCurScope()
const {
1028 const SharingMapTy *Top = getTopOfStackOrNull();
1029 return Top ? Top->CurScope :
nullptr;
1031 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
1032 SourceLocation getConstructLoc()
const {
1033 const SharingMapTy *Top = getTopOfStackOrNull();
1034 return Top ? Top->ConstructLoc : SourceLocation();
1039 bool checkMappableExprComponentListsForDecl(
1040 const ValueDecl *VD,
bool CurrentRegionOnly,
1041 const llvm::function_ref<
1053 if (CurrentRegionOnly)
1056 std::advance(SI, 1);
1058 for (; SI != SE; ++SI) {
1059 auto MI = SI->MappedExprComponents.find(VD);
1060 if (MI != SI->MappedExprComponents.end())
1062 MI->second.Components)
1063 if (Check(L, MI->second.Kind))
1071 bool checkMappableExprComponentListsForDeclAtLevel(
1072 const ValueDecl *VD,
unsigned Level,
1073 const llvm::function_ref<
1077 if (getStackSize() <= Level)
1080 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1081 auto MI = StackElem.MappedExprComponents.find(VD);
1082 if (MI != StackElem.MappedExprComponents.end())
1084 MI->second.Components)
1085 if (Check(L, MI->second.Kind))
1092 void addMappableExpressionComponents(
1093 const ValueDecl *VD,
1096 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1098 MEC.Components.resize(MEC.Components.size() + 1);
1099 MEC.Components.back().append(Components.begin(), Components.end());
1100 MEC.Kind = WhereFoundClauseKind;
1103 unsigned getNestingLevel()
const {
1104 assert(!isStackEmpty());
1105 return getStackSize() - 1;
1107 void addDoacrossDependClause(OMPClause *
C,
const OperatorOffsetTy &OpsOffs) {
1108 SharingMapTy *Parent = getSecondOnStackOrNull();
1110 Parent->DoacrossDepends.try_emplace(
C, OpsOffs);
1112 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1113 getDoacrossDependClauses()
const {
1114 const SharingMapTy &StackElem = getTopOfStack();
1116 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1117 return llvm::make_range(Ref.begin(), Ref.end());
1119 return llvm::make_range(StackElem.DoacrossDepends.end(),
1120 StackElem.DoacrossDepends.end());
1124 void addMappedClassesQualTypes(QualType QT) {
1125 SharingMapTy &StackElem = getTopOfStack();
1126 StackElem.MappedClassesQualTypes.insert(QT);
1130 bool isClassPreviouslyMapped(QualType QT)
const {
1131 const SharingMapTy &StackElem = getTopOfStack();
1132 return StackElem.MappedClassesQualTypes.contains(QT);
1136 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1137 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1138 E->
getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1139 "Expected declare target link global.");
1140 for (
auto &Elem : *
this) {
1142 Elem.DeclareTargetLinkVarDecls.push_back(E);
1150 ArrayRef<DeclRefExpr *> getLinkGlobals()
const {
1152 "Expected target executable directive.");
1153 return getTopOfStack().DeclareTargetLinkVarDecls;
1157 void addInnerAllocatorExpr(Expr *E) {
1158 getTopOfStack().InnerUsedAllocators.push_back(E);
1161 ArrayRef<Expr *> getInnerAllocators()
const {
1162 return getTopOfStack().InnerUsedAllocators;
1166 void addImplicitTaskFirstprivate(
unsigned Level, Decl *D) {
1167 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(D);
1170 bool isImplicitTaskFirstprivate(Decl *D)
const {
1171 return getTopOfStack().ImplicitTaskFirstprivates.contains(D);
1175 void addUsesAllocatorsDecl(
const Decl *D, UsesAllocatorsDeclKind Kind) {
1176 getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind);
1180 std::optional<UsesAllocatorsDeclKind>
1181 isUsesAllocatorsDecl(
unsigned Level,
const Decl *D)
const {
1182 const SharingMapTy &StackElem = getTopOfStack();
1183 auto I = StackElem.UsesAllocatorsDecls.find(D);
1184 if (I == StackElem.UsesAllocatorsDecls.end())
1185 return std::nullopt;
1186 return I->getSecond();
1188 std::optional<UsesAllocatorsDeclKind>
1189 isUsesAllocatorsDecl(
const Decl *D)
const {
1190 const SharingMapTy &StackElem = getTopOfStack();
1191 auto I = StackElem.UsesAllocatorsDecls.find(D);
1192 if (I == StackElem.UsesAllocatorsDecls.end())
1193 return std::nullopt;
1194 return I->getSecond();
1197 void addDeclareMapperVarRef(Expr *Ref) {
1198 SharingMapTy &StackElem = getTopOfStack();
1199 StackElem.DeclareMapperVar = Ref;
1201 const Expr *getDeclareMapperVarRef()
const {
1202 const SharingMapTy *Top = getTopOfStackOrNull();
1203 return Top ? Top->DeclareMapperVar :
nullptr;
1207 void addIteratorVarDecl(VarDecl *VD) {
1208 SharingMapTy &StackElem = getTopOfStack();
1212 bool isIteratorVarDecl(
const VarDecl *VD)
const {
1213 const SharingMapTy *Top = getTopOfStackOrNull();
1220 VarDecl *getImplicitFDCapExprDecl(
const FieldDecl *FD)
const {
1221 const_iterator I = begin();
1222 const_iterator EndI = end();
1223 size_t StackLevel = getStackSize();
1224 for (; I != EndI; ++I) {
1225 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1229 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1232 for (
const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1233 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1238 bool isImplicitDefaultFirstprivateFD(VarDecl *VD)
const {
1239 const_iterator I = begin();
1240 const_iterator EndI = end();
1241 for (; I != EndI; ++I)
1242 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1246 for (
const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1252 void addImplicitDefaultFirstprivateFD(
const FieldDecl *FD, VarDecl *VD) {
1253 iterator I = begin();
1254 const_iterator EndI = end();
1255 size_t StackLevel = getStackSize();
1256 for (; I != EndI; ++I) {
1257 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1258 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1263 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1273 DKind == OMPD_unknown;
1279 if (
const auto *FE = dyn_cast<FullExpr>(E))
1280 E = FE->getSubExpr();
1282 if (
const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
1283 E = MTE->getSubExpr();
1285 while (
const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
1286 E = Binder->getSubExpr();
1288 if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
1289 E = ICE->getSubExprAsWritten();
1298 if (
const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
1299 if (
const auto *ME = dyn_cast<MemberExpr>(
getExprAsWritten(CED->getInit())))
1300 D = ME->getMemberDecl();
1312 if (
C == OMPC_threadprivate)
1313 return getOpenMPClauseName(
C).str() +
" or thread local";
1314 return getOpenMPClauseName(
C).str();
1320 auto *VD = dyn_cast<VarDecl>(D);
1321 const auto *FD = dyn_cast<FieldDecl>(D);
1323 if (Iter == end()) {
1330 DVar.CKind = OMPC_shared;
1337 DVar.CKind = OMPC_shared;
1341 DVar.CKind = OMPC_shared;
1352 DVar.CKind = OMPC_private;
1356 DVar.DKind = Iter->Directive;
1359 if (Iter->SharingMap.count(D)) {
1360 const DSAInfo &
Data = Iter->SharingMap.lookup(D);
1361 DVar.RefExpr =
Data.RefExpr.getPointer();
1362 DVar.PrivateCopy =
Data.PrivateCopy;
1363 DVar.CKind =
Data.Attributes;
1364 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1365 DVar.Modifier =
Data.Modifier;
1366 DVar.AppliedToPointee =
Data.AppliedToPointee;
1370 DefaultDataSharingAttributes IterDA = Iter->DefaultAttr;
1371 switch (Iter->DefaultVCAttr) {
1372 case DSA_VC_aggregate:
1376 case DSA_VC_allocatable:
1381 case DSA_VC_pointer:
1399 DVar.CKind = OMPC_shared;
1400 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1404 case DSA_firstprivate:
1407 DVar.CKind = OMPC_unknown;
1409 DVar.CKind = OMPC_firstprivate;
1411 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1419 DVar.CKind = OMPC_unknown;
1421 DVar.CKind = OMPC_private;
1423 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1425 case DSA_unspecified:
1430 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1434 DVar.CKind = OMPC_shared;
1444 DSAVarData DVarTemp;
1445 const_iterator I = Iter, E = end();
1453 DVarTemp = getDSA(I, D);
1454 if (DVarTemp.CKind != OMPC_shared) {
1455 DVar.RefExpr =
nullptr;
1456 DVar.CKind = OMPC_firstprivate;
1459 }
while (I != E && !isImplicitTaskingRegion(I->Directive));
1461 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1470 return getDSA(++Iter, D);
1473const Expr *DSAStackTy::addUniqueAligned(
const ValueDecl *D,
1474 const Expr *NewDE) {
1475 assert(!isStackEmpty() &&
"Data sharing attributes stack is empty");
1477 SharingMapTy &StackElem = getTopOfStack();
1478 auto [It, Inserted] = StackElem.AlignedMap.try_emplace(D, NewDE);
1480 assert(NewDE &&
"Unexpected nullptr expr to be added into aligned map");
1483 assert(It->second &&
"Unexpected nullptr expr in the aligned map");
1487const Expr *DSAStackTy::addUniqueNontemporal(
const ValueDecl *D,
1488 const Expr *NewDE) {
1489 assert(!isStackEmpty() &&
"Data sharing attributes stack is empty");
1491 SharingMapTy &StackElem = getTopOfStack();
1492 auto [It, Inserted] = StackElem.NontemporalMap.try_emplace(D, NewDE);
1494 assert(NewDE &&
"Unexpected nullptr expr to be added into aligned map");
1497 assert(It->second &&
"Unexpected nullptr expr in the aligned map");
1501void DSAStackTy::addLoopControlVariable(
const ValueDecl *D, VarDecl *
Capture) {
1502 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1504 SharingMapTy &StackElem = getTopOfStack();
1505 StackElem.LCVMap.try_emplace(
1506 D, LCDeclInfo(StackElem.LCVMap.size() + 1,
Capture));
1509const DSAStackTy::LCDeclInfo
1510DSAStackTy::isLoopControlVariable(
const ValueDecl *D)
const {
1511 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1513 const SharingMapTy &StackElem = getTopOfStack();
1514 auto It = StackElem.LCVMap.find(D);
1515 if (It != StackElem.LCVMap.end())
1517 return {0,
nullptr};
1520const DSAStackTy::LCDeclInfo
1521DSAStackTy::isLoopControlVariable(
const ValueDecl *D,
unsigned Level)
const {
1522 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1524 for (
unsigned I = Level + 1; I > 0; --I) {
1525 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1526 auto It = StackElem.LCVMap.find(D);
1527 if (It != StackElem.LCVMap.end())
1530 return {0,
nullptr};
1533const DSAStackTy::LCDeclInfo
1534DSAStackTy::isParentLoopControlVariable(
const ValueDecl *D)
const {
1535 const SharingMapTy *Parent = getSecondOnStackOrNull();
1536 assert(Parent &&
"Data-sharing attributes stack is empty");
1538 auto It = Parent->LCVMap.find(D);
1539 if (It != Parent->LCVMap.end())
1541 return {0,
nullptr};
1544const ValueDecl *DSAStackTy::getParentLoopControlVariable(
unsigned I)
const {
1545 const SharingMapTy *Parent = getSecondOnStackOrNull();
1546 assert(Parent &&
"Data-sharing attributes stack is empty");
1547 if (Parent->LCVMap.size() < I)
1549 for (
const auto &Pair : Parent->LCVMap)
1550 if (Pair.second.first == I)
1555void DSAStackTy::addDSA(
const ValueDecl *D,
const Expr *E,
OpenMPClauseKind A,
1556 DeclRefExpr *PrivateCopy,
unsigned Modifier,
1557 bool AppliedToPointee) {
1559 if (A == OMPC_threadprivate) {
1560 DSAInfo &
Data = Threadprivates[D];
1561 Data.Attributes = A;
1562 Data.RefExpr.setPointer(E);
1563 Data.PrivateCopy =
nullptr;
1564 Data.Modifier = Modifier;
1565 }
else if (A == OMPC_groupprivate) {
1566 DSAInfo &
Data = Groupprivates[D];
1567 Data.Attributes = A;
1568 Data.RefExpr.setPointer(E);
1569 Data.PrivateCopy =
nullptr;
1570 Data.Modifier = Modifier;
1572 DSAInfo &
Data = getTopOfStack().SharingMap[D];
1573 assert(
Data.Attributes == OMPC_unknown || (A ==
Data.Attributes) ||
1574 (A == OMPC_firstprivate &&
Data.Attributes == OMPC_lastprivate) ||
1575 (A == OMPC_lastprivate &&
Data.Attributes == OMPC_firstprivate) ||
1576 (isLoopControlVariable(D).first && A == OMPC_private));
1577 Data.Modifier = Modifier;
1578 if (A == OMPC_lastprivate &&
Data.Attributes == OMPC_firstprivate) {
1579 Data.RefExpr.setInt(
true);
1582 const bool IsLastprivate =
1583 A == OMPC_lastprivate ||
Data.Attributes == OMPC_lastprivate;
1584 Data.Attributes = A;
1585 Data.RefExpr.setPointerAndInt(E, IsLastprivate);
1586 Data.PrivateCopy = PrivateCopy;
1587 Data.AppliedToPointee = AppliedToPointee;
1589 DSAInfo &
Data = getTopOfStack().SharingMap[PrivateCopy->
getDecl()];
1590 Data.Modifier = Modifier;
1591 Data.Attributes = A;
1592 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1593 Data.PrivateCopy =
nullptr;
1594 Data.AppliedToPointee = AppliedToPointee;
1601 StringRef Name,
const AttrVec *Attrs =
nullptr,
1616 OMPReferencedVarAttr::CreateImplicit(SemaRef.
Context, OrigRef));
1623 bool RefersToCapture =
false) {
1631void DSAStackTy::addTaskgroupReductionData(
const ValueDecl *D, SourceRange SR,
1634 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1636 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1637 "Additional reduction info may be specified only for reduction items.");
1638 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1639 assert(ReductionData.ReductionRange.isInvalid() &&
1640 (getTopOfStack().
Directive == OMPD_taskgroup ||
1644 "Additional reduction info may be specified only once for reduction "
1646 ReductionData.set(BOK, SR);
1647 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1648 if (!TaskgroupReductionRef) {
1651 TaskgroupReductionRef =
1656void DSAStackTy::addTaskgroupReductionData(
const ValueDecl *D, SourceRange SR,
1657 const Expr *ReductionRef) {
1659 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1661 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1662 "Additional reduction info may be specified only for reduction items.");
1663 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1664 assert(ReductionData.ReductionRange.isInvalid() &&
1665 (getTopOfStack().
Directive == OMPD_taskgroup ||
1669 "Additional reduction info may be specified only once for reduction "
1671 ReductionData.set(ReductionRef, SR);
1672 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1673 if (!TaskgroupReductionRef) {
1676 TaskgroupReductionRef =
1681const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1683 Expr *&TaskgroupDescriptor)
const {
1685 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty.");
1686 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1687 const DSAInfo &
Data = I->SharingMap.lookup(D);
1688 if (
Data.Attributes != OMPC_reduction ||
1689 Data.Modifier != OMPC_REDUCTION_task)
1691 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1692 if (!ReductionData.ReductionOp ||
1694 return DSAVarData();
1695 SR = ReductionData.ReductionRange;
1697 assert(I->TaskgroupReductionRef &&
"taskgroup reduction reference "
1698 "expression for the descriptor is not "
1700 TaskgroupDescriptor = I->TaskgroupReductionRef;
1701 return DSAVarData(I->Directive, OMPC_reduction,
Data.RefExpr.getPointer(),
1702 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1705 return DSAVarData();
1708const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1709 const ValueDecl *D, SourceRange &SR,
const Expr *&ReductionRef,
1710 Expr *&TaskgroupDescriptor)
const {
1712 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty.");
1713 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1714 const DSAInfo &
Data = I->SharingMap.lookup(D);
1715 if (
Data.Attributes != OMPC_reduction ||
1716 Data.Modifier != OMPC_REDUCTION_task)
1718 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1719 if (!ReductionData.ReductionOp ||
1721 return DSAVarData();
1722 SR = ReductionData.ReductionRange;
1724 assert(I->TaskgroupReductionRef &&
"taskgroup reduction reference "
1725 "expression for the descriptor is not "
1727 TaskgroupDescriptor = I->TaskgroupReductionRef;
1728 return DSAVarData(I->Directive, OMPC_reduction,
Data.RefExpr.getPointer(),
1729 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1732 return DSAVarData();
1735bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I)
const {
1737 for (const_iterator E = end(); I != E; ++I) {
1738 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1741 Scope *TopScope = I->CurScope->getParent();
1742 Scope *CurScope = getCurScope();
1743 while (CurScope && CurScope != TopScope && !CurScope->
isDeclScope(D))
1745 return CurScope != TopScope;
1748 if (I->Context == DC)
1757 bool AcceptIfMutable =
true,
1758 bool *IsClassType =
nullptr) {
1760 Type =
Type.getNonReferenceType().getCanonicalType();
1761 bool IsConstant =
Type.isConstant(Context);
1762 Type = Context.getBaseElementType(
Type);
1766 if (
const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1768 RD = CTD->getTemplatedDecl();
1778 bool AcceptIfMutable =
true,
1779 bool ListItemNotVar =
false) {
1783 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1784 : IsClassType ? diag::err_omp_const_not_mutable_variable
1785 : diag::err_omp_const_variable;
1787 if (!ListItemNotVar && D) {
1788 const VarDecl *VD = dyn_cast<VarDecl>(D);
1792 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1800const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1805 auto *VD = dyn_cast<VarDecl>(D);
1806 auto TI = Threadprivates.find(D);
1807 if (TI != Threadprivates.end()) {
1808 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1809 DVar.CKind = OMPC_threadprivate;
1810 DVar.Modifier = TI->getSecond().Modifier;
1813 if (VD && VD->
hasAttr<OMPThreadPrivateDeclAttr>()) {
1816 VD->
getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1817 DVar.CKind = OMPC_threadprivate;
1818 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1825 !(VD->
hasAttr<OMPThreadPrivateDeclAttr>() &&
1832 DVar.CKind = OMPC_threadprivate;
1833 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1838 !isLoopControlVariable(D).first) {
1839 const_iterator IterTarget =
1840 std::find_if(begin(), end(), [](
const SharingMapTy &
Data) {
1843 if (IterTarget != end()) {
1844 const_iterator ParentIterTarget = IterTarget + 1;
1845 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1846 if (isOpenMPLocal(VD, Iter)) {
1850 DVar.CKind = OMPC_threadprivate;
1854 if (!isClauseParsingMode() || IterTarget != begin()) {
1855 auto DSAIter = IterTarget->SharingMap.find(D);
1856 if (DSAIter != IterTarget->SharingMap.end() &&
1858 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1859 DVar.CKind = OMPC_threadprivate;
1862 const_iterator End = end();
1864 D, std::distance(ParentIterTarget, End),
1868 IterTarget->ConstructLoc);
1869 DVar.CKind = OMPC_threadprivate;
1889 const_iterator I = begin();
1890 const_iterator EndI = end();
1891 if (FromParent && I != EndI)
1894 auto It = I->SharingMap.find(D);
1895 if (It != I->SharingMap.end()) {
1896 const DSAInfo &
Data = It->getSecond();
1897 DVar.RefExpr =
Data.RefExpr.getPointer();
1898 DVar.PrivateCopy =
Data.PrivateCopy;
1899 DVar.CKind =
Data.Attributes;
1900 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1901 DVar.DKind = I->Directive;
1902 DVar.Modifier =
Data.Modifier;
1903 DVar.AppliedToPointee =
Data.AppliedToPointee;
1908 DVar.CKind = OMPC_shared;
1915 if (SemaRef.
LangOpts.OpenMP <= 31) {
1923 DSAVarData DVarTemp = hasInnermostDSA(
1926 return C == OMPC_firstprivate ||
C == OMPC_shared;
1928 MatchesAlways, FromParent);
1929 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1932 DVar.CKind = OMPC_shared;
1939 const_iterator I = begin();
1940 const_iterator EndI = end();
1941 if (FromParent && I != EndI)
1945 auto It = I->SharingMap.find(D);
1946 if (It != I->SharingMap.end()) {
1947 const DSAInfo &
Data = It->getSecond();
1948 DVar.RefExpr =
Data.RefExpr.getPointer();
1949 DVar.PrivateCopy =
Data.PrivateCopy;
1950 DVar.CKind =
Data.Attributes;
1951 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1952 DVar.DKind = I->Directive;
1953 DVar.Modifier =
Data.Modifier;
1954 DVar.AppliedToPointee =
Data.AppliedToPointee;
1960const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1961 bool FromParent)
const {
1962 if (isStackEmpty()) {
1964 return getDSA(I, D);
1967 const_iterator StartI = begin();
1968 const_iterator EndI = end();
1969 if (FromParent && StartI != EndI)
1971 return getDSA(StartI, D);
1974const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1975 unsigned Level)
const {
1976 if (getStackSize() <= Level)
1977 return DSAVarData();
1979 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
1980 return getDSA(StartI, D);
1983const DSAStackTy::DSAVarData
1984DSAStackTy::hasDSA(ValueDecl *D,
1986 DefaultDataSharingAttributes)>
1989 bool FromParent)
const {
1993 const_iterator I = begin();
1994 const_iterator EndI = end();
1995 if (FromParent && I != EndI)
1997 for (; I != EndI; ++I) {
1998 if (!DPred(I->Directive) &&
1999 !isImplicitOrExplicitTaskingRegion(I->Directive))
2001 const_iterator NewI = I;
2002 DSAVarData DVar = getDSA(NewI, D);
2003 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
2009const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
2010 ValueDecl *D,
const llvm::function_ref<
bool(
OpenMPClauseKind,
bool)> CPred,
2012 bool FromParent)
const {
2016 const_iterator StartI = begin();
2017 const_iterator EndI = end();
2018 if (FromParent && StartI != EndI)
2020 if (StartI == EndI || !DPred(StartI->Directive))
2022 const_iterator NewI = StartI;
2023 DSAVarData DVar = getDSA(NewI, D);
2024 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
2029bool DSAStackTy::hasExplicitDSA(
2032 unsigned Level,
bool NotLastprivate)
const {
2033 if (getStackSize() <= Level)
2036 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2037 auto I = StackElem.SharingMap.find(D);
2038 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
2039 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
2040 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
2043 auto LI = StackElem.LCVMap.find(D);
2044 if (LI != StackElem.LCVMap.end())
2045 return CPred(OMPC_private,
false);
2049bool DSAStackTy::hasExplicitDirective(
2051 unsigned Level)
const {
2052 if (getStackSize() <= Level)
2054 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2055 return DPred(StackElem.Directive);
2058bool DSAStackTy::hasDirective(
2060 const DeclarationNameInfo &, SourceLocation)>
2062 bool FromParent)
const {
2064 size_t Skip = FromParent ? 2 : 1;
2065 for (const_iterator I = begin() + std::min(
Skip, getStackSize()), E = end();
2067 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
2073void SemaOpenMP::InitDataSharingAttributesStack() {
2074 VarDataSharingAttributesStack =
new DSAStackTy(SemaRef);
2077#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2079void SemaOpenMP::pushOpenMPFunctionRegion() {
DSAStack->pushFunction(); }
2081void SemaOpenMP::popOpenMPFunctionRegion(
const FunctionScopeInfo *OldFSI) {
2087 "Expected OpenMP device compilation.");
2093enum class FunctionEmissionStatus {
2100SemaBase::SemaDiagnosticBuilder
2104 "Expected OpenMP device compilation.");
2106 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2111 Kind = SemaDiagnosticBuilder::K_Immediate;
2122 ? SemaDiagnosticBuilder::K_Deferred
2123 : SemaDiagnosticBuilder::K_Immediate;
2127 Kind = SemaDiagnosticBuilder::K_Nop;
2130 llvm_unreachable(
"CUDADiscarded unexpected in OpenMP device compilation");
2142 "Expected OpenMP host compilation.");
2144 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2149 Kind = SemaDiagnosticBuilder::K_Immediate;
2152 Kind = SemaDiagnosticBuilder::K_Deferred;
2157 Kind = SemaDiagnosticBuilder::K_Nop;
2167 if (LO.OpenMP <= 45) {
2169 return OMPC_DEFAULTMAP_scalar;
2170 return OMPC_DEFAULTMAP_aggregate;
2173 return OMPC_DEFAULTMAP_pointer;
2175 return OMPC_DEFAULTMAP_scalar;
2176 return OMPC_DEFAULTMAP_aggregate;
2180 unsigned OpenMPCaptureLevel)
const {
2181 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2184 bool IsByRef =
true;
2190 bool IsVariableUsedInMapClause =
false;
2252 bool IsVariableAssociatedWithSection =
false;
2254 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2256 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2263 if (WhereFoundClauseKind != OMPC_map &&
2264 WhereFoundClauseKind != OMPC_has_device_addr)
2267 auto EI = MapExprComponents.rbegin();
2268 auto EE = MapExprComponents.rend();
2270 assert(EI != EE &&
"Invalid map expression!");
2273 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D;
2278 auto Last = std::prev(EE);
2280 dyn_cast<UnaryOperator>(
Last->getAssociatedExpression());
2281 if ((UO && UO->getOpcode() == UO_Deref) ||
2286 IsVariableAssociatedWithSection =
true;
2295 if (IsVariableUsedInMapClause) {
2298 IsByRef = !(Ty->
isPointerType() && IsVariableAssociatedWithSection);
2303 IsByRef = (
DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2306 DSAStack->isDefaultmapCapturedByRef(
2311 return K == OMPC_reduction && !AppliedToPointee;
2319 ((IsVariableUsedInMapClause &&
2320 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2325 return K == OMPC_firstprivate ||
2326 (K == OMPC_reduction && AppliedToPointee);
2329 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2336 !((
DSAStack->getDefaultDSA() == DSA_firstprivate ||
2337 DSAStack->getDefaultDSA() == DSA_private) &&
2341 !
DSAStack->isLoopControlVariable(D, Level).first);
2358unsigned SemaOpenMP::getOpenMPNestingLevel()
const {
2359 assert(getLangOpts().OpenMP);
2360 return DSAStack->getNestingLevel();
2370 !
DSAStack->isClauseParsingMode()) ||
2383 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2386 DefaultDataSharingAttributes DefaultAttr) {
2388 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2392 if (DVarPrivate.CKind != OMPC_unknown)
2398 Expr *CaptureExpr,
bool WithInit,
2404 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2407 auto *VD = dyn_cast<VarDecl>(D);
2416 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2426 DSAStackTy::DSAVarData DVarTop =
2428 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2433 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2437 llvm::reverse(
SemaRef.FunctionScopes),
2438 CheckScopeInfo ? (
SemaRef.FunctionScopes.size() - (StopAt + 1))
2442 if (
auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2448 assert(CSI &&
"Failed to find CapturedRegionScopeInfo");
2459 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2465 if (CheckScopeInfo) {
2466 bool OpenMPFound =
false;
2467 for (
unsigned I = StopAt + 1; I > 0; --I) {
2471 if (
auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2481 if (
DSAStack->getCurrentDirective() != OMPD_unknown &&
2482 (!
DSAStack->isClauseParsingMode() ||
2483 DSAStack->getParentDirective() != OMPD_unknown)) {
2484 auto &&Info =
DSAStack->isLoopControlVariable(D);
2487 isImplicitOrExplicitTaskingRegion(
DSAStack->getCurrentDirective())) ||
2488 (VD &&
DSAStack->isForceVarCapturing()))
2489 return VD ? VD : Info.second;
2490 DSAStackTy::DSAVarData DVarTop =
2492 if (DVarTop.CKind != OMPC_unknown &&
isOpenMPPrivate(DVarTop.CKind) &&
2500 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2508 if (VD && !VD->
hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2509 ((
DSAStack->getDefaultDSA() != DSA_none &&
2510 DSAStack->getDefaultDSA() != DSA_private &&
2511 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2512 DVarTop.CKind == OMPC_shared))
2514 auto *FD = dyn_cast<FieldDecl>(D);
2515 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2516 !DVarPrivate.PrivateCopy) {
2517 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2520 DefaultDataSharingAttributes DefaultAttr) {
2522 (DefaultAttr == DSA_firstprivate ||
2523 DefaultAttr == DSA_private);
2527 if (DVarPrivate.CKind == OMPC_unknown)
2533 if (
SemaRef.getCurrentThisType().isNull())
2547 SemaRef.CurContext->getParent(),
false);
2551 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2554 if (DVarPrivate.CKind != OMPC_unknown ||
2555 (VD && (
DSAStack->getDefaultDSA() == DSA_none ||
2556 DSAStack->getDefaultDSA() == DSA_private ||
2557 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2563void SemaOpenMP::adjustOpenMPTargetScopeIndex(
unsigned &FunctionScopesIndex,
2564 unsigned Level)
const {
2565 FunctionScopesIndex -= getOpenMPCaptureLevels(
DSAStack->getDirective(Level));
2569 assert(
getLangOpts().OpenMP &&
"OpenMP must be enabled.");
2575 assert(
getLangOpts().OpenMP &&
"OpenMP must be enabled.");
2577 DSAStack->resetPossibleLoopCounter();
2583 unsigned CapLevel)
const {
2584 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2585 if (
DSAStack->getCurrentDirective() != OMPD_unknown &&
2586 (!
DSAStack->isClauseParsingMode() ||
2587 DSAStack->getParentDirective() != OMPD_unknown)) {
2588 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2591 DefaultDataSharingAttributes DefaultAttr) {
2593 DefaultAttr == DSA_private;
2599 !
DSAStack->isLoopControlVariable(D).first)
2600 return OMPC_private;
2603 bool IsTriviallyCopyable =
2614 (IsTriviallyCopyable ||
2620 return OMPC_firstprivate;
2621 DSAStackTy::DSAVarData DVar =
DSAStack->getImplicitDSA(D, Level);
2622 if (DVar.CKind != OMPC_shared &&
2623 !
DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2624 DSAStack->addImplicitTaskFirstprivate(Level, D);
2625 return OMPC_firstprivate;
2632 DSAStack->resetPossibleLoopCounter(D);
2634 return OMPC_private;
2637 DSAStack->isLoopControlVariable(D).first) &&
2642 return OMPC_private;
2644 if (
const auto *VD = dyn_cast<VarDecl>(D)) {
2650 return OMPC_private;
2655 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2656 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2657 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2658 return OMPC_private;
2662 (
DSAStack->isClauseParsingMode() &&
2663 DSAStack->getClauseParsingMode() == OMPC_private) ||
2668 return K == OMPD_taskgroup ||
2669 ((isOpenMPParallelDirective(K) ||
2670 isOpenMPWorksharingDirective(K)) &&
2671 !isOpenMPSimdDirective(K));
2674 DSAStack->isTaskgroupReductionRef(D, Level)))
2681 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2684 for (
unsigned I =
DSAStack->getNestingLevel() + 1; I > Level; --I) {
2685 const unsigned NewLevel = I - 1;
2689 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2697 if (
DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2707 if (
DSAStack->mustBeFirstprivateAtLevel(
2709 OMPC = OMPC_firstprivate;
2713 if (OMPC != OMPC_unknown)
2715 OMPCaptureKindAttr::CreateImplicit(getASTContext(),
unsigned(OMPC)));
2719 unsigned CaptureLevel)
const {
2720 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2725 const auto *VD = dyn_cast<VarDecl>(D);
2729 Regions[CaptureLevel] != OMPD_task;
2733 unsigned CaptureLevel)
const {
2734 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2737 if (
const auto *VD = dyn_cast<VarDecl>(D)) {
2741 DSAStackTy::DSAVarData TopDVar =
2743 unsigned NumLevels =
2748 return (NumLevels == CaptureLevel + 1 &&
2749 (TopDVar.CKind != OMPC_shared ||
2750 DSAStack->getDefaultDSA() == DSA_firstprivate));
2753 DSAStackTy::DSAVarData DVar =
DSAStack->getImplicitDSA(D, Level);
2754 if (DVar.CKind != OMPC_shared)
2756 }
while (Level > 0);
2762void SemaOpenMP::DestroyDataSharingAttributesStack() {
delete DSAStack; }
2766 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2771 "Not in OpenMP declare variant scope!");
2773 OMPDeclareVariantScopes.pop_back();
2779 assert(
getLangOpts().OpenMP &&
"Expected OpenMP compilation mode.");
2780 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2784 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2787 if (!
getLangOpts().OpenMPIsTargetDevice && DevTy &&
2788 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2791 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2792 if (
getLangOpts().OpenMPIsTargetDevice && DevTy &&
2793 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2795 StringRef HostDevTy =
2797 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2798 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2799 diag::note_omp_marked_device_type_here)
2805 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2809 for (OMPDeclareVariantAttr *A :
2810 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2813 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2814 OMPDeclareTargetDeclAttr::getDeviceType(
2815 VariantFD->getMostRecentDecl());
2816 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2822 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2826 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2827 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2828 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2829 diag::note_omp_marked_device_type_here)
2837 DSAStack->push(DKind, DirName, CurScope, Loc);
2838 SemaRef.PushExpressionEvaluationContext(
2847 DSAStack->setClauseParsingMode(OMPC_unknown);
2848 SemaRef.CleanupVarDeclMarking();
2851static std::pair<ValueDecl *, bool>
2853 SourceRange &ERange,
bool AllowArraySection =
false,
2854 bool AllowAssumedSizeArray =
false, StringRef DiagType =
"");
2859 bool InscanFound =
false;
2866 if (
C->getClauseKind() != OMPC_reduction)
2869 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2871 InscanLoc = RC->getModifierLoc();
2874 if (RC->getModifier() == OMPC_REDUCTION_task) {
2884 S.
Diag(RC->getModifierLoc(),
2885 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2891 if (
C->getClauseKind() != OMPC_reduction)
2894 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2897 : RC->getModifierLoc(),
2898 diag::err_omp_inscan_reduction_expected);
2899 S.
Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2902 for (
Expr *Ref : RC->varlist()) {
2903 assert(Ref &&
"NULL expr in OpenMP reduction clause.");
2906 Expr *SimpleRefExpr = Ref;
2913 S.
Diag(Ref->getExprLoc(),
2914 diag::err_omp_reduction_not_inclusive_exclusive)
2915 << Ref->getSourceRange();
2923 ArrayRef<OMPClause *> Clauses);
2924static DeclRefExpr *
buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2929 const DSAStackTy::DSAVarData &DVar,
2930 bool IsLoopIterVar =
false);
2941 for (
Expr *DE : Clause->varlist()) {
2942 if (DE->isValueDependent() || DE->isTypeDependent()) {
2943 PrivateCopies.push_back(
nullptr);
2949 const DSAStackTy::DSAVarData DVar =
2951 if (DVar.CKind != OMPC_lastprivate) {
2954 PrivateCopies.push_back(
nullptr);
2965 SemaRef.ActOnUninitializedDecl(VDPrivate);
2967 PrivateCopies.push_back(
nullptr);
2973 Clause->setPrivateCopies(PrivateCopies);
2979 for (
Expr *RefExpr : Clause->varlist()) {
2980 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
2983 Expr *SimpleRefExpr = RefExpr;
2987 PrivateRefs.push_back(RefExpr);
2992 const DSAStackTy::DSAVarData DVar =
2994 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2997 Clause->setPrivateRefs(PrivateRefs);
3001 for (
unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
3009 DSAStackTy::DSAVarData DVar =
3015 Expr *MapExpr =
nullptr;
3017 DSAStack->checkMappableExprComponentListsForDecl(
3023 auto MI = MapExprComponents.rbegin();
3024 auto ME = MapExprComponents.rend();
3026 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
3027 VD->getCanonicalDecl()) {
3028 MapExpr = MI->getAssociatedExpression();
3033 Diag(D.Allocator->getExprLoc(), diag::err_omp_allocator_used_in_clauses)
3038 Diag(MapExpr->getExprLoc(), diag::note_used_here)
3039 << MapExpr->getSourceRange();
3044 if (
const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
3046 if (
auto *Clause = dyn_cast<OMPLastprivateClause>(
C)) {
3047 FinalizeLastprivate(Clause);
3048 }
else if (
auto *Clause = dyn_cast<OMPNontemporalClause>(
C)) {
3049 FinalizeNontemporal(Clause);
3050 }
else if (
auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(
C)) {
3051 FinalizeAllocators(Clause);
3066 Expr *NumIterations, Sema &SemaRef,
3067 Scope *S, DSAStackTy *Stack);
3070 OMPLoopBasedDirective::HelperExprs &B,
3071 DSAStackTy *Stack) {
3073 "loop exprs were not built");
3080 auto *LC = dyn_cast<OMPLinearClause>(
C);
3084 B.NumIterations, SemaRef,
3094class VarDeclFilterCCC final :
public CorrectionCandidateCallback {
3099 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3100 bool ValidateCandidate(
const TypoCorrection &Candidate)
override {
3102 if (
const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3110 std::unique_ptr<CorrectionCandidateCallback> clone()
override {
3111 return std::make_unique<VarDeclFilterCCC>(*
this);
3115class VarOrFuncDeclFilterCCC final :
public CorrectionCandidateCallback {
3120 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3121 bool ValidateCandidate(
const TypoCorrection &Candidate)
override {
3131 std::unique_ptr<CorrectionCandidateCallback> clone()
override {
3132 return std::make_unique<VarOrFuncDeclFilterCCC>(*
this);
3145 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
3154 VarDeclFilterCCC CCC(
SemaRef);
3160 SemaRef.PDiag(Lookup.
empty() ? diag::err_undeclared_var_use_suggest
3161 : diag::err_omp_expected_var_arg_suggest)
3163 VD = Corrected.getCorrectionDeclAs<
VarDecl>();
3166 : diag::err_omp_expected_var_arg)
3179 if ((Kind == OMPD_threadprivate || Kind == OMPD_groupprivate) &&
3181 Diag(Id.
getLoc(), diag::err_omp_global_var_arg)
3182 << getOpenMPDirectiveName(Kind, OMPVersion) << !VD->
isStaticLocal();
3186 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3197 !
SemaRef.getCurLexicalContext()->isTranslationUnit()) {
3199 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3203 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3214 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3218 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3227 (!
SemaRef.getCurLexicalContext()->isFileContext() ||
3228 !
SemaRef.getCurLexicalContext()->Encloses(
3231 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3235 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3244 !
SemaRef.isDeclInScope(ND,
SemaRef.getCurLexicalContext(), CurScope)) {
3246 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3250 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3258 if ((Kind == OMPD_threadprivate && VD->
isUsed() &&
3260 (Kind == OMPD_groupprivate && VD->
isUsed())) {
3262 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3277 SemaRef.CurContext->addDecl(D);
3287 Diag(Loc, diag::err_omp_unexpected_directive)
3288 << getOpenMPDirectiveName(OMPD_groupprivate,
getLangOpts().OpenMP);
3292 SemaRef.CurContext->addDecl(D);
3299class LocalVarRefChecker final
3305 if (
const auto *VD = dyn_cast<VarDecl>(E->
getDecl())) {
3308 diag::err_omp_local_var_in_threadprivate_init)
3310 SemaRef.Diag(VD->
getLocation(), diag::note_defined_here)
3317 bool VisitStmt(
const Stmt *S) {
3318 for (
const Stmt *Child : S->
children()) {
3319 if (Child && Visit(Child))
3324 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3328OMPThreadPrivateDecl *
3333 for (
Expr *RefExpr : VarList) {
3351 if (
SemaRef.RequireCompleteType(
3352 ILoc, VD->
getType(), diag::err_omp_threadprivate_incomplete_type)) {
3360 Diag(ILoc, diag::err_omp_ref_type_arg)
3361 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion)
3366 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3374 !(VD->
hasAttr<OMPThreadPrivateDeclAttr>() &&
3379 Diag(ILoc, diag::err_omp_var_thread_local)
3384 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3392 LocalVarRefChecker Checker(
SemaRef);
3393 if (Checker.Visit(
Init))
3397 Vars.push_back(RefExpr);
3398 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3399 VD->
addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3402 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3405 if (!Vars.empty()) {
3418 for (
Expr *RefExpr : VarList) {
3436 if (
SemaRef.RequireCompleteType(
3437 ILoc, VD->
getType(), diag::err_omp_groupprivate_incomplete_type)) {
3443 Diag(ILoc, diag::err_omp_ref_type_arg)
3444 << getOpenMPDirectiveName(OMPD_groupprivate) << VD->
getType();
3448 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3456 Diag(ILoc, diag::err_omp_groupprivate_with_initializer)
3461 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3466 Vars.push_back(RefExpr);
3467 DSAStack->addDSA(VD, DE, OMPC_groupprivate);
3468 VD->
addAttr(OMPGroupPrivateDeclAttr::CreateImplicit(Context,
3471 ML->DeclarationMarkedOpenMPGroupPrivate(VD);
3474 if (!Vars.empty()) {
3482static OMPAllocateDeclAttr::AllocatorTypeTy
3485 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3489 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3490 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3491 llvm::FoldingSetNodeID AEId;
3494 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3495 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
3496 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3497 llvm::FoldingSetNodeID DAEId;
3500 if (AEId == DAEId) {
3501 AllocatorKindRes = AllocatorKind;
3505 return AllocatorKindRes;
3510 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
Expr *Allocator) {
3511 if (!VD->
hasAttr<OMPAllocateDeclAttr>())
3513 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
3514 Expr *PrevAllocator = A->getAllocator();
3515 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3517 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3518 if (AllocatorsMatch &&
3519 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3520 Allocator && PrevAllocator) {
3523 llvm::FoldingSetNodeID AEId, PAEId;
3526 AllocatorsMatch = AEId == PAEId;
3528 if (!AllocatorsMatch) {
3530 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3534 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3536 PrevAllocator->printPretty(PrevAllocatorStream,
nullptr,
3544 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3546 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3547 S.
Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3548 << (Allocator ? 1 : 0) << AllocatorStream.str()
3549 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3551 S.
Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3552 << PrevAllocatorRange;
3560 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3562 if (VD->
hasAttr<OMPAllocateDeclAttr>())
3575 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.
Context, AllocatorKind,
3576 Allocator, Alignment, SR);
3579 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3585 assert(Clauses.size() <= 2 &&
"Expected at most two clauses.");
3586 Expr *Alignment =
nullptr;
3587 Expr *Allocator =
nullptr;
3588 if (Clauses.empty()) {
3595 SemaRef.targetDiag(Loc, diag::err_expected_allocator_clause);
3598 if (
const auto *AC = dyn_cast<OMPAllocatorClause>(
C))
3599 Allocator = AC->getAllocator();
3600 else if (
const auto *AC = dyn_cast<OMPAlignClause>(
C))
3601 Alignment = AC->getAlignment();
3603 llvm_unreachable(
"Unexpected clause on allocate directive");
3605 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3608 for (
Expr *RefExpr : VarList) {
3614 VD->
hasAttr<OMPThreadPrivateDeclAttr>() ||
3622 AllocatorKind, Allocator))
3630 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3632 diag::err_omp_expected_predefined_allocator)
3637 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3643 Vars.push_back(RefExpr);
3650 Owner =
SemaRef.getCurLexicalContext();
3661 if (!
SemaRef.CurContext->isFileContext()) {
3662 Diag(Loc, diag::err_omp_invalid_scope) <<
"requires";
3666 SemaRef.CurContext->addDecl(D);
3676 bool SkippedClauses) {
3677 if (!SkippedClauses && Assumptions.empty()) {
3679 Diag(Loc, diag::err_omp_no_clause_for_directive)
3680 << llvm::omp::getAllAssumeClauseOptions()
3681 << llvm::omp::getOpenMPDirectiveName(DKind, OMPVersion);
3685 OMPAssumeAttr::Create(
getASTContext(), llvm::join(Assumptions,
","), Loc);
3686 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3687 OMPAssumeScoped.push_back(AA);
3692 if (Assumptions.empty())
3695 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3696 "Unexpected omp assumption directive!");
3697 OMPAssumeGlobal.push_back(AA);
3704 auto *Ctx =
SemaRef.CurContext;
3705 while (Ctx->getLexicalParent())
3706 Ctx = Ctx->getLexicalParent();
3707 DeclContexts.push_back(Ctx);
3708 while (!DeclContexts.empty()) {
3710 for (
auto *SubDC : DC->
decls()) {
3711 if (SubDC->isInvalidDecl())
3713 if (
auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3714 DeclContexts.push_back(CTD->getTemplatedDecl());
3715 llvm::append_range(DeclContexts, CTD->specializations());
3718 if (
auto *DC = dyn_cast<DeclContext>(SubDC))
3719 DeclContexts.push_back(DC);
3720 if (
auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3730 OMPAssumeScoped.pop_back();
3751 DSAStack->getEncounteredTargetLocs();
3753 if (!TargetLocations.empty() || !AtomicLoc.
isInvalid()) {
3754 for (
const OMPClause *CNew : ClauseList) {
3760 Diag(Loc, diag::err_omp_directive_before_requires)
3763 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3768 Diag(Loc, diag::err_omp_directive_before_requires)
3770 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3776 if (!
DSAStack->hasDuplicateRequiresClause(ClauseList))
3784 const DSAStackTy::DSAVarData &DVar,
3785 bool IsLoopIterVar) {
3787 SemaRef.
Diag(DVar.RefExpr->
getExprLoc(), diag::note_omp_explicit_dsa)
3792 PDSA_StaticMemberShared,
3793 PDSA_StaticLocalVarShared,
3794 PDSA_LoopIterVarPrivate,
3795 PDSA_LoopIterVarLinear,
3796 PDSA_LoopIterVarLastprivate,
3797 PDSA_ConstVarShared,
3798 PDSA_GlobalVarShared,
3799 PDSA_TaskVarFirstprivate,
3800 PDSA_LocalVarPrivate,
3802 } Reason = PDSA_Implicit;
3803 bool ReportHint =
false;
3805 auto *VD = dyn_cast<VarDecl>(D);
3806 if (IsLoopIterVar) {
3807 if (DVar.CKind == OMPC_private)
3808 Reason = PDSA_LoopIterVarPrivate;
3809 else if (DVar.CKind == OMPC_lastprivate)
3810 Reason = PDSA_LoopIterVarLastprivate;
3812 Reason = PDSA_LoopIterVarLinear;
3814 DVar.CKind == OMPC_firstprivate) {
3815 Reason = PDSA_TaskVarFirstprivate;
3816 ReportLoc = DVar.ImplicitDSALoc;
3818 Reason = PDSA_StaticLocalVarShared;
3820 Reason = PDSA_StaticMemberShared;
3822 Reason = PDSA_GlobalVarShared;
3824 Reason = PDSA_ConstVarShared;
3825 else if (VD && VD->
isLocalVarDecl() && DVar.CKind == OMPC_private) {
3827 Reason = PDSA_LocalVarPrivate;
3829 if (Reason != PDSA_Implicit) {
3830 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
3831 SemaRef.
Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3832 << Reason << ReportHint
3833 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
3834 }
else if (DVar.ImplicitDSALoc.
isValid()) {
3835 SemaRef.
Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3842 bool IsAggregateOrDeclareTarget) {
3845 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3846 case OMPC_DEFAULTMAP_MODIFIER_storage:
3847 Kind = OMPC_MAP_alloc;
3849 case OMPC_DEFAULTMAP_MODIFIER_to:
3852 case OMPC_DEFAULTMAP_MODIFIER_from:
3853 Kind = OMPC_MAP_from;
3855 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3856 Kind = OMPC_MAP_tofrom;
3858 case OMPC_DEFAULTMAP_MODIFIER_present:
3864 Kind = OMPC_MAP_alloc;
3866 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3867 case OMPC_DEFAULTMAP_MODIFIER_private:
3869 llvm_unreachable(
"Unexpected defaultmap implicit behavior");
3870 case OMPC_DEFAULTMAP_MODIFIER_none:
3871 case OMPC_DEFAULTMAP_MODIFIER_default:
3876 if (IsAggregateOrDeclareTarget) {
3877 Kind = OMPC_MAP_tofrom;
3880 llvm_unreachable(
"Unexpected defaultmap implicit behavior");
3887struct VariableImplicitInfo {
3891 llvm::SetVector<Expr *> Privates;
3892 llvm::SetVector<Expr *> Firstprivates;
3893 llvm::SetVector<Expr *> Mappings[DefaultmapKindNum][MapKindNum];
3894 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
3895 MapModifiers[DefaultmapKindNum];
3898class DSAAttrChecker final :
public StmtVisitor<DSAAttrChecker, void> {
3902 bool ErrorFound =
false;
3903 bool TryCaptureCXXThisMembers =
false;
3904 CapturedStmt *CS =
nullptr;
3906 VariableImplicitInfo ImpInfo;
3908 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3910 void VisitSubCaptures(OMPExecutableDirective *S) {
3912 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3914 if (S->getDirectiveKind() == OMPD_atomic ||
3915 S->getDirectiveKind() == OMPD_critical ||
3916 S->getDirectiveKind() == OMPD_section ||
3917 S->getDirectiveKind() == OMPD_master ||
3918 S->getDirectiveKind() == OMPD_masked ||
3919 S->getDirectiveKind() == OMPD_scope ||
3920 S->getDirectiveKind() == OMPD_assume ||
3922 Visit(S->getAssociatedStmt());
3925 visitSubCaptures(S->getInnermostCapturedStmt());
3928 if (TryCaptureCXXThisMembers ||
3930 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3931 [](
const CapturedStmt::Capture &
C) {
3932 return C.capturesThis();
3934 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3935 TryCaptureCXXThisMembers =
true;
3936 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3937 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3943 for (OMPClause *
C : S->clauses())
3944 if (
auto *FC = dyn_cast<OMPFirstprivateClause>(
C)) {
3945 for (Expr *Ref : FC->varlist())
3952 void VisitDeclRefExpr(DeclRefExpr *E) {
3958 if (
auto *VD = dyn_cast<VarDecl>(E->
getDecl())) {
3961 !Stack->getTopDSA(VD,
false).RefExpr &&
3962 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3963 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3964 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3965 Visit(CED->getInit());
3971 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3976 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3977 !Stack->isImplicitTaskFirstprivate(VD))
3980 if (Stack->isUsesAllocatorsDecl(VD))
3983 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD,
false);
3985 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3989 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3990 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3992 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
3993 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3994 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3995 !Stack->isImplicitTaskFirstprivate(VD))
4003 if (DVar.CKind == OMPC_unknown &&
4004 (Stack->getDefaultDSA() == DSA_none ||
4005 Stack->getDefaultDSA() == DSA_private ||
4006 Stack->getDefaultDSA() == DSA_firstprivate) &&
4007 isImplicitOrExplicitTaskingRegion(DKind) &&
4008 VarsWithInheritedDSA.count(VD) == 0) {
4009 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
4010 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
4011 Stack->getDefaultDSA() == DSA_private)) {
4012 DSAStackTy::DSAVarData DVar =
4013 Stack->getImplicitDSA(VD,
false);
4014 InheritedDSA = DVar.CKind == OMPC_unknown;
4017 VarsWithInheritedDSA[VD] = E;
4018 if (Stack->getDefaultDSA() == DSA_none)
4033 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
4034 OMPC_DEFAULTMAP_MODIFIER_none;
4035 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
4036 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
4040 if (!Stack->checkMappableExprComponentListsForDecl(
4045 auto MI = MapExprComponents.rbegin();
4046 auto ME = MapExprComponents.rend();
4047 return MI != ME && MI->getAssociatedDeclaration() == VD;
4049 VarsWithInheritedDSA[VD] = E;
4055 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
4056 OMPC_DEFAULTMAP_MODIFIER_present;
4057 if (IsModifierPresent) {
4058 if (!llvm::is_contained(ImpInfo.MapModifiers[ClauseKind],
4059 OMPC_MAP_MODIFIER_present)) {
4060 ImpInfo.MapModifiers[ClauseKind].push_back(
4061 OMPC_MAP_MODIFIER_present);
4067 !Stack->isLoopControlVariable(VD).first) {
4068 if (!Stack->checkMappableExprComponentListsForDecl(
4073 if (SemaRef.LangOpts.OpenMP >= 50)
4074 return !StackComponents.empty();
4077 return StackComponents.size() == 1 ||
4079 llvm::drop_begin(llvm::reverse(StackComponents)),
4080 [](const OMPClauseMappableExprCommon::
4081 MappableComponent &MC) {
4082 return MC.getAssociatedDeclaration() ==
4084 (isa<ArraySectionExpr>(
4085 MC.getAssociatedExpression()) ||
4086 isa<OMPArrayShapingExpr>(
4087 MC.getAssociatedExpression()) ||
4088 isa<ArraySubscriptExpr>(
4089 MC.getAssociatedExpression()));
4092 bool IsFirstprivate =
false;
4094 if (
const auto *RD =
4096 IsFirstprivate = RD->isLambda();
4098 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
4099 if (IsFirstprivate) {
4100 ImpInfo.Firstprivates.insert(E);
4103 Stack->getDefaultmapModifier(ClauseKind);
4104 if (M == OMPC_DEFAULTMAP_MODIFIER_private) {
4105 ImpInfo.Privates.insert(E);
4108 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
4109 ImpInfo.Mappings[ClauseKind][
Kind].insert(E);
4120 DVar = Stack->hasInnermostDSA(
4123 return C == OMPC_reduction && !AppliedToPointee;
4132 SemaRef.
Diag(ELoc, diag::err_omp_reduction_in_task);
4138 DVar = Stack->getImplicitDSA(VD,
false);
4140 (((Stack->getDefaultDSA() == DSA_firstprivate &&
4141 DVar.CKind == OMPC_firstprivate) ||
4142 (Stack->getDefaultDSA() == DSA_private &&
4143 DVar.CKind == OMPC_private)) &&
4145 !Stack->isLoopControlVariable(VD).first) {
4146 if (Stack->getDefaultDSA() == DSA_private)
4147 ImpInfo.Privates.insert(E);
4149 ImpInfo.Firstprivates.insert(E);
4156 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
4157 Stack->addToParentTargetRegionLinkGlobals(E);
4162 void VisitMemberExpr(MemberExpr *E) {
4170 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD,
false);
4173 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
4177 !Stack->isLoopControlVariable(FD).first &&
4178 !Stack->checkMappableExprComponentListsForDecl(
4183 return isa<CXXThisExpr>(
4185 StackComponents.back().getAssociatedExpression())
4197 if (Stack->isClassPreviouslyMapped(TE->getType()))
4201 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4206 ImpInfo.Mappings[ClauseKind][
Kind].insert(E);
4215 DVar = Stack->hasInnermostDSA(
4218 return C == OMPC_reduction && !AppliedToPointee;
4227 SemaRef.
Diag(ELoc, diag::err_omp_reduction_in_task);
4233 DVar = Stack->getImplicitDSA(FD,
false);
4235 !Stack->isLoopControlVariable(FD).first) {
4240 if (DVar.CKind != OMPC_unknown)
4241 ImpInfo.Firstprivates.insert(E);
4251 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4252 if (!Stack->checkMappableExprComponentListsForDecl(
4258 auto CCI = CurComponents.rbegin();
4259 auto CCE = CurComponents.rend();
4260 for (const auto &SC : llvm::reverse(StackComponents)) {
4262 if (CCI->getAssociatedExpression()->getStmtClass() !=
4263 SC.getAssociatedExpression()->getStmtClass())
4264 if (!((isa<ArraySectionExpr>(
4265 SC.getAssociatedExpression()) ||
4266 isa<OMPArrayShapingExpr>(
4267 SC.getAssociatedExpression())) &&
4268 isa<ArraySubscriptExpr>(
4269 CCI->getAssociatedExpression())))
4272 const Decl *CCD = CCI->getAssociatedDeclaration();
4273 const Decl *SCD = SC.getAssociatedDeclaration();
4274 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4275 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4278 std::advance(CCI, 1);
4286 }
else if (!TryCaptureCXXThisMembers) {
4290 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4291 for (OMPClause *
C : S->clauses()) {
4294 if (isa_and_nonnull<OMPPrivateClause>(
C))
4302 for (Stmt *CC :
C->children()) {
4309 VisitSubCaptures(S);
4312 void VisitOMPCanonicalLoopNestTransformationDirective(
4313 OMPCanonicalLoopNestTransformationDirective *S) {
4318 void VisitCallExpr(CallExpr *S) {
4327 auto *CI =
Callee->IgnoreParenImpCasts();
4328 if (
auto *CE = dyn_cast<MemberExpr>(CI))
4329 Visit(CE->getBase());
4330 else if (
auto *CE = dyn_cast<DeclRefExpr>(CI))
4334 void VisitStmt(Stmt *S) {
4344 void visitSubCaptures(CapturedStmt *S) {
4345 for (
const CapturedStmt::Capture &Cap : S->
captures()) {
4346 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4348 VarDecl *VD = Cap.getCapturedVar();
4352 Stack->checkMappableExprComponentListsForDecl(
4359 Cap.getLocation(),
true);
4363 bool isErrorFound()
const {
return ErrorFound; }
4364 const VariableImplicitInfo &getImplicitInfo()
const {
return ImpInfo; }
4366 return VarsWithInheritedDSA;
4369 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4370 : Stack(S), SemaRef(SemaRef), ErrorFound(
false), CS(CS) {
4371 DKind = S->getCurrentDirective();
4374 for (DeclRefExpr *E : Stack->getLinkGlobals())
4386 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4388 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4390 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4392 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4394 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4395 Stack->handleConstructTrait(Traits, ScopeEntry);
4398static SmallVector<SemaOpenMP::CapturedParamNameType>
4402 Context.getIntTypeForBitwidth(32, 1).
withConst();
4406 std::make_pair(
".global_tid.", KmpInt32PtrTy),
4407 std::make_pair(
".bound_tid.", KmpInt32PtrTy),
4409 if (LoopBoundSharing) {
4411 Params.push_back(std::make_pair(
".previous.lb.", KmpSizeTy));
4412 Params.push_back(std::make_pair(
".previous.ub.", KmpSizeTy));
4416 Params.push_back(std::make_pair(StringRef(),
QualType()));
4420static SmallVector<SemaOpenMP::CapturedParamNameType>
4425static SmallVector<SemaOpenMP::CapturedParamNameType>
4435 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4437 std::make_pair(
".global_tid.", KmpInt32Ty),
4438 std::make_pair(
".part_id.", KmpInt32PtrTy),
4439 std::make_pair(
".privates.", VoidPtrTy),
4442 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4443 std::make_pair(
".task_t.", Context.VoidPtrTy.withConst()),
4444 std::make_pair(StringRef(),
QualType())
4449static SmallVector<SemaOpenMP::CapturedParamNameType>
4455 Params.push_back(std::make_pair(StringRef(
"dyn_ptr"), VoidPtrTy));
4458 Params.push_back(std::make_pair(StringRef(),
QualType()));
4462static SmallVector<SemaOpenMP::CapturedParamNameType>
4465 std::make_pair(StringRef(),
QualType())
4470static SmallVector<SemaOpenMP::CapturedParamNameType>
4474 Context.getIntTypeForBitwidth(32, 1).
withConst();
4476 Context.getIntTypeForBitwidth(64, 0).
withConst();
4478 Context.getIntTypeForBitwidth(64, 1).
withConst();
4485 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4487 std::make_pair(
".global_tid.", KmpInt32Ty),
4488 std::make_pair(
".part_id.", KmpInt32PtrTy),
4489 std::make_pair(
".privates.", VoidPtrTy),
4492 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4493 std::make_pair(
".task_t.", Context.VoidPtrTy.withConst()),
4494 std::make_pair(
".lb.", KmpUInt64Ty),
4495 std::make_pair(
".ub.", KmpUInt64Ty),
4496 std::make_pair(
".st.", KmpInt64Ty),
4497 std::make_pair(
".liter.", KmpInt32Ty),
4498 std::make_pair(
".reductions.", VoidPtrTy),
4499 std::make_pair(StringRef(),
QualType())
4512 CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
4513 SemaRef.
getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
4516 for (
auto [Level, RKind] : llvm::enumerate(Regions)) {
4551 case OMPD_metadirective:
4554 llvm_unreachable(
"Unexpected capture region");
4571 case OMPD_interchange:
4584int SemaOpenMP::getNumberOfConstructScopes(
unsigned Level)
const {
4585 return getOpenMPCaptureLevels(
DSAStack->getDirective(Level));
4591 return CaptureRegions.size();
4595 Expr *CaptureExpr,
bool WithInit,
4597 bool AsExpression) {
4598 assert(CaptureExpr);
4604 Ty =
C.getLValueReferenceType(Ty);
4606 Ty =
C.getPointerType(Ty);
4618 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(
C));
4668class CaptureRegionUnwinderRAII {
4675 CaptureRegionUnwinderRAII(Sema &S,
bool &ErrorFound,
4677 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4678 ~CaptureRegionUnwinderRAII() {
4681 while (--ThisCaptureLevel >= 0)
4691 if (!
SemaRef.CurContext->isDependentContext() &&
4694 DSAStack->getCurrentDirective()))) {
4696 if (
const auto *RD =
Type.getCanonicalType()
4697 .getNonReferenceType()
4699 bool SavedForceCaptureByReferenceInTargetExecutable =
4700 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4701 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4703 if (RD->isLambda()) {
4704 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4706 RD->getCaptureFields(Captures, ThisCapture);
4713 SemaRef.MarkVariableReferenced(LC.getLocation(), VD);
4714 }
else if (LC.getCaptureKind() ==
LCK_This) {
4717 ThisTy, ThisCapture->
getType()))
4718 SemaRef.CheckCXXThisCapture(LC.getLocation());
4722 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4723 SavedForceCaptureByReferenceInTargetExecutable);
4733 for (
const OMPClause *Clause : Clauses) {
4734 if (Clause->getClauseKind() == OMPC_ordered)
4736 else if (Clause->getClauseKind() == OMPC_order) {
4738 if (Order->
getKind() != OMPC_ORDER_concurrent)
4741 if (Ordered && Order)
4745 if (Ordered && Order) {
4747 diag::err_omp_simple_clause_incompatible_with_ordered)
4765 bool ErrorFound =
false;
4766 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4783 DSAStack->getCurrentDirective() == OMPD_target) &&
4784 Clause->getClauseKind() == OMPC_in_reduction) {
4788 for (
Expr *E : IRC->taskgroup_descriptors())
4790 SemaRef.MarkDeclarationsReferencedInExpr(E);
4793 Clause->getClauseKind() == OMPC_copyprivate ||
4796 Clause->getClauseKind() == OMPC_copyin)) {
4797 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4800 if (
auto *E = cast_or_null<Expr>(VarRef)) {
4801 SemaRef.MarkDeclarationsReferencedInExpr(E);
4804 DSAStack->setForceVarCapturing(
false);
4805 }
else if (CaptureRegions.size() > 1 ||
4806 CaptureRegions.back() != OMPD_unknown) {
4810 if (
Expr *E =
C->getPostUpdateExpr())
4811 SemaRef.MarkDeclarationsReferencedInExpr(E);
4814 if (Clause->getClauseKind() == OMPC_schedule)
4816 else if (Clause->getClauseKind() == OMPC_ordered)
4818 else if (Clause->getClauseKind() == OMPC_linear)
4823 SemaRef.MarkDeclarationsReferencedInExpr(E);
4830 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4835 diag::err_omp_simple_clause_incompatible_with_ordered)
4838 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4849 Diag(
C->getBeginLoc(), diag::err_omp_linear_ordered)
4859 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(), OMPVersion);
4866 unsigned CompletedRegions = 0;
4871 if (ThisCaptureRegion != OMPD_unknown) {
4879 if (CaptureRegion == ThisCaptureRegion ||
4880 CaptureRegion == OMPD_unknown) {
4881 if (
auto *DS = cast_or_null<DeclStmt>(
C->getPreInitStmt())) {
4882 for (
Decl *D : DS->decls())
4889 if (ThisCaptureRegion == OMPD_target) {
4893 if (
const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(
C)) {
4894 for (
unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4898 SemaRef.MarkDeclarationsReferencedInExpr(E);
4904 if (ThisCaptureRegion == OMPD_parallel) {
4908 if (
auto *RC = dyn_cast<OMPReductionClause>(
C)) {
4909 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4911 for (
Expr *E : RC->copy_array_temps())
4913 SemaRef.MarkDeclarationsReferencedInExpr(E);
4915 if (
auto *AC = dyn_cast<OMPAlignedClause>(
C)) {
4916 for (
Expr *E : AC->varlist())
4917 SemaRef.MarkDeclarationsReferencedInExpr(E);
4921 if (++CompletedRegions == CaptureRegions.size())
4923 SR =
SemaRef.ActOnCapturedRegionEnd(SR.
get());
4932 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4935 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4936 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4939 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
4940 SemaRef.
Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4941 << getOpenMPDirectiveName(CancelRegion, OMPVersion);
4951 if (!Stack->getCurScope())
4956 bool NestingProhibited =
false;
4957 bool CloseNesting =
true;
4958 bool OrphanSeen =
false;
4961 ShouldBeInParallelRegion,
4962 ShouldBeInOrderedRegion,
4963 ShouldBeInTargetRegion,
4964 ShouldBeInTeamsRegion,
4965 ShouldBeInLoopSimdRegion,
4966 } Recommend = NoRecommend;
4970 getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
4972 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
4974 if (OMPVersion >= 50 && Stack->isParentOrderConcurrent() &&
4977 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_order)
4978 << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
4982 ((OMPVersion <= 45 && CurrentRegion != OMPD_ordered) ||
4983 (OMPVersion >= 50 && CurrentRegion != OMPD_ordered &&
4984 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
4985 CurrentRegion != OMPD_scan))) {
4998 SemaRef.
Diag(StartLoc, (CurrentRegion != OMPD_simd)
4999 ? diag::err_omp_prohibited_region_simd
5000 : diag::warn_omp_nesting_simd)
5001 << (OMPVersion >= 50 ? 1 : 0);
5002 return CurrentRegion != OMPD_simd;
5004 if (EnclosingConstruct == OMPD_atomic) {
5007 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
5010 if (CurrentRegion == OMPD_section) {
5015 if (EnclosingConstruct != OMPD_sections) {
5016 SemaRef.
Diag(StartLoc, diag::err_omp_orphaned_section_directive)
5017 << (ParentRegion != OMPD_unknown)
5018 << getOpenMPDirectiveName(ParentRegion, OMPVersion);
5026 if (ParentRegion == OMPD_unknown &&
5028 CurrentRegion != OMPD_cancellation_point &&
5029 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
5033 if (OMPVersion >= 50 && CurrentRegion == OMPD_loop &&
5034 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
5036 EnclosingConstruct == OMPD_loop)) {
5037 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
5038 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region)
5039 <<
true << getOpenMPDirectiveName(ParentRegion, OMPVersion)
5040 << ErrorMsgNumber << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5043 if (CurrentRegion == OMPD_cancellation_point ||
5044 CurrentRegion == OMPD_cancel) {
5057 if (CancelRegion == OMPD_taskgroup) {
5059 EnclosingConstruct != OMPD_task &&
5060 (OMPVersion < 50 || EnclosingConstruct != OMPD_taskloop);
5061 }
else if (CancelRegion == OMPD_sections) {
5062 NestingProhibited = EnclosingConstruct != OMPD_section &&
5063 EnclosingConstruct != OMPD_sections;
5065 NestingProhibited = CancelRegion != Leafs.back();
5067 OrphanSeen = ParentRegion == OMPD_unknown;
5068 }
else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5075 }
else if (CurrentRegion == OMPD_critical && CurrentName.
getName()) {
5081 bool DeadLock = Stack->hasDirective(
5085 if (K == OMPD_critical && DNI.
getName() == CurrentName.
getName()) {
5086 PreviousCriticalLoc = Loc;
5093 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name)
5095 if (PreviousCriticalLoc.
isValid())
5096 SemaRef.
Diag(PreviousCriticalLoc,
5097 diag::note_omp_previous_critical_region);
5100 }
else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
5110 llvm::is_contained({OMPD_masked, OMPD_master,
5111 OMPD_critical, OMPD_ordered},
5112 EnclosingConstruct);
5123 llvm::is_contained({OMPD_masked, OMPD_master,
5124 OMPD_critical, OMPD_ordered},
5125 EnclosingConstruct);
5126 Recommend = ShouldBeInParallelRegion;
5127 }
else if (CurrentRegion == OMPD_ordered) {
5136 NestingProhibited = EnclosingConstruct == OMPD_critical ||
5139 Stack->isParentOrderedRegion());
5140 Recommend = ShouldBeInOrderedRegion;
5146 (OMPVersion <= 45 && EnclosingConstruct != OMPD_target) ||
5147 (OMPVersion >= 50 && EnclosingConstruct != OMPD_unknown &&
5148 EnclosingConstruct != OMPD_target);
5149 OrphanSeen = ParentRegion == OMPD_unknown;
5150 Recommend = ShouldBeInTargetRegion;
5151 }
else if (CurrentRegion == OMPD_scan) {
5152 if (OMPVersion >= 50) {
5157 NestingProhibited = !llvm::is_contained(
5158 {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
5160 NestingProhibited =
true;
5162 OrphanSeen = ParentRegion == OMPD_unknown;
5163 Recommend = ShouldBeInLoopSimdRegion;
5167 EnclosingConstruct == OMPD_teams) {
5179 CurrentRegion != OMPD_loop &&
5181 CurrentRegion == OMPD_atomic);
5182 Recommend = ShouldBeInParallelRegion;
5184 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5190 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5191 Recommend = ShouldBeInTeamsRegion;
5197 NestingProhibited = EnclosingConstruct != OMPD_teams;
5198 Recommend = ShouldBeInTeamsRegion;
5200 if (!NestingProhibited &&
5207 NestingProhibited = Stack->hasDirective(
5211 OffendingRegion = K;
5217 CloseNesting =
false;
5219 if (NestingProhibited) {
5221 SemaRef.
Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5222 << getOpenMPDirectiveName(CurrentRegion, OMPVersion) << Recommend;
5224 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region)
5225 << CloseNesting << getOpenMPDirectiveName(OffendingRegion, OMPVersion)
5226 << Recommend << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5240 bool ErrorFound =
false;
5241 unsigned NamedModifiersNumber = 0;
5242 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5243 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5247 if (
const auto *IC = dyn_cast_or_null<OMPIfClause>(
C)) {
5251 auto &FNM = FoundNameModifiers[CurNM];
5253 S.
Diag(
C->getBeginLoc(), diag::err_omp_more_one_clause)
5254 << getOpenMPDirectiveName(Kind, OMPVersion)
5256 << getOpenMPDirectiveName(CurNM, OMPVersion);
5258 }
else if (CurNM != OMPD_unknown) {
5259 NameModifierLoc.push_back(IC->getNameModifierLoc());
5260 ++NamedModifiersNumber;
5263 if (CurNM == OMPD_unknown)
5269 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5270 S.
Diag(IC->getNameModifierLoc(),
5271 diag::err_omp_wrong_if_directive_name_modifier)
5272 << getOpenMPDirectiveName(CurNM, OMPVersion)
5273 << getOpenMPDirectiveName(Kind, OMPVersion);
5280 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5281 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5282 S.
Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5283 diag::err_omp_no_more_if_clause);
5286 std::string Sep(
", ");
5287 unsigned AllowedCnt = 0;
5288 unsigned TotalAllowedNum =
5289 AllowedNameModifiers.size() - NamedModifiersNumber;
5290 for (
unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5293 if (!FoundNameModifiers[NM]) {
5295 Values += getOpenMPDirectiveName(NM, OMPVersion);
5297 if (AllowedCnt + 2 == TotalAllowedNum)
5299 else if (AllowedCnt + 1 != TotalAllowedNum)
5304 S.
Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5305 diag::err_omp_unnamed_if_clause)
5306 << (TotalAllowedNum > 1) << Values;
5309 S.
Diag(Loc, diag::note_omp_previous_named_if_clause);
5316static std::pair<ValueDecl *, bool>
5319 bool AllowAssumedSizeArray, StringRef DiagType) {
5322 return std::make_pair(
nullptr,
true);
5348 } IsArrayExpr = NoArrayExpr;
5349 if (AllowArraySection) {
5350 if (
auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5351 Expr *
Base = ASE->getBase()->IgnoreParenImpCasts();
5352 while (
auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
5353 Base = TempASE->getBase()->IgnoreParenImpCasts();
5356 }
else if (
auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5357 Expr *
Base = OASE->getBase()->IgnoreParenImpCasts();
5358 if (S.
getLangOpts().OpenMP >= 60 && !AllowAssumedSizeArray &&
5359 OASE->getColonLocFirst().isValid() && !OASE->getLength()) {
5361 if (BaseType.isNull() || (!BaseType->isConstantArrayType() &&
5362 !BaseType->isVariableArrayType())) {
5363 S.
Diag(OASE->getColonLocFirst(),
5364 diag::err_omp_section_length_undefined)
5365 << (!BaseType.isNull() && BaseType->isArrayType());
5366 return std::make_pair(
nullptr,
false);
5369 while (
auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base))
5370 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5371 while (
auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
5372 Base = TempASE->getBase()->IgnoreParenImpCasts();
5374 IsArrayExpr = OMPArraySection;
5380 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5381 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5386 if (IsArrayExpr != NoArrayExpr) {
5387 S.
Diag(ELoc, diag::err_omp_expected_base_var_name)
5388 << IsArrayExpr << ERange;
5389 }
else if (!DiagType.empty()) {
5393 S.
Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5394 << DiagSelect << DiagType << ERange;
5398 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5399 : diag::err_omp_expected_var_name_member_expr)
5402 return std::make_pair(
nullptr,
false);
5404 return std::make_pair(
5411class AllocatorChecker final :
public ConstStmtVisitor<AllocatorChecker, bool> {
5412 DSAStackTy *S =
nullptr;
5415 bool VisitDeclRefExpr(
const DeclRefExpr *E) {
5416 return S->isUsesAllocatorsDecl(E->
getDecl())
5417 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5418 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5420 bool VisitStmt(
const Stmt *S) {
5421 for (
const Stmt *Child : S->
children()) {
5422 if (Child && Visit(Child))
5427 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5434 "Expected non-dependent context.");
5435 auto AllocateRange =
5438 auto PrivateRange = llvm::make_filter_range(Clauses, [](
const OMPClause *
C) {
5443 if (
Cl->getClauseKind() == OMPC_private) {
5445 I = PC->private_copies().begin();
5446 It = PC->varlist_begin();
5447 Et = PC->varlist_end();
5448 }
else if (
Cl->getClauseKind() == OMPC_firstprivate) {
5450 I = PC->private_copies().begin();
5451 It = PC->varlist_begin();
5452 Et = PC->varlist_end();
5453 }
else if (
Cl->getClauseKind() == OMPC_lastprivate) {
5455 I = PC->private_copies().begin();
5456 It = PC->varlist_begin();
5457 Et = PC->varlist_end();
5458 }
else if (
Cl->getClauseKind() == OMPC_linear) {
5460 I = PC->privates().begin();
5461 It = PC->varlist_begin();
5462 Et = PC->varlist_end();
5463 }
else if (
Cl->getClauseKind() == OMPC_reduction) {
5465 I = PC->privates().begin();
5466 It = PC->varlist_begin();
5467 Et = PC->varlist_end();
5468 }
else if (
Cl->getClauseKind() == OMPC_task_reduction) {
5470 I = PC->privates().begin();
5471 It = PC->varlist_begin();
5472 Et = PC->varlist_end();
5473 }
else if (
Cl->getClauseKind() == OMPC_in_reduction) {
5475 I = PC->privates().begin();
5476 It = PC->varlist_begin();
5477 Et = PC->varlist_end();
5479 llvm_unreachable(
"Expected private clause.");
5481 for (
Expr *E : llvm::make_range(It, Et)) {
5488 Expr *SimpleRefExpr = E;
5491 DeclToCopy.try_emplace(Res.first,
5501 AC->getAllocator()) {
5502 Expr *Allocator = AC->getAllocator();
5508 AllocatorChecker Checker(Stack);
5509 if (Checker.Visit(Allocator))
5511 diag::err_omp_allocator_not_in_uses_allocators)
5514 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5520 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5524 S.
Diag(AC->getAllocator()->getExprLoc(),
5525 diag::warn_omp_allocate_thread_on_task_target_directive)
5526 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
5528 for (
Expr *E : AC->varlist()) {
5531 Expr *SimpleRefExpr = E;
5536 DSAStackTy::DSAVarData
Data = Stack->getTopDSA(VD,
false);
5539 diag::err_omp_expected_private_copy_for_allocate);
5542 VarDecl *PrivateVD = DeclToCopy[VD];
5544 AllocatorKind, AC->getAllocator()))
5558class CaptureVars :
public TreeTransform<CaptureVars> {
5559 using BaseTransform = TreeTransform<CaptureVars>;
5562 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5564 bool AlwaysRebuild() {
return true; }
5577 BodyStmts.push_back(NewDeclStmt);
5615 DistParam, LogicalTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
5626 auto BuildVarRef = [&](
VarDecl *VD) {
5631 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 0), LogicalTy, {});
5633 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 1), LogicalTy, {});
5639 Actions.
BuildBinOp(
nullptr, {}, BO_LT, BuildVarRef(NewStep),
Zero));
5643 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5647 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5651 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5655 Actions.
BuildUnaryOp(
nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5657 Actions.
BuildBinOp(
nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5661 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5663 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5664 "Expected one of these relational operators");
5671 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5675 if (Rel == BO_GE || Rel == BO_GT)
5677 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5680 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5686 if (Rel == BO_LE || Rel == BO_GE) {
5698 Expr *Divisor = BuildVarRef(NewStep);
5699 if (Rel == BO_GE || Rel == BO_GT)
5702 Expr *DivisorMinusOne =
5705 Actions.
BuildBinOp(
nullptr, {}, BO_Add, Range, DivisorMinusOne));
5707 Actions.
BuildBinOp(
nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5717 Actions.
getCurScope(), {}, BO_Assign, DistRef, Dist));
5718 BodyStmts.push_back(ResultAssign);
5750 {
"Logical", LogicalTy},
5761 assert(!
Invalid &&
"Expecting capture-by-value to work.");
5770 TargetParam, LoopVarTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
5773 IndvarParam, LogicalTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
5776 CaptureVars Recap(Actions);
5781 Actions.
BuildBinOp(
nullptr, {}, BO_Mul, NewStep, LogicalRef));
5796 BO_Assign, TargetRef, Advanced));
5809 if (
auto *For = dyn_cast<ForStmt>(AStmt)) {
5811 if (
auto *LCVarDeclStmt = dyn_cast<DeclStmt>(
Init)) {
5814 }
else if (
auto *LCAssign = dyn_cast<BinaryOperator>(
Init)) {
5816 assert(LCAssign->getOpcode() == BO_Assign &&
5817 "init part must be a loop variable assignment");
5821 llvm_unreachable(
"Cannot determine loop variable");
5824 Cond = For->getCond();
5825 Inc = For->getInc();
5826 }
else if (
auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5827 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5829 LUVDecl = RangeFor->getLoopVariable();
5831 Cond = RangeFor->getCond();
5832 Inc = RangeFor->getInc();
5834 llvm_unreachable(
"unhandled kind of loop");
5843 if (
auto *CondBinExpr = dyn_cast<BinaryOperator>(
Cond)) {
5844 LHS = CondBinExpr->getLHS();
5845 RHS = CondBinExpr->getRHS();
5846 CondRel = CondBinExpr->getOpcode();
5847 }
else if (
auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(
Cond)) {
5848 assert(CondCXXOp->getNumArgs() == 2 &&
"Comparison should have 2 operands");
5849 LHS = CondCXXOp->getArg(0);
5850 RHS = CondCXXOp->getArg(1);
5851 switch (CondCXXOp->getOperator()) {
5852 case OO_ExclaimEqual:
5864 case OO_GreaterEqual:
5868 llvm_unreachable(
"unexpected iterator operator");
5871 llvm_unreachable(
"unexpected loop condition");
5876 std::swap(LHS, RHS);
5893 if (
auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5895 switch (IncUn->getOpcode()) {
5905 llvm_unreachable(
"unhandled unary increment operator");
5909 llvm::APInt(Ctx.
getIntWidth(LogicalTy), Direction,
true),
5911 }
else if (
auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5912 if (IncBin->getOpcode() == BO_AddAssign) {
5913 Step = IncBin->getRHS();
5914 }
else if (IncBin->getOpcode() == BO_SubAssign) {
5916 SemaRef.BuildUnaryOp(
nullptr, {}, UO_Minus, IncBin->getRHS()));
5918 llvm_unreachable(
"unhandled binary increment operator");
5919 }
else if (
auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5920 switch (CondCXXOp->getOperator()) {
5923 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 1), LogicalTy, {});
5927 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), -1), LogicalTy, {});
5930 Step = CondCXXOp->getArg(1);
5934 SemaRef.BuildUnaryOp(
nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5937 llvm_unreachable(
"unhandled overloaded increment operator");
5940 llvm_unreachable(
"unknown increment expression");
5948 nullptr,
nullptr, {},
nullptr);
5949 return OMPCanonicalLoop::create(
getASTContext(), AStmt, DistanceFunc,
5950 LoopVarFunc, LVRef);
5962 "Loop transformation directive expected");
5963 return LoopTransform;
5970 Expr *UnresolvedMapper);
5981 for (
int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
5982 auto *
C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
5986 auto *MI =
C->mapperlist_begin();
5987 for (
auto I =
C->varlist_begin(), End =
C->varlist_end(); I != End;
6006 if (
const auto *ATy = BaseType->getAsArrayTypeUnsafe())
6007 ElemType = ATy->getElementType();
6010 CanonType = ElemType;
6015 1, {CanonType,
nullptr});
6016 llvm::DenseMap<const Type *, Expr *> Visited;
6019 while (!Types.empty()) {
6022 std::tie(BaseType, CurFD) = Types.pop_back_val();
6023 while (ParentChain.back().second == 0)
6024 ParentChain.pop_back();
6025 --ParentChain.back().second;
6026 if (BaseType.isNull())
6029 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
6032 auto It = Visited.find(BaseType.getTypePtr());
6033 if (It == Visited.end()) {
6041 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
6045 It = Visited.try_emplace(BaseType.getTypePtr(), ER.
get()).first;
6052 Expr *BaseExpr = OE;
6053 for (
const auto &P : ParentChain) {
6071 SubExprs.push_back(BaseExpr);
6075 bool FirstIter =
true;
6085 ParentChain.emplace_back(CurFD, 1);
6087 ++ParentChain.back().second;
6089 Types.emplace_back(FieldTy, FD);
6093 if (SubExprs.empty())
6098 nullptr,
C->getMapTypeModifiers(),
C->getMapTypeModifiersLoc(),
6099 MapperIdScopeSpec, MapperId,
C->getMapType(),
6102 Clauses.push_back(NewClause);
6109class TeamsLoopChecker final :
public ConstStmtVisitor<TeamsLoopChecker> {
6116 void VisitOMPExecutableDirective(
const OMPExecutableDirective *D) {
6117 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
6118 if (
const auto *
C = D->getSingleClause<OMPBindClause>())
6119 if (
C->getBindKind() == OMPC_BIND_parallel) {
6120 TeamsLoopCanBeParallelFor =
false;
6125 for (
const Stmt *Child : D->children())
6130 void VisitCallExpr(
const CallExpr *
C) {
6135 bool IsOpenMPAPI =
false;
6136 auto *FD = dyn_cast_or_null<FunctionDecl>(
C->getCalleeDecl());
6138 std::string Name = FD->getNameInfo().getAsString();
6139 IsOpenMPAPI = Name.find(
"omp_") == 0;
6141 TeamsLoopCanBeParallelFor =
6142 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
6143 if (!TeamsLoopCanBeParallelFor)
6146 for (
const Stmt *Child :
C->children())
6151 void VisitCapturedStmt(
const CapturedStmt *S) {
6157 void VisitStmt(
const Stmt *S) {
6160 for (
const Stmt *Child : S->
children())
6164 explicit TeamsLoopChecker(Sema &SemaRef)
6165 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(
true) {}
6168 bool TeamsLoopCanBeParallelFor;
6173 TeamsLoopChecker Checker(SemaRef);
6174 Checker.Visit(AStmt);
6175 return Checker.teamsLoopCanBeParallelFor();
6189 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6190 BindKind = BC->getBindKind();
6202 BindKind = OMPC_BIND_thread;
6204 getLeafConstructsOrSelf(ParentDirective);
6206 if (ParentDirective == OMPD_unknown) {
6208 diag::err_omp_bind_required_on_loop);
6209 }
else if (ParentLeafs.back() == OMPD_parallel) {
6210 BindKind = OMPC_BIND_parallel;
6211 }
else if (ParentLeafs.back() == OMPD_teams) {
6212 BindKind = OMPC_BIND_teams;
6220 ClausesWithImplicit.push_back(
C);
6224 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6226 if (
C->getClauseKind() == OMPC_reduction)
6228 diag::err_omp_loop_reduction_clause);
6235 BindKind, StartLoc)) {
6242 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6245 bool ErrorFound =
false;
6246 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6248 if (AStmt && !
SemaRef.CurContext->isDependentContext() &&
6256 while (--ThisCaptureLevel >= 0)
6258 DSAChecker.Visit(S);
6266 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6268 DSAChecker.visitSubCaptures(CS);
6270 if (DSAChecker.isErrorFound())
6273 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6274 VariableImplicitInfo ImpInfo = DSAChecker.getImplicitInfo();
6277 ImplicitMapModifiersLoc[VariableImplicitInfo::DefaultmapKindNum];
6279 SourceLocation PresentModifierLocs[VariableImplicitInfo::DefaultmapKindNum];
6281 if (
auto *DMC = dyn_cast<OMPDefaultmapClause>(
C))
6282 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6283 PresentModifierLocs[DMC->getDefaultmapKind()] =
6284 DMC->getDefaultmapModifierLoc();
6288 llvm::enum_seq_inclusive<OpenMPDefaultmapClauseKind>(
6290 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[K]),
6291 ImpInfo.MapModifiers[K].size(), PresentModifierLocs[K]);
6295 if (
auto *IRC = dyn_cast<OMPInReductionClause>(
C)) {
6296 for (
Expr *E : IRC->taskgroup_descriptors())
6298 ImpInfo.Firstprivates.insert(E);
6303 if (
auto *DC = dyn_cast<OMPDetachClause>(
C))
6304 ImpInfo.Firstprivates.insert(DC->getEventHandler());
6306 if (!ImpInfo.Firstprivates.empty()) {
6310 ClausesWithImplicit.push_back(
Implicit);
6312 ImpInfo.Firstprivates.size();
6317 if (!ImpInfo.Privates.empty()) {
6321 ClausesWithImplicit.push_back(
Implicit);
6323 ImpInfo.Privates.size();
6332 if (
getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6336 if (
auto *RC = dyn_cast<OMPReductionClause>(
C))
6337 for (
Expr *E : RC->varlist())
6339 ImplicitExprs.emplace_back(E);
6341 if (!ImplicitExprs.empty()) {
6347 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6350 ClausesWithImplicit.emplace_back(
Implicit);
6353 for (
unsigned I = 0; I < VariableImplicitInfo::DefaultmapKindNum; ++I) {
6354 int ClauseKindCnt = -1;
6355 for (
unsigned J = 0; J < VariableImplicitInfo::MapKindNum; ++J) {
6358 if (ImplicitMap.empty())
6364 nullptr, ImpInfo.MapModifiers[I], ImplicitMapModifiersLoc[I],
6365 MapperIdScopeSpec, MapperId, K,
true,
6368 ClausesWithImplicit.emplace_back(
Implicit);
6380 ClausesWithImplicit);
6390 VarsWithInheritedDSA);
6405 assert(ClausesWithImplicit.empty() &&
6406 "reverse directive does not support any clauses");
6409 case OMPD_interchange:
6415 VarsWithInheritedDSA);
6419 EndLoc, VarsWithInheritedDSA);
6426 assert(ClausesWithImplicit.empty() &&
6427 "No clauses are allowed for 'omp section' directive");
6435 assert(ClausesWithImplicit.empty() &&
6436 "No clauses are allowed for 'omp master' directive");
6447 case OMPD_parallel_for:
6449 EndLoc, VarsWithInheritedDSA);
6451 case OMPD_parallel_for_simd:
6453 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6459 case OMPD_parallel_master:
6463 case OMPD_parallel_masked:
6467 case OMPD_parallel_sections:
6475 case OMPD_taskyield:
6476 assert(ClausesWithImplicit.empty() &&
6477 "No clauses are allowed for 'omp taskyield' directive");
6478 assert(AStmt ==
nullptr &&
6479 "No associated statement allowed for 'omp taskyield' directive");
6483 assert(AStmt ==
nullptr &&
6484 "No associated statement allowed for 'omp error' directive");
6488 assert(ClausesWithImplicit.empty() &&
6489 "No clauses are allowed for 'omp barrier' directive");
6490 assert(AStmt ==
nullptr &&
6491 "No associated statement allowed for 'omp barrier' directive");
6495 assert(AStmt ==
nullptr &&
6496 "No associated statement allowed for 'omp taskwait' directive");
6499 case OMPD_taskgroup:
6504 assert(AStmt ==
nullptr &&
6505 "No associated statement allowed for 'omp flush' directive");
6509 assert(AStmt ==
nullptr &&
6510 "No associated statement allowed for 'omp depobj' directive");
6514 assert(AStmt ==
nullptr &&
6515 "No associated statement allowed for 'omp scan' directive");
6534 case OMPD_target_parallel:
6538 case OMPD_target_parallel_for:
6540 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6542 case OMPD_cancellation_point:
6543 assert(ClausesWithImplicit.empty() &&
6544 "No clauses are allowed for 'omp cancellation point' directive");
6545 assert(AStmt ==
nullptr &&
"No associated statement allowed for 'omp "
6546 "cancellation point' directive");
6550 assert(AStmt ==
nullptr &&
6551 "No associated statement allowed for 'omp cancel' directive");
6555 case OMPD_target_data:
6559 case OMPD_target_enter_data:
6563 case OMPD_target_exit_data:
6569 EndLoc, VarsWithInheritedDSA);
6571 case OMPD_taskloop_simd:
6573 EndLoc, VarsWithInheritedDSA);
6575 case OMPD_master_taskloop:
6577 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6579 case OMPD_masked_taskloop:
6581 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6583 case OMPD_master_taskloop_simd:
6585 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6587 case OMPD_masked_taskloop_simd:
6589 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6591 case OMPD_parallel_master_taskloop:
6593 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6595 case OMPD_parallel_masked_taskloop:
6597 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6599 case OMPD_parallel_master_taskloop_simd:
6601 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6603 case OMPD_parallel_masked_taskloop_simd:
6605 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6607 case OMPD_distribute:
6609 EndLoc, VarsWithInheritedDSA);
6611 case OMPD_target_update:
6615 case OMPD_distribute_parallel_for:
6617 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6619 case OMPD_distribute_parallel_for_simd:
6621 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6623 case OMPD_distribute_simd:
6625 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6627 case OMPD_target_parallel_for_simd:
6629 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6631 case OMPD_target_simd:
6633 EndLoc, VarsWithInheritedDSA);
6635 case OMPD_teams_distribute:
6637 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6639 case OMPD_teams_distribute_simd:
6641 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6643 case OMPD_teams_distribute_parallel_for_simd:
6645 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6647 case OMPD_teams_distribute_parallel_for:
6649 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6651 case OMPD_target_teams:
6655 case OMPD_target_teams_distribute:
6657 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6659 case OMPD_target_teams_distribute_parallel_for:
6661 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6663 case OMPD_target_teams_distribute_parallel_for_simd:
6665 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6667 case OMPD_target_teams_distribute_simd:
6669 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6672 assert(AStmt ==
nullptr &&
6673 "No associated statement allowed for 'omp interop' directive");
6682 EndLoc, VarsWithInheritedDSA);
6684 case OMPD_teams_loop:
6686 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6688 case OMPD_target_teams_loop:
6690 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6692 case OMPD_parallel_loop:
6694 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6696 case OMPD_target_parallel_loop:
6698 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6700 case OMPD_declare_target:
6701 case OMPD_end_declare_target:
6702 case OMPD_threadprivate:
6704 case OMPD_declare_reduction:
6705 case OMPD_declare_mapper:
6706 case OMPD_declare_simd:
6708 case OMPD_declare_variant:
6709 case OMPD_begin_declare_variant:
6710 case OMPD_end_declare_variant:
6711 llvm_unreachable(
"OpenMP Directive is not allowed");
6714 llvm_unreachable(
"Unknown OpenMP directive");
6717 ErrorFound = Res.
isInvalid() || ErrorFound;
6721 if (
DSAStack->getDefaultDSA() == DSA_none ||
6722 DSAStack->getDefaultDSA() == DSA_private ||
6723 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6726 switch (
C->getClauseKind()) {
6727 case OMPC_num_threads:
6728 case OMPC_dist_schedule:
6745 case OMPC_grainsize:
6746 case OMPC_num_tasks:
6749 case OMPC_novariants:
6750 case OMPC_nocontext:
6757 case OMPC_num_teams:
6758 case OMPC_thread_limit:
6765 case OMPC_proc_bind:
6767 case OMPC_firstprivate:
6768 case OMPC_lastprivate:
6770 case OMPC_reduction:
6771 case OMPC_task_reduction:
6772 case OMPC_in_reduction:
6776 case OMPC_copyprivate:
6779 case OMPC_mergeable:
6796 case OMPC_defaultmap:
6799 case OMPC_use_device_ptr:
6800 case OMPC_use_device_addr:
6801 case OMPC_is_device_ptr:
6802 case OMPC_has_device_addr:
6803 case OMPC_nontemporal:
6806 case OMPC_inclusive:
6807 case OMPC_exclusive:
6808 case OMPC_uses_allocators:
6815 case OMPC_allocator:
6818 case OMPC_threadprivate:
6819 case OMPC_groupprivate:
6822 case OMPC_unified_address:
6823 case OMPC_unified_shared_memory:
6824 case OMPC_reverse_offload:
6825 case OMPC_dynamic_allocators:
6826 case OMPC_atomic_default_mem_order:
6827 case OMPC_self_maps:
6828 case OMPC_device_type:
6833 llvm_unreachable(
"Unexpected clause");
6835 for (
Stmt *CC :
C->children()) {
6837 DSAChecker.Visit(CC);
6840 for (
const auto &P : DSAChecker.getVarsWithInheritedDSA())
6841 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6843 for (
const auto &P : VarsWithInheritedDSA) {
6847 if (
DSAStack->getDefaultDSA() == DSA_none ||
6848 DSAStack->getDefaultDSA() == DSA_private ||
6849 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6850 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6851 << P.first << P.second->getSourceRange();
6852 Diag(
DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6854 Diag(P.second->getExprLoc(),
6855 diag::err_omp_defaultmap_no_attr_for_variable)
6856 << P.first << P.second->getSourceRange();
6858 diag::note_omp_defaultmap_attr_none);
6864 if (isAllowedClauseForDirective(D, OMPC_if,
getLangOpts().OpenMP))
6865 AllowedNameModifiers.push_back(D);
6867 if (!AllowedNameModifiers.empty())
6874 if (!
SemaRef.CurContext->isDependentContext() &&
6881 DSAStack->addTargetDirLocation(StartLoc);
6892 assert(Aligneds.size() == Alignments.size());
6893 assert(Linears.size() == LinModifiers.size());
6894 assert(Linears.size() == Steps.size());
6898 const int SimdId = 0;
6900 Diag(SR.
getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6905 if (
auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6906 ADecl = FTD->getTemplatedDecl();
6908 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6910 Diag(ADecl->
getLocation(), diag::err_omp_function_expected) << SimdId;
6926 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6927 const Expr *UniformedLinearThis =
nullptr;
6928 for (
const Expr *E : Uniforms) {
6930 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E))
6931 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
6932 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6933 FD->getParamDecl(PVD->getFunctionScopeIndex())
6935 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
6939 UniformedLinearThis = E;
6953 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6954 const Expr *AlignedThis =
nullptr;
6955 for (
const Expr *E : Aligneds) {
6957 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E))
6958 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6960 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6961 FD->getParamDecl(PVD->getFunctionScopeIndex())
6965 auto [It, Inserted] = AlignedArgs.try_emplace(CanonPVD, E);
6970 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
6975 .getNonReferenceType()
6976 .getUnqualifiedType()
6977 .getCanonicalType();
6980 Diag(E->
getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
6982 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
7006 for (
Expr *E : Alignments) {
7010 NewAligns.push_back(Align.
get());
7021 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
7022 const bool IsUniformedThis = UniformedLinearThis !=
nullptr;
7023 auto MI = LinModifiers.begin();
7024 for (
const Expr *E : Linears) {
7028 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E))
7029 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7031 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7032 FD->getParamDecl(PVD->getFunctionScopeIndex())
7036 if (
auto It = LinearArgs.find(CanonPVD); It != LinearArgs.end()) {
7041 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7046 if (
auto It = UniformedArgs.find(CanonPVD);
7047 It != UniformedArgs.end()) {
7052 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7056 LinearArgs[CanonPVD] = E;
7062 PVD->getOriginalType(),
7068 if (UniformedLinearThis) {
7074 Diag(UniformedLinearThis->
getExprLoc(), diag::note_omp_explicit_dsa)
7079 UniformedLinearThis = E;
7090 Expr *Step =
nullptr;
7091 Expr *NewStep =
nullptr;
7093 for (
Expr *E : Steps) {
7095 if (Step == E || !E) {
7096 NewSteps.push_back(E ? NewStep :
nullptr);
7100 if (
const auto *DRE = dyn_cast<DeclRefExpr>(Step))
7101 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7103 if (UniformedArgs.count(CanonPVD) == 0) {
7110 NewSteps.push_back(Step);
7125 .VerifyIntegerConstantExpression(
7129 NewSteps.push_back(NewStep);
7131 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7133 Uniforms.size(),
const_cast<Expr **
>(Aligneds.data()), Aligneds.size(),
7134 const_cast<Expr **
>(NewAligns.data()), NewAligns.size(),
7135 const_cast<Expr **
>(Linears.data()), Linears.size(),
7136 const_cast<unsigned *
>(LinModifiers.data()), LinModifiers.size(),
7137 NewSteps.data(), NewSteps.size(), SR);
7147 "Unexpected directive category");
7156 llvm_unreachable(
"Unknown OpenMP directive");
7165 "Expected function type with prototype.");
7167 "Expected function with type with no prototype.");
7169 "Expected function with prototype.");
7177 Param->setScopeInfo(0, Params.size());
7178 Param->setImplicit();
7179 Params.push_back(Param);
7182 FD->setParams(Params);
7189 if (
auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7190 FD = UTemplDecl->getTemplatedDecl();
7193 assert(FD &&
"Expected a function declaration!");
7198 if (!
SemaRef.inTemplateInstantiation()) {
7199 for (OMPAssumeAttr *AA : OMPAssumeScoped)
7202 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7206SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(
OMPTraitInfo &TI)
7207 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7215 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7218 bool IsTemplated = !TemplateParamLists.empty();
7221 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7238 for (
auto *Candidate : Lookup) {
7239 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7243 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7244 UDecl = FTD->getTemplatedDecl();
7245 }
else if (!IsTemplated)
7246 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7260 FType, UDeclTy,
false,
7267 Bases.push_back(UDecl);
7271 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7273 if (Bases.empty() && UseImplicitBase) {
7275 Decl *BaseD =
SemaRef.HandleDeclarator(S, D, TemplateParamLists);
7277 if (
auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7278 Bases.push_back(BaseTemplD->getTemplatedDecl());
7283 std::string MangledName;
7286 MangledName += DVScope.NameSuffix;
7301 if (
auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7302 FD = UTemplDecl->getTemplatedDecl();
7310 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7311 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7318 BaseFD->addAttr(OMPDeclareVariantA);
7338 CalleeFnDecl->
getName().starts_with_insensitive(
"omp_")) {
7341 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7344 if (!CalleeFnDecl->
hasAttr<OMPDeclareVariantAttr>())
7349 CE](StringRef ISATrait) {
7363 while (CalleeFnDecl) {
7364 for (OMPDeclareVariantAttr *A :
7366 Expr *VariantRef = A->getVariantFuncRef();
7368 VariantMatchInfo VMI;
7371 if (!isVariantApplicableInContext(VMI, OMPCtx,
7375 VMIs.push_back(VMI);
7376 Exprs.push_back(VariantRef);
7384 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7404 if (
auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7405 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7407 Context, MemberCall->getImplicitObjectArgument(),
7408 false, SpecializedMethod, Context.BoundMemberTy,
7409 MemberCall->getValueKind(), MemberCall->getObjectKind());
7411 NewCall =
SemaRef.BuildCallExpr(
Scope, BestExpr, LParenLoc, ArgExprs,
7412 RParenLoc, ExecConfig);
7414 if (
CallExpr *NCE = dyn_cast<CallExpr>(NewCall.
get())) {
7415 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7417 CalleeFnType, NewCalleeFnDecl->
getType(),
7428 VMIs.erase(VMIs.begin() + BestIdx);
7429 Exprs.erase(Exprs.begin() + BestIdx);
7430 }
while (!VMIs.empty());
7437std::optional<std::pair<FunctionDecl *, Expr *>>
7441 unsigned NumAppendArgs,
7445 return std::nullopt;
7447 const int VariantId = 1;
7450 Diag(SR.
getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7452 return std::nullopt;
7455 if (
auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7456 ADecl = FTD->getTemplatedDecl();
7459 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7463 return std::nullopt;
7466 auto &&HasMultiVersionAttributes = [](
const FunctionDecl *FD) {
7469 return FD->isMultiVersion() || FD->
hasAttr<TargetAttr>();
7472 if (HasMultiVersionAttributes(FD)) {
7473 Diag(FD->
getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7475 return std::nullopt;
7480 Diag(SR.
getBegin(), diag::warn_omp_declare_variant_after_used)
7485 if (!FD->isThisDeclarationADefinition() && FD->isDefined(
Definition) &&
7487 Diag(SR.
getBegin(), diag::warn_omp_declare_variant_after_emitted)
7492 Diag(SR.
getBegin(), diag::err_omp_function_expected) << VariantId;
7493 return std::nullopt;
7496 auto ShouldDelayChecks = [](
Expr *&E, bool) {
7502 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef,
false) ||
7504 return std::make_pair(FD, VariantRef);
7507 auto HandleNonConstantScoresAndConditions = [
this](
Expr *&E,
7508 bool IsScore) ->
bool {
7514 Diag(E->
getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7522 diag::err_omp_declare_variant_user_condition_not_constant)
7528 return std::nullopt;
7531 if (NumAppendArgs) {
7534 Diag(FD->
getLocation(), diag::err_omp_declare_variant_prototype_required)
7536 return std::nullopt;
7545 TD = dyn_cast_or_null<TypeDecl>(ND);
7548 Diag(SR.
getBegin(), diag::err_omp_interop_type_not_found) << SR;
7549 return std::nullopt;
7554 if (PTy->isVariadic()) {
7555 Diag(FD->
getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7556 return std::nullopt;
7559 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7560 Params.insert(Params.end(), NumAppendArgs, InteropType);
7561 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7562 PTy->getExtProtoInfo());
7570 auto *
Method = dyn_cast<CXXMethodDecl>(FD);
7572 FnPtrType = Context.getMemberPointerType(
7573 AdjustedFnType, std::nullopt,
Method->getParent());
7585 return std::nullopt;
7587 VariantRef = ER.
get();
7589 FnPtrType = Context.getPointerType(AdjustedFnType);
7591 QualType VarianPtrType = Context.getPointerType(VariantRef->
getType());
7595 false, Sema::AllowedExplicit::None,
7601 diag::err_omp_declare_variant_incompat_types)
7605 return std::nullopt;
7607 VariantRefCast =
SemaRef.PerformImplicitConversion(
7611 return std::nullopt;
7615 Expr *PossibleAddrOfVariantRef = VariantRefCast.
get();
7616 if (
auto *UO = dyn_cast<UnaryOperator>(
7618 VariantRefCast = UO->getSubExpr();
7627 return std::nullopt;
7635 return std::nullopt;
7637 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7641 return std::nullopt;
7646 diag::err_omp_declare_variant_same_base_function)
7648 return std::nullopt;
7654 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7657 diag::err_omp_declare_variant_incompat_types)
7658 << NewFD->getType() << FD->
getType() << (NumAppendArgs ? 1 : 0)
7660 return std::nullopt;
7665 else if (NewFD->getType()->isFunctionNoProtoType())
7671 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7673 diag::warn_omp_declare_variant_marked_as_declare_variant)
7676 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->
getRange();
7677 Diag(SR.
getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7678 return std::nullopt;
7681 enum DoesntSupport {
7690 if (
const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7691 if (CXXFD->isVirtual()) {
7694 return std::nullopt;
7700 return std::nullopt;
7706 return std::nullopt;
7710 if (FD->isDeleted()) {
7713 return std::nullopt;
7716 if (FD->isDefaulted()) {
7719 return std::nullopt;
7722 if (FD->isConstexpr()) {
7724 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7725 return std::nullopt;
7729 if (
SemaRef.areMultiversionVariantFunctionsCompatible(
7735 SemaRef.PDiag(diag::err_omp_declare_variant_doesnt_support)),
7737 SemaRef.PDiag(diag::err_omp_declare_variant_diff)
7741 return std::nullopt;
7759 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7760 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7761 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDeviceAddr);
7763 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7764 VariantMatchInfo VMI;
7766 if (!llvm::is_contained(
7767 VMI.ConstructTraits,
7768 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7769 if (!AllAdjustArgs.empty())
7770 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7772 if (!AppendArgs.empty())
7773 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7784 for (
Expr *E : AllAdjustArgs) {
7786 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7787 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7789 if (FD->
getNumParams() > PVD->getFunctionScopeIndex() &&
7793 if (!AdjustVars.insert(CanonPVD).second) {
7794 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7803 Diag(E->
getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7812 for (
Expr *E : AdjustArgsNeedDeviceAddr) {
7814 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7815 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
7818 diag::err_omp_non_by_ref_need_device_addr_modifier_argument);
7824 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7826 const_cast<Expr **
>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7827 const_cast<Expr **
>(AdjustArgsNeedDevicePtr.data()),
7828 AdjustArgsNeedDevicePtr.size(),
7829 const_cast<Expr **
>(AdjustArgsNeedDeviceAddr.data()),
7830 AdjustArgsNeedDeviceAddr.size(),
7831 const_cast<OMPInteropInfo *
>(AppendArgs.data()), AppendArgs.size(), SR);
7837 auto *CS = dyn_cast<CapturedStmt>(AStmt);
7838 assert(CS &&
"Captured statement expected");
7847 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7869 return OMPParallelDirective::Create(
7876struct LoopIterationSpace final {
7879 bool IsStrictCompare =
false;
7881 Expr *PreCond =
nullptr;
7884 Expr *NumIterations =
nullptr;
7886 Expr *CounterVar =
nullptr;
7888 Expr *PrivateCounterVar =
nullptr;
7890 Expr *CounterInit =
nullptr;
7893 Expr *CounterStep =
nullptr;
7895 bool Subtract =
false;
7905 Expr *MinValue =
nullptr;
7909 Expr *MaxValue =
nullptr;
7911 bool IsNonRectangularLB =
false;
7913 bool IsNonRectangularUB =
false;
7916 unsigned LoopDependentIdx = 0;
7920 Expr *FinalCondition =
nullptr;
7927 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7928 VarDecl *ForbiddenVar =
nullptr;
7932 explicit ForSubExprChecker(
7933 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
7934 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
7937 ShouldVisitImplicitCode =
true;
7940 bool VisitDeclRefExpr(DeclRefExpr *E)
override {
7945 if (
V->getType()->isReferenceType()) {
7946 VarDecl *VD =
V->getDefinition();
7949 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(I);
7955 Decl *Canon =
V->getCanonicalDecl();
7956 if (CollapsedLoopVarDecls.contains(Canon)) {
7965 VarDecl *getForbiddenVar()
const {
return ForbiddenVar; }
7966 SourceRange getErrRange()
const {
return ErrLoc; }
7972class OpenMPIterationSpaceChecker {
7976 bool SupportsNonRectangular;
7980 SourceLocation DefaultLoc;
7982 SourceLocation ConditionLoc;
7984 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7986 SourceRange InitSrcRange;
7988 SourceRange ConditionSrcRange;
7990 SourceRange IncrementSrcRange;
7992 ValueDecl *LCDecl =
nullptr;
7994 Expr *LCRef =
nullptr;
8000 Expr *Step =
nullptr;
8007 std::optional<bool> TestIsLessOp;
8009 bool TestIsStrictOp =
false;
8011 bool SubtractStep =
false;
8013 const ValueDecl *DepDecl =
nullptr;
8016 std::optional<unsigned> InitDependOnLC;
8019 std::optional<unsigned> CondDependOnLC;
8021 std::optional<unsigned> doesDependOnLoopCounter(
const Stmt *S,
8022 bool IsInitializer);
8028 OpenMPIterationSpaceChecker(
8029 Sema &SemaRef,
bool SupportsNonRectangular, DSAStackTy &Stack,
8030 SourceLocation DefaultLoc,
8031 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls)
8032 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
8033 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
8034 CollapsedLoopVarDecls(CollapsedLoopDecls) {}
8037 bool checkAndSetInit(Stmt *S,
bool EmitDiags =
true);
8040 bool checkAndSetCond(Expr *S);
8043 bool checkAndSetInc(Expr *S);
8045 ValueDecl *getLoopDecl()
const {
return LCDecl; }
8047 Expr *getLoopDeclRefExpr()
const {
return LCRef; }
8049 SourceRange getInitSrcRange()
const {
return InitSrcRange; }
8051 SourceRange getConditionSrcRange()
const {
return ConditionSrcRange; }
8053 SourceRange getIncrementSrcRange()
const {
return IncrementSrcRange; }
8055 bool shouldSubtractStep()
const {
return SubtractStep; }
8057 bool isStrictTestOp()
const {
return TestIsStrictOp; }
8059 Expr *buildNumIterations(
8060 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces,
bool LimitedType,
8061 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
8064 buildPreCond(Scope *S, Expr *
Cond,
8065 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
8068 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8069 DSAStackTy &DSA)
const;
8072 Expr *buildPrivateCounterVar()
const;
8076 Expr *buildCounterStep()
const;
8080 buildOrderedLoopData(Scope *S, Expr *Counter,
8081 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8082 SourceLocation Loc, Expr *Inc =
nullptr,
8085 std::pair<Expr *, Expr *> buildMinMaxValues(
8086 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
8088 Expr *buildFinalCondition(Scope *S)
const;
8090 bool dependent()
const;
8092 bool doesInitDependOnLC()
const {
return InitDependOnLC.has_value(); }
8094 bool doesCondDependOnLC()
const {
return CondDependOnLC.has_value(); }
8096 unsigned getLoopDependentIdx()
const {
8097 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
8103 bool checkAndSetIncRHS(Expr *RHS);
8105 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
8108 bool setUB(Expr *NewUB, std::optional<bool> LessOp,
bool StrictOp,
8109 SourceRange SR, SourceLocation SL);
8111 bool setStep(Expr *NewStep,
bool Subtract);
8114bool OpenMPIterationSpaceChecker::dependent()
const {
8116 assert(!LB && !UB && !Step);
8124bool OpenMPIterationSpaceChecker::setLCDeclAndLB(
ValueDecl *NewLCDecl,
8126 Expr *NewLB,
bool EmitDiags) {
8128 assert(LCDecl ==
nullptr && LB ==
nullptr && LCRef ==
nullptr &&
8129 UB ==
nullptr && Step ==
nullptr && !TestIsLessOp && !TestIsStrictOp);
8133 LCRef = NewLCRefExpr;
8134 if (
auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
8136 if ((Ctor->isCopyOrMoveConstructor() ||
8137 Ctor->isConvertingConstructor(
false)) &&
8138 CE->getNumArgs() > 0 && CE->getArg(0) !=
nullptr)
8142 InitDependOnLC = doesDependOnLoopCounter(LB,
true);
8146bool OpenMPIterationSpaceChecker::setUB(
Expr *NewUB, std::optional<bool> LessOp,
8150 assert(LCDecl !=
nullptr && LB !=
nullptr && UB ==
nullptr &&
8151 Step ==
nullptr && !TestIsLessOp && !TestIsStrictOp);
8156 TestIsLessOp = LessOp;
8157 TestIsStrictOp = StrictOp;
8158 ConditionSrcRange = SR;
8160 CondDependOnLC = doesDependOnLoopCounter(UB,
false);
8164bool OpenMPIterationSpaceChecker::setStep(
Expr *NewStep,
bool Subtract) {
8166 assert(LCDecl !=
nullptr && LB !=
nullptr && Step ==
nullptr);
8176 NewStep = Val.
get();
8189 std::optional<llvm::APSInt>
Result =
8200 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8201 if (UB && (IsConstZero ||
8202 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8203 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8205 diag::err_omp_loop_incr_not_compatible)
8207 SemaRef.
Diag(ConditionLoc,
8208 diag::note_omp_loop_cond_requires_compatible_incr)
8209 << *TestIsLessOp << ConditionSrcRange;
8212 if (*TestIsLessOp == Subtract) {
8216 Subtract = !Subtract;
8221 SubtractStep = Subtract;
8228class LoopCounterRefChecker final
8232 const ValueDecl *CurLCDecl =
nullptr;
8233 const ValueDecl *DepDecl =
nullptr;
8234 const ValueDecl *PrevDepDecl =
nullptr;
8235 bool IsInitializer =
true;
8236 bool SupportsNonRectangular;
8237 unsigned BaseLoopId = 0;
8238 bool checkDecl(
const Expr *E,
const ValueDecl *VD) {
8240 SemaRef.Diag(E->
getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8241 << (IsInitializer ? 0 : 1);
8244 const auto &&
Data = Stack.isLoopControlVariable(VD);
8249 SmallString<128> Name;
8250 llvm::raw_svector_ostream
OS(Name);
8254 diag::err_omp_wrong_dependency_iterator_type)
8256 SemaRef.Diag(VD->
getLocation(), diag::note_previous_decl) << VD;
8259 if (
Data.first && !SupportsNonRectangular) {
8260 SemaRef.Diag(E->
getExprLoc(), diag::err_omp_invariant_dependency);
8264 (DepDecl || (PrevDepDecl &&
8266 if (!DepDecl && PrevDepDecl)
8267 DepDecl = PrevDepDecl;
8268 SmallString<128> Name;
8269 llvm::raw_svector_ostream
OS(Name);
8273 diag::err_omp_invariant_or_linear_dependency)
8279 BaseLoopId =
Data.first;
8285 bool VisitDeclRefExpr(
const DeclRefExpr *E) {
8286 const ValueDecl *VD = E->
getDecl();
8288 return checkDecl(E, VD);
8291 bool VisitMemberExpr(
const MemberExpr *E) {
8295 return checkDecl(E, VD);
8299 bool VisitStmt(
const Stmt *S) {
8301 for (
const Stmt *Child : S->
children())
8302 Res = (Child && Visit(Child)) || Res;
8305 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8306 const ValueDecl *CurLCDecl,
bool IsInitializer,
8307 const ValueDecl *PrevDepDecl =
nullptr,
8308 bool SupportsNonRectangular =
true)
8309 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8310 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8311 SupportsNonRectangular(SupportsNonRectangular) {}
8312 unsigned getBaseLoopId()
const {
8313 assert(CurLCDecl &&
"Expected loop dependency.");
8316 const ValueDecl *getDepDecl()
const {
8317 assert(CurLCDecl &&
"Expected loop dependency.");
8323std::optional<unsigned>
8324OpenMPIterationSpaceChecker::doesDependOnLoopCounter(
const Stmt *S,
8325 bool IsInitializer) {
8327 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8328 DepDecl, SupportsNonRectangular);
8329 if (LoopStmtChecker.Visit(S)) {
8330 DepDecl = LoopStmtChecker.getDepDecl();
8331 return LoopStmtChecker.getBaseLoopId();
8333 return std::nullopt;
8336bool OpenMPIterationSpaceChecker::checkAndSetInit(
Stmt *S,
bool EmitDiags) {
8347 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8351 if (
auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8352 if (!ExprTemp->cleanupsHaveSideEffects())
8353 S = ExprTemp->getSubExpr();
8355 if (!CollapsedLoopVarDecls.empty()) {
8356 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8357 if (!FSEC.TraverseStmt(S)) {
8359 SemaRef.Diag(
Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8360 <<
Range.getEnd() << 0 << FSEC.getForbiddenVar();
8366 if (
Expr *E = dyn_cast<Expr>(S))
8368 if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8369 if (BO->getOpcode() == BO_Assign) {
8371 if (
auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8372 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->
getDecl()))
8374 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8376 return setLCDeclAndLB(DRE->
getDecl(), DRE, BO->getRHS(), EmitDiags);
8378 if (
auto *ME = dyn_cast<MemberExpr>(LHS)) {
8379 if (ME->isArrow() &&
8381 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8385 }
else if (
auto *DS = dyn_cast<DeclStmt>(S)) {
8386 if (DS->isSingleDecl()) {
8387 if (
auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8388 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8392 diag::ext_omp_loop_not_canonical_init)
8394 return setLCDeclAndLB(
8397 Var->getType().getNonReferenceType(),
8399 Var->getInit(), EmitDiags);
8403 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8404 if (CE->getOperator() == OO_Equal) {
8405 Expr *LHS = CE->getArg(0);
8406 if (
auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8407 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->
getDecl()))
8409 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8411 return setLCDeclAndLB(DRE->
getDecl(), DRE, CE->getArg(1), EmitDiags);
8413 if (
auto *ME = dyn_cast<MemberExpr>(LHS)) {
8414 if (ME->isArrow() &&
8416 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8422 if (dependent() || SemaRef.CurContext->isDependentContext())
8425 SemaRef.Diag(S->
getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8437 if (
const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8439 if ((Ctor->isCopyOrMoveConstructor() ||
8440 Ctor->isConvertingConstructor(
false)) &&
8441 CE->getNumArgs() > 0 && CE->getArg(0) !=
nullptr)
8443 if (
const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8444 if (
const auto *VD = dyn_cast<VarDecl>(DRE->
getDecl()))
8447 if (
const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8448 if (ME->isArrow() &&
isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8453bool OpenMPIterationSpaceChecker::checkAndSetCond(
Expr *S) {
8460 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8462 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8463 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8469 if (!CollapsedLoopVarDecls.empty()) {
8470 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8471 if (!FSEC.TraverseStmt(S)) {
8473 SemaRef.Diag(
Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8474 <<
Range.getEnd() << 1 << FSEC.getForbiddenVar();
8480 auto &&CheckAndSetCond =
8485 if (getInitLCDecl(LHS) == LCDecl)
8486 return setUB(
const_cast<Expr *
>(RHS),
8487 (Opcode == BO_LT || Opcode == BO_LE),
8488 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8489 if (getInitLCDecl(RHS) == LCDecl)
8490 return setUB(
const_cast<Expr *
>(LHS),
8491 (Opcode == BO_GT || Opcode == BO_GE),
8492 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8493 }
else if (IneqCondIsCanonical && Opcode == BO_NE) {
8494 return setUB(
const_cast<Expr *
>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8498 return std::nullopt;
8500 std::optional<bool> Res;
8501 if (
auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8504 RBO->getOperatorLoc());
8505 }
else if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8506 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8507 BO->getSourceRange(), BO->getOperatorLoc());
8508 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8509 if (CE->getNumArgs() == 2) {
8510 Res = CheckAndSetCond(
8512 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8517 if (dependent() || SemaRef.CurContext->isDependentContext())
8519 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8520 << (IneqCondIsCanonical ? 1 : 0) << S->
getSourceRange() << LCDecl;
8524bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(
Expr *RHS) {
8531 if (
auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8532 if (BO->isAdditiveOp()) {
8533 bool IsAdd = BO->getOpcode() == BO_Add;
8534 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8535 return setStep(BO->getRHS(), !IsAdd);
8536 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8537 return setStep(BO->getLHS(),
false);
8539 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8540 bool IsAdd = CE->getOperator() == OO_Plus;
8541 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8542 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8543 return setStep(CE->getArg(1), !IsAdd);
8544 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8545 return setStep(CE->getArg(0),
false);
8548 if (dependent() || SemaRef.CurContext->isDependentContext())
8550 SemaRef.Diag(RHS->
getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8555bool OpenMPIterationSpaceChecker::checkAndSetInc(
Expr *S) {
8570 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8573 if (
auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8574 if (!ExprTemp->cleanupsHaveSideEffects())
8575 S = ExprTemp->getSubExpr();
8577 if (!CollapsedLoopVarDecls.empty()) {
8578 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8579 if (!FSEC.TraverseStmt(S)) {
8581 SemaRef.Diag(
Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8582 <<
Range.getEnd() << 2 << FSEC.getForbiddenVar();
8589 if (
auto *UO = dyn_cast<UnaryOperator>(S)) {
8590 if (UO->isIncrementDecrementOp() &&
8591 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8592 return setStep(SemaRef
8593 .ActOnIntegerConstant(UO->getBeginLoc(),
8594 (UO->isDecrementOp() ? -1 : 1))
8597 }
else if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8598 switch (BO->getOpcode()) {
8601 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8602 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8605 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8606 return checkAndSetIncRHS(BO->getRHS());
8611 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8612 switch (CE->getOperator()) {
8615 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8616 return setStep(SemaRef
8617 .ActOnIntegerConstant(
8619 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8625 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8626 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8629 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8630 return checkAndSetIncRHS(CE->getArg(1));
8636 if (dependent() || SemaRef.CurContext->isDependentContext())
8638 SemaRef.Diag(S->
getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8645 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8646 StringRef Name =
".capture_expr.") {
8654 auto I = Captures.find(
Capture);
8655 if (I != Captures.end())
8668 bool TestIsStrictOp,
bool RoundToStep,
8669 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8670 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures,
".new_step");
8673 llvm::APSInt LRes, SRes;
8674 bool IsLowerConst =
false, IsStepConst =
false;
8675 if (std::optional<llvm::APSInt> Res =
8678 IsLowerConst =
true;
8680 if (std::optional<llvm::APSInt> Res =
8685 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8686 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8687 (TestIsStrictOp && LRes.isStrictlyPositive()));
8688 bool NeedToReorganize =
false;
8690 if (!NoNeedToConvert && IsLowerConst &&
8691 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8692 NoNeedToConvert =
true;
8694 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8695 ? LRes.getBitWidth()
8696 : SRes.getBitWidth();
8697 LRes = LRes.extend(BW + 1);
8698 LRes.setIsSigned(
true);
8699 SRes = SRes.extend(BW + 1);
8700 SRes.setIsSigned(
true);
8702 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8703 LRes = LRes.trunc(BW);
8705 if (TestIsStrictOp) {
8706 unsigned BW = LRes.getBitWidth();
8707 LRes = LRes.extend(BW + 1);
8708 LRes.setIsSigned(
true);
8711 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8713 LRes = LRes.trunc(BW);
8715 NeedToReorganize = NoNeedToConvert;
8718 bool IsUpperConst =
false;
8719 if (std::optional<llvm::APSInt> Res =
8722 IsUpperConst =
true;
8724 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8725 (!RoundToStep || IsStepConst)) {
8726 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8727 : URes.getBitWidth();
8728 LRes = LRes.extend(BW + 1);
8729 LRes.setIsSigned(
true);
8730 URes = URes.extend(BW + 1);
8731 URes.setIsSigned(
true);
8733 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8734 NeedToReorganize = NoNeedToConvert;
8739 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8745 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8748 LowerSize > UpperSize ? LowerSize : UpperSize, 0);
8759 if (!Lower || !Upper || NewStep.
isInvalid())
8765 if (NeedToReorganize) {
8779 S, DefaultLoc, BO_Add, Diff.
get(),
8789 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.
get());
8793 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8809 S, DefaultLoc, BO_Sub, Diff.
get(),
8829 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Div, Diff.
get(), NewStep.
get());
8837Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8839 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
8848 if (InitDependOnLC) {
8849 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8850 if (!IS.MinValue || !IS.MaxValue)
8859 IS.CounterVar, MinValue.
get());
8864 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.
get(), LBVal);
8879 IS.CounterVar, MaxValue.
get());
8884 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.
get(), LBVal);
8893 tryBuildCapture(SemaRef, LBMinVal.
get(), Captures,
".lb_min").get();
8895 tryBuildCapture(SemaRef, LBMaxVal.
get(), Captures,
".lb_max").get();
8896 if (!LBMin || !LBMax)
8900 SemaRef.
BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8904 tryBuildCapture(SemaRef, MinLessMaxRes.
get(), Captures,
".min_less_max")
8908 if (*TestIsLessOp) {
8912 MinLessMax, LBMin, LBMax);
8915 LBVal = MinLB.
get();
8920 MinLessMax, LBMax, LBMin);
8923 LBVal = MaxLB.
get();
8927 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8930 LBVal = LBMinVal.
get();
8934 if (CondDependOnLC) {
8935 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8936 if (!IS.MinValue || !IS.MaxValue)
8945 IS.CounterVar, MinValue.
get());
8950 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.
get(), UBVal);
8965 IS.CounterVar, MaxValue.
get());
8970 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.
get(), UBVal);
8979 tryBuildCapture(SemaRef, UBMinVal.
get(), Captures,
".ub_min").get();
8981 tryBuildCapture(SemaRef, UBMaxVal.
get(), Captures,
".ub_max").get();
8982 if (!UBMin || !UBMax)
8986 SemaRef.
BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
8989 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.
get(),
8990 Captures,
".min_greater_max")
8994 if (*TestIsLessOp) {
8998 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
9001 UBVal = MaxUB.
get();
9006 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
9009 UBVal = MinUB.
get();
9012 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
9013 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
9014 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures,
".upper").get();
9015 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures,
".lower").get();
9016 if (!Upper || !Lower)
9019 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9020 Step, VarType, TestIsStrictOp,
9029 C.getTypeSize(
Type) >
C.getTypeSize(VarType);
9032 UseVarType ?
C.getTypeSize(VarType) :
C.getTypeSize(
Type);
9035 Type =
C.getIntTypeForBitwidth(NewSize, IsSigned);
9045 unsigned NewSize = (
C.getTypeSize(
Type) > 32) ? 64 : 32;
9046 if (NewSize !=
C.getTypeSize(
Type)) {
9047 if (NewSize <
C.getTypeSize(
Type)) {
9048 assert(NewSize == 64 &&
"incorrect loop var size");
9049 SemaRef.
Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
9050 << InitSrcRange << ConditionSrcRange;
9052 QualType NewType =
C.getIntTypeForBitwidth(
9054 C.getTypeSize(
Type) < NewSize);
9068std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
9069 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
9073 return std::make_pair(
nullptr,
nullptr);
9076 Expr *MinExpr =
nullptr;
9077 Expr *MaxExpr =
nullptr;
9078 Expr *LBExpr = *TestIsLessOp ? LB : UB;
9079 Expr *UBExpr = *TestIsLessOp ? UB : LB;
9081 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
9083 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
9085 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
9087 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
9088 if (!Upper || !Lower)
9089 return std::make_pair(
nullptr,
nullptr);
9099 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9100 Step, VarType, TestIsStrictOp,
9103 return std::make_pair(
nullptr,
nullptr);
9109 return std::make_pair(
nullptr,
nullptr);
9111 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures,
".new_step");
9113 return std::make_pair(
nullptr,
nullptr);
9114 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Mul, Diff.
get(), NewStep.
get());
9116 return std::make_pair(
nullptr,
nullptr);
9121 return std::make_pair(
nullptr,
nullptr);
9133 return std::make_pair(
nullptr,
nullptr);
9135 if (*TestIsLessOp) {
9139 S, DefaultLoc, BO_Add,
9143 return std::make_pair(
nullptr,
nullptr);
9148 S, DefaultLoc, BO_Sub,
9152 return std::make_pair(
nullptr,
nullptr);
9161 return std::make_pair(
nullptr,
nullptr);
9166 return std::make_pair(
nullptr,
nullptr);
9169 MaxExpr = Diff.
get();
9171 MinExpr = Diff.
get();
9173 return std::make_pair(MinExpr, MaxExpr);
9176Expr *OpenMPIterationSpaceChecker::buildFinalCondition(
Scope *S)
const {
9177 if (InitDependOnLC || CondDependOnLC)
9182Expr *OpenMPIterationSpaceChecker::buildPreCond(
9184 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
9189 if (CondDependOnLC || InitDependOnLC)
9200 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
9201 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
9207 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
9208 : (TestIsStrictOp ? BO_GT : BO_GE),
9209 NewLB.
get(), NewUB.
get());
9224DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9225 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9226 DSAStackTy &DSA)
const {
9227 auto *VD = dyn_cast<VarDecl>(LCDecl);
9232 const DSAStackTy::DSAVarData
Data =
9233 DSA.getTopDSA(LCDecl,
false);
9237 Captures.insert(std::make_pair(LCRef, Ref));
9243Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar()
const {
9260Expr *OpenMPIterationSpaceChecker::buildCounterInit()
const {
return LB; }
9263Expr *OpenMPIterationSpaceChecker::buildCounterStep()
const {
return Step; }
9265Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9267 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
SourceLocation Loc,
9273 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9274 "Expected only + or - operations for depend clauses.");
9286 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9288 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9289 if (!Upper || !Lower)
9293 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9294 false,
false, Captures);
9304 assert(
getLangOpts().OpenMP &&
"OpenMP is not active.");
9305 assert(
Init &&
"Expected loop in canonical form.");
9306 unsigned AssociatedLoops =
DSAStack->getAssociatedLoops();
9313 OpenMPIterationSpaceChecker ISC(
SemaRef,
true,
9315 if (!ISC.checkAndSetInit(
Init,
false)) {
9317 auto *VD = dyn_cast<VarDecl>(D);
9328 DSAStack->addLoopControlVariable(D, VD);
9330 if (LD != D->getCanonicalDecl()) {
9331 DSAStack->resetPossibleLoopCounter();
9332 if (
auto *Var = dyn_cast_or_null<VarDecl>(LD))
9345 DSAStackTy::DSAVarData DVar =
9349 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9352 ? (
DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9355 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9358 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9360 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9362 IsOpenMPTaskloopDirective(DKind) ||
9365 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9366 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9368 Diag(
Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9370 << getOpenMPDirectiveName(DKind, OMPVersion)
9372 if (DVar.RefExpr ==
nullptr)
9373 DVar.CKind = PredeterminedCKind;
9375 }
else if (LoopDeclRefExpr) {
9380 if (DVar.CKind == OMPC_unknown)
9381 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9385 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9390class OMPDoacrossKind {
9393 return C->getDependenceType() == OMPC_DOACROSS_source ||
9394 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9397 return C->getDependenceType() == OMPC_DOACROSS_sink;
9399 bool isSinkIter(
const OMPDoacrossClause *
C) {
9400 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9408 unsigned CurrentNestedLoopCount,
unsigned NestedLoopCount,
9409 unsigned TotalNestedLoopCount,
Expr *CollapseLoopCountExpr,
9410 Expr *OrderedLoopCountExpr,
9413 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9414 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls) {
9419 if (
auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9420 S = CanonLoop->getLoopStmt();
9421 auto *For = dyn_cast_or_null<ForStmt>(S);
9422 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9424 if (!For && (SemaRef.
LangOpts.OpenMP <= 45 || !CXXFor)) {
9425 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
9427 << (CollapseLoopCountExpr !=
nullptr || OrderedLoopCountExpr !=
nullptr)
9428 << getOpenMPDirectiveName(DKind, OMPVersion) << TotalNestedLoopCount
9429 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9430 if (TotalNestedLoopCount > 1) {
9431 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9432 SemaRef.
Diag(DSA.getConstructLoc(),
9433 diag::note_omp_collapse_ordered_expr)
9436 else if (CollapseLoopCountExpr)
9438 diag::note_omp_collapse_ordered_expr)
9440 else if (OrderedLoopCountExpr)
9442 diag::note_omp_collapse_ordered_expr)
9447 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9453 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9454 For ? For->getForLoc() : CXXFor->getForLoc(),
9455 CollapsedLoopVarDecls);
9458 Stmt *
Init = For ? For->getInit() : CXXFor->getBeginStmt();
9459 if (ISC.checkAndSetInit(
Init))
9462 bool HasErrors =
false;
9465 if (
ValueDecl *LCDecl = ISC.getLoopDecl()) {
9475 SemaRef.
Diag(
Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9489 VarsWithImplicitDSA.erase(LCDecl);
9494 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9497 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9504 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9505 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9506 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9507 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9514 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9515 ISC.buildCounterVar(Captures, DSA);
9516 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9517 ISC.buildPrivateCounterVar();
9518 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9519 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9520 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9521 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9522 ISC.getConditionSrcRange();
9523 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9524 ISC.getIncrementSrcRange();
9525 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9526 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9527 ISC.isStrictTestOp();
9528 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9529 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9530 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9531 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9532 ISC.buildFinalCondition(DSA.getCurScope());
9533 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9534 ISC.doesInitDependOnLC();
9535 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9536 ISC.doesCondDependOnLC();
9537 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9538 ISC.getLoopDependentIdx();
9541 (ResultIterSpaces[CurrentNestedLoopCount].PreCond ==
nullptr ||
9542 ResultIterSpaces[CurrentNestedLoopCount].NumIterations ==
nullptr ||
9543 ResultIterSpaces[CurrentNestedLoopCount].CounterVar ==
nullptr ||
9544 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar ==
nullptr ||
9545 ResultIterSpaces[CurrentNestedLoopCount].CounterInit ==
nullptr ||
9546 ResultIterSpaces[CurrentNestedLoopCount].CounterStep ==
nullptr);
9547 if (!HasErrors && DSA.isOrderedRegion()) {
9548 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9549 if (CurrentNestedLoopCount <
9550 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9551 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9552 CurrentNestedLoopCount,
9553 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9554 DSA.getOrderedRegionParam().second->setLoopCounter(
9555 CurrentNestedLoopCount,
9556 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9559 for (
auto &Pair : DSA.getDoacrossDependClauses()) {
9560 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9561 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9563 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9564 if (CurrentNestedLoopCount >= NumLoops) {
9568 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9569 Pair.second.size() <= CurrentNestedLoopCount) {
9571 DependC->setLoopData(CurrentNestedLoopCount,
nullptr);
9574 OMPDoacrossKind ODK;
9575 if (DoacrossC && ODK.isSink(DoacrossC) &&
9576 Pair.second.size() <= CurrentNestedLoopCount) {
9578 DoacrossC->setLoopData(CurrentNestedLoopCount,
nullptr);
9583 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9584 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9585 (DoacrossC && ODK.isSource(DoacrossC)))
9586 CntValue = ISC.buildOrderedLoopData(
9588 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9590 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9593 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9601 CntValue = ISC.buildOrderedLoopData(
9603 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9604 DepLoc, Inc, clang::OO_Minus);
9606 CntValue = ISC.buildOrderedLoopData(
9608 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9609 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9610 Pair.second[CurrentNestedLoopCount].second);
9612 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9614 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9625 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9629 : tryBuildCapture(SemaRef, Start.
get(), Captures);
9650 bool IsNonRectangularLB,
9651 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures =
nullptr) {
9660 NewStep = tryBuildCapture(SemaRef, Step.
get(), *Captures);
9675 if (Captures && !IsNonRectangularLB)
9676 NewStart = tryBuildCapture(SemaRef, Start.
get(), *Captures);
9685 Update.get()->getType()->isOverloadableType()) {
9692 SemaRef.
BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9693 VarRef.
get(), SavedUpdate.
get());
9704 NewStart.
get(), SavedUpdate.
get());
9729 unsigned HasBits =
C.getTypeSize(OldType);
9730 if (HasBits >= Bits)
9733 QualType NewType =
C.getIntTypeForBitwidth(Bits,
true);
9743 if (std::optional<llvm::APSInt> Result =
9745 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9752 if (!PreInits.empty()) {
9773 if (
auto *CS = dyn_cast<CompoundStmt>(Item))
9782 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9783 if (!Captures.empty()) {
9785 for (
const auto &Pair : Captures)
9786 PreInits.push_back(Pair.second->getDecl());
9794 if (PreInits.empty())
9798 for (
Stmt *S : PreInits)
9805 Expr *PostUpdate =
nullptr;
9806 if (!PostUpdates.empty()) {
9807 for (
Expr *E : PostUpdates) {
9813 PostUpdate = PostUpdate
9827 int NestingDepth = 0;
9828 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
9850 if (NestingDepth > 0)
9861 Expr *OrderedLoopCountExpr,
Stmt *AStmt,
Sema &SemaRef,
9864 OMPLoopBasedDirective::HelperExprs &Built) {
9868 if ((CollapseLoopCountExpr && CollapseLoopCountExpr->
containsErrors()) ||
9869 (OrderedLoopCountExpr && OrderedLoopCountExpr->
containsErrors()))
9872 unsigned NestedLoopCount = 1;
9873 bool SupportsNonPerfectlyNested = (SemaRef.
LangOpts.OpenMP >= 50) &&
9877 if (CollapseLoopCountExpr) {
9882 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9891 unsigned OrderedLoopCount = 1;
9892 if (OrderedLoopCountExpr) {
9898 llvm::APSInt Result = EVResult.
Val.
getInt();
9899 if (Result.getLimitedValue() < NestedLoopCount) {
9901 diag::err_omp_wrong_ordered_loop_count)
9904 diag::note_collapse_loop_count)
9907 OrderedLoopCount = Result.getLimitedValue();
9915 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9916 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9918 if (!OMPLoopBasedDirective::doForAllLoops(
9920 SupportsNonPerfectlyNested, NumLoops,
9921 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9922 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9923 &IterSpaces, &Captures,
9924 &CollapsedLoopVarDecls](
unsigned Cnt,
Stmt *CurStmt) {
9926 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9927 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9928 VarsWithImplicitDSA, IterSpaces, Captures,
9929 CollapsedLoopVarDecls))
9931 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9932 IterSpaces[Cnt].CounterVar) {
9936 Captures[DRE] = DRE;
9943 Stmt *DependentPreInits = Transform->getPreInits();
9944 if (!DependentPreInits)
9951 for (
Stmt *S : Constituents) {
9952 if (
auto *DC = dyn_cast<DeclStmt>(S)) {
9953 for (
Decl *
C : DC->decls()) {
9956 SemaRef, D, D->getType().getNonReferenceType(),
9957 Transform->getBeginLoc());
9958 Captures[Ref] = Ref;
9965 Built.clear(NestedLoopCount);
9968 return NestedLoopCount;
10001 auto PreCond =
ExprResult(IterSpaces[0].PreCond);
10002 Expr *N0 = IterSpaces[0].NumIterations;
10021 return NestedLoopCount;
10024 bool AllCountsNeedLessThan32Bits =
C.getTypeSize(N0->
getType()) < 32;
10026 Scope *CurScope = DSA.getCurScope();
10027 for (
unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
10028 if (PreCond.isUsable()) {
10030 SemaRef.
BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
10031 PreCond.get(), IterSpaces[Cnt].PreCond);
10033 Expr *N = IterSpaces[Cnt].NumIterations;
10035 AllCountsNeedLessThan32Bits &=
C.getTypeSize(N->
getType()) < 32;
10038 CurScope, Loc, BO_Mul, LastIteration32.
get(),
10046 CurScope, Loc, BO_Mul, LastIteration64.
get(),
10056 if (SemaRef.
getLangOpts().OpenMPOptimisticCollapse ||
10058 C.getTypeSize(LastIteration32.
get()->
getType()) == 32 &&
10059 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
10063 LastIteration64.
get(), SemaRef))))
10064 LastIteration = LastIteration32;
10083 LastIteration.
get(),
10095 tryBuildCapture(SemaRef, LastIteration.
get(), Captures);
10096 LastIteration = SaveRef;
10109 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
10138 buildVarDecl(SemaRef, InitLoc, StrideVType,
".omp.stride");
10147 UB.
get(), LastIteration.
get());
10150 LastIteration.
get(), UB.
get());
10151 EUB = SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, UB.
get(),
10162 buildVarDecl(SemaRef, InitLoc, VType,
".omp.comb.lb");
10170 buildVarDecl(SemaRef, InitLoc, VType,
".omp.comb.ub");
10176 CurScope, InitLoc, BO_GT, CombUB.
get(), LastIteration.
get());
10179 LastIteration.
get(), CombUB.
get());
10180 CombEUB = SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.
get(),
10189 "Unexpected number of parameters in loop combined directive");
10230 SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, IV.
get(), CombRHS);
10236 bool UseStrictCompare =
10238 llvm::all_of(IterSpaces, [](
const LoopIterationSpace &LIS) {
10239 return LIS.IsStrictCompare;
10245 if (UseStrictCompare) {
10248 .
BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
10260 UseStrictCompare ? BO_LT : BO_LE, IV.
get(),
10263 NumIterations.
get());
10266 CombDistCond = SemaRef.
BuildBinOp(CurScope, CondLoc, BO_LT, IV.
get(),
10267 NumIterations.
get());
10272 Expr *BoundCombUB = CombUB.
get();
10273 if (UseStrictCompare) {
10277 CurScope, CondLoc, BO_Add, BoundCombUB,
10285 SemaRef.
BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10286 IV.
get(), BoundCombUB);
10293 if (!Inc.isUsable())
10295 Inc = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, IV.
get(), Inc.get());
10297 if (!Inc.isUsable())
10304 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10310 NextLB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Add, LB.
get(), ST.
get());
10321 NextUB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Add, UB.
get(), ST.
get());
10337 CombNextLB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.
get(),
10349 CombNextUB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.
get(),
10363 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10366 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.
get(), BoundUB);
10367 assert(DistCond.
isUsable() &&
"distribute cond expr was not built");
10371 assert(DistInc.
isUsable() &&
"distribute inc expr was not built");
10372 DistInc = SemaRef.
BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.
get(),
10376 assert(DistInc.
isUsable() &&
"distribute inc expr was not built");
10387 DistEUBLoc, NewPrevUB.
get());
10392 UB.
get(), NewPrevUB.
get());
10394 DistEUBLoc, DistEUBLoc, IsUBGreater.
get(), NewPrevUB.
get(), UB.
get());
10395 PrevEUB = SemaRef.
BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.
get(),
10403 Expr *BoundPrevUB = PrevUB.
get();
10404 if (UseStrictCompare) {
10408 CurScope, CondLoc, BO_Add, BoundPrevUB,
10416 SemaRef.
BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10417 IV.
get(), BoundPrevUB);
10421 bool HasErrors =
false;
10422 Built.Counters.resize(NestedLoopCount);
10423 Built.Inits.resize(NestedLoopCount);
10424 Built.Updates.resize(NestedLoopCount);
10425 Built.Finals.resize(NestedLoopCount);
10426 Built.DependentCounters.resize(NestedLoopCount);
10427 Built.DependentInits.resize(NestedLoopCount);
10428 Built.FinalsConditions.resize(NestedLoopCount);
10446 for (
unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10447 LoopIterationSpace &IS = IterSpaces[Cnt];
10453 for (
unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10454 Prod = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.
get(),
10455 IterSpaces[K].NumIterations);
10460 if (Cnt + 1 < NestedLoopCount)
10474 if (Cnt + 1 < NestedLoopCount)
10475 Prod = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.
get(),
10479 Acc = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.
get(), Prod.
get());
10488 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10489 if (!
Init.isUsable()) {
10494 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10495 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10496 if (!
Update.isUsable()) {
10504 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10505 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10506 if (!Final.isUsable()) {
10511 if (!
Update.isUsable() || !Final.isUsable()) {
10516 Built.Counters[Cnt] = IS.CounterVar;
10517 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10518 Built.Inits[Cnt] =
Init.get();
10519 Built.Updates[Cnt] =
Update.get();
10520 Built.Finals[Cnt] = Final.get();
10521 Built.DependentCounters[Cnt] =
nullptr;
10522 Built.DependentInits[Cnt] =
nullptr;
10523 Built.FinalsConditions[Cnt] =
nullptr;
10524 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10525 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10526 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10527 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10536 Built.IterationVarRef = IV.
get();
10537 Built.LastIteration = LastIteration.
get();
10538 Built.NumIterations = NumIterations.
get();
10539 Built.CalcLastIteration = SemaRef
10543 Built.PreCond = PreCond.get();
10545 Built.Cond =
Cond.get();
10546 Built.Init =
Init.get();
10547 Built.Inc = Inc.get();
10548 Built.LB = LB.
get();
10549 Built.UB = UB.
get();
10550 Built.IL = IL.
get();
10551 Built.ST = ST.
get();
10552 Built.EUB = EUB.
get();
10553 Built.NLB = NextLB.
get();
10554 Built.NUB = NextUB.
get();
10555 Built.PrevLB = PrevLB.
get();
10556 Built.PrevUB = PrevUB.
get();
10557 Built.DistInc = DistInc.
get();
10558 Built.PrevEUB = PrevEUB.
get();
10559 Built.DistCombinedFields.LB = CombLB.
get();
10560 Built.DistCombinedFields.UB = CombUB.
get();
10561 Built.DistCombinedFields.EUB = CombEUB.
get();
10562 Built.DistCombinedFields.Init = CombInit.
get();
10563 Built.DistCombinedFields.Cond = CombCond.
get();
10564 Built.DistCombinedFields.NLB = CombNextLB.
get();
10565 Built.DistCombinedFields.NUB = CombNextUB.
get();
10566 Built.DistCombinedFields.DistCond = CombDistCond.
get();
10567 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.
get();
10569 return NestedLoopCount;
10573 auto CollapseClauses =
10574 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10575 if (CollapseClauses.begin() != CollapseClauses.end())
10576 return (*CollapseClauses.begin())->getNumForLoops();
10581 auto OrderedClauses =
10582 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10583 if (OrderedClauses.begin() != OrderedClauses.end())
10584 return (*OrderedClauses.begin())->getNumForLoops();
10593 for (
const OMPClause *Clause : Clauses) {
10594 if (Clause->getClauseKind() == OMPC_safelen)
10596 else if (Clause->getClauseKind() == OMPC_simdlen)
10598 if (Safelen && Simdlen)
10602 if (Simdlen && Safelen) {
10616 llvm::APSInt SimdlenRes = SimdlenResult.
Val.
getInt();
10617 llvm::APSInt SafelenRes = SafelenResult.
Val.
getInt();
10622 if (SimdlenRes > SafelenRes) {
10624 diag::err_omp_wrong_simdlen_safelen_values)
10641 OMPLoopBasedDirective::HelperExprs B;
10647 if (NestedLoopCount == 0)
10656 auto *SimdDirective = OMPSimdDirective::Create(
10657 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10658 return SimdDirective;
10668 OMPLoopBasedDirective::HelperExprs B;
10674 if (NestedLoopCount == 0)
10680 auto *ForDirective = OMPForDirective::Create(
10681 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10683 return ForDirective;
10695 OMPLoopBasedDirective::HelperExprs B;
10698 unsigned NestedLoopCount =
10701 VarsWithImplicitDSA, B);
10702 if (NestedLoopCount == 0)
10711 return OMPForSimdDirective::Create(
getASTContext(), StartLoc, EndLoc,
10712 NestedLoopCount, Clauses, AStmt, B);
10716 Stmt *AStmt, DSAStackTy *Stack) {
10721 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
10722 auto BaseStmt = AStmt;
10723 while (
auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10725 if (
auto *
C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10726 auto S =
C->children();
10727 if (S.begin() == S.end())
10731 for (
Stmt *SectionStmt : llvm::drop_begin(S)) {
10734 SemaRef.
Diag(SectionStmt->getBeginLoc(),
10735 diag::err_omp_sections_substmt_not_section)
10736 << getOpenMPDirectiveName(DKind, OMPVersion);
10740 ->setHasCancel(Stack->isCancelRegion());
10743 SemaRef.
Diag(AStmt->
getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10744 << getOpenMPDirectiveName(DKind, OMPVersion);
10757 SemaRef.setFunctionHasBranchProtectedScope();
10759 return OMPSectionsDirective::Create(
10770 SemaRef.setFunctionHasBranchProtectedScope();
10773 return OMPSectionDirective::Create(
getASTContext(), StartLoc, EndLoc, AStmt,
10779 if (
auto *CE = dyn_cast<CallExpr>(E))
10780 if (CE->getDirectCallee())
10801 if (!
SemaRef.CurContext->isDependentContext()) {
10802 Expr *TargetCall =
nullptr;
10804 auto *E = dyn_cast<Expr>(S);
10812 if (
auto *BO = dyn_cast<BinaryOperator>(E)) {
10813 if (BO->getOpcode() == BO_Assign)
10816 if (
auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10817 if (COCE->getOperator() == OO_Equal)
10829 SemaRef.setFunctionHasBranchProtectedScope();
10832 Clauses, AStmt, TargetCallLoc);
10837 DSAStackTy *Stack) {
10838 bool ErrorFound =
false;
10840 if (
auto *LPC = dyn_cast<OMPLastprivateClause>(
C)) {
10841 for (
Expr *RefExpr : LPC->varlist()) {
10844 Expr *SimpleRefExpr = RefExpr;
10847 auto &&Info = Stack->isLoopControlVariable(D);
10850 S.
Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10851 << getOpenMPDirectiveName(K, OMPVersion);
10875 OMPLoopDirective::HelperExprs B;
10880 if (NestedLoopCount == 0)
10883 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10884 "omp loop exprs were not built");
10887 NestedLoopCount, Clauses, AStmt, B);
10904 OMPLoopDirective::HelperExprs B;
10906 unsigned NestedLoopCount =
10909 VarsWithImplicitDSA, B);
10910 if (NestedLoopCount == 0)
10913 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10914 "omp loop exprs were not built");
10916 DSAStack->setParentTeamsRegionLoc(StartLoc);
10919 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10938 OMPLoopDirective::HelperExprs B;
10940 unsigned NestedLoopCount =
10943 VarsWithImplicitDSA, B);
10944 if (NestedLoopCount == 0)
10947 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10948 "omp loop exprs were not built");
10951 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);
11003 OMPLoopDirective::HelperExprs B;
11005 unsigned NestedLoopCount =
11008 VarsWithImplicitDSA, B);
11009 if (NestedLoopCount == 0)
11012 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11013 "omp loop exprs were not built");
11016 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11028 SemaRef.setFunctionHasBranchProtectedScope();
11033 const OMPClause *Copyprivate =
nullptr;
11034 for (
const OMPClause *Clause : Clauses) {
11035 if (Clause->getClauseKind() == OMPC_nowait)
11037 else if (Clause->getClauseKind() == OMPC_copyprivate)
11038 Copyprivate = Clause;
11039 if (Copyprivate && Nowait) {
11041 diag::err_omp_single_copyprivate_with_nowait);
11047 return OMPSingleDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses,
11057 SemaRef.setFunctionHasBranchProtectedScope();
11059 return OMPMasterDirective::Create(
getASTContext(), StartLoc, EndLoc, AStmt);
11069 SemaRef.setFunctionHasBranchProtectedScope();
11081 bool ErrorFound =
false;
11084 bool DependentHint =
false;
11086 if (
C->getClauseKind() == OMPC_hint) {
11088 Diag(
C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
11094 DependentHint =
true;
11097 HintLoc =
C->getBeginLoc();
11103 const auto Pair =
DSAStack->getCriticalWithHint(DirName);
11104 if (Pair.first && DirName.
getName() && !DependentHint) {
11105 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
11106 Diag(StartLoc, diag::err_omp_critical_with_hint);
11108 Diag(HintLoc, diag::note_omp_critical_hint_here)
11109 << 0 <<
toString(Hint, 10,
false);
11111 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
11112 if (
const auto *
C = Pair.first->getSingleClause<
OMPHintClause>()) {
11113 Diag(
C->getBeginLoc(), diag::note_omp_critical_hint_here)
11118 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
11123 SemaRef.setFunctionHasBranchProtectedScope();
11125 auto *Dir = OMPCriticalDirective::Create(
getASTContext(), DirName, StartLoc,
11126 EndLoc, Clauses, AStmt);
11127 if (!Pair.first && DirName.
getName() && !DependentHint)
11128 DSAStack->addCriticalWithHint(Dir, Hint);
11140 OMPLoopBasedDirective::HelperExprs B;
11143 unsigned NestedLoopCount =
11146 VarsWithImplicitDSA, B);
11147 if (NestedLoopCount == 0)
11153 return OMPParallelForDirective::Create(
11154 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11167 OMPLoopBasedDirective::HelperExprs B;
11170 unsigned NestedLoopCount =
11173 VarsWithImplicitDSA, B);
11174 if (NestedLoopCount == 0)
11183 return OMPParallelForSimdDirective::Create(
11184 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11195 return OMPParallelMasterDirective::Create(
11197 DSAStack->getTaskgroupReductionRef());
11208 return OMPParallelMaskedDirective::Create(
11210 DSAStack->getTaskgroupReductionRef());
11219 SemaRef.setFunctionHasBranchProtectedScope();
11221 return OMPParallelSectionsDirective::Create(
11231 bool ErrorFound =
false;
11233 if (llvm::is_contained(MutuallyExclusiveClauses,
C->getClauseKind())) {
11237 S.
Diag(
C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
11260 {OMPC_detach, OMPC_mergeable}))
11265 return OMPTaskDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses,
11266 AStmt,
DSAStack->isCancelRegion());
11271 return OMPTaskyieldDirective::Create(
getASTContext(), StartLoc, EndLoc);
11276 return OMPBarrierDirective::Create(
getASTContext(), StartLoc, EndLoc);
11282 bool InExContext) {
11284 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11286 if (AtC && !InExContext && AtC->
getAtKind() == OMPC_AT_execution) {
11291 if (!AtC || AtC->
getAtKind() == OMPC_AT_compilation) {
11293 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11295 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11296 std::optional<std::string> SL =
11299 if (MessageC && !SL)
11301 diag::warn_clause_expected_string)
11303 if (SeverityC && SeverityC->
getSeverityKind() == OMPC_SEVERITY_warning)
11305 << SL.value_or(
"WARNING");
11307 Diag(StartLoc, diag::err_diagnose_if_succeeded) << SL.value_or(
"ERROR");
11308 if (!SeverityC || SeverityC->
getSeverityKind() != OMPC_SEVERITY_warning)
11320 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11322 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11324 if (NowaitC && !HasDependC) {
11325 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11329 return OMPTaskwaitDirective::Create(
getASTContext(), StartLoc, EndLoc,
11342 SemaRef.setFunctionHasBranchProtectedScope();
11344 return OMPTaskgroupDirective::Create(
getASTContext(), StartLoc, EndLoc,
11346 DSAStack->getTaskgroupReductionRef());
11355 if (
C->getClauseKind() == OMPC_flush)
11364 if (
C->getClauseKind() == OMPC_acq_rel ||
11365 C->getClauseKind() == OMPC_acquire ||
11366 C->getClauseKind() == OMPC_release ||
11367 C->getClauseKind() == OMPC_seq_cst ) {
11368 if (MemOrderKind != OMPC_unknown) {
11369 Diag(
C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11370 << getOpenMPDirectiveName(OMPD_flush, OMPVersion) << 1
11372 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11375 MemOrderKind =
C->getClauseKind();
11376 MemOrderLoc =
C->getBeginLoc();
11380 if (FC && OrderClause) {
11383 Diag(OrderClause->
getBeginLoc(), diag::note_omp_flush_order_clause_here)
11387 return OMPFlushDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses);
11393 if (Clauses.empty()) {
11394 Diag(StartLoc, diag::err_omp_depobj_expected);
11396 }
else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11397 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11401 if (Clauses.size() > 2) {
11402 Diag(Clauses[2]->getBeginLoc(),
11403 diag::err_omp_depobj_single_clause_expected);
11405 }
else if (Clauses.size() < 1) {
11406 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11409 return OMPDepobjDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses);
11416 if (Clauses.size() != 1) {
11417 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11418 diag::err_omp_scan_single_clause_expected);
11427 return StmtError(
Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11428 << getOpenMPDirectiveName(OMPD_scan, OMPVersion) << 5);
11433 if (
DSAStack->doesParentHasScanDirective()) {
11434 Diag(StartLoc, diag::err_omp_several_directives_in_region) <<
"scan";
11436 diag::note_omp_previous_directive)
11440 DSAStack->setParentHasScanDirective(StartLoc);
11448 const OMPClause *DependFound =
nullptr;
11449 const OMPClause *DependSourceClause =
nullptr;
11450 const OMPClause *DependSinkClause =
nullptr;
11451 const OMPClause *DoacrossFound =
nullptr;
11452 const OMPClause *DoacrossSourceClause =
nullptr;
11453 const OMPClause *DoacrossSinkClause =
nullptr;
11454 bool ErrorFound =
false;
11458 auto DOC = dyn_cast<OMPDoacrossClause>(
C);
11459 auto DC = dyn_cast<OMPDependClause>(
C);
11461 DependFound = DC ?
C :
nullptr;
11462 DoacrossFound = DOC ?
C :
nullptr;
11463 OMPDoacrossKind ODK;
11464 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11465 (DOC && (ODK.isSource(DOC)))) {
11466 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11468 Diag(
C->getBeginLoc(), diag::err_omp_more_one_clause)
11469 << getOpenMPDirectiveName(OMPD_ordered, OMPVersion)
11475 DependSourceClause =
C;
11477 DoacrossSourceClause =
C;
11479 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11480 Diag(
C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11481 << (DC ?
"depend" :
"doacross") << 0;
11484 }
else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11485 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11486 if (DependSourceClause || DoacrossSourceClause) {
11487 Diag(
C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11488 << (DC ?
"depend" :
"doacross") << 1;
11492 DependSinkClause =
C;
11494 DoacrossSinkClause =
C;
11496 }
else if (
C->getClauseKind() == OMPC_threads) {
11498 }
else if (
C->getClauseKind() == OMPC_simd) {
11502 if (!ErrorFound && !SC &&
11507 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11510 }
else if ((DependFound || DoacrossFound) && (TC || SC)) {
11513 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11518 }
else if ((DependFound || DoacrossFound) &&
11519 !
DSAStack->getParentOrderedRegionParam().first) {
11522 Diag(Loc, diag::err_omp_ordered_directive_without_param)
11526 }
else if (TC || Clauses.empty()) {
11527 if (
const Expr *Param =
DSAStack->getParentOrderedRegionParam().first) {
11529 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11530 << (TC !=
nullptr);
11531 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11535 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11543 if (!DependFound && !DoacrossFound) {
11544 if (
DSAStack->doesParentHasOrderedDirective()) {
11545 Diag(StartLoc, diag::err_omp_several_directives_in_region) <<
"ordered";
11547 diag::note_omp_previous_directive)
11551 DSAStack->setParentHasOrderedDirective(StartLoc);
11557 SemaRef.setFunctionHasBranchProtectedScope();
11560 return OMPOrderedDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses,
11567class OpenMPAtomicUpdateChecker {
11569 enum ExprAnalysisErrorCode {
11573 NotABinaryOrUnaryExpression,
11575 NotAnUnaryIncDecExpression,
11581 NotABinaryExpression,
11584 NotABinaryOperator,
11587 NotAnUpdateExpression,
11590 NotAValidExpression,
11616 OpenMPAtomicUpdateChecker(
Sema &SemaRef)
11626 bool checkStatement(Stmt *S,
unsigned DiagId = 0,
unsigned NoteId = 0);
11628 Expr *
getX()
const {
return X; }
11630 Expr *
getExpr()
const {
return E; }
11644 bool checkBinaryOperation(BinaryOperator *AtomicBinOp,
unsigned DiagId = 0,
11645 unsigned NoteId = 0);
11648bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11649 BinaryOperator *AtomicBinOp,
unsigned DiagId,
unsigned NoteId) {
11650 ExprAnalysisErrorCode ErrorFound = NoError;
11656 if (AtomicBinOp->
getOpcode() == BO_Assign) {
11658 if (
const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11660 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11661 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11662 AtomicInnerBinOp->isBitwiseOp()) {
11663 Op = AtomicInnerBinOp->getOpcode();
11664 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11665 Expr *LHS = AtomicInnerBinOp->getLHS();
11666 Expr *RHS = AtomicInnerBinOp->getRHS();
11667 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11674 if (XId == LHSId) {
11677 }
else if (XId == RHSId) {
11681 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11682 ErrorRange = AtomicInnerBinOp->getSourceRange();
11683 NoteLoc =
X->getExprLoc();
11684 NoteRange =
X->getSourceRange();
11685 ErrorFound = NotAnUpdateExpression;
11688 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11689 ErrorRange = AtomicInnerBinOp->getSourceRange();
11690 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11692 ErrorFound = NotABinaryOperator;
11697 ErrorFound = NotABinaryExpression;
11704 ErrorFound = NotAnAssignmentOp;
11706 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11707 SemaRef.
Diag(ErrorLoc, DiagId) << ErrorRange;
11708 SemaRef.
Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11712 E =
X = UpdateExpr =
nullptr;
11713 return ErrorFound != NoError;
11716bool OpenMPAtomicUpdateChecker::checkStatement(
Stmt *S,
unsigned DiagId,
11718 ExprAnalysisErrorCode ErrorFound = NoError;
11729 if (
auto *AtomicBody = dyn_cast<Expr>(S)) {
11730 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11731 if (AtomicBody->getType()->isScalarType() ||
11732 AtomicBody->isInstantiationDependent()) {
11733 if (
const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11734 AtomicBody->IgnoreParenImpCasts())) {
11737 AtomicCompAssignOp->getOpcode());
11738 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11739 E = AtomicCompAssignOp->getRHS();
11742 }
else if (
auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11743 AtomicBody->IgnoreParenImpCasts())) {
11745 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11747 }
else if (
const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11748 AtomicBody->IgnoreParenImpCasts())) {
11750 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11752 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11753 OpLoc = AtomicUnaryOp->getOperatorLoc();
11754 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11758 ErrorFound = NotAnUnaryIncDecExpression;
11759 ErrorLoc = AtomicUnaryOp->getExprLoc();
11760 ErrorRange = AtomicUnaryOp->getSourceRange();
11761 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11764 }
else if (!AtomicBody->isInstantiationDependent()) {
11765 ErrorFound = NotABinaryOrUnaryExpression;
11766 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11767 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11768 }
else if (AtomicBody->containsErrors()) {
11769 ErrorFound = NotAValidExpression;
11770 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11771 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11774 ErrorFound = NotAScalarType;
11775 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11776 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
11779 ErrorFound = NotAnExpression;
11781 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
11783 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11784 SemaRef.
Diag(ErrorLoc, DiagId) << ErrorRange;
11785 SemaRef.
Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11789 E =
X = UpdateExpr =
nullptr;
11790 if (ErrorFound == NoError && E &&
X) {
11807 UpdateExpr =
Update.get();
11809 return ErrorFound != NoError;
11813llvm::FoldingSetNodeID getNodeId(
ASTContext &Context,
const Expr *S) {
11814 llvm::FoldingSetNodeID Id;
11820bool checkIfTwoExprsAreSame(
ASTContext &Context,
const Expr *LHS,
11822 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11825class OpenMPAtomicCompareChecker {
11872 struct ErrorInfoTy {
11874 SourceLocation ErrorLoc;
11875 SourceRange ErrorRange;
11876 SourceLocation NoteLoc;
11877 SourceRange NoteRange;
11880 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11883 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11885 Expr *
getX()
const {
return X; }
11886 Expr *getE()
const {
return E; }
11887 Expr *
getD()
const {
return D; }
11888 Expr *getCond()
const {
return C; }
11889 bool isXBinopExpr()
const {
return IsXBinopExpr; }
11893 ASTContext &ContextRef;
11908 bool IsXBinopExpr =
true;
11911 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11914 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11917 bool checkType(ErrorInfoTy &ErrorInfo)
const;
11919 static bool CheckValue(
const Expr *E, ErrorInfoTy &ErrorInfo,
11920 bool ShouldBeLValue,
bool ShouldBeInteger =
false) {
11924 if (ShouldBeLValue && !E->
isLValue()) {
11925 ErrorInfo.Error = ErrorTy::XNotLValue;
11926 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->
getExprLoc();
11927 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->
getSourceRange();
11933 ErrorInfo.Error = ErrorTy::NotScalar;
11934 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->
getExprLoc();
11935 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->
getSourceRange();
11939 ErrorInfo.Error = ErrorTy::NotInteger;
11940 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->
getExprLoc();
11941 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->
getSourceRange();
11949bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(
IfStmt *S,
11950 ErrorInfoTy &ErrorInfo) {
11952 if (
auto *CS = dyn_cast<CompoundStmt>(Then)) {
11953 if (CS->body_empty()) {
11954 ErrorInfo.Error = ErrorTy::NoStmt;
11955 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11956 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11959 if (CS->size() > 1) {
11960 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11961 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11962 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
11965 Then = CS->body_front();
11968 auto *BO = dyn_cast<BinaryOperator>(Then);
11970 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11971 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11972 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11975 if (BO->getOpcode() != BO_Assign) {
11976 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11977 ErrorInfo.ErrorLoc = BO->getExprLoc();
11978 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11979 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11985 auto *
Cond = dyn_cast<BinaryOperator>(S->
getCond());
11986 auto *
Call = dyn_cast<CXXOperatorCallExpr>(S->
getCond());
11987 Expr *LHS =
nullptr;
11988 Expr *RHS =
nullptr;
11990 LHS =
Cond->getLHS();
11991 RHS =
Cond->getRHS();
11993 LHS =
Call->getArg(0);
11994 RHS =
Call->getArg(1);
11996 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12002 if ((
Cond &&
Cond->getOpcode() == BO_EQ) ||
12003 (
Call &&
Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12006 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS)) {
12008 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12011 ErrorInfo.Error = ErrorTy::InvalidComparison;
12013 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12017 }
else if ((
Cond &&
12018 (
Cond->getOpcode() == BO_LT ||
Cond->getOpcode() == BO_GT)) ||
12020 (
Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12021 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12023 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS) &&
12024 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12026 }
else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12027 checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12029 IsXBinopExpr =
false;
12031 ErrorInfo.Error = ErrorTy::InvalidComparison;
12033 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12038 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12045 ErrorInfo.Error = ErrorTy::UnexpectedElse;
12054bool OpenMPAtomicCompareChecker::checkCondExprStmt(
Stmt *S,
12055 ErrorInfoTy &ErrorInfo) {
12056 auto *BO = dyn_cast<BinaryOperator>(S);
12058 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12059 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->
getBeginLoc();
12060 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
12063 if (BO->getOpcode() != BO_Assign) {
12064 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12065 ErrorInfo.ErrorLoc = BO->getExprLoc();
12066 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12067 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12073 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
12075 ErrorInfo.Error = ErrorTy::NotCondOp;
12076 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
12077 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
12081 if (!checkIfTwoExprsAreSame(ContextRef,
X, CO->getFalseExpr())) {
12082 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
12083 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
12084 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12085 CO->getFalseExpr()->getSourceRange();
12089 auto *
Cond = dyn_cast<BinaryOperator>(CO->getCond());
12090 auto *
Call = dyn_cast<CXXOperatorCallExpr>(CO->getCond());
12091 Expr *LHS =
nullptr;
12092 Expr *RHS =
nullptr;
12094 LHS =
Cond->getLHS();
12095 RHS =
Cond->getRHS();
12097 LHS =
Call->getArg(0);
12098 RHS =
Call->getArg(1);
12100 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12101 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12102 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12103 CO->getCond()->getSourceRange();
12107 if ((
Cond &&
Cond->getOpcode() == BO_EQ) ||
12108 (
Call &&
Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12110 D = CO->getTrueExpr();
12111 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS)) {
12113 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12116 ErrorInfo.Error = ErrorTy::InvalidComparison;
12117 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12118 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12119 CO->getCond()->getSourceRange();
12122 }
else if ((
Cond &&
12123 (
Cond->getOpcode() == BO_LT ||
Cond->getOpcode() == BO_GT)) ||
12125 (
Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12126 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12128 E = CO->getTrueExpr();
12129 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS) &&
12130 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12132 }
else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12133 checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12135 IsXBinopExpr =
false;
12137 ErrorInfo.Error = ErrorTy::InvalidComparison;
12138 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12139 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12140 CO->getCond()->getSourceRange();
12144 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12145 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12146 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12147 CO->getCond()->getSourceRange();
12154bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo)
const {
12156 assert(
X && E &&
"X and E cannot be nullptr");
12158 if (!CheckValue(
X, ErrorInfo,
true))
12161 if (!CheckValue(E, ErrorInfo,
false))
12164 if (D && !CheckValue(D, ErrorInfo,
false))
12170bool OpenMPAtomicCompareChecker::checkStmt(
12171 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
12172 auto *CS = dyn_cast<CompoundStmt>(S);
12174 if (CS->body_empty()) {
12175 ErrorInfo.Error = ErrorTy::NoStmt;
12176 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12177 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12181 if (CS->size() != 1) {
12182 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12183 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12184 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12187 S = CS->body_front();
12192 if (
auto *IS = dyn_cast<IfStmt>(S)) {
12198 Res = checkCondUpdateStmt(IS, ErrorInfo);
12204 Res = checkCondExprStmt(S, ErrorInfo);
12210 return checkType(ErrorInfo);
12213class OpenMPAtomicCompareCaptureChecker final
12214 :
public OpenMPAtomicCompareChecker {
12216 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
12218 Expr *
getV()
const {
return V; }
12219 Expr *
getR()
const {
return R; }
12224 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12227 bool checkType(ErrorInfoTy &ErrorInfo);
12239 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12243 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12255bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12256 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12259 if (
V && !CheckValue(
V, ErrorInfo,
true))
12262 if (R && !CheckValue(R, ErrorInfo,
true,
true))
12268bool OpenMPAtomicCompareCaptureChecker::checkForm3(
IfStmt *S,
12269 ErrorInfoTy &ErrorInfo) {
12273 if (
auto *CS = dyn_cast<CompoundStmt>(Then)) {
12274 if (CS->body_empty()) {
12275 ErrorInfo.Error = ErrorTy::NoStmt;
12276 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12277 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12280 if (CS->size() > 1) {
12281 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12282 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12283 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12286 Then = CS->body_front();
12289 auto *BO = dyn_cast<BinaryOperator>(Then);
12291 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12292 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12293 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12296 if (BO->getOpcode() != BO_Assign) {
12297 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12298 ErrorInfo.ErrorLoc = BO->getExprLoc();
12299 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12300 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12307 auto *
Cond = dyn_cast<BinaryOperator>(S->
getCond());
12308 auto *
Call = dyn_cast<CXXOperatorCallExpr>(S->
getCond());
12309 Expr *LHS =
nullptr;
12310 Expr *RHS =
nullptr;
12312 LHS =
Cond->getLHS();
12313 RHS =
Cond->getRHS();
12315 LHS =
Call->getArg(0);
12316 RHS =
Call->getArg(1);
12318 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12323 if ((
Cond &&
Cond->getOpcode() != BO_EQ) ||
12324 (
Call &&
Call->getOperator() != OverloadedOperatorKind::OO_EqualEqual)) {
12325 ErrorInfo.Error = ErrorTy::NotEQ;
12331 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS)) {
12333 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12336 ErrorInfo.Error = ErrorTy::InvalidComparison;
12345 ErrorInfo.Error = ErrorTy::NoElse;
12346 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->
getBeginLoc();
12347 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
12352 if (
auto *CS = dyn_cast<CompoundStmt>(Else)) {
12353 if (CS->body_empty()) {
12354 ErrorInfo.Error = ErrorTy::NoStmt;
12355 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12356 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12359 if (CS->size() > 1) {
12360 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12361 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12362 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
12365 Else = CS->body_front();
12368 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12370 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12371 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12372 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12375 if (ElseBO->getOpcode() != BO_Assign) {
12376 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12377 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12378 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12379 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12383 if (!checkIfTwoExprsAreSame(ContextRef,
X, ElseBO->getRHS())) {
12384 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12385 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12386 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12387 ElseBO->getRHS()->getSourceRange();
12391 V = ElseBO->getLHS();
12393 return checkType(ErrorInfo);
12396bool OpenMPAtomicCompareCaptureChecker::checkForm45(
Stmt *S,
12397 ErrorInfoTy &ErrorInfo) {
12401 assert(CS->size() == 2 &&
"CompoundStmt size is not expected");
12404 assert(S1->getOpcode() == BO_Assign &&
"unexpected binary operator");
12406 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12407 ErrorInfo.Error = ErrorTy::InvalidCondition;
12408 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12409 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12415 auto *Then = S2->getThen();
12416 if (
auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12417 if (ThenCS->body_empty()) {
12418 ErrorInfo.Error = ErrorTy::NoStmt;
12419 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12420 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12423 if (ThenCS->size() > 1) {
12424 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12425 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12426 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12429 Then = ThenCS->body_front();
12432 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12434 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12435 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12436 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12439 if (ThenBO->getOpcode() != BO_Assign) {
12440 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12441 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12442 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12443 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12447 X = ThenBO->getLHS();
12448 D = ThenBO->getRHS();
12451 if (BO->getOpcode() != BO_EQ) {
12452 ErrorInfo.Error = ErrorTy::NotEQ;
12453 ErrorInfo.ErrorLoc = BO->getExprLoc();
12454 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12455 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12461 if (checkIfTwoExprsAreSame(ContextRef,
X, BO->getLHS())) {
12463 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, BO->getRHS())) {
12466 ErrorInfo.Error = ErrorTy::InvalidComparison;
12467 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12468 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12472 if (S2->getElse()) {
12475 auto *Else = S2->getElse();
12476 if (
auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12477 if (ElseCS->body_empty()) {
12478 ErrorInfo.Error = ErrorTy::NoStmt;
12479 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12480 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12483 if (ElseCS->size() > 1) {
12484 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12485 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12486 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12489 Else = ElseCS->body_front();
12492 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12494 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12495 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12496 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12499 if (ElseBO->getOpcode() != BO_Assign) {
12500 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12501 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12502 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12503 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12506 if (!checkIfTwoExprsAreSame(ContextRef,
X, ElseBO->getRHS())) {
12507 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12508 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12509 ErrorInfo.NoteLoc =
X->getExprLoc();
12510 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12511 ErrorInfo.NoteRange =
X->getSourceRange();
12515 V = ElseBO->getLHS();
12518 return checkType(ErrorInfo);
12521bool OpenMPAtomicCompareCaptureChecker::checkStmt(
Stmt *S,
12522 ErrorInfoTy &ErrorInfo) {
12524 if (
auto *IS = dyn_cast<IfStmt>(S))
12525 return checkForm3(IS, ErrorInfo);
12527 auto *CS = dyn_cast<CompoundStmt>(S);
12529 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12530 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->
getBeginLoc();
12531 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
12534 if (CS->body_empty()) {
12535 ErrorInfo.Error = ErrorTy::NoStmt;
12536 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12537 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12542 if (CS->size() == 1) {
12543 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12545 ErrorInfo.Error = ErrorTy::NotIfStmt;
12546 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->
getBeginLoc();
12547 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12552 return checkForm3(IS, ErrorInfo);
12553 }
else if (CS->size() == 2) {
12554 auto *S1 = CS->body_front();
12555 auto *S2 = CS->body_back();
12557 Stmt *UpdateStmt =
nullptr;
12558 Stmt *CondUpdateStmt =
nullptr;
12559 Stmt *CondExprStmt =
nullptr;
12561 if (
auto *BO = dyn_cast<BinaryOperator>(S1)) {
12571 return checkForm45(CS, ErrorInfo);
12580 CondUpdateStmt = S2;
12589 CondUpdateStmt = S1;
12592 auto CheckCondUpdateStmt = [
this, &ErrorInfo](
Stmt *CUS) {
12593 auto *IS = dyn_cast<IfStmt>(CUS);
12595 ErrorInfo.Error = ErrorTy::NotIfStmt;
12596 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12597 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12601 return checkCondUpdateStmt(IS, ErrorInfo);
12605 auto CheckUpdateStmt = [
this, &ErrorInfo](
Stmt *US) {
12606 auto *BO = dyn_cast<BinaryOperator>(US);
12608 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12609 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12610 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12613 if (BO->getOpcode() != BO_Assign) {
12614 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12615 ErrorInfo.ErrorLoc = BO->getExprLoc();
12616 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12617 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12620 if (!checkIfTwoExprsAreSame(ContextRef, this->
X, BO->getRHS())) {
12621 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12622 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12623 ErrorInfo.NoteLoc = this->
X->getExprLoc();
12624 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12625 ErrorInfo.NoteRange = this->
X->getSourceRange();
12629 this->
V = BO->getLHS();
12634 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12636 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12638 if (!CheckUpdateStmt(UpdateStmt))
12641 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12642 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12643 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12647 return checkType(ErrorInfo);
12658 DSAStack->addAtomicDirectiveLoc(StartLoc);
12671 bool MutexClauseEncountered =
false;
12672 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12674 switch (
C->getClauseKind()) {
12678 MutexClauseEncountered =
true;
12681 case OMPC_compare: {
12682 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12683 Diag(
C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12685 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12688 AtomicKind =
C->getClauseKind();
12689 AtomicKindLoc =
C->getBeginLoc();
12690 if (!EncounteredAtomicKinds.insert(
C->getClauseKind()).second) {
12691 Diag(
C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12693 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12701 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12702 Diag(
C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12713 case OMPC_relaxed: {
12714 if (MemOrderKind != OMPC_unknown) {
12715 Diag(
C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12716 << getOpenMPDirectiveName(OMPD_atomic, OMPVersion) << 0
12718 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12721 MemOrderKind =
C->getClauseKind();
12722 MemOrderLoc =
C->getBeginLoc();
12730 llvm_unreachable(
"unknown clause is encountered");
12733 bool IsCompareCapture =
false;
12734 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12735 EncounteredAtomicKinds.contains(OMPC_capture)) {
12736 IsCompareCapture =
true;
12737 AtomicKind = OMPC_compare;
12746 if ((AtomicKind == OMPC_read &&
12747 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12748 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12749 AtomicKind == OMPC_unknown) &&
12750 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12752 if (AtomicKind == OMPC_unknown)
12754 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12756 << (AtomicKind == OMPC_unknown ? 1 : 0)
12758 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12762 Stmt *Body = AStmt;
12763 if (
auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12764 Body = EWC->getSubExpr();
12769 Expr *UE =
nullptr;
12771 Expr *CE =
nullptr;
12798 if (AtomicKind == OMPC_read) {
12805 } ErrorFound = NoError;
12810 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12811 const auto *AtomicBinOp =
12812 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12813 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12816 if ((
X->isInstantiationDependent() ||
X->getType()->isScalarType()) &&
12817 (
V->isInstantiationDependent() ||
V->getType()->isScalarType())) {
12818 if (!
X->isLValue() || !
V->isLValue()) {
12819 const Expr *NotLValueExpr =
X->isLValue() ?
V :
X;
12820 ErrorFound = NotAnLValue;
12826 }
else if (!
X->isInstantiationDependent() ||
12827 !
V->isInstantiationDependent()) {
12828 const Expr *NotScalarExpr =
12829 (
X->isInstantiationDependent() ||
X->getType()->isScalarType())
12832 ErrorFound = NotAScalarType;
12838 }
else if (!AtomicBody->isInstantiationDependent()) {
12839 ErrorFound = NotAnAssignmentOp;
12840 ErrorLoc = AtomicBody->getExprLoc();
12841 ErrorRange = AtomicBody->getSourceRange();
12843 : AtomicBody->getExprLoc();
12845 : AtomicBody->getSourceRange();
12848 ErrorFound = NotAnExpression;
12850 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
12852 if (ErrorFound != NoError) {
12853 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12855 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12856 << ErrorFound << NoteRange;
12859 if (
SemaRef.CurContext->isDependentContext())
12861 }
else if (AtomicKind == OMPC_write) {
12868 } ErrorFound = NoError;
12873 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12874 const auto *AtomicBinOp =
12875 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12876 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12878 E = AtomicBinOp->
getRHS();
12879 if ((
X->isInstantiationDependent() ||
X->getType()->isScalarType()) &&
12881 if (!
X->isLValue()) {
12882 ErrorFound = NotAnLValue;
12885 NoteLoc =
X->getExprLoc();
12886 NoteRange =
X->getSourceRange();
12888 }
else if (!
X->isInstantiationDependent() ||
12890 const Expr *NotScalarExpr =
12891 (
X->isInstantiationDependent() ||
X->getType()->isScalarType())
12894 ErrorFound = NotAScalarType;
12900 }
else if (!AtomicBody->isInstantiationDependent()) {
12901 ErrorFound = NotAnAssignmentOp;
12902 ErrorLoc = AtomicBody->getExprLoc();
12903 ErrorRange = AtomicBody->getSourceRange();
12905 : AtomicBody->getExprLoc();
12907 : AtomicBody->getSourceRange();
12910 ErrorFound = NotAnExpression;
12912 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
12914 if (ErrorFound != NoError) {
12915 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12917 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12918 << ErrorFound << NoteRange;
12921 if (
SemaRef.CurContext->isDependentContext())
12923 }
else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12932 OpenMPAtomicUpdateChecker Checker(
SemaRef);
12933 if (Checker.checkStatement(
12935 (AtomicKind == OMPC_update)
12936 ? diag::err_omp_atomic_update_not_expression_statement
12937 : diag::err_omp_atomic_not_expression_statement,
12938 diag::note_omp_atomic_update))
12940 if (!
SemaRef.CurContext->isDependentContext()) {
12941 E = Checker.getExpr();
12942 X = Checker.getX();
12943 UE = Checker.getUpdateExpr();
12946 }
else if (AtomicKind == OMPC_capture) {
12949 NotACompoundStatement,
12950 NotTwoSubstatements,
12951 NotASpecificExpression,
12953 } ErrorFound = NoError;
12956 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12965 const auto *AtomicBinOp =
12966 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12967 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12970 OpenMPAtomicUpdateChecker Checker(
SemaRef);
12971 if (Checker.checkStatement(
12972 Body, diag::err_omp_atomic_capture_not_expression_statement,
12973 diag::note_omp_atomic_update))
12975 E = Checker.getExpr();
12976 X = Checker.getX();
12977 UE = Checker.getUpdateExpr();
12980 }
else if (!AtomicBody->isInstantiationDependent()) {
12981 ErrorLoc = AtomicBody->getExprLoc();
12982 ErrorRange = AtomicBody->getSourceRange();
12984 : AtomicBody->getExprLoc();
12986 : AtomicBody->getSourceRange();
12987 ErrorFound = NotAnAssignmentOp;
12989 if (ErrorFound != NoError) {
12990 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
12992 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12995 if (
SemaRef.CurContext->isDependentContext())
12996 UE =
V = E =
X =
nullptr;
13014 if (
auto *CS = dyn_cast<CompoundStmt>(Body)) {
13016 if (CS->size() == 2) {
13018 Stmt *Second = CS->body_back();
13019 if (
auto *EWC = dyn_cast<ExprWithCleanups>(
First))
13020 First = EWC->getSubExpr()->IgnoreParenImpCasts();
13021 if (
auto *EWC = dyn_cast<ExprWithCleanups>(Second))
13022 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
13024 OpenMPAtomicUpdateChecker Checker(
SemaRef);
13025 bool IsUpdateExprFound = !Checker.checkStatement(Second);
13027 if (IsUpdateExprFound) {
13028 BinOp = dyn_cast<BinaryOperator>(
First);
13029 IsUpdateExprFound = BinOp && BinOp->
getOpcode() == BO_Assign;
13031 if (IsUpdateExprFound && !
SemaRef.CurContext->isDependentContext()) {
13041 llvm::FoldingSetNodeID XId, PossibleXId;
13042 Checker.getX()->Profile(XId, Context,
true);
13043 PossibleX->
Profile(PossibleXId, Context,
true);
13044 IsUpdateExprFound = XId == PossibleXId;
13045 if (IsUpdateExprFound) {
13047 X = Checker.getX();
13048 E = Checker.getExpr();
13049 UE = Checker.getUpdateExpr();
13054 if (!IsUpdateExprFound) {
13055 IsUpdateExprFound = !Checker.checkStatement(
First);
13057 if (IsUpdateExprFound) {
13058 BinOp = dyn_cast<BinaryOperator>(Second);
13059 IsUpdateExprFound = BinOp && BinOp->
getOpcode() == BO_Assign;
13061 if (IsUpdateExprFound &&
13062 !
SemaRef.CurContext->isDependentContext()) {
13072 llvm::FoldingSetNodeID XId, PossibleXId;
13073 Checker.getX()->Profile(XId, Context,
true);
13074 PossibleX->
Profile(PossibleXId, Context,
true);
13075 IsUpdateExprFound = XId == PossibleXId;
13076 if (IsUpdateExprFound) {
13078 X = Checker.getX();
13079 E = Checker.getExpr();
13080 UE = Checker.getUpdateExpr();
13086 if (!IsUpdateExprFound) {
13088 auto *FirstExpr = dyn_cast<Expr>(
First);
13089 auto *SecondExpr = dyn_cast<Expr>(Second);
13090 if (!FirstExpr || !SecondExpr ||
13091 !(FirstExpr->isInstantiationDependent() ||
13092 SecondExpr->isInstantiationDependent())) {
13093 auto *FirstBinOp = dyn_cast<BinaryOperator>(
First);
13094 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
13095 ErrorFound = NotAnAssignmentOp;
13096 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
13097 :
First->getBeginLoc();
13098 NoteRange = ErrorRange = FirstBinOp
13099 ? FirstBinOp->getSourceRange()
13102 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
13103 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
13104 ErrorFound = NotAnAssignmentOp;
13105 NoteLoc = ErrorLoc = SecondBinOp
13106 ? SecondBinOp->getOperatorLoc()
13108 NoteRange = ErrorRange =
13109 SecondBinOp ? SecondBinOp->getSourceRange()
13112 Expr *PossibleXRHSInFirst =
13114 Expr *PossibleXLHSInSecond =
13116 llvm::FoldingSetNodeID X1Id, X2Id;
13117 PossibleXRHSInFirst->
Profile(X1Id, Context,
13119 PossibleXLHSInSecond->
Profile(X2Id, Context,
13121 IsUpdateExprFound = X1Id == X2Id;
13122 if (IsUpdateExprFound) {
13123 V = FirstBinOp->getLHS();
13124 X = SecondBinOp->getLHS();
13125 E = SecondBinOp->getRHS();
13130 ErrorFound = NotASpecificExpression;
13131 ErrorLoc = FirstBinOp->getExprLoc();
13132 ErrorRange = FirstBinOp->getSourceRange();
13133 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
13134 NoteRange = SecondBinOp->getRHS()->getSourceRange();
13142 NoteRange = ErrorRange =
13144 ErrorFound = NotTwoSubstatements;
13148 NoteRange = ErrorRange =
13150 ErrorFound = NotACompoundStatement;
13153 if (ErrorFound != NoError) {
13154 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
13156 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13159 if (
SemaRef.CurContext->isDependentContext())
13160 UE =
V = E =
X =
nullptr;
13161 }
else if (AtomicKind == OMPC_compare) {
13162 if (IsCompareCapture) {
13163 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
13164 OpenMPAtomicCompareCaptureChecker Checker(
SemaRef);
13165 if (!Checker.checkStmt(Body, ErrorInfo)) {
13166 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
13167 << ErrorInfo.ErrorRange;
13168 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13169 << ErrorInfo.Error << ErrorInfo.NoteRange;
13172 X = Checker.getX();
13173 E = Checker.getE();
13174 D = Checker.getD();
13175 CE = Checker.getCond();
13176 V = Checker.getV();
13177 R = Checker.getR();
13183 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
13184 OpenMPAtomicCompareChecker Checker(
SemaRef);
13185 if (!Checker.checkStmt(Body, ErrorInfo)) {
13186 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
13187 << ErrorInfo.ErrorRange;
13188 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13189 << ErrorInfo.Error << ErrorInfo.NoteRange;
13192 X = Checker.getX();
13193 E = Checker.getE();
13194 D = Checker.getD();
13195 CE = Checker.getCond();
13201 auto *It = find_if(Clauses, [](
OMPClause *
C) {
13202 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
13204 if (It != Clauses.end()) {
13205 auto *
Cond = dyn_cast<BinaryOperator>(CE);
13206 if (
Cond->getOpcode() != BO_EQ) {
13207 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
13208 ErrorInfo.ErrorLoc =
Cond->getExprLoc();
13209 ErrorInfo.NoteLoc =
Cond->getOperatorLoc();
13210 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
Cond->getSourceRange();
13212 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
13213 << ErrorInfo.ErrorRange;
13222 SemaRef.setFunctionHasBranchProtectedScope();
13224 return OMPAtomicDirective::Create(
13225 Context, StartLoc, EndLoc, Clauses, AStmt,
13242 if (
DSAStack->hasInnerTeamsRegion()) {
13244 bool OMPTeamsFound =
true;
13245 if (
const auto *CS = dyn_cast<CompoundStmt>(S)) {
13246 auto I = CS->body_begin();
13247 while (I != CS->body_end()) {
13248 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
13250 if (!IsTeams || I != CS->body_begin()) {
13251 OMPTeamsFound =
false;
13252 if (IsTeams && I != CS->body_begin()) {
13261 assert(I != CS->body_end() &&
"Not found statement");
13264 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
13267 if (!OMPTeamsFound) {
13268 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
13270 diag::note_omp_nested_teams_construct_here);
13303 OMPLoopBasedDirective::HelperExprs B;
13306 unsigned NestedLoopCount =
13309 VarsWithImplicitDSA, B);
13310 if (NestedLoopCount == 0)
13317 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13324 return llvm::any_of(
13325 Clauses, [K](
const OMPClause *
C) {
return C->getClauseKind() == K; });
13328template <
typename... Params>
13330 const Params... ClauseTypes) {
13337 if (
auto *TC = dyn_cast<OMPToClause>(
C))
13338 return llvm::all_of(TC->all_decls(), [](
ValueDecl *VD) {
13339 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13340 (VD->isExternallyVisible() &&
13341 VD->getVisibility() != HiddenVisibility);
13343 else if (
auto *FC = dyn_cast<OMPFromClause>(
C))
13344 return llvm::all_of(FC->all_decls(), [](
ValueDecl *VD) {
13345 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13346 (VD->isExternallyVisible() &&
13347 VD->getVisibility() != HiddenVisibility);
13366 if (!
hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13368 !
hasClauses(Clauses, OMPC_use_device_addr))) {
13371 Expected =
"'map' or 'use_device_ptr'";
13373 Expected =
"'map', 'use_device_ptr', or 'use_device_addr'";
13375 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13376 <<
Expected << getOpenMPDirectiveName(OMPD_target_data, OMPVersion);
13380 SemaRef.setFunctionHasBranchProtectedScope();
13398 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13400 << getOpenMPDirectiveName(OMPD_target_enter_data, OMPVersion);
13420 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13421 <<
"'map'" << getOpenMPDirectiveName(OMPD_target_exit_data, OMPVersion);
13437 if (!
hasClauses(Clauses, OMPC_to, OMPC_from)) {
13438 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13443 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13453template <
typename ClauseType>
13456 unsigned MaxNum,
unsigned Diag) {
13457 auto ClauseItr = llvm::find_if(Clauses, llvm::IsaPred<ClauseType>);
13458 if (ClauseItr == Clauses.end())
13461 auto VarList =
C->getVarRefs();
13462 if (VarList.size() > MaxNum) {
13463 SemaRef.
Diag(VarList[MaxNum]->getBeginLoc(),
Diag)
13478 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
13480 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
13485 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13489 DSAStack->setParentTeamsRegionLoc(StartLoc);
13498 if (
DSAStack->isParentNowaitRegion()) {
13499 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13502 if (
DSAStack->isParentOrderedRegion()) {
13503 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13507 EndLoc, CancelRegion);
13513 if (
DSAStack->isParentNowaitRegion()) {
13514 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13517 if (
DSAStack->isParentOrderedRegion()) {
13518 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13521 DSAStack->setParentCancelRegion(
true);
13528 const OMPClause *ReductionClause =
nullptr;
13529 const OMPClause *NogroupClause =
nullptr;
13531 if (
C->getClauseKind() == OMPC_reduction) {
13532 ReductionClause =
C;
13537 if (
C->getClauseKind() == OMPC_nogroup) {
13539 if (ReductionClause)
13544 if (ReductionClause && NogroupClause) {
13545 S.
Diag(ReductionClause->
getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13560 OMPLoopBasedDirective::HelperExprs B;
13563 unsigned NestedLoopCount =
13566 *
DSAStack, VarsWithImplicitDSA, B);
13567 if (NestedLoopCount == 0)
13570 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13571 "omp for loop exprs were not built");
13577 {OMPC_grainsize, OMPC_num_tasks}))
13585 SemaRef.setFunctionHasBranchProtectedScope();
13587 NestedLoopCount, Clauses, AStmt, B,
13601 OMPLoopBasedDirective::HelperExprs B;
13604 unsigned NestedLoopCount =
13607 VarsWithImplicitDSA, B);
13608 if (NestedLoopCount == 0)
13618 {OMPC_grainsize, OMPC_num_tasks}))
13629 NestedLoopCount, Clauses, AStmt, B);
13639 OMPLoopBasedDirective::HelperExprs B;
13642 unsigned NestedLoopCount =
13645 *
DSAStack, VarsWithImplicitDSA, B);
13646 if (NestedLoopCount == 0)
13649 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13650 "omp for loop exprs were not built");
13656 {OMPC_grainsize, OMPC_num_tasks}))
13664 SemaRef.setFunctionHasBranchProtectedScope();
13666 NestedLoopCount, Clauses, AStmt, B,
13677 OMPLoopBasedDirective::HelperExprs B;
13680 unsigned NestedLoopCount =
13683 *
DSAStack, VarsWithImplicitDSA, B);
13684 if (NestedLoopCount == 0)
13687 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13688 "omp for loop exprs were not built");
13694 {OMPC_grainsize, OMPC_num_tasks}))
13702 SemaRef.setFunctionHasBranchProtectedScope();
13704 NestedLoopCount, Clauses, AStmt, B,
13718 OMPLoopBasedDirective::HelperExprs B;
13721 unsigned NestedLoopCount =
13724 VarsWithImplicitDSA, B);
13725 if (NestedLoopCount == 0)
13735 {OMPC_grainsize, OMPC_num_tasks}))
13746 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13759 OMPLoopBasedDirective::HelperExprs B;
13762 unsigned NestedLoopCount =
13765 VarsWithImplicitDSA, B);
13766 if (NestedLoopCount == 0)
13776 {OMPC_grainsize, OMPC_num_tasks}))
13787 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13799 OMPLoopBasedDirective::HelperExprs B;
13805 VarsWithImplicitDSA, B);
13806 if (NestedLoopCount == 0)
13809 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13810 "omp for loop exprs were not built");
13816 {OMPC_grainsize, OMPC_num_tasks}))
13825 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13838 OMPLoopBasedDirective::HelperExprs B;
13844 VarsWithImplicitDSA, B);
13845 if (NestedLoopCount == 0)
13848 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13849 "omp for loop exprs were not built");
13855 {OMPC_grainsize, OMPC_num_tasks}))
13864 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13875 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
13877 OMPLoopBasedDirective::HelperExprs B;
13883 VarsWithImplicitDSA, B);
13884 if (NestedLoopCount == 0)
13894 {OMPC_grainsize, OMPC_num_tasks}))
13905 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13915 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
13917 OMPLoopBasedDirective::HelperExprs B;
13923 VarsWithImplicitDSA, B);
13924 if (NestedLoopCount == 0)
13934 {OMPC_grainsize, OMPC_num_tasks}))
13945 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13955 OMPLoopBasedDirective::HelperExprs B;
13958 unsigned NestedLoopCount =
13962 if (NestedLoopCount == 0)
13965 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13966 "omp for loop exprs were not built");
13968 SemaRef.setFunctionHasBranchProtectedScope();
13970 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13971 return DistributeDirective;
13983 OMPLoopBasedDirective::HelperExprs B;
13989 VarsWithImplicitDSA, B);
13990 if (NestedLoopCount == 0)
13993 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13994 "omp for loop exprs were not built");
13997 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14008 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
14010 OMPLoopBasedDirective::HelperExprs B;
14016 VarsWithImplicitDSA, B);
14017 if (NestedLoopCount == 0)
14027 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14039 OMPLoopBasedDirective::HelperExprs B;
14042 unsigned NestedLoopCount =
14046 if (NestedLoopCount == 0)
14056 NestedLoopCount, Clauses, AStmt, B);
14068 OMPLoopBasedDirective::HelperExprs B;
14074 VarsWithImplicitDSA, B);
14075 if (NestedLoopCount == 0)
14085 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14096 OMPLoopBasedDirective::HelperExprs B;
14099 unsigned NestedLoopCount =
14102 VarsWithImplicitDSA, B);
14103 if (NestedLoopCount == 0)
14113 NestedLoopCount, Clauses, AStmt, B);
14125 OMPLoopBasedDirective::HelperExprs B;
14128 unsigned NestedLoopCount =
14132 if (NestedLoopCount == 0)
14135 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14136 "omp teams distribute loop exprs were not built");
14138 DSAStack->setParentTeamsRegionLoc(StartLoc);
14141 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14153 OMPLoopBasedDirective::HelperExprs B;
14159 VarsWithImplicitDSA, B);
14160 if (NestedLoopCount == 0)
14169 DSAStack->setParentTeamsRegionLoc(StartLoc);
14172 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14182 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
14184 OMPLoopBasedDirective::HelperExprs B;
14190 VarsWithImplicitDSA, B);
14191 if (NestedLoopCount == 0)
14200 DSAStack->setParentTeamsRegionLoc(StartLoc);
14203 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14213 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
14215 OMPLoopBasedDirective::HelperExprs B;
14221 VarsWithImplicitDSA, B);
14223 if (NestedLoopCount == 0)
14226 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14227 "omp for loop exprs were not built");
14229 DSAStack->setParentTeamsRegionLoc(StartLoc);
14232 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14245 bool HasThreadLimitAndNumTeamsClause =
hasClauses(Clauses, OMPC_num_teams) &&
14247 bool HasBareClause = llvm::any_of(Clauses, [&](
const OMPClause *
C) {
14249 return C->getClauseKind() == OMPC_ompx_bare;
14252 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
14257 unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 1;
14258 unsigned DiagNo = HasBareClause
14259 ? diag::err_ompx_more_than_three_expr_not_allowed
14260 : diag::err_omp_multi_expr_not_allowed;
14262 ClauseMaxNumExprs, DiagNo) ||
14264 ClauseMaxNumExprs, DiagNo))
14278 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
14280 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14286 OMPLoopBasedDirective::HelperExprs B;
14292 VarsWithImplicitDSA, B);
14293 if (NestedLoopCount == 0)
14296 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14297 "omp target teams distribute loop exprs were not built");
14300 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14310 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
14312 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14316 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
14318 OMPLoopBasedDirective::HelperExprs B;
14324 VarsWithImplicitDSA, B);
14325 if (NestedLoopCount == 0)
14332 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_simd, AStmt);
14351 OMPLoopBasedDirective::HelperExprs B;
14354 unsigned NestedLoopCount =
14359 if (NestedLoopCount == 0)
14369 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14379 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
14381 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14385 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
14387 OMPLoopBasedDirective::HelperExprs B;
14393 VarsWithImplicitDSA, B);
14394 if (NestedLoopCount == 0)
14404 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14407bool SemaOpenMP::checkTransformableLoopNest(
14411 OriginalInits.emplace_back();
14412 bool Result = OMPLoopBasedDirective::doForAllLoops(
14414 [
this, &LoopHelpers, &Body, &OriginalInits, Kind](
unsigned Cnt,
14416 VarsWithInheritedDSAType TmpDSA;
14417 unsigned SingleNumLoops =
14418 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
14419 TmpDSA, LoopHelpers[Cnt]);
14420 if (SingleNumLoops == 0)
14422 assert(SingleNumLoops == 1 &&
"Expect single loop iteration space");
14423 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14424 OriginalInits.back().push_back(For->getInit());
14425 Body = For->getBody();
14427 assert(isa<CXXForRangeStmt>(CurStmt) &&
14428 "Expected canonical for or range-based for loops.");
14429 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14430 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14431 Body = CXXFor->getBody();
14433 OriginalInits.emplace_back();
14436 [&OriginalInits](OMPLoopBasedDirective *Transform) {
14437 Stmt *DependentPreInits;
14438 if (
auto *Dir = dyn_cast<OMPTileDirective>(Transform))
14439 DependentPreInits = Dir->getPreInits();
14440 else if (
auto *Dir = dyn_cast<OMPStripeDirective>(Transform))
14441 DependentPreInits = Dir->getPreInits();
14442 else if (
auto *Dir = dyn_cast<OMPUnrollDirective>(Transform))
14443 DependentPreInits = Dir->getPreInits();
14444 else if (
auto *Dir = dyn_cast<OMPReverseDirective>(Transform))
14445 DependentPreInits = Dir->getPreInits();
14446 else if (
auto *Dir = dyn_cast<OMPInterchangeDirective>(Transform))
14447 DependentPreInits = Dir->getPreInits();
14449 llvm_unreachable(
"Unhandled loop transformation");
14453 assert(OriginalInits.back().empty() &&
"No preinit after innermost loop");
14454 OriginalInits.pop_back();
14460 OMPLoopBasedDirective::HelperExprs &LoopHelper,
14466 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
14467 Stmt *RangeInit = CXXRangeFor->getInit();
14469 PreInits.push_back(RangeInit);
14471 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14476 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14482 llvm::append_range(PreInits, OriginalInit);
14485 if (
auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits)) {
14486 PreInits.push_back(
new (Context)
DeclStmt(
14487 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14491 for (
Expr *CounterRef : LoopHelper.Counters) {
14494 PreInits.push_back(
new (Context)
DeclStmt(
14502 size_t NumLoops = LoopStmts.size();
14503 OMPLoopBasedDirective::doForAllLoops(
14504 AStmt,
false, NumLoops,
14505 [LoopStmts](
unsigned Cnt,
Stmt *CurStmt) {
14506 assert(!LoopStmts[Cnt] &&
"Loop statement must not yet be assigned");
14507 LoopStmts[Cnt] = CurStmt;
14510 assert(!is_contained(LoopStmts,
nullptr) &&
14511 "Expecting a loop statement for each affected loop");
14529 const auto *SizesClause =
14530 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14531 if (!SizesClause ||
14532 llvm::any_of(SizesClause->getSizesRefs(), [](
Expr *E) { return !E; }))
14534 unsigned NumLoops = SizesClause->getNumSizes();
14542 Stmt *Body =
nullptr;
14544 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14549 if (
SemaRef.CurContext->isDependentContext())
14551 NumLoops, AStmt,
nullptr,
nullptr);
14553 assert(LoopHelpers.size() == NumLoops &&
14554 "Expecting loop iteration space dimensionality to match number of "
14556 assert(OriginalInits.size() == NumLoops &&
14557 "Expecting loop iteration space dimensionality to match number of "
14565 CaptureVars CopyTransformer(
SemaRef);
14570 FloorIndVars.resize(NumLoops);
14571 TileIndVars.resize(NumLoops);
14572 for (
unsigned I = 0; I < NumLoops; ++I) {
14573 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14575 assert(LoopHelper.Counters.size() == 1 &&
14576 "Expect single-dimensional loop iteration space");
14578 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14584 std::string FloorCntName =
14585 (Twine(
".floor_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
14588 FloorIndVars[I] = FloorCntDecl;
14593 std::string TileCntName =
14594 (Twine(
".tile_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
14600 TileCntDecl->setDeclName(
14601 &
SemaRef.PP.getIdentifierTable().get(TileCntName));
14602 TileIndVars[I] = TileCntDecl;
14610 Stmt *Inner = Body;
14612 auto MakeDimTileSize = [&
SemaRef = this->SemaRef, &CopyTransformer, &Context,
14613 SizesClause, CurScope](
int I) ->
Expr * {
14614 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
14620 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
14639 uint64_t DimWidth = Context.getTypeSize(DimTy);
14641 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14645 CurScope, {}, BO_LE,
14649 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
14655 for (
int I = NumLoops - 1; I >= 0; --I) {
14656 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14657 Expr *NumIterations = LoopHelper.NumIterations;
14660 Stmt *LoopStmt = LoopStmts[I];
14665 auto MakeTileIVRef = [&
SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
14668 OrigCntVar->getExprLoc());
14672 SemaRef.AddInitializerToDecl(
14675 .DefaultLvalueConversion(
14679 Decl *CounterDecl = TileIndVars[I];
14682 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14688 Expr *DimTileSize = MakeDimTileSize(I);
14692 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14698 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14699 NumIterations, EndOfTile.
get());
14703 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
14704 IsPartialTile.
get(), NumIterations, EndOfTile.
get());
14705 if (!MinTileAndIterSpace.
isUsable())
14708 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14709 MakeTileIVRef(), MinTileAndIterSpace.
get());
14715 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef());
14736 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
14737 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14738 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
14739 BodyParts.push_back(Inner);
14742 Inner =
new (Context)
14745 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14749 for (
int I = NumLoops - 1; I >= 0; --I) {
14750 auto &LoopHelper = LoopHelpers[I];
14751 Expr *NumIterations = LoopHelper.NumIterations;
14756 SemaRef.AddInitializerToDecl(
14758 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
14760 Decl *CounterDecl = FloorIndVars[I];
14769 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14776 Expr *DimTileSize = MakeDimTileSize(I);
14780 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
14786 Inner =
new (Context)
14789 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14804 const auto *SizesClause =
14805 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14806 if (!SizesClause ||
14807 llvm::any_of(SizesClause->getSizesRefs(), [](
const Expr *SizeExpr) {
14808 return !SizeExpr || SizeExpr->containsErrors();
14811 unsigned NumLoops = SizesClause->getNumSizes();
14819 Stmt *Body =
nullptr;
14821 if (!checkTransformableLoopNest(OMPD_stripe, AStmt, NumLoops, LoopHelpers,
14822 Body, OriginalInits))
14826 if (
SemaRef.CurContext->isDependentContext())
14828 NumLoops, AStmt,
nullptr,
nullptr);
14830 assert(LoopHelpers.size() == NumLoops &&
14831 "Expecting loop iteration space dimensionality to match number of "
14833 assert(OriginalInits.size() == NumLoops &&
14834 "Expecting loop iteration space dimensionality to match number of "
14842 CaptureVars CopyTransformer(
SemaRef);
14847 FloorIndVars.resize(NumLoops);
14848 StripeIndVars.resize(NumLoops);
14849 for (
unsigned I : llvm::seq<unsigned>(NumLoops)) {
14850 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14852 assert(LoopHelper.Counters.size() == 1 &&
14853 "Expect single-dimensional loop iteration space");
14855 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14861 std::string FloorCntName =
14862 (Twine(
".floor_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
14865 FloorIndVars[I] = FloorCntDecl;
14870 std::string StripeCntName =
14871 (Twine(
".stripe_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
14877 StripeCntDecl->setDeclName(
14878 &
SemaRef.PP.getIdentifierTable().get(StripeCntName));
14879 StripeIndVars[I] = StripeCntDecl;
14887 Stmt *Inner = Body;
14889 auto MakeDimStripeSize = [&](
int I) ->
Expr * {
14890 Expr *DimStripeSizeExpr = SizesClause->getSizesRefs()[I];
14892 return AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr));
14911 uint64_t DimWidth = Context.getTypeSize(DimTy);
14913 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14917 CurScope, {}, BO_LE,
14921 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), DimTy,
14927 for (
int I = NumLoops - 1; I >= 0; --I) {
14928 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14929 Expr *NumIterations = LoopHelper.NumIterations;
14932 Stmt *LoopStmt = LoopStmts[I];
14935 SemaRef.AddInitializerToDecl(
14938 .DefaultLvalueConversion(
14942 Decl *CounterDecl = StripeIndVars[I];
14945 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14952 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14954 MakeDimStripeSize(I));
14958 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14959 NumIterations, EndOfStripe.
get());
14963 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
14964 IsPartialStripe.
get(), NumIterations, EndOfStripe.
get());
14965 if (!MinStripeAndIterSpace.
isUsable())
14968 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14970 MinStripeAndIterSpace.
get());
14976 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc,
14998 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
14999 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15000 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15001 BodyParts.push_back(Inner);
15004 Inner =
new (Context)
15007 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15011 for (
int I = NumLoops - 1; I >= 0; --I) {
15012 auto &LoopHelper = LoopHelpers[I];
15013 Expr *NumIterations = LoopHelper.NumIterations;
15018 SemaRef.AddInitializerToDecl(
15020 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15022 Decl *CounterDecl = FloorIndVars[I];
15031 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15039 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15041 MakeDimStripeSize(I));
15045 Inner =
new (Context)
15048 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15052 NumLoops, AStmt, Inner,
15067 {OMPC_partial, OMPC_full}))
15071 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
15073 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
15074 assert(!(FullClause && PartialClause) &&
15075 "mutual exclusivity must have been checked before");
15077 constexpr unsigned NumLoops = 1;
15078 Stmt *Body =
nullptr;
15082 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
15083 Body, OriginalInits))
15086 unsigned NumGeneratedTopLevelLoops = PartialClause ? 1 : 0;
15089 if (
SemaRef.CurContext->isDependentContext())
15091 NumGeneratedTopLevelLoops,
nullptr,
15094 assert(LoopHelpers.size() == NumLoops &&
15095 "Expecting a single-dimensional loop iteration space");
15096 assert(OriginalInits.size() == NumLoops &&
15097 "Expecting a single-dimensional loop iteration space");
15098 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15102 LoopHelper.NumIterations, OMPC_full,
false,
15105 Diag(AStmt->
getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
15107 <<
"#pragma omp unroll full";
15115 if (NumGeneratedTopLevelLoops == 0)
15117 NumGeneratedTopLevelLoops,
nullptr,
15163 Stmt *LoopStmt =
nullptr;
15168 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15171 QualType IVTy = IterationVarRef->getType();
15172 assert(LoopHelper.Counters.size() == 1 &&
15173 "Expecting a single-dimensional loop iteration space");
15181 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
15182 FactorLoc = FactorVal->getExprLoc();
15187 assert(Factor > 0 &&
"Expected positive unroll factor");
15188 auto MakeFactorExpr = [
this, Factor, IVTy, FactorLoc]() {
15200 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15201 std::string OuterIVName = (Twine(
".unrolled.iv.") + OrigVarName).str();
15202 std::string InnerIVName = (Twine(
".unroll_inner.iv.") + OrigVarName).str();
15207 auto MakeOuterRef = [
this, OuterIVDecl, IVTy, OrigVarLoc]() {
15213 auto *InnerIVDecl =
cast<VarDecl>(IterationVarRef->getDecl());
15214 InnerIVDecl->setDeclName(&
SemaRef.PP.getIdentifierTable().get(InnerIVName));
15215 auto MakeInnerRef = [
this, InnerIVDecl, IVTy, OrigVarLoc]() {
15221 CaptureVars CopyTransformer(
SemaRef);
15222 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() ->
Expr * {
15224 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15229 SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.
get(),
15244 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15245 MakeOuterRef(), MakeFactorExpr());
15249 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15250 MakeInnerRef(), EndOfTile.
get());
15254 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15255 MakeInnerRef(), MakeNumIterations());
15259 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
15260 InnerCond1.
get(), InnerCond2.
get());
15266 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef());
15272 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15273 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15274 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15275 InnerBodyStmts.push_back(Body);
15279 ForStmt *InnerFor =
new (Context)
15280 ForStmt(Context, InnerInit.
get(), InnerCond.
get(),
nullptr,
15282 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15296 LoopHintAttr *UnrollHintAttr =
15297 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
15298 LoopHintAttr::Numeric, MakeFactorExpr());
15303 SemaRef.AddInitializerToDecl(
15305 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15314 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15315 MakeOuterRef(), MakeNumIterations());
15321 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15322 MakeOuterRef(), MakeFactorExpr());
15327 ForStmt *OuterFor =
new (Context)
15328 ForStmt(Context, OuterInit.
get(), OuterConde.
get(),
nullptr,
15330 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15333 NumGeneratedTopLevelLoops, OuterFor,
15347 constexpr unsigned NumLoops = 1;
15348 Stmt *Body =
nullptr;
15352 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
15353 Body, OriginalInits))
15358 if (
SemaRef.CurContext->isDependentContext())
15360 NumLoops,
nullptr,
nullptr);
15362 assert(LoopHelpers.size() == NumLoops &&
15363 "Expecting a single-dimensional loop iteration space");
15364 assert(OriginalInits.size() == NumLoops &&
15365 "Expecting a single-dimensional loop iteration space");
15366 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15369 Stmt *LoopStmt =
nullptr;
15374 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15377 QualType IVTy = IterationVarRef->getType();
15378 uint64_t IVWidth = Context.getTypeSize(IVTy);
15392 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15394 ForwardIVName += OrigVarName;
15396 ReversedIVName += OrigVarName;
15429 CaptureVars CopyTransformer(
SemaRef);
15430 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() ->
Expr * {
15432 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15438 auto MakeForwardRef = [&
SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
15445 auto *ReversedIVDecl =
cast<VarDecl>(IterationVarRef->getDecl());
15446 ReversedIVDecl->setDeclName(
15447 &
SemaRef.PP.getIdentifierTable().get(ReversedIVName));
15454 ForwardIVDecl->
getType(), OrigVarLoc);
15455 SemaRef.AddInitializerToDecl(ForwardIVDecl,
Zero,
false);
15458 if (!
Init.isUsable())
15466 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15467 MakeForwardRef(), MakeNumIterations());
15468 if (!
Cond.isUsable())
15476 UO_PreInc, MakeForwardRef());
15487 MakeNumIterations(), One);
15490 Minus =
SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, Minus.
get(),
15495 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
15498 SemaRef.AddInitializerToDecl(ReversedIVDecl, Minus.
get(),
15503 BodyStmts.reserve(LoopHelper.Updates.size() + 2 +
15505 BodyStmts.push_back(InitReversed.
get());
15506 llvm::append_range(BodyStmts, LoopHelper.Updates);
15507 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15508 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15509 BodyStmts.push_back(Body);
15510 auto *ReversedBody =
15515 auto *ReversedFor =
new (Context)
15518 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15537 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
15538 size_t NumLoops = PermutationClause ? PermutationClause->
getNumLoops() : 2;
15542 Stmt *Body =
nullptr;
15544 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
15545 LoopHelpers, Body, OriginalInits))
15551 NumLoops, AStmt,
nullptr,
nullptr);
15555 if (PermutationClause &&
15556 llvm::is_contained(PermutationClause->
getArgsRefs(),
nullptr))
15559 assert(LoopHelpers.size() == NumLoops &&
15560 "Expecting loop iteration space dimensionaly to match number of "
15562 assert(OriginalInits.size() == NumLoops &&
15563 "Expecting loop iteration space dimensionaly to match number of "
15568 if (!PermutationClause) {
15569 Permutation = {1, 0};
15572 llvm::BitVector Flags(PermArgs.size());
15573 for (
Expr *PermArg : PermArgs) {
15574 std::optional<llvm::APSInt> PermCstExpr =
15575 PermArg->getIntegerConstantExpr(Context);
15578 uint64_t PermInt = PermCstExpr->getZExtValue();
15579 assert(1 <= PermInt && PermInt <= NumLoops &&
15580 "Must be a permutation; diagnostic emitted in "
15581 "ActOnOpenMPPermutationClause");
15582 if (Flags[PermInt - 1]) {
15583 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
15584 Diag(PermArg->getExprLoc(),
15585 diag::err_omp_interchange_permutation_value_repeated)
15586 << PermInt << ExprRange;
15589 Flags[PermInt - 1] =
true;
15591 Permutation.push_back(PermInt - 1);
15594 if (Permutation.size() != NumLoops)
15599 if (NumLoops <= 1 || llvm::all_of(llvm::enumerate(Permutation), [](
auto P) {
15600 auto [Idx, Arg] = P;
15604 NumLoops, AStmt, AStmt,
nullptr);
15612 for (
auto I : llvm::seq<int>(NumLoops)) {
15613 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15615 assert(LoopHelper.Counters.size() == 1 &&
15616 "Single-dimensional loop iteration space expected");
15623 CaptureVars CopyTransformer(
SemaRef);
15628 Stmt *Inner = Body;
15629 for (
auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
15631 uint64_t SourceIdx = Permutation[TargetIdx];
15632 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
15633 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
15634 assert(SourceHelper.Counters.size() == 1 &&
15635 "Single-dimensional loop iteration space expected");
15642 "Expected the logical iteration counter to be an integer");
15644 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15649 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() ->
Expr * {
15651 CopyTransformer.TransformExpr(SourceHelper.NumIterations));
15658 PermutedCntName.append({llvm::utostr(TargetIdx),
".iv.", OrigVarName});
15660 PermutedCntDecl->setDeclName(
15661 &
SemaRef.PP.getIdentifierTable().get(PermutedCntName));
15662 PermutedIndVars[TargetIdx] = PermutedCntDecl;
15663 auto MakePermutedRef = [
this, PermutedCntDecl, IVTy, OrigVarLoc]() {
15672 if (!
Zero.isUsable())
15674 SemaRef.AddInitializerToDecl(PermutedCntDecl,
Zero.get(),
15678 OrigCntVar->getEndLoc());
15687 SemaRef.BuildBinOp(CurScope, SourceHelper.Cond->getExprLoc(), BO_LT,
15688 MakePermutedRef(), MakeNumIterations());
15697 CurScope, SourceHelper.Inc->getExprLoc(), UO_PreInc, MakePermutedRef());
15702 SourceHelper.Updates.end());
15703 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
15704 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15705 BodyParts.push_back(Inner);
15708 Inner =
new (Context)
ForStmt(
15709 Context, InitStmt.
get(), CondExpr.
get(),
nullptr, IncrStmt.
get(), Inner,
15710 SourceHelper.Init->
getBeginLoc(), SourceHelper.Init->getBeginLoc(),
15711 SourceHelper.Inc->getEndLoc());
15715 NumLoops, AStmt, Inner,
15735 case OMPC_allocator:
15738 case OMPC_collapse:
15744 case OMPC_priority:
15756 case OMPC_novariants:
15759 case OMPC_nocontext:
15774 case OMPC_ompx_dyn_cgroup_mem:
15780 case OMPC_grainsize:
15781 case OMPC_num_tasks:
15782 case OMPC_num_threads:
15786 case OMPC_proc_bind:
15787 case OMPC_schedule:
15789 case OMPC_firstprivate:
15790 case OMPC_lastprivate:
15792 case OMPC_reduction:
15793 case OMPC_task_reduction:
15794 case OMPC_in_reduction:
15798 case OMPC_copyprivate:
15801 case OMPC_mergeable:
15802 case OMPC_threadprivate:
15803 case OMPC_groupprivate:
15805 case OMPC_allocate:
15822 case OMPC_dist_schedule:
15823 case OMPC_defaultmap:
15828 case OMPC_use_device_ptr:
15829 case OMPC_use_device_addr:
15830 case OMPC_is_device_ptr:
15831 case OMPC_unified_address:
15832 case OMPC_unified_shared_memory:
15833 case OMPC_reverse_offload:
15834 case OMPC_dynamic_allocators:
15835 case OMPC_atomic_default_mem_order:
15836 case OMPC_self_maps:
15837 case OMPC_device_type:
15839 case OMPC_nontemporal:
15842 case OMPC_severity:
15844 case OMPC_inclusive:
15845 case OMPC_exclusive:
15846 case OMPC_uses_allocators:
15847 case OMPC_affinity:
15850 case OMPC_num_teams:
15851 case OMPC_thread_limit:
15853 llvm_unreachable(
"Clause is not allowed.");
15866 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
15867 "Invalid directive with CKind-clause");
15870 if (NameModifier != OMPD_unknown &&
15871 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
15872 return OMPD_unknown;
15891 case OMPD_teams_loop:
15892 case OMPD_target_teams_loop:
15896 case OMPD_target_update:
15897 case OMPD_target_enter_data:
15898 case OMPD_target_exit_data:
15904 case OMPC_num_teams:
15905 case OMPC_thread_limit:
15906 case OMPC_ompx_dyn_cgroup_mem:
15907 if (Leafs[0] == OMPD_target)
15908 return OMPD_target;
15911 if (Leafs[0] == OMPD_target ||
15912 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
15913 OMPD_target_enter_data, OMPD_target_exit_data},
15917 case OMPC_novariants:
15918 case OMPC_nocontext:
15919 if (DKind == OMPD_dispatch)
15923 if (DKind == OMPD_metadirective)
15924 return OMPD_metadirective;
15927 return OMPD_unknown;
15940 int InnermostIdx = [&]() {
15941 for (
int I = EndIdx - 1; I >= 0; --I) {
15942 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
15950 for (
int I = InnermostIdx - 1; I >= 0; --I) {
15955 if (Regions[0] != OMPD_unknown)
15956 return Regions.back();
15958 return OMPD_unknown;
15963 for (
int I = 0, E = Leafs.size(); I != E; ++I) {
15964 if (Leafs[I] == Dir)
15970 int End = NameModifier == OMPD_unknown ? Leafs.size()
15971 : GetLeafIndex(NameModifier);
15972 return GetEnclosingRegion(End, CKind);
15975 return OMPD_unknown;
15983 Stmt *HelperValStmt =
nullptr;
15986 !
Condition->isInstantiationDependent() &&
15987 !
Condition->containsUnexpandedParameterPack()) {
15992 ValExpr = Val.
get();
15996 DKind, OMPC_if,
getLangOpts().OpenMP, NameModifier);
15997 if (CaptureRegion != OMPD_unknown &&
15998 !
SemaRef.CurContext->isDependentContext()) {
15999 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
16000 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16001 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16007 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
16008 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
16016 Stmt *HelperValStmt =
nullptr;
16019 !
Condition->isInstantiationDependent() &&
16020 !
Condition->containsUnexpandedParameterPack()) {
16025 ValExpr =
SemaRef.MakeFullExpr(Val.
get()).get();
16030 if (CaptureRegion != OMPD_unknown &&
16031 !
SemaRef.CurContext->isDependentContext()) {
16032 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
16033 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16034 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16040 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16051 IntConvertDiagnoser()
16052 : ICEConvertDiagnoser(
false,
false,
true) {}
16055 return S.
Diag(Loc, diag::err_omp_not_integral) <<
T;
16059 return S.
Diag(Loc, diag::err_omp_incomplete_type) <<
T;
16064 return S.
Diag(Loc, diag::err_omp_explicit_conversion) <<
T << ConvTy;
16073 return S.
Diag(Loc, diag::err_omp_ambiguous_conversion) <<
T;
16082 llvm_unreachable(
"conversion functions are permitted");
16084 } ConvertDiagnoser;
16085 return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
16090 bool StrictlyPositive,
bool BuildCapture =
false,
16093 Stmt **HelperValStmt =
nullptr) {
16099 if (
Value.isInvalid())
16102 ValExpr =
Value.get();
16104 if (std::optional<llvm::APSInt> Result =
16106 if (Result->isSigned() &&
16107 !((!StrictlyPositive && Result->isNonNegative()) ||
16108 (StrictlyPositive && Result->isStrictlyPositive()))) {
16109 SemaRef.
Diag(Loc, diag::err_omp_negative_expression_in_clause)
16119 if (*CaptureRegion != OMPD_unknown &&
16122 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16123 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16134 llvm::raw_svector_ostream
Out(Buffer);
16135 unsigned Skipped = Exclude.size();
16136 for (
unsigned I =
First; I <
Last; ++I) {
16137 if (llvm::is_contained(Exclude, I)) {
16142 if (I + Skipped + 2 ==
Last)
16144 else if (I + Skipped + 1 !=
Last)
16147 return std::string(
Out.str());
16155 "Unexpected num_threads modifier in OpenMP < 60.");
16160 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
16165 Expr *ValExpr = NumThreads;
16166 Stmt *HelperValStmt =
nullptr;
16177 if (CaptureRegion != OMPD_unknown &&
16178 !
SemaRef.CurContext->isDependentContext()) {
16179 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
16180 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16181 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16187 StartLoc, LParenLoc, ModifierLoc, EndLoc);
16192 bool SuppressExprDiags) {
16201 if (SuppressExprDiags) {
16205 SuppressedDiagnoser() : VerifyICEDiagnoser(
true) {}
16208 llvm_unreachable(
"Diagnostic suppressed");
16211 ICE =
SemaRef.VerifyIntegerConstantExpression(E, &
Result, Diagnoser,
16221 if ((StrictlyPositive && !
Result.isStrictlyPositive()) ||
16222 (!StrictlyPositive && !
Result.isNonNegative())) {
16223 Diag(E->
getExprLoc(), diag::err_omp_negative_expression_in_clause)
16228 if ((CKind == OMPC_aligned || CKind == OMPC_align ||
16229 CKind == OMPC_allocate) &&
16231 Diag(E->
getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
16236 if (!
Result.isRepresentableByInt64()) {
16242 if (CKind == OMPC_collapse &&
DSAStack->getAssociatedLoops() == 1)
16244 else if (CKind == OMPC_ordered)
16263 if (
Result.isNonNegative()) {
16267 diag::err_omp_negative_expression_in_clause)
16270 }
else if (
auto *DeclRef = dyn_cast<DeclRefExpr>(DeviceNumExpr)) {
16277 Diag(DeviceNumExpr->
getExprLoc(), diag::err_expected_expression);
16311 DSAStackTy *Stack) {
16312 if (!Stack->getOMPAllocatorHandleT().isNull())
16319 S.
Diag(Loc, diag::err_omp_implied_type_not_found)
16320 <<
"omp_allocator_handle_t";
16325 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
16328 bool ErrorFound =
false;
16329 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
16330 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
16331 StringRef Allocator =
16332 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
16334 auto *VD = dyn_cast_or_null<ValueDecl>(
16354 Stack->setAllocator(AllocatorKind, Res.
get());
16357 S.
Diag(Loc, diag::err_omp_implied_type_not_found)
16358 <<
"omp_allocator_handle_t";
16377 Allocator =
SemaRef.PerformImplicitConversion(
16378 Allocator.
get(),
DSAStack->getOMPAllocatorHandleT(),
16407 Expr *NumForLoops) {
16413 if (NumForLoops && LParenLoc.
isValid()) {
16418 NumForLoops = NumForLoopsResult.
get();
16420 NumForLoops =
nullptr;
16424 NumForLoops ?
DSAStack->getAssociatedLoops() : 0,
16425 StartLoc, LParenLoc, EndLoc);
16426 DSAStack->setOrderedRegion(
true, NumForLoops, Clause);
16435 case OMPC_proc_bind:
16437 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16439 case OMPC_atomic_default_mem_order:
16442 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16446 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16450 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16454 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16458 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16460 case OMPC_severity:
16463 LParenLoc, EndLoc);
16467 case OMPC_num_threads:
16471 case OMPC_allocator:
16472 case OMPC_collapse:
16473 case OMPC_schedule:
16475 case OMPC_firstprivate:
16476 case OMPC_lastprivate:
16478 case OMPC_reduction:
16479 case OMPC_task_reduction:
16480 case OMPC_in_reduction:
16484 case OMPC_copyprivate:
16488 case OMPC_mergeable:
16489 case OMPC_threadprivate:
16490 case OMPC_groupprivate:
16491 case OMPC_allocate:
16508 case OMPC_num_teams:
16509 case OMPC_thread_limit:
16510 case OMPC_priority:
16511 case OMPC_grainsize:
16513 case OMPC_num_tasks:
16515 case OMPC_dist_schedule:
16517 case OMPC_defaultmap:
16522 case OMPC_use_device_ptr:
16523 case OMPC_use_device_addr:
16524 case OMPC_is_device_ptr:
16525 case OMPC_has_device_addr:
16526 case OMPC_unified_address:
16527 case OMPC_unified_shared_memory:
16528 case OMPC_reverse_offload:
16529 case OMPC_dynamic_allocators:
16530 case OMPC_self_maps:
16531 case OMPC_device_type:
16533 case OMPC_nontemporal:
16535 case OMPC_novariants:
16536 case OMPC_nocontext:
16538 case OMPC_inclusive:
16539 case OMPC_exclusive:
16540 case OMPC_uses_allocators:
16541 case OMPC_affinity:
16545 llvm_unreachable(
"Clause is not allowed.");
16554 if (M == OMP_DEFAULT_unknown) {
16555 Diag(MLoc, diag::err_omp_unexpected_clause_value)
16557 unsigned(OMP_DEFAULT_unknown))
16563 case OMP_DEFAULT_none:
16564 DSAStack->setDefaultDSANone(MLoc);
16566 case OMP_DEFAULT_shared:
16567 DSAStack->setDefaultDSAShared(MLoc);
16569 case OMP_DEFAULT_firstprivate:
16570 DSAStack->setDefaultDSAFirstPrivate(MLoc);
16572 case OMP_DEFAULT_private:
16573 DSAStack->setDefaultDSAPrivate(MLoc);
16576 llvm_unreachable(
"DSA unexpected in OpenMP default clause");
16580 case OMPC_DEFAULT_VC_aggregate:
16581 DSAStack->setDefaultDSAVCAggregate(VCKindLoc);
16583 case OMPC_DEFAULT_VC_all:
16584 DSAStack->setDefaultDSAVCAll(VCKindLoc);
16586 case OMPC_DEFAULT_VC_allocatable:
16587 DSAStack->setDefaultDSAVCAllocatable(VCKindLoc);
16589 case OMPC_DEFAULT_VC_pointer:
16590 DSAStack->setDefaultDSAVCPointer(VCKindLoc);
16592 case OMPC_DEFAULT_VC_scalar:
16593 DSAStack->setDefaultDSAVCScalar(VCKindLoc);
16596 Diag(VCKindLoc, diag::err_omp_default_vc)
16601 OMPDefaultClause(M, MLoc, VCKind, VCKindLoc, StartLoc, LParenLoc, EndLoc);
16609 if (Kind == OMP_PROC_BIND_unknown) {
16610 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16612 unsigned(OMP_PROC_BIND_master),
16615 ? OMP_PROC_BIND_primary
16616 : OMP_PROC_BIND_spread) +
16621 if (Kind == OMP_PROC_BIND_primary &&
getLangOpts().OpenMP < 51)
16622 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16624 unsigned(OMP_PROC_BIND_master),
16626 unsigned(OMP_PROC_BIND_spread) + 1)
16636 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16638 OMPC_atomic_default_mem_order, 0,
16644 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16653 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16660 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16669 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16683 assert(ME &&
"NULL expr in Message clause");
16692 Stmt *HelperValStmt =
nullptr;
16698 DKind == OMPD_unknown ? OMPD_unknown
16701 if (CaptureRegion != OMPD_unknown &&
16702 !
SemaRef.CurContext->isDependentContext()) {
16703 ME =
SemaRef.MakeFullExpr(ME).get();
16704 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16705 ME = tryBuildCapture(
SemaRef, ME, Captures).get();
16710 ME =
SemaRef.DefaultFunctionArrayLvalueConversion(ME).get();
16713 ME, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16720 if (Kind != OMPC_ORDER_concurrent ||
16725 "OMPC_ORDER_unknown not greater than 0");
16727 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16736 Diag(MLoc, diag::err_omp_unexpected_clause_value)
16742 DSAStack->setRegionHasOrderConcurrent(
true);
16745 unsigned existingFlags =
DSAStack->getCurScope()->getFlags();
16746 DSAStack->getCurScope()->setFlags(existingFlags |
16751 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
16760 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
16762 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
16763 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
16765 Except.push_back(OMPC_DEPEND_inoutset);
16766 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16773 KindKwLoc, Kind, EndLoc);
16782 for (
Expr *&SizeExpr : SanitizedSizeExprs) {
16792 QualType SizeTy = SizeExpr->getType();
16821 if (!SizeExpr->isInstantiationDependent() && !IsValid)
16822 SizeExpr =
nullptr;
16826 SanitizedSizeExprs);
16833 size_t NumLoops = PermExprs.size();
16835 llvm::append_range(SanitizedPermExprs, PermExprs);
16837 for (
Expr *&PermExpr : SanitizedPermExprs) {
16840 if (!PermExpr || PermExpr->isInstantiationDependent())
16843 llvm::APSInt PermVal;
16846 bool IsValid = PermEvalExpr.
isUsable();
16848 PermExpr = PermEvalExpr.
get();
16850 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
16854 diag::err_omp_interchange_permutation_value_range)
16855 << NumLoops << ExprRange;
16859 if (!PermExpr->isInstantiationDependent() && !IsValid)
16860 PermExpr =
nullptr;
16864 EndLoc, SanitizedPermExprs);
16880 FactorExpr, OMPC_partial,
true);
16883 FactorExpr = FactorResult.
get();
16898 LParenLoc, EndLoc);
16908 case OMPC_schedule:
16909 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
16910 assert(Argument.size() == NumberOfElements &&
16911 ArgumentLoc.size() == NumberOfElements);
16916 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
16917 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
16920 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16922 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
16925 case OMPC_dist_schedule:
16928 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
16931 enum { DefaultModifier, DefaultVarCategory };
16933 static_cast<llvm::omp::DefaultKind
>(Argument[DefaultModifier]),
16934 ArgumentLoc[DefaultModifier],
16936 Argument[DefaultVarCategory]),
16937 ArgumentLoc[DefaultVarCategory], StartLoc, LParenLoc, EndLoc);
16939 case OMPC_defaultmap:
16940 enum { Modifier, DefaultmapKind };
16944 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
16948 enum { OrderModifier, OrderKind };
16952 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
16955 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16958 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16960 case OMPC_grainsize:
16961 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16962 "Modifier for grainsize clause and its location are expected.");
16965 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16967 case OMPC_num_tasks:
16968 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16969 "Modifier for num_tasks clause and its location are expected.");
16972 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16974 case OMPC_num_threads:
16975 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16976 "Modifier for num_threads clause and its location are expected.");
16979 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16985 case OMPC_allocator:
16986 case OMPC_collapse:
16987 case OMPC_proc_bind:
16989 case OMPC_firstprivate:
16990 case OMPC_lastprivate:
16992 case OMPC_reduction:
16993 case OMPC_task_reduction:
16994 case OMPC_in_reduction:
16998 case OMPC_copyprivate:
17002 case OMPC_mergeable:
17003 case OMPC_threadprivate:
17004 case OMPC_groupprivate:
17005 case OMPC_allocate:
17022 case OMPC_num_teams:
17023 case OMPC_thread_limit:
17024 case OMPC_priority:
17031 case OMPC_use_device_ptr:
17032 case OMPC_use_device_addr:
17033 case OMPC_is_device_ptr:
17034 case OMPC_has_device_addr:
17035 case OMPC_unified_address:
17036 case OMPC_unified_shared_memory:
17037 case OMPC_reverse_offload:
17038 case OMPC_dynamic_allocators:
17039 case OMPC_atomic_default_mem_order:
17040 case OMPC_self_maps:
17041 case OMPC_device_type:
17043 case OMPC_nontemporal:
17045 case OMPC_severity:
17048 case OMPC_novariants:
17049 case OMPC_nocontext:
17051 case OMPC_inclusive:
17052 case OMPC_exclusive:
17053 case OMPC_uses_allocators:
17054 case OMPC_affinity:
17058 llvm_unreachable(
"Clause is not allowed.");
17069 Excluded.push_back(M2);
17070 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
17071 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
17072 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
17073 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
17074 S.
Diag(M1Loc, diag::err_omp_unexpected_clause_value)
17097 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
17098 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
17099 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
17100 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
17101 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
17107 std::string Values;
17117 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17126 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
17127 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
17128 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
17129 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
17130 diag::err_omp_schedule_nonmonotonic_static);
17133 Expr *ValExpr = ChunkSize;
17134 Stmt *HelperValStmt =
nullptr;
17145 ValExpr = Val.
get();
17150 if (std::optional<llvm::APSInt>
Result =
17152 if (
Result->isSigned() && !
Result->isStrictlyPositive()) {
17153 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
17158 DSAStack->getCurrentDirective(), OMPC_schedule,
17160 !
SemaRef.CurContext->isDependentContext()) {
17161 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
17162 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17163 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
17171 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
17188 case OMPC_mergeable:
17236 case OMPC_unified_address:
17239 case OMPC_unified_shared_memory:
17242 case OMPC_reverse_offload:
17245 case OMPC_dynamic_allocators:
17248 case OMPC_self_maps:
17262 case OMPC_ompx_bare:
17267 case OMPC_num_threads:
17271 case OMPC_allocator:
17272 case OMPC_collapse:
17273 case OMPC_schedule:
17275 case OMPC_firstprivate:
17276 case OMPC_lastprivate:
17278 case OMPC_reduction:
17279 case OMPC_task_reduction:
17280 case OMPC_in_reduction:
17284 case OMPC_copyprivate:
17286 case OMPC_proc_bind:
17287 case OMPC_threadprivate:
17288 case OMPC_groupprivate:
17289 case OMPC_allocate:
17295 case OMPC_num_teams:
17296 case OMPC_thread_limit:
17297 case OMPC_priority:
17298 case OMPC_grainsize:
17299 case OMPC_num_tasks:
17301 case OMPC_dist_schedule:
17302 case OMPC_defaultmap:
17307 case OMPC_use_device_ptr:
17308 case OMPC_use_device_addr:
17309 case OMPC_is_device_ptr:
17310 case OMPC_has_device_addr:
17311 case OMPC_atomic_default_mem_order:
17312 case OMPC_device_type:
17314 case OMPC_nontemporal:
17317 case OMPC_severity:
17319 case OMPC_novariants:
17320 case OMPC_nocontext:
17322 case OMPC_inclusive:
17323 case OMPC_exclusive:
17324 case OMPC_uses_allocators:
17325 case OMPC_affinity:
17327 case OMPC_ompx_dyn_cgroup_mem:
17329 llvm_unreachable(
"Clause is not allowed.");
17388 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
17474 if (!
hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
17476 StringRef
Expected =
"'init', 'use', 'destroy', or 'nowait'";
17477 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
17478 <<
Expected << getOpenMPDirectiveName(OMPD_interop, OMPVersion);
17491 bool HasInitClause =
false;
17492 bool IsTargetSync =
false;
17496 if (
const auto *InitClause = dyn_cast<OMPInitClause>(
C)) {
17497 HasInitClause =
true;
17498 if (InitClause->getIsTargetSync())
17499 IsTargetSync =
true;
17500 }
else if (
const auto *DC = dyn_cast<OMPDependClause>(
C)) {
17504 if (DependClause && HasInitClause && !IsTargetSync) {
17505 Diag(DependClause->
getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
17519 if (ClauseKind == OMPC_init) {
17522 }
else if (ClauseKind == OMPC_use) {
17525 }
else if (ClauseKind == OMPC_destroy) {
17531 if (!InteropVars.insert(
DeclResult.first).second) {
17532 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
17548 Expr *RefExpr = InteropVarExpr;
17563 bool HasError =
false;
17569 if (
const auto *TD = dyn_cast<TypeDecl>(ND)) {
17570 InteropType =
QualType(TD->getTypeForDecl(), 0);
17579 SemaRef.
Diag(VarLoc, diag::err_omp_implied_type_not_found)
17580 <<
"omp_interop_t";
17586 SemaRef.
Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
17592 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
17594 SemaRef.
Diag(VarLoc, diag::err_omp_interop_variable_expected)
17623 StartLoc, LParenLoc, VarLoc, EndLoc);
17636 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
17645 DSAStack->getCurrentDirective() == OMPD_depobj) {
17647 Diag(StartLoc, diag::err_omp_expected_clause_argument)
17649 << getOpenMPDirectiveName(OMPD_depobj, OMPVersion);
17665 Stmt *HelperValStmt =
nullptr;
17668 !
Condition->isInstantiationDependent() &&
17669 !
Condition->containsUnexpandedParameterPack()) {
17674 ValExpr =
SemaRef.MakeFullExpr(Val.
get()).get();
17679 if (CaptureRegion != OMPD_unknown &&
17680 !
SemaRef.CurContext->isDependentContext()) {
17681 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
17682 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17683 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
17689 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17697 Stmt *HelperValStmt =
nullptr;
17700 !
Condition->isInstantiationDependent() &&
17701 !
Condition->containsUnexpandedParameterPack()) {
17706 ValExpr =
SemaRef.MakeFullExpr(Val.
get()).get();
17711 if (CaptureRegion != OMPD_unknown &&
17712 !
SemaRef.CurContext->isDependentContext()) {
17713 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
17714 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17715 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
17721 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17728 Expr *ValExpr = ThreadID;
17729 Stmt *HelperValStmt =
nullptr;
17734 if (CaptureRegion != OMPD_unknown &&
17735 !
SemaRef.CurContext->isDependentContext()) {
17736 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
17737 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17738 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
17743 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17754 int ExtraModifier =
Data.ExtraModifier;
17755 int OriginalSharingModifier =
Data.OriginalSharingModifier;
17762 case OMPC_firstprivate:
17765 case OMPC_lastprivate:
17767 "Unexpected lastprivate modifier.");
17770 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
17775 case OMPC_reduction:
17777 "Unexpected lastprivate modifier.");
17781 ExtraModifier, OriginalSharingModifier),
17782 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
17783 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
17785 case OMPC_task_reduction:
17787 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17788 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
17790 case OMPC_in_reduction:
17792 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17793 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
17797 "Unexpected linear modifier.");
17799 VarList,
Data.DepModOrTailExpr, StartLoc, LParenLoc,
17801 ColonLoc,
Data.StepModifierLoc, EndLoc);
17805 LParenLoc, ColonLoc, EndLoc);
17810 case OMPC_copyprivate:
17818 "Unexpected depend modifier.");
17821 ColonLoc,
Data.OmpAllMemoryLoc},
17822 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
17826 "Unexpected map modifier.");
17828 Data.IteratorExpr,
Data.MapTypeModifiers,
Data.MapTypeModifiersLoc,
17829 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId,
17831 ExtraModifierLoc, ColonLoc, VarList, Locs);
17836 Data.ReductionOrMapperIdScopeSpec,
17837 Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
17841 Data.ReductionOrMapperIdScopeSpec,
17842 Data.ReductionOrMapperId, ColonLoc, VarList,
17845 case OMPC_use_device_ptr:
17848 case OMPC_use_device_addr:
17851 case OMPC_is_device_ptr:
17854 case OMPC_has_device_addr:
17857 case OMPC_allocate: {
17861 if (!
Data.AllocClauseModifiers.empty()) {
17862 assert(
Data.AllocClauseModifiers.size() <= 2 &&
17863 "More allocate modifiers than expected");
17864 Modifier1 =
Data.AllocClauseModifiers[0];
17865 Modifier1Loc =
Data.AllocClauseModifiersLoc[0];
17866 if (
Data.AllocClauseModifiers.size() == 2) {
17867 Modifier2 =
Data.AllocClauseModifiers[1];
17868 Modifier2Loc =
Data.AllocClauseModifiersLoc[1];
17872 Data.DepModOrTailExpr,
Data.AllocateAlignment, Modifier1, Modifier1Loc,
17873 Modifier2, Modifier2Loc, VarList, StartLoc, LParenLoc, ColonLoc,
17877 case OMPC_nontemporal:
17880 case OMPC_inclusive:
17883 case OMPC_exclusive:
17886 case OMPC_affinity:
17888 Data.DepModOrTailExpr, VarList);
17890 case OMPC_doacross:
17893 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
17895 case OMPC_num_teams:
17898 case OMPC_thread_limit:
17904 case OMPC_num_threads:
17908 case OMPC_allocator:
17909 case OMPC_collapse:
17911 case OMPC_proc_bind:
17912 case OMPC_schedule:
17916 case OMPC_mergeable:
17917 case OMPC_threadprivate:
17918 case OMPC_groupprivate:
17932 case OMPC_priority:
17933 case OMPC_grainsize:
17935 case OMPC_num_tasks:
17937 case OMPC_dist_schedule:
17938 case OMPC_defaultmap:
17941 case OMPC_unified_address:
17942 case OMPC_unified_shared_memory:
17943 case OMPC_reverse_offload:
17944 case OMPC_dynamic_allocators:
17945 case OMPC_atomic_default_mem_order:
17946 case OMPC_self_maps:
17947 case OMPC_device_type:
17951 case OMPC_severity:
17954 case OMPC_novariants:
17955 case OMPC_nocontext:
17957 case OMPC_uses_allocators:
17961 llvm_unreachable(
"Clause is not allowed.");
17974 Res =
SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.
get());
17979 Res =
SemaRef.DefaultLvalueConversion(Res.
get());
17993 bool IsImplicitClause =
17995 for (
Expr *RefExpr : VarList) {
17996 assert(RefExpr &&
"NULL expr in OpenMP private clause.");
17999 Expr *SimpleRefExpr = RefExpr;
18003 Vars.push_back(RefExpr);
18004 PrivateCopies.push_back(
nullptr);
18011 auto *VD = dyn_cast<VarDecl>(D);
18017 diag::err_omp_private_incomplete_type))
18019 Type =
Type.getNonReferenceType();
18039 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
18040 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
18041 Diag(ELoc, diag::err_omp_wrong_dsa)
18052 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18054 << getOpenMPDirectiveName(CurrDir, OMPVersion);
18055 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
18058 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18073 CurrDir == OMPD_target) {
18075 if (
DSAStack->checkMappableExprComponentListsForDecl(
18079 ConflictKind = WhereFoundClauseKind;
18082 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18085 << getOpenMPDirectiveName(CurrDir, OMPVersion);
18105 SemaRef.ActOnUninitializedDecl(VDPrivate);
18112 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
18113 auto *FD = dyn_cast<FieldDecl>(D);
18117 RefExpr->getExprLoc());
18121 if (!IsImplicitClause)
18122 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
18123 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
18124 ? RefExpr->IgnoreParens()
18126 PrivateCopies.push_back(VDPrivateRefExpr);
18133 Vars, PrivateCopies);
18144 bool IsImplicitClause =
18149 for (
Expr *RefExpr : VarList) {
18150 assert(RefExpr &&
"NULL expr in OpenMP firstprivate clause.");
18153 Expr *SimpleRefExpr = RefExpr;
18157 Vars.push_back(RefExpr);
18158 PrivateCopies.push_back(
nullptr);
18159 Inits.push_back(
nullptr);
18165 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
18167 auto *VD = dyn_cast<VarDecl>(D);
18173 diag::err_omp_firstprivate_incomplete_type))
18175 Type =
Type.getNonReferenceType();
18185 DSAStackTy::DSAVarData TopDVar;
18186 if (!IsImplicitClause) {
18187 DSAStackTy::DSAVarData DVar =
18199 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
18201 DVar.CKind != OMPC_lastprivate) &&
18203 Diag(ELoc, diag::err_omp_wrong_dsa)
18221 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
18222 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
18223 Diag(ELoc, diag::err_omp_wrong_dsa)
18249 DVar =
DSAStack->getImplicitDSA(D,
true);
18250 if (DVar.CKind != OMPC_shared &&
18253 DVar.DKind == OMPD_unknown)) {
18254 Diag(ELoc, diag::err_omp_required_access)
18276 return C == OMPC_reduction && !AppliedToPointee;
18284 if (DVar.CKind == OMPC_reduction &&
18288 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
18289 << getOpenMPDirectiveName(DVar.DKind, OMPVersion);
18305 CurrDir == OMPD_target) {
18307 if (
DSAStack->checkMappableExprComponentListsForDecl(
18312 ConflictKind = WhereFoundClauseKind;
18315 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18318 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
18329 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18331 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
18333 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
18336 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18351 Expr *VDInitRefExpr =
nullptr;
18361 ElemType,
".firstprivate.temp");
18376 ".firstprivate.temp");
18378 RefExpr->getExprLoc());
18379 SemaRef.AddInitializerToDecl(
18380 VDPrivate,
SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
18384 if (IsImplicitClause) {
18385 Diag(RefExpr->getExprLoc(),
18386 diag::note_omp_task_predetermined_firstprivate_here);
18390 SemaRef.CurContext->addDecl(VDPrivate);
18393 RefExpr->getExprLoc());
18395 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
18396 if (TopDVar.CKind == OMPC_lastprivate) {
18397 Ref = TopDVar.PrivateCopy;
18399 auto *FD = dyn_cast<FieldDecl>(D);
18404 RefExpr->getExprLoc());
18408 ExprCaptures.push_back(Ref->
getDecl());
18411 if (!IsImplicitClause)
18412 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
18413 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
18414 ? RefExpr->IgnoreParens()
18416 PrivateCopies.push_back(VDPrivateRefExpr);
18417 Inits.push_back(VDInitRefExpr);
18424 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
18433 assert(ColonLoc.
isValid() &&
"Colon location must be valid.");
18434 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
18447 for (
Expr *RefExpr : VarList) {
18448 assert(RefExpr &&
"NULL expr in OpenMP lastprivate clause.");
18451 Expr *SimpleRefExpr = RefExpr;
18455 Vars.push_back(RefExpr);
18456 SrcExprs.push_back(
nullptr);
18457 DstExprs.push_back(
nullptr);
18458 AssignmentOps.push_back(
nullptr);
18465 auto *VD = dyn_cast<VarDecl>(D);
18471 diag::err_omp_lastprivate_incomplete_type))
18473 Type =
Type.getNonReferenceType();
18490 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
18491 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
18494 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18508 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
18509 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
18511 DVar.CKind != OMPC_firstprivate) &&
18512 (DVar.CKind != OMPC_private || DVar.RefExpr !=
nullptr)) {
18513 Diag(ELoc, diag::err_omp_wrong_dsa)
18526 DSAStackTy::DSAVarData TopDVar = DVar;
18530 DVar =
DSAStack->getImplicitDSA(D,
true);
18531 if (DVar.CKind != OMPC_shared) {
18532 Diag(ELoc, diag::err_omp_required_access)
18550 Type.getUnqualifiedType(),
".lastprivate.src",
18561 PseudoDstExpr, PseudoSrcExpr);
18564 AssignmentOp =
SemaRef.ActOnFinishFullExpr(AssignmentOp.
get(), ELoc,
18570 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
18571 if (TopDVar.CKind == OMPC_firstprivate) {
18572 Ref = TopDVar.PrivateCopy;
18576 ExprCaptures.push_back(Ref->
getDecl());
18578 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
18586 SimpleRefExpr, RefRes.
get());
18589 ExprPostUpdates.push_back(
18590 SemaRef.IgnoredValueConversions(PostUpdateRes.
get()).get());
18593 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
18594 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
18595 ? RefExpr->IgnoreParens()
18597 SrcExprs.push_back(PseudoSrcExpr);
18598 DstExprs.push_back(PseudoDstExpr);
18599 AssignmentOps.push_back(AssignmentOp.
get());
18606 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
18607 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
18617 for (
Expr *RefExpr : VarList) {
18618 assert(RefExpr &&
"NULL expr in OpenMP shared clause.");
18621 Expr *SimpleRefExpr = RefExpr;
18625 Vars.push_back(RefExpr);
18631 auto *VD = dyn_cast<VarDecl>(D);
18639 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
18640 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
18642 Diag(ELoc, diag::err_omp_wrong_dsa)
18651 !
SemaRef.CurContext->isDependentContext())
18653 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
18654 Vars.push_back((VD || !Ref ||
SemaRef.CurContext->isDependentContext())
18655 ? RefExpr->IgnoreParens()
18667class DSARefChecker :
public StmtVisitor<DSARefChecker, bool> {
18672 if (
auto *VD = dyn_cast<VarDecl>(E->
getDecl())) {
18673 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD,
false);
18674 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
18676 if (DVar.CKind != OMPC_unknown)
18678 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
18685 return DVarPrivate.CKind != OMPC_unknown;
18689 bool VisitStmt(Stmt *S) {
18690 for (Stmt *Child : S->
children()) {
18691 if (Child && Visit(Child))
18696 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
18703class TransformExprToCaptures :
public TreeTransform<TransformExprToCaptures> {
18704 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
18705 ValueDecl *
Field =
nullptr;
18706 DeclRefExpr *CapturedExpr =
nullptr;
18709 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
18710 : BaseTransform(SemaRef),
Field(FieldDecl), CapturedExpr(
nullptr) {}
18712 ExprResult TransformMemberExpr(MemberExpr *E) {
18715 CapturedExpr =
buildCapture(SemaRef, Field, E,
false);
18716 return CapturedExpr;
18718 return BaseTransform::TransformMemberExpr(E);
18720 DeclRefExpr *getCapturedExpr() {
return CapturedExpr; }
18724template <
typename T,
typename U>
18727 for (
U &
Set : Lookups) {
18728 for (
auto *D :
Set) {
18739 for (
auto *RD : D->
redecls()) {
18762 AssociatedClasses);
18775 for (
auto *NS : AssociatedNamespaces) {
18788 for (
auto *D : R) {
18789 auto *Underlying = D;
18790 if (
auto *USD = dyn_cast<UsingShadowDecl>(D))
18791 Underlying = USD->getTargetDecl();
18801 if (
auto *USD = dyn_cast<UsingShadowDecl>(D))
18802 Underlying = USD->getTargetDecl();
18804 Lookups.emplace_back();
18805 Lookups.back().addDecl(Underlying);
18829 Lookups.emplace_back();
18830 Lookups.back().append(Lookup.
begin(), Lookup.
end());
18833 }
else if (
auto *ULE =
18834 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
18836 Decl *PrevD =
nullptr;
18840 else if (
auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
18841 Lookups.back().addDecl(DRD);
18849 return !D->isInvalidDecl() &&
18850 (D->getType()->isDependentType() ||
18851 D->getType()->isInstantiationDependentType() ||
18852 D->getType()->containsUnexpandedParameterPack());
18865 true, ResSet.
begin(), ResSet.
end(),
false,
18888 if (IsComplete || RD->isBeingDefined()) {
18891 if (Lookup.
empty()) {
18892 Lookups.emplace_back();
18893 Lookups.back().append(Lookup.
begin(), Lookup.
end());
18935 if (ReductionIdScopeSpec.
isSet()) {
18936 SemaRef.
Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
18945struct ReductionData {
18947 SmallVector<Expr *, 8> Vars;
18949 SmallVector<Expr *, 8> Privates;
18951 SmallVector<Expr *, 8> LHSs;
18953 SmallVector<Expr *, 8> RHSs;
18955 SmallVector<Expr *, 8> ReductionOps;
18957 SmallVector<Expr *, 8> InscanCopyOps;
18959 SmallVector<Expr *, 8> InscanCopyArrayTemps;
18961 SmallVector<Expr *, 8> InscanCopyArrayElems;
18964 SmallVector<Expr *, 8> TaskgroupDescriptors;
18966 SmallVector<Decl *, 4> ExprCaptures;
18968 SmallVector<Expr *, 4> ExprPostUpdates;
18970 unsigned RedModifier = 0;
18972 unsigned OrigSharingModifier = 0;
18974 SmallVector<bool, 8> IsPrivateVarReduction;
18975 ReductionData() =
delete;
18977 ReductionData(
unsigned Size,
unsigned Modifier = 0,
unsigned OrgModifier = 0)
18978 : RedModifier(Modifier), OrigSharingModifier(OrgModifier) {
18979 Vars.reserve(Size);
18980 Privates.reserve(Size);
18981 LHSs.reserve(Size);
18982 RHSs.reserve(Size);
18983 ReductionOps.reserve(Size);
18984 IsPrivateVarReduction.reserve(Size);
18985 if (RedModifier == OMPC_REDUCTION_inscan) {
18986 InscanCopyOps.reserve(Size);
18987 InscanCopyArrayTemps.reserve(Size);
18988 InscanCopyArrayElems.reserve(Size);
18990 TaskgroupDescriptors.reserve(Size);
18991 ExprCaptures.reserve(Size);
18992 ExprPostUpdates.reserve(Size);
18996 void push(Expr *Item, Expr *ReductionOp) {
18997 Vars.emplace_back(Item);
18998 Privates.emplace_back(
nullptr);
18999 LHSs.emplace_back(
nullptr);
19000 RHSs.emplace_back(
nullptr);
19001 ReductionOps.emplace_back(ReductionOp);
19002 IsPrivateVarReduction.emplace_back(
false);
19003 TaskgroupDescriptors.emplace_back(
nullptr);
19004 if (RedModifier == OMPC_REDUCTION_inscan) {
19005 InscanCopyOps.push_back(
nullptr);
19006 InscanCopyArrayTemps.push_back(
nullptr);
19007 InscanCopyArrayElems.push_back(
nullptr);
19011 void push(Expr *Item, Expr *
Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
19012 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
19013 Expr *CopyArrayElem,
bool IsPrivate) {
19014 Vars.emplace_back(Item);
19015 Privates.emplace_back(
Private);
19016 LHSs.emplace_back(LHS);
19017 RHSs.emplace_back(RHS);
19018 ReductionOps.emplace_back(ReductionOp);
19019 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
19020 if (RedModifier == OMPC_REDUCTION_inscan) {
19021 InscanCopyOps.push_back(CopyOp);
19022 InscanCopyArrayTemps.push_back(CopyArrayTemp);
19023 InscanCopyArrayElems.push_back(CopyArrayElem);
19025 assert(CopyOp ==
nullptr && CopyArrayTemp ==
nullptr &&
19026 CopyArrayElem ==
nullptr &&
19027 "Copy operation must be used for inscan reductions only.");
19029 IsPrivateVarReduction.emplace_back(IsPrivate);
19038 if (Length ==
nullptr) {
19045 SingleElement =
true;
19046 ArraySizes.push_back(llvm::APSInt::get(1));
19049 if (!Length->EvaluateAsInt(Result, Context))
19052 llvm::APSInt ConstantLengthValue = Result.
Val.
getInt();
19053 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
19054 ArraySizes.push_back(ConstantLengthValue);
19062 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base)) {
19063 Length = TempOASE->getLength();
19064 if (Length ==
nullptr) {
19071 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
19072 ArraySizes.push_back(ConstantOne);
19075 if (!Length->EvaluateAsInt(Result, Context))
19078 llvm::APSInt ConstantLengthValue = Result.
Val.
getInt();
19079 if (ConstantLengthValue.getSExtValue() != 1)
19082 ArraySizes.push_back(ConstantLengthValue);
19084 Base = TempOASE->getBase()->IgnoreParenImpCasts();
19088 if (!SingleElement) {
19089 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base)) {
19091 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
19092 ArraySizes.push_back(ConstantOne);
19093 Base = TempASE->getBase()->IgnoreParenImpCasts();
19105 return BO_AddAssign;
19107 return BO_MulAssign;
19109 return BO_AndAssign;
19111 return BO_OrAssign;
19113 return BO_XorAssign;
19169 case OO_Array_Delete:
19178 case OO_GreaterEqual:
19180 case OO_MinusEqual:
19182 case OO_SlashEqual:
19183 case OO_PercentEqual:
19184 case OO_CaretEqual:
19188 case OO_GreaterGreater:
19189 case OO_LessLessEqual:
19190 case OO_GreaterGreaterEqual:
19191 case OO_EqualEqual:
19192 case OO_ExclaimEqual:
19195 case OO_MinusMinus:
19201 case OO_Conditional:
19204 llvm_unreachable(
"Unexpected reduction identifier");
19207 if (II->isStr(
"max"))
19209 else if (II->isStr(
"min"))
19217 if (OOK == OO_Minus && S.
LangOpts.OpenMP == 52)
19218 S.
Diag(ReductionId.
getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
19221 if (ReductionIdScopeSpec.
isValid())
19227 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
19228 bool FirstIter =
true;
19229 for (
Expr *RefExpr : VarList) {
19230 assert(RefExpr &&
"nullptr expr in OpenMP reduction clause.");
19238 if (!FirstIter && IR != ER)
19243 bool IsPrivate =
false;
19244 Expr *SimpleRefExpr = RefExpr;
19253 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
19254 ReductionId,
Type, BasePath, IR == ER ?
nullptr : *IR);
19255 Expr *ReductionOp =
nullptr;
19257 (DeclareReductionRef.
isUnset() ||
19259 ReductionOp = DeclareReductionRef.
get();
19261 RD.push(RefExpr, ReductionOp);
19267 Expr *TaskgroupDescriptor =
nullptr;
19269 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
19270 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
19272 Type = ASE->getType().getNonReferenceType();
19276 if (
const auto *ATy = BaseType->getAsArrayTypeUnsafe())
19277 Type = ATy->getElementType();
19280 Type =
Type.getNonReferenceType();
19284 auto *VD = dyn_cast<VarDecl>(D);
19290 diag::err_omp_reduction_incomplete_type))
19296 false, ASE || OASE))
19303 if (!ASE && !OASE) {
19305 VarDecl *VDDef = VD->getDefinition();
19307 DSARefChecker Check(Stack);
19308 if (Check.Visit(VDDef->
getInit())) {
19309 S.
Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
19328 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D,
false);
19329 if (DVar.CKind == OMPC_reduction) {
19330 S.
Diag(ELoc, diag::err_omp_once_referenced)
19336 if (DVar.CKind != OMPC_unknown) {
19337 S.
Diag(ELoc, diag::err_omp_wrong_dsa)
19353 DVar = Stack->getImplicitDSA(D,
true);
19354 if (DVar.CKind != OMPC_shared) {
19355 S.
Diag(ELoc, diag::err_omp_required_access)
19369 DVar = Stack->getImplicitDSA(D,
true);
19371 IsPrivate = DVar.CKind != OMPC_shared;
19372 bool IsOrphaned =
false;
19374 IsOrphaned = ParentDir == OMPD_unknown;
19376 RD.OrigSharingModifier == OMPC_ORIGINAL_SHARING_private))
19382 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D,
false);
19383 if (DVar.CKind == OMPC_threadprivate) {
19384 S.
Diag(ELoc, diag::err_omp_wrong_dsa)
19396 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
19397 ReductionId,
Type, BasePath, IR == ER ?
nullptr : *IR);
19401 (DeclareReductionRef.
isUnset() ||
19403 RD.push(RefExpr, DeclareReductionRef.
get());
19406 if (BOK == BO_Comma && DeclareReductionRef.
isUnset()) {
19410 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
19411 <<
Type << ReductionIdRange;
19414 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
19415 <<
Type << ReductionIdRange;
19427 if (DeclareReductionRef.
isUnset()) {
19428 if ((BOK == BO_GT || BOK == BO_LT) &&
19431 S.
Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
19434 if (!ASE && !OASE) {
19435 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19438 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19443 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
19445 S.
Diag(ELoc, diag::err_omp_clause_floating_type_arg)
19447 if (!ASE && !OASE) {
19448 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19451 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19458 Type =
Type.getNonLValueExprType(Context).getUnqualifiedType();
19467 bool ConstantLengthOASE =
false;
19469 bool SingleElement;
19472 Context, OASE, SingleElement, ArraySizes);
19475 if (ConstantLengthOASE && !SingleElement) {
19476 for (llvm::APSInt &Size : ArraySizes)
19477 PrivateTy = Context.getConstantArrayType(PrivateTy, Size,
nullptr,
19483 if ((OASE && !ConstantLengthOASE) ||
19486 if (!Context.getTargetInfo().isVLASupported()) {
19488 S.
Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19489 S.
Diag(ELoc, diag::note_vla_unsupported);
19492 S.
targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19493 S.
targetDiag(ELoc, diag::note_vla_unsupported);
19501 PrivateTy = Context.getVariableArrayType(
19506 }
else if (!ASE && !OASE &&
19519 if (DeclareReductionRef.
isUsable()) {
19522 if (DRD->getInitializer()) {
19548 Type = ComplexTy->getElementType();
19550 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
19551 Context.getFloatTypeSemantics(
Type));
19555 uint64_t Size = Context.getTypeSize(
Type);
19556 QualType IntTy = Context.getIntTypeForBitwidth(Size, 0);
19557 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
19576 uint64_t Size = Context.getTypeSize(
Type);
19578 Context.getIntTypeForBitwidth(Size, IsSigned);
19579 llvm::APInt InitValue =
19580 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
19581 : llvm::APInt::getMinValue(Size)
19582 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
19583 : llvm::APInt::getMaxValue(Size);
19588 ELoc, Context.getTrivialTypeSourceInfo(
Type, ELoc), ELoc,
Init);
19594 llvm::APFloat InitValue = llvm::APFloat::getLargest(
19595 Context.getFloatTypeSemantics(
Type), BOK != BO_LT);
19625 llvm_unreachable(
"Unexpected reduction operation");
19634 }
else if (!
Init) {
19644 S.
Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
19645 <<
Type << ReductionIdRange;
19646 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19649 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19655 if (DeclareReductionRef.
isUsable()) {
19657 QualType PtrRedTy = Context.getPointerType(RedTy);
19660 if (!BasePath.empty()) {
19664 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.
get(), &BasePath,
19667 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.
get(), &BasePath,
19671 QualType Params[] = {PtrRedTy, PtrRedTy};
19672 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
19686 CombBOK, LHSDRE, RHSDRE);
19693 if (BOK != BO_LT && BOK != BO_GT) {
19696 BO_Assign, LHSDRE, ReductionOp.
get());
19698 auto *ConditionalOp =
new (Context)
19703 BO_Assign, LHSDRE, ConditionalOp);
19716 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
19717 if (ClauseKind == OMPC_reduction &&
19718 RD.RedModifier == OMPC_REDUCTION_inscan) {
19720 CopyOpRes = S.
BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
19730 if (Stack->getCurrentDirective() == OMPD_simd ||
19768 if (ClauseKind == OMPC_in_reduction) {
19771 const Expr *ParentReductionOp =
nullptr;
19772 Expr *ParentBOKTD =
nullptr, *ParentReductionOpTD =
nullptr;
19773 DSAStackTy::DSAVarData ParentBOKDSA =
19774 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
19776 DSAStackTy::DSAVarData ParentReductionOpDSA =
19777 Stack->getTopMostTaskgroupReductionData(
19778 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
19779 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
19780 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
19781 if ((DeclareReductionRef.
isUnset() && IsParentReductionOp) ||
19782 (DeclareReductionRef.
isUsable() && IsParentBOK) ||
19783 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
19784 bool EmitError =
true;
19785 if (IsParentReductionOp && DeclareReductionRef.
isUsable()) {
19786 llvm::FoldingSetNodeID RedId, ParentRedId;
19787 ParentReductionOp->
Profile(ParentRedId, Context,
true);
19788 DeclareReductionRef.
get()->
Profile(RedId, Context,
19790 EmitError = RedId != ParentRedId;
19794 diag::err_omp_reduction_identifier_mismatch)
19795 << ReductionIdRange << RefExpr->getSourceRange();
19797 diag::note_omp_previous_reduction_identifier)
19799 << (IsParentBOK ? ParentBOKDSA.RefExpr
19800 : ParentReductionOpDSA.RefExpr)
19801 ->getSourceRange();
19805 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
19812 TransformExprToCaptures RebuildToCapture(S, D);
19814 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
19815 Ref = RebuildToCapture.getCapturedExpr();
19817 VarsExpr = Ref =
buildCapture(S, D, SimpleRefExpr,
false);
19820 RD.ExprCaptures.emplace_back(Ref->
getDecl());
19826 S.
BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
19831 Stack->getCurrentDirective() == OMPD_taskgroup) {
19832 S.
Diag(RefExpr->getExprLoc(),
19833 diag::err_omp_reduction_non_addressable_expression)
19834 << RefExpr->getSourceRange();
19837 RD.ExprPostUpdates.emplace_back(
19844 unsigned Modifier = RD.RedModifier;
19847 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
19848 Modifier = OMPC_REDUCTION_task;
19849 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
19851 if (Modifier == OMPC_REDUCTION_task &&
19852 (CurrDir == OMPD_taskgroup ||
19856 if (DeclareReductionRef.
isUsable())
19857 Stack->addTaskgroupReductionData(D, ReductionIdRange,
19858 DeclareReductionRef.
get());
19860 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
19862 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.
get(),
19863 TaskgroupDescriptor, CopyOpRes.
get(), TempArrayRes.
get(),
19864 TempArrayElem.
get(), IsPrivate);
19866 return RD.Vars.empty();
19882 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
19893 if (Modifier == OMPC_REDUCTION_inscan &&
19894 (
DSAStack->getCurrentDirective() != OMPD_for &&
19895 DSAStack->getCurrentDirective() != OMPD_for_simd &&
19896 DSAStack->getCurrentDirective() != OMPD_simd &&
19897 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
19898 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
19899 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
19902 ReductionData RD(VarList.size(), Modifier, OriginalSharingModifier);
19904 StartLoc, LParenLoc, ColonLoc, EndLoc,
19905 ReductionIdScopeSpec, ReductionId,
19906 UnresolvedReductions, RD))
19910 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
19913 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
19914 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
19917 OriginalSharingModifier);
19925 ReductionData RD(VarList.size());
19927 VarList, StartLoc, LParenLoc, ColonLoc,
19928 EndLoc, ReductionIdScopeSpec, ReductionId,
19929 UnresolvedReductions, RD))
19933 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19935 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
19945 ReductionData RD(VarList.size());
19947 StartLoc, LParenLoc, ColonLoc, EndLoc,
19948 ReductionIdScopeSpec, ReductionId,
19949 UnresolvedReductions, RD))
19953 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19955 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
19964 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
19974 const auto *VD = dyn_cast_or_null<VarDecl>(D);
19977 diag::err_omp_linear_incomplete_type))
19979 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
19981 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
19985 Type =
Type.getNonReferenceType();
19992 if (!IsDeclareSimd &&
19997 Type =
Type.getUnqualifiedType().getCanonicalType();
19998 const auto *Ty =
Type.getTypePtrOrNull();
19999 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
20000 !Ty->isIntegralType(
getASTContext()) && !Ty->isPointerType())) {
20001 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) <<
Type;
20003 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
20006 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20029 Diag(Step->
getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
20031 LinKind = OMPC_LINEAR_val;
20032 for (
Expr *RefExpr : VarList) {
20033 assert(RefExpr &&
"NULL expr in OpenMP linear clause.");
20036 Expr *SimpleRefExpr = RefExpr;
20040 Vars.push_back(RefExpr);
20041 Privates.push_back(
nullptr);
20042 Inits.push_back(
nullptr);
20049 auto *VD = dyn_cast<VarDecl>(D);
20055 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
20056 if (DVar.RefExpr) {
20057 Diag(ELoc, diag::err_omp_wrong_dsa)
20066 Type =
Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20078 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
20081 ExprCaptures.push_back(Ref->
getDecl());
20088 SimpleRefExpr, RefRes.
get());
20091 ExprPostUpdates.push_back(
20092 SemaRef.IgnoredValueConversions(PostUpdateRes.
get()).get());
20096 if (LinKind == OMPC_LINEAR_uval)
20097 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
20099 InitExpr = VD ? SimpleRefExpr : Ref;
20100 SemaRef.AddInitializerToDecl(
20101 Init,
SemaRef.DefaultLvalueConversion(InitExpr).get(),
20105 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
20106 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
20107 ? RefExpr->IgnoreParens()
20109 Privates.push_back(PrivateRef);
20110 Inits.push_back(InitRef);
20116 Expr *StepExpr = Step;
20117 Expr *CalcStepExpr =
nullptr;
20125 StepExpr = Val.
get();
20133 SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.
get(), StepExpr);
20135 SemaRef.ActOnFinishFullExpr(CalcStep.
get(),
false);
20139 if (std::optional<llvm::APSInt>
Result =
20141 if (!
Result->isNegative() && !
Result->isStrictlyPositive())
20142 Diag(StepLoc, diag::warn_omp_linear_step_zero)
20143 << Vars[0] << (Vars.size() > 1);
20147 CalcStepExpr = CalcStep.
get();
20152 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
20153 Vars, Privates, Inits, StepExpr, CalcStepExpr,
20159 Expr *NumIterations,
Sema &SemaRef,
20160 Scope *S, DSAStackTy *Stack) {
20165 Expr *Step = Clause.getStep();
20166 Expr *CalcStep = Clause.getCalcStep();
20173 bool HasErrors =
false;
20174 auto CurInit = Clause.inits().begin();
20175 auto CurPrivate = Clause.privates().begin();
20177 for (
Expr *RefExpr : Clause.varlist()) {
20180 Expr *SimpleRefExpr = RefExpr;
20181 auto Res =
getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20183 if (Res.second || !D) {
20184 Updates.push_back(
nullptr);
20185 Finals.push_back(
nullptr);
20189 auto &&Info = Stack->isLoopControlVariable(D);
20196 diag::err_omp_linear_distribute_var_non_loop_iteration);
20197 Updates.push_back(
nullptr);
20198 Finals.push_back(
nullptr);
20202 Expr *InitExpr = *CurInit;
20207 if (LinKind == OMPC_LINEAR_uval)
20212 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
20219 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
20230 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
20233 Final = *CurPrivate;
20237 if (!
Update.isUsable() || !Final.isUsable()) {
20238 Updates.push_back(
nullptr);
20239 Finals.push_back(
nullptr);
20240 UsedExprs.push_back(
nullptr);
20243 Updates.push_back(
Update.get());
20244 Finals.push_back(Final.get());
20246 UsedExprs.push_back(SimpleRefExpr);
20251 if (
Expr *S = Clause.getStep())
20252 UsedExprs.push_back(S);
20254 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(),
nullptr);
20255 Clause.setUpdates(Updates);
20256 Clause.setFinals(Finals);
20257 Clause.setUsedExprs(UsedExprs);
20265 for (
Expr *RefExpr : VarList) {
20266 assert(RefExpr &&
"NULL expr in OpenMP aligned clause.");
20269 Expr *SimpleRefExpr = RefExpr;
20273 Vars.push_back(RefExpr);
20280 auto *VD = dyn_cast<VarDecl>(D);
20288 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
20290 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
20293 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20300 if (
const Expr *PrevRef =
DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
20301 Diag(ELoc, diag::err_omp_used_in_clause_twice)
20303 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
20312 .DefaultFunctionArrayConversion(
20313 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
20322 if (Alignment !=
nullptr) {
20327 Alignment = AlignResult.
get();
20333 ColonLoc, EndLoc, Vars, Alignment);
20344 for (
Expr *RefExpr : VarList) {
20345 assert(RefExpr &&
"NULL expr in OpenMP copyin clause.");
20348 Vars.push_back(RefExpr);
20349 SrcExprs.push_back(
nullptr);
20350 DstExprs.push_back(
nullptr);
20351 AssignmentOps.push_back(
nullptr);
20360 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
20362 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
20363 << 0 << RefExpr->getSourceRange();
20367 Decl *D = DE->getDecl();
20373 Vars.push_back(DE);
20374 SrcExprs.push_back(
nullptr);
20375 DstExprs.push_back(
nullptr);
20376 AssignmentOps.push_back(
nullptr);
20382 if (!
DSAStack->isThreadPrivate(VD)) {
20384 Diag(ELoc, diag::err_omp_required_access)
20386 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion);
20409 SemaRef.BuildBinOp(
nullptr, DE->getExprLoc(), BO_Assign,
20410 PseudoDstExpr, PseudoSrcExpr);
20419 DSAStack->addDSA(VD, DE, OMPC_copyin);
20420 Vars.push_back(DE);
20421 SrcExprs.push_back(PseudoSrcExpr);
20422 DstExprs.push_back(PseudoDstExpr);
20423 AssignmentOps.push_back(AssignmentOp.
get());
20430 Vars, SrcExprs, DstExprs, AssignmentOps);
20441 for (
Expr *RefExpr : VarList) {
20442 assert(RefExpr &&
"NULL expr in OpenMP copyprivate clause.");
20445 Expr *SimpleRefExpr = RefExpr;
20449 Vars.push_back(RefExpr);
20450 SrcExprs.push_back(
nullptr);
20451 DstExprs.push_back(
nullptr);
20452 AssignmentOps.push_back(
nullptr);
20459 auto *VD = dyn_cast<VarDecl>(D);
20464 if (!VD || !
DSAStack->isThreadPrivate(VD)) {
20465 DSAStackTy::DSAVarData DVar =
20467 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
20469 Diag(ELoc, diag::err_omp_wrong_dsa)
20479 if (DVar.CKind == OMPC_unknown) {
20480 DVar =
DSAStack->getImplicitDSA(D,
false);
20481 if (DVar.CKind == OMPC_shared) {
20482 Diag(ELoc, diag::err_omp_required_access)
20484 <<
"threadprivate or private in the enclosing context";
20494 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
20496 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
20498 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
20501 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20522 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
20525 AssignmentOp =
SemaRef.ActOnFinishFullExpr(AssignmentOp.
get(), ELoc,
20534 VD ? RefExpr->IgnoreParens()
20536 SrcExprs.push_back(PseudoSrcExpr);
20537 DstExprs.push_back(PseudoDstExpr);
20538 AssignmentOps.push_back(AssignmentOp.
get());
20545 EndLoc, Vars, SrcExprs, DstExprs,
20553 if (VarList.empty())
20562 bool Diagnose =
true) {
20563 QualType OMPDependT = Stack->getOMPDependT();
20564 if (!OMPDependT.
isNull())
20570 S.
Diag(Loc, diag::err_omp_implied_type_not_found) <<
"omp_depend_t";
20573 Stack->setOMPDependT(PT.
get());
20594 Diag(Depobj->
getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20599 Diag(Depobj->
getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20609struct DoacrossDataInfoTy {
20613 DSAStackTy::OperatorOffsetTy OpsOffs;
20615 llvm::APSInt TotalDepCount;
20618static DoacrossDataInfoTy
20624 DSAStackTy::OperatorOffsetTy OpsOffs;
20625 llvm::APSInt DepCounter(32);
20626 llvm::APSInt TotalDepCount(32);
20628 if (
const Expr *OrderedCountExpr =
20629 Stack->getParentOrderedRegionParam().first) {
20630 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.
Context);
20631 TotalDepCount.setIsUnsigned(
true);
20634 for (
Expr *RefExpr : VarList) {
20635 assert(RefExpr &&
"NULL expr in OpenMP doacross clause.");
20638 Vars.push_back(RefExpr);
20645 if (Stack->getParentOrderedRegionParam().first &&
20646 DepCounter >= TotalDepCount) {
20647 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
20661 Vars.push_back(RefExpr);
20668 Expr *RHS =
nullptr;
20669 if (
auto *BO = dyn_cast<BinaryOperator>(
SimpleExpr)) {
20671 OOLoc = BO->getOperatorLoc();
20674 }
else if (
auto *OCE = dyn_cast<CXXOperatorCallExpr>(
SimpleExpr)) {
20675 OOK = OCE->getOperator();
20676 OOLoc = OCE->getOperatorLoc();
20679 }
else if (
auto *MCE = dyn_cast<CXXMemberCallExpr>(
SimpleExpr)) {
20680 OOK = MCE->getMethodDecl()
20683 .getCXXOverloadedOperator();
20684 OOLoc = MCE->getCallee()->getExprLoc();
20693 Vars.push_back(RefExpr);
20699 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK !=
OO_None)) {
20700 SemaRef.
Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
20706 RHS, OMPC_depend,
false);
20711 Stack->getParentOrderedRegionParam().first &&
20712 DepCounter != Stack->isParentLoopControlVariable(D).first) {
20714 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
20716 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
20719 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
20723 OpsOffs.emplace_back(RHS, OOK);
20725 Vars.push_back(RefExpr->IgnoreParenImpCasts());
20728 TotalDepCount > VarList.size() &&
20729 Stack->getParentOrderedRegionParam().first &&
20730 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
20731 SemaRef.
Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
20732 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
20734 return {Vars, OpsOffs, TotalDepCount};
20743 if (
DSAStack->getCurrentDirective() == OMPD_ordered &&
20744 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
20745 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20749 if (
DSAStack->getCurrentDirective() == OMPD_taskwait &&
20750 DepKind == OMPC_DEPEND_mutexinoutset) {
20751 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
20754 if ((
DSAStack->getCurrentDirective() != OMPD_ordered ||
20755 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20757 DepKind == OMPC_DEPEND_sink ||
20759 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20760 DepKind == OMPC_DEPEND_depobj))) {
20762 OMPC_DEPEND_outallmemory,
20763 OMPC_DEPEND_inoutallmemory};
20765 DSAStack->getCurrentDirective() == OMPD_depobj)
20766 Except.push_back(OMPC_DEPEND_depobj);
20768 Except.push_back(OMPC_DEPEND_inoutset);
20770 ?
"depend modifier(iterator) or "
20772 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20780 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
20782 diag::err_omp_depend_sink_source_with_modifier);
20787 Diag(DepModifier->
getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
20790 DSAStackTy::OperatorOffsetTy OpsOffs;
20791 llvm::APSInt TotalDepCount(32);
20793 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
20796 Vars = VarOffset.Vars;
20797 OpsOffs = VarOffset.OpsOffs;
20798 TotalDepCount = VarOffset.TotalDepCount;
20800 for (
Expr *RefExpr : VarList) {
20801 assert(RefExpr &&
"NULL expr in OpenMP depend clause.");
20804 Vars.push_back(RefExpr);
20810 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
20811 bool OMPDependTFound =
getLangOpts().OpenMP >= 50;
20812 if (OMPDependTFound)
20814 DepKind == OMPC_DEPEND_depobj);
20815 if (DepKind == OMPC_DEPEND_depobj) {
20819 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20820 !RefExpr->isInstantiationDependent() &&
20821 !RefExpr->containsUnexpandedParameterPack() &&
20822 (OMPDependTFound &&
20824 DSAStack->getOMPDependT(), RefExpr->getType()))) {
20825 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20826 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
20829 if (!RefExpr->isLValue()) {
20830 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20831 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
20838 QualType ExprTy = RefExpr->getType().getNonReferenceType();
20839 const auto *OASE = dyn_cast<ArraySectionExpr>(
SimpleExpr);
20843 if (BaseType.isNull())
20845 if (
const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20846 ExprTy = ATy->getElementType();
20849 if (BaseType.isNull() || ExprTy.
isNull())
20852 const Expr *Length = OASE->getLength();
20854 if (Length && !Length->isValueDependent() &&
20856 Result.Val.getInt().isZero()) {
20858 diag::err_omp_depend_zero_length_array_section_not_allowed)
20868 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20869 !RefExpr->isInstantiationDependent() &&
20870 !RefExpr->containsUnexpandedParameterPack() &&
20871 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
20872 (OMPDependTFound &&
DSAStack->getOMPDependT().getTypePtr() ==
20874 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20877 << RefExpr->getSourceRange();
20881 auto *ASE = dyn_cast<ArraySubscriptExpr>(
SimpleExpr);
20882 if (ASE && !ASE->getBase()->isTypeDependent() &&
20885 .getNonReferenceType()
20886 ->isPointerType() &&
20887 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
20888 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20891 << RefExpr->getSourceRange();
20898 Res =
SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
20899 RefExpr->IgnoreParenImpCasts());
20903 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20906 << RefExpr->getSourceRange();
20911 Vars.push_back(RefExpr->IgnoreParenImpCasts());
20915 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
20916 DepKind != OMPC_DEPEND_outallmemory &&
20917 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
20922 {DepKind, DepLoc,
Data.ColonLoc,
Data.OmpAllMemoryLoc}, DepModifier, Vars,
20923 TotalDepCount.getZExtValue());
20924 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
20925 DSAStack->isParentOrderedRegion())
20926 DSAStack->addDoacrossDependClause(
C, OpsOffs);
20935 "Unexpected device modifier in OpenMP < 50.");
20937 bool ErrorFound =
false;
20939 std::string Values =
20941 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
20947 Stmt *HelperValStmt =
nullptr;
20960 if (Modifier == OMPC_DEVICE_ancestor) {
20964 diag::err_omp_device_ancestor_without_requires_reverse_offload);
20972 if (CaptureRegion != OMPD_unknown &&
20973 !
SemaRef.CurContext->isDependentContext()) {
20974 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
20975 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20976 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
20981 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
20982 LParenLoc, ModifierLoc, EndLoc);
20987 bool FullCheck =
true) {
20992 SemaRef.
Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
21002 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
21008 (OASE && OASE->getColonLocFirst().isInvalid())) {
21009 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
21010 return ATy->getSExtSize() != 1;
21015 assert(OASE &&
"Expecting array section if not an array subscript.");
21016 const Expr *LowerBound = OASE->getLowerBound();
21017 const Expr *Length = OASE->getLength();
21026 llvm::APSInt ConstLowerBound = Result.
Val.
getInt();
21027 if (ConstLowerBound.getSExtValue())
21042 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr());
21047 if (!Length->EvaluateAsInt(Result, SemaRef.
getASTContext()))
21050 llvm::APSInt ConstLength = Result.
Val.
getInt();
21051 return CATy->getSExtSize() != ConstLength.getSExtValue();
21060 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
21065 (OASE && OASE->getColonLocFirst().isInvalid()))
21068 assert(OASE &&
"Expecting array section if not an array subscript.");
21069 const Expr *Length = OASE->getLength();
21075 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
21076 return ATy->getSExtSize() != 1;
21083 if (!Length->EvaluateAsInt(Result, SemaRef.
getASTContext()))
21086 llvm::APSInt ConstLength = Result.
Val.
getInt();
21087 return ConstLength.getSExtValue() != 1;
21126class MapBaseChecker final :
public StmtVisitor<MapBaseChecker, bool> {
21131 bool IsNonContiguous =
false;
21132 bool NoDiagnose =
false;
21133 const Expr *RelevantExpr =
nullptr;
21134 bool AllowUnitySizeArraySection =
true;
21135 bool AllowWholeSizeArraySection =
true;
21136 bool AllowAnotherPtr =
true;
21137 SourceLocation ELoc;
21138 SourceRange ERange;
21140 void emitErrorMsg() {
21142 if (SemaRef.getLangOpts().OpenMP < 50) {
21144 diag::err_omp_expected_named_var_member_or_array_expression)
21147 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21153 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
21158 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
21159 RelevantExpr = DRE;
21161 Components.emplace_back(DRE, DRE->
getDecl(), IsNonContiguous);
21165 bool VisitMemberExpr(MemberExpr *ME) {
21170 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
21179 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
21195 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
21215 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
21219 return RelevantExpr || Visit(E);
21229 AllowUnitySizeArraySection =
false;
21230 AllowWholeSizeArraySection =
false;
21233 Components.emplace_back(ME, FD, IsNonContiguous);
21234 return RelevantExpr || Visit(E);
21237 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
21242 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21246 return RelevantExpr || Visit(E);
21253 AllowWholeSizeArraySection =
false;
21256 Expr::EvalResult
Result;
21259 !
Result.Val.getInt().isZero()) {
21261 diag::err_omp_invalid_map_this_expr);
21263 diag::note_omp_invalid_subscript_on_this_ptr_map);
21265 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
21270 Components.emplace_back(AE,
nullptr, IsNonContiguous);
21272 return RelevantExpr || Visit(E);
21275 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
21278 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
21279 "Array sections cannot be implicitly mapped.");
21293 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21303 if (AllowWholeSizeArraySection) {
21310 if (NotWhole || IsPointer)
21311 AllowWholeSizeArraySection =
false;
21312 }
else if (DKind == OMPD_target_update &&
21313 SemaRef.getLangOpts().OpenMP >= 50) {
21314 if (IsPointer && !AllowAnotherPtr)
21315 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
21318 IsNonContiguous =
true;
21319 }
else if (AllowUnitySizeArraySection && NotUnity) {
21325 diag::err_array_section_does_not_specify_contiguous_storage)
21331 AllowAnotherPtr =
false;
21333 if (
const auto *TE = dyn_cast<CXXThisExpr>(E)) {
21334 Expr::EvalResult ResultR;
21335 Expr::EvalResult ResultL;
21340 diag::err_omp_invalid_map_this_expr);
21342 diag::note_omp_invalid_length_on_this_ptr_mapping);
21346 SemaRef.getASTContext()) &&
21349 diag::err_omp_invalid_map_this_expr);
21351 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
21353 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
21358 Components.emplace_back(OASE,
nullptr,
false);
21359 return RelevantExpr || Visit(E);
21361 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
21365 Components.emplace_back(E,
nullptr, IsNonContiguous);
21367 return Visit(
Base->IgnoreParenImpCasts());
21370 bool VisitUnaryOperator(UnaryOperator *UO) {
21371 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->
isLValue() ||
21376 if (!RelevantExpr) {
21378 Components.emplace_back(UO,
nullptr,
false);
21382 bool VisitBinaryOperator(BinaryOperator *BO) {
21394 Components.emplace_back(BO,
nullptr,
false);
21397 "Either LHS or RHS have base decl inside");
21399 return RelevantExpr || Visit(LE);
21400 return RelevantExpr || Visit(RE);
21402 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
21403 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
21404 RelevantExpr = CTE;
21405 Components.emplace_back(CTE,
nullptr, IsNonContiguous);
21408 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
21409 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
21410 Components.emplace_back(COCE,
nullptr, IsNonContiguous);
21413 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
21419 return Visit(Source);
21421 bool VisitStmt(Stmt *) {
21425 const Expr *getFoundBase()
const {
return RelevantExpr; }
21426 explicit MapBaseChecker(
21429 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
21430 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
21431 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
21445 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
21449 if (SemaRef.
getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
21450 (CKind == OMPC_to || CKind == OMPC_from)) {
21451 auto CI = CurComponents.rbegin();
21452 auto CE = CurComponents.rend();
21453 for (; CI != CE; ++CI) {
21455 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
21460 SemaRef.
Diag(ELoc, diag::err_array_section_does_not_specify_length)
21464 return Checker.getFoundBase();
21473 bool CurrentRegionOnly,
21484 assert(!CurComponents.empty() &&
"Map clause expression with no components!");
21485 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
21486 "Map clause expression with unexpected base!");
21489 bool IsEnclosedByDataEnvironmentExpr =
false;
21490 const Expr *EnclosingExpr =
nullptr;
21492 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
21493 VD, CurrentRegionOnly,
21494 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
21495 ERange, CKind, &EnclosingExpr,
21499 if (CKind == Kind && SemaRef.
LangOpts.OpenMP >= 50)
21501 assert(!StackComponents.empty() &&
21502 "Map clause expression with no components!");
21503 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
21504 "Map clause expression with unexpected base!");
21508 const Expr *RE = StackComponents.front().getAssociatedExpression();
21514 auto CI = CurComponents.rbegin();
21515 auto CE = CurComponents.rend();
21516 auto SI = StackComponents.rbegin();
21517 auto SE = StackComponents.rend();
21518 for (; CI != CE && SI != SE; ++CI, ++SI) {
21523 if (CurrentRegionOnly &&
21530 SemaRef.
Diag(CI->getAssociatedExpression()->getExprLoc(),
21531 diag::err_omp_multiple_array_items_in_map_clause)
21532 << CI->getAssociatedExpression()->getSourceRange();
21533 SemaRef.
Diag(SI->getAssociatedExpression()->getExprLoc(),
21534 diag::note_used_here)
21535 << SI->getAssociatedExpression()->getSourceRange();
21540 if (CI->getAssociatedExpression()->getStmtClass() !=
21541 SI->getAssociatedExpression()->getStmtClass())
21545 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
21551 for (; SI != SE; ++SI) {
21553 if (
const auto *ASE =
21554 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
21555 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
21556 }
else if (
const auto *OASE = dyn_cast<ArraySectionExpr>(
21557 SI->getAssociatedExpression())) {
21560 }
else if (
const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
21561 SI->getAssociatedExpression())) {
21566 SemaRef, SI->getAssociatedExpression(),
Type))
21576 if (CI == CE && SI == SE) {
21577 if (CurrentRegionOnly) {
21578 if (CKind == OMPC_map) {
21579 SemaRef.
Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21581 assert(CKind == OMPC_to || CKind == OMPC_from);
21582 SemaRef.
Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21591 IsEnclosedByDataEnvironmentExpr =
true;
21596 std::prev(CI)->getAssociatedDeclaration()->getType();
21598 std::prev(CI)->getAssociatedExpression()->getExprLoc();
21617 if (CI == CE || SI == SE) {
21620 diag::err_omp_pointer_mapped_along_with_derived_section)
21626 if (CI->getAssociatedExpression()->getStmtClass() !=
21627 SI->getAssociatedExpression()->getStmtClass() ||
21628 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
21629 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
21630 assert(CI != CE && SI != SE);
21631 SemaRef.
Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
21644 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
21645 if (CKind == OMPC_map) {
21646 if (CI != CE || SI != SE) {
21650 CI != CE ? CurComponents.begin() : StackComponents.begin();
21651 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
21653 while (It != End && !It->getAssociatedDeclaration())
21654 std::advance(It, 1);
21655 assert(It != End &&
21656 "Expected at least one component with the declaration.");
21657 if (It != Begin && It->getAssociatedDeclaration()
21659 .getCanonicalType()
21660 ->isAnyPointerType()) {
21661 IsEnclosedByDataEnvironmentExpr =
false;
21662 EnclosingExpr =
nullptr;
21666 SemaRef.
Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21668 assert(CKind == OMPC_to || CKind == OMPC_from);
21669 SemaRef.
Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21679 if (!CurrentRegionOnly && SI != SE)
21680 EnclosingExpr = RE;
21684 IsEnclosedByDataEnvironmentExpr |=
21685 (!CurrentRegionOnly && CI != CE && SI == SE);
21690 if (CurrentRegionOnly)
21704 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
21706 diag::err_omp_original_storage_is_shared_and_does_not_contain)
21722 Expr *UnresolvedMapper) {
21742 Lookups.emplace_back();
21743 Lookups.back().append(Lookup.
begin(), Lookup.
end());
21746 }
else if (
auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
21751 assert(DMD &&
"Expect valid OMPDeclareMapperDecl during instantiation.");
21752 Lookups.back().addDecl(DMD);
21761 return !D->isInvalidDecl() &&
21762 (D->getType()->isDependentType() ||
21763 D->getType()->isInstantiationDependentType() ||
21764 D->getType()->containsUnexpandedParameterPack());
21775 false, URS.
begin(), URS.
end(),
false,
21783 SemaRef.
Diag(Loc, diag::err_omp_mapper_wrong_type);
21824 SemaRef.
Diag(Loc, diag::err_omp_invalid_mapper)
21834struct MappableVarListInfo {
21836 ArrayRef<Expr *> VarList;
21838 SmallVector<Expr *, 16> ProcessedVarList;
21842 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
21844 SmallVector<Expr *, 16> UDMapperList;
21846 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
21849 VarComponents.reserve(VarList.size());
21850 VarBaseDeclarations.reserve(VarList.size());
21859 const RecordDecl *RD = BaseType->getAsRecordDecl();
21869 for (
auto *FD : RD->
fields()) {
21871 MapperVarRef,
false, Range.getBegin(),
21877 SExprs.push_back(BE);
21885 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
21888 Maps.push_back(MapClause);
21889 return MapperVarRef;
21893 DSAStackTy *Stack) {
21899 const RecordDecl *RD = BaseType->getAsRecordDecl();
21908 MapperId = DeclNames.getIdentifier(&Ctx.
Idents.
get(
"default"));
21910 BaseType, MapperId, Maps,
nullptr);
21920 DMD->setMapperVarRef(MapperVarRef);
21944 Lookups.emplace_back();
21945 Lookups.back().append(Lookup.
begin(), Lookup.
end());
21952 return !D->isInvalidDecl() &&
21953 (D->getType()->isDependentType() ||
21954 D->getType()->isInstantiationDependentType() ||
21955 D->getType()->containsUnexpandedParameterPack());
22001 {CanonType,
nullptr});
22002 llvm::DenseMap<const Type *, bool> Visited;
22004 while (!Types.empty()) {
22005 auto [BaseType, CurFD] = Types.pop_back_val();
22006 while (ParentChain.back().second == 0)
22007 ParentChain.pop_back();
22008 --ParentChain.back().second;
22009 if (BaseType.isNull())
22012 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
22015 auto It = Visited.find(BaseType.getTypePtr());
22016 if (It == Visited.end()) {
22025 DefaultMapperId, BaseType);
22026 It = Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
22032 bool FirstIter =
true;
22042 ParentChain.emplace_back(CurFD, 1);
22044 ++ParentChain.back().second;
22046 Types.emplace_back(FieldTy, FD);
22065 bool IsMapTypeImplicit =
false,
bool NoDiagnose =
false) {
22067 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
22068 "Unexpected clause kind with mappable expressions!");
22069 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
22077 MapperId.
setName(DeclNames.getIdentifier(
22079 MapperId.
setLoc(StartLoc);
22083 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
22084 bool UpdateUMIt =
false;
22085 Expr *UnresolvedMapper =
nullptr;
22087 bool HasHoldModifier =
22088 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
22096 for (
Expr *RE : MVLI.VarList) {
22097 assert(RE &&
"Null expr in omp to/from/map clause");
22101 if (UpdateUMIt && UMIt != UMEnd) {
22105 "Expect the size of UnresolvedMappers to match with that of VarList");
22109 UnresolvedMapper = *UMIt;
22113 if (
VE->isValueDependent() ||
VE->isTypeDependent() ||
22114 VE->isInstantiationDependent() ||
22115 VE->containsUnexpandedParameterPack()) {
22118 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22119 VE->getType().getCanonicalType(), UnresolvedMapper);
22122 MVLI.UDMapperList.push_back(ER.
get());
22125 MVLI.ProcessedVarList.push_back(RE);
22134 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
22137 SemaRef.
Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
22150 DSAS->getCurrentDirective(), NoDiagnose);
22154 assert(!CurComponents.empty() &&
22155 "Invalid mappable expression information.");
22157 if (
const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
22159 DSAS->addMappedClassesQualTypes(TE->getType());
22162 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22163 VE->getType().getCanonicalType(), UnresolvedMapper);
22166 MVLI.UDMapperList.push_back(ER.
get());
22168 MVLI.ProcessedVarList.push_back(RE);
22169 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22170 MVLI.VarComponents.back().append(CurComponents.begin(),
22171 CurComponents.end());
22172 MVLI.VarBaseDeclarations.push_back(
nullptr);
22179 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
22180 assert(CurDeclaration &&
"Null decl on map clause.");
22183 "Expecting components to have associated only canonical declarations.");
22185 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
22186 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
22188 assert((VD || FD) &&
"Only variables or fields are expected here!");
22195 if (VD && DSAS->isThreadPrivate(VD)) {
22198 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD,
false);
22199 SemaRef.
Diag(ELoc, diag::err_omp_threadprivate_in_clause)
22214 true, CurComponents, CKind))
22216 if (CKind == OMPC_map &&
22219 false, CurComponents, CKind))
22226 auto I = llvm::find_if(
22231 assert(I != CurComponents.end() &&
"Null decl on map clause.");
22234 auto *ASE = dyn_cast<ArraySubscriptExpr>(
VE->IgnoreParens());
22235 auto *OASE = dyn_cast<ArraySectionExpr>(
VE->IgnoreParens());
22236 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(
VE->IgnoreParens());
22238 Type = ASE->getType().getNonReferenceType();
22243 Type = ATy->getElementType();
22246 Type =
Type.getNonReferenceType();
22247 }
else if (OAShE) {
22261 if (CKind == OMPC_map) {
22268 if (DKind == OMPD_target_enter_data &&
22269 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
22271 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22272 << (IsMapTypeImplicit ? 1 : 0)
22274 << getOpenMPDirectiveName(DKind, OMPVersion);
22283 if (DKind == OMPD_target_exit_data &&
22284 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
22285 MapType == OMPC_MAP_delete || SemaRef.
getLangOpts().OpenMP >= 52)) {
22286 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22287 << (IsMapTypeImplicit ? 1 : 0)
22289 << getOpenMPDirectiveName(DKind, OMPVersion);
22298 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
22300 SemaRef.
Diag(StartLoc,
22301 diag::err_omp_invalid_map_type_modifier_for_directive)
22303 OMPC_MAP_MODIFIER_ompx_hold)
22304 << getOpenMPDirectiveName(DKind, OMPVersion);
22312 if ((DKind == OMPD_target_data ||
22314 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
22315 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
22316 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22317 << (IsMapTypeImplicit ? 1 : 0)
22319 << getOpenMPDirectiveName(DKind, OMPVersion);
22331 if (VD && ((SemaRef.
LangOpts.OpenMP <= 45 &&
22333 DKind == OMPD_target)) {
22334 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD,
false);
22336 SemaRef.
Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
22339 << getOpenMPDirectiveName(DSAS->getCurrentDirective(),
22349 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22350 Type.getCanonicalType(), UnresolvedMapper);
22362 BaseType =
VE->getType().getCanonicalType();
22369 ElemType = ATy->getElementType();
22374 }
else if (
VE->getType()->isArrayType()) {
22375 const ArrayType *AT =
VE->getType()->getAsArrayTypeUnsafe();
22385 MVLI.UDMapperList.push_back(ER.
get());
22388 MVLI.ProcessedVarList.push_back(RE);
22392 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
22398 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22399 MVLI.VarComponents.back().append(CurComponents.begin(),
22400 CurComponents.end());
22422 BuiltinType::OMPIterator))
22424 diag::err_omp_map_modifier_not_iterator);
22427 unsigned Count = 0;
22428 for (
unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
22430 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
22431 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
22435 "Modifiers exceed the allowed number of map type modifiers");
22436 Modifiers[Count] = MapTypeModifiers[I];
22437 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
22441 MappableVarListInfo MVLI(VarList);
22443 MapperIdScopeSpec, MapperId, UnresolvedMappers,
22444 MapType, Modifiers, IsMapTypeImplicit,
22450 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22451 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
22453 MapperId, MapType, IsMapTypeImplicit, MapLoc);
22461 if (ReductionType.
isNull())
22469 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
22474 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
22478 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
22482 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
22485 return ReductionType;
22491 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
22494 Decls.reserve(ReductionTypes.size());
22498 SemaRef.forRedeclarationInCurContext());
22503 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22505 bool InCompoundScope =
true;
22506 if (S !=
nullptr) {
22512 SemaRef.LookupName(Lookup, S);
22513 SemaRef.FilterLookupForScope(Lookup, DC, S,
false,
22515 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
22517 while (Filter.hasNext()) {
22519 if (InCompoundScope) {
22520 UsedAsPrevious.try_emplace(PrevDecl,
false);
22522 UsedAsPrevious[D] =
true;
22524 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22525 PrevDecl->getLocation();
22528 if (InCompoundScope) {
22529 for (
const auto &PrevData : UsedAsPrevious) {
22530 if (!PrevData.second) {
22531 PrevDRD = PrevData.first;
22536 }
else if (PrevDeclInScope !=
nullptr) {
22537 auto *PrevDRDInScope = PrevDRD =
22540 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
22541 PrevDRDInScope->getLocation();
22542 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
22543 }
while (PrevDRDInScope !=
nullptr);
22545 for (
const auto &TyData : ReductionTypes) {
22546 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
22548 if (I != PreviousRedeclTypes.end()) {
22549 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
22551 Diag(I->second, diag::note_previous_definition);
22554 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
22556 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
22558 DRD->setAccess(AS);
22559 Decls.push_back(DRD);
22561 DRD->setInvalidDecl();
22575 SemaRef.setFunctionHasBranchProtectedScope();
22576 SemaRef.getCurFunction()->setHasOMPDeclareReductionCombiner();
22579 SemaRef.PushDeclContext(S, DRD);
22583 SemaRef.PushExpressionEvaluationContext(
22586 QualType ReductionType = DRD->getType();
22603 if (S !=
nullptr) {
22604 SemaRef.PushOnScopeChains(OmpInParm, S);
22605 SemaRef.PushOnScopeChains(OmpOutParm, S);
22607 DRD->addDecl(OmpInParm);
22608 DRD->addDecl(OmpOutParm);
22614 DRD->setCombinerData(InE, OutE);
22620 SemaRef.DiscardCleanupsInEvaluationContext();
22621 SemaRef.PopExpressionEvaluationContext();
22624 SemaRef.PopFunctionScopeInfo();
22626 if (Combiner !=
nullptr)
22627 DRD->setCombiner(Combiner);
22629 DRD->setInvalidDecl();
22638 SemaRef.setFunctionHasBranchProtectedScope();
22641 SemaRef.PushDeclContext(S, DRD);
22645 SemaRef.PushExpressionEvaluationContext(
22648 QualType ReductionType = DRD->getType();
22665 if (S !=
nullptr) {
22666 SemaRef.PushOnScopeChains(OmpPrivParm, S);
22667 SemaRef.PushOnScopeChains(OmpOrigParm, S);
22669 DRD->addDecl(OmpPrivParm);
22670 DRD->addDecl(OmpOrigParm);
22676 DRD->setInitializerData(OrigE, PrivE);
22677 return OmpPrivParm;
22683 SemaRef.DiscardCleanupsInEvaluationContext();
22684 SemaRef.PopExpressionEvaluationContext();
22687 SemaRef.PopFunctionScopeInfo();
22691 }
else if (OmpPrivParm->
hasInit()) {
22692 DRD->setInitializer(OmpPrivParm->
getInit(),
22697 DRD->setInvalidDecl();
22703 for (
Decl *D : DeclReductions.
get()) {
22709 D->setInvalidDecl();
22712 return DeclReductions;
22724 SemaRef.CheckExtraCXXDefaultArguments(D);
22727 return SemaRef.CreateParsedType(
T, TInfo);
22732 assert(
ParsedType.isUsable() &&
"Expect usable parsed mapper type");
22735 assert(!MapperType.
isNull() &&
"Expect valid mapper type");
22740 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
22752 SemaRef.forRedeclarationInCurContext());
22757 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22759 bool InCompoundScope =
true;
22760 if (S !=
nullptr) {
22766 SemaRef.LookupName(Lookup, S);
22767 SemaRef.FilterLookupForScope(Lookup, DC, S,
false,
22769 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
22771 while (Filter.hasNext()) {
22773 if (InCompoundScope) {
22774 UsedAsPrevious.try_emplace(PrevDecl,
false);
22776 UsedAsPrevious[D] =
true;
22778 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22779 PrevDecl->getLocation();
22782 if (InCompoundScope) {
22783 for (
const auto &PrevData : UsedAsPrevious) {
22784 if (!PrevData.second) {
22785 PrevDMD = PrevData.first;
22790 }
else if (PrevDeclInScope) {
22791 auto *PrevDMDInScope = PrevDMD =
22794 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
22795 PrevDMDInScope->getLocation();
22796 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
22797 }
while (PrevDMDInScope !=
nullptr);
22801 if (I != PreviousRedeclTypes.end()) {
22802 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
22803 << MapperType << Name;
22804 Diag(I->second, diag::note_previous_definition);
22812 ClausesWithImplicit);
22814 MapperType, VN, ClausesWithImplicit,
22817 SemaRef.PushOnScopeChains(DMD, S);
22820 DMD->setAccess(AS);
22822 DMD->setInvalidDecl();
22828 DMD->setMapperVarRef(MapperVarRef);
22842 SemaRef.PushOnScopeChains(VD, S,
false);
22844 DSAStack->addDeclareMapperVarRef(E);
22851 if (
DSAStack->getDeclareMapperVarRef()) {
22857 assert(!IsGlobalVar &&
"Only declare mapper handles TU-scope iterators.");
22862 assert(
getLangOpts().OpenMP &&
"Expected OpenMP mode.");
22864 if (
const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
22877 assert(
getLangOpts().OpenMP &&
"Expected OpenMP mode.");
22885 if (VarList.empty())
22888 for (
Expr *ValExpr : VarList) {
22899 if (CaptureRegion == OMPD_unknown ||
SemaRef.CurContext->isDependentContext())
22901 LParenLoc, EndLoc, VarList,
22904 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22906 for (
Expr *ValExpr : VarList) {
22907 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
22908 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
22909 Vars.push_back(ValExpr);
22914 LParenLoc, EndLoc, Vars, PreInit);
22921 if (VarList.empty())
22924 for (
Expr *ValExpr : VarList) {
22935 if (CaptureRegion == OMPD_unknown ||
SemaRef.CurContext->isDependentContext())
22937 StartLoc, LParenLoc, EndLoc, VarList,
22940 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22942 for (
Expr *ValExpr : VarList) {
22943 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
22944 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
22945 Vars.push_back(ValExpr);
22950 LParenLoc, EndLoc, Vars, PreInit);
22957 Expr *ValExpr = Priority;
22958 Stmt *HelperValStmt =
nullptr;
22964 ValExpr,
SemaRef, OMPC_priority,
22966 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22970 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
22978 "Unexpected grainsize modifier in OpenMP < 51.");
22983 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22988 Expr *ValExpr = Grainsize;
22989 Stmt *HelperValStmt =
nullptr;
22999 &CaptureRegion, &HelperValStmt))
23004 StartLoc, LParenLoc, ModifierLoc, EndLoc);
23012 "Unexpected num_tasks modifier in OpenMP < 51.");
23017 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
23022 Expr *ValExpr = NumTasks;
23023 Stmt *HelperValStmt =
nullptr;
23030 ValExpr,
SemaRef, OMPC_num_tasks,
23032 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
23037 StartLoc, LParenLoc, ModifierLoc, EndLoc);
23057 DSAStackTy *Stack) {
23058 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
23059 if (!OMPEventHandleT.
isNull())
23064 S.
Diag(Loc, diag::err_omp_implied_type_not_found) <<
"omp_event_handle_t";
23067 Stack->setOMPEventHandleT(PT.
get());
23088 auto *VD = dyn_cast_or_null<VarDecl>(Ref->
getDecl());
23098 <<
"omp_event_handle_t" << 1 << VD->
getType()
23105 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(VD,
false);
23106 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
23125 std::string Values;
23129 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23133 Expr *ValExpr = ChunkSize;
23134 Stmt *HelperValStmt =
nullptr;
23145 ValExpr = Val.
get();
23150 if (std::optional<llvm::APSInt>
Result =
23152 if (
Result->isSigned() && !
Result->isStrictlyPositive()) {
23153 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
23154 <<
"dist_schedule" << 1
23159 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
23161 !
SemaRef.CurContext->isDependentContext()) {
23162 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
23163 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23164 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
23172 Kind, ValExpr, HelperValStmt);
23180 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
23181 Kind != OMPC_DEFAULTMAP_scalar) {
23185 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
23187 OMPC_DEFAULTMAP_MODIFIER_tofrom);
23191 OMPC_DEFAULTMAP_scalar);
23195 Diag(Loc, diag::err_omp_unexpected_clause_value)
23203 if (!isDefaultmapKind || !isDefaultmapModifier) {
23205 ?
"'scalar', 'aggregate', 'pointer'"
23206 :
"'scalar', 'aggregate', 'pointer', 'all'";
23208 StringRef ModifierValue =
"'alloc', 'from', 'to', 'tofrom', "
23209 "'firstprivate', 'none', 'default'";
23210 if (!isDefaultmapKind && isDefaultmapModifier) {
23211 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23213 }
else if (isDefaultmapKind && !isDefaultmapModifier) {
23214 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23217 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23219 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23223 StringRef ModifierValue =
23225 ?
"'alloc', 'from', 'to', 'tofrom', "
23226 "'firstprivate', 'none', 'default', 'present'"
23227 :
"'storage', 'from', 'to', 'tofrom', "
23228 "'firstprivate', 'private', 'none', 'default', 'present'";
23229 if (!isDefaultmapKind && isDefaultmapModifier) {
23230 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23232 }
else if (isDefaultmapKind && !isDefaultmapModifier) {
23233 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23236 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23238 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23248 if (
DSAStack->checkDefaultmapCategory(Kind)) {
23249 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
23255 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
23256 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
23257 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
23259 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
23276 Diag(DTCI.
Loc, diag::err_omp_region_not_file_context);
23282 Diag(DTCI.
Loc, diag::warn_hip_omp_target_directives);
23284 DeclareTargetNesting.push_back(DTCI);
23290 assert(!DeclareTargetNesting.empty() &&
23291 "check isInOpenMPDeclareTargetContext() first!");
23292 return DeclareTargetNesting.pop_back_val();
23302 if (DeclareTargetNesting.empty())
23306 Diag(DTCI.
Loc, diag::warn_omp_unterminated_declare_target)
23307 << getOpenMPDirectiveName(DTCI.
Kind, OMPVersion);
23313 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
23322 VarOrFuncDeclFilterCCC CCC(
SemaRef);
23326 SemaRef.diagnoseTypo(Corrected,
23327 SemaRef.PDiag(diag::err_undeclared_var_use_suggest)
23351 "Expected variable, function or function template.");
23353 if (
auto *VD = dyn_cast<VarDecl>(ND)) {
23355 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
23356 !VD->isStaticDataMember()) {
23357 Diag(Loc, diag::err_omp_declare_target_has_local_vars)
23366 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
23370 Diag(Loc, diag::warn_hip_omp_target_directives);
23373 const unsigned Level = -1;
23376 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23377 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23378 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.
DT &&
23379 (*ActiveAttr)->getLevel() == Level) {
23380 Diag(Loc, diag::err_omp_device_type_mismatch)
23381 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.
DT)
23382 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
23383 (*ActiveAttr)->getDevType());
23386 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
23387 (*ActiveAttr)->getLevel() == Level) {
23388 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
23392 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
23395 Expr *IndirectE =
nullptr;
23396 bool IsIndirect =
false;
23402 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23407 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
23409 if (
auto *VD = dyn_cast<VarDecl>(ND);
23411 VD->hasGlobalStorage())
23420 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy>
MapTy =
23421 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
23422 if (SemaRef.
LangOpts.OpenMP >= 50 &&
23425 VD->hasGlobalStorage()) {
23426 if (!
MapTy || (*
MapTy != OMPDeclareTargetDeclAttr::MT_To &&
23427 *
MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
23434 diag::err_omp_lambda_capture_in_declare_target_not_to);
23435 SemaRef.
Diag(SL, diag::note_var_explicitly_captured_here)
23442 SemaRef.
Diag(VD->
getLocation(), diag::warn_omp_not_in_target_context);
23443 SemaRef.
Diag(SL, diag::note_used_here) << SR;
23447 Sema &SemaRef, DSAStackTy *Stack,
23449 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
23460 if (
auto *VD = dyn_cast<VarDecl>(D)) {
23462 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
23463 !VD->isStaticDataMember())
23467 if (
DSAStack->isThreadPrivate(VD)) {
23468 Diag(SL, diag::err_omp_threadprivate_in_target);
23473 if (
const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
23474 D = FTD->getTemplatedDecl();
23475 if (
auto *FD = dyn_cast<FunctionDecl>(D)) {
23476 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
23477 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
23478 if (IdLoc.
isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
23479 Diag(IdLoc, diag::err_omp_function_in_link_clause);
23484 if (
auto *VD = dyn_cast<ValueDecl>(D)) {
23494 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23495 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23496 unsigned Level = DeclareTargetNesting.size();
23497 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
23500 Expr *IndirectE =
nullptr;
23501 bool IsIndirect =
false;
23507 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23509 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
23510 : OMPDeclareTargetDeclAttr::MT_To,
23511 DTCI.
DT, IndirectE, IsIndirect, Level,
23515 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
23535 if (
auto *VD = dyn_cast<VarDecl>(Node->
getDecl())) {
23537 DeclVector.push_back(VD);
23542 for (
auto *Child : Ex->
children()) {
23551 A = TD->
getAttr<OMPDeclareTargetDeclAttr>();
23553 llvm::SmallDenseSet<Decl *> Visited;
23554 while (!DeclVector.empty()) {
23555 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
23556 if (!Visited.insert(TargetVarDecl).second)
23559 if (TargetVarDecl->
hasAttr<OMPDeclareTargetDeclAttr>() &&
23588 unsigned Count = 0;
23589 for (
unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23591 llvm::is_contained(Modifiers, MotionModifiers[I])) {
23592 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23596 "Modifiers exceed the allowed number of motion modifiers");
23597 Modifiers[Count] = MotionModifiers[I];
23598 ModifiersLoc[Count] = MotionModifiersLoc[I];
23602 MappableVarListInfo MVLI(VarList);
23604 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23605 if (MVLI.ProcessedVarList.empty())
23609 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23610 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23625 unsigned Count = 0;
23626 for (
unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23628 llvm::is_contained(Modifiers, MotionModifiers[I])) {
23629 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23633 "Modifiers exceed the allowed number of motion modifiers");
23634 Modifiers[Count] = MotionModifiers[I];
23635 ModifiersLoc[Count] = MotionModifiersLoc[I];
23639 MappableVarListInfo MVLI(VarList);
23641 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23642 if (MVLI.ProcessedVarList.empty())
23646 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23647 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23654 MappableVarListInfo MVLI(VarList);
23658 for (
Expr *RefExpr : VarList) {
23659 assert(RefExpr &&
"NULL expr in OpenMP use_device_ptr clause.");
23662 Expr *SimpleRefExpr = RefExpr;
23666 MVLI.ProcessedVarList.push_back(RefExpr);
23667 PrivateCopies.push_back(
nullptr);
23668 Inits.push_back(
nullptr);
23675 Type =
Type.getNonReferenceType().getUnqualifiedType();
23677 auto *VD = dyn_cast<VarDecl>(D);
23681 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
23682 << 0 << RefExpr->getSourceRange();
23691 if (VDPrivate->isInvalidDecl())
23694 SemaRef.CurContext->addDecl(VDPrivate);
23696 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
23703 SemaRef.AddInitializerToDecl(
23704 VDPrivate,
SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
23712 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
23713 PrivateCopies.push_back(VDPrivateRefExpr);
23714 Inits.push_back(VDInitRefExpr);
23719 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23723 MVLI.VarBaseDeclarations.push_back(D);
23724 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23725 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
23729 if (MVLI.ProcessedVarList.empty())
23733 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
23734 MVLI.VarBaseDeclarations, MVLI.VarComponents);
23740 MappableVarListInfo MVLI(VarList);
23742 for (
Expr *RefExpr : VarList) {
23743 assert(RefExpr &&
"NULL expr in OpenMP use_device_addr clause.");
23746 Expr *SimpleRefExpr = RefExpr;
23752 MVLI.ProcessedVarList.push_back(RefExpr);
23757 auto *VD = dyn_cast<VarDecl>(D);
23764 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
23769 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23773 MVLI.VarBaseDeclarations.push_back(D);
23774 MVLI.VarComponents.emplace_back();
23775 Expr *Component = SimpleRefExpr;
23779 SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
23780 MVLI.VarComponents.back().emplace_back(Component, D,
23784 if (MVLI.ProcessedVarList.empty())
23788 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23789 MVLI.VarComponents);
23795 MappableVarListInfo MVLI(VarList);
23796 for (
Expr *RefExpr : VarList) {
23797 assert(RefExpr &&
"NULL expr in OpenMP is_device_ptr clause.");
23800 Expr *SimpleRefExpr = RefExpr;
23804 MVLI.ProcessedVarList.push_back(RefExpr);
23814 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
23815 << 0 << RefExpr->getSourceRange();
23821 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
23824 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23827 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
23833 const Expr *ConflictExpr;
23834 if (
DSAStack->checkMappableExprComponentListsForDecl(
23839 ConflictExpr = R.front().getAssociatedExpression();
23842 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23851 SimpleRefExpr, D,
false);
23852 DSAStack->addMappableExpressionComponents(
23853 D, MC, OMPC_is_device_ptr);
23856 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
23863 "Unexpected device pointer expression!");
23864 MVLI.VarBaseDeclarations.push_back(
23866 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23867 MVLI.VarComponents.back().push_back(MC);
23870 if (MVLI.ProcessedVarList.empty())
23874 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23875 MVLI.VarComponents);
23881 MappableVarListInfo MVLI(VarList);
23882 for (
Expr *RefExpr : VarList) {
23883 assert(RefExpr &&
"NULL expr in OpenMP has_device_addr clause.");
23886 Expr *SimpleRefExpr = RefExpr;
23891 MVLI.ProcessedVarList.push_back(RefExpr);
23899 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
23902 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23905 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
23911 const Expr *ConflictExpr;
23912 if (
DSAStack->checkMappableExprComponentListsForDecl(
23917 ConflictExpr = R.front().getAssociatedExpression();
23920 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23928 Expr *Component = SimpleRefExpr;
23929 auto *VD = dyn_cast<VarDecl>(D);
23933 SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
23935 Component, D,
false);
23936 DSAStack->addMappableExpressionComponents(
23937 D, MC, OMPC_has_device_addr);
23940 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
23943 assert(Ref &&
"has_device_addr capture failed");
23944 MVLI.ProcessedVarList.push_back(Ref);
23946 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
23953 "Unexpected device pointer expression!");
23954 MVLI.VarBaseDeclarations.push_back(
23956 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23957 MVLI.VarComponents.back().push_back(MC);
23960 if (MVLI.ProcessedVarList.empty())
23964 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23965 MVLI.VarComponents);
23979 bool AllocDependent =
23983 if (!AllocDependent) {
23992 AllocatorRes =
SemaRef.PerformImplicitConversion(
23993 AllocatorRes.
get(),
DSAStack->getOMPAllocatorHandleT(),
23998 Allocator = AllocatorRes.
isUsable() ? AllocatorRes.
get() :
nullptr;
24008 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
24015 if (!AlignmentDependent) {
24018 Alignment = AlignResult.
isUsable() ? AlignResult.
get() :
nullptr;
24023 for (
Expr *RefExpr : VarList) {
24024 assert(RefExpr &&
"NULL expr in OpenMP allocate clause.");
24027 Expr *SimpleRefExpr = RefExpr;
24031 Vars.push_back(RefExpr);
24037 auto *VD = dyn_cast<VarDecl>(D);
24039 if (!VD && !
SemaRef.CurContext->isDependentContext())
24041 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
24042 ? RefExpr->IgnoreParens()
24050 DSAStack->addInnerAllocatorExpr(Allocator);
24053 getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
24054 FirstAllocateModifier, FirstAllocateModifierLoc, SecondAllocateModifier,
24055 SecondAllocateModifierLoc, EndLoc, Vars);
24063 for (
Expr *RefExpr : VarList) {
24064 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
24067 Expr *SimpleRefExpr = RefExpr;
24071 Vars.push_back(RefExpr);
24078 if (
const Expr *PrevRef =
24079 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
24080 Diag(ELoc, diag::err_omp_used_in_clause_twice)
24082 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
24087 Vars.push_back(RefExpr);
24104 SemaRef.setFunctionHasBranchProtectedScope();
24106 return OMPScopeDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses,
24115 for (
Expr *RefExpr : VarList) {
24116 assert(RefExpr &&
"NULL expr in OpenMP inclusive clause.");
24119 Expr *SimpleRefExpr = RefExpr;
24124 Vars.push_back(RefExpr);
24129 const DSAStackTy::DSAVarData DVar =
24135 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
24136 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
24137 << RefExpr->getSourceRange();
24139 if (
DSAStack->getParentDirective() != OMPD_unknown)
24140 DSAStack->markDeclAsUsedInScanDirective(D);
24141 Vars.push_back(RefExpr);
24156 for (
Expr *RefExpr : VarList) {
24157 assert(RefExpr &&
"NULL expr in OpenMP exclusive clause.");
24160 Expr *SimpleRefExpr = RefExpr;
24165 Vars.push_back(RefExpr);
24171 DSAStackTy::DSAVarData DVar;
24172 if (ParentDirective != OMPD_unknown)
24173 DVar =
DSAStack->getTopDSA(D,
true);
24178 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
24179 DVar.Modifier != OMPC_REDUCTION_inscan) {
24180 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
24181 << RefExpr->getSourceRange();
24183 DSAStack->markDeclAsUsedInScanDirective(D);
24185 Vars.push_back(RefExpr);
24197 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
24198 if (!OMPAlloctraitT.
isNull())
24203 S.
Diag(Loc, diag::err_omp_implied_type_not_found) <<
"omp_alloctrait_t";
24206 Stack->setOMPAlloctraitT(PT.
get());
24226 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
24227 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
24228 StringRef Allocator =
24229 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
24231 PredefinedAllocators.insert(
SemaRef.LookupSingleName(
24237 Expr *AllocatorExpr =
nullptr;
24245 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
24246 bool IsPredefinedAllocator =
false;
24248 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
24250 IsPredefinedAllocator =
24252 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
24256 bool IsTypeCompatible = IsPredefinedAllocator;
24257 IsTypeCompatible = IsTypeCompatible ||
24258 Context.hasSameUnqualifiedType(AllocatorExprType,
24259 OMPAllocatorHandleT);
24261 IsTypeCompatible ||
24262 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
24263 bool IsNonConstantLValue =
24265 if (!DRE || !IsTypeCompatible ||
24266 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
24268 <<
"omp_allocator_handle_t" << (DRE ? 1 : 0)
24277 diag::err_omp_predefined_allocator_with_traits)
24290 diag::err_omp_nonpredefined_allocator_without_traits);
24296 AllocatorExpr =
SemaRef.DefaultLvalueConversion(AllocatorExpr).get();
24299 IsPredefinedAllocator
24300 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
24301 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
24303 Expr *AllocatorTraitsExpr =
nullptr;
24317 if (
const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
24318 TraitTy = ConstArrayTy->getElementType();
24320 !(Context.hasSameUnqualifiedType(TraitTy,
24322 Context.typesAreCompatible(TraitTy,
DSAStack->getOMPAlloctraitT(),
24325 diag::err_omp_expected_array_alloctraits)
24326 << AllocatorTraitsExpr->
getType();
24331 if (
auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
24334 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
24351 for (
Expr *RefExpr : Locators) {
24352 assert(RefExpr &&
"NULL expr in OpenMP affinity clause.");
24355 Vars.push_back(RefExpr);
24363 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24364 << 1 << 0 << RefExpr->getSourceRange();
24375 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24376 << 1 << 0 << RefExpr->getSourceRange();
24383 ColonLoc, EndLoc, Modifier, Vars);
24392 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24400 LParenLoc, EndLoc);
24407 Expr *ValExpr = Size;
24408 Stmt *HelperValStmt =
nullptr;
24419 DKind, OMPC_ompx_dyn_cgroup_mem,
getLangOpts().OpenMP);
24420 if (CaptureRegion != OMPD_unknown &&
24421 !
SemaRef.CurContext->isDependentContext()) {
24422 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
24423 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24424 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
24429 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
24437 if (
DSAStack->getCurrentDirective() == OMPD_ordered &&
24438 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
24439 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
24440 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
24441 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
24447 DSAStackTy::OperatorOffsetTy OpsOffs;
24448 llvm::APSInt TotalDepCount(32);
24451 DepType == OMPC_DOACROSS_source ||
24452 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
24453 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
24455 Vars = VarOffset.Vars;
24456 OpsOffs = VarOffset.OpsOffs;
24457 TotalDepCount = VarOffset.TotalDepCount;
24459 EndLoc, DepType, DepLoc, ColonLoc, Vars,
24460 TotalDepCount.getZExtValue());
24461 if (
DSAStack->isParentOrderedRegion())
24462 DSAStack->addDoacrossDependClause(
C, OpsOffs);
24491 case OMPC_contains:
24494 llvm_unreachable(
"Unexpected OpenMP clause");
24502 case OMPC_no_openmp:
24504 case OMPC_no_openmp_routines:
24506 case OMPC_no_parallelism:
24508 case OMPC_no_openmp_constructs:
24511 llvm_unreachable(
"Unexpected OpenMP clause");
24520 if (
Base->hasPlaceholderType() &&
24521 !
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
24534 LowerBound =
Result.get();
24536 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
24556 if (
Base->isTypeDependent() ||
24559 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
24562 Base, LowerBound, Length, Stride, Context.DependentTy,
VK_LValue,
24563 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
24575 Diag(
Base->getExprLoc(), diag::err_omp_typecheck_section_value)
24576 <<
Base->getSourceRange());
24582 if (Res.isInvalid())
24584 diag::err_omp_typecheck_section_not_integer)
24586 LowerBound = Res.get();
24596 if (Res.isInvalid())
24598 diag::err_omp_typecheck_section_not_integer)
24599 << 1 << Length->getSourceRange());
24600 Length = Res.get();
24602 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
24603 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
24604 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
24605 << 1 << Length->getSourceRange();
24612 diag::err_omp_typecheck_section_not_integer)
24614 Stride = Res.
get();
24627 Diag(
Base->getExprLoc(), diag::err_omp_section_function_type)
24628 << ResultTy <<
Base->getSourceRange();
24632 if (
SemaRef.RequireCompleteType(
Base->getExprLoc(), ResultTy,
24633 diag::err_omp_section_incomplete_type,
Base))
24641 llvm::APSInt LowerBoundValue =
Result.Val.getInt();
24642 if (LowerBoundValue.isNegative()) {
24644 diag::err_omp_section_not_subset_of_array)
24653 if (Length->EvaluateAsInt(
Result, Context)) {
24656 llvm::APSInt LengthValue =
Result.Val.getInt();
24657 if (LengthValue.isNegative()) {
24658 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
24659 <<
toString(LengthValue, 10,
true)
24660 << Length->getSourceRange();
24664 }
else if (
SemaRef.getLangOpts().OpenMP < 60 && ColonLocFirst.
isValid() &&
24670 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
24680 llvm::APSInt StrideValue =
Result.Val.getInt();
24681 if (!StrideValue.isStrictlyPositive()) {
24682 Diag(Stride->
getExprLoc(), diag::err_omp_section_stride_non_positive)
24683 <<
toString(StrideValue, 10,
true)
24690 if (!
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
24697 Base, LowerBound, Length, Stride, Context.ArraySectionTy,
VK_LValue,
24698 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
24705 if (
Base->hasPlaceholderType()) {
24719 LParenLoc, RParenLoc, Dims, Brackets);
24721 (!
Base->isTypeDependent() &&
24724 diag::err_omp_non_pointer_type_array_shaping_base)
24725 <<
Base->getSourceRange());
24728 bool ErrorFound =
false;
24730 if (
Dim->hasPlaceholderType()) {
24732 if (
Result.isInvalid()) {
24737 if (
Result.isInvalid()) {
24743 if (!
Dim->isTypeDependent()) {
24746 if (
Result.isInvalid()) {
24748 Diag(
Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
24749 <<
Dim->getSourceRange();
24754 if (!
Dim->isValueDependent() &&
Dim->EvaluateAsInt(EvResult, Context)) {
24759 if (!
Value.isStrictlyPositive()) {
24760 Diag(
Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
24762 <<
Dim->getSourceRange();
24768 NewDims.push_back(
Dim);
24773 LParenLoc, RParenLoc, NewDims, Brackets);
24783 bool IsCorrect =
true;
24788 if (!D.Type.getAsOpaquePtr()) {
24792 DeclTy = Context.IntTy;
24793 StartLoc = D.DeclIdentLoc;
24799 bool IsDeclTyDependent = DeclTy->isDependentType() ||
24800 DeclTy->containsUnexpandedParameterPack() ||
24801 DeclTy->isInstantiationDependentType();
24802 if (!IsDeclTyDependent) {
24803 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
24806 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
24811 if (DeclTy.isConstant(Context)) {
24814 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
24822 assert(D.DeclIdent &&
"Identifier expected.");
24827 D.DeclIdent, DeclTy, TInfo,
SC_None);
24845 SemaRef.PushOnScopeChains(VD, S);
24848 SemaRef.CurContext->addDecl(VD);
24854 Expr *Begin = D.Range.Begin;
24858 Begin = BeginRes.
get();
24860 Expr *End = D.Range.End;
24864 End = EndRes.
get();
24866 Expr *Step = D.Range.Step;
24869 Diag(Step->
getExprLoc(), diag::err_omp_iterator_step_not_integral)
24874 std::optional<llvm::APSInt>
Result =
24880 Diag(Step->
getExprLoc(), diag::err_omp_iterator_step_constant_zero)
24886 if (!Begin || !End || !IsCorrect) {
24902 if (
Decl *ID = D.IteratorDecl)
24903 ID->setInvalidDecl();
24908 if (!
SemaRef.CurContext->isDependentContext()) {
24915 D.Range.End, D.Range.Begin);
24921 if (D.Range.Step) {
24924 Res =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.
get(),
24931 Res =
SemaRef.CreateBuiltinBinOp(
24932 D.AssignmentLoc, BO_Sub, Res.
get(),
24933 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
24939 Res =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.
get(),
24945 St1 =
SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus,
24949 D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End);
24955 Res1 =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.
get(),
24962 Res1 =
SemaRef.CreateBuiltinBinOp(
24963 D.AssignmentLoc, BO_Sub, Res1.
get(),
24964 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
24970 Res1 =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.
get(),
24978 D.AssignmentLoc, BO_GT, D.Range.Step,
24979 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get());
24984 Res =
SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc,
24991 Res =
SemaRef.ActOnFinishFullExpr(Res.
get(),
false);
25003 CounterVD->setImplicit();
25010 if (D.Range.Step) {
25011 UpdateRes =
SemaRef.CreateBuiltinBinOp(
25012 D.AssignmentLoc, BO_Mul,
25013 SemaRef.DefaultLvalueConversion(RefRes.
get()).get(), St.
get());
25015 UpdateRes =
SemaRef.DefaultLvalueConversion(RefRes.
get());
25021 UpdateRes =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add,
25022 D.Range.Begin, UpdateRes.
get());
25031 UpdateRes =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign,
25032 VDRes.
get(), UpdateRes.
get());
25038 SemaRef.ActOnFinishFullExpr(UpdateRes.
get(),
true);
25044 D.AssignmentLoc, UO_PreInc, RefRes.
get());
25045 if (!CounterUpdateRes.
isUsable()) {
25049 CounterUpdateRes =
SemaRef.ActOnFinishFullExpr(CounterUpdateRes.
get(),
25051 if (!CounterUpdateRes.
isUsable()) {
25062 Helpers.assign(ID.size(), {});
25067 if (
Decl *ID = D.IteratorDecl)
25068 ID->setInvalidDecl();
25073 LLoc, RLoc, ID, Helpers);
25078 StringRef AssumptionStr) {
25079 if (llvm::getKnownAssumptionStrings().count(AssumptionStr))
25082 unsigned BestEditDistance = 3;
25083 StringRef Suggestion;
25084 for (
const auto &KnownAssumptionIt : llvm::getKnownAssumptionStrings()) {
25085 unsigned EditDistance =
25086 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
25087 if (EditDistance < BestEditDistance) {
25088 Suggestion = KnownAssumptionIt.getKey();
25089 BestEditDistance = EditDistance;
25093 if (!Suggestion.empty())
25094 S.
Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
25095 << AssumptionStr << Suggestion;
25097 S.
Diag(Loc, diag::warn_omp_assume_attribute_string_unknown)
25105 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 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 propageted 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.
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 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
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.
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
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.
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
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.
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
const TargetInfo & getTargetInfo() const
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)
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.
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.
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 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 '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, 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 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.
static OMPToClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, 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.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
ASTContext & getASTContext() const
const LangOptions & getLangOpts() const
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 * 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...
OMPClause * ActOnOpenMPToClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers={})
Called on well-formed 'to' clause.
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 * ActOnOpenMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nowait' clause.
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 * ActOnOpenMPFromClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers={})
Called on well-formed 'from' 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.
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.
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.
StmtResult ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Called on well-formed '#pragma omp cancellation point'.
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.
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
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()
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.
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
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.
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.
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.
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.
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
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.