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) &&
2494 !(DVarTop.AppliedToPointee && DVarTop.CKind != OMPC_reduction)))
2501 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2509 if (VD && !VD->
hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2510 ((
DSAStack->getDefaultDSA() != DSA_none &&
2511 DSAStack->getDefaultDSA() != DSA_private &&
2512 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2513 DVarTop.CKind == OMPC_shared))
2515 auto *FD = dyn_cast<FieldDecl>(D);
2516 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2517 !DVarPrivate.PrivateCopy) {
2518 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2521 DefaultDataSharingAttributes DefaultAttr) {
2523 (DefaultAttr == DSA_firstprivate ||
2524 DefaultAttr == DSA_private);
2528 if (DVarPrivate.CKind == OMPC_unknown)
2534 if (
SemaRef.getCurrentThisType().isNull())
2548 SemaRef.CurContext->getParent(),
false);
2552 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2555 if (DVarPrivate.CKind != OMPC_unknown ||
2556 (VD && (
DSAStack->getDefaultDSA() == DSA_none ||
2557 DSAStack->getDefaultDSA() == DSA_private ||
2558 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2564void SemaOpenMP::adjustOpenMPTargetScopeIndex(
unsigned &FunctionScopesIndex,
2565 unsigned Level)
const {
2566 FunctionScopesIndex -= getOpenMPCaptureLevels(
DSAStack->getDirective(Level));
2570 assert(
getLangOpts().OpenMP &&
"OpenMP must be enabled.");
2576 assert(
getLangOpts().OpenMP &&
"OpenMP must be enabled.");
2578 DSAStack->resetPossibleLoopCounter();
2584 unsigned CapLevel)
const {
2585 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2586 if (
DSAStack->getCurrentDirective() != OMPD_unknown &&
2587 (!
DSAStack->isClauseParsingMode() ||
2588 DSAStack->getParentDirective() != OMPD_unknown)) {
2589 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2592 DefaultDataSharingAttributes DefaultAttr) {
2594 DefaultAttr == DSA_private;
2600 !
DSAStack->isLoopControlVariable(D).first)
2601 return OMPC_private;
2604 bool IsTriviallyCopyable =
2615 (IsTriviallyCopyable ||
2621 return OMPC_firstprivate;
2622 DSAStackTy::DSAVarData DVar =
DSAStack->getImplicitDSA(D, Level);
2623 if (DVar.CKind != OMPC_shared &&
2624 !
DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2625 DSAStack->addImplicitTaskFirstprivate(Level, D);
2626 return OMPC_firstprivate;
2633 DSAStack->resetPossibleLoopCounter(D);
2635 return OMPC_private;
2638 DSAStack->isLoopControlVariable(D).first) &&
2643 return OMPC_private;
2645 if (
const auto *VD = dyn_cast<VarDecl>(D)) {
2651 return OMPC_private;
2656 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2657 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2658 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2659 return OMPC_private;
2663 (
DSAStack->isClauseParsingMode() &&
2664 DSAStack->getClauseParsingMode() == OMPC_private) ||
2669 return K == OMPD_taskgroup ||
2670 ((isOpenMPParallelDirective(K) ||
2671 isOpenMPWorksharingDirective(K)) &&
2672 !isOpenMPSimdDirective(K));
2675 DSAStack->isTaskgroupReductionRef(D, Level)))
2682 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2685 for (
unsigned I =
DSAStack->getNestingLevel() + 1; I > Level; --I) {
2686 const unsigned NewLevel = I - 1;
2690 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2698 if (
DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2708 if (
DSAStack->mustBeFirstprivateAtLevel(
2710 OMPC = OMPC_firstprivate;
2714 if (OMPC != OMPC_unknown)
2716 OMPCaptureKindAttr::CreateImplicit(getASTContext(),
unsigned(OMPC)));
2720 unsigned CaptureLevel)
const {
2721 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2726 const auto *VD = dyn_cast<VarDecl>(D);
2730 Regions[CaptureLevel] != OMPD_task;
2734 unsigned CaptureLevel)
const {
2735 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2738 if (
const auto *VD = dyn_cast<VarDecl>(D)) {
2742 DSAStackTy::DSAVarData TopDVar =
2744 unsigned NumLevels =
2749 return (NumLevels == CaptureLevel + 1 &&
2750 (TopDVar.CKind != OMPC_shared ||
2751 DSAStack->getDefaultDSA() == DSA_firstprivate));
2754 DSAStackTy::DSAVarData DVar =
DSAStack->getImplicitDSA(D, Level);
2755 if (DVar.CKind != OMPC_shared)
2757 }
while (Level > 0);
2763void SemaOpenMP::DestroyDataSharingAttributesStack() {
delete DSAStack; }
2767 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2772 "Not in OpenMP declare variant scope!");
2774 OMPDeclareVariantScopes.pop_back();
2780 assert(
getLangOpts().OpenMP &&
"Expected OpenMP compilation mode.");
2781 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2785 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2788 if (!
getLangOpts().OpenMPIsTargetDevice && DevTy &&
2789 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2792 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2793 if (
getLangOpts().OpenMPIsTargetDevice && DevTy &&
2794 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2796 StringRef HostDevTy =
2798 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2799 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2800 diag::note_omp_marked_device_type_here)
2806 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2810 for (OMPDeclareVariantAttr *A :
2811 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2814 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2815 OMPDeclareTargetDeclAttr::getDeviceType(
2816 VariantFD->getMostRecentDecl());
2817 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2823 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2827 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2828 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2829 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2830 diag::note_omp_marked_device_type_here)
2838 DSAStack->push(DKind, DirName, CurScope, Loc);
2839 SemaRef.PushExpressionEvaluationContext(
2848 DSAStack->setClauseParsingMode(OMPC_unknown);
2849 SemaRef.CleanupVarDeclMarking();
2852static std::pair<ValueDecl *, bool>
2854 SourceRange &ERange,
bool AllowArraySection =
false,
2855 bool AllowAssumedSizeArray =
false, StringRef DiagType =
"");
2860 bool InscanFound =
false;
2867 if (
C->getClauseKind() != OMPC_reduction)
2870 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2872 InscanLoc = RC->getModifierLoc();
2875 if (RC->getModifier() == OMPC_REDUCTION_task) {
2885 S.
Diag(RC->getModifierLoc(),
2886 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2892 if (
C->getClauseKind() != OMPC_reduction)
2895 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2898 : RC->getModifierLoc(),
2899 diag::err_omp_inscan_reduction_expected);
2900 S.
Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2903 for (
Expr *Ref : RC->varlist()) {
2904 assert(Ref &&
"NULL expr in OpenMP reduction clause.");
2907 Expr *SimpleRefExpr = Ref;
2914 S.
Diag(Ref->getExprLoc(),
2915 diag::err_omp_reduction_not_inclusive_exclusive)
2916 << Ref->getSourceRange();
2924 ArrayRef<OMPClause *> Clauses);
2925static DeclRefExpr *
buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2930 const DSAStackTy::DSAVarData &DVar,
2931 bool IsLoopIterVar =
false);
2942 for (
Expr *DE : Clause->varlist()) {
2943 if (DE->isValueDependent() || DE->isTypeDependent()) {
2944 PrivateCopies.push_back(
nullptr);
2950 const DSAStackTy::DSAVarData DVar =
2952 if (DVar.CKind != OMPC_lastprivate) {
2955 PrivateCopies.push_back(
nullptr);
2966 SemaRef.ActOnUninitializedDecl(VDPrivate);
2968 PrivateCopies.push_back(
nullptr);
2974 Clause->setPrivateCopies(PrivateCopies);
2980 for (
Expr *RefExpr : Clause->varlist()) {
2981 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
2984 Expr *SimpleRefExpr = RefExpr;
2988 PrivateRefs.push_back(RefExpr);
2993 const DSAStackTy::DSAVarData DVar =
2995 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2998 Clause->setPrivateRefs(PrivateRefs);
3002 for (
unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
3010 DSAStackTy::DSAVarData DVar =
3016 Expr *MapExpr =
nullptr;
3018 DSAStack->checkMappableExprComponentListsForDecl(
3024 auto MI = MapExprComponents.rbegin();
3025 auto ME = MapExprComponents.rend();
3027 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
3028 VD->getCanonicalDecl()) {
3029 MapExpr = MI->getAssociatedExpression();
3034 Diag(D.Allocator->getExprLoc(), diag::err_omp_allocator_used_in_clauses)
3039 Diag(MapExpr->getExprLoc(), diag::note_used_here)
3040 << MapExpr->getSourceRange();
3045 if (
const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
3047 if (
auto *Clause = dyn_cast<OMPLastprivateClause>(
C)) {
3048 FinalizeLastprivate(Clause);
3049 }
else if (
auto *Clause = dyn_cast<OMPNontemporalClause>(
C)) {
3050 FinalizeNontemporal(Clause);
3051 }
else if (
auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(
C)) {
3052 FinalizeAllocators(Clause);
3067 Expr *NumIterations, Sema &SemaRef,
3068 Scope *S, DSAStackTy *Stack);
3071 OMPLoopBasedDirective::HelperExprs &B,
3072 DSAStackTy *Stack) {
3074 "loop exprs were not built");
3081 auto *LC = dyn_cast<OMPLinearClause>(
C);
3085 B.NumIterations, SemaRef,
3095class VarDeclFilterCCC final :
public CorrectionCandidateCallback {
3100 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3101 bool ValidateCandidate(
const TypoCorrection &Candidate)
override {
3103 if (
const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3111 std::unique_ptr<CorrectionCandidateCallback> clone()
override {
3112 return std::make_unique<VarDeclFilterCCC>(*
this);
3116class VarOrFuncDeclFilterCCC final :
public CorrectionCandidateCallback {
3121 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3122 bool ValidateCandidate(
const TypoCorrection &Candidate)
override {
3132 std::unique_ptr<CorrectionCandidateCallback> clone()
override {
3133 return std::make_unique<VarOrFuncDeclFilterCCC>(*
this);
3146 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
3155 VarDeclFilterCCC CCC(
SemaRef);
3161 SemaRef.PDiag(Lookup.
empty() ? diag::err_undeclared_var_use_suggest
3162 : diag::err_omp_expected_var_arg_suggest)
3164 VD = Corrected.getCorrectionDeclAs<
VarDecl>();
3167 : diag::err_omp_expected_var_arg)
3180 if ((Kind == OMPD_threadprivate || Kind == OMPD_groupprivate) &&
3182 Diag(Id.
getLoc(), diag::err_omp_global_var_arg)
3183 << getOpenMPDirectiveName(Kind, OMPVersion) << !VD->
isStaticLocal();
3187 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3198 !
SemaRef.getCurLexicalContext()->isTranslationUnit()) {
3200 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3204 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3215 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3219 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3228 (!
SemaRef.getCurLexicalContext()->isFileContext() ||
3229 !
SemaRef.getCurLexicalContext()->Encloses(
3232 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3236 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3245 !
SemaRef.isDeclInScope(ND,
SemaRef.getCurLexicalContext(), CurScope)) {
3247 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3251 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3259 if ((Kind == OMPD_threadprivate && VD->
isUsed() &&
3261 (Kind == OMPD_groupprivate && VD->
isUsed())) {
3263 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3278 SemaRef.CurContext->addDecl(D);
3288 Diag(Loc, diag::err_omp_unexpected_directive)
3289 << getOpenMPDirectiveName(OMPD_groupprivate,
getLangOpts().OpenMP);
3293 SemaRef.CurContext->addDecl(D);
3300class LocalVarRefChecker final
3306 if (
const auto *VD = dyn_cast<VarDecl>(E->
getDecl())) {
3309 diag::err_omp_local_var_in_threadprivate_init)
3311 SemaRef.Diag(VD->
getLocation(), diag::note_defined_here)
3318 bool VisitStmt(
const Stmt *S) {
3319 for (
const Stmt *Child : S->
children()) {
3320 if (Child && Visit(Child))
3325 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3329OMPThreadPrivateDecl *
3334 for (
Expr *RefExpr : VarList) {
3352 if (
SemaRef.RequireCompleteType(
3353 ILoc, VD->
getType(), diag::err_omp_threadprivate_incomplete_type)) {
3361 Diag(ILoc, diag::err_omp_ref_type_arg)
3362 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion)
3367 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3375 !(VD->
hasAttr<OMPThreadPrivateDeclAttr>() &&
3380 Diag(ILoc, diag::err_omp_var_thread_local)
3385 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3393 LocalVarRefChecker Checker(
SemaRef);
3394 if (Checker.Visit(
Init))
3398 Vars.push_back(RefExpr);
3399 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3400 VD->
addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3403 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3406 if (!Vars.empty()) {
3419 for (
Expr *RefExpr : VarList) {
3437 if (
SemaRef.RequireCompleteType(
3438 ILoc, VD->
getType(), diag::err_omp_groupprivate_incomplete_type)) {
3444 Diag(ILoc, diag::err_omp_ref_type_arg)
3445 << getOpenMPDirectiveName(OMPD_groupprivate) << VD->
getType();
3449 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3457 Diag(ILoc, diag::err_omp_groupprivate_with_initializer)
3462 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3467 Vars.push_back(RefExpr);
3468 DSAStack->addDSA(VD, DE, OMPC_groupprivate);
3469 VD->
addAttr(OMPGroupPrivateDeclAttr::CreateImplicit(Context,
3472 ML->DeclarationMarkedOpenMPGroupPrivate(VD);
3475 if (!Vars.empty()) {
3483static OMPAllocateDeclAttr::AllocatorTypeTy
3486 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3490 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3491 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3492 llvm::FoldingSetNodeID AEId;
3495 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3496 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
3497 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3498 llvm::FoldingSetNodeID DAEId;
3501 if (AEId == DAEId) {
3502 AllocatorKindRes = AllocatorKind;
3506 return AllocatorKindRes;
3511 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
Expr *Allocator) {
3512 if (!VD->
hasAttr<OMPAllocateDeclAttr>())
3514 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
3515 Expr *PrevAllocator = A->getAllocator();
3516 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3518 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3519 if (AllocatorsMatch &&
3520 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3521 Allocator && PrevAllocator) {
3524 llvm::FoldingSetNodeID AEId, PAEId;
3527 AllocatorsMatch = AEId == PAEId;
3529 if (!AllocatorsMatch) {
3531 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3535 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3537 PrevAllocator->printPretty(PrevAllocatorStream,
nullptr,
3545 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3547 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3548 S.
Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3549 << (Allocator ? 1 : 0) << AllocatorStream.str()
3550 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3552 S.
Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3553 << PrevAllocatorRange;
3561 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3563 if (VD->
hasAttr<OMPAllocateDeclAttr>())
3576 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.
Context, AllocatorKind,
3577 Allocator, Alignment, SR);
3580 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3586 assert(Clauses.size() <= 2 &&
"Expected at most two clauses.");
3587 Expr *Alignment =
nullptr;
3588 Expr *Allocator =
nullptr;
3589 if (Clauses.empty()) {
3596 SemaRef.targetDiag(Loc, diag::err_expected_allocator_clause);
3599 if (
const auto *AC = dyn_cast<OMPAllocatorClause>(
C))
3600 Allocator = AC->getAllocator();
3601 else if (
const auto *AC = dyn_cast<OMPAlignClause>(
C))
3602 Alignment = AC->getAlignment();
3604 llvm_unreachable(
"Unexpected clause on allocate directive");
3606 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3609 for (
Expr *RefExpr : VarList) {
3615 VD->
hasAttr<OMPThreadPrivateDeclAttr>() ||
3623 AllocatorKind, Allocator))
3631 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3633 diag::err_omp_expected_predefined_allocator)
3638 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3644 Vars.push_back(RefExpr);
3651 Owner =
SemaRef.getCurLexicalContext();
3662 if (!
SemaRef.CurContext->isFileContext()) {
3663 Diag(Loc, diag::err_omp_invalid_scope) <<
"requires";
3667 SemaRef.CurContext->addDecl(D);
3677 bool SkippedClauses) {
3678 if (!SkippedClauses && Assumptions.empty()) {
3680 Diag(Loc, diag::err_omp_no_clause_for_directive)
3681 << llvm::omp::getAllAssumeClauseOptions()
3682 << llvm::omp::getOpenMPDirectiveName(DKind, OMPVersion);
3686 OMPAssumeAttr::Create(
getASTContext(), llvm::join(Assumptions,
","), Loc);
3687 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3688 OMPAssumeScoped.push_back(AA);
3693 if (Assumptions.empty())
3696 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3697 "Unexpected omp assumption directive!");
3698 OMPAssumeGlobal.push_back(AA);
3705 auto *Ctx =
SemaRef.CurContext;
3706 while (Ctx->getLexicalParent())
3707 Ctx = Ctx->getLexicalParent();
3708 DeclContexts.push_back(Ctx);
3709 while (!DeclContexts.empty()) {
3711 for (
auto *SubDC : DC->
decls()) {
3712 if (SubDC->isInvalidDecl())
3714 if (
auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3715 DeclContexts.push_back(CTD->getTemplatedDecl());
3716 llvm::append_range(DeclContexts, CTD->specializations());
3719 if (
auto *DC = dyn_cast<DeclContext>(SubDC))
3720 DeclContexts.push_back(DC);
3721 if (
auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3731 OMPAssumeScoped.pop_back();
3752 DSAStack->getEncounteredTargetLocs();
3754 if (!TargetLocations.empty() || !AtomicLoc.
isInvalid()) {
3755 for (
const OMPClause *CNew : ClauseList) {
3761 Diag(Loc, diag::err_omp_directive_before_requires)
3764 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3769 Diag(Loc, diag::err_omp_directive_before_requires)
3771 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3777 if (!
DSAStack->hasDuplicateRequiresClause(ClauseList))
3785 const DSAStackTy::DSAVarData &DVar,
3786 bool IsLoopIterVar) {
3788 SemaRef.
Diag(DVar.RefExpr->
getExprLoc(), diag::note_omp_explicit_dsa)
3793 PDSA_StaticMemberShared,
3794 PDSA_StaticLocalVarShared,
3795 PDSA_LoopIterVarPrivate,
3796 PDSA_LoopIterVarLinear,
3797 PDSA_LoopIterVarLastprivate,
3798 PDSA_ConstVarShared,
3799 PDSA_GlobalVarShared,
3800 PDSA_TaskVarFirstprivate,
3801 PDSA_LocalVarPrivate,
3803 } Reason = PDSA_Implicit;
3804 bool ReportHint =
false;
3806 auto *VD = dyn_cast<VarDecl>(D);
3807 if (IsLoopIterVar) {
3808 if (DVar.CKind == OMPC_private)
3809 Reason = PDSA_LoopIterVarPrivate;
3810 else if (DVar.CKind == OMPC_lastprivate)
3811 Reason = PDSA_LoopIterVarLastprivate;
3813 Reason = PDSA_LoopIterVarLinear;
3815 DVar.CKind == OMPC_firstprivate) {
3816 Reason = PDSA_TaskVarFirstprivate;
3817 ReportLoc = DVar.ImplicitDSALoc;
3819 Reason = PDSA_StaticLocalVarShared;
3821 Reason = PDSA_StaticMemberShared;
3823 Reason = PDSA_GlobalVarShared;
3825 Reason = PDSA_ConstVarShared;
3826 else if (VD && VD->
isLocalVarDecl() && DVar.CKind == OMPC_private) {
3828 Reason = PDSA_LocalVarPrivate;
3830 if (Reason != PDSA_Implicit) {
3831 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
3832 SemaRef.
Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3833 << Reason << ReportHint
3834 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
3835 }
else if (DVar.ImplicitDSALoc.
isValid()) {
3836 SemaRef.
Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3843 bool IsAggregateOrDeclareTarget) {
3846 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3847 case OMPC_DEFAULTMAP_MODIFIER_storage:
3848 Kind = OMPC_MAP_alloc;
3850 case OMPC_DEFAULTMAP_MODIFIER_to:
3853 case OMPC_DEFAULTMAP_MODIFIER_from:
3854 Kind = OMPC_MAP_from;
3856 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3857 Kind = OMPC_MAP_tofrom;
3859 case OMPC_DEFAULTMAP_MODIFIER_present:
3865 Kind = OMPC_MAP_alloc;
3867 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3868 case OMPC_DEFAULTMAP_MODIFIER_private:
3870 llvm_unreachable(
"Unexpected defaultmap implicit behavior");
3871 case OMPC_DEFAULTMAP_MODIFIER_none:
3872 case OMPC_DEFAULTMAP_MODIFIER_default:
3877 if (IsAggregateOrDeclareTarget) {
3878 Kind = OMPC_MAP_tofrom;
3881 llvm_unreachable(
"Unexpected defaultmap implicit behavior");
3888struct VariableImplicitInfo {
3892 llvm::SetVector<Expr *> Privates;
3893 llvm::SetVector<Expr *> Firstprivates;
3894 llvm::SetVector<Expr *> Mappings[DefaultmapKindNum][MapKindNum];
3895 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
3896 MapModifiers[DefaultmapKindNum];
3899class DSAAttrChecker final :
public StmtVisitor<DSAAttrChecker, void> {
3903 bool ErrorFound =
false;
3904 bool TryCaptureCXXThisMembers =
false;
3905 CapturedStmt *CS =
nullptr;
3907 VariableImplicitInfo ImpInfo;
3909 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3911 void VisitSubCaptures(OMPExecutableDirective *S) {
3913 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3915 if (S->getDirectiveKind() == OMPD_atomic ||
3916 S->getDirectiveKind() == OMPD_critical ||
3917 S->getDirectiveKind() == OMPD_section ||
3918 S->getDirectiveKind() == OMPD_master ||
3919 S->getDirectiveKind() == OMPD_masked ||
3920 S->getDirectiveKind() == OMPD_scope ||
3921 S->getDirectiveKind() == OMPD_assume ||
3923 Visit(S->getAssociatedStmt());
3926 visitSubCaptures(S->getInnermostCapturedStmt());
3929 if (TryCaptureCXXThisMembers ||
3931 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3932 [](
const CapturedStmt::Capture &
C) {
3933 return C.capturesThis();
3935 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3936 TryCaptureCXXThisMembers =
true;
3937 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3938 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3944 for (OMPClause *
C : S->clauses())
3945 if (
auto *FC = dyn_cast<OMPFirstprivateClause>(
C)) {
3946 for (Expr *Ref : FC->varlist())
3953 void VisitDeclRefExpr(DeclRefExpr *E) {
3959 if (
auto *VD = dyn_cast<VarDecl>(E->
getDecl())) {
3962 !Stack->getTopDSA(VD,
false).RefExpr &&
3963 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3964 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3965 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3966 Visit(CED->getInit());
3972 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3977 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3978 !Stack->isImplicitTaskFirstprivate(VD))
3981 if (Stack->isUsesAllocatorsDecl(VD))
3984 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD,
false);
3986 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3990 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3991 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3993 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
3994 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3995 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3996 !Stack->isImplicitTaskFirstprivate(VD))
4004 if (DVar.CKind == OMPC_unknown &&
4005 (Stack->getDefaultDSA() == DSA_none ||
4006 Stack->getDefaultDSA() == DSA_private ||
4007 Stack->getDefaultDSA() == DSA_firstprivate) &&
4008 isImplicitOrExplicitTaskingRegion(DKind) &&
4009 VarsWithInheritedDSA.count(VD) == 0) {
4010 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
4011 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
4012 Stack->getDefaultDSA() == DSA_private)) {
4013 DSAStackTy::DSAVarData DVar =
4014 Stack->getImplicitDSA(VD,
false);
4015 InheritedDSA = DVar.CKind == OMPC_unknown;
4018 VarsWithInheritedDSA[VD] = E;
4019 if (Stack->getDefaultDSA() == DSA_none)
4034 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
4035 OMPC_DEFAULTMAP_MODIFIER_none;
4036 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
4037 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
4041 if (!Stack->checkMappableExprComponentListsForDecl(
4046 auto MI = MapExprComponents.rbegin();
4047 auto ME = MapExprComponents.rend();
4048 return MI != ME && MI->getAssociatedDeclaration() == VD;
4050 VarsWithInheritedDSA[VD] = E;
4056 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
4057 OMPC_DEFAULTMAP_MODIFIER_present;
4058 if (IsModifierPresent) {
4059 if (!llvm::is_contained(ImpInfo.MapModifiers[ClauseKind],
4060 OMPC_MAP_MODIFIER_present)) {
4061 ImpInfo.MapModifiers[ClauseKind].push_back(
4062 OMPC_MAP_MODIFIER_present);
4068 !Stack->isLoopControlVariable(VD).first) {
4069 if (!Stack->checkMappableExprComponentListsForDecl(
4074 if (SemaRef.LangOpts.OpenMP >= 50)
4075 return !StackComponents.empty();
4078 return StackComponents.size() == 1 ||
4080 llvm::drop_begin(llvm::reverse(StackComponents)),
4081 [](const OMPClauseMappableExprCommon::
4082 MappableComponent &MC) {
4083 return MC.getAssociatedDeclaration() ==
4085 (isa<ArraySectionExpr>(
4086 MC.getAssociatedExpression()) ||
4087 isa<OMPArrayShapingExpr>(
4088 MC.getAssociatedExpression()) ||
4089 isa<ArraySubscriptExpr>(
4090 MC.getAssociatedExpression()));
4093 bool IsFirstprivate =
false;
4095 if (
const auto *RD =
4097 IsFirstprivate = RD->isLambda();
4099 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
4100 if (IsFirstprivate) {
4101 ImpInfo.Firstprivates.insert(E);
4104 Stack->getDefaultmapModifier(ClauseKind);
4105 if (M == OMPC_DEFAULTMAP_MODIFIER_private) {
4106 ImpInfo.Privates.insert(E);
4109 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
4110 ImpInfo.Mappings[ClauseKind][
Kind].insert(E);
4121 DVar = Stack->hasInnermostDSA(
4124 return C == OMPC_reduction && !AppliedToPointee;
4133 SemaRef.
Diag(ELoc, diag::err_omp_reduction_in_task);
4139 DVar = Stack->getImplicitDSA(VD,
false);
4141 (((Stack->getDefaultDSA() == DSA_firstprivate &&
4142 DVar.CKind == OMPC_firstprivate) ||
4143 (Stack->getDefaultDSA() == DSA_private &&
4144 DVar.CKind == OMPC_private)) &&
4146 !Stack->isLoopControlVariable(VD).first) {
4147 if (Stack->getDefaultDSA() == DSA_private)
4148 ImpInfo.Privates.insert(E);
4150 ImpInfo.Firstprivates.insert(E);
4157 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
4158 Stack->addToParentTargetRegionLinkGlobals(E);
4163 void VisitMemberExpr(MemberExpr *E) {
4171 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD,
false);
4174 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
4178 !Stack->isLoopControlVariable(FD).first &&
4179 !Stack->checkMappableExprComponentListsForDecl(
4184 return isa<CXXThisExpr>(
4186 StackComponents.back().getAssociatedExpression())
4198 if (Stack->isClassPreviouslyMapped(TE->getType()))
4202 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4207 ImpInfo.Mappings[ClauseKind][
Kind].insert(E);
4216 DVar = Stack->hasInnermostDSA(
4219 return C == OMPC_reduction && !AppliedToPointee;
4228 SemaRef.
Diag(ELoc, diag::err_omp_reduction_in_task);
4234 DVar = Stack->getImplicitDSA(FD,
false);
4236 !Stack->isLoopControlVariable(FD).first) {
4241 if (DVar.CKind != OMPC_unknown)
4242 ImpInfo.Firstprivates.insert(E);
4252 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4253 if (!Stack->checkMappableExprComponentListsForDecl(
4259 auto CCI = CurComponents.rbegin();
4260 auto CCE = CurComponents.rend();
4261 for (const auto &SC : llvm::reverse(StackComponents)) {
4263 if (CCI->getAssociatedExpression()->getStmtClass() !=
4264 SC.getAssociatedExpression()->getStmtClass())
4265 if (!((isa<ArraySectionExpr>(
4266 SC.getAssociatedExpression()) ||
4267 isa<OMPArrayShapingExpr>(
4268 SC.getAssociatedExpression())) &&
4269 isa<ArraySubscriptExpr>(
4270 CCI->getAssociatedExpression())))
4273 const Decl *CCD = CCI->getAssociatedDeclaration();
4274 const Decl *SCD = SC.getAssociatedDeclaration();
4275 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4276 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4279 std::advance(CCI, 1);
4287 }
else if (!TryCaptureCXXThisMembers) {
4291 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4292 for (OMPClause *
C : S->clauses()) {
4295 if (isa_and_nonnull<OMPPrivateClause>(
C))
4303 for (Stmt *CC :
C->children()) {
4310 VisitSubCaptures(S);
4313 void VisitOMPCanonicalLoopNestTransformationDirective(
4314 OMPCanonicalLoopNestTransformationDirective *S) {
4319 void VisitCallExpr(CallExpr *S) {
4328 auto *CI =
Callee->IgnoreParenImpCasts();
4329 if (
auto *CE = dyn_cast<MemberExpr>(CI))
4330 Visit(CE->getBase());
4331 else if (
auto *CE = dyn_cast<DeclRefExpr>(CI))
4335 void VisitStmt(Stmt *S) {
4345 void visitSubCaptures(CapturedStmt *S) {
4346 for (
const CapturedStmt::Capture &Cap : S->
captures()) {
4347 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4349 VarDecl *VD = Cap.getCapturedVar();
4353 Stack->checkMappableExprComponentListsForDecl(
4360 Cap.getLocation(),
true);
4364 bool isErrorFound()
const {
return ErrorFound; }
4365 const VariableImplicitInfo &getImplicitInfo()
const {
return ImpInfo; }
4367 return VarsWithInheritedDSA;
4370 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4371 : Stack(S), SemaRef(SemaRef), ErrorFound(
false), CS(CS) {
4372 DKind = S->getCurrentDirective();
4375 for (DeclRefExpr *E : Stack->getLinkGlobals())
4387 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4389 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4391 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4393 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4395 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4396 Stack->handleConstructTrait(Traits, ScopeEntry);
4399static SmallVector<SemaOpenMP::CapturedParamNameType>
4403 Context.getIntTypeForBitwidth(32, 1).
withConst();
4407 std::make_pair(
".global_tid.", KmpInt32PtrTy),
4408 std::make_pair(
".bound_tid.", KmpInt32PtrTy),
4410 if (LoopBoundSharing) {
4412 Params.push_back(std::make_pair(
".previous.lb.", KmpSizeTy));
4413 Params.push_back(std::make_pair(
".previous.ub.", KmpSizeTy));
4417 Params.push_back(std::make_pair(StringRef(),
QualType()));
4421static SmallVector<SemaOpenMP::CapturedParamNameType>
4426static SmallVector<SemaOpenMP::CapturedParamNameType>
4436 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4438 std::make_pair(
".global_tid.", KmpInt32Ty),
4439 std::make_pair(
".part_id.", KmpInt32PtrTy),
4440 std::make_pair(
".privates.", VoidPtrTy),
4443 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4444 std::make_pair(
".task_t.", Context.VoidPtrTy.withConst()),
4445 std::make_pair(StringRef(),
QualType())
4450static SmallVector<SemaOpenMP::CapturedParamNameType>
4456 Params.push_back(std::make_pair(StringRef(
"dyn_ptr"), VoidPtrTy));
4459 Params.push_back(std::make_pair(StringRef(),
QualType()));
4463static SmallVector<SemaOpenMP::CapturedParamNameType>
4466 std::make_pair(StringRef(),
QualType())
4471static SmallVector<SemaOpenMP::CapturedParamNameType>
4475 Context.getIntTypeForBitwidth(32, 1).
withConst();
4477 Context.getIntTypeForBitwidth(64, 0).
withConst();
4479 Context.getIntTypeForBitwidth(64, 1).
withConst();
4486 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4488 std::make_pair(
".global_tid.", KmpInt32Ty),
4489 std::make_pair(
".part_id.", KmpInt32PtrTy),
4490 std::make_pair(
".privates.", VoidPtrTy),
4493 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4494 std::make_pair(
".task_t.", Context.VoidPtrTy.withConst()),
4495 std::make_pair(
".lb.", KmpUInt64Ty),
4496 std::make_pair(
".ub.", KmpUInt64Ty),
4497 std::make_pair(
".st.", KmpInt64Ty),
4498 std::make_pair(
".liter.", KmpInt32Ty),
4499 std::make_pair(
".reductions.", VoidPtrTy),
4500 std::make_pair(StringRef(),
QualType())
4513 CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
4514 SemaRef.
getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
4517 for (
auto [Level, RKind] : llvm::enumerate(Regions)) {
4552 case OMPD_metadirective:
4555 llvm_unreachable(
"Unexpected capture region");
4572 case OMPD_interchange:
4586int SemaOpenMP::getNumberOfConstructScopes(
unsigned Level)
const {
4587 return getOpenMPCaptureLevels(
DSAStack->getDirective(Level));
4593 return CaptureRegions.size();
4597 Expr *CaptureExpr,
bool WithInit,
4599 bool AsExpression) {
4600 assert(CaptureExpr);
4606 Ty =
C.getLValueReferenceType(Ty);
4608 Ty =
C.getPointerType(Ty);
4620 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(
C));
4670class CaptureRegionUnwinderRAII {
4677 CaptureRegionUnwinderRAII(Sema &S,
bool &ErrorFound,
4679 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4680 ~CaptureRegionUnwinderRAII() {
4683 while (--ThisCaptureLevel >= 0)
4693 if (!
SemaRef.CurContext->isDependentContext() &&
4696 DSAStack->getCurrentDirective()))) {
4698 if (
const auto *RD =
Type.getCanonicalType()
4699 .getNonReferenceType()
4701 bool SavedForceCaptureByReferenceInTargetExecutable =
4702 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4703 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4705 if (RD->isLambda()) {
4706 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4708 RD->getCaptureFields(Captures, ThisCapture);
4715 SemaRef.MarkVariableReferenced(LC.getLocation(), VD);
4716 }
else if (LC.getCaptureKind() ==
LCK_This) {
4719 ThisTy, ThisCapture->
getType()))
4720 SemaRef.CheckCXXThisCapture(LC.getLocation());
4724 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4725 SavedForceCaptureByReferenceInTargetExecutable);
4735 for (
const OMPClause *Clause : Clauses) {
4736 if (Clause->getClauseKind() == OMPC_ordered)
4738 else if (Clause->getClauseKind() == OMPC_order) {
4740 if (Order->
getKind() != OMPC_ORDER_concurrent)
4743 if (Ordered && Order)
4747 if (Ordered && Order) {
4749 diag::err_omp_simple_clause_incompatible_with_ordered)
4767 bool ErrorFound =
false;
4768 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4785 DSAStack->getCurrentDirective() == OMPD_target) &&
4786 Clause->getClauseKind() == OMPC_in_reduction) {
4790 for (
Expr *E : IRC->taskgroup_descriptors())
4792 SemaRef.MarkDeclarationsReferencedInExpr(E);
4795 Clause->getClauseKind() == OMPC_copyprivate ||
4798 Clause->getClauseKind() == OMPC_copyin)) {
4799 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4802 if (
auto *E = cast_or_null<Expr>(VarRef)) {
4803 SemaRef.MarkDeclarationsReferencedInExpr(E);
4806 DSAStack->setForceVarCapturing(
false);
4807 }
else if (CaptureRegions.size() > 1 ||
4808 CaptureRegions.back() != OMPD_unknown) {
4812 if (
Expr *E =
C->getPostUpdateExpr())
4813 SemaRef.MarkDeclarationsReferencedInExpr(E);
4816 if (Clause->getClauseKind() == OMPC_schedule)
4818 else if (Clause->getClauseKind() == OMPC_ordered)
4820 else if (Clause->getClauseKind() == OMPC_linear)
4825 SemaRef.MarkDeclarationsReferencedInExpr(E);
4832 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4837 diag::err_omp_simple_clause_incompatible_with_ordered)
4840 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4851 Diag(
C->getBeginLoc(), diag::err_omp_linear_ordered)
4861 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(), OMPVersion);
4868 unsigned CompletedRegions = 0;
4873 if (ThisCaptureRegion != OMPD_unknown) {
4881 if (CaptureRegion == ThisCaptureRegion ||
4882 CaptureRegion == OMPD_unknown) {
4883 if (
auto *DS = cast_or_null<DeclStmt>(
C->getPreInitStmt())) {
4884 for (
Decl *D : DS->decls())
4891 if (ThisCaptureRegion == OMPD_target) {
4895 if (
const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(
C)) {
4896 for (
unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4900 SemaRef.MarkDeclarationsReferencedInExpr(E);
4906 if (ThisCaptureRegion == OMPD_parallel) {
4910 if (
auto *RC = dyn_cast<OMPReductionClause>(
C)) {
4911 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4913 for (
Expr *E : RC->copy_array_temps())
4915 SemaRef.MarkDeclarationsReferencedInExpr(E);
4917 if (
auto *AC = dyn_cast<OMPAlignedClause>(
C)) {
4918 for (
Expr *E : AC->varlist())
4919 SemaRef.MarkDeclarationsReferencedInExpr(E);
4923 if (++CompletedRegions == CaptureRegions.size())
4925 SR =
SemaRef.ActOnCapturedRegionEnd(SR.
get());
4934 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4937 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4938 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4941 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
4942 SemaRef.
Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4943 << getOpenMPDirectiveName(CancelRegion, OMPVersion);
4953 if (!Stack->getCurScope())
4958 bool NestingProhibited =
false;
4959 bool CloseNesting =
true;
4960 bool OrphanSeen =
false;
4963 ShouldBeInParallelRegion,
4964 ShouldBeInOrderedRegion,
4965 ShouldBeInTargetRegion,
4966 ShouldBeInTeamsRegion,
4967 ShouldBeInLoopSimdRegion,
4968 } Recommend = NoRecommend;
4972 getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
4974 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
4976 if (OMPVersion >= 50 && Stack->isParentOrderConcurrent() &&
4979 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_order)
4980 << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
4984 ((OMPVersion <= 45 && CurrentRegion != OMPD_ordered) ||
4985 (OMPVersion >= 50 && CurrentRegion != OMPD_ordered &&
4986 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
4987 CurrentRegion != OMPD_scan))) {
5000 SemaRef.
Diag(StartLoc, (CurrentRegion != OMPD_simd)
5001 ? diag::err_omp_prohibited_region_simd
5002 : diag::warn_omp_nesting_simd)
5003 << (OMPVersion >= 50 ? 1 : 0);
5004 return CurrentRegion != OMPD_simd;
5006 if (EnclosingConstruct == OMPD_atomic) {
5009 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
5012 if (CurrentRegion == OMPD_section) {
5017 if (EnclosingConstruct != OMPD_sections) {
5018 SemaRef.
Diag(StartLoc, diag::err_omp_orphaned_section_directive)
5019 << (ParentRegion != OMPD_unknown)
5020 << getOpenMPDirectiveName(ParentRegion, OMPVersion);
5028 if (ParentRegion == OMPD_unknown &&
5030 CurrentRegion != OMPD_cancellation_point &&
5031 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
5035 if (OMPVersion >= 50 && CurrentRegion == OMPD_loop &&
5036 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
5038 EnclosingConstruct == OMPD_loop)) {
5039 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
5040 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region)
5041 <<
true << getOpenMPDirectiveName(ParentRegion, OMPVersion)
5042 << ErrorMsgNumber << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5045 if (CurrentRegion == OMPD_cancellation_point ||
5046 CurrentRegion == OMPD_cancel) {
5059 if (CancelRegion == OMPD_taskgroup) {
5061 EnclosingConstruct != OMPD_task &&
5062 (OMPVersion < 50 || EnclosingConstruct != OMPD_taskloop);
5063 }
else if (CancelRegion == OMPD_sections) {
5064 NestingProhibited = EnclosingConstruct != OMPD_section &&
5065 EnclosingConstruct != OMPD_sections;
5067 NestingProhibited = CancelRegion != Leafs.back();
5069 OrphanSeen = ParentRegion == OMPD_unknown;
5070 }
else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5077 }
else if (CurrentRegion == OMPD_critical && CurrentName.
getName()) {
5083 bool DeadLock = Stack->hasDirective(
5087 if (K == OMPD_critical && DNI.
getName() == CurrentName.
getName()) {
5088 PreviousCriticalLoc = Loc;
5095 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name)
5097 if (PreviousCriticalLoc.
isValid())
5098 SemaRef.
Diag(PreviousCriticalLoc,
5099 diag::note_omp_previous_critical_region);
5102 }
else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
5112 llvm::is_contained({OMPD_masked, OMPD_master,
5113 OMPD_critical, OMPD_ordered},
5114 EnclosingConstruct);
5125 llvm::is_contained({OMPD_masked, OMPD_master,
5126 OMPD_critical, OMPD_ordered},
5127 EnclosingConstruct);
5128 Recommend = ShouldBeInParallelRegion;
5129 }
else if (CurrentRegion == OMPD_ordered) {
5138 NestingProhibited = EnclosingConstruct == OMPD_critical ||
5141 Stack->isParentOrderedRegion());
5142 Recommend = ShouldBeInOrderedRegion;
5148 (OMPVersion <= 45 && EnclosingConstruct != OMPD_target) ||
5149 (OMPVersion >= 50 && EnclosingConstruct != OMPD_unknown &&
5150 EnclosingConstruct != OMPD_target);
5151 OrphanSeen = ParentRegion == OMPD_unknown;
5152 Recommend = ShouldBeInTargetRegion;
5153 }
else if (CurrentRegion == OMPD_scan) {
5154 if (OMPVersion >= 50) {
5159 NestingProhibited = !llvm::is_contained(
5160 {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
5162 NestingProhibited =
true;
5164 OrphanSeen = ParentRegion == OMPD_unknown;
5165 Recommend = ShouldBeInLoopSimdRegion;
5169 EnclosingConstruct == OMPD_teams) {
5181 CurrentRegion != OMPD_loop &&
5183 CurrentRegion == OMPD_atomic);
5184 Recommend = ShouldBeInParallelRegion;
5186 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5192 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5193 Recommend = ShouldBeInTeamsRegion;
5199 NestingProhibited = EnclosingConstruct != OMPD_teams;
5200 Recommend = ShouldBeInTeamsRegion;
5202 if (!NestingProhibited &&
5209 NestingProhibited = Stack->hasDirective(
5213 OffendingRegion = K;
5219 CloseNesting =
false;
5221 if (NestingProhibited) {
5223 SemaRef.
Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5224 << getOpenMPDirectiveName(CurrentRegion, OMPVersion) << Recommend;
5226 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region)
5227 << CloseNesting << getOpenMPDirectiveName(OffendingRegion, OMPVersion)
5228 << Recommend << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5242 bool ErrorFound =
false;
5243 unsigned NamedModifiersNumber = 0;
5244 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5245 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5249 if (
const auto *IC = dyn_cast_or_null<OMPIfClause>(
C)) {
5253 auto &FNM = FoundNameModifiers[CurNM];
5255 S.
Diag(
C->getBeginLoc(), diag::err_omp_more_one_clause)
5256 << getOpenMPDirectiveName(Kind, OMPVersion)
5258 << getOpenMPDirectiveName(CurNM, OMPVersion);
5260 }
else if (CurNM != OMPD_unknown) {
5261 NameModifierLoc.push_back(IC->getNameModifierLoc());
5262 ++NamedModifiersNumber;
5265 if (CurNM == OMPD_unknown)
5271 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5272 S.
Diag(IC->getNameModifierLoc(),
5273 diag::err_omp_wrong_if_directive_name_modifier)
5274 << getOpenMPDirectiveName(CurNM, OMPVersion)
5275 << getOpenMPDirectiveName(Kind, OMPVersion);
5282 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5283 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5284 S.
Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5285 diag::err_omp_no_more_if_clause);
5288 std::string Sep(
", ");
5289 unsigned AllowedCnt = 0;
5290 unsigned TotalAllowedNum =
5291 AllowedNameModifiers.size() - NamedModifiersNumber;
5292 for (
unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5295 if (!FoundNameModifiers[NM]) {
5297 Values += getOpenMPDirectiveName(NM, OMPVersion);
5299 if (AllowedCnt + 2 == TotalAllowedNum)
5301 else if (AllowedCnt + 1 != TotalAllowedNum)
5306 S.
Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5307 diag::err_omp_unnamed_if_clause)
5308 << (TotalAllowedNum > 1) << Values;
5311 S.
Diag(Loc, diag::note_omp_previous_named_if_clause);
5318static std::pair<ValueDecl *, bool>
5321 bool AllowAssumedSizeArray, StringRef DiagType) {
5324 return std::make_pair(
nullptr,
true);
5350 } IsArrayExpr = NoArrayExpr;
5351 if (AllowArraySection) {
5352 if (
auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5353 Expr *
Base = ASE->getBase()->IgnoreParenImpCasts();
5354 while (
auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
5355 Base = TempASE->getBase()->IgnoreParenImpCasts();
5358 }
else if (
auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5359 Expr *
Base = OASE->getBase()->IgnoreParenImpCasts();
5360 if (S.
getLangOpts().OpenMP >= 60 && !AllowAssumedSizeArray &&
5361 OASE->getColonLocFirst().isValid() && !OASE->getLength()) {
5363 if (BaseType.isNull() || (!BaseType->isConstantArrayType() &&
5364 !BaseType->isVariableArrayType())) {
5365 S.
Diag(OASE->getColonLocFirst(),
5366 diag::err_omp_section_length_undefined)
5367 << (!BaseType.isNull() && BaseType->isArrayType());
5368 return std::make_pair(
nullptr,
false);
5371 while (
auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base))
5372 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5373 while (
auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
5374 Base = TempASE->getBase()->IgnoreParenImpCasts();
5376 IsArrayExpr = OMPArraySection;
5382 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5383 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5388 if (IsArrayExpr != NoArrayExpr) {
5389 S.
Diag(ELoc, diag::err_omp_expected_base_var_name)
5390 << IsArrayExpr << ERange;
5391 }
else if (!DiagType.empty()) {
5395 S.
Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5396 << DiagSelect << DiagType << ERange;
5400 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5401 : diag::err_omp_expected_var_name_member_expr)
5404 return std::make_pair(
nullptr,
false);
5406 return std::make_pair(
5413class AllocatorChecker final :
public ConstStmtVisitor<AllocatorChecker, bool> {
5414 DSAStackTy *S =
nullptr;
5417 bool VisitDeclRefExpr(
const DeclRefExpr *E) {
5418 return S->isUsesAllocatorsDecl(E->
getDecl())
5419 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5420 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5422 bool VisitStmt(
const Stmt *S) {
5423 for (
const Stmt *Child : S->
children()) {
5424 if (Child && Visit(Child))
5429 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5436 "Expected non-dependent context.");
5437 auto AllocateRange =
5440 auto PrivateRange = llvm::make_filter_range(Clauses, [](
const OMPClause *
C) {
5445 if (
Cl->getClauseKind() == OMPC_private) {
5447 I = PC->private_copies().begin();
5448 It = PC->varlist_begin();
5449 Et = PC->varlist_end();
5450 }
else if (
Cl->getClauseKind() == OMPC_firstprivate) {
5452 I = PC->private_copies().begin();
5453 It = PC->varlist_begin();
5454 Et = PC->varlist_end();
5455 }
else if (
Cl->getClauseKind() == OMPC_lastprivate) {
5457 I = PC->private_copies().begin();
5458 It = PC->varlist_begin();
5459 Et = PC->varlist_end();
5460 }
else if (
Cl->getClauseKind() == OMPC_linear) {
5462 I = PC->privates().begin();
5463 It = PC->varlist_begin();
5464 Et = PC->varlist_end();
5465 }
else if (
Cl->getClauseKind() == OMPC_reduction) {
5467 I = PC->privates().begin();
5468 It = PC->varlist_begin();
5469 Et = PC->varlist_end();
5470 }
else if (
Cl->getClauseKind() == OMPC_task_reduction) {
5472 I = PC->privates().begin();
5473 It = PC->varlist_begin();
5474 Et = PC->varlist_end();
5475 }
else if (
Cl->getClauseKind() == OMPC_in_reduction) {
5477 I = PC->privates().begin();
5478 It = PC->varlist_begin();
5479 Et = PC->varlist_end();
5481 llvm_unreachable(
"Expected private clause.");
5483 for (
Expr *E : llvm::make_range(It, Et)) {
5490 Expr *SimpleRefExpr = E;
5493 DeclToCopy.try_emplace(Res.first,
5503 AC->getAllocator()) {
5504 Expr *Allocator = AC->getAllocator();
5510 AllocatorChecker Checker(Stack);
5511 if (Checker.Visit(Allocator))
5513 diag::err_omp_allocator_not_in_uses_allocators)
5516 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5522 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5526 S.
Diag(AC->getAllocator()->getExprLoc(),
5527 diag::warn_omp_allocate_thread_on_task_target_directive)
5528 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
5530 for (
Expr *E : AC->varlist()) {
5533 Expr *SimpleRefExpr = E;
5538 DSAStackTy::DSAVarData
Data = Stack->getTopDSA(VD,
false);
5541 diag::err_omp_expected_private_copy_for_allocate);
5544 VarDecl *PrivateVD = DeclToCopy[VD];
5546 AllocatorKind, AC->getAllocator()))
5560class CaptureVars :
public TreeTransform<CaptureVars> {
5561 using BaseTransform = TreeTransform<CaptureVars>;
5564 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5566 bool AlwaysRebuild() {
return true; }
5579 BodyStmts.push_back(NewDeclStmt);
5617 DistParam, LogicalTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
5628 auto BuildVarRef = [&](
VarDecl *VD) {
5633 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 0), LogicalTy, {});
5635 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 1), LogicalTy, {});
5641 Actions.
BuildBinOp(
nullptr, {}, BO_LT, BuildVarRef(NewStep),
Zero));
5645 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5649 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5653 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5657 Actions.
BuildUnaryOp(
nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5659 Actions.
BuildBinOp(
nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5663 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5665 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5666 "Expected one of these relational operators");
5673 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5677 if (Rel == BO_GE || Rel == BO_GT)
5679 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5682 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5688 if (Rel == BO_LE || Rel == BO_GE) {
5700 Expr *Divisor = BuildVarRef(NewStep);
5701 if (Rel == BO_GE || Rel == BO_GT)
5704 Expr *DivisorMinusOne =
5707 Actions.
BuildBinOp(
nullptr, {}, BO_Add, Range, DivisorMinusOne));
5709 Actions.
BuildBinOp(
nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5719 Actions.
getCurScope(), {}, BO_Assign, DistRef, Dist));
5720 BodyStmts.push_back(ResultAssign);
5752 {
"Logical", LogicalTy},
5763 assert(!
Invalid &&
"Expecting capture-by-value to work.");
5772 TargetParam, LoopVarTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
5775 IndvarParam, LogicalTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
5778 CaptureVars Recap(Actions);
5783 Actions.
BuildBinOp(
nullptr, {}, BO_Mul, NewStep, LogicalRef));
5798 BO_Assign, TargetRef, Advanced));
5811 if (
auto *For = dyn_cast<ForStmt>(AStmt)) {
5813 if (
auto *LCVarDeclStmt = dyn_cast<DeclStmt>(
Init)) {
5816 }
else if (
auto *LCAssign = dyn_cast<BinaryOperator>(
Init)) {
5818 assert(LCAssign->getOpcode() == BO_Assign &&
5819 "init part must be a loop variable assignment");
5823 llvm_unreachable(
"Cannot determine loop variable");
5826 Cond = For->getCond();
5827 Inc = For->getInc();
5828 }
else if (
auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5829 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5831 LUVDecl = RangeFor->getLoopVariable();
5833 Cond = RangeFor->getCond();
5834 Inc = RangeFor->getInc();
5836 llvm_unreachable(
"unhandled kind of loop");
5845 if (
auto *CondBinExpr = dyn_cast<BinaryOperator>(
Cond)) {
5846 LHS = CondBinExpr->getLHS();
5847 RHS = CondBinExpr->getRHS();
5848 CondRel = CondBinExpr->getOpcode();
5849 }
else if (
auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(
Cond)) {
5850 assert(CondCXXOp->getNumArgs() == 2 &&
"Comparison should have 2 operands");
5851 LHS = CondCXXOp->getArg(0);
5852 RHS = CondCXXOp->getArg(1);
5853 switch (CondCXXOp->getOperator()) {
5854 case OO_ExclaimEqual:
5866 case OO_GreaterEqual:
5870 llvm_unreachable(
"unexpected iterator operator");
5873 llvm_unreachable(
"unexpected loop condition");
5878 std::swap(LHS, RHS);
5895 if (
auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5897 switch (IncUn->getOpcode()) {
5907 llvm_unreachable(
"unhandled unary increment operator");
5911 llvm::APInt(Ctx.
getIntWidth(LogicalTy), Direction,
true),
5913 }
else if (
auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5914 if (IncBin->getOpcode() == BO_AddAssign) {
5915 Step = IncBin->getRHS();
5916 }
else if (IncBin->getOpcode() == BO_SubAssign) {
5918 SemaRef.BuildUnaryOp(
nullptr, {}, UO_Minus, IncBin->getRHS()));
5920 llvm_unreachable(
"unhandled binary increment operator");
5921 }
else if (
auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5922 switch (CondCXXOp->getOperator()) {
5925 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 1), LogicalTy, {});
5929 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), -1), LogicalTy, {});
5932 Step = CondCXXOp->getArg(1);
5936 SemaRef.BuildUnaryOp(
nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5939 llvm_unreachable(
"unhandled overloaded increment operator");
5942 llvm_unreachable(
"unknown increment expression");
5950 nullptr,
nullptr, {},
nullptr);
5951 return OMPCanonicalLoop::create(
getASTContext(), AStmt, DistanceFunc,
5952 LoopVarFunc, LVRef);
5964 "Loop transformation directive expected");
5965 return LoopTransform;
5972 Expr *UnresolvedMapper);
5983 for (
int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
5984 auto *
C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
5988 auto *MI =
C->mapperlist_begin();
5989 for (
auto I =
C->varlist_begin(), End =
C->varlist_end(); I != End;
6008 if (
const auto *ATy = BaseType->getAsArrayTypeUnsafe())
6009 ElemType = ATy->getElementType();
6012 CanonType = ElemType;
6017 1, {CanonType,
nullptr});
6018 llvm::DenseMap<const Type *, Expr *> Visited;
6021 while (!Types.empty()) {
6024 std::tie(BaseType, CurFD) = Types.pop_back_val();
6025 while (ParentChain.back().second == 0)
6026 ParentChain.pop_back();
6027 --ParentChain.back().second;
6028 if (BaseType.isNull())
6031 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
6034 auto It = Visited.find(BaseType.getTypePtr());
6035 if (It == Visited.end()) {
6043 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
6047 It = Visited.try_emplace(BaseType.getTypePtr(), ER.
get()).first;
6054 Expr *BaseExpr = OE;
6055 for (
const auto &P : ParentChain) {
6073 SubExprs.push_back(BaseExpr);
6077 bool FirstIter =
true;
6087 ParentChain.emplace_back(CurFD, 1);
6089 ++ParentChain.back().second;
6091 Types.emplace_back(FieldTy, FD);
6095 if (SubExprs.empty())
6100 nullptr,
C->getMapTypeModifiers(),
C->getMapTypeModifiersLoc(),
6101 MapperIdScopeSpec, MapperId,
C->getMapType(),
6104 Clauses.push_back(NewClause);
6111class TeamsLoopChecker final :
public ConstStmtVisitor<TeamsLoopChecker> {
6118 void VisitOMPExecutableDirective(
const OMPExecutableDirective *D) {
6119 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
6120 if (
const auto *
C = D->getSingleClause<OMPBindClause>())
6121 if (
C->getBindKind() == OMPC_BIND_parallel) {
6122 TeamsLoopCanBeParallelFor =
false;
6127 for (
const Stmt *Child : D->children())
6132 void VisitCallExpr(
const CallExpr *
C) {
6137 bool IsOpenMPAPI =
false;
6138 auto *FD = dyn_cast_or_null<FunctionDecl>(
C->getCalleeDecl());
6140 std::string Name = FD->getNameInfo().getAsString();
6141 IsOpenMPAPI = Name.find(
"omp_") == 0;
6143 TeamsLoopCanBeParallelFor =
6144 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
6145 if (!TeamsLoopCanBeParallelFor)
6148 for (
const Stmt *Child :
C->children())
6153 void VisitCapturedStmt(
const CapturedStmt *S) {
6159 void VisitStmt(
const Stmt *S) {
6162 for (
const Stmt *Child : S->
children())
6166 explicit TeamsLoopChecker(Sema &SemaRef)
6167 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(
true) {}
6170 bool TeamsLoopCanBeParallelFor;
6175 TeamsLoopChecker Checker(SemaRef);
6176 Checker.Visit(AStmt);
6177 return Checker.teamsLoopCanBeParallelFor();
6191 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6192 BindKind = BC->getBindKind();
6204 BindKind = OMPC_BIND_thread;
6206 getLeafConstructsOrSelf(ParentDirective);
6208 if (ParentDirective == OMPD_unknown) {
6210 diag::err_omp_bind_required_on_loop);
6211 }
else if (ParentLeafs.back() == OMPD_parallel) {
6212 BindKind = OMPC_BIND_parallel;
6213 }
else if (ParentLeafs.back() == OMPD_teams) {
6214 BindKind = OMPC_BIND_teams;
6222 ClausesWithImplicit.push_back(
C);
6226 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6228 if (
C->getClauseKind() == OMPC_reduction)
6230 diag::err_omp_loop_reduction_clause);
6237 BindKind, StartLoc)) {
6244 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6247 bool ErrorFound =
false;
6248 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6250 if (AStmt && !
SemaRef.CurContext->isDependentContext() &&
6258 while (--ThisCaptureLevel >= 0)
6260 DSAChecker.Visit(S);
6268 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6270 DSAChecker.visitSubCaptures(CS);
6272 if (DSAChecker.isErrorFound())
6275 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6276 VariableImplicitInfo ImpInfo = DSAChecker.getImplicitInfo();
6279 ImplicitMapModifiersLoc[VariableImplicitInfo::DefaultmapKindNum];
6281 SourceLocation PresentModifierLocs[VariableImplicitInfo::DefaultmapKindNum];
6283 if (
auto *DMC = dyn_cast<OMPDefaultmapClause>(
C))
6284 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6285 PresentModifierLocs[DMC->getDefaultmapKind()] =
6286 DMC->getDefaultmapModifierLoc();
6290 llvm::enum_seq_inclusive<OpenMPDefaultmapClauseKind>(
6292 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[K]),
6293 ImpInfo.MapModifiers[K].size(), PresentModifierLocs[K]);
6297 if (
auto *IRC = dyn_cast<OMPInReductionClause>(
C)) {
6298 for (
Expr *E : IRC->taskgroup_descriptors())
6300 ImpInfo.Firstprivates.insert(E);
6305 if (
auto *DC = dyn_cast<OMPDetachClause>(
C))
6306 ImpInfo.Firstprivates.insert(DC->getEventHandler());
6308 if (!ImpInfo.Firstprivates.empty()) {
6312 ClausesWithImplicit.push_back(
Implicit);
6314 ImpInfo.Firstprivates.size();
6319 if (!ImpInfo.Privates.empty()) {
6323 ClausesWithImplicit.push_back(
Implicit);
6325 ImpInfo.Privates.size();
6334 if (
getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6338 if (
auto *RC = dyn_cast<OMPReductionClause>(
C))
6339 for (
Expr *E : RC->varlist())
6341 ImplicitExprs.emplace_back(E);
6343 if (!ImplicitExprs.empty()) {
6349 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6352 ClausesWithImplicit.emplace_back(
Implicit);
6355 for (
unsigned I = 0; I < VariableImplicitInfo::DefaultmapKindNum; ++I) {
6356 int ClauseKindCnt = -1;
6357 for (
unsigned J = 0; J < VariableImplicitInfo::MapKindNum; ++J) {
6360 if (ImplicitMap.empty())
6366 nullptr, ImpInfo.MapModifiers[I], ImplicitMapModifiersLoc[I],
6367 MapperIdScopeSpec, MapperId, K,
true,
6370 ClausesWithImplicit.emplace_back(
Implicit);
6382 ClausesWithImplicit);
6392 VarsWithInheritedDSA);
6407 assert(ClausesWithImplicit.empty() &&
6408 "reverse directive does not support any clauses");
6411 case OMPD_interchange:
6421 VarsWithInheritedDSA);
6425 EndLoc, VarsWithInheritedDSA);
6432 assert(ClausesWithImplicit.empty() &&
6433 "No clauses are allowed for 'omp section' directive");
6441 assert(ClausesWithImplicit.empty() &&
6442 "No clauses are allowed for 'omp master' directive");
6453 case OMPD_parallel_for:
6455 EndLoc, VarsWithInheritedDSA);
6457 case OMPD_parallel_for_simd:
6459 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6465 case OMPD_parallel_master:
6469 case OMPD_parallel_masked:
6473 case OMPD_parallel_sections:
6481 case OMPD_taskyield:
6482 assert(ClausesWithImplicit.empty() &&
6483 "No clauses are allowed for 'omp taskyield' directive");
6484 assert(AStmt ==
nullptr &&
6485 "No associated statement allowed for 'omp taskyield' directive");
6489 assert(AStmt ==
nullptr &&
6490 "No associated statement allowed for 'omp error' directive");
6494 assert(ClausesWithImplicit.empty() &&
6495 "No clauses are allowed for 'omp barrier' directive");
6496 assert(AStmt ==
nullptr &&
6497 "No associated statement allowed for 'omp barrier' directive");
6501 assert(AStmt ==
nullptr &&
6502 "No associated statement allowed for 'omp taskwait' directive");
6505 case OMPD_taskgroup:
6510 assert(AStmt ==
nullptr &&
6511 "No associated statement allowed for 'omp flush' directive");
6515 assert(AStmt ==
nullptr &&
6516 "No associated statement allowed for 'omp depobj' directive");
6520 assert(AStmt ==
nullptr &&
6521 "No associated statement allowed for 'omp scan' directive");
6540 case OMPD_target_parallel:
6544 case OMPD_target_parallel_for:
6546 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6548 case OMPD_cancellation_point:
6549 assert(ClausesWithImplicit.empty() &&
6550 "No clauses are allowed for 'omp cancellation point' directive");
6551 assert(AStmt ==
nullptr &&
"No associated statement allowed for 'omp "
6552 "cancellation point' directive");
6556 assert(AStmt ==
nullptr &&
6557 "No associated statement allowed for 'omp cancel' directive");
6561 case OMPD_target_data:
6565 case OMPD_target_enter_data:
6569 case OMPD_target_exit_data:
6575 EndLoc, VarsWithInheritedDSA);
6577 case OMPD_taskloop_simd:
6579 EndLoc, VarsWithInheritedDSA);
6581 case OMPD_master_taskloop:
6583 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6585 case OMPD_masked_taskloop:
6587 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6589 case OMPD_master_taskloop_simd:
6591 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6593 case OMPD_masked_taskloop_simd:
6595 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6597 case OMPD_parallel_master_taskloop:
6599 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6601 case OMPD_parallel_masked_taskloop:
6603 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6605 case OMPD_parallel_master_taskloop_simd:
6607 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6609 case OMPD_parallel_masked_taskloop_simd:
6611 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6613 case OMPD_distribute:
6615 EndLoc, VarsWithInheritedDSA);
6617 case OMPD_target_update:
6621 case OMPD_distribute_parallel_for:
6623 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6625 case OMPD_distribute_parallel_for_simd:
6627 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6629 case OMPD_distribute_simd:
6631 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6633 case OMPD_target_parallel_for_simd:
6635 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6637 case OMPD_target_simd:
6639 EndLoc, VarsWithInheritedDSA);
6641 case OMPD_teams_distribute:
6643 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6645 case OMPD_teams_distribute_simd:
6647 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6649 case OMPD_teams_distribute_parallel_for_simd:
6651 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6653 case OMPD_teams_distribute_parallel_for:
6655 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6657 case OMPD_target_teams:
6661 case OMPD_target_teams_distribute:
6663 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6665 case OMPD_target_teams_distribute_parallel_for:
6667 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6669 case OMPD_target_teams_distribute_parallel_for_simd:
6671 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6673 case OMPD_target_teams_distribute_simd:
6675 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6678 assert(AStmt ==
nullptr &&
6679 "No associated statement allowed for 'omp interop' directive");
6688 EndLoc, VarsWithInheritedDSA);
6690 case OMPD_teams_loop:
6692 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6694 case OMPD_target_teams_loop:
6696 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6698 case OMPD_parallel_loop:
6700 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6702 case OMPD_target_parallel_loop:
6704 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6706 case OMPD_declare_target:
6707 case OMPD_end_declare_target:
6708 case OMPD_threadprivate:
6710 case OMPD_declare_reduction:
6711 case OMPD_declare_mapper:
6712 case OMPD_declare_simd:
6714 case OMPD_declare_variant:
6715 case OMPD_begin_declare_variant:
6716 case OMPD_end_declare_variant:
6717 llvm_unreachable(
"OpenMP Directive is not allowed");
6720 llvm_unreachable(
"Unknown OpenMP directive");
6723 ErrorFound = Res.
isInvalid() || ErrorFound;
6727 if (
DSAStack->getDefaultDSA() == DSA_none ||
6728 DSAStack->getDefaultDSA() == DSA_private ||
6729 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6732 switch (
C->getClauseKind()) {
6733 case OMPC_num_threads:
6734 case OMPC_dist_schedule:
6751 case OMPC_grainsize:
6752 case OMPC_num_tasks:
6755 case OMPC_novariants:
6756 case OMPC_nocontext:
6763 case OMPC_num_teams:
6764 case OMPC_thread_limit:
6771 case OMPC_proc_bind:
6773 case OMPC_firstprivate:
6774 case OMPC_lastprivate:
6776 case OMPC_reduction:
6777 case OMPC_task_reduction:
6778 case OMPC_in_reduction:
6782 case OMPC_copyprivate:
6785 case OMPC_mergeable:
6802 case OMPC_defaultmap:
6805 case OMPC_use_device_ptr:
6806 case OMPC_use_device_addr:
6807 case OMPC_is_device_ptr:
6808 case OMPC_has_device_addr:
6809 case OMPC_nontemporal:
6812 case OMPC_inclusive:
6813 case OMPC_exclusive:
6814 case OMPC_uses_allocators:
6821 case OMPC_allocator:
6824 case OMPC_threadprivate:
6825 case OMPC_groupprivate:
6828 case OMPC_unified_address:
6829 case OMPC_unified_shared_memory:
6830 case OMPC_reverse_offload:
6831 case OMPC_dynamic_allocators:
6832 case OMPC_atomic_default_mem_order:
6833 case OMPC_self_maps:
6834 case OMPC_device_type:
6839 llvm_unreachable(
"Unexpected clause");
6841 for (
Stmt *CC :
C->children()) {
6843 DSAChecker.Visit(CC);
6846 for (
const auto &P : DSAChecker.getVarsWithInheritedDSA())
6847 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6849 for (
const auto &P : VarsWithInheritedDSA) {
6853 if (
DSAStack->getDefaultDSA() == DSA_none ||
6854 DSAStack->getDefaultDSA() == DSA_private ||
6855 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6856 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6857 << P.first << P.second->getSourceRange();
6858 Diag(
DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6860 Diag(P.second->getExprLoc(),
6861 diag::err_omp_defaultmap_no_attr_for_variable)
6862 << P.first << P.second->getSourceRange();
6864 diag::note_omp_defaultmap_attr_none);
6870 if (isAllowedClauseForDirective(D, OMPC_if,
getLangOpts().OpenMP))
6871 AllowedNameModifiers.push_back(D);
6873 if (!AllowedNameModifiers.empty())
6880 if (!
SemaRef.CurContext->isDependentContext() &&
6887 DSAStack->addTargetDirLocation(StartLoc);
6898 assert(Aligneds.size() == Alignments.size());
6899 assert(Linears.size() == LinModifiers.size());
6900 assert(Linears.size() == Steps.size());
6904 const int SimdId = 0;
6906 Diag(SR.
getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6911 if (
auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6912 ADecl = FTD->getTemplatedDecl();
6914 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6916 Diag(ADecl->
getLocation(), diag::err_omp_function_expected) << SimdId;
6932 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6933 const Expr *UniformedLinearThis =
nullptr;
6934 for (
const Expr *E : Uniforms) {
6936 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E))
6937 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
6938 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6939 FD->getParamDecl(PVD->getFunctionScopeIndex())
6941 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
6945 UniformedLinearThis = E;
6959 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6960 const Expr *AlignedThis =
nullptr;
6961 for (
const Expr *E : Aligneds) {
6963 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E))
6964 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6966 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6967 FD->getParamDecl(PVD->getFunctionScopeIndex())
6971 auto [It, Inserted] = AlignedArgs.try_emplace(CanonPVD, E);
6976 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
6981 .getNonReferenceType()
6982 .getUnqualifiedType()
6983 .getCanonicalType();
6986 Diag(E->
getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
6988 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
7012 for (
Expr *E : Alignments) {
7016 NewAligns.push_back(Align.
get());
7027 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
7028 const bool IsUniformedThis = UniformedLinearThis !=
nullptr;
7029 auto MI = LinModifiers.begin();
7030 for (
const Expr *E : Linears) {
7034 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E))
7035 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7037 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7038 FD->getParamDecl(PVD->getFunctionScopeIndex())
7042 if (
auto It = LinearArgs.find(CanonPVD); It != LinearArgs.end()) {
7047 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7052 if (
auto It = UniformedArgs.find(CanonPVD);
7053 It != UniformedArgs.end()) {
7058 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7062 LinearArgs[CanonPVD] = E;
7068 PVD->getOriginalType(),
7074 if (UniformedLinearThis) {
7080 Diag(UniformedLinearThis->
getExprLoc(), diag::note_omp_explicit_dsa)
7085 UniformedLinearThis = E;
7096 Expr *Step =
nullptr;
7097 Expr *NewStep =
nullptr;
7099 for (
Expr *E : Steps) {
7101 if (Step == E || !E) {
7102 NewSteps.push_back(E ? NewStep :
nullptr);
7106 if (
const auto *DRE = dyn_cast<DeclRefExpr>(Step))
7107 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7109 if (UniformedArgs.count(CanonPVD) == 0) {
7116 NewSteps.push_back(Step);
7131 .VerifyIntegerConstantExpression(
7135 NewSteps.push_back(NewStep);
7137 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7139 Uniforms.size(),
const_cast<Expr **
>(Aligneds.data()), Aligneds.size(),
7140 const_cast<Expr **
>(NewAligns.data()), NewAligns.size(),
7141 const_cast<Expr **
>(Linears.data()), Linears.size(),
7142 const_cast<unsigned *
>(LinModifiers.data()), LinModifiers.size(),
7143 NewSteps.data(), NewSteps.size(), SR);
7153 "Unexpected directive category");
7162 llvm_unreachable(
"Unknown OpenMP directive");
7171 "Expected function type with prototype.");
7173 "Expected function with type with no prototype.");
7175 "Expected function with prototype.");
7183 Param->setScopeInfo(0, Params.size());
7184 Param->setImplicit();
7185 Params.push_back(Param);
7188 FD->setParams(Params);
7195 if (
auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7196 FD = UTemplDecl->getTemplatedDecl();
7199 assert(FD &&
"Expected a function declaration!");
7204 if (!
SemaRef.inTemplateInstantiation()) {
7205 for (OMPAssumeAttr *AA : OMPAssumeScoped)
7208 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7212SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(
OMPTraitInfo &TI)
7213 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7221 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7224 bool IsTemplated = !TemplateParamLists.empty();
7227 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7244 for (
auto *Candidate : Lookup) {
7245 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7249 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7250 UDecl = FTD->getTemplatedDecl();
7251 }
else if (!IsTemplated)
7252 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7266 FType, UDeclTy,
false,
7273 Bases.push_back(UDecl);
7277 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7279 if (Bases.empty() && UseImplicitBase) {
7281 Decl *BaseD =
SemaRef.HandleDeclarator(S, D, TemplateParamLists);
7283 if (
auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7284 Bases.push_back(BaseTemplD->getTemplatedDecl());
7289 std::string MangledName;
7292 MangledName += DVScope.NameSuffix;
7307 if (
auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7308 FD = UTemplDecl->getTemplatedDecl();
7316 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7317 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7324 BaseFD->addAttr(OMPDeclareVariantA);
7344 CalleeFnDecl->
getName().starts_with_insensitive(
"omp_")) {
7347 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7350 if (!CalleeFnDecl->
hasAttr<OMPDeclareVariantAttr>())
7355 CE](StringRef ISATrait) {
7369 while (CalleeFnDecl) {
7370 for (OMPDeclareVariantAttr *A :
7372 Expr *VariantRef = A->getVariantFuncRef();
7374 VariantMatchInfo VMI;
7377 if (!isVariantApplicableInContext(VMI, OMPCtx,
7381 VMIs.push_back(VMI);
7382 Exprs.push_back(VariantRef);
7390 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7410 if (
auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7411 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7413 Context, MemberCall->getImplicitObjectArgument(),
7414 false, SpecializedMethod, Context.BoundMemberTy,
7415 MemberCall->getValueKind(), MemberCall->getObjectKind());
7417 NewCall =
SemaRef.BuildCallExpr(
Scope, BestExpr, LParenLoc, ArgExprs,
7418 RParenLoc, ExecConfig);
7420 if (
CallExpr *NCE = dyn_cast<CallExpr>(NewCall.
get())) {
7421 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7423 CalleeFnType, NewCalleeFnDecl->
getType(),
7434 VMIs.erase(VMIs.begin() + BestIdx);
7435 Exprs.erase(Exprs.begin() + BestIdx);
7436 }
while (!VMIs.empty());
7443std::optional<std::pair<FunctionDecl *, Expr *>>
7447 unsigned NumAppendArgs,
7451 return std::nullopt;
7453 const int VariantId = 1;
7456 Diag(SR.
getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7458 return std::nullopt;
7461 if (
auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7462 ADecl = FTD->getTemplatedDecl();
7465 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7469 return std::nullopt;
7472 auto &&HasMultiVersionAttributes = [](
const FunctionDecl *FD) {
7475 return FD->isMultiVersion() || FD->
hasAttr<TargetAttr>();
7478 if (HasMultiVersionAttributes(FD)) {
7479 Diag(FD->
getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7481 return std::nullopt;
7486 Diag(SR.
getBegin(), diag::warn_omp_declare_variant_after_used)
7491 if (!FD->isThisDeclarationADefinition() && FD->isDefined(
Definition) &&
7493 Diag(SR.
getBegin(), diag::warn_omp_declare_variant_after_emitted)
7498 Diag(SR.
getBegin(), diag::err_omp_function_expected) << VariantId;
7499 return std::nullopt;
7502 auto ShouldDelayChecks = [](
Expr *&E, bool) {
7508 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef,
false) ||
7510 return std::make_pair(FD, VariantRef);
7513 auto HandleNonConstantScoresAndConditions = [
this](
Expr *&E,
7514 bool IsScore) ->
bool {
7520 Diag(E->
getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7528 diag::err_omp_declare_variant_user_condition_not_constant)
7534 return std::nullopt;
7537 if (NumAppendArgs) {
7540 Diag(FD->
getLocation(), diag::err_omp_declare_variant_prototype_required)
7542 return std::nullopt;
7551 TD = dyn_cast_or_null<TypeDecl>(ND);
7554 Diag(SR.
getBegin(), diag::err_omp_interop_type_not_found) << SR;
7555 return std::nullopt;
7560 if (PTy->isVariadic()) {
7561 Diag(FD->
getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7562 return std::nullopt;
7565 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7566 Params.insert(Params.end(), NumAppendArgs, InteropType);
7567 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7568 PTy->getExtProtoInfo());
7576 auto *
Method = dyn_cast<CXXMethodDecl>(FD);
7578 FnPtrType = Context.getMemberPointerType(
7579 AdjustedFnType, std::nullopt,
Method->getParent());
7591 return std::nullopt;
7593 VariantRef = ER.
get();
7595 FnPtrType = Context.getPointerType(AdjustedFnType);
7597 QualType VarianPtrType = Context.getPointerType(VariantRef->
getType());
7601 false, Sema::AllowedExplicit::None,
7607 diag::err_omp_declare_variant_incompat_types)
7611 return std::nullopt;
7613 VariantRefCast =
SemaRef.PerformImplicitConversion(
7617 return std::nullopt;
7621 Expr *PossibleAddrOfVariantRef = VariantRefCast.
get();
7622 if (
auto *UO = dyn_cast<UnaryOperator>(
7624 VariantRefCast = UO->getSubExpr();
7633 return std::nullopt;
7641 return std::nullopt;
7643 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7647 return std::nullopt;
7652 diag::err_omp_declare_variant_same_base_function)
7654 return std::nullopt;
7660 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7663 diag::err_omp_declare_variant_incompat_types)
7664 << NewFD->getType() << FD->
getType() << (NumAppendArgs ? 1 : 0)
7666 return std::nullopt;
7671 else if (NewFD->getType()->isFunctionNoProtoType())
7677 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7679 diag::warn_omp_declare_variant_marked_as_declare_variant)
7682 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->
getRange();
7683 Diag(SR.
getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7684 return std::nullopt;
7687 enum DoesntSupport {
7696 if (
const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7697 if (CXXFD->isVirtual()) {
7700 return std::nullopt;
7706 return std::nullopt;
7712 return std::nullopt;
7716 if (FD->isDeleted()) {
7719 return std::nullopt;
7722 if (FD->isDefaulted()) {
7725 return std::nullopt;
7728 if (FD->isConstexpr()) {
7730 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7731 return std::nullopt;
7735 if (
SemaRef.areMultiversionVariantFunctionsCompatible(
7741 SemaRef.PDiag(diag::err_omp_declare_variant_doesnt_support)),
7743 SemaRef.PDiag(diag::err_omp_declare_variant_diff)
7747 return std::nullopt;
7765 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7766 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7767 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDeviceAddr);
7769 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7770 VariantMatchInfo VMI;
7772 if (!llvm::is_contained(
7773 VMI.ConstructTraits,
7774 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7775 if (!AllAdjustArgs.empty())
7776 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7778 if (!AppendArgs.empty())
7779 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7790 for (
Expr *E : AllAdjustArgs) {
7792 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7793 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7795 if (FD->
getNumParams() > PVD->getFunctionScopeIndex() &&
7799 if (!AdjustVars.insert(CanonPVD).second) {
7800 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7809 Diag(E->
getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7818 for (
Expr *E : AdjustArgsNeedDeviceAddr) {
7820 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7821 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
7824 diag::err_omp_non_by_ref_need_device_addr_modifier_argument);
7830 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7832 const_cast<Expr **
>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7833 const_cast<Expr **
>(AdjustArgsNeedDevicePtr.data()),
7834 AdjustArgsNeedDevicePtr.size(),
7835 const_cast<Expr **
>(AdjustArgsNeedDeviceAddr.data()),
7836 AdjustArgsNeedDeviceAddr.size(),
7837 const_cast<OMPInteropInfo *
>(AppendArgs.data()), AppendArgs.size(), SR);
7843 auto *CS = dyn_cast<CapturedStmt>(AStmt);
7844 assert(CS &&
"Captured statement expected");
7853 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7875 return OMPParallelDirective::Create(
7882struct LoopIterationSpace final {
7885 bool IsStrictCompare =
false;
7887 Expr *PreCond =
nullptr;
7890 Expr *NumIterations =
nullptr;
7892 Expr *CounterVar =
nullptr;
7894 Expr *PrivateCounterVar =
nullptr;
7896 Expr *CounterInit =
nullptr;
7899 Expr *CounterStep =
nullptr;
7901 bool Subtract =
false;
7911 Expr *MinValue =
nullptr;
7915 Expr *MaxValue =
nullptr;
7917 bool IsNonRectangularLB =
false;
7919 bool IsNonRectangularUB =
false;
7922 unsigned LoopDependentIdx = 0;
7926 Expr *FinalCondition =
nullptr;
7933 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7934 VarDecl *ForbiddenVar =
nullptr;
7938 explicit ForSubExprChecker(
7939 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
7940 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
7943 ShouldVisitImplicitCode =
true;
7946 bool VisitDeclRefExpr(DeclRefExpr *E)
override {
7951 if (
V->getType()->isReferenceType()) {
7952 VarDecl *VD =
V->getDefinition();
7955 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(I);
7961 Decl *Canon =
V->getCanonicalDecl();
7962 if (CollapsedLoopVarDecls.contains(Canon)) {
7971 VarDecl *getForbiddenVar()
const {
return ForbiddenVar; }
7972 SourceRange getErrRange()
const {
return ErrLoc; }
7978class OpenMPIterationSpaceChecker {
7982 bool SupportsNonRectangular;
7986 SourceLocation DefaultLoc;
7988 SourceLocation ConditionLoc;
7990 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7992 SourceRange InitSrcRange;
7994 SourceRange ConditionSrcRange;
7996 SourceRange IncrementSrcRange;
7998 ValueDecl *LCDecl =
nullptr;
8000 Expr *LCRef =
nullptr;
8006 Expr *Step =
nullptr;
8013 std::optional<bool> TestIsLessOp;
8015 bool TestIsStrictOp =
false;
8017 bool SubtractStep =
false;
8019 const ValueDecl *DepDecl =
nullptr;
8022 std::optional<unsigned> InitDependOnLC;
8025 std::optional<unsigned> CondDependOnLC;
8027 std::optional<unsigned> doesDependOnLoopCounter(
const Stmt *S,
8028 bool IsInitializer);
8034 OpenMPIterationSpaceChecker(
8035 Sema &SemaRef,
bool SupportsNonRectangular, DSAStackTy &Stack,
8036 SourceLocation DefaultLoc,
8037 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls)
8038 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
8039 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
8040 CollapsedLoopVarDecls(CollapsedLoopDecls) {}
8043 bool checkAndSetInit(Stmt *S,
bool EmitDiags =
true);
8046 bool checkAndSetCond(Expr *S);
8049 bool checkAndSetInc(Expr *S);
8051 ValueDecl *getLoopDecl()
const {
return LCDecl; }
8053 Expr *getLoopDeclRefExpr()
const {
return LCRef; }
8055 SourceRange getInitSrcRange()
const {
return InitSrcRange; }
8057 SourceRange getConditionSrcRange()
const {
return ConditionSrcRange; }
8059 SourceRange getIncrementSrcRange()
const {
return IncrementSrcRange; }
8061 bool shouldSubtractStep()
const {
return SubtractStep; }
8063 bool isStrictTestOp()
const {
return TestIsStrictOp; }
8065 Expr *buildNumIterations(
8066 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces,
bool LimitedType,
8067 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
8070 buildPreCond(Scope *S, Expr *
Cond,
8071 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
8074 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8075 DSAStackTy &DSA)
const;
8078 Expr *buildPrivateCounterVar()
const;
8082 Expr *buildCounterStep()
const;
8086 buildOrderedLoopData(Scope *S, Expr *Counter,
8087 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8088 SourceLocation Loc, Expr *Inc =
nullptr,
8091 std::pair<Expr *, Expr *> buildMinMaxValues(
8092 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
8094 Expr *buildFinalCondition(Scope *S)
const;
8096 bool dependent()
const;
8098 bool doesInitDependOnLC()
const {
return InitDependOnLC.has_value(); }
8100 bool doesCondDependOnLC()
const {
return CondDependOnLC.has_value(); }
8102 unsigned getLoopDependentIdx()
const {
8103 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
8109 bool checkAndSetIncRHS(Expr *RHS);
8111 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
8114 bool setUB(Expr *NewUB, std::optional<bool> LessOp,
bool StrictOp,
8115 SourceRange SR, SourceLocation SL);
8117 bool setStep(Expr *NewStep,
bool Subtract);
8120bool OpenMPIterationSpaceChecker::dependent()
const {
8122 assert(!LB && !UB && !Step);
8130bool OpenMPIterationSpaceChecker::setLCDeclAndLB(
ValueDecl *NewLCDecl,
8132 Expr *NewLB,
bool EmitDiags) {
8134 assert(LCDecl ==
nullptr && LB ==
nullptr && LCRef ==
nullptr &&
8135 UB ==
nullptr && Step ==
nullptr && !TestIsLessOp && !TestIsStrictOp);
8139 LCRef = NewLCRefExpr;
8140 if (
auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
8142 if ((Ctor->isCopyOrMoveConstructor() ||
8143 Ctor->isConvertingConstructor(
false)) &&
8144 CE->getNumArgs() > 0 && CE->getArg(0) !=
nullptr)
8148 InitDependOnLC = doesDependOnLoopCounter(LB,
true);
8152bool OpenMPIterationSpaceChecker::setUB(
Expr *NewUB, std::optional<bool> LessOp,
8156 assert(LCDecl !=
nullptr && LB !=
nullptr && UB ==
nullptr &&
8157 Step ==
nullptr && !TestIsLessOp && !TestIsStrictOp);
8162 TestIsLessOp = LessOp;
8163 TestIsStrictOp = StrictOp;
8164 ConditionSrcRange = SR;
8166 CondDependOnLC = doesDependOnLoopCounter(UB,
false);
8170bool OpenMPIterationSpaceChecker::setStep(
Expr *NewStep,
bool Subtract) {
8172 assert(LCDecl !=
nullptr && LB !=
nullptr && Step ==
nullptr);
8182 NewStep = Val.
get();
8195 std::optional<llvm::APSInt>
Result =
8206 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8207 if (UB && (IsConstZero ||
8208 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8209 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8211 diag::err_omp_loop_incr_not_compatible)
8213 SemaRef.
Diag(ConditionLoc,
8214 diag::note_omp_loop_cond_requires_compatible_incr)
8215 << *TestIsLessOp << ConditionSrcRange;
8218 if (*TestIsLessOp == Subtract) {
8222 Subtract = !Subtract;
8227 SubtractStep = Subtract;
8234class LoopCounterRefChecker final
8238 const ValueDecl *CurLCDecl =
nullptr;
8239 const ValueDecl *DepDecl =
nullptr;
8240 const ValueDecl *PrevDepDecl =
nullptr;
8241 bool IsInitializer =
true;
8242 bool SupportsNonRectangular;
8243 unsigned BaseLoopId = 0;
8244 bool checkDecl(
const Expr *E,
const ValueDecl *VD) {
8246 SemaRef.Diag(E->
getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8247 << (IsInitializer ? 0 : 1);
8250 const auto &&
Data = Stack.isLoopControlVariable(VD);
8255 SmallString<128> Name;
8256 llvm::raw_svector_ostream
OS(Name);
8260 diag::err_omp_wrong_dependency_iterator_type)
8262 SemaRef.Diag(VD->
getLocation(), diag::note_previous_decl) << VD;
8265 if (
Data.first && !SupportsNonRectangular) {
8266 SemaRef.Diag(E->
getExprLoc(), diag::err_omp_invariant_dependency);
8270 (DepDecl || (PrevDepDecl &&
8272 if (!DepDecl && PrevDepDecl)
8273 DepDecl = PrevDepDecl;
8274 SmallString<128> Name;
8275 llvm::raw_svector_ostream
OS(Name);
8279 diag::err_omp_invariant_or_linear_dependency)
8285 BaseLoopId =
Data.first;
8291 bool VisitDeclRefExpr(
const DeclRefExpr *E) {
8292 const ValueDecl *VD = E->
getDecl();
8294 return checkDecl(E, VD);
8297 bool VisitMemberExpr(
const MemberExpr *E) {
8301 return checkDecl(E, VD);
8305 bool VisitStmt(
const Stmt *S) {
8307 for (
const Stmt *Child : S->
children())
8308 Res = (Child && Visit(Child)) || Res;
8311 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8312 const ValueDecl *CurLCDecl,
bool IsInitializer,
8313 const ValueDecl *PrevDepDecl =
nullptr,
8314 bool SupportsNonRectangular =
true)
8315 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8316 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8317 SupportsNonRectangular(SupportsNonRectangular) {}
8318 unsigned getBaseLoopId()
const {
8319 assert(CurLCDecl &&
"Expected loop dependency.");
8322 const ValueDecl *getDepDecl()
const {
8323 assert(CurLCDecl &&
"Expected loop dependency.");
8329std::optional<unsigned>
8330OpenMPIterationSpaceChecker::doesDependOnLoopCounter(
const Stmt *S,
8331 bool IsInitializer) {
8333 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8334 DepDecl, SupportsNonRectangular);
8335 if (LoopStmtChecker.Visit(S)) {
8336 DepDecl = LoopStmtChecker.getDepDecl();
8337 return LoopStmtChecker.getBaseLoopId();
8339 return std::nullopt;
8342bool OpenMPIterationSpaceChecker::checkAndSetInit(
Stmt *S,
bool EmitDiags) {
8353 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8357 if (
auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8358 if (!ExprTemp->cleanupsHaveSideEffects())
8359 S = ExprTemp->getSubExpr();
8361 if (!CollapsedLoopVarDecls.empty()) {
8362 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8363 if (!FSEC.TraverseStmt(S)) {
8365 SemaRef.Diag(
Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8366 <<
Range.getEnd() << 0 << FSEC.getForbiddenVar();
8372 if (
Expr *E = dyn_cast<Expr>(S))
8374 if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8375 if (BO->getOpcode() == BO_Assign) {
8377 if (
auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8378 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->
getDecl()))
8380 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8382 return setLCDeclAndLB(DRE->
getDecl(), DRE, BO->getRHS(), EmitDiags);
8384 if (
auto *ME = dyn_cast<MemberExpr>(LHS)) {
8385 if (ME->isArrow() &&
8387 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8391 }
else if (
auto *DS = dyn_cast<DeclStmt>(S)) {
8392 if (DS->isSingleDecl()) {
8393 if (
auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8394 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8398 diag::ext_omp_loop_not_canonical_init)
8400 return setLCDeclAndLB(
8403 Var->getType().getNonReferenceType(),
8405 Var->getInit(), EmitDiags);
8409 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8410 if (CE->getOperator() == OO_Equal) {
8411 Expr *LHS = CE->getArg(0);
8412 if (
auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8413 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->
getDecl()))
8415 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8417 return setLCDeclAndLB(DRE->
getDecl(), DRE, CE->getArg(1), EmitDiags);
8419 if (
auto *ME = dyn_cast<MemberExpr>(LHS)) {
8420 if (ME->isArrow() &&
8422 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8428 if (dependent() || SemaRef.CurContext->isDependentContext())
8431 SemaRef.Diag(S->
getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8443 if (
const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8445 if ((Ctor->isCopyOrMoveConstructor() ||
8446 Ctor->isConvertingConstructor(
false)) &&
8447 CE->getNumArgs() > 0 && CE->getArg(0) !=
nullptr)
8449 if (
const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8450 if (
const auto *VD = dyn_cast<VarDecl>(DRE->
getDecl()))
8453 if (
const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8454 if (ME->isArrow() &&
isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8459bool OpenMPIterationSpaceChecker::checkAndSetCond(
Expr *S) {
8466 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8468 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8469 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8475 if (!CollapsedLoopVarDecls.empty()) {
8476 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8477 if (!FSEC.TraverseStmt(S)) {
8479 SemaRef.Diag(
Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8480 <<
Range.getEnd() << 1 << FSEC.getForbiddenVar();
8486 auto &&CheckAndSetCond =
8491 if (getInitLCDecl(LHS) == LCDecl)
8492 return setUB(
const_cast<Expr *
>(RHS),
8493 (Opcode == BO_LT || Opcode == BO_LE),
8494 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8495 if (getInitLCDecl(RHS) == LCDecl)
8496 return setUB(
const_cast<Expr *
>(LHS),
8497 (Opcode == BO_GT || Opcode == BO_GE),
8498 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8499 }
else if (IneqCondIsCanonical && Opcode == BO_NE) {
8500 return setUB(
const_cast<Expr *
>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8504 return std::nullopt;
8506 std::optional<bool> Res;
8507 if (
auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8510 RBO->getOperatorLoc());
8511 }
else if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8512 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8513 BO->getSourceRange(), BO->getOperatorLoc());
8514 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8515 if (CE->getNumArgs() == 2) {
8516 Res = CheckAndSetCond(
8518 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8523 if (dependent() || SemaRef.CurContext->isDependentContext())
8525 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8526 << (IneqCondIsCanonical ? 1 : 0) << S->
getSourceRange() << LCDecl;
8530bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(
Expr *RHS) {
8537 if (
auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8538 if (BO->isAdditiveOp()) {
8539 bool IsAdd = BO->getOpcode() == BO_Add;
8540 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8541 return setStep(BO->getRHS(), !IsAdd);
8542 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8543 return setStep(BO->getLHS(),
false);
8545 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8546 bool IsAdd = CE->getOperator() == OO_Plus;
8547 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8548 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8549 return setStep(CE->getArg(1), !IsAdd);
8550 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8551 return setStep(CE->getArg(0),
false);
8554 if (dependent() || SemaRef.CurContext->isDependentContext())
8556 SemaRef.Diag(RHS->
getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8561bool OpenMPIterationSpaceChecker::checkAndSetInc(
Expr *S) {
8576 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8579 if (
auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8580 if (!ExprTemp->cleanupsHaveSideEffects())
8581 S = ExprTemp->getSubExpr();
8583 if (!CollapsedLoopVarDecls.empty()) {
8584 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8585 if (!FSEC.TraverseStmt(S)) {
8587 SemaRef.Diag(
Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8588 <<
Range.getEnd() << 2 << FSEC.getForbiddenVar();
8595 if (
auto *UO = dyn_cast<UnaryOperator>(S)) {
8596 if (UO->isIncrementDecrementOp() &&
8597 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8598 return setStep(SemaRef
8599 .ActOnIntegerConstant(UO->getBeginLoc(),
8600 (UO->isDecrementOp() ? -1 : 1))
8603 }
else if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8604 switch (BO->getOpcode()) {
8607 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8608 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8611 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8612 return checkAndSetIncRHS(BO->getRHS());
8617 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8618 switch (CE->getOperator()) {
8621 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8622 return setStep(SemaRef
8623 .ActOnIntegerConstant(
8625 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8631 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8632 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8635 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8636 return checkAndSetIncRHS(CE->getArg(1));
8642 if (dependent() || SemaRef.CurContext->isDependentContext())
8644 SemaRef.Diag(S->
getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8651 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8652 StringRef Name =
".capture_expr.") {
8660 auto I = Captures.find(
Capture);
8661 if (I != Captures.end())
8674 bool TestIsStrictOp,
bool RoundToStep,
8675 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8676 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures,
".new_step");
8679 llvm::APSInt LRes, SRes;
8680 bool IsLowerConst =
false, IsStepConst =
false;
8681 if (std::optional<llvm::APSInt> Res =
8684 IsLowerConst =
true;
8686 if (std::optional<llvm::APSInt> Res =
8691 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8692 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8693 (TestIsStrictOp && LRes.isStrictlyPositive()));
8694 bool NeedToReorganize =
false;
8696 if (!NoNeedToConvert && IsLowerConst &&
8697 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8698 NoNeedToConvert =
true;
8700 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8701 ? LRes.getBitWidth()
8702 : SRes.getBitWidth();
8703 LRes = LRes.extend(BW + 1);
8704 LRes.setIsSigned(
true);
8705 SRes = SRes.extend(BW + 1);
8706 SRes.setIsSigned(
true);
8708 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8709 LRes = LRes.trunc(BW);
8711 if (TestIsStrictOp) {
8712 unsigned BW = LRes.getBitWidth();
8713 LRes = LRes.extend(BW + 1);
8714 LRes.setIsSigned(
true);
8717 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8719 LRes = LRes.trunc(BW);
8721 NeedToReorganize = NoNeedToConvert;
8724 bool IsUpperConst =
false;
8725 if (std::optional<llvm::APSInt> Res =
8728 IsUpperConst =
true;
8730 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8731 (!RoundToStep || IsStepConst)) {
8732 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8733 : URes.getBitWidth();
8734 LRes = LRes.extend(BW + 1);
8735 LRes.setIsSigned(
true);
8736 URes = URes.extend(BW + 1);
8737 URes.setIsSigned(
true);
8739 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8740 NeedToReorganize = NoNeedToConvert;
8745 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8751 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8754 LowerSize > UpperSize ? LowerSize : UpperSize, 0);
8765 if (!Lower || !Upper || NewStep.
isInvalid())
8771 if (NeedToReorganize) {
8785 S, DefaultLoc, BO_Add, Diff.
get(),
8795 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.
get());
8799 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8815 S, DefaultLoc, BO_Sub, Diff.
get(),
8835 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Div, Diff.
get(), NewStep.
get());
8843Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8845 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
8854 if (InitDependOnLC) {
8855 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8856 if (!IS.MinValue || !IS.MaxValue)
8865 IS.CounterVar, MinValue.
get());
8870 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.
get(), LBVal);
8885 IS.CounterVar, MaxValue.
get());
8890 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.
get(), LBVal);
8899 tryBuildCapture(SemaRef, LBMinVal.
get(), Captures,
".lb_min").get();
8901 tryBuildCapture(SemaRef, LBMaxVal.
get(), Captures,
".lb_max").get();
8902 if (!LBMin || !LBMax)
8906 SemaRef.
BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8910 tryBuildCapture(SemaRef, MinLessMaxRes.
get(), Captures,
".min_less_max")
8914 if (*TestIsLessOp) {
8918 MinLessMax, LBMin, LBMax);
8921 LBVal = MinLB.
get();
8926 MinLessMax, LBMax, LBMin);
8929 LBVal = MaxLB.
get();
8933 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8936 LBVal = LBMinVal.
get();
8940 if (CondDependOnLC) {
8941 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8942 if (!IS.MinValue || !IS.MaxValue)
8951 IS.CounterVar, MinValue.
get());
8956 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.
get(), UBVal);
8971 IS.CounterVar, MaxValue.
get());
8976 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.
get(), UBVal);
8985 tryBuildCapture(SemaRef, UBMinVal.
get(), Captures,
".ub_min").get();
8987 tryBuildCapture(SemaRef, UBMaxVal.
get(), Captures,
".ub_max").get();
8988 if (!UBMin || !UBMax)
8992 SemaRef.
BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
8995 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.
get(),
8996 Captures,
".min_greater_max")
9000 if (*TestIsLessOp) {
9004 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
9007 UBVal = MaxUB.
get();
9012 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
9015 UBVal = MinUB.
get();
9018 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
9019 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
9020 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures,
".upper").get();
9021 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures,
".lower").get();
9022 if (!Upper || !Lower)
9025 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9026 Step, VarType, TestIsStrictOp,
9035 C.getTypeSize(
Type) >
C.getTypeSize(VarType);
9038 UseVarType ?
C.getTypeSize(VarType) :
C.getTypeSize(
Type);
9041 Type =
C.getIntTypeForBitwidth(NewSize, IsSigned);
9051 unsigned NewSize = (
C.getTypeSize(
Type) > 32) ? 64 : 32;
9052 if (NewSize !=
C.getTypeSize(
Type)) {
9053 if (NewSize <
C.getTypeSize(
Type)) {
9054 assert(NewSize == 64 &&
"incorrect loop var size");
9055 SemaRef.
Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
9056 << InitSrcRange << ConditionSrcRange;
9058 QualType NewType =
C.getIntTypeForBitwidth(
9060 C.getTypeSize(
Type) < NewSize);
9074std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
9075 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
9079 return std::make_pair(
nullptr,
nullptr);
9082 Expr *MinExpr =
nullptr;
9083 Expr *MaxExpr =
nullptr;
9084 Expr *LBExpr = *TestIsLessOp ? LB : UB;
9085 Expr *UBExpr = *TestIsLessOp ? UB : LB;
9087 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
9089 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
9091 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
9093 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
9094 if (!Upper || !Lower)
9095 return std::make_pair(
nullptr,
nullptr);
9105 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9106 Step, VarType, TestIsStrictOp,
9109 return std::make_pair(
nullptr,
nullptr);
9115 return std::make_pair(
nullptr,
nullptr);
9117 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures,
".new_step");
9119 return std::make_pair(
nullptr,
nullptr);
9120 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Mul, Diff.
get(), NewStep.
get());
9122 return std::make_pair(
nullptr,
nullptr);
9127 return std::make_pair(
nullptr,
nullptr);
9139 return std::make_pair(
nullptr,
nullptr);
9141 if (*TestIsLessOp) {
9145 S, DefaultLoc, BO_Add,
9149 return std::make_pair(
nullptr,
nullptr);
9154 S, DefaultLoc, BO_Sub,
9158 return std::make_pair(
nullptr,
nullptr);
9167 return std::make_pair(
nullptr,
nullptr);
9172 return std::make_pair(
nullptr,
nullptr);
9175 MaxExpr = Diff.
get();
9177 MinExpr = Diff.
get();
9179 return std::make_pair(MinExpr, MaxExpr);
9182Expr *OpenMPIterationSpaceChecker::buildFinalCondition(
Scope *S)
const {
9183 if (InitDependOnLC || CondDependOnLC)
9188Expr *OpenMPIterationSpaceChecker::buildPreCond(
9190 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
9195 if (CondDependOnLC || InitDependOnLC)
9206 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
9207 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
9213 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
9214 : (TestIsStrictOp ? BO_GT : BO_GE),
9215 NewLB.
get(), NewUB.
get());
9230DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9231 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9232 DSAStackTy &DSA)
const {
9233 auto *VD = dyn_cast<VarDecl>(LCDecl);
9238 const DSAStackTy::DSAVarData
Data =
9239 DSA.getTopDSA(LCDecl,
false);
9243 Captures.insert(std::make_pair(LCRef, Ref));
9249Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar()
const {
9266Expr *OpenMPIterationSpaceChecker::buildCounterInit()
const {
return LB; }
9269Expr *OpenMPIterationSpaceChecker::buildCounterStep()
const {
return Step; }
9271Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9273 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
SourceLocation Loc,
9279 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9280 "Expected only + or - operations for depend clauses.");
9292 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9294 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9295 if (!Upper || !Lower)
9299 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9300 false,
false, Captures);
9310 assert(
getLangOpts().OpenMP &&
"OpenMP is not active.");
9311 assert(
Init &&
"Expected loop in canonical form.");
9312 unsigned AssociatedLoops =
DSAStack->getAssociatedLoops();
9319 OpenMPIterationSpaceChecker ISC(
SemaRef,
true,
9321 if (!ISC.checkAndSetInit(
Init,
false)) {
9323 auto *VD = dyn_cast<VarDecl>(D);
9334 DSAStack->addLoopControlVariable(D, VD);
9336 if (LD != D->getCanonicalDecl()) {
9337 DSAStack->resetPossibleLoopCounter();
9338 if (
auto *Var = dyn_cast_or_null<VarDecl>(LD))
9351 DSAStackTy::DSAVarData DVar =
9355 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9358 ? (
DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9361 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9364 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9366 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9368 IsOpenMPTaskloopDirective(DKind) ||
9371 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9372 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9374 Diag(
Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9376 << getOpenMPDirectiveName(DKind, OMPVersion)
9378 if (DVar.RefExpr ==
nullptr)
9379 DVar.CKind = PredeterminedCKind;
9381 }
else if (LoopDeclRefExpr) {
9386 if (DVar.CKind == OMPC_unknown)
9387 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9391 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9396class OMPDoacrossKind {
9399 return C->getDependenceType() == OMPC_DOACROSS_source ||
9400 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9403 return C->getDependenceType() == OMPC_DOACROSS_sink;
9405 bool isSinkIter(
const OMPDoacrossClause *
C) {
9406 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9414 unsigned CurrentNestedLoopCount,
unsigned NestedLoopCount,
9415 unsigned TotalNestedLoopCount,
Expr *CollapseLoopCountExpr,
9416 Expr *OrderedLoopCountExpr,
9419 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9420 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls) {
9425 if (
auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9426 S = CanonLoop->getLoopStmt();
9427 auto *For = dyn_cast_or_null<ForStmt>(S);
9428 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9430 if (!For && (SemaRef.
LangOpts.OpenMP <= 45 || !CXXFor)) {
9431 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
9433 << (CollapseLoopCountExpr !=
nullptr || OrderedLoopCountExpr !=
nullptr)
9434 << getOpenMPDirectiveName(DKind, OMPVersion) << TotalNestedLoopCount
9435 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9436 if (TotalNestedLoopCount > 1) {
9437 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9438 SemaRef.
Diag(DSA.getConstructLoc(),
9439 diag::note_omp_collapse_ordered_expr)
9442 else if (CollapseLoopCountExpr)
9444 diag::note_omp_collapse_ordered_expr)
9446 else if (OrderedLoopCountExpr)
9448 diag::note_omp_collapse_ordered_expr)
9453 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9459 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9460 For ? For->getForLoc() : CXXFor->getForLoc(),
9461 CollapsedLoopVarDecls);
9464 Stmt *
Init = For ? For->getInit() : CXXFor->getBeginStmt();
9465 if (ISC.checkAndSetInit(
Init))
9468 bool HasErrors =
false;
9471 if (
ValueDecl *LCDecl = ISC.getLoopDecl()) {
9481 SemaRef.
Diag(
Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9495 VarsWithImplicitDSA.erase(LCDecl);
9499 "DSA for non-loop vars");
9502 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9505 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9512 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9513 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9514 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9515 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9522 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9523 ISC.buildCounterVar(Captures, DSA);
9524 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9525 ISC.buildPrivateCounterVar();
9526 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9527 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9528 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9529 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9530 ISC.getConditionSrcRange();
9531 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9532 ISC.getIncrementSrcRange();
9533 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9534 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9535 ISC.isStrictTestOp();
9536 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9537 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9538 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9539 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9540 ISC.buildFinalCondition(DSA.getCurScope());
9541 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9542 ISC.doesInitDependOnLC();
9543 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9544 ISC.doesCondDependOnLC();
9545 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9546 ISC.getLoopDependentIdx();
9549 (ResultIterSpaces[CurrentNestedLoopCount].PreCond ==
nullptr ||
9550 ResultIterSpaces[CurrentNestedLoopCount].NumIterations ==
nullptr ||
9551 ResultIterSpaces[CurrentNestedLoopCount].CounterVar ==
nullptr ||
9552 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar ==
nullptr ||
9553 ResultIterSpaces[CurrentNestedLoopCount].CounterInit ==
nullptr ||
9554 ResultIterSpaces[CurrentNestedLoopCount].CounterStep ==
nullptr);
9555 if (!HasErrors && DSA.isOrderedRegion()) {
9556 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9557 if (CurrentNestedLoopCount <
9558 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9559 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9560 CurrentNestedLoopCount,
9561 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9562 DSA.getOrderedRegionParam().second->setLoopCounter(
9563 CurrentNestedLoopCount,
9564 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9567 for (
auto &Pair : DSA.getDoacrossDependClauses()) {
9568 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9569 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9571 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9572 if (CurrentNestedLoopCount >= NumLoops) {
9576 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9577 Pair.second.size() <= CurrentNestedLoopCount) {
9579 DependC->setLoopData(CurrentNestedLoopCount,
nullptr);
9582 OMPDoacrossKind ODK;
9583 if (DoacrossC && ODK.isSink(DoacrossC) &&
9584 Pair.second.size() <= CurrentNestedLoopCount) {
9586 DoacrossC->setLoopData(CurrentNestedLoopCount,
nullptr);
9591 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9592 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9593 (DoacrossC && ODK.isSource(DoacrossC)))
9594 CntValue = ISC.buildOrderedLoopData(
9596 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9598 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9601 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9609 CntValue = ISC.buildOrderedLoopData(
9611 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9612 DepLoc, Inc, clang::OO_Minus);
9614 CntValue = ISC.buildOrderedLoopData(
9616 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9617 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9618 Pair.second[CurrentNestedLoopCount].second);
9620 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9622 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9633 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9637 : tryBuildCapture(SemaRef, Start.
get(), Captures);
9658 bool IsNonRectangularLB,
9659 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures =
nullptr) {
9668 NewStep = tryBuildCapture(SemaRef, Step.
get(), *Captures);
9683 if (Captures && !IsNonRectangularLB)
9684 NewStart = tryBuildCapture(SemaRef, Start.
get(), *Captures);
9693 Update.get()->getType()->isOverloadableType()) {
9700 SemaRef.
BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9701 VarRef.
get(), SavedUpdate.
get());
9712 NewStart.
get(), SavedUpdate.
get());
9737 unsigned HasBits =
C.getTypeSize(OldType);
9738 if (HasBits >= Bits)
9741 QualType NewType =
C.getIntTypeForBitwidth(Bits,
true);
9751 if (std::optional<llvm::APSInt> Result =
9753 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9760 if (!PreInits.empty()) {
9781 if (
auto *CS = dyn_cast<CompoundStmt>(Item))
9790 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9791 if (!Captures.empty()) {
9793 for (
const auto &Pair : Captures)
9794 PreInits.push_back(Pair.second->getDecl());
9802 if (PreInits.empty())
9806 for (
Stmt *S : PreInits)
9813 Expr *PostUpdate =
nullptr;
9814 if (!PostUpdates.empty()) {
9815 for (
Expr *E : PostUpdates) {
9821 PostUpdate = PostUpdate
9835 int NestingDepth = 0;
9836 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
9858 if (NestingDepth > 0)
9869 Expr *OrderedLoopCountExpr,
Stmt *AStmt,
Sema &SemaRef,
9872 OMPLoopBasedDirective::HelperExprs &Built) {
9876 if ((CollapseLoopCountExpr && CollapseLoopCountExpr->
containsErrors()) ||
9877 (OrderedLoopCountExpr && OrderedLoopCountExpr->
containsErrors()))
9880 unsigned NestedLoopCount = 1;
9881 bool SupportsNonPerfectlyNested = (SemaRef.
LangOpts.OpenMP >= 50) &&
9885 if (CollapseLoopCountExpr) {
9890 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9899 unsigned OrderedLoopCount = 1;
9900 if (OrderedLoopCountExpr) {
9906 llvm::APSInt Result = EVResult.
Val.
getInt();
9907 if (Result.getLimitedValue() < NestedLoopCount) {
9909 diag::err_omp_wrong_ordered_loop_count)
9912 diag::note_collapse_loop_count)
9915 OrderedLoopCount = Result.getLimitedValue();
9923 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9924 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9926 if (!OMPLoopBasedDirective::doForAllLoops(
9929 SupportsNonPerfectlyNested, NumLoops,
9930 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9931 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9932 &IterSpaces, &Captures,
9933 &CollapsedLoopVarDecls](
unsigned Cnt,
Stmt *CurStmt) {
9935 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9936 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9937 VarsWithImplicitDSA, IterSpaces, Captures,
9938 CollapsedLoopVarDecls))
9940 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9941 IterSpaces[Cnt].CounterVar) {
9945 Captures[DRE] = DRE;
9951 Stmt *DependentPreInits = Transform->getPreInits();
9952 if (!DependentPreInits)
9959 for (
Stmt *S : Constituents) {
9960 if (
auto *DC = dyn_cast<DeclStmt>(S)) {
9961 for (
Decl *
C : DC->decls()) {
9964 SemaRef, D, D->getType().getNonReferenceType(),
9967 Captures[Ref] = Ref;
9974 Built.clear(NestedLoopCount);
9977 return NestedLoopCount;
10010 auto PreCond =
ExprResult(IterSpaces[0].PreCond);
10011 Expr *N0 = IterSpaces[0].NumIterations;
10030 return NestedLoopCount;
10033 bool AllCountsNeedLessThan32Bits =
C.getTypeSize(N0->
getType()) < 32;
10035 Scope *CurScope = DSA.getCurScope();
10036 for (
unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
10037 if (PreCond.isUsable()) {
10039 SemaRef.
BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
10040 PreCond.get(), IterSpaces[Cnt].PreCond);
10042 Expr *N = IterSpaces[Cnt].NumIterations;
10044 AllCountsNeedLessThan32Bits &=
C.getTypeSize(N->
getType()) < 32;
10047 CurScope, Loc, BO_Mul, LastIteration32.
get(),
10055 CurScope, Loc, BO_Mul, LastIteration64.
get(),
10065 if (SemaRef.
getLangOpts().OpenMPOptimisticCollapse ||
10067 C.getTypeSize(LastIteration32.
get()->
getType()) == 32 &&
10068 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
10072 LastIteration64.
get(), SemaRef))))
10073 LastIteration = LastIteration32;
10092 LastIteration.
get(),
10104 tryBuildCapture(SemaRef, LastIteration.
get(), Captures);
10105 LastIteration = SaveRef;
10118 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
10147 buildVarDecl(SemaRef, InitLoc, StrideVType,
".omp.stride");
10156 UB.
get(), LastIteration.
get());
10159 LastIteration.
get(), UB.
get());
10160 EUB = SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, UB.
get(),
10171 buildVarDecl(SemaRef, InitLoc, VType,
".omp.comb.lb");
10179 buildVarDecl(SemaRef, InitLoc, VType,
".omp.comb.ub");
10185 CurScope, InitLoc, BO_GT, CombUB.
get(), LastIteration.
get());
10188 LastIteration.
get(), CombUB.
get());
10189 CombEUB = SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.
get(),
10198 "Unexpected number of parameters in loop combined directive");
10239 SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, IV.
get(), CombRHS);
10245 bool UseStrictCompare =
10247 llvm::all_of(IterSpaces, [](
const LoopIterationSpace &LIS) {
10248 return LIS.IsStrictCompare;
10254 if (UseStrictCompare) {
10257 .
BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
10269 UseStrictCompare ? BO_LT : BO_LE, IV.
get(),
10272 NumIterations.
get());
10275 CombDistCond = SemaRef.
BuildBinOp(CurScope, CondLoc, BO_LT, IV.
get(),
10276 NumIterations.
get());
10281 Expr *BoundCombUB = CombUB.
get();
10282 if (UseStrictCompare) {
10286 CurScope, CondLoc, BO_Add, BoundCombUB,
10294 SemaRef.
BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10295 IV.
get(), BoundCombUB);
10302 if (!Inc.isUsable())
10304 Inc = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, IV.
get(), Inc.get());
10306 if (!Inc.isUsable())
10313 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10319 NextLB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Add, LB.
get(), ST.
get());
10330 NextUB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Add, UB.
get(), ST.
get());
10346 CombNextLB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.
get(),
10358 CombNextUB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.
get(),
10372 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10375 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.
get(), BoundUB);
10376 assert(DistCond.
isUsable() &&
"distribute cond expr was not built");
10380 assert(DistInc.
isUsable() &&
"distribute inc expr was not built");
10381 DistInc = SemaRef.
BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.
get(),
10385 assert(DistInc.
isUsable() &&
"distribute inc expr was not built");
10396 DistEUBLoc, NewPrevUB.
get());
10401 UB.
get(), NewPrevUB.
get());
10403 DistEUBLoc, DistEUBLoc, IsUBGreater.
get(), NewPrevUB.
get(), UB.
get());
10404 PrevEUB = SemaRef.
BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.
get(),
10412 Expr *BoundPrevUB = PrevUB.
get();
10413 if (UseStrictCompare) {
10417 CurScope, CondLoc, BO_Add, BoundPrevUB,
10425 SemaRef.
BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10426 IV.
get(), BoundPrevUB);
10430 bool HasErrors =
false;
10431 Built.Counters.resize(NestedLoopCount);
10432 Built.Inits.resize(NestedLoopCount);
10433 Built.Updates.resize(NestedLoopCount);
10434 Built.Finals.resize(NestedLoopCount);
10435 Built.DependentCounters.resize(NestedLoopCount);
10436 Built.DependentInits.resize(NestedLoopCount);
10437 Built.FinalsConditions.resize(NestedLoopCount);
10455 for (
unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10456 LoopIterationSpace &IS = IterSpaces[Cnt];
10462 for (
unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10463 Prod = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.
get(),
10464 IterSpaces[K].NumIterations);
10469 if (Cnt + 1 < NestedLoopCount)
10483 if (Cnt + 1 < NestedLoopCount)
10484 Prod = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.
get(),
10488 Acc = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.
get(), Prod.
get());
10497 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10498 if (!
Init.isUsable()) {
10503 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10504 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10505 if (!
Update.isUsable()) {
10513 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10514 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10515 if (!Final.isUsable()) {
10520 if (!
Update.isUsable() || !Final.isUsable()) {
10525 Built.Counters[Cnt] = IS.CounterVar;
10526 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10527 Built.Inits[Cnt] =
Init.get();
10528 Built.Updates[Cnt] =
Update.get();
10529 Built.Finals[Cnt] = Final.get();
10530 Built.DependentCounters[Cnt] =
nullptr;
10531 Built.DependentInits[Cnt] =
nullptr;
10532 Built.FinalsConditions[Cnt] =
nullptr;
10533 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10534 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10535 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10536 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10545 Built.IterationVarRef = IV.
get();
10546 Built.LastIteration = LastIteration.
get();
10547 Built.NumIterations = NumIterations.
get();
10548 Built.CalcLastIteration = SemaRef
10552 Built.PreCond = PreCond.get();
10554 Built.Cond =
Cond.get();
10555 Built.Init =
Init.get();
10556 Built.Inc = Inc.get();
10557 Built.LB = LB.
get();
10558 Built.UB = UB.
get();
10559 Built.IL = IL.
get();
10560 Built.ST = ST.
get();
10561 Built.EUB = EUB.
get();
10562 Built.NLB = NextLB.
get();
10563 Built.NUB = NextUB.
get();
10564 Built.PrevLB = PrevLB.
get();
10565 Built.PrevUB = PrevUB.
get();
10566 Built.DistInc = DistInc.
get();
10567 Built.PrevEUB = PrevEUB.
get();
10568 Built.DistCombinedFields.LB = CombLB.
get();
10569 Built.DistCombinedFields.UB = CombUB.
get();
10570 Built.DistCombinedFields.EUB = CombEUB.
get();
10571 Built.DistCombinedFields.Init = CombInit.
get();
10572 Built.DistCombinedFields.Cond = CombCond.
get();
10573 Built.DistCombinedFields.NLB = CombNextLB.
get();
10574 Built.DistCombinedFields.NUB = CombNextUB.
get();
10575 Built.DistCombinedFields.DistCond = CombDistCond.
get();
10576 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.
get();
10578 return NestedLoopCount;
10582 auto CollapseClauses =
10583 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10584 if (CollapseClauses.begin() != CollapseClauses.end())
10585 return (*CollapseClauses.begin())->getNumForLoops();
10590 auto OrderedClauses =
10591 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10592 if (OrderedClauses.begin() != OrderedClauses.end())
10593 return (*OrderedClauses.begin())->getNumForLoops();
10602 for (
const OMPClause *Clause : Clauses) {
10603 if (Clause->getClauseKind() == OMPC_safelen)
10605 else if (Clause->getClauseKind() == OMPC_simdlen)
10607 if (Safelen && Simdlen)
10611 if (Simdlen && Safelen) {
10625 llvm::APSInt SimdlenRes = SimdlenResult.
Val.
getInt();
10626 llvm::APSInt SafelenRes = SafelenResult.
Val.
getInt();
10631 if (SimdlenRes > SafelenRes) {
10633 diag::err_omp_wrong_simdlen_safelen_values)
10650 OMPLoopBasedDirective::HelperExprs B;
10656 if (NestedLoopCount == 0)
10665 auto *SimdDirective = OMPSimdDirective::Create(
10666 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10667 return SimdDirective;
10677 OMPLoopBasedDirective::HelperExprs B;
10683 if (NestedLoopCount == 0)
10689 auto *ForDirective = OMPForDirective::Create(
10690 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10692 return ForDirective;
10704 OMPLoopBasedDirective::HelperExprs B;
10707 unsigned NestedLoopCount =
10710 VarsWithImplicitDSA, B);
10711 if (NestedLoopCount == 0)
10720 return OMPForSimdDirective::Create(
getASTContext(), StartLoc, EndLoc,
10721 NestedLoopCount, Clauses, AStmt, B);
10725 Stmt *AStmt, DSAStackTy *Stack) {
10730 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
10731 auto BaseStmt = AStmt;
10732 while (
auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10734 if (
auto *
C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10735 auto S =
C->children();
10736 if (S.begin() == S.end())
10740 for (
Stmt *SectionStmt : llvm::drop_begin(S)) {
10743 SemaRef.
Diag(SectionStmt->getBeginLoc(),
10744 diag::err_omp_sections_substmt_not_section)
10745 << getOpenMPDirectiveName(DKind, OMPVersion);
10749 ->setHasCancel(Stack->isCancelRegion());
10752 SemaRef.
Diag(AStmt->
getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10753 << getOpenMPDirectiveName(DKind, OMPVersion);
10766 SemaRef.setFunctionHasBranchProtectedScope();
10768 return OMPSectionsDirective::Create(
10779 SemaRef.setFunctionHasBranchProtectedScope();
10782 return OMPSectionDirective::Create(
getASTContext(), StartLoc, EndLoc, AStmt,
10788 if (
auto *CE = dyn_cast<CallExpr>(E))
10789 if (CE->getDirectCallee())
10810 if (!
SemaRef.CurContext->isDependentContext()) {
10811 Expr *TargetCall =
nullptr;
10813 auto *E = dyn_cast<Expr>(S);
10821 if (
auto *BO = dyn_cast<BinaryOperator>(E)) {
10822 if (BO->getOpcode() == BO_Assign)
10825 if (
auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10826 if (COCE->getOperator() == OO_Equal)
10838 SemaRef.setFunctionHasBranchProtectedScope();
10841 Clauses, AStmt, TargetCallLoc);
10846 DSAStackTy *Stack) {
10847 bool ErrorFound =
false;
10849 if (
auto *LPC = dyn_cast<OMPLastprivateClause>(
C)) {
10850 for (
Expr *RefExpr : LPC->varlist()) {
10853 Expr *SimpleRefExpr = RefExpr;
10856 auto &&Info = Stack->isLoopControlVariable(D);
10859 S.
Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10860 << getOpenMPDirectiveName(K, OMPVersion);
10884 OMPLoopDirective::HelperExprs B;
10889 if (NestedLoopCount == 0)
10892 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10893 "omp loop exprs were not built");
10896 NestedLoopCount, Clauses, AStmt, B);
10913 OMPLoopDirective::HelperExprs B;
10915 unsigned NestedLoopCount =
10918 VarsWithImplicitDSA, B);
10919 if (NestedLoopCount == 0)
10922 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10923 "omp loop exprs were not built");
10925 DSAStack->setParentTeamsRegionLoc(StartLoc);
10928 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10947 OMPLoopDirective::HelperExprs B;
10949 unsigned NestedLoopCount =
10952 VarsWithImplicitDSA, B);
10953 if (NestedLoopCount == 0)
10956 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10957 "omp loop exprs were not built");
10960 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10980 OMPLoopDirective::HelperExprs B;
10982 unsigned NestedLoopCount =
10985 VarsWithImplicitDSA, B);
10986 if (NestedLoopCount == 0)
10989 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10990 "omp loop exprs were not built");
10993 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11012 OMPLoopDirective::HelperExprs B;
11014 unsigned NestedLoopCount =
11017 VarsWithImplicitDSA, B);
11018 if (NestedLoopCount == 0)
11021 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11022 "omp loop exprs were not built");
11025 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11037 SemaRef.setFunctionHasBranchProtectedScope();
11042 const OMPClause *Copyprivate =
nullptr;
11043 for (
const OMPClause *Clause : Clauses) {
11044 if (Clause->getClauseKind() == OMPC_nowait)
11046 else if (Clause->getClauseKind() == OMPC_copyprivate)
11047 Copyprivate = Clause;
11048 if (Copyprivate && Nowait) {
11050 diag::err_omp_single_copyprivate_with_nowait);
11056 return OMPSingleDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses,
11066 SemaRef.setFunctionHasBranchProtectedScope();
11068 return OMPMasterDirective::Create(
getASTContext(), StartLoc, EndLoc, AStmt);
11078 SemaRef.setFunctionHasBranchProtectedScope();
11090 bool ErrorFound =
false;
11093 bool DependentHint =
false;
11095 if (
C->getClauseKind() == OMPC_hint) {
11097 Diag(
C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
11103 DependentHint =
true;
11106 HintLoc =
C->getBeginLoc();
11112 const auto Pair =
DSAStack->getCriticalWithHint(DirName);
11113 if (Pair.first && DirName.
getName() && !DependentHint) {
11114 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
11115 Diag(StartLoc, diag::err_omp_critical_with_hint);
11117 Diag(HintLoc, diag::note_omp_critical_hint_here)
11118 << 0 <<
toString(Hint, 10,
false);
11120 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
11121 if (
const auto *
C = Pair.first->getSingleClause<
OMPHintClause>()) {
11122 Diag(
C->getBeginLoc(), diag::note_omp_critical_hint_here)
11127 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
11132 SemaRef.setFunctionHasBranchProtectedScope();
11134 auto *Dir = OMPCriticalDirective::Create(
getASTContext(), DirName, StartLoc,
11135 EndLoc, Clauses, AStmt);
11136 if (!Pair.first && DirName.
getName() && !DependentHint)
11137 DSAStack->addCriticalWithHint(Dir, Hint);
11149 OMPLoopBasedDirective::HelperExprs B;
11152 unsigned NestedLoopCount =
11155 VarsWithImplicitDSA, B);
11156 if (NestedLoopCount == 0)
11162 return OMPParallelForDirective::Create(
11163 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11176 OMPLoopBasedDirective::HelperExprs B;
11179 unsigned NestedLoopCount =
11182 VarsWithImplicitDSA, B);
11183 if (NestedLoopCount == 0)
11192 return OMPParallelForSimdDirective::Create(
11193 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11204 return OMPParallelMasterDirective::Create(
11206 DSAStack->getTaskgroupReductionRef());
11217 return OMPParallelMaskedDirective::Create(
11219 DSAStack->getTaskgroupReductionRef());
11228 SemaRef.setFunctionHasBranchProtectedScope();
11230 return OMPParallelSectionsDirective::Create(
11240 bool ErrorFound =
false;
11242 if (llvm::is_contained(MutuallyExclusiveClauses,
C->getClauseKind())) {
11246 S.
Diag(
C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
11269 {OMPC_detach, OMPC_mergeable}))
11274 return OMPTaskDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses,
11275 AStmt,
DSAStack->isCancelRegion());
11280 return OMPTaskyieldDirective::Create(
getASTContext(), StartLoc, EndLoc);
11285 return OMPBarrierDirective::Create(
getASTContext(), StartLoc, EndLoc);
11291 bool InExContext) {
11293 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11295 if (AtC && !InExContext && AtC->
getAtKind() == OMPC_AT_execution) {
11300 if (!AtC || AtC->
getAtKind() == OMPC_AT_compilation) {
11302 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11304 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11305 std::optional<std::string> SL =
11308 if (MessageC && !SL)
11310 diag::warn_clause_expected_string)
11312 if (SeverityC && SeverityC->
getSeverityKind() == OMPC_SEVERITY_warning)
11314 << SL.value_or(
"WARNING");
11316 Diag(StartLoc, diag::err_diagnose_if_succeeded) << SL.value_or(
"ERROR");
11317 if (!SeverityC || SeverityC->
getSeverityKind() != OMPC_SEVERITY_warning)
11329 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11331 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11333 if (NowaitC && !HasDependC) {
11334 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11338 return OMPTaskwaitDirective::Create(
getASTContext(), StartLoc, EndLoc,
11351 SemaRef.setFunctionHasBranchProtectedScope();
11353 return OMPTaskgroupDirective::Create(
getASTContext(), StartLoc, EndLoc,
11355 DSAStack->getTaskgroupReductionRef());
11364 if (
C->getClauseKind() == OMPC_flush)
11373 if (
C->getClauseKind() == OMPC_acq_rel ||
11374 C->getClauseKind() == OMPC_acquire ||
11375 C->getClauseKind() == OMPC_release ||
11376 C->getClauseKind() == OMPC_seq_cst ) {
11377 if (MemOrderKind != OMPC_unknown) {
11378 Diag(
C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11379 << getOpenMPDirectiveName(OMPD_flush, OMPVersion) << 1
11381 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11384 MemOrderKind =
C->getClauseKind();
11385 MemOrderLoc =
C->getBeginLoc();
11389 if (FC && OrderClause) {
11392 Diag(OrderClause->
getBeginLoc(), diag::note_omp_flush_order_clause_here)
11396 return OMPFlushDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses);
11402 if (Clauses.empty()) {
11403 Diag(StartLoc, diag::err_omp_depobj_expected);
11405 }
else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11406 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11410 if (Clauses.size() > 2) {
11411 Diag(Clauses[2]->getBeginLoc(),
11412 diag::err_omp_depobj_single_clause_expected);
11414 }
else if (Clauses.size() < 1) {
11415 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11418 return OMPDepobjDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses);
11425 if (Clauses.size() != 1) {
11426 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11427 diag::err_omp_scan_single_clause_expected);
11436 return StmtError(
Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11437 << getOpenMPDirectiveName(OMPD_scan, OMPVersion) << 5);
11442 if (
DSAStack->doesParentHasScanDirective()) {
11443 Diag(StartLoc, diag::err_omp_several_directives_in_region) <<
"scan";
11445 diag::note_omp_previous_directive)
11449 DSAStack->setParentHasScanDirective(StartLoc);
11457 const OMPClause *DependFound =
nullptr;
11458 const OMPClause *DependSourceClause =
nullptr;
11459 const OMPClause *DependSinkClause =
nullptr;
11460 const OMPClause *DoacrossFound =
nullptr;
11461 const OMPClause *DoacrossSourceClause =
nullptr;
11462 const OMPClause *DoacrossSinkClause =
nullptr;
11463 bool ErrorFound =
false;
11467 auto DOC = dyn_cast<OMPDoacrossClause>(
C);
11468 auto DC = dyn_cast<OMPDependClause>(
C);
11470 DependFound = DC ?
C :
nullptr;
11471 DoacrossFound = DOC ?
C :
nullptr;
11472 OMPDoacrossKind ODK;
11473 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11474 (DOC && (ODK.isSource(DOC)))) {
11475 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11477 Diag(
C->getBeginLoc(), diag::err_omp_more_one_clause)
11478 << getOpenMPDirectiveName(OMPD_ordered, OMPVersion)
11484 DependSourceClause =
C;
11486 DoacrossSourceClause =
C;
11488 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11489 Diag(
C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11490 << (DC ?
"depend" :
"doacross") << 0;
11493 }
else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11494 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11495 if (DependSourceClause || DoacrossSourceClause) {
11496 Diag(
C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11497 << (DC ?
"depend" :
"doacross") << 1;
11501 DependSinkClause =
C;
11503 DoacrossSinkClause =
C;
11505 }
else if (
C->getClauseKind() == OMPC_threads) {
11507 }
else if (
C->getClauseKind() == OMPC_simd) {
11511 if (!ErrorFound && !SC &&
11516 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11519 }
else if ((DependFound || DoacrossFound) && (TC || SC)) {
11522 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11527 }
else if ((DependFound || DoacrossFound) &&
11528 !
DSAStack->getParentOrderedRegionParam().first) {
11531 Diag(Loc, diag::err_omp_ordered_directive_without_param)
11535 }
else if (TC || Clauses.empty()) {
11536 if (
const Expr *Param =
DSAStack->getParentOrderedRegionParam().first) {
11538 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11539 << (TC !=
nullptr);
11540 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11544 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11552 if (!DependFound && !DoacrossFound) {
11553 if (
DSAStack->doesParentHasOrderedDirective()) {
11554 Diag(StartLoc, diag::err_omp_several_directives_in_region) <<
"ordered";
11556 diag::note_omp_previous_directive)
11560 DSAStack->setParentHasOrderedDirective(StartLoc);
11566 SemaRef.setFunctionHasBranchProtectedScope();
11569 return OMPOrderedDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses,
11576class OpenMPAtomicUpdateChecker {
11578 enum ExprAnalysisErrorCode {
11582 NotABinaryOrUnaryExpression,
11584 NotAnUnaryIncDecExpression,
11590 NotABinaryExpression,
11593 NotABinaryOperator,
11596 NotAnUpdateExpression,
11599 NotAValidExpression,
11625 OpenMPAtomicUpdateChecker(
Sema &SemaRef)
11635 bool checkStatement(Stmt *S,
unsigned DiagId = 0,
unsigned NoteId = 0);
11637 Expr *
getX()
const {
return X; }
11639 Expr *
getExpr()
const {
return E; }
11653 bool checkBinaryOperation(BinaryOperator *AtomicBinOp,
unsigned DiagId = 0,
11654 unsigned NoteId = 0);
11657bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11658 BinaryOperator *AtomicBinOp,
unsigned DiagId,
unsigned NoteId) {
11659 ExprAnalysisErrorCode ErrorFound = NoError;
11665 if (AtomicBinOp->
getOpcode() == BO_Assign) {
11667 if (
const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11669 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11670 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11671 AtomicInnerBinOp->isBitwiseOp()) {
11672 Op = AtomicInnerBinOp->getOpcode();
11673 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11674 Expr *LHS = AtomicInnerBinOp->getLHS();
11675 Expr *RHS = AtomicInnerBinOp->getRHS();
11676 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11683 if (XId == LHSId) {
11686 }
else if (XId == RHSId) {
11690 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11691 ErrorRange = AtomicInnerBinOp->getSourceRange();
11692 NoteLoc =
X->getExprLoc();
11693 NoteRange =
X->getSourceRange();
11694 ErrorFound = NotAnUpdateExpression;
11697 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11698 ErrorRange = AtomicInnerBinOp->getSourceRange();
11699 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11701 ErrorFound = NotABinaryOperator;
11706 ErrorFound = NotABinaryExpression;
11713 ErrorFound = NotAnAssignmentOp;
11715 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11716 SemaRef.
Diag(ErrorLoc, DiagId) << ErrorRange;
11717 SemaRef.
Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11721 E =
X = UpdateExpr =
nullptr;
11722 return ErrorFound != NoError;
11725bool OpenMPAtomicUpdateChecker::checkStatement(
Stmt *S,
unsigned DiagId,
11727 ExprAnalysisErrorCode ErrorFound = NoError;
11738 if (
auto *AtomicBody = dyn_cast<Expr>(S)) {
11739 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11740 if (AtomicBody->getType()->isScalarType() ||
11741 AtomicBody->isInstantiationDependent()) {
11742 if (
const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11743 AtomicBody->IgnoreParenImpCasts())) {
11746 AtomicCompAssignOp->getOpcode());
11747 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11748 E = AtomicCompAssignOp->getRHS();
11751 }
else if (
auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11752 AtomicBody->IgnoreParenImpCasts())) {
11754 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11756 }
else if (
const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11757 AtomicBody->IgnoreParenImpCasts())) {
11759 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11761 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11762 OpLoc = AtomicUnaryOp->getOperatorLoc();
11763 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11767 ErrorFound = NotAnUnaryIncDecExpression;
11768 ErrorLoc = AtomicUnaryOp->getExprLoc();
11769 ErrorRange = AtomicUnaryOp->getSourceRange();
11770 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11773 }
else if (!AtomicBody->isInstantiationDependent()) {
11774 ErrorFound = NotABinaryOrUnaryExpression;
11775 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11776 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11777 }
else if (AtomicBody->containsErrors()) {
11778 ErrorFound = NotAValidExpression;
11779 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11780 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11783 ErrorFound = NotAScalarType;
11784 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11785 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
11788 ErrorFound = NotAnExpression;
11790 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
11792 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11793 SemaRef.
Diag(ErrorLoc, DiagId) << ErrorRange;
11794 SemaRef.
Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11798 E =
X = UpdateExpr =
nullptr;
11799 if (ErrorFound == NoError && E &&
X) {
11816 UpdateExpr =
Update.get();
11818 return ErrorFound != NoError;
11822llvm::FoldingSetNodeID getNodeId(
ASTContext &Context,
const Expr *S) {
11823 llvm::FoldingSetNodeID Id;
11829bool checkIfTwoExprsAreSame(
ASTContext &Context,
const Expr *LHS,
11831 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11834class OpenMPAtomicCompareChecker {
11881 struct ErrorInfoTy {
11883 SourceLocation ErrorLoc;
11884 SourceRange ErrorRange;
11885 SourceLocation NoteLoc;
11886 SourceRange NoteRange;
11889 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11892 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11894 Expr *
getX()
const {
return X; }
11895 Expr *getE()
const {
return E; }
11896 Expr *
getD()
const {
return D; }
11897 Expr *getCond()
const {
return C; }
11898 bool isXBinopExpr()
const {
return IsXBinopExpr; }
11902 ASTContext &ContextRef;
11917 bool IsXBinopExpr =
true;
11920 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11923 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11926 bool checkType(ErrorInfoTy &ErrorInfo)
const;
11928 static bool CheckValue(
const Expr *E, ErrorInfoTy &ErrorInfo,
11929 bool ShouldBeLValue,
bool ShouldBeInteger =
false) {
11933 if (ShouldBeLValue && !E->
isLValue()) {
11934 ErrorInfo.Error = ErrorTy::XNotLValue;
11935 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->
getExprLoc();
11936 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->
getSourceRange();
11942 ErrorInfo.Error = ErrorTy::NotScalar;
11943 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->
getExprLoc();
11944 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->
getSourceRange();
11948 ErrorInfo.Error = ErrorTy::NotInteger;
11949 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->
getExprLoc();
11950 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->
getSourceRange();
11958bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(
IfStmt *S,
11959 ErrorInfoTy &ErrorInfo) {
11961 if (
auto *CS = dyn_cast<CompoundStmt>(Then)) {
11962 if (CS->body_empty()) {
11963 ErrorInfo.Error = ErrorTy::NoStmt;
11964 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11965 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11968 if (CS->size() > 1) {
11969 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11970 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11971 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
11974 Then = CS->body_front();
11977 auto *BO = dyn_cast<BinaryOperator>(Then);
11979 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11980 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11981 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11984 if (BO->getOpcode() != BO_Assign) {
11985 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11986 ErrorInfo.ErrorLoc = BO->getExprLoc();
11987 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11988 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11994 auto *
Cond = dyn_cast<BinaryOperator>(S->
getCond());
11995 auto *
Call = dyn_cast<CXXOperatorCallExpr>(S->
getCond());
11996 Expr *LHS =
nullptr;
11997 Expr *RHS =
nullptr;
11999 LHS =
Cond->getLHS();
12000 RHS =
Cond->getRHS();
12002 LHS =
Call->getArg(0);
12003 RHS =
Call->getArg(1);
12005 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12011 if ((
Cond &&
Cond->getOpcode() == BO_EQ) ||
12012 (
Call &&
Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12015 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS)) {
12017 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12020 ErrorInfo.Error = ErrorTy::InvalidComparison;
12022 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12026 }
else if ((
Cond &&
12027 (
Cond->getOpcode() == BO_LT ||
Cond->getOpcode() == BO_GT)) ||
12029 (
Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12030 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12032 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS) &&
12033 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12035 }
else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12036 checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12038 IsXBinopExpr =
false;
12040 ErrorInfo.Error = ErrorTy::InvalidComparison;
12042 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12047 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12054 ErrorInfo.Error = ErrorTy::UnexpectedElse;
12063bool OpenMPAtomicCompareChecker::checkCondExprStmt(
Stmt *S,
12064 ErrorInfoTy &ErrorInfo) {
12065 auto *BO = dyn_cast<BinaryOperator>(S);
12067 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12068 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->
getBeginLoc();
12069 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
12072 if (BO->getOpcode() != BO_Assign) {
12073 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12074 ErrorInfo.ErrorLoc = BO->getExprLoc();
12075 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12076 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12082 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
12084 ErrorInfo.Error = ErrorTy::NotCondOp;
12085 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
12086 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
12090 if (!checkIfTwoExprsAreSame(ContextRef,
X, CO->getFalseExpr())) {
12091 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
12092 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
12093 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12094 CO->getFalseExpr()->getSourceRange();
12098 auto *
Cond = dyn_cast<BinaryOperator>(CO->getCond());
12099 auto *
Call = dyn_cast<CXXOperatorCallExpr>(CO->getCond());
12100 Expr *LHS =
nullptr;
12101 Expr *RHS =
nullptr;
12103 LHS =
Cond->getLHS();
12104 RHS =
Cond->getRHS();
12106 LHS =
Call->getArg(0);
12107 RHS =
Call->getArg(1);
12109 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12110 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12111 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12112 CO->getCond()->getSourceRange();
12116 if ((
Cond &&
Cond->getOpcode() == BO_EQ) ||
12117 (
Call &&
Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12119 D = CO->getTrueExpr();
12120 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS)) {
12122 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12125 ErrorInfo.Error = ErrorTy::InvalidComparison;
12126 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12127 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12128 CO->getCond()->getSourceRange();
12131 }
else if ((
Cond &&
12132 (
Cond->getOpcode() == BO_LT ||
Cond->getOpcode() == BO_GT)) ||
12134 (
Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12135 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12137 E = CO->getTrueExpr();
12138 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS) &&
12139 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12141 }
else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12142 checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12144 IsXBinopExpr =
false;
12146 ErrorInfo.Error = ErrorTy::InvalidComparison;
12147 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12148 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12149 CO->getCond()->getSourceRange();
12153 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12154 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12155 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12156 CO->getCond()->getSourceRange();
12163bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo)
const {
12165 assert(
X && E &&
"X and E cannot be nullptr");
12167 if (!CheckValue(
X, ErrorInfo,
true))
12170 if (!CheckValue(E, ErrorInfo,
false))
12173 if (D && !CheckValue(D, ErrorInfo,
false))
12179bool OpenMPAtomicCompareChecker::checkStmt(
12180 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
12181 auto *CS = dyn_cast<CompoundStmt>(S);
12183 if (CS->body_empty()) {
12184 ErrorInfo.Error = ErrorTy::NoStmt;
12185 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12186 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12190 if (CS->size() != 1) {
12191 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12192 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12193 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12196 S = CS->body_front();
12201 if (
auto *IS = dyn_cast<IfStmt>(S)) {
12207 Res = checkCondUpdateStmt(IS, ErrorInfo);
12213 Res = checkCondExprStmt(S, ErrorInfo);
12219 return checkType(ErrorInfo);
12222class OpenMPAtomicCompareCaptureChecker final
12223 :
public OpenMPAtomicCompareChecker {
12225 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
12227 Expr *
getV()
const {
return V; }
12228 Expr *
getR()
const {
return R; }
12233 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12236 bool checkType(ErrorInfoTy &ErrorInfo);
12248 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12252 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12264bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12265 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12268 if (
V && !CheckValue(
V, ErrorInfo,
true))
12271 if (R && !CheckValue(R, ErrorInfo,
true,
true))
12277bool OpenMPAtomicCompareCaptureChecker::checkForm3(
IfStmt *S,
12278 ErrorInfoTy &ErrorInfo) {
12282 if (
auto *CS = dyn_cast<CompoundStmt>(Then)) {
12283 if (CS->body_empty()) {
12284 ErrorInfo.Error = ErrorTy::NoStmt;
12285 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12286 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12289 if (CS->size() > 1) {
12290 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12291 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12292 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12295 Then = CS->body_front();
12298 auto *BO = dyn_cast<BinaryOperator>(Then);
12300 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12301 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12302 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12305 if (BO->getOpcode() != BO_Assign) {
12306 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12307 ErrorInfo.ErrorLoc = BO->getExprLoc();
12308 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12309 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12316 auto *
Cond = dyn_cast<BinaryOperator>(S->
getCond());
12317 auto *
Call = dyn_cast<CXXOperatorCallExpr>(S->
getCond());
12318 Expr *LHS =
nullptr;
12319 Expr *RHS =
nullptr;
12321 LHS =
Cond->getLHS();
12322 RHS =
Cond->getRHS();
12324 LHS =
Call->getArg(0);
12325 RHS =
Call->getArg(1);
12327 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12332 if ((
Cond &&
Cond->getOpcode() != BO_EQ) ||
12333 (
Call &&
Call->getOperator() != OverloadedOperatorKind::OO_EqualEqual)) {
12334 ErrorInfo.Error = ErrorTy::NotEQ;
12340 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS)) {
12342 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12345 ErrorInfo.Error = ErrorTy::InvalidComparison;
12354 ErrorInfo.Error = ErrorTy::NoElse;
12355 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->
getBeginLoc();
12356 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
12361 if (
auto *CS = dyn_cast<CompoundStmt>(Else)) {
12362 if (CS->body_empty()) {
12363 ErrorInfo.Error = ErrorTy::NoStmt;
12364 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12365 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12368 if (CS->size() > 1) {
12369 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12370 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12371 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
12374 Else = CS->body_front();
12377 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12379 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12380 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12381 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12384 if (ElseBO->getOpcode() != BO_Assign) {
12385 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12386 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12387 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12388 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12392 if (!checkIfTwoExprsAreSame(ContextRef,
X, ElseBO->getRHS())) {
12393 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12394 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12395 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12396 ElseBO->getRHS()->getSourceRange();
12400 V = ElseBO->getLHS();
12402 return checkType(ErrorInfo);
12405bool OpenMPAtomicCompareCaptureChecker::checkForm45(
Stmt *S,
12406 ErrorInfoTy &ErrorInfo) {
12410 assert(CS->size() == 2 &&
"CompoundStmt size is not expected");
12413 assert(S1->getOpcode() == BO_Assign &&
"unexpected binary operator");
12415 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12416 ErrorInfo.Error = ErrorTy::InvalidCondition;
12417 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12418 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12424 auto *Then = S2->getThen();
12425 if (
auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12426 if (ThenCS->body_empty()) {
12427 ErrorInfo.Error = ErrorTy::NoStmt;
12428 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12429 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12432 if (ThenCS->size() > 1) {
12433 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12434 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12435 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12438 Then = ThenCS->body_front();
12441 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12443 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12444 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12445 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12448 if (ThenBO->getOpcode() != BO_Assign) {
12449 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12450 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12451 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12452 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12456 X = ThenBO->getLHS();
12457 D = ThenBO->getRHS();
12460 if (BO->getOpcode() != BO_EQ) {
12461 ErrorInfo.Error = ErrorTy::NotEQ;
12462 ErrorInfo.ErrorLoc = BO->getExprLoc();
12463 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12464 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12470 if (checkIfTwoExprsAreSame(ContextRef,
X, BO->getLHS())) {
12472 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, BO->getRHS())) {
12475 ErrorInfo.Error = ErrorTy::InvalidComparison;
12476 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12477 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12481 if (S2->getElse()) {
12484 auto *Else = S2->getElse();
12485 if (
auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12486 if (ElseCS->body_empty()) {
12487 ErrorInfo.Error = ErrorTy::NoStmt;
12488 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12489 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12492 if (ElseCS->size() > 1) {
12493 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12494 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12495 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12498 Else = ElseCS->body_front();
12501 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12503 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12504 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12505 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12508 if (ElseBO->getOpcode() != BO_Assign) {
12509 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12510 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12511 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12512 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12515 if (!checkIfTwoExprsAreSame(ContextRef,
X, ElseBO->getRHS())) {
12516 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12517 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12518 ErrorInfo.NoteLoc =
X->getExprLoc();
12519 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12520 ErrorInfo.NoteRange =
X->getSourceRange();
12524 V = ElseBO->getLHS();
12527 return checkType(ErrorInfo);
12530bool OpenMPAtomicCompareCaptureChecker::checkStmt(
Stmt *S,
12531 ErrorInfoTy &ErrorInfo) {
12533 if (
auto *IS = dyn_cast<IfStmt>(S))
12534 return checkForm3(IS, ErrorInfo);
12536 auto *CS = dyn_cast<CompoundStmt>(S);
12538 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12539 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->
getBeginLoc();
12540 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
12543 if (CS->body_empty()) {
12544 ErrorInfo.Error = ErrorTy::NoStmt;
12545 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12546 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12551 if (CS->size() == 1) {
12552 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12554 ErrorInfo.Error = ErrorTy::NotIfStmt;
12555 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->
getBeginLoc();
12556 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12561 return checkForm3(IS, ErrorInfo);
12562 }
else if (CS->size() == 2) {
12563 auto *S1 = CS->body_front();
12564 auto *S2 = CS->body_back();
12566 Stmt *UpdateStmt =
nullptr;
12567 Stmt *CondUpdateStmt =
nullptr;
12568 Stmt *CondExprStmt =
nullptr;
12570 if (
auto *BO = dyn_cast<BinaryOperator>(S1)) {
12580 return checkForm45(CS, ErrorInfo);
12589 CondUpdateStmt = S2;
12598 CondUpdateStmt = S1;
12601 auto CheckCondUpdateStmt = [
this, &ErrorInfo](
Stmt *CUS) {
12602 auto *IS = dyn_cast<IfStmt>(CUS);
12604 ErrorInfo.Error = ErrorTy::NotIfStmt;
12605 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12606 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12610 return checkCondUpdateStmt(IS, ErrorInfo);
12614 auto CheckUpdateStmt = [
this, &ErrorInfo](
Stmt *US) {
12615 auto *BO = dyn_cast<BinaryOperator>(US);
12617 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12618 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12619 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12622 if (BO->getOpcode() != BO_Assign) {
12623 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12624 ErrorInfo.ErrorLoc = BO->getExprLoc();
12625 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12626 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12629 if (!checkIfTwoExprsAreSame(ContextRef, this->
X, BO->getRHS())) {
12630 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12631 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12632 ErrorInfo.NoteLoc = this->
X->getExprLoc();
12633 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12634 ErrorInfo.NoteRange = this->
X->getSourceRange();
12638 this->
V = BO->getLHS();
12643 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12645 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12647 if (!CheckUpdateStmt(UpdateStmt))
12650 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12651 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12652 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12656 return checkType(ErrorInfo);
12667 DSAStack->addAtomicDirectiveLoc(StartLoc);
12680 bool MutexClauseEncountered =
false;
12681 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12683 switch (
C->getClauseKind()) {
12687 MutexClauseEncountered =
true;
12690 case OMPC_compare: {
12691 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12692 Diag(
C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12694 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12697 AtomicKind =
C->getClauseKind();
12698 AtomicKindLoc =
C->getBeginLoc();
12699 if (!EncounteredAtomicKinds.insert(
C->getClauseKind()).second) {
12700 Diag(
C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12702 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12710 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12711 Diag(
C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12722 case OMPC_relaxed: {
12723 if (MemOrderKind != OMPC_unknown) {
12724 Diag(
C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12725 << getOpenMPDirectiveName(OMPD_atomic, OMPVersion) << 0
12727 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12730 MemOrderKind =
C->getClauseKind();
12731 MemOrderLoc =
C->getBeginLoc();
12739 llvm_unreachable(
"unknown clause is encountered");
12742 bool IsCompareCapture =
false;
12743 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12744 EncounteredAtomicKinds.contains(OMPC_capture)) {
12745 IsCompareCapture =
true;
12746 AtomicKind = OMPC_compare;
12755 if ((AtomicKind == OMPC_read &&
12756 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12757 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12758 AtomicKind == OMPC_unknown) &&
12759 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12761 if (AtomicKind == OMPC_unknown)
12763 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12765 << (AtomicKind == OMPC_unknown ? 1 : 0)
12767 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12771 Stmt *Body = AStmt;
12772 if (
auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12773 Body = EWC->getSubExpr();
12778 Expr *UE =
nullptr;
12780 Expr *CE =
nullptr;
12807 if (AtomicKind == OMPC_read) {
12814 } ErrorFound = NoError;
12819 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12820 const auto *AtomicBinOp =
12821 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12822 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12825 if ((
X->isInstantiationDependent() ||
X->getType()->isScalarType()) &&
12826 (
V->isInstantiationDependent() ||
V->getType()->isScalarType())) {
12827 if (!
X->isLValue() || !
V->isLValue()) {
12828 const Expr *NotLValueExpr =
X->isLValue() ?
V :
X;
12829 ErrorFound = NotAnLValue;
12835 }
else if (!
X->isInstantiationDependent() ||
12836 !
V->isInstantiationDependent()) {
12837 const Expr *NotScalarExpr =
12838 (
X->isInstantiationDependent() ||
X->getType()->isScalarType())
12841 ErrorFound = NotAScalarType;
12847 }
else if (!AtomicBody->isInstantiationDependent()) {
12848 ErrorFound = NotAnAssignmentOp;
12849 ErrorLoc = AtomicBody->getExprLoc();
12850 ErrorRange = AtomicBody->getSourceRange();
12852 : AtomicBody->getExprLoc();
12854 : AtomicBody->getSourceRange();
12857 ErrorFound = NotAnExpression;
12859 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
12861 if (ErrorFound != NoError) {
12862 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12864 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12865 << ErrorFound << NoteRange;
12868 if (
SemaRef.CurContext->isDependentContext())
12870 }
else if (AtomicKind == OMPC_write) {
12877 } ErrorFound = NoError;
12882 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12883 const auto *AtomicBinOp =
12884 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12885 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12887 E = AtomicBinOp->
getRHS();
12888 if ((
X->isInstantiationDependent() ||
X->getType()->isScalarType()) &&
12890 if (!
X->isLValue()) {
12891 ErrorFound = NotAnLValue;
12894 NoteLoc =
X->getExprLoc();
12895 NoteRange =
X->getSourceRange();
12897 }
else if (!
X->isInstantiationDependent() ||
12899 const Expr *NotScalarExpr =
12900 (
X->isInstantiationDependent() ||
X->getType()->isScalarType())
12903 ErrorFound = NotAScalarType;
12909 }
else if (!AtomicBody->isInstantiationDependent()) {
12910 ErrorFound = NotAnAssignmentOp;
12911 ErrorLoc = AtomicBody->getExprLoc();
12912 ErrorRange = AtomicBody->getSourceRange();
12914 : AtomicBody->getExprLoc();
12916 : AtomicBody->getSourceRange();
12919 ErrorFound = NotAnExpression;
12921 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
12923 if (ErrorFound != NoError) {
12924 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12926 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12927 << ErrorFound << NoteRange;
12930 if (
SemaRef.CurContext->isDependentContext())
12932 }
else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12941 OpenMPAtomicUpdateChecker Checker(
SemaRef);
12942 if (Checker.checkStatement(
12944 (AtomicKind == OMPC_update)
12945 ? diag::err_omp_atomic_update_not_expression_statement
12946 : diag::err_omp_atomic_not_expression_statement,
12947 diag::note_omp_atomic_update))
12949 if (!
SemaRef.CurContext->isDependentContext()) {
12950 E = Checker.getExpr();
12951 X = Checker.getX();
12952 UE = Checker.getUpdateExpr();
12955 }
else if (AtomicKind == OMPC_capture) {
12958 NotACompoundStatement,
12959 NotTwoSubstatements,
12960 NotASpecificExpression,
12962 } ErrorFound = NoError;
12965 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12974 const auto *AtomicBinOp =
12975 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12976 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12979 OpenMPAtomicUpdateChecker Checker(
SemaRef);
12980 if (Checker.checkStatement(
12981 Body, diag::err_omp_atomic_capture_not_expression_statement,
12982 diag::note_omp_atomic_update))
12984 E = Checker.getExpr();
12985 X = Checker.getX();
12986 UE = Checker.getUpdateExpr();
12989 }
else if (!AtomicBody->isInstantiationDependent()) {
12990 ErrorLoc = AtomicBody->getExprLoc();
12991 ErrorRange = AtomicBody->getSourceRange();
12993 : AtomicBody->getExprLoc();
12995 : AtomicBody->getSourceRange();
12996 ErrorFound = NotAnAssignmentOp;
12998 if (ErrorFound != NoError) {
12999 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
13001 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13004 if (
SemaRef.CurContext->isDependentContext())
13005 UE =
V = E =
X =
nullptr;
13023 if (
auto *CS = dyn_cast<CompoundStmt>(Body)) {
13025 if (CS->size() == 2) {
13027 Stmt *Second = CS->body_back();
13028 if (
auto *EWC = dyn_cast<ExprWithCleanups>(
First))
13029 First = EWC->getSubExpr()->IgnoreParenImpCasts();
13030 if (
auto *EWC = dyn_cast<ExprWithCleanups>(Second))
13031 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
13033 OpenMPAtomicUpdateChecker Checker(
SemaRef);
13034 bool IsUpdateExprFound = !Checker.checkStatement(Second);
13036 if (IsUpdateExprFound) {
13037 BinOp = dyn_cast<BinaryOperator>(
First);
13038 IsUpdateExprFound = BinOp && BinOp->
getOpcode() == BO_Assign;
13040 if (IsUpdateExprFound && !
SemaRef.CurContext->isDependentContext()) {
13050 llvm::FoldingSetNodeID XId, PossibleXId;
13051 Checker.getX()->Profile(XId, Context,
true);
13052 PossibleX->
Profile(PossibleXId, Context,
true);
13053 IsUpdateExprFound = XId == PossibleXId;
13054 if (IsUpdateExprFound) {
13056 X = Checker.getX();
13057 E = Checker.getExpr();
13058 UE = Checker.getUpdateExpr();
13063 if (!IsUpdateExprFound) {
13064 IsUpdateExprFound = !Checker.checkStatement(
First);
13066 if (IsUpdateExprFound) {
13067 BinOp = dyn_cast<BinaryOperator>(Second);
13068 IsUpdateExprFound = BinOp && BinOp->
getOpcode() == BO_Assign;
13070 if (IsUpdateExprFound &&
13071 !
SemaRef.CurContext->isDependentContext()) {
13081 llvm::FoldingSetNodeID XId, PossibleXId;
13082 Checker.getX()->Profile(XId, Context,
true);
13083 PossibleX->
Profile(PossibleXId, Context,
true);
13084 IsUpdateExprFound = XId == PossibleXId;
13085 if (IsUpdateExprFound) {
13087 X = Checker.getX();
13088 E = Checker.getExpr();
13089 UE = Checker.getUpdateExpr();
13095 if (!IsUpdateExprFound) {
13097 auto *FirstExpr = dyn_cast<Expr>(
First);
13098 auto *SecondExpr = dyn_cast<Expr>(Second);
13099 if (!FirstExpr || !SecondExpr ||
13100 !(FirstExpr->isInstantiationDependent() ||
13101 SecondExpr->isInstantiationDependent())) {
13102 auto *FirstBinOp = dyn_cast<BinaryOperator>(
First);
13103 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
13104 ErrorFound = NotAnAssignmentOp;
13105 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
13106 :
First->getBeginLoc();
13107 NoteRange = ErrorRange = FirstBinOp
13108 ? FirstBinOp->getSourceRange()
13111 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
13112 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
13113 ErrorFound = NotAnAssignmentOp;
13114 NoteLoc = ErrorLoc = SecondBinOp
13115 ? SecondBinOp->getOperatorLoc()
13117 NoteRange = ErrorRange =
13118 SecondBinOp ? SecondBinOp->getSourceRange()
13121 Expr *PossibleXRHSInFirst =
13123 Expr *PossibleXLHSInSecond =
13125 llvm::FoldingSetNodeID X1Id, X2Id;
13126 PossibleXRHSInFirst->
Profile(X1Id, Context,
13128 PossibleXLHSInSecond->
Profile(X2Id, Context,
13130 IsUpdateExprFound = X1Id == X2Id;
13131 if (IsUpdateExprFound) {
13132 V = FirstBinOp->getLHS();
13133 X = SecondBinOp->getLHS();
13134 E = SecondBinOp->getRHS();
13139 ErrorFound = NotASpecificExpression;
13140 ErrorLoc = FirstBinOp->getExprLoc();
13141 ErrorRange = FirstBinOp->getSourceRange();
13142 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
13143 NoteRange = SecondBinOp->getRHS()->getSourceRange();
13151 NoteRange = ErrorRange =
13153 ErrorFound = NotTwoSubstatements;
13157 NoteRange = ErrorRange =
13159 ErrorFound = NotACompoundStatement;
13162 if (ErrorFound != NoError) {
13163 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
13165 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13168 if (
SemaRef.CurContext->isDependentContext())
13169 UE =
V = E =
X =
nullptr;
13170 }
else if (AtomicKind == OMPC_compare) {
13171 if (IsCompareCapture) {
13172 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
13173 OpenMPAtomicCompareCaptureChecker Checker(
SemaRef);
13174 if (!Checker.checkStmt(Body, ErrorInfo)) {
13175 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
13176 << ErrorInfo.ErrorRange;
13177 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13178 << ErrorInfo.Error << ErrorInfo.NoteRange;
13181 X = Checker.getX();
13182 E = Checker.getE();
13183 D = Checker.getD();
13184 CE = Checker.getCond();
13185 V = Checker.getV();
13186 R = Checker.getR();
13192 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
13193 OpenMPAtomicCompareChecker Checker(
SemaRef);
13194 if (!Checker.checkStmt(Body, ErrorInfo)) {
13195 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
13196 << ErrorInfo.ErrorRange;
13197 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13198 << ErrorInfo.Error << ErrorInfo.NoteRange;
13201 X = Checker.getX();
13202 E = Checker.getE();
13203 D = Checker.getD();
13204 CE = Checker.getCond();
13210 auto *It = find_if(Clauses, [](
OMPClause *
C) {
13211 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
13213 if (It != Clauses.end()) {
13214 auto *
Cond = dyn_cast<BinaryOperator>(CE);
13215 if (
Cond->getOpcode() != BO_EQ) {
13216 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
13217 ErrorInfo.ErrorLoc =
Cond->getExprLoc();
13218 ErrorInfo.NoteLoc =
Cond->getOperatorLoc();
13219 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
Cond->getSourceRange();
13221 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
13222 << ErrorInfo.ErrorRange;
13231 SemaRef.setFunctionHasBranchProtectedScope();
13233 return OMPAtomicDirective::Create(
13234 Context, StartLoc, EndLoc, Clauses, AStmt,
13251 if (
DSAStack->hasInnerTeamsRegion()) {
13253 bool OMPTeamsFound =
true;
13254 if (
const auto *CS = dyn_cast<CompoundStmt>(S)) {
13255 auto I = CS->body_begin();
13256 while (I != CS->body_end()) {
13257 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
13259 if (!IsTeams || I != CS->body_begin()) {
13260 OMPTeamsFound =
false;
13261 if (IsTeams && I != CS->body_begin()) {
13270 assert(I != CS->body_end() &&
"Not found statement");
13273 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
13276 if (!OMPTeamsFound) {
13277 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
13279 diag::note_omp_nested_teams_construct_here);
13312 OMPLoopBasedDirective::HelperExprs B;
13315 unsigned NestedLoopCount =
13318 VarsWithImplicitDSA, B);
13319 if (NestedLoopCount == 0)
13326 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13333 return llvm::any_of(
13334 Clauses, [K](
const OMPClause *
C) {
return C->getClauseKind() == K; });
13337template <
typename... Params>
13339 const Params... ClauseTypes) {
13346 if (
auto *TC = dyn_cast<OMPToClause>(
C))
13347 return llvm::all_of(TC->all_decls(), [](
ValueDecl *VD) {
13348 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13349 (VD->isExternallyVisible() &&
13350 VD->getVisibility() != HiddenVisibility);
13352 else if (
auto *FC = dyn_cast<OMPFromClause>(
C))
13353 return llvm::all_of(FC->all_decls(), [](
ValueDecl *VD) {
13354 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13355 (VD->isExternallyVisible() &&
13356 VD->getVisibility() != HiddenVisibility);
13375 if (!
hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13377 !
hasClauses(Clauses, OMPC_use_device_addr))) {
13380 Expected =
"'map' or 'use_device_ptr'";
13382 Expected =
"'map', 'use_device_ptr', or 'use_device_addr'";
13384 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13385 <<
Expected << getOpenMPDirectiveName(OMPD_target_data, OMPVersion);
13389 SemaRef.setFunctionHasBranchProtectedScope();
13407 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13409 << getOpenMPDirectiveName(OMPD_target_enter_data, OMPVersion);
13429 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13430 <<
"'map'" << getOpenMPDirectiveName(OMPD_target_exit_data, OMPVersion);
13446 if (!
hasClauses(Clauses, OMPC_to, OMPC_from)) {
13447 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13452 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13462template <
typename ClauseType>
13465 unsigned MaxNum,
unsigned Diag) {
13466 auto ClauseItr = llvm::find_if(Clauses, llvm::IsaPred<ClauseType>);
13467 if (ClauseItr == Clauses.end())
13470 auto VarList =
C->getVarRefs();
13471 if (VarList.size() > MaxNum) {
13472 SemaRef.
Diag(VarList[MaxNum]->getBeginLoc(),
Diag)
13487 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
13489 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
13494 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13498 DSAStack->setParentTeamsRegionLoc(StartLoc);
13507 if (
DSAStack->isParentNowaitRegion()) {
13508 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13511 if (
DSAStack->isParentOrderedRegion()) {
13512 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13516 EndLoc, CancelRegion);
13522 if (
DSAStack->isParentNowaitRegion()) {
13523 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13526 if (
DSAStack->isParentOrderedRegion()) {
13527 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13530 DSAStack->setParentCancelRegion(
true);
13537 const OMPClause *ReductionClause =
nullptr;
13538 const OMPClause *NogroupClause =
nullptr;
13540 if (
C->getClauseKind() == OMPC_reduction) {
13541 ReductionClause =
C;
13546 if (
C->getClauseKind() == OMPC_nogroup) {
13548 if (ReductionClause)
13553 if (ReductionClause && NogroupClause) {
13554 S.
Diag(ReductionClause->
getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13569 OMPLoopBasedDirective::HelperExprs B;
13572 unsigned NestedLoopCount =
13575 *
DSAStack, VarsWithImplicitDSA, B);
13576 if (NestedLoopCount == 0)
13579 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13580 "omp for loop exprs were not built");
13586 {OMPC_grainsize, OMPC_num_tasks}))
13594 SemaRef.setFunctionHasBranchProtectedScope();
13596 NestedLoopCount, Clauses, AStmt, B,
13610 OMPLoopBasedDirective::HelperExprs B;
13613 unsigned NestedLoopCount =
13616 VarsWithImplicitDSA, B);
13617 if (NestedLoopCount == 0)
13627 {OMPC_grainsize, OMPC_num_tasks}))
13638 NestedLoopCount, Clauses, AStmt, B);
13648 OMPLoopBasedDirective::HelperExprs B;
13651 unsigned NestedLoopCount =
13654 *
DSAStack, VarsWithImplicitDSA, B);
13655 if (NestedLoopCount == 0)
13658 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13659 "omp for loop exprs were not built");
13665 {OMPC_grainsize, OMPC_num_tasks}))
13673 SemaRef.setFunctionHasBranchProtectedScope();
13675 NestedLoopCount, Clauses, AStmt, B,
13686 OMPLoopBasedDirective::HelperExprs B;
13689 unsigned NestedLoopCount =
13692 *
DSAStack, VarsWithImplicitDSA, B);
13693 if (NestedLoopCount == 0)
13696 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13697 "omp for loop exprs were not built");
13703 {OMPC_grainsize, OMPC_num_tasks}))
13711 SemaRef.setFunctionHasBranchProtectedScope();
13713 NestedLoopCount, Clauses, AStmt, B,
13727 OMPLoopBasedDirective::HelperExprs B;
13730 unsigned NestedLoopCount =
13733 VarsWithImplicitDSA, B);
13734 if (NestedLoopCount == 0)
13744 {OMPC_grainsize, OMPC_num_tasks}))
13755 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13768 OMPLoopBasedDirective::HelperExprs B;
13771 unsigned NestedLoopCount =
13774 VarsWithImplicitDSA, B);
13775 if (NestedLoopCount == 0)
13785 {OMPC_grainsize, OMPC_num_tasks}))
13796 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13808 OMPLoopBasedDirective::HelperExprs B;
13814 VarsWithImplicitDSA, B);
13815 if (NestedLoopCount == 0)
13818 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13819 "omp for loop exprs were not built");
13825 {OMPC_grainsize, OMPC_num_tasks}))
13834 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13847 OMPLoopBasedDirective::HelperExprs B;
13853 VarsWithImplicitDSA, B);
13854 if (NestedLoopCount == 0)
13857 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13858 "omp for loop exprs were not built");
13864 {OMPC_grainsize, OMPC_num_tasks}))
13873 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13884 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
13886 OMPLoopBasedDirective::HelperExprs B;
13892 VarsWithImplicitDSA, B);
13893 if (NestedLoopCount == 0)
13903 {OMPC_grainsize, OMPC_num_tasks}))
13914 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13924 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
13926 OMPLoopBasedDirective::HelperExprs B;
13932 VarsWithImplicitDSA, B);
13933 if (NestedLoopCount == 0)
13943 {OMPC_grainsize, OMPC_num_tasks}))
13954 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13964 OMPLoopBasedDirective::HelperExprs B;
13967 unsigned NestedLoopCount =
13971 if (NestedLoopCount == 0)
13974 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13975 "omp for loop exprs were not built");
13977 SemaRef.setFunctionHasBranchProtectedScope();
13979 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13980 return DistributeDirective;
13992 OMPLoopBasedDirective::HelperExprs B;
13998 VarsWithImplicitDSA, B);
13999 if (NestedLoopCount == 0)
14002 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14003 "omp for loop exprs were not built");
14006 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14017 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
14019 OMPLoopBasedDirective::HelperExprs B;
14025 VarsWithImplicitDSA, B);
14026 if (NestedLoopCount == 0)
14036 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14048 OMPLoopBasedDirective::HelperExprs B;
14051 unsigned NestedLoopCount =
14055 if (NestedLoopCount == 0)
14065 NestedLoopCount, Clauses, AStmt, B);
14077 OMPLoopBasedDirective::HelperExprs B;
14083 VarsWithImplicitDSA, B);
14084 if (NestedLoopCount == 0)
14094 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14105 OMPLoopBasedDirective::HelperExprs B;
14108 unsigned NestedLoopCount =
14111 VarsWithImplicitDSA, B);
14112 if (NestedLoopCount == 0)
14122 NestedLoopCount, Clauses, AStmt, B);
14134 OMPLoopBasedDirective::HelperExprs B;
14137 unsigned NestedLoopCount =
14141 if (NestedLoopCount == 0)
14144 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14145 "omp teams distribute loop exprs were not built");
14147 DSAStack->setParentTeamsRegionLoc(StartLoc);
14150 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14162 OMPLoopBasedDirective::HelperExprs B;
14168 VarsWithImplicitDSA, B);
14169 if (NestedLoopCount == 0)
14178 DSAStack->setParentTeamsRegionLoc(StartLoc);
14181 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14191 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
14193 OMPLoopBasedDirective::HelperExprs B;
14199 VarsWithImplicitDSA, B);
14200 if (NestedLoopCount == 0)
14209 DSAStack->setParentTeamsRegionLoc(StartLoc);
14212 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14222 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
14224 OMPLoopBasedDirective::HelperExprs B;
14230 VarsWithImplicitDSA, B);
14232 if (NestedLoopCount == 0)
14235 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14236 "omp for loop exprs were not built");
14238 DSAStack->setParentTeamsRegionLoc(StartLoc);
14241 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14254 bool HasThreadLimitAndNumTeamsClause =
hasClauses(Clauses, OMPC_num_teams) &&
14256 bool HasBareClause = llvm::any_of(Clauses, [&](
const OMPClause *
C) {
14258 return C->getClauseKind() == OMPC_ompx_bare;
14261 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
14266 unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 1;
14267 unsigned DiagNo = HasBareClause
14268 ? diag::err_ompx_more_than_three_expr_not_allowed
14269 : diag::err_omp_multi_expr_not_allowed;
14271 ClauseMaxNumExprs, DiagNo) ||
14273 ClauseMaxNumExprs, DiagNo))
14287 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
14289 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14295 OMPLoopBasedDirective::HelperExprs B;
14301 VarsWithImplicitDSA, B);
14302 if (NestedLoopCount == 0)
14305 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14306 "omp target teams distribute loop exprs were not built");
14309 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14319 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
14321 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14325 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
14327 OMPLoopBasedDirective::HelperExprs B;
14333 VarsWithImplicitDSA, B);
14334 if (NestedLoopCount == 0)
14341 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14352 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
14354 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14358 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
14360 OMPLoopBasedDirective::HelperExprs B;
14363 unsigned NestedLoopCount =
14368 if (NestedLoopCount == 0)
14378 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14388 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
14390 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14394 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
14396 OMPLoopBasedDirective::HelperExprs B;
14402 VarsWithImplicitDSA, B);
14403 if (NestedLoopCount == 0)
14413 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14420 Stmt *Dir = Transform->getDirective();
14422#define STMT(CLASS, PARENT)
14423#define ABSTRACT_STMT(CLASS)
14424#define COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT) \
14425 case Stmt::CLASS##Class: \
14426 appendFlattenedStmtList(PreInits, \
14427 static_cast<const CLASS *>(Dir)->getPreInits()); \
14429#define OMPCANONICALLOOPNESTTRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14430 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14431#define OMPCANONICALLOOPSEQUENCETRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14432 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14433#include "clang/AST/StmtNodes.inc"
14434#undef COMMON_OMP_LOOP_TRANSFORMATION
14436 llvm_unreachable(
"Not a loop transformation");
14440bool SemaOpenMP::checkTransformableLoopNest(
14444 OriginalInits.emplace_back();
14445 bool Result = OMPLoopBasedDirective::doForAllLoops(
14447 [
this, &LoopHelpers, &Body, &OriginalInits, Kind](
unsigned Cnt,
14449 VarsWithInheritedDSAType TmpDSA;
14450 unsigned SingleNumLoops =
14451 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
14452 TmpDSA, LoopHelpers[Cnt]);
14453 if (SingleNumLoops == 0)
14455 assert(SingleNumLoops == 1 &&
"Expect single loop iteration space");
14456 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14457 OriginalInits.back().push_back(For->getInit());
14458 Body = For->getBody();
14460 assert(isa<CXXForRangeStmt>(CurStmt) &&
14461 "Expected canonical for or range-based for loops.");
14462 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14463 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14464 Body = CXXFor->getBody();
14466 OriginalInits.emplace_back();
14469 [&OriginalInits](OMPLoopTransformationDirective *Transform) {
14472 assert(OriginalInits.back().empty() &&
"No preinit after innermost loop");
14473 OriginalInits.pop_back();
14511 unsigned NestedLoopCount = 0;
14558bool SemaOpenMP::analyzeLoopSequence(
Stmt *LoopSeqStmt,
14559 LoopSequenceAnalysis &SeqAnalysis,
14565 auto StoreLoopStatements = [](LoopAnalysis &Analysis, Stmt *LoopStmt) {
14566 if (
auto *For = dyn_cast<ForStmt>(LoopStmt)) {
14567 Analysis.OriginalInits.push_back(For->getInit());
14568 Analysis.TheForStmt = For;
14571 Analysis.OriginalInits.push_back(CXXFor->getBeginStmt());
14572 Analysis.TheForStmt = CXXFor;
14579 auto AnalyzeLoopGeneration = [&](Stmt *Child) {
14581 Stmt *TransformedStmt = LoopTransform->getTransformedStmt();
14582 unsigned NumGeneratedTopLevelLoops =
14583 LoopTransform->getNumGeneratedTopLevelLoops();
14586 if (!TransformedStmt) {
14587 if (NumGeneratedTopLevelLoops > 0) {
14588 SeqAnalysis.LoopSeqSize += NumGeneratedTopLevelLoops;
14592 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14593 << 0 << getOpenMPDirectiveName(Kind);
14598 if (!NumGeneratedTopLevelLoops) {
14599 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14600 << 0 << getOpenMPDirectiveName(Kind);
14604 if (NumGeneratedTopLevelLoops > 1) {
14611 updatePreInits(LoopTransform, SeqAnalysis.LoopSequencePreInits);
14612 return analyzeLoopSequence(TransformedStmt, SeqAnalysis, Context, Kind);
14616 LoopAnalysis &NewTransformedSingleLoop =
14617 SeqAnalysis.Loops.emplace_back(Child);
14620 NewTransformedSingleLoop.HelperExprs);
14625 StoreLoopStatements(NewTransformedSingleLoop, TransformedStmt);
14626 updatePreInits(LoopTransform, NewTransformedSingleLoop.TransformsPreInits);
14628 SeqAnalysis.LoopSeqSize++;
14633 auto AnalyzeRegularLoop = [&](Stmt *Child) {
14634 LoopAnalysis &NewRegularLoop = SeqAnalysis.Loops.emplace_back(Child);
14635 unsigned IsCanonical =
14637 TmpDSA, NewRegularLoop.HelperExprs);
14642 StoreLoopStatements(NewRegularLoop, Child);
14643 NestedLoopCounterVisitor NLCV;
14649 for (Stmt *Child : LoopSeqStmt->
children()) {
14653 if (!LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
14654 Child = Child->IgnoreContainers();
14661 if (!analyzeLoopSequence(Child, SeqAnalysis, Context, Kind))
14668 if (LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
14669 if (LoopAnalysis::isLoopTransformation(Child)) {
14670 if (!AnalyzeLoopGeneration(Child))
14674 if (!AnalyzeRegularLoop(Child))
14676 SeqAnalysis.LoopSeqSize++;
14680 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14681 << 0 << getOpenMPDirectiveName(Kind);
14688bool SemaOpenMP::checkTransformableLoopSequence(
14713 << getOpenMPDirectiveName(Kind);
14718 if (!analyzeLoopSequence(AStmt, SeqAnalysis, Context, Kind))
14722 if (!SeqAnalysis.LoopSeqSize) {
14724 << getOpenMPDirectiveName(Kind);
14732 OMPLoopBasedDirective::HelperExprs &LoopHelper,
14738 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
14739 Stmt *RangeInit = CXXRangeFor->getInit();
14741 PreInits.push_back(RangeInit);
14743 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14748 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14754 llvm::append_range(PreInits, OriginalInit);
14757 if (
auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits)) {
14758 PreInits.push_back(
new (Context)
DeclStmt(
14759 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14763 for (
Expr *CounterRef : LoopHelper.Counters) {
14766 PreInits.push_back(
new (Context)
DeclStmt(
14774 size_t NumLoops = LoopStmts.size();
14775 OMPLoopBasedDirective::doForAllLoops(
14776 AStmt,
false, NumLoops,
14777 [LoopStmts](
unsigned Cnt,
Stmt *CurStmt) {
14778 assert(!LoopStmts[Cnt] &&
"Loop statement must not yet be assigned");
14779 LoopStmts[Cnt] = CurStmt;
14782 assert(!is_contained(LoopStmts,
nullptr) &&
14783 "Expecting a loop statement for each affected loop");
14801 const auto *SizesClause =
14802 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14803 if (!SizesClause ||
14804 llvm::any_of(SizesClause->getSizesRefs(), [](
Expr *E) { return !E; }))
14806 unsigned NumLoops = SizesClause->getNumSizes();
14814 Stmt *Body =
nullptr;
14816 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14821 if (
SemaRef.CurContext->isDependentContext())
14823 NumLoops, AStmt,
nullptr,
nullptr);
14825 assert(LoopHelpers.size() == NumLoops &&
14826 "Expecting loop iteration space dimensionality to match number of "
14828 assert(OriginalInits.size() == NumLoops &&
14829 "Expecting loop iteration space dimensionality to match number of "
14837 CaptureVars CopyTransformer(
SemaRef);
14842 FloorIndVars.resize(NumLoops);
14843 TileIndVars.resize(NumLoops);
14844 for (
unsigned I = 0; I < NumLoops; ++I) {
14845 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14847 assert(LoopHelper.Counters.size() == 1 &&
14848 "Expect single-dimensional loop iteration space");
14850 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14856 std::string FloorCntName =
14857 (Twine(
".floor_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
14860 FloorIndVars[I] = FloorCntDecl;
14865 std::string TileCntName =
14866 (Twine(
".tile_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
14872 TileCntDecl->setDeclName(
14873 &
SemaRef.PP.getIdentifierTable().get(TileCntName));
14874 TileIndVars[I] = TileCntDecl;
14882 Stmt *Inner = Body;
14884 auto MakeDimTileSize = [&
SemaRef = this->SemaRef, &CopyTransformer, &Context,
14885 SizesClause, CurScope](
int I) ->
Expr * {
14886 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
14892 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
14911 uint64_t DimWidth = Context.getTypeSize(DimTy);
14913 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14917 CurScope, {}, BO_LE,
14921 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), 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];
14937 auto MakeTileIVRef = [&
SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
14940 OrigCntVar->getExprLoc());
14944 SemaRef.AddInitializerToDecl(
14947 .DefaultLvalueConversion(
14951 Decl *CounterDecl = TileIndVars[I];
14954 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14960 Expr *DimTileSize = MakeDimTileSize(I);
14964 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14970 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14971 NumIterations, EndOfTile.
get());
14975 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
14976 IsPartialTile.
get(), NumIterations, EndOfTile.
get());
14977 if (!MinTileAndIterSpace.
isUsable())
14980 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14981 MakeTileIVRef(), MinTileAndIterSpace.
get());
14987 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef());
15008 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15009 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15010 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15011 BodyParts.push_back(Inner);
15014 Inner =
new (Context)
15017 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15021 for (
int I = NumLoops - 1; I >= 0; --I) {
15022 auto &LoopHelper = LoopHelpers[I];
15023 Expr *NumIterations = LoopHelper.NumIterations;
15028 SemaRef.AddInitializerToDecl(
15030 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15032 Decl *CounterDecl = FloorIndVars[I];
15041 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15048 Expr *DimTileSize = MakeDimTileSize(I);
15052 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15058 Inner =
new (Context)
15061 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15076 const auto *SizesClause =
15077 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
15078 if (!SizesClause ||
15079 llvm::any_of(SizesClause->getSizesRefs(), [](
const Expr *SizeExpr) {
15080 return !SizeExpr || SizeExpr->containsErrors();
15083 unsigned NumLoops = SizesClause->getNumSizes();
15091 Stmt *Body =
nullptr;
15093 if (!checkTransformableLoopNest(OMPD_stripe, AStmt, NumLoops, LoopHelpers,
15094 Body, OriginalInits))
15098 if (
SemaRef.CurContext->isDependentContext())
15100 NumLoops, AStmt,
nullptr,
nullptr);
15102 assert(LoopHelpers.size() == NumLoops &&
15103 "Expecting loop iteration space dimensionality to match number of "
15105 assert(OriginalInits.size() == NumLoops &&
15106 "Expecting loop iteration space dimensionality to match number of "
15114 CaptureVars CopyTransformer(
SemaRef);
15119 FloorIndVars.resize(NumLoops);
15120 StripeIndVars.resize(NumLoops);
15121 for (
unsigned I : llvm::seq<unsigned>(NumLoops)) {
15122 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15124 assert(LoopHelper.Counters.size() == 1 &&
15125 "Expect single-dimensional loop iteration space");
15127 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15133 std::string FloorCntName =
15134 (Twine(
".floor_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
15137 FloorIndVars[I] = FloorCntDecl;
15142 std::string StripeCntName =
15143 (Twine(
".stripe_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
15149 StripeCntDecl->setDeclName(
15150 &
SemaRef.PP.getIdentifierTable().get(StripeCntName));
15151 StripeIndVars[I] = StripeCntDecl;
15159 Stmt *Inner = Body;
15161 auto MakeDimStripeSize = [&](
int I) ->
Expr * {
15162 Expr *DimStripeSizeExpr = SizesClause->getSizesRefs()[I];
15164 return AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr));
15183 uint64_t DimWidth = Context.getTypeSize(DimTy);
15185 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
15189 CurScope, {}, BO_LE,
15193 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), DimTy,
15199 for (
int I = NumLoops - 1; I >= 0; --I) {
15200 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15201 Expr *NumIterations = LoopHelper.NumIterations;
15204 Stmt *LoopStmt = LoopStmts[I];
15207 SemaRef.AddInitializerToDecl(
15210 .DefaultLvalueConversion(
15214 Decl *CounterDecl = StripeIndVars[I];
15217 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15224 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15226 MakeDimStripeSize(I));
15230 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15231 NumIterations, EndOfStripe.
get());
15235 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
15236 IsPartialStripe.
get(), NumIterations, EndOfStripe.
get());
15237 if (!MinStripeAndIterSpace.
isUsable())
15240 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15242 MinStripeAndIterSpace.
get());
15248 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc,
15270 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15271 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15272 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15273 BodyParts.push_back(Inner);
15276 Inner =
new (Context)
15279 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15283 for (
int I = NumLoops - 1; I >= 0; --I) {
15284 auto &LoopHelper = LoopHelpers[I];
15285 Expr *NumIterations = LoopHelper.NumIterations;
15290 SemaRef.AddInitializerToDecl(
15292 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15294 Decl *CounterDecl = FloorIndVars[I];
15303 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15311 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15313 MakeDimStripeSize(I));
15317 Inner =
new (Context)
15320 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15324 NumLoops, AStmt, Inner,
15339 {OMPC_partial, OMPC_full}))
15343 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
15345 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
15346 assert(!(FullClause && PartialClause) &&
15347 "mutual exclusivity must have been checked before");
15349 constexpr unsigned NumLoops = 1;
15350 Stmt *Body =
nullptr;
15354 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
15355 Body, OriginalInits))
15358 unsigned NumGeneratedTopLevelLoops = PartialClause ? 1 : 0;
15361 if (
SemaRef.CurContext->isDependentContext())
15363 NumGeneratedTopLevelLoops,
nullptr,
15366 assert(LoopHelpers.size() == NumLoops &&
15367 "Expecting a single-dimensional loop iteration space");
15368 assert(OriginalInits.size() == NumLoops &&
15369 "Expecting a single-dimensional loop iteration space");
15370 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15374 LoopHelper.NumIterations, OMPC_full,
false,
15377 Diag(AStmt->
getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
15379 <<
"#pragma omp unroll full";
15387 if (NumGeneratedTopLevelLoops == 0)
15389 NumGeneratedTopLevelLoops,
nullptr,
15435 Stmt *LoopStmt =
nullptr;
15440 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15443 QualType IVTy = IterationVarRef->getType();
15444 assert(LoopHelper.Counters.size() == 1 &&
15445 "Expecting a single-dimensional loop iteration space");
15453 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
15454 FactorLoc = FactorVal->getExprLoc();
15459 assert(Factor > 0 &&
"Expected positive unroll factor");
15460 auto MakeFactorExpr = [
this, Factor, IVTy, FactorLoc]() {
15472 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15473 std::string OuterIVName = (Twine(
".unrolled.iv.") + OrigVarName).str();
15474 std::string InnerIVName = (Twine(
".unroll_inner.iv.") + OrigVarName).str();
15479 auto MakeOuterRef = [
this, OuterIVDecl, IVTy, OrigVarLoc]() {
15485 auto *InnerIVDecl =
cast<VarDecl>(IterationVarRef->getDecl());
15486 InnerIVDecl->setDeclName(&
SemaRef.PP.getIdentifierTable().get(InnerIVName));
15487 auto MakeInnerRef = [
this, InnerIVDecl, IVTy, OrigVarLoc]() {
15493 CaptureVars CopyTransformer(
SemaRef);
15494 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() ->
Expr * {
15496 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15501 SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.
get(),
15516 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15517 MakeOuterRef(), MakeFactorExpr());
15521 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15522 MakeInnerRef(), EndOfTile.
get());
15526 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15527 MakeInnerRef(), MakeNumIterations());
15531 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
15532 InnerCond1.
get(), InnerCond2.
get());
15538 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef());
15544 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15545 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15546 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15547 InnerBodyStmts.push_back(Body);
15551 ForStmt *InnerFor =
new (Context)
15552 ForStmt(Context, InnerInit.
get(), InnerCond.
get(),
nullptr,
15554 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15568 LoopHintAttr *UnrollHintAttr =
15569 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
15570 LoopHintAttr::Numeric, MakeFactorExpr());
15575 SemaRef.AddInitializerToDecl(
15577 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15586 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15587 MakeOuterRef(), MakeNumIterations());
15593 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15594 MakeOuterRef(), MakeFactorExpr());
15599 ForStmt *OuterFor =
new (Context)
15600 ForStmt(Context, OuterInit.
get(), OuterConde.
get(),
nullptr,
15602 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15605 NumGeneratedTopLevelLoops, OuterFor,
15619 constexpr unsigned NumLoops = 1;
15620 Stmt *Body =
nullptr;
15624 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
15625 Body, OriginalInits))
15630 if (
SemaRef.CurContext->isDependentContext())
15632 NumLoops,
nullptr,
nullptr);
15634 assert(LoopHelpers.size() == NumLoops &&
15635 "Expecting a single-dimensional loop iteration space");
15636 assert(OriginalInits.size() == NumLoops &&
15637 "Expecting a single-dimensional loop iteration space");
15638 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15641 Stmt *LoopStmt =
nullptr;
15646 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15649 QualType IVTy = IterationVarRef->getType();
15650 uint64_t IVWidth = Context.getTypeSize(IVTy);
15664 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15666 ForwardIVName += OrigVarName;
15668 ReversedIVName += OrigVarName;
15701 CaptureVars CopyTransformer(
SemaRef);
15702 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() ->
Expr * {
15704 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15710 auto MakeForwardRef = [&
SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
15717 auto *ReversedIVDecl =
cast<VarDecl>(IterationVarRef->getDecl());
15718 ReversedIVDecl->setDeclName(
15719 &
SemaRef.PP.getIdentifierTable().get(ReversedIVName));
15726 ForwardIVDecl->
getType(), OrigVarLoc);
15727 SemaRef.AddInitializerToDecl(ForwardIVDecl,
Zero,
false);
15730 if (!
Init.isUsable())
15738 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15739 MakeForwardRef(), MakeNumIterations());
15740 if (!
Cond.isUsable())
15748 UO_PreInc, MakeForwardRef());
15759 MakeNumIterations(), One);
15762 Minus =
SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, Minus.
get(),
15767 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
15770 SemaRef.AddInitializerToDecl(ReversedIVDecl, Minus.
get(),
15775 BodyStmts.reserve(LoopHelper.Updates.size() + 2 +
15777 BodyStmts.push_back(InitReversed.
get());
15778 llvm::append_range(BodyStmts, LoopHelper.Updates);
15779 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15780 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15781 BodyStmts.push_back(Body);
15782 auto *ReversedBody =
15787 auto *ReversedFor =
new (Context)
15790 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15809 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
15810 size_t NumLoops = PermutationClause ? PermutationClause->
getNumLoops() : 2;
15814 Stmt *Body =
nullptr;
15816 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
15817 LoopHelpers, Body, OriginalInits))
15823 NumLoops, AStmt,
nullptr,
nullptr);
15827 if (PermutationClause &&
15828 llvm::is_contained(PermutationClause->
getArgsRefs(),
nullptr))
15831 assert(LoopHelpers.size() == NumLoops &&
15832 "Expecting loop iteration space dimensionaly to match number of "
15834 assert(OriginalInits.size() == NumLoops &&
15835 "Expecting loop iteration space dimensionaly to match number of "
15840 if (!PermutationClause) {
15841 Permutation = {1, 0};
15844 llvm::BitVector Flags(PermArgs.size());
15845 for (
Expr *PermArg : PermArgs) {
15846 std::optional<llvm::APSInt> PermCstExpr =
15847 PermArg->getIntegerConstantExpr(Context);
15850 uint64_t PermInt = PermCstExpr->getZExtValue();
15851 assert(1 <= PermInt && PermInt <= NumLoops &&
15852 "Must be a permutation; diagnostic emitted in "
15853 "ActOnOpenMPPermutationClause");
15854 if (Flags[PermInt - 1]) {
15855 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
15856 Diag(PermArg->getExprLoc(),
15857 diag::err_omp_interchange_permutation_value_repeated)
15858 << PermInt << ExprRange;
15861 Flags[PermInt - 1] =
true;
15863 Permutation.push_back(PermInt - 1);
15866 if (Permutation.size() != NumLoops)
15871 if (NumLoops <= 1 || llvm::all_of(llvm::enumerate(Permutation), [](
auto P) {
15872 auto [Idx, Arg] = P;
15876 NumLoops, AStmt, AStmt,
nullptr);
15884 for (
auto I : llvm::seq<int>(NumLoops)) {
15885 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15887 assert(LoopHelper.Counters.size() == 1 &&
15888 "Single-dimensional loop iteration space expected");
15895 CaptureVars CopyTransformer(
SemaRef);
15900 Stmt *Inner = Body;
15901 for (
auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
15903 uint64_t SourceIdx = Permutation[TargetIdx];
15904 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
15905 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
15906 assert(SourceHelper.Counters.size() == 1 &&
15907 "Single-dimensional loop iteration space expected");
15914 "Expected the logical iteration counter to be an integer");
15916 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15921 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() ->
Expr * {
15923 CopyTransformer.TransformExpr(SourceHelper.NumIterations));
15930 PermutedCntName.append({llvm::utostr(TargetIdx),
".iv.", OrigVarName});
15932 PermutedCntDecl->setDeclName(
15933 &
SemaRef.PP.getIdentifierTable().get(PermutedCntName));
15934 PermutedIndVars[TargetIdx] = PermutedCntDecl;
15935 auto MakePermutedRef = [
this, PermutedCntDecl, IVTy, OrigVarLoc]() {
15944 if (!
Zero.isUsable())
15946 SemaRef.AddInitializerToDecl(PermutedCntDecl,
Zero.get(),
15950 OrigCntVar->getEndLoc());
15959 SemaRef.BuildBinOp(CurScope, SourceHelper.Cond->getExprLoc(), BO_LT,
15960 MakePermutedRef(), MakeNumIterations());
15969 CurScope, SourceHelper.Inc->getExprLoc(), UO_PreInc, MakePermutedRef());
15974 SourceHelper.Updates.end());
15975 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
15976 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15977 BodyParts.push_back(Inner);
15980 Inner =
new (Context)
ForStmt(
15981 Context, InitStmt.
get(), CondExpr.
get(),
nullptr, IncrStmt.
get(), Inner,
15982 SourceHelper.Init->
getBeginLoc(), SourceHelper.Init->getBeginLoc(),
15983 SourceHelper.Inc->getEndLoc());
15987 NumLoops, AStmt, Inner,
15999 CaptureVars CopyTransformer(
SemaRef);
16011 1, AStmt,
nullptr,
nullptr);
16015 LoopSequenceAnalysis SeqAnalysis;
16016 if (!checkTransformableLoopSequence(OMPD_fuse, AStmt, SeqAnalysis, Context))
16021 assert(SeqAnalysis.LoopSeqSize == SeqAnalysis.Loops.size() &&
16022 "Inconsistent size of the loop sequence and the number of loops "
16023 "found in the sequence");
16027 OMPExecutableDirective::getSingleClause<OMPLoopRangeClause>(Clauses);
16031 if (LRC && (!LRC->getFirst() || !LRC->getCount()))
16036 auto EvaluateLoopRangeArguments = [&Context](
Expr *
First,
Expr *Count,
16037 uint64_t &FirstVal,
16038 uint64_t &CountVal) {
16039 llvm::APSInt FirstInt =
First->EvaluateKnownConstInt(Context);
16040 llvm::APSInt CountInt = Count->EvaluateKnownConstInt(Context);
16041 FirstVal = FirstInt.getZExtValue();
16042 CountVal = CountInt.getZExtValue();
16048 auto ValidLoopRange = [](uint64_t FirstVal, uint64_t CountVal,
16049 unsigned NumLoops) ->
bool {
16050 return FirstVal + CountVal - 1 <= NumLoops;
16052 uint64_t FirstVal = 1, CountVal = 0, LastVal = SeqAnalysis.LoopSeqSize;
16058 EvaluateLoopRangeArguments(LRC->getFirst(), LRC->getCount(), FirstVal,
16061 SemaRef.Diag(LRC->getCountLoc(), diag::warn_omp_redundant_fusion)
16062 << getOpenMPDirectiveName(OMPD_fuse);
16064 if (!ValidLoopRange(FirstVal, CountVal, SeqAnalysis.LoopSeqSize)) {
16065 SemaRef.Diag(LRC->getFirstLoc(), diag::err_omp_invalid_looprange)
16066 << getOpenMPDirectiveName(OMPD_fuse) << FirstVal
16067 << (FirstVal + CountVal - 1) << SeqAnalysis.LoopSeqSize;
16071 LastVal = FirstVal + CountVal - 1;
16076 unsigned NumGeneratedTopLevelLoops =
16077 LRC ? SeqAnalysis.LoopSeqSize - CountVal + 1 : 1;
16081 if (SeqAnalysis.LoopSeqSize == 1)
16083 << getOpenMPDirectiveName(OMPD_fuse);
16087 SeqAnalysis.Loops[FirstVal - 1].HelperExprs.IterationVarRef->getType();
16088 for (
unsigned I : llvm::seq<unsigned>(FirstVal, LastVal)) {
16090 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef->getType();
16091 if (Context.getTypeSize(CurrentIVType) > Context.getTypeSize(IVType)) {
16092 IVType = CurrentIVType;
16095 uint64_t IVBitWidth = Context.getIntWidth(IVType);
16108 auto CreateHelperVarAndStmt =
16110 unsigned I,
bool NeedsNewVD =
false) {
16111 Expr *TransformedExpr =
16113 if (!TransformedExpr)
16114 return std::pair<VarDecl *, StmtResult>(
nullptr,
StmtError());
16116 auto Name = (Twine(
".omp.") + BaseName + std::to_string(I)).str();
16121 SemaRef.AddInitializerToDecl(VD, TransformedExpr,
false);
16131 return std::make_pair(VD,
DeclStmt);
16149 llvm::append_range(PreInits, SeqAnalysis.LoopSequencePreInits);
16162 unsigned int TransformIndex = 0;
16163 for (
unsigned I : llvm::seq<unsigned>(FirstVal - 1)) {
16164 if (SeqAnalysis.Loops[I].isLoopTransformation())
16168 for (
unsigned int I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16169 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16171 SeqAnalysis.Loops[I].TheForStmt,
16172 SeqAnalysis.Loops[I].OriginalInits, PreInits);
16173 }
else if (SeqAnalysis.Loops[I].isLoopTransformation()) {
16178 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16179 llvm::append_range(PreInits, TransformPreInit);
16182 SeqAnalysis.Loops[I].TheForStmt,
16183 SeqAnalysis.Loops[I].OriginalInits, PreInits);
16185 auto [UBVD, UBDStmt] =
16186 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.UB,
"ub", J);
16187 auto [LBVD, LBDStmt] =
16188 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.LB,
"lb", J);
16189 auto [STVD, STDStmt] =
16190 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.ST,
"st", J);
16191 auto [NIVD, NIDStmt] = CreateHelperVarAndStmt(
16192 SeqAnalysis.Loops[I].HelperExprs.NumIterations,
"ni", J,
true);
16193 auto [IVVD, IVDStmt] = CreateHelperVarAndStmt(
16194 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef,
"iv", J);
16196 assert(LBVD && STVD && NIVD && IVVD &&
16197 "OpenMP Fuse Helper variables creation failed");
16199 UBVarDecls.push_back(UBVD);
16200 LBVarDecls.push_back(LBVD);
16201 STVarDecls.push_back(STVD);
16202 NIVarDecls.push_back(NIVD);
16203 IVVarDecls.push_back(IVVD);
16205 PreInits.push_back(LBDStmt.get());
16206 PreInits.push_back(STDStmt.get());
16207 PreInits.push_back(NIDStmt.get());
16208 PreInits.push_back(IVDStmt.get());
16241 StringRef IndexName =
".omp.fuse.index";
16246 SemaRef.AddInitializerToDecl(IndexDecl, InitVal,
false);
16253 auto MakeIVRef = [&
SemaRef = this->SemaRef, IndexDecl, IVType,
16271 for (
unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16272 DeclRefExpr *NIRef = MakeVarDeclRef(NIVarDecls[J]);
16280 std::string TempName = (Twine(
".omp.temp.") + Twine(J)).str();
16294 PreInits.push_back(TempStmt.
get());
16303 DeclRefExpr *NIRef2 = MakeVarDeclRef(NIVarDecls[J]);
16317 const std::string MaxName = Twine(
".omp.fuse.max").str();
16325 if (MaxStmt.isInvalid())
16327 PreInits.push_back(MaxStmt.get());
16331 MakeIVRef(), MaxRef);
16357 for (
unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16362 MakeVarDeclRef(STVarDecls[J]), MakeIVRef());
16366 MakeVarDeclRef(LBVarDecls[J]), IdxExpr.
get());
16371 MakeVarDeclRef(IVVarDecls[J]), IdxExpr.
get());
16377 BodyStmts.push_back(IdxExpr.
get());
16378 llvm::append_range(BodyStmts, SeqAnalysis.Loops[I].HelperExprs.Updates);
16381 if (
auto *SourceCXXFor =
16382 dyn_cast<CXXForRangeStmt>(SeqAnalysis.Loops[I].TheForStmt))
16383 BodyStmts.push_back(SourceCXXFor->getLoopVarStmt());
16387 ?
cast<ForStmt>(SeqAnalysis.Loops[I].TheForStmt)->getBody()
16389 BodyStmts.push_back(Body);
16396 MakeVarDeclRef(NIVarDecls[J]));
16406 FusedBodyStmts.push_back(IfStatement);
16412 ForStmt *FusedForStmt =
new (Context)
16426 Stmt *FusionStmt = FusedForStmt;
16427 if (LRC && CountVal != SeqAnalysis.LoopSeqSize) {
16431 TransformIndex = 0;
16437 for (
unsigned I : llvm::seq<unsigned>(SeqAnalysis.LoopSeqSize)) {
16438 if (I >= FirstVal - 1 && I < FirstVal + CountVal - 1) {
16441 if (!SeqAnalysis.Loops[I].isLoopTransformation())
16450 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16451 const auto &TransformPreInit =
16452 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16453 if (!TransformPreInit.empty())
16454 llvm::append_range(PreInits, TransformPreInit);
16457 FinalLoops.push_back(SeqAnalysis.Loops[I].TheForStmt);
16460 FinalLoops.insert(FinalLoops.begin() + (FirstVal - 1), FusedForStmt);
16465 NumGeneratedTopLevelLoops, AStmt, FusionStmt,
16485 case OMPC_allocator:
16488 case OMPC_collapse:
16494 case OMPC_priority:
16506 case OMPC_novariants:
16509 case OMPC_nocontext:
16524 case OMPC_ompx_dyn_cgroup_mem:
16530 case OMPC_grainsize:
16531 case OMPC_num_tasks:
16532 case OMPC_num_threads:
16536 case OMPC_proc_bind:
16537 case OMPC_schedule:
16539 case OMPC_firstprivate:
16540 case OMPC_lastprivate:
16542 case OMPC_reduction:
16543 case OMPC_task_reduction:
16544 case OMPC_in_reduction:
16548 case OMPC_copyprivate:
16551 case OMPC_mergeable:
16552 case OMPC_threadprivate:
16553 case OMPC_groupprivate:
16555 case OMPC_allocate:
16572 case OMPC_dist_schedule:
16573 case OMPC_defaultmap:
16578 case OMPC_use_device_ptr:
16579 case OMPC_use_device_addr:
16580 case OMPC_is_device_ptr:
16581 case OMPC_unified_address:
16582 case OMPC_unified_shared_memory:
16583 case OMPC_reverse_offload:
16584 case OMPC_dynamic_allocators:
16585 case OMPC_atomic_default_mem_order:
16586 case OMPC_self_maps:
16587 case OMPC_device_type:
16589 case OMPC_nontemporal:
16592 case OMPC_severity:
16594 case OMPC_inclusive:
16595 case OMPC_exclusive:
16596 case OMPC_uses_allocators:
16597 case OMPC_affinity:
16600 case OMPC_num_teams:
16601 case OMPC_thread_limit:
16603 llvm_unreachable(
"Clause is not allowed.");
16616 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
16617 "Invalid directive with CKind-clause");
16620 if (NameModifier != OMPD_unknown &&
16621 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
16622 return OMPD_unknown;
16641 case OMPD_teams_loop:
16642 case OMPD_target_teams_loop:
16646 case OMPD_target_update:
16647 case OMPD_target_enter_data:
16648 case OMPD_target_exit_data:
16654 case OMPC_num_teams:
16655 case OMPC_thread_limit:
16656 case OMPC_ompx_dyn_cgroup_mem:
16657 if (Leafs[0] == OMPD_target)
16658 return OMPD_target;
16661 if (Leafs[0] == OMPD_target ||
16662 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
16663 OMPD_target_enter_data, OMPD_target_exit_data},
16667 case OMPC_novariants:
16668 case OMPC_nocontext:
16669 if (DKind == OMPD_dispatch)
16673 if (DKind == OMPD_metadirective)
16674 return OMPD_metadirective;
16677 return OMPD_unknown;
16690 int InnermostIdx = [&]() {
16691 for (
int I = EndIdx - 1; I >= 0; --I) {
16692 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
16700 for (
int I = InnermostIdx - 1; I >= 0; --I) {
16705 if (Regions[0] != OMPD_unknown)
16706 return Regions.back();
16708 return OMPD_unknown;
16713 for (
int I = 0, E = Leafs.size(); I != E; ++I) {
16714 if (Leafs[I] == Dir)
16720 int End = NameModifier == OMPD_unknown ? Leafs.size()
16721 : GetLeafIndex(NameModifier);
16722 return GetEnclosingRegion(End, CKind);
16725 return OMPD_unknown;
16733 Stmt *HelperValStmt =
nullptr;
16736 !
Condition->isInstantiationDependent() &&
16737 !
Condition->containsUnexpandedParameterPack()) {
16742 ValExpr = Val.
get();
16746 DKind, OMPC_if,
getLangOpts().OpenMP, NameModifier);
16747 if (CaptureRegion != OMPD_unknown &&
16748 !
SemaRef.CurContext->isDependentContext()) {
16749 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
16750 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16751 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16757 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
16758 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
16766 Stmt *HelperValStmt =
nullptr;
16769 !
Condition->isInstantiationDependent() &&
16770 !
Condition->containsUnexpandedParameterPack()) {
16775 ValExpr =
SemaRef.MakeFullExpr(Val.
get()).get();
16780 if (CaptureRegion != OMPD_unknown &&
16781 !
SemaRef.CurContext->isDependentContext()) {
16782 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
16783 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16784 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16790 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16801 IntConvertDiagnoser()
16802 : ICEConvertDiagnoser(
false,
false,
true) {}
16805 return S.
Diag(Loc, diag::err_omp_not_integral) <<
T;
16809 return S.
Diag(Loc, diag::err_omp_incomplete_type) <<
T;
16814 return S.
Diag(Loc, diag::err_omp_explicit_conversion) <<
T << ConvTy;
16823 return S.
Diag(Loc, diag::err_omp_ambiguous_conversion) <<
T;
16832 llvm_unreachable(
"conversion functions are permitted");
16834 } ConvertDiagnoser;
16835 return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
16840 bool StrictlyPositive,
bool BuildCapture =
false,
16843 Stmt **HelperValStmt =
nullptr) {
16849 if (
Value.isInvalid())
16852 ValExpr =
Value.get();
16854 if (std::optional<llvm::APSInt> Result =
16856 if (Result->isSigned() &&
16857 !((!StrictlyPositive && Result->isNonNegative()) ||
16858 (StrictlyPositive && Result->isStrictlyPositive()))) {
16859 SemaRef.
Diag(Loc, diag::err_omp_negative_expression_in_clause)
16869 if (*CaptureRegion != OMPD_unknown &&
16872 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16873 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16884 llvm::raw_svector_ostream
Out(Buffer);
16885 unsigned Skipped = Exclude.size();
16886 for (
unsigned I =
First; I <
Last; ++I) {
16887 if (llvm::is_contained(Exclude, I)) {
16892 if (I + Skipped + 2 ==
Last)
16894 else if (I + Skipped + 1 !=
Last)
16897 return std::string(
Out.str());
16905 "Unexpected num_threads modifier in OpenMP < 60.");
16910 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
16915 Expr *ValExpr = NumThreads;
16916 Stmt *HelperValStmt =
nullptr;
16927 if (CaptureRegion != OMPD_unknown &&
16928 !
SemaRef.CurContext->isDependentContext()) {
16929 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
16930 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16931 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16937 StartLoc, LParenLoc, ModifierLoc, EndLoc);
16942 bool SuppressExprDiags) {
16951 if (SuppressExprDiags) {
16955 SuppressedDiagnoser() : VerifyICEDiagnoser(
true) {}
16958 llvm_unreachable(
"Diagnostic suppressed");
16961 ICE =
SemaRef.VerifyIntegerConstantExpression(E, &
Result, Diagnoser,
16971 if ((StrictlyPositive && !
Result.isStrictlyPositive()) ||
16972 (!StrictlyPositive && !
Result.isNonNegative())) {
16973 Diag(E->
getExprLoc(), diag::err_omp_negative_expression_in_clause)
16978 if ((CKind == OMPC_aligned || CKind == OMPC_align ||
16979 CKind == OMPC_allocate) &&
16981 Diag(E->
getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
16986 if (!
Result.isRepresentableByInt64()) {
16992 if (CKind == OMPC_collapse &&
DSAStack->getAssociatedLoops() == 1)
16994 else if (CKind == OMPC_ordered)
17013 if (
Result.isNonNegative()) {
17017 diag::err_omp_negative_expression_in_clause)
17020 }
else if (
auto *DeclRef = dyn_cast<DeclRefExpr>(DeviceNumExpr)) {
17027 Diag(DeviceNumExpr->
getExprLoc(), diag::err_expected_expression);
17061 DSAStackTy *Stack) {
17062 if (!Stack->getOMPAllocatorHandleT().isNull())
17069 S.
Diag(Loc, diag::err_omp_implied_type_not_found)
17070 <<
"omp_allocator_handle_t";
17075 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
17078 bool ErrorFound =
false;
17079 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
17080 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
17081 StringRef Allocator =
17082 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
17084 auto *VD = dyn_cast_or_null<ValueDecl>(
17104 Stack->setAllocator(AllocatorKind, Res.
get());
17107 S.
Diag(Loc, diag::err_omp_implied_type_not_found)
17108 <<
"omp_allocator_handle_t";
17127 Allocator =
SemaRef.PerformImplicitConversion(
17128 Allocator.
get(),
DSAStack->getOMPAllocatorHandleT(),
17157 Expr *NumForLoops) {
17163 if (NumForLoops && LParenLoc.
isValid()) {
17168 NumForLoops = NumForLoopsResult.
get();
17170 NumForLoops =
nullptr;
17174 NumForLoops ?
DSAStack->getAssociatedLoops() : 0,
17175 StartLoc, LParenLoc, EndLoc);
17176 DSAStack->setOrderedRegion(
true, NumForLoops, Clause);
17185 case OMPC_proc_bind:
17187 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17189 case OMPC_atomic_default_mem_order:
17192 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17196 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17200 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17204 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17208 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17210 case OMPC_severity:
17213 LParenLoc, EndLoc);
17217 case OMPC_num_threads:
17221 case OMPC_allocator:
17222 case OMPC_collapse:
17223 case OMPC_schedule:
17225 case OMPC_firstprivate:
17226 case OMPC_lastprivate:
17228 case OMPC_reduction:
17229 case OMPC_task_reduction:
17230 case OMPC_in_reduction:
17234 case OMPC_copyprivate:
17238 case OMPC_mergeable:
17239 case OMPC_threadprivate:
17240 case OMPC_groupprivate:
17241 case OMPC_allocate:
17258 case OMPC_num_teams:
17259 case OMPC_thread_limit:
17260 case OMPC_priority:
17261 case OMPC_grainsize:
17263 case OMPC_num_tasks:
17265 case OMPC_dist_schedule:
17267 case OMPC_defaultmap:
17272 case OMPC_use_device_ptr:
17273 case OMPC_use_device_addr:
17274 case OMPC_is_device_ptr:
17275 case OMPC_has_device_addr:
17276 case OMPC_unified_address:
17277 case OMPC_unified_shared_memory:
17278 case OMPC_reverse_offload:
17279 case OMPC_dynamic_allocators:
17280 case OMPC_self_maps:
17281 case OMPC_device_type:
17283 case OMPC_nontemporal:
17285 case OMPC_novariants:
17286 case OMPC_nocontext:
17288 case OMPC_inclusive:
17289 case OMPC_exclusive:
17290 case OMPC_uses_allocators:
17291 case OMPC_affinity:
17295 llvm_unreachable(
"Clause is not allowed.");
17304 if (M == OMP_DEFAULT_unknown) {
17305 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17307 unsigned(OMP_DEFAULT_unknown))
17313 case OMP_DEFAULT_none:
17314 DSAStack->setDefaultDSANone(MLoc);
17316 case OMP_DEFAULT_shared:
17317 DSAStack->setDefaultDSAShared(MLoc);
17319 case OMP_DEFAULT_firstprivate:
17320 DSAStack->setDefaultDSAFirstPrivate(MLoc);
17322 case OMP_DEFAULT_private:
17323 DSAStack->setDefaultDSAPrivate(MLoc);
17326 llvm_unreachable(
"DSA unexpected in OpenMP default clause");
17330 case OMPC_DEFAULT_VC_aggregate:
17331 DSAStack->setDefaultDSAVCAggregate(VCKindLoc);
17333 case OMPC_DEFAULT_VC_all:
17334 DSAStack->setDefaultDSAVCAll(VCKindLoc);
17336 case OMPC_DEFAULT_VC_allocatable:
17337 DSAStack->setDefaultDSAVCAllocatable(VCKindLoc);
17339 case OMPC_DEFAULT_VC_pointer:
17340 DSAStack->setDefaultDSAVCPointer(VCKindLoc);
17342 case OMPC_DEFAULT_VC_scalar:
17343 DSAStack->setDefaultDSAVCScalar(VCKindLoc);
17346 Diag(VCKindLoc, diag::err_omp_default_vc)
17351 OMPDefaultClause(M, MLoc, VCKind, VCKindLoc, StartLoc, LParenLoc, EndLoc);
17359 if (Kind == OMP_PROC_BIND_unknown) {
17360 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17362 unsigned(OMP_PROC_BIND_master),
17365 ? OMP_PROC_BIND_primary
17366 : OMP_PROC_BIND_spread) +
17371 if (Kind == OMP_PROC_BIND_primary &&
getLangOpts().OpenMP < 51)
17372 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17374 unsigned(OMP_PROC_BIND_master),
17376 unsigned(OMP_PROC_BIND_spread) + 1)
17386 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17388 OMPC_atomic_default_mem_order, 0,
17394 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17403 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17410 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17419 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17433 assert(ME &&
"NULL expr in Message clause");
17442 Stmt *HelperValStmt =
nullptr;
17448 DKind == OMPD_unknown ? OMPD_unknown
17451 if (CaptureRegion != OMPD_unknown &&
17452 !
SemaRef.CurContext->isDependentContext()) {
17453 ME =
SemaRef.MakeFullExpr(ME).get();
17454 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17455 ME = tryBuildCapture(
SemaRef, ME, Captures).get();
17460 ME =
SemaRef.DefaultFunctionArrayLvalueConversion(ME).get();
17463 ME, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17470 if (Kind != OMPC_ORDER_concurrent ||
17475 "OMPC_ORDER_unknown not greater than 0");
17477 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17486 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17492 DSAStack->setRegionHasOrderConcurrent(
true);
17495 unsigned existingFlags =
DSAStack->getCurScope()->getFlags();
17496 DSAStack->getCurScope()->setFlags(existingFlags |
17501 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
17510 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
17512 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
17513 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
17515 Except.push_back(OMPC_DEPEND_inoutset);
17516 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17523 KindKwLoc, Kind, EndLoc);
17532 for (
Expr *&SizeExpr : SanitizedSizeExprs) {
17542 QualType SizeTy = SizeExpr->getType();
17571 if (!SizeExpr->isInstantiationDependent() && !IsValid)
17572 SizeExpr =
nullptr;
17576 SanitizedSizeExprs);
17583 size_t NumLoops = PermExprs.size();
17585 llvm::append_range(SanitizedPermExprs, PermExprs);
17587 for (
Expr *&PermExpr : SanitizedPermExprs) {
17590 if (!PermExpr || PermExpr->isInstantiationDependent())
17593 llvm::APSInt PermVal;
17596 bool IsValid = PermEvalExpr.
isUsable();
17598 PermExpr = PermEvalExpr.
get();
17600 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
17604 diag::err_omp_interchange_permutation_value_range)
17605 << NumLoops << ExprRange;
17609 if (!PermExpr->isInstantiationDependent() && !IsValid)
17610 PermExpr =
nullptr;
17614 EndLoc, SanitizedPermExprs);
17630 FactorExpr, OMPC_partial,
true);
17633 FactorExpr = FactorResult.
get();
17662 FirstLoc, CountLoc, EndLoc,
First, Count);
17673 LParenLoc, EndLoc);
17683 case OMPC_schedule:
17684 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
17685 assert(Argument.size() == NumberOfElements &&
17686 ArgumentLoc.size() == NumberOfElements);
17691 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
17692 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
17695 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17697 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
17700 case OMPC_dist_schedule:
17703 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
17706 enum { DefaultModifier, DefaultVarCategory };
17708 static_cast<llvm::omp::DefaultKind
>(Argument[DefaultModifier]),
17709 ArgumentLoc[DefaultModifier],
17711 Argument[DefaultVarCategory]),
17712 ArgumentLoc[DefaultVarCategory], StartLoc, LParenLoc, EndLoc);
17714 case OMPC_defaultmap:
17715 enum { Modifier, DefaultmapKind };
17719 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
17723 enum { OrderModifier, OrderKind };
17727 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
17730 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17733 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17735 case OMPC_grainsize:
17736 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17737 "Modifier for grainsize clause and its location are expected.");
17740 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17742 case OMPC_num_tasks:
17743 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17744 "Modifier for num_tasks clause and its location are expected.");
17747 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17749 case OMPC_num_threads:
17750 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17751 "Modifier for num_threads clause and its location are expected.");
17754 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17760 case OMPC_allocator:
17761 case OMPC_collapse:
17762 case OMPC_proc_bind:
17764 case OMPC_firstprivate:
17765 case OMPC_lastprivate:
17767 case OMPC_reduction:
17768 case OMPC_task_reduction:
17769 case OMPC_in_reduction:
17773 case OMPC_copyprivate:
17777 case OMPC_mergeable:
17778 case OMPC_threadprivate:
17779 case OMPC_groupprivate:
17780 case OMPC_allocate:
17797 case OMPC_num_teams:
17798 case OMPC_thread_limit:
17799 case OMPC_priority:
17806 case OMPC_use_device_ptr:
17807 case OMPC_use_device_addr:
17808 case OMPC_is_device_ptr:
17809 case OMPC_has_device_addr:
17810 case OMPC_unified_address:
17811 case OMPC_unified_shared_memory:
17812 case OMPC_reverse_offload:
17813 case OMPC_dynamic_allocators:
17814 case OMPC_atomic_default_mem_order:
17815 case OMPC_self_maps:
17816 case OMPC_device_type:
17818 case OMPC_nontemporal:
17820 case OMPC_severity:
17823 case OMPC_novariants:
17824 case OMPC_nocontext:
17826 case OMPC_inclusive:
17827 case OMPC_exclusive:
17828 case OMPC_uses_allocators:
17829 case OMPC_affinity:
17833 llvm_unreachable(
"Clause is not allowed.");
17844 Excluded.push_back(M2);
17845 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
17846 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
17847 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
17848 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
17849 S.
Diag(M1Loc, diag::err_omp_unexpected_clause_value)
17872 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
17873 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
17874 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
17875 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
17876 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
17882 std::string Values;
17892 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17901 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
17902 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
17903 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
17904 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
17905 diag::err_omp_schedule_nonmonotonic_static);
17908 Expr *ValExpr = ChunkSize;
17909 Stmt *HelperValStmt =
nullptr;
17920 ValExpr = Val.
get();
17925 if (std::optional<llvm::APSInt>
Result =
17927 if (
Result->isSigned() && !
Result->isStrictlyPositive()) {
17928 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
17933 DSAStack->getCurrentDirective(), OMPC_schedule,
17935 !
SemaRef.CurContext->isDependentContext()) {
17936 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
17937 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17938 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
17946 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
17963 case OMPC_mergeable:
18011 case OMPC_unified_address:
18014 case OMPC_unified_shared_memory:
18017 case OMPC_reverse_offload:
18020 case OMPC_dynamic_allocators:
18023 case OMPC_self_maps:
18037 case OMPC_ompx_bare:
18042 case OMPC_num_threads:
18046 case OMPC_allocator:
18047 case OMPC_collapse:
18048 case OMPC_schedule:
18050 case OMPC_firstprivate:
18051 case OMPC_lastprivate:
18053 case OMPC_reduction:
18054 case OMPC_task_reduction:
18055 case OMPC_in_reduction:
18059 case OMPC_copyprivate:
18061 case OMPC_proc_bind:
18062 case OMPC_threadprivate:
18063 case OMPC_groupprivate:
18064 case OMPC_allocate:
18070 case OMPC_num_teams:
18071 case OMPC_thread_limit:
18072 case OMPC_priority:
18073 case OMPC_grainsize:
18074 case OMPC_num_tasks:
18076 case OMPC_dist_schedule:
18077 case OMPC_defaultmap:
18082 case OMPC_use_device_ptr:
18083 case OMPC_use_device_addr:
18084 case OMPC_is_device_ptr:
18085 case OMPC_has_device_addr:
18086 case OMPC_atomic_default_mem_order:
18087 case OMPC_device_type:
18089 case OMPC_nontemporal:
18092 case OMPC_severity:
18094 case OMPC_novariants:
18095 case OMPC_nocontext:
18097 case OMPC_inclusive:
18098 case OMPC_exclusive:
18099 case OMPC_uses_allocators:
18100 case OMPC_affinity:
18102 case OMPC_ompx_dyn_cgroup_mem:
18104 llvm_unreachable(
"Clause is not allowed.");
18163 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
18249 if (!
hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
18251 StringRef
Expected =
"'init', 'use', 'destroy', or 'nowait'";
18252 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
18253 <<
Expected << getOpenMPDirectiveName(OMPD_interop, OMPVersion);
18266 bool HasInitClause =
false;
18267 bool IsTargetSync =
false;
18271 if (
const auto *InitClause = dyn_cast<OMPInitClause>(
C)) {
18272 HasInitClause =
true;
18273 if (InitClause->getIsTargetSync())
18274 IsTargetSync =
true;
18275 }
else if (
const auto *DC = dyn_cast<OMPDependClause>(
C)) {
18279 if (DependClause && HasInitClause && !IsTargetSync) {
18280 Diag(DependClause->
getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
18294 if (ClauseKind == OMPC_init) {
18297 }
else if (ClauseKind == OMPC_use) {
18300 }
else if (ClauseKind == OMPC_destroy) {
18306 if (!InteropVars.insert(
DeclResult.first).second) {
18307 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
18323 Expr *RefExpr = InteropVarExpr;
18338 bool HasError =
false;
18344 if (
const auto *TD = dyn_cast<TypeDecl>(ND)) {
18345 InteropType =
QualType(TD->getTypeForDecl(), 0);
18354 SemaRef.
Diag(VarLoc, diag::err_omp_implied_type_not_found)
18355 <<
"omp_interop_t";
18361 SemaRef.
Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
18367 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
18369 SemaRef.
Diag(VarLoc, diag::err_omp_interop_variable_expected)
18398 StartLoc, LParenLoc, VarLoc, EndLoc);
18411 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
18420 DSAStack->getCurrentDirective() == OMPD_depobj) {
18422 Diag(StartLoc, diag::err_omp_expected_clause_argument)
18424 << getOpenMPDirectiveName(OMPD_depobj, OMPVersion);
18440 Stmt *HelperValStmt =
nullptr;
18443 !
Condition->isInstantiationDependent() &&
18444 !
Condition->containsUnexpandedParameterPack()) {
18449 ValExpr =
SemaRef.MakeFullExpr(Val.
get()).get();
18454 if (CaptureRegion != OMPD_unknown &&
18455 !
SemaRef.CurContext->isDependentContext()) {
18456 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
18457 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18458 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
18464 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18472 Stmt *HelperValStmt =
nullptr;
18475 !
Condition->isInstantiationDependent() &&
18476 !
Condition->containsUnexpandedParameterPack()) {
18481 ValExpr =
SemaRef.MakeFullExpr(Val.
get()).get();
18486 if (CaptureRegion != OMPD_unknown &&
18487 !
SemaRef.CurContext->isDependentContext()) {
18488 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
18489 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18490 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
18496 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18503 Expr *ValExpr = ThreadID;
18504 Stmt *HelperValStmt =
nullptr;
18509 if (CaptureRegion != OMPD_unknown &&
18510 !
SemaRef.CurContext->isDependentContext()) {
18511 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
18512 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18513 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
18518 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18529 int ExtraModifier =
Data.ExtraModifier;
18530 int OriginalSharingModifier =
Data.OriginalSharingModifier;
18537 case OMPC_firstprivate:
18540 case OMPC_lastprivate:
18542 "Unexpected lastprivate modifier.");
18545 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
18550 case OMPC_reduction:
18552 "Unexpected lastprivate modifier.");
18556 ExtraModifier, OriginalSharingModifier),
18557 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
18558 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
18560 case OMPC_task_reduction:
18562 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18563 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
18565 case OMPC_in_reduction:
18567 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18568 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
18572 "Unexpected linear modifier.");
18574 VarList,
Data.DepModOrTailExpr, StartLoc, LParenLoc,
18576 ColonLoc,
Data.StepModifierLoc, EndLoc);
18580 LParenLoc, ColonLoc, EndLoc);
18585 case OMPC_copyprivate:
18593 "Unexpected depend modifier.");
18596 ColonLoc,
Data.OmpAllMemoryLoc},
18597 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
18601 "Unexpected map modifier.");
18603 Data.IteratorExpr,
Data.MapTypeModifiers,
Data.MapTypeModifiersLoc,
18604 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId,
18606 ExtraModifierLoc, ColonLoc, VarList, Locs);
18611 Data.ReductionOrMapperIdScopeSpec,
18612 Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
18616 Data.ReductionOrMapperIdScopeSpec,
18617 Data.ReductionOrMapperId, ColonLoc, VarList,
18620 case OMPC_use_device_ptr:
18623 case OMPC_use_device_addr:
18626 case OMPC_is_device_ptr:
18629 case OMPC_has_device_addr:
18632 case OMPC_allocate: {
18636 if (!
Data.AllocClauseModifiers.empty()) {
18637 assert(
Data.AllocClauseModifiers.size() <= 2 &&
18638 "More allocate modifiers than expected");
18639 Modifier1 =
Data.AllocClauseModifiers[0];
18640 Modifier1Loc =
Data.AllocClauseModifiersLoc[0];
18641 if (
Data.AllocClauseModifiers.size() == 2) {
18642 Modifier2 =
Data.AllocClauseModifiers[1];
18643 Modifier2Loc =
Data.AllocClauseModifiersLoc[1];
18647 Data.DepModOrTailExpr,
Data.AllocateAlignment, Modifier1, Modifier1Loc,
18648 Modifier2, Modifier2Loc, VarList, StartLoc, LParenLoc, ColonLoc,
18652 case OMPC_nontemporal:
18655 case OMPC_inclusive:
18658 case OMPC_exclusive:
18661 case OMPC_affinity:
18663 Data.DepModOrTailExpr, VarList);
18665 case OMPC_doacross:
18668 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
18670 case OMPC_num_teams:
18673 case OMPC_thread_limit:
18679 case OMPC_num_threads:
18683 case OMPC_allocator:
18684 case OMPC_collapse:
18686 case OMPC_proc_bind:
18687 case OMPC_schedule:
18691 case OMPC_mergeable:
18692 case OMPC_threadprivate:
18693 case OMPC_groupprivate:
18707 case OMPC_priority:
18708 case OMPC_grainsize:
18710 case OMPC_num_tasks:
18712 case OMPC_dist_schedule:
18713 case OMPC_defaultmap:
18716 case OMPC_unified_address:
18717 case OMPC_unified_shared_memory:
18718 case OMPC_reverse_offload:
18719 case OMPC_dynamic_allocators:
18720 case OMPC_atomic_default_mem_order:
18721 case OMPC_self_maps:
18722 case OMPC_device_type:
18726 case OMPC_severity:
18729 case OMPC_novariants:
18730 case OMPC_nocontext:
18732 case OMPC_uses_allocators:
18736 llvm_unreachable(
"Clause is not allowed.");
18749 Res =
SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.
get());
18754 Res =
SemaRef.DefaultLvalueConversion(Res.
get());
18768 bool IsImplicitClause =
18770 for (
Expr *RefExpr : VarList) {
18771 assert(RefExpr &&
"NULL expr in OpenMP private clause.");
18774 Expr *SimpleRefExpr = RefExpr;
18778 Vars.push_back(RefExpr);
18779 PrivateCopies.push_back(
nullptr);
18786 auto *VD = dyn_cast<VarDecl>(D);
18792 diag::err_omp_private_incomplete_type))
18794 Type =
Type.getNonReferenceType();
18814 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
18815 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
18816 Diag(ELoc, diag::err_omp_wrong_dsa)
18827 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18829 << getOpenMPDirectiveName(CurrDir, OMPVersion);
18830 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
18833 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18848 CurrDir == OMPD_target) {
18850 if (
DSAStack->checkMappableExprComponentListsForDecl(
18854 ConflictKind = WhereFoundClauseKind;
18857 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18860 << getOpenMPDirectiveName(CurrDir, OMPVersion);
18880 SemaRef.ActOnUninitializedDecl(VDPrivate);
18887 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
18888 auto *FD = dyn_cast<FieldDecl>(D);
18892 RefExpr->getExprLoc());
18896 if (!IsImplicitClause)
18897 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
18898 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
18899 ? RefExpr->IgnoreParens()
18901 PrivateCopies.push_back(VDPrivateRefExpr);
18908 Vars, PrivateCopies);
18919 bool IsImplicitClause =
18924 for (
Expr *RefExpr : VarList) {
18925 assert(RefExpr &&
"NULL expr in OpenMP firstprivate clause.");
18928 Expr *SimpleRefExpr = RefExpr;
18932 Vars.push_back(RefExpr);
18933 PrivateCopies.push_back(
nullptr);
18934 Inits.push_back(
nullptr);
18940 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
18942 auto *VD = dyn_cast<VarDecl>(D);
18948 diag::err_omp_firstprivate_incomplete_type))
18950 Type =
Type.getNonReferenceType();
18960 DSAStackTy::DSAVarData TopDVar;
18961 if (!IsImplicitClause) {
18962 DSAStackTy::DSAVarData DVar =
18974 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
18976 DVar.CKind != OMPC_lastprivate) &&
18978 Diag(ELoc, diag::err_omp_wrong_dsa)
18996 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
18997 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
18998 Diag(ELoc, diag::err_omp_wrong_dsa)
19024 DVar =
DSAStack->getImplicitDSA(D,
true);
19025 if (DVar.CKind != OMPC_shared &&
19028 DVar.DKind == OMPD_unknown)) {
19029 Diag(ELoc, diag::err_omp_required_access)
19051 return C == OMPC_reduction && !AppliedToPointee;
19059 if (DVar.CKind == OMPC_reduction &&
19063 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
19064 << getOpenMPDirectiveName(DVar.DKind, OMPVersion);
19080 CurrDir == OMPD_target) {
19082 if (
DSAStack->checkMappableExprComponentListsForDecl(
19087 ConflictKind = WhereFoundClauseKind;
19090 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
19093 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
19104 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19106 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
19108 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19111 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19126 Expr *VDInitRefExpr =
nullptr;
19136 ElemType,
".firstprivate.temp");
19151 ".firstprivate.temp");
19153 RefExpr->getExprLoc());
19154 SemaRef.AddInitializerToDecl(
19155 VDPrivate,
SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
19159 if (IsImplicitClause) {
19160 Diag(RefExpr->getExprLoc(),
19161 diag::note_omp_task_predetermined_firstprivate_here);
19165 SemaRef.CurContext->addDecl(VDPrivate);
19168 RefExpr->getExprLoc());
19170 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
19171 if (TopDVar.CKind == OMPC_lastprivate) {
19172 Ref = TopDVar.PrivateCopy;
19174 auto *FD = dyn_cast<FieldDecl>(D);
19179 RefExpr->getExprLoc());
19183 ExprCaptures.push_back(Ref->
getDecl());
19186 if (!IsImplicitClause)
19187 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
19188 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
19189 ? RefExpr->IgnoreParens()
19191 PrivateCopies.push_back(VDPrivateRefExpr);
19192 Inits.push_back(VDInitRefExpr);
19199 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
19208 assert(ColonLoc.
isValid() &&
"Colon location must be valid.");
19209 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
19222 for (
Expr *RefExpr : VarList) {
19223 assert(RefExpr &&
"NULL expr in OpenMP lastprivate clause.");
19226 Expr *SimpleRefExpr = RefExpr;
19230 Vars.push_back(RefExpr);
19231 SrcExprs.push_back(
nullptr);
19232 DstExprs.push_back(
nullptr);
19233 AssignmentOps.push_back(
nullptr);
19240 auto *VD = dyn_cast<VarDecl>(D);
19246 diag::err_omp_lastprivate_incomplete_type))
19248 Type =
Type.getNonReferenceType();
19265 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
19266 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19269 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19283 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
19284 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
19286 DVar.CKind != OMPC_firstprivate) &&
19287 (DVar.CKind != OMPC_private || DVar.RefExpr !=
nullptr)) {
19288 Diag(ELoc, diag::err_omp_wrong_dsa)
19301 DSAStackTy::DSAVarData TopDVar = DVar;
19305 DVar =
DSAStack->getImplicitDSA(D,
true);
19306 if (DVar.CKind != OMPC_shared) {
19307 Diag(ELoc, diag::err_omp_required_access)
19325 Type.getUnqualifiedType(),
".lastprivate.src",
19336 PseudoDstExpr, PseudoSrcExpr);
19339 AssignmentOp =
SemaRef.ActOnFinishFullExpr(AssignmentOp.
get(), ELoc,
19345 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
19346 if (TopDVar.CKind == OMPC_firstprivate) {
19347 Ref = TopDVar.PrivateCopy;
19351 ExprCaptures.push_back(Ref->
getDecl());
19353 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
19361 SimpleRefExpr, RefRes.
get());
19364 ExprPostUpdates.push_back(
19365 SemaRef.IgnoredValueConversions(PostUpdateRes.
get()).get());
19368 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
19369 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
19370 ? RefExpr->IgnoreParens()
19372 SrcExprs.push_back(PseudoSrcExpr);
19373 DstExprs.push_back(PseudoDstExpr);
19374 AssignmentOps.push_back(AssignmentOp.
get());
19381 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
19382 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
19392 for (
Expr *RefExpr : VarList) {
19393 assert(RefExpr &&
"NULL expr in OpenMP shared clause.");
19396 Expr *SimpleRefExpr = RefExpr;
19400 Vars.push_back(RefExpr);
19406 auto *VD = dyn_cast<VarDecl>(D);
19414 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
19415 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
19417 Diag(ELoc, diag::err_omp_wrong_dsa)
19426 !
SemaRef.CurContext->isDependentContext())
19428 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
19429 Vars.push_back((VD || !Ref ||
SemaRef.CurContext->isDependentContext())
19430 ? RefExpr->IgnoreParens()
19442class DSARefChecker :
public StmtVisitor<DSARefChecker, bool> {
19447 if (
auto *VD = dyn_cast<VarDecl>(E->
getDecl())) {
19448 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD,
false);
19449 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
19451 if (DVar.CKind != OMPC_unknown)
19453 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
19460 return DVarPrivate.CKind != OMPC_unknown;
19464 bool VisitStmt(Stmt *S) {
19465 for (Stmt *Child : S->
children()) {
19466 if (Child && Visit(Child))
19471 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
19478class TransformExprToCaptures :
public TreeTransform<TransformExprToCaptures> {
19479 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
19480 ValueDecl *
Field =
nullptr;
19481 DeclRefExpr *CapturedExpr =
nullptr;
19484 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
19485 : BaseTransform(SemaRef),
Field(FieldDecl), CapturedExpr(
nullptr) {}
19487 ExprResult TransformMemberExpr(MemberExpr *E) {
19490 CapturedExpr =
buildCapture(SemaRef, Field, E,
false);
19491 return CapturedExpr;
19493 return BaseTransform::TransformMemberExpr(E);
19495 DeclRefExpr *getCapturedExpr() {
return CapturedExpr; }
19499template <
typename T,
typename U>
19502 for (
U &
Set : Lookups) {
19503 for (
auto *D :
Set) {
19514 for (
auto *RD : D->
redecls()) {
19537 AssociatedClasses);
19550 for (
auto *NS : AssociatedNamespaces) {
19563 for (
auto *D : R) {
19564 auto *Underlying = D;
19565 if (
auto *USD = dyn_cast<UsingShadowDecl>(D))
19566 Underlying = USD->getTargetDecl();
19576 if (
auto *USD = dyn_cast<UsingShadowDecl>(D))
19577 Underlying = USD->getTargetDecl();
19579 Lookups.emplace_back();
19580 Lookups.back().addDecl(Underlying);
19604 Lookups.emplace_back();
19605 Lookups.back().append(Lookup.
begin(), Lookup.
end());
19608 }
else if (
auto *ULE =
19609 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
19611 Decl *PrevD =
nullptr;
19615 else if (
auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
19616 Lookups.back().addDecl(DRD);
19624 return !D->isInvalidDecl() &&
19625 (D->getType()->isDependentType() ||
19626 D->getType()->isInstantiationDependentType() ||
19627 D->getType()->containsUnexpandedParameterPack());
19640 true, ResSet.
begin(), ResSet.
end(),
false,
19663 if (IsComplete || RD->isBeingDefined()) {
19666 if (Lookup.
empty()) {
19667 Lookups.emplace_back();
19668 Lookups.back().append(Lookup.
begin(), Lookup.
end());
19710 if (ReductionIdScopeSpec.
isSet()) {
19711 SemaRef.
Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
19720struct ReductionData {
19722 SmallVector<Expr *, 8> Vars;
19724 SmallVector<Expr *, 8> Privates;
19726 SmallVector<Expr *, 8> LHSs;
19728 SmallVector<Expr *, 8> RHSs;
19730 SmallVector<Expr *, 8> ReductionOps;
19732 SmallVector<Expr *, 8> InscanCopyOps;
19734 SmallVector<Expr *, 8> InscanCopyArrayTemps;
19736 SmallVector<Expr *, 8> InscanCopyArrayElems;
19739 SmallVector<Expr *, 8> TaskgroupDescriptors;
19741 SmallVector<Decl *, 4> ExprCaptures;
19743 SmallVector<Expr *, 4> ExprPostUpdates;
19745 unsigned RedModifier = 0;
19747 unsigned OrigSharingModifier = 0;
19749 SmallVector<bool, 8> IsPrivateVarReduction;
19750 ReductionData() =
delete;
19752 ReductionData(
unsigned Size,
unsigned Modifier = 0,
unsigned OrgModifier = 0)
19753 : RedModifier(Modifier), OrigSharingModifier(OrgModifier) {
19754 Vars.reserve(Size);
19755 Privates.reserve(Size);
19756 LHSs.reserve(Size);
19757 RHSs.reserve(Size);
19758 ReductionOps.reserve(Size);
19759 IsPrivateVarReduction.reserve(Size);
19760 if (RedModifier == OMPC_REDUCTION_inscan) {
19761 InscanCopyOps.reserve(Size);
19762 InscanCopyArrayTemps.reserve(Size);
19763 InscanCopyArrayElems.reserve(Size);
19765 TaskgroupDescriptors.reserve(Size);
19766 ExprCaptures.reserve(Size);
19767 ExprPostUpdates.reserve(Size);
19771 void push(Expr *Item, Expr *ReductionOp) {
19772 Vars.emplace_back(Item);
19773 Privates.emplace_back(
nullptr);
19774 LHSs.emplace_back(
nullptr);
19775 RHSs.emplace_back(
nullptr);
19776 ReductionOps.emplace_back(ReductionOp);
19777 IsPrivateVarReduction.emplace_back(
false);
19778 TaskgroupDescriptors.emplace_back(
nullptr);
19779 if (RedModifier == OMPC_REDUCTION_inscan) {
19780 InscanCopyOps.push_back(
nullptr);
19781 InscanCopyArrayTemps.push_back(
nullptr);
19782 InscanCopyArrayElems.push_back(
nullptr);
19786 void push(Expr *Item, Expr *
Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
19787 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
19788 Expr *CopyArrayElem,
bool IsPrivate) {
19789 Vars.emplace_back(Item);
19790 Privates.emplace_back(
Private);
19791 LHSs.emplace_back(LHS);
19792 RHSs.emplace_back(RHS);
19793 ReductionOps.emplace_back(ReductionOp);
19794 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
19795 if (RedModifier == OMPC_REDUCTION_inscan) {
19796 InscanCopyOps.push_back(CopyOp);
19797 InscanCopyArrayTemps.push_back(CopyArrayTemp);
19798 InscanCopyArrayElems.push_back(CopyArrayElem);
19800 assert(CopyOp ==
nullptr && CopyArrayTemp ==
nullptr &&
19801 CopyArrayElem ==
nullptr &&
19802 "Copy operation must be used for inscan reductions only.");
19804 IsPrivateVarReduction.emplace_back(IsPrivate);
19813 if (Length ==
nullptr) {
19820 SingleElement =
true;
19821 ArraySizes.push_back(llvm::APSInt::get(1));
19824 if (!Length->EvaluateAsInt(Result, Context))
19827 llvm::APSInt ConstantLengthValue = Result.
Val.
getInt();
19828 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
19829 ArraySizes.push_back(ConstantLengthValue);
19837 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base)) {
19838 Length = TempOASE->getLength();
19839 if (Length ==
nullptr) {
19846 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
19847 ArraySizes.push_back(ConstantOne);
19850 if (!Length->EvaluateAsInt(Result, Context))
19853 llvm::APSInt ConstantLengthValue = Result.
Val.
getInt();
19854 if (ConstantLengthValue.getSExtValue() != 1)
19857 ArraySizes.push_back(ConstantLengthValue);
19859 Base = TempOASE->getBase()->IgnoreParenImpCasts();
19863 if (!SingleElement) {
19864 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base)) {
19866 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
19867 ArraySizes.push_back(ConstantOne);
19868 Base = TempASE->getBase()->IgnoreParenImpCasts();
19880 return BO_AddAssign;
19882 return BO_MulAssign;
19884 return BO_AndAssign;
19886 return BO_OrAssign;
19888 return BO_XorAssign;
19944 case OO_Array_Delete:
19953 case OO_GreaterEqual:
19955 case OO_MinusEqual:
19957 case OO_SlashEqual:
19958 case OO_PercentEqual:
19959 case OO_CaretEqual:
19963 case OO_GreaterGreater:
19964 case OO_LessLessEqual:
19965 case OO_GreaterGreaterEqual:
19966 case OO_EqualEqual:
19967 case OO_ExclaimEqual:
19970 case OO_MinusMinus:
19976 case OO_Conditional:
19979 llvm_unreachable(
"Unexpected reduction identifier");
19982 if (II->isStr(
"max"))
19984 else if (II->isStr(
"min"))
19992 if (OOK == OO_Minus && S.
LangOpts.OpenMP == 52)
19993 S.
Diag(ReductionId.
getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
19996 if (ReductionIdScopeSpec.
isValid())
20002 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
20003 bool FirstIter =
true;
20004 for (
Expr *RefExpr : VarList) {
20005 assert(RefExpr &&
"nullptr expr in OpenMP reduction clause.");
20013 if (!FirstIter && IR != ER)
20018 bool IsPrivate =
false;
20019 Expr *SimpleRefExpr = RefExpr;
20028 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
20029 ReductionId,
Type, BasePath, IR == ER ?
nullptr : *IR);
20030 Expr *ReductionOp =
nullptr;
20032 (DeclareReductionRef.
isUnset() ||
20034 ReductionOp = DeclareReductionRef.
get();
20036 RD.push(RefExpr, ReductionOp);
20042 Expr *TaskgroupDescriptor =
nullptr;
20044 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
20045 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
20047 Type = ASE->getType().getNonReferenceType();
20051 if (
const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20052 Type = ATy->getElementType();
20055 Type =
Type.getNonReferenceType();
20059 auto *VD = dyn_cast<VarDecl>(D);
20065 diag::err_omp_reduction_incomplete_type))
20071 false, ASE || OASE))
20078 if (!ASE && !OASE) {
20080 VarDecl *VDDef = VD->getDefinition();
20082 DSARefChecker Check(Stack);
20083 if (Check.Visit(VDDef->
getInit())) {
20084 S.
Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
20103 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D,
false);
20104 if (DVar.CKind == OMPC_reduction) {
20105 S.
Diag(ELoc, diag::err_omp_once_referenced)
20111 if (DVar.CKind != OMPC_unknown) {
20112 S.
Diag(ELoc, diag::err_omp_wrong_dsa)
20128 DVar = Stack->getImplicitDSA(D,
true);
20129 if (DVar.CKind != OMPC_shared) {
20130 S.
Diag(ELoc, diag::err_omp_required_access)
20144 DVar = Stack->getImplicitDSA(D,
true);
20146 IsPrivate = DVar.CKind != OMPC_shared;
20147 bool IsOrphaned =
false;
20149 IsOrphaned = ParentDir == OMPD_unknown;
20151 RD.OrigSharingModifier == OMPC_ORIGINAL_SHARING_private))
20157 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D,
false);
20158 if (DVar.CKind == OMPC_threadprivate) {
20159 S.
Diag(ELoc, diag::err_omp_wrong_dsa)
20171 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
20172 ReductionId,
Type, BasePath, IR == ER ?
nullptr : *IR);
20176 (DeclareReductionRef.
isUnset() ||
20178 RD.push(RefExpr, DeclareReductionRef.
get());
20181 if (BOK == BO_Comma && DeclareReductionRef.
isUnset()) {
20185 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
20186 <<
Type << ReductionIdRange;
20189 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
20190 <<
Type << ReductionIdRange;
20202 if (DeclareReductionRef.
isUnset()) {
20203 if ((BOK == BO_GT || BOK == BO_LT) &&
20206 S.
Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
20209 if (!ASE && !OASE) {
20210 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20213 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20218 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
20220 S.
Diag(ELoc, diag::err_omp_clause_floating_type_arg)
20222 if (!ASE && !OASE) {
20223 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20226 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20233 Type =
Type.getNonLValueExprType(Context).getUnqualifiedType();
20242 bool ConstantLengthOASE =
false;
20244 bool SingleElement;
20247 Context, OASE, SingleElement, ArraySizes);
20250 if (ConstantLengthOASE && !SingleElement) {
20251 for (llvm::APSInt &Size : ArraySizes)
20252 PrivateTy = Context.getConstantArrayType(PrivateTy, Size,
nullptr,
20258 if ((OASE && !ConstantLengthOASE) ||
20261 if (!Context.getTargetInfo().isVLASupported()) {
20263 S.
Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
20264 S.
Diag(ELoc, diag::note_vla_unsupported);
20267 S.
targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
20268 S.
targetDiag(ELoc, diag::note_vla_unsupported);
20276 PrivateTy = Context.getVariableArrayType(
20281 }
else if (!ASE && !OASE &&
20294 if (DeclareReductionRef.
isUsable()) {
20297 if (DRD->getInitializer()) {
20323 Type = ComplexTy->getElementType();
20325 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
20326 Context.getFloatTypeSemantics(
Type));
20330 uint64_t Size = Context.getTypeSize(
Type);
20331 QualType IntTy = Context.getIntTypeForBitwidth(Size, 0);
20332 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
20351 uint64_t Size = Context.getTypeSize(
Type);
20353 Context.getIntTypeForBitwidth(Size, IsSigned);
20354 llvm::APInt InitValue =
20355 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
20356 : llvm::APInt::getMinValue(Size)
20357 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
20358 : llvm::APInt::getMaxValue(Size);
20363 ELoc, Context.getTrivialTypeSourceInfo(
Type, ELoc), ELoc,
Init);
20369 llvm::APFloat InitValue = llvm::APFloat::getLargest(
20370 Context.getFloatTypeSemantics(
Type), BOK != BO_LT);
20400 llvm_unreachable(
"Unexpected reduction operation");
20409 }
else if (!
Init) {
20419 S.
Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
20420 <<
Type << ReductionIdRange;
20421 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20424 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20430 if (DeclareReductionRef.
isUsable()) {
20432 QualType PtrRedTy = Context.getPointerType(RedTy);
20435 if (!BasePath.empty()) {
20439 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.
get(), &BasePath,
20442 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.
get(), &BasePath,
20446 QualType Params[] = {PtrRedTy, PtrRedTy};
20447 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
20461 CombBOK, LHSDRE, RHSDRE);
20468 if (BOK != BO_LT && BOK != BO_GT) {
20471 BO_Assign, LHSDRE, ReductionOp.
get());
20473 auto *ConditionalOp =
new (Context)
20478 BO_Assign, LHSDRE, ConditionalOp);
20491 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
20492 if (ClauseKind == OMPC_reduction &&
20493 RD.RedModifier == OMPC_REDUCTION_inscan) {
20495 CopyOpRes = S.
BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
20505 if (Stack->getCurrentDirective() == OMPD_simd ||
20543 if (ClauseKind == OMPC_in_reduction) {
20546 const Expr *ParentReductionOp =
nullptr;
20547 Expr *ParentBOKTD =
nullptr, *ParentReductionOpTD =
nullptr;
20548 DSAStackTy::DSAVarData ParentBOKDSA =
20549 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
20551 DSAStackTy::DSAVarData ParentReductionOpDSA =
20552 Stack->getTopMostTaskgroupReductionData(
20553 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
20554 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
20555 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
20556 if ((DeclareReductionRef.
isUnset() && IsParentReductionOp) ||
20557 (DeclareReductionRef.
isUsable() && IsParentBOK) ||
20558 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
20559 bool EmitError =
true;
20560 if (IsParentReductionOp && DeclareReductionRef.
isUsable()) {
20561 llvm::FoldingSetNodeID RedId, ParentRedId;
20562 ParentReductionOp->
Profile(ParentRedId, Context,
true);
20563 DeclareReductionRef.
get()->
Profile(RedId, Context,
20565 EmitError = RedId != ParentRedId;
20569 diag::err_omp_reduction_identifier_mismatch)
20570 << ReductionIdRange << RefExpr->getSourceRange();
20572 diag::note_omp_previous_reduction_identifier)
20574 << (IsParentBOK ? ParentBOKDSA.RefExpr
20575 : ParentReductionOpDSA.RefExpr)
20576 ->getSourceRange();
20580 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
20587 TransformExprToCaptures RebuildToCapture(S, D);
20589 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
20590 Ref = RebuildToCapture.getCapturedExpr();
20592 VarsExpr = Ref =
buildCapture(S, D, SimpleRefExpr,
false);
20595 RD.ExprCaptures.emplace_back(Ref->
getDecl());
20601 S.
BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
20606 Stack->getCurrentDirective() == OMPD_taskgroup) {
20607 S.
Diag(RefExpr->getExprLoc(),
20608 diag::err_omp_reduction_non_addressable_expression)
20609 << RefExpr->getSourceRange();
20612 RD.ExprPostUpdates.emplace_back(
20619 unsigned Modifier = RD.RedModifier;
20622 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
20623 Modifier = OMPC_REDUCTION_task;
20624 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
20626 if (Modifier == OMPC_REDUCTION_task &&
20627 (CurrDir == OMPD_taskgroup ||
20631 if (DeclareReductionRef.
isUsable())
20632 Stack->addTaskgroupReductionData(D, ReductionIdRange,
20633 DeclareReductionRef.
get());
20635 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
20637 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.
get(),
20638 TaskgroupDescriptor, CopyOpRes.
get(), TempArrayRes.
get(),
20639 TempArrayElem.
get(), IsPrivate);
20641 return RD.Vars.empty();
20657 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
20668 if (Modifier == OMPC_REDUCTION_inscan &&
20669 (
DSAStack->getCurrentDirective() != OMPD_for &&
20670 DSAStack->getCurrentDirective() != OMPD_for_simd &&
20671 DSAStack->getCurrentDirective() != OMPD_simd &&
20672 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
20673 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
20674 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
20677 ReductionData RD(VarList.size(), Modifier, OriginalSharingModifier);
20679 StartLoc, LParenLoc, ColonLoc, EndLoc,
20680 ReductionIdScopeSpec, ReductionId,
20681 UnresolvedReductions, RD))
20685 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
20688 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
20689 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
20692 OriginalSharingModifier);
20700 ReductionData RD(VarList.size());
20702 VarList, StartLoc, LParenLoc, ColonLoc,
20703 EndLoc, ReductionIdScopeSpec, ReductionId,
20704 UnresolvedReductions, RD))
20708 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20710 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
20720 ReductionData RD(VarList.size());
20722 StartLoc, LParenLoc, ColonLoc, EndLoc,
20723 ReductionIdScopeSpec, ReductionId,
20724 UnresolvedReductions, RD))
20728 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20730 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
20739 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
20749 const auto *VD = dyn_cast_or_null<VarDecl>(D);
20752 diag::err_omp_linear_incomplete_type))
20754 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
20756 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
20760 Type =
Type.getNonReferenceType();
20767 if (!IsDeclareSimd &&
20772 Type =
Type.getUnqualifiedType().getCanonicalType();
20773 const auto *Ty =
Type.getTypePtrOrNull();
20774 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
20775 !Ty->isIntegralType(
getASTContext()) && !Ty->isPointerType())) {
20776 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) <<
Type;
20778 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
20781 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20804 Diag(Step->
getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
20806 LinKind = OMPC_LINEAR_val;
20807 for (
Expr *RefExpr : VarList) {
20808 assert(RefExpr &&
"NULL expr in OpenMP linear clause.");
20811 Expr *SimpleRefExpr = RefExpr;
20815 Vars.push_back(RefExpr);
20816 Privates.push_back(
nullptr);
20817 Inits.push_back(
nullptr);
20824 auto *VD = dyn_cast<VarDecl>(D);
20830 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
20831 if (DVar.RefExpr) {
20832 Diag(ELoc, diag::err_omp_wrong_dsa)
20841 Type =
Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20853 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
20856 ExprCaptures.push_back(Ref->
getDecl());
20863 SimpleRefExpr, RefRes.
get());
20866 ExprPostUpdates.push_back(
20867 SemaRef.IgnoredValueConversions(PostUpdateRes.
get()).get());
20871 if (LinKind == OMPC_LINEAR_uval)
20872 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
20874 InitExpr = VD ? SimpleRefExpr : Ref;
20875 SemaRef.AddInitializerToDecl(
20876 Init,
SemaRef.DefaultLvalueConversion(InitExpr).get(),
20880 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
20881 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
20882 ? RefExpr->IgnoreParens()
20884 Privates.push_back(PrivateRef);
20885 Inits.push_back(InitRef);
20891 Expr *StepExpr = Step;
20892 Expr *CalcStepExpr =
nullptr;
20900 StepExpr = Val.
get();
20908 SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.
get(), StepExpr);
20910 SemaRef.ActOnFinishFullExpr(CalcStep.
get(),
false);
20914 if (std::optional<llvm::APSInt>
Result =
20916 if (!
Result->isNegative() && !
Result->isStrictlyPositive())
20917 Diag(StepLoc, diag::warn_omp_linear_step_zero)
20918 << Vars[0] << (Vars.size() > 1);
20922 CalcStepExpr = CalcStep.
get();
20927 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
20928 Vars, Privates, Inits, StepExpr, CalcStepExpr,
20934 Expr *NumIterations,
Sema &SemaRef,
20935 Scope *S, DSAStackTy *Stack) {
20940 Expr *Step = Clause.getStep();
20941 Expr *CalcStep = Clause.getCalcStep();
20948 bool HasErrors =
false;
20949 auto CurInit = Clause.inits().begin();
20950 auto CurPrivate = Clause.privates().begin();
20952 for (
Expr *RefExpr : Clause.varlist()) {
20955 Expr *SimpleRefExpr = RefExpr;
20956 auto Res =
getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20958 if (Res.second || !D) {
20959 Updates.push_back(
nullptr);
20960 Finals.push_back(
nullptr);
20964 auto &&Info = Stack->isLoopControlVariable(D);
20971 diag::err_omp_linear_distribute_var_non_loop_iteration);
20972 Updates.push_back(
nullptr);
20973 Finals.push_back(
nullptr);
20977 Expr *InitExpr = *CurInit;
20982 if (LinKind == OMPC_LINEAR_uval)
20987 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
20994 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
21005 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
21008 Final = *CurPrivate;
21012 if (!
Update.isUsable() || !Final.isUsable()) {
21013 Updates.push_back(
nullptr);
21014 Finals.push_back(
nullptr);
21015 UsedExprs.push_back(
nullptr);
21018 Updates.push_back(
Update.get());
21019 Finals.push_back(Final.get());
21021 UsedExprs.push_back(SimpleRefExpr);
21026 if (
Expr *S = Clause.getStep())
21027 UsedExprs.push_back(S);
21029 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(),
nullptr);
21030 Clause.setUpdates(Updates);
21031 Clause.setFinals(Finals);
21032 Clause.setUsedExprs(UsedExprs);
21040 for (
Expr *RefExpr : VarList) {
21041 assert(RefExpr &&
"NULL expr in OpenMP aligned clause.");
21044 Expr *SimpleRefExpr = RefExpr;
21048 Vars.push_back(RefExpr);
21055 auto *VD = dyn_cast<VarDecl>(D);
21063 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
21065 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
21068 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21075 if (
const Expr *PrevRef =
DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
21076 Diag(ELoc, diag::err_omp_used_in_clause_twice)
21078 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
21087 .DefaultFunctionArrayConversion(
21088 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
21097 if (Alignment !=
nullptr) {
21102 Alignment = AlignResult.
get();
21108 ColonLoc, EndLoc, Vars, Alignment);
21119 for (
Expr *RefExpr : VarList) {
21120 assert(RefExpr &&
"NULL expr in OpenMP copyin clause.");
21123 Vars.push_back(RefExpr);
21124 SrcExprs.push_back(
nullptr);
21125 DstExprs.push_back(
nullptr);
21126 AssignmentOps.push_back(
nullptr);
21135 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
21137 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
21138 << 0 << RefExpr->getSourceRange();
21142 Decl *D = DE->getDecl();
21148 Vars.push_back(DE);
21149 SrcExprs.push_back(
nullptr);
21150 DstExprs.push_back(
nullptr);
21151 AssignmentOps.push_back(
nullptr);
21157 if (!
DSAStack->isThreadPrivate(VD)) {
21159 Diag(ELoc, diag::err_omp_required_access)
21161 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion);
21184 SemaRef.BuildBinOp(
nullptr, DE->getExprLoc(), BO_Assign,
21185 PseudoDstExpr, PseudoSrcExpr);
21194 DSAStack->addDSA(VD, DE, OMPC_copyin);
21195 Vars.push_back(DE);
21196 SrcExprs.push_back(PseudoSrcExpr);
21197 DstExprs.push_back(PseudoDstExpr);
21198 AssignmentOps.push_back(AssignmentOp.
get());
21205 Vars, SrcExprs, DstExprs, AssignmentOps);
21216 for (
Expr *RefExpr : VarList) {
21217 assert(RefExpr &&
"NULL expr in OpenMP copyprivate clause.");
21220 Expr *SimpleRefExpr = RefExpr;
21224 Vars.push_back(RefExpr);
21225 SrcExprs.push_back(
nullptr);
21226 DstExprs.push_back(
nullptr);
21227 AssignmentOps.push_back(
nullptr);
21234 auto *VD = dyn_cast<VarDecl>(D);
21239 if (!VD || !
DSAStack->isThreadPrivate(VD)) {
21240 DSAStackTy::DSAVarData DVar =
21242 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
21244 Diag(ELoc, diag::err_omp_wrong_dsa)
21254 if (DVar.CKind == OMPC_unknown) {
21255 DVar =
DSAStack->getImplicitDSA(D,
false);
21256 if (DVar.CKind == OMPC_shared) {
21257 Diag(ELoc, diag::err_omp_required_access)
21259 <<
"threadprivate or private in the enclosing context";
21269 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
21271 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
21273 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
21276 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21297 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
21300 AssignmentOp =
SemaRef.ActOnFinishFullExpr(AssignmentOp.
get(), ELoc,
21309 VD ? RefExpr->IgnoreParens()
21311 SrcExprs.push_back(PseudoSrcExpr);
21312 DstExprs.push_back(PseudoDstExpr);
21313 AssignmentOps.push_back(AssignmentOp.
get());
21320 EndLoc, Vars, SrcExprs, DstExprs,
21328 if (VarList.empty())
21337 bool Diagnose =
true) {
21338 QualType OMPDependT = Stack->getOMPDependT();
21339 if (!OMPDependT.
isNull())
21345 S.
Diag(Loc, diag::err_omp_implied_type_not_found) <<
"omp_depend_t";
21348 Stack->setOMPDependT(PT.
get());
21369 Diag(Depobj->
getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
21374 Diag(Depobj->
getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
21384struct DoacrossDataInfoTy {
21388 DSAStackTy::OperatorOffsetTy OpsOffs;
21390 llvm::APSInt TotalDepCount;
21393static DoacrossDataInfoTy
21399 DSAStackTy::OperatorOffsetTy OpsOffs;
21400 llvm::APSInt DepCounter(32);
21401 llvm::APSInt TotalDepCount(32);
21403 if (
const Expr *OrderedCountExpr =
21404 Stack->getParentOrderedRegionParam().first) {
21405 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.
Context);
21406 TotalDepCount.setIsUnsigned(
true);
21409 for (
Expr *RefExpr : VarList) {
21410 assert(RefExpr &&
"NULL expr in OpenMP doacross clause.");
21413 Vars.push_back(RefExpr);
21420 if (Stack->getParentOrderedRegionParam().first &&
21421 DepCounter >= TotalDepCount) {
21422 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
21436 Vars.push_back(RefExpr);
21443 Expr *RHS =
nullptr;
21444 if (
auto *BO = dyn_cast<BinaryOperator>(
SimpleExpr)) {
21446 OOLoc = BO->getOperatorLoc();
21449 }
else if (
auto *OCE = dyn_cast<CXXOperatorCallExpr>(
SimpleExpr)) {
21450 OOK = OCE->getOperator();
21451 OOLoc = OCE->getOperatorLoc();
21454 }
else if (
auto *MCE = dyn_cast<CXXMemberCallExpr>(
SimpleExpr)) {
21455 OOK = MCE->getMethodDecl()
21458 .getCXXOverloadedOperator();
21459 OOLoc = MCE->getCallee()->getExprLoc();
21468 Vars.push_back(RefExpr);
21474 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK !=
OO_None)) {
21475 SemaRef.
Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
21481 RHS, OMPC_depend,
false);
21486 Stack->getParentOrderedRegionParam().first &&
21487 DepCounter != Stack->isParentLoopControlVariable(D).first) {
21489 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
21491 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
21494 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
21498 OpsOffs.emplace_back(RHS, OOK);
21500 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21503 TotalDepCount > VarList.size() &&
21504 Stack->getParentOrderedRegionParam().first &&
21505 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
21506 SemaRef.
Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
21507 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
21509 return {Vars, OpsOffs, TotalDepCount};
21518 if (
DSAStack->getCurrentDirective() == OMPD_ordered &&
21519 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
21520 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21524 if (
DSAStack->getCurrentDirective() == OMPD_taskwait &&
21525 DepKind == OMPC_DEPEND_mutexinoutset) {
21526 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
21529 if ((
DSAStack->getCurrentDirective() != OMPD_ordered ||
21530 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21532 DepKind == OMPC_DEPEND_sink ||
21534 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21535 DepKind == OMPC_DEPEND_depobj))) {
21537 OMPC_DEPEND_outallmemory,
21538 OMPC_DEPEND_inoutallmemory};
21540 DSAStack->getCurrentDirective() == OMPD_depobj)
21541 Except.push_back(OMPC_DEPEND_depobj);
21543 Except.push_back(OMPC_DEPEND_inoutset);
21545 ?
"depend modifier(iterator) or "
21547 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21555 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
21557 diag::err_omp_depend_sink_source_with_modifier);
21562 Diag(DepModifier->
getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
21565 DSAStackTy::OperatorOffsetTy OpsOffs;
21566 llvm::APSInt TotalDepCount(32);
21568 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
21571 Vars = VarOffset.Vars;
21572 OpsOffs = VarOffset.OpsOffs;
21573 TotalDepCount = VarOffset.TotalDepCount;
21575 for (
Expr *RefExpr : VarList) {
21576 assert(RefExpr &&
"NULL expr in OpenMP depend clause.");
21579 Vars.push_back(RefExpr);
21585 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
21586 bool OMPDependTFound =
getLangOpts().OpenMP >= 50;
21587 if (OMPDependTFound)
21589 DepKind == OMPC_DEPEND_depobj);
21590 if (DepKind == OMPC_DEPEND_depobj) {
21594 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21595 !RefExpr->isInstantiationDependent() &&
21596 !RefExpr->containsUnexpandedParameterPack() &&
21597 (OMPDependTFound &&
21599 DSAStack->getOMPDependT(), RefExpr->getType()))) {
21600 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21601 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
21604 if (!RefExpr->isLValue()) {
21605 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21606 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
21613 QualType ExprTy = RefExpr->getType().getNonReferenceType();
21614 const auto *OASE = dyn_cast<ArraySectionExpr>(
SimpleExpr);
21618 if (BaseType.isNull())
21620 if (
const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21621 ExprTy = ATy->getElementType();
21624 if (BaseType.isNull() || ExprTy.
isNull())
21627 const Expr *Length = OASE->getLength();
21629 if (Length && !Length->isValueDependent() &&
21631 Result.Val.getInt().isZero()) {
21633 diag::err_omp_depend_zero_length_array_section_not_allowed)
21643 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21644 !RefExpr->isInstantiationDependent() &&
21645 !RefExpr->containsUnexpandedParameterPack() &&
21646 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
21647 (OMPDependTFound &&
DSAStack->getOMPDependT().getTypePtr() ==
21649 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21652 << RefExpr->getSourceRange();
21656 auto *ASE = dyn_cast<ArraySubscriptExpr>(
SimpleExpr);
21657 if (ASE && !ASE->getBase()->isTypeDependent() &&
21660 .getNonReferenceType()
21661 ->isPointerType() &&
21662 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
21663 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21666 << RefExpr->getSourceRange();
21673 Res =
SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
21674 RefExpr->IgnoreParenImpCasts());
21678 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21681 << RefExpr->getSourceRange();
21686 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21690 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
21691 DepKind != OMPC_DEPEND_outallmemory &&
21692 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
21697 {DepKind, DepLoc,
Data.ColonLoc,
Data.OmpAllMemoryLoc}, DepModifier, Vars,
21698 TotalDepCount.getZExtValue());
21699 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
21700 DSAStack->isParentOrderedRegion())
21701 DSAStack->addDoacrossDependClause(
C, OpsOffs);
21710 "Unexpected device modifier in OpenMP < 50.");
21712 bool ErrorFound =
false;
21714 std::string Values =
21716 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
21722 Stmt *HelperValStmt =
nullptr;
21735 if (Modifier == OMPC_DEVICE_ancestor) {
21739 diag::err_omp_device_ancestor_without_requires_reverse_offload);
21747 if (CaptureRegion != OMPD_unknown &&
21748 !
SemaRef.CurContext->isDependentContext()) {
21749 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
21750 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21751 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
21756 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
21757 LParenLoc, ModifierLoc, EndLoc);
21762 bool FullCheck =
true) {
21767 SemaRef.
Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
21777 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
21783 (OASE && OASE->getColonLocFirst().isInvalid())) {
21784 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
21785 return ATy->getSExtSize() != 1;
21790 assert(OASE &&
"Expecting array section if not an array subscript.");
21791 const Expr *LowerBound = OASE->getLowerBound();
21792 const Expr *Length = OASE->getLength();
21801 llvm::APSInt ConstLowerBound = Result.
Val.
getInt();
21802 if (ConstLowerBound.getSExtValue())
21817 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr());
21822 if (!Length->EvaluateAsInt(Result, SemaRef.
getASTContext()))
21825 llvm::APSInt ConstLength = Result.
Val.
getInt();
21826 return CATy->getSExtSize() != ConstLength.getSExtValue();
21835 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
21840 (OASE && OASE->getColonLocFirst().isInvalid()))
21843 assert(OASE &&
"Expecting array section if not an array subscript.");
21844 const Expr *Length = OASE->getLength();
21850 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
21851 return ATy->getSExtSize() != 1;
21858 if (!Length->EvaluateAsInt(Result, SemaRef.
getASTContext()))
21861 llvm::APSInt ConstLength = Result.
Val.
getInt();
21862 return ConstLength.getSExtValue() != 1;
21901class MapBaseChecker final :
public StmtVisitor<MapBaseChecker, bool> {
21906 bool IsNonContiguous =
false;
21907 bool NoDiagnose =
false;
21908 const Expr *RelevantExpr =
nullptr;
21909 bool AllowUnitySizeArraySection =
true;
21910 bool AllowWholeSizeArraySection =
true;
21911 bool AllowAnotherPtr =
true;
21912 SourceLocation ELoc;
21913 SourceRange ERange;
21915 void emitErrorMsg() {
21917 if (SemaRef.getLangOpts().OpenMP < 50) {
21919 diag::err_omp_expected_named_var_member_or_array_expression)
21922 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21928 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
21933 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
21934 RelevantExpr = DRE;
21936 Components.emplace_back(DRE, DRE->
getDecl(), IsNonContiguous);
21940 bool VisitMemberExpr(MemberExpr *ME) {
21945 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
21954 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
21970 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
21990 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
21994 return RelevantExpr || Visit(E);
22004 AllowUnitySizeArraySection =
false;
22005 AllowWholeSizeArraySection =
false;
22008 Components.emplace_back(ME, FD, IsNonContiguous);
22009 return RelevantExpr || Visit(E);
22012 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
22017 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
22021 return RelevantExpr || Visit(E);
22028 AllowWholeSizeArraySection =
false;
22031 Expr::EvalResult
Result;
22034 !
Result.Val.getInt().isZero()) {
22036 diag::err_omp_invalid_map_this_expr);
22038 diag::note_omp_invalid_subscript_on_this_ptr_map);
22040 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22045 Components.emplace_back(AE,
nullptr, IsNonContiguous);
22047 return RelevantExpr || Visit(E);
22050 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
22053 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
22054 "Array sections cannot be implicitly mapped.");
22068 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
22078 if (AllowWholeSizeArraySection) {
22085 if (NotWhole || IsPointer)
22086 AllowWholeSizeArraySection =
false;
22087 }
else if (DKind == OMPD_target_update &&
22088 SemaRef.getLangOpts().OpenMP >= 50) {
22089 if (IsPointer && !AllowAnotherPtr)
22090 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
22093 IsNonContiguous =
true;
22094 }
else if (AllowUnitySizeArraySection && NotUnity) {
22100 diag::err_array_section_does_not_specify_contiguous_storage)
22106 AllowAnotherPtr =
false;
22108 if (
const auto *TE = dyn_cast<CXXThisExpr>(E)) {
22109 Expr::EvalResult ResultR;
22110 Expr::EvalResult ResultL;
22115 diag::err_omp_invalid_map_this_expr);
22117 diag::note_omp_invalid_length_on_this_ptr_mapping);
22121 SemaRef.getASTContext()) &&
22124 diag::err_omp_invalid_map_this_expr);
22126 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
22128 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22133 Components.emplace_back(OASE,
nullptr,
false);
22134 return RelevantExpr || Visit(E);
22136 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
22140 Components.emplace_back(E,
nullptr, IsNonContiguous);
22142 return Visit(
Base->IgnoreParenImpCasts());
22145 bool VisitUnaryOperator(UnaryOperator *UO) {
22146 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->
isLValue() ||
22151 if (!RelevantExpr) {
22153 Components.emplace_back(UO,
nullptr,
false);
22157 bool VisitBinaryOperator(BinaryOperator *BO) {
22169 Components.emplace_back(BO,
nullptr,
false);
22172 "Either LHS or RHS have base decl inside");
22174 return RelevantExpr || Visit(LE);
22175 return RelevantExpr || Visit(RE);
22177 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
22178 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22179 RelevantExpr = CTE;
22180 Components.emplace_back(CTE,
nullptr, IsNonContiguous);
22183 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
22184 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22185 Components.emplace_back(COCE,
nullptr, IsNonContiguous);
22188 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
22194 return Visit(Source);
22196 bool VisitStmt(Stmt *) {
22200 const Expr *getFoundBase()
const {
return RelevantExpr; }
22201 explicit MapBaseChecker(
22204 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
22205 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
22206 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
22220 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
22224 if (SemaRef.
getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
22225 (CKind == OMPC_to || CKind == OMPC_from)) {
22226 auto CI = CurComponents.rbegin();
22227 auto CE = CurComponents.rend();
22228 for (; CI != CE; ++CI) {
22230 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
22235 SemaRef.
Diag(ELoc, diag::err_array_section_does_not_specify_length)
22239 return Checker.getFoundBase();
22248 bool CurrentRegionOnly,
22259 assert(!CurComponents.empty() &&
"Map clause expression with no components!");
22260 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
22261 "Map clause expression with unexpected base!");
22264 bool IsEnclosedByDataEnvironmentExpr =
false;
22265 const Expr *EnclosingExpr =
nullptr;
22267 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
22268 VD, CurrentRegionOnly,
22269 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
22270 ERange, CKind, &EnclosingExpr,
22274 if (CKind == Kind && SemaRef.
LangOpts.OpenMP >= 50)
22276 assert(!StackComponents.empty() &&
22277 "Map clause expression with no components!");
22278 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
22279 "Map clause expression with unexpected base!");
22283 const Expr *RE = StackComponents.front().getAssociatedExpression();
22289 auto CI = CurComponents.rbegin();
22290 auto CE = CurComponents.rend();
22291 auto SI = StackComponents.rbegin();
22292 auto SE = StackComponents.rend();
22293 for (; CI != CE && SI != SE; ++CI, ++SI) {
22298 if (CurrentRegionOnly &&
22305 SemaRef.
Diag(CI->getAssociatedExpression()->getExprLoc(),
22306 diag::err_omp_multiple_array_items_in_map_clause)
22307 << CI->getAssociatedExpression()->getSourceRange();
22308 SemaRef.
Diag(SI->getAssociatedExpression()->getExprLoc(),
22309 diag::note_used_here)
22310 << SI->getAssociatedExpression()->getSourceRange();
22315 if (CI->getAssociatedExpression()->getStmtClass() !=
22316 SI->getAssociatedExpression()->getStmtClass())
22320 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
22326 for (; SI != SE; ++SI) {
22328 if (
const auto *ASE =
22329 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
22330 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
22331 }
else if (
const auto *OASE = dyn_cast<ArraySectionExpr>(
22332 SI->getAssociatedExpression())) {
22335 }
else if (
const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
22336 SI->getAssociatedExpression())) {
22341 SemaRef, SI->getAssociatedExpression(),
Type))
22351 if (CI == CE && SI == SE) {
22352 if (CurrentRegionOnly) {
22353 if (CKind == OMPC_map) {
22354 SemaRef.
Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
22356 assert(CKind == OMPC_to || CKind == OMPC_from);
22357 SemaRef.
Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
22366 IsEnclosedByDataEnvironmentExpr =
true;
22371 std::prev(CI)->getAssociatedDeclaration()->getType();
22373 std::prev(CI)->getAssociatedExpression()->getExprLoc();
22392 if (CI == CE || SI == SE) {
22395 diag::err_omp_pointer_mapped_along_with_derived_section)
22401 if (CI->getAssociatedExpression()->getStmtClass() !=
22402 SI->getAssociatedExpression()->getStmtClass() ||
22403 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
22404 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
22405 assert(CI != CE && SI != SE);
22406 SemaRef.
Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
22419 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
22420 if (CKind == OMPC_map) {
22421 if (CI != CE || SI != SE) {
22425 CI != CE ? CurComponents.begin() : StackComponents.begin();
22426 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
22428 while (It != End && !It->getAssociatedDeclaration())
22429 std::advance(It, 1);
22430 assert(It != End &&
22431 "Expected at least one component with the declaration.");
22432 if (It != Begin && It->getAssociatedDeclaration()
22434 .getCanonicalType()
22435 ->isAnyPointerType()) {
22436 IsEnclosedByDataEnvironmentExpr =
false;
22437 EnclosingExpr =
nullptr;
22441 SemaRef.
Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
22443 assert(CKind == OMPC_to || CKind == OMPC_from);
22444 SemaRef.
Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
22454 if (!CurrentRegionOnly && SI != SE)
22455 EnclosingExpr = RE;
22459 IsEnclosedByDataEnvironmentExpr |=
22460 (!CurrentRegionOnly && CI != CE && SI == SE);
22465 if (CurrentRegionOnly)
22479 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
22481 diag::err_omp_original_storage_is_shared_and_does_not_contain)
22497 Expr *UnresolvedMapper) {
22517 Lookups.emplace_back();
22518 Lookups.back().append(Lookup.
begin(), Lookup.
end());
22521 }
else if (
auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
22526 assert(DMD &&
"Expect valid OMPDeclareMapperDecl during instantiation.");
22527 Lookups.back().addDecl(DMD);
22536 return !D->isInvalidDecl() &&
22537 (D->getType()->isDependentType() ||
22538 D->getType()->isInstantiationDependentType() ||
22539 D->getType()->containsUnexpandedParameterPack());
22550 false, URS.
begin(), URS.
end(),
false,
22558 SemaRef.
Diag(Loc, diag::err_omp_mapper_wrong_type);
22599 SemaRef.
Diag(Loc, diag::err_omp_invalid_mapper)
22609struct MappableVarListInfo {
22611 ArrayRef<Expr *> VarList;
22613 SmallVector<Expr *, 16> ProcessedVarList;
22617 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
22619 SmallVector<Expr *, 16> UDMapperList;
22621 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
22624 VarComponents.reserve(VarList.size());
22625 VarBaseDeclarations.reserve(VarList.size());
22634 const RecordDecl *RD = BaseType->getAsRecordDecl();
22644 for (
auto *FD : RD->
fields()) {
22646 MapperVarRef,
false, Range.getBegin(),
22652 SExprs.push_back(BE);
22660 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
22663 Maps.push_back(MapClause);
22664 return MapperVarRef;
22668 DSAStackTy *Stack) {
22674 const RecordDecl *RD = BaseType->getAsRecordDecl();
22683 MapperId = DeclNames.getIdentifier(&Ctx.
Idents.
get(
"default"));
22685 BaseType, MapperId, Maps,
nullptr);
22695 DMD->setMapperVarRef(MapperVarRef);
22719 Lookups.emplace_back();
22720 Lookups.back().append(Lookup.
begin(), Lookup.
end());
22727 return !D->isInvalidDecl() &&
22728 (D->getType()->isDependentType() ||
22729 D->getType()->isInstantiationDependentType() ||
22730 D->getType()->containsUnexpandedParameterPack());
22776 {CanonType,
nullptr});
22777 llvm::DenseMap<const Type *, bool> Visited;
22779 while (!Types.empty()) {
22780 auto [BaseType, CurFD] = Types.pop_back_val();
22781 while (ParentChain.back().second == 0)
22782 ParentChain.pop_back();
22783 --ParentChain.back().second;
22784 if (BaseType.isNull())
22787 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
22790 auto It = Visited.find(BaseType.getTypePtr());
22791 if (It == Visited.end()) {
22800 DefaultMapperId, BaseType);
22801 It = Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
22807 bool FirstIter =
true;
22817 ParentChain.emplace_back(CurFD, 1);
22819 ++ParentChain.back().second;
22821 Types.emplace_back(FieldTy, FD);
22840 bool IsMapTypeImplicit =
false,
bool NoDiagnose =
false) {
22842 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
22843 "Unexpected clause kind with mappable expressions!");
22844 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
22852 MapperId.
setName(DeclNames.getIdentifier(
22854 MapperId.
setLoc(StartLoc);
22858 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
22859 bool UpdateUMIt =
false;
22860 Expr *UnresolvedMapper =
nullptr;
22862 bool HasHoldModifier =
22863 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
22871 for (
Expr *RE : MVLI.VarList) {
22872 assert(RE &&
"Null expr in omp to/from/map clause");
22876 if (UpdateUMIt && UMIt != UMEnd) {
22880 "Expect the size of UnresolvedMappers to match with that of VarList");
22884 UnresolvedMapper = *UMIt;
22888 if (
VE->isValueDependent() ||
VE->isTypeDependent() ||
22889 VE->isInstantiationDependent() ||
22890 VE->containsUnexpandedParameterPack()) {
22893 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22894 VE->getType().getCanonicalType(), UnresolvedMapper);
22897 MVLI.UDMapperList.push_back(ER.
get());
22900 MVLI.ProcessedVarList.push_back(RE);
22909 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
22912 SemaRef.
Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
22925 DSAS->getCurrentDirective(), NoDiagnose);
22929 assert(!CurComponents.empty() &&
22930 "Invalid mappable expression information.");
22932 if (
const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
22934 DSAS->addMappedClassesQualTypes(TE->getType());
22937 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22938 VE->getType().getCanonicalType(), UnresolvedMapper);
22941 MVLI.UDMapperList.push_back(ER.
get());
22943 MVLI.ProcessedVarList.push_back(RE);
22944 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22945 MVLI.VarComponents.back().append(CurComponents.begin(),
22946 CurComponents.end());
22947 MVLI.VarBaseDeclarations.push_back(
nullptr);
22954 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
22955 assert(CurDeclaration &&
"Null decl on map clause.");
22958 "Expecting components to have associated only canonical declarations.");
22960 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
22961 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
22963 assert((VD || FD) &&
"Only variables or fields are expected here!");
22970 if (VD && DSAS->isThreadPrivate(VD)) {
22973 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD,
false);
22974 SemaRef.
Diag(ELoc, diag::err_omp_threadprivate_in_clause)
22989 true, CurComponents, CKind))
22991 if (CKind == OMPC_map &&
22994 false, CurComponents, CKind))
23001 auto I = llvm::find_if(
23006 assert(I != CurComponents.end() &&
"Null decl on map clause.");
23009 auto *ASE = dyn_cast<ArraySubscriptExpr>(
VE->IgnoreParens());
23010 auto *OASE = dyn_cast<ArraySectionExpr>(
VE->IgnoreParens());
23011 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(
VE->IgnoreParens());
23013 Type = ASE->getType().getNonReferenceType();
23018 Type = ATy->getElementType();
23021 Type =
Type.getNonReferenceType();
23022 }
else if (OAShE) {
23036 if (CKind == OMPC_map) {
23043 if (DKind == OMPD_target_enter_data &&
23044 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
23046 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23047 << (IsMapTypeImplicit ? 1 : 0)
23049 << getOpenMPDirectiveName(DKind, OMPVersion);
23058 if (DKind == OMPD_target_exit_data &&
23059 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
23060 MapType == OMPC_MAP_delete || SemaRef.
getLangOpts().OpenMP >= 52)) {
23061 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23062 << (IsMapTypeImplicit ? 1 : 0)
23064 << getOpenMPDirectiveName(DKind, OMPVersion);
23073 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
23075 SemaRef.
Diag(StartLoc,
23076 diag::err_omp_invalid_map_type_modifier_for_directive)
23078 OMPC_MAP_MODIFIER_ompx_hold)
23079 << getOpenMPDirectiveName(DKind, OMPVersion);
23087 if ((DKind == OMPD_target_data ||
23089 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
23090 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
23091 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23092 << (IsMapTypeImplicit ? 1 : 0)
23094 << getOpenMPDirectiveName(DKind, OMPVersion);
23106 if (VD && ((SemaRef.
LangOpts.OpenMP <= 45 &&
23108 DKind == OMPD_target)) {
23109 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD,
false);
23111 SemaRef.
Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23114 << getOpenMPDirectiveName(DSAS->getCurrentDirective(),
23124 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23125 Type.getCanonicalType(), UnresolvedMapper);
23137 BaseType =
VE->getType().getCanonicalType();
23144 ElemType = ATy->getElementType();
23149 }
else if (
VE->getType()->isArrayType()) {
23150 const ArrayType *AT =
VE->getType()->getAsArrayTypeUnsafe();
23160 MVLI.UDMapperList.push_back(ER.
get());
23163 MVLI.ProcessedVarList.push_back(RE);
23167 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
23173 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23174 MVLI.VarComponents.back().append(CurComponents.begin(),
23175 CurComponents.end());
23197 BuiltinType::OMPIterator))
23199 diag::err_omp_map_modifier_not_iterator);
23202 unsigned Count = 0;
23203 for (
unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
23205 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
23206 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
23210 "Modifiers exceed the allowed number of map type modifiers");
23211 Modifiers[Count] = MapTypeModifiers[I];
23212 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
23216 MappableVarListInfo MVLI(VarList);
23218 MapperIdScopeSpec, MapperId, UnresolvedMappers,
23219 MapType, Modifiers, IsMapTypeImplicit,
23225 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23226 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
23228 MapperId, MapType, IsMapTypeImplicit, MapLoc);
23236 if (ReductionType.
isNull())
23244 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
23249 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
23253 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
23257 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
23260 return ReductionType;
23266 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
23269 Decls.reserve(ReductionTypes.size());
23273 SemaRef.forRedeclarationInCurContext());
23278 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
23280 bool InCompoundScope =
true;
23281 if (S !=
nullptr) {
23287 SemaRef.LookupName(Lookup, S);
23288 SemaRef.FilterLookupForScope(Lookup, DC, S,
false,
23290 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
23292 while (Filter.hasNext()) {
23294 if (InCompoundScope) {
23295 UsedAsPrevious.try_emplace(PrevDecl,
false);
23297 UsedAsPrevious[D] =
true;
23299 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
23300 PrevDecl->getLocation();
23303 if (InCompoundScope) {
23304 for (
const auto &PrevData : UsedAsPrevious) {
23305 if (!PrevData.second) {
23306 PrevDRD = PrevData.first;
23311 }
else if (PrevDeclInScope !=
nullptr) {
23312 auto *PrevDRDInScope = PrevDRD =
23315 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
23316 PrevDRDInScope->getLocation();
23317 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
23318 }
while (PrevDRDInScope !=
nullptr);
23320 for (
const auto &TyData : ReductionTypes) {
23321 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
23323 if (I != PreviousRedeclTypes.end()) {
23324 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
23326 Diag(I->second, diag::note_previous_definition);
23329 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
23331 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
23333 DRD->setAccess(AS);
23334 Decls.push_back(DRD);
23336 DRD->setInvalidDecl();
23350 SemaRef.setFunctionHasBranchProtectedScope();
23351 SemaRef.getCurFunction()->setHasOMPDeclareReductionCombiner();
23354 SemaRef.PushDeclContext(S, DRD);
23358 SemaRef.PushExpressionEvaluationContext(
23361 QualType ReductionType = DRD->getType();
23378 if (S !=
nullptr) {
23379 SemaRef.PushOnScopeChains(OmpInParm, S);
23380 SemaRef.PushOnScopeChains(OmpOutParm, S);
23382 DRD->addDecl(OmpInParm);
23383 DRD->addDecl(OmpOutParm);
23389 DRD->setCombinerData(InE, OutE);
23395 SemaRef.DiscardCleanupsInEvaluationContext();
23396 SemaRef.PopExpressionEvaluationContext();
23399 SemaRef.PopFunctionScopeInfo();
23401 if (Combiner !=
nullptr)
23402 DRD->setCombiner(Combiner);
23404 DRD->setInvalidDecl();
23413 SemaRef.setFunctionHasBranchProtectedScope();
23416 SemaRef.PushDeclContext(S, DRD);
23420 SemaRef.PushExpressionEvaluationContext(
23423 QualType ReductionType = DRD->getType();
23440 if (S !=
nullptr) {
23441 SemaRef.PushOnScopeChains(OmpPrivParm, S);
23442 SemaRef.PushOnScopeChains(OmpOrigParm, S);
23444 DRD->addDecl(OmpPrivParm);
23445 DRD->addDecl(OmpOrigParm);
23451 DRD->setInitializerData(OrigE, PrivE);
23452 return OmpPrivParm;
23458 SemaRef.DiscardCleanupsInEvaluationContext();
23459 SemaRef.PopExpressionEvaluationContext();
23462 SemaRef.PopFunctionScopeInfo();
23466 }
else if (OmpPrivParm->
hasInit()) {
23467 DRD->setInitializer(OmpPrivParm->
getInit(),
23472 DRD->setInvalidDecl();
23478 for (
Decl *D : DeclReductions.
get()) {
23484 D->setInvalidDecl();
23487 return DeclReductions;
23499 SemaRef.CheckExtraCXXDefaultArguments(D);
23502 return SemaRef.CreateParsedType(
T, TInfo);
23507 assert(
ParsedType.isUsable() &&
"Expect usable parsed mapper type");
23510 assert(!MapperType.
isNull() &&
"Expect valid mapper type");
23515 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
23527 SemaRef.forRedeclarationInCurContext());
23532 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
23534 bool InCompoundScope =
true;
23535 if (S !=
nullptr) {
23541 SemaRef.LookupName(Lookup, S);
23542 SemaRef.FilterLookupForScope(Lookup, DC, S,
false,
23544 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
23546 while (Filter.hasNext()) {
23548 if (InCompoundScope) {
23549 UsedAsPrevious.try_emplace(PrevDecl,
false);
23551 UsedAsPrevious[D] =
true;
23553 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
23554 PrevDecl->getLocation();
23557 if (InCompoundScope) {
23558 for (
const auto &PrevData : UsedAsPrevious) {
23559 if (!PrevData.second) {
23560 PrevDMD = PrevData.first;
23565 }
else if (PrevDeclInScope) {
23566 auto *PrevDMDInScope = PrevDMD =
23569 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
23570 PrevDMDInScope->getLocation();
23571 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
23572 }
while (PrevDMDInScope !=
nullptr);
23576 if (I != PreviousRedeclTypes.end()) {
23577 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
23578 << MapperType << Name;
23579 Diag(I->second, diag::note_previous_definition);
23587 ClausesWithImplicit);
23589 MapperType, VN, ClausesWithImplicit,
23592 SemaRef.PushOnScopeChains(DMD, S);
23595 DMD->setAccess(AS);
23597 DMD->setInvalidDecl();
23603 DMD->setMapperVarRef(MapperVarRef);
23617 SemaRef.PushOnScopeChains(VD, S,
false);
23619 DSAStack->addDeclareMapperVarRef(E);
23626 if (
DSAStack->getDeclareMapperVarRef()) {
23632 assert(!IsGlobalVar &&
"Only declare mapper handles TU-scope iterators.");
23637 assert(
getLangOpts().OpenMP &&
"Expected OpenMP mode.");
23639 if (
const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
23652 assert(
getLangOpts().OpenMP &&
"Expected OpenMP mode.");
23660 if (VarList.empty())
23663 for (
Expr *ValExpr : VarList) {
23674 if (CaptureRegion == OMPD_unknown ||
SemaRef.CurContext->isDependentContext())
23676 LParenLoc, EndLoc, VarList,
23679 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23681 for (
Expr *ValExpr : VarList) {
23682 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
23683 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
23684 Vars.push_back(ValExpr);
23689 LParenLoc, EndLoc, Vars, PreInit);
23696 if (VarList.empty())
23699 for (
Expr *ValExpr : VarList) {
23710 if (CaptureRegion == OMPD_unknown ||
SemaRef.CurContext->isDependentContext())
23712 StartLoc, LParenLoc, EndLoc, VarList,
23715 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23717 for (
Expr *ValExpr : VarList) {
23718 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
23719 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
23720 Vars.push_back(ValExpr);
23725 LParenLoc, EndLoc, Vars, PreInit);
23732 Expr *ValExpr = Priority;
23733 Stmt *HelperValStmt =
nullptr;
23739 ValExpr,
SemaRef, OMPC_priority,
23741 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
23745 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23753 "Unexpected grainsize modifier in OpenMP < 51.");
23758 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
23763 Expr *ValExpr = Grainsize;
23764 Stmt *HelperValStmt =
nullptr;
23774 &CaptureRegion, &HelperValStmt))
23779 StartLoc, LParenLoc, ModifierLoc, EndLoc);
23787 "Unexpected num_tasks modifier in OpenMP < 51.");
23792 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
23797 Expr *ValExpr = NumTasks;
23798 Stmt *HelperValStmt =
nullptr;
23805 ValExpr,
SemaRef, OMPC_num_tasks,
23807 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
23812 StartLoc, LParenLoc, ModifierLoc, EndLoc);
23832 DSAStackTy *Stack) {
23833 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
23834 if (!OMPEventHandleT.
isNull())
23839 S.
Diag(Loc, diag::err_omp_implied_type_not_found) <<
"omp_event_handle_t";
23842 Stack->setOMPEventHandleT(PT.
get());
23863 auto *VD = dyn_cast_or_null<VarDecl>(Ref->
getDecl());
23873 <<
"omp_event_handle_t" << 1 << VD->
getType()
23880 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(VD,
false);
23881 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
23900 std::string Values;
23904 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23908 Expr *ValExpr = ChunkSize;
23909 Stmt *HelperValStmt =
nullptr;
23920 ValExpr = Val.
get();
23925 if (std::optional<llvm::APSInt>
Result =
23927 if (
Result->isSigned() && !
Result->isStrictlyPositive()) {
23928 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
23929 <<
"dist_schedule" << 1
23934 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
23936 !
SemaRef.CurContext->isDependentContext()) {
23937 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
23938 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23939 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
23947 Kind, ValExpr, HelperValStmt);
23955 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
23956 Kind != OMPC_DEFAULTMAP_scalar) {
23960 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
23962 OMPC_DEFAULTMAP_MODIFIER_tofrom);
23966 OMPC_DEFAULTMAP_scalar);
23970 Diag(Loc, diag::err_omp_unexpected_clause_value)
23978 if (!isDefaultmapKind || !isDefaultmapModifier) {
23980 ?
"'scalar', 'aggregate', 'pointer'"
23981 :
"'scalar', 'aggregate', 'pointer', 'all'";
23983 StringRef ModifierValue =
"'alloc', 'from', 'to', 'tofrom', "
23984 "'firstprivate', 'none', 'default'";
23985 if (!isDefaultmapKind && isDefaultmapModifier) {
23986 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23988 }
else if (isDefaultmapKind && !isDefaultmapModifier) {
23989 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23992 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23994 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23998 StringRef ModifierValue =
24000 ?
"'alloc', 'from', 'to', 'tofrom', "
24001 "'firstprivate', 'none', 'default', 'present'"
24002 :
"'storage', 'from', 'to', 'tofrom', "
24003 "'firstprivate', 'private', 'none', 'default', 'present'";
24004 if (!isDefaultmapKind && isDefaultmapModifier) {
24005 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24007 }
else if (isDefaultmapKind && !isDefaultmapModifier) {
24008 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24011 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24013 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24023 if (
DSAStack->checkDefaultmapCategory(Kind)) {
24024 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
24030 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
24031 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
24032 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
24034 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
24051 Diag(DTCI.
Loc, diag::err_omp_region_not_file_context);
24057 Diag(DTCI.
Loc, diag::warn_hip_omp_target_directives);
24059 DeclareTargetNesting.push_back(DTCI);
24065 assert(!DeclareTargetNesting.empty() &&
24066 "check isInOpenMPDeclareTargetContext() first!");
24067 return DeclareTargetNesting.pop_back_val();
24077 if (DeclareTargetNesting.empty())
24081 Diag(DTCI.
Loc, diag::warn_omp_unterminated_declare_target)
24082 << getOpenMPDirectiveName(DTCI.
Kind, OMPVersion);
24088 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
24097 VarOrFuncDeclFilterCCC CCC(
SemaRef);
24101 SemaRef.diagnoseTypo(Corrected,
24102 SemaRef.PDiag(diag::err_undeclared_var_use_suggest)
24126 "Expected variable, function or function template.");
24128 if (
auto *VD = dyn_cast<VarDecl>(ND)) {
24130 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
24131 !VD->isStaticDataMember()) {
24132 Diag(Loc, diag::err_omp_declare_target_has_local_vars)
24141 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
24145 Diag(Loc, diag::warn_hip_omp_target_directives);
24148 const unsigned Level = -1;
24151 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
24152 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
24153 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.
DT &&
24154 (*ActiveAttr)->getLevel() == Level) {
24155 Diag(Loc, diag::err_omp_device_type_mismatch)
24156 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.
DT)
24157 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
24158 (*ActiveAttr)->getDevType());
24161 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
24162 (*ActiveAttr)->getLevel() == Level) {
24163 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
24167 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
24170 Expr *IndirectE =
nullptr;
24171 bool IsIndirect =
false;
24177 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
24182 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
24184 if (
auto *VD = dyn_cast<VarDecl>(ND);
24186 VD->hasGlobalStorage())
24195 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy>
MapTy =
24196 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
24197 if (SemaRef.
LangOpts.OpenMP >= 50 &&
24200 VD->hasGlobalStorage()) {
24201 if (!
MapTy || (*
MapTy != OMPDeclareTargetDeclAttr::MT_To &&
24202 *
MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
24209 diag::err_omp_lambda_capture_in_declare_target_not_to);
24210 SemaRef.
Diag(SL, diag::note_var_explicitly_captured_here)
24217 SemaRef.
Diag(VD->
getLocation(), diag::warn_omp_not_in_target_context);
24218 SemaRef.
Diag(SL, diag::note_used_here) << SR;
24222 Sema &SemaRef, DSAStackTy *Stack,
24224 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
24235 if (
auto *VD = dyn_cast<VarDecl>(D)) {
24237 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
24238 !VD->isStaticDataMember())
24242 if (
DSAStack->isThreadPrivate(VD)) {
24243 Diag(SL, diag::err_omp_threadprivate_in_target);
24248 if (
const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
24249 D = FTD->getTemplatedDecl();
24250 if (
auto *FD = dyn_cast<FunctionDecl>(D)) {
24251 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
24252 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
24253 if (IdLoc.
isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
24254 Diag(IdLoc, diag::err_omp_function_in_link_clause);
24259 if (
auto *VD = dyn_cast<ValueDecl>(D)) {
24269 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
24270 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
24271 unsigned Level = DeclareTargetNesting.size();
24272 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
24275 Expr *IndirectE =
nullptr;
24276 bool IsIndirect =
false;
24282 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
24284 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
24285 : OMPDeclareTargetDeclAttr::MT_To,
24286 DTCI.
DT, IndirectE, IsIndirect, Level,
24290 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
24310 if (
auto *VD = dyn_cast<VarDecl>(Node->
getDecl())) {
24312 DeclVector.push_back(VD);
24317 for (
auto *Child : Ex->
children()) {
24326 A = TD->
getAttr<OMPDeclareTargetDeclAttr>();
24328 llvm::SmallDenseSet<Decl *> Visited;
24329 while (!DeclVector.empty()) {
24330 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
24331 if (!Visited.insert(TargetVarDecl).second)
24334 if (TargetVarDecl->
hasAttr<OMPDeclareTargetDeclAttr>() &&
24363 unsigned Count = 0;
24364 for (
unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
24366 llvm::is_contained(Modifiers, MotionModifiers[I])) {
24367 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
24371 "Modifiers exceed the allowed number of motion modifiers");
24372 Modifiers[Count] = MotionModifiers[I];
24373 ModifiersLoc[Count] = MotionModifiersLoc[I];
24377 MappableVarListInfo MVLI(VarList);
24379 MapperIdScopeSpec, MapperId, UnresolvedMappers);
24380 if (MVLI.ProcessedVarList.empty())
24384 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24385 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
24400 unsigned Count = 0;
24401 for (
unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
24403 llvm::is_contained(Modifiers, MotionModifiers[I])) {
24404 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
24408 "Modifiers exceed the allowed number of motion modifiers");
24409 Modifiers[Count] = MotionModifiers[I];
24410 ModifiersLoc[Count] = MotionModifiersLoc[I];
24414 MappableVarListInfo MVLI(VarList);
24416 MapperIdScopeSpec, MapperId, UnresolvedMappers);
24417 if (MVLI.ProcessedVarList.empty())
24421 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24422 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
24429 MappableVarListInfo MVLI(VarList);
24433 for (
Expr *RefExpr : VarList) {
24434 assert(RefExpr &&
"NULL expr in OpenMP use_device_ptr clause.");
24437 Expr *SimpleRefExpr = RefExpr;
24441 MVLI.ProcessedVarList.push_back(RefExpr);
24442 PrivateCopies.push_back(
nullptr);
24443 Inits.push_back(
nullptr);
24450 Type =
Type.getNonReferenceType().getUnqualifiedType();
24452 auto *VD = dyn_cast<VarDecl>(D);
24456 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
24457 << 0 << RefExpr->getSourceRange();
24466 if (VDPrivate->isInvalidDecl())
24469 SemaRef.CurContext->addDecl(VDPrivate);
24471 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
24478 SemaRef.AddInitializerToDecl(
24479 VDPrivate,
SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
24487 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
24488 PrivateCopies.push_back(VDPrivateRefExpr);
24489 Inits.push_back(VDInitRefExpr);
24494 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
24498 MVLI.VarBaseDeclarations.push_back(D);
24499 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24500 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
24504 if (MVLI.ProcessedVarList.empty())
24508 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
24509 MVLI.VarBaseDeclarations, MVLI.VarComponents);
24515 MappableVarListInfo MVLI(VarList);
24517 for (
Expr *RefExpr : VarList) {
24518 assert(RefExpr &&
"NULL expr in OpenMP use_device_addr clause.");
24521 Expr *SimpleRefExpr = RefExpr;
24527 MVLI.ProcessedVarList.push_back(RefExpr);
24532 auto *VD = dyn_cast<VarDecl>(D);
24539 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
24544 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
24548 MVLI.VarBaseDeclarations.push_back(D);
24549 MVLI.VarComponents.emplace_back();
24550 Expr *Component = SimpleRefExpr;
24554 SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
24555 MVLI.VarComponents.back().emplace_back(Component, D,
24559 if (MVLI.ProcessedVarList.empty())
24563 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24564 MVLI.VarComponents);
24570 MappableVarListInfo MVLI(VarList);
24571 for (
Expr *RefExpr : VarList) {
24572 assert(RefExpr &&
"NULL expr in OpenMP is_device_ptr clause.");
24575 Expr *SimpleRefExpr = RefExpr;
24579 MVLI.ProcessedVarList.push_back(RefExpr);
24589 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
24590 << 0 << RefExpr->getSourceRange();
24596 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
24599 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
24602 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
24608 const Expr *ConflictExpr;
24609 if (
DSAStack->checkMappableExprComponentListsForDecl(
24614 ConflictExpr = R.front().getAssociatedExpression();
24617 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
24626 SimpleRefExpr, D,
false);
24627 DSAStack->addMappableExpressionComponents(
24628 D, MC, OMPC_is_device_ptr);
24631 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
24638 "Unexpected device pointer expression!");
24639 MVLI.VarBaseDeclarations.push_back(
24641 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24642 MVLI.VarComponents.back().push_back(MC);
24645 if (MVLI.ProcessedVarList.empty())
24649 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24650 MVLI.VarComponents);
24656 MappableVarListInfo MVLI(VarList);
24657 for (
Expr *RefExpr : VarList) {
24658 assert(RefExpr &&
"NULL expr in OpenMP has_device_addr clause.");
24661 Expr *SimpleRefExpr = RefExpr;
24666 MVLI.ProcessedVarList.push_back(RefExpr);
24674 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
24677 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
24680 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
24686 const Expr *ConflictExpr;
24687 if (
DSAStack->checkMappableExprComponentListsForDecl(
24692 ConflictExpr = R.front().getAssociatedExpression();
24695 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
24703 Expr *Component = SimpleRefExpr;
24704 auto *VD = dyn_cast<VarDecl>(D);
24708 SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
24710 Component, D,
false);
24711 DSAStack->addMappableExpressionComponents(
24712 D, MC, OMPC_has_device_addr);
24715 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
24718 assert(Ref &&
"has_device_addr capture failed");
24719 MVLI.ProcessedVarList.push_back(Ref);
24721 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
24728 "Unexpected device pointer expression!");
24729 MVLI.VarBaseDeclarations.push_back(
24731 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24732 MVLI.VarComponents.back().push_back(MC);
24735 if (MVLI.ProcessedVarList.empty())
24739 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24740 MVLI.VarComponents);
24754 bool AllocDependent =
24758 if (!AllocDependent) {
24767 AllocatorRes =
SemaRef.PerformImplicitConversion(
24768 AllocatorRes.
get(),
DSAStack->getOMPAllocatorHandleT(),
24773 Allocator = AllocatorRes.
isUsable() ? AllocatorRes.
get() :
nullptr;
24783 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
24790 if (!AlignmentDependent) {
24793 Alignment = AlignResult.
isUsable() ? AlignResult.
get() :
nullptr;
24798 for (
Expr *RefExpr : VarList) {
24799 assert(RefExpr &&
"NULL expr in OpenMP allocate clause.");
24802 Expr *SimpleRefExpr = RefExpr;
24806 Vars.push_back(RefExpr);
24812 auto *VD = dyn_cast<VarDecl>(D);
24814 if (!VD && !
SemaRef.CurContext->isDependentContext())
24816 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
24817 ? RefExpr->IgnoreParens()
24825 DSAStack->addInnerAllocatorExpr(Allocator);
24828 getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
24829 FirstAllocateModifier, FirstAllocateModifierLoc, SecondAllocateModifier,
24830 SecondAllocateModifierLoc, EndLoc, Vars);
24838 for (
Expr *RefExpr : VarList) {
24839 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
24842 Expr *SimpleRefExpr = RefExpr;
24846 Vars.push_back(RefExpr);
24853 if (
const Expr *PrevRef =
24854 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
24855 Diag(ELoc, diag::err_omp_used_in_clause_twice)
24857 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
24862 Vars.push_back(RefExpr);
24879 SemaRef.setFunctionHasBranchProtectedScope();
24881 return OMPScopeDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses,
24890 for (
Expr *RefExpr : VarList) {
24891 assert(RefExpr &&
"NULL expr in OpenMP inclusive clause.");
24894 Expr *SimpleRefExpr = RefExpr;
24899 Vars.push_back(RefExpr);
24904 const DSAStackTy::DSAVarData DVar =
24910 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
24911 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
24912 << RefExpr->getSourceRange();
24914 if (
DSAStack->getParentDirective() != OMPD_unknown)
24915 DSAStack->markDeclAsUsedInScanDirective(D);
24916 Vars.push_back(RefExpr);
24931 for (
Expr *RefExpr : VarList) {
24932 assert(RefExpr &&
"NULL expr in OpenMP exclusive clause.");
24935 Expr *SimpleRefExpr = RefExpr;
24940 Vars.push_back(RefExpr);
24946 DSAStackTy::DSAVarData DVar;
24947 if (ParentDirective != OMPD_unknown)
24948 DVar =
DSAStack->getTopDSA(D,
true);
24953 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
24954 DVar.Modifier != OMPC_REDUCTION_inscan) {
24955 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
24956 << RefExpr->getSourceRange();
24958 DSAStack->markDeclAsUsedInScanDirective(D);
24960 Vars.push_back(RefExpr);
24972 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
24973 if (!OMPAlloctraitT.
isNull())
24978 S.
Diag(Loc, diag::err_omp_implied_type_not_found) <<
"omp_alloctrait_t";
24981 Stack->setOMPAlloctraitT(PT.
get());
25001 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
25002 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
25003 StringRef Allocator =
25004 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
25006 PredefinedAllocators.insert(
SemaRef.LookupSingleName(
25012 Expr *AllocatorExpr =
nullptr;
25020 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
25021 bool IsPredefinedAllocator =
false;
25023 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
25025 IsPredefinedAllocator =
25027 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
25031 bool IsTypeCompatible = IsPredefinedAllocator;
25032 IsTypeCompatible = IsTypeCompatible ||
25033 Context.hasSameUnqualifiedType(AllocatorExprType,
25034 OMPAllocatorHandleT);
25036 IsTypeCompatible ||
25037 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
25038 bool IsNonConstantLValue =
25040 if (!DRE || !IsTypeCompatible ||
25041 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
25043 <<
"omp_allocator_handle_t" << (DRE ? 1 : 0)
25052 diag::err_omp_predefined_allocator_with_traits)
25065 diag::err_omp_nonpredefined_allocator_without_traits);
25071 AllocatorExpr =
SemaRef.DefaultLvalueConversion(AllocatorExpr).get();
25074 IsPredefinedAllocator
25075 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
25076 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
25078 Expr *AllocatorTraitsExpr =
nullptr;
25092 if (
const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
25093 TraitTy = ConstArrayTy->getElementType();
25095 !(Context.hasSameUnqualifiedType(TraitTy,
25097 Context.typesAreCompatible(TraitTy,
DSAStack->getOMPAlloctraitT(),
25100 diag::err_omp_expected_array_alloctraits)
25101 << AllocatorTraitsExpr->
getType();
25106 if (
auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
25109 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
25126 for (
Expr *RefExpr : Locators) {
25127 assert(RefExpr &&
"NULL expr in OpenMP affinity clause.");
25130 Vars.push_back(RefExpr);
25138 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
25139 << 1 << 0 << RefExpr->getSourceRange();
25150 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
25151 << 1 << 0 << RefExpr->getSourceRange();
25158 ColonLoc, EndLoc, Modifier, Vars);
25167 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
25175 LParenLoc, EndLoc);
25182 Expr *ValExpr = Size;
25183 Stmt *HelperValStmt =
nullptr;
25194 DKind, OMPC_ompx_dyn_cgroup_mem,
getLangOpts().OpenMP);
25195 if (CaptureRegion != OMPD_unknown &&
25196 !
SemaRef.CurContext->isDependentContext()) {
25197 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
25198 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
25199 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
25204 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
25212 if (
DSAStack->getCurrentDirective() == OMPD_ordered &&
25213 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
25214 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
25215 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
25216 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
25222 DSAStackTy::OperatorOffsetTy OpsOffs;
25223 llvm::APSInt TotalDepCount(32);
25226 DepType == OMPC_DOACROSS_source ||
25227 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
25228 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
25230 Vars = VarOffset.Vars;
25231 OpsOffs = VarOffset.OpsOffs;
25232 TotalDepCount = VarOffset.TotalDepCount;
25234 EndLoc, DepType, DepLoc, ColonLoc, Vars,
25235 TotalDepCount.getZExtValue());
25236 if (
DSAStack->isParentOrderedRegion())
25237 DSAStack->addDoacrossDependClause(
C, OpsOffs);
25266 case OMPC_contains:
25269 llvm_unreachable(
"Unexpected OpenMP clause");
25277 case OMPC_no_openmp:
25279 case OMPC_no_openmp_routines:
25281 case OMPC_no_parallelism:
25283 case OMPC_no_openmp_constructs:
25286 llvm_unreachable(
"Unexpected OpenMP clause");
25295 if (
Base->hasPlaceholderType() &&
25296 !
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
25309 LowerBound =
Result.get();
25311 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
25331 if (
Base->isTypeDependent() ||
25334 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
25337 Base, LowerBound, Length, Stride, Context.DependentTy,
VK_LValue,
25338 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
25350 Diag(
Base->getExprLoc(), diag::err_omp_typecheck_section_value)
25351 <<
Base->getSourceRange());
25357 if (Res.isInvalid())
25359 diag::err_omp_typecheck_section_not_integer)
25361 LowerBound = Res.get();
25371 if (Res.isInvalid())
25373 diag::err_omp_typecheck_section_not_integer)
25374 << 1 << Length->getSourceRange());
25375 Length = Res.get();
25377 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
25378 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
25379 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
25380 << 1 << Length->getSourceRange();
25387 diag::err_omp_typecheck_section_not_integer)
25389 Stride = Res.
get();
25402 Diag(
Base->getExprLoc(), diag::err_omp_section_function_type)
25403 << ResultTy <<
Base->getSourceRange();
25407 if (
SemaRef.RequireCompleteType(
Base->getExprLoc(), ResultTy,
25408 diag::err_omp_section_incomplete_type,
Base))
25416 llvm::APSInt LowerBoundValue =
Result.Val.getInt();
25417 if (LowerBoundValue.isNegative()) {
25419 diag::err_omp_section_not_subset_of_array)
25428 if (Length->EvaluateAsInt(
Result, Context)) {
25431 llvm::APSInt LengthValue =
Result.Val.getInt();
25432 if (LengthValue.isNegative()) {
25433 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
25434 <<
toString(LengthValue, 10,
true)
25435 << Length->getSourceRange();
25439 }
else if (
SemaRef.getLangOpts().OpenMP < 60 && ColonLocFirst.
isValid() &&
25445 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
25455 llvm::APSInt StrideValue =
Result.Val.getInt();
25456 if (!StrideValue.isStrictlyPositive()) {
25457 Diag(Stride->
getExprLoc(), diag::err_omp_section_stride_non_positive)
25458 <<
toString(StrideValue, 10,
true)
25465 if (!
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
25472 Base, LowerBound, Length, Stride, Context.ArraySectionTy,
VK_LValue,
25473 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
25480 if (
Base->hasPlaceholderType()) {
25494 LParenLoc, RParenLoc, Dims, Brackets);
25496 (!
Base->isTypeDependent() &&
25499 diag::err_omp_non_pointer_type_array_shaping_base)
25500 <<
Base->getSourceRange());
25503 bool ErrorFound =
false;
25505 if (
Dim->hasPlaceholderType()) {
25507 if (
Result.isInvalid()) {
25512 if (
Result.isInvalid()) {
25518 if (!
Dim->isTypeDependent()) {
25521 if (
Result.isInvalid()) {
25523 Diag(
Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
25524 <<
Dim->getSourceRange();
25529 if (!
Dim->isValueDependent() &&
Dim->EvaluateAsInt(EvResult, Context)) {
25534 if (!
Value.isStrictlyPositive()) {
25535 Diag(
Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
25537 <<
Dim->getSourceRange();
25543 NewDims.push_back(
Dim);
25548 LParenLoc, RParenLoc, NewDims, Brackets);
25558 bool IsCorrect =
true;
25563 if (!D.Type.getAsOpaquePtr()) {
25567 DeclTy = Context.IntTy;
25568 StartLoc = D.DeclIdentLoc;
25574 bool IsDeclTyDependent = DeclTy->isDependentType() ||
25575 DeclTy->containsUnexpandedParameterPack() ||
25576 DeclTy->isInstantiationDependentType();
25577 if (!IsDeclTyDependent) {
25578 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
25581 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
25586 if (DeclTy.isConstant(Context)) {
25589 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
25597 assert(D.DeclIdent &&
"Identifier expected.");
25602 D.DeclIdent, DeclTy, TInfo,
SC_None);
25620 SemaRef.PushOnScopeChains(VD, S);
25623 SemaRef.CurContext->addDecl(VD);
25629 Expr *Begin = D.Range.Begin;
25633 Begin = BeginRes.
get();
25635 Expr *End = D.Range.End;
25639 End = EndRes.
get();
25641 Expr *Step = D.Range.Step;
25644 Diag(Step->
getExprLoc(), diag::err_omp_iterator_step_not_integral)
25649 std::optional<llvm::APSInt>
Result =
25655 Diag(Step->
getExprLoc(), diag::err_omp_iterator_step_constant_zero)
25661 if (!Begin || !End || !IsCorrect) {
25677 if (
Decl *ID = D.IteratorDecl)
25678 ID->setInvalidDecl();
25683 if (!
SemaRef.CurContext->isDependentContext()) {
25690 D.Range.End, D.Range.Begin);
25696 if (D.Range.Step) {
25699 Res =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.
get(),
25706 Res =
SemaRef.CreateBuiltinBinOp(
25707 D.AssignmentLoc, BO_Sub, Res.
get(),
25708 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
25714 Res =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.
get(),
25720 St1 =
SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus,
25724 D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End);
25730 Res1 =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.
get(),
25737 Res1 =
SemaRef.CreateBuiltinBinOp(
25738 D.AssignmentLoc, BO_Sub, Res1.
get(),
25739 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
25745 Res1 =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.
get(),
25753 D.AssignmentLoc, BO_GT, D.Range.Step,
25754 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get());
25759 Res =
SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc,
25766 Res =
SemaRef.ActOnFinishFullExpr(Res.
get(),
false);
25778 CounterVD->setImplicit();
25785 if (D.Range.Step) {
25786 UpdateRes =
SemaRef.CreateBuiltinBinOp(
25787 D.AssignmentLoc, BO_Mul,
25788 SemaRef.DefaultLvalueConversion(RefRes.
get()).get(), St.
get());
25790 UpdateRes =
SemaRef.DefaultLvalueConversion(RefRes.
get());
25796 UpdateRes =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add,
25797 D.Range.Begin, UpdateRes.
get());
25806 UpdateRes =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign,
25807 VDRes.
get(), UpdateRes.
get());
25813 SemaRef.ActOnFinishFullExpr(UpdateRes.
get(),
true);
25819 D.AssignmentLoc, UO_PreInc, RefRes.
get());
25820 if (!CounterUpdateRes.
isUsable()) {
25824 CounterUpdateRes =
SemaRef.ActOnFinishFullExpr(CounterUpdateRes.
get(),
25826 if (!CounterUpdateRes.
isUsable()) {
25837 Helpers.assign(ID.size(), {});
25842 if (
Decl *ID = D.IteratorDecl)
25843 ID->setInvalidDecl();
25848 LLoc, RLoc, ID, Helpers);
25853 StringRef AssumptionStr) {
25854 if (llvm::getKnownAssumptionStrings().count(AssumptionStr))
25857 unsigned BestEditDistance = 3;
25858 StringRef Suggestion;
25859 for (
const auto &KnownAssumptionIt : llvm::getKnownAssumptionStrings()) {
25860 unsigned EditDistance =
25861 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
25862 if (EditDistance < BestEditDistance) {
25863 Suggestion = KnownAssumptionIt.getKey();
25864 BestEditDistance = EditDistance;
25868 if (!Suggestion.empty())
25869 S.
Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
25870 << AssumptionStr << Suggestion;
25872 S.
Diag(Loc, diag::warn_omp_assume_attribute_string_unknown)
25880 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc))
Defines the clang::ASTContext interface.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
This file defines OpenMP nodes for declarative directives.
static const Decl * getCanonicalDecl(const Decl *D)
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
llvm::MachO::TargetList TargetList
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
llvm::DenseMap< Stmt *, Stmt * > MapTy
Implements a partial diagnostic that can be emitted anwyhere in a DiagnosticBuilder stream.
@ ForVisibleRedeclaration
The lookup results will be used for redeclaration of a name, if an entity by that name already exists...
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
static VarDecl * buildVarDecl(Sema &S, SourceLocation Loc, QualType Type, IdentifierInfo *II)
Build a variable declaration for move parameter.
static NamedDecl * findAcceptableDecl(Sema &SemaRef, NamedDecl *D, unsigned IDNS)
Retrieve the visible declaration corresponding to D, if any.
static Expr * getOrderedNumberExpr(ArrayRef< OMPClause * > Clauses)
static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack, bool Diagnose=true)
Tries to find omp_depend_t. type.
static Stmt * buildPreInits(ASTContext &Context, MutableArrayRef< Decl * > PreInits)
Build preinits statement for the given declarations.
static void argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id, SourceLocation Loc, QualType Ty, SmallVectorImpl< UnresolvedSet< 8 > > &Lookups)
static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR, Sema &SemaRef, Decl *D)
static void updatePreInits(OMPLoopTransformationDirective *Transform, SmallVectorImpl< Stmt * > &PreInits)
Updates OriginalInits by checking Transform against loop transformation directives and appending thei...
static bool checkGenericLoopLastprivate(Sema &S, ArrayRef< OMPClause * > Clauses, OpenMPDirectiveKind K, DSAStackTy *Stack)
static bool checkSimdlenSafelenSpecified(Sema &S, const ArrayRef< OMPClause * > Clauses)
static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto, QualType NewType)
static bool checkOMPArraySectionConstantForReduction(ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement, SmallVectorImpl< llvm::APSInt > &ArraySizes)
static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind, ArrayRef< OMPClause * > Clauses, ArrayRef< OpenMPDirectiveKind > AllowedNameModifiers)
static void handleDeclareVariantConstructTrait(DSAStackTy *Stack, OpenMPDirectiveKind DKind, bool ScopeEntry)
static VarDecl * precomputeExpr(Sema &Actions, SmallVectorImpl< Stmt * > &BodyStmts, Expr *E, StringRef Name)
static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S, CXXScopeSpec &MapperIdScopeSpec, const DeclarationNameInfo &MapperId, QualType Type)
static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, CXXScopeSpec &MapperIdScopeSpec, const DeclarationNameInfo &MapperId, QualType Type, Expr *UnresolvedMapper)
static bool checkReductionClauseWithNogroup(Sema &S, ArrayRef< OMPClause * > Clauses)
static bool checkSectionsDirective(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt, DSAStackTy *Stack)
static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, SourceLocation M1Loc, SourceLocation M2Loc)
static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef)
static Expr * makeFloorIVRef(Sema &SemaRef, ArrayRef< VarDecl * > FloorIndVars, int I, QualType IVTy, DeclRefExpr *OrigCntVar)
Build and return a DeclRefExpr for the floor induction variable using the SemaRef and the provided pa...
static OMPAllocateDeclAttr::AllocatorTypeTy getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator)
static bool isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind, bool StrictlyPositive, bool BuildCapture=false, OpenMPDirectiveKind DKind=OMPD_unknown, OpenMPDirectiveKind *CaptureRegion=nullptr, Stmt **HelperValStmt=nullptr)
static Expr * buildPostUpdate(Sema &S, ArrayRef< Expr * > PostUpdates)
Build postupdate expression for the given list of postupdates expressions.
static CapturedStmt * buildLoopVarFunc(Sema &Actions, QualType LoopVarTy, QualType LogicalTy, DeclRefExpr *StartExpr, Expr *Step, bool Deref)
Create a closure that computes the loop variable from the logical iteration number.
static ExprResult buildCounterUpdate(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef, ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract, bool IsNonRectangularLB, llvm::MapVector< const Expr *, DeclRefExpr * > *Captures=nullptr)
Build 'VarRef = Start + Iter * Step'.
static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion, OpenMPDirectiveKind NameModifier=OMPD_unknown)
static bool finishLinearClauses(Sema &SemaRef, ArrayRef< OMPClause * > Clauses, OMPLoopBasedDirective::HelperExprs &B, DSAStackTy *Stack)
static Expr * getCollapseNumberExpr(ArrayRef< OMPClause * > Clauses)
static Expr * getDirectCallExpr(Expr *E)
static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef, const Expr *E, QualType BaseQTy)
static OMPCapturedExprDecl * buildCaptureDecl(Sema &S, IdentifierInfo *Id, Expr *CaptureExpr, bool WithInit, DeclContext *CurContext, bool AsExpression)
static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_allocator_handle_t type.
static bool isClauseMappable(ArrayRef< OMPClause * > Clauses)
Check if the variables in the mapping clause are externally visible.
static BinaryOperatorKind getRelatedCompoundReductionOp(BinaryOperatorKind BOK)
static SmallVector< SemaOpenMP::CapturedParamNameType > getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing)
static void collectLoopStmts(Stmt *AStmt, MutableArrayRef< Stmt * > LoopStmts)
Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected loop of a construct.
static bool checkMutuallyExclusiveClauses(Sema &S, ArrayRef< OMPClause * > Clauses, ArrayRef< OpenMPClauseKind > MutuallyExclusiveClauses)
Find and diagnose mutually exclusive clause kinds.
static std::pair< ValueDecl *, bool > getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc, SourceRange &ERange, bool AllowArraySection=false, bool AllowAssumedSizeArray=false, StringRef DiagType="")
static DeclRefExpr * buildImplicitMap(Sema &S, QualType BaseType, DSAStackTy *Stack, SmallVectorImpl< OMPClause * > &Maps)
static bool checkOrderedOrderSpecified(Sema &S, const ArrayRef< OMPClause * > Clauses)
static OpenMPMapClauseKind getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M, bool IsAggregateOrDeclareTarget)
static void processCapturedRegions(Sema &SemaRef, OpenMPDirectiveKind DKind, Scope *CurScope, SourceLocation Loc)
static const Expr * getExprAsWritten(const Expr *E)
static bool checkMapConflicts(Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E, bool CurrentRegionOnly, OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents, OpenMPClauseKind CKind)
static bool isOpenMPDeviceDelayedContext(Sema &S)
static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef)
Convert integer expression E to make it have at least Bits bits.
static SmallVector< SemaOpenMP::CapturedParamNameType > getUnknownRegionParams(Sema &SemaRef)
static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack, QualType CanonType, const Expr *E)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTeamsRegionParams(Sema &SemaRef)
static void checkOMPAssumeAttr(Sema &S, SourceLocation Loc, StringRef AssumptionStr)
Check if AssumptionStr is a known assumption and warn if not.
static void applyOMPAllocateAttribute(Sema &S, VarDecl *VD, OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator, Expr *Alignment, SourceRange SR)
static ExprResult buildImplicitMapper(Sema &S, QualType BaseType, DSAStackTy *Stack)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTargetRegionParams(Sema &SemaRef)
static CapturedStmt * buildDistanceFunc(Sema &Actions, QualType LogicalTy, BinaryOperator::Opcode Rel, Expr *StartExpr, Expr *StopExpr, Expr *StepExpr)
Create a closure that computes the number of iterations of a loop.
static bool checkPreviousOMPAllocateAttribute(Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD, OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator)
static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, Expr *NumIterations, Sema &SemaRef, Scope *S, DSAStackTy *Stack)
static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D, QualType Type, OpenMPClauseKind CKind, SourceLocation ELoc, bool AcceptIfMutable=true, bool ListItemNotVar=false)
static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr, SourceLocation VarLoc, OpenMPClauseKind Kind)
static const ValueDecl * getCanonicalDecl(const ValueDecl *D)
static std::string getOpenMPClauseNameForDiag(OpenMPClauseKind C)
static const Expr * checkMapClauseExpressionBase(Sema &SemaRef, Expr *E, OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose)
Return the expression of the base of the mappable expression or null if it cannot be determined and d...
static void checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind, MappableVarListInfo &MVLI, SourceLocation StartLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId, ArrayRef< Expr * > UnresolvedMappers, OpenMPMapClauseKind MapType=OMPC_MAP_unknown, ArrayRef< OpenMPMapModifierKind > Modifiers={}, bool IsMapTypeImplicit=false, bool NoDiagnose=false)
static bool hasClauses(ArrayRef< OMPClause * > Clauses, const OpenMPClauseKind K)
Check for existence of a map clause in the list of clauses.
static bool checkOpenMPIterationSpace(OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA, unsigned CurrentNestedLoopCount, unsigned NestedLoopCount, unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA, llvm::MutableArrayRef< LoopIterationSpace > ResultIterSpaces, llvm::MapVector< const Expr *, DeclRefExpr * > &Captures, const llvm::SmallPtrSetImpl< const Decl * > &CollapsedLoopVarDecls)
Called on a for stmt to check and extract its iteration space for further processing (such as collaps...
static CapturedStmt * setBranchProtectedScope(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt)
static void processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack, SmallVectorImpl< OMPClause * > &Clauses)
Perform DFS through the structure/class data members trying to find member(s) with user-defined 'defa...
static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion, OpenMPDirectiveKind CancelRegion, SourceLocation StartLoc)
static DeclRefExpr * buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty, SourceLocation Loc, bool RefersToCapture=false)
static ExprResult buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef, ExprResult Start, bool IsNonRectangularLB, llvm::MapVector< const Expr *, DeclRefExpr * > &Captures)
Build 'VarRef = Start.
static DoacrossDataInfoTy ProcessOpenMPDoacrossClauseCommon(Sema &SemaRef, bool IsSource, ArrayRef< Expr * > VarList, DSAStackTy *Stack, SourceLocation EndLoc)
static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR, Sema &SemaRef, DSAStackTy *Stack, ValueDecl *VD)
static bool findOMPEventHandleT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_event_handle_t type.
static ExprResult buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, Scope *S, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, QualType Ty, CXXCastPath &BasePath, Expr *UnresolvedReduction)
static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef)
Check if the given expression E is a constant integer that fits into Bits bits.
static void checkAllocateClauses(Sema &S, DSAStackTy *Stack, ArrayRef< OMPClause * > Clauses)
static bool actOnOMPReductionKindClause(Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions, ReductionData &RD)
static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack, const ValueDecl *D, const DSAStackTy::DSAVarData &DVar, bool IsLoopIterVar=false)
static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last, ArrayRef< unsigned > Exclude={})
static DeclRefExpr * buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr, bool WithInit)
static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_alloctrait_t type.
static void appendFlattenedStmtList(SmallVectorImpl< Stmt * > &TargetList, Stmt *Item)
Append the Item or the content of a CompoundStmt to the list TargetList.
static bool isConstNotMutableType(Sema &SemaRef, QualType Type, bool AcceptIfMutable=true, bool *IsClassType=nullptr)
static void addLoopPreInits(ASTContext &Context, OMPLoopBasedDirective::HelperExprs &LoopHelper, Stmt *LoopStmt, ArrayRef< Stmt * > OriginalInit, SmallVectorImpl< Stmt * > &PreInits)
Add preinit statements that need to be propagated from the selected loop.
static void checkReductionClauses(Sema &S, DSAStackTy *Stack, ArrayRef< OMPClause * > Clauses)
Check consistency of the reduction clauses.
static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef, DSAStackTy *Stack, QualType QTy, bool FullCheck=true)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTaskRegionParams(Sema &SemaRef)
static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack, OpenMPDirectiveKind CurrentRegion, const DeclarationNameInfo &CurrentName, OpenMPDirectiveKind CancelRegion, OpenMPBindClauseKind BindKind, SourceLocation StartLoc)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTaskloopRegionParams(Sema &SemaRef)
static unsigned checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef, DSAStackTy &DSA, SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA, OMPLoopBasedDirective::HelperExprs &Built)
Called on a for stmt to check itself and nested loops (if any).
static OpenMPDefaultmapClauseKind getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD)
static bool checkNumExprsInClause(SemaBase &SemaRef, ArrayRef< OMPClause * > Clauses, unsigned MaxNum, unsigned Diag)
This checks whether a ClauseType clause C has at most Max expression.
static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef, const Expr *E, QualType BaseQTy)
Return true if it can be proven that the provided array expression (array section or array subscript)...
static T filterLookupForUDReductionAndMapper(SmallVectorImpl< U > &Lookups, const llvm::function_ref< T(ValueDecl *)> Gen)
This file declares semantic analysis for OpenMP constructs and clauses.
static CharSourceRange getRange(const CharSourceRange &EditRange, const SourceManager &SM, const LangOptions &LangOpts, bool IncludeMacroExpansion)
This file defines OpenMP AST classes for executable directives and clauses.
Expr * getUpdateExpr()
Get helper expression of the form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or 'OpaqueValueExp...
Expr * getV()
Get 'v' part of the associated expression/statement.
Expr * getR()
Get 'r' part of the associated expression/statement.
Expr * getD()
Get 'd' part of the associated expression/statement.
Expr * getX()
Get 'x' part of the associated expression/statement.
bool isFailOnly() const
Return true if 'v' is updated only when the condition is evaluated false (compare capture only).
bool isPostfixUpdate() const
Return true if 'v' expression must be updated to original value of 'x', false if 'v' must be updated ...
Expr * getExpr()
Get 'expr' part of the associated expression/statement.
bool isXLHSInRHSPart() const
Return true if helper update expression has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' and...
static QualType getPointeeType(const MemRegion *R)
VerifyDiagnosticConsumer::Directive Directive
Look for variables declared in the body parts of a for-loop nest.
bool VisitCXXForRangeStmt(CXXForRangeStmt *RF) override
bool VisitVarDecl(VarDecl *D) override
ForVarDeclFinder(llvm::SmallPtrSetImpl< const Decl * > &VD)
bool VisitForStmt(ForStmt *F) override
This class visits every VarDecl that the initializer references and adds OMPDeclareTargetDeclAttr to ...
void declareTargetInitializer(Decl *TD)
A function that keeps a record of all the Decls that are variables, has OMPDeclareTargetDeclAttr,...
void VisitDeclRefExpr(DeclRefExpr *Node)
A StmtVisitor class function that visits all DeclRefExpr and adds OMPDeclareTargetDeclAttr to them.
void VisitExpr(Expr *Ex)
A function that iterates across each of the Expr's children.
bool VisitCXXForRangeStmt(CXXForRangeStmt *FRS) override
NestedLoopCounterVisitor()=default
bool VisitForStmt(ForStmt *FS) override
bool TraverseStmt(Stmt *S) override
bool TraverseDecl(Decl *D) override
unsigned getNestedLoopCount() const
static OMPAssumeDirective * Create(const ASTContext &Ctx, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AStmt)
static OMPCancelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, OpenMPDirectiveKind CancelRegion)
Creates directive.
static OMPCancellationPointDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Creates directive.
static OMPDispatchDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, SourceLocation TargetCallLoc)
Creates directive with a list of Clauses.
static OMPDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPErrorDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
static OMPFuseDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumGeneratedTopLevelLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for pragma omp fuse'.
static OMPGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPInterchangeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp interchange'.
static OMPInteropDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive.
static OMPMaskedDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
static OMPMaskedTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPMaskedTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPMasterTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPMasterTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelMaskedTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPParallelMaskedTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelMasterTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPParallelMasterTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPReverseDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt, unsigned NumLoops, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp reverse'.
static OMPScanDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
static OMPStripeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp stripe'.
static OMPTargetDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetEnterDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetExitDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetParallelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetParallelGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool CanBeParallelFor)
Creates directive with a list of Clauses.
static OMPTargetUpdateDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTeamsDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTeamsDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTileDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp tile'.
static OMPUnrollDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, unsigned NumGeneratedTopLevelLoops, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp unroll'.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
unsigned getIntWidth(QualType T) const
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.
static IfStmt * Create(const ASTContext &Ctx, SourceLocation IL, IfStatementKind Kind, Stmt *Init, VarDecl *Var, Expr *Cond, SourceLocation LPL, SourceLocation RPL, Stmt *Then, SourceLocation EL=SourceLocation(), Stmt *Else=nullptr)
Create an IfStmt.
SourceLocation getBeginLoc() const
ImaginaryLiteral - We support imaginary integer and floating point literals, like "1....
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
ImplicitConversionSequence - Represents an implicit conversion sequence, which may be a standard conv...
Describes the kind of initialization being performed, along with location information for tokens rela...
static InitializationKind CreateCopy(SourceLocation InitLoc, SourceLocation EqualLoc, bool AllowExplicitConvs=false)
Create a copy initialization.
Describes the sequence of initializations required to initialize a given object or reference with a s...
ExprResult Perform(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType *ResultType=nullptr)
Perform the actual initialization of the given entity based on the computed initialization sequence.
Describes an entity that is being initialized.
static InitializedEntity InitializeVariable(VarDecl *Var)
Create the initialization entity for a variable.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Describes the capture of a variable or of this, or of a C++1y init-capture.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
A class for iterating through a result set and possibly filtering out results.
Represents the results of name lookup.
LLVM_ATTRIBUTE_REINITIALIZES void clear()
Clears out any current state.
DeclClass * getAsSingle() const
bool empty() const
Return true if no decls were found.
Filter makeFilter()
Create a filter for this result set.
NamedDecl * getFoundDecl() const
Fetch the unique decl found by this lookup.
bool isSingleResult() const
Determines if this names a single result which is not an unresolved value using decl.
NamedDecl * getRepresentativeDecl() const
Fetches a representative decl. Useful for lazy diagnostics.
void suppressDiagnostics()
Suppress the diagnostics that would normally fire because of this lookup.
static bool isVisible(Sema &SemaRef, NamedDecl *D)
Determine whether the given declaration is visible to the program.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
static MemberExpr * CreateImplicit(const ASTContext &C, Expr *Base, bool IsArrow, ValueDecl *MemberDecl, QualType T, ExprValueKind VK, ExprObjectKind OK)
Create an implicit MemberExpr, with no location, qualifier, template arguments, and so on.
SourceLocation getExprLoc() const LLVM_READONLY
This represents a decl that may have a name.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
virtual void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const
Appends a human-readable name for this declaration into the given stream.
void setDeclName(DeclarationName N)
Set the name of this declaration.
A C++ nested-name-specifier augmented with source location information.
static OMPAbsentClause * Create(const ASTContext &C, ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
This represents 'acq_rel' clause in the 'pragma omp atomic|flush' directives.
This represents 'acquire' clause in the 'pragma omp atomic|flush' directives.
static OMPAffinityClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Creates clause with a modifier a list of locator items.
static OMPAlignClause * Create(const ASTContext &C, Expr *A, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'align' clause with the given alignment.
static OMPAlignedClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Expr *A)
Creates clause with a list of variables VL and alignment A.
static OMPAllocateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, Expr *Allocator, Expr *Alignment, SourceLocation ColonLoc, OpenMPAllocateClauseModifier Modifier1, SourceLocation Modifier1Loc, OpenMPAllocateClauseModifier Modifier2, SourceLocation Modifier2Loc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static bool classof(const OMPClause *T)
static OMPAllocateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL, ArrayRef< OMPClause * > CL)
This represents 'allocator' clause in the 'pragma omp ...' directive.
Expr * getBase()
Fetches base expression of array shaping expression.
static OMPArrayShapingExpr * Create(const ASTContext &Context, QualType T, Expr *Op, SourceLocation L, SourceLocation R, ArrayRef< Expr * > Dims, ArrayRef< SourceRange > BracketRanges)
This represents 'at' clause in the 'pragma omp error' directive.
SourceLocation getAtKindKwLoc() const
Returns location of clause kind.
OpenMPAtClauseKind getAtKind() const
Returns kind of the clause.
This represents 'atomic_default_mem_order' clause in the 'pragma omp requires' directive.
This represents 'bind' clause in the 'pragma omp ...' directives.
static OMPBindClause * Create(const ASTContext &C, OpenMPBindClauseKind K, SourceLocation KLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'bind' clause with kind K ('teams', 'parallel', or 'thread').
This represents 'capture' clause in the 'pragma omp atomic' directive.
Pseudo declaration for capturing expressions.
static OMPCapturedExprDecl * Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, QualType T, SourceLocation StartLoc)
Class that represents a component of a mappable expression.
ValueDecl * getAssociatedDeclaration() const
ArrayRef< MappableComponent > MappableExprComponentListRef
SmallVector< MappableComponent, 8 > MappableExprComponentList
SmallVector< MappableExprComponentList, 8 > MappableExprComponentLists
static 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 OMPLoopRangeClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation FirstLoc, SourceLocation CountLoc, SourceLocation EndLoc, Expr *First, Expr *Count)
Build a 'looprange' clause AST node.
static OMPMapClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, Expr *IteratorModifier, ArrayRef< OpenMPMapModifierKind > MapModifiers, ArrayRef< SourceLocation > MapModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId, OpenMPMapClauseKind Type, bool TypeIsImplicit, SourceLocation TypeLoc)
Creates clause with a list of variables VL.
This represents 'mergeable' clause in the 'pragma omp ...' directive.
This represents the 'message' clause in the 'pragma omp error' and the 'pragma omp parallel' directiv...
Expr * getMessageString() const
Returns message string of the clause.
std::optional< std::string > tryEvaluateString(ASTContext &Ctx) const
Try to evaluate the message string at compile time.
This represents the 'no_openmp' clause in the 'pragma omp assume' directive.
This represents the 'no_openmp_constructs' clause in the.
This represents the 'no_openmp_routines' clause in the 'pragma omp assume' directive.
This represents the 'no_parallelism' clause in the 'pragma omp assume' directive.
This represents 'nocontext' clause in the 'pragma omp ...' directive.
This represents 'nogroup' clause in the 'pragma omp ...' directive.
This represents clause 'nontemporal' in the 'pragma omp ...' directives.
static OMPNontemporalClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This represents 'novariants' clause in the 'pragma omp ...' directive.
This represents 'nowait' clause in the 'pragma omp ...' directive.
This represents 'num_tasks' clause in the 'pragma omp ...' directive.
static OMPNumTeamsClause * Create(const ASTContext &C, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents 'num_threads' clause in the 'pragma omp ...' directive.
This represents 'order' clause in the 'pragma omp ...' directive.
SourceLocation getKindKwLoc() const
Returns location of clause kind.
OpenMPOrderClauseKind getKind() const
Returns kind of the clause.
This represents 'ordered' clause in the 'pragma omp ...' directive.
Expr * getNumForLoops() const
Return the number of associated for-loops.
static OMPOrderedClause * Create(const ASTContext &C, Expr *Num, unsigned NumLoops, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'ordered' clause.
Representation of the 'partial' clause of the 'pragma omp unroll' directive.
static OMPPartialClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, Expr *Factor)
Build an AST node for a 'partial' clause.
Expr * getFactor() const
Returns the argument of the clause or nullptr if not set.
This class represents the 'permutation' clause in the 'pragma omp interchange' directive.
unsigned getNumLoops() const
Returns the number of list items.
MutableArrayRef< Expr * > getArgsRefs()
Returns the permutation index expressions.
static OMPPermutationClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Args)
Build a 'permutation' clause AST node.
This represents 'priority' clause in the 'pragma omp ...' directive.
static OMPPrivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PrivateVL)
Creates clause with a list of variables VL.
This represents 'proc_bind' clause in the 'pragma omp ...' directive.
This represents 'read' clause in the 'pragma omp atomic' directive.
static OMPReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, OpenMPReductionClauseModifier Modifier, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, ArrayRef< Expr * > CopyOps, ArrayRef< Expr * > CopyArrayTemps, ArrayRef< Expr * > CopyArrayElems, Stmt *PreInit, Expr *PostUpdate, ArrayRef< bool > IsPrivateVarReduction, OpenMPOriginalSharingModifier OriginalSharingModifier)
Creates clause with a list of variables VL.
This represents 'relaxed' clause in the 'pragma omp atomic' directives.
This represents 'release' clause in the 'pragma omp atomic|flush' directives.
This represents 'pragma omp requires...' directive.
clauselist_range clauselists()
static OMPRequiresDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< OMPClause * > CL)
Create requires node.
This represents 'reverse_offload' clause in the 'pragma omp requires' directive.
This represents 'simd' clause in the 'pragma omp ...' directive.
This represents 'safelen' clause in the 'pragma omp ...' directive.
Expr * getSafelen() const
Return safe iteration space distance.
This represents 'schedule' clause in the 'pragma omp ...' directive.
SourceLocation getFirstScheduleModifierLoc() const
Get the first modifier location.
OpenMPScheduleClauseModifier getSecondScheduleModifier() const
Get the second modifier of the clause.
OpenMPScheduleClauseModifier getFirstScheduleModifier() const
Get the first modifier of the clause.
SourceLocation getSecondScheduleModifierLoc() const
Get the second modifier location.
This represents 'self_maps' clause in the 'pragma omp requires' directive.
This represents 'seq_cst' clause in the 'pragma omp atomic|flush' directives.
This represents the 'severity' clause in the 'pragma omp error' and the 'pragma omp parallel' directi...
OpenMPSeverityClauseKind getSeverityKind() const
Returns kind of the clause.
SourceLocation getSeverityKindKwLoc() const
Returns location of clause kind.
static OMPSharedClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This represents 'simdlen' clause in the 'pragma omp ...' directive.
Expr * getSimdlen() const
Return safe iteration space distance.
static OMPSizesClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Sizes)
Build a 'sizes' AST node.
static OMPTaskReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
static OMPThreadLimitClause * Create(const ASTContext &C, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents 'pragma omp threadprivate ...' directive.
static OMPThreadPrivateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL)
This represents 'threads' clause in the 'pragma omp ...' directive.
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 * ActOnOpenMPLoopRangeClause(Expr *First, Expr *Count, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation FirstLoc, SourceLocation CountLoc, SourceLocation EndLoc)
Called on well-form 'looprange' clause after parsing its arguments.
OMPClause * ActOnOpenMPPermutationClause(ArrayRef< Expr * > PermExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'permutation' clause after parsing its arguments.
OMPClause * ActOnOpenMPNontemporalClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nontemporal' clause.
OMPClause * 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.
StmtResult ActOnOpenMPFuseDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp fuse' after parsing of its clauses and the associated statement.
OMPClause * ActOnOpenMPNumTeamsClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_teams' clause.
StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel sections' after parsing of the associated statement.
OMPClause * ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'update' clause.
OMPClause * ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data, Expr *DepModifier, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depend' clause.
OMPClause * ActOnOpenMPDoacrossClause(OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'doacross' clause.
VarDecl * ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
StmtResult ActOnOpenMPTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute parallel for' after parsing of the associated sta...
StmtResult ActOnOpenMPMasterDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp master' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskgroupDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskgroup'.
VarDecl * isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo=false, unsigned StopAt=0)
Check if the specified variable is used in one of the private clauses (private, firstprivate,...
StmtResult ActOnOpenMPMasterTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp master taskloop simd' after parsing of the associated statement.
ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id, OpenMPDirectiveKind Kind)
Called on correct id-expression from the 'pragma omp threadprivate'.
void ActOnOpenMPEndAssumesDirective()
Called on well-formed 'pragma omp end assumes'.
OMPClause * ActOnOpenMPNogroupClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nogroup' clause.
OMPClause * ActOnOpenMPGrainsizeClause(OpenMPGrainsizeClauseModifier Modifier, Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'grainsize' clause.
ExprResult ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc, Expr *LowerBound, SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length, Expr *Stride, SourceLocation RBLoc)
bool isOpenMPRebuildMemberExpr(ValueDecl *D)
The member expression(this->fd) needs to be rebuilt in the template instantiation to generate private...
void ActOnOpenMPDeviceNum(Expr *DeviceNumExpr)
Called on device_num selector in context selectors.
QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare reduction' construct.
StmtResult ActOnOpenMPMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp masked taskloop simd' after parsing of the associated statement.
bool isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, unsigned OpenMPCaptureLevel) const
Return true if the provided declaration VD should be captured by reference.
StmtResult ActOnOpenMPParallelGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel loop' after parsing of the associated statement.
DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList, ArrayRef< OMPClause * > Clauses, DeclContext *Owner=nullptr)
Called on well-formed 'pragma omp allocate'.
OMPClause * ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind)
Return the number of captured regions created for an OpenMP directive.
bool isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified variable is captured by 'target' directive.
StmtResult ActOnOpenMPParallelMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop simd' after parsing of the associated sta...
OMPClause * ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'dynamic_allocators' clause.
StmtResult ActOnOpenMPScopeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scope' after parsing of the associated statement.
void ActOnOpenMPIteratorVarDecl(VarDecl *VD)
bool isInOpenMPDeclareVariantScope() const
Can we exit an OpenMP declare variant scope at the moment.
StmtResult ActOnOpenMPDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute parallel for simd' after parsing of the associated stat...
StmtResult ActOnOpenMPBarrierDirective(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp barrier'.
TypeResult ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D)
Check variable declaration in 'omp declare mapper' construct.
ExprResult ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc, SourceLocation LLoc, SourceLocation RLoc, ArrayRef< OMPIteratorData > Data)
OMPClause * ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< UsesAllocatorsData > Data)
Called on well-formed 'uses_allocators' clause.
StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef< OMPClause * > Clauses)
End of OpenMP region.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveStart(Scope *S, DeclContext *DC, DeclarationName Name, ArrayRef< std::pair< QualType, SourceLocation > > ReductionTypes, AccessSpecifier AS, Decl *PrevDeclInScope=nullptr)
Called on start of 'pragma omp declare reduction'.
OMPClause * ActOnOpenMPAcqRelClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'acq_rel' clause.
OMPClause * ActOnOpenMPAllocatorClause(Expr *Allocator, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocator' clause.
ExprResult VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind, bool StrictlyPositive=true, bool SuppressExprDiags=false)
DeclGroupPtrTy ActOnOpenMPGroupPrivateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList)
Called on well-formed 'pragma omp groupprivate'.
bool isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const
OMPClause * ActOnOpenMPInclusiveClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'inclusive' clause.
SemaDiagnosticBuilder diagIfOpenMPHostCode(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as host cod...
SemaDiagnosticBuilder diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as device c...
StmtResult ActOnOpenMPSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp sections' after parsing of the associated statement.
void ActOnOpenMPEndDeclareVariant()
Handle a omp end declare variant.
OMPClause * ActOnOpenMPTaskReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions={})
Called on well-formed 'task_reduction' clause.
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
StmtClass getStmtClass() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical, bool ProfileLambdaExpr=false) const
Produce a unique representation of the given statement.
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
SourceLocation getBeginLoc() const LLVM_READONLY
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
bool isTLSSupported() const
Whether the target supports thread-local storage.
Represents a declaration of a type.
SourceLocation getBeginLoc() const
Get the begin source location.
A container of type source information.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
QualType getType() const
Return the type wrapped by this type source info.
The base class of the type hierarchy.
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantArrayType() const
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool hasIntegerRepresentation() const
Determine whether this type has an integer representation of some sort, e.g., it is an integer type o...
bool isArithmeticType() const
bool isPointerType() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isEnumeralType() const
bool isScalarType() const
bool isVariableArrayType() const
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
bool isAnyCharacterType() const
Determine whether this type is any of the built-in character types.
bool isNonOverloadPlaceholderType() const
Test for a placeholder type other than Overload; see BuiltinType::isNonOverloadPlaceholderType.
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
RecordDecl * castAsRecordDecl() const
bool isAnyComplexType() const
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
bool isFunctionProtoType() const
bool isOverloadableType() const
Determines whether this is a type for which one can define an overloaded operator.
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
const T * getAsAdjusted() const
Member-template getAsAdjusted<specific type>.
bool isFunctionType() const
bool isStructureOrClassType() const
bool isRealFloatingType() const
Floating point categories.
bool isFloatingType() const
bool isAnyPointerType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
bool isFunctionNoProtoType() const
Simple class containing the result of Sema::CorrectTypo.
NamedDecl * getCorrectionDecl() const
Gets the pointer to the declaration of the typo correction.
Expr * getSubExpr() const
static UnresolvedLookupExpr * Create(const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End, bool KnownDependent, bool KnownInstantiationDependent)
void append(iterator I, iterator E)
void addDecl(NamedDecl *D)
A set of unresolved declarations.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
void setType(QualType newType)
VarDecl * getPotentiallyDecomposedVarDecl()
const Expr * getExprStmt() const
Represents a variable declaration or definition.
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
bool isFunctionOrMethodVarDecl() const
Similar to isLocalVarDecl, but excludes variables declared in blocks.
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
TLSKind getTLSKind() const
void setInitStyle(InitializationStyle Style)
InitializationStyle getInitStyle() const
The style of initialization for this declaration.
DefinitionKind isThisDeclarationADefinition(ASTContext &) const
Check whether this declaration is a definition.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
@ CInit
C-style initialization with assignment.
@ CallInit
Call-style initialization (C++98)
bool isStaticDataMember() const
Determines whether this is a static data member.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
bool isFileVarDecl() const
Returns true for file scoped variable declaration.
const Expr * getInit() const
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
@ TLS_None
Not a TLS variable.
@ DeclarationOnly
This declaration is only a declaration.
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
bool isDirectInit() const
Whether the initializer is a direct-initializer (list or call).
StorageDuration getStorageDuration() const
Get the storage duration of this variable, per C++ [basic.stc].
StorageClass getStorageClass() const
Returns the storage class as written in the source.
bool isUsableInConstantExpressions(const ASTContext &C) const
Determine whether this variable's value can be used in a constant expression, according to the releva...
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Retains information about a captured region.
unsigned short OpenMPLevel
unsigned short OpenMPCaptureLevel
Retains information about a function, method, or block that is currently being parsed.
SmallVector< CompoundScopeInfo, 4 > CompoundScopes
The stack of currently active compound statement scopes in the function.
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
Defines the clang::TargetInfo interface.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
bool LE(InterpState &S, CodePtr OpPC)
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
The JSON file list parser is used to communicate input to InstallAPI.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
OpenMPOriginalSharingModifier
OpenMP 6.0 original sharing modifiers.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ OO_None
Not an overloaded operator.
@ NUM_OVERLOADED_OPERATORS
bool isOpenMPNestingTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a teams directive in the outermost n...
bool isa(CodeGen::Address addr)
bool checkFailClauseParameter(OpenMPClauseKind FailClauseParameter)
Checks if the parameter to the fail clause in "#pragma atomic compare fail" is restricted only to mem...
MutableArrayRef< TemplateParameterList * > MultiTemplateParamsArg
bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target data offload directive.
OpenMPDefaultClauseVariableCategory
OpenMP variable-category for 'default' clause.
bool isOpenMPLoopTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive.
OpenMPDefaultmapClauseModifier
OpenMP modifiers for 'defaultmap' clause.
@ OMPC_DEFAULTMAP_MODIFIER_last
@ OMPC_DEFAULTMAP_MODIFIER_unknown
OpenMPOrderClauseModifier
OpenMP modifiers for 'order' clause.
@ OMPC_ORDER_MODIFIER_unknown
@ OMPC_ORDER_MODIFIER_last
@ Comparison
A comparison.
ExprObjectKind
A further classification of the kind of object referenced by an l-value or x-value.
@ OK_Ordinary
An ordinary object is located at an address in memory.
OpenMPAtClauseKind
OpenMP attributes for 'at' clause.
Expr * AssertSuccess(ExprResult R)
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
@ LCK_This
Capturing the *this object by reference.
OpenMPReductionClauseModifier
OpenMP modifiers for 'reduction' clause.
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
@ OMPC_SCHEDULE_MODIFIER_last
@ OMPC_SCHEDULE_MODIFIER_unknown
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
SmallVector< Attr *, 4 > AttrVec
AttrVec - A vector of Attr, which is how they are stored on the AST.
ActionResult< Decl * > DeclResult
const char * getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
bool isOpenMPPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of private clauses like 'private', 'firstprivate',...
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
@ OMPC_DIST_SCHEDULE_unknown
static constexpr StringRef getOpenMPVariantManglingSeparatorStr()
OpenMP variants are mangled early based on their OpenMP context selector.
OpenMPDoacrossClauseModifier
OpenMP dependence types for 'doacross' clause.
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
static constexpr unsigned NumberOfOMPMapClauseModifiers
Number of allowed map-type-modifiers.
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
MutableArrayRef< Expr * > MultiExprArg
@ SD_Static
Static storage duration.
@ Parameter
The parameter type of a method or function.
@ Result
The result type of a method or function.
ActionResult< ParsedType > TypeResult
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
bool isOpenMPGenericLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive constitutes a 'loop' directive in the outermost nest.
OpenMPBindClauseKind
OpenMP bindings for the 'bind' clause.
const FunctionProtoType * T
OpenMPLastprivateModifier
OpenMP 'lastprivate' clause modifier.
@ OMPC_LASTPRIVATE_unknown
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
bool isOpenMPCanonicalLoopSequenceTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive that applies to a canonical loop...
OpenMPGrainsizeClauseModifier
bool IsXLHSInRHSPart
True if UE has the first form and false if the second.
bool IsPostfixUpdate
True if original value of 'x' must be stored in 'v', not an updated one.
bool isOpenMPCanonicalLoopNestTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive that applies to a canonical loop...
OpenMPNumTasksClauseModifier
bool isOpenMPOrderConcurrentNestableDirective(OpenMPDirectiveKind DKind, const LangOptions &LangOpts)
Checks if the specified directive is an order concurrent nestable directive that can be nested within...
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
bool isOpenMPCapturingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive can capture variables.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
bool isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of the composite or combined directives that need loop ...
static constexpr unsigned NumberOfOMPMotionModifiers
Number of allowed motion-modifiers.
OpenMPMotionModifierKind
OpenMP modifier kind for 'to' or 'from' clause.
@ OMPC_MOTION_MODIFIER_unknown
OpenMPDefaultmapClauseKind
OpenMP attributes for 'defaultmap' clause.
@ OMPC_DEFAULTMAP_unknown
OpenMPAllocateClauseModifier
OpenMP modifiers for 'allocate' clause.
bool isOpenMPThreadPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of threadprivate clauses like 'threadprivate',...
OpenMPLinearClauseKind
OpenMP attributes for 'linear' clause.
bool isOpenMPExecutableDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "executable".
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
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.