39#include "llvm/ADT/IndexedMap.h"
40#include "llvm/ADT/PointerEmbeddedInt.h"
41#include "llvm/ADT/STLExtras.h"
42#include "llvm/ADT/Sequence.h"
43#include "llvm/ADT/SetVector.h"
44#include "llvm/ADT/SmallSet.h"
45#include "llvm/ADT/StringExtras.h"
46#include "llvm/Frontend/OpenMP/OMPAssume.h"
47#include "llvm/Frontend/OpenMP/OMPConstants.h"
48#include "llvm/IR/Assumptions.h"
52using namespace llvm::omp;
65enum DefaultDataSharingAttributes {
70 DSA_firstprivate = 1 << 3,
80 unsigned Modifier = 0;
81 const Expr *RefExpr =
nullptr;
84 bool AppliedToPointee =
false;
85 DSAVarData() =
default;
89 bool AppliedToPointee)
90 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
91 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
92 AppliedToPointee(AppliedToPointee) {}
94 using OperatorOffsetTy =
96 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
98 enum class UsesAllocatorsDeclKind {
102 UserDefinedAllocator,
110 unsigned Modifier = 0;
113 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
117 bool AppliedToPointee =
false;
119 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
120 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
121 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
122 using LoopControlVariablesMapTy =
123 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
126 struct MappedExprComponentTy {
130 using MappedExprComponentsTy =
131 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
132 using CriticalsWithHintsTy =
133 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
134 struct ReductionData {
135 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
137 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
138 ReductionData() =
default;
145 ReductionOp = RefExpr;
148 using DeclReductionMapTy =
149 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
150 struct DefaultmapInfo {
154 DefaultmapInfo() =
default;
156 : ImplicitBehavior(M), SLoc(
Loc) {}
159 struct SharingMapTy {
160 DeclSAMapTy SharingMap;
161 DeclReductionMapTy ReductionMap;
162 UsedRefMapTy AlignedMap;
163 UsedRefMapTy NontemporalMap;
164 MappedExprComponentsTy MappedExprComponents;
165 LoopControlVariablesMapTy LCVMap;
166 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
171 Scope *CurScope =
nullptr;
177 DoacrossClauseMapTy DoacrossDepends;
181 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
182 bool RegionHasOrderConcurrent =
false;
183 unsigned AssociatedLoops = 1;
184 bool HasMutipleLoops =
false;
185 const Decl *PossiblyLoopCounter =
nullptr;
186 bool NowaitRegion =
false;
187 bool UntiedRegion =
false;
188 bool CancelRegion =
false;
189 bool LoopStart =
false;
190 bool BodyComplete =
false;
195 Expr *TaskgroupReductionRef =
nullptr;
196 llvm::DenseSet<QualType> MappedClassesQualTypes;
198 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
203 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
204 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
208 struct ImplicitDefaultFDInfoTy {
212 size_t StackLevel = 0;
215 ImplicitDefaultFDInfoTy(
const FieldDecl *FD,
size_t StackLevel,
217 : FD(FD), StackLevel(StackLevel), VD(VD) {}
221 ImplicitDefaultFirstprivateFDs;
222 Expr *DeclareMapperVar =
nullptr;
226 :
Directive(DKind), DirectiveName(Name), CurScope(CurScope),
228 SharingMapTy() =
default;
234 DeclSAMapTy Threadprivates;
241 bool ForceCapturing =
false;
244 bool ForceCaptureByReferenceInTargetExecutable =
false;
245 CriticalsWithHintsTy Criticals;
246 unsigned IgnoredStackElements = 0;
250 using const_iterator = StackTy::const_reverse_iterator;
251 const_iterator begin()
const {
252 return Stack.empty() ? const_iterator()
253 : Stack.back().first.rbegin() + IgnoredStackElements;
255 const_iterator end()
const {
256 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
258 using iterator = StackTy::reverse_iterator;
260 return Stack.empty() ? iterator()
261 : Stack.back().first.rbegin() + IgnoredStackElements;
264 return Stack.empty() ? iterator() : Stack.back().first.rend();
269 bool isStackEmpty()
const {
270 return Stack.empty() ||
271 Stack.back().second != CurrentNonCapturingFunctionScope ||
272 Stack.back().first.size() <= IgnoredStackElements;
274 size_t getStackSize()
const {
275 return isStackEmpty() ? 0
276 : Stack.back().first.size() - IgnoredStackElements;
279 SharingMapTy *getTopOfStackOrNull() {
280 size_t Size = getStackSize();
283 return &Stack.back().first[
Size - 1];
285 const SharingMapTy *getTopOfStackOrNull()
const {
286 return const_cast<DSAStackTy &
>(*this).getTopOfStackOrNull();
288 SharingMapTy &getTopOfStack() {
289 assert(!isStackEmpty() &&
"no current directive");
290 return *getTopOfStackOrNull();
292 const SharingMapTy &getTopOfStack()
const {
293 return const_cast<DSAStackTy &
>(*this).getTopOfStack();
296 SharingMapTy *getSecondOnStackOrNull() {
297 size_t Size = getStackSize();
300 return &Stack.back().first[
Size - 2];
302 const SharingMapTy *getSecondOnStackOrNull()
const {
303 return const_cast<DSAStackTy &
>(*this).getSecondOnStackOrNull();
312 SharingMapTy &getStackElemAtLevel(
unsigned Level) {
313 assert(Level < getStackSize() &&
"no such stack element");
314 return Stack.back().first[
Level];
316 const SharingMapTy &getStackElemAtLevel(
unsigned Level)
const {
317 return const_cast<DSAStackTy &
>(*this).getStackElemAtLevel(Level);
323 bool isOpenMPLocal(
VarDecl *
D, const_iterator
Iter)
const;
336 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
345 explicit DSAStackTy(
Sema &S) : SemaRef(S) {}
348 void setOMPAllocatorHandleT(
QualType Ty) { OMPAllocatorHandleT = Ty; }
350 QualType getOMPAllocatorHandleT()
const {
return OMPAllocatorHandleT; }
352 void setOMPAlloctraitT(
QualType Ty) { OMPAlloctraitT = Ty; }
354 QualType getOMPAlloctraitT()
const {
return OMPAlloctraitT; }
356 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
358 OMPPredefinedAllocators[AllocatorKind] = Allocator;
361 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind)
const {
362 return OMPPredefinedAllocators[AllocatorKind];
365 void setOMPDependT(
QualType Ty) { OMPDependT = Ty; }
367 QualType getOMPDependT()
const {
return OMPDependT; }
370 void setOMPEventHandleT(
QualType Ty) { OMPEventHandleT = Ty; }
372 QualType getOMPEventHandleT()
const {
return OMPEventHandleT; }
374 bool isClauseParsingMode()
const {
return ClauseKindMode != OMPC_unknown; }
376 assert(isClauseParsingMode() &&
"Must be in clause parsing mode.");
377 return ClauseKindMode;
381 bool isBodyComplete()
const {
382 const SharingMapTy *Top = getTopOfStackOrNull();
383 return Top && Top->BodyComplete;
385 void setBodyComplete() { getTopOfStack().BodyComplete =
true; }
387 bool isForceVarCapturing()
const {
return ForceCapturing; }
388 void setForceVarCapturing(
bool V) { ForceCapturing =
V; }
390 void setForceCaptureByReferenceInTargetExecutable(
bool V) {
391 ForceCaptureByReferenceInTargetExecutable =
V;
393 bool isForceCaptureByReferenceInTargetExecutable()
const {
394 return ForceCaptureByReferenceInTargetExecutable;
399 assert(!IgnoredStackElements &&
400 "cannot change stack while ignoring elements");
402 Stack.back().second != CurrentNonCapturingFunctionScope)
403 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
404 Stack.back().first.emplace_back(DKind, DirName, CurScope,
Loc);
405 Stack.back().first.back().DefaultAttrLoc =
Loc;
409 assert(!IgnoredStackElements &&
410 "cannot change stack while ignoring elements");
411 assert(!Stack.back().first.empty() &&
412 "Data-sharing attributes stack is empty!");
413 Stack.back().first.pop_back();
418 class ParentDirectiveScope {
423 ParentDirectiveScope(DSAStackTy &Self,
bool Activate)
424 : Self(Self), Active(
false) {
428 ~ParentDirectiveScope() { disable(); }
431 --Self.IgnoredStackElements;
437 ++Self.IgnoredStackElements;
446 "Expected loop-based directive.");
447 getTopOfStack().LoopStart =
true;
452 "Expected loop-based directive.");
453 getTopOfStack().LoopStart =
false;
456 bool isLoopStarted()
const {
458 "Expected loop-based directive.");
459 return !getTopOfStack().LoopStart;
462 void resetPossibleLoopCounter(
const Decl *
D =
nullptr) {
466 const Decl *getPossiblyLoopCounter()
const {
467 return getTopOfStack().PossiblyLoopCounter;
470 void pushFunction() {
471 assert(!IgnoredStackElements &&
472 "cannot change stack while ignoring elements");
474 assert(!isa<CapturingScopeInfo>(CurFnScope));
475 CurrentNonCapturingFunctionScope = CurFnScope;
479 assert(!IgnoredStackElements &&
480 "cannot change stack while ignoring elements");
481 if (!Stack.empty() && Stack.back().second == OldFSI) {
482 assert(Stack.back().first.empty());
485 CurrentNonCapturingFunctionScope =
nullptr;
487 if (!isa<CapturingScopeInfo>(FSI)) {
488 CurrentNonCapturingFunctionScope = FSI;
495 Criticals.try_emplace(
D->getDirectiveName().getAsString(),
D, Hint);
497 const std::pair<const OMPCriticalDirective *, llvm::APSInt>
499 auto I = Criticals.find(Name.getAsString());
500 if (I != Criticals.end())
502 return std::make_pair(
nullptr, llvm::APSInt());
519 const LCDeclInfo isLoopControlVariable(
const ValueDecl *
D)
const;
524 const LCDeclInfo isParentLoopControlVariable(
const ValueDecl *
D)
const;
529 const LCDeclInfo isLoopControlVariable(
const ValueDecl *
D,
530 unsigned Level)
const;
533 const ValueDecl *getParentLoopControlVariable(
unsigned I)
const;
536 void markDeclAsUsedInScanDirective(
ValueDecl *
D) {
537 if (SharingMapTy *Stack = getSecondOnStackOrNull())
538 Stack->UsedInScanDirective.insert(
D);
542 bool isUsedInScanDirective(
ValueDecl *
D)
const {
543 if (
const SharingMapTy *Stack = getTopOfStackOrNull())
544 return Stack->UsedInScanDirective.contains(
D);
550 DeclRefExpr *PrivateCopy =
nullptr,
unsigned Modifier = 0,
551 bool AppliedToPointee =
false);
560 const Expr *ReductionRef);
566 Expr *&TaskgroupDescriptor)
const;
571 const Expr *&ReductionRef,
572 Expr *&TaskgroupDescriptor)
const;
575 Expr *getTaskgroupReductionRef()
const {
576 assert((getTopOfStack().
Directive == OMPD_taskgroup ||
580 "taskgroup reference expression requested for non taskgroup or "
581 "parallel/worksharing directive.");
582 return getTopOfStack().TaskgroupReductionRef;
586 bool isTaskgroupReductionRef(
const ValueDecl *VD,
unsigned Level)
const {
587 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
588 cast<DeclRefExpr>(getStackElemAtLevel(Level).TaskgroupReductionRef)
594 const DSAVarData getTopDSA(
ValueDecl *
D,
bool FromParent);
596 const DSAVarData getImplicitDSA(
ValueDecl *
D,
bool FromParent)
const;
598 const DSAVarData getImplicitDSA(
ValueDecl *
D,
unsigned Level)
const;
605 DefaultDataSharingAttributes)>
608 bool FromParent)
const;
616 bool FromParent)
const;
623 unsigned Level,
bool NotLastprivate =
false)
const;
627 bool hasExplicitDirective(
629 unsigned Level)
const;
633 const llvm::function_ref<
bool(
636 bool FromParent)
const;
640 const SharingMapTy *Top = getTopOfStackOrNull();
641 return Top ? Top->Directive : OMPD_unknown;
645 assert(!isStackEmpty() &&
"No directive at specified level.");
646 return getStackElemAtLevel(Level).Directive;
650 unsigned OpenMPCaptureLevel)
const {
653 return CaptureRegions[OpenMPCaptureLevel];
657 const SharingMapTy *
Parent = getSecondOnStackOrNull();
662 void addRequiresDecl(
OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
665 template <
typename ClauseType>
bool hasRequiresDeclWithClause()
const {
667 return llvm::any_of(
D->clauselists(), [](
const OMPClause *
C) {
668 return isa<ClauseType>(C);
676 bool IsDuplicate =
false;
679 for (
const OMPClause *CPrev :
D->clauselists()) {
680 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
681 SemaRef.
Diag(CNew->getBeginLoc(),
682 diag::err_omp_requires_clause_redeclaration)
683 << getOpenMPClauseName(CNew->getClauseKind());
684 SemaRef.
Diag(CPrev->getBeginLoc(),
685 diag::note_omp_requires_previous_clause)
686 << getOpenMPClauseName(CPrev->getClauseKind());
697 TargetLocations.push_back(LocStart);
703 AtomicLocation =
Loc;
708 SourceLocation getAtomicDirectiveLoc()
const {
return AtomicLocation; }
712 return TargetLocations;
717 getTopOfStack().DefaultAttr = DSA_none;
718 getTopOfStack().DefaultAttrLoc =
Loc;
722 getTopOfStack().DefaultAttr = DSA_shared;
723 getTopOfStack().DefaultAttrLoc =
Loc;
727 getTopOfStack().DefaultAttr = DSA_private;
728 getTopOfStack().DefaultAttrLoc =
Loc;
732 getTopOfStack().DefaultAttr = DSA_firstprivate;
733 getTopOfStack().DefaultAttrLoc =
Loc;
738 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[
Kind];
739 DMI.ImplicitBehavior = M;
745 return getTopOfStack()
746 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
749 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
752 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
754 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
759 return ConstructTraits;
764 ConstructTraits.append(Traits.begin(), Traits.end());
766 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
767 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
768 assert(Top == Trait &&
"Something left a trait on the stack!");
774 DefaultDataSharingAttributes getDefaultDSA(
unsigned Level)
const {
775 return getStackSize() <=
Level ? DSA_unspecified
776 : getStackElemAtLevel(Level).DefaultAttr;
778 DefaultDataSharingAttributes getDefaultDSA()
const {
779 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
782 return isStackEmpty() ?
SourceLocation() : getTopOfStack().DefaultAttrLoc;
786 return isStackEmpty()
788 : getTopOfStack().DefaultmapMap[
Kind].ImplicitBehavior;
791 getDefaultmapModifierAtLevel(
unsigned Level,
793 return getStackElemAtLevel(Level).DefaultmapMap[
Kind].ImplicitBehavior;
795 bool isDefaultmapCapturedByRef(
unsigned Level,
798 getDefaultmapModifierAtLevel(Level, Kind);
799 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
800 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
801 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
802 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
803 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom) ||
804 (M == OMPC_DEFAULTMAP_MODIFIER_present);
811 case OMPC_DEFAULTMAP_scalar:
812 case OMPC_DEFAULTMAP_pointer:
814 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
815 (M == OMPC_DEFAULTMAP_MODIFIER_default);
816 case OMPC_DEFAULTMAP_aggregate:
817 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
821 llvm_unreachable(
"Unexpected OpenMPDefaultmapClauseKind enum");
823 bool mustBeFirstprivateAtLevel(
unsigned Level,
826 getDefaultmapModifierAtLevel(Level, Kind);
827 return mustBeFirstprivateBase(M, Kind);
831 return mustBeFirstprivateBase(M, Kind);
836 const DSAVarData DVar = getTopDSA(
D,
false);
841 void setOrderedRegion(
bool IsOrdered,
const Expr *Param,
844 getTopOfStack().OrderedRegion.emplace(Param, Clause);
846 getTopOfStack().OrderedRegion.reset();
850 bool isOrderedRegion()
const {
851 if (
const SharingMapTy *Top = getTopOfStackOrNull())
852 return Top->OrderedRegion.has_value();
856 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam()
const {
857 if (
const SharingMapTy *Top = getTopOfStackOrNull())
858 if (Top->OrderedRegion)
859 return *Top->OrderedRegion;
860 return std::make_pair(
nullptr,
nullptr);
864 bool isParentOrderedRegion()
const {
865 if (
const SharingMapTy *
Parent = getSecondOnStackOrNull())
866 return Parent->OrderedRegion.has_value();
870 std::pair<const Expr *, OMPOrderedClause *>
871 getParentOrderedRegionParam()
const {
872 if (
const SharingMapTy *
Parent = getSecondOnStackOrNull())
873 if (
Parent->OrderedRegion)
874 return *
Parent->OrderedRegion;
875 return std::make_pair(
nullptr,
nullptr);
878 void setRegionHasOrderConcurrent(
bool HasOrderConcurrent) {
879 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
883 bool isParentOrderConcurrent()
const {
884 if (
const SharingMapTy *
Parent = getSecondOnStackOrNull())
885 return Parent->RegionHasOrderConcurrent;
889 void setNowaitRegion(
bool IsNowait =
true) {
890 getTopOfStack().NowaitRegion = IsNowait;
894 bool isParentNowaitRegion()
const {
895 if (
const SharingMapTy *
Parent = getSecondOnStackOrNull())
896 return Parent->NowaitRegion;
900 void setUntiedRegion(
bool IsUntied =
true) {
901 getTopOfStack().UntiedRegion = IsUntied;
904 bool isUntiedRegion()
const {
905 const SharingMapTy *Top = getTopOfStackOrNull();
906 return Top ? Top->UntiedRegion :
false;
909 void setParentCancelRegion(
bool Cancel =
true) {
910 if (SharingMapTy *
Parent = getSecondOnStackOrNull())
911 Parent->CancelRegion |= Cancel;
914 bool isCancelRegion()
const {
915 const SharingMapTy *Top = getTopOfStackOrNull();
916 return Top ? Top->CancelRegion :
false;
921 if (SharingMapTy *
Parent = getSecondOnStackOrNull())
925 bool doesParentHasScanDirective()
const {
926 const SharingMapTy *Top = getSecondOnStackOrNull();
927 return Top ? Top->PrevScanLocation.isValid() :
false;
931 const SharingMapTy *Top = getSecondOnStackOrNull();
936 if (SharingMapTy *
Parent = getSecondOnStackOrNull())
940 bool doesParentHasOrderedDirective()
const {
941 const SharingMapTy *Top = getSecondOnStackOrNull();
942 return Top ? Top->PrevOrderedLocation.isValid() :
false;
946 const SharingMapTy *Top = getSecondOnStackOrNull();
951 void setAssociatedLoops(
unsigned Val) {
952 getTopOfStack().AssociatedLoops = Val;
954 getTopOfStack().HasMutipleLoops =
true;
957 unsigned getAssociatedLoops()
const {
958 const SharingMapTy *Top = getTopOfStackOrNull();
959 return Top ? Top->AssociatedLoops : 0;
962 bool hasMutipleLoops()
const {
963 const SharingMapTy *Top = getTopOfStackOrNull();
964 return Top ? Top->HasMutipleLoops :
false;
970 if (SharingMapTy *
Parent = getSecondOnStackOrNull())
971 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
974 bool hasInnerTeamsRegion()
const {
975 return getInnerTeamsRegionLoc().
isValid();
979 const SharingMapTy *Top = getTopOfStackOrNull();
983 Scope *getCurScope()
const {
984 const SharingMapTy *Top = getTopOfStackOrNull();
985 return Top ? Top->CurScope :
nullptr;
987 void setContext(
DeclContext *DC) { getTopOfStack().Context = DC; }
989 const SharingMapTy *Top = getTopOfStackOrNull();
995 bool checkMappableExprComponentListsForDecl(
996 const ValueDecl *VD,
bool CurrentRegionOnly,
997 const llvm::function_ref<
1009 if (CurrentRegionOnly)
1012 std::advance(SI, 1);
1014 for (; SI != SE; ++SI) {
1015 auto MI = SI->MappedExprComponents.find(VD);
1016 if (MI != SI->MappedExprComponents.end())
1018 MI->second.Components)
1019 if (Check(L, MI->second.Kind))
1027 bool checkMappableExprComponentListsForDeclAtLevel(
1029 const llvm::function_ref<
1033 if (getStackSize() <= Level)
1036 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1037 auto MI = StackElem.MappedExprComponents.find(VD);
1038 if (MI != StackElem.MappedExprComponents.end())
1040 MI->second.Components)
1041 if (Check(L, MI->second.Kind))
1048 void addMappableExpressionComponents(
1052 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1054 MEC.Components.resize(MEC.Components.size() + 1);
1055 MEC.Components.back().append(Components.begin(), Components.end());
1056 MEC.Kind = WhereFoundClauseKind;
1059 unsigned getNestingLevel()
const {
1060 assert(!isStackEmpty());
1061 return getStackSize() - 1;
1063 void addDoacrossDependClause(
OMPClause *
C,
const OperatorOffsetTy &OpsOffs) {
1064 SharingMapTy *
Parent = getSecondOnStackOrNull();
1066 Parent->DoacrossDepends.try_emplace(
C, OpsOffs);
1068 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1069 getDoacrossDependClauses()
const {
1070 const SharingMapTy &StackElem = getTopOfStack();
1072 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1073 return llvm::make_range(Ref.begin(), Ref.end());
1075 return llvm::make_range(StackElem.DoacrossDepends.end(),
1076 StackElem.DoacrossDepends.end());
1080 void addMappedClassesQualTypes(
QualType QT) {
1081 SharingMapTy &StackElem = getTopOfStack();
1082 StackElem.MappedClassesQualTypes.insert(QT);
1086 bool isClassPreviouslyMapped(
QualType QT)
const {
1087 const SharingMapTy &StackElem = getTopOfStack();
1088 return StackElem.MappedClassesQualTypes.contains(QT);
1092 void addToParentTargetRegionLinkGlobals(
DeclRefExpr *
E) {
1093 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1094 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1095 "Expected declare target link global.");
1096 for (
auto &Elem : *
this) {
1098 Elem.DeclareTargetLinkVarDecls.push_back(
E);
1108 "Expected target executable directive.");
1109 return getTopOfStack().DeclareTargetLinkVarDecls;
1113 void addInnerAllocatorExpr(
Expr *
E) {
1114 getTopOfStack().InnerUsedAllocators.push_back(
E);
1118 return getTopOfStack().InnerUsedAllocators;
1122 void addImplicitTaskFirstprivate(
unsigned Level,
Decl *
D) {
1123 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(
D);
1126 bool isImplicitTaskFirstprivate(
Decl *
D)
const {
1127 return getTopOfStack().ImplicitTaskFirstprivates.contains(
D);
1131 void addUsesAllocatorsDecl(
const Decl *
D, UsesAllocatorsDeclKind Kind) {
1132 getTopOfStack().UsesAllocatorsDecls.try_emplace(
D, Kind);
1136 std::optional<UsesAllocatorsDeclKind>
1137 isUsesAllocatorsDecl(
unsigned Level,
const Decl *
D)
const {
1138 const SharingMapTy &StackElem = getTopOfStack();
1139 auto I = StackElem.UsesAllocatorsDecls.find(
D);
1140 if (I == StackElem.UsesAllocatorsDecls.end())
1141 return std::nullopt;
1142 return I->getSecond();
1144 std::optional<UsesAllocatorsDeclKind>
1145 isUsesAllocatorsDecl(
const Decl *
D)
const {
1146 const SharingMapTy &StackElem = getTopOfStack();
1147 auto I = StackElem.UsesAllocatorsDecls.find(
D);
1148 if (I == StackElem.UsesAllocatorsDecls.end())
1149 return std::nullopt;
1150 return I->getSecond();
1153 void addDeclareMapperVarRef(
Expr *Ref) {
1154 SharingMapTy &StackElem = getTopOfStack();
1155 StackElem.DeclareMapperVar = Ref;
1157 const Expr *getDeclareMapperVarRef()
const {
1158 const SharingMapTy *Top = getTopOfStackOrNull();
1159 return Top ? Top->DeclareMapperVar :
nullptr;
1163 void addIteratorVarDecl(
VarDecl *VD) {
1164 SharingMapTy &StackElem = getTopOfStack();
1168 bool isIteratorVarDecl(
const VarDecl *VD)
const {
1169 const SharingMapTy *Top = getTopOfStackOrNull();
1177 const_iterator I = begin();
1178 const_iterator EndI = end();
1179 size_t StackLevel = getStackSize();
1180 for (; I != EndI; ++I) {
1181 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1185 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1188 for (
const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1189 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1194 bool isImplicitDefaultFirstprivateFD(
VarDecl *VD)
const {
1195 const_iterator I = begin();
1196 const_iterator EndI = end();
1197 for (; I != EndI; ++I)
1198 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1202 for (
const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1209 iterator I = begin();
1210 const_iterator EndI = end();
1211 size_t StackLevel = getStackSize();
1212 for (; I != EndI; ++I) {
1213 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1214 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1219 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1229 DKind == OMPD_unknown;
1235 if (
const auto *FE = dyn_cast<FullExpr>(
E))
1236 E = FE->getSubExpr();
1238 if (
const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(
E))
1239 E = MTE->getSubExpr();
1241 while (
const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(
E))
1242 E = Binder->getSubExpr();
1244 if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(
E))
1245 E = ICE->getSubExprAsWritten();
1254 if (
const auto *CED = dyn_cast<OMPCapturedExprDecl>(
D))
1255 if (
const auto *ME = dyn_cast<MemberExpr>(
getExprAsWritten(CED->getInit())))
1256 D = ME->getMemberDecl();
1267DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &
Iter,
1270 auto *VD = dyn_cast<VarDecl>(
D);
1271 const auto *FD = dyn_cast<FieldDecl>(
D);
1273 if (
Iter == end()) {
1280 DVar.CKind = OMPC_shared;
1287 DVar.CKind = OMPC_shared;
1291 DVar.CKind = OMPC_shared;
1302 DVar.CKind = OMPC_private;
1306 DVar.DKind =
Iter->Directive;
1309 if (
Iter->SharingMap.count(
D)) {
1310 const DSAInfo &
Data =
Iter->SharingMap.lookup(
D);
1311 DVar.RefExpr =
Data.RefExpr.getPointer();
1312 DVar.PrivateCopy =
Data.PrivateCopy;
1313 DVar.CKind =
Data.Attributes;
1314 DVar.ImplicitDSALoc =
Iter->DefaultAttrLoc;
1315 DVar.Modifier =
Data.Modifier;
1316 DVar.AppliedToPointee =
Data.AppliedToPointee;
1324 switch (
Iter->DefaultAttr) {
1326 DVar.CKind = OMPC_shared;
1327 DVar.ImplicitDSALoc =
Iter->DefaultAttrLoc;
1331 case DSA_firstprivate:
1334 DVar.CKind = OMPC_unknown;
1336 DVar.CKind = OMPC_firstprivate;
1338 DVar.ImplicitDSALoc =
Iter->DefaultAttrLoc;
1346 DVar.CKind = OMPC_unknown;
1348 DVar.CKind = OMPC_private;
1350 DVar.ImplicitDSALoc =
Iter->DefaultAttrLoc;
1352 case DSA_unspecified:
1357 DVar.ImplicitDSALoc =
Iter->DefaultAttrLoc;
1361 DVar.CKind = OMPC_shared;
1371 DSAVarData DVarTemp;
1372 const_iterator I =
Iter,
E = end();
1380 DVarTemp = getDSA(I,
D);
1381 if (DVarTemp.CKind != OMPC_shared) {
1382 DVar.RefExpr =
nullptr;
1383 DVar.CKind = OMPC_firstprivate;
1386 }
while (I !=
E && !isImplicitTaskingRegion(I->Directive));
1388 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1397 return getDSA(++
Iter,
D);
1401 const Expr *NewDE) {
1402 assert(!isStackEmpty() &&
"Data sharing attributes stack is empty");
1404 SharingMapTy &StackElem = getTopOfStack();
1405 auto [It, Inserted] = StackElem.AlignedMap.try_emplace(
D, NewDE);
1407 assert(NewDE &&
"Unexpected nullptr expr to be added into aligned map");
1410 assert(It->second &&
"Unexpected nullptr expr in the aligned map");
1415 const Expr *NewDE) {
1416 assert(!isStackEmpty() &&
"Data sharing attributes stack is empty");
1418 SharingMapTy &StackElem = getTopOfStack();
1419 auto [It, Inserted] = StackElem.NontemporalMap.try_emplace(
D, NewDE);
1421 assert(NewDE &&
"Unexpected nullptr expr to be added into aligned map");
1424 assert(It->second &&
"Unexpected nullptr expr in the aligned map");
1429 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1431 SharingMapTy &StackElem = getTopOfStack();
1432 StackElem.LCVMap.try_emplace(
1433 D, LCDeclInfo(StackElem.LCVMap.size() + 1,
Capture));
1436const DSAStackTy::LCDeclInfo
1437DSAStackTy::isLoopControlVariable(
const ValueDecl *
D)
const {
1438 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1440 const SharingMapTy &StackElem = getTopOfStack();
1441 auto It = StackElem.LCVMap.find(
D);
1442 if (It != StackElem.LCVMap.end())
1444 return {0,
nullptr};
1447const DSAStackTy::LCDeclInfo
1448DSAStackTy::isLoopControlVariable(
const ValueDecl *
D,
unsigned Level)
const {
1449 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1451 for (
unsigned I = Level + 1; I > 0; --I) {
1452 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1453 auto It = StackElem.LCVMap.find(
D);
1454 if (It != StackElem.LCVMap.end())
1457 return {0,
nullptr};
1460const DSAStackTy::LCDeclInfo
1461DSAStackTy::isParentLoopControlVariable(
const ValueDecl *
D)
const {
1462 const SharingMapTy *
Parent = getSecondOnStackOrNull();
1463 assert(
Parent &&
"Data-sharing attributes stack is empty");
1465 auto It =
Parent->LCVMap.find(
D);
1466 if (It !=
Parent->LCVMap.end())
1468 return {0,
nullptr};
1471const ValueDecl *DSAStackTy::getParentLoopControlVariable(
unsigned I)
const {
1472 const SharingMapTy *
Parent = getSecondOnStackOrNull();
1473 assert(
Parent &&
"Data-sharing attributes stack is empty");
1474 if (
Parent->LCVMap.size() < I)
1476 for (
const auto &Pair :
Parent->LCVMap)
1477 if (Pair.second.first == I)
1484 bool AppliedToPointee) {
1486 if (A == OMPC_threadprivate) {
1487 DSAInfo &
Data = Threadprivates[
D];
1488 Data.Attributes = A;
1489 Data.RefExpr.setPointer(
E);
1490 Data.PrivateCopy =
nullptr;
1491 Data.Modifier = Modifier;
1493 DSAInfo &
Data = getTopOfStack().SharingMap[
D];
1494 assert(
Data.Attributes == OMPC_unknown || (A ==
Data.Attributes) ||
1495 (A == OMPC_firstprivate &&
Data.Attributes == OMPC_lastprivate) ||
1496 (A == OMPC_lastprivate &&
Data.Attributes == OMPC_firstprivate) ||
1497 (isLoopControlVariable(
D).first && A == OMPC_private));
1498 Data.Modifier = Modifier;
1499 if (A == OMPC_lastprivate &&
Data.Attributes == OMPC_firstprivate) {
1500 Data.RefExpr.setInt(
true);
1503 const bool IsLastprivate =
1504 A == OMPC_lastprivate ||
Data.Attributes == OMPC_lastprivate;
1505 Data.Attributes = A;
1506 Data.RefExpr.setPointerAndInt(
E, IsLastprivate);
1507 Data.PrivateCopy = PrivateCopy;
1508 Data.AppliedToPointee = AppliedToPointee;
1510 DSAInfo &
Data = getTopOfStack().SharingMap[PrivateCopy->
getDecl()];
1511 Data.Modifier = Modifier;
1512 Data.Attributes = A;
1513 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1514 Data.PrivateCopy =
nullptr;
1515 Data.AppliedToPointee = AppliedToPointee;
1522 StringRef Name,
const AttrVec *Attrs =
nullptr,
1537 OMPReferencedVarAttr::CreateImplicit(SemaRef.
Context, OrigRef));
1544 bool RefersToCapture =
false) {
1555 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1557 getTopOfStack().SharingMap[
D].Attributes == OMPC_reduction &&
1558 "Additional reduction info may be specified only for reduction items.");
1559 ReductionData &ReductionData = getTopOfStack().ReductionMap[
D];
1560 assert(ReductionData.ReductionRange.isInvalid() &&
1561 (getTopOfStack().
Directive == OMPD_taskgroup ||
1565 "Additional reduction info may be specified only once for reduction "
1567 ReductionData.set(BOK, SR);
1568 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1569 if (!TaskgroupReductionRef) {
1572 TaskgroupReductionRef =
1578 const Expr *ReductionRef) {
1580 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1582 getTopOfStack().SharingMap[
D].Attributes == OMPC_reduction &&
1583 "Additional reduction info may be specified only for reduction items.");
1584 ReductionData &ReductionData = getTopOfStack().ReductionMap[
D];
1585 assert(ReductionData.ReductionRange.isInvalid() &&
1586 (getTopOfStack().
Directive == OMPD_taskgroup ||
1590 "Additional reduction info may be specified only once for reduction "
1592 ReductionData.set(ReductionRef, SR);
1593 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1594 if (!TaskgroupReductionRef) {
1597 TaskgroupReductionRef =
1602const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1604 Expr *&TaskgroupDescriptor)
const {
1606 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty.");
1607 for (const_iterator I = begin() + 1,
E = end(); I !=
E; ++I) {
1608 const DSAInfo &
Data = I->SharingMap.lookup(
D);
1609 if (
Data.Attributes != OMPC_reduction ||
1610 Data.Modifier != OMPC_REDUCTION_task)
1612 const ReductionData &ReductionData = I->ReductionMap.lookup(
D);
1613 if (!ReductionData.ReductionOp ||
1614 isa<const Expr *>(ReductionData.ReductionOp))
1615 return DSAVarData();
1616 SR = ReductionData.ReductionRange;
1617 BOK = cast<ReductionData::BOKPtrType>(ReductionData.ReductionOp);
1618 assert(I->TaskgroupReductionRef &&
"taskgroup reduction reference "
1619 "expression for the descriptor is not "
1621 TaskgroupDescriptor = I->TaskgroupReductionRef;
1622 return DSAVarData(I->Directive, OMPC_reduction,
Data.RefExpr.getPointer(),
1623 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1626 return DSAVarData();
1629const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1631 Expr *&TaskgroupDescriptor)
const {
1633 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty.");
1634 for (const_iterator I = begin() + 1,
E = end(); I !=
E; ++I) {
1635 const DSAInfo &
Data = I->SharingMap.lookup(
D);
1636 if (
Data.Attributes != OMPC_reduction ||
1637 Data.Modifier != OMPC_REDUCTION_task)
1639 const ReductionData &ReductionData = I->ReductionMap.lookup(
D);
1640 if (!ReductionData.ReductionOp ||
1641 !isa<const Expr *>(ReductionData.ReductionOp))
1642 return DSAVarData();
1643 SR = ReductionData.ReductionRange;
1644 ReductionRef = cast<const Expr *>(ReductionData.ReductionOp);
1645 assert(I->TaskgroupReductionRef &&
"taskgroup reduction reference "
1646 "expression for the descriptor is not "
1648 TaskgroupDescriptor = I->TaskgroupReductionRef;
1649 return DSAVarData(I->Directive, OMPC_reduction,
Data.RefExpr.getPointer(),
1650 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1653 return DSAVarData();
1656bool DSAStackTy::isOpenMPLocal(
VarDecl *
D, const_iterator I)
const {
1658 for (const_iterator
E = end(); I !=
E; ++I) {
1659 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1663 Scope *CurScope = getCurScope();
1664 while (CurScope && CurScope != TopScope && !CurScope->
isDeclScope(
D))
1666 return CurScope != TopScope;
1669 if (I->Context == DC)
1678 bool AcceptIfMutable =
true,
1679 bool *IsClassType =
nullptr) {
1681 Type =
Type.getNonReferenceType().getCanonicalType();
1682 bool IsConstant =
Type.isConstant(Context);
1687 if (
const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1689 RD = CTD->getTemplatedDecl();
1692 return IsConstant && !(SemaRef.
getLangOpts().CPlusPlus && RD &&
1699 bool AcceptIfMutable =
true,
1700 bool ListItemNotVar =
false) {
1704 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1705 : IsClassType ? diag::err_omp_const_not_mutable_variable
1706 : diag::err_omp_const_variable;
1707 SemaRef.
Diag(ELoc,
Diag) << getOpenMPClauseName(CKind);
1708 if (!ListItemNotVar &&
D) {
1709 const VarDecl *VD = dyn_cast<VarDecl>(
D);
1713 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1721const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(
ValueDecl *
D,
1726 auto *VD = dyn_cast<VarDecl>(
D);
1727 auto TI = Threadprivates.find(
D);
1728 if (TI != Threadprivates.end()) {
1729 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1730 DVar.CKind = OMPC_threadprivate;
1731 DVar.Modifier = TI->getSecond().Modifier;
1734 if (VD && VD->
hasAttr<OMPThreadPrivateDeclAttr>()) {
1736 SemaRef, VD,
D->getType().getNonReferenceType(),
1737 VD->
getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1738 DVar.CKind = OMPC_threadprivate;
1739 addDSA(
D, DVar.RefExpr, OMPC_threadprivate);
1746 !(VD->
hasAttr<OMPThreadPrivateDeclAttr>() &&
1752 SemaRef, VD,
D->getType().getNonReferenceType(),
D->
getLocation());
1753 DVar.CKind = OMPC_threadprivate;
1754 addDSA(
D, DVar.RefExpr, OMPC_threadprivate);
1759 !isLoopControlVariable(
D).first) {
1760 const_iterator IterTarget =
1761 std::find_if(begin(), end(), [](
const SharingMapTy &
Data) {
1764 if (IterTarget != end()) {
1765 const_iterator ParentIterTarget = IterTarget + 1;
1766 for (const_iterator
Iter = begin();
Iter != ParentIterTarget; ++
Iter) {
1767 if (isOpenMPLocal(VD,
Iter)) {
1771 DVar.CKind = OMPC_threadprivate;
1775 if (!isClauseParsingMode() || IterTarget != begin()) {
1776 auto DSAIter = IterTarget->SharingMap.find(
D);
1777 if (DSAIter != IterTarget->SharingMap.end() &&
1779 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1780 DVar.CKind = OMPC_threadprivate;
1783 const_iterator End = end();
1785 D, std::distance(ParentIterTarget, End),
1789 IterTarget->ConstructLoc);
1790 DVar.CKind = OMPC_threadprivate;
1810 const_iterator I = begin();
1811 const_iterator EndI = end();
1812 if (FromParent && I != EndI)
1815 auto It = I->SharingMap.find(
D);
1816 if (It != I->SharingMap.end()) {
1817 const DSAInfo &
Data = It->getSecond();
1818 DVar.RefExpr =
Data.RefExpr.getPointer();
1819 DVar.PrivateCopy =
Data.PrivateCopy;
1820 DVar.CKind =
Data.Attributes;
1821 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1822 DVar.DKind = I->Directive;
1823 DVar.Modifier =
Data.Modifier;
1824 DVar.AppliedToPointee =
Data.AppliedToPointee;
1829 DVar.CKind = OMPC_shared;
1836 if (SemaRef.
LangOpts.OpenMP <= 31) {
1844 DSAVarData DVarTemp = hasInnermostDSA(
1847 return C == OMPC_firstprivate ||
C == OMPC_shared;
1849 MatchesAlways, FromParent);
1850 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1853 DVar.CKind = OMPC_shared;
1860 const_iterator I = begin();
1861 const_iterator EndI = end();
1862 if (FromParent && I != EndI)
1866 auto It = I->SharingMap.find(
D);
1867 if (It != I->SharingMap.end()) {
1868 const DSAInfo &
Data = It->getSecond();
1869 DVar.RefExpr =
Data.RefExpr.getPointer();
1870 DVar.PrivateCopy =
Data.PrivateCopy;
1871 DVar.CKind =
Data.Attributes;
1872 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1873 DVar.DKind = I->Directive;
1874 DVar.Modifier =
Data.Modifier;
1875 DVar.AppliedToPointee =
Data.AppliedToPointee;
1881const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(
ValueDecl *
D,
1882 bool FromParent)
const {
1883 if (isStackEmpty()) {
1885 return getDSA(I,
D);
1888 const_iterator StartI = begin();
1889 const_iterator EndI = end();
1890 if (FromParent && StartI != EndI)
1892 return getDSA(StartI,
D);
1895const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(
ValueDecl *
D,
1896 unsigned Level)
const {
1897 if (getStackSize() <= Level)
1898 return DSAVarData();
1900 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
1901 return getDSA(StartI,
D);
1904const DSAStackTy::DSAVarData
1907 DefaultDataSharingAttributes)>
1910 bool FromParent)
const {
1914 const_iterator I = begin();
1915 const_iterator EndI = end();
1916 if (FromParent && I != EndI)
1918 for (; I != EndI; ++I) {
1919 if (!DPred(I->Directive) &&
1920 !isImplicitOrExplicitTaskingRegion(I->Directive))
1922 const_iterator NewI = I;
1923 DSAVarData DVar = getDSA(NewI,
D);
1924 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1930const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1933 bool FromParent)
const {
1937 const_iterator StartI = begin();
1938 const_iterator EndI = end();
1939 if (FromParent && StartI != EndI)
1941 if (StartI == EndI || !DPred(StartI->Directive))
1943 const_iterator NewI = StartI;
1944 DSAVarData DVar = getDSA(NewI,
D);
1945 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
1950bool DSAStackTy::hasExplicitDSA(
1953 unsigned Level,
bool NotLastprivate)
const {
1954 if (getStackSize() <= Level)
1957 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1958 auto I = StackElem.SharingMap.find(
D);
1959 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
1960 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
1961 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
1964 auto LI = StackElem.LCVMap.find(
D);
1965 if (LI != StackElem.LCVMap.end())
1966 return CPred(OMPC_private,
false);
1970bool DSAStackTy::hasExplicitDirective(
1972 unsigned Level)
const {
1973 if (getStackSize() <= Level)
1975 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1976 return DPred(StackElem.Directive);
1979bool DSAStackTy::hasDirective(
1983 bool FromParent)
const {
1985 size_t Skip = FromParent ? 2 : 1;
1986 for (const_iterator I = begin() + std::min(
Skip, getStackSize()),
E = end();
1988 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
1994void SemaOpenMP::InitDataSharingAttributesStack() {
1995 VarDataSharingAttributesStack =
new DSAStackTy(
SemaRef);
1998#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2000void SemaOpenMP::pushOpenMPFunctionRegion() {
DSAStack->pushFunction(); }
2008 "Expected OpenMP device compilation.");
2014enum class FunctionEmissionStatus {
2025 "Expected OpenMP device compilation.");
2027 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2032 Kind = SemaDiagnosticBuilder::K_Immediate;
2043 ? SemaDiagnosticBuilder::K_Deferred
2044 : SemaDiagnosticBuilder::K_Immediate;
2048 Kind = SemaDiagnosticBuilder::K_Nop;
2051 llvm_unreachable(
"CUDADiscarded unexpected in OpenMP device compilation");
2063 "Expected OpenMP host compilation.");
2065 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2070 Kind = SemaDiagnosticBuilder::K_Immediate;
2073 Kind = SemaDiagnosticBuilder::K_Deferred;
2078 Kind = SemaDiagnosticBuilder::K_Nop;
2088 if (LO.OpenMP <= 45) {
2090 return OMPC_DEFAULTMAP_scalar;
2091 return OMPC_DEFAULTMAP_aggregate;
2094 return OMPC_DEFAULTMAP_pointer;
2096 return OMPC_DEFAULTMAP_scalar;
2097 return OMPC_DEFAULTMAP_aggregate;
2101 unsigned OpenMPCaptureLevel)
const {
2102 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2105 bool IsByRef =
true;
2111 bool IsVariableUsedInMapClause =
false;
2173 bool IsVariableAssociatedWithSection =
false;
2175 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2177 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2184 if (WhereFoundClauseKind != OMPC_map &&
2185 WhereFoundClauseKind != OMPC_has_device_addr)
2188 auto EI = MapExprComponents.rbegin();
2189 auto EE = MapExprComponents.rend();
2191 assert(EI != EE &&
"Invalid map expression!");
2193 if (isa<DeclRefExpr>(EI->getAssociatedExpression()))
2194 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() ==
D;
2199 auto Last = std::prev(EE);
2201 dyn_cast<UnaryOperator>(
Last->getAssociatedExpression());
2202 if ((UO && UO->getOpcode() == UO_Deref) ||
2203 isa<ArraySubscriptExpr>(
Last->getAssociatedExpression()) ||
2204 isa<ArraySectionExpr>(
Last->getAssociatedExpression()) ||
2205 isa<MemberExpr>(EI->getAssociatedExpression()) ||
2206 isa<OMPArrayShapingExpr>(
Last->getAssociatedExpression())) {
2207 IsVariableAssociatedWithSection =
true;
2216 if (IsVariableUsedInMapClause) {
2219 IsByRef = !(Ty->
isPointerType() && IsVariableAssociatedWithSection);
2224 IsByRef = (
DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2227 DSAStack->isDefaultmapCapturedByRef(
2232 return K == OMPC_reduction && !AppliedToPointee;
2240 ((IsVariableUsedInMapClause &&
2241 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2246 return K == OMPC_firstprivate ||
2247 (K == OMPC_reduction && AppliedToPointee);
2250 DSAStack->isUsesAllocatorsDecl(Level,
D))) &&
2253 !(isa<OMPCapturedExprDecl>(
D) && !
D->
hasAttr<OMPCaptureNoInitAttr>() &&
2254 !cast<OMPCapturedExprDecl>(
D)->getInit()->isGLValue()) &&
2257 !((
DSAStack->getDefaultDSA() == DSA_firstprivate ||
2258 DSAStack->getDefaultDSA() == DSA_private) &&
2262 !
DSAStack->isLoopControlVariable(
D, Level).first);
2279unsigned SemaOpenMP::getOpenMPNestingLevel()
const {
2281 return DSAStack->getNestingLevel();
2291 !
DSAStack->isClauseParsingMode()) ||
2302 if (!dyn_cast<FieldDecl>(
D))
2304 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2307 DefaultDataSharingAttributes DefaultAttr) {
2309 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2313 if (DVarPrivate.CKind != OMPC_unknown)
2319 Expr *CaptureExpr,
bool WithInit,
2325 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2328 auto *VD = dyn_cast<VarDecl>(
D);
2337 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2347 DSAStackTy::DSAVarData DVarTop =
2349 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2354 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2361 if (!isa<CapturingScopeInfo>(FSI))
2363 if (
auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2369 assert(CSI &&
"Failed to find CapturedRegionScopeInfo");
2380 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2386 if (CheckScopeInfo) {
2387 bool OpenMPFound =
false;
2388 for (
unsigned I = StopAt + 1; I > 0; --I) {
2390 if (!isa<CapturingScopeInfo>(FSI))
2392 if (
auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2402 if (
DSAStack->getCurrentDirective() != OMPD_unknown &&
2403 (!
DSAStack->isClauseParsingMode() ||
2404 DSAStack->getParentDirective() != OMPD_unknown)) {
2405 auto &&Info =
DSAStack->isLoopControlVariable(
D);
2408 isImplicitOrExplicitTaskingRegion(
DSAStack->getCurrentDirective())) ||
2409 (VD &&
DSAStack->isForceVarCapturing()))
2410 return VD ? VD : Info.second;
2411 DSAStackTy::DSAVarData DVarTop =
2413 if (DVarTop.CKind != OMPC_unknown &&
isOpenMPPrivate(DVarTop.CKind) &&
2415 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2421 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2429 if (VD && !VD->
hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2430 ((
DSAStack->getDefaultDSA() != DSA_none &&
2431 DSAStack->getDefaultDSA() != DSA_private &&
2432 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2433 DVarTop.CKind == OMPC_shared))
2435 auto *FD = dyn_cast<FieldDecl>(
D);
2436 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2437 !DVarPrivate.PrivateCopy) {
2438 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2441 DefaultDataSharingAttributes DefaultAttr) {
2443 (DefaultAttr == DSA_firstprivate ||
2444 DefaultAttr == DSA_private);
2448 if (DVarPrivate.CKind == OMPC_unknown)
2471 VD = cast<VarDecl>(VDPrivateRefExpr->
getDecl());
2472 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2475 if (DVarPrivate.CKind != OMPC_unknown ||
2476 (VD && (
DSAStack->getDefaultDSA() == DSA_none ||
2477 DSAStack->getDefaultDSA() == DSA_private ||
2478 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2479 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2484void SemaOpenMP::adjustOpenMPTargetScopeIndex(
unsigned &FunctionScopesIndex,
2485 unsigned Level)
const {
2490 assert(
getLangOpts().OpenMP &&
"OpenMP must be enabled.");
2496 assert(
getLangOpts().OpenMP &&
"OpenMP must be enabled.");
2498 DSAStack->resetPossibleLoopCounter();
2504 unsigned CapLevel)
const {
2505 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2506 if (
DSAStack->getCurrentDirective() != OMPD_unknown &&
2507 (!
DSAStack->isClauseParsingMode() ||
2508 DSAStack->getParentDirective() != OMPD_unknown)) {
2509 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2512 DefaultDataSharingAttributes DefaultAttr) {
2514 DefaultAttr == DSA_private;
2518 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(
D) &&
2519 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(
D)) &&
2520 !
DSAStack->isLoopControlVariable(
D).first)
2521 return OMPC_private;
2524 bool IsTriviallyCopyable =
2525 D->getType().getNonReferenceType().isTriviallyCopyableType(
2528 .getNonReferenceType()
2530 ->getAsCXXRecordDecl();
2535 (IsTriviallyCopyable ||
2541 return OMPC_firstprivate;
2542 DSAStackTy::DSAVarData DVar =
DSAStack->getImplicitDSA(
D, Level);
2543 if (DVar.CKind != OMPC_shared &&
2544 !
DSAStack->isLoopControlVariable(
D, Level).first && !DVar.RefExpr) {
2545 DSAStack->addImplicitTaskFirstprivate(Level,
D);
2546 return OMPC_firstprivate;
2555 return OMPC_private;
2558 DSAStack->isLoopControlVariable(
D).first) &&
2563 return OMPC_private;
2565 if (
const auto *VD = dyn_cast<VarDecl>(
D)) {
2571 return OMPC_private;
2576 DSAStack->isUsesAllocatorsDecl(Level,
D).value_or(
2577 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2578 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2579 return OMPC_private;
2583 (
DSAStack->isClauseParsingMode() &&
2584 DSAStack->getClauseParsingMode() == OMPC_private) ||
2589 return K == OMPD_taskgroup ||
2590 ((isOpenMPParallelDirective(K) ||
2591 isOpenMPWorksharingDirective(K)) &&
2592 !isOpenMPSimdDirective(K));
2595 DSAStack->isTaskgroupReductionRef(
D, Level)))
2602 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2605 for (
unsigned I =
DSAStack->getNestingLevel() + 1; I > Level; --I) {
2606 const unsigned NewLevel = I - 1;
2610 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2618 if (
DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2628 if (
DSAStack->mustBeFirstprivateAtLevel(
2630 OMPC = OMPC_firstprivate;
2634 if (OMPC != OMPC_unknown)
2636 OMPCaptureKindAttr::CreateImplicit(getASTContext(),
unsigned(OMPC)));
2640 unsigned CaptureLevel)
const {
2641 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2646 const auto *VD = dyn_cast<VarDecl>(
D);
2650 Regions[CaptureLevel] != OMPD_task;
2654 unsigned CaptureLevel)
const {
2655 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2658 if (
const auto *VD = dyn_cast<VarDecl>(
D)) {
2662 DSAStackTy::DSAVarData TopDVar =
2664 unsigned NumLevels =
2669 return (NumLevels == CaptureLevel + 1 &&
2670 (TopDVar.CKind != OMPC_shared ||
2671 DSAStack->getDefaultDSA() == DSA_firstprivate));
2674 DSAStackTy::DSAVarData DVar =
DSAStack->getImplicitDSA(
D, Level);
2675 if (DVar.CKind != OMPC_shared)
2677 }
while (Level > 0);
2683void SemaOpenMP::DestroyDataSharingAttributesStack() {
delete DSAStack; }
2687 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2692 "Not in OpenMP declare variant scope!");
2694 OMPDeclareVariantScopes.pop_back();
2700 assert(
getLangOpts().OpenMP &&
"Expected OpenMP compilation mode.");
2701 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2705 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2708 if (!
getLangOpts().OpenMPIsTargetDevice && DevTy &&
2709 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2712 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2713 if (
getLangOpts().OpenMPIsTargetDevice && DevTy &&
2714 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2716 StringRef HostDevTy =
2718 Diag(
Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2719 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2720 diag::note_omp_marked_device_type_here)
2726 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2730 for (OMPDeclareVariantAttr *A :
2731 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2732 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2733 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2734 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2735 OMPDeclareTargetDeclAttr::getDeviceType(
2736 VariantFD->getMostRecentDecl());
2737 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2743 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2747 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2748 Diag(
Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2749 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2750 diag::note_omp_marked_device_type_here)
2768 DSAStack->setClauseParsingMode(OMPC_unknown);
2772static std::pair<ValueDecl *, bool>
2774 SourceRange &ERange,
bool AllowArraySection =
false,
2775 StringRef DiagType =
"");
2780 bool InscanFound =
false;
2787 if (
C->getClauseKind() != OMPC_reduction)
2789 auto *RC = cast<OMPReductionClause>(
C);
2790 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2792 InscanLoc = RC->getModifierLoc();
2795 if (RC->getModifier() == OMPC_REDUCTION_task) {
2805 S.
Diag(RC->getModifierLoc(),
2806 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2812 if (
C->getClauseKind() != OMPC_reduction)
2814 auto *RC = cast<OMPReductionClause>(
C);
2815 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2818 : RC->getModifierLoc(),
2819 diag::err_omp_inscan_reduction_expected);
2820 S.
Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2823 for (
Expr *Ref : RC->varlist()) {
2824 assert(Ref &&
"NULL expr in OpenMP nontemporal clause.");
2827 Expr *SimpleRefExpr = Ref;
2834 S.
Diag(Ref->getExprLoc(),
2835 diag::err_omp_reduction_not_inclusive_exclusive)
2836 << Ref->getSourceRange();
2850 const DSAStackTy::DSAVarData &DVar,
2851 bool IsLoopIterVar =
false);
2862 for (
Expr *DE : Clause->varlist()) {
2863 if (DE->isValueDependent() || DE->isTypeDependent()) {
2864 PrivateCopies.push_back(
nullptr);
2867 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2868 auto *VD = cast<VarDecl>(DRE->getDecl());
2870 const DSAStackTy::DSAVarData DVar =
2872 if (DVar.CKind != OMPC_lastprivate) {
2875 PrivateCopies.push_back(
nullptr);
2888 PrivateCopies.push_back(
nullptr);
2894 Clause->setPrivateCopies(PrivateCopies);
2900 for (
Expr *RefExpr : Clause->varlist()) {
2901 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
2904 Expr *SimpleRefExpr = RefExpr;
2908 PrivateRefs.push_back(RefExpr);
2913 const DSAStackTy::DSAVarData DVar =
2915 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2918 Clause->setPrivateRefs(PrivateRefs);
2922 for (
unsigned I = 0,
E = Clause->getNumberOfAllocators(); I <
E; ++I) {
2924 auto *DRE = dyn_cast<DeclRefExpr>(
D.Allocator->IgnoreParenImpCasts());
2928 if (!VD || !isa<VarDecl>(VD))
2930 DSAStackTy::DSAVarData DVar =
2936 Expr *MapExpr =
nullptr;
2938 DSAStack->checkMappableExprComponentListsForDecl(
2944 auto MI = MapExprComponents.rbegin();
2945 auto ME = MapExprComponents.rend();
2947 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
2948 VD->getCanonicalDecl()) {
2949 MapExpr = MI->getAssociatedExpression();
2954 Diag(
D.Allocator->getExprLoc(), diag::err_omp_allocator_used_in_clauses)
2959 Diag(MapExpr->getExprLoc(), diag::note_used_here)
2960 << MapExpr->getSourceRange();
2965 if (
const auto *
D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
2967 if (
auto *Clause = dyn_cast<OMPLastprivateClause>(
C)) {
2968 FinalizeLastprivate(Clause);
2969 }
else if (
auto *Clause = dyn_cast<OMPNontemporalClause>(
C)) {
2970 FinalizeNontemporal(Clause);
2971 }
else if (
auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(
C)) {
2972 FinalizeAllocators(Clause);
2987 Expr *NumIterations,
Sema &SemaRef,
2988 Scope *S, DSAStackTy *Stack);
2992 DSAStackTy *Stack) {
2994 "loop exprs were not built");
3001 auto *LC = dyn_cast<OMPLinearClause>(
C);
3020 explicit VarDeclFilterCCC(
Sema &S) : SemaRef(S) {}
3021 bool ValidateCandidate(
const TypoCorrection &Candidate)
override {
3023 if (
const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3031 std::unique_ptr<CorrectionCandidateCallback> clone()
override {
3032 return std::make_unique<VarDeclFilterCCC>(*
this);
3041 explicit VarOrFuncDeclFilterCCC(
Sema &S) : SemaRef(S) {}
3042 bool ValidateCandidate(
const TypoCorrection &Candidate)
override {
3044 if (ND && ((isa<VarDecl>(ND) && ND->
getKind() == Decl::Var) ||
3045 isa<FunctionDecl>(ND))) {
3052 std::unique_ptr<CorrectionCandidateCallback> clone()
override {
3053 return std::make_unique<VarOrFuncDeclFilterCCC>(*
this);
3074 VarDeclFilterCCC CCC(
SemaRef);
3081 : diag::err_omp_expected_var_arg_suggest)
3083 VD = Corrected.getCorrectionDeclAs<
VarDecl>();
3085 Diag(
Id.getLoc(), Lookup.
empty() ? diag::err_undeclared_var_use
3086 : diag::err_omp_expected_var_arg)
3091 Diag(
Id.getLoc(), diag::err_omp_expected_var_arg) <<
Id.getName();
3100 Diag(
Id.getLoc(), diag::err_omp_global_var_arg)
3105 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3117 Diag(
Id.getLoc(), diag::err_omp_var_scope)
3118 << getOpenMPDirectiveName(Kind) << VD;
3122 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3132 Diag(
Id.getLoc(), diag::err_omp_var_scope)
3133 << getOpenMPDirectiveName(Kind) << VD;
3137 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3149 Diag(
Id.getLoc(), diag::err_omp_var_scope)
3150 << getOpenMPDirectiveName(Kind) << VD;
3154 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3163 Diag(
Id.getLoc(), diag::err_omp_var_scope)
3164 << getOpenMPDirectiveName(Kind) << VD;
3168 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3176 if (Kind == OMPD_threadprivate && VD->
isUsed() &&
3178 Diag(
Id.getLoc(), diag::err_omp_var_used)
3179 << getOpenMPDirectiveName(Kind) << VD;
3201class LocalVarRefChecker final
3207 if (
const auto *VD = dyn_cast<VarDecl>(
E->getDecl())) {
3210 diag::err_omp_local_var_in_threadprivate_init)
3212 SemaRef.Diag(VD->
getLocation(), diag::note_defined_here)
3219 bool VisitStmt(
const Stmt *S) {
3220 for (
const Stmt *Child : S->children()) {
3221 if (Child && Visit(Child))
3226 explicit LocalVarRefChecker(
Sema &SemaRef) : SemaRef(SemaRef) {}
3235 for (
Expr *RefExpr : VarList) {
3236 auto *DE = cast<DeclRefExpr>(RefExpr);
3237 auto *VD = cast<VarDecl>(DE->getDecl());
3254 ILoc, VD->
getType(), diag::err_omp_threadprivate_incomplete_type)) {
3261 Diag(ILoc, diag::err_omp_ref_type_arg)
3262 << getOpenMPDirectiveName(OMPD_threadprivate) << VD->
getType();
3266 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3274 !(VD->
hasAttr<OMPThreadPrivateDeclAttr>() &&
3279 Diag(ILoc, diag::err_omp_var_thread_local)
3284 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3292 LocalVarRefChecker Checker(
SemaRef);
3293 if (Checker.Visit(
Init))
3297 Vars.push_back(RefExpr);
3298 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3299 VD->
addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3302 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3305 if (!Vars.empty()) {
3313static OMPAllocateDeclAttr::AllocatorTypeTy
3316 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3317 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3318 Allocator->isInstantiationDependent() ||
3319 Allocator->containsUnexpandedParameterPack())
3320 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3321 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3322 llvm::FoldingSetNodeID AEId;
3323 const Expr *AE = Allocator->IgnoreParenImpCasts();
3325 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3326 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
3327 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3328 llvm::FoldingSetNodeID DAEId;
3331 if (AEId == DAEId) {
3332 AllocatorKindRes = AllocatorKind;
3336 return AllocatorKindRes;
3341 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
Expr *Allocator) {
3342 if (!VD->
hasAttr<OMPAllocateDeclAttr>())
3344 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
3345 Expr *PrevAllocator = A->getAllocator();
3346 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3348 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3349 if (AllocatorsMatch &&
3350 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3351 Allocator && PrevAllocator) {
3352 const Expr *AE = Allocator->IgnoreParenImpCasts();
3354 llvm::FoldingSetNodeID AEId, PAEId;
3357 AllocatorsMatch = AEId == PAEId;
3359 if (!AllocatorsMatch) {
3361 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3365 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3367 PrevAllocator->printPretty(PrevAllocatorStream,
nullptr,
3371 Allocator ? Allocator->getExprLoc() : RefExpr->
getExprLoc();
3373 Allocator ? Allocator->getSourceRange() : RefExpr->
getSourceRange();
3375 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3377 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3378 S.
Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3379 << (Allocator ? 1 : 0) << AllocatorStream.str()
3380 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3382 S.
Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3383 << PrevAllocatorRange;
3391 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3393 if (VD->
hasAttr<OMPAllocateDeclAttr>())
3402 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3403 Allocator->isInstantiationDependent() ||
3404 Allocator->containsUnexpandedParameterPack()))
3406 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.
Context, AllocatorKind,
3407 Allocator, Alignment, SR);
3410 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3416 assert(Clauses.size() <= 2 &&
"Expected at most two clauses.");
3417 Expr *Alignment =
nullptr;
3418 Expr *Allocator =
nullptr;
3419 if (Clauses.empty()) {
3429 if (
const auto *AC = dyn_cast<OMPAllocatorClause>(
C))
3430 Allocator = AC->getAllocator();
3431 else if (
const auto *AC = dyn_cast<OMPAlignClause>(
C))
3432 Alignment = AC->getAlignment();
3434 llvm_unreachable(
"Unexpected clause on allocate directive");
3436 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3439 for (
Expr *RefExpr : VarList) {
3440 auto *DE = cast<DeclRefExpr>(RefExpr);
3441 auto *VD = cast<VarDecl>(DE->getDecl());
3445 VD->
hasAttr<OMPThreadPrivateDeclAttr>() ||
3453 AllocatorKind, Allocator))
3461 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3462 Diag(Allocator->getExprLoc(),
3463 diag::err_omp_expected_predefined_allocator)
3464 << Allocator->getSourceRange();
3468 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3474 Vars.push_back(RefExpr);
3493 Diag(
Loc, diag::err_omp_invalid_scope) <<
"requires";
3507 bool SkippedClauses) {
3508 if (!SkippedClauses && Assumptions.empty())
3509 Diag(
Loc, diag::err_omp_no_clause_for_directive)
3510 << llvm::omp::getAllAssumeClauseOptions()
3511 << llvm::omp::getOpenMPDirectiveName(DKind);
3515 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3516 OMPAssumeScoped.push_back(AA);
3521 if (Assumptions.empty())
3524 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3525 "Unexpected omp assumption directive!");
3526 OMPAssumeGlobal.push_back(AA);
3534 while (Ctx->getLexicalParent())
3536 DeclContexts.push_back(Ctx);
3537 while (!DeclContexts.empty()) {
3539 for (
auto *SubDC : DC->
decls()) {
3540 if (SubDC->isInvalidDecl())
3542 if (
auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3543 DeclContexts.push_back(CTD->getTemplatedDecl());
3544 llvm::append_range(DeclContexts, CTD->specializations());
3547 if (
auto *DC = dyn_cast<DeclContext>(SubDC))
3548 DeclContexts.push_back(DC);
3549 if (
auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3559 OMPAssumeScoped.pop_back();
3580 DSAStack->getEncounteredTargetLocs();
3582 if (!TargetLocations.empty() || !AtomicLoc.
isInvalid()) {
3583 for (
const OMPClause *CNew : ClauseList) {
3585 if (isa<OMPUnifiedSharedMemoryClause>(CNew) ||
3586 isa<OMPUnifiedAddressClause>(CNew) ||
3587 isa<OMPReverseOffloadClause>(CNew) ||
3588 isa<OMPDynamicAllocatorsClause>(CNew)) {
3589 Diag(
Loc, diag::err_omp_directive_before_requires)
3590 <<
"target" << getOpenMPClauseName(CNew->getClauseKind());
3592 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3596 isa<OMPAtomicDefaultMemOrderClause>(CNew)) {
3597 Diag(
Loc, diag::err_omp_directive_before_requires)
3598 <<
"atomic" << getOpenMPClauseName(CNew->getClauseKind());
3599 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3605 if (!
DSAStack->hasDuplicateRequiresClause(ClauseList))
3613 const DSAStackTy::DSAVarData &DVar,
3614 bool IsLoopIterVar) {
3616 SemaRef.
Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3617 << getOpenMPClauseName(DVar.CKind);
3621 PDSA_StaticMemberShared,
3622 PDSA_StaticLocalVarShared,
3623 PDSA_LoopIterVarPrivate,
3624 PDSA_LoopIterVarLinear,
3625 PDSA_LoopIterVarLastprivate,
3626 PDSA_ConstVarShared,
3627 PDSA_GlobalVarShared,
3628 PDSA_TaskVarFirstprivate,
3629 PDSA_LocalVarPrivate,
3631 } Reason = PDSA_Implicit;
3632 bool ReportHint =
false;
3634 auto *VD = dyn_cast<VarDecl>(
D);
3635 if (IsLoopIterVar) {
3636 if (DVar.CKind == OMPC_private)
3637 Reason = PDSA_LoopIterVarPrivate;
3638 else if (DVar.CKind == OMPC_lastprivate)
3639 Reason = PDSA_LoopIterVarLastprivate;
3641 Reason = PDSA_LoopIterVarLinear;
3643 DVar.CKind == OMPC_firstprivate) {
3644 Reason = PDSA_TaskVarFirstprivate;
3645 ReportLoc = DVar.ImplicitDSALoc;
3647 Reason = PDSA_StaticLocalVarShared;
3649 Reason = PDSA_StaticMemberShared;
3651 Reason = PDSA_GlobalVarShared;
3653 Reason = PDSA_ConstVarShared;
3654 else if (VD && VD->
isLocalVarDecl() && DVar.CKind == OMPC_private) {
3656 Reason = PDSA_LocalVarPrivate;
3658 if (Reason != PDSA_Implicit) {
3659 SemaRef.
Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3660 << Reason << ReportHint
3661 << getOpenMPDirectiveName(Stack->getCurrentDirective());
3662 }
else if (DVar.ImplicitDSALoc.isValid()) {
3663 SemaRef.
Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3664 << getOpenMPClauseName(DVar.CKind);
3670 bool IsAggregateOrDeclareTarget) {
3673 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3674 Kind = OMPC_MAP_alloc;
3676 case OMPC_DEFAULTMAP_MODIFIER_to:
3679 case OMPC_DEFAULTMAP_MODIFIER_from:
3680 Kind = OMPC_MAP_from;
3682 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3683 Kind = OMPC_MAP_tofrom;
3685 case OMPC_DEFAULTMAP_MODIFIER_present:
3691 Kind = OMPC_MAP_alloc;
3693 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3695 llvm_unreachable(
"Unexpected defaultmap implicit behavior");
3696 case OMPC_DEFAULTMAP_MODIFIER_none:
3697 case OMPC_DEFAULTMAP_MODIFIER_default:
3702 if (IsAggregateOrDeclareTarget) {
3703 Kind = OMPC_MAP_tofrom;
3706 llvm_unreachable(
"Unexpected defaultmap implicit behavior");
3713struct VariableImplicitInfo {
3717 llvm::SetVector<Expr *> Privates;
3718 llvm::SetVector<Expr *> Firstprivates;
3719 llvm::SetVector<Expr *> Mappings[DefaultmapKindNum][MapKindNum];
3721 MapModifiers[DefaultmapKindNum];
3724class DSAAttrChecker final :
public StmtVisitor<DSAAttrChecker, void> {
3728 bool ErrorFound =
false;
3729 bool TryCaptureCXXThisMembers =
false;
3732 VariableImplicitInfo ImpInfo;
3734 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3738 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3740 if (S->getDirectiveKind() == OMPD_atomic ||
3741 S->getDirectiveKind() == OMPD_critical ||
3742 S->getDirectiveKind() == OMPD_section ||
3743 S->getDirectiveKind() == OMPD_master ||
3744 S->getDirectiveKind() == OMPD_masked ||
3745 S->getDirectiveKind() == OMPD_scope ||
3746 S->getDirectiveKind() == OMPD_assume ||
3748 Visit(S->getAssociatedStmt());
3751 visitSubCaptures(S->getInnermostCapturedStmt());
3754 if (TryCaptureCXXThisMembers ||
3756 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3758 return C.capturesThis();
3760 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3761 TryCaptureCXXThisMembers =
true;
3762 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3763 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3770 if (
auto *FC = dyn_cast<OMPFirstprivateClause>(
C)) {
3771 for (
Expr *Ref : FC->varlist())
3784 if (
auto *VD = dyn_cast<VarDecl>(
E->getDecl())) {
3787 !Stack->getTopDSA(VD,
false).RefExpr &&
3788 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3789 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3790 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3791 Visit(CED->getInit());
3794 }
else if (VD->
isImplicit() || isa<OMPCapturedExprDecl>(VD))
3797 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3802 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3803 !Stack->isImplicitTaskFirstprivate(VD))
3806 if (Stack->isUsesAllocatorsDecl(VD))
3809 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD,
false);
3811 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3815 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3816 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3819 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3820 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3821 !Stack->isImplicitTaskFirstprivate(VD))
3829 if (DVar.CKind == OMPC_unknown &&
3830 (Stack->getDefaultDSA() == DSA_none ||
3831 Stack->getDefaultDSA() == DSA_private ||
3832 Stack->getDefaultDSA() == DSA_firstprivate) &&
3833 isImplicitOrExplicitTaskingRegion(DKind) &&
3834 VarsWithInheritedDSA.count(VD) == 0) {
3835 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
3836 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
3837 Stack->getDefaultDSA() == DSA_private)) {
3838 DSAStackTy::DSAVarData DVar =
3839 Stack->getImplicitDSA(VD,
false);
3840 InheritedDSA = DVar.CKind == OMPC_unknown;
3843 VarsWithInheritedDSA[VD] =
E;
3844 if (Stack->getDefaultDSA() == DSA_none)
3859 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
3860 OMPC_DEFAULTMAP_MODIFIER_none;
3861 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
3862 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
3866 if (!Stack->checkMappableExprComponentListsForDecl(
3871 auto MI = MapExprComponents.rbegin();
3872 auto ME = MapExprComponents.rend();
3873 return MI != ME && MI->getAssociatedDeclaration() == VD;
3875 VarsWithInheritedDSA[VD] =
E;
3881 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
3882 OMPC_DEFAULTMAP_MODIFIER_present;
3883 if (IsModifierPresent) {
3884 if (!llvm::is_contained(ImpInfo.MapModifiers[ClauseKind],
3885 OMPC_MAP_MODIFIER_present)) {
3886 ImpInfo.MapModifiers[ClauseKind].push_back(
3887 OMPC_MAP_MODIFIER_present);
3893 !Stack->isLoopControlVariable(VD).first) {
3894 if (!Stack->checkMappableExprComponentListsForDecl(
3899 if (SemaRef.LangOpts.OpenMP >= 50)
3900 return !StackComponents.empty();
3903 return StackComponents.size() == 1 ||
3905 llvm::drop_begin(llvm::reverse(StackComponents)),
3906 [](const OMPClauseMappableExprCommon::
3907 MappableComponent &MC) {
3908 return MC.getAssociatedDeclaration() ==
3910 (isa<ArraySectionExpr>(
3911 MC.getAssociatedExpression()) ||
3912 isa<OMPArrayShapingExpr>(
3913 MC.getAssociatedExpression()) ||
3914 isa<ArraySubscriptExpr>(
3915 MC.getAssociatedExpression()));
3918 bool IsFirstprivate =
false;
3920 if (
const auto *RD =
3922 IsFirstprivate = RD->isLambda();
3924 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
3925 if (IsFirstprivate) {
3926 ImpInfo.Firstprivates.insert(
E);
3929 Stack->getDefaultmapModifier(ClauseKind);
3931 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
3932 ImpInfo.Mappings[ClauseKind][
Kind].insert(
E);
3942 DVar = Stack->hasInnermostDSA(
3945 return C == OMPC_reduction && !AppliedToPointee;
3954 SemaRef.
Diag(ELoc, diag::err_omp_reduction_in_task);
3960 DVar = Stack->getImplicitDSA(VD,
false);
3962 (((Stack->getDefaultDSA() == DSA_firstprivate &&
3963 DVar.CKind == OMPC_firstprivate) ||
3964 (Stack->getDefaultDSA() == DSA_private &&
3965 DVar.CKind == OMPC_private)) &&
3967 !Stack->isLoopControlVariable(VD).first) {
3968 if (Stack->getDefaultDSA() == DSA_private)
3969 ImpInfo.Privates.insert(
E);
3971 ImpInfo.Firstprivates.insert(
E);
3978 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
3979 Stack->addToParentTargetRegionLinkGlobals(
E);
3988 auto *FD = dyn_cast<FieldDecl>(
E->getMemberDecl());
3992 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD,
false);
3995 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
3999 !Stack->isLoopControlVariable(FD).first &&
4000 !Stack->checkMappableExprComponentListsForDecl(
4005 return isa<CXXThisExpr>(
4007 StackComponents.back().getAssociatedExpression())
4019 if (Stack->isClassPreviouslyMapped(TE->getType()))
4023 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4028 ImpInfo.Mappings[ClauseKind][
Kind].insert(
E);
4037 DVar = Stack->hasInnermostDSA(
4040 return C == OMPC_reduction && !AppliedToPointee;
4049 SemaRef.
Diag(ELoc, diag::err_omp_reduction_in_task);
4055 DVar = Stack->getImplicitDSA(FD,
false);
4057 !Stack->isLoopControlVariable(FD).first) {
4062 if (DVar.CKind != OMPC_unknown)
4063 ImpInfo.Firstprivates.insert(
E);
4072 const auto *VD = cast<ValueDecl>(
4073 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4074 if (!Stack->checkMappableExprComponentListsForDecl(
4080 auto CCI = CurComponents.rbegin();
4081 auto CCE = CurComponents.rend();
4082 for (const auto &SC : llvm::reverse(StackComponents)) {
4084 if (CCI->getAssociatedExpression()->getStmtClass() !=
4085 SC.getAssociatedExpression()->getStmtClass())
4086 if (!((isa<ArraySectionExpr>(
4087 SC.getAssociatedExpression()) ||
4088 isa<OMPArrayShapingExpr>(
4089 SC.getAssociatedExpression())) &&
4090 isa<ArraySubscriptExpr>(
4091 CCI->getAssociatedExpression())))
4094 const Decl *CCD = CCI->getAssociatedDeclaration();
4095 const Decl *SCD = SC.getAssociatedDeclaration();
4096 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4097 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4100 std::advance(CCI, 1);
4106 Visit(
E->getBase());
4108 }
else if (!TryCaptureCXXThisMembers) {
4109 Visit(
E->getBase());
4116 if (isa_and_nonnull<OMPPrivateClause>(
C))
4122 if (
C && !((isa<OMPFirstprivateClause>(
C) || isa<OMPMapClause>(
C)) &&
4124 for (
Stmt *CC :
C->children()) {
4131 VisitSubCaptures(S);
4140 for (
Stmt *
C : S->arguments()) {
4147 if (
Expr *Callee = S->getCallee()) {
4148 auto *CI =
Callee->IgnoreParenImpCasts();
4149 if (
auto *CE = dyn_cast<MemberExpr>(CI))
4150 Visit(CE->getBase());
4151 else if (
auto *CE = dyn_cast<DeclRefExpr>(CI))
4155 void VisitStmt(
Stmt *S) {
4156 for (
Stmt *
C : S->children()) {
4167 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4169 VarDecl *VD = Cap.getCapturedVar();
4173 Stack->checkMappableExprComponentListsForDecl(
4180 Cap.getLocation(),
true);
4184 bool isErrorFound()
const {
return ErrorFound; }
4185 const VariableImplicitInfo &getImplicitInfo()
const {
return ImpInfo; }
4187 return VarsWithInheritedDSA;
4191 : Stack(S), SemaRef(SemaRef), ErrorFound(
false), CS(CS) {
4192 DKind = S->getCurrentDirective();
4207 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4209 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4211 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4213 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4215 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4216 Stack->handleConstructTrait(Traits, ScopeEntry);
4227 std::make_pair(
".global_tid.", KmpInt32PtrTy),
4228 std::make_pair(
".bound_tid.", KmpInt32PtrTy),
4230 if (LoopBoundSharing) {
4232 Params.push_back(std::make_pair(
".previous.lb.", KmpSizeTy));
4233 Params.push_back(std::make_pair(
".previous.ub.", KmpSizeTy));
4237 Params.push_back(std::make_pair(StringRef(),
QualType()));
4258 std::make_pair(
".global_tid.", KmpInt32Ty),
4259 std::make_pair(
".part_id.", KmpInt32PtrTy),
4260 std::make_pair(
".privates.", VoidPtrTy),
4265 std::make_pair(StringRef(),
QualType())
4276 Params.push_back(std::make_pair(StringRef(
"dyn_ptr"), VoidPtrTy));
4279 Params.push_back(std::make_pair(StringRef(),
QualType()));
4286 std::make_pair(StringRef(),
QualType())
4308 std::make_pair(
".global_tid.", KmpInt32Ty),
4309 std::make_pair(
".part_id.", KmpInt32PtrTy),
4310 std::make_pair(
".privates.", VoidPtrTy),
4315 std::make_pair(
".lb.", KmpUInt64Ty),
4316 std::make_pair(
".ub.", KmpUInt64Ty),
4317 std::make_pair(
".st.", KmpInt64Ty),
4318 std::make_pair(
".liter.", KmpInt32Ty),
4319 std::make_pair(
".reductions.", VoidPtrTy),
4320 std::make_pair(StringRef(),
QualType())
4333 CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
4334 SemaRef.
getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
4337 for (
auto [Level, RKind] : llvm::enumerate(Regions)) {
4372 case OMPD_metadirective:
4375 llvm_unreachable(
"Unexpected capture region");
4391 case OMPD_interchange:
4404int SemaOpenMP::getNumberOfConstructScopes(
unsigned Level)
const {
4411 return CaptureRegions.size();
4415 Expr *CaptureExpr,
bool WithInit,
4417 bool AsExpression) {
4418 assert(CaptureExpr);
4424 Ty =
C.getLValueReferenceType(Ty);
4426 Ty =
C.getPointerType(Ty);
4438 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(
C));
4449 CD = cast<OMPCapturedExprDecl>(VD);
4488class CaptureRegionUnwinderRAII {
4495 CaptureRegionUnwinderRAII(
Sema &S,
bool &ErrorFound,
4497 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4498 ~CaptureRegionUnwinderRAII() {
4501 while (--ThisCaptureLevel >= 0)
4514 DSAStack->getCurrentDirective()))) {
4516 if (
const auto *RD =
Type.getCanonicalType()
4517 .getNonReferenceType()
4519 bool SavedForceCaptureByReferenceInTargetExecutable =
4520 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4521 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4523 if (RD->isLambda()) {
4524 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4526 RD->getCaptureFields(Captures, ThisCapture);
4529 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4534 }
else if (LC.getCaptureKind() ==
LCK_This) {
4537 ThisTy, ThisCapture->
getType()))
4542 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4543 SavedForceCaptureByReferenceInTargetExecutable);
4553 for (
const OMPClause *Clause : Clauses) {
4555 Ordered = cast<OMPOrderedClause>(Clause);
4557 Order = cast<OMPOrderClause>(Clause);
4558 if (Order->
getKind() != OMPC_ORDER_concurrent)
4561 if (Ordered && Order)
4565 if (Ordered && Order) {
4567 diag::err_omp_simple_clause_incompatible_with_ordered)
4568 << getOpenMPClauseName(OMPC_order)
4585 bool ErrorFound =
false;
4586 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4588 if (!S.isUsable()) {
4603 DSAStack->getCurrentDirective() == OMPD_target) &&
4607 auto *IRC = cast<OMPInReductionClause>(Clause);
4608 for (
Expr *
E : IRC->taskgroup_descriptors())
4620 if (
auto *
E = cast_or_null<Expr>(VarRef)) {
4624 DSAStack->setForceVarCapturing(
false);
4625 }
else if (CaptureRegions.size() > 1 ||
4626 CaptureRegions.back() != OMPD_unknown) {
4630 if (
Expr *
E =
C->getPostUpdateExpr())
4635 SC = cast<OMPScheduleClause>(Clause);
4637 OC = cast<OMPOrderedClause>(Clause);
4639 LCs.push_back(cast<OMPLinearClause>(Clause));
4650 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4655 diag::err_omp_simple_clause_incompatible_with_ordered)
4656 << getOpenMPClauseName(OMPC_schedule)
4658 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4669 Diag(
C->getBeginLoc(), diag::err_omp_linear_ordered)
4678 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
4685 unsigned CompletedRegions = 0;
4690 if (ThisCaptureRegion != OMPD_unknown) {
4698 if (CaptureRegion == ThisCaptureRegion ||
4699 CaptureRegion == OMPD_unknown) {
4700 if (
auto *DS = cast_or_null<DeclStmt>(
C->getPreInitStmt())) {
4701 for (
Decl *
D : DS->decls())
4708 if (ThisCaptureRegion == OMPD_target) {
4712 if (
const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(
C)) {
4713 for (
unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4716 if (
Expr *
E =
D.AllocatorTraits)
4723 if (ThisCaptureRegion == OMPD_parallel) {
4727 if (
auto *RC = dyn_cast<OMPReductionClause>(
C)) {
4728 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4730 for (
Expr *
E : RC->copy_array_temps())
4734 if (
auto *AC = dyn_cast<OMPAlignedClause>(
C)) {
4735 for (
Expr *
E : AC->varlist())
4740 if (++CompletedRegions == CaptureRegions.size())
4751 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4754 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4755 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4758 SemaRef.
Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4759 << getOpenMPDirectiveName(CancelRegion);
4769 if (!Stack->getCurScope())
4774 bool NestingProhibited =
false;
4775 bool CloseNesting =
true;
4776 bool OrphanSeen =
false;
4779 ShouldBeInParallelRegion,
4780 ShouldBeInOrderedRegion,
4781 ShouldBeInTargetRegion,
4782 ShouldBeInTeamsRegion,
4783 ShouldBeInLoopSimdRegion,
4784 } Recommend = NoRecommend;
4788 getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
4791 if (SemaRef.
LangOpts.OpenMP >= 51 && Stack->isParentOrderConcurrent() &&
4792 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_loop &&
4793 CurrentRegion != OMPD_parallel &&
4795 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_order)
4796 << getOpenMPDirectiveName(CurrentRegion);
4800 ((SemaRef.
LangOpts.OpenMP <= 45 && CurrentRegion != OMPD_ordered) ||
4801 (SemaRef.
LangOpts.OpenMP >= 50 && CurrentRegion != OMPD_ordered &&
4802 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
4803 CurrentRegion != OMPD_scan))) {
4816 SemaRef.
Diag(StartLoc, (CurrentRegion != OMPD_simd)
4817 ? diag::err_omp_prohibited_region_simd
4818 : diag::warn_omp_nesting_simd)
4819 << (SemaRef.
LangOpts.OpenMP >= 50 ? 1 : 0);
4820 return CurrentRegion != OMPD_simd;
4822 if (EnclosingConstruct == OMPD_atomic) {
4825 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
4828 if (CurrentRegion == OMPD_section) {
4833 if (EnclosingConstruct != OMPD_sections) {
4834 SemaRef.
Diag(StartLoc, diag::err_omp_orphaned_section_directive)
4835 << (ParentRegion != OMPD_unknown)
4836 << getOpenMPDirectiveName(ParentRegion);
4844 if (ParentRegion == OMPD_unknown &&
4846 CurrentRegion != OMPD_cancellation_point &&
4847 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
4851 if (SemaRef.
LangOpts.OpenMP >= 50 && CurrentRegion == OMPD_loop &&
4852 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
4854 EnclosingConstruct == OMPD_loop)) {
4855 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
4856 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region)
4857 <<
true << getOpenMPDirectiveName(ParentRegion) << ErrorMsgNumber
4858 << getOpenMPDirectiveName(CurrentRegion);
4861 if (CurrentRegion == OMPD_cancellation_point ||
4862 CurrentRegion == OMPD_cancel) {
4875 if (CancelRegion == OMPD_taskgroup) {
4876 NestingProhibited = EnclosingConstruct != OMPD_task &&
4878 EnclosingConstruct != OMPD_taskloop);
4879 }
else if (CancelRegion == OMPD_sections) {
4880 NestingProhibited = EnclosingConstruct != OMPD_section &&
4881 EnclosingConstruct != OMPD_sections;
4883 NestingProhibited = CancelRegion != Leafs.back();
4885 OrphanSeen = ParentRegion == OMPD_unknown;
4886 }
else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
4893 }
else if (CurrentRegion == OMPD_critical && CurrentName.
getName()) {
4899 bool DeadLock = Stack->hasDirective(
4903 if (K == OMPD_critical && DNI.
getName() == CurrentName.
getName()) {
4904 PreviousCriticalLoc = Loc;
4911 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name)
4913 if (PreviousCriticalLoc.
isValid())
4914 SemaRef.
Diag(PreviousCriticalLoc,
4915 diag::note_omp_previous_critical_region);
4918 }
else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
4928 llvm::is_contained({OMPD_masked, OMPD_master,
4929 OMPD_critical, OMPD_ordered},
4930 EnclosingConstruct);
4941 llvm::is_contained({OMPD_masked, OMPD_master,
4942 OMPD_critical, OMPD_ordered},
4943 EnclosingConstruct);
4944 Recommend = ShouldBeInParallelRegion;
4945 }
else if (CurrentRegion == OMPD_ordered) {
4954 NestingProhibited = EnclosingConstruct == OMPD_critical ||
4957 Stack->isParentOrderedRegion());
4958 Recommend = ShouldBeInOrderedRegion;
4964 (SemaRef.
LangOpts.OpenMP <= 45 && EnclosingConstruct != OMPD_target) ||
4965 (SemaRef.
LangOpts.OpenMP >= 50 && EnclosingConstruct != OMPD_unknown &&
4966 EnclosingConstruct != OMPD_target);
4967 OrphanSeen = ParentRegion == OMPD_unknown;
4968 Recommend = ShouldBeInTargetRegion;
4969 }
else if (CurrentRegion == OMPD_scan) {
4970 if (SemaRef.
LangOpts.OpenMP >= 50) {
4975 NestingProhibited = !llvm::is_contained(
4976 {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
4978 NestingProhibited =
true;
4980 OrphanSeen = ParentRegion == OMPD_unknown;
4981 Recommend = ShouldBeInLoopSimdRegion;
4985 EnclosingConstruct == OMPD_teams) {
4997 CurrentRegion != OMPD_loop &&
4999 CurrentRegion == OMPD_atomic);
5000 Recommend = ShouldBeInParallelRegion;
5002 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5008 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5009 Recommend = ShouldBeInTeamsRegion;
5015 NestingProhibited = EnclosingConstruct != OMPD_teams;
5016 Recommend = ShouldBeInTeamsRegion;
5018 if (!NestingProhibited &&
5025 NestingProhibited = Stack->hasDirective(
5029 OffendingRegion = K;
5035 CloseNesting =
false;
5037 if (NestingProhibited) {
5039 SemaRef.
Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5040 << getOpenMPDirectiveName(CurrentRegion) << Recommend;
5042 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region)
5043 << CloseNesting << getOpenMPDirectiveName(OffendingRegion)
5044 << Recommend << getOpenMPDirectiveName(CurrentRegion);
5058 bool ErrorFound =
false;
5059 unsigned NamedModifiersNumber = 0;
5060 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5061 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5064 if (
const auto *IC = dyn_cast_or_null<OMPIfClause>(
C)) {
5068 if (FoundNameModifiers[CurNM]) {
5069 S.
Diag(
C->getBeginLoc(), diag::err_omp_more_one_clause)
5070 << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if)
5071 << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM);
5073 }
else if (CurNM != OMPD_unknown) {
5074 NameModifierLoc.push_back(IC->getNameModifierLoc());
5075 ++NamedModifiersNumber;
5077 FoundNameModifiers[CurNM] = IC;
5078 if (CurNM == OMPD_unknown)
5084 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5085 S.
Diag(IC->getNameModifierLoc(),
5086 diag::err_omp_wrong_if_directive_name_modifier)
5087 << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind);
5094 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5095 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5096 S.
Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5097 diag::err_omp_no_more_if_clause);
5100 std::string Sep(
", ");
5101 unsigned AllowedCnt = 0;
5102 unsigned TotalAllowedNum =
5103 AllowedNameModifiers.size() - NamedModifiersNumber;
5104 for (
unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5107 if (!FoundNameModifiers[NM]) {
5109 Values += getOpenMPDirectiveName(NM);
5111 if (AllowedCnt + 2 == TotalAllowedNum)
5113 else if (AllowedCnt + 1 != TotalAllowedNum)
5118 S.
Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5119 diag::err_omp_unnamed_if_clause)
5120 << (TotalAllowedNum > 1) << Values;
5123 S.
Diag(
Loc, diag::note_omp_previous_named_if_clause);
5133 bool AllowArraySection,
5134 StringRef DiagType) {
5137 return std::make_pair(
nullptr,
true);
5149 } IsArrayExpr = NoArrayExpr;
5150 if (AllowArraySection) {
5151 if (
auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5152 Expr *
Base = ASE->getBase()->IgnoreParenImpCasts();
5153 while (
auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
5154 Base = TempASE->getBase()->IgnoreParenImpCasts();
5156 IsArrayExpr = ArraySubscript;
5157 }
else if (
auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5158 Expr *
Base = OASE->getBase()->IgnoreParenImpCasts();
5159 while (
auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base))
5160 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5161 while (
auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
5162 Base = TempASE->getBase()->IgnoreParenImpCasts();
5164 IsArrayExpr = OMPArraySection;
5170 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5171 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5172 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5174 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5175 !isa<FieldDecl>(ME->getMemberDecl()))) {
5176 if (IsArrayExpr != NoArrayExpr) {
5177 S.
Diag(ELoc, diag::err_omp_expected_base_var_name)
5178 << IsArrayExpr << ERange;
5179 }
else if (!DiagType.empty()) {
5183 S.
Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5184 << DiagSelect << DiagType << ERange;
5188 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5189 : diag::err_omp_expected_var_name_member_expr)
5192 return std::make_pair(
nullptr,
false);
5194 return std::make_pair(
5201class AllocatorChecker final :
public ConstStmtVisitor<AllocatorChecker, bool> {
5202 DSAStackTy *S =
nullptr;
5206 return S->isUsesAllocatorsDecl(
E->getDecl())
5207 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5208 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5210 bool VisitStmt(
const Stmt *S) {
5211 for (
const Stmt *Child : S->children()) {
5212 if (Child && Visit(Child))
5217 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5224 "Expected non-dependent context.");
5225 auto AllocateRange =
5228 auto PrivateRange = llvm::make_filter_range(Clauses, [](
const OMPClause *
C) {
5233 if (
Cl->getClauseKind() == OMPC_private) {
5234 auto *PC = cast<OMPPrivateClause>(
Cl);
5235 I = PC->private_copies().begin();
5236 It = PC->varlist_begin();
5237 Et = PC->varlist_end();
5238 }
else if (
Cl->getClauseKind() == OMPC_firstprivate) {
5239 auto *PC = cast<OMPFirstprivateClause>(
Cl);
5240 I = PC->private_copies().begin();
5241 It = PC->varlist_begin();
5242 Et = PC->varlist_end();
5243 }
else if (
Cl->getClauseKind() == OMPC_lastprivate) {
5244 auto *PC = cast<OMPLastprivateClause>(
Cl);
5245 I = PC->private_copies().begin();
5246 It = PC->varlist_begin();
5247 Et = PC->varlist_end();
5248 }
else if (
Cl->getClauseKind() == OMPC_linear) {
5249 auto *PC = cast<OMPLinearClause>(
Cl);
5250 I = PC->privates().begin();
5251 It = PC->varlist_begin();
5252 Et = PC->varlist_end();
5253 }
else if (
Cl->getClauseKind() == OMPC_reduction) {
5254 auto *PC = cast<OMPReductionClause>(
Cl);
5255 I = PC->privates().begin();
5256 It = PC->varlist_begin();
5257 Et = PC->varlist_end();
5258 }
else if (
Cl->getClauseKind() == OMPC_task_reduction) {
5259 auto *PC = cast<OMPTaskReductionClause>(
Cl);
5260 I = PC->privates().begin();
5261 It = PC->varlist_begin();
5262 Et = PC->varlist_end();
5263 }
else if (
Cl->getClauseKind() == OMPC_in_reduction) {
5264 auto *PC = cast<OMPInReductionClause>(
Cl);
5265 I = PC->privates().begin();
5266 It = PC->varlist_begin();
5267 Et = PC->varlist_end();
5269 llvm_unreachable(
"Expected private clause.");
5271 for (
Expr *
E : llvm::make_range(It, Et)) {
5278 Expr *SimpleRefExpr =
E;
5281 DeclToCopy.try_emplace(Res.first,
5282 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5287 auto *AC = cast<OMPAllocateClause>(
C);
5291 AC->getAllocator()) {
5292 Expr *Allocator = AC->getAllocator();
5298 AllocatorChecker Checker(Stack);
5299 if (Checker.Visit(Allocator))
5300 S.
Diag(Allocator->getExprLoc(),
5301 diag::err_omp_allocator_not_in_uses_allocators)
5302 << Allocator->getSourceRange();
5304 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5310 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5313 S.
Diag(AC->getAllocator()->getExprLoc(),
5314 diag::warn_omp_allocate_thread_on_task_target_directive)
5315 << getOpenMPDirectiveName(Stack->getCurrentDirective());
5317 for (
Expr *
E : AC->varlist()) {
5320 Expr *SimpleRefExpr =
E;
5323 DSAStackTy::DSAVarData
Data = Stack->getTopDSA(VD,
false);
5326 diag::err_omp_expected_private_copy_for_allocate);
5329 VarDecl *PrivateVD = DeclToCopy[VD];
5331 AllocatorKind, AC->getAllocator()))
5334 Expr *Alignment =
nullptr;
5351 CaptureVars(
Sema &Actions) : BaseTransform(Actions) {}
5353 bool AlwaysRebuild() {
return true; }
5366 BodyStmts.push_back(NewDeclStmt);
5404 DistParam, LogicalTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
5415 auto BuildVarRef = [&](
VarDecl *VD) {
5420 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 0), LogicalTy, {});
5422 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 1), LogicalTy, {});
5428 Actions.
BuildBinOp(
nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5432 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5436 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5440 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5444 Actions.
BuildUnaryOp(
nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5446 Actions.
BuildBinOp(
nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5450 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5452 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5453 "Expected one of these relational operators");
5460 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5464 if (Rel == BO_GE || Rel == BO_GT)
5466 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5469 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5475 if (Rel == BO_LE || Rel == BO_GE) {
5487 Expr *Divisor = BuildVarRef(NewStep);
5488 if (Rel == BO_GE || Rel == BO_GT)
5491 Expr *DivisorMinusOne =
5496 Actions.
BuildBinOp(
nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5506 Actions.
getCurScope(), {}, BO_Assign, DistRef, Dist));
5507 BodyStmts.push_back(ResultAssign);
5512 return cast<CapturedStmt>(
5539 {
"Logical", LogicalTy},
5550 assert(!
Invalid &&
"Expecting capture-by-value to work.");
5555 auto *CS = cast<CapturedDecl>(Actions.
CurContext);
5559 TargetParam, LoopVarTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
5562 IndvarParam, LogicalTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
5565 CaptureVars Recap(Actions);
5570 Actions.
BuildBinOp(
nullptr, {}, BO_Mul, NewStep, LogicalRef));
5585 BO_Assign, TargetRef, Advanced));
5587 return cast<CapturedStmt>(
5598 if (
auto *For = dyn_cast<ForStmt>(AStmt)) {
5600 if (
auto *LCVarDeclStmt = dyn_cast<DeclStmt>(
Init)) {
5602 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5603 }
else if (
auto *LCAssign = dyn_cast<BinaryOperator>(
Init)) {
5605 assert(LCAssign->getOpcode() == BO_Assign &&
5606 "init part must be a loop variable assignment");
5607 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5608 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5610 llvm_unreachable(
"Cannot determine loop variable");
5613 Cond = For->getCond();
5614 Inc = For->getInc();
5615 }
else if (
auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5616 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5618 LUVDecl = RangeFor->getLoopVariable();
5620 Cond = RangeFor->getCond();
5621 Inc = RangeFor->getInc();
5623 llvm_unreachable(
"unhandled kind of loop");
5632 if (
auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5633 LHS = CondBinExpr->getLHS();
5634 RHS = CondBinExpr->getRHS();
5635 CondRel = CondBinExpr->getOpcode();
5636 }
else if (
auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5637 assert(CondCXXOp->getNumArgs() == 2 &&
"Comparison should have 2 operands");
5638 LHS = CondCXXOp->getArg(0);
5639 RHS = CondCXXOp->getArg(1);
5640 switch (CondCXXOp->getOperator()) {
5641 case OO_ExclaimEqual:
5653 case OO_GreaterEqual:
5657 llvm_unreachable(
"unexpected iterator operator");
5660 llvm_unreachable(
"unexpected loop condition");
5664 cast<DeclRefExpr>(LHS->
IgnoreImplicit())->getDecl() != LIVDecl) {
5665 std::swap(LHS, RHS);
5682 if (
auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5684 switch (IncUn->getOpcode()) {
5694 llvm_unreachable(
"unhandled unary increment operator");
5698 llvm::APInt(Ctx.
getIntWidth(LogicalTy), Direction,
true),
5700 }
else if (
auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5701 if (IncBin->getOpcode() == BO_AddAssign) {
5702 Step = IncBin->getRHS();
5703 }
else if (IncBin->getOpcode() == BO_SubAssign) {
5707 llvm_unreachable(
"unhandled binary increment operator");
5708 }
else if (
auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5709 switch (CondCXXOp->getOperator()) {
5712 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 1), LogicalTy, {});
5716 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), -1), LogicalTy, {});
5719 Step = CondCXXOp->getArg(1);
5726 llvm_unreachable(
"unhandled overloaded increment operator");
5729 llvm_unreachable(
"unknown increment expression");
5734 SemaRef, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
5737 nullptr,
nullptr, {},
nullptr);
5739 LoopVarFunc, LVRef);
5744 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
5751 "Loop transformation directive expected");
5752 return LoopTransform;
5759 Expr *UnresolvedMapper);
5771 for (
int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
5772 auto *
C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
5776 auto *MI =
C->mapperlist_begin();
5777 for (
auto I =
C->varlist_begin(), End =
C->varlist_end(); I != End;
5797 ElemType = ATy->getElementType();
5800 CanonType = ElemType;
5805 1, {CanonType,
nullptr});
5806 llvm::DenseMap<const Type *, Expr *>
Visited;
5809 while (!Types.empty()) {
5812 std::tie(BaseType, CurFD) = Types.pop_back_val();
5813 while (ParentChain.back().second == 0)
5814 ParentChain.pop_back();
5815 --ParentChain.back().second;
5831 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
5842 Expr *BaseExpr = OE;
5843 for (
const auto &
P : ParentChain) {
5861 SubExprs.push_back(BaseExpr);
5865 bool FirstIter =
true;
5875 ParentChain.emplace_back(CurFD, 1);
5877 ++ParentChain.back().second;
5879 Types.emplace_back(FieldTy, FD);
5883 if (SubExprs.empty())
5888 nullptr,
C->getMapTypeModifiers(),
C->getMapTypeModifiersLoc(),
5889 MapperIdScopeSpec, MapperId,
C->getMapType(),
5892 Clauses.push_back(NewClause);
5907 if (
D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
5909 if (
C->getBindKind() == OMPC_BIND_parallel) {
5910 TeamsLoopCanBeParallelFor =
false;
5915 for (
const Stmt *Child :
D->children())
5925 bool IsOpenMPAPI =
false;
5926 auto *FD = dyn_cast_or_null<FunctionDecl>(
C->getCalleeDecl());
5928 std::string Name = FD->getNameInfo().getAsString();
5929 IsOpenMPAPI = Name.find(
"omp_") == 0;
5931 TeamsLoopCanBeParallelFor =
5932 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
5933 if (!TeamsLoopCanBeParallelFor)
5936 for (
const Stmt *Child :
C->children())
5944 Visit(S->getCapturedDecl()->getBody());
5947 void VisitStmt(
const Stmt *S) {
5950 for (
const Stmt *Child : S->children())
5954 explicit TeamsLoopChecker(
Sema &SemaRef)
5955 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(
true) {}
5958 bool TeamsLoopCanBeParallelFor;
5963 TeamsLoopChecker Checker(SemaRef);
5964 Checker.Visit(AStmt);
5965 return Checker.teamsLoopCanBeParallelFor();
5979 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
5980 BindKind = BC->getBindKind();
5992 BindKind = OMPC_BIND_thread;
5994 getLeafConstructsOrSelf(ParentDirective);
5996 if (ParentDirective == OMPD_unknown) {
5998 diag::err_omp_bind_required_on_loop);
5999 }
else if (ParentLeafs.back() == OMPD_parallel) {
6000 BindKind = OMPC_BIND_parallel;
6001 }
else if (ParentLeafs.back() == OMPD_teams) {
6002 BindKind = OMPC_BIND_teams;
6010 ClausesWithImplicit.push_back(
C);
6014 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6016 if (
C->getClauseKind() == OMPC_reduction)
6018 diag::err_omp_loop_reduction_clause);
6025 BindKind, StartLoc)) {
6032 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6035 bool ErrorFound =
false;
6036 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6040 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
6043 DSAAttrChecker DSAChecker(
DSAStack,
SemaRef, cast<CapturedStmt>(AStmt));
6046 while (--ThisCaptureLevel >= 0)
6047 S = cast<CapturedStmt>(S)->getCapturedStmt();
6048 DSAChecker.Visit(S);
6052 auto *CS = cast<CapturedStmt>(AStmt);
6056 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6058 DSAChecker.visitSubCaptures(CS);
6060 if (DSAChecker.isErrorFound())
6063 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6064 VariableImplicitInfo ImpInfo = DSAChecker.getImplicitInfo();
6067 ImplicitMapModifiersLoc[VariableImplicitInfo::DefaultmapKindNum];
6069 SourceLocation PresentModifierLocs[VariableImplicitInfo::DefaultmapKindNum];
6071 if (
auto *DMC = dyn_cast<OMPDefaultmapClause>(
C))
6072 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6073 PresentModifierLocs[DMC->getDefaultmapKind()] =
6074 DMC->getDefaultmapModifierLoc();
6078 llvm::enum_seq_inclusive<OpenMPDefaultmapClauseKind>(
6080 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[K]),
6081 ImpInfo.MapModifiers[K].size(), PresentModifierLocs[K]);
6085 if (
auto *IRC = dyn_cast<OMPInReductionClause>(
C)) {
6086 for (
Expr *
E : IRC->taskgroup_descriptors())
6088 ImpInfo.Firstprivates.insert(
E);
6093 if (
auto *DC = dyn_cast<OMPDetachClause>(
C))
6094 ImpInfo.Firstprivates.insert(DC->getEventHandler());
6096 if (!ImpInfo.Firstprivates.empty()) {
6100 ClausesWithImplicit.push_back(
Implicit);
6101 ErrorFound = cast<OMPFirstprivateClause>(
Implicit)->varlist_size() !=
6102 ImpInfo.Firstprivates.size();
6107 if (!ImpInfo.Privates.empty()) {
6111 ClausesWithImplicit.push_back(
Implicit);
6112 ErrorFound = cast<OMPPrivateClause>(
Implicit)->varlist_size() !=
6113 ImpInfo.Privates.size();
6122 if (
getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6126 if (
auto *RC = dyn_cast<OMPReductionClause>(
C))
6127 for (
Expr *
E : RC->varlist())
6129 ImplicitExprs.emplace_back(
E);
6131 if (!ImplicitExprs.empty()) {
6137 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6140 ClausesWithImplicit.emplace_back(
Implicit);
6143 for (
unsigned I = 0; I < VariableImplicitInfo::DefaultmapKindNum; ++I) {
6144 int ClauseKindCnt = -1;
6145 for (
unsigned J = 0; J < VariableImplicitInfo::MapKindNum; ++J) {
6148 if (ImplicitMap.empty())
6154 nullptr, ImpInfo.MapModifiers[I], ImplicitMapModifiersLoc[I],
6155 MapperIdScopeSpec, MapperId, K,
true,
6158 ClausesWithImplicit.emplace_back(
Implicit);
6159 ErrorFound |= cast<OMPMapClause>(
Implicit)->varlist_size() !=
6170 ClausesWithImplicit);
6180 VarsWithInheritedDSA);
6191 assert(ClausesWithImplicit.empty() &&
6192 "reverse directive does not support any clauses");
6195 case OMPD_interchange:
6201 VarsWithInheritedDSA);
6205 EndLoc, VarsWithInheritedDSA);
6212 assert(ClausesWithImplicit.empty() &&
6213 "No clauses are allowed for 'omp section' directive");
6221 assert(ClausesWithImplicit.empty() &&
6222 "No clauses are allowed for 'omp master' directive");
6233 case OMPD_parallel_for:
6235 EndLoc, VarsWithInheritedDSA);
6237 case OMPD_parallel_for_simd:
6239 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6245 case OMPD_parallel_master:
6249 case OMPD_parallel_masked:
6253 case OMPD_parallel_sections:
6261 case OMPD_taskyield:
6262 assert(ClausesWithImplicit.empty() &&
6263 "No clauses are allowed for 'omp taskyield' directive");
6264 assert(AStmt ==
nullptr &&
6265 "No associated statement allowed for 'omp taskyield' directive");
6269 assert(AStmt ==
nullptr &&
6270 "No associated statement allowed for 'omp error' directive");
6274 assert(ClausesWithImplicit.empty() &&
6275 "No clauses are allowed for 'omp barrier' directive");
6276 assert(AStmt ==
nullptr &&
6277 "No associated statement allowed for 'omp barrier' directive");
6281 assert(AStmt ==
nullptr &&
6282 "No associated statement allowed for 'omp taskwait' directive");
6285 case OMPD_taskgroup:
6290 assert(AStmt ==
nullptr &&
6291 "No associated statement allowed for 'omp flush' directive");
6295 assert(AStmt ==
nullptr &&
6296 "No associated statement allowed for 'omp depobj' directive");
6300 assert(AStmt ==
nullptr &&
6301 "No associated statement allowed for 'omp scan' directive");
6320 case OMPD_target_parallel:
6324 case OMPD_target_parallel_for:
6326 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6328 case OMPD_cancellation_point:
6329 assert(ClausesWithImplicit.empty() &&
6330 "No clauses are allowed for 'omp cancellation point' directive");
6331 assert(AStmt ==
nullptr &&
"No associated statement allowed for 'omp "
6332 "cancellation point' directive");
6336 assert(AStmt ==
nullptr &&
6337 "No associated statement allowed for 'omp cancel' directive");
6341 case OMPD_target_data:
6345 case OMPD_target_enter_data:
6349 case OMPD_target_exit_data:
6355 EndLoc, VarsWithInheritedDSA);
6357 case OMPD_taskloop_simd:
6359 EndLoc, VarsWithInheritedDSA);
6361 case OMPD_master_taskloop:
6363 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6365 case OMPD_masked_taskloop:
6367 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6369 case OMPD_master_taskloop_simd:
6371 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6373 case OMPD_masked_taskloop_simd:
6375 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6377 case OMPD_parallel_master_taskloop:
6379 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6381 case OMPD_parallel_masked_taskloop:
6383 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6385 case OMPD_parallel_master_taskloop_simd:
6387 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6389 case OMPD_parallel_masked_taskloop_simd:
6391 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6393 case OMPD_distribute:
6395 EndLoc, VarsWithInheritedDSA);
6397 case OMPD_target_update:
6401 case OMPD_distribute_parallel_for:
6403 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6405 case OMPD_distribute_parallel_for_simd:
6407 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6409 case OMPD_distribute_simd:
6411 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6413 case OMPD_target_parallel_for_simd:
6415 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6417 case OMPD_target_simd:
6419 EndLoc, VarsWithInheritedDSA);
6421 case OMPD_teams_distribute:
6423 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6425 case OMPD_teams_distribute_simd:
6427 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6429 case OMPD_teams_distribute_parallel_for_simd:
6431 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6433 case OMPD_teams_distribute_parallel_for:
6435 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6437 case OMPD_target_teams:
6441 case OMPD_target_teams_distribute:
6443 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6445 case OMPD_target_teams_distribute_parallel_for:
6447 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6449 case OMPD_target_teams_distribute_parallel_for_simd:
6451 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6453 case OMPD_target_teams_distribute_simd:
6455 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6458 assert(AStmt ==
nullptr &&
6459 "No associated statement allowed for 'omp interop' directive");
6468 EndLoc, VarsWithInheritedDSA);
6470 case OMPD_teams_loop:
6472 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6474 case OMPD_target_teams_loop:
6476 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6478 case OMPD_parallel_loop:
6480 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6482 case OMPD_target_parallel_loop:
6484 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6486 case OMPD_declare_target:
6487 case OMPD_end_declare_target:
6488 case OMPD_threadprivate:
6490 case OMPD_declare_reduction:
6491 case OMPD_declare_mapper:
6492 case OMPD_declare_simd:
6494 case OMPD_declare_variant:
6495 case OMPD_begin_declare_variant:
6496 case OMPD_end_declare_variant:
6497 llvm_unreachable(
"OpenMP Directive is not allowed");
6500 llvm_unreachable(
"Unknown OpenMP directive");
6503 ErrorFound = Res.
isInvalid() || ErrorFound;
6507 if (
DSAStack->getDefaultDSA() == DSA_none ||
6508 DSAStack->getDefaultDSA() == DSA_private ||
6509 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6512 switch (
C->getClauseKind()) {
6513 case OMPC_num_threads:
6514 case OMPC_dist_schedule:
6521 cast<OMPIfClause>(
C)->getNameModifier() != OMPD_target)
6525 cast<OMPIfClause>(
C)->getNameModifier() != OMPD_parallel)
6531 case OMPC_grainsize:
6532 case OMPC_num_tasks:
6535 case OMPC_novariants:
6536 case OMPC_nocontext:
6543 case OMPC_num_teams:
6544 case OMPC_thread_limit:
6551 case OMPC_proc_bind:
6553 case OMPC_firstprivate:
6554 case OMPC_lastprivate:
6556 case OMPC_reduction:
6557 case OMPC_task_reduction:
6558 case OMPC_in_reduction:
6562 case OMPC_copyprivate:
6565 case OMPC_mergeable:
6582 case OMPC_defaultmap:
6585 case OMPC_use_device_ptr:
6586 case OMPC_use_device_addr:
6587 case OMPC_is_device_ptr:
6588 case OMPC_has_device_addr:
6589 case OMPC_nontemporal:
6592 case OMPC_inclusive:
6593 case OMPC_exclusive:
6594 case OMPC_uses_allocators:
6599 case OMPC_allocator:
6602 case OMPC_threadprivate:
6605 case OMPC_unified_address:
6606 case OMPC_unified_shared_memory:
6607 case OMPC_reverse_offload:
6608 case OMPC_dynamic_allocators:
6609 case OMPC_atomic_default_mem_order:
6610 case OMPC_device_type:
6617 llvm_unreachable(
"Unexpected clause");
6619 for (
Stmt *CC :
C->children()) {
6621 DSAChecker.Visit(CC);
6624 for (
const auto &
P : DSAChecker.getVarsWithInheritedDSA())
6625 VarsWithInheritedDSA[
P.getFirst()] =
P.getSecond();
6627 for (
const auto &
P : VarsWithInheritedDSA) {
6628 if (
P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(
P.getFirst()))
6631 if (
DSAStack->getDefaultDSA() == DSA_none ||
6632 DSAStack->getDefaultDSA() == DSA_private ||
6633 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6634 Diag(
P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6635 <<
P.first <<
P.second->getSourceRange();
6636 Diag(
DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6638 Diag(
P.second->getExprLoc(),
6639 diag::err_omp_defaultmap_no_attr_for_variable)
6640 <<
P.first <<
P.second->getSourceRange();
6642 diag::note_omp_defaultmap_attr_none);
6648 if (isAllowedClauseForDirective(
D, OMPC_if,
getLangOpts().OpenMP))
6649 AllowedNameModifiers.push_back(
D);
6651 if (!AllowedNameModifiers.empty())
6665 DSAStack->addTargetDirLocation(StartLoc);
6676 assert(Aligneds.size() == Alignments.size());
6677 assert(Linears.size() == LinModifiers.size());
6678 assert(Linears.size() == Steps.size());
6679 if (!DG || DG.
get().isNull())
6682 const int SimdId = 0;
6683 if (!DG.
get().isSingleDecl()) {
6684 Diag(SR.
getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6688 Decl *ADecl = DG.
get().getSingleDecl();
6689 if (
auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6690 ADecl = FTD->getTemplatedDecl();
6692 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6694 Diag(ADecl->
getLocation(), diag::err_omp_function_expected) << SimdId;
6710 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6711 const Expr *UniformedLinearThis =
nullptr;
6712 for (
const Expr *
E : Uniforms) {
6714 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
E))
6715 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
6716 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6717 FD->getParamDecl(PVD->getFunctionScopeIndex())
6719 UniformedArgs.try_emplace(PVD->getCanonicalDecl(),
E);
6722 if (isa<CXXThisExpr>(
E)) {
6723 UniformedLinearThis =
E;
6727 << FD->
getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6737 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6738 const Expr *AlignedThis =
nullptr;
6739 for (
const Expr *
E : Aligneds) {
6741 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
E))
6742 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6744 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6745 FD->getParamDecl(PVD->getFunctionScopeIndex())
6749 if (AlignedArgs.count(CanonPVD) > 0) {
6751 << 1 << getOpenMPClauseName(OMPC_aligned)
6753 Diag(AlignedArgs[CanonPVD]->getExprLoc(),
6754 diag::note_omp_explicit_dsa)
6755 << getOpenMPClauseName(OMPC_aligned);
6758 AlignedArgs[CanonPVD] =
E;
6760 .getNonReferenceType()
6761 .getUnqualifiedType()
6762 .getCanonicalType();
6767 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
6772 if (isa<CXXThisExpr>(
E)) {
6777 << getOpenMPClauseName(OMPC_aligned);
6783 << FD->
getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6790 for (
Expr *
E : Alignments) {
6794 NewAligns.push_back(Align.
get());
6805 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
6806 const bool IsUniformedThis = UniformedLinearThis !=
nullptr;
6807 auto MI = LinModifiers.begin();
6808 for (
const Expr *
E : Linears) {
6812 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
E))
6813 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6815 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6816 FD->getParamDecl(PVD->getFunctionScopeIndex())
6820 if (LinearArgs.count(CanonPVD) > 0) {
6822 << getOpenMPClauseName(OMPC_linear)
6824 Diag(LinearArgs[CanonPVD]->getExprLoc(),
6825 diag::note_omp_explicit_dsa)
6826 << getOpenMPClauseName(OMPC_linear);
6830 if (UniformedArgs.count(CanonPVD) > 0) {
6832 << getOpenMPClauseName(OMPC_linear)
6834 Diag(UniformedArgs[CanonPVD]->getExprLoc(),
6835 diag::note_omp_explicit_dsa)
6836 << getOpenMPClauseName(OMPC_uniform);
6839 LinearArgs[CanonPVD] =
E;
6845 PVD->getOriginalType(),
6850 if (isa<CXXThisExpr>(
E)) {
6851 if (UniformedLinearThis) {
6853 << getOpenMPClauseName(OMPC_linear)
6854 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform : OMPC_linear)
6856 Diag(UniformedLinearThis->
getExprLoc(), diag::note_omp_explicit_dsa)
6857 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform
6861 UniformedLinearThis =
E;
6870 << FD->
getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6872 Expr *Step =
nullptr;
6873 Expr *NewStep =
nullptr;
6875 for (
Expr *
E : Steps) {
6877 if (Step ==
E || !
E) {
6878 NewSteps.push_back(
E ? NewStep :
nullptr);
6882 if (
const auto *DRE = dyn_cast<DeclRefExpr>(Step))
6883 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6885 if (UniformedArgs.count(CanonPVD) == 0) {
6892 NewSteps.push_back(Step);
6911 NewSteps.push_back(NewStep);
6913 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
6915 Uniforms.size(),
const_cast<Expr **
>(Aligneds.data()), Aligneds.size(),
6916 const_cast<Expr **
>(NewAligns.data()), NewAligns.size(),
6917 const_cast<Expr **
>(Linears.data()), Linears.size(),
6918 const_cast<unsigned *
>(LinModifiers.data()), LinModifiers.size(),
6919 NewSteps.data(), NewSteps.size(), SR);
6929 "Unexpected directive category");
6938 llvm_unreachable(
"Unknown OpenMP directive");
6947 "Expected function type with prototype.");
6949 "Expected function with type with no prototype.");
6951 "Expected function with prototype.");
6959 Param->setScopeInfo(0, Params.size());
6960 Param->setImplicit();
6961 Params.push_back(Param);
6964 FD->setParams(Params);
6971 if (
auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(
D))
6972 FD = UTemplDecl->getTemplatedDecl();
6974 FD = cast<FunctionDecl>(
D);
6975 assert(FD &&
"Expected a function declaration!");
6981 for (OMPAssumeAttr *AA : OMPAssumeScoped)
6984 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
6988SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(
OMPTraitInfo &TI)
6989 : TI(&TI), NameSuffix(TI.getMangledName()) {}
6994 if (!
D.getIdentifier())
6997 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7000 bool IsTemplated = !TemplateParamLists.empty();
7002 !DVScope.TI->isExtensionActive(
7003 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7020 for (
auto *Candidate : Lookup) {
7021 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7023 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7024 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7025 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7026 UDecl = FTD->getTemplatedDecl();
7027 }
else if (!IsTemplated)
7028 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7042 FType, UDeclTy,
false,
7049 Bases.push_back(UDecl);
7052 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7053 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7055 if (Bases.empty() && UseImplicitBase) {
7059 if (
auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7060 Bases.push_back(BaseTemplD->getTemplatedDecl());
7062 Bases.push_back(cast<FunctionDecl>(BaseD));
7065 std::string MangledName;
7066 MangledName +=
D.getIdentifier()->getName();
7068 MangledName += DVScope.NameSuffix;
7083 if (
auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(
D))
7084 FD = UTemplDecl->getTemplatedDecl();
7086 FD = cast<FunctionDecl>(
D);
7092 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7093 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7099 BaseFD->addAttr(OMPDeclareVariantA);
7118 CalleeFnDecl->
getName().starts_with_insensitive(
"omp_")) {
7121 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7124 if (!CalleeFnDecl->
hasAttr<OMPDeclareVariantAttr>())
7128 std::function<void(StringRef)> DiagUnknownTrait = [
this,
7129 CE](StringRef ISATrait) {
7143 while (CalleeFnDecl) {
7144 for (OMPDeclareVariantAttr *A :
7146 Expr *VariantRef = A->getVariantFuncRef();
7148 VariantMatchInfo VMI;
7151 if (!isVariantApplicableInContext(VMI, OMPCtx,
7155 VMIs.push_back(VMI);
7156 Exprs.push_back(VariantRef);
7164 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7167 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7168 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7184 if (
auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7185 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7187 Context, MemberCall->getImplicitObjectArgument(),
7189 MemberCall->getValueKind(), MemberCall->getObjectKind());
7192 RParenLoc, ExecConfig);
7194 if (
CallExpr *NCE = dyn_cast<CallExpr>(NewCall.
get())) {
7195 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7197 CalleeFnType, NewCalleeFnDecl->
getType(),
7208 VMIs.erase(VMIs.begin() + BestIdx);
7209 Exprs.erase(Exprs.begin() + BestIdx);
7210 }
while (!VMIs.empty());
7217std::optional<std::pair<FunctionDecl *, Expr *>>
7221 unsigned NumAppendArgs,
7224 if (!DG || DG.
get().isNull())
7225 return std::nullopt;
7227 const int VariantId = 1;
7229 if (!DG.
get().isSingleDecl()) {
7230 Diag(SR.
getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7232 return std::nullopt;
7234 Decl *ADecl = DG.
get().getSingleDecl();
7235 if (
auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7236 ADecl = FTD->getTemplatedDecl();
7239 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7243 return std::nullopt;
7246 auto &&HasMultiVersionAttributes = [](
const FunctionDecl *FD) {
7249 return FD->isMultiVersion() || FD->
hasAttr<TargetAttr>();
7252 if (HasMultiVersionAttributes(FD)) {
7253 Diag(FD->
getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7255 return std::nullopt;
7260 Diag(SR.
getBegin(), diag::warn_omp_declare_variant_after_used)
7265 if (!FD->isThisDeclarationADefinition() && FD->isDefined(
Definition) &&
7267 Diag(SR.
getBegin(), diag::warn_omp_declare_variant_after_emitted)
7272 Diag(SR.
getBegin(), diag::err_omp_function_expected) << VariantId;
7273 return std::nullopt;
7276 auto ShouldDelayChecks = [](
Expr *&
E,
bool) {
7282 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef,
false) ||
7284 return std::make_pair(FD, VariantRef);
7287 auto HandleNonConstantScoresAndConditions = [
this](
Expr *&
E,
7288 bool IsScore) ->
bool {
7294 Diag(
E->
getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7302 diag::err_omp_declare_variant_user_condition_not_constant)
7308 return std::nullopt;
7311 if (NumAppendArgs) {
7314 Diag(FD->
getLocation(), diag::err_omp_declare_variant_prototype_required)
7316 return std::nullopt;
7325 TD = dyn_cast_or_null<TypeDecl>(ND);
7328 Diag(SR.
getBegin(), diag::err_omp_interop_type_not_found) << SR;
7329 return std::nullopt;
7332 if (PTy->isVariadic()) {
7333 Diag(FD->
getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7334 return std::nullopt;
7337 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7338 Params.insert(Params.end(), NumAppendArgs, InteropType);
7339 AdjustedFnType = Context.
getFunctionType(PTy->getReturnType(), Params,
7340 PTy->getExtProtoInfo());
7348 auto *Method = dyn_cast<CXXMethodDecl>(FD);
7349 if (Method && !Method->isStatic()) {
7350 const Type *ClassType =
7364 return std::nullopt;
7366 VariantRef = ER.
get();
7374 false, Sema::AllowedExplicit::None,
7380 diag::err_omp_declare_variant_incompat_types)
7382 << ((Method && !Method->isStatic()) ? FnPtrType : FD->
getType())
7384 return std::nullopt;
7390 return std::nullopt;
7393 if (Method && !Method->isStatic()) {
7394 Expr *PossibleAddrOfVariantRef = VariantRefCast.
get();
7395 if (
auto *UO = dyn_cast<UnaryOperator>(
7397 VariantRefCast = UO->getSubExpr();
7406 return std::nullopt;
7414 return std::nullopt;
7416 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7420 return std::nullopt;
7425 diag::err_omp_declare_variant_same_base_function)
7427 return std::nullopt;
7436 diag::err_omp_declare_variant_incompat_types)
7437 << NewFD->getType() << FD->
getType() << (NumAppendArgs ? 1 : 0)
7439 return std::nullopt;
7444 else if (NewFD->getType()->isFunctionNoProtoType())
7450 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7452 diag::warn_omp_declare_variant_marked_as_declare_variant)
7455 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->
getRange();
7456 Diag(SR.
getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7457 return std::nullopt;
7460 enum DoesntSupport {
7469 if (
const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7470 if (CXXFD->isVirtual()) {
7473 return std::nullopt;
7476 if (isa<CXXConstructorDecl>(FD)) {
7479 return std::nullopt;
7482 if (isa<CXXDestructorDecl>(FD)) {
7485 return std::nullopt;
7489 if (FD->isDeleted()) {
7492 return std::nullopt;
7495 if (FD->isDefaulted()) {
7498 return std::nullopt;
7501 if (FD->isConstexpr()) {
7503 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7504 return std::nullopt;
7514 SemaRef.
PDiag(diag::err_omp_declare_variant_doesnt_support)),
7520 return std::nullopt;
7521 return std::make_pair(FD, cast<Expr>(DRE));
7537 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7538 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7540 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7541 VariantMatchInfo VMI;
7543 if (!llvm::is_contained(
7544 VMI.ConstructTraits,
7545 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7546 if (!AllAdjustArgs.empty())
7547 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7548 << getOpenMPClauseName(OMPC_adjust_args);
7549 if (!AppendArgs.empty())
7550 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7551 << getOpenMPClauseName(OMPC_append_args);
7561 for (
Expr *
E : AllAdjustArgs) {
7563 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
E)) {
7564 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7566 if (FD->
getNumParams() > PVD->getFunctionScopeIndex() &&
7570 if (!AdjustVars.insert(CanonPVD).second) {
7571 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7580 Diag(
E->
getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7584 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7586 const_cast<Expr **
>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7587 const_cast<Expr **
>(AdjustArgsNeedDevicePtr.data()),
7588 AdjustArgsNeedDevicePtr.size(),
7589 const_cast<OMPInteropInfo *
>(AppendArgs.data()), AppendArgs.size(), SR);
7595 auto *CS = dyn_cast<CapturedStmt>(AStmt);
7596 assert(CS &&
"Captured statement expected");
7605 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7634struct LoopIterationSpace final {
7637 bool IsStrictCompare =
false;
7639 Expr *PreCond =
nullptr;
7642 Expr *NumIterations =
nullptr;
7644 Expr *CounterVar =
nullptr;
7646 Expr *PrivateCounterVar =
nullptr;
7648 Expr *CounterInit =
nullptr;
7651 Expr *CounterStep =
nullptr;
7653 bool Subtract =
false;
7663 Expr *MinValue =
nullptr;
7667 Expr *MaxValue =
nullptr;
7669 bool IsNonRectangularLB =
false;
7671 bool IsNonRectangularUB =
false;
7674 unsigned LoopDependentIdx = 0;
7678 Expr *FinalCondition =
nullptr;
7685 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7686 VarDecl *ForbiddenVar =
nullptr;
7690 explicit ForSubExprChecker(
7691 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
7692 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
7695 ShouldVisitImplicitCode =
true;
7700 if (!isa<VarDecl, BindingDecl>(VD))
7703 if (
V->getType()->isReferenceType()) {
7713 Decl *Canon =
V->getCanonicalDecl();
7714 if (CollapsedLoopVarDecls.contains(Canon)) {
7723 VarDecl *getForbiddenVar()
const {
return ForbiddenVar; }
7724 SourceRange getErrRange()
const {
return ErrLoc; }
7730class OpenMPIterationSpaceChecker {
7734 bool SupportsNonRectangular;
7742 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7752 Expr *LCRef =
nullptr;
7758 Expr *Step =
nullptr;
7765 std::optional<bool> TestIsLessOp;
7767 bool TestIsStrictOp =
false;
7769 bool SubtractStep =
false;
7774 std::optional<unsigned> InitDependOnLC;
7777 std::optional<unsigned> CondDependOnLC;
7779 std::optional<unsigned> doesDependOnLoopCounter(
const Stmt *S,
7780 bool IsInitializer);
7786 OpenMPIterationSpaceChecker(
7787 Sema &SemaRef,
bool SupportsNonRectangular, DSAStackTy &Stack,
7789 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls)
7790 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
7791 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
7792 CollapsedLoopVarDecls(CollapsedLoopDecls) {}
7795 bool checkAndSetInit(
Stmt *S,
bool EmitDiags =
true);
7798 bool checkAndSetCond(
Expr *S);
7801 bool checkAndSetInc(
Expr *S);
7803 ValueDecl *getLoopDecl()
const {
return LCDecl; }
7805 Expr *getLoopDeclRefExpr()
const {
return LCRef; }
7807 SourceRange getInitSrcRange()
const {
return InitSrcRange; }
7809 SourceRange getConditionSrcRange()
const {
return ConditionSrcRange; }
7811 SourceRange getIncrementSrcRange()
const {
return IncrementSrcRange; }
7813 bool shouldSubtractStep()
const {
return SubtractStep; }
7815 bool isStrictTestOp()
const {
return TestIsStrictOp; }
7817 Expr *buildNumIterations(
7819 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
7823 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
7826 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7827 DSAStackTy &DSA)
const;
7830 Expr *buildPrivateCounterVar()
const;
7834 Expr *buildCounterStep()
const;
7838 buildOrderedLoopData(
Scope *S,
Expr *Counter,
7839 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7843 std::pair<Expr *, Expr *> buildMinMaxValues(
7844 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
7846 Expr *buildFinalCondition(
Scope *S)
const;
7848 bool dependent()
const;
7850 bool doesInitDependOnLC()
const {
return InitDependOnLC.has_value(); }
7852 bool doesCondDependOnLC()
const {
return CondDependOnLC.has_value(); }
7854 unsigned getLoopDependentIdx()
const {
7855 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
7861 bool checkAndSetIncRHS(
Expr *RHS);
7866 bool setUB(
Expr *NewUB, std::optional<bool> LessOp,
bool StrictOp,
7869 bool setStep(
Expr *NewStep,
bool Subtract);
7872bool OpenMPIterationSpaceChecker::dependent()
const {
7874 assert(!LB && !UB && !Step);
7882bool OpenMPIterationSpaceChecker::setLCDeclAndLB(
ValueDecl *NewLCDecl,
7884 Expr *NewLB,
bool EmitDiags) {
7886 assert(LCDecl ==
nullptr && LB ==
nullptr && LCRef ==
nullptr &&
7887 UB ==
nullptr && Step ==
nullptr && !TestIsLessOp && !TestIsStrictOp);
7891 LCRef = NewLCRefExpr;
7892 if (
auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
7894 if ((Ctor->isCopyOrMoveConstructor() ||
7895 Ctor->isConvertingConstructor(
false)) &&
7896 CE->getNumArgs() > 0 && CE->getArg(0) !=
nullptr)
7900 InitDependOnLC = doesDependOnLoopCounter(LB,
true);
7904bool OpenMPIterationSpaceChecker::setUB(
Expr *NewUB, std::optional<bool> LessOp,
7908 assert(LCDecl !=
nullptr && LB !=
nullptr && UB ==
nullptr &&
7909 Step ==
nullptr && !TestIsLessOp && !TestIsStrictOp);
7914 TestIsLessOp = LessOp;
7915 TestIsStrictOp = StrictOp;
7916 ConditionSrcRange = SR;
7918 CondDependOnLC = doesDependOnLoopCounter(UB,
false);
7922bool OpenMPIterationSpaceChecker::setStep(
Expr *NewStep,
bool Subtract) {
7924 assert(LCDecl !=
nullptr && LB !=
nullptr && Step ==
nullptr);
7934 NewStep = Val.
get();
7947 std::optional<llvm::APSInt>
Result =
7958 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
7959 if (UB && (IsConstZero ||
7960 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
7961 : (IsConstPos || (IsUnsigned && !Subtract))))) {
7963 diag::err_omp_loop_incr_not_compatible)
7965 SemaRef.
Diag(ConditionLoc,
7966 diag::note_omp_loop_cond_requires_compatible_incr)
7967 << *TestIsLessOp << ConditionSrcRange;
7970 if (*TestIsLessOp == Subtract) {
7974 Subtract = !Subtract;
7979 SubtractStep = Subtract;
7986class LoopCounterRefChecker final
7993 bool IsInitializer =
true;
7994 bool SupportsNonRectangular;
7995 unsigned BaseLoopId = 0;
7998 SemaRef.Diag(
E->
getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
7999 << (IsInitializer ? 0 : 1);
8002 const auto &&
Data = Stack.isLoopControlVariable(VD);
8008 llvm::raw_svector_ostream OS(Name);
8012 diag::err_omp_wrong_dependency_iterator_type)
8014 SemaRef.Diag(VD->
getLocation(), diag::note_previous_decl) << VD;
8017 if (
Data.first && !SupportsNonRectangular) {
8018 SemaRef.Diag(
E->
getExprLoc(), diag::err_omp_invariant_dependency);
8022 (DepDecl || (PrevDepDecl &&
8024 if (!DepDecl && PrevDepDecl)
8025 DepDecl = PrevDepDecl;
8027 llvm::raw_svector_ostream OS(Name);
8031 diag::err_omp_invariant_or_linear_dependency)
8037 BaseLoopId =
Data.first;
8045 if (isa<VarDecl>(VD))
8046 return checkDecl(
E, VD);
8052 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8053 return checkDecl(
E, VD);
8057 bool VisitStmt(
const Stmt *S) {
8059 for (
const Stmt *Child : S->children())
8060 Res = (Child && Visit(Child)) || Res;
8063 explicit LoopCounterRefChecker(
Sema &SemaRef, DSAStackTy &Stack,
8064 const ValueDecl *CurLCDecl,
bool IsInitializer,
8066 bool SupportsNonRectangular =
true)
8067 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8068 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8069 SupportsNonRectangular(SupportsNonRectangular) {}
8070 unsigned getBaseLoopId()
const {
8071 assert(CurLCDecl &&
"Expected loop dependency.");
8075 assert(CurLCDecl &&
"Expected loop dependency.");
8081std::optional<unsigned>
8082OpenMPIterationSpaceChecker::doesDependOnLoopCounter(
const Stmt *S,
8083 bool IsInitializer) {
8085 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8086 DepDecl, SupportsNonRectangular);
8087 if (LoopStmtChecker.Visit(S)) {
8088 DepDecl = LoopStmtChecker.getDepDecl();
8089 return LoopStmtChecker.getBaseLoopId();
8091 return std::nullopt;
8094bool OpenMPIterationSpaceChecker::checkAndSetInit(
Stmt *S,
bool EmitDiags) {
8105 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8109 if (
auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8110 if (!ExprTemp->cleanupsHaveSideEffects())
8111 S = ExprTemp->getSubExpr();
8113 if (!CollapsedLoopVarDecls.empty()) {
8114 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8115 if (!FSEC.TraverseStmt(S)) {
8117 SemaRef.Diag(
Range.
getBegin(), diag::err_omp_loop_bad_collapse_var)
8123 InitSrcRange = S->getSourceRange();
8124 if (
Expr *
E = dyn_cast<Expr>(S))
8126 if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8127 if (BO->getOpcode() == BO_Assign) {
8129 if (
auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8130 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->
getDecl()))
8132 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8134 return setLCDeclAndLB(DRE->
getDecl(), DRE, BO->getRHS(), EmitDiags);
8136 if (
auto *ME = dyn_cast<MemberExpr>(LHS)) {
8137 if (ME->isArrow() &&
8138 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8139 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8143 }
else if (
auto *DS = dyn_cast<DeclStmt>(S)) {
8144 if (DS->isSingleDecl()) {
8145 if (
auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8146 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8149 SemaRef.Diag(S->getBeginLoc(),
8150 diag::ext_omp_loop_not_canonical_init)
8151 << S->getSourceRange();
8152 return setLCDeclAndLB(
8155 Var->getType().getNonReferenceType(),
8157 Var->getInit(), EmitDiags);
8161 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8162 if (CE->getOperator() == OO_Equal) {
8163 Expr *LHS = CE->getArg(0);
8164 if (
auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8165 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->
getDecl()))
8167 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8169 return setLCDeclAndLB(DRE->
getDecl(), DRE, CE->getArg(1), EmitDiags);
8171 if (
auto *ME = dyn_cast<MemberExpr>(LHS)) {
8172 if (ME->isArrow() &&
8173 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8174 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8180 if (dependent() || SemaRef.CurContext->isDependentContext())
8183 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8184 << S->getSourceRange();
8195 if (
const auto *CE = dyn_cast_or_null<CXXConstructExpr>(
E))
8197 if ((Ctor->isCopyOrMoveConstructor() ||
8198 Ctor->isConvertingConstructor(
false)) &&
8199 CE->getNumArgs() > 0 && CE->getArg(0) !=
nullptr)
8201 if (
const auto *DRE = dyn_cast_or_null<DeclRefExpr>(
E)) {
8202 if (
const auto *VD = dyn_cast<VarDecl>(DRE->
getDecl()))
8205 if (
const auto *ME = dyn_cast_or_null<MemberExpr>(
E))
8206 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8211bool OpenMPIterationSpaceChecker::checkAndSetCond(
Expr *S) {
8218 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8220 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8221 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8227 if (!CollapsedLoopVarDecls.empty()) {
8228 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8229 if (!FSEC.TraverseStmt(S)) {
8231 SemaRef.Diag(
Range.
getBegin(), diag::err_omp_loop_bad_collapse_var)
8238 auto &&CheckAndSetCond =
8243 if (getInitLCDecl(LHS) == LCDecl)
8244 return setUB(
const_cast<Expr *
>(RHS),
8246 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8247 if (getInitLCDecl(RHS) == LCDecl)
8248 return setUB(
const_cast<Expr *
>(LHS),
8250 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8251 }
else if (IneqCondIsCanonical && Opcode == BO_NE) {
8252 return setUB(
const_cast<Expr *
>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8256 return std::nullopt;
8258 std::optional<bool> Res;
8259 if (
auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8262 RBO->getOperatorLoc());
8263 }
else if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8264 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8265 BO->getSourceRange(), BO->getOperatorLoc());
8266 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8267 if (CE->getNumArgs() == 2) {
8268 Res = CheckAndSetCond(
8270 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8275 if (dependent() || SemaRef.CurContext->isDependentContext())
8277 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8278 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8282bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(
Expr *RHS) {
8289 if (
auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8290 if (BO->isAdditiveOp()) {
8291 bool IsAdd = BO->getOpcode() == BO_Add;
8292 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8293 return setStep(BO->getRHS(), !IsAdd);
8294 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8295 return setStep(BO->getLHS(),
false);
8297 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8298 bool IsAdd = CE->getOperator() == OO_Plus;
8299 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8300 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8301 return setStep(CE->getArg(1), !IsAdd);
8302 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8303 return setStep(CE->getArg(0),
false);
8306 if (dependent() || SemaRef.CurContext->isDependentContext())
8308 SemaRef.Diag(RHS->
getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8313bool OpenMPIterationSpaceChecker::checkAndSetInc(
Expr *S) {
8328 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8331 if (
auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8332 if (!ExprTemp->cleanupsHaveSideEffects())
8333 S = ExprTemp->getSubExpr();
8335 if (!CollapsedLoopVarDecls.empty()) {
8336 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8337 if (!FSEC.TraverseStmt(S)) {
8339 SemaRef.Diag(
Range.
getBegin(), diag::err_omp_loop_bad_collapse_var)
8345 IncrementSrcRange = S->getSourceRange();
8346 S = S->IgnoreParens();
8347 if (
auto *UO = dyn_cast<UnaryOperator>(S)) {
8348 if (UO->isIncrementDecrementOp() &&
8349 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8350 return setStep(SemaRef
8351 .ActOnIntegerConstant(UO->getBeginLoc(),
8352 (UO->isDecrementOp() ? -1 : 1))
8355 }
else if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8356 switch (BO->getOpcode()) {
8359 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8360 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8363 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8364 return checkAndSetIncRHS(BO->getRHS());
8369 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8370 switch (CE->getOperator()) {
8373 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8374 return setStep(SemaRef
8375 .ActOnIntegerConstant(
8377 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8383 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8384 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8387 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8388 return checkAndSetIncRHS(CE->getArg(1));
8394 if (dependent() || SemaRef.CurContext->isDependentContext())
8396 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8397 << S->getSourceRange() << LCDecl;
8403 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8404 StringRef Name =
".capture_expr.") {
8412 auto I = Captures.find(
Capture);
8413 if (I != Captures.end())
8426 bool TestIsStrictOp,
bool RoundToStep,
8427 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8428 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures,
".new_step");
8431 llvm::APSInt LRes, SRes;
8432 bool IsLowerConst =
false, IsStepConst =
false;
8433 if (std::optional<llvm::APSInt> Res =
8436 IsLowerConst =
true;
8438 if (std::optional<llvm::APSInt> Res =
8443 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8444 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8445 (TestIsStrictOp && LRes.isStrictlyPositive()));
8446 bool NeedToReorganize =
false;
8448 if (!NoNeedToConvert && IsLowerConst &&
8449 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8450 NoNeedToConvert =
true;
8452 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8453 ? LRes.getBitWidth()
8454 : SRes.getBitWidth();
8455 LRes = LRes.extend(BW + 1);
8456 LRes.setIsSigned(
true);
8457 SRes = SRes.extend(BW + 1);
8458 SRes.setIsSigned(
true);
8460 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8461 LRes = LRes.trunc(BW);
8463 if (TestIsStrictOp) {
8464 unsigned BW = LRes.getBitWidth();
8465 LRes = LRes.extend(BW + 1);
8466 LRes.setIsSigned(
true);
8469 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8471 LRes = LRes.trunc(BW);
8473 NeedToReorganize = NoNeedToConvert;
8476 bool IsUpperConst =
false;
8477 if (std::optional<llvm::APSInt> Res =
8480 IsUpperConst =
true;
8482 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8483 (!RoundToStep || IsStepConst)) {
8484 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8485 : URes.getBitWidth();
8486 LRes = LRes.extend(BW + 1);
8487 LRes.setIsSigned(
true);
8488 URes = URes.extend(BW + 1);
8489 URes.setIsSigned(
true);
8491 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8492 NeedToReorganize = NoNeedToConvert;
8497 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8503 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8506 LowerSize > UpperSize ? LowerSize : UpperSize, 0);
8517 if (!Lower || !Upper || NewStep.
isInvalid())
8523 if (NeedToReorganize) {
8537 S, DefaultLoc, BO_Add, Diff.
get(),
8547 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.
get());
8551 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8567 S, DefaultLoc, BO_Sub, Diff.
get(),
8587 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Div, Diff.
get(), NewStep.
get());
8595Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8597 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
8606 if (InitDependOnLC) {
8607 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8608 if (!IS.MinValue || !IS.MaxValue)
8617 IS.CounterVar, MinValue.
get());
8622 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.
get(), LBVal);
8637 IS.CounterVar, MaxValue.
get());
8642 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.
get(), LBVal);
8651 tryBuildCapture(SemaRef, LBMinVal.
get(), Captures,
".lb_min").get();
8653 tryBuildCapture(SemaRef, LBMaxVal.
get(), Captures,
".lb_max").get();
8654 if (!LBMin || !LBMax)
8658 SemaRef.
BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8662 tryBuildCapture(SemaRef, MinLessMaxRes.
get(), Captures,
".min_less_max")
8666 if (*TestIsLessOp) {
8670 MinLessMax, LBMin, LBMax);
8673 LBVal = MinLB.
get();
8678 MinLessMax, LBMax, LBMin);
8681 LBVal = MaxLB.
get();
8685 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8688 LBVal = LBMinVal.
get();
8692 if (CondDependOnLC) {
8693 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8694 if (!IS.MinValue || !IS.MaxValue)
8703 IS.CounterVar, MinValue.
get());
8708 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.
get(), UBVal);
8723 IS.CounterVar, MaxValue.
get());
8728 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.
get(), UBVal);
8737 tryBuildCapture(SemaRef, UBMinVal.
get(), Captures,
".ub_min").get();
8739 tryBuildCapture(SemaRef, UBMaxVal.
get(), Captures,
".ub_max").get();
8740 if (!UBMin || !UBMax)
8744 SemaRef.
BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
8747 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.
get(),
8748 Captures,
".min_greater_max")
8752 if (*TestIsLessOp) {
8756 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
8759 UBVal = MaxUB.
get();
8764 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
8767 UBVal = MinUB.
get();
8770 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
8771 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
8772 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures,
".upper").get();
8773 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures,
".lower").get();
8774 if (!Upper || !Lower)
8777 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8778 Step, VarType, TestIsStrictOp,
8787 C.getTypeSize(
Type) >
C.getTypeSize(VarType);
8790 UseVarType ?
C.getTypeSize(VarType) :
C.getTypeSize(
Type);
8793 Type =
C.getIntTypeForBitwidth(NewSize, IsSigned);
8803 unsigned NewSize = (
C.getTypeSize(
Type) > 32) ? 64 : 32;
8804 if (NewSize !=
C.getTypeSize(
Type)) {
8805 if (NewSize <
C.getTypeSize(
Type)) {
8806 assert(NewSize == 64 &&
"incorrect loop var size");
8807 SemaRef.
Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
8808 << InitSrcRange << ConditionSrcRange;
8810 QualType NewType =
C.getIntTypeForBitwidth(
8812 C.getTypeSize(
Type) < NewSize);
8826std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
8827 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
8831 return std::make_pair(
nullptr,
nullptr);
8834 Expr *MinExpr =
nullptr;
8835 Expr *MaxExpr =
nullptr;
8836 Expr *LBExpr = *TestIsLessOp ? LB : UB;
8837 Expr *UBExpr = *TestIsLessOp ? UB : LB;
8839 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
8841 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
8843 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
8845 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
8846 if (!Upper || !Lower)
8847 return std::make_pair(
nullptr,
nullptr);
8857 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8858 Step, VarType, TestIsStrictOp,
8861 return std::make_pair(
nullptr,
nullptr);
8867 return std::make_pair(
nullptr,
nullptr);
8869 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures,
".new_step");
8871 return std::make_pair(
nullptr,
nullptr);
8872 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Mul, Diff.
get(), NewStep.
get());
8874 return std::make_pair(
nullptr,
nullptr);
8879 return std::make_pair(
nullptr,
nullptr);
8891 return std::make_pair(
nullptr,
nullptr);
8893 if (*TestIsLessOp) {
8897 S, DefaultLoc, BO_Add,
8901 return std::make_pair(
nullptr,
nullptr);
8906 S, DefaultLoc, BO_Sub,
8910 return std::make_pair(
nullptr,
nullptr);
8919 return std::make_pair(
nullptr,
nullptr);
8924 return std::make_pair(
nullptr,
nullptr);
8927 MaxExpr = Diff.
get();
8929 MinExpr = Diff.
get();
8931 return std::make_pair(MinExpr, MaxExpr);
8934Expr *OpenMPIterationSpaceChecker::buildFinalCondition(
Scope *S)
const {
8935 if (InitDependOnLC || CondDependOnLC)
8940Expr *OpenMPIterationSpaceChecker::buildPreCond(
8942 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
8947 if (CondDependOnLC || InitDependOnLC)
8958 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
8959 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
8965 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
8966 : (TestIsStrictOp ? BO_GT : BO_GE),
8967 NewLB.
get(), NewUB.
get());
8978 return CondExpr.
isUsable() ? CondExpr.
get() : Cond;
8982DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
8983 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8984 DSAStackTy &DSA)
const {
8985 auto *VD = dyn_cast<VarDecl>(LCDecl);
8990 const DSAStackTy::DSAVarData
Data =
8991 DSA.getTopDSA(LCDecl,
false);
8995 Captures.insert(std::make_pair(LCRef, Ref));
8998 return cast<DeclRefExpr>(LCRef);
9001Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar()
const {
9007 isa<VarDecl>(LCDecl)
9018Expr *OpenMPIterationSpaceChecker::buildCounterInit()
const {
return LB; }
9021Expr *OpenMPIterationSpaceChecker::buildCounterStep()
const {
return Step; }
9023Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9031 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9032 "Expected only + or - operations for depend clauses.");
9044 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9046 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9047 if (!Upper || !Lower)
9051 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9052 false,
false, Captures);
9062 assert(
getLangOpts().OpenMP &&
"OpenMP is not active.");
9063 assert(
Init &&
"Expected loop in canonical form.");
9064 unsigned AssociatedLoops =
DSAStack->getAssociatedLoops();
9071 OpenMPIterationSpaceChecker ISC(
SemaRef,
true,
9073 if (!ISC.checkAndSetInit(
Init,
false)) {
9075 auto *VD = dyn_cast<VarDecl>(
D);
9083 VD = cast<VarDecl>(PrivateRef->
getDecl());
9086 DSAStack->addLoopControlVariable(
D, VD);
9089 DSAStack->resetPossibleLoopCounter();
9090 if (
auto *Var = dyn_cast_or_null<VarDecl>(LD))
9103 DSAStackTy::DSAVarData DVar =
9107 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9110 ? (
DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9113 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9116 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9118 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9120 IsOpenMPTaskloopDirective(DKind) ||
9123 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9124 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9125 Diag(
Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9126 << getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind)
9127 << getOpenMPClauseName(PredeterminedCKind);
9128 if (DVar.RefExpr ==
nullptr)
9129 DVar.CKind = PredeterminedCKind;
9131 }
else if (LoopDeclRefExpr) {
9136 if (DVar.CKind == OMPC_unknown)
9137 DSAStack->addDSA(
D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9141 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9146class OMPDoacrossKind {
9149 return C->getDependenceType() == OMPC_DOACROSS_source ||
9150 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9153 return C->getDependenceType() == OMPC_DOACROSS_sink;
9156 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9164 unsigned CurrentNestedLoopCount,
unsigned NestedLoopCount,
9165 unsigned TotalNestedLoopCount,
Expr *CollapseLoopCountExpr,
9166 Expr *OrderedLoopCountExpr,
9169 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9170 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls) {
9175 if (
auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9176 S = CanonLoop->getLoopStmt();
9177 auto *For = dyn_cast_or_null<ForStmt>(S);
9178 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9180 if (!For && (SemaRef.
LangOpts.OpenMP <= 45 || !CXXFor)) {
9181 SemaRef.
Diag(S->getBeginLoc(), diag::err_omp_not_for)
9182 << (CollapseLoopCountExpr !=
nullptr || OrderedLoopCountExpr !=
nullptr)
9183 << getOpenMPDirectiveName(DKind) << TotalNestedLoopCount
9184 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9185 if (TotalNestedLoopCount > 1) {
9186 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9187 SemaRef.
Diag(DSA.getConstructLoc(),
9188 diag::note_omp_collapse_ordered_expr)
9191 else if (CollapseLoopCountExpr)
9193 diag::note_omp_collapse_ordered_expr)
9195 else if (OrderedLoopCountExpr)
9197 diag::note_omp_collapse_ordered_expr)
9202 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9208 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9209 For ? For->getForLoc() : CXXFor->getForLoc(),
9210 CollapsedLoopVarDecls);
9213 Stmt *
Init = For ? For->getInit() : CXXFor->getBeginStmt();
9214 if (ISC.checkAndSetInit(
Init))
9217 bool HasErrors =
false;
9220 if (
ValueDecl *LCDecl = ISC.getLoopDecl()) {
9230 SemaRef.
Diag(
Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9244 VarsWithImplicitDSA.erase(LCDecl);
9249 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9252 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9259 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9260 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9261 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9262 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9269 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9270 ISC.buildCounterVar(Captures, DSA);
9271 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9272 ISC.buildPrivateCounterVar();
9273 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9274 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9275 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9276 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9277 ISC.getConditionSrcRange();
9278 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9279 ISC.getIncrementSrcRange();
9280 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9281 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9282 ISC.isStrictTestOp();
9283 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9284 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9285 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9286 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9287 ISC.buildFinalCondition(DSA.getCurScope());
9288 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9289 ISC.doesInitDependOnLC();
9290 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9291 ISC.doesCondDependOnLC();
9292 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9293 ISC.getLoopDependentIdx();
9296 (ResultIterSpaces[CurrentNestedLoopCount].PreCond ==
nullptr ||
9297 ResultIterSpaces[CurrentNestedLoopCount].NumIterations ==
nullptr ||
9298 ResultIterSpaces[CurrentNestedLoopCount].CounterVar ==
nullptr ||
9299 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar ==
nullptr ||
9300 ResultIterSpaces[CurrentNestedLoopCount].CounterInit ==
nullptr ||
9301 ResultIterSpaces[CurrentNestedLoopCount].CounterStep ==
nullptr);
9302 if (!HasErrors && DSA.isOrderedRegion()) {
9303 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9304 if (CurrentNestedLoopCount <
9305 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9306 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9307 CurrentNestedLoopCount,
9308 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9309 DSA.getOrderedRegionParam().second->setLoopCounter(
9310 CurrentNestedLoopCount,
9311 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9314 for (
auto &Pair : DSA.getDoacrossDependClauses()) {
9315 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9316 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9318 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9319 if (CurrentNestedLoopCount >= NumLoops) {
9323 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9324 Pair.second.size() <= CurrentNestedLoopCount) {
9326 DependC->setLoopData(CurrentNestedLoopCount,
nullptr);
9329 OMPDoacrossKind ODK;
9330 if (DoacrossC && ODK.isSink(DoacrossC) &&
9331 Pair.second.size() <= CurrentNestedLoopCount) {
9333 DoacrossC->setLoopData(CurrentNestedLoopCount,
nullptr);
9338 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9339 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9340 (DoacrossC && ODK.isSource(DoacrossC)))
9341 CntValue = ISC.buildOrderedLoopData(
9343 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9345 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9348 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9356 CntValue = ISC.buildOrderedLoopData(
9358 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9359 DepLoc, Inc, clang::OO_Minus);
9361 CntValue = ISC.buildOrderedLoopData(
9363 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9364 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9365 Pair.second[CurrentNestedLoopCount].second);
9367 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9369 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9380 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9384 : tryBuildCapture(SemaRef, Start.
get(), Captures);
9405 bool IsNonRectangularLB,
9406 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures =
nullptr) {
9415 NewStep = tryBuildCapture(SemaRef, Step.
get(), *Captures);
9430 if (Captures && !IsNonRectangularLB)
9431 NewStart = tryBuildCapture(SemaRef, Start.
get(), *Captures);
9440 Update.get()->getType()->isOverloadableType()) {
9447 SemaRef.
BuildBinOp(S,
Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9448 VarRef.
get(), SavedUpdate.
get());
9459 NewStart.
get(), SavedUpdate.
get());
9484 unsigned HasBits =
C.getTypeSize(OldType);
9485 if (HasBits >= Bits)
9488 QualType NewType =
C.getIntTypeForBitwidth(Bits,
true);
9498 if (std::optional<llvm::APSInt>
Result =
9507 if (!PreInits.empty()) {
9528 if (
auto *CS = dyn_cast<CompoundStmt>(Item))
9537 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9538 if (!Captures.empty()) {
9540 for (
const auto &Pair : Captures)
9541 PreInits.push_back(Pair.second->getDecl());
9549 if (PreInits.empty())
9553 for (
Stmt *S : PreInits)
9560 Expr *PostUpdate =
nullptr;
9561 if (!PostUpdates.empty()) {
9562 for (
Expr *
E : PostUpdates) {
9568 PostUpdate = PostUpdate
9582 int NestingDepth = 0;
9583 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
9605 if (NestingDepth > 0)
9616 Expr *OrderedLoopCountExpr,
Stmt *AStmt,
Sema &SemaRef,
9620 unsigned NestedLoopCount = 1;
9621 bool SupportsNonPerfectlyNested = (SemaRef.
LangOpts.OpenMP >= 50) &&
9625 if (CollapseLoopCountExpr) {
9630 NestedLoopCount =
Result.Val.getInt().getLimitedValue();
9633 FVDF.TraverseStmt(AStmt);
9639 unsigned OrderedLoopCount = 1;
9640 if (OrderedLoopCountExpr) {
9647 if (
Result.getLimitedValue() < NestedLoopCount) {
9649 diag::err_omp_wrong_ordered_loop_count)
9652 diag::note_collapse_loop_count)
9655 OrderedLoopCount =
Result.getLimitedValue();
9663 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9664 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9668 SupportsNonPerfectlyNested, NumLoops,
9669 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9670 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9671 &IterSpaces, &Captures,
9672 &CollapsedLoopVarDecls](
unsigned Cnt,
Stmt *CurStmt) {
9674 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9675 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9676 VarsWithImplicitDSA, IterSpaces, Captures,
9677 CollapsedLoopVarDecls))
9679 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9680 IterSpaces[Cnt].CounterVar) {
9682 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9683 if (isa<OMPCapturedExprDecl>(DRE->
getDecl())) {
9684 Captures[DRE] = DRE;
9690 Stmt *DependentPreInits = Transform->getPreInits();
9691 if (!DependentPreInits)
9698 for (
Stmt *S : Constituents) {
9699 if (
auto *DC = dyn_cast<DeclStmt>(S)) {
9700 for (
Decl *
C : DC->decls()) {
9701 auto *
D = cast<VarDecl>(
C);
9703 SemaRef,
D,
D->getType().getNonReferenceType(),
9705 Captures[Ref] = Ref;
9712 Built.
clear(NestedLoopCount);
9715 return NestedLoopCount;
9748 auto PreCond =
ExprResult(IterSpaces[0].PreCond);
9749 Expr *N0 = IterSpaces[0].NumIterations;
9768 return NestedLoopCount;
9771 bool AllCountsNeedLessThan32Bits =
C.getTypeSize(N0->
getType()) < 32;
9773 Scope *CurScope = DSA.getCurScope();
9774 for (
unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
9775 if (PreCond.isUsable()) {
9777 SemaRef.
BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
9778 PreCond.get(), IterSpaces[Cnt].PreCond);
9780 Expr *N = IterSpaces[Cnt].NumIterations;
9782 AllCountsNeedLessThan32Bits &=
C.getTypeSize(N->
getType()) < 32;
9785 CurScope,
Loc, BO_Mul, LastIteration32.
get(),
9793 CurScope,
Loc, BO_Mul, LastIteration64.
get(),
9803 if (SemaRef.
getLangOpts().OpenMPOptimisticCollapse ||
9805 C.getTypeSize(LastIteration32.
get()->
getType()) == 32 &&
9806 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
9810 LastIteration64.
get(), SemaRef))))
9811 LastIteration = LastIteration32;
9830 LastIteration.
get(),
9842 tryBuildCapture(SemaRef, LastIteration.
get(), Captures);
9843 LastIteration = SaveRef;
9856 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
9885 buildVarDecl(SemaRef, InitLoc, StrideVType,
".omp.stride");
9894 UB.
get(), LastIteration.
get());
9897 LastIteration.
get(), UB.
get());
9898 EUB = SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, UB.
get(),
9923 CurScope, InitLoc, BO_GT, CombUB.
get(), LastIteration.
get());
9926 LastIteration.
get(), CombUB.
get());
9927 CombEUB = SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.
get(),
9932 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
9936 "Unexpected number of parameters in loop combined directive");
9977 SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, IV.
get(), CombRHS);
9983 bool UseStrictCompare =
9985 llvm::all_of(IterSpaces, [](
const LoopIterationSpace &LIS) {
9986 return LIS.IsStrictCompare;
9992 if (UseStrictCompare) {
9995 .
BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
10007 UseStrictCompare ? BO_LT : BO_LE, IV.
get(),
10010 NumIterations.
get());
10013 CombDistCond = SemaRef.
BuildBinOp(CurScope, CondLoc, BO_LT, IV.
get(),
10014 NumIterations.
get());
10019 Expr *BoundCombUB = CombUB.
get();
10020 if (UseStrictCompare) {
10024 CurScope, CondLoc, BO_Add, BoundCombUB,
10032 SemaRef.
BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10033 IV.
get(), BoundCombUB);
10040 if (!Inc.isUsable())
10042 Inc = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, IV.
get(), Inc.get());
10044 if (!Inc.isUsable())
10051 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10057 NextLB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Add, LB.
get(), ST.
get());
10068 NextUB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Add, UB.
get(), ST.
get());
10084 CombNextLB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.
get(),
10096 CombNextUB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.
get(),
10110 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10113 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.
get(), BoundUB);
10114 assert(DistCond.
isUsable() &&
"distribute cond expr was not built");
10118 assert(DistInc.
isUsable() &&
"distribute inc expr was not built");
10119 DistInc = SemaRef.
BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.
get(),
10123 assert(DistInc.
isUsable() &&
"distribute inc expr was not built");
10134 DistEUBLoc, NewPrevUB.
get());
10139 UB.
get(), NewPrevUB.
get());
10141 DistEUBLoc, DistEUBLoc, IsUBGreater.
get(), NewPrevUB.
get(), UB.
get());
10142 PrevEUB = SemaRef.
BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.
get(),
10150 Expr *BoundPrevUB = PrevUB.
get();
10151 if (UseStrictCompare) {
10155 CurScope, CondLoc, BO_Add, BoundPrevUB,
10163 SemaRef.
BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10164 IV.
get(), BoundPrevUB);
10168 bool HasErrors =
false;
10169 Built.
Counters.resize(NestedLoopCount);
10170 Built.
Inits.resize(NestedLoopCount);
10171 Built.
Updates.resize(NestedLoopCount);
10172 Built.
Finals.resize(NestedLoopCount);
10193 for (
unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10194 LoopIterationSpace &IS = IterSpaces[Cnt];
10200 for (
unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10201 Prod = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.
get(),
10202 IterSpaces[K].NumIterations);
10207 if (Cnt + 1 < NestedLoopCount)
10212 if (!
Iter.isUsable()) {
10221 if (Cnt + 1 < NestedLoopCount)
10226 Acc = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.
get(), Prod.
get());
10229 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10231 SemaRef, VD, IS.CounterVar->
getType(), IS.CounterVar->getExprLoc(),
10235 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10236 if (!
Init.isUsable()) {
10241 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit,
Iter,
10242 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10243 if (!
Update.isUsable()) {
10251 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10252 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10253 if (!Final.isUsable()) {
10258 if (!
Update.isUsable() || !Final.isUsable()) {
10263 Built.
Counters[Cnt] = IS.CounterVar;
10267 Built.
Finals[Cnt] = Final.get();
10271 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10290 Built.
PreCond = PreCond.get();
10294 Built.
Inc = Inc.get();
10295 Built.
LB = LB.
get();
10296 Built.
UB = UB.
get();
10297 Built.
IL = IL.
get();
10298 Built.
ST = ST.
get();
10300 Built.
NLB = NextLB.
get();
10301 Built.
NUB = NextUB.
get();
10316 return NestedLoopCount;
10320 auto CollapseClauses =
10321 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10322 if (CollapseClauses.begin() != CollapseClauses.end())
10323 return (*CollapseClauses.begin())->getNumForLoops();
10328 auto OrderedClauses =
10329 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10330 if (OrderedClauses.begin() != OrderedClauses.end())
10331 return (*OrderedClauses.begin())->getNumForLoops();
10340 for (
const OMPClause *Clause : Clauses) {
10342 Safelen = cast<OMPSafelenClause>(Clause);
10344 Simdlen = cast<OMPSimdlenClause>(Clause);
10345 if (Safelen && Simdlen)
10349 if (Simdlen && Safelen) {
10363 llvm::APSInt SimdlenRes = SimdlenResult.
Val.
getInt();
10364 llvm::APSInt SafelenRes = SafelenResult.
Val.
getInt();
10369 if (SimdlenRes > SafelenRes) {
10371 diag::err_omp_wrong_simdlen_safelen_values)
10387 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
10394 if (NestedLoopCount == 0)
10404 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10405 return SimdDirective;
10414 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
10421 if (NestedLoopCount == 0)
10428 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10430 return ForDirective;
10441 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
10445 unsigned NestedLoopCount =
10448 VarsWithImplicitDSA, B);
10449 if (NestedLoopCount == 0)
10459 NestedLoopCount, Clauses, AStmt, B);
10463 Stmt *AStmt, DSAStackTy *Stack) {
10467 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
10468 auto BaseStmt = AStmt;
10469 while (
auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10471 if (
auto *
C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10472 auto S =
C->children();
10473 if (S.begin() == S.end())
10477 for (
Stmt *SectionStmt : llvm::drop_begin(S)) {
10478 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10480 SemaRef.
Diag(SectionStmt->getBeginLoc(),
10481 diag::err_omp_sections_substmt_not_section)
10482 << getOpenMPDirectiveName(DKind);
10485 cast<OMPSectionDirective>(SectionStmt)
10486 ->setHasCancel(Stack->isCancelRegion());
10489 SemaRef.
Diag(AStmt->
getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10490 << getOpenMPDirectiveName(DKind);
10525 if (
auto *CE = dyn_cast<CallExpr>(
E))
10526 if (CE->getDirectCallee())
10538 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10548 Expr *TargetCall =
nullptr;
10550 auto *
E = dyn_cast<Expr>(S);
10552 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10558 if (
auto *BO = dyn_cast<BinaryOperator>(
E)) {
10559 if (BO->getOpcode() == BO_Assign)
10562 if (
auto *COCE = dyn_cast<CXXOperatorCallExpr>(
E))
10563 if (COCE->getOperator() == OO_Equal)
10578 Clauses, AStmt, TargetCallLoc);
10583 DSAStackTy *Stack) {
10584 bool ErrorFound =
false;
10586 if (
auto *LPC = dyn_cast<OMPLastprivateClause>(
C)) {
10587 for (
Expr *RefExpr : LPC->varlist()) {
10590 Expr *SimpleRefExpr = RefExpr;
10593 auto &&Info = Stack->isLoopControlVariable(
D);
10595 S.
Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10596 << getOpenMPDirectiveName(K);
10625 if (NestedLoopCount == 0)
10629 "omp loop exprs were not built");
10632 NestedLoopCount, Clauses, AStmt, B);
10651 unsigned NestedLoopCount =
10654 VarsWithImplicitDSA, B);
10655 if (NestedLoopCount == 0)
10659 "omp loop exprs were not built");
10661 DSAStack->setParentTeamsRegionLoc(StartLoc);
10664 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10685 unsigned NestedLoopCount =
10688 VarsWithImplicitDSA, B);
10689 if (NestedLoopCount == 0)
10693 "omp loop exprs were not built");
10696 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10718 unsigned NestedLoopCount =
10721 VarsWithImplicitDSA, B);
10722 if (NestedLoopCount == 0)
10726 "omp loop exprs were not built");
10729 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10750 unsigned NestedLoopCount =
10753 VarsWithImplicitDSA, B);
10754 if (NestedLoopCount == 0)
10758 "omp loop exprs were not built");
10761 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10771 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
10778 const OMPClause *Copyprivate =
nullptr;
10779 for (
const OMPClause *Clause : Clauses) {
10783 Copyprivate = Clause;
10784 if (Copyprivate && Nowait) {
10786 diag::err_omp_single_copyprivate_with_nowait);
10826 bool ErrorFound =
false;
10829 bool DependentHint =
false;
10831 if (
C->getClauseKind() == OMPC_hint) {
10833 Diag(
C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
10836 Expr *
E = cast<OMPHintClause>(
C)->getHint();
10839 DependentHint =
true;
10842 HintLoc =
C->getBeginLoc();
10848 const auto Pair =
DSAStack->getCriticalWithHint(DirName);
10849 if (Pair.first && DirName.
getName() && !DependentHint) {
10850 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
10851 Diag(StartLoc, diag::err_omp_critical_with_hint);
10853 Diag(HintLoc, diag::note_omp_critical_hint_here)
10854 << 0 <<
toString(Hint, 10,
false);
10856 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
10857 if (
const auto *
C = Pair.first->getSingleClause<
OMPHintClause>()) {
10858 Diag(
C->getBeginLoc(), diag::note_omp_critical_hint_here)
10863 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
10871 EndLoc, Clauses, AStmt);
10872 if (!Pair.first && DirName.
getName() && !DependentHint)
10873 DSAStack->addCriticalWithHint(Dir, Hint);
10888 unsigned NestedLoopCount =
10891 VarsWithImplicitDSA, B);
10892 if (NestedLoopCount == 0)
10899 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10915 unsigned NestedLoopCount =
10918 VarsWithImplicitDSA, B);
10919 if (NestedLoopCount == 0)
10929 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10942 DSAStack->getTaskgroupReductionRef());
10955 DSAStack->getTaskgroupReductionRef());
10976 bool ErrorFound =
false;
10978 if (llvm::is_contained(MutuallyExclusiveClauses,
C->getClauseKind())) {
10982 S.
Diag(
C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
10983 << getOpenMPClauseName(
C->getClauseKind())
11005 {OMPC_detach, OMPC_mergeable}))
11011 AStmt,
DSAStack->isCancelRegion());
11027 bool InExContext) {
11029 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11031 if (AtC && !InExContext && AtC->
getAtKind() == OMPC_AT_execution) {
11037 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11039 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11042 if (!AtC || AtC->
getAtKind() == OMPC_AT_compilation) {
11043 if (SeverityC && SeverityC->
getSeverityKind() == OMPC_SEVERITY_warning)
11045 << (ME ? cast<StringLiteral>(ME)->getString() :
"WARNING");
11047 Diag(StartLoc, diag::err_diagnose_if_succeeded)
11048 << (ME ? cast<StringLiteral>(ME)->getString() :
"ERROR");
11049 if (!SeverityC || SeverityC->
getSeverityKind() != OMPC_SEVERITY_warning)
11060 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11062 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11064 if (NowaitC && !HasDependC) {
11065 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11080 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
11086 DSAStack->getTaskgroupReductionRef());
11095 if (
C->getClauseKind() == OMPC_flush)
11096 FC = cast<OMPFlushClause>(
C);
11103 if (
C->getClauseKind() == OMPC_acq_rel ||
11104 C->getClauseKind() == OMPC_acquire ||
11105 C->getClauseKind() == OMPC_release ||
11106 C->getClauseKind() == OMPC_seq_cst ) {
11107 if (MemOrderKind != OMPC_unknown) {
11108 Diag(
C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11109 << getOpenMPDirectiveName(OMPD_flush) << 1
11111 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11112 << getOpenMPClauseName(MemOrderKind);
11114 MemOrderKind =
C->getClauseKind();
11115 MemOrderLoc =
C->getBeginLoc();
11119 if (FC && OrderClause) {
11122 Diag(OrderClause->
getBeginLoc(), diag::note_omp_flush_order_clause_here)
11132 if (Clauses.empty()) {
11133 Diag(StartLoc, diag::err_omp_depobj_expected);
11135 }
else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11136 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11140 if (Clauses.size() > 2) {
11141 Diag(Clauses[2]->getBeginLoc(),
11142 diag::err_omp_depobj_single_clause_expected);
11144 }
else if (Clauses.size() < 1) {
11145 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11155 if (Clauses.size() != 1) {
11156 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11157 diag::err_omp_scan_single_clause_expected);
11162 Scope *ParentS = S->getParent();
11165 return StmtError(
Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11166 << getOpenMPDirectiveName(OMPD_scan) << 5);
11170 if (
DSAStack->doesParentHasScanDirective()) {
11171 Diag(StartLoc, diag::err_omp_several_directives_in_region) <<
"scan";
11173 diag::note_omp_previous_directive)
11177 DSAStack->setParentHasScanDirective(StartLoc);
11185 const OMPClause *DependFound =
nullptr;
11186 const OMPClause *DependSourceClause =
nullptr;
11187 const OMPClause *DependSinkClause =
nullptr;
11188 const OMPClause *DoacrossFound =
nullptr;
11189 const OMPClause *DoacrossSourceClause =
nullptr;
11190 const OMPClause *DoacrossSinkClause =
nullptr;
11191 bool ErrorFound =
false;
11195 auto DOC = dyn_cast<OMPDoacrossClause>(
C);
11196 auto DC = dyn_cast<OMPDependClause>(
C);
11198 DependFound = DC ?
C :
nullptr;
11199 DoacrossFound = DOC ?
C :
nullptr;
11200 OMPDoacrossKind ODK;
11201 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11202 (DOC && (ODK.isSource(DOC)))) {
11203 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11204 Diag(
C->getBeginLoc(), diag::err_omp_more_one_clause)
11205 << getOpenMPDirectiveName(OMPD_ordered)
11206 << getOpenMPClauseName(DC ? OMPC_depend : OMPC_doacross) << 2;
11210 DependSourceClause =
C;
11212 DoacrossSourceClause =
C;
11214 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11215 Diag(
C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11216 << (DC ?
"depend" :
"doacross") << 0;
11219 }
else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11220 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11221 if (DependSourceClause || DoacrossSourceClause) {
11222 Diag(
C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11223 << (DC ?
"depend" :
"doacross") << 1;
11227 DependSinkClause =
C;
11229 DoacrossSinkClause =
C;
11231 }
else if (
C->getClauseKind() == OMPC_threads) {
11232 TC = cast<OMPThreadsClause>(
C);
11233 }
else if (
C->getClauseKind() == OMPC_simd) {
11234 SC = cast<OMPSIMDClause>(
C);
11237 if (!ErrorFound && !SC &&
11242 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11245 }
else if ((DependFound || DoacrossFound) && (TC || SC)) {
11248 Diag(
Loc, diag::err_omp_depend_clause_thread_simd)
11249 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross)
11252 }
else if ((DependFound || DoacrossFound) &&
11253 !
DSAStack->getParentOrderedRegionParam().first) {
11256 Diag(
Loc, diag::err_omp_ordered_directive_without_param)
11257 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross);
11259 }
else if (TC || Clauses.empty()) {
11260 if (
const Expr *Param =
DSAStack->getParentOrderedRegionParam().first) {
11262 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11263 << (TC !=
nullptr);
11268 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11276 if (!DependFound && !DoacrossFound) {
11277 if (
DSAStack->doesParentHasOrderedDirective()) {
11278 Diag(StartLoc, diag::err_omp_several_directives_in_region) <<
"ordered";
11280 diag::note_omp_previous_directive)
11284 DSAStack->setParentHasOrderedDirective(StartLoc);
11288 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
11300class OpenMPAtomicUpdateChecker {
11302 enum ExprAnalysisErrorCode {
11306 NotABinaryOrUnaryExpression,
11308 NotAnUnaryIncDecExpression,
11314 NotABinaryExpression,
11317 NotABinaryOperator,
11320 NotAnUpdateExpression,
11323 NotAValidExpression,
11341 bool IsXLHSInRHSPart;
11346 bool IsPostfixUpdate;
11349 OpenMPAtomicUpdateChecker(
Sema &SemaRef)
11350 : SemaRef(SemaRef),
X(nullptr),
E(nullptr), UpdateExpr(nullptr),
11351 IsXLHSInRHSPart(
false), Op(BO_PtrMemD), IsPostfixUpdate(
false) {}
11359 bool checkStatement(
Stmt *S,
unsigned DiagId = 0,
unsigned NoteId = 0);
11361 Expr *getX()
const {
return X; }
11363 Expr *getExpr()
const {
return E; }
11367 Expr *getUpdateExpr()
const {
return UpdateExpr; }
11370 bool isXLHSInRHSPart()
const {
return IsXLHSInRHSPart; }
11374 bool isPostfixUpdate()
const {
return IsPostfixUpdate; }
11377 bool checkBinaryOperation(
BinaryOperator *AtomicBinOp,
unsigned DiagId = 0,
11378 unsigned NoteId = 0);
11381bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11382 BinaryOperator *AtomicBinOp,
unsigned DiagId,
unsigned NoteId) {
11383 ExprAnalysisErrorCode ErrorFound = NoError;
11389 if (AtomicBinOp->
getOpcode() == BO_Assign) {
11391 if (
const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11393 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11394 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11395 AtomicInnerBinOp->isBitwiseOp()) {
11396 Op = AtomicInnerBinOp->getOpcode();
11397 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11398 Expr *LHS = AtomicInnerBinOp->getLHS();
11399 Expr *RHS = AtomicInnerBinOp->getRHS();
11400 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11407 if (XId == LHSId) {
11409 IsXLHSInRHSPart =
true;
11410 }
else if (XId == RHSId) {
11412 IsXLHSInRHSPart =
false;
11414 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11415 ErrorRange = AtomicInnerBinOp->getSourceRange();
11416 NoteLoc =
X->getExprLoc();
11417 NoteRange =
X->getSourceRange();
11418 ErrorFound = NotAnUpdateExpression;
11421 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11422 ErrorRange = AtomicInnerBinOp->getSourceRange();
11423 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11425 ErrorFound = NotABinaryOperator;
11430 ErrorFound = NotABinaryExpression;
11437 ErrorFound = NotAnAssignmentOp;
11439 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11440 SemaRef.
Diag(ErrorLoc, DiagId) << ErrorRange;
11441 SemaRef.
Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11445 E =
X = UpdateExpr =
nullptr;
11446 return ErrorFound != NoError;
11449bool OpenMPAtomicUpdateChecker::checkStatement(
Stmt *S,
unsigned DiagId,
11451 ExprAnalysisErrorCode ErrorFound = NoError;
11462 if (
auto *AtomicBody = dyn_cast<Expr>(S)) {
11463 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11464 if (AtomicBody->getType()->isScalarType() ||
11465 AtomicBody->isInstantiationDependent()) {
11466 if (
const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11467 AtomicBody->IgnoreParenImpCasts())) {
11470 AtomicCompAssignOp->getOpcode());
11471 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11472 E = AtomicCompAssignOp->getRHS();
11473 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11474 IsXLHSInRHSPart =
true;
11475 }
else if (
auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11476 AtomicBody->IgnoreParenImpCasts())) {
11478 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11480 }
else if (
const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11481 AtomicBody->IgnoreParenImpCasts())) {
11483 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11484 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11485 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11486 OpLoc = AtomicUnaryOp->getOperatorLoc();
11487 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11489 IsXLHSInRHSPart =
true;
11491 ErrorFound = NotAnUnaryIncDecExpression;
11492 ErrorLoc = AtomicUnaryOp->getExprLoc();
11493 ErrorRange = AtomicUnaryOp->getSourceRange();
11494 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11497 }
else if (!AtomicBody->isInstantiationDependent()) {
11498 ErrorFound = NotABinaryOrUnaryExpression;
11499 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11500 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11501 }
else if (AtomicBody->containsErrors()) {
11502 ErrorFound = NotAValidExpression;
11503 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11504 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11507 ErrorFound = NotAScalarType;
11508 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11509 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
11512 ErrorFound = NotAnExpression;
11513 NoteLoc = ErrorLoc = S->getBeginLoc();
11514 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
11516 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11517 SemaRef.
Diag(ErrorLoc, DiagId) << ErrorRange;
11518 SemaRef.
Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11522 E =
X = UpdateExpr =
nullptr;
11523 if (ErrorFound == NoError &&
E &&
X) {
11533 IsXLHSInRHSPart ? OVEExpr : OVEX);
11540 UpdateExpr =
Update.get();
11542 return ErrorFound != NoError;
11546llvm::FoldingSetNodeID getNodeId(
ASTContext &Context,
const Expr *S) {
11547 llvm::FoldingSetNodeID
Id;
11548 S->IgnoreParenImpCasts()->Profile(
Id, Context,
true);
11553bool checkIfTwoExprsAreSame(
ASTContext &Context,
const Expr *LHS,
11555 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11558class OpenMPAtomicCompareChecker {
11605 struct ErrorInfoTy {
11613 OpenMPAtomicCompareChecker(
Sema &S) : ContextRef(S.getASTContext()) {}
11616 bool checkStmt(
Stmt *S, ErrorInfoTy &ErrorInfo);
11618 Expr *getX()
const {
return X; }
11619 Expr *getE()
const {
return E; }
11620 Expr *getD()
const {
return D; }
11621 Expr *getCond()
const {
return C; }
11622 bool isXBinopExpr()
const {
return IsXBinopExpr; }
11641 bool IsXBinopExpr =
true;
11644 bool checkCondUpdateStmt(
IfStmt *S, ErrorInfoTy &ErrorInfo);
11647 bool checkCondExprStmt(
Stmt *S, ErrorInfoTy &ErrorInfo);
11650 bool checkType(ErrorInfoTy &ErrorInfo)
const;
11652 static bool CheckValue(
const Expr *
E, ErrorInfoTy &ErrorInfo,
11653 bool ShouldBeLValue,
bool ShouldBeInteger =
false) {
11657 if (ShouldBeLValue && !
E->
isLValue()) {
11658 ErrorInfo.Error = ErrorTy::XNotLValue;
11659 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc =
E->
getExprLoc();
11666 ErrorInfo.Error = ErrorTy::NotScalar;
11667 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc =
E->
getExprLoc();
11672 ErrorInfo.Error = ErrorTy::NotInteger;
11673 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc =
E->
getExprLoc();
11682bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(
IfStmt *S,
11683 ErrorInfoTy &ErrorInfo) {
11684 auto *Then = S->getThen();
11685 if (
auto *CS = dyn_cast<CompoundStmt>(Then)) {
11686 if (CS->body_empty()) {
11687 ErrorInfo.Error = ErrorTy::NoStmt;
11688 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11689 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11692 if (CS->size() > 1) {
11693 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11694 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11695 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11698 Then = CS->body_front();
11701 auto *BO = dyn_cast<BinaryOperator>(Then);
11703 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11704 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11705 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11708 if (BO->getOpcode() != BO_Assign) {
11709 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11710 ErrorInfo.ErrorLoc = BO->getExprLoc();
11711 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11712 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11718 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11720 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11721 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11722 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11726 switch (Cond->getOpcode()) {
11730 if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getLHS())) {
11731 E = Cond->getRHS();
11732 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getRHS())) {
11733 E = Cond->getLHS();
11735 ErrorInfo.Error = ErrorTy::InvalidComparison;
11736 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11737 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11745 if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getLHS()) &&
11746 checkIfTwoExprsAreSame(ContextRef,
E, Cond->getRHS())) {
11748 }
else if (checkIfTwoExprsAreSame(ContextRef,
E, Cond->getLHS()) &&
11749 checkIfTwoExprsAreSame(ContextRef,
X, Cond->getRHS())) {
11751 IsXBinopExpr =
false;
11753 ErrorInfo.Error = ErrorTy::InvalidComparison;
11754 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11755 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11761 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11762 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11763 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11767 if (S->getElse()) {
11768 ErrorInfo.Error = ErrorTy::UnexpectedElse;
11769 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
11770 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
11777bool OpenMPAtomicCompareChecker::checkCondExprStmt(
Stmt *S,
11778 ErrorInfoTy &ErrorInfo) {
11779 auto *BO = dyn_cast<BinaryOperator>(S);
11781 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11782 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
11783 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11786 if (BO->getOpcode() != BO_Assign) {
11787 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11788 ErrorInfo.ErrorLoc = BO->getExprLoc();
11789 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11790 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11796 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
11798 ErrorInfo.Error = ErrorTy::NotCondOp;
11799 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
11800 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
11804 if (!checkIfTwoExprsAreSame(ContextRef,
X, CO->getFalseExpr())) {
11805 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
11806 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
11807 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11808 CO->getFalseExpr()->getSourceRange();
11812 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
11814 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11815 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11816 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11817 CO->getCond()->getSourceRange();
11821 switch (Cond->getOpcode()) {
11824 D = CO->getTrueExpr();
11825 if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getLHS())) {
11826 E = Cond->getRHS();
11827 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getRHS())) {
11828 E = Cond->getLHS();
11830 ErrorInfo.Error = ErrorTy::InvalidComparison;
11831 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11832 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11839 E = CO->getTrueExpr();
11840 if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getLHS()) &&
11841 checkIfTwoExprsAreSame(ContextRef,
E, Cond->getRHS())) {
11843 }
else if (checkIfTwoExprsAreSame(ContextRef,
E, Cond->getLHS()) &&
11844 checkIfTwoExprsAreSame(ContextRef,
X, Cond->getRHS())) {
11846 IsXBinopExpr =
false;
11848 ErrorInfo.Error = ErrorTy::InvalidComparison;
11849 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11850 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11856 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11857 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11858 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11865bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo)
const {
11867 assert(
X &&
E &&
"X and E cannot be nullptr");
11869 if (!CheckValue(
X, ErrorInfo,
true))
11872 if (!CheckValue(
E, ErrorInfo,
false))
11875 if (
D && !CheckValue(
D, ErrorInfo,
false))
11881bool OpenMPAtomicCompareChecker::checkStmt(
11882 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
11883 auto *CS = dyn_cast<CompoundStmt>(S);
11885 if (CS->body_empty()) {
11886 ErrorInfo.Error = ErrorTy::NoStmt;
11887 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11888 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11892 if (CS->size() != 1) {
11893 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11894 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11895 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11898 S = CS->body_front();
11903 if (
auto *IS = dyn_cast<IfStmt>(S)) {
11909 Res = checkCondUpdateStmt(IS, ErrorInfo);
11915 Res = checkCondExprStmt(S, ErrorInfo);
11921 return checkType(ErrorInfo);
11924class OpenMPAtomicCompareCaptureChecker final
11925 :
public OpenMPAtomicCompareChecker {
11927 OpenMPAtomicCompareCaptureChecker(
Sema &S) : OpenMPAtomicCompareChecker(S) {}
11929 Expr *getV()
const {
return V; }
11930 Expr *getR()
const {
return R; }
11931 bool isFailOnly()
const {
return IsFailOnly; }
11932 bool isPostfixUpdate()
const {
return IsPostfixUpdate; }
11935 bool checkStmt(
Stmt *S, ErrorInfoTy &ErrorInfo);
11938 bool checkType(ErrorInfoTy &ErrorInfo);
11950 bool checkForm3(
IfStmt *S, ErrorInfoTy &ErrorInfo);
11954 bool checkForm45(
Stmt *S, ErrorInfoTy &ErrorInfo);
11961 bool IsFailOnly =
false;
11963 bool IsPostfixUpdate =
false;
11966bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
11967 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
11970 if (
V && !CheckValue(
V, ErrorInfo,
true))
11973 if (R && !CheckValue(R, ErrorInfo,
true,
true))
11979bool OpenMPAtomicCompareCaptureChecker::checkForm3(
IfStmt *S,
11980 ErrorInfoTy &ErrorInfo) {
11983 auto *Then = S->getThen();
11984 if (
auto *CS = dyn_cast<CompoundStmt>(Then)) {
11985 if (CS->body_empty()) {
11986 ErrorInfo.Error = ErrorTy::NoStmt;
11987 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11988 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11991 if (CS->size() > 1) {
11992 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11993 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11994 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11997 Then = CS->body_front();
12000 auto *BO = dyn_cast<BinaryOperator>(Then);
12002 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12003 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12004 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12007 if (BO->getOpcode() != BO_Assign) {
12008 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12009 ErrorInfo.ErrorLoc = BO->getExprLoc();
12010 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12011 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12018 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12020 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12021 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12022 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12025 if (Cond->getOpcode() != BO_EQ) {
12026 ErrorInfo.Error = ErrorTy::NotEQ;
12027 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
12028 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
12032 if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getLHS())) {
12033 E = Cond->getRHS();
12034 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getRHS())) {
12035 E = Cond->getLHS();
12037 ErrorInfo.Error = ErrorTy::InvalidComparison;
12038 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
12039 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
12045 if (!S->getElse()) {
12046 ErrorInfo.Error = ErrorTy::NoElse;
12047 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12048 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12052 auto *Else = S->getElse();
12053 if (
auto *CS = dyn_cast<CompoundStmt>(Else)) {
12054 if (CS->body_empty()) {
12055 ErrorInfo.Error = ErrorTy::NoStmt;
12056 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12057 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12060 if (CS->size() > 1) {
12061 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12062 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12063 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12066 Else = CS->body_front();
12069 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12071 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12072 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12073 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12076 if (ElseBO->getOpcode() != BO_Assign) {
12077 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12078 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12079 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12080 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12084 if (!checkIfTwoExprsAreSame(ContextRef,
X, ElseBO->getRHS())) {
12085 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12086 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12087 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12088 ElseBO->getRHS()->getSourceRange();
12092 V = ElseBO->getLHS();
12094 return checkType(ErrorInfo);
12097bool OpenMPAtomicCompareCaptureChecker::checkForm45(
Stmt *S,
12098 ErrorInfoTy &ErrorInfo) {
12101 auto *CS = cast<CompoundStmt>(S);
12102 assert(CS->size() == 2 &&
"CompoundStmt size is not expected");
12103 auto *S1 = cast<BinaryOperator>(CS->body_front());
12104 auto *S2 = cast<IfStmt>(CS->body_back());
12105 assert(S1->getOpcode() == BO_Assign &&
"unexpected binary operator");
12107 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12108 ErrorInfo.Error = ErrorTy::InvalidCondition;
12109 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12110 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12116 auto *Then = S2->getThen();
12117 if (
auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12118 if (ThenCS->body_empty()) {
12119 ErrorInfo.Error = ErrorTy::NoStmt;
12120 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12121 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12124 if (ThenCS->size() > 1) {
12125 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12126 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12127 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12130 Then = ThenCS->body_front();
12133 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12135 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12136 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12137 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12140 if (ThenBO->getOpcode() != BO_Assign) {
12141 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12142 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12143 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12144 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12148 X = ThenBO->getLHS();
12149 D = ThenBO->getRHS();
12151 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12152 if (BO->getOpcode() != BO_EQ) {
12153 ErrorInfo.Error = ErrorTy::NotEQ;
12154 ErrorInfo.ErrorLoc = BO->getExprLoc();
12155 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12156 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12162 if (checkIfTwoExprsAreSame(ContextRef,
X, BO->getLHS())) {
12164 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, BO->getRHS())) {
12167 ErrorInfo.Error = ErrorTy::InvalidComparison;
12168 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->
getExprLoc();
12169 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12173 if (S2->getElse()) {
12176 auto *Else = S2->getElse();
12177 if (
auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12178 if (ElseCS->body_empty()) {
12179 ErrorInfo.Error = ErrorTy::NoStmt;
12180 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12181 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12184 if (ElseCS->size() > 1) {
12185 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12186 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12187 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12190 Else = ElseCS->body_front();
12193 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12195 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12196 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12197 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12200 if (ElseBO->getOpcode() != BO_Assign) {
12201 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12202 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12203 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12204 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12207 if (!checkIfTwoExprsAreSame(ContextRef,
X, ElseBO->getRHS())) {
12208 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12209 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12210 ErrorInfo.NoteLoc =
X->getExprLoc();
12211 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12212 ErrorInfo.NoteRange =
X->getSourceRange();
12216 V = ElseBO->getLHS();
12219 return checkType(ErrorInfo);
12222bool OpenMPAtomicCompareCaptureChecker::checkStmt(
Stmt *S,
12223 ErrorInfoTy &ErrorInfo) {
12225 if (
auto *IS = dyn_cast<IfStmt>(S))
12226 return checkForm3(IS, ErrorInfo);
12228 auto *CS = dyn_cast<CompoundStmt>(S);
12230 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12231 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12232 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12235 if (CS->body_empty()) {
12236 ErrorInfo.Error = ErrorTy::NoStmt;
12237 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12238 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12243 if (CS->size() == 1) {
12244 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12246 ErrorInfo.Error = ErrorTy::NotIfStmt;
12247 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->
getBeginLoc();
12248 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12253 return checkForm3(IS, ErrorInfo);
12254 }
else if (CS->size() == 2) {
12255 auto *S1 = CS->body_front();
12256 auto *S2 = CS->body_back();
12258 Stmt *UpdateStmt =
nullptr;
12259 Stmt *CondUpdateStmt =
nullptr;
12260 Stmt *CondExprStmt =
nullptr;
12262 if (
auto *BO = dyn_cast<BinaryOperator>(S1)) {
12268 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12269 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12271 if (isa<IfStmt>(S2))
12272 return checkForm45(CS, ErrorInfo);
12277 IsPostfixUpdate =
true;
12279 if (isa<IfStmt>(S2)) {
12281 CondUpdateStmt = S2;
12290 CondUpdateStmt = S1;
12293 auto CheckCondUpdateStmt = [
this, &ErrorInfo](
Stmt *CUS) {
12294 auto *IS = dyn_cast<IfStmt>(CUS);
12296 ErrorInfo.Error = ErrorTy::NotIfStmt;
12297 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12298 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12302 return checkCondUpdateStmt(IS, ErrorInfo);
12306 auto CheckUpdateStmt = [
this, &ErrorInfo](
Stmt *US) {
12307 auto *BO = dyn_cast<BinaryOperator>(US);
12309 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12310 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12311 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12314 if (BO->getOpcode() != BO_Assign) {
12315 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12316 ErrorInfo.ErrorLoc = BO->getExprLoc();
12317 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12318 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12321 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12322 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12323 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12325 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12330 this->V = BO->getLHS();
12335 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12337 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12339 if (!CheckUpdateStmt(UpdateStmt))
12342 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12343 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12344 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12348 return checkType(ErrorInfo);
12358 DSAStack->addAtomicDirectiveLoc(StartLoc);
12371 bool MutexClauseEncountered =
false;
12372 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12374 switch (
C->getClauseKind()) {
12378 MutexClauseEncountered =
true;
12381 case OMPC_compare: {
12382 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12383 Diag(
C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12385 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12386 << getOpenMPClauseName(AtomicKind);
12388 AtomicKind =
C->getClauseKind();
12389 AtomicKindLoc =
C->getBeginLoc();
12390 if (!EncounteredAtomicKinds.insert(
C->getClauseKind()).second) {
12391 Diag(
C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12393 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12394 << getOpenMPClauseName(AtomicKind);
12401 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12402 Diag(
C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12403 << getOpenMPClauseName(
C->getClauseKind())
12413 case OMPC_relaxed: {
12414 if (MemOrderKind != OMPC_unknown) {
12415 Diag(
C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12416 << getOpenMPDirectiveName(OMPD_atomic) << 0
12418 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12419 << getOpenMPClauseName(MemOrderKind);
12421 MemOrderKind =
C->getClauseKind();
12422 MemOrderLoc =
C->getBeginLoc();
12430 llvm_unreachable(
"unknown clause is encountered");
12433 bool IsCompareCapture =
false;
12434 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12435 EncounteredAtomicKinds.contains(OMPC_capture)) {
12436 IsCompareCapture =
true;
12437 AtomicKind = OMPC_compare;
12446 if ((AtomicKind == OMPC_read &&
12447 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12448 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12449 AtomicKind == OMPC_unknown) &&
12450 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12452 if (AtomicKind == OMPC_unknown)
12454 Diag(
Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12455 << getOpenMPClauseName(AtomicKind)
12456 << (AtomicKind == OMPC_unknown ? 1 : 0)
12457 << getOpenMPClauseName(MemOrderKind);
12458 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12459 << getOpenMPClauseName(MemOrderKind);
12462 Stmt *Body = AStmt;
12463 if (
auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12464 Body = EWC->getSubExpr();
12469 Expr *UE =
nullptr;
12471 Expr *CE =
nullptr;
12473 bool IsXLHSInRHSPart =
false;
12474 bool IsPostfixUpdate =
false;
12475 bool IsFailOnly =
false;
12498 if (AtomicKind == OMPC_read) {
12505 } ErrorFound = NoError;
12510 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12511 const auto *AtomicBinOp =
12512 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12513 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12516 if ((
X->isInstantiationDependent() ||
X->getType()->isScalarType()) &&
12517 (
V->isInstantiationDependent() ||
V->getType()->isScalarType())) {
12518 if (!
X->isLValue() || !
V->isLValue()) {
12519 const Expr *NotLValueExpr =
X->isLValue() ?
V :
X;
12520 ErrorFound = NotAnLValue;
12526 }
else if (!
X->isInstantiationDependent() ||
12527 !
V->isInstantiationDependent()) {
12528 const Expr *NotScalarExpr =
12529 (
X->isInstantiationDependent() ||
X->getType()->isScalarType())
12532 ErrorFound = NotAScalarType;
12538 }
else if (!AtomicBody->isInstantiationDependent()) {
12539 ErrorFound = NotAnAssignmentOp;
12540 ErrorLoc = AtomicBody->getExprLoc();
12541 ErrorRange = AtomicBody->getSourceRange();
12543 : AtomicBody->getExprLoc();
12545 : AtomicBody->getSourceRange();
12548 ErrorFound = NotAnExpression;
12550 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
12552 if (ErrorFound != NoError) {
12553 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12555 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12556 << ErrorFound << NoteRange;
12561 }
else if (AtomicKind == OMPC_write) {
12568 } ErrorFound = NoError;
12573 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12574 const auto *AtomicBinOp =
12575 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12576 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12579 if ((
X->isInstantiationDependent() ||
X->getType()->isScalarType()) &&
12581 if (!
X->isLValue()) {
12582 ErrorFound = NotAnLValue;
12585 NoteLoc =
X->getExprLoc();
12586 NoteRange =
X->getSourceRange();
12588 }
else if (!
X->isInstantiationDependent() ||
12590 const Expr *NotScalarExpr =
12591 (
X->isInstantiationDependent() ||
X->getType()->isScalarType())
12594 ErrorFound = NotAScalarType;
12600 }
else if (!AtomicBody->isInstantiationDependent()) {
12601 ErrorFound = NotAnAssignmentOp;
12602 ErrorLoc = AtomicBody->getExprLoc();
12603 ErrorRange = AtomicBody->getSourceRange();
12605 : AtomicBody->getExprLoc();
12607 : AtomicBody->getSourceRange();
12610 ErrorFound = NotAnExpression;
12612 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
12614 if (ErrorFound != NoError) {
12615 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12617 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12618 << ErrorFound << NoteRange;
12623 }
else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12632 OpenMPAtomicUpdateChecker Checker(
SemaRef);
12633 if (Checker.checkStatement(
12635 (AtomicKind == OMPC_update)
12636 ? diag::err_omp_atomic_update_not_expression_statement
12637 : diag::err_omp_atomic_not_expression_statement,
12638 diag::note_omp_atomic_update))
12641 E = Checker.getExpr();
12642 X = Checker.getX();
12643 UE = Checker.getUpdateExpr();
12644 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12646 }
else if (AtomicKind == OMPC_capture) {
12649 NotACompoundStatement,
12650 NotTwoSubstatements,
12651 NotASpecificExpression,
12653 } ErrorFound = NoError;
12656 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12665 const auto *AtomicBinOp =
12666 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12667 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12670 OpenMPAtomicUpdateChecker Checker(
SemaRef);
12671 if (Checker.checkStatement(
12672 Body, diag::err_omp_atomic_capture_not_expression_statement,
12673 diag::note_omp_atomic_update))
12675 E = Checker.getExpr();
12676 X = Checker.getX();
12677 UE = Checker.getUpdateExpr();
12678 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12679 IsPostfixUpdate = Checker.isPostfixUpdate();
12680 }
else if (!AtomicBody->isInstantiationDependent()) {
12681 ErrorLoc = AtomicBody->getExprLoc();
12682 ErrorRange = AtomicBody->getSourceRange();
12684 : AtomicBody->getExprLoc();
12686 : AtomicBody->getSourceRange();
12687 ErrorFound = NotAnAssignmentOp;
12689 if (ErrorFound != NoError) {
12690 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
12692 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12696 UE =
V =
E =
X =
nullptr;
12714 if (
auto *CS = dyn_cast<CompoundStmt>(Body)) {
12716 if (CS->size() == 2) {
12718 Stmt *Second = CS->body_back();
12719 if (
auto *EWC = dyn_cast<ExprWithCleanups>(
First))
12720 First = EWC->getSubExpr()->IgnoreParenImpCasts();
12721 if (
auto *EWC = dyn_cast<ExprWithCleanups>(Second))
12722 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
12724 OpenMPAtomicUpdateChecker Checker(
SemaRef);
12725 bool IsUpdateExprFound = !Checker.checkStatement(Second);
12727 if (IsUpdateExprFound) {
12728 BinOp = dyn_cast<BinaryOperator>(
First);
12729 IsUpdateExprFound = BinOp && BinOp->
getOpcode() == BO_Assign;
12741 llvm::FoldingSetNodeID XId, PossibleXId;
12742 Checker.getX()->
Profile(XId, Context,
true);
12743 PossibleX->
Profile(PossibleXId, Context,
true);
12744 IsUpdateExprFound = XId == PossibleXId;
12745 if (IsUpdateExprFound) {
12747 X = Checker.getX();
12748 E = Checker.getExpr();
12749 UE = Checker.getUpdateExpr();
12750 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12751 IsPostfixUpdate =
true;
12754 if (!IsUpdateExprFound) {
12755 IsUpdateExprFound = !Checker.checkStatement(
First);
12757 if (IsUpdateExprFound) {
12758 BinOp = dyn_cast<BinaryOperator>(Second);
12759 IsUpdateExprFound = BinOp && BinOp->
getOpcode() == BO_Assign;
12761 if (IsUpdateExprFound &&
12772 llvm::FoldingSetNodeID XId, PossibleXId;
12773 Checker.getX()->
Profile(XId, Context,
true);
12774 PossibleX->
Profile(PossibleXId, Context,
true);
12775 IsUpdateExprFound = XId == PossibleXId;
12776 if (IsUpdateExprFound) {
12778 X = Checker.getX();
12779 E = Checker.getExpr();
12780 UE = Checker.getUpdateExpr();
12781 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12782 IsPostfixUpdate =
false;
12786 if (!IsUpdateExprFound) {
12788 auto *FirstExpr = dyn_cast<Expr>(
First);
12789 auto *SecondExpr = dyn_cast<Expr>(Second);
12790 if (!FirstExpr || !SecondExpr ||
12791 !(FirstExpr->isInstantiationDependent() ||
12792 SecondExpr->isInstantiationDependent())) {
12793 auto *FirstBinOp = dyn_cast<BinaryOperator>(
First);
12794 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
12795 ErrorFound = NotAnAssignmentOp;
12796 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
12797 :
First->getBeginLoc();
12798 NoteRange = ErrorRange = FirstBinOp
12799 ? FirstBinOp->getSourceRange()
12802 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
12803 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
12804 ErrorFound = NotAnAssignmentOp;
12805 NoteLoc = ErrorLoc = SecondBinOp
12806 ? SecondBinOp->getOperatorLoc()
12808 NoteRange = ErrorRange =
12809 SecondBinOp ? SecondBinOp->getSourceRange()
12812 Expr *PossibleXRHSInFirst =
12814 Expr *PossibleXLHSInSecond =
12816 llvm::FoldingSetNodeID X1Id, X2Id;
12817 PossibleXRHSInFirst->
Profile(X1Id, Context,
12819 PossibleXLHSInSecond->
Profile(X2Id, Context,
12821 IsUpdateExprFound = X1Id == X2Id;
12822 if (IsUpdateExprFound) {
12823 V = FirstBinOp->getLHS();
12824 X = SecondBinOp->getLHS();
12825 E = SecondBinOp->getRHS();
12827 IsXLHSInRHSPart =
false;
12828 IsPostfixUpdate =
true;
12830 ErrorFound = NotASpecificExpression;
12831 ErrorLoc = FirstBinOp->getExprLoc();
12832 ErrorRange = FirstBinOp->getSourceRange();
12833 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
12834 NoteRange = SecondBinOp->getRHS()->getSourceRange();
12842 NoteRange = ErrorRange =
12844 ErrorFound = NotTwoSubstatements;
12848 NoteRange = ErrorRange =
12850 ErrorFound = NotACompoundStatement;
12853 if (ErrorFound != NoError) {
12854 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
12856 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12860 UE =
V =
E =
X =
nullptr;
12861 }
else if (AtomicKind == OMPC_compare) {
12862 if (IsCompareCapture) {
12863 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
12864 OpenMPAtomicCompareCaptureChecker Checker(
SemaRef);
12865 if (!Checker.checkStmt(Body, ErrorInfo)) {
12866 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
12867 << ErrorInfo.ErrorRange;
12868 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12869 << ErrorInfo.Error << ErrorInfo.NoteRange;
12872 X = Checker.getX();
12873 E = Checker.getE();
12874 D = Checker.getD();
12875 CE = Checker.getCond();
12876 V = Checker.getV();
12877 R = Checker.getR();
12879 IsXLHSInRHSPart = Checker.isXBinopExpr();
12880 IsFailOnly = Checker.isFailOnly();
12881 IsPostfixUpdate = Checker.isPostfixUpdate();
12883 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
12884 OpenMPAtomicCompareChecker Checker(
SemaRef);
12885 if (!Checker.checkStmt(Body, ErrorInfo)) {
12886 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
12887 << ErrorInfo.ErrorRange;
12888 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12889 << ErrorInfo.Error << ErrorInfo.NoteRange;
12892 X = Checker.getX();
12893 E = Checker.getE();
12894 D = Checker.getD();
12895 CE = Checker.getCond();
12901 auto *It = find_if(Clauses, [](
OMPClause *
C) {
12902 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
12904 if (It != Clauses.end()) {
12905 auto *Cond = dyn_cast<BinaryOperator>(CE);
12906 if (Cond->getOpcode() != BO_EQ) {
12907 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
12909 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
12910 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
12912 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
12913 << ErrorInfo.ErrorRange;
12918 IsXLHSInRHSPart = Checker.isXBinopExpr();
12925 Context, StartLoc, EndLoc, Clauses, AStmt,
12926 {
X,
V, R,
E, UE,
D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
12942 if (
DSAStack->hasInnerTeamsRegion()) {
12944 bool OMPTeamsFound =
true;
12945 if (
const auto *CS = dyn_cast<CompoundStmt>(S)) {
12946 auto I = CS->body_begin();
12947 while (I != CS->body_end()) {
12948 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
12950 if (!IsTeams || I != CS->body_begin()) {
12951 OMPTeamsFound =
false;
12952 if (IsTeams && I != CS->body_begin()) {
12961 assert(I != CS->body_end() &&
"Not found statement");
12964 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
12967 if (!OMPTeamsFound) {
12968 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
12970 diag::note_omp_nested_teams_construct_here);
12971 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
12972 << isa<OMPExecutableDirective>(S);
13006 unsigned NestedLoopCount =
13009 VarsWithImplicitDSA, B);
13010 if (NestedLoopCount == 0)
13017 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13024 return llvm::any_of(
13025 Clauses, [K](
const OMPClause *
C) {
return C->getClauseKind() == K; });
13028template <
typename... Params>
13030 const Params... ClauseTypes) {
13037 if (
auto *TC = dyn_cast<OMPToClause>(
C))
13038 return llvm::all_of(TC->all_decls(), [](
ValueDecl *VD) {
13039 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13040 (VD->isExternallyVisible() &&
13041 VD->getVisibility() != HiddenVisibility);
13043 else if (
auto *FC = dyn_cast<OMPFromClause>(
C))
13044 return llvm::all_of(FC->all_decls(), [](
ValueDecl *VD) {
13045 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13046 (VD->isExternallyVisible() &&
13047 VD->getVisibility() != HiddenVisibility);
13061 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13066 if (!
hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13068 !
hasClauses(Clauses, OMPC_use_device_addr))) {
13071 Expected =
"'map' or 'use_device_ptr'";
13073 Expected =
"'map', 'use_device_ptr', or 'use_device_addr'";
13074 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13075 <<
Expected << getOpenMPDirectiveName(OMPD_target_data);
13096 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13097 <<
"'map'" << getOpenMPDirectiveName(OMPD_target_enter_data);
13116 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13117 <<
"'map'" << getOpenMPDirectiveName(OMPD_target_exit_data);
13133 if (!
hasClauses(Clauses, OMPC_to, OMPC_from)) {
13134 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13139 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13149template <
typename ClauseType>
13152 unsigned MaxNum,
unsigned Diag) {
13153 auto ClauseItr = llvm::find_if(Clauses, llvm::IsaPred<ClauseType>);
13154 if (ClauseItr == Clauses.end())
13156 const auto *
C = cast<ClauseType>(*ClauseItr);
13157 auto VarList =
C->getVarRefs();
13158 if (VarList.size() > MaxNum) {
13159 SemaRef.
Diag(VarList[MaxNum]->getBeginLoc(),
Diag)
13160 << getOpenMPClauseName(
C->getClauseKind());
13173 if (!checkNumExprsInClause<OMPNumTeamsClause>(
13174 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
13175 !checkNumExprsInClause<OMPThreadLimitClause>(
13176 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
13181 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13185 DSAStack->setParentTeamsRegionLoc(StartLoc);
13194 if (
DSAStack->isParentNowaitRegion()) {
13195 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13198 if (
DSAStack->isParentOrderedRegion()) {
13199 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13203 EndLoc, CancelRegion);
13209 if (
DSAStack->isParentNowaitRegion()) {
13210 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13213 if (
DSAStack->isParentOrderedRegion()) {
13214 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13217 DSAStack->setParentCancelRegion(
true);
13224 const OMPClause *ReductionClause =
nullptr;
13225 const OMPClause *NogroupClause =
nullptr;
13227 if (
C->getClauseKind() == OMPC_reduction) {
13228 ReductionClause =
C;
13233 if (
C->getClauseKind() == OMPC_nogroup) {
13235 if (ReductionClause)
13240 if (ReductionClause && NogroupClause) {
13241 S.
Diag(ReductionClause->
getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13255 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13259 unsigned NestedLoopCount =
13262 *
DSAStack, VarsWithImplicitDSA, B);
13263 if (NestedLoopCount == 0)
13267 "omp for loop exprs were not built");
13273 {OMPC_grainsize, OMPC_num_tasks}))
13283 NestedLoopCount, Clauses, AStmt, B,
13296 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13300 unsigned NestedLoopCount =
13303 VarsWithImplicitDSA, B);
13304 if (NestedLoopCount == 0)
13314 {OMPC_grainsize, OMPC_num_tasks}))
13325 NestedLoopCount, Clauses, AStmt, B);
13334 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13338 unsigned NestedLoopCount =
13341 *
DSAStack, VarsWithImplicitDSA, B);
13342 if (NestedLoopCount == 0)
13346 "omp for loop exprs were not built");
13352 {OMPC_grainsize, OMPC_num_tasks}))
13362 NestedLoopCount, Clauses, AStmt, B,
13372 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13376 unsigned NestedLoopCount =
13379 *
DSAStack, VarsWithImplicitDSA, B);
13380 if (NestedLoopCount == 0)
13384 "omp for loop exprs were not built");
13390 {OMPC_grainsize, OMPC_num_tasks}))
13400 NestedLoopCount, Clauses, AStmt, B,
13413 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13417 unsigned NestedLoopCount =
13420 VarsWithImplicitDSA, B);
13421 if (NestedLoopCount == 0)
13431 {OMPC_grainsize, OMPC_num_tasks}))
13442 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13454 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13458 unsigned NestedLoopCount =
13461 VarsWithImplicitDSA, B);
13462 if (NestedLoopCount == 0)
13472 {OMPC_grainsize, OMPC_num_tasks}))
13483 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13501 VarsWithImplicitDSA, B);
13502 if (NestedLoopCount == 0)
13506 "omp for loop exprs were not built");
13512 {OMPC_grainsize, OMPC_num_tasks}))
13521 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13540 VarsWithImplicitDSA, B);
13541 if (NestedLoopCount == 0)
13545 "omp for loop exprs were not built");
13551 {OMPC_grainsize, OMPC_num_tasks}))
13560 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13571 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
13579 VarsWithImplicitDSA, B);
13580 if (NestedLoopCount == 0)
13590 {OMPC_grainsize, OMPC_num_tasks}))
13601 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13611 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
13619 VarsWithImplicitDSA, B);
13620 if (NestedLoopCount == 0)
13630 {OMPC_grainsize, OMPC_num_tasks}))
13641 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13650 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13654 unsigned NestedLoopCount =
13658 if (NestedLoopCount == 0)
13662 "omp for loop exprs were not built");
13666 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13667 return DistributeDirective;
13685 VarsWithImplicitDSA, B);
13686 if (NestedLoopCount == 0)
13690 "omp for loop exprs were not built");
13693 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13704 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
13712 VarsWithImplicitDSA, B);
13713 if (NestedLoopCount == 0)
13723 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13738 unsigned NestedLoopCount =
13742 if (NestedLoopCount == 0)
13752 NestedLoopCount, Clauses, AStmt, B);
13770 VarsWithImplicitDSA, B);
13771 if (NestedLoopCount == 0)
13781 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13795 unsigned NestedLoopCount =
13798 VarsWithImplicitDSA, B);
13799 if (NestedLoopCount == 0)
13809 NestedLoopCount, Clauses, AStmt, B);
13824 unsigned NestedLoopCount =
13828 if (NestedLoopCount == 0)
13832 "omp teams distribute loop exprs were not built");
13834 DSAStack->setParentTeamsRegionLoc(StartLoc);
13837 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13855 VarsWithImplicitDSA, B);
13856 if (NestedLoopCount == 0)
13865 DSAStack->setParentTeamsRegionLoc(StartLoc);
13868 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13878 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
13886 VarsWithImplicitDSA, B);
13887 if (NestedLoopCount == 0)
13896 DSAStack->setParentTeamsRegionLoc(StartLoc);
13899 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13909 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
13917 VarsWithImplicitDSA, B);
13919 if (NestedLoopCount == 0)
13923 "omp for loop exprs were not built");
13925 DSAStack->setParentTeamsRegionLoc(StartLoc);
13928 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13941 bool HasThreadLimitAndNumTeamsClause =
hasClauses(Clauses, OMPC_num_teams) &&
13943 bool HasBareClause = llvm::any_of(Clauses, [&](
const OMPClause *
C) {
13945 return C->getClauseKind() == OMPC_ompx_bare;
13948 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
13953 unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 1;
13954 unsigned DiagNo = HasBareClause
13955 ? diag::err_ompx_more_than_three_expr_not_allowed
13956 : diag::err_omp_multi_expr_not_allowed;
13957 if (!checkNumExprsInClause<OMPNumTeamsClause>(*
this, Clauses,
13958 ClauseMaxNumExprs, DiagNo) ||
13959 !checkNumExprsInClause<OMPThreadLimitClause>(*
this, Clauses,
13960 ClauseMaxNumExprs, DiagNo))
13973 if (!checkNumExprsInClause<OMPNumTeamsClause>(
13974 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
13975 !checkNumExprsInClause<OMPThreadLimitClause>(
13976 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
13988 VarsWithImplicitDSA, B);
13989 if (NestedLoopCount == 0)
13993 "omp target teams distribute loop exprs were not built");
13996 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14005 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14006 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
14007 !checkNumExprsInClause<OMPThreadLimitClause>(
14008 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14012 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
14020 VarsWithImplicitDSA, B);
14021 if (NestedLoopCount == 0)
14028 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14038 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14039 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
14040 !checkNumExprsInClause<OMPThreadLimitClause>(
14041 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14045 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
14050 unsigned NestedLoopCount =
14055 if (NestedLoopCount == 0)
14065 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14074 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14075 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
14076 !checkNumExprsInClause<OMPThreadLimitClause>(
14077 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14081 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
14089 VarsWithImplicitDSA, B);
14090 if (NestedLoopCount == 0)
14100 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14103bool SemaOpenMP::checkTransformableLoopNest(
14107 OriginalInits.emplace_back();
14110 [
this, &LoopHelpers, &Body, &OriginalInits, Kind](
unsigned Cnt,
14112 VarsWithInheritedDSAType TmpDSA;
14113 unsigned SingleNumLoops =
14114 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
14115 TmpDSA, LoopHelpers[Cnt]);
14116 if (SingleNumLoops == 0)
14118 assert(SingleNumLoops == 1 &&
"Expect single loop iteration space");
14119 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14120 OriginalInits.back().push_back(For->getInit());
14121 Body = For->getBody();
14123 assert(isa<CXXForRangeStmt>(CurStmt) &&
14124 "Expected canonical for or range-based for loops.");
14125 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14126 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14127 Body = CXXFor->getBody();
14129 OriginalInits.emplace_back();
14133 Stmt *DependentPreInits;
14134 if (
auto *Dir = dyn_cast<OMPTileDirective>(Transform))
14135 DependentPreInits = Dir->getPreInits();
14136 else if (
auto *Dir = dyn_cast<OMPUnrollDirective>(Transform))
14137 DependentPreInits = Dir->getPreInits();
14138 else if (
auto *Dir = dyn_cast<OMPReverseDirective>(Transform))
14139 DependentPreInits = Dir->getPreInits();
14140 else if (
auto *Dir = dyn_cast<OMPInterchangeDirective>(Transform))
14141 DependentPreInits = Dir->getPreInits();
14143 llvm_unreachable(
"Unhandled loop transformation");
14147 assert(OriginalInits.back().empty() &&
"No preinit after innermost loop");
14148 OriginalInits.pop_back();
14160 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
14161 Stmt *RangeInit = CXXRangeFor->getInit();
14163 PreInits.push_back(RangeInit);
14165 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14170 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14176 llvm::append_range(PreInits, OriginalInit);
14179 if (
auto *PI = cast_or_null<DeclStmt>(LoopHelper.
PreInits)) {
14180 PreInits.push_back(
new (Context)
DeclStmt(
14181 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14186 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14187 if (isa<OMPCapturedExprDecl>(CounterDecl))
14188 PreInits.push_back(
new (Context)
DeclStmt(
14196 size_t NumLoops = LoopStmts.size();
14198 AStmt,
false, NumLoops,
14199 [LoopStmts](
unsigned Cnt,
Stmt *CurStmt) {
14200 assert(!LoopStmts[Cnt] &&
"Loop statement must not yet be assigned");
14201 LoopStmts[Cnt] = CurStmt;
14204 assert(!is_contained(LoopStmts,
nullptr) &&
14205 "Expecting a loop statement for each affected loop");
14215 const auto *SizesClause =
14216 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14217 if (!SizesClause ||
14218 llvm::any_of(SizesClause->getSizesRefs(), [](
Expr *
E) { return !E; }))
14220 unsigned NumLoops = SizesClause->getNumSizes();
14228 Stmt *Body =
nullptr;
14230 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14237 NumLoops, AStmt,
nullptr,
nullptr);
14239 assert(LoopHelpers.size() == NumLoops &&
14240 "Expecting loop iteration space dimensionality to match number of "
14242 assert(OriginalInits.size() == NumLoops &&
14243 "Expecting loop iteration space dimensionality to match number of "
14251 CaptureVars CopyTransformer(
SemaRef);
14256 FloorIndVars.resize(NumLoops);
14257 TileIndVars.resize(NumLoops);
14258 for (
unsigned I = 0; I < NumLoops; ++I) {
14261 assert(LoopHelper.
Counters.size() == 1 &&
14262 "Expect single-dimensional loop iteration space");
14263 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.
Counters.front());
14264 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14270 std::string FloorCntName =
14271 (Twine(
".floor_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
14274 FloorIndVars[I] = FloorCntDecl;
14279 std::string TileCntName =
14280 (Twine(
".tile_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
14285 auto *TileCntDecl = cast<VarDecl>(IterVarRef->
getDecl());
14286 TileCntDecl->setDeclName(
14288 TileIndVars[I] = TileCntDecl;
14296 Stmt *Inner = Body;
14298 auto MakeDimTileSize = [&
SemaRef = this->
SemaRef, &CopyTransformer, &Context,
14299 SizesClause, CurScope](
int I) ->
Expr * {
14300 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
14301 if (isa<ConstantExpr>(DimTileSizeExpr))
14302 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
14323 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14327 CurScope, {}, BO_LE,
14328 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero));
14331 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
14337 for (
int I = NumLoops - 1; I >= 0; --I) {
14340 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.
Counters[0]);
14342 Stmt *LoopStmt = LoopStmts[I];
14347 auto MakeTileIVRef = [&
SemaRef = this->
SemaRef, &TileIndVars, I, IVTy,
14350 OrigCntVar->getExprLoc());
14352 auto MakeFloorIVRef = [&
SemaRef = this->
SemaRef, &FloorIndVars, I, IVTy,
14355 OrigCntVar->getExprLoc());
14362 Decl *CounterDecl = TileIndVars[I];
14365 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14373 MakeFloorIVRef(), MakeDimTileSize(I));
14378 NumIterations, EndOfTile.
get());
14383 IsPartialTile.
get(), NumIterations, EndOfTile.
get());
14384 if (!MinTileAndIterSpace.
isUsable())
14388 MakeTileIVRef(), MinTileAndIterSpace.
get());
14394 CurScope, LoopHelper.
Inc->
getExprLoc(), UO_PreInc, MakeTileIVRef());
14415 BodyParts.append(LoopHelper.
Updates.begin(), LoopHelper.
Updates.end());
14416 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14417 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
14418 BodyParts.push_back(Inner);
14420 Inner->getBeginLoc(), Inner->getEndLoc());
14421 Inner =
new (Context)
14428 for (
int I = NumLoops - 1; I >= 0; --I) {
14429 auto &LoopHelper = LoopHelpers[I];
14430 Expr *NumIterations = LoopHelper.NumIterations;
14431 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14437 auto MakeFloorIVRef = [&
SemaRef = this->
SemaRef, &FloorIndVars, I, IVTy,
14448 Decl *CounterDecl = FloorIndVars[I];
14458 MakeFloorIVRef(), NumIterations);
14465 MakeFloorIVRef(), MakeDimTileSize(I));
14469 Inner =
new (Context)
14471 IncrStmt.
get(), Inner, LoopHelper.Init->getBeginLoc(),
14472 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14491 {OMPC_partial, OMPC_full}))
14495 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
14497 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
14498 assert(!(FullClause && PartialClause) &&
14499 "mutual exclusivity must have been checked before");
14501 constexpr unsigned NumLoops = 1;
14502 Stmt *Body =
nullptr;
14506 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
14507 Body, OriginalInits))
14510 unsigned NumGeneratedLoops = PartialClause ? 1 : 0;
14515 NumGeneratedLoops,
nullptr,
nullptr);
14517 assert(LoopHelpers.size() == NumLoops &&
14518 "Expecting a single-dimensional loop iteration space");
14519 assert(OriginalInits.size() == NumLoops &&
14520 "Expecting a single-dimensional loop iteration space");
14528 Diag(AStmt->
getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
14530 <<
"#pragma omp unroll full";
14538 if (NumGeneratedLoops == 0)
14540 NumGeneratedLoops,
nullptr,
nullptr);
14585 Stmt *LoopStmt =
nullptr;
14590 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
14592 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.
IterationVarRef);
14593 QualType IVTy = IterationVarRef->getType();
14594 assert(LoopHelper.
Counters.size() == 1 &&
14595 "Expecting a single-dimensional loop iteration space");
14596 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.
Counters.front());
14602 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
14603 FactorLoc = FactorVal->getExprLoc();
14608 assert(Factor > 0 &&
"Expected positive unroll factor");
14609 auto MakeFactorExpr = [
this, Factor, IVTy, FactorLoc]() {
14621 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
14622 std::string OuterIVName = (Twine(
".unrolled.iv.") + OrigVarName).str();
14623 std::string InnerIVName = (Twine(
".unroll_inner.iv.") + OrigVarName).str();
14624 std::string InnerTripCountName =
14625 (Twine(
".unroll_inner.tripcount.") + OrigVarName).str();
14630 auto MakeOuterRef = [
this, OuterIVDecl, IVTy, OrigVarLoc]() {
14636 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
14638 auto MakeInnerRef = [
this, InnerIVDecl, IVTy, OrigVarLoc]() {
14644 CaptureVars CopyTransformer(
SemaRef);
14645 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() ->
Expr * {
14668 MakeOuterRef(), MakeFactorExpr());
14673 MakeInnerRef(), EndOfTile.
get());
14678 MakeInnerRef(), MakeNumIterations());
14683 InnerCond1.
get(), InnerCond2.
get());
14689 CurScope, LoopHelper.
Inc->
getExprLoc(), UO_PreInc, MakeInnerRef());
14695 InnerBodyStmts.append(LoopHelper.
Updates.begin(), LoopHelper.
Updates.end());
14696 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14697 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
14698 InnerBodyStmts.push_back(Body);
14702 ForStmt *InnerFor =
new (Context)
14703 ForStmt(Context, InnerInit.
get(), InnerCond.
get(),
nullptr,
14719 LoopHintAttr *UnrollHintAttr =
14720 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
14721 LoopHintAttr::Numeric, MakeFactorExpr());
14738 MakeOuterRef(), MakeNumIterations());
14745 MakeOuterRef(), MakeFactorExpr());
14750 ForStmt *OuterFor =
new (Context)
14751 ForStmt(Context, OuterInit.
get(), OuterConde.
get(),
nullptr,
14756 NumGeneratedLoops, OuterFor,
14770 constexpr unsigned NumLoops = 1;
14771 Stmt *Body =
nullptr;
14775 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
14776 Body, OriginalInits))
14785 assert(LoopHelpers.size() == NumLoops &&
14786 "Expecting a single-dimensional loop iteration space");
14787 assert(OriginalInits.size() == NumLoops &&
14788 "Expecting a single-dimensional loop iteration space");
14792 Stmt *LoopStmt =
nullptr;
14797 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
14799 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.
IterationVarRef);
14800 QualType IVTy = IterationVarRef->getType();
14802 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.
Counters.front());
14815 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
14817 ForwardIVName += OrigVarName;
14819 ReversedIVName += OrigVarName;
14852 CaptureVars CopyTransformer(
SemaRef);
14853 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() ->
Expr * {
14861 auto MakeForwardRef = [&
SemaRef = this->
SemaRef, ForwardIVDecl, IVTy,
14868 auto *ReversedIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
14869 ReversedIVDecl->setDeclName(
14877 ForwardIVDecl->
getType(), OrigVarLoc);
14881 if (!
Init.isUsable())
14890 MakeForwardRef(), MakeNumIterations());
14899 UO_PreInc, MakeForwardRef());
14910 MakeNumIterations(), One);
14918 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
14926 BodyStmts.reserve(LoopHelper.
Updates.size() + 2 +
14927 (isa<CXXForRangeStmt>(LoopStmt) ? 1 : 0));
14928 BodyStmts.push_back(InitReversed.
get());
14929 llvm::append_range(BodyStmts, LoopHelper.
Updates);
14930 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14931 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
14932 BodyStmts.push_back(Body);
14933 auto *ReversedBody =
14938 auto *ReversedFor =
new (Context)
14960 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
14961 size_t NumLoops = PermutationClause ? PermutationClause->
getNumLoops() : 2;
14965 Stmt *Body =
nullptr;
14967 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
14968 LoopHelpers, Body, OriginalInits))
14974 NumLoops, AStmt,
nullptr,
nullptr);
14978 if (PermutationClause &&
14979 llvm::is_contained(PermutationClause->
getArgsRefs(),
nullptr))
14982 assert(LoopHelpers.size() == NumLoops &&
14983 "Expecting loop iteration space dimensionaly to match number of "
14985 assert(OriginalInits.size() == NumLoops &&
14986 "Expecting loop iteration space dimensionaly to match number of "
14991 if (!PermutationClause) {
14992 Permutation = {1, 0};
14995 llvm::BitVector Flags(PermArgs.size());
14996 for (
Expr *PermArg : PermArgs) {
14997 std::optional<llvm::APSInt> PermCstExpr =
14998 PermArg->getIntegerConstantExpr(Context);
15001 uint64_t PermInt = PermCstExpr->getZExtValue();
15002 assert(1 <= PermInt && PermInt <= NumLoops &&
15003 "Must be a permutation; diagnostic emitted in "
15004 "ActOnOpenMPPermutationClause");
15005 if (Flags[PermInt - 1]) {
15006 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
15007 Diag(PermArg->getExprLoc(),
15008 diag::err_omp_interchange_permutation_value_repeated)
15009 << PermInt << ExprRange;
15012 Flags[PermInt - 1] =
true;
15014 Permutation.push_back(PermInt - 1);
15017 if (Permutation.size() != NumLoops)
15022 if (NumLoops <= 1 || llvm::all_of(llvm::enumerate(Permutation), [](
auto P) {
15023 auto [Idx, Arg] =
P;
15027 NumLoops, AStmt, AStmt,
nullptr);
15035 for (
auto I : llvm::seq<int>(NumLoops)) {
15038 assert(LoopHelper.
Counters.size() == 1 &&
15039 "Single-dimensional loop iteration space expected");
15040 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.
Counters.front());
15042 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15048 CaptureVars CopyTransformer(
SemaRef);
15053 Stmt *Inner = Body;
15054 for (
auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
15056 uint64_t SourceIdx = Permutation[TargetIdx];
15058 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
15059 assert(SourceHelper.
Counters.size() == 1 &&
15060 "Single-dimensional loop iteration space expected");
15061 auto *OrigCntVar = cast<DeclRefExpr>(SourceHelper.
Counters.front());
15067 "Expected the logical iteration counter to be an integer");
15069 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15074 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() ->
Expr * {
15076 CopyTransformer.TransformExpr(SourceHelper.
NumIterations));
15083 PermutedCntName.append({llvm::utostr(TargetIdx),
".iv.", OrigVarName});
15084 auto *PermutedCntDecl = cast<VarDecl>(IterVarRef->
getDecl());
15085 PermutedCntDecl->setDeclName(
15087 PermutedIndVars[TargetIdx] = PermutedCntDecl;
15088 auto MakePermutedRef = [
this, PermutedCntDecl, IVTy, OrigVarLoc]() {
15097 if (!Zero.isUsable())
15103 OrigCntVar->getEndLoc());
15113 MakePermutedRef(), MakeNumIterations());
15122 CurScope, SourceHelper.
Inc->
getExprLoc(), UO_PreInc, MakePermutedRef());
15128 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
15129 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15130 BodyParts.push_back(Inner);
15132 Inner->getBeginLoc(), Inner->getEndLoc());
15133 Inner =
new (Context)
ForStmt(
15134 Context, InitStmt.
get(), CondExpr.
get(),
nullptr, IncrStmt.
get(), Inner,
15140 NumLoops, AStmt, Inner,
15154 case OMPC_num_threads:
15163 case OMPC_allocator:
15166 case OMPC_collapse:
15172 case OMPC_priority:
15184 case OMPC_novariants:
15187 case OMPC_nocontext:
15202 case OMPC_ompx_dyn_cgroup_mem:
15208 case OMPC_grainsize:
15209 case OMPC_num_tasks:
15213 case OMPC_proc_bind:
15214 case OMPC_schedule:
15216 case OMPC_firstprivate:
15217 case OMPC_lastprivate:
15219 case OMPC_reduction:
15220 case OMPC_task_reduction:
15221 case OMPC_in_reduction:
15225 case OMPC_copyprivate:
15228 case OMPC_mergeable:
15229 case OMPC_threadprivate:
15231 case OMPC_allocate:
15248 case OMPC_dist_schedule:
15249 case OMPC_defaultmap:
15254 case OMPC_use_device_ptr:
15255 case OMPC_use_device_addr:
15256 case OMPC_is_device_ptr:
15257 case OMPC_unified_address:
15258 case OMPC_unified_shared_memory:
15259 case OMPC_reverse_offload:
15260 case OMPC_dynamic_allocators:
15261 case OMPC_atomic_default_mem_order:
15262 case OMPC_device_type:
15264 case OMPC_nontemporal:
15267 case OMPC_severity:
15269 case OMPC_inclusive:
15270 case OMPC_exclusive:
15271 case OMPC_uses_allocators:
15272 case OMPC_affinity:
15275 case OMPC_num_teams:
15276 case OMPC_thread_limit:
15278 llvm_unreachable(
"Clause is not allowed.");
15291 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
15292 "Invalid directive with CKind-clause");
15295 if (NameModifier != OMPD_unknown &&
15296 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
15297 return OMPD_unknown;
15316 case OMPD_teams_loop:
15317 case OMPD_target_teams_loop:
15321 case OMPD_target_update:
15322 case OMPD_target_enter_data:
15323 case OMPD_target_exit_data:
15329 case OMPC_num_teams:
15330 case OMPC_thread_limit:
15331 case OMPC_ompx_dyn_cgroup_mem:
15332 if (Leafs[0] == OMPD_target)
15333 return OMPD_target;
15336 if (Leafs[0] == OMPD_target ||
15337 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
15338 OMPD_target_enter_data, OMPD_target_exit_data},
15342 case OMPC_novariants:
15343 case OMPC_nocontext:
15344 if (DKind == OMPD_dispatch)
15348 if (DKind == OMPD_metadirective)
15349 return OMPD_metadirective;
15352 return OMPD_unknown;
15365 int InnermostIdx = [&]() {
15366 for (
int I = EndIdx - 1; I >= 0; --I) {
15367 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
15375 for (
int I = InnermostIdx - 1; I >= 0; --I) {
15380 if (Regions[0] != OMPD_unknown)
15381 return Regions.back();
15383 return OMPD_unknown;
15388 for (
int I = 0,
E = Leafs.size(); I !=
E; ++I) {
15389 if (Leafs[I] == Dir)
15395 int End = NameModifier == OMPD_unknown ? Leafs.size()
15396 : GetLeafIndex(NameModifier);
15397 return GetEnclosingRegion(End, CKind);
15400 return OMPD_unknown;
15408 Stmt *HelperValStmt =
nullptr;
15411 !
Condition->isInstantiationDependent() &&
15412 !
Condition->containsUnexpandedParameterPack()) {
15417 ValExpr = Val.
get();
15421 DKind, OMPC_if,
getLangOpts().OpenMP, NameModifier);
15422 if (CaptureRegion != OMPD_unknown &&
15425 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15426 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
15432 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
15433 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
15441 Stmt *HelperValStmt =
nullptr;
15444 !
Condition->isInstantiationDependent() &&
15445 !
Condition->containsUnexpandedParameterPack()) {
15455 if (CaptureRegion != OMPD_unknown &&
15458 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15459 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
15465 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
15476 IntConvertDiagnoser()
15477 : ICEConvertDiagnoser(
false,
false,
true) {}
15480 return S.
Diag(
Loc, diag::err_omp_not_integral) <<
T;
15484 return S.
Diag(
Loc, diag::err_omp_incomplete_type) <<
T;
15489 return S.
Diag(
Loc, diag::err_omp_explicit_conversion) <<
T << ConvTy;
15498 return S.
Diag(
Loc, diag::err_omp_ambiguous_conversion) <<
T;
15507 llvm_unreachable(
"conversion functions are permitted");
15509 } ConvertDiagnoser;
15515 bool StrictlyPositive,
bool BuildCapture =
false,
15518 Stmt **HelperValStmt =
nullptr) {
15524 if (
Value.isInvalid())
15527 ValExpr =
Value.get();
15529 if (std::optional<llvm::APSInt>
Result =
15531 if (
Result->isSigned() &&
15532 !((!StrictlyPositive &&
Result->isNonNegative()) ||
15533 (StrictlyPositive &&
Result->isStrictlyPositive()))) {
15534 SemaRef.
Diag(
Loc, diag::err_omp_negative_expression_in_clause)
15535 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
15544 if (*CaptureRegion != OMPD_unknown &&
15547 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15548 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15559 Expr *ValExpr = NumThreads;
15560 Stmt *HelperValStmt =
nullptr;
15571 if (CaptureRegion != OMPD_unknown &&
15574 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15575 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
15580 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
15585 bool SuppressExprDiags) {
15594 if (SuppressExprDiags) {
15598 SuppressedDiagnoser() : VerifyICEDiagnoser(
true) {}
15601 llvm_unreachable(
"Diagnostic suppressed");
15613 if ((StrictlyPositive && !
Result.isStrictlyPositive()) ||
15614 (!StrictlyPositive && !
Result.isNonNegative())) {
15616 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
15620 if ((CKind == OMPC_aligned || CKind == OMPC_align) && !
Result.isPowerOf2()) {
15625 if (CKind == OMPC_collapse &&
DSAStack->getAssociatedLoops() == 1)
15627 else if (CKind == OMPC_ordered)
15662 DSAStackTy *Stack) {
15663 if (!Stack->getOMPAllocatorHandleT().isNull())
15670 S.
Diag(
Loc, diag::err_omp_implied_type_not_found)
15671 <<
"omp_allocator_handle_t";
15676 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
15679 bool ErrorFound =
false;
15680 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
15681 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
15682 StringRef Allocator =
15683 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
15685 auto *VD = dyn_cast_or_null<ValueDecl>(
15705 Stack->setAllocator(AllocatorKind, Res.
get());
15708 S.
Diag(
Loc, diag::err_omp_implied_type_not_found)
15709 <<
"omp_allocator_handle_t";
15726 if (Allocator.isInvalid())
15729 Allocator.get(),
DSAStack->getOMPAllocatorHandleT(),
15732 if (Allocator.isInvalid())
15758 Expr *NumForLoops) {
15764 if (NumForLoops && LParenLoc.
isValid()) {
15769 NumForLoops = NumForLoopsResult.
get();
15771 NumForLoops =
nullptr;
15775 NumForLoops ?
DSAStack->getAssociatedLoops() : 0,
15776 StartLoc, LParenLoc, EndLoc);
15777 DSAStack->setOrderedRegion(
true, NumForLoops, Clause);
15788 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15790 case OMPC_proc_bind:
15792 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15794 case OMPC_atomic_default_mem_order:
15797 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15801 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15805 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15809 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15813 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15815 case OMPC_severity:
15818 LParenLoc, EndLoc);
15822 case OMPC_num_threads:
15826 case OMPC_allocator:
15827 case OMPC_collapse:
15828 case OMPC_schedule:
15830 case OMPC_firstprivate:
15831 case OMPC_lastprivate:
15833 case OMPC_reduction:
15834 case OMPC_task_reduction:
15835 case OMPC_in_reduction:
15839 case OMPC_copyprivate:
15843 case OMPC_mergeable:
15844 case OMPC_threadprivate:
15845 case OMPC_allocate:
15862 case OMPC_num_teams:
15863 case OMPC_thread_limit:
15864 case OMPC_priority:
15865 case OMPC_grainsize:
15867 case OMPC_num_tasks:
15869 case OMPC_dist_schedule:
15870 case OMPC_defaultmap:
15875 case OMPC_use_device_ptr:
15876 case OMPC_use_device_addr:
15877 case OMPC_is_device_ptr:
15878 case OMPC_has_device_addr:
15879 case OMPC_unified_address:
15880 case OMPC_unified_shared_memory:
15881 case OMPC_reverse_offload:
15882 case OMPC_dynamic_allocators:
15883 case OMPC_device_type:
15885 case OMPC_nontemporal:
15887 case OMPC_novariants:
15888 case OMPC_nocontext:
15890 case OMPC_inclusive:
15891 case OMPC_exclusive:
15892 case OMPC_uses_allocators:
15893 case OMPC_affinity:
15897 llvm_unreachable(
"Clause is not allowed.");
15906 llvm::raw_svector_ostream Out(Buffer);
15907 unsigned Skipped = Exclude.size();
15908 for (
unsigned I =
First; I <
Last; ++I) {
15909 if (llvm::is_contained(Exclude, I)) {
15914 if (I + Skipped + 2 ==
Last)
15916 else if (I + Skipped + 1 !=
Last)
15919 return std::string(Out.str());
15927 if (Kind == OMP_DEFAULT_unknown) {
15928 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15930 unsigned(OMP_DEFAULT_unknown))
15931 << getOpenMPClauseName(OMPC_default);
15936 case OMP_DEFAULT_none:
15937 DSAStack->setDefaultDSANone(KindKwLoc);
15939 case OMP_DEFAULT_shared:
15940 DSAStack->setDefaultDSAShared(KindKwLoc);
15942 case OMP_DEFAULT_firstprivate:
15943 DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
15945 case OMP_DEFAULT_private:
15946 DSAStack->setDefaultDSAPrivate(KindKwLoc);
15949 llvm_unreachable(
"DSA unexpected in OpenMP default clause");
15961 if (Kind == OMP_PROC_BIND_unknown) {
15962 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15964 unsigned(OMP_PROC_BIND_master),
15967 ? OMP_PROC_BIND_primary
15968 : OMP_PROC_BIND_spread) +
15970 << getOpenMPClauseName(OMPC_proc_bind);
15973 if (Kind == OMP_PROC_BIND_primary &&
getLangOpts().OpenMP < 51)
15974 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15976 unsigned(OMP_PROC_BIND_master),
15978 unsigned(OMP_PROC_BIND_spread) + 1)
15979 << getOpenMPClauseName(OMPC_proc_bind);
15988 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15990 OMPC_atomic_default_mem_order, 0,
15992 << getOpenMPClauseName(OMPC_atomic_default_mem_order);
15996 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16005 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16008 << getOpenMPClauseName(OMPC_at);
16012 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16021 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16024 << getOpenMPClauseName(OMPC_severity);
16035 assert(ME &&
"NULL expr in Message clause");
16036 if (!isa<StringLiteral>(ME)) {
16038 << getOpenMPClauseName(OMPC_message);
16049 if (Kind != OMPC_ORDER_concurrent ||
16054 "OMPC_ORDER_unknown not greater than 0");
16056 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16060 << getOpenMPClauseName(OMPC_order);
16065 Diag(MLoc, diag::err_omp_unexpected_clause_value)
16069 << getOpenMPClauseName(OMPC_order);
16071 DSAStack->setRegionHasOrderConcurrent(
true);
16074 unsigned existingFlags =
DSAStack->getCurScope()->getFlags();
16075 DSAStack->getCurScope()->setFlags(existingFlags |
16081 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
16090 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
16092 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
16093 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
16095 Except.push_back(OMPC_DEPEND_inoutset);
16096 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16099 << getOpenMPClauseName(OMPC_update);
16103 KindKwLoc, Kind, EndLoc);
16112 for (
Expr *&SizeExpr : SanitizedSizeExprs) {
16122 QualType SizeTy = SizeExpr->getType();
16151 if (!SizeExpr->isInstantiationDependent() && !IsValid)
16152 SizeExpr =
nullptr;
16156 SanitizedSizeExprs);
16163 size_t NumLoops = PermExprs.size();
16165 llvm::append_range(SanitizedPermExprs, PermExprs);
16167 for (
Expr *&PermExpr : SanitizedPermExprs) {
16170 if (!PermExpr || PermExpr->isInstantiationDependent())
16173 llvm::APSInt PermVal;
16176 bool IsValid = PermEvalExpr.
isUsable();
16178 PermExpr = PermEvalExpr.
get();
16180 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
16184 diag::err_omp_interchange_permutation_value_range)
16185 << NumLoops << ExprRange;
16189 if (!PermExpr->isInstantiationDependent() && !IsValid)
16190 PermExpr =
nullptr;
16194 EndLoc, SanitizedPermExprs);
16210 FactorExpr, OMPC_partial,
true);
16213 FactorExpr = FactorResult.
get();
16228 LParenLoc, EndLoc);
16238 case OMPC_schedule:
16239 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
16240 assert(Argument.size() == NumberOfElements &&
16241 ArgumentLoc.size() == NumberOfElements);
16246 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
16247 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
16250 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16252 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
16255 case OMPC_dist_schedule:
16258 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
16260 case OMPC_defaultmap:
16261 enum { Modifier, DefaultmapKind };
16265 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
16269 enum { OrderModifier, OrderKind };
16273 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
16276 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16279 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16281 case OMPC_grainsize:
16282 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16283 "Modifier for grainsize clause and its location are expected.");
16286 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16288 case OMPC_num_tasks:
16289 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16290 "Modifier for num_tasks clause and its location are expected.");
16293 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16296 case OMPC_num_threads:
16300 case OMPC_allocator:
16301 case OMPC_collapse:
16303 case OMPC_proc_bind:
16305 case OMPC_firstprivate:
16306 case OMPC_lastprivate:
16308 case OMPC_reduction:
16309 case OMPC_task_reduction:
16310 case OMPC_in_reduction:
16314 case OMPC_copyprivate:
16318 case OMPC_mergeable:
16319 case OMPC_threadprivate:
16320 case OMPC_allocate:
16337 case OMPC_num_teams:
16338 case OMPC_thread_limit:
16339 case OMPC_priority:
16346 case OMPC_use_device_ptr:
16347 case OMPC_use_device_addr:
16348 case OMPC_is_device_ptr:
16349 case OMPC_has_device_addr:
16350 case OMPC_unified_address:
16351 case OMPC_unified_shared_memory:
16352 case OMPC_reverse_offload:
16353 case OMPC_dynamic_allocators:
16354 case OMPC_atomic_default_mem_order:
16355 case OMPC_device_type:
16357 case OMPC_nontemporal:
16359 case OMPC_severity:
16362 case OMPC_novariants:
16363 case OMPC_nocontext:
16365 case OMPC_inclusive:
16366 case OMPC_exclusive:
16367 case OMPC_uses_allocators:
16368 case OMPC_affinity:
16372 llvm_unreachable(
"Clause is not allowed.");
16383 Excluded.push_back(M2);
16384 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
16385 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
16386 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
16387 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
16388 S.
Diag(M1Loc, diag::err_omp_unexpected_clause_value)
16393 << getOpenMPClauseName(OMPC_schedule);
16411 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
16412 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
16413 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
16414 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
16415 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
16421 std::string Values;
16431 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16432 << Values << getOpenMPClauseName(OMPC_schedule);
16440 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
16441 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
16442 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
16443 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
16444 diag::err_omp_schedule_nonmonotonic_static);
16447 Expr *ValExpr = ChunkSize;
16448 Stmt *HelperValStmt =
nullptr;
16459 ValExpr = Val.
get();
16464 if (std::optional<llvm::APSInt>
Result =
16466 if (
Result->isSigned() && !
Result->isStrictlyPositive()) {
16467 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
16472 DSAStack->getCurrentDirective(), OMPC_schedule,
16476 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16477 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16485 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
16502 case OMPC_mergeable:
16550 case OMPC_unified_address:
16553 case OMPC_unified_shared_memory:
16556 case OMPC_reverse_offload:
16559 case OMPC_dynamic_allocators:
16573 case OMPC_ompx_bare:
16578 case OMPC_num_threads:
16582 case OMPC_allocator:
16583 case OMPC_collapse:
16584 case OMPC_schedule:
16586 case OMPC_firstprivate:
16587 case OMPC_lastprivate:
16589 case OMPC_reduction:
16590 case OMPC_task_reduction:
16591 case OMPC_in_reduction:
16595 case OMPC_copyprivate:
16597 case OMPC_proc_bind:
16598 case OMPC_threadprivate:
16599 case OMPC_allocate:
16605 case OMPC_num_teams:
16606 case OMPC_thread_limit:
16607 case OMPC_priority:
16608 case OMPC_grainsize:
16609 case OMPC_num_tasks:
16611 case OMPC_dist_schedule:
16612 case OMPC_defaultmap:
16617 case OMPC_use_device_ptr:
16618 case OMPC_use_device_addr:
16619 case OMPC_is_device_ptr:
16620 case OMPC_has_device_addr:
16621 case OMPC_atomic_default_mem_order:
16622 case OMPC_device_type:
16624 case OMPC_nontemporal:
16627 case OMPC_severity:
16629 case OMPC_novariants:
16630 case OMPC_nocontext:
16632 case OMPC_inclusive:
16633 case OMPC_exclusive:
16634 case OMPC_uses_allocators:
16635 case OMPC_affinity:
16637 case OMPC_ompx_dyn_cgroup_mem:
16639 llvm_unreachable(
"Clause is not allowed.");
16698 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
16779 if (!
hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
16780 StringRef
Expected =
"'init', 'use', 'destroy', or 'nowait'";
16781 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
16782 <<
Expected << getOpenMPDirectiveName(OMPD_interop);
16795 bool HasInitClause =
false;
16796 bool IsTargetSync =
false;
16800 if (
const auto *InitClause = dyn_cast<OMPInitClause>(
C)) {
16801 HasInitClause =
true;
16802 if (InitClause->getIsTargetSync())
16803 IsTargetSync =
true;
16804 }
else if (
const auto *DC = dyn_cast<OMPDependClause>(
C)) {
16808 if (DependClause && HasInitClause && !IsTargetSync) {
16809 Diag(DependClause->
getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
16823 if (ClauseKind == OMPC_init) {
16824 auto *
E = cast<OMPInitClause>(
C)->getInteropVar();
16826 }
else if (ClauseKind == OMPC_use) {
16827 auto *
E = cast<OMPUseClause>(
C)->getInteropVar();
16829 }
else if (ClauseKind == OMPC_destroy) {
16830 auto *
E = cast<OMPDestroyClause>(
C)->getInteropVar();
16835 if (!InteropVars.insert(
DeclResult.first).second) {
16836 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
16852 Expr *RefExpr = InteropVarExpr;
16855 false,
"omp_interop_t");
16866 bool HasError =
false;
16872 if (
const auto *TD = dyn_cast<TypeDecl>(ND)) {
16873 InteropType =
QualType(TD->getTypeForDecl(), 0);
16882 SemaRef.
Diag(VarLoc, diag::err_omp_implied_type_not_found)
16883 <<
"omp_interop_t";
16889 SemaRef.
Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
16895 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
16897 SemaRef.
Diag(VarLoc, diag::err_omp_interop_variable_expected)
16919 if (isa<StringLiteral>(
E))
16926 StartLoc, LParenLoc, VarLoc, EndLoc);
16939 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
16948 DSAStack->getCurrentDirective() == OMPD_depobj) {
16949 Diag(StartLoc, diag::err_omp_expected_clause_argument)
16950 << getOpenMPClauseName(OMPC_destroy)
16951 << getOpenMPDirectiveName(OMPD_depobj);
16967 Stmt *HelperValStmt =
nullptr;
16970 !
Condition->isInstantiationDependent() &&
16971 !
Condition->containsUnexpandedParameterPack()) {
16981 if (CaptureRegion != OMPD_unknown &&
16984 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16985 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16991 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16999 Stmt *HelperValStmt =
nullptr;
17002 !
Condition->isInstantiationDependent() &&
17003 !
Condition->containsUnexpandedParameterPack()) {
17013 if (CaptureRegion != OMPD_unknown &&
17016 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17017 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
17023 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17030 Expr *ValExpr = ThreadID;
17031 Stmt *HelperValStmt =
nullptr;
17036 if (CaptureRegion != OMPD_unknown &&
17039 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17040 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
17045 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17056 int ExtraModifier =
Data.ExtraModifier;
17063 case OMPC_firstprivate:
17066 case OMPC_lastprivate:
17068 "Unexpected lastprivate modifier.");
17071 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
17076 case OMPC_reduction:
17078 "Unexpected lastprivate modifier.");
17081 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
17082 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
17084 case OMPC_task_reduction:
17086 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17087 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
17089 case OMPC_in_reduction:
17091 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17092 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
17096 "Unexpected linear modifier.");
17098 VarList,
Data.DepModOrTailExpr, StartLoc, LParenLoc,
17100 ColonLoc,
Data.StepModifierLoc, EndLoc);
17104 LParenLoc, ColonLoc, EndLoc);
17109 case OMPC_copyprivate:
17117 "Unexpected depend modifier.");
17120 ColonLoc,
Data.OmpAllMemoryLoc},
17121 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
17125 "Unexpected map modifier.");
17127 Data.IteratorExpr,
Data.MapTypeModifiers,
Data.MapTypeModifiersLoc,
17128 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId,
17130 ExtraModifierLoc, ColonLoc, VarList, Locs);
17135 Data.ReductionOrMapperIdScopeSpec,
17136 Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
17140 Data.ReductionOrMapperIdScopeSpec,
17141 Data.ReductionOrMapperId, ColonLoc, VarList,
17144 case OMPC_use_device_ptr:
17147 case OMPC_use_device_addr:
17150 case OMPC_is_device_ptr:
17153 case OMPC_has_device_addr:
17156 case OMPC_allocate:
17158 Data.AllocClauseModifier, VarList, StartLoc,
17159 LParenLoc, ColonLoc, EndLoc);
17161 case OMPC_nontemporal:
17164 case OMPC_inclusive:
17167 case OMPC_exclusive:
17170 case OMPC_affinity:
17172 Data.DepModOrTailExpr, VarList);
17174 case OMPC_doacross:
17177 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
17179 case OMPC_num_teams:
17182 case OMPC_thread_limit:
17188 case OMPC_num_threads:
17192 case OMPC_allocator:
17193 case OMPC_collapse:
17195 case OMPC_proc_bind:
17196 case OMPC_schedule:
17200 case OMPC_mergeable:
17201 case OMPC_threadprivate:
17215 case OMPC_priority:
17216 case OMPC_grainsize:
17218 case OMPC_num_tasks:
17220 case OMPC_dist_schedule:
17221 case OMPC_defaultmap:
17224 case OMPC_unified_address:
17225 case OMPC_unified_shared_memory:
17226 case OMPC_reverse_offload:
17227 case OMPC_dynamic_allocators:
17228 case OMPC_atomic_default_mem_order:
17229 case OMPC_device_type:
17233 case OMPC_severity:
17236 case OMPC_novariants:
17237 case OMPC_nocontext:
17239 case OMPC_uses_allocators:
17243 llvm_unreachable(
"Clause is not allowed.");
17274 bool IsImplicitClause =
17276 for (
Expr *RefExpr : VarList) {
17277 assert(RefExpr &&
"NULL expr in OpenMP private clause.");
17280 Expr *SimpleRefExpr = RefExpr;
17284 Vars.push_back(RefExpr);
17285 PrivateCopies.push_back(
nullptr);
17292 auto *VD = dyn_cast<VarDecl>(
D);
17298 diag::err_omp_private_incomplete_type))
17300 Type =
Type.getNonReferenceType();
17320 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
17321 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
17322 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
17323 << getOpenMPClauseName(OMPC_private);
17332 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17333 << getOpenMPClauseName(OMPC_private) <<
Type
17334 << getOpenMPDirectiveName(CurrDir);
17335 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
17338 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17353 CurrDir == OMPD_target) {
17355 if (
DSAStack->checkMappableExprComponentListsForDecl(
17359 ConflictKind = WhereFoundClauseKind;
17362 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17363 << getOpenMPClauseName(OMPC_private)
17364 << getOpenMPClauseName(ConflictKind)
17365 << getOpenMPDirectiveName(CurrDir);
17384 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
17393 auto *FD = dyn_cast<FieldDecl>(
D);
17397 RefExpr->getExprLoc());
17401 if (!IsImplicitClause)
17402 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_private, Ref);
17404 ? RefExpr->IgnoreParens()
17406 PrivateCopies.push_back(VDPrivateRefExpr);
17413 Vars, PrivateCopies);
17424 bool IsImplicitClause =
17428 for (
Expr *RefExpr : VarList) {
17429 assert(RefExpr &&
"NULL expr in OpenMP firstprivate clause.");
17432 Expr *SimpleRefExpr = RefExpr;
17436 Vars.push_back(RefExpr);
17437 PrivateCopies.push_back(
nullptr);
17438 Inits.push_back(
nullptr);
17444 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
17446 auto *VD = dyn_cast<VarDecl>(
D);
17452 diag::err_omp_firstprivate_incomplete_type))
17454 Type =
Type.getNonReferenceType();
17464 DSAStackTy::DSAVarData TopDVar;
17465 if (!IsImplicitClause) {
17466 DSAStackTy::DSAVarData DVar =
17478 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
17480 DVar.CKind != OMPC_lastprivate) &&
17482 Diag(ELoc, diag::err_omp_wrong_dsa)
17483 << getOpenMPClauseName(DVar.CKind)
17484 << getOpenMPClauseName(OMPC_firstprivate);
17500 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
17501 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
17502 Diag(ELoc, diag::err_omp_wrong_dsa)
17503 << getOpenMPClauseName(DVar.CKind)
17504 << getOpenMPClauseName(OMPC_firstprivate);
17528 DVar =
DSAStack->getImplicitDSA(
D,
true);
17529 if (DVar.CKind != OMPC_shared &&
17532 DVar.DKind == OMPD_unknown)) {
17533 Diag(ELoc, diag::err_omp_required_access)
17534 << getOpenMPClauseName(OMPC_firstprivate)
17535 << getOpenMPClauseName(OMPC_shared);
17555 return C == OMPC_reduction && !AppliedToPointee;
17563 if (DVar.CKind == OMPC_reduction &&
17567 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
17568 << getOpenMPDirectiveName(DVar.DKind);
17584 CurrDir == OMPD_target) {
17586 if (
DSAStack->checkMappableExprComponentListsForDecl(
17591 ConflictKind = WhereFoundClauseKind;
17594 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17595 << getOpenMPClauseName(OMPC_firstprivate)
17596 << getOpenMPClauseName(ConflictKind)
17597 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
17607 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17608 << getOpenMPClauseName(OMPC_firstprivate) <<
Type
17609 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
17610 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
17613 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17622 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
17628 Expr *VDInitRefExpr =
nullptr;
17638 ElemType,
".firstprivate.temp");
17653 ".firstprivate.temp");
17655 RefExpr->getExprLoc());
17661 if (IsImplicitClause) {
17662 Diag(RefExpr->getExprLoc(),
17663 diag::note_omp_task_predetermined_firstprivate_here);
17670 RefExpr->getExprLoc());
17673 if (TopDVar.CKind == OMPC_lastprivate) {
17674 Ref = TopDVar.PrivateCopy;
17676 auto *FD = dyn_cast<FieldDecl>(
D);
17681 RefExpr->getExprLoc());
17685 ExprCaptures.push_back(Ref->
getDecl());
17688 if (!IsImplicitClause)
17689 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
17691 ? RefExpr->IgnoreParens()
17693 PrivateCopies.push_back(VDPrivateRefExpr);
17694 Inits.push_back(VDInitRefExpr);
17701 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
17710 assert(ColonLoc.
isValid() &&
"Colon location must be valid.");
17711 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
17714 << getOpenMPClauseName(OMPC_lastprivate);
17724 for (
Expr *RefExpr : VarList) {
17725 assert(RefExpr &&
"NULL expr in OpenMP lastprivate clause.");
17728 Expr *SimpleRefExpr = RefExpr;
17732 Vars.push_back(RefExpr);
17733 SrcExprs.push_back(
nullptr);
17734 DstExprs.push_back(
nullptr);
17735 AssignmentOps.push_back(
nullptr);
17742 auto *VD = dyn_cast<VarDecl>(
D);
17748 diag::err_omp_lastprivate_incomplete_type))
17750 Type =
Type.getNonReferenceType();
17767 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
17768 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
17771 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17785 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
17786 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
17788 DVar.CKind != OMPC_firstprivate) &&
17789 (DVar.CKind != OMPC_private || DVar.RefExpr !=
nullptr)) {
17790 Diag(ELoc, diag::err_omp_wrong_dsa)
17791 << getOpenMPClauseName(DVar.CKind)
17792 << getOpenMPClauseName(OMPC_lastprivate);
17803 DSAStackTy::DSAVarData TopDVar = DVar;
17807 DVar =
DSAStack->getImplicitDSA(
D,
true);
17808 if (DVar.CKind != OMPC_shared) {
17809 Diag(ELoc, diag::err_omp_required_access)
17810 << getOpenMPClauseName(OMPC_lastprivate)
17811 << getOpenMPClauseName(OMPC_shared);
17827 Type.getUnqualifiedType(),
".lastprivate.src",
17838 PseudoDstExpr, PseudoSrcExpr);
17848 if (TopDVar.CKind == OMPC_firstprivate) {
17849 Ref = TopDVar.PrivateCopy;
17853 ExprCaptures.push_back(Ref->
getDecl());
17855 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
17863 SimpleRefExpr, RefRes.
get());
17866 ExprPostUpdates.push_back(
17870 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
17872 ? RefExpr->IgnoreParens()
17874 SrcExprs.push_back(PseudoSrcExpr);
17875 DstExprs.push_back(PseudoDstExpr);
17876 AssignmentOps.push_back(AssignmentOp.
get());
17883 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
17884 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
17894 for (
Expr *RefExpr : VarList) {
17895 assert(RefExpr &&
"NULL expr in OpenMP lastprivate clause.");
17898 Expr *SimpleRefExpr = RefExpr;
17902 Vars.push_back(RefExpr);
17908 auto *VD = dyn_cast<VarDecl>(
D);
17916 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
17917 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
17919 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
17920 << getOpenMPClauseName(OMPC_shared);
17929 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
17931 ? RefExpr->IgnoreParens()
17943class DSARefChecker :
public StmtVisitor<DSARefChecker, bool> {
17948 if (
auto *VD = dyn_cast<VarDecl>(
E->getDecl())) {
17949 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD,
false);
17950 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
17952 if (DVar.CKind != OMPC_unknown)
17954 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
17961 return DVarPrivate.CKind != OMPC_unknown;
17965 bool VisitStmt(
Stmt *S) {
17966 for (
Stmt *Child : S->children()) {
17967 if (Child && Visit(Child))
17972 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
17979class TransformExprToCaptures :
public TreeTransform<TransformExprToCaptures> {
17986 : BaseTransform(SemaRef),
Field(
FieldDecl), CapturedExpr(nullptr) {}
17990 E->getMemberDecl() == Field) {
17992 return CapturedExpr;
17994 return BaseTransform::TransformMemberExpr(
E);
17996 DeclRefExpr *getCapturedExpr() {
return CapturedExpr; }
18000template <
typename T,
typename U>
18003 for (
U &
Set : Lookups) {
18004 for (
auto *
D :
Set) {
18005 if (
T Res = Gen(cast<ValueDecl>(
D)))
18020 auto ND = cast<NamedDecl>(RD);
18038 AssociatedClasses);
18051 for (
auto *NS : AssociatedNamespaces) {
18064 for (
auto *
D : R) {
18065 auto *Underlying =
D;
18066 if (
auto *USD = dyn_cast<UsingShadowDecl>(
D))
18067 Underlying = USD->getTargetDecl();
18069 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
18070 !isa<OMPDeclareMapperDecl>(Underlying))
18077 if (
auto *USD = dyn_cast<UsingShadowDecl>(
D))
18078 Underlying = USD->getTargetDecl();
18080 Lookups.emplace_back();
18081 Lookups.back().addDecl(Underlying);
18101 S = S->getParent();
18102 }
while (S && !S->isDeclScope(
D));
18104 S = S->getParent();
18105 Lookups.emplace_back();
18106 Lookups.back().append(Lookup.
begin(), Lookup.
end());
18109 }
else if (
auto *ULE =
18110 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
18112 Decl *PrevD =
nullptr;
18116 else if (
auto *DRD = dyn_cast<OMPDeclareReductionDecl>(
D))
18117 Lookups.back().addDecl(DRD);
18124 filterLookupForUDReductionAndMapper<bool>(Lookups, [](
ValueDecl *
D) {
18125 return !D->isInvalidDecl() &&
18126 (D->getType()->isDependentType() ||
18127 D->getType()->isInstantiationDependentType() ||
18128 D->getType()->containsUnexpandedParameterPack());
18141 true, ResSet.
begin(), ResSet.
end(),
false,
18163 TyRec->getDecl()->getDefinition()) {
18166 if (Lookup.
empty()) {
18167 Lookups.emplace_back();
18168 Lookups.back().append(Lookup.
begin(), Lookup.
end());
18175 if (
auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18185 if (
auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18210 if (ReductionIdScopeSpec.
isSet()) {
18211 SemaRef.
Diag(
Loc, diag::err_omp_not_resolved_reduction_identifier)
18220struct ReductionData {
18245 unsigned RedModifier = 0;
18246 ReductionData() =
delete;
18248 ReductionData(
unsigned Size,
unsigned Modifier = 0) : RedModifier(Modifier) {
18249 Vars.reserve(Size);
18250 Privates.reserve(Size);
18251 LHSs.reserve(Size);
18252 RHSs.reserve(Size);
18253 ReductionOps.reserve(Size);
18254 if (RedModifier == OMPC_REDUCTION_inscan) {
18255 InscanCopyOps.reserve(Size);
18256 InscanCopyArrayTemps.reserve(Size);
18257 InscanCopyArrayElems.reserve(Size);
18259 TaskgroupDescriptors.reserve(Size);
18260 ExprCaptures.reserve(Size);
18261 ExprPostUpdates.reserve(Size);
18265 void push(
Expr *Item,
Expr *ReductionOp) {
18266 Vars.emplace_back(Item);
18267 Privates.emplace_back(
nullptr);
18268 LHSs.emplace_back(
nullptr);
18269 RHSs.emplace_back(
nullptr);
18270 ReductionOps.emplace_back(ReductionOp);
18271 TaskgroupDescriptors.emplace_back(
nullptr);
18272 if (RedModifier == OMPC_REDUCTION_inscan) {
18273 InscanCopyOps.push_back(
nullptr);
18274 InscanCopyArrayTemps.push_back(
nullptr);
18275 InscanCopyArrayElems.push_back(
nullptr);
18280 Expr *TaskgroupDescriptor,
Expr *CopyOp,
Expr *CopyArrayTemp,
18281 Expr *CopyArrayElem) {
18282 Vars.emplace_back(Item);
18283 Privates.emplace_back(Private);
18284 LHSs.emplace_back(LHS);
18285 RHSs.emplace_back(RHS);
18286 ReductionOps.emplace_back(ReductionOp);
18287 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
18288 if (RedModifier == OMPC_REDUCTION_inscan) {
18289 InscanCopyOps.push_back(CopyOp);
18290 InscanCopyArrayTemps.push_back(CopyArrayTemp);
18291 InscanCopyArrayElems.push_back(CopyArrayElem);
18293 assert(CopyOp ==
nullptr && CopyArrayTemp ==
nullptr &&
18294 CopyArrayElem ==
nullptr &&
18295 "Copy operation must be used for inscan reductions only.");
18305 if (Length ==
nullptr) {
18312 SingleElement =
true;
18313 ArraySizes.push_back(llvm::APSInt::get(1));
18316 if (!Length->EvaluateAsInt(
Result, Context))
18319 llvm::APSInt ConstantLengthValue =
Result.Val.getInt();
18320 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
18321 ArraySizes.push_back(ConstantLengthValue);
18329 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base)) {
18330 Length = TempOASE->getLength();
18331 if (Length ==
nullptr) {
18338 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
18339 ArraySizes.push_back(ConstantOne);
18342 if (!Length->EvaluateAsInt(
Result, Context))
18345 llvm::APSInt ConstantLengthValue =
Result.Val.getInt();
18346 if (ConstantLengthValue.getSExtValue() != 1)
18349 ArraySizes.push_back(ConstantLengthValue);
18351 Base = TempOASE->getBase()->IgnoreParenImpCasts();
18355 if (!SingleElement) {
18356 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base)) {
18358 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
18359 ArraySizes.push_back(ConstantOne);
18360 Base = TempASE->getBase()->IgnoreParenImpCasts();
18372 return BO_AddAssign;
18374 return BO_MulAssign;
18376 return BO_AndAssign;
18378 return BO_OrAssign;
18380 return BO_XorAssign;
18436 case OO_Array_Delete:
18445 case OO_GreaterEqual:
18447 case OO_MinusEqual:
18449 case OO_SlashEqual:
18450 case OO_PercentEqual:
18451 case OO_CaretEqual:
18455 case OO_GreaterGreater:
18456 case OO_LessLessEqual:
18457 case OO_GreaterGreaterEqual:
18458 case OO_EqualEqual:
18459 case OO_ExclaimEqual:
18462 case OO_MinusMinus:
18468 case OO_Conditional:
18471 llvm_unreachable(
"Unexpected reduction identifier");
18474 if (II->isStr(
"max"))
18476 else if (II->isStr(
"min"))
18484 if (OOK == OO_Minus && S.
LangOpts.OpenMP == 52)
18485 S.
Diag(ReductionId.
getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
18488 if (ReductionIdScopeSpec.
isValid())
18494 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
18495 bool FirstIter =
true;
18496 for (
Expr *RefExpr : VarList) {
18497 assert(RefExpr &&
"nullptr expr in OpenMP reduction clause.");
18505 if (!FirstIter && IR != ER)
18510 Expr *SimpleRefExpr = RefExpr;
18519 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
18520 ReductionId,
Type, BasePath, IR == ER ?
nullptr : *IR);
18521 Expr *ReductionOp =
nullptr;
18523 (DeclareReductionRef.
isUnset() ||
18524 isa<UnresolvedLookupExpr>(DeclareReductionRef.
get())))
18525 ReductionOp = DeclareReductionRef.
get();
18527 RD.push(RefExpr, ReductionOp);
18533 Expr *TaskgroupDescriptor =
nullptr;
18535 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
18536 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
18538 Type = ASE->getType().getNonReferenceType();
18543 Type = ATy->getElementType();
18546 Type =
Type.getNonReferenceType();
18550 auto *VD = dyn_cast<VarDecl>(
D);
18556 diag::err_omp_reduction_incomplete_type))
18562 false, ASE || OASE))
18569 if (!ASE && !OASE) {
18571 VarDecl *VDDef = VD->getDefinition();
18573 DSARefChecker Check(Stack);
18574 if (Check.Visit(VDDef->
getInit())) {
18575 S.
Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
18576 << getOpenMPClauseName(ClauseKind) << ERange;
18594 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(
D,
false);
18595 if (DVar.CKind == OMPC_reduction) {
18596 S.
Diag(ELoc, diag::err_omp_once_referenced)
18597 << getOpenMPClauseName(ClauseKind);
18599 S.
Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
18602 if (DVar.CKind != OMPC_unknown) {
18603 S.
Diag(ELoc, diag::err_omp_wrong_dsa)
18604 << getOpenMPClauseName(DVar.CKind)
18605 << getOpenMPClauseName(OMPC_reduction);
18617 DVar = Stack->getImplicitDSA(
D,
true);
18618 if (DVar.CKind != OMPC_shared) {
18619 S.
Diag(ELoc, diag::err_omp_required_access)
18620 << getOpenMPClauseName(OMPC_reduction)
18621 << getOpenMPClauseName(OMPC_shared);
18629 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(
D,
false);
18630 if (DVar.CKind == OMPC_threadprivate) {
18631 S.
Diag(ELoc, diag::err_omp_wrong_dsa)
18632 << getOpenMPClauseName(DVar.CKind)
18633 << getOpenMPClauseName(OMPC_reduction);
18643 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
18644 ReductionId,
Type, BasePath, IR == ER ?
nullptr : *IR);
18648 (DeclareReductionRef.
isUnset() ||
18649 isa<UnresolvedLookupExpr>(DeclareReductionRef.
get()))) {
18650 RD.push(RefExpr, DeclareReductionRef.
get());
18653 if (BOK == BO_Comma && DeclareReductionRef.
isUnset()) {
18657 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
18658 <<
Type << ReductionIdRange;
18661 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
18662 <<
Type << ReductionIdRange;
18674 if (DeclareReductionRef.
isUnset()) {
18675 if ((BOK == BO_GT || BOK == BO_LT) &&
18678 S.
Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
18679 << getOpenMPClauseName(ClauseKind) << S.
getLangOpts().CPlusPlus;
18680 if (!ASE && !OASE) {
18681 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18684 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18689 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
18691 S.
Diag(ELoc, diag::err_omp_clause_floating_type_arg)
18692 << getOpenMPClauseName(ClauseKind);
18693 if (!ASE && !OASE) {
18694 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18697 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18704 Type =
Type.getNonLValueExprType(Context).getUnqualifiedType();
18713 bool ConstantLengthOASE =
false;
18715 bool SingleElement;
18718 Context, OASE, SingleElement, ArraySizes);
18721 if (ConstantLengthOASE && !SingleElement) {
18722 for (llvm::APSInt &Size : ArraySizes)
18729 if ((OASE && !ConstantLengthOASE) ||
18731 D->getType().getNonReferenceType()->isVariablyModifiedType())) {
18734 S.
Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
18735 S.
Diag(ELoc, diag::note_vla_unsupported);
18738 S.
targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
18739 S.
targetDiag(ELoc, diag::note_vla_unsupported);
18752 }
else if (!ASE && !OASE &&
18754 PrivateTy =
D->getType().getNonReferenceType();
18760 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
18765 if (DeclareReductionRef.
isUsable()) {
18767 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
18768 if (DRD->getInitializer()) {
18794 Type = ComplexTy->getElementType();
18796 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
18803 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
18825 llvm::APInt InitValue =
18826 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
18827 : llvm::APInt::getMinValue(Size)
18828 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
18829 : llvm::APInt::getMaxValue(Size);
18840 llvm::APFloat InitValue = llvm::APFloat::getLargest(
18871 llvm_unreachable(
"Unexpected reduction operation");
18880 }
else if (!
Init) {
18890 S.
Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
18891 <<
Type << ReductionIdRange;
18892 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18895 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18901 if (DeclareReductionRef.
isUsable()) {
18906 if (!BasePath.empty()) {
18910 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.
get(), &BasePath,
18913 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.
get(), &BasePath,
18917 QualType Params[] = {PtrRedTy, PtrRedTy};
18932 CombBOK, LHSDRE, RHSDRE);
18939 if (BOK != BO_LT && BOK != BO_GT) {
18942 BO_Assign, LHSDRE, ReductionOp.
get());
18944 auto *ConditionalOp =
new (Context)
18949 BO_Assign, LHSDRE, ConditionalOp);
18962 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
18963 if (ClauseKind == OMPC_reduction &&
18964 RD.RedModifier == OMPC_REDUCTION_inscan) {
18966 CopyOpRes = S.
BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
18976 if (Stack->getCurrentDirective() == OMPD_simd ||
19014 if (ClauseKind == OMPC_in_reduction) {
19017 const Expr *ParentReductionOp =
nullptr;
19018 Expr *ParentBOKTD =
nullptr, *ParentReductionOpTD =
nullptr;
19019 DSAStackTy::DSAVarData ParentBOKDSA =
19020 Stack->getTopMostTaskgroupReductionData(
D, ParentSR, ParentBOK,
19022 DSAStackTy::DSAVarData ParentReductionOpDSA =
19023 Stack->getTopMostTaskgroupReductionData(
19024 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
19025 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
19026 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
19027 if ((DeclareReductionRef.
isUnset() && IsParentReductionOp) ||
19028 (DeclareReductionRef.
isUsable() && IsParentBOK) ||
19029 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
19030 bool EmitError =
true;
19031 if (IsParentReductionOp && DeclareReductionRef.
isUsable()) {
19032 llvm::FoldingSetNodeID RedId, ParentRedId;
19033 ParentReductionOp->
Profile(ParentRedId, Context,
true);
19034 DeclareReductionRef.
get()->
Profile(RedId, Context,
19036 EmitError = RedId != ParentRedId;
19040 diag::err_omp_reduction_identifier_mismatch)
19041 << ReductionIdRange << RefExpr->getSourceRange();
19043 diag::note_omp_previous_reduction_identifier)
19045 << (IsParentBOK ? ParentBOKDSA.RefExpr
19046 : ParentReductionOpDSA.RefExpr)
19047 ->getSourceRange();
19051 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
19058 TransformExprToCaptures RebuildToCapture(S,
D);
19060 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
19061 Ref = RebuildToCapture.getCapturedExpr();
19066 RD.ExprCaptures.emplace_back(Ref->
getDecl());
19072 S.
BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
19077 Stack->getCurrentDirective() == OMPD_taskgroup) {
19078 S.
Diag(RefExpr->getExprLoc(),
19079 diag::err_omp_reduction_non_addressable_expression)
19080 << RefExpr->getSourceRange();
19083 RD.ExprPostUpdates.emplace_back(
19090 unsigned Modifier = RD.RedModifier;
19093 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
19094 Modifier = OMPC_REDUCTION_task;
19095 Stack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
19097 if (Modifier == OMPC_REDUCTION_task &&
19098 (CurrDir == OMPD_taskgroup ||
19102 if (DeclareReductionRef.
isUsable())
19103 Stack->addTaskgroupReductionData(
D, ReductionIdRange,
19104 DeclareReductionRef.
get());
19106 Stack->addTaskgroupReductionData(
D, ReductionIdRange, BOK);
19108 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.
get(),
19109 TaskgroupDescriptor, CopyOpRes.
get(), TempArrayRes.
get(),
19110 TempArrayElem.
get());
19112 return RD.Vars.empty();
19122 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
19125 << getOpenMPClauseName(OMPC_reduction);
19133 if (Modifier == OMPC_REDUCTION_inscan &&
19134 (
DSAStack->getCurrentDirective() != OMPD_for &&
19135 DSAStack->getCurrentDirective() != OMPD_for_simd &&
19136 DSAStack->getCurrentDirective() != OMPD_simd &&
19137 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
19138 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
19139 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
19143 ReductionData RD(VarList.size(), Modifier);
19145 StartLoc, LParenLoc, ColonLoc, EndLoc,
19146 ReductionIdScopeSpec, ReductionId,
19147 UnresolvedReductions, RD))
19151 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
19154 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
19155 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
19165 ReductionData RD(VarList.size());
19167 VarList, StartLoc, LParenLoc, ColonLoc,
19168 EndLoc, ReductionIdScopeSpec, ReductionId,
19169 UnresolvedReductions, RD))
19173 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19175 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
19185 ReductionData RD(VarList.size());
19187 StartLoc, LParenLoc, ColonLoc, EndLoc,
19188 ReductionIdScopeSpec, ReductionId,
19189 UnresolvedReductions, RD))
19193 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19195 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
19204 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
19214 const auto *VD = dyn_cast_or_null<VarDecl>(
D);
19217 diag::err_omp_linear_incomplete_type))
19219 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
19221 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
19225 Type =
Type.getNonReferenceType();
19232 if (!IsDeclareSimd &&
19237 Type =
Type.getUnqualifiedType().getCanonicalType();
19238 const auto *Ty =
Type.getTypePtrOrNull();
19239 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
19240 !Ty->isIntegralType(
getASTContext()) && !Ty->isPointerType())) {
19241 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) <<
Type;
19243 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19246 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19269 Diag(Step->
getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
19271 LinKind = OMPC_LINEAR_val;
19272 for (
Expr *RefExpr : VarList) {
19273 assert(RefExpr &&
"NULL expr in OpenMP linear clause.");
19276 Expr *SimpleRefExpr = RefExpr;
19280 Vars.push_back(RefExpr);
19281 Privates.push_back(
nullptr);
19282 Inits.push_back(
nullptr);
19289 auto *VD = dyn_cast<VarDecl>(
D);
19295 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
19296 if (DVar.RefExpr) {
19297 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
19298 << getOpenMPClauseName(OMPC_linear);
19305 Type =
Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
19311 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
19320 ExprCaptures.push_back(Ref->
getDecl());
19327 SimpleRefExpr, RefRes.
get());
19330 ExprPostUpdates.push_back(
19335 if (LinKind == OMPC_LINEAR_uval)
19336 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
19338 InitExpr = VD ? SimpleRefExpr : Ref;
19344 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
19346 ? RefExpr->IgnoreParens()
19348 Privates.push_back(PrivateRef);
19349 Inits.push_back(InitRef);
19355 Expr *StepExpr = Step;
19356 Expr *CalcStepExpr =
nullptr;
19364 StepExpr = Val.
get();
19378 if (std::optional<llvm::APSInt>
Result =
19380 if (!
Result->isNegative() && !
Result->isStrictlyPositive())
19381 Diag(StepLoc, diag::warn_omp_linear_step_zero)
19382 << Vars[0] << (Vars.size() > 1);
19386 CalcStepExpr = CalcStep.
get();
19391 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
19392 Vars, Privates, Inits, StepExpr, CalcStepExpr,
19398 Expr *NumIterations,
Sema &SemaRef,
19399 Scope *S, DSAStackTy *Stack) {
19411 Step = cast<BinaryOperator>(CalcStep)->getLHS();
19412 bool HasErrors =
false;
19413 auto CurInit = Clause.
inits().begin();
19414 auto CurPrivate = Clause.
privates().begin();
19419 Expr *SimpleRefExpr = RefExpr;
19420 auto Res =
getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19422 if (Res.second || !
D) {
19423 Updates.push_back(
nullptr);
19424 Finals.push_back(
nullptr);
19428 auto &&Info = Stack->isLoopControlVariable(
D);
19435 diag::err_omp_linear_distribute_var_non_loop_iteration);
19436 Updates.push_back(
nullptr);
19437 Finals.push_back(
nullptr);
19441 Expr *InitExpr = *CurInit;
19444 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
19446 if (LinKind == OMPC_LINEAR_uval)
19447 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
19451 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
19458 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
19469 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
19472 Final = *CurPrivate;
19476 if (!
Update.isUsable() || !Final.isUsable()) {
19477 Updates.push_back(
nullptr);
19478 Finals.push_back(
nullptr);
19479 UsedExprs.push_back(
nullptr);
19482 Updates.push_back(
Update.get());
19483 Finals.push_back(Final.get());
19485 UsedExprs.push_back(SimpleRefExpr);
19491 UsedExprs.push_back(S);
19493 UsedExprs.append(Clause.
varlist_size() + 1 - UsedExprs.size(),
nullptr);
19504 for (
Expr *RefExpr : VarList) {
19505 assert(RefExpr &&
"NULL expr in OpenMP linear clause.");
19508 Expr *SimpleRefExpr = RefExpr;
19512 Vars.push_back(RefExpr);
19519 auto *VD = dyn_cast<VarDecl>(
D);
19527 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
19529 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19532 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19539 if (
const Expr *PrevRef =
DSAStack->addUniqueAligned(
D, SimpleRefExpr)) {
19540 Diag(ELoc, diag::err_omp_used_in_clause_twice)
19541 << 0 << getOpenMPClauseName(OMPC_aligned) << ERange;
19542 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
19543 << getOpenMPClauseName(OMPC_aligned);
19551 .DefaultFunctionArrayConversion(
19552 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
19561 if (Alignment !=
nullptr) {
19566 Alignment = AlignResult.
get();
19572 ColonLoc, EndLoc, Vars, Alignment);
19583 for (
Expr *RefExpr : VarList) {
19584 assert(RefExpr &&
"NULL expr in OpenMP copyin clause.");
19585 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19587 Vars.push_back(RefExpr);
19588 SrcExprs.push_back(
nullptr);
19589 DstExprs.push_back(
nullptr);
19590 AssignmentOps.push_back(
nullptr);
19599 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
19600 if (!DE || !isa<VarDecl>(DE->getDecl())) {
19601 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
19602 << 0 << RefExpr->getSourceRange();
19606 Decl *
D = DE->getDecl();
19607 auto *VD = cast<VarDecl>(
D);
19612 Vars.push_back(DE);
19613 SrcExprs.push_back(
nullptr);
19614 DstExprs.push_back(
nullptr);
19615 AssignmentOps.push_back(
nullptr);
19621 if (!
DSAStack->isThreadPrivate(VD)) {
19622 Diag(ELoc, diag::err_omp_required_access)
19623 << getOpenMPClauseName(OMPC_copyin)
19624 << getOpenMPDirectiveName(OMPD_threadprivate);
19648 PseudoDstExpr, PseudoSrcExpr);
19657 DSAStack->addDSA(VD, DE, OMPC_copyin);
19658 Vars.push_back(DE);
19659 SrcExprs.push_back(PseudoSrcExpr);
19660 DstExprs.push_back(PseudoDstExpr);
19661 AssignmentOps.push_back(AssignmentOp.
get());
19668 Vars, SrcExprs, DstExprs, AssignmentOps);
19679 for (
Expr *RefExpr : VarList) {
19680 assert(RefExpr &&
"NULL expr in OpenMP linear clause.");
19683 Expr *SimpleRefExpr = RefExpr;
19687 Vars.push_back(RefExpr);
19688 SrcExprs.push_back(
nullptr);
19689 DstExprs.push_back(
nullptr);
19690 AssignmentOps.push_back(
nullptr);
19697 auto *VD = dyn_cast<VarDecl>(
D);
19702 if (!VD || !
DSAStack->isThreadPrivate(VD)) {
19703 DSAStackTy::DSAVarData DVar =
19705 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
19707 Diag(ELoc, diag::err_omp_wrong_dsa)
19708 << getOpenMPClauseName(DVar.CKind)
19709 << getOpenMPClauseName(OMPC_copyprivate);
19717 if (DVar.CKind == OMPC_unknown) {
19718 DVar =
DSAStack->getImplicitDSA(
D,
false);
19719 if (DVar.CKind == OMPC_shared) {
19720 Diag(ELoc, diag::err_omp_required_access)
19721 << getOpenMPClauseName(OMPC_copyprivate)
19722 <<
"threadprivate or private in the enclosing context";
19731 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19732 << getOpenMPClauseName(OMPC_copyprivate) <<
Type
19733 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
19734 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19737 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19758 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
19770 VD ? RefExpr->IgnoreParens()
19772 SrcExprs.push_back(PseudoSrcExpr);
19773 DstExprs.push_back(PseudoDstExpr);
19774 AssignmentOps.push_back(AssignmentOp.
get());
19781 EndLoc, Vars, SrcExprs, DstExprs,
19789 if (VarList.empty())
19798 bool Diagnose =
true) {
19799 QualType OMPDependT = Stack->getOMPDependT();
19800 if (!OMPDependT.
isNull())
19806 S.
Diag(
Loc, diag::err_omp_implied_type_not_found) <<
"omp_depend_t";
19809 Stack->setOMPDependT(PT.
get());
19830 Diag(Depobj->
getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
19835 Diag(Depobj->
getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
19845struct DoacrossDataInfoTy {
19851 llvm::APSInt TotalDepCount;
19854static DoacrossDataInfoTy
19861 llvm::APSInt DepCounter(32);
19862 llvm::APSInt TotalDepCount(32);
19864 if (
const Expr *OrderedCountExpr =
19865 Stack->getParentOrderedRegionParam().first) {
19866 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.
Context);
19867 TotalDepCount.setIsUnsigned(
true);
19870 for (
Expr *RefExpr : VarList) {
19871 assert(RefExpr &&
"NULL expr in OpenMP doacross clause.");
19872 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19874 Vars.push_back(RefExpr);
19881 if (Stack->getParentOrderedRegionParam().first &&
19882 DepCounter >= TotalDepCount) {
19883 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
19897 Vars.push_back(RefExpr);
19903 Expr *LHS = SimpleExpr;
19904 Expr *RHS =
nullptr;
19905 if (
auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
19907 OOLoc = BO->getOperatorLoc();
19910 }
else if (
auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
19911 OOK = OCE->getOperator();
19912 OOLoc = OCE->getOperatorLoc();
19915 }
else if (
auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
19916 OOK = MCE->getMethodDecl()
19919 .getCXXOverloadedOperator();
19920 OOLoc = MCE->getCallee()->getExprLoc();
19929 Vars.push_back(RefExpr);
19935 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK !=
OO_None)) {
19936 SemaRef.
Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
19942 RHS, OMPC_depend,
false);
19947 Stack->getParentOrderedRegionParam().first &&
19948 DepCounter != Stack->isParentLoopControlVariable(
D).first) {
19950 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
19952 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
19955 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
19959 OpsOffs.emplace_back(RHS, OOK);
19961 Vars.push_back(RefExpr->IgnoreParenImpCasts());
19964 TotalDepCount > VarList.size() &&
19965 Stack->getParentOrderedRegionParam().first &&
19966 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
19967 SemaRef.
Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
19968 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
19970 return {Vars, OpsOffs, TotalDepCount};
19979 if (
DSAStack->getCurrentDirective() == OMPD_ordered &&
19980 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
19981 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
19982 <<
"'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
19985 if (
DSAStack->getCurrentDirective() == OMPD_taskwait &&
19986 DepKind == OMPC_DEPEND_mutexinoutset) {
19987 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
19990 if ((
DSAStack->getCurrentDirective() != OMPD_ordered ||
19991 DSAStack->getCurrentDirective() == OMPD_depobj) &&
19993 DepKind == OMPC_DEPEND_sink ||
19995 DSAStack->getCurrentDirective() == OMPD_depobj) &&
19996 DepKind == OMPC_DEPEND_depobj))) {
19998 OMPC_DEPEND_outallmemory,
19999 OMPC_DEPEND_inoutallmemory};
20001 DSAStack->getCurrentDirective() == OMPD_depobj)
20002 Except.push_back(OMPC_DEPEND_depobj);
20004 Except.push_back(OMPC_DEPEND_inoutset);
20006 ?
"depend modifier(iterator) or "
20008 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20012 << getOpenMPClauseName(OMPC_depend);
20016 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
20018 diag::err_omp_depend_sink_source_with_modifier);
20023 Diag(DepModifier->
getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
20027 llvm::APSInt TotalDepCount(32);
20029 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
20032 Vars = VarOffset.Vars;
20033 OpsOffs = VarOffset.OpsOffs;
20034 TotalDepCount = VarOffset.TotalDepCount;
20036 for (
Expr *RefExpr : VarList) {
20037 assert(RefExpr &&
"NULL expr in OpenMP shared clause.");
20038 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20040 Vars.push_back(RefExpr);
20046 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
20047 bool OMPDependTFound =
getLangOpts().OpenMP >= 50;
20048 if (OMPDependTFound)
20050 DepKind == OMPC_DEPEND_depobj);
20051 if (DepKind == OMPC_DEPEND_depobj) {
20055 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20056 !RefExpr->isInstantiationDependent() &&
20057 !RefExpr->containsUnexpandedParameterPack() &&
20058 (OMPDependTFound &&
20060 DSAStack->getOMPDependT(), RefExpr->getType()))) {
20061 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20062 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
20065 if (!RefExpr->isLValue()) {
20066 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20067 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
20074 QualType ExprTy = RefExpr->getType().getNonReferenceType();
20075 const auto *OASE = dyn_cast<ArraySectionExpr>(SimpleExpr);
20082 ExprTy = ATy->getElementType();
20088 const Expr *Length = OASE->getLength();
20090 if (Length && !Length->isValueDependent() &&
20092 Result.Val.getInt().isZero()) {
20094 diag::err_omp_depend_zero_length_array_section_not_allowed)
20104 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20105 !RefExpr->isInstantiationDependent() &&
20106 !RefExpr->containsUnexpandedParameterPack() &&
20107 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
20108 (OMPDependTFound &&
DSAStack->getOMPDependT().getTypePtr() ==
20110 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20113 << RefExpr->getSourceRange();
20117 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
20118 if (ASE && !ASE->getBase()->isTypeDependent() &&
20121 .getNonReferenceType()
20122 ->isPointerType() &&
20123 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
20124 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20127 << RefExpr->getSourceRange();
20135 RefExpr->IgnoreParenImpCasts());
20137 if (!Res.
isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
20138 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
20139 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20142 << RefExpr->getSourceRange();
20147 Vars.push_back(RefExpr->IgnoreParenImpCasts());
20151 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
20152 DepKind != OMPC_DEPEND_outallmemory &&
20153 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
20158 {DepKind, DepLoc,
Data.ColonLoc,
Data.OmpAllMemoryLoc}, DepModifier, Vars,
20159 TotalDepCount.getZExtValue());
20160 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
20161 DSAStack->isParentOrderedRegion())
20162 DSAStack->addDoacrossDependClause(
C, OpsOffs);
20171 "Unexpected device modifier in OpenMP < 50.");
20173 bool ErrorFound =
false;
20175 std::string Values =
20177 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
20178 << Values << getOpenMPClauseName(OMPC_device);
20183 Stmt *HelperValStmt =
nullptr;
20196 if (Modifier == OMPC_DEVICE_ancestor) {
20200 diag::err_omp_device_ancestor_without_requires_reverse_offload);
20208 if (CaptureRegion != OMPD_unknown &&
20211 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20212 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
20217 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
20218 LParenLoc, ModifierLoc, EndLoc);
20223 bool FullCheck =
true) {
20228 SemaRef.
Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
20238 const auto *OASE = dyn_cast<ArraySectionExpr>(
E);
20243 if (isa<ArraySubscriptExpr>(
E) ||
20244 (OASE && OASE->getColonLocFirst().isInvalid())) {
20245 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
20246 return ATy->getSExtSize() != 1;
20251 assert(OASE &&
"Expecting array section if not an array subscript.");
20252 const Expr *LowerBound = OASE->getLowerBound();
20253 const Expr *Length = OASE->getLength();
20262 llvm::APSInt ConstLowerBound =
Result.Val.getInt();
20263 if (ConstLowerBound.getSExtValue())
20278 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr());
20286 llvm::APSInt ConstLength =
Result.Val.getInt();
20287 return CATy->getSExtSize() != ConstLength.getSExtValue();
20296 const auto *OASE = dyn_cast<ArraySectionExpr>(
E);
20300 if (isa<ArraySubscriptExpr>(
E) ||
20301 (OASE && OASE->getColonLocFirst().isInvalid()))
20304 assert(OASE &&
"Expecting array section if not an array subscript.");
20305 const Expr *Length = OASE->getLength();
20311 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
20312 return ATy->getSExtSize() != 1;
20322 llvm::APSInt ConstLength =
Result.Val.getInt();
20323 return ConstLength.getSExtValue() != 1;
20362class MapBaseChecker final :
public StmtVisitor<MapBaseChecker, bool> {
20367 bool IsNonContiguous =
false;
20368 bool NoDiagnose =
false;
20369 const Expr *RelevantExpr =
nullptr;
20370 bool AllowUnitySizeArraySection =
true;
20371 bool AllowWholeSizeArraySection =
true;
20372 bool AllowAnotherPtr =
true;
20376 void emitErrorMsg() {
20378 if (SemaRef.getLangOpts().OpenMP < 50) {
20380 diag::err_omp_expected_named_var_member_or_array_expression)
20383 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
20384 << getOpenMPClauseName(CKind) << ERange;
20390 if (!isa<VarDecl>(DRE->
getDecl())) {
20394 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20395 RelevantExpr = DRE;
20397 Components.emplace_back(DRE, DRE->
getDecl(), IsNonContiguous);
20405 if (isa<CXXThisExpr>(BaseE)) {
20406 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20415 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
20431 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
20451 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
20455 return RelevantExpr || Visit(
E);
20465 AllowUnitySizeArraySection =
false;
20466 AllowWholeSizeArraySection =
false;
20469 Components.emplace_back(ME, FD, IsNonContiguous);
20470 return RelevantExpr || Visit(
E);
20478 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20482 return RelevantExpr || Visit(
E);
20489 AllowWholeSizeArraySection =
false;
20495 !Result.Val.getInt().isZero()) {
20497 diag::err_omp_invalid_map_this_expr);
20499 diag::note_omp_invalid_subscript_on_this_ptr_map);
20501 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20506 Components.emplace_back(AE,
nullptr, IsNonContiguous);
20508 return RelevantExpr || Visit(
E);
20514 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
20515 "Array sections cannot be implicitly mapped.");
20529 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20539 if (AllowWholeSizeArraySection) {
20546 if (NotWhole || IsPointer)
20547 AllowWholeSizeArraySection =
false;
20548 }
else if (DKind == OMPD_target_update &&
20549 SemaRef.getLangOpts().OpenMP >= 50) {
20550 if (IsPointer && !AllowAnotherPtr)
20551 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
20554 IsNonContiguous =
true;
20555 }
else if (AllowUnitySizeArraySection && NotUnity) {
20561 diag::err_array_section_does_not_specify_contiguous_storage)
20567 AllowAnotherPtr =
false;
20569 if (
const auto *TE = dyn_cast<CXXThisExpr>(
E)) {
20576 diag::err_omp_invalid_map_this_expr);
20578 diag::note_omp_invalid_length_on_this_ptr_mapping);
20582 SemaRef.getASTContext()) &&
20585 diag::err_omp_invalid_map_this_expr);
20587 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
20589 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20594 Components.emplace_back(OASE,
nullptr,
false);
20595 return RelevantExpr || Visit(
E);
20601 Components.emplace_back(
E,
nullptr, IsNonContiguous);
20603 return Visit(
Base->IgnoreParenImpCasts());
20607 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->
isLValue() ||
20612 if (!RelevantExpr) {
20614 Components.emplace_back(UO,
nullptr,
false);
20630 Components.emplace_back(BO,
nullptr,
false);
20633 "Either LHS or RHS have base decl inside");
20635 return RelevantExpr || Visit(LE);
20636 return RelevantExpr || Visit(RE);
20639 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20640 RelevantExpr = CTE;
20641 Components.emplace_back(CTE,
nullptr, IsNonContiguous);
20645 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20646 Components.emplace_back(COCE,
nullptr, IsNonContiguous);
20650 Expr *Source =
E->getSourceExpr();
20655 return Visit(Source);
20657 bool VisitStmt(
Stmt *) {
20661 const Expr *getFoundBase()
const {
return RelevantExpr; }
20662 explicit MapBaseChecker(
20666 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
20667 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
20681 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
20685 if (SemaRef.
getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
20686 (CKind == OMPC_to || CKind == OMPC_from)) {
20687 auto CI = CurComponents.rbegin();
20688 auto CE = CurComponents.rend();
20689 for (; CI != CE; ++CI) {
20691 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
20696 SemaRef.
Diag(ELoc, diag::err_array_section_does_not_specify_length)
20700 return Checker.getFoundBase();
20709 bool CurrentRegionOnly,
20720 assert(!CurComponents.empty() &&
"Map clause expression with no components!");
20721 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
20722 "Map clause expression with unexpected base!");
20725 bool IsEnclosedByDataEnvironmentExpr =
false;
20726 const Expr *EnclosingExpr =
nullptr;
20728 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
20729 VD, CurrentRegionOnly,
20730 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
20731 ERange, CKind, &EnclosingExpr,
20735 if (CKind == Kind && SemaRef.
LangOpts.OpenMP >= 50)
20737 assert(!StackComponents.empty() &&
20738 "Map clause expression with no components!");
20739 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
20740 "Map clause expression with unexpected base!");
20744 const Expr *RE = StackComponents.front().getAssociatedExpression();
20750 auto CI = CurComponents.rbegin();
20751 auto CE = CurComponents.rend();
20752 auto SI = StackComponents.rbegin();
20753 auto SE = StackComponents.rend();
20754 for (; CI != CE && SI != SE; ++CI, ++SI) {
20759 if (CurrentRegionOnly &&
20760 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
20761 isa<ArraySectionExpr>(CI->getAssociatedExpression()) ||
20762 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
20763 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
20764 isa<ArraySectionExpr>(SI->getAssociatedExpression()) ||
20765 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
20766 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
20767 diag::err_omp_multiple_array_items_in_map_clause)
20768 << CI->getAssociatedExpression()->getSourceRange();
20769 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
20770 diag::note_used_here)
20771 << SI->getAssociatedExpression()->getSourceRange();
20776 if (CI->getAssociatedExpression()->getStmtClass() !=
20777 SI->getAssociatedExpression()->getStmtClass())
20781 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
20787 for (; SI != SE; ++SI) {
20789 if (
const auto *ASE =
20790 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
20791 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
20792 }
else if (
const auto *OASE = dyn_cast<ArraySectionExpr>(
20793 SI->getAssociatedExpression())) {
20794 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
20795 Type = ArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
20796 }
else if (
const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
20797 SI->getAssociatedExpression())) {
20798 Type = OASE->getBase()->getType()->getPointeeType();
20802 SemaRef, SI->getAssociatedExpression(),
Type))
20812 if (CI == CE && SI == SE) {
20813 if (CurrentRegionOnly) {
20814 if (CKind == OMPC_map) {
20815 SemaRef.
Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
20817 assert(CKind == OMPC_to || CKind == OMPC_from);
20818 SemaRef.
Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
20827 IsEnclosedByDataEnvironmentExpr =
true;
20832 std::prev(CI)->getAssociatedDeclaration()->getType();
20834 std::prev(CI)->getAssociatedExpression()->getExprLoc();
20853 if (CI == CE || SI == SE) {
20856 diag::err_omp_pointer_mapped_along_with_derived_section)
20862 if (CI->getAssociatedExpression()->getStmtClass() !=
20863 SI->getAssociatedExpression()->getStmtClass() ||
20864 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
20865 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
20866 assert(CI != CE && SI != SE);
20867 SemaRef.
Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
20880 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
20881 if (CKind == OMPC_map) {
20882 if (CI != CE || SI != SE) {
20886 CI != CE ? CurComponents.begin() : StackComponents.begin();
20887 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
20889 while (It != End && !It->getAssociatedDeclaration())
20890 std::advance(It, 1);
20891 assert(It != End &&
20892 "Expected at least one component with the declaration.");
20893 if (It !=
Begin && It->getAssociatedDeclaration()
20895 .getCanonicalType()
20896 ->isAnyPointerType()) {
20897 IsEnclosedByDataEnvironmentExpr =
false;
20898 EnclosingExpr =
nullptr;
20902 SemaRef.
Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
20904 assert(CKind == OMPC_to || CKind == OMPC_from);
20905 SemaRef.
Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
20915 if (!CurrentRegionOnly && SI != SE)
20916 EnclosingExpr = RE;
20920 IsEnclosedByDataEnvironmentExpr |=
20921 (!CurrentRegionOnly && CI != CE && SI == SE);
20926 if (CurrentRegionOnly)
20940 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
20942 diag::err_omp_original_storage_is_shared_and_does_not_contain)
20958 Expr *UnresolvedMapper) {
20974 while (S && !S->isDeclScope(
D))
20975 S = S->getParent();
20977 S = S->getParent();
20978 Lookups.emplace_back();
20979 Lookups.back().append(Lookup.
begin(), Lookup.
end());
20982 }
else if (
auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
20986 auto *DMD = cast<OMPDeclareMapperDecl>(
D);
20987 assert(DMD &&
"Expect valid OMPDeclareMapperDecl during instantiation.");
20988 Lookups.back().addDecl(DMD);
20996 filterLookupForUDReductionAndMapper<bool>(Lookups, [](
ValueDecl *
D) {
20997 return !D->isInvalidDecl() &&
20998 (D->getType()->isDependentType() ||
20999 D->getType()->isInstantiationDependentType() ||
21000 D->getType()->containsUnexpandedParameterPack());
21011 false, URS.
begin(), URS.
end(),
false,
21019 SemaRef.
Diag(
Loc, diag::err_omp_mapper_wrong_type);
21026 if (
auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21036 if (
auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21040 !
Type.isMoreQualifiedThan(
D->getType(),
21060 SemaRef.
Diag(
Loc, diag::err_omp_invalid_mapper)
21070struct MappableVarListInfo {
21085 VarComponents.reserve(VarList.size());
21086 VarBaseDeclarations.reserve(VarList.size());
21105 for (
auto *FD : RD->
fields()) {
21113 SExprs.push_back(BE);
21121 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
21124 Maps.push_back(MapClause);
21125 return MapperVarRef;
21129 DSAStackTy *Stack) {
21144 MapperId = DeclNames.getIdentifier(&Ctx.
Idents.
get(
"default"));
21146 BaseType, MapperId, Maps,
nullptr);
21152 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
21156 DMD->setMapperVarRef(MapperVarRef);
21176 while (S && !S->isDeclScope(
D))
21177 S = S->getParent();
21179 S = S->getParent();
21180 Lookups.emplace_back();
21181 Lookups.back().append(Lookup.
begin(), Lookup.
end());
21187 filterLookupForUDReductionAndMapper<bool>(Lookups, [](
ValueDecl *
D) {
21188 return !D->isInvalidDecl() &&
21189 (D->getType()->isDependentType() ||
21190 D->getType()->isInstantiationDependentType() ||
21191 D->getType()->containsUnexpandedParameterPack());
21198 if (filterLookupForUDReductionAndMapper<ValueDecl *>(
21208 auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21221 bool IsAmbiguous = !Paths.isAmbiguous(
21237 {CanonType,
nullptr});
21238 llvm::DenseMap<const Type *, bool>
Visited;
21240 while (!Types.empty()) {
21241 auto [BaseType, CurFD] = Types.pop_back_val();
21242 while (ParentChain.back().second == 0)
21243 ParentChain.pop_back();
21244 --ParentChain.back().second;
21245 if (BaseType.isNull())
21248 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
21251 auto It =
Visited.find(BaseType.getTypePtr());
21261 DefaultMapperId, BaseType);
21262 It =
Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
21268 bool FirstIter =
true;
21278 ParentChain.emplace_back(CurFD, 1);
21280 ++ParentChain.back().second;
21282 Types.emplace_back(FieldTy, FD);
21301 bool IsMapTypeImplicit =
false,
bool NoDiagnose =
false) {
21303 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
21304 "Unexpected clause kind with mappable expressions!");
21312 MapperId.
setName(DeclNames.getIdentifier(
21314 MapperId.
setLoc(StartLoc);
21318 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
21319 bool UpdateUMIt =
false;
21320 Expr *UnresolvedMapper =
nullptr;
21322 bool HasHoldModifier =
21323 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
21331 for (
Expr *RE : MVLI.VarList) {
21332 assert(RE &&
"Null expr in omp to/from/map clause");
21336 if (UpdateUMIt && UMIt != UMEnd) {
21340 "Expect the size of UnresolvedMappers to match with that of VarList");
21344 UnresolvedMapper = *UMIt;
21353 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21357 MVLI.UDMapperList.push_back(ER.
get());
21360 MVLI.ProcessedVarList.push_back(RE);
21369 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
21372 SemaRef.
Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21385 DSAS->getCurrentDirective(), NoDiagnose);
21389 assert(!CurComponents.empty() &&
21390 "Invalid mappable expression information.");
21392 if (
const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
21394 DSAS->addMappedClassesQualTypes(TE->getType());
21397 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21401 MVLI.UDMapperList.push_back(ER.
get());
21403 MVLI.ProcessedVarList.push_back(RE);
21404 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21405 MVLI.VarComponents.back().append(CurComponents.begin(),
21406 CurComponents.end());
21407 MVLI.VarBaseDeclarations.push_back(
nullptr);
21414 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
21415 assert(CurDeclaration &&
"Null decl on map clause.");
21418 "Expecting components to have associated only canonical declarations.");
21420 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
21421 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
21423 assert((VD || FD) &&
"Only variables or fields are expected here!");
21430 if (VD && DSAS->isThreadPrivate(VD)) {
21433 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD,
false);
21434 SemaRef.
Diag(ELoc, diag::err_omp_threadprivate_in_clause)
21435 << getOpenMPClauseName(CKind);
21449 true, CurComponents, CKind))
21451 if (CKind == OMPC_map &&
21454 false, CurComponents, CKind))
21461 auto I = llvm::find_if(
21466 assert(I != CurComponents.end() &&
"Null decl on map clause.");
21469 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->
IgnoreParens());
21470 auto *OASE = dyn_cast<ArraySectionExpr>(VE->
IgnoreParens());
21471 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->
IgnoreParens());
21473 Type = ASE->getType().getNonReferenceType();
21478 Type = ATy->getElementType();
21481 Type =
Type.getNonReferenceType();
21482 }
else if (OAShE) {
21496 if (CKind == OMPC_map) {
21503 if (DKind == OMPD_target_enter_data &&
21504 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
21506 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21507 << (IsMapTypeImplicit ? 1 : 0)
21509 << getOpenMPDirectiveName(DKind);
21518 if (DKind == OMPD_target_exit_data &&
21519 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
21520 MapType == OMPC_MAP_delete || SemaRef.
getLangOpts().OpenMP >= 52)) {
21521 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21522 << (IsMapTypeImplicit ? 1 : 0)
21524 << getOpenMPDirectiveName(DKind);
21533 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
21535 SemaRef.
Diag(StartLoc,
21536 diag::err_omp_invalid_map_type_modifier_for_directive)
21538 OMPC_MAP_MODIFIER_ompx_hold)
21539 << getOpenMPDirectiveName(DKind);
21547 if ((DKind == OMPD_target_data ||
21549 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
21550 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
21551 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21552 << (IsMapTypeImplicit ? 1 : 0)
21554 << getOpenMPDirectiveName(DKind);
21566 if (VD && ((SemaRef.
LangOpts.OpenMP <= 45 &&
21568 DKind == OMPD_target)) {
21569 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD,
false);
21571 SemaRef.
Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
21572 << getOpenMPClauseName(DVar.CKind)
21573 << getOpenMPClauseName(OMPC_map)
21574 << getOpenMPDirectiveName(DSAS->getCurrentDirective());
21583 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21584 Type.getCanonicalType(), UnresolvedMapper);
21587 if (!ER.
get() && isa<ArraySectionExpr>(VE)) {
21595 ElemType = ATy->getElementType();
21605 MVLI.UDMapperList.push_back(ER.
get());
21608 MVLI.ProcessedVarList.push_back(RE);
21612 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
21618 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21619 MVLI.VarComponents.back().append(CurComponents.begin(),
21620 CurComponents.end());
21621 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ?
nullptr
21641 BuiltinType::OMPIterator))
21643 diag::err_omp_map_modifier_not_iterator);
21646 unsigned Count = 0;
21647 for (
unsigned I = 0,
E = MapTypeModifiers.size(); I <
E; ++I) {
21649 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
21650 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
21654 "Modifiers exceed the allowed number of map type modifiers");
21655 Modifiers[Count] = MapTypeModifiers[I];
21656 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
21660 MappableVarListInfo MVLI(VarList);
21662 MapperIdScopeSpec, MapperId, UnresolvedMappers,
21663 MapType, Modifiers, IsMapTypeImplicit,
21669 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
21670 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
21672 MapperId, MapType, IsMapTypeImplicit, MapLoc);
21680 if (ReductionType.
isNull())
21688 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
21693 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
21697 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
21701 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
21704 return ReductionType;
21710 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
21713 Decls.reserve(ReductionTypes.size());
21722 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
21724 bool InCompoundScope =
true;
21725 if (S !=
nullptr) {
21734 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
21736 while (Filter.hasNext()) {
21737 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
21738 if (InCompoundScope) {
21739 UsedAsPrevious.try_emplace(PrevDecl,
false);
21741 UsedAsPrevious[
D] =
true;
21743 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
21744 PrevDecl->getLocation();
21747 if (InCompoundScope) {
21748 for (
const auto &PrevData : UsedAsPrevious) {
21749 if (!PrevData.second) {
21750 PrevDRD = PrevData.first;
21755 }
else if (PrevDeclInScope !=
nullptr) {
21756 auto *PrevDRDInScope = PrevDRD =
21757 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
21759 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
21760 PrevDRDInScope->getLocation();
21761 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
21762 }
while (PrevDRDInScope !=
nullptr);
21764 for (
const auto &TyData : ReductionTypes) {
21765 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
21767 if (I != PreviousRedeclTypes.end()) {
21768 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
21770 Diag(I->second, diag::note_previous_definition);
21773 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
21775 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
21777 DRD->setAccess(AS);
21778 Decls.push_back(DRD);
21780 DRD->setInvalidDecl();
21790 auto *DRD = cast<OMPDeclareReductionDecl>(
D);
21805 QualType ReductionType = DRD->getType();
21822 if (S !=
nullptr) {
21826 DRD->addDecl(OmpInParm);
21827 DRD->addDecl(OmpOutParm);
21833 DRD->setCombinerData(InE, OutE);
21838 auto *DRD = cast<OMPDeclareReductionDecl>(
D);
21845 if (Combiner !=
nullptr)
21846 DRD->setCombiner(Combiner);
21848 DRD->setInvalidDecl();
21853 auto *DRD = cast<OMPDeclareReductionDecl>(
D);
21867 QualType ReductionType = DRD->getType();
21884 if (S !=
nullptr) {
21888 DRD->addDecl(OmpPrivParm);
21889 DRD->addDecl(OmpOrigParm);
21895 DRD->setInitializerData(OrigE, PrivE);
21896 return OmpPrivParm;
21901 auto *DRD = cast<OMPDeclareReductionDecl>(
D);
21910 }
else if (OmpPrivParm->
hasInit()) {
21911 DRD->setInitializer(OmpPrivParm->
getInit(),
21916 DRD->setInvalidDecl();
21922 for (
Decl *
D : DeclReductions.
get()) {
21931 return DeclReductions;
21938 if (
D.isInvalidType())
21951 assert(
ParsedType.isUsable() &&
"Expect usable parsed mapper type");
21954 assert(!MapperType.
isNull() &&
"Expect valid mapper type");
21959 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
21976 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
21978 bool InCompoundScope =
true;
21979 if (S !=
nullptr) {
21988 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
21990 while (Filter.hasNext()) {
21991 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
21992 if (InCompoundScope) {
21993 UsedAsPrevious.try_emplace(PrevDecl,
false);
21995 UsedAsPrevious[
D] =
true;
21997 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
21998 PrevDecl->getLocation();
22001 if (InCompoundScope) {
22002 for (
const auto &PrevData : UsedAsPrevious) {
22003 if (!PrevData.second) {
22004 PrevDMD = PrevData.first;
22009 }
else if (PrevDeclInScope) {
22010 auto *PrevDMDInScope = PrevDMD =
22011 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
22013 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
22014 PrevDMDInScope->getLocation();
22015 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
22016 }
while (PrevDMDInScope !=
nullptr);
22020 if (I != PreviousRedeclTypes.end()) {
22021 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
22022 << MapperType << Name;
22023 Diag(I->second, diag::note_previous_definition);
22031 ClausesWithImplicit);
22033 MapperType, VN, ClausesWithImplicit,
22039 DMD->setAccess(AS);
22041 DMD->setInvalidDecl();
22043 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
22047 DMD->setMapperVarRef(MapperVarRef);
22068 if (
DSAStack->getDeclareMapperVarRef())
22073 assert(
getLangOpts().OpenMP &&
"Expected OpenMP mode.");
22075 if (
const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
22088 assert(
getLangOpts().OpenMP &&
"Expected OpenMP mode.");
22089 return cast<DeclRefExpr>(
DSAStack->getDeclareMapperVarRef())->getDecl();
22096 if (VarList.empty())
22099 for (
Expr *ValExpr : VarList) {
22112 LParenLoc, EndLoc, VarList,
22115 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22117 for (
Expr *ValExpr : VarList) {
22119 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
22120 Vars.push_back(ValExpr);
22125 LParenLoc, EndLoc, Vars, PreInit);
22132 if (VarList.empty())
22135 for (
Expr *ValExpr : VarList) {
22148 StartLoc, LParenLoc, EndLoc, VarList,
22151 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22153 for (
Expr *ValExpr : VarList) {
22155 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
22156 Vars.push_back(ValExpr);
22161 LParenLoc, EndLoc, Vars, PreInit);
22169 Stmt *HelperValStmt =
nullptr;
22175 ValExpr,
SemaRef, OMPC_priority,
22177 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22181 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
22189 "Unexpected grainsize modifier in OpenMP < 51.");
22194 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22195 << Values << getOpenMPClauseName(OMPC_grainsize);
22199 Expr *ValExpr = Grainsize;
22200 Stmt *HelperValStmt =
nullptr;
22210 &CaptureRegion, &HelperValStmt))
22215 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22223 "Unexpected num_tasks modifier in OpenMP < 51.");
22228 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22229 << Values << getOpenMPClauseName(OMPC_num_tasks);
22233 Expr *ValExpr = NumTasks;
22234 Stmt *HelperValStmt =
nullptr;
22241 ValExpr,
SemaRef, OMPC_num_tasks,
22243 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22248 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22268 DSAStackTy *Stack) {
22269 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
22270 if (!OMPEventHandleT.
isNull())
22275 S.
Diag(
Loc, diag::err_omp_implied_type_not_found) <<
"omp_event_handle_t";
22278 Stack->setOMPEventHandleT(PT.
get());
22299 auto *VD = dyn_cast_or_null<VarDecl>(Ref->
getDecl());
22309 <<
"omp_event_handle_t" << 1 << VD->
getType()
22316 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(VD,
false);
22317 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
22320 << getOpenMPClauseName(DVar.CKind)
22321 << getOpenMPClauseName(OMPC_firstprivate);
22336 std::string Values;
22340 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22341 << Values << getOpenMPClauseName(OMPC_dist_schedule);
22344 Expr *ValExpr = ChunkSize;
22345 Stmt *HelperValStmt =
nullptr;
22356 ValExpr = Val.
get();
22361 if (std::optional<llvm::APSInt>
Result =
22363 if (
Result->isSigned() && !
Result->isStrictlyPositive()) {
22364 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
22369 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
22373 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22374 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
22382 Kind, ValExpr, HelperValStmt);
22390 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
22391 Kind != OMPC_DEFAULTMAP_scalar) {
22395 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
22397 OMPC_DEFAULTMAP_MODIFIER_tofrom);
22401 OMPC_DEFAULTMAP_scalar);
22405 Diag(
Loc, diag::err_omp_unexpected_clause_value)
22406 <<
Value << getOpenMPClauseName(OMPC_defaultmap);
22413 if (!isDefaultmapKind || !isDefaultmapModifier) {
22415 ?
"'scalar', 'aggregate', 'pointer'"
22416 :
"'scalar', 'aggregate', 'pointer', 'all'";
22418 StringRef ModifierValue =
"'alloc', 'from', 'to', 'tofrom', "
22419 "'firstprivate', 'none', 'default'";
22420 if (!isDefaultmapKind && isDefaultmapModifier) {
22421 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22422 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22423 }
else if (isDefaultmapKind && !isDefaultmapModifier) {
22424 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22425 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22427 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22428 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22429 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22430 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22433 StringRef ModifierValue =
22434 "'alloc', 'from', 'to', 'tofrom', "
22435 "'firstprivate', 'none', 'default', 'present'";
22436 if (!isDefaultmapKind && isDefaultmapModifier) {
22437 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22438 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22439 }
else if (isDefaultmapKind && !isDefaultmapModifier) {
22440 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22441 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22443 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22444 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22445 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22446 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22455 if (
DSAStack->checkDefaultmapCategory(Kind)) {
22456 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
22462 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
22463 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
22464 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
22466 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
22479 !isa<CXXRecordDecl>(CurLexicalContext) &&
22480 !isa<ClassTemplateDecl>(CurLexicalContext) &&
22481 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
22482 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
22483 Diag(DTCI.
Loc, diag::err_omp_region_not_file_context);
22489 Diag(DTCI.
Loc, diag::warn_hip_omp_target_directives);
22491 DeclareTargetNesting.push_back(DTCI);
22497 assert(!DeclareTargetNesting.empty() &&
22498 "check isInOpenMPDeclareTargetContext() first!");
22499 return DeclareTargetNesting.pop_back_val();
22509 if (DeclareTargetNesting.empty())
22512 Diag(DTCI.
Loc, diag::warn_omp_unterminated_declare_target)
22513 << getOpenMPDirectiveName(DTCI.
Kind);
22528 VarOrFuncDeclFilterCCC CCC(
SemaRef);
22539 Diag(
Id.getLoc(), diag::err_undeclared_var_use) <<
Id.getName();
22544 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
22545 !isa<FunctionTemplateDecl>(ND)) {
22546 Diag(
Id.getLoc(), diag::err_omp_invalid_target_decl) <<
Id.getName();
22555 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
22556 isa<FunctionTemplateDecl>(ND)) &&
22557 "Expected variable, function or function template.");
22559 if (
auto *VD = dyn_cast<VarDecl>(ND)) {
22561 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
22562 !VD->isStaticDataMember()) {
22563 Diag(
Loc, diag::err_omp_declare_target_has_local_vars)
22572 Diag(
Loc, diag::warn_omp_declare_target_after_first_use);
22576 Diag(
Loc, diag::warn_hip_omp_target_directives);
22579 const unsigned Level = -1;
22581 auto *VD = cast<ValueDecl>(ND);
22582 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22583 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22584 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.
DT &&
22585 (*ActiveAttr)->getLevel() == Level) {
22586 Diag(
Loc, diag::err_omp_device_type_mismatch)
22587 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.
DT)
22588 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
22589 (*ActiveAttr)->getDevType());
22592 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
22593 (*ActiveAttr)->getLevel() == Level) {
22594 Diag(
Loc, diag::err_omp_declare_target_to_and_link) << ND;
22598 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
22601 Expr *IndirectE =
nullptr;
22602 bool IsIndirect =
false;
22608 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22613 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
22615 if (
auto *VD = dyn_cast<VarDecl>(ND);
22617 VD->hasGlobalStorage())
22623 if (!
D || !isa<VarDecl>(
D))
22625 auto *VD = cast<VarDecl>(
D);
22626 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy>
MapTy =
22627 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
22628 if (SemaRef.
LangOpts.OpenMP >= 50 &&
22631 VD->hasGlobalStorage()) {
22632 if (!
MapTy || (*
MapTy != OMPDeclareTargetDeclAttr::MT_To &&
22633 *
MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
22640 diag::err_omp_lambda_capture_in_declare_target_not_to);
22641 SemaRef.
Diag(SL, diag::note_var_explicitly_captured_here)
22648 SemaRef.
Diag(VD->
getLocation(), diag::warn_omp_not_in_target_context);
22649 SemaRef.
Diag(SL, diag::note_used_here) << SR;
22653 Sema &SemaRef, DSAStackTy *Stack,
22655 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
22666 if (
auto *VD = dyn_cast<VarDecl>(
D)) {
22668 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
22669 !VD->isStaticDataMember())
22673 if (
DSAStack->isThreadPrivate(VD)) {
22674 Diag(SL, diag::err_omp_threadprivate_in_target);
22679 if (
const auto *FTD = dyn_cast<FunctionTemplateDecl>(
D))
22680 D = FTD->getTemplatedDecl();
22681 if (
auto *FD = dyn_cast<FunctionDecl>(
D)) {
22682 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
22683 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
22684 if (IdLoc.
isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
22685 Diag(IdLoc, diag::err_omp_function_in_link_clause);
22690 if (
auto *VD = dyn_cast<ValueDecl>(
D)) {
22698 if (isa<VarDecl>(
D) || isa<FunctionDecl>(
D) ||
22699 isa<FunctionTemplateDecl>(
D)) {
22700 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22701 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22702 unsigned Level = DeclareTargetNesting.size();
22703 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
22706 Expr *IndirectE =
nullptr;
22707 bool IsIndirect =
false;
22713 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22715 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
22716 : OMPDeclareTargetDeclAttr::MT_To,
22717 DTCI.
DT, IndirectE, IsIndirect, Level,
22721 ML->DeclarationMarkedOpenMPDeclareTarget(
D, A);
22741 if (
auto *VD = dyn_cast<VarDecl>(
Node->getDecl())) {
22743 DeclVector.push_back(VD);
22748 for (
auto *Child : Ex->
children()) {
22757 A = TD->
getAttr<OMPDeclareTargetDeclAttr>();
22758 DeclVector.push_back(cast<VarDecl>(TD));
22759 while (!DeclVector.empty()) {
22760 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
22761 if (TargetVarDecl->
hasAttr<OMPDeclareTargetDeclAttr>() &&
22775 if (isa<VarDecl>(TargetDecl))
22790 unsigned Count = 0;
22791 for (
unsigned I = 0,
E = MotionModifiers.size(); I <
E; ++I) {
22793 llvm::is_contained(Modifiers, MotionModifiers[I])) {
22794 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22798 "Modifiers exceed the allowed number of motion modifiers");
22799 Modifiers[Count] = MotionModifiers[I];
22800 ModifiersLoc[Count] = MotionModifiersLoc[I];
22804 MappableVarListInfo MVLI(VarList);
22806 MapperIdScopeSpec, MapperId, UnresolvedMappers);
22807 if (MVLI.ProcessedVarList.empty())
22811 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22812 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22827 unsigned Count = 0;
22828 for (
unsigned I = 0,
E = MotionModifiers.size(); I <
E; ++I) {
22830 llvm::is_contained(Modifiers, MotionModifiers[I])) {
22831 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22835 "Modifiers exceed the allowed number of motion modifiers");
22836 Modifiers[Count] = MotionModifiers[I];
22837 ModifiersLoc[Count] = MotionModifiersLoc[I];
22841 MappableVarListInfo MVLI(VarList);
22843 MapperIdScopeSpec, MapperId, UnresolvedMappers);
22844 if (MVLI.ProcessedVarList.empty())
22848 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22849 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22856 MappableVarListInfo MVLI(VarList);
22860 for (
Expr *RefExpr : VarList) {
22861 assert(RefExpr &&
"NULL expr in OpenMP use_device_ptr clause.");
22864 Expr *SimpleRefExpr = RefExpr;
22868 MVLI.ProcessedVarList.push_back(RefExpr);
22869 PrivateCopies.push_back(
nullptr);
22870 Inits.push_back(
nullptr);
22877 Type =
Type.getNonReferenceType().getUnqualifiedType();
22879 auto *VD = dyn_cast<VarDecl>(
D);
22883 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
22884 << 0 << RefExpr->getSourceRange();
22892 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
22893 if (VDPrivate->isInvalidDecl())
22898 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
22914 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22915 PrivateCopies.push_back(VDPrivateRefExpr);
22916 Inits.push_back(VDInitRefExpr);
22921 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22925 MVLI.VarBaseDeclarations.push_back(
D);
22926 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22927 MVLI.VarComponents.back().emplace_back(SimpleRefExpr,
D,
22931 if (MVLI.ProcessedVarList.empty())
22935 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
22936 MVLI.VarBaseDeclarations, MVLI.VarComponents);
22942 MappableVarListInfo MVLI(VarList);
22944 for (
Expr *RefExpr : VarList) {
22945 assert(RefExpr &&
"NULL expr in OpenMP use_device_addr clause.");
22948 Expr *SimpleRefExpr = RefExpr;
22953 MVLI.ProcessedVarList.push_back(RefExpr);
22958 auto *VD = dyn_cast<VarDecl>(
D);
22965 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22970 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22974 MVLI.VarBaseDeclarations.push_back(
D);
22975 MVLI.VarComponents.emplace_back();
22976 Expr *Component = SimpleRefExpr;
22977 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
22978 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
22981 MVLI.VarComponents.back().emplace_back(Component,
D,
22985 if (MVLI.ProcessedVarList.empty())
22989 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22990 MVLI.VarComponents);
22996 MappableVarListInfo MVLI(VarList);
22997 for (
Expr *RefExpr : VarList) {
22998 assert(RefExpr &&
"NULL expr in OpenMP is_device_ptr clause.");
23001 Expr *SimpleRefExpr = RefExpr;
23005 MVLI.ProcessedVarList.push_back(RefExpr);
23015 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
23016 << 0 << RefExpr->getSourceRange();
23022 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
23024 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23025 << getOpenMPClauseName(DVar.CKind)
23026 << getOpenMPClauseName(OMPC_is_device_ptr)
23027 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
23032 const Expr *ConflictExpr;
23033 if (
DSAStack->checkMappableExprComponentListsForDecl(
23038 ConflictExpr = R.front().getAssociatedExpression();
23041 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23050 SimpleRefExpr,
D,
false);
23051 DSAStack->addMappableExpressionComponents(
23052 D, MC, OMPC_is_device_ptr);
23055 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
23060 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23061 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23062 "Unexpected device pointer expression!");
23063 MVLI.VarBaseDeclarations.push_back(
23064 isa<DeclRefExpr>(SimpleRefExpr) ?
D :
nullptr);
23065 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23066 MVLI.VarComponents.back().push_back(MC);
23069 if (MVLI.ProcessedVarList.empty())
23073 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23074 MVLI.VarComponents);
23080 MappableVarListInfo MVLI(VarList);
23081 for (
Expr *RefExpr : VarList) {
23082 assert(RefExpr &&
"NULL expr in OpenMP has_device_addr clause.");
23085 Expr *SimpleRefExpr = RefExpr;
23090 MVLI.ProcessedVarList.push_back(RefExpr);
23098 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
23100 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23101 << getOpenMPClauseName(DVar.CKind)
23102 << getOpenMPClauseName(OMPC_has_device_addr)
23103 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
23108 const Expr *ConflictExpr;
23109 if (
DSAStack->checkMappableExprComponentListsForDecl(
23114 ConflictExpr = R.front().getAssociatedExpression();
23117 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23125 Expr *Component = SimpleRefExpr;
23126 auto *VD = dyn_cast<VarDecl>(
D);
23127 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23128 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23132 Component,
D,
false);
23133 DSAStack->addMappableExpressionComponents(
23134 D, MC, OMPC_has_device_addr);
23140 assert(Ref &&
"has_device_addr capture failed");
23141 MVLI.ProcessedVarList.push_back(Ref);
23143 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
23148 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23149 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23150 "Unexpected device pointer expression!");
23151 MVLI.VarBaseDeclarations.push_back(
23152 isa<DeclRefExpr>(SimpleRefExpr) ?
D :
nullptr);
23153 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23154 MVLI.VarComponents.back().push_back(MC);
23157 if (MVLI.ProcessedVarList.empty())
23161 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23162 MVLI.VarComponents);
23173 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
23174 Allocator->isInstantiationDependent() ||
23175 Allocator->containsUnexpandedParameterPack())
23186 AllocatorRes.
get(),
DSAStack->getOMPAllocatorHandleT(),
23191 Allocator = AllocatorRes.
get();
23204 for (
Expr *RefExpr : VarList) {
23205 assert(RefExpr &&
"NULL expr in OpenMP private clause.");
23208 Expr *SimpleRefExpr = RefExpr;
23212 Vars.push_back(RefExpr);
23218 auto *VD = dyn_cast<VarDecl>(
D);
23223 ? RefExpr->IgnoreParens()
23231 DSAStack->addInnerAllocatorExpr(Allocator);
23236 Allocator, ColonLoc, AllocatorModifier,
23237 AllocatorModifierLoc, EndLoc, Vars);
23245 for (
Expr *RefExpr : VarList) {
23246 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
23249 Expr *SimpleRefExpr = RefExpr;
23253 Vars.push_back(RefExpr);
23260 if (
const Expr *PrevRef =
23261 DSAStack->addUniqueNontemporal(
D, SimpleRefExpr)) {
23262 Diag(ELoc, diag::err_omp_used_in_clause_twice)
23263 << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange;
23264 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
23265 << getOpenMPClauseName(OMPC_nontemporal);
23269 Vars.push_back(RefExpr);
23297 for (
Expr *RefExpr : VarList) {
23298 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
23301 Expr *SimpleRefExpr = RefExpr;
23306 Vars.push_back(RefExpr);
23311 const DSAStackTy::DSAVarData DVar =
23317 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
23318 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23319 << RefExpr->getSourceRange();
23321 if (
DSAStack->getParentDirective() != OMPD_unknown)
23322 DSAStack->markDeclAsUsedInScanDirective(
D);
23323 Vars.push_back(RefExpr);
23338 for (
Expr *RefExpr : VarList) {
23339 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
23342 Expr *SimpleRefExpr = RefExpr;
23347 Vars.push_back(RefExpr);
23353 DSAStackTy::DSAVarData DVar;
23354 if (ParentDirective != OMPD_unknown)
23360 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
23361 DVar.Modifier != OMPC_REDUCTION_inscan) {
23362 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23363 << RefExpr->getSourceRange();
23365 DSAStack->markDeclAsUsedInScanDirective(
D);
23367 Vars.push_back(RefExpr);
23379 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
23380 if (!OMPAlloctraitT.
isNull())
23385 S.
Diag(
Loc, diag::err_omp_implied_type_not_found) <<
"omp_alloctrait_t";
23388 Stack->setOMPAlloctraitT(PT.
get());
23408 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
23409 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
23410 StringRef Allocator =
23411 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
23419 Expr *AllocatorExpr =
nullptr;
23421 if (
D.Allocator->isTypeDependent()) {
23422 AllocatorExpr =
D.Allocator;
23426 AllocatorExpr =
D.Allocator->IgnoreParenImpCasts();
23427 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
23428 bool IsPredefinedAllocator =
false;
23430 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
23432 IsPredefinedAllocator =
23434 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
23438 bool IsTypeCompatible = IsPredefinedAllocator;
23439 IsTypeCompatible = IsTypeCompatible ||
23441 OMPAllocatorHandleT);
23443 IsTypeCompatible ||
23445 bool IsNonConstantLValue =
23447 if (!DRE || !IsTypeCompatible ||
23448 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
23449 Diag(
D.Allocator->getExprLoc(), diag::err_omp_var_expected)
23450 <<
"omp_allocator_handle_t" << (DRE ? 1 : 0)
23457 if (IsPredefinedAllocator &&
D.AllocatorTraits) {
23458 Diag(
D.AllocatorTraits->getExprLoc(),
23459 diag::err_omp_predefined_allocator_with_traits)
23461 Diag(
D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
23462 << cast<NamedDecl>(DRE->
getDecl())->getName()
23469 if (!IsPredefinedAllocator && !
D.AllocatorTraits) {
23470 Diag(
D.Allocator->getExprLoc(),
23471 diag::err_omp_nonpredefined_allocator_without_traits);
23475 if (!
D.AllocatorTraits)
23479 IsPredefinedAllocator
23480 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
23481 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
23483 Expr *AllocatorTraitsExpr =
nullptr;
23484 if (
D.AllocatorTraits) {
23485 if (
D.AllocatorTraits->isTypeDependent()) {
23486 AllocatorTraitsExpr =
D.AllocatorTraits;
23492 AllocatorTraitsExpr =
D.AllocatorTraits->IgnoreParenImpCasts();
23497 if (
const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
23498 TraitTy = ConstArrayTy->getElementType();
23504 Diag(
D.AllocatorTraits->getExprLoc(),
23505 diag::err_omp_expected_array_alloctraits)
23506 << AllocatorTraitsExpr->
getType();
23511 if (
auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
23514 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
23531 for (
Expr *RefExpr : Locators) {
23532 assert(RefExpr &&
"NULL expr in OpenMP shared clause.");
23533 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
23535 Vars.push_back(RefExpr);
23543 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23544 << 1 << 0 << RefExpr->getSourceRange();
23553 if (!Res.
isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
23554 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
23555 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23556 << 1 << 0 << RefExpr->getSourceRange();
23559 Vars.push_back(SimpleExpr);
23563 ColonLoc, EndLoc, Modifier, Vars);
23572 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23575 << getOpenMPClauseName(OMPC_bind);
23580 LParenLoc, EndLoc);
23587 Expr *ValExpr = Size;
23588 Stmt *HelperValStmt =
nullptr;
23599 DKind, OMPC_ompx_dyn_cgroup_mem,
getLangOpts().OpenMP);
23600 if (CaptureRegion != OMPD_unknown &&
23603 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23604 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
23609 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23617 if (
DSAStack->getCurrentDirective() == OMPD_ordered &&
23618 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
23619 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
23620 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
23621 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
23622 <<
"'source' or 'sink'" << getOpenMPClauseName(OMPC_doacross);
23628 llvm::APSInt TotalDepCount(32);
23631 DepType == OMPC_DOACROSS_source ||
23632 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
23633 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
23635 Vars = VarOffset.Vars;
23636 OpsOffs = VarOffset.OpsOffs;
23637 TotalDepCount = VarOffset.TotalDepCount;
23639 EndLoc, DepType, DepLoc, ColonLoc, Vars,
23640 TotalDepCount.getZExtValue());
23641 if (
DSAStack->isParentOrderedRegion())
23642 DSAStack->addDoacrossDependClause(
C, OpsOffs);
23671 case OMPC_contains:
23674 llvm_unreachable(
"Unexpected OpenMP clause");
23682 case OMPC_no_openmp:
23684 case OMPC_no_openmp_routines:
23686 case OMPC_no_parallelism:
23689 llvm_unreachable(
"Unexpected OpenMP clause");
23698 if (
Base->hasPlaceholderType() &&
23699 !
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
23712 LowerBound =
Result.get();
23714 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
23734 if (
Base->isTypeDependent() ||
23737 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
23741 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
23753 Diag(
Base->getExprLoc(), diag::err_omp_typecheck_section_value)
23754 <<
Base->getSourceRange());
23760 if (Res.isInvalid())
23762 diag::err_omp_typecheck_section_not_integer)
23764 LowerBound = Res.get();
23774 if (Res.isInvalid())
23776 diag::err_omp_typecheck_section_not_integer)
23777 << 1 << Length->getSourceRange());
23778 Length = Res.get();
23780 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
23781 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
23782 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
23783 << 1 << Length->getSourceRange();
23790 diag::err_omp_typecheck_section_not_integer)
23792 Stride = Res.
get();
23805 Diag(
Base->getExprLoc(), diag::err_omp_section_function_type)
23806 << ResultTy <<
Base->getSourceRange();
23811 diag::err_omp_section_incomplete_type,
Base))
23819 llvm::APSInt LowerBoundValue =
Result.Val.getInt();
23820 if (LowerBoundValue.isNegative()) {
23822 diag::err_omp_section_not_subset_of_array)
23831 if (Length->EvaluateAsInt(
Result, Context)) {
23834 llvm::APSInt LengthValue =
Result.Val.getInt();
23835 if (LengthValue.isNegative()) {
23836 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
23837 <<
toString(LengthValue, 10,
true)
23838 << Length->getSourceRange();
23842 }
else if (ColonLocFirst.
isValid() &&
23848 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
23858 llvm::APSInt StrideValue =
Result.Val.getInt();
23859 if (!StrideValue.isStrictlyPositive()) {
23860 Diag(Stride->
getExprLoc(), diag::err_omp_section_stride_non_positive)
23861 <<
toString(StrideValue, 10,
true)
23868 if (!
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
23876 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
23883 if (
Base->hasPlaceholderType()) {
23897 LParenLoc, RParenLoc, Dims, Brackets);
23899 (!
Base->isTypeDependent() &&
23902 diag::err_omp_non_pointer_type_array_shaping_base)
23903 <<
Base->getSourceRange());
23906 bool ErrorFound =
false;
23908 if (
Dim->hasPlaceholderType()) {
23910 if (
Result.isInvalid()) {
23915 if (
Result.isInvalid()) {
23921 if (!
Dim->isTypeDependent()) {
23924 if (
Result.isInvalid()) {
23926 Diag(
Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
23927 <<
Dim->getSourceRange();
23932 if (!
Dim->isValueDependent() &&
Dim->EvaluateAsInt(EvResult, Context)) {
23937 if (!
Value.isStrictlyPositive()) {
23938 Diag(
Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
23940 <<
Dim->getSourceRange();
23946 NewDims.push_back(
Dim);
23951 LParenLoc, RParenLoc, NewDims, Brackets);
23961 bool IsCorrect =
true;
23966 if (!
D.Type.getAsOpaquePtr()) {
23970 DeclTy = Context.
IntTy;
23971 StartLoc =
D.DeclIdentLoc;
23977 bool IsDeclTyDependent = DeclTy->isDependentType() ||
23978 DeclTy->containsUnexpandedParameterPack() ||
23979 DeclTy->isInstantiationDependentType();
23980 if (!IsDeclTyDependent) {
23981 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
23984 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
23989 if (DeclTy.isConstant(Context)) {
23992 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
24000 assert(
D.DeclIdent &&
"Identifier expected.");
24005 D.DeclIdent, DeclTy, TInfo,
SC_None);
24011 RedeclarationKind::ForVisibleRedeclaration);
24033 if (!IsDeclTyDependent &&
Begin && !
Begin->isTypeDependent()) {
24038 Expr *End =
D.Range.End;
24039 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
24042 End = EndRes.
get();
24044 Expr *Step =
D.Range.Step;
24047 Diag(Step->
getExprLoc(), diag::err_omp_iterator_step_not_integral)
24052 std::optional<llvm::APSInt>
Result =
24058 Diag(Step->
getExprLoc(), diag::err_omp_iterator_step_constant_zero)
24064 if (!
Begin || !End || !IsCorrect) {
24080 if (
Decl *ID =
D.IteratorDecl)
24081 ID->setInvalidDecl();
24093 D.Range.End,
D.Range.Begin);
24099 if (
D.Range.Step) {
24110 D.AssignmentLoc, BO_Sub, Res.
get(),
24127 D.AssignmentLoc, BO_Sub,
D.Range.Begin,
D.Range.End);
24141 D.AssignmentLoc, BO_Sub, Res1.
get(),
24156 D.AssignmentLoc, BO_GT,
D.Range.Step,
24181 CounterVD->setImplicit();
24188 if (
D.Range.Step) {
24190 D.AssignmentLoc, BO_Mul,
24200 D.Range.Begin, UpdateRes.
get());
24207 cast<VarDecl>(
D.IteratorDecl)->getType(),
24210 VDRes.
get(), UpdateRes.
get());
24222 D.AssignmentLoc, UO_PreInc, RefRes.
get());
24223 if (!CounterUpdateRes.
isUsable()) {
24229 if (!CounterUpdateRes.
isUsable()) {
24240 Helpers.assign(ID.size(), {});
24245 if (
Decl *ID =
D.IteratorDecl)
24246 ID->setInvalidDecl();
24251 LLoc, RLoc, ID, Helpers);
24256 StringRef AssumptionStr) {
24257 if (llvm::KnownAssumptionStrings.count(AssumptionStr))
24260 unsigned BestEditDistance = 3;
24261 StringRef Suggestion;
24262 for (
const auto &KnownAssumptionIt : llvm::KnownAssumptionStrings) {
24263 unsigned EditDistance =
24264 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
24265 if (EditDistance < BestEditDistance) {
24266 Suggestion = KnownAssumptionIt.getKey();
24267 BestEditDistance = EditDistance;
24271 if (!Suggestion.empty())
24272 S.
Diag(
Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
24273 << AssumptionStr << Suggestion;
24275 S.
Diag(
Loc, diag::warn_omp_assume_attribute_string_unknown)
24292 :
SemaBase(S), VarDataSharingAttributesStack(nullptr) {}
Defines the clang::ASTContext interface.
enum clang::sema::@1714::IndirectLocalPathEntry::EntryKind Kind
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
This file defines OpenMP nodes for declarative directives.
llvm::DenseSet< const void * > Visited
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.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
static VarDecl * buildVarDecl(Sema &S, SourceLocation Loc, QualType Type, IdentifierInfo *II)
Build a variable declaration for move parameter.
static NamedDecl * findAcceptableDecl(Sema &SemaRef, NamedDecl *D, unsigned IDNS)
Retrieve the visible declaration corresponding to D, if any.
static Expr * getOrderedNumberExpr(ArrayRef< OMPClause * > Clauses)
static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack, bool Diagnose=true)
Tries to find omp_depend_t. type.
static Stmt * buildPreInits(ASTContext &Context, MutableArrayRef< Decl * > PreInits)
Build preinits statement for the given declarations.
static void argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id, SourceLocation Loc, QualType Ty, SmallVectorImpl< UnresolvedSet< 8 > > &Lookups)
static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR, Sema &SemaRef, Decl *D)
static bool checkGenericLoopLastprivate(Sema &S, ArrayRef< OMPClause * > Clauses, OpenMPDirectiveKind K, DSAStackTy *Stack)
static bool checkSimdlenSafelenSpecified(Sema &S, const ArrayRef< OMPClause * > Clauses)
static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto, QualType NewType)
static bool checkOMPArraySectionConstantForReduction(ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement, SmallVectorImpl< llvm::APSInt > &ArraySizes)
static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind, ArrayRef< OMPClause * > Clauses, ArrayRef< OpenMPDirectiveKind > AllowedNameModifiers)
static void handleDeclareVariantConstructTrait(DSAStackTy *Stack, OpenMPDirectiveKind DKind, bool ScopeEntry)
static VarDecl * precomputeExpr(Sema &Actions, SmallVectorImpl< Stmt * > &BodyStmts, Expr *E, StringRef Name)
static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S, CXXScopeSpec &MapperIdScopeSpec, const DeclarationNameInfo &MapperId, QualType Type)
static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, CXXScopeSpec &MapperIdScopeSpec, const DeclarationNameInfo &MapperId, QualType Type, Expr *UnresolvedMapper)
static bool checkReductionClauseWithNogroup(Sema &S, ArrayRef< OMPClause * > Clauses)
static bool checkSectionsDirective(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt, DSAStackTy *Stack)
static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, SourceLocation M1Loc, SourceLocation M2Loc)
static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef)
static 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 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 std::pair< ValueDecl *, bool > getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc, SourceRange &ERange, bool AllowArraySection=false, StringRef DiagType="")
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 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 VarDecl * buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type, StringRef Name, const AttrVec *Attrs=nullptr, DeclRefExpr *OrigRef=nullptr)
Build a variable declaration for OpenMP loop iteration variable.
static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last, ArrayRef< unsigned > Exclude={})
static DeclRefExpr * buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr, bool WithInit)
static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_alloctrait_t type.
static void appendFlattenedStmtList(SmallVectorImpl< Stmt * > &TargetList, Stmt *Item)
Append the Item or the content of a CompoundStmt to the list TargetList.
static bool isConstNotMutableType(Sema &SemaRef, QualType Type, bool AcceptIfMutable=true, bool *IsClassType=nullptr)
static void addLoopPreInits(ASTContext &Context, OMPLoopBasedDirective::HelperExprs &LoopHelper, Stmt *LoopStmt, ArrayRef< Stmt * > OriginalInit, SmallVectorImpl< Stmt * > &PreInits)
Add preinit statements that need to be propageted from the selected loop.
static void checkReductionClauses(Sema &S, DSAStackTy *Stack, ArrayRef< OMPClause * > Clauses)
Check consistency of the reduction clauses.
static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef, DSAStackTy *Stack, QualType QTy, bool FullCheck=true)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTaskRegionParams(Sema &SemaRef)
static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack, OpenMPDirectiveKind CurrentRegion, const DeclarationNameInfo &CurrentName, OpenMPDirectiveKind CancelRegion, OpenMPBindClauseKind BindKind, SourceLocation StartLoc)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTaskloopRegionParams(Sema &SemaRef)
static unsigned checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef, DSAStackTy &DSA, SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA, OMPLoopBasedDirective::HelperExprs &Built)
Called on a for stmt to check itself and nested loops (if any).
static OpenMPDefaultmapClauseKind getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD)
static bool checkNumExprsInClause(SemaBase &SemaRef, ArrayRef< OMPClause * > Clauses, unsigned MaxNum, unsigned Diag)
This checks whether a ClauseType clause C has at most Max expression.
static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef, const Expr *E, QualType BaseQTy)
Return true if it can be proven that the provided array expression (array section or array subscript)...
static T filterLookupForUDReductionAndMapper(SmallVectorImpl< U > &Lookups, const llvm::function_ref< T(ValueDecl *)> Gen)
This file declares semantic analysis for OpenMP constructs and clauses.
static CharSourceRange getRange(const CharSourceRange &EditRange, const SourceManager &SM, const LangOptions &LangOpts, bool IncludeMacroExpansion)
This file defines OpenMP AST classes for executable directives and clauses.
static QualType getPointeeType(const MemRegion *R)
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.
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
const llvm::fltSemantics & getFloatTypeSemantics(QualType T) const
Return the APFloat 'semantics' for the specified scalar floating point type.
QualType getMemberPointerType(QualType T, const Type *Cls) const
Return the uniqued reference to the type for a member pointer to the specified type in the specified ...
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.
QualType getVariableArrayType(QualType EltTy, Expr *NumElts, ArraySizeModifier ASM, unsigned IndexTypeQuals, SourceRange Brackets) const
Return a non-unique reference to the type for a variable array of the specified element 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.
bool DeclMustBeEmitted(const Decl *D)
Determines if the decl can be CodeGen'ed or deserialized from PCH lazily, only when used; this is onl...
CanQualType OMPArrayShapingTy
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
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 getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
CanQualType OMPIteratorTy
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element 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.
CanQualType ArraySectionTy
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,...
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
CanQualType BoundMemberTy
CharUnits getAlignOfGlobalVarInChars(QualType T, const VarDecl *VD) const
Return the alignment in characters that should be given to a global variable with type T.
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
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 getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
const TargetInfo & getTargetInfo() const
bool typesAreCompatible(QualType T1, QualType T2, bool CompareUnqualified=false)
Compatibility predicates used to check assignment expressions.
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
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
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)
A builtin binary operation expression such as "x + y" or "x <= y".
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
static Opcode getOpForCompoundAssignment(Opcode Opc)
bool isRelationalOp() const
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.
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
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...
A call to an overloaded operator written using operator syntax.
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.
Represents the this expression in C++.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
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.
SourceLocation getBeginLoc() const LLVM_READONLY
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
QualType withConst() const
Retrieves a version of this type with const applied.
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)
ImplicitParamDecl * getParam(unsigned i) const
Describes the capture of either a variable, or 'this', or variable-length array type.
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 }.
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
ConditionalOperator - The ?: ternary operator.
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
Base class for callback objects used by Sema::CorrectTypo to check the validity of a potential typo c...
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
The results of name lookup within a DeclContext.
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
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.
DeclContext * getLexicalParent()
getLexicalParent - Returns the containing lexical DeclContext.
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 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)
A reference to a declared variable, function, enum, etc.
SourceLocation getBeginLoc() const LLVM_READONLY
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)
SourceLocation getEndLoc() const LLVM_READONLY
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
SourceLocation getBeginLoc() const LLVM_READONLY
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.
Recursive AST visitor that supports extension via dynamic dispatch.
RAII object that enters a new expression evaluation context.
The return type of classify().
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,...
@ 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.
bool containsUnexpandedParameterPack() const
Whether this expression contains an unexpanded parameter pack (for C++11 variadic templates).
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
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, e.g.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
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.
bool isIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
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...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
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.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
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.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
IfStmt - This represents an if/then/else.
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.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
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.
This represents a decl that may have a name.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
virtual void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const
Appends a human-readable name for this declaration into the given stream.
A C++ nested-name-specifier augmented with source location information.
static OMPAbsentClause * Create(const ASTContext &C, ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
This represents 'acq_rel' clause in the '#pragma omp atomic|flush' directives.
This represents 'acquire' clause in the '#pragma omp atomic|flush' directives.
static OMPAffinityClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Creates clause with a modifier a list of locator items.
static OMPAlignClause * Create(const ASTContext &C, Expr *A, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'align' clause with the given alignment.
static OMPAlignedClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Expr *A)
Creates clause with a list of variables VL and alignment A.
static OMPAllocateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, Expr *Allocator, SourceLocation ColonLoc, OpenMPAllocateClauseModifier AllocatorModifier, SourceLocation AllocatorModifierLoc, 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.
An explicit cast in C or a C-style cast in C++, which uses the syntax ([s1][s2]......
static OMPArrayShapingExpr * Create(const ASTContext &Context, QualType T, Expr *Op, SourceLocation L, SourceLocation R, ArrayRef< Expr * > Dims, ArrayRef< SourceRange > BracketRanges)
static OMPAssumeDirective * Create(const ASTContext &Ctx, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AStmt)
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.
static OMPAtomicDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expressions Exprs)
Creates directive with a list of Clauses and 'x', 'v' and 'expr' parts of the atomic construct (see S...
static OMPBarrierDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates 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').
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 OMPCanonicalLoop * create(const ASTContext &Ctx, Stmt *LoopStmt, CapturedStmt *DistanceFunc, CapturedStmt *LoopVarFunc, DeclRefExpr *LoopVarRef)
Create a new OMPCanonicalLoop.
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
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 critical' directive.
static OMPCriticalDirective * Create(const ASTContext &C, const DeclarationNameInfo &Name, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
This represents '#pragma omp declare mapper ...' directive.
static OMPDeclareMapperDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, QualType T, DeclarationName VarName, ArrayRef< OMPClause * > Clauses, OMPDeclareMapperDecl *PrevDeclInScope)
Creates declare mapper node.
This represents '#pragma omp declare reduction ...' directive.
static OMPDeclareReductionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, QualType T, OMPDeclareReductionDecl *PrevDeclInScope)
Create declare reduction node.
This represents 'default' clause in the '#pragma omp ...' directive.
This represents '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.
static OMPDepobjDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
This represents 'destroy' clause in the '#pragma omp depobj' directive or the '#pragma omp interop' d...
This represents 'detach' clause in the '#pragma omp task' directive.
This represents 'device' clause in the '#pragma omp ...' directive.
static OMPDispatchDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, SourceLocation TargetCallLoc)
Creates directive with a list of Clauses.
This represents 'dist_schedule' clause in the '#pragma omp ...' directive.
static OMPDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents the 'doacross' clause for the '#pragma omp ordered' directive.
static OMPDoacrossClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VL, unsigned NumLoops)
Creates clause with a list of expressions VL.
This represents 'dynamic_allocators' clause in the '#pragma omp requires' directive.
static OMPErrorDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
static OMPExclusiveClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This is a basic class for representing single OpenMP executable directive.
OpenMPDirectiveKind getDirectiveKind() const
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 OMPFlushDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
static OMPForDirective * 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 OMPForSimdDirective * 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 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.
static OMPGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents 'grainsize' clause in the '#pragma omp ...' directive.
static OMPHasDeviceAddrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
This represents 'hint' clause in the '#pragma omp ...' directive.
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 OMPInterchangeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp interchange'.
static OMPInteropDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive.
static OMPIsDevicePtrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static 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.
Expr * getStep()
Returns linear step.
void setUpdates(ArrayRef< Expr * > UL)
Sets the list of update expressions for linear variables.
privates_range privates()
void setFinals(ArrayRef< Expr * > FL)
Sets the list of final update expressions for linear variables.
void setUsedExprs(ArrayRef< Expr * > UE)
Sets the list of used expressions for the linear clause.
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.
Expr * getCalcStep()
Returns expression to calculate linear step.
OpenMPLinearClauseKind getModifier() const
Return modifier.
The base class for all loop-based directives, including loop transformation directives.
static bool doForAllLoops(Stmt *CurStmt, bool TryImperfectlyNestedLoops, unsigned NumLoops, llvm::function_ref< bool(unsigned, Stmt *)> Callback, llvm::function_ref< void(OMPLoopTransformationDirective *)> OnTransformationCallback)
Calls the specified callback function for all the loops in CurStmt, from the outermost to the innermo...
static OMPMapClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, Expr *IteratorModifier, ArrayRef< OpenMPMapModifierKind > MapModifiers, ArrayRef< SourceLocation > MapModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId, OpenMPMapClauseKind Type, bool TypeIsImplicit, SourceLocation TypeLoc)
Creates clause with a list of variables VL.
static OMPMaskedDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
static OMPMaskedTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPMaskedTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPMasterDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt)
Creates directive.
static OMPMasterTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPMasterTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents 'mergeable' clause in the '#pragma omp ...' directive.
This represents 'message' clause in the '#pragma omp error' directive.
Expr * getMessageString() const
Returns message string of the clause.
This represents the 'no_openmp' clause in the '#pragma omp assume' directive.
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.
static OMPOrderedDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
static OMPParallelDirective * 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 OMPParallelForDirective * 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 OMPParallelForSimdDirective * 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 OMPParallelMaskedDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef)
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 OMPParallelMasterDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef)
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 OMPParallelSectionsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
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)
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.
static OMPRequiresDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< OMPClause * > CL)
Create requires node.
static OMPReverseDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp reverse'.
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.
static OMPScanDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
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.
static OMPScopeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
static OMPSectionDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt, bool HasCancel)
Creates directive.
static OMPSectionsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
This represents 'seq_cst' clause in the '#pragma omp atomic|flush' directives.
This represents 'severity' clause in the '#pragma omp error' directive.
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.
static OMPSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents 'simdlen' clause in the '#pragma omp ...' directive.
Expr * getSimdlen() const
Return safe iteration space distance.
static OMPSingleDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPSizesClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Sizes)
Build a 'sizes' AST node.
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 OMPTaskDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, bool HasCancel)
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 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 OMPTaskgroupDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *ReductionRef)
Creates directive.
static OMPTaskwaitDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive.
static OMPTaskyieldDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates directive.
static OMPTeamsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTeamsDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTeamsDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPThreadLimitClause * Create(const ASTContext &C, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents '#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 OMPTileDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp tile'.
static OMPToClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, 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 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.
static OMPUnrollDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, unsigned NumGeneratedLoops, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp unroll'.
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 '('.
unsigned varlist_size() const
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.
Wrapper for void* pointer.
void * getAsOpaquePtr() const
static OpaquePtr make(PtrTy P)
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
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
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
decl_type * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
decl_type * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
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.
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial 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...
OMPClause * ActOnOpenMPDefaultClause(llvm::omp::DefaultKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'default' clause.
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...
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 en...
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.
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'.
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)
OMPClause * ActOnOpenMPAllocateClause(Expr *Allocator, OpenMPAllocateClauseModifier ACModifier, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocate' clause.
StmtResult ActOnOpenMPTargetParallelDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target parallel' after parsing of the associated statement.
OMPClause * ActOnOpenMPDistScheduleClause(OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'dist_schedule' clause.
OpenMPClauseKind isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, unsigned CapLevel) const
Check if the specified variable is used in 'private' clause.
OMPClause * ActOnOpenMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nowait' clause.
OMPClause * ActOnOpenMPPermutationClause(ArrayRef< Expr * > PermExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'permutation' clause after parsing its arguments.
OMPClause * ActOnOpenMPNontemporalClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nontemporal' clause.
OMPClause * ActOnOpenMPFromClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers={})
Called on well-formed 'from' clause.
OMPClause * ActOnOpenMPBindClause(OpenMPBindClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'bind' clause.
OMPClause * ActOnOpenMPThreadsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'threads' clause.
OMPClause * ActOnOpenMPThreadLimitClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'thread_limit' clause.
OMPClause * ActOnOpenMPSharedClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'shared' clause.
StmtResult ActOnOpenMPTargetExitDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target exit data' after parsing of the associated statement.
StmtResult ActOnOpenMPTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp teams' after parsing of the associated statement.
OMPClause * ActOnOpenMPCopyinClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'copyin' clause.
OMPClause * ActOnOpenMPMergeableClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'mergeable' clause.
void startOpenMPCXXRangeFor()
If the current region is a range loop-based region, mark the start of the loop construct.
OMPClause * ActOnOpenMPDestroyClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'destroy' clause.
StmtResult ActOnOpenMPParallelMaskedTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop' after parsing of the associated statemen...
OMPClause * ActOnOpenMPAffinityClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Called on well-formed 'affinity' clause.
OMPClause * ActOnOpenMPCompareClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'compare' clause.
OMPClause * ActOnOpenMPNumTeamsClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_teams' clause.
StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel sections' after parsing of the associated statement.
OMPClause * ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'update' clause.
OMPClause * ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data, Expr *DepModifier, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depend' clause.
OMPClause * ActOnOpenMPDoacrossClause(OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'doacross' clause.
VarDecl * ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
StmtResult ActOnOpenMPTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute parallel for' after parsing of the associated sta...
StmtResult ActOnOpenMPMasterDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp master' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskgroupDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskgroup'.
VarDecl * isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo=false, unsigned StopAt=0)
Check if the specified variable is used in one of the private clauses (private, firstprivate,...
StmtResult ActOnOpenMPMasterTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp master taskloop simd' after parsing of the associated statement.
ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id, OpenMPDirectiveKind Kind)
Called on correct id-expression from the '#pragma omp threadprivate'.
void ActOnOpenMPEndAssumesDirective()
Called on well-formed '#pragma omp end assumes'.
OMPClause * ActOnOpenMPNogroupClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nogroup' clause.
OMPClause * ActOnOpenMPGrainsizeClause(OpenMPGrainsizeClauseModifier Modifier, Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'grainsize' clause.
ExprResult ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc, Expr *LowerBound, SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length, Expr *Stride, SourceLocation RBLoc)
bool isOpenMPRebuildMemberExpr(ValueDecl *D)
The member expression(this->fd) needs to be rebuilt in the template instantiation to generate private...
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)
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.
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.
OMPClause * ActOnOpenMPReductionClause(ArrayRef< Expr * > VarList, OpenMPReductionClauseModifier Modifier, 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 * 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.
OMPClause * ActOnOpenMPNumThreadsClause(Expr *NumThreads, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_threads' 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 state...
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.
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.
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 * 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.
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 ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, ArrayRef< Expr * > AdjustArgsNothing, ArrayRef< Expr * > AdjustArgsNeedDevicePtr, ArrayRef< OMPInteropInfo > AppendArgs, SourceLocation AdjustArgsLoc, SourceLocation AppendArgsLoc, SourceRange SR)
Called on well-formed '#pragma omp declare variant' after parsing of the associated method/function.
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 * 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 * 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.
llvm::SmallDenseMap< const ValueDecl *, const Expr *, 4 > VarsWithInheritedDSAType
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 on start of '#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.
ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo)
Package the given type and TSI into a ParsedType.
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.
ImplicitConversionSequence TryImplicitConversion(Expr *From, QualType ToType, bool SuppressUserConversions, AllowedExplicit AllowExplicit, bool InOverloadResolution, bool CStyle, bool AllowObjCWritebackConversion)
void MarkDeclarationsReferencedInExpr(Expr *E, bool SkipLocalVariables=false, ArrayRef< const Expr * > StopAt={})
Mark any declarations that appear within this expression or any potentially-evaluated subexpressions ...
FunctionEmissionStatus
Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl=nullptr, ExpressionEvaluationContextRecord::ExpressionKind Type=ExpressionEvaluationContextRecord::EK_Other)
ExprResult CheckBooleanCondition(SourceLocation Loc, Expr *E, bool IsConstexpr=false)
CheckBooleanCondition - Diagnose problems involving the use of the given expression as a boolean cond...
SmallVector< sema::FunctionScopeInfo *, 4 > FunctionScopes
Stack containing information about each of the nested function, block, and method scopes that are cur...
PoppedFunctionScopePtr PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP=nullptr, const Decl *D=nullptr, QualType BlockType=QualType())
Pop a function (or block or lambda or captured region) scope from the stack.
Scope * getScopeForContext(DeclContext *Ctx)
Determines the active Scope associated with the given declaration context.
bool CheckCXXThisCapture(SourceLocation Loc, bool Explicit=false, bool BuildAndDiagnose=true, const unsigned *const FunctionScopeIndexToStopAt=nullptr, bool ByCopy=false)
Make sure the value of 'this' is actually available in the current context, if it is a potentially ev...
NamedDecl * HandleDeclarator(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists)
ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, VerifyICEDiagnoser &Diagnoser, AllowFoldKind CanFold=NoFold)
VerifyIntegerConstantExpression - Verifies that an expression is an ICE, and reports the appropriate ...
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.
FunctionDecl * getCurFunctionDecl(bool AllowLambda=false) const
Returns a pointer to the innermost enclosing function, or nullptr if the current context is not insid...
ExprResult PerformContextualImplicitConversion(SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter)
Perform a contextual implicit conversion.
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.
void CleanupVarDeclMarking()
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 MarkVariableReferenced(SourceLocation Loc, VarDecl *Var)
Mark a variable referenced, and check whether it is odr-used (C++ [basic.def.odr]p2,...
void PopExpressionEvaluationContext()
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...
void PushFunctionScope()
Enter a new function scope.
const LangOptions & getLangOpts() const
TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind, Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC, CorrectTypoKind Mode, DeclContext *MemberContext=nullptr, bool EnteringContext=false, const ObjCObjectPointerType *OPT=nullptr, bool RecordFailure=true)
Try to "correct" a typo in the source code by finding visible declarations whose names are similar to...
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...
ExprResult BuildCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig=nullptr, bool IsExecConfig=false, bool AllowRecovery=false)
BuildCallExpr - Handle a call to Fn with the specified array of arguments.
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.
void CheckExtraCXXDefaultArguments(Declarator &D)
CheckExtraCXXDefaultArguments - Check for any extra default arguments in the declarator,...
const LangOptions & LangOpts
sema::LambdaScopeInfo * getCurLambda(bool IgnoreNonLambdaCapturingScope=false)
Retrieve the current lambda scope info, if any.
DeclContext * getCurLexicalContext() const
ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, SourceLocation RParenLoc, Expr *Op)
void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, CapturedRegionKind Kind, unsigned NumParams)
sema::FunctionScopeInfo * getCurFunction() const
Expr * BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit)
Build a CXXThisExpr and mark it referenced in the current context.
ExprResult DefaultLvalueConversion(Expr *E)
bool isVisible(const NamedDecl *D)
Determine whether a declaration is visible to name lookup.
FunctionEmissionStatus getEmissionStatus(const FunctionDecl *Decl, bool Final=false)
sema::BlockScopeInfo * getCurBlock()
Retrieve the current block, if any.
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
StmtResult ActOnCapturedRegionEnd(Stmt *S)
ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E)
ExprResult CheckPlaceholderExpr(Expr *E)
Check for operands with placeholder types and complain if found.
bool inTemplateInstantiation() const
Determine whether we are currently performing template instantiation.
@ TryCapture_ExplicitByVal
bool areMultiversionVariantFunctionsCompatible(const FunctionDecl *OldFD, const FunctionDecl *NewFD, const PartialDiagnostic &NoProtoDiagID, const PartialDiagnosticAt &NoteCausedDiagIDAt, const PartialDiagnosticAt &NoSupportDiagIDAt, const PartialDiagnosticAt &DiffDiagIDAt, bool TemplatesSupported, bool ConstexprSupported, bool CLinkageMayDiffer)
Checks if the variant/multiversion functions are compatible.
ExprResult ActOnConditionalOp(SourceLocation QuestionLoc, SourceLocation ColonLoc, Expr *CondExpr, Expr *LHSExpr, Expr *RHSExpr)
ActOnConditionalOp - Parse a ?: operation.
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()
RedeclarationKind forRedeclarationInCurContext() const
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),...
TypeSourceInfo * GetTypeForDeclarator(Declarator &D)
GetTypeForDeclarator - Convert the type for the specified declarator to Type instances.
void diagnoseTypo(const TypoCorrection &Correction, const PartialDiagnostic &TypoDiag, bool ErrorRecovery=true)
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()
void PushDeclContext(Scope *S, DeclContext *DC)
Set the current declaration context until it gets popped.
ExprResult ActOnIntegerConstant(SourceLocation Loc, int64_t Val)
void FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S, bool ConsiderLinkage, bool AllowInlineNamespace)
Filters out lookup results that don't fall within the given scope as determined by isDeclInScope.
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)
ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr)
ExprResult CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr)
CreateBuiltinBinOp - Creates a new built-in binary operation with operator Opc at location TokLoc.
bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base)
Determine whether the type Derived is a C++ class that is derived from the type Base.
sema::FunctionScopeInfo * getEnclosingFunction() const
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)
bool checkStringLiteralArgumentAttr(const AttributeCommonInfo &CI, const Expr *E, StringRef &Str, SourceLocation *ArgLocation=nullptr)
Check if the argument E is a ASCII string literal.
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 getEnd() const
SourceLocation getBegin() const
void setEnd(SourceLocation e)
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Stmt - This represents one statement.
SourceLocation getEndLoc() const LLVM_READONLY
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.
bool isVLASupported() const
Whether target supports variable-length arrays.
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.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantArrayType() const
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 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 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
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Simple class containing the result of Sema::CorrectTypo.
NamedDecl * getCorrectionDecl() const
Gets the pointer to the declaration of the typo correction.
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Expr * getSubExpr() const
static UnresolvedLookupExpr * Create(const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End, bool KnownDependent, bool KnownInstantiationDependent)
void append(iterator I, iterator E)
void addDecl(NamedDecl *D)
A set of unresolved declarations.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
void setType(QualType newType)
VarDecl * getPotentiallyDecomposedVarDecl()
Represents a variable declaration or definition.
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
bool isFunctionOrMethodVarDecl() const
Similar to isLocalVarDecl, but excludes variables declared in blocks.
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
TLSKind getTLSKind() const
void setInitStyle(InitializationStyle Style)
InitializationStyle getInitStyle() const
The style of initialization for this declaration.
DefinitionKind isThisDeclarationADefinition(ASTContext &) const
Check whether this declaration is a definition.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
@ CInit
C-style initialization with assignment.
@ CallInit
Call-style initialization (C++98)
bool isStaticDataMember() const
Determines whether this is a static data member.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
bool isFileVarDecl() const
Returns true for file scoped variable declaration.
const Expr * getInit() const
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
@ TLS_None
Not a TLS variable.
@ DeclarationOnly
This declaration is only a declaration.
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
bool isDirectInit() const
Whether the initializer is a direct-initializer (list or call).
StorageDuration getStorageDuration() const
Get the storage duration of this variable, per C++ [basic.stc].
StorageClass getStorageClass() const
Returns the storage class as written in the source.
bool isUsableInConstantExpressions(const ASTContext &C) const
Determine whether this variable's value can be used in a constant expression, according to the releva...
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Directive - Abstract class representing a parsed verify directive.
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.
void setHasOMPDeclareReductionCombiner()
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.
bool LE(InterpState &S, CodePtr OpPC)
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.
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 checkFailClauseParameter(OpenMPClauseKind FailClauseParameter)
Checks if the parameter to the fail clause in "#pragma atomic compare fail" is restricted only to mem...
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target data offload directive.
bool isOpenMPLoopTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive.
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
OpenMPDefaultmapClauseModifier
OpenMP modifiers for 'defaultmap' clause.
@ OMPC_DEFAULTMAP_MODIFIER_last
@ OMPC_DEFAULTMAP_MODIFIER_unknown
OpenMPOrderClauseModifier
OpenMP modifiers for 'order' clause.
@ OMPC_ORDER_MODIFIER_unknown
@ OMPC_ORDER_MODIFIER_last
ExprObjectKind
A further classification of the kind of object referenced by an l-value or x-value.
@ OK_Ordinary
An ordinary object is located at an address in memory.
OpenMPAtClauseKind
OpenMP attributes for 'at' clause.
Expr * AssertSuccess(ExprResult R)
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
@ LCK_This
Capturing the *this object by reference.
OpenMPReductionClauseModifier
OpenMP modifiers for 'reduction' clause.
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
@ OMPC_SCHEDULE_MODIFIER_last
@ OMPC_SCHEDULE_MODIFIER_unknown
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
const char * getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type)
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.
@ SD_Static
Static storage duration.
@ Parameter
The parameter type of a method or function.
@ Result
The result type of a method or function.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
bool isOpenMPGenericLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive constitutes a 'loop' directive in the outermost nest.
OpenMPBindClauseKind
OpenMP bindings for the 'bind' clause.
OpenMPLastprivateModifier
OpenMP 'lastprivate' clause modifier.
@ OMPC_LASTPRIVATE_unknown
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
OpenMPGrainsizeClauseModifier
OpenMPNumTasksClauseModifier
ActionResult< Expr * > ExprResult
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".
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.
for(const auto &A :T->param_types())
const FunctionProtoType * T
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPAtomicDefaultMemOrderClauseKind
OpenMP attributes for 'atomic_default_mem_order' clause.
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
ActionResult< Decl * > DeclResult
OpenMPDeviceClauseModifier
OpenMP modifiers for 'device' clause.
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
@ OMPC_MAP_MODIFIER_unknown
bool isOpenMPCombinedParallelADirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a combined construct for which the first construct is a parallel...
bool isOpenMPNestingDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a distribute directive in the outerm...
OpenMPOrderClauseKind
OpenMP attributes for 'order' clause.
@ Implicit
An implicit conversion.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
@ NOUR_Unevaluated
This name appears in an unevaluated operand.
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.
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
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.
Expr * ParForInDistCond
'omp parallel for' loop condition used when composed with 'omp distribute' in the same construct and ...
Expr * LB
DistributeLowerBound - used when composing 'omp distribute' with 'omp for' in a same construct.
Expr * Init
Distribute loop iteration variable init used when composing 'omp distribute' with 'omp for' in a same...
Expr * NUB
Update of UpperBound for statically scheduled omp loops for outer loop in combined constructs (e....
Expr * EUB
DistributeEnsureUpperBound - used when composing 'omp distribute' with 'omp for' in a same construct,...
Expr * UB
DistributeUpperBound - used when composing 'omp distribute' with 'omp for' in a same construct.
Expr * NLB
Update of LowerBound for statically scheduled omp loops for outer loop in combined constructs (e....
Expr * DistCond
Distribute Loop condition used when composing 'omp distribute' with 'omp for' in a same construct whe...
Expr * Cond
Distribute Loop condition used when composing 'omp distribute' with 'omp for' in a same construct.
The expressions built for the OpenMP loop CodeGen for the whole collapsed loop nest.
Expr * LastIteration
Loop last iteration number.
Expr * Cond
Loop condition.
SmallVector< Expr *, 4 > DependentInits
List of initializers required for the generation of the non-rectangular loops.
SmallVector< Expr *, 4 > Inits
Expressions for loop counters inits for CodeGen.
Expr * PrevEUB
PrevEUB - expression similar to EUB but to be used when loop scheduling uses PrevLB and PrevUB (e....
Expr * DistInc
DistInc - increment expression for distribute loop when found combined with a further loop level (e....
Expr * IL
IsLastIteration - local flag variable passed to runtime.
SmallVector< Expr *, 4 > PrivateCounters
PrivateCounters Loop counters.
bool builtAll()
Check if all the expressions are built (does not check the worksharing ones).
Expr * CalcLastIteration
Calculation of last iteration.
SmallVector< Expr *, 4 > Updates
Expressions for loop counters update for CodeGen.
Expr * ST
Stride - local variable passed to runtime.
SmallVector< Expr *, 4 > Finals
Final loop counter values for GodeGen.
SmallVector< Expr *, 4 > FinalsConditions
List of final conditions required for the generation of the non-rectangular loops.
Expr * PreCond
Loop pre-condition.
Stmt * PreInits
Init statement for all captured expressions.
Expr * IterationVarRef
Loop iteration variable.
Expr * NumIterations
Loop number of iterations.
SmallVector< Expr *, 4 > Counters
Counters Loop counters.
Expr * NLB
Update of LowerBound for statically scheduled 'omp for' loops.
Expr * PrevUB
PreviousUpperBound - local variable passed to runtime in the enclosing schedule or null if that does ...
DistCombinedHelperExprs DistCombinedFields
Expressions used when combining OpenMP loop pragmas.
void clear(unsigned Size)
Initialize all the fields to null.
Expr * Inc
Loop increment.
Expr * EUB
EnsureUpperBound – expression UB = min(UB, NumIterations).
Expr * UB
UpperBound - local variable passed to runtime.
Expr * NUB
Update of UpperBound for statically scheduled 'omp for' loops.
Expr * LB
LowerBound - local variable passed to runtime.
Expr * PrevLB
PreviousLowerBound - local variable passed to runtime in the enclosing schedule or null if that does ...
SmallVector< Expr *, 4 > DependentCounters
List of counters required for the generation of the non-rectangular loops.
Expr * Init
Loop iteration variable init.
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.
Data used for processing a list of variables in OpenMP clauses.
Data for list of allocators.
Clang specific specialization of the OMPContext to lookup target features.